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