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