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