* fixed warnings
[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.23 2007/07/28 12:53:15 bernd67 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 TOK_BUF_SIZE 500
59 static char tok_buf[TOK_BUF_SIZE];
60
61 #define MAX_OLSRD_ARGS 10
62 static char olsrd_path[FILENAME_MAX];
63
64 static int
65 get_next_token(char *src, char *dst, size_t buflen)
66 {
67   int i = 0, j = 0;
68
69   dst[0] = 0;
70   /* Skip leading spaces */
71   while(src[j] == ' ' && src[j] != 0)
72     {
73       j++;
74     }
75
76   src += j;
77   i = 0;
78   while((src[i] != ' ') && (src[i] != 0) && (i < ((int)buflen - 1)))
79     {
80       dst[i] = src[i];
81       i++;
82     }
83   dst[i] = 0;
84
85   //if(strlen(dst))
86   //printf("Extracted token: %s\n", dst);
87   return i + j;
88 }
89
90 int
91 ohs_set_olsrd_path(char *path)
92 {
93   strncpy(olsrd_path, path, FILENAME_MAX);
94   return 0;
95 }
96
97 int
98 ohs_cmd_olsrd(char *args)
99 {
100 #ifdef WIN32
101   printf("olsrd command not available in windows version\nStart instances manually\n");
102   return 0;
103 #else
104   char *olsrd_args[MAX_OLSRD_ARGS];
105   struct in_addr iaddr;
106
107   args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
108
109   if(!strlen(tok_buf))
110     goto print_usage;
111
112   /* Start olsrd instance */
113   if(!strncmp(tok_buf, "start", strlen("start")))
114     {
115       int argc = 0, i = 0;
116
117       args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
118       
119       if(!strlen(tok_buf))
120         goto print_usage;
121
122       if(!inet_aton(tok_buf, &iaddr))
123         {
124           printf("Invalid IP %s\n", tok_buf);
125           goto print_usage;
126         }
127
128       olsrd_args[argc++] = olsrd_path;
129
130       if(1) /* config file is set */
131         {
132           olsrd_args[argc++] = "-f";
133           olsrd_args[argc++] = "/etc/olsrd-emu.conf";
134         }
135       olsrd_args[argc++] = "-hemu";
136       olsrd_args[argc++] = tok_buf;
137
138       olsrd_args[argc++] = "-d";
139       olsrd_args[argc++] = "0";
140       olsrd_args[argc++] = "-nofork";
141       olsrd_args[argc] = NULL;
142
143       printf("Executing: %s", olsrd_path);
144       for(i = 0; i < argc; i++)
145         printf(" %s", olsrd_args[i]);
146       printf("\n");
147
148       if(fork())
149         return 1;
150
151       if(execve(olsrd_path, olsrd_args, NULL) < 0)
152         {
153           printf("Error executing olsrd: %s\n", strerror(errno));
154           exit(1);
155         }
156     }
157   /* Stop olsrd instance */
158   else if(!strncmp(tok_buf, "stop", strlen("stop")))
159     {
160       struct ohs_connection *oc;
161
162       args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
163       
164       if(!strlen(tok_buf))
165         goto print_usage;
166
167       if(!inet_aton(tok_buf, &iaddr))
168         {
169           printf("Invalid IP %s\n", tok_buf);
170           goto print_usage;
171         }
172
173       oc = get_client_by_addr((union olsr_ip_addr *)&iaddr.s_addr);
174
175       if(!oc)
176         {
177           printf("No such client: %s\n", tok_buf);
178           return -1;
179         }
180       ohs_delete_connection(oc);
181       
182       return 1;
183     }
184   /* Set olsrd binary path */
185   else if(!strncmp(tok_buf, "setb", strlen("setb")))
186     {
187       struct stat sbuf;
188
189       args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
190       
191       if(!strlen(tok_buf))
192         goto print_usage;
193
194       if(stat(tok_buf, &sbuf) < 0)
195         {
196           printf("Error setting binary \"%s\": %s\n",
197                  tok_buf, strerror(errno));
198           return -1;
199         }
200
201       if((sbuf.st_mode & S_IFDIR) || !(sbuf.st_mode & S_IXUSR))
202         {
203           printf("Error setting binary \"%s\": Not a regular execuatble file!\n",
204                  tok_buf);
205           return -1;
206         }
207
208       printf("New olsrd binary path:\"%s\"\n", tok_buf);
209       ohs_set_olsrd_path(tok_buf);
210
211       return 1;
212
213     }
214   /* Set arguments */
215   else if(!strncmp(tok_buf, "seta", strlen("seta")))
216     {
217         printf("Error - NOT IMPLEMENTED YET\n");
218         return 1;
219     }
220   /* Show settings */
221   else if(!strncmp(tok_buf, "show", strlen("show")))
222     {
223       printf("olsrd command settings:\n\tBinary path: %s\n\tArguments  : \n",
224              olsrd_path);
225       return 1;
226     }
227
228  print_usage:
229   printf("Usage: olsrd [start|stop|show|setb|seta] [IP|path|args]\n");
230   return 0;
231 #endif
232 }
233
234 int
235 ohs_cmd_link(char *args)
236 {
237   olsr_u8_t bi = 0, wildc_src = 0, wildc_dst = 0;
238   struct ohs_connection *src, *dst;
239   struct in_addr iaddr;
240   int qual;
241   struct ohs_ip_link *link, *inv_link;
242
243   args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
244
245   if(!strlen(tok_buf))
246     goto print_usage;
247
248   if(!strncmp(tok_buf, "bi", strlen("bi")))
249     {
250       bi = 1;
251       args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
252
253       if(!strlen(tok_buf))
254         goto print_usage;
255     }
256
257   if(tok_buf[0] == '*')
258     {
259       wildc_src = 1;
260       src = ohs_conns;
261     }
262   else
263     {
264       if(!inet_aton(tok_buf, &iaddr))
265         {
266           printf("Invalid src IP %s\n", tok_buf);
267           return -1;
268         }
269
270       src = get_client_by_addr((union olsr_ip_addr *)&iaddr.s_addr);
271
272       if(!src)
273         {
274           printf("No such client: %s!\n", tok_buf);
275           return -1;
276         }
277     }
278
279   args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
280   
281   if(!strlen(tok_buf))
282     goto print_usage;
283
284   if(tok_buf[0] == '*')
285     {
286       wildc_dst = 1;
287       dst = ohs_conns;
288     }
289   else
290     {
291       
292       if(!inet_aton(tok_buf, &iaddr))
293         {
294           printf("Invalid src IP %s\n", tok_buf);
295           return -1;
296         }
297       
298       dst = get_client_by_addr((union olsr_ip_addr *)&iaddr.s_addr);
299       if(!dst)
300         {
301           printf("No such client: %s!\n", tok_buf);
302           return -1;
303         }
304     }
305
306   args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
307   
308   if(!strlen(tok_buf))
309     goto print_usage;
310
311   /* No use for bi if both src and dst are widcards */
312   if(wildc_src && wildc_dst)
313     {
314       bi = 0;
315     }
316
317   qual = atoi(tok_buf);
318
319   if(qual < 0 || qual > 100)
320     {
321       printf("Link quality out of range(0-100)\n");
322       return -1;
323     }
324
325   while(src)
326     {
327
328       while(dst)
329         {
330
331           if(src == dst)
332             goto next_iteration;
333
334           link = get_link(src, &dst->ip_addr);
335           
336           inv_link = bi ? get_link(dst, &src->ip_addr) : NULL;
337           
338           if(qual == 100)
339             {
340               /* Remove link entry */
341               if(link)
342                 remove_link(src, link);
343               if(inv_link)
344                 remove_link(dst, inv_link);
345             }
346           else 
347             {
348               if(!link)
349                 {
350                   /* Create new link */
351                   link = add_link(src, dst);
352                 }
353               
354               link->quality = qual;
355               
356               if(bi)
357                 {
358                   if(!inv_link)
359                     {
360                       /* Create new link */
361                       inv_link = add_link(dst, src);
362                     }
363                   inv_link->quality = qual;
364                 }
365             }
366
367           printf("%s %sdirectional link(s) %s %c=> %s quality %d\n", 
368                  (qual == 100) ? "Removing" : "Setting", bi ? "bi" : "uni",
369                  olsr_ip_to_string(&src->ip_addr), bi ? '<' : '=', 
370                  olsr_ip_to_string(&dst->ip_addr), qual);
371
372         next_iteration:
373           if(wildc_dst)
374             dst = dst->next;
375           else
376             break;
377         }
378       dst = wildc_dst ? ohs_conns : dst;
379       src = wildc_src ? src->next : NULL;
380     }
381
382   return 1;
383  print_usage:
384   printf("link <bi> srcIP dstIP [0-100]");
385   return -1;
386 }
387
388 int
389 ohs_cmd_list(char *args)
390 {
391   struct ohs_connection *oc = ohs_conns;
392
393   args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
394   
395   if(!strlen(tok_buf) || 
396      !strncmp(tok_buf, "clients", strlen("clients")))
397     {
398       printf("All connected clients:\n");
399       
400       while(oc)
401         {
402           printf("\t%s - Rx: %d Tx: %d LinkCnt: %d\n", olsr_ip_to_string(&oc->ip_addr), 
403                  oc->rx, oc->tx, oc->linkcnt);
404           oc = oc->next;
405         }
406     }
407   else if(!strncmp(tok_buf, "links", strlen("links")))
408     {
409       printf("All configured links:\n");
410       
411       while(oc)
412         {
413           struct ohs_ip_link *links = oc->links;
414
415           while(links)
416             {
417               printf("\t%s => %s Quality: %d\n", 
418                      olsr_ip_to_string(&oc->ip_addr),
419                      olsr_ip_to_string(&links->dst),
420                      links->quality);
421
422               links = links->next;
423             }
424           oc = oc->next;
425         }
426     }
427   else
428     {
429
430       printf("list [clients|links]");
431       return -1;
432     }
433
434   return 1;
435 }
436
437 int
438 ohs_cmd_help(char *args)
439 {
440   int i;
441
442   args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
443   
444   if(!strlen(tok_buf))
445     {
446       printf("Olsrd host switch version %s\n", OHS_VERSION);
447       printf("Available commands:\n");
448       
449       for(i = 0; ohs_commands[i].cmd; i++)
450         {
451           if(ohs_commands[i].helptext_brief)
452             printf("\t%s - %s\n", 
453                    ohs_commands[i].cmd,
454                    ohs_commands[i].helptext_brief);
455         }
456       printf("\nType 'help cmd' for help on a specific command\n");
457     }
458   else
459     {
460       for(i = 0; ohs_commands[i].cmd; i++)
461         {
462           if(!strncmp(tok_buf, ohs_commands[i].cmd, strlen(ohs_commands[i].cmd)))
463             {
464               printf("Usage: %s\nDescription:\n%s\n", 
465                      ohs_commands[i].syntax,
466                      ohs_commands[i].helptext_long);
467               return 1;
468             }
469         }
470
471       printf("Usage: help <command>\n");
472     }
473
474   return i;
475 }
476
477 int
478 ohs_cmd_log(char *args)
479 {
480   olsr_u8_t set = 0;
481
482   args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
483   
484   if(strlen(tok_buf) &&
485      ((set = !strncmp(tok_buf, "set", strlen("set"))) || 
486       !strncmp(tok_buf, "unset", strlen("unset"))))
487     {
488         olsr_u32_t new_bit = 0;
489         
490         args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
491   
492         if(!strlen(tok_buf))
493             goto print_usage;
494         
495         
496         if(!strncmp(tok_buf, "CON", strlen("CON")))
497             new_bit = LOG_CONNECT;
498         else if(!strncmp(tok_buf, "FOR", strlen("FOR")))
499             new_bit = LOG_FORWARD;
500         else if(!strncmp(tok_buf, "LIN", strlen("LIN")))
501             new_bit = LOG_LINK;
502           
503         if(!new_bit)
504             goto print_usage;
505
506         if(set)
507             logbits |= new_bit;
508         else
509             logbits &= ~new_bit;
510
511         printf("%s log bit: 0x%08x, new log: 0x%08x\n", set ? "Setting" : "Removing",
512                new_bit, logbits);
513
514     }
515   else
516     {
517       if(strlen(tok_buf))
518         goto print_usage;
519
520       printf("Log: (0x%08x) ", logbits);
521       if(logbits & LOG_CONNECT)
522         printf("CONNECT ");
523       if(logbits & LOG_FORWARD)
524         printf("FORWARD ");
525       if(logbits & LOG_LINK)
526         printf("LINK ");
527
528       printf("\n");
529     }
530   return 1;
531
532  print_usage:
533   printf("Usage: log <[set|unset] [CONNECT|FORWARD|LINK]>\n");
534   return 0;
535
536 }
537
538 int
539 ohs_cmd_exit(char *args __attribute__((unused)))
540 {
541
542   printf("Exitting... bye-bye!\n");
543
544   ohs_close(0);
545 }
546
547 void
548 ohs_parse_command(void)
549 {
550   static char cmd_line[500];
551   static int cmd_len = 0;
552   char *args;
553   char cmd_token[20];
554   int i;
555 #if defined WIN32
556   char c;
557   unsigned long Read;
558   INPUT_RECORD InRec;
559   KEY_EVENT_RECORD *KeyEventRec;
560 #endif
561
562 #if defined WIN32
563   if (!ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &InRec, sizeof (InRec), &Read))
564   {
565     fprintf(stderr, "ReadConsoleInput failed: %s\n", strerror(GetLastError()));
566     return;
567   }
568
569   if (InRec.EventType != KEY_EVENT)
570     return;
571
572   KeyEventRec = &InRec.Event.KeyEvent;
573
574   if (!KeyEventRec->bKeyDown)
575     return;
576
577   c = KeyEventRec->uChar.AsciiChar;
578
579   if (c == 8)
580   {
581     if (cmd_len == 0)
582       return;
583
584     cmd_len--;
585
586     fputc(8, stdout);
587     fputc(32, stdout);
588     fputc(8, stdout);
589
590     fflush(stdout);
591
592     return;
593   }
594
595   fputc(c, stdout);
596   fflush(stdout);
597
598   if (c != '\n' && c != '\r' && cmd_len < (int)sizeof (cmd_line) - 1)
599     cmd_line[cmd_len++] = (char)c;
600
601   else
602 #else
603   if(fgets(cmd_line, sizeof (cmd_line), stdin) == NULL) {
604     ohs_cmd_exit(NULL);
605   }
606
607   for (cmd_len = 0; cmd_line[cmd_len] != 0 && cmd_line[cmd_len] != '\n';
608        cmd_len++);
609 #endif
610
611   {
612     cmd_line[cmd_len] = 0;
613     cmd_len = 0;
614
615     args = cmd_line + get_next_token(cmd_line, cmd_token, sizeof (cmd_token));
616
617     for (i = 0; ohs_commands[i].cmd != NULL; i++)
618     {
619       if (strcmp(cmd_token, ohs_commands[i].cmd) == 0)
620       {
621         if(ohs_commands[i].cmd_cb != NULL)
622           ohs_commands[i].cmd_cb(args);
623
624         else
625           printf("No action registered on cmd %s!\n", cmd_token);
626
627         break;
628       }
629     }
630   
631     if(ohs_commands[i].cmd == NULL)
632       printf("%s: no such cmd!\n", cmd_token);
633
634     printf("\n> ");
635     fflush(stdout);
636   }
637 }