detect interfaces that are going down (via rtnetlink)
[olsrd.git] / src / main.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in
14  *   the documentation and/or other materials provided with the
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its
17  *   contributors may be used to endorse or promote products derived
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  */
40
41 #include <unistd.h>
42 #include <signal.h>
43 #include <sys/stat.h>
44 #include <assert.h>
45
46 #include "ipcalc.h"
47 #include "defs.h"
48 #include "olsr.h"
49 #include "log.h"
50 #include "scheduler.h"
51 #include "parser.h"
52 #include "generate_msg.h"
53 #include "plugin_loader.h"
54 #include "socket_parser.h"
55 #include "apm.h"
56 #include "net_os.h"
57 #include "build_msg.h"
58 #include "net_olsr.h"
59 #include <fcntl.h>
60
61 #if LINUX_POLICY_ROUTING
62 #include <linux/types.h>
63 #include <linux/rtnetlink.h>
64 #include "kernel_routes.h"
65 #endif
66
67 #ifdef WIN32
68 #define close(x) closesocket(x)
69 int __stdcall SignalHandler(unsigned long signo) __attribute__ ((noreturn));
70 void ListInterfaces(void);
71 void DisableIcmpRedirects(void);
72 bool olsr_win32_end_request = false;
73 bool olsr_win32_end_flag = false;
74 #else
75 static void olsr_shutdown(int) __attribute__ ((noreturn));
76 #endif
77
78 /*
79  * Local function prototypes
80  */
81 void olsr_reconfigure(int) __attribute__ ((noreturn));
82
83 static void print_usage(void);
84
85 static int set_default_ifcnfs(struct olsr_if *, struct if_config_options *);
86
87 static int olsr_process_arguments(int, char *[], struct olsrd_config *,
88     struct if_config_options *);
89
90 #ifndef WIN32
91 static char **olsr_argv;
92 #endif
93
94 static char
95     copyright_string[] __attribute__ ((unused)) =
96         "The olsr.org Optimized Link-State Routing daemon(olsrd) Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org) All rights reserved.";
97
98 /* Data for OLSR locking */
99 static int lock_fd = 0;
100 static char lock_file_name[FILENAME_MAX];
101
102 /*
103  * Creates a zero-length locking file and use fcntl to
104  * place an exclusive lock over it. The lock will be
105  * automatically erased when the olsrd process ends,
106  * so it will even work well with a SIGKILL.
107  *
108  * Additionally the lock can be killed by removing the
109  * locking file.
110  */
111 static void olsr_create_lock_file(void) {
112   struct flock lck;
113
114   /* create file for lock */
115   lock_fd = open(lock_file_name, O_WRONLY | O_CREAT);
116   if (lock_fd == 0) {
117     close(lock_fd);
118     fprintf(stderr,
119         "Error, cannot create OLSR lock '%s'.\n",
120         lock_file_name);
121     olsr_exit("", EXIT_FAILURE);
122   }
123
124   /* create exclusive lock for the whole file */
125   lck.l_type = F_WRLCK;
126   lck.l_whence = SEEK_SET;
127   lck.l_start = 0;
128   lck.l_len = 0;
129   lck.l_pid = 0;
130
131   if (fcntl(lock_fd, F_SETLK, &lck) == -1) {
132     close(lock_fd);
133     fprintf(stderr,
134         "Error, cannot aquire OLSR lock '%s'.\n"
135         "Another OLSR instance might be running.\n",
136         lock_file_name);
137     olsr_exit("", EXIT_FAILURE);
138   }
139   return;
140 }
141
142 /**
143  * Main entrypoint
144  */
145
146 int main(int argc, char *argv[]) {
147   struct if_config_options *default_ifcnf;
148   char conf_file_name[FILENAME_MAX];
149   struct ipaddr_str buf;
150 #ifdef WIN32
151   WSADATA WsaData;
152   size_t len;
153 #endif
154
155   /* paranoia checks */
156   assert(sizeof(uint8_t) == 1);
157   assert(sizeof(uint16_t) == 2);
158   assert(sizeof(uint32_t) == 4);
159   assert(sizeof(int8_t) == 1);
160   assert(sizeof(int16_t) == 2);
161   assert(sizeof(int32_t) == 4);
162
163   debug_handle = stdout;
164 #ifndef WIN32
165   olsr_argv = argv;
166 #endif
167   setbuf(stdout, NULL);
168   setbuf(stderr, NULL);
169
170 #ifndef WIN32
171   /* Check if user is root */
172   if (geteuid()) {
173     fprintf(stderr, "You must be root(uid = 0) to run olsrd!\nExiting\n\n");
174     exit(EXIT_FAILURE);
175   }
176 #else
177   DisableIcmpRedirects();
178
179   if (WSAStartup(0x0202, &WsaData)) {
180     fprintf(stderr, "Could not initialize WinSock.\n");
181     olsr_exit(__func__, EXIT_FAILURE);
182   }
183 #endif
184
185   /* Open syslog */
186   olsr_openlog("olsrd");
187
188   printf("\n *** %s ***\n Build date: %s on %s\n http://www.olsr.org\n\n",
189       olsrd_version, build_date, build_host);
190
191   /* Using PID as random seed */
192   srandom(getpid());
193
194   /* Init widely used statics */
195   memset(&all_zero, 0, sizeof(union olsr_ip_addr));
196
197   /*
198    * Set configfile name and
199    * check if a configfile name was given as parameter
200    */
201 #ifdef WIN32
202 #ifndef WINCE
203   GetWindowsDirectory(conf_file_name, FILENAME_MAX - 11);
204 #else
205   conf_file_name[0] = 0;
206 #endif
207
208   len = strlen(conf_file_name);
209
210   if (len == 0 || conf_file_name[len - 1] != '\\')
211   conf_file_name[len++] = '\\';
212
213   strscpy(conf_file_name + len, "olsrd.conf", sizeof(conf_file_name) - len);
214 #else
215   strscpy(conf_file_name, OLSRD_GLOBAL_CONF_FILE, sizeof(conf_file_name));
216 #endif
217
218   if ((argc > 1) && (strcmp(argv[1], "-f") == 0)) {
219     struct stat statbuf;
220
221     argv++;
222     argc--;
223     if (argc == 1) {
224       fprintf(stderr, "You must provide a filename when using the -f switch!\n");
225       exit(EXIT_FAILURE);
226     }
227
228     if (stat(argv[1], &statbuf) < 0) {
229       fprintf(stderr, "Could not find specified config file %s!\n%s\n\n",
230           argv[1], strerror(errno));
231       exit(EXIT_FAILURE);
232     }
233
234     strscpy(conf_file_name, argv[1], sizeof(conf_file_name));
235     argv++;
236     argc--;
237
238   }
239
240   /*
241    * set up configuration prior to processing commandline options
242    */
243   if (NULL == (olsr_cnf = olsrd_parse_cnf(conf_file_name))) {
244     printf("Using default config values(no configfile)\n");
245     olsr_cnf = olsrd_get_default_cnf();
246   }
247
248   default_ifcnf = get_default_if_config();
249   if (default_ifcnf == NULL) {
250     fprintf(stderr, "No default ifconfig found!\n");
251     exit(EXIT_FAILURE);
252   }
253
254   /* Initialize timers */
255   olsr_init_timers();
256
257   /*
258    * Process olsrd options.
259    */
260   if (olsr_process_arguments(argc, argv, olsr_cnf, default_ifcnf) < 0) {
261     print_usage();
262     olsr_exit(__func__, EXIT_FAILURE);
263   }
264
265   /*
266    * Set configuration for command-line specified interfaces
267    */
268   set_default_ifcnfs(olsr_cnf->interfaces, default_ifcnf);
269
270   /* free the default ifcnf */
271   free(default_ifcnf);
272
273   /* Sanity check configuration */
274   if (olsrd_sanity_check_cnf(olsr_cnf) < 0) {
275     fprintf(stderr, "Bad configuration!\n");
276     olsr_exit(__func__, EXIT_FAILURE);
277   }
278
279   /*
280    * Establish file lock to prevent multiple instances
281    */
282   if (olsr_cnf->lock_file) {
283     strscpy(lock_file_name, olsr_cnf->lock_file, sizeof(lock_file_name));
284   } else {
285     strscpy(lock_file_name, conf_file_name, sizeof(lock_file_name));
286     strscat(lock_file_name, ".lock", sizeof(lock_file_name));
287   }
288
289   /*
290    * Print configuration
291    */
292   if (olsr_cnf->debug_level > 1) {
293     olsrd_print_cnf(olsr_cnf);
294   }
295 #ifndef WIN32
296   /* Disable redirects globally */
297   disable_redirects_global(olsr_cnf->ip_version);
298 #endif
299
300   /*
301    * socket for ioctl calls
302    */
303   olsr_cnf->ioctl_s = socket(olsr_cnf->ip_version, SOCK_DGRAM, 0);
304   if (olsr_cnf->ioctl_s < 0) {
305     olsr_syslog(OLSR_LOG_ERR, "ioctl socket: %m");
306     olsr_exit(__func__, 0);
307   }
308 #if LINUX_POLICY_ROUTING
309   olsr_cnf->rtnl_s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
310   if (olsr_cnf->rtnl_s < 0) {
311     olsr_syslog(OLSR_LOG_ERR, "rtnetlink socket: %m");
312     olsr_exit(__func__, 0);
313   }
314   fcntl(olsr_cnf->rtnl_s, F_SETFL, O_NONBLOCK);
315 #endif
316
317   /*
318    * create routing socket
319    */
320 #if defined __FreeBSD__ || __FreeBSD_kernel__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
321   olsr_cnf->rts = socket(PF_ROUTE, SOCK_RAW, 0);
322   if (olsr_cnf->rts < 0) {
323     olsr_syslog(OLSR_LOG_ERR, "routing socket: %m");
324     olsr_exit(__func__, 0);
325   }
326 #endif
327
328   /* Init empty TC timer */
329   set_empty_tc_timer(GET_TIMESTAMP(0));
330
331   /*
332    *enable ip forwarding on host
333    */
334   enable_ip_forwarding(olsr_cnf->ip_version);
335
336   /* Initialize parser */
337   olsr_init_parser();
338
339   /* Initialize route-exporter */
340   olsr_init_export_route();
341
342   /* Initialize message sequencnumber */
343   init_msg_seqno();
344
345   /* Initialize dynamic willingness calculation */
346   olsr_init_willingness();
347
348   /*
349    *Set up willingness/APM
350    */
351   if (olsr_cnf->willingness_auto) {
352     if (apm_init() < 0) {
353       OLSR_PRINTF(1, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT);
354
355       olsr_syslog(OLSR_LOG_ERR,
356           "Could not read APM info - setting default willingness(%d)\n",
357           WILL_DEFAULT);
358
359       olsr_cnf->willingness_auto = 0;
360       olsr_cnf->willingness = WILL_DEFAULT;
361     } else {
362       olsr_cnf->willingness = olsr_calculate_willingness();
363
364       OLSR_PRINTF(1, "Willingness set to %d - next update in %.1f secs\n", olsr_cnf->willingness, olsr_cnf->will_int);
365     }
366   }
367
368   /* Initialize net */
369   init_net();
370
371   /* Initializing networkinterfaces */
372   if (!ifinit()) {
373     if (olsr_cnf->allow_no_interfaces) {
374       fprintf(
375           stderr,
376           "No interfaces detected! This might be intentional, but it also might mean that your configuration is fubar.\nI will continue after 5 seconds...\n");
377       sleep(5);
378     } else {
379       fprintf(stderr, "No interfaces detected!\nBailing out!\n");
380       olsr_exit(__func__, EXIT_FAILURE);
381     }
382   }
383
384   /* Print heartbeat to stdout */
385
386 #if !defined WINCE
387   if (olsr_cnf->debug_level > 0 && isatty(STDOUT_FILENO)) {
388     olsr_start_timer(STDOUT_PULSE_INT, 0, OLSR_TIMER_PERIODIC,
389         &generate_stdout_pulse, NULL, 0);
390   }
391 #endif
392
393   /* Initialize the IPC socket */
394
395   if (olsr_cnf->ipc_connections > 0) {
396     ipc_init();
397   }
398   /* Initialisation of different tables to be used. */
399   olsr_init_tables();
400
401   /* daemon mode */
402 #ifndef WIN32
403   if (olsr_cnf->debug_level == 0 && !olsr_cnf->no_fork) {
404     printf("%s detaching from the current process...\n", olsrd_version);
405     if (daemon(0, 0) < 0) {
406       printf("daemon(3) failed: %s\n", strerror(errno));
407       exit(EXIT_FAILURE);
408     }
409   }
410 #endif
411
412   /*
413    * Create locking file for olsrd, will be cleared after olsrd exits
414    */
415   olsr_create_lock_file();
416
417   /* Load plugins */
418   olsr_load_plugins();
419
420   OLSR_PRINTF(1, "Main address: %s\n\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
421
422 #if LINUX_POLICY_ROUTING
423   /* Create rule for RtTable to resolve route insertion problems*/
424   if ((olsr_cnf->rttable < 253) & (olsr_cnf->rttable > 0)) {
425     olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable, RTM_NEWRULE);
426   }
427
428   /* Create rtnetlink socket to listen on interface change events RTMGRP_LINK and RTMGRP_IPV4_ROUTE */
429
430 #if LINUX_RTNETLINK_LISTEN
431   rtnetlink_register_socket(RTMGRP_LINK);
432 #endif /*LINUX_RTNETLINK_LISTEN*/
433
434 #endif
435
436   /* Start syslog entry */
437   olsr_syslog(OLSR_LOG_INFO, "%s successfully started", olsrd_version);
438
439   /*
440    *signal-handlers
441    */
442
443   /* ctrl-C and friends */
444 #ifdef WIN32
445 #ifndef WINCE
446   SetConsoleCtrlHandler(SignalHandler, true);
447 #endif
448 #else
449   signal(SIGHUP, olsr_reconfigure);
450   signal(SIGINT, olsr_shutdown);
451   signal(SIGQUIT, olsr_shutdown);
452   signal(SIGILL, olsr_shutdown);
453   signal(SIGABRT, olsr_shutdown);
454   //  signal(SIGSEGV, olsr_shutdown);
455   signal(SIGTERM, olsr_shutdown);
456   signal(SIGPIPE, SIG_IGN);
457 #endif
458
459   link_changes = false;
460
461   /* Starting scheduler */
462   olsr_scheduler();
463
464   /* Like we're ever going to reach this ;-) */
465   return 1;
466 } /* main */
467
468 /**
469  * Reconfigure olsrd. Currently kind of a hack...
470  *
471  *@param signal the signal that triggered this callback
472  */
473 #ifndef WIN32
474 void olsr_reconfigure(int signo __attribute__ ((unused))) {
475   /* if we are started with -nofork, we do not weant to go into the
476    * background here. So we can simply stop on -HUP
477    */
478   olsr_syslog(OLSR_LOG_INFO, "sot: olsr_reconfigure()\n");
479   if (!olsr_cnf->no_fork) {
480     if (!fork()) {
481       int i;
482       sigset_t sigs;
483       /* New process */
484       sleep(3);
485       sigemptyset(&sigs);
486       sigaddset(&sigs, SIGHUP);
487       sigprocmask(SIG_UNBLOCK, &sigs, NULL);
488       for (i = sysconf(_SC_OPEN_MAX); --i > STDERR_FILENO;) {
489         close(i);
490       }
491       printf("Restarting %s\n", olsr_argv[0]);
492       olsr_syslog(OLSR_LOG_INFO, "Restarting %s\n", olsr_argv[0]);
493       execv(olsr_argv[0], olsr_argv);
494       olsr_syslog(OLSR_LOG_ERR, "execv(%s) fails: %s!\n", olsr_argv[0],
495           strerror(errno));
496     } else {
497       olsr_syslog(OLSR_LOG_INFO, "RECONFIGURING!\n");
498     }
499   }
500   olsr_shutdown(0);
501 }
502 #endif
503
504 /**
505  *Function called at shutdown. Signal handler
506  *
507  * @param signal the signal that triggered this call
508  */
509 #ifdef WIN32
510 int __stdcall
511 SignalHandler(unsigned long signo)
512 #else
513 static void olsr_shutdown(int signo __attribute__ ((unused)))
514 #endif
515 {
516   struct interface *ifn;
517
518   OLSR_PRINTF(1, "Received signal %d - shutting down\n", (int)signo);
519
520 #ifdef WIN32
521   OLSR_PRINTF(1, "Waiting for the scheduler to stop.\n");
522
523   olsr_win32_end_request = TRUE;
524
525   while (!olsr_win32_end_flag)
526   Sleep(100);
527
528   OLSR_PRINTF(1, "Scheduler stopped.\n");
529 #endif
530
531   olsr_delete_all_kernel_routes();
532
533   OLSR_PRINTF(1, "Closing sockets...\n");
534
535   /* front-end IPC socket */
536   if (olsr_cnf->ipc_connections > 0) {
537     shutdown_ipc();
538   }
539
540   /* OLSR sockets */
541   for (ifn = ifnet; ifn; ifn = ifn->int_next)
542     close(ifn->olsr_socket);
543
544   /* Closing plug-ins */
545   olsr_close_plugins();
546
547   /* Reset network settings */
548   restore_settings(olsr_cnf->ip_version);
549
550   /* ioctl socket */
551   close(olsr_cnf->ioctl_s);
552
553 #if LINUX_POLICY_ROUTING
554   /* RtTable (linux only!!) */
555   if ((olsr_cnf->rttable < 253) & (olsr_cnf->rttable > 0)) {
556     olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable, RTM_DELRULE);
557   }
558
559   close(olsr_cnf->rtnl_s);
560 #endif
561
562 #if defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
563   /* routing socket */
564   close(olsr_cnf->rts);
565 #endif
566
567   /* Free cookies and memory pools attached. */
568   olsr_delete_all_cookies();
569
570   olsr_syslog(OLSR_LOG_INFO, "%s stopped", olsrd_version);
571
572   OLSR_PRINTF(1, "\n <<<< %s - terminating >>>>\n           http://www.olsr.org\n", olsrd_version);
573
574   exit(olsr_cnf->exit_value);
575 }
576
577 /**
578  * Print the command line usage
579  */
580 static void print_usage(void) {
581
582   fprintf(
583       stderr,
584       "An error occured somwhere between your keyboard and your chair!\n"
585         "usage: olsrd [-f <configfile>] [ -i interface1 interface2 ... ]\n"
586         "  [-d <debug_level>] [-ipv6] [-multi <IPv6 multicast address>]\n"
587         "  [-lql <LQ level>] [-lqw <LQ winsize>] [-lqnt <nat threshold>]\n"
588         "  [-bcast <broadcastaddr>] [-ipc] [-dispin] [-dispout] [-delgw]\n"
589         "  [-hint <hello interval (secs)>] [-tcint <tc interval (secs)>]\n"
590         "  [-midint <mid interval (secs)>] [-hnaint <hna interval (secs)>]\n"
591         "  [-T <Polling Rate (secs)>] [-nofork] [-hemu <ip_address>]\n" "  [-lql <LQ level>] [-lqa <LQ aging factor>]\n");
592 }
593
594 /**
595  * Sets the provided configuration on all unconfigured
596  * interfaces
597  *
598  * @param ifs a linked list of interfaces to check and possible update
599  * @param cnf the default configuration to set on unconfigured interfaces
600  */
601 int set_default_ifcnfs(struct olsr_if *ifs, struct if_config_options *cnf) {
602   int changes = 0;
603
604   while (ifs) {
605     if (ifs->cnf == NULL) {
606       ifs->cnf = olsr_malloc(sizeof(struct if_config_options),
607           "Set default config");
608       *ifs->cnf = *cnf;
609       changes++;
610     }
611     ifs = ifs->next;
612   }
613   return changes;
614 }
615
616 #define NEXT_ARG do { argv++;argc--; } while (0)
617 #define CHECK_ARGC do { if(!argc) { \
618       if((argc - 1) == 1){ \
619       fprintf(stderr, "Error parsing command line options!\n"); \
620       } else { \
621       argv--; \
622       fprintf(stderr, "You must provide a parameter when using the %s switch!\n", *argv); \
623      } \
624      olsr_exit(__func__, EXIT_FAILURE); \
625      } } while (0)
626
627 /**
628  * Process command line arguments passed to olsrd
629  *
630  */
631 static int olsr_process_arguments(int argc, char *argv[],
632     struct olsrd_config *cnf, struct if_config_options *ifcnf) {
633   while (argc > 1) {
634     NEXT_ARG;
635 #ifdef WIN32
636     /*
637      *Interface list
638      */
639     if (strcmp(*argv, "-int") == 0) {
640       ListInterfaces();
641       exit(0);
642     }
643 #endif
644
645     /*
646      *Configfilename
647      */
648     if (strcmp(*argv, "-f") == 0) {
649       fprintf(stderr, "Configfilename must ALWAYS be first argument!\n\n");
650       olsr_exit(__func__, EXIT_FAILURE);
651     }
652
653     /*
654      *Use IP version 6
655      */
656     if (strcmp(*argv, "-ipv6") == 0) {
657       cnf->ip_version = AF_INET6;
658       continue;
659     }
660
661     /*
662      *Broadcast address
663      */
664     if (strcmp(*argv, "-bcast") == 0) {
665       struct in_addr in;
666       NEXT_ARG;
667       CHECK_ARGC;
668
669       if (inet_aton(*argv, &in) == 0) {
670         printf("Invalid broadcast address! %s\nSkipping it!\n", *argv);
671         continue;
672       }
673       memcpy(&ifcnf->ipv4_broadcast.v4, &in.s_addr, sizeof(uint32_t));
674       continue;
675     }
676
677     /*
678      * Set LQ level
679      */
680     if (strcmp(*argv, "-lql") == 0) {
681       int tmp_lq_level;
682       NEXT_ARG;
683       CHECK_ARGC;
684
685       /* Sanity checking is done later */
686       sscanf(*argv, "%d", &tmp_lq_level);
687       olsr_cnf->lq_level = tmp_lq_level;
688       continue;
689     }
690
691     /*
692      * Set LQ winsize
693      */
694     if (strcmp(*argv, "-lqa") == 0) {
695       float tmp_lq_aging;
696       NEXT_ARG;
697       CHECK_ARGC;
698
699       sscanf(*argv, "%f", &tmp_lq_aging);
700
701       if (tmp_lq_aging < MIN_LQ_AGING || tmp_lq_aging > MAX_LQ_AGING) {
702         printf("LQ aging factor %f not allowed. Range [%f-%f]\n", tmp_lq_aging,
703             MIN_LQ_AGING, MAX_LQ_AGING);
704         olsr_exit(__func__, EXIT_FAILURE);
705       }
706       olsr_cnf->lq_aging = tmp_lq_aging;
707       continue;
708     }
709
710     /*
711      * Set NAT threshold
712      */
713     if (strcmp(*argv, "-lqnt") == 0) {
714       float tmp_lq_nat_thresh;
715       NEXT_ARG;
716       CHECK_ARGC;
717
718       sscanf(*argv, "%f", &tmp_lq_nat_thresh);
719
720       if (tmp_lq_nat_thresh < 0.1 || tmp_lq_nat_thresh > 1.0) {
721         printf("NAT threshold %f not allowed. Range [%f-%f]\n",
722             tmp_lq_nat_thresh, 0.1, 1.0);
723         olsr_exit(__func__, EXIT_FAILURE);
724       }
725       olsr_cnf->lq_nat_thresh = tmp_lq_nat_thresh;
726       continue;
727     }
728
729     /*
730      * Enable additional debugging information to be logged.
731      */
732     if (strcmp(*argv, "-d") == 0) {
733       NEXT_ARG;
734       CHECK_ARGC;
735
736       sscanf(*argv, "%d", &cnf->debug_level);
737       continue;
738     }
739
740     /*
741      * Interfaces to be used by olsrd.
742      */
743     if (strcmp(*argv, "-i") == 0) {
744       NEXT_ARG;
745       CHECK_ARGC;
746
747       if (*argv[0] == '-') {
748         fprintf(stderr, "You must provide an interface label!\n");
749         olsr_exit(__func__, EXIT_FAILURE);
750       }
751       printf("Queuing if %s\n", *argv);
752       queue_if(*argv, false);
753
754       while ((argc - 1) && (argv[1][0] != '-')) {
755         NEXT_ARG;
756         printf("Queuing if %s\n", *argv);
757         queue_if(*argv, false);
758       }
759
760       continue;
761     }
762     /*
763      * Set the hello interval to be used by olsrd.
764      *
765      */
766     if (strcmp(*argv, "-hint") == 0) {
767       NEXT_ARG;
768       CHECK_ARGC;
769       sscanf(*argv, "%f", &ifcnf->hello_params.emission_interval);
770       ifcnf->hello_params.validity_time = ifcnf->hello_params.emission_interval
771           * 3;
772       continue;
773     }
774
775     /*
776      * Set the HNA interval to be used by olsrd.
777      *
778      */
779     if (strcmp(*argv, "-hnaint") == 0) {
780       NEXT_ARG;
781       CHECK_ARGC;
782       sscanf(*argv, "%f", &ifcnf->hna_params.emission_interval);
783       ifcnf->hna_params.validity_time = ifcnf->hna_params.emission_interval * 3;
784       continue;
785     }
786
787     /*
788      * Set the MID interval to be used by olsrd.
789      *
790      */
791     if (strcmp(*argv, "-midint") == 0) {
792       NEXT_ARG;
793       CHECK_ARGC;
794       sscanf(*argv, "%f", &ifcnf->mid_params.emission_interval);
795       ifcnf->mid_params.validity_time = ifcnf->mid_params.emission_interval * 3;
796       continue;
797     }
798
799     /*
800      * Set the tc interval to be used by olsrd.
801      *
802      */
803     if (strcmp(*argv, "-tcint") == 0) {
804       NEXT_ARG;
805       CHECK_ARGC;
806       sscanf(*argv, "%f", &ifcnf->tc_params.emission_interval);
807       ifcnf->tc_params.validity_time = ifcnf->tc_params.emission_interval * 3;
808       continue;
809     }
810
811     /*
812      * Set the polling interval to be used by olsrd.
813      */
814     if (strcmp(*argv, "-T") == 0) {
815       NEXT_ARG;
816       CHECK_ARGC;
817       sscanf(*argv, "%f", &cnf->pollrate);
818       continue;
819     }
820
821     /*
822      * Should we display the contents of packages beeing sent?
823      */
824     if (strcmp(*argv, "-dispin") == 0) {
825       parser_set_disp_pack_in(true);
826       continue;
827     }
828
829     /*
830      * Should we display the contents of incoming packages?
831      */
832     if (strcmp(*argv, "-dispout") == 0) {
833       net_set_disp_pack_out(true);
834       continue;
835     }
836
837     /*
838      * Should we set up and send on a IPC socket for the front-end?
839      */
840     if (strcmp(*argv, "-ipc") == 0) {
841       cnf->ipc_connections = 1;
842       continue;
843     }
844
845     /*
846      * IPv6 multicast addr
847      */
848     if (strcmp(*argv, "-multi") == 0) {
849       struct in6_addr in6;
850       NEXT_ARG;
851       CHECK_ARGC;
852       if (inet_pton(AF_INET6, *argv, &in6) <= 0) {
853         fprintf(stderr, "Failed converting IP address %s\n", *argv);
854         exit(EXIT_FAILURE);
855       }
856
857       memcpy(&ifcnf->ipv6_multi_glbl, &in6, sizeof(struct in6_addr));
858
859       continue;
860     }
861
862     /*
863      * Host emulation
864      */
865     if (strcmp(*argv, "-hemu") == 0) {
866       struct in_addr in;
867       struct olsr_if *ifa;
868
869       NEXT_ARG;
870       CHECK_ARGC;
871       if (inet_pton(AF_INET, *argv, &in) <= 0) {
872         fprintf(stderr, "Failed converting IP address %s\n", *argv);
873         exit(EXIT_FAILURE);
874       }
875       /* Add hemu interface */
876
877       ifa = queue_if("hcif01", true);
878
879       if (!ifa)
880         continue;
881
882       ifa->cnf = get_default_if_config();
883       ifa->host_emul = true;
884       memcpy(&ifa->hemu_ip, &in, sizeof(union olsr_ip_addr));
885       cnf->host_emul = true;
886
887       continue;
888     }
889
890     /*
891      * Delete possible default GWs
892      */
893     if (strcmp(*argv, "-delgw") == 0) {
894       olsr_cnf->del_gws = true;
895       continue;
896     }
897
898     if (strcmp(*argv, "-nofork") == 0) {
899       cnf->no_fork = true;
900       continue;
901     }
902
903     return -1;
904   }
905   return 0;
906 }
907
908 /*
909  * Local Variables:
910  * c-basic-offset: 2
911  * indent-tabs-mode: nil
912  * End:
913  */