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