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