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