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