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