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