add rule priorities, and ability to set ip addr of interfaces
[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 "socket_parser.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
63 #if LINUX_POLICY_ROUTING
64 #include <linux/types.h>
65 #include <linux/rtnetlink.h>
66 #include "kernel_routes.h"
67
68 #endif
69
70 #ifdef WIN32
71 #include <winbase.h>
72 #define close(x) closesocket(x)
73 int __stdcall SignalHandler(unsigned long signo) __attribute__ ((noreturn));
74 void ListInterfaces(void);
75 void DisableIcmpRedirects(void);
76 bool olsr_win32_end_request = false;
77 bool olsr_win32_end_flag = false;
78 #else
79 static void olsr_shutdown(int) __attribute__ ((noreturn));
80 #endif
81
82 /*
83  * Local function prototypes
84  */
85 void olsr_reconfigure(int) __attribute__ ((noreturn));
86
87 static void print_usage(void);
88
89 static const char* ipip_default_name = "olsr_tunnel";
90
91 static int set_default_ifcnfs(struct olsr_if *, struct if_config_options *);
92
93 static int olsr_process_arguments(int, char *[], struct olsrd_config *,
94     struct if_config_options *);
95
96 #ifndef WIN32
97 static char **olsr_argv;
98 #endif
99
100 static char
101     copyright_string[] __attribute__ ((unused)) =
102         "The olsr.org Optimized Link-State Routing daemon(olsrd) Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org) All rights reserved.";
103
104 /* Data for OLSR locking */
105 static int lock_fd = 0;
106 static char lock_file_name[FILENAME_MAX];
107
108 /*
109  * Creates a zero-length locking file and use fcntl to
110  * place an exclusive lock over it. The lock will be
111  * automatically erased when the olsrd process ends,
112  * so it will even work well with a SIGKILL.
113  *
114  * Additionally the lock can be killed by removing the
115  * locking file.
116  */
117 static void olsr_create_lock_file(void) {
118 #ifdef WIN32
119   HANDLE lck = CreateEvent(NULL, TRUE, FALSE, lock_file_name);
120   if (NULL == lck || ERROR_ALREADY_EXISTS == GetLastError()) {
121     if (NULL == lck) {
122       fprintf(stderr,
123           "Error, cannot create OLSR lock '%s'.\n",
124           lock_file_name);
125     } else {
126       CloseHandle(lck);
127       fprintf(stderr,
128           "Error, cannot aquire OLSR lock '%s'.\n"
129           "Another OLSR instance might be running.\n",
130           lock_file_name);
131     }
132     olsr_exit("", EXIT_FAILURE);
133   }
134 #else
135   struct flock lck;
136
137   /* create file for lock */
138   lock_fd = open(lock_file_name, O_WRONLY | O_CREAT, S_IRWXU);
139   if (lock_fd == 0) {
140     close(lock_fd);
141     fprintf(stderr,
142         "Error, cannot create OLSR lock '%s'.\n",
143         lock_file_name);
144     olsr_exit("", EXIT_FAILURE);
145   }
146
147   /* create exclusive lock for the whole file */
148   lck.l_type = F_WRLCK;
149   lck.l_whence = SEEK_SET;
150   lck.l_start = 0;
151   lck.l_len = 0;
152   lck.l_pid = 0;
153
154   if (fcntl(lock_fd, F_SETLK, &lck) == -1) {
155     close(lock_fd);
156     fprintf(stderr,
157         "Error, cannot aquire OLSR lock '%s'.\n"
158         "Another OLSR instance might be running.\n",
159         lock_file_name);
160     olsr_exit("", EXIT_FAILURE);
161   }
162 #endif
163   return;
164 }
165
166 /**
167  * loads a config file
168  * @return <0 if load failed, 0 otherwise
169  */
170 static int
171 olsrmain_load_config(char *file) {
172   struct stat statbuf;
173
174   if (stat(file, &statbuf) < 0) {
175     fprintf(stderr, "Could not find specified config file %s!\n%s\n\n",
176         file, strerror(errno));
177     return -1;
178   }
179
180   if (olsrd_parse_cnf(file) < 0) {
181     fprintf(stderr, "Error while reading config file %s!\n", file);
182     return -1;
183   }
184   return 0;
185 }
186
187 /**
188  * Main entrypoint
189  */
190
191 int main(int argc, char *argv[]) {
192   struct if_config_options *default_ifcnf;
193   char conf_file_name[FILENAME_MAX];
194   struct ipaddr_str buf;
195   bool loadedConfig = false;
196   int i;
197 #ifdef WIN32
198   WSADATA WsaData;
199   size_t len;
200 #endif
201
202   /* paranoia checks */
203   assert(sizeof(uint8_t) == 1);
204   assert(sizeof(uint16_t) == 2);
205   assert(sizeof(uint32_t) == 4);
206   assert(sizeof(int8_t) == 1);
207   assert(sizeof(int16_t) == 2);
208   assert(sizeof(int32_t) == 4);
209
210   debug_handle = stdout;
211 #ifndef WIN32
212   olsr_argv = argv;
213 #endif
214   setbuf(stdout, NULL);
215   setbuf(stderr, NULL);
216
217 #ifndef WIN32
218   /* Check if user is root */
219   if (geteuid()) {
220     fprintf(stderr, "You must be root(uid = 0) to run olsrd!\nExiting\n\n");
221     exit(EXIT_FAILURE);
222   }
223 #else
224   DisableIcmpRedirects();
225
226   if (WSAStartup(0x0202, &WsaData)) {
227     fprintf(stderr, "Could not initialize WinSock.\n");
228     olsr_exit(__func__, EXIT_FAILURE);
229   }
230 #endif
231
232   /* Open syslog */
233   olsr_openlog("olsrd");
234
235   printf("\n *** %s ***\n Build date: %s on %s\n http://www.olsr.org\n\n",
236       olsrd_version, build_date, build_host);
237
238   /* Using PID as random seed */
239   srandom(getpid());
240
241   /* Init widely used statics */
242   memset(&all_zero, 0, sizeof(union olsr_ip_addr));
243
244   /*
245    * Set configfile name and
246    * check if a configfile name was given as parameter
247    */
248 #ifdef WIN32
249 #ifndef WINCE
250   GetWindowsDirectory(conf_file_name, FILENAME_MAX - 11);
251 #else
252   conf_file_name[0] = 0;
253 #endif
254
255   len = strlen(conf_file_name);
256
257   if (len == 0 || conf_file_name[len - 1] != '\\')
258   conf_file_name[len++] = '\\';
259
260   strscpy(conf_file_name + len, "olsrd.conf", sizeof(conf_file_name) - len);
261 #else
262   strscpy(conf_file_name, OLSRD_GLOBAL_CONF_FILE, sizeof(conf_file_name));
263 #endif
264
265   olsr_cnf = olsrd_get_default_cnf();
266   for (i=1; i < argc-1;) {
267     if (strcmp(argv[i], "-f") == 0) {
268       loadedConfig = true;
269
270       if (olsrmain_load_config(argv[i+1]) < 0) {
271         exit(EXIT_FAILURE);
272       }
273
274       if (i+2 < argc) {
275         memmove(&argv[i], &argv[i+2], sizeof(*argv) * (argc-i-1));
276       }
277       argc -= 2;
278     }
279     else {
280       i++;
281     }
282   }
283
284   /*
285    * set up configuration prior to processing commandline options
286    */
287   if (!loadedConfig && olsrmain_load_config(conf_file_name) == 0) {
288     loadedConfig = true;
289   }
290
291   if (!loadedConfig) {
292     olsrd_free_cnf(olsr_cnf);
293     olsr_cnf = olsrd_get_default_cnf();
294   }
295
296   default_ifcnf = get_default_if_config();
297   if (default_ifcnf == NULL) {
298     fprintf(stderr, "No default ifconfig found!\n");
299     exit(EXIT_FAILURE);
300   }
301
302   /* Initialize timers */
303   olsr_init_timers();
304
305   /*
306    * Process olsrd options.
307    */
308   if (olsr_process_arguments(argc, argv, olsr_cnf, default_ifcnf) < 0) {
309     print_usage();
310     olsr_exit(__func__, EXIT_FAILURE);
311   }
312
313   /*
314    * Set configuration for command-line specified interfaces
315    */
316   set_default_ifcnfs(olsr_cnf->interfaces, default_ifcnf);
317
318   /* free the default ifcnf */
319   free(default_ifcnf);
320
321   /* Sanity check configuration */
322   if (olsrd_sanity_check_cnf(olsr_cnf) < 0) {
323     fprintf(stderr, "Bad configuration!\n");
324     olsr_exit(__func__, EXIT_FAILURE);
325   }
326
327   /*
328    * Establish file lock to prevent multiple instances
329    */
330   if (olsr_cnf->lock_file) {
331     strscpy(lock_file_name, olsr_cnf->lock_file, sizeof(lock_file_name));
332   } else {
333     strscpy(lock_file_name, conf_file_name, sizeof(lock_file_name));
334     strscat(lock_file_name, ".lock", sizeof(lock_file_name));
335   }
336
337   /*
338    * Print configuration
339    */
340   if (olsr_cnf->debug_level > 1) {
341     olsrd_print_cnf(olsr_cnf);
342   }
343 #ifndef WIN32
344   /* Disable redirects globally */
345   disable_redirects_global(olsr_cnf->ip_version);
346 #endif
347
348   /*
349    * socket for ioctl calls
350    */
351   olsr_cnf->ioctl_s = socket(olsr_cnf->ip_version, SOCK_DGRAM, 0);
352   if (olsr_cnf->ioctl_s < 0) {
353     olsr_syslog(OLSR_LOG_ERR, "ioctl socket: %m");
354     olsr_exit(__func__, 0);
355   }
356 #if LINUX_POLICY_ROUTING
357   olsr_cnf->rtnl_s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
358   if (olsr_cnf->rtnl_s < 0) {
359     olsr_syslog(OLSR_LOG_ERR, "rtnetlink socket: %m");
360     olsr_exit(__func__, 0);
361   }
362   fcntl(olsr_cnf->rtnl_s, F_SETFL, O_NONBLOCK);
363 #endif
364
365   /*
366    * create routing socket
367    */
368 #if defined __FreeBSD__ || __FreeBSD_kernel__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
369   olsr_cnf->rts = socket(PF_ROUTE, SOCK_RAW, 0);
370   if (olsr_cnf->rts < 0) {
371     olsr_syslog(OLSR_LOG_ERR, "routing socket: %m");
372     olsr_exit(__func__, 0);
373   }
374 #endif
375
376   /* Init empty TC timer */
377   set_empty_tc_timer(GET_TIMESTAMP(0));
378
379   /*
380    *enable ip forwarding on host
381    */
382   enable_ip_forwarding(olsr_cnf->ip_version);
383
384   /* Initialize parser */
385   olsr_init_parser();
386
387   /* Initialize route-exporter */
388   olsr_init_export_route();
389
390   /* Initialize message sequencnumber */
391   init_msg_seqno();
392
393   /* Initialize dynamic willingness calculation */
394   olsr_init_willingness();
395
396   /*
397    *Set up willingness/APM
398    */
399   if (olsr_cnf->willingness_auto) {
400     if (apm_init() < 0) {
401       OLSR_PRINTF(1, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT);
402
403       olsr_syslog(OLSR_LOG_ERR,
404           "Could not read APM info - setting default willingness(%d)\n",
405           WILL_DEFAULT);
406
407       olsr_cnf->willingness_auto = 0;
408       olsr_cnf->willingness = WILL_DEFAULT;
409     } else {
410       olsr_cnf->willingness = olsr_calculate_willingness();
411
412       OLSR_PRINTF(1, "Willingness set to %d - next update in %.1f secs\n", olsr_cnf->willingness, olsr_cnf->will_int);
413     }
414   }
415
416   /* Initialize net */
417   init_net();
418
419   /* Initializing networkinterfaces */
420   if (!ifinit()) {
421     if (olsr_cnf->allow_no_interfaces) {
422       fprintf(
423           stderr,
424           "No interfaces detected! This might be intentional, but it also might mean that your configuration is fubar.\nI will continue after 5 seconds...\n");
425       olsr_startup_sleep(5);
426     } else {
427       fprintf(stderr, "No interfaces detected!\nBailing out!\n");
428       olsr_exit(__func__, EXIT_FAILURE);
429     }
430   }
431
432   olsr_do_startup_sleep();
433
434   /* Print heartbeat to stdout */
435
436 #if !defined WINCE
437   if (olsr_cnf->debug_level > 0 && isatty(STDOUT_FILENO)) {
438     olsr_start_timer(STDOUT_PULSE_INT, 0, OLSR_TIMER_PERIODIC,
439         &generate_stdout_pulse, NULL, 0);
440   }
441 #endif
442
443   /* Initialize the IPC socket */
444
445   if (olsr_cnf->ipc_connections > 0) {
446     ipc_init();
447   }
448   /* Initialisation of different tables to be used. */
449   olsr_init_tables();
450
451   /* daemon mode */
452 #ifndef WIN32
453   if (olsr_cnf->debug_level == 0 && !olsr_cnf->no_fork) {
454     printf("%s detaching from the current process...\n", olsrd_version);
455     if (daemon(0, 0) < 0) {
456       printf("daemon(3) failed: %s\n", strerror(errno));
457       exit(EXIT_FAILURE);
458     }
459   }
460 #endif
461
462   /*
463    * Create locking file for olsrd, will be cleared after olsrd exits
464    */
465   olsr_create_lock_file();
466
467   /* Load plugins */
468   olsr_load_plugins();
469
470   OLSR_PRINTF(1, "Main address: %s\n\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
471
472 #if LINUX_POLICY_ROUTING
473   /*create smart-gateway-tunnel policy rules*/
474   if (olsr_cnf->smart_gateway_active) {
475     const char* tunlbase = "tunl0";
476     //take up tunl0 device or disable smartgateway
477     olsr_cnf->smart_gateway_active = olsr_dev_up(tunlbase,false);//!!?? kernel 2.4 may need true to function as gateway, does it harm to do anyway
478
479     if (olsr_cnf->smart_gateway_active) {
480       struct olsr_if *cfg_if;
481
482       //need sanity checks for routintg tables
483
484       //question: if rttable_default unconfigured, determine one?
485       //yes use 112
486       //same with smartTable (113)
487
488       //further checks: tabledefault and smartgateway >0 < 253
489       //check if all tables are unique
490       //if not use other values for unconfigured Tables? or stop startup?
491
492       //future improvement: verify if no rule points to default and smartgateway table, with un unknown realm?
493       //nice as we can use realms to give traffic info about gateway tunnel, and ...
494
495       //question: do we set an defaulttable now, which persists if smartgateway is turned off, due to problems (or an rmmodding user) later?
496       //its easier to stick to tables and also better, 
497       //as users will always find the default route on same place.
498
499       //question: make priority of rules configureable (if configured for rttable this might means we shall create this rule (instead the 65535 dummy)
500       //question olsr did never create rules for a custom table (beside the dummy)
501       //should we start now doing so anyways? (beter not, use only new RTTableRule priority)
502
503       //as above ist neither finalized nor done in parser, we use hardcoded values
504       olsr_cnf->ipip_name=ipip_default_name;
505       olsr_cnf->rttable_default=112;
506       olsr_cnf->rttable_smartgw=113;
507       if (olsr_cnf->rttable_default_rule==0) olsr_cnf->rttable_default_rule=65532;
508       if (olsr_cnf->rttable_smartgw_rule==0) olsr_cnf->rttable_smartgw_rule=olsr_cnf->rttable_default_rule+1;
509       if (olsr_cnf->rttable_backup_rule==0) olsr_cnf->rttable_backup_rule=olsr_cnf->rttable_smartgw_rule+1;
510
511       //!!??warning rule function ignores prio at the moment, so ordering counts (should be enough for a prrof of concept)
512
513       /*table with default routes for olsr interfaces*/
514       for (cfg_if = olsr_cnf->interfaces; cfg_if; cfg_if = cfg_if->next) {
515         olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable_default, RTM_NEWRULE, 
516                              olsr_cnf->rttable_default_rule, cfg_if->name);
517       }
518       /*table with route into tunnel (for all interfaces)*/
519       olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable_smartgw, RTM_NEWRULE,
520                         olsr_cnf->rttable_smartgw_rule, NULL);
521       /*backup rule to default route table (if tunnel table gets empty)*/
522       olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable_default, RTM_NEWRULE, 
523                         olsr_cnf->rttable_backup_rule, NULL);
524     }
525   }
526
527   /* Create rule for RtTable to resolve route insertion problems*/
528   if ((olsr_cnf->rttable < 253) & (olsr_cnf->rttable > 0)) {
529     olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable, RTM_NEWRULE, (olsr_cnf->rttable_rule>0?olsr_cnf->rttable_rule:65535), NULL);
530   }
531
532   /* Create rtnetlink socket to listen on interface change events RTMGRP_LINK and RTMGRP_IPV4_ROUTE */
533   //todo listen on tunl0 events aswell
534
535 #if LINUX_RTNETLINK_LISTEN
536   rtnetlink_register_socket(RTMGRP_LINK);
537 #endif /*LINUX_RTNETLINK_LISTEN*/
538
539 #endif
540
541   /* Start syslog entry */
542   olsr_syslog(OLSR_LOG_INFO, "%s successfully started", olsrd_version);
543
544   /*
545    *signal-handlers
546    */
547
548   /* ctrl-C and friends */
549 #ifdef WIN32
550 #ifndef WINCE
551   SetConsoleCtrlHandler(SignalHandler, true);
552 #endif
553 #else
554   signal(SIGHUP, olsr_reconfigure);
555   signal(SIGINT, olsr_shutdown);
556   signal(SIGQUIT, olsr_shutdown);
557   signal(SIGILL, olsr_shutdown);
558   signal(SIGABRT, olsr_shutdown);
559   //  signal(SIGSEGV, olsr_shutdown);
560   signal(SIGTERM, olsr_shutdown);
561   signal(SIGPIPE, SIG_IGN);
562 #endif
563
564   link_changes = false;
565
566   /* Starting scheduler */
567   olsr_scheduler();
568
569   /* Like we're ever going to reach this ;-) */
570   return 1;
571 } /* main */
572
573 /**
574  * Reconfigure olsrd. Currently kind of a hack...
575  *
576  *@param signal the signal that triggered this callback
577  */
578 #ifndef WIN32
579 void olsr_reconfigure(int signo __attribute__ ((unused))) {
580   /* if we are started with -nofork, we do not weant to go into the
581    * background here. So we can simply stop on -HUP
582    */
583   olsr_syslog(OLSR_LOG_INFO, "sot: olsr_reconfigure()\n");
584   if (!olsr_cnf->no_fork) {
585     if (!fork()) {
586       int i;
587       sigset_t sigs;
588       /* New process */
589       sleep(3);
590       sigemptyset(&sigs);
591       sigaddset(&sigs, SIGHUP);
592       sigprocmask(SIG_UNBLOCK, &sigs, NULL);
593       for (i = sysconf(_SC_OPEN_MAX); --i > STDERR_FILENO;) {
594         close(i);
595       }
596       printf("Restarting %s\n", olsr_argv[0]);
597       olsr_syslog(OLSR_LOG_INFO, "Restarting %s\n", olsr_argv[0]);
598       execv(olsr_argv[0], olsr_argv);
599       olsr_syslog(OLSR_LOG_ERR, "execv(%s) fails: %s!\n", olsr_argv[0],
600           strerror(errno));
601     } else {
602       olsr_syslog(OLSR_LOG_INFO, "RECONFIGURING!\n");
603     }
604   }
605   olsr_shutdown(0);
606 }
607 #endif
608
609 static void olsr_shutdown_messages(void) {
610   struct interface *ifn;
611
612   /* send TC reset */
613   for (ifn = ifnet; ifn; ifn = ifn->int_next) {
614     /* clean output buffer */
615     net_output(ifn);
616
617     /* send 'I'm gone' messages */
618     if (olsr_cnf->lq_level > 0) {
619       olsr_output_lq_tc(ifn);
620       olsr_output_lq_hello(ifn);
621     }
622     else {
623       generate_tc(ifn);
624       generate_hello(ifn);
625     }
626     net_output(ifn);
627   }
628 }
629
630 /**
631  *Function called at shutdown. Signal handler
632  *
633  * @param signal the signal that triggered this call
634  */
635 #ifdef WIN32
636 int __stdcall
637 SignalHandler(unsigned long signo)
638 #else
639 static void olsr_shutdown(int signo __attribute__ ((unused)))
640 #endif
641 {
642   struct interface *ifn;
643   int exit_value;
644
645   OLSR_PRINTF(1, "Received signal %d - shutting down\n", (int)signo);
646
647 #ifdef WIN32
648   OLSR_PRINTF(1, "Waiting for the scheduler to stop.\n");
649
650   olsr_win32_end_request = TRUE;
651
652   while (!olsr_win32_end_flag)
653   Sleep(100);
654
655   OLSR_PRINTF(1, "Scheduler stopped.\n");
656 #endif
657
658   /* clear all links and send empty hellos/tcs */
659   olsr_reset_all_links();
660
661   /* deactivate fisheye and immediate TCs */
662   olsr_cnf->lq_fish = 0;
663   for (ifn = ifnet; ifn; ifn = ifn->int_next) {
664     ifn->immediate_send_tc = false;
665   }
666   increase_local_ansn();
667
668   /* send first shutdown message burst */
669   olsr_shutdown_messages();
670
671   /* delete all routes */
672   olsr_delete_all_kernel_routes();
673
674   /* send second shutdown message burst */
675   olsr_shutdown_messages();
676
677   /* now try to cleanup the rest of the mess */
678   olsr_delete_all_tc_entries();
679
680   olsr_delete_all_mid_entries();
681
682   olsr_destroy_parser();
683
684   OLSR_PRINTF(1, "Closing sockets...\n");
685
686   /* front-end IPC socket */
687   if (olsr_cnf->ipc_connections > 0) {
688     shutdown_ipc();
689   }
690
691   /* OLSR sockets */
692   for (ifn = ifnet; ifn; ifn = ifn->int_next) {
693     close(ifn->olsr_socket);
694     close(ifn->send_socket);
695   }
696
697   /* Closing plug-ins */
698   olsr_close_plugins();
699
700   /* Reset network settings */
701   restore_settings(olsr_cnf->ip_version);
702
703   /* ioctl socket */
704   close(olsr_cnf->ioctl_s);
705
706 #if LINUX_POLICY_ROUTING
707 //!!?? warning we do not delete any smartgw rules
708 printf("smartgw rules where not deleted!");
709
710   /* RtTable (linux only!!) */
711   if ((olsr_cnf->rttable < 253) & (olsr_cnf->rttable > 0)) {
712     olsr_netlink_rule(olsr_cnf->ip_version, olsr_cnf->rttable, RTM_DELRULE, 65535, NULL);
713   }
714
715   close(olsr_cnf->rtnl_s);
716 #endif
717
718 #if defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
719   /* routing socket */
720   close(olsr_cnf->rts);
721 #endif
722
723   /* Free cookies and memory pools attached. */
724   OLSR_PRINTF(0, "Free all memory...\n");
725   olsr_delete_all_cookies();
726
727   olsr_syslog(OLSR_LOG_INFO, "%s stopped", olsrd_version);
728
729   OLSR_PRINTF(1, "\n <<<< %s - terminating >>>>\n           http://www.olsr.org\n", olsrd_version);
730
731   exit_value = olsr_cnf->exit_value;
732   olsrd_free_cnf(olsr_cnf);
733
734   exit(exit_value);
735 }
736
737 /**
738  * Print the command line usage
739  */
740 static void print_usage(void) {
741
742   fprintf(
743       stderr,
744       "An error occured somwhere between your keyboard and your chair!\n"
745         "usage: olsrd [-f <configfile>] [ -i interface1 interface2 ... ]\n"
746         "  [-d <debug_level>] [-ipv6] [-multi <IPv6 multicast address>]\n"
747         "  [-lql <LQ level>] [-lqw <LQ winsize>] [-lqnt <nat threshold>]\n"
748         "  [-bcast <broadcastaddr>] [-ipc] [-dispin] [-dispout] [-delgw]\n"
749         "  [-hint <hello interval (secs)>] [-tcint <tc interval (secs)>]\n"
750         "  [-midint <mid interval (secs)>] [-hnaint <hna interval (secs)>]\n"
751         "  [-T <Polling Rate (secs)>] [-nofork] [-hemu <ip_address>]\n" "  [-lql <LQ level>] [-lqa <LQ aging factor>]\n");
752 }
753
754 /**
755  * Sets the provided configuration on all unconfigured
756  * interfaces
757  *
758  * @param ifs a linked list of interfaces to check and possible update
759  * @param cnf the default configuration to set on unconfigured interfaces
760  */
761 int set_default_ifcnfs(struct olsr_if *ifs, struct if_config_options *cnf) {
762   int changes = 0;
763
764   while (ifs) {
765     if (ifs->cnf == NULL) {
766       ifs->cnf = olsr_malloc(sizeof(struct if_config_options),
767           "Set default config");
768       *ifs->cnf = *cnf;
769       changes++;
770     }
771     ifs = ifs->next;
772   }
773   return changes;
774 }
775
776 #define NEXT_ARG do { argv++;argc--; } while (0)
777 #define CHECK_ARGC do { if(!argc) { \
778       if((argc - 1) == 1){ \
779       fprintf(stderr, "Error parsing command line options!\n"); \
780       } else { \
781       argv--; \
782       fprintf(stderr, "You must provide a parameter when using the %s switch!\n", *argv); \
783      } \
784      olsr_exit(__func__, EXIT_FAILURE); \
785      } } while (0)
786
787 /**
788  * Process command line arguments passed to olsrd
789  *
790  */
791 static int olsr_process_arguments(int argc, char *argv[],
792     struct olsrd_config *cnf, struct if_config_options *ifcnf) {
793   while (argc > 1) {
794     NEXT_ARG;
795 #ifdef WIN32
796     /*
797      *Interface list
798      */
799     if (strcmp(*argv, "-int") == 0) {
800       ListInterfaces();
801       exit(0);
802     }
803 #endif
804
805     /*
806      *Configfilename
807      */
808     if (strcmp(*argv, "-f") == 0) {
809       fprintf(stderr, "Configfilename must ALWAYS be first argument!\n\n");
810       olsr_exit(__func__, EXIT_FAILURE);
811     }
812
813     /*
814      *Use IP version 6
815      */
816     if (strcmp(*argv, "-ipv6") == 0) {
817       cnf->ip_version = AF_INET6;
818       continue;
819     }
820
821     /*
822      *Broadcast address
823      */
824     if (strcmp(*argv, "-bcast") == 0) {
825       struct in_addr in;
826       NEXT_ARG;
827       CHECK_ARGC;
828
829       if (inet_aton(*argv, &in) == 0) {
830         printf("Invalid broadcast address! %s\nSkipping it!\n", *argv);
831         continue;
832       }
833       memcpy(&ifcnf->ipv4_multicast.v4, &in.s_addr, sizeof(ifcnf->ipv4_multicast.v4));
834       continue;
835     }
836
837     /*
838      * Set LQ level
839      */
840     if (strcmp(*argv, "-lql") == 0) {
841       int tmp_lq_level;
842       NEXT_ARG;
843       CHECK_ARGC;
844
845       /* Sanity checking is done later */
846       sscanf(*argv, "%d", &tmp_lq_level);
847       olsr_cnf->lq_level = tmp_lq_level;
848       continue;
849     }
850
851     /*
852      * Set LQ winsize
853      */
854     if (strcmp(*argv, "-lqa") == 0) {
855       float tmp_lq_aging;
856       NEXT_ARG;
857       CHECK_ARGC;
858
859       sscanf(*argv, "%f", &tmp_lq_aging);
860
861       if (tmp_lq_aging < MIN_LQ_AGING || tmp_lq_aging > MAX_LQ_AGING) {
862         printf("LQ aging factor %f not allowed. Range [%f-%f]\n", tmp_lq_aging,
863             MIN_LQ_AGING, MAX_LQ_AGING);
864         olsr_exit(__func__, EXIT_FAILURE);
865       }
866       olsr_cnf->lq_aging = tmp_lq_aging;
867       continue;
868     }
869
870     /*
871      * Set NAT threshold
872      */
873     if (strcmp(*argv, "-lqnt") == 0) {
874       float tmp_lq_nat_thresh;
875       NEXT_ARG;
876       CHECK_ARGC;
877
878       sscanf(*argv, "%f", &tmp_lq_nat_thresh);
879
880       if (tmp_lq_nat_thresh < 0.1 || tmp_lq_nat_thresh > 1.0) {
881         printf("NAT threshold %f not allowed. Range [%f-%f]\n",
882             tmp_lq_nat_thresh, 0.1, 1.0);
883         olsr_exit(__func__, EXIT_FAILURE);
884       }
885       olsr_cnf->lq_nat_thresh = tmp_lq_nat_thresh;
886       continue;
887     }
888
889     /*
890      * Enable additional debugging information to be logged.
891      */
892     if (strcmp(*argv, "-d") == 0) {
893       NEXT_ARG;
894       CHECK_ARGC;
895
896       sscanf(*argv, "%d", &cnf->debug_level);
897       continue;
898     }
899
900     /*
901      * Interfaces to be used by olsrd.
902      */
903     if (strcmp(*argv, "-i") == 0) {
904       NEXT_ARG;
905       CHECK_ARGC;
906
907       if (*argv[0] == '-') {
908         fprintf(stderr, "You must provide an interface label!\n");
909         olsr_exit(__func__, EXIT_FAILURE);
910       }
911       printf("Queuing if %s\n", *argv);
912       queue_if(*argv, false);
913
914       while ((argc - 1) && (argv[1][0] != '-')) {
915         NEXT_ARG;
916         printf("Queuing if %s\n", *argv);
917         queue_if(*argv, false);
918       }
919
920       continue;
921     }
922     /*
923      * Set the hello interval to be used by olsrd.
924      *
925      */
926     if (strcmp(*argv, "-hint") == 0) {
927       NEXT_ARG;
928       CHECK_ARGC;
929       sscanf(*argv, "%f", &ifcnf->hello_params.emission_interval);
930       ifcnf->hello_params.validity_time = ifcnf->hello_params.emission_interval
931           * 3;
932       continue;
933     }
934
935     /*
936      * Set the HNA interval to be used by olsrd.
937      *
938      */
939     if (strcmp(*argv, "-hnaint") == 0) {
940       NEXT_ARG;
941       CHECK_ARGC;
942       sscanf(*argv, "%f", &ifcnf->hna_params.emission_interval);
943       ifcnf->hna_params.validity_time = ifcnf->hna_params.emission_interval * 3;
944       continue;
945     }
946
947     /*
948      * Set the MID interval to be used by olsrd.
949      *
950      */
951     if (strcmp(*argv, "-midint") == 0) {
952       NEXT_ARG;
953       CHECK_ARGC;
954       sscanf(*argv, "%f", &ifcnf->mid_params.emission_interval);
955       ifcnf->mid_params.validity_time = ifcnf->mid_params.emission_interval * 3;
956       continue;
957     }
958
959     /*
960      * Set the tc interval to be used by olsrd.
961      *
962      */
963     if (strcmp(*argv, "-tcint") == 0) {
964       NEXT_ARG;
965       CHECK_ARGC;
966       sscanf(*argv, "%f", &ifcnf->tc_params.emission_interval);
967       ifcnf->tc_params.validity_time = ifcnf->tc_params.emission_interval * 3;
968       continue;
969     }
970
971     /*
972      * Set the polling interval to be used by olsrd.
973      */
974     if (strcmp(*argv, "-T") == 0) {
975       NEXT_ARG;
976       CHECK_ARGC;
977       sscanf(*argv, "%f", &cnf->pollrate);
978       continue;
979     }
980
981     /*
982      * Should we display the contents of packages beeing sent?
983      */
984     if (strcmp(*argv, "-dispin") == 0) {
985       parser_set_disp_pack_in(true);
986       continue;
987     }
988
989     /*
990      * Should we display the contents of incoming packages?
991      */
992     if (strcmp(*argv, "-dispout") == 0) {
993       net_set_disp_pack_out(true);
994       continue;
995     }
996
997     /*
998      * Should we set up and send on a IPC socket for the front-end?
999      */
1000     if (strcmp(*argv, "-ipc") == 0) {
1001       cnf->ipc_connections = 1;
1002       continue;
1003     }
1004
1005     /*
1006      * IPv6 multicast addr
1007      */
1008     if (strcmp(*argv, "-multi") == 0) {
1009       struct in6_addr in6;
1010       NEXT_ARG;
1011       CHECK_ARGC;
1012       if (inet_pton(AF_INET6, *argv, &in6) <= 0) {
1013         fprintf(stderr, "Failed converting IP address %s\n", *argv);
1014         exit(EXIT_FAILURE);
1015       }
1016
1017       memcpy(&ifcnf->ipv6_multicast, &in6, sizeof(struct in6_addr));
1018
1019       continue;
1020     }
1021
1022     /*
1023      * Host emulation
1024      */
1025     if (strcmp(*argv, "-hemu") == 0) {
1026       struct in_addr in;
1027       struct olsr_if *ifa;
1028
1029       NEXT_ARG;
1030       CHECK_ARGC;
1031       if (inet_pton(AF_INET, *argv, &in) <= 0) {
1032         fprintf(stderr, "Failed converting IP address %s\n", *argv);
1033         exit(EXIT_FAILURE);
1034       }
1035       /* Add hemu interface */
1036
1037       ifa = queue_if("hcif01", true);
1038
1039       if (!ifa)
1040         continue;
1041
1042       ifa->cnf = get_default_if_config();
1043       ifa->host_emul = true;
1044       memcpy(&ifa->hemu_ip, &in, sizeof(union olsr_ip_addr));
1045       cnf->host_emul = true;
1046
1047       continue;
1048     }
1049
1050     /*
1051      * Delete possible default GWs
1052      */
1053     if (strcmp(*argv, "-delgw") == 0) {
1054       olsr_cnf->del_gws = true;
1055       continue;
1056     }
1057
1058     if (strcmp(*argv, "-nofork") == 0) {
1059       cnf->no_fork = true;
1060       continue;
1061     }
1062
1063     return -1;
1064   }
1065   return 0;
1066 }
1067
1068 /*
1069  * Local Variables:
1070  * c-basic-offset: 2
1071  * indent-tabs-mode: nil
1072  * End:
1073  */