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