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