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