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