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