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