main: call olsr_exit when writing the PID file fails
[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 initialise 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   /* Print configuration */
212   if (olsr_cnf->debug_level > 1) {
213     olsrd_print_cnf(olsr_cnf);
214   }
215
216   /* config loaded and sane */
217
218   /* initialise timers */
219   olsr_init_timers();
220
221   def_timer_ci = olsr_alloc_cookie("Default Timer Cookie", OLSR_COOKIE_TYPE_TIMER);
222
223   /* create a socket for ioctl calls */
224   olsr_cnf->ioctl_s = socket(olsr_cnf->ip_version, SOCK_DGRAM, 0);
225   if (olsr_cnf->ioctl_s < 0) {
226     char buf2[1024];
227     snprintf(buf2, sizeof(buf2), "ioctl socket: %s", strerror(errno));
228     olsr_exit(buf2, 0);
229   }
230
231   /* create a socket for netlink calls */
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   /* create routing socket */
252 #if defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __NetBSD__ || defined __OpenBSD__
253   olsr_cnf->rts = socket(PF_ROUTE, SOCK_RAW, 0);
254   if (olsr_cnf->rts < 0) {
255     char buf2[1024];
256     snprintf(buf2, sizeof(buf2), "routing socket: %s", strerror(errno));
257     olsr_exit(buf2, 0);
258   }
259 #endif /* defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __NetBSD__ || defined __OpenBSD__ */
260
261   /* initialise gateway system */
262 #ifdef __linux__
263   if (olsr_cnf->smart_gw_active) {
264     if (olsr_init_gateways()) {
265       olsr_exit("Cannot initialise gateway tunnels", 1);
266     }
267   }
268 #endif /* __linux__ */
269
270   /* initialise niit if index */
271 #ifdef __linux__
272   if (olsr_cnf->use_niit) {
273     olsr_init_niit();
274   }
275 #endif /* __linux__ */
276
277   /* initialise empty TC timer */
278   set_empty_tc_timer(GET_TIMESTAMP(0));
279
280   /* enable ip forwarding on host and disable redirects globally (not for WIN32) */
281   net_os_set_global_ifoptions();
282
283   /* initialise parser */
284   olsr_init_parser();
285
286   /* initialise route exporter */
287   olsr_init_export_route();
288
289   /* initialise message sequence number */
290   init_msg_seqno();
291
292   /* initialise dynamic willingness calculation */
293   olsr_init_willingness();
294
295   /* Set up willingness/APM */
296   if (olsr_cnf->willingness_auto) {
297     if (apm_init() < 0) {
298       OLSR_PRINTF(1, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT);
299
300       olsr_syslog(OLSR_LOG_ERR, "Could not read APM info - setting default willingness(%d)\n",
301       WILL_DEFAULT);
302
303       olsr_cnf->willingness_auto = 0;
304       olsr_cnf->willingness = WILL_DEFAULT;
305     } else {
306       olsr_cnf->willingness = olsr_calculate_willingness();
307
308       OLSR_PRINTF(1, "Willingness set to %d - next update in %.1f secs\n", olsr_cnf->willingness, (double )olsr_cnf->will_int);
309     }
310   }
311
312   /* initialise net */
313   init_net();
314
315   /* initialise network interfaces */
316   if (!olsr_init_interfacedb()) {
317     if (olsr_cnf->allow_no_interfaces) {
318       fprintf( stderr, "No interfaces detected! This might be intentional, but it also might mean"
319           " that your configuration is fubar.\nI will continue after 5 seconds...\n");
320       olsr_startup_sleep(5);
321     } else {
322       char buf2[1024];
323       snprintf(buf2, sizeof(buf2), "%s: No interfaces detected", __func__);
324       olsr_exit(buf2, EXIT_FAILURE);
325     }
326   }
327
328 #ifdef __linux__
329   /* startup gateway system */
330   if (olsr_cnf->smart_gw_active) {
331     if (olsr_startup_gateways()) {
332       olsr_exit("Cannot startup gateway tunnels", 1);
333     }
334   }
335 #endif /* __linux__ */
336
337   /* initialise the IPC socket */
338   if (olsr_cnf->ipc_connections > 0) {
339     if (ipc_init()) {
340       olsr_exit("ipc_init failure", 1);
341     }
342   }
343
344   /* Initialisation of different tables to be used. */
345   olsr_init_tables();
346
347   olsr_do_startup_sleep();
348
349   /* start heartbeat that is showing on stdout */
350 #if !defined WINCE
351   if (olsr_cnf->debug_level > 0 && isatty(STDOUT_FILENO)) {
352     olsr_start_timer(STDOUT_PULSE_INT, 0, OLSR_TIMER_PERIODIC, &generate_stdout_pulse, NULL, 0);
353   }
354 #endif /* !defined WINCE */
355
356   /* daemon mode */
357 #ifndef _WIN32
358   if (olsr_cnf->debug_level == 0 && !olsr_cnf->no_fork) {
359     printf("%s detaching from the current process...\n", olsrd_version);
360     if (daemon(0, 0) < 0) {
361       char buf2[1024];
362       snprintf(buf2, sizeof(buf2), "daemon(3) failed: %s", strerror(errno));
363       olsr_exit(buf2, EXIT_FAILURE);
364     }
365   }
366 #endif /* _WIN32 */
367
368   if (!writePidFile()) {
369     olsr_exit(NULL, EXIT_FAILURE);
370   }
371
372   /*
373    * Create locking file for olsrd, will be cleared after olsrd exits
374    */
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   {
385     struct ipaddr_str buf;
386     OLSR_PRINTF(1, "Main address: %s\n\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
387   }
388
389 #ifdef __linux__
390   /* create policy routing rules with priorities if necessary */
391   if (DEF_RT_NONE != olsr_cnf->rt_table_pri) {
392     olsr_os_policy_rule(olsr_cnf->ip_version,
393         olsr_cnf->rt_table, olsr_cnf->rt_table_pri, NULL, true);
394   }
395   if (DEF_RT_NONE != olsr_cnf->rt_table_tunnel_pri) {
396     olsr_os_policy_rule(olsr_cnf->ip_version,
397         olsr_cnf->rt_table_tunnel, olsr_cnf->rt_table_tunnel_pri, NULL, true);
398   }
399   if (DEF_RT_NONE != olsr_cnf->rt_table_default_pri) {
400     olsr_os_policy_rule(olsr_cnf->ip_version,
401         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,
409           olsr_cnf->rt_table_default, olsr_cnf->rt_table_defaultolsr_pri, ifn->int_name, true);
410     }
411   }
412
413   /* trigger gateway selection */
414   if (olsr_cnf->smart_gw_active) {
415     olsr_trigger_inetgw_startup();
416   }
417
418   /* trigger niit static route setup */
419   if (olsr_cnf->use_niit) {
420     olsr_setup_niit_routes();
421   }
422
423   /* create lo:olsr interface */
424   if (olsr_cnf->use_src_ip_routes) {
425     olsr_os_localhost_if(&olsr_cnf->main_addr, true);
426   }
427 #endif /* __linux__ */
428
429   /* Start syslog entry */
430   olsr_syslog(OLSR_LOG_INFO, "%s successfully started", olsrd_version);
431
432   /*
433    *signal-handlers
434    */
435
436   /* ctrl-C and friends */
437 #ifdef _WIN32
438 #ifndef WINCE
439   SetConsoleCtrlHandler(SignalHandler, true);
440 #endif /* WINCE */
441 #else /* _WIN32 */
442   signal(SIGHUP, olsr_reconfigure);
443   signal(SIGINT, olsr_shutdown);
444   signal(SIGQUIT, olsr_shutdown);
445   signal(SIGILL, olsr_shutdown);
446   signal(SIGABRT, olsr_shutdown);
447   //  signal(SIGSEGV, olsr_shutdown);
448   signal(SIGTERM, olsr_shutdown);
449   signal(SIGPIPE, SIG_IGN);
450   // Ignoring SIGUSR1 and SIGUSR1 by default to be able to use them in plugins
451   signal(SIGUSR1, SIG_IGN);
452   signal(SIGUSR2, SIG_IGN);
453 #endif /* _WIN32 */
454
455   link_changes = false;
456
457   /* Starting scheduler */
458   olsr_scheduler();
459
460   /* Like we're ever going to reach this ;-) */
461   olsr_exit(NULL, 0);
462 } /* main */
463
464 #ifndef _WIN32
465 /**
466  * Reconfigure olsrd. Currently kind of a hack...
467  *
468  *@param signo the signal that triggered this callback
469  */
470 void olsr_reconfigure(int signo __attribute__ ((unused))) {
471 #ifndef _WIN32
472   int errNr = errno;
473 #endif
474   /* if we are started with -nofork, we do not want to go into the
475    * background here. So we can simply stop on -HUP
476    */
477   olsr_syslog(OLSR_LOG_INFO, "sot: olsr_reconfigure()\n");
478   if (!olsr_cnf->no_fork) {
479     if (!fork()) {
480       int i;
481       sigset_t sigs;
482       /* New process */
483       sleep(3);
484       sigemptyset(&sigs);
485       sigaddset(&sigs, SIGHUP);
486       sigprocmask(SIG_UNBLOCK, &sigs, NULL);
487       for (i = sysconf(_SC_OPEN_MAX); --i > STDERR_FILENO;) {
488         close(i);
489       }
490       printf("Restarting %s\n", olsr_argv[0]);
491       olsr_syslog(OLSR_LOG_INFO, "Restarting %s\n", olsr_argv[0]);
492       execv(olsr_argv[0], olsr_argv);
493       olsr_syslog(OLSR_LOG_ERR, "execv(%s) fails: %s!\n", olsr_argv[0],
494           strerror(errno));
495     } else {
496       olsr_syslog(OLSR_LOG_INFO, "RECONFIGURING!\n");
497     }
498   }
499 #ifndef _WIN32
500   errno = errNr;
501 #endif
502   olsr_shutdown(0);
503 }
504 #endif /* _WIN32 */
505
506 static void olsr_shutdown_messages(void) {
507   struct interface_olsr *ifn;
508
509   /* send TC reset */
510   for (ifn = ifnet; ifn; ifn = ifn->int_next) {
511     /* clean output buffer */
512     net_output(ifn);
513
514     /* send 'I'm gone' messages */
515     if (olsr_cnf->lq_level > 0) {
516       olsr_output_lq_tc(ifn);
517       olsr_output_lq_hello(ifn);
518     }
519     else {
520       generate_tc(ifn);
521       generate_hello(ifn);
522     }
523     net_output(ifn);
524   }
525 }
526
527 /**
528  *Function called at shutdown. Signal handler
529  *
530  * @param signo the signal that triggered this call
531  */
532 #ifdef _WIN32
533 int __stdcall
534 SignalHandler(unsigned long signo)
535 #else /* _WIN32 */
536 static void olsr_shutdown(int signo __attribute__ ((unused)))
537 #endif /* _WIN32 */
538 {
539 #ifndef _WIN32
540   int errNr = errno;
541 #endif
542   struct interface_olsr *ifn;
543   int exit_value;
544
545   OLSR_PRINTF(1, "Received signal %d - shutting down\n", (int)signo);
546
547 #ifdef _WIN32
548   OLSR_PRINTF(1, "Waiting for the scheduler to stop.\n");
549
550   olsr_win32_end_request = TRUE;
551
552   while (!olsr_win32_end_flag)
553   sleep(1);
554
555   OLSR_PRINTF(1, "Scheduler stopped.\n");
556 #endif /* _WIN32 */
557
558   /* clear all links and send empty hellos/tcs */
559   olsr_reset_all_links();
560
561   /* deactivate fisheye and immediate TCs */
562   olsr_cnf->lq_fish = 0;
563   for (ifn = ifnet; ifn; ifn = ifn->int_next) {
564     ifn->immediate_send_tc = false;
565   }
566   increase_local_ansn();
567
568   /* send first shutdown message burst */
569   olsr_shutdown_messages();
570
571   /* delete all routes */
572   olsr_delete_all_kernel_routes();
573
574   /* send second shutdown message burst */
575   olsr_shutdown_messages();
576
577   /* now try to cleanup the rest of the mess */
578   olsr_delete_all_tc_entries();
579
580   olsr_delete_all_mid_entries();
581
582 #ifdef __linux__
583   /* trigger gateway selection */
584   if (olsr_cnf->smart_gw_active) {
585     olsr_shutdown_gateways();
586     olsr_cleanup_gateways();
587   }
588
589   /* trigger niit static route cleanup */
590   if (olsr_cnf->use_niit) {
591     olsr_cleanup_niit_routes();
592   }
593
594   /* cleanup lo:olsr interface */
595   if (olsr_cnf->use_src_ip_routes) {
596     olsr_os_localhost_if(&olsr_cnf->main_addr, false);
597   }
598 #endif /* __linux__ */
599
600   olsr_destroy_parser();
601
602   OLSR_PRINTF(1, "Closing sockets...\n");
603
604   /* front-end IPC socket */
605   if (olsr_cnf->ipc_connections > 0) {
606     shutdown_ipc();
607   }
608
609   /* OLSR sockets */
610   for (ifn = ifnet; ifn; ifn = ifn->int_next) {
611     close(ifn->olsr_socket);
612     close(ifn->send_socket);
613
614 #ifdef __linux__
615     if (DEF_RT_NONE != olsr_cnf->rt_table_defaultolsr_pri) {
616       olsr_os_policy_rule(olsr_cnf->ip_version, olsr_cnf->rt_table_default,
617           olsr_cnf->rt_table_defaultolsr_pri, ifn->int_name, false);
618     }
619 #endif /* __linux__ */
620   }
621
622   /* Closing plug-ins */
623   olsr_close_plugins();
624
625   /* Reset network settings */
626   net_os_restore_ifoptions();
627
628   /* ioctl socket */
629   close(olsr_cnf->ioctl_s);
630
631 #ifdef __linux__
632   if (DEF_RT_NONE != olsr_cnf->rt_table_pri) {
633     olsr_os_policy_rule(olsr_cnf->ip_version,
634         olsr_cnf->rt_table, olsr_cnf->rt_table_pri, NULL, false);
635   }
636   if (DEF_RT_NONE != olsr_cnf->rt_table_tunnel_pri) {
637     olsr_os_policy_rule(olsr_cnf->ip_version,
638         olsr_cnf->rt_table_tunnel, olsr_cnf->rt_table_tunnel_pri, NULL, false);
639   }
640   if (DEF_RT_NONE != olsr_cnf->rt_table_default_pri) {
641     olsr_os_policy_rule(olsr_cnf->ip_version,
642         olsr_cnf->rt_table_default, olsr_cnf->rt_table_default_pri, NULL, false);
643   }
644   close(olsr_cnf->rtnl_s);
645   close (olsr_cnf->rt_monitor_socket);
646 #endif /* __linux__ */
647
648 #if defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __NetBSD__ || defined __OpenBSD__
649   /* routing socket */
650   close(olsr_cnf->rts);
651 #endif /* defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __NetBSD__ || defined __OpenBSD__ */
652
653   /* remove the lock file */
654   olsr_remove_lock_file();
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 #ifndef _WIN32
668   errno = errNr;
669 #endif
670   exit(exit_value);
671 }
672
673 static void print_version(void) {
674   printf("\n *** %s ***\n Build date: %s on %s\n http://www.olsr.org\n\n",
675       olsrd_version, build_date, build_host);
676 }
677
678 /**
679  * Print the command line usage
680  */
681 static void print_usage(bool error) {
682   fprintf(
683       stderr,
684         "%s"
685         "usage: olsrd [-f <configfile>] [ -i interface1 interface2 ... ]\n"
686         "  [-d <debug_level>] [-ipv6] [-multi <IPv6 multicast address>]\n"
687         "  [-lql <LQ level>] [-lqw <LQ winsize>] [-lqnt <nat threshold>]\n"
688         "  [-bcast <broadcastaddr>] [-ipc] [-delgw]\n"
689         "  [-hint <hello interval (secs)>] [-tcint <tc interval (secs)>]\n"
690         "  [-midint <mid interval (secs)>] [-hnaint <hna interval (secs)>]\n"
691         "  [-T <Polling Rate (secs)>] [-nofork] [-hemu <ip_address>]\n"
692         "  [-lql <LQ level>] [-lqa <LQ aging factor>]\n"
693         "  [-pidfile <pid file>]\n",
694         error ? "Error in command line parameters!\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      char buf[1024]; \
722      argv--; \
723      snprintf(buf, sizeof(buf), "%s: You must provide a parameter when using the %s switch", __func__, *argv); \
724      olsr_exit(buf, EXIT_FAILURE); \
725      } } while (0)
726
727 /**
728  * Process command line arguments passed to olsrd
729  *
730  */
731 static int olsr_process_arguments(int argc, char *argv[],
732     struct olsrd_config *cnf, struct if_config_options *ifcnf) {
733   while (argc > 1) {
734     NEXT_ARG;
735 #ifdef _WIN32
736     /*
737      *Interface list
738      */
739     if (strcmp(*argv, "-int") == 0) {
740       ListInterfaces();
741       olsr_exit(NULL, 0);
742     }
743 #endif /* _WIN32 */
744
745     /*
746      *Configfilename
747      */
748     if (strcmp(*argv, "-f") == 0) {
749       char buf2[1024];
750       snprintf(buf2, sizeof(buf2), "%s: Configfilename must ALWAYS be first argument", __func__);
751       olsr_exit(buf2, EXIT_FAILURE);
752     }
753
754     /*
755      *Use IP version 6
756      */
757     if (strcmp(*argv, "-ipv6") == 0) {
758       cnf->ip_version = AF_INET6;
759       continue;
760     }
761
762     /*
763      *Broadcast address
764      */
765     if (strcmp(*argv, "-bcast") == 0) {
766       struct in_addr in;
767       NEXT_ARG;
768       CHECK_ARGC;
769
770       if (inet_pton(AF_INET, *argv, &in) == 0) {
771         printf("Invalid broadcast address! %s\nSkipping it!\n", *argv);
772         continue;
773       }
774       memcpy(&ifcnf->ipv4_multicast.v4, &in.s_addr, sizeof(ifcnf->ipv4_multicast.v4));
775       continue;
776     }
777
778     /*
779      * Set LQ level
780      */
781     if (strcmp(*argv, "-lql") == 0) {
782       int tmp_lq_level;
783       NEXT_ARG;
784       CHECK_ARGC;
785
786       /* Sanity checking is done later */
787       sscanf(*argv, "%d", &tmp_lq_level);
788       olsr_cnf->lq_level = tmp_lq_level;
789       continue;
790     }
791
792     /*
793      * Set LQ winsize
794      */
795     if (strcmp(*argv, "-lqa") == 0) {
796       float tmp_lq_aging;
797       NEXT_ARG;
798       CHECK_ARGC;
799
800       sscanf(*argv, "%f", &tmp_lq_aging);
801
802       if (tmp_lq_aging < (float)MIN_LQ_AGING || tmp_lq_aging > (float)MAX_LQ_AGING) {
803         char buf[1024];
804         snprintf(buf, sizeof(buf), "%s: LQ aging factor %f not allowed. Range [%f-%f]", __func__,
805             (double)tmp_lq_aging, (double)MIN_LQ_AGING, (double)MAX_LQ_AGING);
806         olsr_exit(buf, EXIT_FAILURE);
807       }
808       olsr_cnf->lq_aging = tmp_lq_aging;
809       continue;
810     }
811
812     /*
813      * Set NAT threshold
814      */
815     if (strcmp(*argv, "-lqnt") == 0) {
816       float tmp_lq_nat_thresh;
817       NEXT_ARG;
818       CHECK_ARGC;
819
820       sscanf(*argv, "%f", &tmp_lq_nat_thresh);
821
822       if (tmp_lq_nat_thresh < 0.1f || tmp_lq_nat_thresh > 1.0f) {
823         char buf[1024];
824         snprintf(buf, sizeof(buf), "%s: NAT threshold %f not allowed. Range [%f-%f]", __func__,
825                         (double)tmp_lq_nat_thresh, (double)0.1, (double)1.0);
826         olsr_exit(buf, 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         char buf[1024];
852         snprintf(buf, sizeof(buf), "%s: You must provide an interface label", __func__);
853         olsr_exit(buf, EXIT_FAILURE);
854       }
855       printf("Queuing if %s\n", *argv);
856       olsr_create_olsrif(*argv, false);
857
858       while ((argc - 1) && (argv[1][0] != '-')) {
859         NEXT_ARG;
860         printf("Queuing if %s\n", *argv);
861         olsr_create_olsrif(*argv, false);
862       }
863
864       continue;
865     }
866     /*
867      * Set the hello interval to be used by olsrd.
868      *
869      */
870     if (strcmp(*argv, "-hint") == 0) {
871       NEXT_ARG;
872       CHECK_ARGC;
873       sscanf(*argv, "%f", &ifcnf->hello_params.emission_interval);
874       ifcnf->hello_params.validity_time = ifcnf->hello_params.emission_interval
875           * 3;
876       continue;
877     }
878
879     /*
880      * Set the HNA interval to be used by olsrd.
881      *
882      */
883     if (strcmp(*argv, "-hnaint") == 0) {
884       NEXT_ARG;
885       CHECK_ARGC;
886       sscanf(*argv, "%f", &ifcnf->hna_params.emission_interval);
887       ifcnf->hna_params.validity_time = ifcnf->hna_params.emission_interval * 3;
888       continue;
889     }
890
891     /*
892      * Set the MID interval to be used by olsrd.
893      *
894      */
895     if (strcmp(*argv, "-midint") == 0) {
896       NEXT_ARG;
897       CHECK_ARGC;
898       sscanf(*argv, "%f", &ifcnf->mid_params.emission_interval);
899       ifcnf->mid_params.validity_time = ifcnf->mid_params.emission_interval * 3;
900       continue;
901     }
902
903     /*
904      * Set the tc interval to be used by olsrd.
905      *
906      */
907     if (strcmp(*argv, "-tcint") == 0) {
908       NEXT_ARG;
909       CHECK_ARGC;
910       sscanf(*argv, "%f", &ifcnf->tc_params.emission_interval);
911       ifcnf->tc_params.validity_time = ifcnf->tc_params.emission_interval * 3;
912       continue;
913     }
914
915     /*
916      * Set the polling interval to be used by olsrd.
917      */
918     if (strcmp(*argv, "-T") == 0) {
919       NEXT_ARG;
920       CHECK_ARGC;
921       sscanf(*argv, "%f", &cnf->pollrate);
922       continue;
923     }
924
925     /*
926      * Should we set up and send on a IPC socket for the front-end?
927      */
928     if (strcmp(*argv, "-ipc") == 0) {
929       cnf->ipc_connections = 1;
930       continue;
931     }
932
933     /*
934      * IPv6 multicast addr
935      */
936     if (strcmp(*argv, "-multi") == 0) {
937       struct in6_addr in6;
938       NEXT_ARG;
939       CHECK_ARGC;
940       if (inet_pton(AF_INET6, *argv, &in6) <= 0) {
941         char buf[1024];
942         snprintf(buf, sizeof(buf), "Failed converting IP address %s", *argv);
943         olsr_exit(buf, EXIT_FAILURE);
944       }
945
946       memcpy(&ifcnf->ipv6_multicast, &in6, sizeof(struct in6_addr));
947
948       continue;
949     }
950
951     /*
952      * Host emulation
953      */
954     if (strcmp(*argv, "-hemu") == 0) {
955       struct in_addr in;
956       struct olsr_if *ifa;
957
958       NEXT_ARG;
959       CHECK_ARGC;
960       if (inet_pton(AF_INET, *argv, &in) <= 0) {
961         char buf[1024];
962         snprintf(buf, sizeof(buf), "Failed converting IP address %s", *argv);
963         olsr_exit(buf, EXIT_FAILURE);
964       }
965       /* Add hemu interface */
966
967       ifa = olsr_create_olsrif("hcif01", true);
968
969       if (!ifa)
970         continue;
971
972       ifa->cnf = get_default_if_config();
973       ifa->host_emul = true;
974       memset(&ifa->hemu_ip, 0, sizeof(ifa->hemu_ip));
975       memcpy(&ifa->hemu_ip, &in, sizeof(in));
976       cnf->host_emul = true;
977
978       continue;
979     }
980
981     /*
982      * Delete possible default GWs
983      */
984     if (strcmp(*argv, "-delgw") == 0) {
985       olsr_cnf->del_gws = true;
986       continue;
987     }
988
989     if (strcmp(*argv, "-nofork") == 0) {
990       cnf->no_fork = true;
991       continue;
992     }
993
994     if (strcmp(*argv, "-pidfile") == 0) {
995       NEXT_ARG;
996       CHECK_ARGC;
997
998       cnf->pidfile = *argv;
999       continue;
1000     }
1001
1002     return -1;
1003   }
1004   return 0;
1005 }
1006
1007 /*
1008  * Local Variables:
1009  * c-basic-offset: 2
1010  * indent-tabs-mode: nil
1011  * End:
1012  */