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