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