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