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