2 * The olsr.org Optimized Link-State Routing daemon(olsrd)
3 * Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
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.
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.
33 * Visit http://www.olsr.org for more information.
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.
39 * $Id: main.c,v 1.98 2007/09/13 16:08:13 bernd67 Exp $
49 #include "scheduler.h"
51 #include "generate_msg.h"
52 #include "plugin_loader.h"
53 #include "socket_parser.h"
56 #include "build_msg.h"
58 #if LINUX_POLICY_ROUTING
59 #include <linux/types.h>
60 #include <linux/rtnetlink.h>
64 /* Global stuff externed in defs.h */
65 FILE *debug_handle; /* Where to send debug(defaults to stdout) */
66 struct olsrd_config *olsr_cnf; /* The global configuration */
69 #define close(x) closesocket(x)
70 int __stdcall SignalHandler(unsigned long signal) __attribute__((noreturn));
71 void ListInterfaces(void);
72 void DisableIcmpRedirects(void);
73 olsr_bool olsr_win32_end_request = OLSR_FALSE;
74 olsr_bool olsr_win32_end_flag = OLSR_FALSE;
77 olsr_shutdown(int) __attribute__((noreturn));
81 * Local function prototypes
84 olsr_reconfigure(int) __attribute__((noreturn));
90 set_default_ifcnfs(struct olsr_if *, struct if_config_options *);
93 olsr_process_arguments(int, char *[],
94 struct olsrd_config *,
95 struct if_config_options *);
97 static char **olsr_argv;
99 static char copyright_string[] = "The olsr.org Optimized Link-State Routing daemon(olsrd) Copyright (c) 2004, Andreas Tønnesen(andreto@olsr.org) All rights reserved.";
107 main(int argc, char *argv[])
109 struct if_config_options *default_ifcnf;
110 char conf_file_name[FILENAME_MAX];
118 /* Stop the compiler from complaining */
119 (void)copyright_string;
121 debug_handle = stdout;
124 setbuf(stdout, NULL);
125 setbuf(stderr, NULL);
128 /* Check if user is root */
131 fprintf(stderr, "You must be root(uid = 0) to run olsrd!\nExiting\n\n");
135 DisableIcmpRedirects();
137 if (WSAStartup(0x0202, &WsaData))
139 fprintf(stderr, "Could not initialize WinSock.\n");
140 olsr_exit(__func__, EXIT_FAILURE);
144 /* Grab initial timestamp */
145 now_times = times(&tms_buf);
148 olsr_openlog("olsrd");
150 /* Get initial timestep */
152 while (nowtm == NULL)
154 nowtm = localtime((time_t *)&now.tv_sec);
157 printf("\n *** %s ***\n Build date: %s\n http://www.olsr.org\n\n",
161 /* Using PID as random seed */
166 * Set configfile name and
167 * check if a configfile name was given as parameter
171 GetWindowsDirectory(conf_file_name, FILENAME_MAX - 11);
173 conf_file_name[0] = 0;
176 len = strlen(conf_file_name);
178 if (len == 0 || conf_file_name[len - 1] != '\\')
179 conf_file_name[len++] = '\\';
181 strcpy(conf_file_name + len, "olsrd.conf");
183 strncpy(conf_file_name, OLSRD_GLOBAL_CONF_FILE, FILENAME_MAX);
186 if ((argc > 1) && (strcmp(argv[1], "-f") == 0))
193 fprintf(stderr, "You must provide a filename when using the -f switch!\n");
197 if (stat(argv[1], &statbuf) < 0)
199 fprintf(stderr, "Could not find specified config file %s!\n%s\n\n", argv[1], strerror(errno));
203 strncpy(conf_file_name, argv[1], FILENAME_MAX);
209 * set up configuration prior to processing commandline options
211 if((olsr_cnf = olsrd_parse_cnf(conf_file_name)) == NULL)
213 printf("Using default config values(no configfile)\n");
214 olsr_cnf = olsrd_get_default_cnf();
216 if((default_ifcnf = get_default_if_config()) == NULL)
218 fprintf(stderr, "No default ifconfig found!\n");
222 /* Initialize tick resolution */
224 olsr_cnf->system_tick_divider = 1000/sysconf(_SC_CLK_TCK);
226 olsr_cnf->system_tick_divider = 1;
230 * Process olsrd options.
232 if(olsr_process_arguments(argc, argv, olsr_cnf, default_ifcnf) < 0)
235 olsr_exit(__func__, EXIT_FAILURE);
239 * Set configuration for command-line specified interfaces
241 set_default_ifcnfs(olsr_cnf->interfaces, default_ifcnf);
243 /* free the default ifcnf */
246 /* Sanity check configuration */
247 if(olsrd_sanity_check_cnf(olsr_cnf) < 0)
249 fprintf(stderr, "Bad configuration!\n");
250 olsr_exit(__func__, EXIT_FAILURE);
254 * Print configuration
256 if(olsr_cnf->debug_level > 1)
257 olsrd_print_cnf(olsr_cnf);
260 /* Disable redirects globally */
261 disable_redirects_global(olsr_cnf->ip_version);
265 *socket for icotl calls
267 if ((olsr_cnf->ioctl_s = socket(olsr_cnf->ip_version, SOCK_DGRAM, 0)) < 0)
270 olsr_syslog(OLSR_LOG_ERR, "ioctl socket: %m");
271 olsr_exit(__func__, 0);
274 #if LINUX_POLICY_ROUTING
275 if ((olsr_cnf->rtnl_s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0)
277 olsr_syslog(OLSR_LOG_ERR, "rtnetlink socket: %m");
278 olsr_exit(__func__, 0);
280 fcntl(olsr_cnf->rtnl_s, F_SETFL, O_NONBLOCK);
283 #if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
284 if ((olsr_cnf->rts = socket(PF_ROUTE, SOCK_RAW, 0)) < 0)
286 olsr_syslog(OLSR_LOG_ERR, "routing socket: %m");
287 olsr_exit(__func__, 0);
291 /* Init empty TC timer */
292 set_empty_tc_timer(GET_TIMESTAMP(0));
295 *enable ip forwarding on host
297 enable_ip_forwarding(olsr_cnf->ip_version);
299 /* Initialize parser */
302 /* Initialize route-exporter */
303 olsr_init_export_route();
305 /* Initialize message sequencnumber */
308 /* Initialize dynamic willingness calculation */
309 olsr_init_willingness();
312 *Set up willingness/APM
314 if(olsr_cnf->willingness_auto)
318 OLSR_PRINTF(1, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT);
320 olsr_syslog(OLSR_LOG_ERR, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT);
322 olsr_cnf->willingness_auto = 0;
323 olsr_cnf->willingness = WILL_DEFAULT;
327 olsr_cnf->willingness = olsr_calculate_willingness();
329 OLSR_PRINTF(1, "Willingness set to %d - next update in %.1f secs\n", olsr_cnf->willingness, olsr_cnf->will_int);
334 if(olsr_cnf->ip_version == AF_INET6)
336 OLSR_PRINTF(1, "Using IP version 6\n");
337 olsr_cnf->ipsize = sizeof(struct in6_addr);
341 OLSR_PRINTF(1, "Using IP version 4\n");
342 olsr_cnf->ipsize = sizeof(olsr_u32_t);
348 /* Initializing networkinterfaces */
351 if(olsr_cnf->allow_no_interfaces)
353 fprintf(stderr, "No interfaces detected! This might be intentional, but it also might mean that your configuration is fubar.\nI will continue after 5 seconds...\n");
358 fprintf(stderr, "No interfaces detected!\nBailing out!\n");
359 olsr_exit(__func__, EXIT_FAILURE);
363 /* Print heartbeat to stdout */
366 if(olsr_cnf->debug_level > 0 && isatty(STDOUT_FILENO))
367 olsr_register_scheduler_event(&generate_stdout_pulse, NULL, STDOUT_PULSE_INT, 0, NULL);
370 gettimeofday(&now, NULL);
373 /* Initialize the IPC socket */
375 if(olsr_cnf->open_ipc)
378 /* Initialisation of different tables to be used.*/
383 if((olsr_cnf->debug_level == 0) && (!olsr_cnf->no_fork))
385 printf("%s detaching from the current process...\n", SOFTWARE_VERSION);
388 printf("daemon(3) failed: %s\n", strerror(errno));
397 OLSR_PRINTF(1, "Main address: %s\n\n", olsr_ip_to_string(&olsr_cnf->main_addr));
399 /* Start syslog entry */
400 olsr_syslog(OLSR_LOG_INFO, "%s successfully started", SOFTWARE_VERSION);
406 /* ctrl-C and friends */
409 SetConsoleCtrlHandler(SignalHandler, OLSR_TRUE);
412 signal(SIGHUP, olsr_reconfigure);
413 signal(SIGINT, olsr_shutdown);
414 signal(SIGTERM, olsr_shutdown);
415 signal(SIGPIPE, SIG_IGN);
418 /* Register socket poll event */
419 olsr_register_timeout_function(&poll_sockets);
421 /* Starting scheduler */
424 /* Stop the compiler from complaining */
425 (void)copyright_string;
427 /* Like we're ever going to reach this ;-) */
434 * Reconfigure olsrd. Currently kind of a hack...
436 *@param signal the signal that triggered this callback
440 olsr_reconfigure(int signal __attribute__((unused)))
446 printf("Restarting %s\n", olsr_argv[0]);
447 execv(olsr_argv[0], olsr_argv);
451 printf("RECONFIGURING!\n");
457 *Function called at shutdown. Signal handler
459 * @param signal the signal that triggered this call
463 SignalHandler(unsigned long signal)
466 olsr_shutdown(int signal)
469 struct interface *ifn;
471 OLSR_PRINTF(1, "Received signal %d - shutting down\n", (int)signal);
474 OLSR_PRINTF(1, "Waiting for the scheduler to stop.\n");
476 olsr_win32_end_request = TRUE;
478 while (!olsr_win32_end_flag)
481 OLSR_PRINTF(1, "Scheduler stopped.\n");
484 olsr_delete_all_kernel_routes();
486 OLSR_PRINTF(1, "Closing sockets...\n");
488 /* front-end IPC socket */
489 if(olsr_cnf->open_ipc)
493 for (ifn = ifnet; ifn; ifn = ifn->int_next)
494 close(ifn->olsr_socket);
496 /* Closing plug-ins */
497 olsr_close_plugins();
499 /* Reset network settings */
500 restore_settings(olsr_cnf->ip_version);
503 close(olsr_cnf->ioctl_s);
505 #if LINUX_POLICY_ROUTING
506 close(olsr_cnf->rtnl_s);
509 #if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
511 close(olsr_cnf->rts);
514 olsr_syslog(OLSR_LOG_INFO, "%s stopped", SOFTWARE_VERSION);
516 OLSR_PRINTF(1, "\n <<<< %s - terminating >>>>\n http://www.olsr.org\n", SOFTWARE_VERSION);
518 exit(olsr_cnf->exit_value);
522 * Print the command line usage
529 "An error occured somwhere between your keyboard and your chair!\n"
530 "usage: olsrd [-f <configfile>] [ -i interface1 interface2 ... ]\n"
531 " [-d <debug_level>] [-ipv6] [-multi <IPv6 multicast address>]\n"
532 " [-lql <LQ level>] [-lqw <LQ winsize>]\n"
533 " [-bcast <broadcastaddr>] [-ipc] [-dispin] [-dispout] [-delgw]\n"
534 " [-hint <hello interval (secs)>] [-tcint <tc interval (secs)>]\n"
535 " [-midint <mid interval (secs)>] [-hnaint <hna interval (secs)>]\n"
536 " [-T <Polling Rate (secs)>] [-nofork] [-hemu <ip_address>]\n"
537 " [-lql <LQ level>] [-lqw <LQ winsize>]\n");
542 * Sets the provided configuration on all unconfigured
545 * @param ifs a linked list of interfaces to check and possible update
546 * @param cnf the default configuration to set on unconfigured interfaces
549 set_default_ifcnfs(struct olsr_if *ifs, struct if_config_options *cnf)
557 ifs->cnf = olsr_malloc(sizeof(struct if_config_options), "Set default config");
567 #define NEXT_ARG argv++;argc--
568 #define CHECK_ARGC if(!argc) { \
569 if((argc - 1) == 1){ \
570 fprintf(stderr, "Error parsing command line options!\n"); \
571 olsr_exit(__func__, EXIT_FAILURE); \
574 fprintf(stderr, "You must provide a parameter when using the %s switch!\n", *argv); \
575 olsr_exit(__func__, EXIT_FAILURE); \
580 * Process command line arguments passed to olsrd
584 olsr_process_arguments(int argc, char *argv[],
585 struct olsrd_config *cnf,
586 struct if_config_options *ifcnf)
595 if (strcmp(*argv, "-int") == 0)
605 if(strcmp(*argv, "-f") == 0)
607 fprintf(stderr, "Configfilename must ALWAYS be first argument!\n\n");
608 olsr_exit(__func__, EXIT_FAILURE);
614 if(strcmp(*argv, "-ipv6") == 0)
616 cnf->ip_version = AF_INET6;
623 if(strcmp(*argv, "-bcast") == 0)
629 if (inet_aton(*argv, &in) == 0)
631 printf("Invalid broadcast address! %s\nSkipping it!\n", *argv);
634 memcpy(&ifcnf->ipv4_broadcast.v4, &in.s_addr, sizeof(olsr_u32_t));
641 if (strcmp(*argv, "-lql") == 0)
647 /* Sanity checking is done later */
648 sscanf(*argv, "%d", &tmp_lq_level);
649 olsr_cnf->lq_level = tmp_lq_level;
656 if (strcmp(*argv, "-lqw") == 0)
662 sscanf(*argv, "%d", &tmp_lq_wsize);
664 if(tmp_lq_wsize < MIN_LQ_WSIZE || tmp_lq_wsize > MAX_LQ_WSIZE)
666 printf("LQ winsize %d not allowed. Range [%d-%d]\n",
667 tmp_lq_wsize, MIN_LQ_WSIZE, MAX_LQ_WSIZE);
668 olsr_exit(__func__, EXIT_FAILURE);
670 olsr_cnf->lq_wsize = tmp_lq_wsize;
675 * Enable additional debugging information to be logged.
677 if (strcmp(*argv, "-d") == 0)
682 sscanf(*argv,"%d", &cnf->debug_level);
688 * Interfaces to be used by olsrd.
690 if (strcmp(*argv, "-i") == 0)
697 fprintf(stderr, "You must provide an interface label!\n");
698 olsr_exit(__func__, EXIT_FAILURE);
700 printf("Queuing if %s\n", *argv);
701 queue_if(*argv, OLSR_FALSE);
703 while((argc - 1) && (argv[1][0] != '-'))
706 printf("Queuing if %s\n", *argv);
707 queue_if(*argv, OLSR_FALSE);
713 * Set the hello interval to be used by olsrd.
716 if (strcmp(*argv, "-hint") == 0)
720 sscanf(*argv,"%f", &ifcnf->hello_params.emission_interval);
721 ifcnf->hello_params.validity_time = ifcnf->hello_params.emission_interval * 3;
726 * Set the HNA interval to be used by olsrd.
729 if (strcmp(*argv, "-hnaint") == 0)
733 sscanf(*argv,"%f", &ifcnf->hna_params.emission_interval);
734 ifcnf->hna_params.validity_time = ifcnf->hna_params.emission_interval * 3;
739 * Set the MID interval to be used by olsrd.
742 if (strcmp(*argv, "-midint") == 0)
746 sscanf(*argv,"%f", &ifcnf->mid_params.emission_interval);
747 ifcnf->mid_params.validity_time = ifcnf->mid_params.emission_interval * 3;
752 * Set the tc interval to be used by olsrd.
755 if (strcmp(*argv, "-tcint") == 0)
759 sscanf(*argv,"%f", &ifcnf->tc_params.emission_interval);
760 ifcnf->tc_params.validity_time = ifcnf->tc_params.emission_interval * 3;
765 * Set the polling interval to be used by olsrd.
767 if (strcmp(*argv, "-T") == 0)
771 sscanf(*argv,"%f",&cnf->pollrate);
777 * Should we display the contents of packages beeing sent?
779 if (strcmp(*argv, "-dispin") == 0)
781 parser_set_disp_pack_in(OLSR_TRUE);
786 * Should we display the contents of incoming packages?
788 if (strcmp(*argv, "-dispout") == 0)
790 net_set_disp_pack_out(OLSR_TRUE);
796 * Should we set up and send on a IPC socket for the front-end?
798 if (strcmp(*argv, "-ipc") == 0)
800 cnf->ipc_connections = 1;
801 cnf->open_ipc = OLSR_TRUE;
806 * IPv6 multicast addr
808 if (strcmp(*argv, "-multi") == 0)
813 if(inet_pton(AF_INET6, *argv, &in6) <= 0)
815 fprintf(stderr, "Failed converting IP address %s\n", *argv);
819 memcpy(&ifcnf->ipv6_multi_glbl, &in6, sizeof(struct in6_addr));
827 if (strcmp(*argv, "-hemu") == 0)
834 if(inet_pton(AF_INET, *argv, &in) <= 0)
836 fprintf(stderr, "Failed converting IP address %s\n", *argv);
839 /* Add hemu interface */
841 ifa = queue_if("hcif01", OLSR_TRUE);
846 ifa->cnf = get_default_if_config();
847 ifa->host_emul = OLSR_TRUE;
848 memcpy(&ifa->hemu_ip, &in, sizeof(union olsr_ip_addr));
849 cnf->host_emul = OLSR_TRUE;
856 * Delete possible default GWs
858 if (strcmp(*argv, "-delgw") == 0)
860 olsr_cnf->del_gws = OLSR_TRUE;
865 if (strcmp(*argv, "-nofork") == 0)
867 cnf->no_fork = OLSR_TRUE;