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