switch now compiles for win32, but there is still the select issue with stdin
[olsrd.git] / src / olsr_switch / ohs_cmd.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2005, Andreas T√łnnesen(andreto@olsr.org)
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without 
8  * modification, are permitted provided that the following conditions 
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright 
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright 
14  *   notice, this list of conditions and the following disclaimer in 
15  *   the documentation and/or other materials provided with the 
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its 
18  *   contributors may be used to endorse or promote products derived 
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  * $Id: ohs_cmd.c,v 1.16 2005/08/04 18:57:11 kattemat Exp $
41  */
42
43 #include "olsr_host_switch.h"
44 #include "olsr_types.h"
45 #include "commands.h"
46 #include "link_rules.h"
47 #include <string.h>
48 #include <stdlib.h>
49 #include <sys/socket.h>
50 #include <netinet/in.h>
51 #include <arpa/inet.h>
52 #include <sys/types.h>
53 #include <sys/stat.h>
54 #include <unistd.h>
55 #include <errno.h>
56
57
58 #define ARG_BUF_SIZE 500
59 static char arg_buf[ARG_BUF_SIZE];
60
61 #define TOK_BUF_SIZE 500
62 static char tok_buf[TOK_BUF_SIZE];
63
64 #define MAX_OLSRD_ARGS 10
65 static char olsrd_path[FILENAME_MAX];
66
67 static void
68 get_arg_buf(FILE *handle, char *buf, size_t size)
69 {
70   char c = 0;
71   int pos = 0;
72
73   while(((c = fgetc(handle)) != '\n') &&
74         pos < ((int)size - 2))
75     {
76       buf[pos] = c;
77       pos++;
78     }
79
80   buf[pos] = 0;
81 }
82
83 static int
84 get_next_token(char *src, char *dst, size_t buflen)
85 {
86   int i = 0, j = 0;
87
88   dst[0] = 0;
89   /* Skip leading spaces */
90   while(src[j] == ' ' && src[j] != 0)
91     {
92       j++;
93     }
94
95   src += j;
96   i = 0;
97   while((src[i] != ' ') && (src[i] != 0) && (i < ((int)buflen - 1)))
98     {
99       dst[i] = src[i];
100       i++;
101     }
102   dst[i] = 0;
103
104   //if(strlen(dst))
105   //printf("Extracted token: %s\n", dst);
106   return i + j;
107 }
108
109 int
110 ohs_set_olsrd_path(char *path)
111 {
112   strncpy(olsrd_path, path, FILENAME_MAX);
113   return 0;
114 }
115
116 int
117 ohs_cmd_olsrd(FILE *handle, char *args)
118 {
119 #ifdef WIN32
120   printf("olsrd command not available in windows version\nStart instances manually\n");
121   return 0;
122 #else
123   char *olsrd_args[MAX_OLSRD_ARGS];
124   struct in_addr iaddr;
125
126   args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
127
128   if(!strlen(tok_buf))
129     goto print_usage;
130
131   /* Start olsrd instance */
132   if(!strncmp(tok_buf, "start", strlen("start")))
133     {
134       int argc = 0, i = 0;
135
136       args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
137       
138       if(!strlen(tok_buf))
139         goto print_usage;
140
141       if(!inet_aton(tok_buf, &iaddr))
142         {
143           printf("Invalid IP %s\n", tok_buf);
144           goto print_usage;
145         }
146
147       olsrd_args[argc++] = olsrd_path;
148
149       if(1) /* config file is set */
150         {
151           olsrd_args[argc++] = "-f";
152           olsrd_args[argc++] = "/etc/olsrd-emu.conf";
153         }
154       olsrd_args[argc++] = "-hemu";
155       olsrd_args[argc++] = tok_buf;
156
157       olsrd_args[argc++] = "-d";
158       olsrd_args[argc++] = "0";
159       olsrd_args[argc++] = "-nofork";
160       olsrd_args[argc] = NULL;
161
162       printf("Executing: %s", olsrd_path);
163       for(i = 0; i < argc; i++)
164         printf(" %s", olsrd_args[i]);
165       printf("\n");
166
167       if(fork())
168         return 1;
169
170       if(execve(olsrd_path, olsrd_args, NULL) < 0)
171         {
172           printf("Error executing olsrd: %s\n", strerror(errno));
173           exit(1);
174         }
175     }
176   /* Stop olsrd instance */
177   else if(!strncmp(tok_buf, "stop", strlen("stop")))
178     {
179       struct ohs_connection *oc;
180
181       args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
182       
183       if(!strlen(tok_buf))
184         goto print_usage;
185
186       if(!inet_aton(tok_buf, &iaddr))
187         {
188           printf("Invalid IP %s\n", tok_buf);
189           goto print_usage;
190         }
191
192       oc = get_client_by_addr((union olsr_ip_addr *)&iaddr.s_addr);
193
194       if(!oc)
195         {
196           printf("No such client: %s\n", tok_buf);
197           return -1;
198         }
199       ohs_delete_connection(oc);
200       
201       return 1;
202     }
203   /* Set olsrd binary path */
204   else if(!strncmp(tok_buf, "setb", strlen("setb")))
205     {
206       struct stat sbuf;
207
208       args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
209       
210       if(!strlen(tok_buf))
211         goto print_usage;
212
213       if(stat(tok_buf, &sbuf) < 0)
214         {
215           printf("Error setting binary \"%s\": %s\n",
216                  tok_buf, strerror(errno));
217           return -1;
218         }
219
220       if((sbuf.st_mode & S_IFDIR) || !(sbuf.st_mode & S_IXUSR))
221         {
222           printf("Error setting binary \"%s\": Not a regular execuatble file!\n",
223                  tok_buf);
224           return -1;
225         }
226
227       printf("New olsrd binary path:\"%s\"\n", tok_buf);
228       ohs_set_olsrd_path(tok_buf);
229
230       return 1;
231
232     }
233   /* Set arguments */
234   else if(!strncmp(tok_buf, "seta", strlen("seta")))
235     {
236
237     }
238   /* Show settings */
239   else if(!strncmp(tok_buf, "show", strlen("show")))
240     {
241       printf("olsrd command settings:\n\tBinary path: %s\n\tArguments  : \n",
242              olsrd_path);
243       return 1;
244     }
245
246  print_usage:
247   printf("Usage: olsrd [start|stop|show|setb|seta] [IP|path|args]\n");
248   return 0;
249 #endif
250 }
251
252 int
253 ohs_cmd_link(FILE *handle, char *args)
254 {
255   olsr_u8_t bi = 0, wildc_src = 0, wildc_dst = 0;
256   struct ohs_connection *src, *dst;
257   struct in_addr iaddr;
258   int qual;
259   struct ohs_ip_link *link, *inv_link;
260
261   args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
262
263   if(!strlen(tok_buf))
264     goto print_usage;
265
266   if(!strncmp(tok_buf, "bi", strlen("bi")))
267     {
268       bi = 1;
269       args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
270
271       if(!strlen(tok_buf))
272         goto print_usage;
273     }
274
275   if(tok_buf[0] == '*')
276     {
277       wildc_src = 1;
278       src = ohs_conns;
279     }
280   else
281     {
282       if(!inet_aton(tok_buf, &iaddr))
283         {
284           printf("Invalid src IP %s\n", tok_buf);
285           return -1;
286         }
287
288       src = get_client_by_addr((union olsr_ip_addr *)&iaddr.s_addr);
289
290       if(!src)
291         {
292           printf("No such client: %s!\n", tok_buf);
293           return -1;
294         }
295     }
296
297   args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
298   
299   if(!strlen(tok_buf))
300     goto print_usage;
301
302   if(tok_buf[0] == '*')
303     {
304       wildc_dst = 1;
305       dst = ohs_conns;
306     }
307   else
308     {
309       
310       if(!inet_aton(tok_buf, &iaddr))
311         {
312           printf("Invalid src IP %s\n", tok_buf);
313           return -1;
314         }
315       
316       dst = get_client_by_addr((union olsr_ip_addr *)&iaddr.s_addr);
317       if(!dst)
318         {
319           printf("No such client: %s!\n", tok_buf);
320           return -1;
321         }
322     }
323
324   args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
325   
326   if(!strlen(tok_buf))
327     goto print_usage;
328
329   /* No use for bi if both src and dst are widcards */
330   if(wildc_src && wildc_dst)
331     {
332       bi = 0;
333     }
334
335   qual = atoi(tok_buf);
336
337   if(qual < 0 || qual > 100)
338     {
339       printf("Link quality out of range(0-100)\n");
340       return -1;
341     }
342
343   while(src)
344     {
345
346       while(dst)
347         {
348
349           if(src == dst)
350             goto next_iteration;
351
352           link = get_link(src, &dst->ip_addr);
353           
354           inv_link = bi ? get_link(dst, &src->ip_addr) : NULL;
355           
356           if(qual == 100)
357             {
358               /* Remove link entry */
359               if(link)
360                 remove_link(src, link);
361               if(inv_link)
362                 remove_link(dst, inv_link);
363             }
364           else 
365             {
366               if(!link)
367                 {
368                   /* Create new link */
369                   link = add_link(src, dst);
370                 }
371               
372               link->quality = qual;
373               
374               if(bi)
375                 {
376                   if(!inv_link)
377                     {
378                       /* Create new link */
379                       inv_link = add_link(dst, src);
380                     }
381                   inv_link->quality = qual;
382                 }
383             }
384
385           printf("%s %sdirectional link(s) %s %c=> %s quality %d\n", 
386                  (qual == 100) ? "Removing" : "Setting", bi ? "bi" : "uni",
387                  olsr_ip_to_string(&src->ip_addr), bi ? '<' : '=', 
388                  olsr_ip_to_string(&dst->ip_addr), qual);
389
390         next_iteration:
391           if(wildc_dst)
392             dst = dst->next;
393           else
394             break;
395         }
396       dst = wildc_dst ? ohs_conns : dst;
397       src = wildc_src ? src->next : NULL;
398     }
399
400   return 1;
401  print_usage:
402   printf("link <bi> srcIP dstIP [0-100]");
403   return -1;
404 }
405
406 int
407 ohs_cmd_list(FILE *handle, char *args)
408 {
409   struct ohs_connection *oc = ohs_conns;
410
411   args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
412   
413   if(!strlen(tok_buf) || 
414      !strncmp(tok_buf, "clients", strlen("clients")))
415     {
416       printf("All connected clients:\n");
417       
418       while(oc)
419         {
420           printf("\t%s - Rx: %d Tx: %d LinkCnt: %d\n", olsr_ip_to_string(&oc->ip_addr), 
421                  oc->rx, oc->tx, oc->linkcnt);
422           oc = oc->next;
423         }
424     }
425   else if(!strncmp(tok_buf, "links", strlen("links")))
426     {
427       printf("All configured links:\n");
428       
429       while(oc)
430         {
431           struct ohs_ip_link *links = oc->links;
432
433           while(links)
434             {
435               printf("\t%s => %s Quality: %d\n", 
436                      olsr_ip_to_string(&oc->ip_addr),
437                      olsr_ip_to_string(&links->dst),
438                      links->quality);
439
440               links = links->next;
441             }
442           oc = oc->next;
443         }
444     }
445   else
446     {
447
448       printf("list [clients|links]");
449       return -1;
450     }
451
452   return 1;
453 }
454
455 int
456 ohs_cmd_help(FILE *handle, char *args)
457 {
458   int i;
459
460   args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
461   
462   if(!strlen(tok_buf))
463     {
464       printf("Olsrd host switch version %s\n", OHS_VERSION);
465       printf("Available commands:\n");
466       
467       for(i = 0; ohs_commands[i].cmd; i++)
468         {
469           if(ohs_commands[i].helptext_brief)
470             printf("\t%s - %s\n", 
471                    ohs_commands[i].cmd,
472                    ohs_commands[i].helptext_brief);
473         }
474       printf("\nType 'help cmd' for help on a specific command\n");
475     }
476   else
477     {
478       for(i = 0; ohs_commands[i].cmd; i++)
479         {
480           if(!strncmp(tok_buf, ohs_commands[i].cmd, strlen(ohs_commands[i].cmd)))
481             {
482               printf("Usage: %s\nDescription:\n%s\n", 
483                      ohs_commands[i].syntax,
484                      ohs_commands[i].helptext_long);
485               return 1;
486             }
487         }
488
489       printf("Usage: help <command>\n");
490     }
491
492   return i;
493 }
494
495 int
496 ohs_cmd_log(FILE *handle, char *args)
497 {
498   olsr_u8_t set = 0;
499
500   args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
501   
502   if(strlen(tok_buf) &&
503      ((set = !strncmp(tok_buf, "set", strlen("set"))) || 
504       !strncmp(tok_buf, "unset", strlen("unset"))))
505     {
506         olsr_u32_t new_bit = 0;
507         
508         args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
509   
510         if(!strlen(tok_buf))
511             goto print_usage;
512         
513         
514         if(!strncmp(tok_buf, "CON", strlen("CON")))
515             new_bit = LOG_CONNECT;
516         else if(!strncmp(tok_buf, "FOR", strlen("FOR")))
517             new_bit = LOG_FORWARD;
518         else if(!strncmp(tok_buf, "LIN", strlen("LIN")))
519             new_bit = LOG_LINK;
520           
521         if(!new_bit)
522             goto print_usage;
523
524         if(set)
525             logbits |= new_bit;
526         else
527             logbits &= ~new_bit;
528
529         printf("%s log bit: 0x%08x, new log: 0x%08x\n", set ? "Setting" : "Removing",
530                new_bit, logbits);
531
532     }
533   else
534     {
535       if(strlen(tok_buf))
536         goto print_usage;
537
538       printf("Log: (0x%08x) ", logbits);
539       if(logbits & LOG_CONNECT)
540         printf("CONNECT ");
541       if(logbits & LOG_FORWARD)
542         printf("FORWARD ");
543       if(logbits & LOG_LINK)
544         printf("LINK ");
545
546       printf("\n");
547     }
548   return 1;
549
550  print_usage:
551   printf("Usage: log <[set|unset] [CONNECT|FORWARD|LINK]>\n");
552   return 0;
553
554 }
555
556 int
557 ohs_cmd_exit(FILE *handle, char *args)
558 {
559
560   printf("Exitting... bye-bye!\n");
561
562   ohs_close(0);
563   return 0;
564 }
565
566 int
567 ohs_parse_command(FILE *handle)
568 {
569   char input_data[100];
570   int i;
571
572   fscanf(handle, "%s", input_data);
573
574   get_arg_buf(handle, arg_buf, ARG_BUF_SIZE);
575
576   for(i = 0; ohs_commands[i].cmd; i++)
577     {
578       if(!strcmp(input_data, ohs_commands[i].cmd))
579         {
580           if(ohs_commands[i].cmd_cb)
581             {
582               ohs_commands[i].cmd_cb(handle, arg_buf);
583             }
584           else
585             {
586               printf("No action registered on cmd %s!\n", input_data);
587             }
588           break;
589         }
590     }
591   
592   if(!ohs_commands[i].cmd)
593     {
594       printf("%s: no such cmd!\n", input_data);
595     }
596
597
598   return 0;
599 }