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