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