draft bugfix to the times(2) overrun situation
[olsrd.git] / src / main.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas T√łnnesen(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
46 #include "ipcalc.h"
47 #include "defs.h"
48 #include "olsr.h"
49 #include "log.h"
50 #include "scheduler.h"
51 #include "parser.h"
52 #include "generate_msg.h"
53 #include "plugin_loader.h"
54 #include "socket_parser.h"
55 #include "apm.h"
56 #include "net_os.h"
57 #include "build_msg.h"
58 #include "net_olsr.h"
59
60 #if LINUX_POLICY_ROUTING
61 #include <linux/types.h>
62 #include <linux/rtnetlink.h>
63 #include <fcntl.h>
64 #endif
65
66 #ifdef WIN32
67 #define close(x) closesocket(x)
68 int __stdcall SignalHandler(unsigned long signal) __attribute__((noreturn));
69 void ListInterfaces(void);
70 void DisableIcmpRedirects(void);
71 olsr_bool olsr_win32_end_request = OLSR_FALSE;
72 olsr_bool olsr_win32_end_flag = OLSR_FALSE;
73 #else
74 static void
75 olsr_shutdown(int) __attribute__((noreturn));
76 #endif
77
78 /*
79  * Local function prototypes
80  */
81 void
82 olsr_reconfigure(int) __attribute__((noreturn));
83
84 static void
85 print_usage(void);
86
87 static int
88 set_default_ifcnfs(struct olsr_if *, struct if_config_options *);
89
90 static int
91 olsr_process_arguments(int, char *[], 
92                        struct olsrd_config *, 
93                        struct if_config_options *);
94
95 #ifndef WIN32
96 static char **olsr_argv;
97 #endif
98
99 static char copyright_string[] __attribute__((unused)) = "The olsr.org Optimized Link-State Routing daemon(olsrd) Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org) All rights reserved.";
100
101
102 /**
103  * Main entrypoint
104  */
105
106 int
107 main(int argc, char *argv[])
108 {
109   struct if_config_options *default_ifcnf;
110   char conf_file_name[FILENAME_MAX];
111   struct ipaddr_str buf;
112 #ifdef WIN32
113   WSADATA WsaData;
114   size_t len;
115 #endif
116
117   /* paranoia checks */
118   assert(sizeof(olsr_u8_t) == 1);
119   assert(sizeof(olsr_u16_t) == 2);
120   assert(sizeof(olsr_u32_t) == 4);
121   assert(sizeof(olsr_8_t) == 1);
122   assert(sizeof(olsr_16_t) == 2);
123   assert(sizeof(olsr_32_t) == 4);
124
125   debug_handle = stdout;
126 #ifndef WIN32
127   olsr_argv = argv;
128 #endif
129   setbuf(stdout, NULL);
130   setbuf(stderr, NULL);
131
132 #ifndef WIN32
133   /* Check if user is root */
134   if(geteuid())
135     {
136       fprintf(stderr, "You must be root(uid = 0) to run olsrd!\nExiting\n\n");
137       exit(EXIT_FAILURE);
138     }
139 #else
140   DisableIcmpRedirects();
141
142   if (WSAStartup(0x0202, &WsaData))
143     {
144       fprintf(stderr, "Could not initialize WinSock.\n");
145       olsr_exit(__func__, EXIT_FAILURE);
146     }
147 #endif
148
149   /* Open syslog */
150   olsr_openlog("olsrd");
151
152   /* Grab initial timestamp */
153   now_times = olsr_times();
154     
155   printf("\n *** %s ***\n Build date: %s on %s\n http://www.olsr.org\n\n", 
156          olsrd_version, 
157          build_date,
158          build_host);
159     
160   /* Using PID as random seed */
161   srandom(getpid());
162
163   /* Init widely used statics */
164   memset(&all_zero, 0, sizeof(union olsr_ip_addr));
165
166   /*
167    * Set configfile name and
168    * check if a configfile name was given as parameter
169    */
170 #ifdef WIN32
171 #ifndef WINCE
172   GetWindowsDirectory(conf_file_name, FILENAME_MAX - 11);
173 #else
174   conf_file_name[0] = 0;
175 #endif
176   
177   len = strlen(conf_file_name);
178   
179   if (len == 0 || conf_file_name[len - 1] != '\\')
180     conf_file_name[len++] = '\\';
181   
182   strscpy(conf_file_name + len, "olsrd.conf", sizeof(conf_file_name) - len);
183 #else
184   strscpy(conf_file_name, OLSRD_GLOBAL_CONF_FILE, sizeof(conf_file_name));
185 #endif
186
187   if ((argc > 1) && (strcmp(argv[1], "-f") == 0)) 
188     {
189       struct stat statbuf;
190
191       argv++; argc--;
192       if(argc == 1)
193         {
194           fprintf(stderr, "You must provide a filename when using the -f switch!\n");
195           exit(EXIT_FAILURE);
196         }
197
198       if (stat(argv[1], &statbuf) < 0)
199         {
200           fprintf(stderr, "Could not find specified config file %s!\n%s\n\n", argv[1], strerror(errno));
201           exit(EXIT_FAILURE);
202         }
203                  
204       strscpy(conf_file_name, argv[1], sizeof(conf_file_name));
205       argv++; argc--;
206
207     }
208
209   /*
210    * set up configuration prior to processing commandline options
211    */
212   if(NULL == (olsr_cnf = olsrd_parse_cnf(conf_file_name)))
213     {
214       printf("Using default config values(no configfile)\n");
215       olsr_cnf = olsrd_get_default_cnf();
216     }
217
218   default_ifcnf = get_default_if_config();
219   if (default_ifcnf == NULL) {
220     fprintf(stderr, "No default ifconfig found!\n");
221     exit(EXIT_FAILURE);
222   }
223
224   /* Initialize tick resolution */
225 #ifndef WIN32
226   olsr_cnf->system_tick_divider = 1000/sysconf(_SC_CLK_TCK);
227 #else
228   olsr_cnf->system_tick_divider = 1;
229 #endif
230
231   /* Initialize timers */
232   olsr_init_timers();
233
234   /*
235    * Process olsrd options.
236    */
237   if(olsr_process_arguments(argc, argv, olsr_cnf, default_ifcnf) < 0)
238     {
239       print_usage();
240       olsr_exit(__func__, EXIT_FAILURE);
241     }
242
243   /*
244    * Set configuration for command-line specified interfaces
245    */
246   set_default_ifcnfs(olsr_cnf->interfaces, default_ifcnf);
247
248   /* free the default ifcnf */
249   free(default_ifcnf);
250
251   /* Sanity check configuration */
252   if(olsrd_sanity_check_cnf(olsr_cnf) < 0)
253     {
254       fprintf(stderr, "Bad configuration!\n");
255       olsr_exit(__func__, EXIT_FAILURE);      
256     }
257
258   /*
259    * Print configuration 
260    */
261   if(olsr_cnf->debug_level > 1) {
262     olsrd_print_cnf(olsr_cnf);
263   }
264 #ifndef WIN32
265   /* Disable redirects globally */
266   disable_redirects_global(olsr_cnf->ip_version);
267 #endif
268
269   /*
270    * socket for ioctl calls
271    */
272   olsr_cnf->ioctl_s = socket(olsr_cnf->ip_version, SOCK_DGRAM, 0);
273   if (olsr_cnf->ioctl_s < 0) {
274     olsr_syslog(OLSR_LOG_ERR, "ioctl socket: %m");
275     olsr_exit(__func__, 0);
276   }
277
278 #if LINUX_POLICY_ROUTING
279   olsr_cnf->rtnl_s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
280   if (olsr_cnf->rtnl_s < 0) {
281     olsr_syslog(OLSR_LOG_ERR, "rtnetlink socket: %m");
282     olsr_exit(__func__, 0);
283   }
284   fcntl(olsr_cnf->rtnl_s, F_SETFL, O_NONBLOCK);
285 #endif
286
287 /*
288  * create routing socket
289  */
290 #if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
291   olsr_cnf->rts = socket(PF_ROUTE, SOCK_RAW, 0);
292   if (olsr_cnf->rts < 0) {
293     olsr_syslog(OLSR_LOG_ERR, "routing socket: %m");
294     olsr_exit(__func__, 0);
295   }
296 #endif
297
298   /* Init empty TC timer */
299   set_empty_tc_timer(GET_TIMESTAMP(0));
300
301   /*
302    *enable ip forwarding on host
303    */
304   enable_ip_forwarding(olsr_cnf->ip_version);
305
306   /* Initialize parser */
307   olsr_init_parser();
308
309   /* Initialize route-exporter */
310   olsr_init_export_route();
311
312   /* Initialize message sequencnumber */
313   init_msg_seqno();
314
315   /* Initialize dynamic willingness calculation */
316   olsr_init_willingness();
317
318   /*
319    *Set up willingness/APM
320    */
321   if(olsr_cnf->willingness_auto)
322     {
323       if(apm_init() < 0)
324         {
325           OLSR_PRINTF(1, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT);
326
327           olsr_syslog(OLSR_LOG_ERR, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT);
328
329           olsr_cnf->willingness_auto = 0;
330           olsr_cnf->willingness = WILL_DEFAULT;
331         }
332       else
333         {
334           olsr_cnf->willingness = olsr_calculate_willingness();
335
336           OLSR_PRINTF(1, "Willingness set to %d - next update in %.1f secs\n", olsr_cnf->willingness, olsr_cnf->will_int);
337         }
338     }
339
340   /* Initialize net */
341   init_net();
342
343   /* Initializing networkinterfaces */
344   if(!ifinit())
345     {
346       if(olsr_cnf->allow_no_interfaces)
347         {
348           fprintf(stderr, "No interfaces detected! This might be intentional, but it also might mean that your configuration is fubar.\nI will continue after 5 seconds...\n");
349           sleep(5);
350         }
351       else
352         {
353           fprintf(stderr, "No interfaces detected!\nBailing out!\n");
354           olsr_exit(__func__, EXIT_FAILURE);
355         }
356     }
357
358   /* Print heartbeat to stdout */
359
360 #if !defined WINCE
361   if (olsr_cnf->debug_level > 0 && isatty(STDOUT_FILENO)) {
362     olsr_start_timer(STDOUT_PULSE_INT, 0, OLSR_TIMER_PERIODIC,
363                      &generate_stdout_pulse, NULL, 0);
364   }
365 #endif
366
367   /* Initialize the IPC socket */
368
369   if (olsr_cnf->ipc_connections > 0) {
370       ipc_init();
371   }
372   /* Initialisation of different tables to be used.*/
373   olsr_init_tables();
374
375   /* daemon mode */
376 #ifndef WIN32
377   if(olsr_cnf->debug_level == 0 && !olsr_cnf->no_fork) {
378     printf("%s detaching from the current process...\n", olsrd_version);
379     if (daemon(0, 0) < 0) {
380       printf("daemon(3) failed: %s\n", strerror(errno));
381       exit(EXIT_FAILURE);
382     }
383   }
384 #endif
385
386   /* Load plugins */
387   olsr_load_plugins();
388
389   OLSR_PRINTF(1, "Main address: %s\n\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr));
390
391   /* Start syslog entry */
392   olsr_syslog(OLSR_LOG_INFO, "%s successfully started", olsrd_version);
393
394   /*
395    *signal-handlers
396    */
397
398   /* ctrl-C and friends */
399 #ifdef WIN32
400 #ifndef WINCE
401   SetConsoleCtrlHandler(SignalHandler, OLSR_TRUE);
402 #endif
403 #else
404   signal(SIGHUP, olsr_reconfigure);  
405   signal(SIGINT,  olsr_shutdown);
406   signal(SIGQUIT, olsr_shutdown);
407   signal(SIGILL,  olsr_shutdown);
408   signal(SIGABRT, olsr_shutdown);
409 //  signal(SIGSEGV, olsr_shutdown);
410   signal(SIGTERM, olsr_shutdown);
411   signal(SIGPIPE, SIG_IGN);
412 #endif
413
414   link_changes = OLSR_FALSE;
415
416   /* Starting scheduler */
417   olsr_scheduler();
418
419   /* Like we're ever going to reach this ;-) */
420   return 1;
421 } /* main */
422
423
424
425 /**
426  * Reconfigure olsrd. Currently kind of a hack...
427  *
428  *@param signal the signal that triggered this callback
429  */
430 #ifndef WIN32
431 void
432 olsr_reconfigure(int signal __attribute__((unused)))
433 {
434   if(!fork())
435     {
436       /* New process */
437       sleep(3);
438       printf("Restarting %s\n", olsr_argv[0]);
439       execv(olsr_argv[0], olsr_argv);
440     }
441   olsr_shutdown(0);
442
443   printf("RECONFIGURING!\n");
444 }
445 #endif
446
447
448 /**
449  *Function called at shutdown. Signal handler
450  *
451  * @param signal the signal that triggered this call
452  */
453 #ifdef WIN32
454 int __stdcall
455 SignalHandler(unsigned long signal)
456 #else
457 static void
458 olsr_shutdown(int signal __attribute__((unused)))
459 #endif
460 {
461   struct interface *ifn;
462
463   OLSR_PRINTF(1, "Received signal %d - shutting down\n", (int)signal);
464
465 #ifdef WIN32
466   OLSR_PRINTF(1, "Waiting for the scheduler to stop.\n");
467
468   olsr_win32_end_request = TRUE;
469
470   while (!olsr_win32_end_flag)
471     Sleep(100);
472
473   OLSR_PRINTF(1, "Scheduler stopped.\n");
474 #endif
475
476   olsr_delete_all_kernel_routes();
477
478   OLSR_PRINTF(1, "Closing sockets...\n");
479
480   /* front-end IPC socket */
481   if (olsr_cnf->ipc_connections > 0) {
482     shutdown_ipc();
483   }
484
485   /* OLSR sockets */
486   for (ifn = ifnet; ifn; ifn = ifn->int_next) 
487     close(ifn->olsr_socket);
488
489   /* Closing plug-ins */
490   olsr_close_plugins();
491
492   /* Reset network settings */
493   restore_settings(olsr_cnf->ip_version);
494
495   /* ioctl socket */
496   close(olsr_cnf->ioctl_s);
497
498 #if LINUX_POLICY_ROUTING
499   close(olsr_cnf->rtnl_s);
500 #endif
501
502 #if defined __FreeBSD__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__
503   /* routing socket */
504   close(olsr_cnf->rts);
505 #endif
506
507   /* Free cookies and memory pools attached. */
508   olsr_delete_all_cookies();
509
510   olsr_syslog(OLSR_LOG_INFO, "%s stopped", olsrd_version);
511
512   OLSR_PRINTF(1, "\n <<<< %s - terminating >>>>\n           http://www.olsr.org\n", olsrd_version);
513
514   exit(olsr_cnf->exit_value);
515 }
516
517 /**
518  * Print the command line usage
519  */
520 static void
521 print_usage(void)
522 {
523
524   fprintf(stderr,
525           "An error occured somwhere between your keyboard and your chair!\n"
526           "usage: olsrd [-f <configfile>] [ -i interface1 interface2 ... ]\n"
527           "  [-d <debug_level>] [-ipv6] [-multi <IPv6 multicast address>]\n"
528           "  [-lql <LQ level>] [-lqw <LQ winsize>] [-lqnt <nat threshold>]\n"
529           "  [-bcast <broadcastaddr>] [-ipc] [-dispin] [-dispout] [-delgw]\n"
530           "  [-hint <hello interval (secs)>] [-tcint <tc interval (secs)>]\n"
531           "  [-midint <mid interval (secs)>] [-hnaint <hna interval (secs)>]\n"
532           "  [-T <Polling Rate (secs)>] [-nofork] [-hemu <ip_address>]\n"
533           "  [-lql <LQ level>] [-lqa <LQ aging factor>]\n");
534 }
535
536
537 /**
538  * Sets the provided configuration on all unconfigured
539  * interfaces
540  *
541  * @param ifs a linked list of interfaces to check and possible update
542  * @param cnf the default configuration to set on unconfigured interfaces
543  */
544 int
545 set_default_ifcnfs(struct olsr_if *ifs, struct if_config_options *cnf)
546 {
547   int changes = 0;
548
549   while(ifs)
550     {
551       if(ifs->cnf == NULL)
552         {
553           ifs->cnf = olsr_malloc(sizeof(struct if_config_options), "Set default config");
554           *ifs->cnf = *cnf;
555           changes++;
556         }
557       ifs = ifs->next;
558     }
559   return changes;
560 }
561
562
563 #define NEXT_ARG do { argv++;argc--; } while (0)
564 #define CHECK_ARGC do { if(!argc) { \
565       if((argc - 1) == 1){ \
566       fprintf(stderr, "Error parsing command line options!\n"); \
567       } else { \
568       argv--; \
569       fprintf(stderr, "You must provide a parameter when using the %s switch!\n", *argv); \
570      } \
571      olsr_exit(__func__, EXIT_FAILURE); \
572      } } while (0)
573
574 /**
575  * Process command line arguments passed to olsrd
576  *
577  */
578 static int
579 olsr_process_arguments(int argc, char *argv[], 
580                        struct olsrd_config *cnf, 
581                        struct if_config_options *ifcnf)
582 {
583   while (argc > 1)
584     {
585       NEXT_ARG;
586 #ifdef WIN32
587       /*
588        *Interface list
589        */
590       if (strcmp(*argv, "-int") == 0)
591         {
592           ListInterfaces();
593           exit(0);
594         }
595 #endif
596
597       /*
598        *Configfilename
599        */
600       if(strcmp(*argv, "-f") == 0) 
601         {
602           fprintf(stderr, "Configfilename must ALWAYS be first argument!\n\n");
603           olsr_exit(__func__, EXIT_FAILURE);
604         }
605
606       /*
607        *Use IP version 6
608        */
609       if(strcmp(*argv, "-ipv6") == 0) 
610         {
611           cnf->ip_version = AF_INET6;
612           continue;
613         }
614
615       /*
616        *Broadcast address
617        */
618       if(strcmp(*argv, "-bcast") == 0) 
619         {
620           struct in_addr in;
621           NEXT_ARG;
622           CHECK_ARGC;
623
624           if (inet_aton(*argv, &in) == 0)
625             {
626               printf("Invalid broadcast address! %s\nSkipping it!\n", *argv);
627               continue;
628             }
629           memcpy(&ifcnf->ipv4_broadcast.v4, &in.s_addr, sizeof(olsr_u32_t));  
630           continue;
631         }
632
633       /*
634        * Set LQ level
635        */
636       if (strcmp(*argv, "-lql") == 0) 
637         {
638           int tmp_lq_level;
639           NEXT_ARG;
640           CHECK_ARGC;
641           
642           /* Sanity checking is done later */
643           sscanf(*argv, "%d", &tmp_lq_level);
644           olsr_cnf->lq_level = tmp_lq_level;
645           continue;
646         }
647
648       /*
649        * Set LQ winsize
650        */
651       if (strcmp(*argv, "-lqa") == 0) 
652         {
653           float tmp_lq_aging;
654           NEXT_ARG;
655           CHECK_ARGC;
656           
657           sscanf(*argv, "%f", &tmp_lq_aging);
658
659           if(tmp_lq_aging < MIN_LQ_AGING || tmp_lq_aging > MAX_LQ_AGING)
660             {
661               printf("LQ aging factor %f not allowed. Range [%f-%f]\n", 
662                      tmp_lq_aging, MIN_LQ_AGING, MAX_LQ_AGING);
663               olsr_exit(__func__, EXIT_FAILURE);
664             }
665           olsr_cnf->lq_aging = tmp_lq_aging;
666           continue;
667         }
668       
669       /*
670        * Set NAT threshold
671        */
672       if (strcmp(*argv, "-lqnt") == 0) 
673         {
674           float tmp_lq_nat_thresh;
675           NEXT_ARG;
676           CHECK_ARGC;
677
678           sscanf(*argv,"%f", &tmp_lq_nat_thresh);
679
680           if(tmp_lq_nat_thresh < 0.1 || tmp_lq_nat_thresh > 1.0)
681             {
682               printf("NAT threshold %f not allowed. Range [%f-%f]\n", 
683                      tmp_lq_nat_thresh, 0.1, 1.0);
684               olsr_exit(__func__, EXIT_FAILURE);
685             }
686           olsr_cnf->lq_nat_thresh = tmp_lq_nat_thresh;
687           continue;
688         }
689
690       /*
691        * Enable additional debugging information to be logged.
692        */
693       if (strcmp(*argv, "-d") == 0) 
694         {
695           NEXT_ARG;
696           CHECK_ARGC;
697
698           sscanf(*argv,"%d", &cnf->debug_level);
699           continue;
700         }
701
702                 
703       /*
704        * Interfaces to be used by olsrd.
705        */
706       if (strcmp(*argv, "-i") == 0) 
707         {
708           NEXT_ARG;
709           CHECK_ARGC;
710
711           if(*argv[0] == '-')
712             {
713               fprintf(stderr, "You must provide an interface label!\n");
714               olsr_exit(__func__, EXIT_FAILURE);
715             }
716           printf("Queuing if %s\n", *argv);
717           queue_if(*argv, OLSR_FALSE);
718
719           while((argc - 1) && (argv[1][0] != '-'))
720             {
721               NEXT_ARG;
722               printf("Queuing if %s\n", *argv);
723               queue_if(*argv, OLSR_FALSE);
724             }
725
726           continue;
727         }
728       /*
729        * Set the hello interval to be used by olsrd.
730        * 
731        */
732       if (strcmp(*argv, "-hint") == 0) 
733         {
734           NEXT_ARG;
735           CHECK_ARGC;
736           sscanf(*argv,"%f", &ifcnf->hello_params.emission_interval);
737           ifcnf->hello_params.validity_time = ifcnf->hello_params.emission_interval * 3;
738           continue;
739         }
740
741       /*
742        * Set the HNA interval to be used by olsrd.
743        * 
744        */
745       if (strcmp(*argv, "-hnaint") == 0) 
746         {
747           NEXT_ARG;
748           CHECK_ARGC;
749           sscanf(*argv,"%f", &ifcnf->hna_params.emission_interval);
750           ifcnf->hna_params.validity_time = ifcnf->hna_params.emission_interval * 3;
751           continue;
752         }
753
754       /*
755        * Set the MID interval to be used by olsrd.
756        * 
757        */
758       if (strcmp(*argv, "-midint") == 0) 
759         {
760           NEXT_ARG;
761           CHECK_ARGC;
762           sscanf(*argv,"%f", &ifcnf->mid_params.emission_interval);
763           ifcnf->mid_params.validity_time = ifcnf->mid_params.emission_interval * 3;
764           continue;
765         }
766
767       /*
768        * Set the tc interval to be used by olsrd.
769        * 
770        */
771       if (strcmp(*argv, "-tcint") == 0) 
772         {
773           NEXT_ARG;
774           CHECK_ARGC;
775           sscanf(*argv,"%f", &ifcnf->tc_params.emission_interval);
776           ifcnf->tc_params.validity_time = ifcnf->tc_params.emission_interval * 3;
777           continue;
778         }
779
780       /*
781        * Set the polling interval to be used by olsrd.
782        */
783       if (strcmp(*argv, "-T") == 0) 
784         {
785           NEXT_ARG;
786           CHECK_ARGC;
787           sscanf(*argv,"%f",&cnf->pollrate);
788           continue;
789         }
790
791
792       /*
793        * Should we display the contents of packages beeing sent?
794        */
795       if (strcmp(*argv, "-dispin") == 0) 
796         {
797           parser_set_disp_pack_in(OLSR_TRUE);
798           continue;
799         }
800
801       /*
802        * Should we display the contents of incoming packages?
803        */
804       if (strcmp(*argv, "-dispout") == 0) 
805         {
806           net_set_disp_pack_out(OLSR_TRUE);
807           continue;
808         }
809
810
811       /*
812        * Should we set up and send on a IPC socket for the front-end?
813        */
814       if (strcmp(*argv, "-ipc") == 0) 
815         {
816           cnf->ipc_connections = 1;
817           continue;
818         }
819
820       /*
821        * IPv6 multicast addr
822        */
823       if (strcmp(*argv, "-multi") == 0) 
824         {
825           struct in6_addr in6;
826           NEXT_ARG;
827           CHECK_ARGC;
828           if(inet_pton(AF_INET6, *argv, &in6) <= 0)
829             {
830               fprintf(stderr, "Failed converting IP address %s\n", *argv);
831               exit(EXIT_FAILURE);
832             }
833
834           memcpy(&ifcnf->ipv6_multi_glbl, &in6, sizeof(struct in6_addr));
835
836           continue;
837         }
838
839       /*
840        * Host emulation
841        */
842       if (strcmp(*argv, "-hemu") == 0) 
843         {
844           struct in_addr in;
845           struct olsr_if *ifa;
846       
847           NEXT_ARG;
848           CHECK_ARGC;
849           if(inet_pton(AF_INET, *argv, &in) <= 0)
850             {
851               fprintf(stderr, "Failed converting IP address %s\n", *argv);
852               exit(EXIT_FAILURE);
853             }
854           /* Add hemu interface */
855
856           ifa = queue_if("hcif01", OLSR_TRUE);
857
858           if(!ifa)
859             continue;
860
861           ifa->cnf = get_default_if_config();
862           ifa->host_emul = OLSR_TRUE;
863           memcpy(&ifa->hemu_ip, &in, sizeof(union olsr_ip_addr));
864           cnf->host_emul = OLSR_TRUE;
865
866           continue;
867         }
868
869
870       /*
871        * Delete possible default GWs
872        */
873       if (strcmp(*argv, "-delgw") == 0) 
874         {
875           olsr_cnf->del_gws = OLSR_TRUE;
876           continue;
877         }
878
879
880       if (strcmp(*argv, "-nofork") == 0) 
881         {
882           cnf->no_fork = OLSR_TRUE;
883           continue;
884         }
885
886       return -1;
887     }
888   return 0;
889 }
890
891 /*
892  * a wrapper around times(2). times(2) has the problem, that it may return -1
893  * in case of an err (e.g. EFAULT on the parameter) or immediately before an
894  * overrun (though it is not en error) just because the jiffies (or whatever
895  * the underlying kernel calls the smallest accountable time unit) are
896  * inherently "unsigned" (and always incremented).
897  */
898 unsigned long olsr_times(void)
899 {
900   struct tms tms_buf;
901   const long t = times(&tms_buf);
902   return t < 0 ? -errno : t;
903 }
904
905 /*
906  * Local Variables:
907  * c-basic-offset: 2
908  * End:
909  */