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