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