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