62721f176460f8acf170d34adc19ce0bbdb84898
[olsrd.git] / src / main.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
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
16  *   distribution.
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.
20  *
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.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
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.
39  *
40  */
41
42 #include <sys/stat.h>
43 #include <assert.h>
44 #include <errno.h>
45 #include <stdio.h>
46 #include <signal.h>
47 #include <unistd.h>
48
49 #include "defs.h"
50 #include "common/avl.h"
51 #include "common/avl_olsr_comp.h"
52 #include "olsr.h"
53 #include "ipcalc.h"
54 #include "olsr_timer.h"
55 #include "olsr_socket.h"
56 #include "parser.h"
57 #include "plugin_loader.h"
58 #include "os_apm.h"
59 #include "net_olsr.h"
60 #include "olsr_cfg_gen.h"
61 #include "common/string.h"
62 #include "mid_set.h"
63 #include "duplicate_set.h"
64 #include "olsr_comport.h"
65 #include "neighbor_table.h"
66 #include "olsr_logging.h"
67 #include "olsr_callbacks.h"
68 #include "os_apm.h"
69 #include "os_net.h"
70 #include "os_kernel_routes.h"
71 #include "os_time.h"
72 #include "os_system.h"
73
74 #if defined linux
75 #include <linux/types.h>
76 #include <linux/rtnetlink.h>
77 #include <fcntl.h>
78 #endif
79
80 #define STDOUT_PULSE_INT 600    /* msec */
81
82 #ifdef WIN32
83 int __stdcall SignalHandler(unsigned long signo);
84 #else
85 static void signal_shutdown(int);
86 #endif
87 static void olsr_shutdown(void);
88
89 /*
90  * Local function prototypes
91  */
92 #ifndef WIN32
93 static void signal_reconfigure(int);
94 #endif
95
96 /* Global stuff externed in olsr_cfg.h */
97 struct olsr_config *olsr_cnf;          /* The global configuration */
98
99 enum app_state app_state = STATE_INIT;
100
101 static char copyright_string[] __attribute__ ((unused)) =
102   "The olsr.org Optimized Link-State Routing daemon(olsrd) Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org) All rights reserved.";
103
104 static char pulsedata[] = "\\|/-";
105 static uint8_t pulse_state = 0;
106
107 static struct olsr_timer_entry *hna_gen_timer;
108 static struct olsr_timer_entry *mid_gen_timer;
109 static struct olsr_timer_entry *tc_gen_timer;
110
111 static void
112 generate_stdout_pulse(void *foo __attribute__ ((unused)))
113 {
114   if (pulsedata[++pulse_state] == '\0') {
115     pulse_state = 0;
116   }
117   fprintf(stderr, "%c\r", pulsedata[pulse_state]);
118 }
119
120 /**
121  * Main entrypoint
122  */
123
124 int
125 main(int argc, char *argv[])
126 {
127   /* Some cookies for stats keeping */
128   static struct olsr_timer_info *pulse_timer_info = NULL;
129   static struct olsr_timer_info *tc_gen_timer_info = NULL;
130   static struct olsr_timer_info *mid_gen_timer_info = NULL;
131   static struct olsr_timer_info *hna_gen_timer_info = NULL;
132
133   char conf_file_name[FILENAME_MAX];
134   char parse_msg[FILENAME_MAX + 256];
135   int exitcode = 0;
136 #if !defined(REMOVE_LOG_INFO) || !defined(REMOVE_LOG_ERROR)
137   struct ipaddr_str buf;
138 #endif
139 #ifdef WIN32
140   WSADATA WsaData;
141   size_t len;
142 #endif
143
144   /* paranoia checks */
145   assert(sizeof(uint8_t) == 1);
146   assert(sizeof(uint16_t) == 2);
147   assert(sizeof(uint32_t) == 4);
148   assert(sizeof(int8_t) == 1);
149   assert(sizeof(int16_t) == 2);
150   assert(sizeof(int32_t) == 4);
151
152   setbuf(stdout, NULL);
153   setbuf(stderr, NULL);
154
155   /* Using PID as random seed */
156   srandom(getpid());
157
158   /* call os dependent argument preprocessor */
159   os_arg(&argc, argv);
160
161   /*
162    * Set default configfile name
163    */
164 #ifdef WIN32
165 #ifndef WINCE
166   GetWindowsDirectory(conf_file_name, sizeof(conf_file_name) - 1 - strlen(OLSRD_CONF_FILE_NAME));
167 #else
168   conf_file_name[0] = 0;
169 #endif
170
171   len = strlen(conf_file_name);
172
173   if (len == 0 || conf_file_name[len - 1] != '\\') {
174     conf_file_name[len++] = '\\';
175   }
176
177   strscpy(conf_file_name + len, OLSRD_CONF_FILE_NAME, sizeof(conf_file_name) - len);
178 #else
179   strscpy(conf_file_name, OLSRD_GLOBAL_CONF_FILE, sizeof(conf_file_name));
180 #endif
181
182   /*
183    * set up configuration prior to processing commandline options
184    */
185   switch (olsr_parse_cfg(argc, argv, conf_file_name, parse_msg, &olsr_cnf)) {
186   case CFG_ERROR:
187     if (parse_msg[0])
188       fprintf(stderr, "Error: %s\n", parse_msg);
189     os_exit(EXIT_FAILURE);
190     break;
191   case CFG_WARN:
192     if (parse_msg[0])
193       fprintf(stderr, "Warning: %s\n", parse_msg);
194     /* No exit */
195     break;
196   case CFG_EXIT:
197     os_exit(EXIT_SUCCESS);
198     break;
199   case CFG_OK:
200     /* Continue */
201     break;
202   }
203
204   /* Set avl tree comparator */
205   if (olsr_cnf->ipsize == 4) {
206     avl_comp_default = avl_comp_ipv4;
207     avl_comp_addr_origin_default = avl_comp_ipv4_addr_origin;
208     avl_comp_prefix_default = avl_comp_ipv4_prefix;
209     avl_comp_prefix_origin_default = avl_comp_ipv4_prefix_origin;
210   } else {
211     avl_comp_default = avl_comp_ipv6;
212     avl_comp_addr_origin_default = avl_comp_ipv6_addr_origin;
213     avl_comp_prefix_default = avl_comp_ipv6_prefix;
214     avl_comp_prefix_origin_default = avl_comp_ipv6_prefix_origin;
215   }
216
217   /* initialize logging */
218   olsr_log_init();
219
220   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);
221
222   /* Sanity check configuration */
223   if (olsr_sanity_check_cfg(olsr_cnf) < 0) {
224     olsr_exit(EXIT_FAILURE);
225   }
226
227   /* setup os specific global options */
228   os_init();
229
230 #ifndef WIN32
231   /* Check if user is root */
232   if (geteuid()) {
233     OLSR_ERROR(LOG_MAIN, "You must be root(uid = 0) to run olsrd!\nExiting\n\n");
234     olsr_exit(EXIT_FAILURE);
235   }
236 #else
237   if (WSAStartup(0x0202, &WsaData)) {
238     OLSR_ERROR(LOG_MAIN, "Could not initialize WinSock.\n");
239     olsr_exit(EXIT_FAILURE);
240   }
241 #endif
242
243   /* initialize olsr clock */
244   olsr_clock_init();
245
246   /* initialize cookie system */
247   olsr_memcookie_init();
248
249   /* Initialize timers and scheduler part */
250   olsr_timer_init();
251   olsr_socket_init();
252
253   /* initialize callback system */
254   olsr_callback_init();
255
256   /* generate global timers */
257   pulse_timer_info = olsr_timer_add("Stdout pulse", &generate_stdout_pulse, true);
258   tc_gen_timer_info = olsr_timer_add("TC generation", &olsr_output_lq_tc, true);
259   mid_gen_timer_info = olsr_timer_add("MID generation", &generate_mid, true);
260   hna_gen_timer_info = olsr_timer_add("HNA generation", &generate_hna, true);
261
262   /* initialize plugin system */
263   olsr_init_pluginsystem();
264   olsr_plugins_init(true);
265
266   /* Initialize link set */
267   olsr_init_link_set();
268
269   /* Initialize duplicate table */
270   olsr_init_duplicate_set();
271
272   /* Initialize neighbor table */
273   olsr_init_neighbor_table();
274
275   /* Initialize routing table */
276   olsr_init_routing_table();
277
278   /* Initialize topology */
279   olsr_init_tc();
280
281   /* Initialize MID set */
282   olsr_init_mid_set();
283
284   /* Initialize HNA set */
285   olsr_init_hna_set();
286
287   /* enable lq-plugins */
288   olsr_plugins_enable(PLUGIN_TYPE_LQ, true);
289
290   /* initialize built in server services */
291   olsr_com_init();
292
293   /* Initialize net */
294   init_net();
295
296   /* Initialize SPF */
297   olsr_init_spf();
298
299   /*
300    * socket for ioctl calls
301    */
302   olsr_cnf->ioctl_s = socket(olsr_cnf->ip_version, SOCK_DGRAM, 0);
303   if (olsr_cnf->ioctl_s < 0) {
304     OLSR_ERROR(LOG_MAIN, "ioctl socket: %s\n", strerror(errno));
305     olsr_exit(EXIT_FAILURE);
306   }
307 #if defined linux
308   olsr_cnf->rtnl_s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
309   if (olsr_cnf->rtnl_s < 0) {
310     OLSR_ERROR(LOG_MAIN, "rtnetlink socket: %s\n", strerror(errno));
311     olsr_exit(EXIT_FAILURE);
312   }
313   os_socket_set_nonblocking(olsr_cnf->rtnl_s);
314
315   /* Create rule for RtTable to resolve route insertion problems*/
316   if ( ( olsr_cnf->rt_table < 253) & ( olsr_cnf->rt_table > 0 ) ) {
317     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)");
318     /*olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rt_table, RTM_NEWRULE);*/
319   }
320 #endif
321
322 /*
323  * create routing socket
324  */
325 #if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
326   olsr_cnf->rts_bsd = socket(PF_ROUTE, SOCK_RAW, 0);
327   if (olsr_cnf->rts_bsd < 0) {
328     OLSR_ERROR(LOG_MAIN, "routing socket: %s\n", strerror(errno));
329     olsr_exit(EXIT_FAILURE);
330   }
331 #endif
332
333   /* Initialize parser */
334   olsr_init_parser();
335
336   /* Initialize route-exporter */
337   olsr_init_export_route();
338
339   /* Initialize message sequencnumber */
340   init_msg_seqno();
341
342   /* Initialize dynamic willingness calculation */
343   olsr_init_willingness();
344
345   /*
346    *Set up willingness/APM
347    */
348   if (olsr_cnf->willingness_auto) {
349     olsr_calculate_willingness();
350   }
351
352 #if defined linux
353   /* Initializing lo:olsr if necessary */
354   if (olsr_cnf->source_ip_mode) {
355     OLSR_INFO(LOG_NETWORKING, "Initializing lo:olsr interface for source ip mode...\n");
356     if (olsr_os_localhost_if(&olsr_cnf->router_id, true) <= 0) {
357       OLSR_ERROR(LOG_NETWORKING, "Cannot create lo:olsr interface for ip '%s'\n", olsr_ip_to_string(&buf, &olsr_cnf->router_id));
358       olsr_exit(EXIT_FAILURE);
359     }
360   }
361 #endif
362
363   /* Initializing networkinterfaces */
364   if (!init_interfaces()) {
365     if (olsr_cnf->allow_no_interfaces) {
366       OLSR_INFO(LOG_MAIN,
367                 "No interfaces detected! This might be intentional, but it also might mean that your configuration is fubar.\nI will continue after 5 seconds...\n");
368       os_sleep(5);
369     } else {
370       OLSR_ERROR(LOG_MAIN, "No interfaces detected!\nBailing out!\n");
371       olsr_exit(EXIT_FAILURE);
372     }
373   }
374
375   /* Print heartbeat to stdout */
376
377 #if !defined WINCE
378   if (olsr_cnf->log_target_stderr > 0 && isatty(STDOUT_FILENO)) {
379     olsr_timer_start(STDOUT_PULSE_INT, 0, NULL, pulse_timer_info);
380   }
381 #endif
382
383   /* daemon mode */
384 #ifndef WIN32
385   if (!olsr_cnf->no_fork) {
386     OLSR_INFO(LOG_MAIN, "%s detaching from the current process...\n", olsrd_version);
387     if (daemon(0, 0) < 0) {
388       OLSR_ERROR(LOG_MAIN, "daemon(3) failed: %s\n", strerror(errno));
389       olsr_exit(EXIT_FAILURE);
390     }
391   }
392 #endif
393
394   /* activate LQ algorithm */
395   init_lq_handler();
396
397   OLSR_INFO(LOG_MAIN, "Main address: %s\n\n", olsr_ip_to_string(&buf, &olsr_cnf->router_id));
398
399   /* Start syslog entry */
400   OLSR_INFO(LOG_MAIN, "%s successfully started", olsrd_version);
401
402   /*
403    *signal-handlers
404    */
405
406   /* ctrl-C and friends */
407 #ifdef WIN32
408 #ifndef WINCE
409   SetConsoleCtrlHandler(SignalHandler, true);
410 #endif
411 #else
412   {
413     struct sigaction act;
414     sigemptyset(&act.sa_mask);
415     act.sa_flags = 0;
416     act.sa_handler = signal_reconfigure;
417     sigaction(SIGHUP, &act, NULL);
418     act.sa_handler = signal_shutdown;
419     sigaction(SIGINT, &act, NULL);
420     sigaction(SIGQUIT, &act, NULL);
421     sigaction(SIGILL, &act, NULL);
422     sigaction(SIGABRT, &act, NULL);
423 //  sigaction(SIGSEGV, &act, NULL);
424     sigaction(SIGTERM, &act, NULL);
425     act.sa_handler = SIG_IGN;
426     sigaction(SIGPIPE, &act, NULL);
427     // Ignoring SIGUSR1 and SIGUSR1 by default to be able to use them in plugins
428     sigaction(SIGUSR1, &act, NULL);
429     sigaction(SIGUSR2, &act, NULL);
430   }
431 #endif
432
433   link_changes = false;
434
435   tc_gen_timer =
436     olsr_timer_start(olsr_cnf->tc_params.emission_interval, TC_JITTER, NULL, tc_gen_timer_info);
437   mid_gen_timer =
438     olsr_timer_start(olsr_cnf->mid_params.emission_interval, MID_JITTER, NULL, mid_gen_timer_info);
439   hna_gen_timer =
440     olsr_timer_start(olsr_cnf->hna_params.emission_interval, HNA_JITTER, NULL, hna_gen_timer_info);
441
442   /* enable default plugins */
443   olsr_plugins_enable(PLUGIN_TYPE_DEFAULT, true);
444
445   /* Starting scheduler */
446   app_state = STATE_RUNNING;
447   while (app_state == STATE_RUNNING) {
448     uint32_t next_interval;
449
450     /*
451      * Update the global timestamp. We are using a non-wallclock timer here
452      * to avoid any undesired side effects if the system clock changes.
453      */
454     olsr_clock_update();
455     next_interval = olsr_clock_getAbsolute(olsr_cnf->pollrate);
456
457     /* Process timers */
458     walk_timers();
459
460     /* Update */
461     olsr_process_changes();
462
463     /* Read incoming data and handle it immediately */
464     olsr_socket_handle(next_interval);
465   }
466
467   olsr_timer_stop(tc_gen_timer);
468   tc_gen_timer = NULL;
469
470   olsr_timer_stop(mid_gen_timer);
471   mid_gen_timer = NULL;
472
473   olsr_timer_stop(hna_gen_timer);
474   hna_gen_timer = NULL;
475
476   exitcode = olsr_cnf->exit_value;
477   switch (app_state) {
478   case STATE_INIT:
479     OLSR_ERROR(LOG_MAIN, "terminating and got \"init\"?");
480     exitcode = EXIT_FAILURE;
481     break;
482   case STATE_RUNNING:
483     OLSR_ERROR(LOG_MAIN, "terminating and got \"running\"?");
484     exitcode = EXIT_FAILURE;
485     break;
486 #ifndef WIN32
487   case STATE_RECONFIGURE:
488     /* if we are started with -nofork, we do not weant to go into the
489      * background here. So we can simply be the child process.
490      */
491     switch (olsr_cnf->no_fork ? 0 : fork()) {
492       int i;
493     case 0:
494       /* child process */
495       for (i = sysconf(_SC_OPEN_MAX); --i > STDERR_FILENO;) {
496         close(i);
497       }
498       os_sleep(1);
499       OLSR_INFO(LOG_MAIN, "Restarting %s\n", argv[0]);
500       execv(argv[0], argv);
501       /* if we reach this, the exev() failed */
502       OLSR_ERROR(LOG_MAIN, "execv() failed: %s", strerror(errno));
503       /* and we simply shutdown */
504       exitcode = EXIT_FAILURE;
505       break;
506     case -1:
507       /* fork() failes */
508       OLSR_ERROR(LOG_MAIN, "fork() failed: %s", strerror(errno));
509       /* and we simply shutdown */
510       exitcode = EXIT_FAILURE;
511       break;
512     default:
513       /* parent process */
514       OLSR_INFO(LOG_MAIN, "Reconfiguring OLSR\n");
515       break;
516     }
517     /* fall through */
518 #endif
519   case STATE_SHUTDOWN:
520     olsr_shutdown();
521     break;
522   };
523
524   return exitcode;
525 }                               /* main */
526
527 #ifndef WIN32
528
529 /**
530  * Request reconfiguration of olsrd.
531  *
532  *@param signal the signal that triggered this callback
533  */
534 static void
535 signal_reconfigure(int signo __attribute__ ((unused)))
536 {
537   const int save_errno = errno;
538   OLSR_INFO(LOG_MAIN, "Received signal %d - requesting reconfiguration", signo);
539   app_state = STATE_RECONFIGURE;
540   errno = save_errno;
541 }
542
543 #endif
544
545 /**
546  *Function called at shutdown. Signal handler
547  *
548  * @param signal the signal that triggered this call
549  */
550 #ifdef WIN32
551 int __stdcall
552 SignalHandler(unsigned long signo)
553 #else
554 static void
555 signal_shutdown(int signo __attribute__ ((unused)))
556 #endif
557 {
558   const int save_errno = errno;
559   OLSR_INFO(LOG_MAIN, "Received signal %d - requesting shutdown", (int)signo);
560   app_state = STATE_SHUTDOWN;
561   errno = save_errno;
562 #ifdef WIN32
563   return 0;
564 #endif
565 }
566
567 static void
568 olsr_shutdown(void)
569 {
570   struct mid_entry *mid, *iterator;
571
572   olsr_delete_all_kernel_routes();
573
574   /* Flush MID database */
575   OLSR_FOR_ALL_MID_ENTRIES(mid, iterator) {
576     olsr_delete_mid_entry(mid);
577   }
578
579   /* Flush TC database */
580   olsr_delete_all_tc_entries();
581
582   OLSR_INFO(LOG_MAIN, "Closing sockets...\n");
583
584   /* kill http/telnet server */
585   olsr_com_destroy();
586
587   /* Flush duplicate set */
588   olsr_flush_duplicate_entries();
589
590   /* Shut down LQ plugin */
591   deinit_lq_handler();
592
593   /* Closing plug-ins */
594   olsr_destroy_pluginsystem();
595
596   /* Remove active interfaces */
597   destroy_interfaces();
598
599 #if defined linux
600   /* delete lo:olsr if neccesarry */
601   if (olsr_cnf->source_ip_mode) {
602     olsr_os_localhost_if(&olsr_cnf->router_id, false);
603   }
604 #endif
605
606   /* ioctl socket */
607   os_close(olsr_cnf->ioctl_s);
608
609 #if defined linux
610   /*if ((olsr_cnf->rttable < 253) & (olsr_cnf->rttable > 0)) {
611     olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable, RTM_DELRULE);
612   }*/
613
614   os_close(olsr_cnf->rtnl_s);
615 #endif
616
617 #if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
618   /* routing socket */
619   os_close(olsr_cnf->rts_bsd);
620 #endif
621
622   /* Close and delete all sockets */
623   olsr_socket_cleanup();
624
625   /* Stop and delete all timers. */
626   olsr_timer_cleanup();
627
628   /* Remove parser hooks */
629   olsr_deinit_parser();
630
631   /* Remove IP filters */
632   deinit_netfilters();
633
634   /* release callback system */
635   olsr_callback_cleanup();
636
637   /* Free cookies and memory pools attached. */
638   olsr_memcookie_cleanup();
639
640   /* Reset os_specific global options */
641   os_cleanup();
642
643   OLSR_INFO(LOG_MAIN, "\n <<<< %s - terminating >>>>\n           http://www.olsr.org\n", olsrd_version);
644
645   /* cleanup logging system */
646   olsr_log_cleanup();
647
648   /* Flush config */
649   olsr_free_cfg(olsr_cnf);
650 }
651
652 /*
653  * Local Variables:
654  * c-basic-offset: 2
655  * indent-tabs-mode: nil
656  * End:
657  */