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