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