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