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