55d00a47e2837e2d9f12ceb44123a922fcc32faf
[olsrd.git] / src / main.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in
14  *   the documentation and/or other materials provided with the
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its
17  *   contributors may be used to endorse or promote products derived
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  */
40
41 #include <unistd.h>
42 #include <signal.h>
43 #include <sys/stat.h>
44 #include <assert.h>
45 #include <fcntl.h>
46
47 #include "ipcalc.h"
48 #include "defs.h"
49 #include "olsr.h"
50 #include "log.h"
51 #include "scheduler.h"
52 #include "parser.h"
53 #include "generate_msg.h"
54 #include "plugin_loader.h"
55 #include "apm.h"
56 #include "net_os.h"
57 #include "build_msg.h"
58 #include "net_olsr.h"
59 #include "mid_set.h"
60 #include "mpr_selector_set.h"
61 #include "gateway.h"
62 #include "olsr_niit.h"
63
64 #ifdef LINUX_NETLINK_ROUTING
65 #include <linux/types.h>
66 #include <linux/rtnetlink.h>
67 #include "kernel_routes.h"
68
69 #endif
70
71 #ifdef WIN32
72 #include <winbase.h>
73 #define close(x) closesocket(x)
74 int __stdcall SignalHandler(unsigned long signo) __attribute__ ((noreturn));
75 void ListInterfaces(void);
76 void DisableIcmpRedirects(void);
77 bool olsr_win32_end_request = false;
78 bool olsr_win32_end_flag = false;
79 #else
80 static void olsr_shutdown(int) __attribute__ ((noreturn));
81 #endif
82
83 #if defined android
84 #define DEFAULT_LOCKFILE_PREFIX "/data/local/olsrd"
85 #elif defined linux || __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__
86 #define DEFAULT_LOCKFILE_PREFIX "/var/run/olsrd"
87 #elif defined WIN32
88 #define DEFAULT_LOCKFILE_PREFIX "C:\\olsrd"
89 #else
90 #define DEFAULT_LOCKFILE_PREFIX "olsrd"
91 #endif
92
93 /*
94  * Local function prototypes
95  */
96 void olsr_reconfigure(int) __attribute__ ((noreturn));
97
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 #ifndef WIN32
106 static char **olsr_argv;
107 #endif
108
109 static char
110     copyright_string[] __attribute__ ((unused)) =
111         "The olsr.org Optimized Link-State Routing daemon(olsrd) Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org) All rights reserved.";
112
113 /* Data for OLSR locking */
114 #ifndef WIN32
115 static int lock_fd = 0;
116 #endif
117 static char lock_file_name[FILENAME_MAX];
118 struct olsr_cookie_info *def_timer_ci = NULL;
119
120 /*
121  * Creates a zero-length locking file and use fcntl to
122  * place an exclusive lock over it. The lock will be
123  * automatically erased when the olsrd process ends,
124  * so it will even work well with a SIGKILL.
125  *
126  * Additionally the lock can be killed by removing the
127  * locking file.
128  */
129 static int olsr_create_lock_file(bool noExitOnFail) {
130 #ifdef WIN32
131   HANDLE lck = CreateEvent(NULL, TRUE, FALSE, lock_file_name);
132   if (NULL == lck || ERROR_ALREADY_EXISTS == GetLastError()) {
133     if (noenoExitOnFail) {
134       return -1;
135     }
136     if (NULL == lck) {
137       fprintf(stderr,
138           "Error, cannot create OLSR lock '%s'.\n",
139           lock_file_name);
140     } else {
141       CloseHandle(lck);
142       fprintf(stderr,
143           "Error, cannot aquire OLSR lock '%s'.\n"
144           "Another OLSR instance might be running.\n",
145           lock_file_name);
146     }
147     olsr_exit("", EXIT_FAILURE);
148   }
149 #else
150   struct flock lck;
151
152   /* create file for lock */
153   lock_fd = open(lock_file_name, O_WRONLY | O_CREAT, S_IRWXU);
154   if (lock_fd == 0) {
155     if (noExitOnFail) {
156       return -1;
157     }
158     fprintf(stderr,
159         "Error, cannot create OLSR lock '%s'.\n",
160         lock_file_name);
161     olsr_exit("", EXIT_FAILURE);
162   }
163
164   /* create exclusive lock for the whole file */
165   lck.l_type = F_WRLCK;
166   lck.l_whence = SEEK_SET;
167   lck.l_start = 0;
168   lck.l_len = 0;
169   lck.l_pid = 0;
170
171   if (fcntl(lock_fd, F_SETLK, &lck) == -1) {
172     close(lock_fd);
173     if (noExitOnFail) {
174       return -1;
175     }
176     fprintf(stderr,
177         "Error, cannot aquire OLSR lock '%s'.\n"
178         "Another OLSR instance might be running.\n",
179         lock_file_name);
180     olsr_exit("", EXIT_FAILURE);
181   }
182 #endif
183   return 0;
184 }
185
186 /**
187  * loads a config file
188  * @return <0 if load failed, 0 otherwise
189  */
190 static int
191 olsrmain_load_config(char *file) {
192   struct stat statbuf;
193
194   if (stat(file, &statbuf) < 0) {
195     fprintf(stderr, "Could not find specified config file %s!\n%s\n\n",
196         file, strerror(errno));
197     return -1;
198   }
199
200   if (olsrd_parse_cnf(file) < 0) {
201     fprintf(stderr, "Error while reading config file %s!\n", file);
202     return -1;
203   }
204   return 0;
205 }
206
207 /**
208  * Main entrypoint
209  */
210
211 int main(int argc, char *argv[]) {
212   struct if_config_options *default_ifcnf;
213   char conf_file_name[FILENAME_MAX];
214   struct ipaddr_str buf;
215   bool loadedConfig = false;
216   int i;
217
218 #ifdef LINUX_NETLINK_ROUTING
219   struct interface *ifn;
220 #endif
221
222 #ifdef WIN32
223   WSADATA WsaData;
224   size_t len;
225 #endif
226
227   /* paranoia checks */
228   assert(sizeof(uint8_t) == 1);
229   assert(sizeof(uint16_t) == 2);
230   assert(sizeof(uint32_t) == 4);
231   assert(sizeof(int8_t) == 1);
232   assert(sizeof(int16_t) == 2);
233   assert(sizeof(int32_t) == 4);
234
235   printf("\n *** %s ***\n Build date: %s on %s\n http://www.olsr.org\n\n",
236       olsrd_version, build_date, build_host);
237
238   if (argc == 2) {
239     if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "/?") == 0) {
240       print_usage(false);
241       exit(0);
242     }
243     if (strcmp(argv[1], "-v") == 0) {
244       exit(0);
245     }
246   }
247
248   debug_handle = stdout;
249 #ifndef WIN32
250   olsr_argv = argv;
251 #endif
252   setbuf(stdout, NULL);
253   setbuf(stderr, NULL);
254
255 #ifndef WIN32
256   /* Check if user is root */
257   if (geteuid()) {
258     fprintf(stderr, "You must be root(uid = 0) to run olsrd!\nExiting\n\n");
259     exit(EXIT_FAILURE);
260   }
261 #else
262   DisableIcmpRedirects();
263
264   if (WSAStartup(0x0202, &WsaData)) {
265     fprintf(stderr, "Could not initialize WinSock.\n");
266     olsr_exit(__func__, EXIT_FAILURE);
267   }
268 #endif
269
270   /* Open syslog */
271   olsr_openlog("olsrd");
272
273   /* Using PID as random seed */
274   srandom(getpid());
275
276   /* Init widely used statics */
277   memset(&all_zero, 0, sizeof(union olsr_ip_addr));
278
279   /*
280    * Set configfile name and
281    * check if a configfile name was given as parameter
282    */
283 #ifdef WIN32
284 #ifndef WINCE
285   GetWindowsDirectory(conf_file_name, FILENAME_MAX - 11);
286 #else
287   conf_file_name[0] = 0;
288 #endif
289
290   len = strlen(conf_file_name);
291
292   if (len == 0 || conf_file_name[len - 1] != '\\')
293   conf_file_name[len++] = '\\';
294
295   strscpy(conf_file_name + len, "olsrd.conf", sizeof(conf_file_name) - len);
296 #else
297   strscpy(conf_file_name, OLSRD_GLOBAL_CONF_FILE, sizeof(conf_file_name));
298 #endif
299
300   olsr_cnf = olsrd_get_default_cnf();
301   for (i=1; i < argc-1;) {
302     if (strcmp(argv[i], "-f") == 0) {
303       loadedConfig = true;
304
305       if (olsrmain_load_config(argv[i+1]) < 0) {
306         exit(EXIT_FAILURE);
307       }
308
309       if (i+2 < argc) {
310         memmove(&argv[i], &argv[i+2], sizeof(*argv) * (argc-i-1));
311       }
312       argc -= 2;
313     }
314     else {
315       i++;
316     }
317   }
318
319   /*
320    * set up configuration prior to processing commandline options
321    */
322   if (!loadedConfig && olsrmain_load_config(conf_file_name) == 0) {
323     loadedConfig = true;
324   }
325
326   if (!loadedConfig) {
327     olsrd_free_cnf(olsr_cnf);
328     olsr_cnf = olsrd_get_default_cnf();
329   }
330
331   default_ifcnf = get_default_if_config();
332   if (default_ifcnf == NULL) {
333     fprintf(stderr, "No default ifconfig found!\n");
334     exit(EXIT_FAILURE);
335   }
336
337   /* Initialize timers */
338   olsr_init_timers();
339
340   /*
341    * Process olsrd options.
342    */
343   if (olsr_process_arguments(argc, argv, olsr_cnf, default_ifcnf) < 0) {
344     print_usage(true);
345     olsr_exit(__func__, EXIT_FAILURE);
346   }
347
348   /*
349    * Set configuration for command-line specified interfaces
350    */
351   set_default_ifcnfs(olsr_cnf->interfaces, default_ifcnf);
352
353   /* free the default ifcnf */
354   free(default_ifcnf);
355
356   /* Sanity check configuration */
357   if (olsrd_sanity_check_cnf(olsr_cnf) < 0) {
358     fprintf(stderr, "Bad configuration!\n");
359     olsr_exit(__func__, EXIT_FAILURE);
360   }
361
362   /*
363    * Establish file lock to prevent multiple instances
364    */
365   if (olsr_cnf->lock_file) {
366     strscpy(lock_file_name, olsr_cnf->lock_file, sizeof(lock_file_name));
367   } else {
368     size_t l;
369 #ifdef DEFAULT_LOCKFILE_PREFIX
370     strscpy(lock_file_name, DEFAULT_LOCKFILE_PREFIX, sizeof(lock_file_name));
371 #else
372     strscpy(lock_file_name, conf_file_name, sizeof(lock_file_name));
373 #endif
374     l = strlen(lock_file_name);
375     snprintf(&lock_file_name[l], sizeof(lock_file_name) - l, "-ipv%d.lock",
376         olsr_cnf->ip_version == AF_INET ? 4 : 6);
377   }
378
379   /*
380    * Print configuration
381    */
382   if (olsr_cnf->debug_level > 1) {
383     olsrd_print_cnf(olsr_cnf);
384   }
385
386   def_timer_ci = olsr_alloc_cookie("Default Timer Cookie", OLSR_COOKIE_TYPE_TIMER);
387
388   /*
389    * socket for ioctl calls
390    */
391   olsr_cnf->ioctl_s = socket(olsr_cnf->ip_version, SOCK_DGRAM, 0);
392   if (olsr_cnf->ioctl_s < 0) {
393 #ifndef WIN32
394     olsr_syslog(OLSR_LOG_ERR, "ioctl socket: %m");
395 #endif
396     olsr_exit(__func__, 0);
397   }
398 #ifdef LINUX_NETLINK_ROUTING
399   olsr_cnf->rtnl_s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
400   if (olsr_cnf->rtnl_s < 0) {
401     olsr_syslog(OLSR_LOG_ERR, "rtnetlink socket: %m");
402     olsr_exit(__func__, 0);
403   }
404   fcntl(olsr_cnf->rtnl_s, F_SETFL, O_NONBLOCK);
405
406   if ((olsr_cnf->rt_monitor_socket = rtnetlink_register_socket(RTMGRP_LINK)) < 0) {
407     olsr_syslog(OLSR_LOG_ERR, "rtmonitor socket: %m");
408     olsr_exit(__func__, 0);
409   }
410 #endif
411
412   /*
413    * create routing socket
414    */
415 #if defined __FreeBSD__ || __FreeBSD_kernel__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
416   olsr_cnf->rts = socket(PF_ROUTE, SOCK_RAW, 0);
417   if (olsr_cnf->rts < 0) {
418     olsr_syslog(OLSR_LOG_ERR, "routing socket: %m");
419     olsr_exit(__func__, 0);
420   }
421 #endif
422
423 #ifdef LINUX_NETLINK_ROUTING
424   /* initialize gateway system */
425   if (olsr_cnf->smart_gw_active) {
426     if (olsr_init_gateways()) {
427       olsr_exit("Cannot initialize gateway tunnels", 1);
428     }
429   }
430
431   /* initialize niit if index */
432   if (olsr_cnf->use_niit) {
433     olsr_init_niit();
434   }
435 #endif
436
437   /* Init empty TC timer */
438   set_empty_tc_timer(GET_TIMESTAMP(0));
439
440   /* enable ip forwarding on host */
441   /* Disable redirects globally */
442 #ifndef WIN32
443   net_os_set_global_ifoptions();
444 #endif
445
446   /* Initialize parser */
447   olsr_init_parser();
448
449   /* Initialize route-exporter */
450   olsr_init_export_route();
451
452   /* Initialize message sequencnumber */
453   init_msg_seqno();
454
455   /* Initialize dynamic willingness calculation */
456   olsr_init_willingness();
457
458   /*
459    *Set up willingness/APM
460    */
461   if (olsr_cnf->willingness_auto) {
462     if (apm_init() < 0) {
463       OLSR_PRINTF(1, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT);
464
465       olsr_syslog(OLSR_LOG_ERR,
466           "Could not read APM info - setting default willingness(%d)\n",
467           WILL_DEFAULT);
468
469       olsr_cnf->willingness_auto = 0;
470       olsr_cnf->willingness = WILL_DEFAULT;
471     } else {
472       olsr_cnf->willingness = olsr_calculate_willingness();
473
474       OLSR_PRINTF(1, "Willingness set to %d - next update in %.1f secs\n", olsr_cnf->willingness, olsr_cnf->will_int);
475     }
476   }
477
478   /* Initialize net */
479   init_net();
480
481   /* Initializing networkinterfaces */
482   if (!olsr_init_interfacedb()) {
483     if (olsr_cnf->allow_no_interfaces) {
484       fprintf(
485           stderr,
486           "No interfaces detected! This might be intentional, but it also might mean that your configuration is fubar.\nI will continue after 5 seconds...\n");
487       olsr_startup_sleep(5);
488     } else {
489       fprintf(stderr, "No interfaces detected!\nBailing out!\n");
490       olsr_exit(__func__, EXIT_FAILURE);
491     }
492   }
493
494   olsr_do_startup_sleep();
495
496   /* Print heartbeat to stdout */
497
498 #if !defined WINCE
499   if (olsr_cnf->debug_level > 0 && isatty(STDOUT_FILENO)) {
500     olsr_start_timer(STDOUT_PULSE_INT, 0, OLSR_TIMER_PERIODIC,
501         &generate_stdout_pulse, NULL, 0);
502   }
503 #endif
504
505   /* Initialize the IPC socket */
506
507   if (olsr_cnf->ipc_connections > 0) {
508     ipc_init();
509   }
510   /* Initialisation of different tables to be used. */
511   olsr_init_tables();
512
513   /* daemon mode */
514 #ifndef WIN32
515   if (olsr_cnf->debug_level == 0 && !olsr_cnf->no_fork) {
516     printf("%s detaching from the current process...\n", olsrd_version);
517     if (daemon(0, 0) < 0) {
518       printf("daemon(3) failed: %s\n", strerror(errno));
519       exit(EXIT_FAILURE);
520     }
521   }
522 #endif
523
524   /*
525    * Create locking file for olsrd, will be cleared after olsrd exits
526    */
527   for (i=5; i>=0; i--) {
528     OLSR_PRINTF(3, "Trying to get olsrd lock...\n");
529     if (olsr_create_lock_file(i > 0) == 0) {
530       /* lock sucessfully created */
531       break;
532     }
533     sleep (1);
534   }
535
536   /* Load plugins */
537   olsr_load_plugins();
538
539   OLSR_PRINTF(1, "Main address: %s\n\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
540
541 #ifdef LINUX_NETLINK_ROUTING
542   /* create policy routing priorities if necessary */
543   if (DEF_RT_NONE != olsr_cnf->rt_table_pri) {
544     olsr_os_policy_rule(olsr_cnf->ip_version,
545         olsr_cnf->rt_table, olsr_cnf->rt_table_pri, NULL, true);
546   }
547   if (DEF_RT_NONE != olsr_cnf->rt_table_tunnel_pri) {
548     olsr_os_policy_rule(olsr_cnf->ip_version,
549         olsr_cnf->rt_table_tunnel, olsr_cnf->rt_table_tunnel_pri, NULL, true);
550   }
551   if (DEF_RT_NONE != olsr_cnf->rt_table_default_pri) {
552     olsr_os_policy_rule(olsr_cnf->ip_version,
553         olsr_cnf->rt_table_default, olsr_cnf->rt_table_default_pri, NULL, true);
554   }
555
556   /* OLSR sockets */
557   if (DEF_RT_NONE != olsr_cnf->rt_table_defaultolsr_pri) {
558     for (ifn = ifnet; ifn; ifn = ifn->int_next) {
559       olsr_os_policy_rule(olsr_cnf->ip_version, olsr_cnf->rt_table_default,
560           olsr_cnf->rt_table_defaultolsr_pri, ifn->int_name, true);
561     }
562   }
563
564   /* trigger gateway selection */
565   if (olsr_cnf->smart_gw_active) {
566     olsr_trigger_inetgw_startup();
567   }
568
569   /* trigger niit static route setup */
570   if (olsr_cnf->use_niit) {
571     olsr_setup_niit_routes();
572   }
573
574   /* create lo:olsr interface */
575   if (olsr_cnf->use_src_ip_routes) {
576     olsr_os_localhost_if(&olsr_cnf->main_addr, true);
577   }
578 #endif
579
580   /* Start syslog entry */
581   olsr_syslog(OLSR_LOG_INFO, "%s successfully started", olsrd_version);
582
583   /*
584    *signal-handlers
585    */
586
587   /* ctrl-C and friends */
588 #ifdef WIN32
589 #ifndef WINCE
590   SetConsoleCtrlHandler(SignalHandler, true);
591 #endif
592 #else
593   signal(SIGHUP, olsr_reconfigure);
594   signal(SIGINT, olsr_shutdown);
595   signal(SIGQUIT, olsr_shutdown);
596   signal(SIGILL, olsr_shutdown);
597   signal(SIGABRT, olsr_shutdown);
598   //  signal(SIGSEGV, olsr_shutdown);
599   signal(SIGTERM, olsr_shutdown);
600   signal(SIGPIPE, SIG_IGN);
601   // Ignoring SIGUSR1 and SIGUSR1 by default to be able to use them in plugins
602   signal(SIGUSR1, SIG_IGN);
603   signal(SIGUSR2, SIG_IGN);
604 #endif
605
606   link_changes = false;
607
608   /* Starting scheduler */
609   olsr_scheduler();
610
611   /* Like we're ever going to reach this ;-) */
612   return 1;
613 } /* main */
614
615 /**
616  * Reconfigure olsrd. Currently kind of a hack...
617  *
618  *@param signal the signal that triggered this callback
619  */
620 #ifndef WIN32
621 void olsr_reconfigure(int signo __attribute__ ((unused))) {
622   /* if we are started with -nofork, we do not weant to go into the
623    * background here. So we can simply stop on -HUP
624    */
625   olsr_syslog(OLSR_LOG_INFO, "sot: olsr_reconfigure()\n");
626   if (!olsr_cnf->no_fork) {
627     if (!fork()) {
628       int i;
629       sigset_t sigs;
630       /* New process */
631       sleep(3);
632       sigemptyset(&sigs);
633       sigaddset(&sigs, SIGHUP);
634       sigprocmask(SIG_UNBLOCK, &sigs, NULL);
635       for (i = sysconf(_SC_OPEN_MAX); --i > STDERR_FILENO;) {
636         close(i);
637       }
638       printf("Restarting %s\n", olsr_argv[0]);
639       olsr_syslog(OLSR_LOG_INFO, "Restarting %s\n", olsr_argv[0]);
640       execv(olsr_argv[0], olsr_argv);
641       olsr_syslog(OLSR_LOG_ERR, "execv(%s) fails: %s!\n", olsr_argv[0],
642           strerror(errno));
643     } else {
644       olsr_syslog(OLSR_LOG_INFO, "RECONFIGURING!\n");
645     }
646   }
647   olsr_shutdown(0);
648 }
649 #endif
650
651 static void olsr_shutdown_messages(void) {
652   struct interface *ifn;
653
654   /* send TC reset */
655   for (ifn = ifnet; ifn; ifn = ifn->int_next) {
656     /* clean output buffer */
657     net_output(ifn);
658
659     /* send 'I'm gone' messages */
660     if (olsr_cnf->lq_level > 0) {
661       olsr_output_lq_tc(ifn);
662       olsr_output_lq_hello(ifn);
663     }
664     else {
665       generate_tc(ifn);
666       generate_hello(ifn);
667     }
668     net_output(ifn);
669   }
670 }
671
672 /**
673  *Function called at shutdown. Signal handler
674  *
675  * @param signal the signal that triggered this call
676  */
677 #ifdef WIN32
678 int __stdcall
679 SignalHandler(unsigned long signo)
680 #else
681 static void olsr_shutdown(int signo __attribute__ ((unused)))
682 #endif
683 {
684   struct interface *ifn;
685   int exit_value;
686
687   OLSR_PRINTF(1, "Received signal %d - shutting down\n", (int)signo);
688
689 #ifdef WIN32
690   OLSR_PRINTF(1, "Waiting for the scheduler to stop.\n");
691
692   olsr_win32_end_request = TRUE;
693
694   while (!olsr_win32_end_flag)
695   Sleep(100);
696
697   OLSR_PRINTF(1, "Scheduler stopped.\n");
698 #endif
699
700   /* clear all links and send empty hellos/tcs */
701   olsr_reset_all_links();
702
703   /* deactivate fisheye and immediate TCs */
704   olsr_cnf->lq_fish = 0;
705   for (ifn = ifnet; ifn; ifn = ifn->int_next) {
706     ifn->immediate_send_tc = false;
707   }
708   increase_local_ansn();
709
710   /* send first shutdown message burst */
711   olsr_shutdown_messages();
712
713   /* delete all routes */
714   olsr_delete_all_kernel_routes();
715
716   /* send second shutdown message burst */
717   olsr_shutdown_messages();
718
719   /* now try to cleanup the rest of the mess */
720   olsr_delete_all_tc_entries();
721
722   olsr_delete_all_mid_entries();
723
724 #ifdef LINUX_NETLINK_ROUTING
725   /* trigger gateway selection */
726   if (olsr_cnf->smart_gw_active) {
727     olsr_cleanup_gateways();
728   }
729
730   /* trigger niit static route cleanup */
731   if (olsr_cnf->use_niit) {
732     olsr_cleanup_niit_routes();
733   }
734
735   /* cleanup lo:olsr interface */
736   if (olsr_cnf->use_src_ip_routes) {
737     olsr_os_localhost_if(&olsr_cnf->main_addr, false);
738   }
739 #endif
740
741   olsr_destroy_parser();
742
743   OLSR_PRINTF(1, "Closing sockets...\n");
744
745   /* front-end IPC socket */
746   if (olsr_cnf->ipc_connections > 0) {
747     shutdown_ipc();
748   }
749
750   /* OLSR sockets */
751   for (ifn = ifnet; ifn; ifn = ifn->int_next) {
752     close(ifn->olsr_socket);
753     close(ifn->send_socket);
754
755 #ifdef LINUX_NETLINK_ROUTING
756     if (DEF_RT_NONE != olsr_cnf->rt_table_defaultolsr_pri) {
757       olsr_os_policy_rule(olsr_cnf->ip_version, olsr_cnf->rt_table_default,
758           olsr_cnf->rt_table_defaultolsr_pri, ifn->int_name, false);
759     }
760 #endif
761   }
762
763   /* Closing plug-ins */
764   olsr_close_plugins();
765
766   /* Reset network settings */
767   net_os_restore_ifoptions();
768
769   /* ioctl socket */
770   close(olsr_cnf->ioctl_s);
771
772 #ifdef LINUX_NETLINK_ROUTING
773   if (DEF_RT_NONE != olsr_cnf->rt_table_pri) {
774     olsr_os_policy_rule(olsr_cnf->ip_version,
775         olsr_cnf->rt_table, olsr_cnf->rt_table_pri, NULL, false);
776   }
777   if (DEF_RT_NONE != olsr_cnf->rt_table_tunnel_pri) {
778     olsr_os_policy_rule(olsr_cnf->ip_version,
779         olsr_cnf->rt_table_tunnel, olsr_cnf->rt_table_tunnel_pri, NULL, false);
780   }
781   if (DEF_RT_NONE != olsr_cnf->rt_table_default_pri) {
782     olsr_os_policy_rule(olsr_cnf->ip_version,
783         olsr_cnf->rt_table_default, olsr_cnf->rt_table_default_pri, NULL, false);
784   }
785   close(olsr_cnf->rtnl_s);
786   close (olsr_cnf->rt_monitor_socket);
787 #endif
788
789 #if defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
790   /* routing socket */
791   close(olsr_cnf->rts);
792 #endif
793
794   /* Free cookies and memory pools attached. */
795   OLSR_PRINTF(0, "Free all memory...\n");
796   olsr_delete_all_cookies();
797
798   olsr_syslog(OLSR_LOG_INFO, "%s stopped", olsrd_version);
799
800   OLSR_PRINTF(1, "\n <<<< %s - terminating >>>>\n           http://www.olsr.org\n", olsrd_version);
801
802   exit_value = olsr_cnf->exit_value;
803   olsrd_free_cnf(olsr_cnf);
804
805   exit(exit_value);
806 }
807
808 /**
809  * Print the command line usage
810  */
811 static void print_usage(bool error) {
812   fprintf(
813       stderr,
814         "%s"
815         "usage: olsrd [-f <configfile>] [ -i interface1 interface2 ... ]\n"
816         "  [-d <debug_level>] [-ipv6] [-multi <IPv6 multicast address>]\n"
817         "  [-lql <LQ level>] [-lqw <LQ winsize>] [-lqnt <nat threshold>]\n"
818         "  [-bcast <broadcastaddr>] [-ipc] [-dispin] [-dispout] [-delgw]\n"
819         "  [-hint <hello interval (secs)>] [-tcint <tc interval (secs)>]\n"
820         "  [-midint <mid interval (secs)>] [-hnaint <hna interval (secs)>]\n"
821         "  [-T <Polling Rate (secs)>] [-nofork] [-hemu <ip_address>]\n"
822         "  [-lql <LQ level>] [-lqa <LQ aging factor>]\n",
823         error ? "An error occured somwhere between your keyboard and your chair!\n" : "");
824 }
825
826 /**
827  * Sets the provided configuration on all unconfigured
828  * interfaces
829  *
830  * @param ifs a linked list of interfaces to check and possible update
831  * @param cnf the default configuration to set on unconfigured interfaces
832  */
833 int set_default_ifcnfs(struct olsr_if *ifs, struct if_config_options *cnf) {
834   int changes = 0;
835
836   while (ifs) {
837     if (ifs->cnf == NULL) {
838       ifs->cnf = olsr_malloc(sizeof(struct if_config_options),
839           "Set default config");
840       *ifs->cnf = *cnf;
841       changes++;
842     }
843     ifs = ifs->next;
844   }
845   return changes;
846 }
847
848 #define NEXT_ARG do { argv++;argc--; } while (0)
849 #define CHECK_ARGC do { if(!argc) { \
850       if((argc - 1) == 1){ \
851       fprintf(stderr, "Error parsing command line options!\n"); \
852       } else { \
853       argv--; \
854       fprintf(stderr, "You must provide a parameter when using the %s switch!\n", *argv); \
855      } \
856      olsr_exit(__func__, EXIT_FAILURE); \
857      } } while (0)
858
859 /**
860  * Process command line arguments passed to olsrd
861  *
862  */
863 static int olsr_process_arguments(int argc, char *argv[],
864     struct olsrd_config *cnf, struct if_config_options *ifcnf) {
865   while (argc > 1) {
866     NEXT_ARG;
867 #ifdef WIN32
868     /*
869      *Interface list
870      */
871     if (strcmp(*argv, "-int") == 0) {
872       ListInterfaces();
873       exit(0);
874     }
875 #endif
876
877     /*
878      *Configfilename
879      */
880     if (strcmp(*argv, "-f") == 0) {
881       fprintf(stderr, "Configfilename must ALWAYS be first argument!\n\n");
882       olsr_exit(__func__, EXIT_FAILURE);
883     }
884
885     /*
886      *Use IP version 6
887      */
888     if (strcmp(*argv, "-ipv6") == 0) {
889       cnf->ip_version = AF_INET6;
890       continue;
891     }
892
893     /*
894      *Broadcast address
895      */
896     if (strcmp(*argv, "-bcast") == 0) {
897       struct in_addr in;
898       NEXT_ARG;
899       CHECK_ARGC;
900
901       if (inet_aton(*argv, &in) == 0) {
902         printf("Invalid broadcast address! %s\nSkipping it!\n", *argv);
903         continue;
904       }
905       memcpy(&ifcnf->ipv4_multicast.v4, &in.s_addr, sizeof(ifcnf->ipv4_multicast.v4));
906       continue;
907     }
908
909     /*
910      * Set LQ level
911      */
912     if (strcmp(*argv, "-lql") == 0) {
913       int tmp_lq_level;
914       NEXT_ARG;
915       CHECK_ARGC;
916
917       /* Sanity checking is done later */
918       sscanf(*argv, "%d", &tmp_lq_level);
919       olsr_cnf->lq_level = tmp_lq_level;
920       continue;
921     }
922
923     /*
924      * Set LQ winsize
925      */
926     if (strcmp(*argv, "-lqa") == 0) {
927       float tmp_lq_aging;
928       NEXT_ARG;
929       CHECK_ARGC;
930
931       sscanf(*argv, "%f", &tmp_lq_aging);
932
933       if (tmp_lq_aging < MIN_LQ_AGING || tmp_lq_aging > MAX_LQ_AGING) {
934         printf("LQ aging factor %f not allowed. Range [%f-%f]\n", tmp_lq_aging,
935             MIN_LQ_AGING, MAX_LQ_AGING);
936         olsr_exit(__func__, EXIT_FAILURE);
937       }
938       olsr_cnf->lq_aging = tmp_lq_aging;
939       continue;
940     }
941
942     /*
943      * Set NAT threshold
944      */
945     if (strcmp(*argv, "-lqnt") == 0) {
946       float tmp_lq_nat_thresh;
947       NEXT_ARG;
948       CHECK_ARGC;
949
950       sscanf(*argv, "%f", &tmp_lq_nat_thresh);
951
952       if (tmp_lq_nat_thresh < 0.1 || tmp_lq_nat_thresh > 1.0) {
953         printf("NAT threshold %f not allowed. Range [%f-%f]\n",
954             tmp_lq_nat_thresh, 0.1, 1.0);
955         olsr_exit(__func__, EXIT_FAILURE);
956       }
957       olsr_cnf->lq_nat_thresh = tmp_lq_nat_thresh;
958       continue;
959     }
960
961     /*
962      * Enable additional debugging information to be logged.
963      */
964     if (strcmp(*argv, "-d") == 0) {
965       NEXT_ARG;
966       CHECK_ARGC;
967
968       sscanf(*argv, "%d", &cnf->debug_level);
969       continue;
970     }
971
972     /*
973      * Interfaces to be used by olsrd.
974      */
975     if (strcmp(*argv, "-i") == 0) {
976       NEXT_ARG;
977       CHECK_ARGC;
978
979       if (*argv[0] == '-') {
980         fprintf(stderr, "You must provide an interface label!\n");
981         olsr_exit(__func__, EXIT_FAILURE);
982       }
983       printf("Queuing if %s\n", *argv);
984       olsr_create_olsrif(*argv, false);
985
986       while ((argc - 1) && (argv[1][0] != '-')) {
987         NEXT_ARG;
988         printf("Queuing if %s\n", *argv);
989         olsr_create_olsrif(*argv, false);
990       }
991
992       continue;
993     }
994     /*
995      * Set the hello interval to be used by olsrd.
996      *
997      */
998     if (strcmp(*argv, "-hint") == 0) {
999       NEXT_ARG;
1000       CHECK_ARGC;
1001       sscanf(*argv, "%f", &ifcnf->hello_params.emission_interval);
1002       ifcnf->hello_params.validity_time = ifcnf->hello_params.emission_interval
1003           * 3;
1004       continue;
1005     }
1006
1007     /*
1008      * Set the HNA interval to be used by olsrd.
1009      *
1010      */
1011     if (strcmp(*argv, "-hnaint") == 0) {
1012       NEXT_ARG;
1013       CHECK_ARGC;
1014       sscanf(*argv, "%f", &ifcnf->hna_params.emission_interval);
1015       ifcnf->hna_params.validity_time = ifcnf->hna_params.emission_interval * 3;
1016       continue;
1017     }
1018
1019     /*
1020      * Set the MID interval to be used by olsrd.
1021      *
1022      */
1023     if (strcmp(*argv, "-midint") == 0) {
1024       NEXT_ARG;
1025       CHECK_ARGC;
1026       sscanf(*argv, "%f", &ifcnf->mid_params.emission_interval);
1027       ifcnf->mid_params.validity_time = ifcnf->mid_params.emission_interval * 3;
1028       continue;
1029     }
1030
1031     /*
1032      * Set the tc interval to be used by olsrd.
1033      *
1034      */
1035     if (strcmp(*argv, "-tcint") == 0) {
1036       NEXT_ARG;
1037       CHECK_ARGC;
1038       sscanf(*argv, "%f", &ifcnf->tc_params.emission_interval);
1039       ifcnf->tc_params.validity_time = ifcnf->tc_params.emission_interval * 3;
1040       continue;
1041     }
1042
1043     /*
1044      * Set the polling interval to be used by olsrd.
1045      */
1046     if (strcmp(*argv, "-T") == 0) {
1047       NEXT_ARG;
1048       CHECK_ARGC;
1049       sscanf(*argv, "%f", &cnf->pollrate);
1050       continue;
1051     }
1052
1053     /*
1054      * Should we display the contents of packages beeing sent?
1055      */
1056     if (strcmp(*argv, "-dispin") == 0) {
1057       parser_set_disp_pack_in(true);
1058       continue;
1059     }
1060
1061     /*
1062      * Should we display the contents of incoming packages?
1063      */
1064     if (strcmp(*argv, "-dispout") == 0) {
1065       net_set_disp_pack_out(true);
1066       continue;
1067     }
1068
1069     /*
1070      * Should we set up and send on a IPC socket for the front-end?
1071      */
1072     if (strcmp(*argv, "-ipc") == 0) {
1073       cnf->ipc_connections = 1;
1074       continue;
1075     }
1076
1077     /*
1078      * IPv6 multicast addr
1079      */
1080     if (strcmp(*argv, "-multi") == 0) {
1081       struct in6_addr in6;
1082       NEXT_ARG;
1083       CHECK_ARGC;
1084       if (inet_pton(AF_INET6, *argv, &in6) <= 0) {
1085         fprintf(stderr, "Failed converting IP address %s\n", *argv);
1086         exit(EXIT_FAILURE);
1087       }
1088
1089       memcpy(&ifcnf->ipv6_multicast, &in6, sizeof(struct in6_addr));
1090
1091       continue;
1092     }
1093
1094     /*
1095      * Host emulation
1096      */
1097     if (strcmp(*argv, "-hemu") == 0) {
1098       struct in_addr in;
1099       struct olsr_if *ifa;
1100
1101       NEXT_ARG;
1102       CHECK_ARGC;
1103       if (inet_pton(AF_INET, *argv, &in) <= 0) {
1104         fprintf(stderr, "Failed converting IP address %s\n", *argv);
1105         exit(EXIT_FAILURE);
1106       }
1107       /* Add hemu interface */
1108
1109       ifa = olsr_create_olsrif("hcif01", true);
1110
1111       if (!ifa)
1112         continue;
1113
1114       ifa->cnf = get_default_if_config();
1115       ifa->host_emul = true;
1116       memcpy(&ifa->hemu_ip, &in, sizeof(union olsr_ip_addr));
1117       cnf->host_emul = true;
1118
1119       continue;
1120     }
1121
1122     /*
1123      * Delete possible default GWs
1124      */
1125     if (strcmp(*argv, "-delgw") == 0) {
1126       olsr_cnf->del_gws = true;
1127       continue;
1128     }
1129
1130     if (strcmp(*argv, "-nofork") == 0) {
1131       cnf->no_fork = true;
1132       continue;
1133     }
1134
1135     return -1;
1136   }
1137   return 0;
1138 }
1139
1140 /*
1141  * Local Variables:
1142  * c-basic-offset: 2
1143  * indent-tabs-mode: nil
1144  * End:
1145  */