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