22d9393a51eceb784df9a9174d839725594b098e
[olsrd.git] / src / main.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in
14  *   the documentation and/or other materials provided with the
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its
17  *   contributors may be used to endorse or promote products derived
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  */
40
41 #include <unistd.h>
42 #include <signal.h>
43 #include <sys/stat.h>
44 #include <assert.h>
45 #include <fcntl.h>
46
47 #include "ipcalc.h"
48 #include "defs.h"
49 #include "olsr.h"
50 #include "log.h"
51 #include "scheduler.h"
52 #include "parser.h"
53 #include "generate_msg.h"
54 #include "plugin_loader.h"
55 #include "apm.h"
56 #include "net_os.h"
57 #include "build_msg.h"
58 #include "net_olsr.h"
59 #include "mid_set.h"
60 #include "mpr_selector_set.h"
61 #include "gateway.h"
62 #include "olsr_niit.h"
63
64 #ifdef __linux__
65 #include <linux/types.h>
66 #include <linux/rtnetlink.h>
67 #include "kernel_routes.h"
68
69 #endif /* __linux__ */
70
71 #ifdef _WIN32
72 #include <winbase.h>
73 #define close(x) closesocket(x)
74 int __stdcall SignalHandler(unsigned long signo) __attribute__ ((noreturn));
75 void ListInterfaces(void);
76 void DisableIcmpRedirects(void);
77 bool olsr_win32_end_request = false;
78 bool olsr_win32_end_flag = false;
79 #else /* _WIN32 */
80 static void olsr_shutdown(int) __attribute__ ((noreturn));
81 #endif /* _WIN32 */
82
83 #if defined __ANDROID__
84 #define DEFAULT_LOCKFILE_PREFIX "/data/local/olsrd"
85 #elif defined linux || defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__
86 #define DEFAULT_LOCKFILE_PREFIX "/var/run/olsrd"
87 #elif defined _WIN32
88 #define DEFAULT_LOCKFILE_PREFIX "C:\\olsrd"
89 #else /* defined _WIN32 */
90 #define DEFAULT_LOCKFILE_PREFIX "olsrd"
91 #endif /* defined _WIN32 */
92
93 /*
94  * Local function prototypes
95  */
96 void olsr_reconfigure(int signo) __attribute__ ((noreturn));
97
98 static void print_usage(bool error);
99
100 static int set_default_ifcnfs(struct olsr_if *, struct if_config_options *);
101
102 static int olsr_process_arguments(int, char *[], struct olsrd_config *,
103     struct if_config_options *);
104
105 #ifndef _WIN32
106 static char **olsr_argv;
107 #endif /* _WIN32 */
108
109 static char
110     copyright_string[] __attribute__ ((unused)) =
111         "The olsr.org Optimized Link-State Routing daemon(olsrd) Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org) All rights reserved.";
112
113 /* Data for OLSR locking */
114 #ifndef _WIN32
115 static int lock_fd = 0;
116 #endif /* _WIN32 */
117 static char lock_file_name[FILENAME_MAX];
118 struct olsr_cookie_info *def_timer_ci = NULL;
119
120 /*
121  * Creates a zero-length locking file and use fcntl to
122  * place an exclusive lock over it. The lock will be
123  * automatically erased when the olsrd process ends,
124  * so it will even work well with a SIGKILL.
125  *
126  * Additionally the lock can be killed by removing the
127  * locking file.
128  */
129 static int olsr_create_lock_file(bool noExitOnFail) {
130 #ifdef _WIN32
131     bool success;
132     HANDLE lck;
133
134     lck = CreateFile(lock_file_name,
135             GENERIC_READ | GENERIC_WRITE,
136             FILE_SHARE_READ | FILE_SHARE_WRITE,
137             NULL,
138             OPEN_ALWAYS,
139             FILE_ATTRIBUTE_NORMAL |
140             FILE_FLAG_DELETE_ON_CLOSE,
141             NULL);
142   CreateEvent(NULL, TRUE, FALSE, lock_file_name);
143   if (INVALID_HANDLE_VALUE == lck || ERROR_ALREADY_EXISTS == GetLastError()) {
144     if (noExitOnFail) {
145       return -1;
146     }
147     if (NULL == lck) {
148       fprintf(stderr,
149           "Error, cannot create OLSR lock '%s'.\n",
150           lock_file_name);
151     } else {
152       CloseHandle(lck);
153       fprintf(stderr,
154           "Error, cannot aquire OLSR lock '%s'.\n"
155           "Another OLSR instance might be running.\n",
156           lock_file_name);
157     }
158     olsr_exit("", EXIT_FAILURE);
159   }
160
161   success = LockFile( lck, 0, 0, 0, 0);
162
163   if (!success) {
164       CloseHandle(lck);
165       if (noExitOnFail) {
166           return -1;
167       }
168       fprintf(stderr,
169           "Error, cannot aquire OLSR lock '%s'.\n"
170           "Another OLSR instance might be running.\n",
171           lock_file_name);
172     olsr_exit("", EXIT_FAILURE);
173   }
174       
175 #else /* _WIN32 */
176   struct flock lck;
177
178   /* create file for lock */
179   lock_fd = open(lock_file_name, O_WRONLY | O_CREAT, S_IRWXU);
180   if (lock_fd == 0) {
181     if (noExitOnFail) {
182       return -1;
183     }
184     fprintf(stderr,
185         "Error, cannot create OLSR lock '%s'.\n",
186         lock_file_name);
187     olsr_exit("", EXIT_FAILURE);
188   }
189
190   /* create exclusive lock for the whole file */
191   lck.l_type = F_WRLCK;
192   lck.l_whence = SEEK_SET;
193   lck.l_start = 0;
194   lck.l_len = 0;
195   lck.l_pid = 0;
196
197   if (fcntl(lock_fd, F_SETLK, &lck) == -1) {
198     close(lock_fd);
199     if (noExitOnFail) {
200       return -1;
201     }
202     fprintf(stderr,
203         "Error, cannot aquire OLSR lock '%s'.\n"
204         "Another OLSR instance might be running.\n",
205         lock_file_name);
206     olsr_exit("", EXIT_FAILURE);
207   }
208 #endif /* _WIN32 */
209   return 0;
210 }
211
212 /**
213  * Write the current PID to the configured PID file (if one is configured)
214  */
215 static void writePidFile(void) {
216   if (olsr_cnf->pidfile) {
217     char buf[PATH_MAX + 256];
218
219     /* create / open the PID file */
220     int fd = open(olsr_cnf->pidfile, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
221     if (fd < 0) {
222       snprintf(buf, sizeof(buf), "Could not open PID file %s", olsr_cnf->pidfile);
223       perror(buf);
224       olsr_shutdown(0);
225     }
226
227     /* write the PID */
228     {
229       pid_t pid = getpid();
230       int chars = snprintf(buf, sizeof(buf), "%d", pid);
231       ssize_t chars_written = write(fd, buf, chars);
232       if (chars_written != chars) {
233         close(fd);
234         snprintf(buf, sizeof(buf), "Could not write the PID %d to the PID file %s", pid, olsr_cnf->pidfile);
235         perror(buf);
236         if (remove(olsr_cnf->pidfile) < 0) {
237           snprintf(buf, sizeof(buf), "Could not remove the PID file %s", olsr_cnf->pidfile);
238           perror(buf);
239         }
240         olsr_shutdown(0);
241       }
242     }
243
244     if (close(fd) < 0) {
245       snprintf(buf, sizeof(buf), "Could not close PID file %s", olsr_cnf->pidfile);
246       perror(buf);
247       if (remove(olsr_cnf->pidfile) < 0) {
248         snprintf(buf, sizeof(buf), "Could not remove the PID file %s", olsr_cnf->pidfile);
249         perror(buf);
250       }
251       olsr_shutdown(0);
252     }
253   }
254 }
255
256 /**
257  * loads a config file
258  * @return <0 if load failed, 0 otherwise
259  */
260 static int
261 olsrmain_load_config(char *file) {
262   struct stat statbuf;
263
264   if (stat(file, &statbuf) < 0) {
265     fprintf(stderr, "Could not find specified config file %s!\n%s\n\n",
266         file, strerror(errno));
267     return -1;
268   }
269
270   if (olsrd_parse_cnf(file) < 0) {
271     fprintf(stderr, "Error while reading config file %s!\n", file);
272     return -1;
273   }
274   return 0;
275 }
276
277 static void initRandom(void) {
278   unsigned int seed = (unsigned int)time(NULL);
279
280 #ifndef _WIN32
281   int randomFile;
282
283   randomFile = open("/dev/random", O_RDONLY);
284   if (randomFile == -1) {
285     randomFile = open("/dev/urandom", O_RDONLY);
286   }
287
288   if (randomFile != -1) {
289     if (read(randomFile, &seed, sizeof(seed)) != sizeof(seed)) {
290       ; /* to fix an 'unused result' compiler warning */
291     }
292     close(randomFile);
293   }
294 #endif /* _WIN32 */
295
296   srandom(seed);
297 }
298
299 /**
300  * Main entrypoint
301  */
302
303 int main(int argc, char *argv[]) {
304   struct if_config_options *default_ifcnf;
305   char conf_file_name[FILENAME_MAX];
306   struct ipaddr_str buf;
307   bool loadedConfig = false;
308   int i;
309
310 #ifdef __linux__
311   struct interface *ifn;
312 #endif /* __linux__ */
313
314 #ifdef _WIN32
315   WSADATA WsaData;
316   size_t len;
317 #endif /* __linux__ */
318
319   /* paranoia checks */
320   assert(sizeof(uint8_t) == 1);
321   assert(sizeof(uint16_t) == 2);
322   assert(sizeof(uint32_t) == 4);
323   assert(sizeof(int8_t) == 1);
324   assert(sizeof(int16_t) == 2);
325   assert(sizeof(int32_t) == 4);
326
327   printf("\n *** %s ***\n Build date: %s on %s\n http://www.olsr.org\n\n",
328       olsrd_version, build_date, build_host);
329
330   if (argc == 2) {
331     if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "/?") == 0) {
332       print_usage(false);
333       exit(0);
334     }
335     if (strcmp(argv[1], "-v") == 0) {
336       exit(0);
337     }
338   }
339
340   debug_handle = stdout;
341 #ifndef _WIN32
342   olsr_argv = argv;
343 #endif /* _WIN32 */
344   setbuf(stdout, NULL);
345   setbuf(stderr, NULL);
346
347 #ifndef _WIN32
348   /* Check if user is root */
349   if (geteuid()) {
350     fprintf(stderr, "You must be root(uid = 0) to run olsrd!\nExiting\n\n");
351     exit(EXIT_FAILURE);
352   }
353 #else /* _WIN32 */
354   DisableIcmpRedirects();
355
356   if (WSAStartup(0x0202, &WsaData)) {
357     fprintf(stderr, "Could not initialize WinSock.\n");
358     olsr_exit(__func__, EXIT_FAILURE);
359   }
360 #endif /* _WIN32 */
361
362   /* Open syslog */
363   olsr_openlog("olsrd");
364
365   /* setup random seed */
366   initRandom();
367
368   /* Init widely used statics */
369   memset(&all_zero, 0, sizeof(union olsr_ip_addr));
370
371   /*
372    * Set configfile name and
373    * check if a configfile name was given as parameter
374    */
375 #ifdef _WIN32
376 #ifndef WINCE
377   GetWindowsDirectory(conf_file_name, FILENAME_MAX - 11);
378 #else /* WINCE */
379   conf_file_name[0] = 0;
380 #endif /* WINCE */
381
382   len = strlen(conf_file_name);
383
384   if (len == 0 || conf_file_name[len - 1] != '\\')
385   conf_file_name[len++] = '\\';
386
387   strscpy(conf_file_name + len, "olsrd.conf", sizeof(conf_file_name) - len);
388 #else /* _WIN32 */
389   strscpy(conf_file_name, OLSRD_GLOBAL_CONF_FILE, sizeof(conf_file_name));
390 #endif /* _WIN32 */
391
392   olsr_cnf = olsrd_get_default_cnf();
393   for (i=1; i < argc-1;) {
394     if (strcmp(argv[i], "-f") == 0) {
395       loadedConfig = true;
396
397       if (olsrmain_load_config(argv[i+1]) < 0) {
398         exit(EXIT_FAILURE);
399       }
400
401       if (i+2 < argc) {
402         memmove(&argv[i], &argv[i+2], sizeof(*argv) * (argc-i-1));
403       }
404       argc -= 2;
405     }
406     else {
407       i++;
408     }
409   }
410
411   /*
412    * set up configuration prior to processing commandline options
413    */
414   if (!loadedConfig && olsrmain_load_config(conf_file_name) == 0) {
415     loadedConfig = true;
416   }
417
418   if (!loadedConfig) {
419     olsrd_free_cnf(olsr_cnf);
420     olsr_cnf = olsrd_get_default_cnf();
421   }
422
423   default_ifcnf = get_default_if_config();
424   if (default_ifcnf == NULL) {
425     fprintf(stderr, "No default ifconfig found!\n");
426     exit(EXIT_FAILURE);
427   }
428
429   /* Initialize timers */
430   olsr_init_timers();
431
432   /*
433    * Process olsrd options.
434    */
435   if (olsr_process_arguments(argc, argv, olsr_cnf, default_ifcnf) < 0) {
436     print_usage(true);
437     olsr_exit(__func__, EXIT_FAILURE);
438   }
439
440   /*
441    * Set configuration for command-line specified interfaces
442    */
443   set_default_ifcnfs(olsr_cnf->interfaces, default_ifcnf);
444
445   /* free the default ifcnf */
446   free(default_ifcnf);
447
448   /* Sanity check configuration */
449   if (olsrd_sanity_check_cnf(olsr_cnf) < 0) {
450     fprintf(stderr, "Bad configuration!\n");
451     olsr_exit(__func__, EXIT_FAILURE);
452   }
453
454   /*
455    * Establish file lock to prevent multiple instances
456    */
457   if (olsr_cnf->lock_file) {
458     strscpy(lock_file_name, olsr_cnf->lock_file, sizeof(lock_file_name));
459   } else {
460     size_t l;
461 #ifdef DEFAULT_LOCKFILE_PREFIX
462     strscpy(lock_file_name, DEFAULT_LOCKFILE_PREFIX, sizeof(lock_file_name));
463 #else /* DEFAULT_LOCKFILE_PREFIX */
464     strscpy(lock_file_name, conf_file_name, sizeof(lock_file_name));
465 #endif /* DEFAULT_LOCKFILE_PREFIX */
466     l = strlen(lock_file_name);
467     snprintf(&lock_file_name[l], sizeof(lock_file_name) - l, "-ipv%d.lock",
468         olsr_cnf->ip_version == AF_INET ? 4 : 6);
469   }
470
471   /*
472    * Print configuration
473    */
474   if (olsr_cnf->debug_level > 1) {
475     olsrd_print_cnf(olsr_cnf);
476   }
477
478   def_timer_ci = olsr_alloc_cookie("Default Timer Cookie", OLSR_COOKIE_TYPE_TIMER);
479
480   /*
481    * socket for ioctl calls
482    */
483   olsr_cnf->ioctl_s = socket(olsr_cnf->ip_version, SOCK_DGRAM, 0);
484   if (olsr_cnf->ioctl_s < 0) {
485 #ifndef _WIN32
486     olsr_syslog(OLSR_LOG_ERR, "ioctl socket: %m");
487 #endif /* _WIN32 */
488     olsr_exit(__func__, 0);
489   }
490 #ifdef __linux__
491   olsr_cnf->rtnl_s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
492   if (olsr_cnf->rtnl_s < 0) {
493     olsr_syslog(OLSR_LOG_ERR, "rtnetlink socket: %m");
494     olsr_exit(__func__, 0);
495   }
496
497   if (fcntl(olsr_cnf->rtnl_s, F_SETFL, O_NONBLOCK)) {
498     olsr_syslog(OLSR_LOG_INFO, "rtnetlink could not be set to nonblocking");
499   }
500
501   if ((olsr_cnf->rt_monitor_socket = rtnetlink_register_socket(RTMGRP_LINK)) < 0) {
502     olsr_syslog(OLSR_LOG_ERR, "rtmonitor socket: %m");
503     olsr_exit(__func__, 0);
504   }
505 #endif /* __linux__ */
506
507   /*
508    * create routing socket
509    */
510 #if defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __NetBSD__ || defined __OpenBSD__
511   olsr_cnf->rts = socket(PF_ROUTE, SOCK_RAW, 0);
512   if (olsr_cnf->rts < 0) {
513     olsr_syslog(OLSR_LOG_ERR, "routing socket: %m");
514     olsr_exit(__func__, 0);
515   }
516 #endif /* defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __NetBSD__ || defined __OpenBSD__ */
517
518 #ifdef __linux__
519   /* initialize gateway system */
520   if (olsr_cnf->smart_gw_active) {
521     if (olsr_init_gateways()) {
522       olsr_exit("Cannot initialize gateway tunnels", 1);
523     }
524   }
525
526   /* initialize niit if index */
527   if (olsr_cnf->use_niit) {
528     olsr_init_niit();
529   }
530 #endif /* __linux__ */
531
532   /* Init empty TC timer */
533   set_empty_tc_timer(GET_TIMESTAMP(0));
534
535   /* enable ip forwarding on host */
536   /* Disable redirects globally (not for WIN32) */
537   net_os_set_global_ifoptions();
538
539   /* Initialize parser */
540   olsr_init_parser();
541
542   /* Initialize route-exporter */
543   olsr_init_export_route();
544
545   /* Initialize message sequencnumber */
546   init_msg_seqno();
547
548   /* Initialize dynamic willingness calculation */
549   olsr_init_willingness();
550
551   /*
552    *Set up willingness/APM
553    */
554   if (olsr_cnf->willingness_auto) {
555     if (apm_init() < 0) {
556       OLSR_PRINTF(1, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT);
557
558       olsr_syslog(OLSR_LOG_ERR,
559           "Could not read APM info - setting default willingness(%d)\n",
560           WILL_DEFAULT);
561
562       olsr_cnf->willingness_auto = 0;
563       olsr_cnf->willingness = WILL_DEFAULT;
564     } else {
565       olsr_cnf->willingness = olsr_calculate_willingness();
566
567       OLSR_PRINTF(1, "Willingness set to %d - next update in %.1f secs\n", olsr_cnf->willingness, (double)olsr_cnf->will_int);
568     }
569   }
570
571   /* Initialize net */
572   init_net();
573
574   /* Initializing networkinterfaces */
575   if (!olsr_init_interfacedb()) {
576     if (olsr_cnf->allow_no_interfaces) {
577       fprintf(
578           stderr,
579           "No interfaces detected! This might be intentional, but it also might mean that your configuration is fubar.\nI will continue after 5 seconds...\n");
580       olsr_startup_sleep(5);
581     } else {
582       fprintf(stderr, "No interfaces detected!\nBailing out!\n");
583       olsr_exit(__func__, EXIT_FAILURE);
584     }
585   }
586
587 #ifdef __linux__
588   /* startup gateway system */
589   if (olsr_cnf->smart_gw_active) {
590     if (olsr_startup_gateways()) {
591       olsr_exit("Cannot startup gateway tunnels", 1);
592     }
593   }
594 #endif /* __linux__ */
595
596   olsr_do_startup_sleep();
597
598   /* Print heartbeat to stdout */
599
600 #if !defined WINCE
601   if (olsr_cnf->debug_level > 0 && isatty(STDOUT_FILENO)) {
602     olsr_start_timer(STDOUT_PULSE_INT, 0, OLSR_TIMER_PERIODIC,
603         &generate_stdout_pulse, NULL, 0);
604   }
605 #endif /* !defined WINCE */
606
607   /* Initialize the IPC socket */
608
609   if (olsr_cnf->ipc_connections > 0) {
610     if (ipc_init()) {
611       olsr_exit("ipc_init failure", 1);
612     }
613   }
614   /* Initialisation of different tables to be used. */
615   olsr_init_tables();
616
617   /* daemon mode */
618 #ifndef _WIN32
619   if (olsr_cnf->debug_level == 0 && !olsr_cnf->no_fork) {
620     printf("%s detaching from the current process...\n", olsrd_version);
621     if (daemon(0, 0) < 0) {
622       printf("daemon(3) failed: %s\n", strerror(errno));
623       exit(EXIT_FAILURE);
624     }
625   }
626 #endif /* _WIN32 */
627
628   writePidFile();
629
630   /*
631    * Create locking file for olsrd, will be cleared after olsrd exits
632    */
633   for (i=5; i>=0; i--) {
634     OLSR_PRINTF(3, "Trying to get olsrd lock...\n");
635     if (!olsr_cnf->host_emul && olsr_create_lock_file(i > 0) == 0) {
636       /* lock sucessfully created */
637       break;
638     }
639     sleep (1);
640   }
641
642   /* Load plugins */
643   olsr_load_plugins();
644
645   OLSR_PRINTF(1, "Main address: %s\n\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
646
647 #ifdef __linux__
648   /* create policy routing rules with priorities if necessary */
649   if (DEF_RT_NONE != olsr_cnf->rt_table_pri) {
650     olsr_os_policy_rule(olsr_cnf->ip_version,
651         olsr_cnf->rt_table, olsr_cnf->rt_table_pri, NULL, true);
652   }
653   if (DEF_RT_NONE != olsr_cnf->rt_table_tunnel_pri) {
654     olsr_os_policy_rule(olsr_cnf->ip_version,
655         olsr_cnf->rt_table_tunnel, olsr_cnf->rt_table_tunnel_pri, NULL, true);
656   }
657   if (DEF_RT_NONE != olsr_cnf->rt_table_default_pri) {
658     olsr_os_policy_rule(olsr_cnf->ip_version,
659         olsr_cnf->rt_table_default, olsr_cnf->rt_table_default_pri, NULL, true);
660   }
661
662   /* rule to default table on all olsrd interfaces */
663   if (DEF_RT_NONE != olsr_cnf->rt_table_defaultolsr_pri) {
664     for (ifn = ifnet; ifn; ifn = ifn->int_next) {
665       olsr_os_policy_rule(olsr_cnf->ip_version,
666           olsr_cnf->rt_table_default, olsr_cnf->rt_table_defaultolsr_pri, ifn->int_name, true);
667     }
668   }
669
670   /* trigger gateway selection */
671   if (olsr_cnf->smart_gw_active) {
672     olsr_trigger_inetgw_startup();
673   }
674
675   /* trigger niit static route setup */
676   if (olsr_cnf->use_niit) {
677     olsr_setup_niit_routes();
678   }
679
680   /* create lo:olsr interface */
681   if (olsr_cnf->use_src_ip_routes) {
682     olsr_os_localhost_if(&olsr_cnf->main_addr, true);
683   }
684 #endif /* __linux__ */
685
686   /* Start syslog entry */
687   olsr_syslog(OLSR_LOG_INFO, "%s successfully started", olsrd_version);
688
689   /*
690    *signal-handlers
691    */
692
693   /* ctrl-C and friends */
694 #ifdef _WIN32
695 #ifndef WINCE
696   SetConsoleCtrlHandler(SignalHandler, true);
697 #endif /* WINCE */
698 #else /* _WIN32 */
699   signal(SIGHUP, olsr_reconfigure);
700   signal(SIGINT, olsr_shutdown);
701   signal(SIGQUIT, olsr_shutdown);
702   signal(SIGILL, olsr_shutdown);
703   signal(SIGABRT, olsr_shutdown);
704   //  signal(SIGSEGV, olsr_shutdown);
705   signal(SIGTERM, olsr_shutdown);
706   signal(SIGPIPE, SIG_IGN);
707   // Ignoring SIGUSR1 and SIGUSR1 by default to be able to use them in plugins
708   signal(SIGUSR1, SIG_IGN);
709   signal(SIGUSR2, SIG_IGN);
710 #endif /* _WIN32 */
711
712   link_changes = false;
713
714   /* Starting scheduler */
715   olsr_scheduler();
716
717   /* Like we're ever going to reach this ;-) */
718   return 1;
719 } /* main */
720
721 #ifndef _WIN32
722 /**
723  * Reconfigure olsrd. Currently kind of a hack...
724  *
725  *@param signo the signal that triggered this callback
726  */
727 void olsr_reconfigure(int signo __attribute__ ((unused))) {
728   /* if we are started with -nofork, we do not want to go into the
729    * background here. So we can simply stop on -HUP
730    */
731   olsr_syslog(OLSR_LOG_INFO, "sot: olsr_reconfigure()\n");
732   if (!olsr_cnf->no_fork) {
733     if (!fork()) {
734       int i;
735       sigset_t sigs;
736       /* New process */
737       sleep(3);
738       sigemptyset(&sigs);
739       sigaddset(&sigs, SIGHUP);
740       sigprocmask(SIG_UNBLOCK, &sigs, NULL);
741       for (i = sysconf(_SC_OPEN_MAX); --i > STDERR_FILENO;) {
742         close(i);
743       }
744       printf("Restarting %s\n", olsr_argv[0]);
745       olsr_syslog(OLSR_LOG_INFO, "Restarting %s\n", olsr_argv[0]);
746       execv(olsr_argv[0], olsr_argv);
747       olsr_syslog(OLSR_LOG_ERR, "execv(%s) fails: %s!\n", olsr_argv[0],
748           strerror(errno));
749     } else {
750       olsr_syslog(OLSR_LOG_INFO, "RECONFIGURING!\n");
751     }
752   }
753   olsr_shutdown(0);
754 }
755 #endif /* _WIN32 */
756
757 static void olsr_shutdown_messages(void) {
758   struct interface *ifn;
759
760   /* send TC reset */
761   for (ifn = ifnet; ifn; ifn = ifn->int_next) {
762     /* clean output buffer */
763     net_output(ifn);
764
765     /* send 'I'm gone' messages */
766     if (olsr_cnf->lq_level > 0) {
767       olsr_output_lq_tc(ifn);
768       olsr_output_lq_hello(ifn);
769     }
770     else {
771       generate_tc(ifn);
772       generate_hello(ifn);
773     }
774     net_output(ifn);
775   }
776 }
777
778 /**
779  *Function called at shutdown. Signal handler
780  *
781  * @param signo the signal that triggered this call
782  */
783 #ifdef _WIN32
784 int __stdcall
785 SignalHandler(unsigned long signo)
786 #else /* _WIN32 */
787 static void olsr_shutdown(int signo __attribute__ ((unused)))
788 #endif /* _WIN32 */
789 {
790   struct interface *ifn;
791   int exit_value;
792
793   OLSR_PRINTF(1, "Received signal %d - shutting down\n", (int)signo);
794
795 #ifdef _WIN32
796   OLSR_PRINTF(1, "Waiting for the scheduler to stop.\n");
797
798   olsr_win32_end_request = TRUE;
799
800   while (!olsr_win32_end_flag)
801   sleep(1);
802
803   OLSR_PRINTF(1, "Scheduler stopped.\n");
804 #endif /* _WIN32 */
805
806   /* clear all links and send empty hellos/tcs */
807   olsr_reset_all_links();
808
809   /* deactivate fisheye and immediate TCs */
810   olsr_cnf->lq_fish = 0;
811   for (ifn = ifnet; ifn; ifn = ifn->int_next) {
812     ifn->immediate_send_tc = false;
813   }
814   increase_local_ansn();
815
816   /* send first shutdown message burst */
817   olsr_shutdown_messages();
818
819   /* delete all routes */
820   olsr_delete_all_kernel_routes();
821
822   /* send second shutdown message burst */
823   olsr_shutdown_messages();
824
825   /* now try to cleanup the rest of the mess */
826   olsr_delete_all_tc_entries();
827
828   olsr_delete_all_mid_entries();
829
830 #ifdef __linux__
831   /* trigger gateway selection */
832   if (olsr_cnf->smart_gw_active) {
833     olsr_shutdown_gateways();
834     olsr_cleanup_gateways();
835   }
836
837   /* trigger niit static route cleanup */
838   if (olsr_cnf->use_niit) {
839     olsr_cleanup_niit_routes();
840   }
841
842   /* cleanup lo:olsr interface */
843   if (olsr_cnf->use_src_ip_routes) {
844     olsr_os_localhost_if(&olsr_cnf->main_addr, false);
845   }
846 #endif /* __linux__ */
847
848   olsr_destroy_parser();
849
850   OLSR_PRINTF(1, "Closing sockets...\n");
851
852   /* front-end IPC socket */
853   if (olsr_cnf->ipc_connections > 0) {
854     shutdown_ipc();
855   }
856
857   /* OLSR sockets */
858   for (ifn = ifnet; ifn; ifn = ifn->int_next) {
859     close(ifn->olsr_socket);
860     close(ifn->send_socket);
861
862 #ifdef __linux__
863     if (DEF_RT_NONE != olsr_cnf->rt_table_defaultolsr_pri) {
864       olsr_os_policy_rule(olsr_cnf->ip_version, olsr_cnf->rt_table_default,
865           olsr_cnf->rt_table_defaultolsr_pri, ifn->int_name, false);
866     }
867 #endif /* __linux__ */
868   }
869
870   /* Closing plug-ins */
871   olsr_close_plugins();
872
873   /* Reset network settings */
874   net_os_restore_ifoptions();
875
876   /* ioctl socket */
877   close(olsr_cnf->ioctl_s);
878
879 #ifdef __linux__
880   if (DEF_RT_NONE != olsr_cnf->rt_table_pri) {
881     olsr_os_policy_rule(olsr_cnf->ip_version,
882         olsr_cnf->rt_table, olsr_cnf->rt_table_pri, NULL, false);
883   }
884   if (DEF_RT_NONE != olsr_cnf->rt_table_tunnel_pri) {
885     olsr_os_policy_rule(olsr_cnf->ip_version,
886         olsr_cnf->rt_table_tunnel, olsr_cnf->rt_table_tunnel_pri, NULL, false);
887   }
888   if (DEF_RT_NONE != olsr_cnf->rt_table_default_pri) {
889     olsr_os_policy_rule(olsr_cnf->ip_version,
890         olsr_cnf->rt_table_default, olsr_cnf->rt_table_default_pri, NULL, false);
891   }
892   close(olsr_cnf->rtnl_s);
893   close (olsr_cnf->rt_monitor_socket);
894 #endif /* __linux__ */
895
896 #if defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __NetBSD__ || defined __OpenBSD__
897   /* routing socket */
898   close(olsr_cnf->rts);
899 #endif /* defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __APPLE__ || defined __NetBSD__ || defined __OpenBSD__ */
900
901   /* Free cookies and memory pools attached. */
902   OLSR_PRINTF(0, "Free all memory...\n");
903   olsr_delete_all_cookies();
904
905   olsr_syslog(OLSR_LOG_INFO, "%s stopped", olsrd_version);
906
907   OLSR_PRINTF(1, "\n <<<< %s - terminating >>>>\n           http://www.olsr.org\n", olsrd_version);
908
909   exit_value = olsr_cnf->exit_value;
910   olsrd_free_cnf(olsr_cnf);
911
912   exit(exit_value);
913 }
914
915 /**
916  * Print the command line usage
917  */
918 static void print_usage(bool error) {
919   fprintf(
920       stderr,
921         "%s"
922         "usage: olsrd [-f <configfile>] [ -i interface1 interface2 ... ]\n"
923         "  [-d <debug_level>] [-ipv6] [-multi <IPv6 multicast address>]\n"
924         "  [-lql <LQ level>] [-lqw <LQ winsize>] [-lqnt <nat threshold>]\n"
925         "  [-bcast <broadcastaddr>] [-ipc] [-delgw]\n"
926         "  [-hint <hello interval (secs)>] [-tcint <tc interval (secs)>]\n"
927         "  [-midint <mid interval (secs)>] [-hnaint <hna interval (secs)>]\n"
928         "  [-T <Polling Rate (secs)>] [-nofork] [-hemu <ip_address>]\n"
929         "  [-lql <LQ level>] [-lqa <LQ aging factor>]\n"
930         "  [-pidfile <pid file>]\n",
931         error ? "Error in command line parameters!\n" : "");
932 }
933
934 /**
935  * Sets the provided configuration on all unconfigured
936  * interfaces
937  *
938  * @param ifs a linked list of interfaces to check and possible update
939  * @param cnf the default configuration to set on unconfigured interfaces
940  */
941 int set_default_ifcnfs(struct olsr_if *ifs, struct if_config_options *cnf) {
942   int changes = 0;
943
944   while (ifs) {
945     if (ifs->cnf == NULL) {
946       ifs->cnf = olsr_malloc(sizeof(struct if_config_options),
947           "Set default config");
948       *ifs->cnf = *cnf;
949       changes++;
950     }
951     ifs = ifs->next;
952   }
953   return changes;
954 }
955
956 #define NEXT_ARG do { argv++;argc--; } while (0)
957 #define CHECK_ARGC do { if(!argc) { \
958      argv--; \
959      fprintf(stderr, "You must provide a parameter when using the %s switch!\n", *argv); \
960      olsr_exit(__func__, EXIT_FAILURE); \
961      } } while (0)
962
963 /**
964  * Process command line arguments passed to olsrd
965  *
966  */
967 static int olsr_process_arguments(int argc, char *argv[],
968     struct olsrd_config *cnf, struct if_config_options *ifcnf) {
969   while (argc > 1) {
970     NEXT_ARG;
971 #ifdef _WIN32
972     /*
973      *Interface list
974      */
975     if (strcmp(*argv, "-int") == 0) {
976       ListInterfaces();
977       exit(0);
978     }
979 #endif /* _WIN32 */
980
981     /*
982      *Configfilename
983      */
984     if (strcmp(*argv, "-f") == 0) {
985       fprintf(stderr, "Configfilename must ALWAYS be first argument!\n\n");
986       olsr_exit(__func__, EXIT_FAILURE);
987     }
988
989     /*
990      *Use IP version 6
991      */
992     if (strcmp(*argv, "-ipv6") == 0) {
993       cnf->ip_version = AF_INET6;
994       continue;
995     }
996
997     /*
998      *Broadcast address
999      */
1000     if (strcmp(*argv, "-bcast") == 0) {
1001       struct in_addr in;
1002       NEXT_ARG;
1003       CHECK_ARGC;
1004
1005       if (inet_aton(*argv, &in) == 0) {
1006         printf("Invalid broadcast address! %s\nSkipping it!\n", *argv);
1007         continue;
1008       }
1009       memcpy(&ifcnf->ipv4_multicast.v4, &in.s_addr, sizeof(ifcnf->ipv4_multicast.v4));
1010       continue;
1011     }
1012
1013     /*
1014      * Set LQ level
1015      */
1016     if (strcmp(*argv, "-lql") == 0) {
1017       int tmp_lq_level;
1018       NEXT_ARG;
1019       CHECK_ARGC;
1020
1021       /* Sanity checking is done later */
1022       sscanf(*argv, "%d", &tmp_lq_level);
1023       olsr_cnf->lq_level = tmp_lq_level;
1024       continue;
1025     }
1026
1027     /*
1028      * Set LQ winsize
1029      */
1030     if (strcmp(*argv, "-lqa") == 0) {
1031       float tmp_lq_aging;
1032       NEXT_ARG;
1033       CHECK_ARGC;
1034
1035       sscanf(*argv, "%f", &tmp_lq_aging);
1036
1037       if (tmp_lq_aging < (float)MIN_LQ_AGING || tmp_lq_aging > (float)MAX_LQ_AGING) {
1038         printf("LQ aging factor %f not allowed. Range [%f-%f]\n", (double)tmp_lq_aging,
1039                         (double)MIN_LQ_AGING, (double)MAX_LQ_AGING);
1040         olsr_exit(__func__, EXIT_FAILURE);
1041       }
1042       olsr_cnf->lq_aging = tmp_lq_aging;
1043       continue;
1044     }
1045
1046     /*
1047      * Set NAT threshold
1048      */
1049     if (strcmp(*argv, "-lqnt") == 0) {
1050       float tmp_lq_nat_thresh;
1051       NEXT_ARG;
1052       CHECK_ARGC;
1053
1054       sscanf(*argv, "%f", &tmp_lq_nat_thresh);
1055
1056       if (tmp_lq_nat_thresh < 0.1f || tmp_lq_nat_thresh > 1.0f) {
1057         printf("NAT threshold %f not allowed. Range [%f-%f]\n",
1058                         (double)tmp_lq_nat_thresh, (double)0.1, (double)1.0);
1059         olsr_exit(__func__, EXIT_FAILURE);
1060       }
1061       olsr_cnf->lq_nat_thresh = tmp_lq_nat_thresh;
1062       continue;
1063     }
1064
1065     /*
1066      * Enable additional debugging information to be logged.
1067      */
1068     if (strcmp(*argv, "-d") == 0) {
1069       NEXT_ARG;
1070       CHECK_ARGC;
1071
1072       sscanf(*argv, "%d", &cnf->debug_level);
1073       continue;
1074     }
1075
1076     /*
1077      * Interfaces to be used by olsrd.
1078      */
1079     if (strcmp(*argv, "-i") == 0) {
1080       NEXT_ARG;
1081       CHECK_ARGC;
1082
1083       if (*argv[0] == '-') {
1084         fprintf(stderr, "You must provide an interface label!\n");
1085         olsr_exit(__func__, EXIT_FAILURE);
1086       }
1087       printf("Queuing if %s\n", *argv);
1088       olsr_create_olsrif(*argv, false);
1089
1090       while ((argc - 1) && (argv[1][0] != '-')) {
1091         NEXT_ARG;
1092         printf("Queuing if %s\n", *argv);
1093         olsr_create_olsrif(*argv, false);
1094       }
1095
1096       continue;
1097     }
1098     /*
1099      * Set the hello interval to be used by olsrd.
1100      *
1101      */
1102     if (strcmp(*argv, "-hint") == 0) {
1103       NEXT_ARG;
1104       CHECK_ARGC;
1105       sscanf(*argv, "%f", &ifcnf->hello_params.emission_interval);
1106       ifcnf->hello_params.validity_time = ifcnf->hello_params.emission_interval
1107           * 3;
1108       continue;
1109     }
1110
1111     /*
1112      * Set the HNA interval to be used by olsrd.
1113      *
1114      */
1115     if (strcmp(*argv, "-hnaint") == 0) {
1116       NEXT_ARG;
1117       CHECK_ARGC;
1118       sscanf(*argv, "%f", &ifcnf->hna_params.emission_interval);
1119       ifcnf->hna_params.validity_time = ifcnf->hna_params.emission_interval * 3;
1120       continue;
1121     }
1122
1123     /*
1124      * Set the MID interval to be used by olsrd.
1125      *
1126      */
1127     if (strcmp(*argv, "-midint") == 0) {
1128       NEXT_ARG;
1129       CHECK_ARGC;
1130       sscanf(*argv, "%f", &ifcnf->mid_params.emission_interval);
1131       ifcnf->mid_params.validity_time = ifcnf->mid_params.emission_interval * 3;
1132       continue;
1133     }
1134
1135     /*
1136      * Set the tc interval to be used by olsrd.
1137      *
1138      */
1139     if (strcmp(*argv, "-tcint") == 0) {
1140       NEXT_ARG;
1141       CHECK_ARGC;
1142       sscanf(*argv, "%f", &ifcnf->tc_params.emission_interval);
1143       ifcnf->tc_params.validity_time = ifcnf->tc_params.emission_interval * 3;
1144       continue;
1145     }
1146
1147     /*
1148      * Set the polling interval to be used by olsrd.
1149      */
1150     if (strcmp(*argv, "-T") == 0) {
1151       NEXT_ARG;
1152       CHECK_ARGC;
1153       sscanf(*argv, "%f", &cnf->pollrate);
1154       continue;
1155     }
1156
1157     /*
1158      * Should we set up and send on a IPC socket for the front-end?
1159      */
1160     if (strcmp(*argv, "-ipc") == 0) {
1161       cnf->ipc_connections = 1;
1162       continue;
1163     }
1164
1165     /*
1166      * IPv6 multicast addr
1167      */
1168     if (strcmp(*argv, "-multi") == 0) {
1169       struct in6_addr in6;
1170       NEXT_ARG;
1171       CHECK_ARGC;
1172       if (inet_pton(AF_INET6, *argv, &in6) <= 0) {
1173         fprintf(stderr, "Failed converting IP address %s\n", *argv);
1174         exit(EXIT_FAILURE);
1175       }
1176
1177       memcpy(&ifcnf->ipv6_multicast, &in6, sizeof(struct in6_addr));
1178
1179       continue;
1180     }
1181
1182     /*
1183      * Host emulation
1184      */
1185     if (strcmp(*argv, "-hemu") == 0) {
1186       struct in_addr in;
1187       struct olsr_if *ifa;
1188
1189       NEXT_ARG;
1190       CHECK_ARGC;
1191       if (inet_pton(AF_INET, *argv, &in) <= 0) {
1192         fprintf(stderr, "Failed converting IP address %s\n", *argv);
1193         exit(EXIT_FAILURE);
1194       }
1195       /* Add hemu interface */
1196
1197       ifa = olsr_create_olsrif("hcif01", true);
1198
1199       if (!ifa)
1200         continue;
1201
1202       ifa->cnf = get_default_if_config();
1203       ifa->host_emul = true;
1204       memset(&ifa->hemu_ip, 0, sizeof(ifa->hemu_ip));
1205       memcpy(&ifa->hemu_ip, &in, sizeof(in));
1206       cnf->host_emul = true;
1207
1208       continue;
1209     }
1210
1211     /*
1212      * Delete possible default GWs
1213      */
1214     if (strcmp(*argv, "-delgw") == 0) {
1215       olsr_cnf->del_gws = true;
1216       continue;
1217     }
1218
1219     if (strcmp(*argv, "-nofork") == 0) {
1220       cnf->no_fork = true;
1221       continue;
1222     }
1223
1224     if (strcmp(*argv, "-pidfile") == 0) {
1225       NEXT_ARG;
1226       CHECK_ARGC;
1227
1228       cnf->pidfile = *argv;
1229       continue;
1230     }
1231
1232     return -1;
1233   }
1234   return 0;
1235 }
1236
1237 /*
1238  * Local Variables:
1239  * c-basic-offset: 2
1240  * indent-tabs-mode: nil
1241  * End:
1242  */