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