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