Removed description of old neighbour table output.
[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 the olsr.org OLSR daemon.
6  *
7  * olsr.org 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  * olsr.org 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 olsr.org; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  * 
21  * 
22  * $Id: main.c,v 1.33 2004/11/10 11:57:12 tlopatic Exp $
23  *
24  */
25
26 #include <unistd.h>
27 #include <signal.h>
28 #include <sys/stat.h>
29
30 #include "defs.h"
31 #include "interfaces.h"
32 #include "local_hna_set.h"
33 #include "scheduler.h"
34 #include "parser.h"
35 #include "generate_msg.h"
36 #include "plugin_loader.h"
37 #include "socket_parser.h"
38 #include "apm.h"
39 #include "link_layer.h"
40 #include "net_os.h"
41
42 #ifdef linux
43 #include "linux/tunnel.h"
44 #endif
45
46 #ifdef WIN32
47 #define close(x) closesocket(x)
48 int __stdcall SignalHandler(unsigned long signal);
49 void ListInterfaces(void);
50 #else
51 static void
52 olsr_shutdown(int);
53 #endif
54
55 /*
56  * Local function prototypes
57  */
58
59 static void
60 print_usage(void);
61
62 static void
63 set_default_values(void);
64
65 static int
66 set_default_ifcnfs(struct olsr_if *, struct if_config_options *);
67
68 #if !defined WIN32
69 /*
70  * Local variable declarations 
71  */
72
73 static pthread_t main_thread;
74 #endif
75
76
77 /**
78  * Main entrypoint
79  */
80
81 int
82 main(int argc, char *argv[])
83 {
84   /* For address convertions */
85   struct in_addr in;
86   struct in6_addr in6;
87
88   /* The thread for the scheduler */
89   pthread_t thread;
90
91   struct if_config_options *default_ifcnf;
92
93   struct stat statbuf;
94   char conf_file_name[FILENAME_MAX];
95
96   stdout_pulse_set = OLSR_FALSE;
97   
98 #ifdef WIN32
99   WSADATA WsaData;
100   int len;
101 #endif
102
103   setbuf(stdout, NULL);
104   setbuf(stderr, NULL);
105
106   /* Initialize socket list */
107   olsr_socket_entries = NULL;
108
109 #ifndef WIN32
110   /* Check if user is root */
111   if(getuid() || getgid())
112     {
113       fprintf(stderr, "You must be root(uid = 0) to run olsrd!\nExiting\n\n");
114       exit(EXIT_FAILURE);
115     }
116 #else
117   if (WSAStartup(0x0202, &WsaData))
118     {
119       fprintf(stderr, "Could not initialize WinSock.\n");
120       olsr_exit(__func__, EXIT_FAILURE);
121     }
122 #endif
123
124   /* Open syslog */
125   olsr_openlog("olsrd");
126
127   /* Set default values */
128   set_default_values();
129
130   /* Initialize network functions */
131   init_net();
132  
133   /* Get initial timestep */
134   nowtm = NULL;
135   while (nowtm == NULL)
136     {
137       nowtm = gmtime((time_t *)&now.tv_sec);
138     }
139     
140   /* The port to use for OLSR traffic */
141   olsr_udp_port = htons(OLSRPORT);
142     
143   printf("\n *** %s ***\n Build date: %s\n http://www.olsr.org\n\n", 
144          SOFTWARE_VERSION, 
145          __DATE__);
146     
147   /* Using PID as random seed */
148   srandom(getpid());
149
150
151   /*
152    * Set configfile name and
153    * check if a configfile name was given as parameter
154    */
155 #ifdef WIN32
156   GetWindowsDirectory(conf_file_name, FILENAME_MAX - 11);
157   
158   len = strlen(conf_file_name);
159   
160   if (conf_file_name[len - 1] != '\\')
161     conf_file_name[len++] = '\\';
162   
163   strcpy(conf_file_name + len, "olsrd.conf");
164 #else
165   strncpy(conf_file_name, OLSRD_GLOBAL_CONF_FILE, FILENAME_MAX);
166 #endif
167
168   if ((argc > 1) && (strcmp(argv[1], "-f") == 0)) 
169     {
170       argv++; argc--;
171       if(argc == 1)
172         {
173           fprintf(stderr, "You must provide a filename when using the -f switch!\n");
174           exit(EXIT_FAILURE);
175         }
176
177       if (stat(argv[1], &statbuf) < 0)
178         {
179           fprintf(stderr, "Could not find specified config file %s!\n%s\n\n", argv[1], strerror(errno));
180           exit(EXIT_FAILURE);
181         }
182                  
183       strncpy(conf_file_name, argv[1], FILENAME_MAX);
184       argv++; argc--;
185
186     }
187
188   /*
189    * set up configuration prior to processing commandline options
190    */
191   if((olsr_cnf = olsrd_parse_cnf(conf_file_name)) == NULL)
192     {
193       printf("Using default config values(no configfile)\n");
194       olsr_cnf = olsrd_get_default_cnf();
195     }
196   if((default_ifcnf = get_default_if_config()) == NULL)
197     {
198       fprintf(stderr, "No default ifconfig found!\n");
199       exit(EXIT_FAILURE);
200     }
201
202   /*
203    * Process olsrd options.
204    */
205   
206   argv++; argc--;
207   while (argc > 0 && **argv == '-')
208     {
209 #ifdef WIN32
210       /*
211        *Interface list
212        */
213       if (strcmp(*argv, "-int") == 0)
214         {
215           ListInterfaces();
216           exit(0);
217         }
218 #endif
219
220       /*
221        *Configfilename
222        */
223       if(strcmp(*argv, "-f") == 0) 
224         {
225           fprintf(stderr, "Configfilename must ALWAYS be first argument!\n\n");
226           olsr_exit(__func__, EXIT_FAILURE);
227         }
228
229       /*
230        *Use IP version 6
231        */
232       if(strcmp(*argv, "-ipv6") == 0) 
233         {
234           olsr_cnf->ip_version = AF_INET6;
235           argv++; argc--;
236           continue;
237         }
238
239       /*
240        *Broadcast address
241        */
242       if(strcmp(*argv, "-bcast") == 0) 
243         {
244           argv++; argc--;
245           if(!argc)
246             {
247               fprintf(stderr, "You must provide a broadcastaddr when using the -bcast switch!\n");
248               olsr_exit(__func__, EXIT_FAILURE);
249             }
250           if (inet_aton(*argv, &in) == 0)
251             {
252               printf("Invalid broadcast address! %s\nSkipping it!\n", *argv);
253               continue;
254             }
255           memcpy(&default_ifcnf->ipv4_broadcast.v4, &in.s_addr, sizeof(olsr_u32_t));  
256           continue;
257         }
258       
259       /*
260        * Enable additional debugging information to be logged.
261        */
262       if (strcmp(*argv, "-d") == 0) 
263         {
264           argv++; argc--;
265           sscanf(*argv,"%d", &olsr_cnf->debug_level);
266           argv++; argc--;
267           continue;
268         }
269
270                 
271       /*
272        * Interfaces to be used by olsrd.
273        */
274       if (strcmp(*argv, "-i") == 0) 
275         {
276           argv++; argc--;
277           if(!argc || (*argv[0] == '-'))
278             {
279               fprintf(stderr, "You must provide an interface label!\n");
280               olsr_exit(__func__, EXIT_FAILURE);
281             }
282
283           queue_if(*argv);
284           argv++; argc--;
285
286           while((argc) && (**argv != '-'))
287             {
288               queue_if(*argv);
289               argv++; argc--;
290             }
291
292           continue;
293         }
294       /*
295        * Set the hello interval to be used by olsrd.
296        * 
297        */
298       if (strcmp(*argv, "-hint") == 0) 
299         {
300           argv++; argc--;
301           sscanf(*argv,"%f", &default_ifcnf->hello_params.emission_interval);
302           default_ifcnf->hello_params.validity_time = default_ifcnf->hello_params.emission_interval * 3;
303           argv++; argc--;
304           continue;
305         }
306
307       /*
308        * Set the HNA interval to be used by olsrd.
309        * 
310        */
311       if (strcmp(*argv, "-hnaint") == 0) 
312         {
313           argv++; argc--;
314           sscanf(*argv,"%f", &default_ifcnf->hna_params.emission_interval);
315           default_ifcnf->hna_params.validity_time = default_ifcnf->hna_params.emission_interval * 3;
316           argv++; argc--;
317           continue;
318         }
319
320       /*
321        * Set the MID interval to be used by olsrd.
322        * 
323        */
324       if (strcmp(*argv, "-midint") == 0) 
325         {
326           argv++; argc--;
327           sscanf(*argv,"%f", &default_ifcnf->mid_params.emission_interval);
328           default_ifcnf->mid_params.validity_time = default_ifcnf->mid_params.emission_interval * 3;
329           argv++; argc--;
330           continue;
331         }
332
333       /*
334        * Set the tc interval to be used by olsrd.
335        * 
336        */
337       if (strcmp(*argv, "-tcint") == 0) 
338         {
339           argv++; argc--;
340           sscanf(*argv,"%f", &default_ifcnf->tc_params.emission_interval);
341           default_ifcnf->tc_params.validity_time = default_ifcnf->tc_params.emission_interval * 3;
342           argv++; argc--;
343           continue;
344         }
345
346       /*
347        * Set the tos bits to be used by olsrd.
348        * 
349        */
350       if (strcmp(*argv, "-tos") == 0) 
351         {
352           argv++; argc--;
353           sscanf(*argv,"%d",(int *)&olsr_cnf->tos);
354           argv++; argc--;
355           continue;
356         }
357
358
359       /*
360        * Set the polling interval to be used by olsrd.
361        */
362       if (strcmp(*argv, "-T") == 0) 
363         {
364           argv++; argc--;
365           sscanf(*argv,"%f",&olsr_cnf->pollrate);
366           argv++; argc--;
367           continue;
368         }
369
370
371       /*
372        * Should we display the contents of packages beeing sent?
373        */
374       if (strcmp(*argv, "-dispin") == 0) 
375         {
376           argv++; argc--;
377           disp_pack_in = OLSR_TRUE;
378           continue;
379         }
380
381       /*
382        * Should we display the contents of incoming packages?
383        */
384       if (strcmp(*argv, "-dispout") == 0) 
385         {
386           argv++; argc--;
387           disp_pack_out = OLSR_TRUE;
388           continue;
389         }
390
391
392       /*
393        * Should we set up and send on a IPC socket for the front-end?
394        */
395       if (strcmp(*argv, "-ipc") == 0) 
396         {
397           argv++; argc--;
398           olsr_cnf->open_ipc = OLSR_TRUE;
399           continue;
400         }
401
402
403       /*
404        * Display link-layer info(experimental)
405        */
406       if (strcmp(*argv, "-llinfo") == 0) 
407         {
408           argv++; argc--;
409           llinfo = OLSR_TRUE;
410           continue;
411         }
412
413       /*
414        * Use Internet gateway tunneling?
415        */
416       if (strcmp(*argv, "-tnl") == 0) 
417         {
418           argv++; argc--;
419           use_tunnel = OLSR_TRUE;
420
421           continue;
422         }
423
424       /*
425        * IPv6 multicast addr
426        */
427       if (strcmp(*argv, "-multi") == 0) 
428         {
429           argv++; argc--;
430           if(inet_pton(AF_INET6, *argv, &in6) < 0)
431             {
432               fprintf(stderr, "Failed converting IP address %s\n", *argv);
433               exit(EXIT_FAILURE);
434             }
435
436           memcpy(&default_ifcnf->ipv6_multi_glbl, &in6, sizeof(struct in6_addr));
437
438           argv++; argc--;
439
440           continue;
441         }
442
443
444       /*
445        * Should we display the contents of packages beeing sent?
446        */
447       if (strcmp(*argv, "-delgw") == 0) 
448         {
449           argv++; argc--;
450           del_gws = OLSR_TRUE;
451           continue;
452         }
453
454
455       print_usage();
456       olsr_exit(__func__, EXIT_FAILURE);
457     }
458
459
460   /*
461    *Interfaces need to be specified
462    */
463   if(olsr_cnf->interfaces == NULL)
464     {
465       fprintf(stderr, "OLSRD: no interfaces specified!\nuse the -i switch to specify interface(s)\nor set interface(s) in the configuration file!\n");
466       print_usage();
467       olsr_exit(__func__, EXIT_FAILURE);
468     }
469
470   /*
471    * Set configuration for command-line specified interfaces
472    */
473   set_default_ifcnfs(olsr_cnf->interfaces, default_ifcnf);
474
475   /*
476    * Print configuration 
477    */
478   olsrd_print_cnf(olsr_cnf);  
479
480   /*
481    *socket for icotl calls
482    */
483   if ((ioctl_s = socket(olsr_cnf->ip_version, SOCK_DGRAM, 0)) < 0) 
484
485     {
486       olsr_syslog(OLSR_LOG_ERR, "ioctl socket: %m");
487       olsr_exit(__func__, 0);
488     }
489
490 #if defined __FreeBSD__ || defined __MacOSX__
491   if ((rts = socket(PF_ROUTE, SOCK_RAW, 0)) < 0)
492     {
493       olsr_syslog(OLSR_LOG_ERR, "routing socket: %m");
494       olsr_exit(__func__, 0);
495     }
496 #endif
497
498   /*
499    *enable ip forwarding on host
500    */
501   enable_ip_forwarding(olsr_cnf->ip_version);
502
503   /* Initialize scheduler MUST HAPPEN BEFORE REGISTERING ANY FUNCTIONS! */
504   init_scheduler(olsr_cnf->pollrate);
505
506   /* Initialize parser */
507   olsr_init_parser();
508
509   /* Initialize message sequencnumber */
510   init_msg_seqno();
511
512   /* Initialize dynamic willingness calculation */
513   olsr_init_willingness();
514
515   /* Sanity check for hysteresis values */
516   if((olsr_cnf->use_hysteresis) &&
517      (olsr_cnf->hysteresis_param.thr_high <= olsr_cnf->hysteresis_param.thr_low))
518     {
519       printf("Hysteresis threshold high lower than threshold low!!\nEdit the configuration file to fix this!\n\n");
520       olsr_exit(__func__, EXIT_FAILURE);
521     }
522
523   /*
524    *Set up willingness/APM
525    */
526   if(olsr_cnf->willingness_auto)
527     {
528       if(apm_init() < 0)
529         {
530           olsr_printf(1, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT);
531
532           olsr_syslog(OLSR_LOG_ERR, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT);
533
534           olsr_cnf->willingness_auto = 0;
535           olsr_cnf->willingness = WILL_DEFAULT;
536         }
537       else
538         {
539           olsr_cnf->willingness = olsr_calculate_willingness();
540
541           olsr_printf(1, "Willingness set to %d - next update in %.1f secs\n", olsr_cnf->willingness, will_int);
542         }
543     }
544
545   /**
546    *Set ipsize and minimum packetsize
547    */
548   if(olsr_cnf->ip_version == AF_INET6)
549     {
550       olsr_printf(1, "Using IP version 6\n");
551       ipsize = sizeof(struct in6_addr);
552
553       minsize = (int)sizeof(olsr_u8_t) * 7; /* Minimum packetsize IPv6 */
554     }
555   else
556     {
557       olsr_printf(1, "Using IP version 4\n");
558       ipsize = sizeof(olsr_u32_t);
559
560       minsize = (int)sizeof(olsr_u8_t) * 4; /* Minimum packetsize IPv4 */
561     }
562
563
564   /* Initializing networkinterfaces */
565
566   if(!ifinit())
567     {
568       if(olsr_cnf->allow_no_interfaces)
569         {
570           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");
571           sleep(5);
572         }
573       else
574         {
575           fprintf(stderr, "No interfaces detected!\nBailing out!\n");
576           olsr_exit(__func__, EXIT_FAILURE);
577         }
578     }
579
580   /* Print heartbeat to stdout */
581
582   if(olsr_cnf->debug_level > 0 && isatty(STDOUT_FILENO))
583     olsr_register_scheduler_event(&generate_stdout_pulse, NULL, STDOUT_PULSE_INT, 0, NULL);
584   
585   gettimeofday(&now, NULL);
586
587
588   /* Initialize the IPC socket */
589
590   if(olsr_cnf->open_ipc)
591       ipc_init();
592
593 #ifdef linux
594   /* Initialize link-layer notifications */
595   if(llinfo)
596     init_link_layer_notification();
597 #endif
598
599   /* Initialisation of different tables to be used.*/
600   olsr_init_tables();
601
602   /* Load plugins */
603   olsr_load_plugins();
604
605 #ifdef linux
606   /* Set up recieving tunnel if Inet gw */
607   if(use_tunnel && check_inet_gw())
608     set_up_gw_tunnel(&main_addr);
609 #endif
610
611   olsr_printf(1, "Main address: %s\n\n", olsr_ip_to_string(&main_addr));
612
613   /* daemon mode */
614 #ifndef WIN32
615   if (olsr_cnf->debug_level == 0)
616     {
617       printf("%s detattching from the current process...\n", SOFTWARE_VERSION);
618       if (fork() != 0)
619         {
620           exit(EXIT_SUCCESS);
621         }
622       setsid();
623     }
624 #endif
625   /* Starting scheduler */
626   start_scheduler(&thread);
627
628   /*
629    * Start syslog entry
630    */
631   olsr_syslog(OLSR_LOG_INFO, "%s successfully started", SOFTWARE_VERSION);
632
633   /*
634    *signal-handlers
635    */
636
637   /* ctrl-C and friends */
638 #ifdef WIN32
639   SetConsoleCtrlHandler(SignalHandler, OLSR_TRUE);
640 #else
641   signal(SIGINT, olsr_shutdown);  
642   signal(SIGTERM, olsr_shutdown);  
643 #endif
644
645   /* Go into listenloop */
646   listen_loop();
647
648   /* Like we're ever going to reach this ;-) */
649   return 1;
650
651 } /* main */
652
653
654
655
656
657
658 /**
659  *Function called at shutdown
660  *
661  */
662 #ifdef WIN32
663 int __stdcall
664 SignalHandler(unsigned long signal)
665 #else
666 static void
667 olsr_shutdown(int signal)
668 #endif
669 {
670   struct interface *ifn;
671 #ifndef WIN32
672   if(main_thread != pthread_self())
673     {
674       pthread_exit(0);
675     }
676 #endif
677
678   olsr_printf(1, "Received signal %d - shutting down\n", signal);
679
680   olsr_delete_all_kernel_routes();
681
682   olsr_printf(1, "Closing sockets...\n");
683
684   /* front-end IPC socket */
685   if(olsr_cnf->open_ipc)
686     shutdown_ipc();
687
688   /* OLSR sockets */
689   for (ifn = ifnet; ifn; ifn = ifn->int_next) 
690     close(ifn->olsr_socket);
691
692   /* Closing plug-ins */
693   olsr_close_plugins();
694
695   /* Reset network settings */
696   restore_settings(olsr_cnf->ip_version);
697
698   /* ioctl socket */
699   close(ioctl_s);
700
701 #if defined __FreeBSD__ || defined __MacOSX__
702   /* routing socket */
703   close(rts);
704 #endif
705
706   olsr_syslog(OLSR_LOG_INFO, "%s stopped", SOFTWARE_VERSION);
707
708   olsr_printf(1, "\n <<<< %s - terminating >>>>\n           http://www.olsr.org\n", SOFTWARE_VERSION);
709
710   exit(exit_value);
711 }
712
713
714
715
716
717 /**
718  *Sets the default values of variables at startup
719  */
720 static void
721 set_default_values()
722 {
723   memset(&main_addr, 0, sizeof(union olsr_ip_addr));
724   memset(&null_addr6, 0, sizeof (union olsr_ip_addr));
725
726   exit_value = EXIT_SUCCESS; 
727   /* If the application exits by signal it is concidered success,
728    * if not, exit_value is set by the function calling olsr_exit.
729    */
730
731   max_jitter = 0;
732   max_tc_vtime = 0;
733   dup_hold_time = DUP_HOLD_TIME;
734
735   will_int = 10 * HELLO_INTERVAL; /* Willingness update interval */
736
737
738 #ifndef WIN32
739   /* Get main thread ID */
740   main_thread = pthread_self();
741 #endif
742
743   /* Gateway tunneling */
744   use_tunnel = OLSR_FALSE;
745   inet_tnl_added = OLSR_FALSE;
746   gw_tunnel = OLSR_FALSE;
747
748   llinfo = OLSR_FALSE;
749   del_gws = OLSR_FALSE;
750
751   /* Display packet content */
752   disp_pack_in = OLSR_FALSE;
753   disp_pack_out = OLSR_FALSE;
754 }
755
756
757
758
759 static void
760 print_usage()
761 {
762
763   fprintf(stderr, "An error occured somwhere between your keyboard and your chair!\n"); 
764   fprintf(stderr, "usage: olsrd [-f <configfile>] [ -i interface1 interface2 ... ]\n");
765   fprintf(stderr, "  [-d <debug_level>] [-ipv6] [-tnl] [-multi <IPv6 multicast address>]\n"); 
766   fprintf(stderr, "  [-bcast <broadcastaddr>] [-ipc] [-dispin] [-dispout] [-delgw]\n");
767   fprintf(stderr, "  [-hint <hello interval value (secs)>] [-tcint <tc interval value (secs)>]\n");
768   fprintf(stderr, "  [-midint <mid interval value (secs)>] [-hnaint <hna interval value (secs)>]\n");
769   fprintf(stderr, "  [-tos value (int)] [-T <Polling Rate (secs)>]\n"); 
770
771 }
772
773
774 /**
775  * Sets the provided configuration on all unconfigured
776  * interfaces
777  */
778 int
779 set_default_ifcnfs(struct olsr_if *ifs, struct if_config_options *cnf)
780 {
781   int changes = 0;
782
783   while(ifs)
784     {
785       if(ifs->cnf == NULL)
786         {
787           ifs->cnf = olsr_malloc(sizeof(struct if_config_options), "Set default config");
788           *ifs->cnf = *cnf;
789           changes++;
790         }
791       ifs = ifs->next;
792     }
793   return changes;
794 }