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