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