Initial import
[olsrd.git] / src / main.c
1 /*
2  * OLSR ad-hoc routing table management protocol
3  * Copyright (C) 2004 Andreas T√łnnesen (andreto@ifi.uio.no)
4  *
5  * This file is part of olsrd-unik.
6  *
7  * UniK olsrd is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * UniK olsrd is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with olsrd-unik; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22
23 /*
24  *This implementation was based on the INRIA OLSR implementation. 
25  *
26  *The INRIA code carries the following copyright:
27  *
28  * This Copyright notice is in French. An English summary is given
29  * but the referee text is the French one.
30  *
31  * Copyright (c) 2000, 2001 Adokoe.Plakoo@inria.fr, INRIA Rocquencourt,
32  *                          Anis.Laouiti@inria.fr, INRIA Rocquencourt.
33  */
34
35
36 #include "main.h"
37 #include "interfaces.h"
38 //#include "ifnet.h"
39 #include "configfile.h"
40 #include "mantissa.h"
41 #include "local_hna_set.h"
42 #include "olsr.h"
43 #include "scheduler.h"
44 #include "parser.h"
45 #include "generate_msg.h"
46 #include "plugin_loader.h"
47 #include "socket_parser.h"
48 #include "apm.h"
49 #include "link_layer.h"
50
51 #ifdef linux
52 #include "linux/tunnel.h"
53 #elif defined WIN32
54 #define close(x) closesocket(x)
55 #include "win32/tunnel.h"
56 int __stdcall SignalHandler(unsigned long signal);
57 void ListInterfaces(void);
58 #else
59 #       error "Unsupported system"
60 #endif
61
62 /**
63  *The main funtion does a LOT of things. It should 
64  *probably be much shorter
65  *
66  *After things are set up and the scheduler thread
67  *is started, the main thread goes into a typical 
68  *select(2) loop listening
69  */
70
71 int
72 main(int argc, char *argv[])
73 {
74   //struct interface *ifp;
75   struct in_addr in;
76
77   /* The thread for the scheduler */
78   pthread_t thread;
79
80   struct stat statbuf;
81   char conf_file_name[FILENAME_MAX];
82   
83 #ifdef WIN32
84   WSADATA WsaData;
85   int len;
86 #endif
87
88   setbuf(stdout, NULL);
89   setbuf(stderr, NULL);
90
91   /* Initialize socket list */
92   olsr_socket_entries = NULL;
93
94 #ifndef WIN32
95   /* Check if user is root */
96   if(getuid() || getgid())
97     {
98       fprintf(stderr, "You must be root(uid = 0) to run olsrd!\nExiting\n\n");
99       olsr_exit(__func__, EXIT_FAILURE);
100     }
101 #else
102   if (WSAStartup(0x0202, &WsaData))
103     {
104       fprintf(stderr, "Could not initialize WinSock.\n");
105       olsr_exit(__func__, EXIT_FAILURE);
106     }
107 #endif
108
109   /* Open syslog */
110   openlog("olsrd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
111   setlogmask(LOG_UPTO(LOG_INFO));
112
113   /*
114    * Start syslog entry
115    */
116   syslog(LOG_INFO, "%s started", SOFTWARE_VERSION);
117
118   /* Set default values */
119   set_default_values();
120
121   /*
122    *socket for icotl calls
123    */
124   if ((ioctl_s = socket(ipversion, SOCK_DGRAM, 0)) < 0) 
125     {
126       syslog(LOG_ERR, "ioctl socket: %m");
127       close(ioctl_s);
128       olsr_exit(__func__, 0);
129     }
130
131   /* Initialize network functions */
132   init_net();
133
134   /* Initialize plugin loader */
135   olsr_init_plugin_loader();
136  
137   /* Get initial timestep */
138   nowtm = NULL;
139   while (nowtm == NULL)
140     {
141       nowtm = gmtime(&now.tv_sec);
142     }
143     
144   /* The port to use for OLSR traffic */
145   olsr_udp_port = htons(OLSRPORT);
146     
147   printf("\n *** %s ***\n Build date: %s\n http://www.olsr.org\n\n", 
148          SOFTWARE_VERSION, 
149          __DATE__);
150     
151   /* Using PID as random seed */
152   srandom(getpid());
153
154
155   /*
156    * Set configfile name and
157    * check if a configfile name was given as parameter
158    */
159 #ifdef WIN32
160   GetWindowsDirectory(conf_file_name, FILENAME_MAX - 11);
161   
162   len = strlen(conf_file_name);
163   
164   if (conf_file_name[len - 1] != '\\')
165     conf_file_name[len++] = '\\';
166   
167   strcpy(conf_file_name + len, "olsrd.conf");
168 #else
169   strncpy(conf_file_name, OLSRD_GLOBAL_CONF_FILE, FILENAME_MAX);
170 #endif
171
172   if ((argc > 1) && (strcmp(argv[1], "-f") == 0)) 
173     {
174       argv++, argc--;
175       if(argc == 1)
176         {
177           fprintf(stderr, "You must provide a filename when using the -f switch!\n");
178           olsr_exit(__func__, EXIT_FAILURE);
179         }
180
181       if (stat(argv[1], &statbuf) < 0)
182         {
183           fprintf(stderr, "Could not finc specified config file %s!\n%s\n\n", argv[1], strerror(errno));
184           olsr_exit(__func__, EXIT_FAILURE);
185         }
186                  
187       strncpy(conf_file_name, argv[1], FILENAME_MAX);
188       argv++, argc--;
189
190     }
191
192   /*
193    * Reading configfile options prior to processing commandline options
194    */
195
196   read_config_file(conf_file_name);
197   
198   /*
199    * Process olsrd options.
200    */
201   
202   argv++, argc--;
203   while (argc > 0 && **argv == '-')
204     {
205 #ifdef WIN32
206       /*
207        *Interface list
208        */
209       if (strcmp(*argv, "-int") == 0)
210         {
211           ListInterfaces();
212           exit(0);
213         }
214 #endif
215
216       /*
217        *Configfilename
218        */
219       if (strcmp(*argv, "-f") == 0) 
220         {
221           fprintf(stderr, "Configfilename must ALWAYS be first argument!\n\n");
222           olsr_exit(__func__, EXIT_FAILURE);
223         }
224
225       /*
226        *Use IP version 6
227        */
228       if (strcmp(*argv, "-ipv6") == 0) 
229         {
230           ipversion = AF_INET6;
231           argv++, argc--;
232           continue;
233         }
234
235
236       /*
237        *Broadcast address
238        */
239       if (strcmp(*argv, "-bcast") == 0) 
240         {
241           argv++, argc--;
242           if(argc == 0)
243             {
244               fprintf(stderr, "You must provide a broadcastaddr when using the -bcast switch!\n");
245               olsr_exit(__func__, EXIT_FAILURE);
246             }
247
248           if (inet_aton(*argv, &in) == 0)
249             {
250               printf("Invalid broadcast address! %s\nSkipping it!\n", *argv);
251               continue;
252             }
253
254           bcast_set = 1;
255                  
256           memcpy(&bcastaddr.sin_addr, &in.s_addr, sizeof(olsr_u32_t));
257
258
259           continue;
260         }
261
262
263       /*
264        * Enable additional debugging information to be logged.
265        */
266       if (strcmp(*argv, "-d") == 0) 
267         {
268           argv++, argc--;
269           sscanf(*argv,"%d", &debug_level);
270           argv++, argc--;
271           continue;
272         }
273
274
275
276                 
277       /*
278        * Interfaces to be used by olsrd.
279        */
280       if (strcmp(*argv, "-i") == 0) 
281         {
282           option_i = 1;
283           argv++, argc--;
284           queue_if(*argv);
285           argv++, argc--;
286
287           while((argc) && (**argv != '-'))
288             {
289               queue_if(*argv);
290               argv++; argc--;
291             }
292
293           continue;
294         }
295                 
296       /*
297        * Set the hello interval to be used by olsrd.
298        * 
299        */
300       if (strcmp(*argv, "-hint") == 0) 
301         {
302           argv++, argc--;
303           sscanf(*argv,"%f",&hello_int);
304           argv++, argc--;
305           continue;
306         }
307
308       /*
309        * Set the hello interval to be used by olsrd.
310        * on nonwireless interfaces
311        */
312       if (strcmp(*argv, "-hintn") == 0) 
313         {
314           argv++, argc--;
315           sscanf(*argv,"%f",&hello_int_nw);
316           argv++, argc--;
317           continue;
318         }
319
320       /*
321        * Set the HNA interval to be used by olsrd.
322        * 
323        */
324       if (strcmp(*argv, "-hnaint") == 0) 
325         {
326           argv++, argc--;
327           sscanf(*argv,"%f", &hna_int);
328           argv++, argc--;
329           continue;
330         }
331
332       /*
333        * Set the MID interval to be used by olsrd.
334        * 
335        */
336       if (strcmp(*argv, "-midint") == 0) 
337         {
338           argv++, argc--;
339           sscanf(*argv,"%f", &mid_int);
340           argv++, argc--;
341           continue;
342         }
343
344       /*
345        * Set the tc interval to be used by olsrd.
346        * 
347        */
348       if (strcmp(*argv, "-tcint") == 0) 
349         {
350           argv++, argc--;
351           sscanf(*argv,"%f",&tc_int);
352           argv++, argc--;
353           continue;
354         }
355
356       /*
357        * Set the tos bits to be used by olsrd.
358        * 
359        */
360       if (strcmp(*argv, "-tos") == 0) 
361         {
362           argv++, argc--;
363           sscanf(*argv,"%d",(int *)&tos);
364           argv++, argc--;
365           continue;
366         }
367
368
369       /*
370        * Set the polling interval to be used by olsrd.
371        */
372       if (strcmp(*argv, "-T") == 0) 
373         {
374           argv++, argc--;
375           sscanf(*argv,"%f",&polling_int);
376           argv++, argc--;
377           continue;
378         }
379
380       /*
381        * Set the vtime miltiplier
382        */
383       if (strcmp(*argv, "-hhold") == 0) 
384         {
385           argv++, argc--;
386           sscanf(*argv,"%d",&neighbor_timeout_mult);
387           argv++, argc--;
388           continue;
389         }
390
391       /*
392        * Set the vtime miltiplier for non-WLAN cards
393        */
394       if (strcmp(*argv, "-nhhold") == 0) 
395         {
396           argv++, argc--;
397           sscanf(*argv,"%d",&neighbor_timeout_mult_nw);
398           argv++, argc--;
399           continue;
400         }
401
402       /*
403        * Set the TC vtime multiplier
404        */
405       if (strcmp(*argv, "-thold") == 0) 
406         {
407           argv++, argc--;
408           sscanf(*argv,"%d",&topology_timeout_mult);
409           argv++, argc--;
410           continue;
411         }
412
413       /*
414        * Should we display the contents of packages beeing sent?
415        */
416       if (strcmp(*argv, "-dispin") == 0) 
417         {
418           argv++, argc--;
419           disp_pack_in = 1;
420           continue;
421         }
422
423       /*
424        * Should we display the contents of incoming packages?
425        */
426       if (strcmp(*argv, "-dispout") == 0) 
427         {
428           argv++, argc--;
429           disp_pack_out = 1;
430           continue;
431         }
432
433
434       /*
435        * Should we set up and send on a IPC socket for the front-end?
436        */
437       if (strcmp(*argv, "-ipc") == 0) 
438         {
439           argv++, argc--;
440           use_ipc = 1;
441           continue;
442         }
443
444
445       /*
446        * Display link-layer info(experimental)
447        */
448       if (strcmp(*argv, "-llinfo") == 0) 
449         {
450           argv++, argc--;
451           llinfo = 1;
452           continue;
453         }
454
455       /*
456        * Use Internet gateway tunneling?
457        */
458       if (strcmp(*argv, "-tnl") == 0) 
459         {
460           argv++, argc--;
461           use_tunnel = 1;
462
463           continue;
464         }
465
466
467       /*
468        * IPv6 multicast addr
469        */
470       if (strcmp(*argv, "-multi") == 0) 
471         {
472           argv++, argc--;
473           strncpy(ipv6_mult, *argv, 50);
474
475           argv++, argc--;
476
477           continue;
478         }
479
480
481       /*
482        * Should we display the contents of packages beeing sent?
483        */
484       if (strcmp(*argv, "-delgw") == 0) 
485         {
486           argv++, argc--;
487           del_gws = 1;
488           continue;
489         }
490
491
492       print_usage();
493       olsr_exit(__func__, EXIT_FAILURE);
494     }
495
496
497   /*
498    *Interfaces need to be specified
499    */
500   if(!option_i)
501     {
502       fprintf(stderr, "OLSRD: no interfaces specified!\nuse the -i switch to specify interface(s)\nor set interface(s) in the configuration file!\n");
503       print_usage();
504       olsr_exit(__func__, EXIT_FAILURE);
505     }
506
507
508   /* Type of service */
509   precedence = IPTOS_PREC(tos);
510   tos_bits = IPTOS_TOS(tos);
511
512
513   /*
514    *enable ip forwarding on host
515    */
516   enable_ip_forwarding(ipversion);
517
518
519
520
521   /* Initialize scheduler MUST HAPPEN BEFORE REGISTERING ANY FUNCTIONS! */
522   init_scheduler(polling_int);
523
524   /* Initialize parser */
525   olsr_init_parser();
526
527   /* Initialize message sequencnumber */
528   init_msg_seqno();
529
530   /* Initialize dynamic willingness calculation */
531   olsr_init_willingness();
532
533
534   /* Initialize values for emission data 
535    * This also initiates message generation
536    */
537   olsr_set_hello_interval(hello_int);
538   olsr_set_hello_nw_interval(hello_int_nw);
539   olsr_set_tc_interval(tc_int);
540   olsr_set_mid_interval(mid_int);
541   olsr_set_hna_interval(hna_int);
542
543   /* Print tables to stdout */
544   if(debug_level > 0)
545     olsr_register_scheduler_event(&generate_tabledisplay, hello_int, 0, NULL);
546
547
548   /* printout settings */
549   olsr_printf(1, "\n\
550 hello interval = %0.2f       hello int nonwireless = %0.2f \n\
551 tc interval = %0.2f          polling interval = %0.2f \n\
552 neighbor_hold_time = %0.2f   neighbor_hold_time_nw = %0.2f \n\
553 topology_hold_time = %0.2f  tos setting = %d \n\
554 hna_interval = %0.2f         mid_interval = %0.2f\n\
555 tc_redunadancy = %d          mpr coverage = %d\n", 
556               hello_int, hello_int_nw, \
557               tc_int, polling_int, \
558               neighbor_hold_time, neighbor_hold_time_nw, topology_hold_time, \
559               tos, hna_int, mid_int, \
560               tc_redundancy, mpr_coverage);
561       
562   if(use_hysteresis)
563     {
564       olsr_printf(1, "hysteresis scaling factor = %0.2f\nhysteresis threshold high = %0.2f\nhysteresis threshold low  = %0.2f\n\n",
565                   hyst_scaling,
566                   hyst_threshold_high,
567                   hyst_threshold_low);
568
569       if(hyst_threshold_high <= hyst_threshold_low)
570         {
571           printf("Hysteresis threshold high lower than threshold low!!\nEdit the configuration file to fix this!\n\n");
572           olsr_exit(__func__, EXIT_FAILURE);
573         }
574     }
575
576   if(ipversion == AF_INET)
577     {
578       if(bcast_set)
579         olsr_printf(2, "Using %s broadcast\n", olsr_ip_to_string((union olsr_ip_addr *) &bcastaddr.sin_addr));
580       else
581         olsr_printf(2, "Using broadcastaddresses fetched from interfaces\n");
582     }
583
584   /*
585    *Set up willingness/APM
586    */
587   if(!willingness_set)
588     {
589       if(apm_init() < 0)
590         {
591           olsr_printf(1, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT);
592
593           syslog(LOG_ERR, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT);
594
595           willingness_set = 1;
596           my_willingness = WILL_DEFAULT;
597         }
598       else
599         {
600           my_willingness = olsr_calculate_willingness();
601
602           olsr_printf(1, "Willingness set to %d - next update in %.1f secs\n", my_willingness, will_int);
603         }
604     }
605
606   /**
607    *Set ipsize and minimum packetsize
608    */
609   if(ipversion == AF_INET6)
610     {
611       olsr_printf(1, "Using IP version 6\n");
612       ipsize = sizeof(struct in6_addr);
613
614       /* Set multicast address */
615       if(ipv6_addrtype == IPV6_ADDR_SITELOCAL)
616         {
617           /* Site local */
618           strncpy(ipv6_mult, ipv6_mult_site, 50);
619         }
620       else
621         {
622           /* Global */
623           strncpy(ipv6_mult, ipv6_mult_global, 50);
624         }
625
626       olsr_printf(1, "Using multicast address %s\n", ipv6_mult);
627
628       minsize = (int)sizeof(olsr_u8_t) * 7; /* Minimum packetsize IPv6 */
629     }
630   else
631     {
632       olsr_printf(1, "Using IP version 4\n");
633       ipsize = sizeof(olsr_u32_t);
634
635       minsize = (int)sizeof(olsr_u8_t) * 4; /* Minimum packetsize IPv4 */
636     }
637
638
639   /* Initializing networkinterfaces */
640
641   if(!ifinit())
642     {
643       if(allow_no_int)
644         {
645           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");
646           sleep(5);
647         }
648       else
649         {
650           fprintf(stderr, "No interfaces detected!\nBailing out!\n");
651           olsr_exit(__func__, EXIT_FAILURE);
652         }
653     }
654
655
656   gettimeofday(&now, NULL);
657
658
659   /* Initialize the IPC socket */
660
661   if(use_ipc)
662       ipc_init();
663
664 #ifndef WIN32
665   /* Initialize link-layer notifications */
666   if(llinfo)
667     init_link_layer_notification();
668 #endif
669
670   /* Initialisation of different tables to be used.*/
671   olsr_init_tables();
672
673   /* Load plugins */
674   olsr_load_plugins();
675
676   /* Set up recieving tunnel if Inet gw */
677   if(use_tunnel && inet_gw)
678     set_up_gw_tunnel(&main_addr);
679
680   olsr_printf(1, "Main address: %s\n\n", olsr_ip_to_string(&main_addr));
681
682   olsr_printf(1, "NEIGHBORS: l=linkstate, m=MPR, w=willingness\n\n");
683
684
685   /* daemon mode */
686 #ifndef WIN32
687   if (debug_level == 0)
688     {
689       printf("%s detattching from the current process...\n", SOFTWARE_VERSION);
690       if (fork() != 0)
691         {
692           olsr_exit(__func__, EXIT_SUCCESS);
693         }
694       setsid();
695     }
696 #endif
697   /* Starting scheduler */
698   start_scheduler(&thread);
699
700   /*
701    *signal-handlers
702    */
703
704   /* ctrl-C and friends */
705 #ifdef WIN32
706   SetConsoleCtrlHandler(SignalHandler, TRUE);
707 #else
708   signal(SIGINT, olsr_shutdown);  
709   signal(SIGTERM, olsr_shutdown);  
710 #endif
711
712   /* Go into listenloop */
713   listen_loop();
714
715   /* Like we're ever going to reach this ;-) */
716   return 1;
717
718 } /* main */
719
720
721
722
723
724
725 /**
726  *Function called at shutdown
727  *
728  */
729 #ifdef WIN32
730 int __stdcall
731 SignalHandler(unsigned long signal)
732 #else
733 void
734 olsr_shutdown(int signal)
735 #endif
736 {
737   struct interface *ifn;
738 #ifndef WIN32
739   if(main_thread != pthread_self())
740     {
741       pthread_exit(0);
742     }
743 #endif
744
745   olsr_printf(1, "Received signal %d - shutting down\n", signal);
746
747   olsr_delete_all_kernel_routes();
748
749   olsr_printf(1, "Closing sockets...\n");
750
751   /* front-end IPC socket */
752   if(use_ipc)
753     shutdown_ipc();
754
755   /* OLSR sockets */
756   for (ifn = ifnet; ifn; ifn = ifn->int_next) 
757     close(ifn->olsr_socket);
758
759   /* Closing plug-ins */
760   olsr_close_plugins();
761
762   /* Reset network settings */
763   restore_settings(ipversion);
764
765   /* ioctl socket */
766   close(ioctl_s);
767
768   syslog(LOG_INFO, "%s stopped", SOFTWARE_VERSION);
769
770   olsr_printf(1, "\n <<<< %s - terminating >>>>\n           http://www.olsr.org\n", SOFTWARE_VERSION);
771
772   exit(exit_value);
773 }
774
775
776
777
778
779
780 /**
781  *Sets the default values of variables at startup
782  */
783 void
784 set_default_values()
785 {
786   memset(&main_addr, 0, sizeof(union olsr_ip_addr));
787   memset(&null_addr6, 0, sizeof (union olsr_ip_addr));
788
789   allow_no_int = 1;
790
791   exit_value = EXIT_SUCCESS; 
792   /* If the application exits by signal it is concidered success,
793    * if not, exit_value is set by the function calling olsr_exit.
794    */
795
796   tos = 16;
797
798   if_names = NULL;
799
800   sending_tc = 0;
801
802   queued_ifs = 0;
803
804   mpr_coverage = MPR_COVERAGE;
805
806   maxmessagesize = MAXMESSAGESIZE;
807
808   ipv6_addrtype = IPV6_ADDR_SITELOCAL;
809
810   /* Default multicastaddresses */
811   strncpy(ipv6_mult_site, OLSR_IPV6_MCAST_SITE_LOCAL, strlen(OLSR_IPV6_MCAST_SITE_LOCAL));
812   strncpy(ipv6_mult_global, OLSR_IPV6_MCAST_GLOBAL, strlen(OLSR_IPV6_MCAST_GLOBAL));
813
814   /* EMISSION/HOLD INTERVALS */
815
816   hello_int = HELLO_INTERVAL;
817   hello_int_nw = HELLO_INTERVAL;
818   tc_int = TC_INTERVAL;
819   hna_int = 2 * TC_INTERVAL;
820   polling_int = 0.1;
821   mid_int = MID_INTERVAL;
822   will_int = 10 * HELLO_INTERVAL; /* Willingness update interval */
823
824   neighbor_timeout_mult = 3;
825   topology_timeout_mult = 3;
826   neighbor_timeout_mult_nw = 3;
827   mid_timeout_mult = 3;
828   hna_timeout_mult = 3;
829
830   topology_hold_time = TOP_HOLD_TIME;
831   neighbor_hold_time = NEIGHB_HOLD_TIME;
832   neighbor_hold_time_nw = NEIGHB_HOLD_TIME;
833   mid_hold_time = MID_HOLD_TIME;
834   hna_hold_time = 2 * (3 * TC_INTERVAL);
835   dup_hold_time = DUP_HOLD_TIME;
836
837   /* TC redundancy */
838   tc_redundancy = TC_REDUNDANCY;
839
840   /* Hysteresis */
841   use_hysteresis = 1;
842   hyst_scaling = HYST_SCALING;
843   hyst_threshold_low = HYST_THRESHOLD_LOW;
844   hyst_threshold_high = HYST_THRESHOLD_HIGH;
845
846   use_ipc = 0;
847   llinfo = 0;
848   bcast_set = 0;
849   del_gws = 0;
850   /* DEBUG ON BY DEFAULT */
851   debug_level = 1;
852
853 #ifndef WIN32
854   /* Get main thread ID */
855   main_thread = pthread_self();
856 #endif
857
858   /* local HNA set must be initialized before reading options */
859   olsr_init_local_hna_set();
860
861   /*
862    * set fixed willingness off by default
863    */
864   willingness_set = 0;
865
866   ipv6_mult[0] = 0;
867
868   /* Gateway tunneling */
869   use_tunnel = 0;
870   inet_tnl_added = 0;
871   gw_tunnel = 0;
872
873   /* Display packet content */
874   disp_pack_in = 0;
875   disp_pack_out = 0;
876
877   ipversion = AF_INET;
878 }
879
880
881
882
883 void
884 print_usage()
885 {
886
887   fprintf(stderr, "An error occured somwhere between your keyboard and your chair!\n"); 
888   fprintf(stderr, "usage: olsrd [-f <configfile>] [ -i interface1 interface2 ... ]\n");
889   fprintf(stderr, "  [-d <debug_level>] [-ipv6] [-tnl] [-multi <IPv6 multicast address>]\n"); 
890   fprintf(stderr, "  [-bcast <broadcastaddr>] [-ipc] [-dispin] [-dispout] [-delgw]\n");
891   fprintf(stderr, "  [-midint <mid interval value (secs)>] [-hnaint <hna interval value (secs)>]\n");
892   fprintf(stderr, "  [-hint <hello interval value (secs)>] [-tcint <tc interval value (secs)>]\n");
893   fprintf(stderr, "  [-hhold <HELLO validity time as a multiplier of the HELLO interval>]\n");
894   fprintf(stderr, "  [-nhhold <HELLO validity time on non-wireless interfaces>]\n");
895   fprintf(stderr, "  [-thold <TC validity time as a multiplier of the TC interval>]\n");
896   fprintf(stderr, "  [-tos value (int)] [-nhint <hello interval value (secs) for non-WLAN>]\n");
897   fprintf(stderr, "  [-T <Polling Rate (secs)>]\n"); 
898
899 }