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