3 * The olsr.org Optimized Link-State Routing daemon(olsrd)
4 * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * * Neither the name of olsr.org, olsrd nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
34 * Visit http://www.olsr.org for more information.
36 * If you find this software useful feel free to make a donation
37 * to the project. For more information see the website or contact
38 * the copyright holders.
49 #include "common/avl.h"
50 #include "common/avl_olsr_comp.h"
53 #include "scheduler.h"
55 #include "plugin_loader.h"
58 #include "olsr_cfg_gen.h"
59 #include "common/string.h"
61 #include "duplicate_set.h"
62 #include "olsr_comport.h"
63 #include "neighbor_table.h"
64 #include "olsr_logging.h"
65 #include "olsr_callbacks.h"
68 #include "os_kernel_routes.h"
70 #include "os_system.h"
73 #include <linux/types.h>
74 #include <linux/rtnetlink.h>
78 #define STDOUT_PULSE_INT 600 /* msec */
81 int __stdcall SignalHandler(unsigned long signo);
83 static void signal_shutdown(int);
85 static void olsr_shutdown(void);
88 * Local function prototypes
91 static void signal_reconfigure(int);
94 /* Global stuff externed in olsr_cfg.h */
95 struct olsr_config *olsr_cnf; /* The global configuration */
97 enum app_state app_state = STATE_INIT;
99 static char copyright_string[] __attribute__ ((unused)) =
100 "The olsr.org Optimized Link-State Routing daemon(olsrd) Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org) All rights reserved.";
102 static char pulsedata[] = "\\|/-";
103 static uint8_t pulse_state = 0;
105 static struct timer_entry *hna_gen_timer;
106 static struct timer_entry *mid_gen_timer;
107 static struct timer_entry *tc_gen_timer;
110 generate_stdout_pulse(void *foo __attribute__ ((unused)))
112 if (pulsedata[++pulse_state] == '\0') {
115 fprintf(stderr, "%c\r", pulsedata[pulse_state]);
123 main(int argc, char *argv[])
125 /* Some cookies for stats keeping */
126 static struct olsr_timer_info *pulse_timer_info = NULL;
127 static struct olsr_timer_info *tc_gen_timer_info = NULL;
128 static struct olsr_timer_info *mid_gen_timer_info = NULL;
129 static struct olsr_timer_info *hna_gen_timer_info = NULL;
131 char conf_file_name[FILENAME_MAX];
132 char parse_msg[FILENAME_MAX + 256];
134 #if !defined(REMOVE_LOG_INFO) || !defined(REMOVE_LOG_ERROR)
135 struct ipaddr_str buf;
142 /* paranoia checks */
143 assert(sizeof(uint8_t) == 1);
144 assert(sizeof(uint16_t) == 2);
145 assert(sizeof(uint32_t) == 4);
146 assert(sizeof(int8_t) == 1);
147 assert(sizeof(int16_t) == 2);
148 assert(sizeof(int32_t) == 4);
150 setbuf(stdout, NULL);
151 setbuf(stderr, NULL);
153 /* Using PID as random seed */
156 /* call os dependent argument preprocessor */
160 * Set default configfile name
164 GetWindowsDirectory(conf_file_name, sizeof(conf_file_name) - 1 - strlen(OLSRD_CONF_FILE_NAME));
166 conf_file_name[0] = 0;
169 len = strlen(conf_file_name);
171 if (len == 0 || conf_file_name[len - 1] != '\\') {
172 conf_file_name[len++] = '\\';
175 strscpy(conf_file_name + len, OLSRD_CONF_FILE_NAME, sizeof(conf_file_name) - len);
177 strscpy(conf_file_name, OLSRD_GLOBAL_CONF_FILE, sizeof(conf_file_name));
181 * set up configuration prior to processing commandline options
183 switch (olsr_parse_cfg(argc, argv, conf_file_name, parse_msg, &olsr_cnf)) {
186 fprintf(stderr, "Error: %s\n", parse_msg);
187 os_exit(EXIT_FAILURE);
191 fprintf(stderr, "Warning: %s\n", parse_msg);
195 os_exit(EXIT_SUCCESS);
202 /* Set avl tree comparator */
203 if (olsr_cnf->ipsize == 4) {
204 avl_comp_default = avl_comp_ipv4;
205 avl_comp_addr_origin_default = avl_comp_ipv4_addr_origin;
206 avl_comp_prefix_default = avl_comp_ipv4_prefix;
207 avl_comp_prefix_origin_default = avl_comp_ipv4_prefix_origin;
209 avl_comp_default = avl_comp_ipv6;
210 avl_comp_addr_origin_default = avl_comp_ipv6_addr_origin;
211 avl_comp_prefix_default = avl_comp_ipv6_prefix;
212 avl_comp_prefix_origin_default = avl_comp_ipv6_prefix_origin;
215 /* initialize logging */
218 OLSR_INFO(LOG_MAIN, "\n *** %s ***\n Build date: %s on %s\n http://www.olsr.org\n\n", olsrd_version, build_date, build_host);
220 /* Sanity check configuration */
221 if (olsr_sanity_check_cfg(olsr_cnf) < 0) {
222 olsr_exit(EXIT_FAILURE);
225 /* setup os specific global options */
229 /* Check if user is root */
231 OLSR_ERROR(LOG_MAIN, "You must be root(uid = 0) to run olsrd!\nExiting\n\n");
232 olsr_exit(EXIT_FAILURE);
235 if (WSAStartup(0x0202, &WsaData)) {
236 OLSR_ERROR(LOG_MAIN, "Could not initialize WinSock.\n");
237 olsr_exit(EXIT_FAILURE);
241 /* initialize cookie system */
242 olsr_memcookie_init();
244 /* Initialize timers and scheduler part */
247 /* initialize callback system */
248 olsr_callback_init();
250 /* generate global timers */
251 pulse_timer_info = olsr_alloc_timerinfo("Stdout pulse", &generate_stdout_pulse, true);
252 tc_gen_timer_info = olsr_alloc_timerinfo("TC generation", &olsr_output_lq_tc, true);
253 mid_gen_timer_info = olsr_alloc_timerinfo("MID generation", &generate_mid, true);
254 hna_gen_timer_info = olsr_alloc_timerinfo("HNA generation", &generate_hna, true);
256 /* initialize plugin system */
257 olsr_init_pluginsystem();
258 olsr_plugins_init(true);
260 /* Initialize link set */
261 olsr_init_link_set();
263 /* Initialize duplicate table */
264 olsr_init_duplicate_set();
266 /* Initialize neighbor table */
267 olsr_init_neighbor_table();
269 /* Initialize routing table */
270 olsr_init_routing_table();
272 /* Initialize topology */
275 /* Initialize MID set */
278 /* Initialize HNA set */
281 /* enable lq-plugins */
282 olsr_plugins_enable(PLUGIN_TYPE_LQ, true);
284 /* initialize built in server services */
294 * socket for ioctl calls
296 olsr_cnf->ioctl_s = socket(olsr_cnf->ip_version, SOCK_DGRAM, 0);
297 if (olsr_cnf->ioctl_s < 0) {
298 OLSR_ERROR(LOG_MAIN, "ioctl socket: %s\n", strerror(errno));
299 olsr_exit(EXIT_FAILURE);
302 olsr_cnf->rtnl_s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
303 if (olsr_cnf->rtnl_s < 0) {
304 OLSR_ERROR(LOG_MAIN, "rtnetlink socket: %s\n", strerror(errno));
305 olsr_exit(EXIT_FAILURE);
307 os_socket_set_nonblocking(olsr_cnf->rtnl_s);
309 /* Create rule for RtTable to resolve route insertion problems*/
310 if ( ( olsr_cnf->rt_table < 253) & ( olsr_cnf->rt_table > 0 ) ) {
311 OLSR_WARN(LOG_NETWORKING,"make sure to have correct policy routing rules (destination based rules are required, or a dummy rule with prio like 65535)");
312 /*olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rt_table, RTM_NEWRULE);*/
317 * create routing socket
319 #if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
320 olsr_cnf->rts_bsd = socket(PF_ROUTE, SOCK_RAW, 0);
321 if (olsr_cnf->rts_bsd < 0) {
322 OLSR_ERROR(LOG_MAIN, "routing socket: %s\n", strerror(errno));
323 olsr_exit(EXIT_FAILURE);
327 /* Initialize parser */
330 /* Initialize route-exporter */
331 olsr_init_export_route();
333 /* Initialize message sequencnumber */
336 /* Initialize dynamic willingness calculation */
337 olsr_init_willingness();
340 *Set up willingness/APM
342 if (olsr_cnf->willingness_auto) {
343 olsr_calculate_willingness();
347 /* Initializing lo:olsr if necessary */
348 if (olsr_cnf->source_ip_mode) {
349 OLSR_INFO(LOG_NETWORKING, "Initializing lo:olsr interface for source ip mode...\n");
350 if (olsr_os_localhost_if(&olsr_cnf->router_id, true) <= 0) {
351 OLSR_ERROR(LOG_NETWORKING, "Cannot create lo:olsr interface for ip '%s'\n", olsr_ip_to_string(&buf, &olsr_cnf->router_id));
352 olsr_exit(EXIT_FAILURE);
357 /* Initializing networkinterfaces */
358 if (!init_interfaces()) {
359 if (olsr_cnf->allow_no_interfaces) {
361 "No interfaces detected! This might be intentional, but it also might mean that your configuration is fubar.\nI will continue after 5 seconds...\n");
364 OLSR_ERROR(LOG_MAIN, "No interfaces detected!\nBailing out!\n");
365 olsr_exit(EXIT_FAILURE);
369 /* Print heartbeat to stdout */
372 if (olsr_cnf->log_target_stderr > 0 && isatty(STDOUT_FILENO)) {
373 olsr_start_timer(STDOUT_PULSE_INT, 0, NULL, pulse_timer_info);
379 if (!olsr_cnf->no_fork) {
380 OLSR_INFO(LOG_MAIN, "%s detaching from the current process...\n", olsrd_version);
381 if (daemon(0, 0) < 0) {
382 OLSR_ERROR(LOG_MAIN, "daemon(3) failed: %s\n", strerror(errno));
383 olsr_exit(EXIT_FAILURE);
388 /* activate LQ algorithm */
391 OLSR_INFO(LOG_MAIN, "Main address: %s\n\n", olsr_ip_to_string(&buf, &olsr_cnf->router_id));
393 /* Start syslog entry */
394 OLSR_INFO(LOG_MAIN, "%s successfully started", olsrd_version);
400 /* ctrl-C and friends */
403 SetConsoleCtrlHandler(SignalHandler, true);
407 struct sigaction act;
408 sigemptyset(&act.sa_mask);
410 act.sa_handler = signal_reconfigure;
411 sigaction(SIGHUP, &act, NULL);
412 act.sa_handler = signal_shutdown;
413 sigaction(SIGINT, &act, NULL);
414 sigaction(SIGQUIT, &act, NULL);
415 sigaction(SIGILL, &act, NULL);
416 sigaction(SIGABRT, &act, NULL);
417 // sigaction(SIGSEGV, &act, NULL);
418 sigaction(SIGTERM, &act, NULL);
419 act.sa_handler = SIG_IGN;
420 sigaction(SIGPIPE, &act, NULL);
421 // Ignoring SIGUSR1 and SIGUSR1 by default to be able to use them in plugins
422 sigaction(SIGUSR1, &act, NULL);
423 sigaction(SIGUSR2, &act, NULL);
427 link_changes = false;
430 olsr_start_timer(olsr_cnf->tc_params.emission_interval, TC_JITTER, NULL, tc_gen_timer_info);
432 olsr_start_timer(olsr_cnf->mid_params.emission_interval, MID_JITTER, NULL, mid_gen_timer_info);
434 olsr_start_timer(olsr_cnf->hna_params.emission_interval, HNA_JITTER, NULL, hna_gen_timer_info);
436 /* enable default plugins */
437 olsr_plugins_enable(PLUGIN_TYPE_DEFAULT, true);
439 /* Starting scheduler */
440 app_state = STATE_RUNNING;
443 olsr_stop_timer(tc_gen_timer);
446 olsr_stop_timer(mid_gen_timer);
447 mid_gen_timer = NULL;
449 olsr_stop_timer(hna_gen_timer);
450 hna_gen_timer = NULL;
452 exitcode = olsr_cnf->exit_value;
455 OLSR_ERROR(LOG_MAIN, "terminating and got \"init\"?");
456 exitcode = EXIT_FAILURE;
459 OLSR_ERROR(LOG_MAIN, "terminating and got \"running\"?");
460 exitcode = EXIT_FAILURE;
463 case STATE_RECONFIGURE:
464 /* if we are started with -nofork, we do not weant to go into the
465 * background here. So we can simply be the child process.
467 switch (olsr_cnf->no_fork ? 0 : fork()) {
471 for (i = sysconf(_SC_OPEN_MAX); --i > STDERR_FILENO;) {
475 OLSR_INFO(LOG_MAIN, "Restarting %s\n", argv[0]);
476 execv(argv[0], argv);
477 /* if we reach this, the exev() failed */
478 OLSR_ERROR(LOG_MAIN, "execv() failed: %s", strerror(errno));
479 /* and we simply shutdown */
480 exitcode = EXIT_FAILURE;
484 OLSR_ERROR(LOG_MAIN, "fork() failed: %s", strerror(errno));
485 /* and we simply shutdown */
486 exitcode = EXIT_FAILURE;
490 OLSR_INFO(LOG_MAIN, "Reconfiguring OLSR\n");
506 * Request reconfiguration of olsrd.
508 *@param signal the signal that triggered this callback
511 signal_reconfigure(int signo __attribute__ ((unused)))
513 const int save_errno = errno;
514 OLSR_INFO(LOG_MAIN, "Received signal %d - requesting reconfiguration", signo);
515 app_state = STATE_RECONFIGURE;
522 *Function called at shutdown. Signal handler
524 * @param signal the signal that triggered this call
528 SignalHandler(unsigned long signo)
531 signal_shutdown(int signo __attribute__ ((unused)))
534 const int save_errno = errno;
535 OLSR_INFO(LOG_MAIN, "Received signal %d - requesting shutdown", (int)signo);
536 app_state = STATE_SHUTDOWN;
546 struct mid_entry *mid, *iterator;
548 olsr_delete_all_kernel_routes();
550 /* Flush MID database */
551 OLSR_FOR_ALL_MID_ENTRIES(mid, iterator) {
552 olsr_delete_mid_entry(mid);
555 /* Flush TC database */
556 olsr_delete_all_tc_entries();
558 OLSR_INFO(LOG_MAIN, "Closing sockets...\n");
560 /* kill http/telnet server */
563 /* Flush duplicate set */
564 olsr_flush_duplicate_entries();
566 /* Shut down LQ plugin */
569 /* Closing plug-ins */
570 olsr_destroy_pluginsystem();
572 /* Remove active interfaces */
573 destroy_interfaces();
576 /* delete lo:olsr if neccesarry */
577 if (olsr_cnf->source_ip_mode) {
578 olsr_os_localhost_if(&olsr_cnf->router_id, false);
583 os_close(olsr_cnf->ioctl_s);
586 /*if ((olsr_cnf->rttable < 253) & (olsr_cnf->rttable > 0)) {
587 olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable, RTM_DELRULE);
590 os_close(olsr_cnf->rtnl_s);
593 #if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
595 os_close(olsr_cnf->rts_bsd);
598 /* Close and delete all sockets */
599 olsr_flush_sockets();
601 /* Stop and delete all timers. */
604 /* Remove parser hooks */
605 olsr_deinit_parser();
607 /* Remove IP filters */
610 /* release callback system */
611 olsr_callback_cleanup();
613 /* Free cookies and memory pools attached. */
614 olsr_memcookie_cleanup();
616 /* Reset os_specific global options */
619 OLSR_INFO(LOG_MAIN, "\n <<<< %s - terminating >>>>\n http://www.olsr.org\n", olsrd_version);
621 /* cleanup logging system */
625 olsr_free_cfg(olsr_cnf);
631 * indent-tabs-mode: nil