Added the olsrd command
[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.15 2005/06/04 21:07:33 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   char *olsrd_args[MAX_OLSRD_ARGS];
120   struct in_addr iaddr;
121
122   args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
123
124   if(!strlen(tok_buf))
125     goto print_usage;
126
127   /* Start olsrd instance */
128   if(!strncmp(tok_buf, "start", strlen("start")))
129     {
130       int argc = 0, i = 0;
131
132       args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
133       
134       if(!strlen(tok_buf))
135         goto print_usage;
136
137       if(!inet_aton(tok_buf, &iaddr))
138         {
139           printf("Invalid IP %s\n", tok_buf);
140           goto print_usage;
141         }
142
143       olsrd_args[argc++] = olsrd_path;
144
145       if(1) /* config file is set */
146         {
147           olsrd_args[argc++] = "-f";
148           olsrd_args[argc++] = "/etc/olsrd-emu.conf";
149         }
150       olsrd_args[argc++] = "-hemu";
151       olsrd_args[argc++] = tok_buf;
152
153       olsrd_args[argc++] = "-d";
154       olsrd_args[argc++] = "0";
155       olsrd_args[argc++] = "-nofork";
156       olsrd_args[argc] = NULL;
157
158       printf("Executing: %s", olsrd_path);
159       for(i = 0; i < argc; i++)
160         printf(" %s", olsrd_args[i]);
161       printf("\n");
162
163       if(fork())
164         return 1;
165
166       if(execve(olsrd_path, olsrd_args, NULL) < 0)
167         {
168           printf("Error executing olsrd: %s\n", strerror(errno));
169           exit(1);
170         }
171     }
172   /* Stop olsrd instance */
173   else if(!strncmp(tok_buf, "stop", strlen("stop")))
174     {
175       struct ohs_connection *oc;
176
177       args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
178       
179       if(!strlen(tok_buf))
180         goto print_usage;
181
182       if(!inet_aton(tok_buf, &iaddr))
183         {
184           printf("Invalid IP %s\n", tok_buf);
185           goto print_usage;
186         }
187
188       oc = get_client_by_addr((union olsr_ip_addr *)&iaddr.s_addr);
189
190       if(!oc)
191         {
192           printf("No such client: %s\n", tok_buf);
193           return -1;
194         }
195       ohs_delete_connection(oc);
196       
197       return 1;
198     }
199   /* Set olsrd binary path */
200   else if(!strncmp(tok_buf, "setb", strlen("setb")))
201     {
202       struct stat sbuf;
203
204       args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
205       
206       if(!strlen(tok_buf))
207         goto print_usage;
208
209       if(stat(tok_buf, &sbuf) < 0)
210         {
211           printf("Error setting binary \"%s\": %s\n",
212                  tok_buf, strerror(errno));
213           return -1;
214         }
215
216       if((sbuf.st_mode & S_IFDIR) || !(sbuf.st_mode & S_IXUSR))
217         {
218           printf("Error setting binary \"%s\": Not a regular execuatble file!\n",
219                  tok_buf);
220           return -1;
221         }
222
223       printf("New olsrd binary path:\"%s\"\n", tok_buf);
224       ohs_set_olsrd_path(tok_buf);
225
226       return 1;
227
228     }
229   /* Set arguments */
230   else if(!strncmp(tok_buf, "seta", strlen("seta")))
231     {
232
233     }
234   /* Show settings */
235   else if(!strncmp(tok_buf, "show", strlen("show")))
236     {
237       printf("olsrd command settings:\n\tBinary path: %s\n\tArguments  : \n",
238              olsrd_path);
239       return 1;
240     }
241
242  print_usage:
243   printf("Usage: olsrd [start|stop|show|setb|seta] [IP|path|args]\n");
244   return 0;
245 }
246
247 int
248 ohs_cmd_link(FILE *handle, char *args)
249 {
250   olsr_u8_t bi = 0, wildc_src = 0, wildc_dst = 0;
251   struct ohs_connection *src, *dst;
252   struct in_addr iaddr;
253   int qual;
254   struct ohs_ip_link *link, *inv_link;
255
256   args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
257
258   if(!strlen(tok_buf))
259     goto print_usage;
260
261   if(!strncmp(tok_buf, "bi", strlen("bi")))
262     {
263       bi = 1;
264       args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
265
266       if(!strlen(tok_buf))
267         goto print_usage;
268     }
269
270   if(tok_buf[0] == '*')
271     {
272       wildc_src = 1;
273       src = ohs_conns;
274     }
275   else
276     {
277       if(!inet_aton(tok_buf, &iaddr))
278         {
279           printf("Invalid src IP %s\n", tok_buf);
280           return -1;
281         }
282
283       src = get_client_by_addr((union olsr_ip_addr *)&iaddr.s_addr);
284
285       if(!src)
286         {
287           printf("No such client: %s!\n", tok_buf);
288           return -1;
289         }
290     }
291
292   args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
293   
294   if(!strlen(tok_buf))
295     goto print_usage;
296
297   if(tok_buf[0] == '*')
298     {
299       wildc_dst = 1;
300       dst = ohs_conns;
301     }
302   else
303     {
304       
305       if(!inet_aton(tok_buf, &iaddr))
306         {
307           printf("Invalid src IP %s\n", tok_buf);
308           return -1;
309         }
310       
311       dst = get_client_by_addr((union olsr_ip_addr *)&iaddr.s_addr);
312       if(!dst)
313         {
314           printf("No such client: %s!\n", tok_buf);
315           return -1;
316         }
317     }
318
319   args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
320   
321   if(!strlen(tok_buf))
322     goto print_usage;
323
324   /* No use for bi if both src and dst are widcards */
325   if(wildc_src && wildc_dst)
326     {
327       bi = 0;
328     }
329
330   qual = atoi(tok_buf);
331
332   if(qual < 0 || qual > 100)
333     {
334       printf("Link quality out of range(0-100)\n");
335       return -1;
336     }
337
338   while(src)
339     {
340
341       while(dst)
342         {
343
344           if(src == dst)
345             goto next_iteration;
346
347           link = get_link(src, &dst->ip_addr);
348           
349           inv_link = bi ? get_link(dst, &src->ip_addr) : NULL;
350           
351           if(qual == 100)
352             {
353               /* Remove link entry */
354               if(link)
355                 remove_link(src, link);
356               if(inv_link)
357                 remove_link(dst, inv_link);
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
380           printf("%s %sdirectional link(s) %s %c=> %s quality %d\n", 
381                  (qual == 100) ? "Removing" : "Setting", bi ? "bi" : "uni",
382                  olsr_ip_to_string(&src->ip_addr), bi ? '<' : '=', 
383                  olsr_ip_to_string(&dst->ip_addr), qual);
384
385         next_iteration:
386           if(wildc_dst)
387             dst = dst->next;
388           else
389             break;
390         }
391       dst = wildc_dst ? ohs_conns : dst;
392       src = wildc_src ? src->next : NULL;
393     }
394
395   return 1;
396  print_usage:
397   printf("link <bi> srcIP dstIP [0-100]");
398   return -1;
399 }
400
401 int
402 ohs_cmd_list(FILE *handle, char *args)
403 {
404   struct ohs_connection *oc = ohs_conns;
405
406   args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
407   
408   if(!strlen(tok_buf) || 
409      !strncmp(tok_buf, "clients", strlen("clients")))
410     {
411       printf("All connected clients:\n");
412       
413       while(oc)
414         {
415           printf("\t%s - Rx: %d Tx: %d LinkCnt: %d\n", olsr_ip_to_string(&oc->ip_addr), 
416                  oc->rx, oc->tx, oc->linkcnt);
417           oc = oc->next;
418         }
419     }
420   else if(!strncmp(tok_buf, "links", strlen("links")))
421     {
422       printf("All configured links:\n");
423       
424       while(oc)
425         {
426           struct ohs_ip_link *links = oc->links;
427
428           while(links)
429             {
430               printf("\t%s => %s Quality: %d\n", 
431                      olsr_ip_to_string(&oc->ip_addr),
432                      olsr_ip_to_string(&links->dst),
433                      links->quality);
434
435               links = links->next;
436             }
437           oc = oc->next;
438         }
439     }
440   else
441     {
442
443       printf("list [clients|links]");
444       return -1;
445     }
446
447   return 1;
448 }
449
450 int
451 ohs_cmd_help(FILE *handle, char *args)
452 {
453   int i;
454
455   args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
456   
457   if(!strlen(tok_buf))
458     {
459       printf("Olsrd host switch version %s\n", OHS_VERSION);
460       printf("Available commands:\n");
461       
462       for(i = 0; ohs_commands[i].cmd; i++)
463         {
464           if(ohs_commands[i].helptext_brief)
465             printf("\t%s - %s\n", 
466                    ohs_commands[i].cmd,
467                    ohs_commands[i].helptext_brief);
468         }
469       printf("\nType 'help cmd' for help on a specific command\n");
470     }
471   else
472     {
473       for(i = 0; ohs_commands[i].cmd; i++)
474         {
475           if(!strncmp(tok_buf, ohs_commands[i].cmd, strlen(ohs_commands[i].cmd)))
476             {
477               printf("Usage: %s\nDescription:\n%s\n", 
478                      ohs_commands[i].syntax,
479                      ohs_commands[i].helptext_long);
480               return 1;
481             }
482         }
483
484       printf("Usage: help <command>\n");
485     }
486
487   return i;
488 }
489
490 int
491 ohs_cmd_log(FILE *handle, char *args)
492 {
493   olsr_u8_t set = 0;
494
495   args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
496   
497   if(strlen(tok_buf) &&
498      ((set = !strncmp(tok_buf, "set", strlen("set"))) || 
499       !strncmp(tok_buf, "unset", strlen("unset"))))
500     {
501         olsr_u32_t new_bit = 0;
502         
503         args += get_next_token(args, tok_buf, TOK_BUF_SIZE);
504   
505         if(!strlen(tok_buf))
506             goto print_usage;
507         
508         
509         if(!strncmp(tok_buf, "CON", strlen("CON")))
510             new_bit = LOG_CONNECT;
511         else if(!strncmp(tok_buf, "FOR", strlen("FOR")))
512             new_bit = LOG_FORWARD;
513         else if(!strncmp(tok_buf, "LIN", strlen("LIN")))
514             new_bit = LOG_LINK;
515           
516         if(!new_bit)
517             goto print_usage;
518
519         if(set)
520             logbits |= new_bit;
521         else
522             logbits &= ~new_bit;
523
524         printf("%s log bit: 0x%08x, new log: 0x%08x\n", set ? "Setting" : "Removing",
525                new_bit, logbits);
526
527     }
528   else
529     {
530       if(strlen(tok_buf))
531         goto print_usage;
532
533       printf("Log: (0x%08x) ", logbits);
534       if(logbits & LOG_CONNECT)
535         printf("CONNECT ");
536       if(logbits & LOG_FORWARD)
537         printf("FORWARD ");
538       if(logbits & LOG_LINK)
539         printf("LINK ");
540
541       printf("\n");
542     }
543   return 1;
544
545  print_usage:
546   printf("Usage: log <[set|unset] [CONNECT|FORWARD|LINK]>\n");
547   return 0;
548
549 }
550
551 int
552 ohs_cmd_exit(FILE *handle, char *args)
553 {
554
555   printf("Exitting... bye-bye!\n");
556
557   ohs_close(0);
558   return 0;
559 }
560
561 int
562 ohs_parse_command(FILE *handle)
563 {
564   char input_data[100];
565   int i;
566
567   fscanf(handle, "%s", input_data);
568
569   get_arg_buf(handle, arg_buf, ARG_BUF_SIZE);
570
571   for(i = 0; ohs_commands[i].cmd; i++)
572     {
573       if(!strcmp(input_data, ohs_commands[i].cmd))
574         {
575           if(ohs_commands[i].cmd_cb)
576             {
577               ohs_commands[i].cmd_cb(handle, arg_buf);
578             }
579           else
580             {
581               printf("No action registered on cmd %s!\n", input_data);
582             }
583           break;
584         }
585     }
586   
587   if(!ohs_commands[i].cmd)
588     {
589       printf("%s: no such cmd!\n", input_data);
590     }
591
592
593   return 0;
594 }