17df90549e2ffbd18c42cd8ae2955a193c50524b
[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 "socket_parser.h"
56 #include "apm.h"
57 #include "net_os.h"
58 #include "build_msg.h"
59 #include "net_olsr.h"
60 #include "mid_set.h"
61 #include "mpr_selector_set.h"
62
63 #if LINUX_POLICY_ROUTING
64 #include <linux/types.h>
65 #include <linux/rtnetlink.h>
66 #include "kernel_routes.h"
67
68 #endif
69
70 #ifdef WIN32
71 #include <winbase.h>
72 #define close(x) closesocket(x)
73 int __stdcall SignalHandler(unsigned long signo) __attribute__ ((noreturn));
74 void ListInterfaces(void);
75 void DisableIcmpRedirects(void);
76 bool olsr_win32_end_request = false;
77 bool olsr_win32_end_flag = false;
78 #else
79 static void olsr_shutdown(int) __attribute__ ((noreturn));
80 #endif
81
82 /*
83  * Local function prototypes
84  */
85 void olsr_reconfigure(int) __attribute__ ((noreturn));
86
87 static void print_usage(void);
88
89 #ifdef linux
90 static const char* ipip_default_name = "olsr_tunnel";
91 #endif
92
93 static int set_default_ifcnfs(struct olsr_if *, struct if_config_options *);
94
95 static int olsr_process_arguments(int, char *[], struct olsrd_config *,
96     struct if_config_options *);
97
98 #ifndef WIN32
99 static char **olsr_argv;
100 #endif
101
102 static char
103     copyright_string[] __attribute__ ((unused)) =
104         "The olsr.org Optimized Link-State Routing daemon(olsrd) Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org) All rights reserved.";
105
106 /* Data for OLSR locking */
107 #ifndef WIN32
108 static int lock_fd = 0;
109 #endif
110 static char lock_file_name[FILENAME_MAX];
111
112 /*
113  * Creates a zero-length locking file and use fcntl to
114  * place an exclusive lock over it. The lock will be
115  * automatically erased when the olsrd process ends,
116  * so it will even work well with a SIGKILL.
117  *
118  * Additionally the lock can be killed by removing the
119  * locking file.
120  */
121 static void olsr_create_lock_file(void) {
122 #ifdef WIN32
123   HANDLE lck = CreateEvent(NULL, TRUE, FALSE, lock_file_name);
124   if (NULL == lck || ERROR_ALREADY_EXISTS == GetLastError()) {
125     if (NULL == lck) {
126       fprintf(stderr,
127           "Error, cannot create OLSR lock '%s'.\n",
128           lock_file_name);
129     } else {
130       CloseHandle(lck);
131       fprintf(stderr,
132           "Error, cannot aquire OLSR lock '%s'.\n"
133           "Another OLSR instance might be running.\n",
134           lock_file_name);
135     }
136     olsr_exit("", EXIT_FAILURE);
137   }
138 #else
139   struct flock lck;
140
141   /* create file for lock */
142   lock_fd = open(lock_file_name, O_WRONLY | O_CREAT, S_IRWXU);
143   if (lock_fd == 0) {
144     close(lock_fd);
145     fprintf(stderr,
146         "Error, cannot create OLSR lock '%s'.\n",
147         lock_file_name);
148     olsr_exit("", EXIT_FAILURE);
149   }
150
151   /* create exclusive lock for the whole file */
152   lck.l_type = F_WRLCK;
153   lck.l_whence = SEEK_SET;
154   lck.l_start = 0;
155   lck.l_len = 0;
156   lck.l_pid = 0;
157
158   if (fcntl(lock_fd, F_SETLK, &lck) == -1) {
159     close(lock_fd);
160     fprintf(stderr,
161         "Error, cannot aquire OLSR lock '%s'.\n"
162         "Another OLSR instance might be running.\n",
163         lock_file_name);
164     olsr_exit("", EXIT_FAILURE);
165   }
166 #endif
167   return;
168 }
169
170 /**
171  * loads a config file
172  * @return <0 if load failed, 0 otherwise
173  */
174 static int
175 olsrmain_load_config(char *file) {
176   struct stat statbuf;
177
178   if (stat(file, &statbuf) < 0) {
179     fprintf(stderr, "Could not find specified config file %s!\n%s\n\n",
180         file, strerror(errno));
181     return -1;
182   }
183
184   if (olsrd_parse_cnf(file) < 0) {
185     fprintf(stderr, "Error while reading config file %s!\n", file);
186     return -1;
187   }
188   return 0;
189 }
190
191 /**
192  * Main entrypoint
193  */
194
195 int main(int argc, char *argv[]) {
196   struct if_config_options *default_ifcnf;
197   char conf_file_name[FILENAME_MAX];
198   struct ipaddr_str buf;
199   bool loadedConfig = false;
200   int i;
201 #ifdef WIN32
202   WSADATA WsaData;
203   size_t len;
204 #endif
205
206   /* paranoia checks */
207   assert(sizeof(uint8_t) == 1);
208   assert(sizeof(uint16_t) == 2);
209   assert(sizeof(uint32_t) == 4);
210   assert(sizeof(int8_t) == 1);
211   assert(sizeof(int16_t) == 2);
212   assert(sizeof(int32_t) == 4);
213
214   debug_handle = stdout;
215 #ifndef WIN32
216   olsr_argv = argv;
217 #endif
218   setbuf(stdout, NULL);
219   setbuf(stderr, NULL);
220
221 #ifndef WIN32
222   /* Check if user is root */
223   if (geteuid()) {
224     fprintf(stderr, "You must be root(uid = 0) to run olsrd!\nExiting\n\n");
225     exit(EXIT_FAILURE);
226   }
227 #else
228   DisableIcmpRedirects();
229
230   if (WSAStartup(0x0202, &WsaData)) {
231     fprintf(stderr, "Could not initialize WinSock.\n");
232     olsr_exit(__func__, EXIT_FAILURE);
233   }
234 #endif
235
236   /* Open syslog */
237   olsr_openlog("olsrd");
238
239   printf("\n *** %s ***\n Build date: %s on %s\n http://www.olsr.org\n\n",
240       olsrd_version, build_date, build_host);
241
242   /* Using PID as random seed */
243   srandom(getpid());
244
245   /* Init widely used statics */
246   memset(&all_zero, 0, sizeof(union olsr_ip_addr));
247
248   /*
249    * Set configfile name and
250    * check if a configfile name was given as parameter
251    */
252 #ifdef WIN32
253 #ifndef WINCE
254   GetWindowsDirectory(conf_file_name, FILENAME_MAX - 11);
255 #else
256   conf_file_name[0] = 0;
257 #endif
258
259   len = strlen(conf_file_name);
260
261   if (len == 0 || conf_file_name[len - 1] != '\\')
262   conf_file_name[len++] = '\\';
263
264   strscpy(conf_file_name + len, "olsrd.conf", sizeof(conf_file_name) - len);
265 #else
266   strscpy(conf_file_name, OLSRD_GLOBAL_CONF_FILE, sizeof(conf_file_name));
267 #endif
268
269   olsr_cnf = olsrd_get_default_cnf();
270   for (i=1; i < argc-1;) {
271     if (strcmp(argv[i], "-f") == 0) {
272       loadedConfig = true;
273
274       if (olsrmain_load_config(argv[i+1]) < 0) {
275         exit(EXIT_FAILURE);
276       }
277
278       if (i+2 < argc) {
279         memmove(&argv[i], &argv[i+2], sizeof(*argv) * (argc-i-1));
280       }
281       argc -= 2;
282     }
283     else {
284       i++;
285     }
286   }
287
288   /*
289    * set up configuration prior to processing commandline options
290    */
291   if (!loadedConfig && olsrmain_load_config(conf_file_name) == 0) {
292     loadedConfig = true;
293   }
294
295   if (!loadedConfig) {
296     olsrd_free_cnf(olsr_cnf);
297     olsr_cnf = olsrd_get_default_cnf();
298   }
299
300   default_ifcnf = get_default_if_config();
301   if (default_ifcnf == NULL) {
302     fprintf(stderr, "No default ifconfig found!\n");
303     exit(EXIT_FAILURE);
304   }
305
306   /* Initialize timers */
307   olsr_init_timers();
308
309   /*
310    * Process olsrd options.
311    */
312   if (olsr_process_arguments(argc, argv, olsr_cnf, default_ifcnf) < 0) {
313     print_usage();
314     olsr_exit(__func__, EXIT_FAILURE);
315   }
316
317   /*
318    * Set configuration for command-line specified interfaces
319    */
320   set_default_ifcnfs(olsr_cnf->interfaces, default_ifcnf);
321
322   /* free the default ifcnf */
323   free(default_ifcnf);
324
325   /* Sanity check configuration */
326   if (olsrd_sanity_check_cnf(olsr_cnf) < 0) {
327     fprintf(stderr, "Bad configuration!\n");
328     olsr_exit(__func__, EXIT_FAILURE);
329   }
330
331   /*
332    * Establish file lock to prevent multiple instances
333    */
334   if (olsr_cnf->lock_file) {
335     strscpy(lock_file_name, olsr_cnf->lock_file, sizeof(lock_file_name));
336   } else {
337     strscpy(lock_file_name, conf_file_name, sizeof(lock_file_name));
338     strscat(lock_file_name, ".lock", sizeof(lock_file_name));
339   }
340
341   /*
342    * Print configuration
343    */
344   if (olsr_cnf->debug_level > 1) {
345     olsrd_print_cnf(olsr_cnf);
346   }
347 #ifndef WIN32
348   /* Disable redirects globally */
349   disable_redirects_global(olsr_cnf->ip_version);
350 #endif
351
352   /*
353    * socket for ioctl calls
354    */
355   olsr_cnf->ioctl_s = socket(olsr_cnf->ip_version, SOCK_DGRAM, 0);
356   if (olsr_cnf->ioctl_s < 0) {
357 #ifndef WIN32
358     olsr_syslog(OLSR_LOG_ERR, "ioctl socket: %m");
359 #endif
360     olsr_exit(__func__, 0);
361   }
362 #if LINUX_POLICY_ROUTING
363   olsr_cnf->rtnl_s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
364   if (olsr_cnf->rtnl_s < 0) {
365     olsr_syslog(OLSR_LOG_ERR, "rtnetlink socket: %m");
366     olsr_exit(__func__, 0);
367   }
368   fcntl(olsr_cnf->rtnl_s, F_SETFL, O_NONBLOCK);
369 #endif
370
371   /*
372    * create routing socket
373    */
374 #if defined __FreeBSD__ || __FreeBSD_kernel__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
375   olsr_cnf->rts = socket(PF_ROUTE, SOCK_RAW, 0);
376   if (olsr_cnf->rts < 0) {
377     olsr_syslog(OLSR_LOG_ERR, "routing socket: %m");
378     olsr_exit(__func__, 0);
379   }
380 #endif
381
382   /* Init empty TC timer */
383   set_empty_tc_timer(GET_TIMESTAMP(0));
384
385   /*
386    *enable ip forwarding on host
387    */
388   enable_ip_forwarding(olsr_cnf->ip_version);
389
390   /* Initialize parser */
391   olsr_init_parser();
392
393   /* Initialize route-exporter */
394   olsr_init_export_route();
395
396   /* Initialize message sequencnumber */
397   init_msg_seqno();
398
399   /* Initialize dynamic willingness calculation */
400   olsr_init_willingness();
401
402   /*
403    *Set up willingness/APM
404    */
405   if (olsr_cnf->willingness_auto) {
406     if (apm_init() < 0) {
407       OLSR_PRINTF(1, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT);
408
409       olsr_syslog(OLSR_LOG_ERR,
410           "Could not read APM info - setting default willingness(%d)\n",
411           WILL_DEFAULT);
412
413       olsr_cnf->willingness_auto = 0;
414       olsr_cnf->willingness = WILL_DEFAULT;
415     } else {
416       olsr_cnf->willingness = olsr_calculate_willingness();
417
418       OLSR_PRINTF(1, "Willingness set to %d - next update in %.1f secs\n", olsr_cnf->willingness, olsr_cnf->will_int);
419     }
420   }
421
422   /* Initialize net */
423   init_net();
424
425   /* Initializing networkinterfaces */
426   if (!ifinit()) {
427     if (olsr_cnf->allow_no_interfaces) {
428       fprintf(
429           stderr,
430           "No interfaces detected! This might be intentional, but it also might mean that your configuration is fubar.\nI will continue after 5 seconds...\n");
431       olsr_startup_sleep(5);
432     } else {
433       fprintf(stderr, "No interfaces detected!\nBailing out!\n");
434       olsr_exit(__func__, EXIT_FAILURE);
435     }
436   }
437
438   olsr_do_startup_sleep();
439
440   /* Print heartbeat to stdout */
441
442 #if !defined WINCE
443   if (olsr_cnf->debug_level > 0 && isatty(STDOUT_FILENO)) {
444     olsr_start_timer(STDOUT_PULSE_INT, 0, OLSR_TIMER_PERIODIC,
445         &generate_stdout_pulse, NULL, 0);
446   }
447 #endif
448
449   /* Initialize the IPC socket */
450
451   if (olsr_cnf->ipc_connections > 0) {
452     ipc_init();
453   }
454   /* Initialisation of different tables to be used. */
455   olsr_init_tables();
456
457   /* daemon mode */
458 #ifndef WIN32
459   if (olsr_cnf->debug_level == 0 && !olsr_cnf->no_fork) {
460     printf("%s detaching from the current process...\n", olsrd_version);
461     if (daemon(0, 0) < 0) {
462       printf("daemon(3) failed: %s\n", strerror(errno));
463       exit(EXIT_FAILURE);
464     }
465   }
466 #endif
467
468   /*
469    * Create locking file for olsrd, will be cleared after olsrd exits
470    */
471   olsr_create_lock_file();
472
473   /* Load plugins */
474   olsr_load_plugins();
475
476   OLSR_PRINTF(1, "Main address: %s\n\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
477
478 #if LINUX_POLICY_ROUTING
479   /*create smart-gateway-tunnel policy rules*/
480   //!!?? disable smartgateway if not ipv4?, or better: do not start olsr
481   if (olsr_cnf->smart_gateway_active) {
482     int r = olsr_ifconfig(TUNL_BASE,IF_SET_UP);
483     //take up tunl0 device or disable smartgateway
484     olsr_cnf->ipip_base_orig_down = (r == -1 ?true:false);
485     olsr_cnf->smart_gateway_active = (r != 0); //!!?? kernel 2.4 may need true to function as gateway, does it harm to do anyway
486     /*create an interface structure for the tunlbase to store procnet settings*/
487     /*hmmm integrate it into the olsr_interface list to ensure spoof setting clenaup at end!???*/
488     olsr_cnf->ipip_base_if.if_index = if_nametoindex(TUNL_BASE);
489
490     deactivate_spoof(TUNL_BASE, &olsr_cnf->ipip_base_if, AF_INET );//ipip is an ipv4 tunnel
491
492     if (!olsr_cnf->smart_gateway_active) 
493     {
494       printf("disabled smart Gateway! (ipip tunnels not useable for olsrd on this host)");
495     }
496     else {
497       struct olsr_if *cfg_if;
498
499       //need sanity checks for routintg tables
500
501       //question: if rttable_default unconfigured, determine one?
502       //yes use 112
503       //same with smartTable (113)
504
505       //further checks: tabledefault and smartgateway >0 < 253
506       //check if all tables are unique
507       //if not use other values for unconfigured Tables? or stop startup?
508
509       //future improvement: verify if no rule points to default and smartgateway table, with un unknown realm?
510       //nice as we can use realms to give traffic info about gateway tunnel, and ...
511
512       //question: do we set an defaulttable now, which persists if smartgateway is turned off, due to problems (or an rmmodding user) later?
513       //its easier to stick to tables and also better, 
514       //as users will always find the default route on same place.
515
516       //question: make priority of rules configureable (if configured for rttable this might means we shall create this rule (instead the 65535 dummy)
517       //question olsr did never create rules for a custom table (beside the dummy)
518       //should we start now doing so anyways? (beter not, use only new RTTableRule priority)
519
520       //as above ist neither finalized nor done in parser, we use hardcoded values
521       olsr_cnf->ipip_if_index = false;
522       olsr_cnf->ipip_name=ipip_default_name;
523       olsr_cnf->rttable_default=112;
524       olsr_cnf->rttable_smartgw=113;
525       if (olsr_cnf->rttable_default_rule==0) olsr_cnf->rttable_default_rule=65532;
526       if (olsr_cnf->rttable_smartgw_rule==0) olsr_cnf->rttable_smartgw_rule=olsr_cnf->rttable_default_rule+1;
527       if (olsr_cnf->rttable_backup_rule==0) olsr_cnf->rttable_backup_rule=olsr_cnf->rttable_smartgw_rule+1;
528
529 //!!?? just a test
530 olsr_cnf->rttable_rule=65531;
531
532       /*table with default routes for olsr interfaces*/
533       for (cfg_if = olsr_cnf->interfaces; cfg_if; cfg_if = cfg_if->next) {
534         olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable_default, RTM_NEWRULE, 
535                              olsr_cnf->rttable_default_rule, cfg_if->name);
536       }
537       /*table with route into tunnel (for all interfaces)*/
538       olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable_smartgw, RTM_NEWRULE,
539                         olsr_cnf->rttable_smartgw_rule, NULL);
540       /*backup rule to default route table (if tunnel table gets empty)*/
541       olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable_default, RTM_NEWRULE, 
542                         olsr_cnf->rttable_backup_rule, NULL);
543     }
544   }
545
546   /* Create rule for RtTable to resolve route insertion problems*/
547   if ((olsr_cnf->rttable < 253) & (olsr_cnf->rttable > 0)) {
548     olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable, RTM_NEWRULE, (olsr_cnf->rttable_rule>0?olsr_cnf->rttable_rule:65535), NULL);
549   }
550
551   /* Create rtnetlink socket to listen on interface change events RTMGRP_LINK and RTMGRP_IPV4_ROUTE */
552   //todo listen on tunl0 events aswell
553
554 #if LINUX_RTNETLINK_LISTEN
555   rtnetlink_register_socket(RTMGRP_LINK);
556 #endif /*LINUX_RTNETLINK_LISTEN*/
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   olsr_destroy_parser();
702
703   OLSR_PRINTF(1, "Closing sockets...\n");
704
705   /* front-end IPC socket */
706   if (olsr_cnf->ipc_connections > 0) {
707     shutdown_ipc();
708   }
709
710   /* OLSR sockets */
711   for (ifn = ifnet; ifn; ifn = ifn->int_next) {
712     close(ifn->olsr_socket);
713     close(ifn->send_socket);
714   }
715
716   /* Closing plug-ins */
717   olsr_close_plugins();
718
719   /* Reset network settings */
720   restore_settings(olsr_cnf->ip_version);
721
722   /* ioctl socket */
723   close(olsr_cnf->ioctl_s);
724
725 #if LINUX_POLICY_ROUTING
726
727   /*delete smartgw tunnel if it index is known*/
728   if (olsr_cnf->ipip_if_index) olsr_del_tunl();
729
730   /*!!?? we should take down the tunl0 interface*/
731
732   /*we shall delete all rules with an configured prio*/
733   if (olsr_cnf->rttable_default_rule>0) {
734     struct olsr_if * cfg_if;
735     for (cfg_if = olsr_cnf->interfaces; cfg_if; cfg_if = cfg_if->next) {
736       olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable_default, RTM_DELRULE, olsr_cnf->rttable_default_rule, cfg_if->name);
737     }
738   }
739   if (olsr_cnf->rttable_smartgw_rule>0)
740     olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable_smartgw, RTM_DELRULE, olsr_cnf->rttable_smartgw_rule, NULL);
741   if (olsr_cnf->rttable_backup_rule>0)
742     olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable_default, RTM_DELRULE, olsr_cnf->rttable_backup_rule, NULL);
743
744   /*tunl0*/
745   if (olsr_cnf->ipip_base_orig_down) olsr_ifconfig(TUNL_BASE,IF_SET_DOWN);
746
747   /*rp_filter*/
748   if (olsr_cnf->ipip_base_if.if_index) printf("resetting of tunl0 rp_filter not implemented");//!!?? no function extits to reset a single interface
749
750   /* RtTable backup rule */
751   if ((olsr_cnf->rttable < 253) & (olsr_cnf->rttable > 0)) {
752     olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable, RTM_DELRULE, (olsr_cnf->rttable_rule?olsr_cnf->rttable_rule:65535), NULL);
753   }
754
755   close(olsr_cnf->rtnl_s);
756 #endif
757
758 #if defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
759   /* routing socket */
760   close(olsr_cnf->rts);
761 #endif
762
763   /* Free cookies and memory pools attached. */
764   OLSR_PRINTF(0, "Free all memory...\n");
765   olsr_delete_all_cookies();
766
767   olsr_syslog(OLSR_LOG_INFO, "%s stopped", olsrd_version);
768
769   OLSR_PRINTF(1, "\n <<<< %s - terminating >>>>\n           http://www.olsr.org\n", olsrd_version);
770
771   exit_value = olsr_cnf->exit_value;
772   olsrd_free_cnf(olsr_cnf);
773
774   exit(exit_value);
775 }
776
777 /**
778  * Print the command line usage
779  */
780 static void print_usage(void) {
781
782   fprintf(
783       stderr,
784       "An error occured somwhere between your keyboard and your chair!\n"
785         "usage: olsrd [-f <configfile>] [ -i interface1 interface2 ... ]\n"
786         "  [-d <debug_level>] [-ipv6] [-multi <IPv6 multicast address>]\n"
787         "  [-lql <LQ level>] [-lqw <LQ winsize>] [-lqnt <nat threshold>]\n"
788         "  [-bcast <broadcastaddr>] [-ipc] [-dispin] [-dispout] [-delgw]\n"
789         "  [-hint <hello interval (secs)>] [-tcint <tc interval (secs)>]\n"
790         "  [-midint <mid interval (secs)>] [-hnaint <hna interval (secs)>]\n"
791         "  [-T <Polling Rate (secs)>] [-nofork] [-hemu <ip_address>]\n" "  [-lql <LQ level>] [-lqa <LQ aging factor>]\n");
792 }
793
794 /**
795  * Sets the provided configuration on all unconfigured
796  * interfaces
797  *
798  * @param ifs a linked list of interfaces to check and possible update
799  * @param cnf the default configuration to set on unconfigured interfaces
800  */
801 int set_default_ifcnfs(struct olsr_if *ifs, struct if_config_options *cnf) {
802   int changes = 0;
803
804   while (ifs) {
805     if (ifs->cnf == NULL) {
806       ifs->cnf = olsr_malloc(sizeof(struct if_config_options),
807           "Set default config");
808       *ifs->cnf = *cnf;
809       changes++;
810     }
811     ifs = ifs->next;
812   }
813   return changes;
814 }
815
816 #define NEXT_ARG do { argv++;argc--; } while (0)
817 #define CHECK_ARGC do { if(!argc) { \
818       if((argc - 1) == 1){ \
819       fprintf(stderr, "Error parsing command line options!\n"); \
820       } else { \
821       argv--; \
822       fprintf(stderr, "You must provide a parameter when using the %s switch!\n", *argv); \
823      } \
824      olsr_exit(__func__, EXIT_FAILURE); \
825      } } while (0)
826
827 /**
828  * Process command line arguments passed to olsrd
829  *
830  */
831 static int olsr_process_arguments(int argc, char *argv[],
832     struct olsrd_config *cnf, struct if_config_options *ifcnf) {
833   while (argc > 1) {
834     NEXT_ARG;
835 #ifdef WIN32
836     /*
837      *Interface list
838      */
839     if (strcmp(*argv, "-int") == 0) {
840       ListInterfaces();
841       exit(0);
842     }
843 #endif
844
845     /*
846      *Configfilename
847      */
848     if (strcmp(*argv, "-f") == 0) {
849       fprintf(stderr, "Configfilename must ALWAYS be first argument!\n\n");
850       olsr_exit(__func__, EXIT_FAILURE);
851     }
852
853     /*
854      *Use IP version 6
855      */
856     if (strcmp(*argv, "-ipv6") == 0) {
857       cnf->ip_version = AF_INET6;
858       continue;
859     }
860
861     /*
862      *Broadcast address
863      */
864     if (strcmp(*argv, "-bcast") == 0) {
865       struct in_addr in;
866       NEXT_ARG;
867       CHECK_ARGC;
868
869       if (inet_aton(*argv, &in) == 0) {
870         printf("Invalid broadcast address! %s\nSkipping it!\n", *argv);
871         continue;
872       }
873       memcpy(&ifcnf->ipv4_multicast.v4, &in.s_addr, sizeof(ifcnf->ipv4_multicast.v4));
874       continue;
875     }
876
877     /*
878      * Set LQ level
879      */
880     if (strcmp(*argv, "-lql") == 0) {
881       int tmp_lq_level;
882       NEXT_ARG;
883       CHECK_ARGC;
884
885       /* Sanity checking is done later */
886       sscanf(*argv, "%d", &tmp_lq_level);
887       olsr_cnf->lq_level = tmp_lq_level;
888       continue;
889     }
890
891     /*
892      * Set LQ winsize
893      */
894     if (strcmp(*argv, "-lqa") == 0) {
895       float tmp_lq_aging;
896       NEXT_ARG;
897       CHECK_ARGC;
898
899       sscanf(*argv, "%f", &tmp_lq_aging);
900
901       if (tmp_lq_aging < MIN_LQ_AGING || tmp_lq_aging > MAX_LQ_AGING) {
902         printf("LQ aging factor %f not allowed. Range [%f-%f]\n", tmp_lq_aging,
903             MIN_LQ_AGING, MAX_LQ_AGING);
904         olsr_exit(__func__, EXIT_FAILURE);
905       }
906       olsr_cnf->lq_aging = tmp_lq_aging;
907       continue;
908     }
909
910     /*
911      * Set NAT threshold
912      */
913     if (strcmp(*argv, "-lqnt") == 0) {
914       float tmp_lq_nat_thresh;
915       NEXT_ARG;
916       CHECK_ARGC;
917
918       sscanf(*argv, "%f", &tmp_lq_nat_thresh);
919
920       if (tmp_lq_nat_thresh < 0.1 || tmp_lq_nat_thresh > 1.0) {
921         printf("NAT threshold %f not allowed. Range [%f-%f]\n",
922             tmp_lq_nat_thresh, 0.1, 1.0);
923         olsr_exit(__func__, EXIT_FAILURE);
924       }
925       olsr_cnf->lq_nat_thresh = tmp_lq_nat_thresh;
926       continue;
927     }
928
929     /*
930      * Enable additional debugging information to be logged.
931      */
932     if (strcmp(*argv, "-d") == 0) {
933       NEXT_ARG;
934       CHECK_ARGC;
935
936       sscanf(*argv, "%d", &cnf->debug_level);
937       continue;
938     }
939
940     /*
941      * Interfaces to be used by olsrd.
942      */
943     if (strcmp(*argv, "-i") == 0) {
944       NEXT_ARG;
945       CHECK_ARGC;
946
947       if (*argv[0] == '-') {
948         fprintf(stderr, "You must provide an interface label!\n");
949         olsr_exit(__func__, EXIT_FAILURE);
950       }
951       printf("Queuing if %s\n", *argv);
952       queue_if(*argv, false);
953
954       while ((argc - 1) && (argv[1][0] != '-')) {
955         NEXT_ARG;
956         printf("Queuing if %s\n", *argv);
957         queue_if(*argv, false);
958       }
959
960       continue;
961     }
962     /*
963      * Set the hello interval to be used by olsrd.
964      *
965      */
966     if (strcmp(*argv, "-hint") == 0) {
967       NEXT_ARG;
968       CHECK_ARGC;
969       sscanf(*argv, "%f", &ifcnf->hello_params.emission_interval);
970       ifcnf->hello_params.validity_time = ifcnf->hello_params.emission_interval
971           * 3;
972       continue;
973     }
974
975     /*
976      * Set the HNA interval to be used by olsrd.
977      *
978      */
979     if (strcmp(*argv, "-hnaint") == 0) {
980       NEXT_ARG;
981       CHECK_ARGC;
982       sscanf(*argv, "%f", &ifcnf->hna_params.emission_interval);
983       ifcnf->hna_params.validity_time = ifcnf->hna_params.emission_interval * 3;
984       continue;
985     }
986
987     /*
988      * Set the MID interval to be used by olsrd.
989      *
990      */
991     if (strcmp(*argv, "-midint") == 0) {
992       NEXT_ARG;
993       CHECK_ARGC;
994       sscanf(*argv, "%f", &ifcnf->mid_params.emission_interval);
995       ifcnf->mid_params.validity_time = ifcnf->mid_params.emission_interval * 3;
996       continue;
997     }
998
999     /*
1000      * Set the tc interval to be used by olsrd.
1001      *
1002      */
1003     if (strcmp(*argv, "-tcint") == 0) {
1004       NEXT_ARG;
1005       CHECK_ARGC;
1006       sscanf(*argv, "%f", &ifcnf->tc_params.emission_interval);
1007       ifcnf->tc_params.validity_time = ifcnf->tc_params.emission_interval * 3;
1008       continue;
1009     }
1010
1011     /*
1012      * Set the polling interval to be used by olsrd.
1013      */
1014     if (strcmp(*argv, "-T") == 0) {
1015       NEXT_ARG;
1016       CHECK_ARGC;
1017       sscanf(*argv, "%f", &cnf->pollrate);
1018       continue;
1019     }
1020
1021     /*
1022      * Should we display the contents of packages beeing sent?
1023      */
1024     if (strcmp(*argv, "-dispin") == 0) {
1025       parser_set_disp_pack_in(true);
1026       continue;
1027     }
1028
1029     /*
1030      * Should we display the contents of incoming packages?
1031      */
1032     if (strcmp(*argv, "-dispout") == 0) {
1033       net_set_disp_pack_out(true);
1034       continue;
1035     }
1036
1037     /*
1038      * Should we set up and send on a IPC socket for the front-end?
1039      */
1040     if (strcmp(*argv, "-ipc") == 0) {
1041       cnf->ipc_connections = 1;
1042       continue;
1043     }
1044
1045     /*
1046      * IPv6 multicast addr
1047      */
1048     if (strcmp(*argv, "-multi") == 0) {
1049       struct in6_addr in6;
1050       NEXT_ARG;
1051       CHECK_ARGC;
1052       if (inet_pton(AF_INET6, *argv, &in6) <= 0) {
1053         fprintf(stderr, "Failed converting IP address %s\n", *argv);
1054         exit(EXIT_FAILURE);
1055       }
1056
1057       memcpy(&ifcnf->ipv6_multicast, &in6, sizeof(struct in6_addr));
1058
1059       continue;
1060     }
1061
1062     /*
1063      * Host emulation
1064      */
1065     if (strcmp(*argv, "-hemu") == 0) {
1066       struct in_addr in;
1067       struct olsr_if *ifa;
1068
1069       NEXT_ARG;
1070       CHECK_ARGC;
1071       if (inet_pton(AF_INET, *argv, &in) <= 0) {
1072         fprintf(stderr, "Failed converting IP address %s\n", *argv);
1073         exit(EXIT_FAILURE);
1074       }
1075       /* Add hemu interface */
1076
1077       ifa = queue_if("hcif01", true);
1078
1079       if (!ifa)
1080         continue;
1081
1082       ifa->cnf = get_default_if_config();
1083       ifa->host_emul = true;
1084       memcpy(&ifa->hemu_ip, &in, sizeof(union olsr_ip_addr));
1085       cnf->host_emul = true;
1086
1087       continue;
1088     }
1089
1090     /*
1091      * Delete possible default GWs
1092      */
1093     if (strcmp(*argv, "-delgw") == 0) {
1094       olsr_cnf->del_gws = true;
1095       continue;
1096     }
1097
1098     if (strcmp(*argv, "-nofork") == 0) {
1099       cnf->no_fork = true;
1100       continue;
1101     }
1102
1103     return -1;
1104   }
1105   return 0;
1106 }
1107
1108 /*
1109  * Local Variables:
1110  * c-basic-offset: 2
1111  * indent-tabs-mode: nil
1112  * End:
1113  */