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