Added some de-initializing funcs to plugins, lq_plugins, netfilter, parser
[olsrd.git] / src / main.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
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 "ipcalc.h"
49 #include "defs.h"
50 #include "olsr.h"
51 #include "log.h"
52 #include "scheduler.h"
53 #include "parser.h"
54 #include "generate_msg.h"
55 #include "plugin_loader.h"
56 #include "apm.h"
57 #include "net_os.h"
58 #include "build_msg.h"
59 #include "net_olsr.h"
60 #include "ipc_frontend.h"
61 #include "misc.h"
62 #include "olsr_cfg_gen.h"
63 #include "common/string.h"
64 #include "mid_set.h"
65 #include "duplicate_set.h"
66
67 #if defined linux
68 #include <linux/types.h>
69 #include <linux/rtnetlink.h>
70 #include <fcntl.h>
71 #endif
72
73 #ifdef WIN32
74 int __stdcall SignalHandler(unsigned long signo);
75 void DisableIcmpRedirects(void);
76 #else
77 static void signal_shutdown(int);
78 #endif
79 static void olsr_shutdown(void);
80
81 /*
82  * Local function prototypes
83  */
84 #ifndef WIN32
85 static void signal_reconfigure(int);
86 #endif
87
88 volatile enum app_state app_state = STATE_RUNNING;
89
90 static char copyright_string[] __attribute__ ((unused)) =
91   "The olsr.org Optimized Link-State Routing daemon(olsrd) Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org) All rights reserved.";
92
93 /**
94  * Main entrypoint
95  */
96
97 int
98 main(int argc, char *argv[])
99 {
100   /* Some cookies for stats keeping */
101   static struct olsr_cookie_info *pulse_timer_cookie = NULL;
102
103   char conf_file_name[FILENAME_MAX];
104   struct ipaddr_str buf;
105 #ifdef WIN32
106   WSADATA WsaData;
107   size_t len;
108 #endif
109
110   /* paranoia checks */
111   assert(sizeof(uint8_t) == 1);
112   assert(sizeof(uint16_t) == 2);
113   assert(sizeof(uint32_t) == 4);
114   assert(sizeof(int8_t) == 1);
115   assert(sizeof(int16_t) == 2);
116   assert(sizeof(int32_t) == 4);
117
118   debug_handle = stdout;
119   setbuf(stdout, NULL);
120   setbuf(stderr, NULL);
121
122 #ifndef WIN32
123   /* Check if user is root */
124   if (geteuid()) {
125     fprintf(stderr, "You must be root(uid = 0) to run olsrd!\nExiting\n\n");
126     exit(EXIT_FAILURE);
127   }
128 #else
129   DisableIcmpRedirects();
130
131   if (WSAStartup(0x0202, &WsaData)) {
132     fprintf(stderr, "Could not initialize WinSock.\n");
133     olsr_exit(__func__, EXIT_FAILURE);
134   }
135 #endif
136
137   /* Open syslog */
138   olsr_openlog("olsrd");
139
140   /* Initialize timers and scheduler part */
141   olsr_init_timers();
142
143   printf("\n *** %s ***\n Build date: %s on %s\n http://www.olsr.org\n\n", olsrd_version, build_date, build_host);
144
145   /* Using PID as random seed */
146   srandom(getpid());
147
148   /*
149    * Set configfile name and
150    * check if a configfile name was given as parameter
151    */
152 #ifdef WIN32
153 #ifndef WINCE
154   GetWindowsDirectory(conf_file_name, sizeof(conf_file_name) - 1 - strlen(OLSRD_CONF_FILE_NAME));
155 #else
156   conf_file_name[0] = 0;
157 #endif
158
159   len = strlen(conf_file_name);
160
161   if (len == 0 || conf_file_name[len - 1] != '\\') {
162     conf_file_name[len++] = '\\';
163   }
164
165   strscpy(conf_file_name + len, OLSRD_CONF_FILE_NAME, sizeof(conf_file_name) - len);
166 #else
167   strscpy(conf_file_name, OLSRD_GLOBAL_CONF_FILE, sizeof(conf_file_name));
168 #endif
169
170   /*
171    * set up configuration prior to processing commandline options
172    */
173   if (NULL == (olsr_cnf = olsr_parse_cfg(argc, argv, conf_file_name))) {
174     printf("Using default config values(no configfile)\n");
175     olsr_cnf = olsr_get_default_cfg();
176   }
177
178   /* Set avl tree comparator */
179   if (olsr_cnf->ipsize == 4) {
180     avl_comp_default = avl_comp_ipv4;
181     avl_comp_prefix_default = avl_comp_ipv4_prefix;
182     avl_comp_prefix_origin_default = avl_comp_ipv4_prefix_origin;
183   } else {
184     avl_comp_default = avl_comp_ipv6;
185     avl_comp_prefix_default = avl_comp_ipv6_prefix;
186     avl_comp_prefix_origin_default = avl_comp_ipv6_prefix_origin;
187   }
188
189   /* Initialize tick resolution */
190 #ifndef WIN32
191   olsr_cnf->system_tick_divider = 1000 / sysconf(_SC_CLK_TCK);
192 #else
193   olsr_cnf->system_tick_divider = 1;
194 #endif
195
196   /* Initialize net */
197   init_net();
198
199   /* Sanity check configuration */
200   if (olsr_sanity_check_cfg(olsr_cnf) < 0) {
201     olsr_exit(__func__, EXIT_FAILURE);
202   }
203
204   /*
205    * Print configuration
206    */
207   if (olsr_cnf->debug_level > 1) {
208     olsr_print_cnf(olsr_cnf);
209   }
210 #ifndef WIN32
211   /* Disable redirects globally */
212   disable_redirects_global(olsr_cnf->ip_version);
213 #endif
214
215   /*
216    * socket for ioctl calls
217    */
218   olsr_cnf->ioctl_s = socket(olsr_cnf->ip_version, SOCK_DGRAM, 0);
219   if (olsr_cnf->ioctl_s < 0) {
220     olsr_syslog(OLSR_LOG_ERR, "ioctl socket: %m");
221     olsr_exit(__func__, 0);
222   }
223 #if defined linux
224   olsr_cnf->rts_linux = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
225   if (olsr_cnf->rts_linux < 0) {
226     olsr_syslog(OLSR_LOG_ERR, "rtnetlink socket: %m");
227     olsr_exit(__func__, 0);
228   }
229   set_nonblocking(olsr_cnf->rts_linux);
230 #endif
231
232 /*
233  * create routing socket
234  */
235 #if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
236   olsr_cnf->rts_bsd = socket(PF_ROUTE, SOCK_RAW, 0);
237   if (olsr_cnf->rts_bsd < 0) {
238     olsr_syslog(OLSR_LOG_ERR, "routing socket: %m");
239     olsr_exit(__func__, 0);
240   }
241 #endif
242
243   /*
244    *enable ip forwarding on host
245    */
246   enable_ip_forwarding(olsr_cnf->ip_version);
247
248   /* Initialize parser */
249   olsr_init_parser();
250
251   /* Initialize route-exporter */
252   olsr_init_export_route();
253
254   /* Initialize message sequencnumber */
255   init_msg_seqno();
256
257   /* Initialize dynamic willingness calculation */
258   olsr_init_willingness();
259
260   /*
261    *Set up willingness/APM
262    */
263   if (olsr_cnf->willingness_auto) {
264     if (apm_init() < 0) {
265       OLSR_PRINTF(1, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT);
266
267       olsr_syslog(OLSR_LOG_ERR, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT);
268
269       olsr_cnf->willingness_auto = 0;
270       olsr_cnf->willingness = WILL_DEFAULT;
271     } else {
272       olsr_cnf->willingness = olsr_calculate_willingness();
273
274       OLSR_PRINTF(1, "Willingness set to %d - next update in %.1f secs\n", olsr_cnf->willingness, olsr_cnf->will_int);
275     }
276   }
277
278   /* Initializing networkinterfaces */
279   if (!ifinit()) {
280     if (olsr_cnf->allow_no_interfaces) {
281       fprintf(stderr,
282               "No interfaces detected! This might be intentional, but it also might mean that your configuration is fubar.\nI will continue after 5 seconds...\n");
283       sleep(5);
284     } else {
285       fprintf(stderr, "No interfaces detected!\nBailing out!\n");
286       olsr_exit(__func__, EXIT_FAILURE);
287     }
288   }
289
290   /* Print heartbeat to stdout */
291
292 #if !defined WINCE
293   if (olsr_cnf->debug_level > 0 && isatty(STDOUT_FILENO)) {
294     pulse_timer_cookie = olsr_alloc_cookie("Pulse", OLSR_COOKIE_TYPE_TIMER);
295     olsr_start_timer(STDOUT_PULSE_INT, 0, OLSR_TIMER_PERIODIC, &generate_stdout_pulse, NULL, pulse_timer_cookie->ci_id);
296   }
297 #endif
298
299   /* Initialize the IPC socket */
300
301   if (olsr_cnf->ipc_connections > 0) {
302     ipc_init();
303   }
304   /* Initialisation of different tables to be used. */
305   olsr_init_tables();
306
307   /* daemon mode */
308 #ifndef WIN32
309   if (olsr_cnf->debug_level == 0 && !olsr_cnf->no_fork) {
310     printf("%s detaching from the current process...\n", olsrd_version);
311     if (daemon(0, 0) < 0) {
312       printf("daemon(3) failed: %s\n", strerror(errno));
313       exit(EXIT_FAILURE);
314     }
315   }
316 #endif
317
318   /* Load plugins */
319   olsr_load_plugins();
320
321   /* activate LQ algorithm */
322   activate_lq_handler();
323
324   OLSR_PRINTF(1, "Main address: %s\n\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
325
326   /* Start syslog entry */
327   olsr_syslog(OLSR_LOG_INFO, "%s successfully started", olsrd_version);
328
329   /*
330    *signal-handlers
331    */
332
333   /* ctrl-C and friends */
334 #ifdef WIN32
335 #ifndef WINCE
336   SetConsoleCtrlHandler(SignalHandler, true);
337 #endif
338 #else
339   {
340     struct sigaction act;
341     sigemptyset(&act.sa_mask);
342     act.sa_flags = 0;
343     act.sa_handler = signal_reconfigure;
344     sigaction(SIGHUP, &act, NULL);
345     act.sa_handler = signal_shutdown;
346     sigaction(SIGINT, &act, NULL);
347     sigaction(SIGQUIT, &act, NULL);
348     sigaction(SIGILL, &act, NULL);
349     sigaction(SIGABRT, &act, NULL);
350 //  sigaction(SIGSEGV, &act, NULL);
351     sigaction(SIGTERM, &act, NULL);
352     act.sa_handler = SIG_IGN;
353     sigaction(SIGPIPE, &act, NULL);
354   }
355 #endif
356
357   link_changes = false;
358
359   /* Starting scheduler */
360   olsr_scheduler();
361
362   switch (app_state) {
363   case STATE_RUNNING:
364     olsr_syslog(OLSR_LOG_ERR, "terminating and got \"running\"?");
365     return 1;
366 #ifndef WIN32
367   case STATE_RECONFIGURE:
368     /* if we are started with -nofork, we do not weant to go into the
369      * background here. So we can simply be the child process.
370      */
371     switch (olsr_cnf->no_fork ? 0 : fork()) {
372       int i;
373     case 0:
374       /* child process */
375       for (i = sysconf(_SC_OPEN_MAX); --i > STDERR_FILENO;) {
376         close(i);
377       }
378       sleep(1);
379       printf("Restarting %s\n", argv[0]);
380       execv(argv[0], argv);
381       /* if we reach this, the exev() failed */
382       olsr_syslog(OLSR_LOG_ERR, "execv() failed: %s", strerror(errno));
383       /* and we simply shutdown */
384       olsr_cnf->exit_value = EXIT_FAILURE;
385       break;
386     case -1:
387       /* fork() failes */
388       olsr_syslog(OLSR_LOG_ERR, "fork() failed: %s", strerror(errno));
389       /* and we simply shutdown */
390       olsr_cnf->exit_value = EXIT_FAILURE;
391       break;
392     default:
393       /* parent process */
394       printf("RECONFIGURING!\n");
395       break;
396     }
397     /* fall through */
398 #endif
399   case STATE_SHUTDOWN:
400     olsr_shutdown();
401     break;
402   };
403
404   return olsr_cnf->exit_value;
405 }                               /* main */
406
407 #ifndef WIN32
408
409 /**
410  * Request reconfiguration of olsrd.
411  *
412  *@param signal the signal that triggered this callback
413  */
414 static void
415 signal_reconfigure(int signo)
416 {
417   const int save_errno = errno;
418   olsr_syslog(OLSR_LOG_INFO, "Received signal %d - requesting reconfiguration", signo);
419   app_state = STATE_RECONFIGURE;
420   errno = save_errno;
421 }
422
423 #endif
424
425 /**
426  *Function called at shutdown. Signal handler
427  *
428  * @param signal the signal that triggered this call
429  */
430 #ifdef WIN32
431 int __stdcall
432 SignalHandler(unsigned long signo)
433 #else
434 static void
435 signal_shutdown(int signo)
436 #endif
437 {
438   const int save_errno = errno;
439   olsr_syslog(OLSR_LOG_INFO, "Received signal %d - requesting shutdown", (int)signo);
440   app_state = STATE_SHUTDOWN;
441   errno = save_errno;
442 #ifdef WIN32
443   return 0;
444 #endif
445 }
446
447 static void
448 olsr_shutdown(void)
449 {
450   struct tc_entry *tc;
451   struct mid_entry *mid;
452   struct olsr_if_config *iface;
453
454   olsr_delete_all_kernel_routes();
455
456   /* Flush link state database */
457   OLSR_FOR_ALL_TC_ENTRIES(tc) {
458     olsr_delete_tc_entry(tc);
459   } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
460
461   /* Flush MID database */
462   OLSR_FOR_ALL_MID_ENTRIES(mid) {
463     olsr_delete_mid_entry(mid);
464   } OLSR_FOR_ALL_MID_ENTRIES_END(mid);
465
466   OLSR_PRINTF(1, "Closing sockets...\n");
467
468   /* Flush duplicate set */
469   olsr_flush_duplicate_entries();
470
471   /* front-end IPC socket */
472   if (olsr_cnf->ipc_connections > 0) {
473     shutdown_ipc();
474   }
475
476   /* Shut down LQ plugin */
477   deactivate_lq_handler();
478
479   /* Closing plug-ins */
480   olsr_close_plugins();
481
482   /* Remove active interfaces */
483   for (iface = olsr_cnf->if_configs; iface != NULL; iface = iface->next) {
484     remove_interface(&iface->interf);
485   }
486
487   /* Reset network settings */
488   restore_settings(olsr_cnf->ip_version);
489
490   /* ioctl socket */
491   CLOSESOCKET(olsr_cnf->ioctl_s);
492
493 #if defined linux
494   CLOSESOCKET(olsr_cnf->rts_linux);
495 #endif
496
497 #if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
498   /* routing socket */
499   CLOSESOCKET(olsr_cnf->rts_bsd);
500 #endif
501
502   /* Flush config */
503   olsr_free_cfg(olsr_cnf);
504
505   /* Close and delete all sockets */
506   olsr_flush_sockets();
507
508   /* Stop and delete all timers. */
509   olsr_flush_timers();
510
511   /* Free cookies and memory pools attached. */
512   olsr_delete_all_cookies();
513
514   /* Remove parser hooks */
515   olsr_deinit_parser();
516
517   /* Remove IP filters */
518   deinit_netfilters();
519
520   olsr_syslog(OLSR_LOG_INFO, "%s stopped", olsrd_version);
521
522   OLSR_PRINTF(1, "\n <<<< %s - terminating >>>>\n           http://www.olsr.org\n", olsrd_version);
523 }
524
525 /*
526  * Local Variables:
527  * c-basic-offset: 2
528  * indent-tabs-mode: nil
529  * End:
530  */