Use two sockets, one for input and one for output bound to the outgoing IP.
[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     close(ifn->send_socket);
563   }
564
565   /* Closing plug-ins */
566   olsr_close_plugins();
567
568   /* Reset network settings */
569   restore_settings(olsr_cnf->ip_version);
570
571   /* ioctl socket */
572   close(olsr_cnf->ioctl_s);
573
574 #if LINUX_POLICY_ROUTING
575   /* RtTable (linux only!!) */
576   if ((olsr_cnf->rttable < 253) & (olsr_cnf->rttable > 0)) {
577     olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable, RTM_DELRULE);
578   }
579
580   close(olsr_cnf->rtnl_s);
581 #endif
582
583 #if defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
584   /* routing socket */
585   close(olsr_cnf->rts);
586 #endif
587
588   /* Free cookies and memory pools attached. */
589   olsr_delete_all_cookies();
590
591   olsr_syslog(OLSR_LOG_INFO, "%s stopped", olsrd_version);
592
593   OLSR_PRINTF(1, "\n <<<< %s - terminating >>>>\n           http://www.olsr.org\n", olsrd_version);
594
595   exit(olsr_cnf->exit_value);
596 }
597
598 /**
599  * Print the command line usage
600  */
601 static void print_usage(void) {
602
603   fprintf(
604       stderr,
605       "An error occured somwhere between your keyboard and your chair!\n"
606         "usage: olsrd [-f <configfile>] [ -i interface1 interface2 ... ]\n"
607         "  [-d <debug_level>] [-ipv6] [-multi <IPv6 multicast address>]\n"
608         "  [-lql <LQ level>] [-lqw <LQ winsize>] [-lqnt <nat threshold>]\n"
609         "  [-bcast <broadcastaddr>] [-ipc] [-dispin] [-dispout] [-delgw]\n"
610         "  [-hint <hello interval (secs)>] [-tcint <tc interval (secs)>]\n"
611         "  [-midint <mid interval (secs)>] [-hnaint <hna interval (secs)>]\n"
612         "  [-T <Polling Rate (secs)>] [-nofork] [-hemu <ip_address>]\n" "  [-lql <LQ level>] [-lqa <LQ aging factor>]\n");
613 }
614
615 /**
616  * Sets the provided configuration on all unconfigured
617  * interfaces
618  *
619  * @param ifs a linked list of interfaces to check and possible update
620  * @param cnf the default configuration to set on unconfigured interfaces
621  */
622 int set_default_ifcnfs(struct olsr_if *ifs, struct if_config_options *cnf) {
623   int changes = 0;
624
625   while (ifs) {
626     if (ifs->cnf == NULL) {
627       ifs->cnf = olsr_malloc(sizeof(struct if_config_options),
628           "Set default config");
629       *ifs->cnf = *cnf;
630       changes++;
631     }
632     ifs = ifs->next;
633   }
634   return changes;
635 }
636
637 #define NEXT_ARG do { argv++;argc--; } while (0)
638 #define CHECK_ARGC do { if(!argc) { \
639       if((argc - 1) == 1){ \
640       fprintf(stderr, "Error parsing command line options!\n"); \
641       } else { \
642       argv--; \
643       fprintf(stderr, "You must provide a parameter when using the %s switch!\n", *argv); \
644      } \
645      olsr_exit(__func__, EXIT_FAILURE); \
646      } } while (0)
647
648 /**
649  * Process command line arguments passed to olsrd
650  *
651  */
652 static int olsr_process_arguments(int argc, char *argv[],
653     struct olsrd_config *cnf, struct if_config_options *ifcnf) {
654   while (argc > 1) {
655     NEXT_ARG;
656 #ifdef WIN32
657     /*
658      *Interface list
659      */
660     if (strcmp(*argv, "-int") == 0) {
661       ListInterfaces();
662       exit(0);
663     }
664 #endif
665
666     /*
667      *Configfilename
668      */
669     if (strcmp(*argv, "-f") == 0) {
670       fprintf(stderr, "Configfilename must ALWAYS be first argument!\n\n");
671       olsr_exit(__func__, EXIT_FAILURE);
672     }
673
674     /*
675      *Use IP version 6
676      */
677     if (strcmp(*argv, "-ipv6") == 0) {
678       cnf->ip_version = AF_INET6;
679       continue;
680     }
681
682     /*
683      *Broadcast address
684      */
685     if (strcmp(*argv, "-bcast") == 0) {
686       struct in_addr in;
687       NEXT_ARG;
688       CHECK_ARGC;
689
690       if (inet_aton(*argv, &in) == 0) {
691         printf("Invalid broadcast address! %s\nSkipping it!\n", *argv);
692         continue;
693       }
694       memcpy(&ifcnf->ipv4_broadcast.v4, &in.s_addr, sizeof(uint32_t));
695       continue;
696     }
697
698     /*
699      * Set LQ level
700      */
701     if (strcmp(*argv, "-lql") == 0) {
702       int tmp_lq_level;
703       NEXT_ARG;
704       CHECK_ARGC;
705
706       /* Sanity checking is done later */
707       sscanf(*argv, "%d", &tmp_lq_level);
708       olsr_cnf->lq_level = tmp_lq_level;
709       continue;
710     }
711
712     /*
713      * Set LQ winsize
714      */
715     if (strcmp(*argv, "-lqa") == 0) {
716       float tmp_lq_aging;
717       NEXT_ARG;
718       CHECK_ARGC;
719
720       sscanf(*argv, "%f", &tmp_lq_aging);
721
722       if (tmp_lq_aging < MIN_LQ_AGING || tmp_lq_aging > MAX_LQ_AGING) {
723         printf("LQ aging factor %f not allowed. Range [%f-%f]\n", tmp_lq_aging,
724             MIN_LQ_AGING, MAX_LQ_AGING);
725         olsr_exit(__func__, EXIT_FAILURE);
726       }
727       olsr_cnf->lq_aging = tmp_lq_aging;
728       continue;
729     }
730
731     /*
732      * Set NAT threshold
733      */
734     if (strcmp(*argv, "-lqnt") == 0) {
735       float tmp_lq_nat_thresh;
736       NEXT_ARG;
737       CHECK_ARGC;
738
739       sscanf(*argv, "%f", &tmp_lq_nat_thresh);
740
741       if (tmp_lq_nat_thresh < 0.1 || tmp_lq_nat_thresh > 1.0) {
742         printf("NAT threshold %f not allowed. Range [%f-%f]\n",
743             tmp_lq_nat_thresh, 0.1, 1.0);
744         olsr_exit(__func__, EXIT_FAILURE);
745       }
746       olsr_cnf->lq_nat_thresh = tmp_lq_nat_thresh;
747       continue;
748     }
749
750     /*
751      * Enable additional debugging information to be logged.
752      */
753     if (strcmp(*argv, "-d") == 0) {
754       NEXT_ARG;
755       CHECK_ARGC;
756
757       sscanf(*argv, "%d", &cnf->debug_level);
758       continue;
759     }
760
761     /*
762      * Interfaces to be used by olsrd.
763      */
764     if (strcmp(*argv, "-i") == 0) {
765       NEXT_ARG;
766       CHECK_ARGC;
767
768       if (*argv[0] == '-') {
769         fprintf(stderr, "You must provide an interface label!\n");
770         olsr_exit(__func__, EXIT_FAILURE);
771       }
772       printf("Queuing if %s\n", *argv);
773       queue_if(*argv, false);
774
775       while ((argc - 1) && (argv[1][0] != '-')) {
776         NEXT_ARG;
777         printf("Queuing if %s\n", *argv);
778         queue_if(*argv, false);
779       }
780
781       continue;
782     }
783     /*
784      * Set the hello interval to be used by olsrd.
785      *
786      */
787     if (strcmp(*argv, "-hint") == 0) {
788       NEXT_ARG;
789       CHECK_ARGC;
790       sscanf(*argv, "%f", &ifcnf->hello_params.emission_interval);
791       ifcnf->hello_params.validity_time = ifcnf->hello_params.emission_interval
792           * 3;
793       continue;
794     }
795
796     /*
797      * Set the HNA interval to be used by olsrd.
798      *
799      */
800     if (strcmp(*argv, "-hnaint") == 0) {
801       NEXT_ARG;
802       CHECK_ARGC;
803       sscanf(*argv, "%f", &ifcnf->hna_params.emission_interval);
804       ifcnf->hna_params.validity_time = ifcnf->hna_params.emission_interval * 3;
805       continue;
806     }
807
808     /*
809      * Set the MID interval to be used by olsrd.
810      *
811      */
812     if (strcmp(*argv, "-midint") == 0) {
813       NEXT_ARG;
814       CHECK_ARGC;
815       sscanf(*argv, "%f", &ifcnf->mid_params.emission_interval);
816       ifcnf->mid_params.validity_time = ifcnf->mid_params.emission_interval * 3;
817       continue;
818     }
819
820     /*
821      * Set the tc interval to be used by olsrd.
822      *
823      */
824     if (strcmp(*argv, "-tcint") == 0) {
825       NEXT_ARG;
826       CHECK_ARGC;
827       sscanf(*argv, "%f", &ifcnf->tc_params.emission_interval);
828       ifcnf->tc_params.validity_time = ifcnf->tc_params.emission_interval * 3;
829       continue;
830     }
831
832     /*
833      * Set the polling interval to be used by olsrd.
834      */
835     if (strcmp(*argv, "-T") == 0) {
836       NEXT_ARG;
837       CHECK_ARGC;
838       sscanf(*argv, "%f", &cnf->pollrate);
839       continue;
840     }
841
842     /*
843      * Should we display the contents of packages beeing sent?
844      */
845     if (strcmp(*argv, "-dispin") == 0) {
846       parser_set_disp_pack_in(true);
847       continue;
848     }
849
850     /*
851      * Should we display the contents of incoming packages?
852      */
853     if (strcmp(*argv, "-dispout") == 0) {
854       net_set_disp_pack_out(true);
855       continue;
856     }
857
858     /*
859      * Should we set up and send on a IPC socket for the front-end?
860      */
861     if (strcmp(*argv, "-ipc") == 0) {
862       cnf->ipc_connections = 1;
863       continue;
864     }
865
866     /*
867      * IPv6 multicast addr
868      */
869     if (strcmp(*argv, "-multi") == 0) {
870       struct in6_addr in6;
871       NEXT_ARG;
872       CHECK_ARGC;
873       if (inet_pton(AF_INET6, *argv, &in6) <= 0) {
874         fprintf(stderr, "Failed converting IP address %s\n", *argv);
875         exit(EXIT_FAILURE);
876       }
877
878       memcpy(&ifcnf->ipv6_multi_glbl, &in6, sizeof(struct in6_addr));
879
880       continue;
881     }
882
883     /*
884      * Host emulation
885      */
886     if (strcmp(*argv, "-hemu") == 0) {
887       struct in_addr in;
888       struct olsr_if *ifa;
889
890       NEXT_ARG;
891       CHECK_ARGC;
892       if (inet_pton(AF_INET, *argv, &in) <= 0) {
893         fprintf(stderr, "Failed converting IP address %s\n", *argv);
894         exit(EXIT_FAILURE);
895       }
896       /* Add hemu interface */
897
898       ifa = queue_if("hcif01", true);
899
900       if (!ifa)
901         continue;
902
903       ifa->cnf = get_default_if_config();
904       ifa->host_emul = true;
905       memcpy(&ifa->hemu_ip, &in, sizeof(union olsr_ip_addr));
906       cnf->host_emul = true;
907
908       continue;
909     }
910
911     /*
912      * Delete possible default GWs
913      */
914     if (strcmp(*argv, "-delgw") == 0) {
915       olsr_cnf->del_gws = true;
916       continue;
917     }
918
919     if (strcmp(*argv, "-nofork") == 0) {
920       cnf->no_fork = true;
921       continue;
922     }
923
924     return -1;
925   }
926   return 0;
927 }
928
929 /*
930  * Local Variables:
931  * c-basic-offset: 2
932  * indent-tabs-mode: nil
933  * End:
934  */