static struct olsr_if *AddInterface(struct olsrd_config **Conf, CString Name) { struct olsr_if *Int; Int = (struct olsr_if *)win32_olsrd_malloc(sizeof (struct olsr_if)); if (Int == NULL) { AfxMessageBox("Cannot allocate memory."); return NULL; } Int->name = (char *)win32_olsrd_malloc(Name.GetLength() + 1); if (Int->name == NULL) { win32_olsrd_free(Int); AfxMessageBox("Cannot allocate memory."); return NULL; } ::lstrcpy(Int->name, Name); Int->config = NULL; Int->configured = false; Int->interf = NULL; Int->cnf = get_default_if_config(); Int->next = (*Conf)->interfaces; (*Conf)->interfaces = Int; return Int; }
int olsrd_sanity_check_cnf(struct olsrd_config *cnf) { struct olsr_if *in = cnf->interfaces; struct if_config_options *io; /* Debug level */ if (cnf->debug_level < MIN_DEBUGLVL || cnf->debug_level > MAX_DEBUGLVL) { fprintf(stderr, "Debuglevel %d is not allowed\n", cnf->debug_level); return -1; } /* IP version */ if (cnf->ip_version != AF_INET && cnf->ip_version != AF_INET6) { fprintf(stderr, "Ipversion %d not allowed!\n", cnf->ip_version); return -1; } /* TOS */ if (cnf->tos > MAX_TOS) { fprintf(stderr, "TOS %d is not allowed\n", cnf->tos); return -1; } if (cnf->willingness_auto == false && (cnf->willingness > MAX_WILLINGNESS)) { fprintf(stderr, "Willingness %d is not allowed\n", cnf->willingness); return -1; } /* Hysteresis */ if (cnf->use_hysteresis == true) { if (cnf->hysteresis_param.scaling < MIN_HYST_PARAM || cnf->hysteresis_param.scaling > MAX_HYST_PARAM) { fprintf(stderr, "Hyst scaling %0.2f is not allowed\n", cnf->hysteresis_param.scaling); return -1; } if (cnf->hysteresis_param.thr_high <= cnf->hysteresis_param.thr_low) { fprintf(stderr, "Hyst upper(%0.2f) thr must be bigger than lower(%0.2f) threshold!\n", cnf->hysteresis_param.thr_high, cnf->hysteresis_param.thr_low); return -1; } if (cnf->hysteresis_param.thr_high < MIN_HYST_PARAM || cnf->hysteresis_param.thr_high > MAX_HYST_PARAM) { fprintf(stderr, "Hyst upper thr %0.2f is not allowed\n", cnf->hysteresis_param.thr_high); return -1; } if (cnf->hysteresis_param.thr_low < MIN_HYST_PARAM || cnf->hysteresis_param.thr_low > MAX_HYST_PARAM) { fprintf(stderr, "Hyst lower thr %0.2f is not allowed\n", cnf->hysteresis_param.thr_low); return -1; } } /* Pollrate */ if (cnf->pollrate < MIN_POLLRATE || cnf->pollrate > MAX_POLLRATE) { fprintf(stderr, "Pollrate %0.2f is not allowed\n", cnf->pollrate); return -1; } /* NIC Changes Pollrate */ if (cnf->nic_chgs_pollrate < MIN_NICCHGPOLLRT || cnf->nic_chgs_pollrate > MAX_NICCHGPOLLRT) { fprintf(stderr, "NIC Changes Pollrate %0.2f is not allowed\n", cnf->nic_chgs_pollrate); return -1; } /* TC redundancy */ if (cnf->tc_redundancy != 2) { fprintf(stderr, "Sorry, tc-redundancy 0/1 are not working on 0.5.6. " "It was discovered late in the stable tree development and cannot " "be solved without a difficult change in the dijkstra code. " "Feel free to contact the olsr-user mailinglist " "(http://www.olsr.org/?q=mailing-lists) to learn more " "about the problem. The next version of OLSR will have working " "tc-redundancy again.\n"); return -1; } /* MPR coverage */ if (cnf->mpr_coverage < MIN_MPR_COVERAGE || cnf->mpr_coverage > MAX_MPR_COVERAGE) { fprintf(stderr, "MPR coverage %d is not allowed\n", cnf->mpr_coverage); return -1; } /* Link Q and hysteresis cannot be activated at the same time */ if (cnf->use_hysteresis == true && cnf->lq_level) { fprintf(stderr, "Hysteresis and LinkQuality cannot both be active! Deactivate one of them.\n"); return -1; } /* Link quality level */ if (cnf->lq_level != 0 && cnf->lq_level != 2) { fprintf(stderr, "LQ level %d is not allowed\n", cnf->lq_level); return -1; } /* Link quality window size */ if (cnf->lq_level && (cnf->lq_aging < MIN_LQ_AGING || cnf->lq_aging > MAX_LQ_AGING)) { fprintf(stderr, "LQ aging factor %f is not allowed\n", cnf->lq_aging); return -1; } /* NAT threshold value */ if (cnf->lq_level && (cnf->lq_nat_thresh < 0.1 || cnf->lq_nat_thresh > 1.0)) { fprintf(stderr, "NAT threshold %f is not allowed\n", cnf->lq_nat_thresh); return -1; } #if defined linux #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) if (cnf->ip_version == AF_INET6 && cnf->smart_gw_active) { fprintf(stderr, "Smart gateways are not supported for linux kernel 2.4 and ipv6\n"); return -1; } #endif /* this rtpolicy settings are also currently only used in Linux */ if (olsrd_sanity_check_rtpolicy(cnf)) { return -1; } #endif if (in == NULL) { fprintf(stderr, "No interfaces configured!\n"); return -1; } if (cnf->min_tc_vtime < 0.0) { fprintf(stderr, "Error, negative minimal tc time not allowed.\n"); return -1; } if (cnf->min_tc_vtime > 0.0) { fprintf(stderr, "Warning, you are using the min_tc_vtime hack. We hope you know what you are doing... contact olsr.org otherwise.\n"); } if (cnf->smart_gw_type >= GW_UPLINK_CNT) { fprintf(stderr, "Error, illegal gateway uplink type: %d\n", cnf->smart_gw_type); return -1; } if (cnf->smart_gw_downlink < MIN_SMARTGW_SPEED || cnf->smart_gw_downlink > MAX_SMARTGW_SPEED) { fprintf(stderr, "Error, bad gateway downlink speed: %d kbit/s (should be %d-%d)\n", cnf->smart_gw_downlink, MIN_SMARTGW_SPEED, MAX_SMARTGW_SPEED); return -1; } if (cnf->smart_gw_uplink < MIN_SMARTGW_SPEED || cnf->smart_gw_uplink > MAX_SMARTGW_SPEED) { fprintf(stderr, "Error, bad gateway uplink speed: %d kbit/s (should be %d-%d)\n", cnf->smart_gw_uplink, MIN_SMARTGW_SPEED, MAX_SMARTGW_SPEED); return -1; } if (cnf->interface_defaults == NULL) { /* get a default configuration if the user did not specify one */ cnf->interface_defaults = get_default_if_config(); } else { olsrd_print_interface_cnf(cnf->interface_defaults, cnf->interface_defaults, false); olsrd_sanity_check_interface_cnf(cnf->interface_defaults, cnf, interface_defaults_name); } /* Interfaces */ while (in) { struct olsr_lq_mult *mult, *mult_orig; io = in->cnf; olsrd_print_interface_cnf(in->cnf, in->cnfi, false); /*apply defaults*/ { size_t pos; struct olsr_lq_mult *mult_temp, *mult_orig_walk; uint8_t *cnfptr = (uint8_t*)in->cnf; uint8_t *cnfiptr = (uint8_t*)in->cnfi; uint8_t *defptr = (uint8_t*)cnf->interface_defaults; /*save interface specific lqmults, as they are merged togehter later*/ mult_orig = io->lq_mult; assert(in->cnf); assert(in->cnfi); for (pos = 0; pos < sizeof(*in->cnf); pos++) { if (cnfptr[pos] != cnfiptr[pos]) { cnfptr[pos] = defptr[pos]; cnfiptr[pos]=0x00; } else cnfiptr[pos]=0xFF; } io->lq_mult=NULL; /*copy default lqmults into this interface*/ for (mult = cnf->interface_defaults->lq_mult; mult; mult=mult->next) { /*search same lqmult in orig_list*/ for (mult_orig_walk = mult_orig; mult_orig_walk; mult_orig_walk=mult_orig_walk->next) { if (ipequal(&mult_orig_walk->addr,&mult->addr)) { break; } } if (mult_orig_walk == NULL) { mult_temp=malloc(sizeof(struct olsr_lq_mult)); memcpy(mult_temp,mult,sizeof(struct olsr_lq_mult)); mult_temp->next=io->lq_mult; io->lq_mult=mult_temp; } } } if (in->name == NULL || !strlen(in->name)) { fprintf(stderr, "Interface has no name!\n"); return -1; } if (io == NULL) { fprintf(stderr, "Interface %s has no configuration!\n", in->name); return -1; } /*merge lqmults*/ if (mult_orig!=NULL) { io->orig_lq_mult_cnt=1; /*search last of interface specific lqmults*/ mult = mult_orig; while (mult->next!=NULL) { mult=mult->next; } /*append default lqmults ath the end of the interface specific (to ensure they can overwrite them)*/ mult->next=io->lq_mult; io->lq_mult=mult_orig; } if (olsrd_sanity_check_interface_cnf(io, cnf, in->name)) return -1; in = in->next; } return 0; }
int main(int argc, char *argv[]) { struct if_config_options *default_ifcnf; char conf_file_name[FILENAME_MAX]; struct ipaddr_str buf; bool loadedConfig = false; int i; #ifdef LINUX_NETLINK_ROUTING struct interface *ifn; #endif #ifdef WIN32 WSADATA WsaData; size_t len; #endif /* paranoia checks */ assert(sizeof(uint8_t) == 1); assert(sizeof(uint16_t) == 2); assert(sizeof(uint32_t) == 4); assert(sizeof(int8_t) == 1); assert(sizeof(int16_t) == 2); assert(sizeof(int32_t) == 4); printf("\n *** %s ***\n Build date: %s on %s\n http://www.olsr.org\n\n", olsrd_version, build_date, build_host); if (argc == 2) { if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "/?") == 0) { print_usage(false); exit(0); } if (strcmp(argv[1], "-v") == 0) { exit(0); } } debug_handle = stdout; #ifndef WIN32 olsr_argv = argv; #endif setbuf(stdout, NULL); setbuf(stderr, NULL); #ifndef WIN32 /* Check if user is root */ if (geteuid()) { fprintf(stderr, "You must be root(uid = 0) to run olsrd!\nExiting\n\n"); exit(EXIT_FAILURE); } #else DisableIcmpRedirects(); if (WSAStartup(0x0202, &WsaData)) { fprintf(stderr, "Could not initialize WinSock.\n"); olsr_exit(__func__, EXIT_FAILURE); } #endif /* Open syslog */ olsr_openlog("olsrd"); /* Using PID as random seed */ srandom(getpid()); /* Init widely used statics */ memset(&all_zero, 0, sizeof(union olsr_ip_addr)); /* * Set configfile name and * check if a configfile name was given as parameter */ #ifdef WIN32 #ifndef WINCE GetWindowsDirectory(conf_file_name, FILENAME_MAX - 11); #else conf_file_name[0] = 0; #endif len = strlen(conf_file_name); if (len == 0 || conf_file_name[len - 1] != '\\') conf_file_name[len++] = '\\'; strscpy(conf_file_name + len, "olsrd.conf", sizeof(conf_file_name) - len); #else strscpy(conf_file_name, OLSRD_GLOBAL_CONF_FILE, sizeof(conf_file_name)); #endif olsr_cnf = olsrd_get_default_cnf(); for (i=1; i < argc-1;) { if (strcmp(argv[i], "-f") == 0) { loadedConfig = true; if (olsrmain_load_config(argv[i+1]) < 0) { exit(EXIT_FAILURE); } if (i+2 < argc) { memmove(&argv[i], &argv[i+2], sizeof(*argv) * (argc-i-1)); } argc -= 2; } else { i++; } } /* * set up configuration prior to processing commandline options */ if (!loadedConfig && olsrmain_load_config(conf_file_name) == 0) { loadedConfig = true; } if (!loadedConfig) { olsrd_free_cnf(olsr_cnf); olsr_cnf = olsrd_get_default_cnf(); } default_ifcnf = get_default_if_config(); if (default_ifcnf == NULL) { fprintf(stderr, "No default ifconfig found!\n"); exit(EXIT_FAILURE); } /* Initialize timers */ olsr_init_timers(); /* * Process olsrd options. */ if (olsr_process_arguments(argc, argv, olsr_cnf, default_ifcnf) < 0) { print_usage(true); olsr_exit(__func__, EXIT_FAILURE); } /* * Set configuration for command-line specified interfaces */ set_default_ifcnfs(olsr_cnf->interfaces, default_ifcnf); /* free the default ifcnf */ free(default_ifcnf); /* Sanity check configuration */ if (olsrd_sanity_check_cnf(olsr_cnf) < 0) { fprintf(stderr, "Bad configuration!\n"); olsr_exit(__func__, EXIT_FAILURE); } /* * Establish file lock to prevent multiple instances */ if (olsr_cnf->lock_file) { strscpy(lock_file_name, olsr_cnf->lock_file, sizeof(lock_file_name)); } else { size_t l; #ifdef DEFAULT_LOCKFILE_PREFIX strscpy(lock_file_name, DEFAULT_LOCKFILE_PREFIX, sizeof(lock_file_name)); #else strscpy(lock_file_name, conf_file_name, sizeof(lock_file_name)); #endif l = strlen(lock_file_name); snprintf(&lock_file_name[l], sizeof(lock_file_name) - l, "-ipv%d.lock", olsr_cnf->ip_version == AF_INET ? 4 : 6); } /* * Print configuration */ if (olsr_cnf->debug_level > 1) { olsrd_print_cnf(olsr_cnf); } def_timer_ci = olsr_alloc_cookie("Default Timer Cookie", OLSR_COOKIE_TYPE_TIMER); /* * socket for ioctl calls */ olsr_cnf->ioctl_s = socket(olsr_cnf->ip_version, SOCK_DGRAM, 0); if (olsr_cnf->ioctl_s < 0) { #ifndef WIN32 olsr_syslog(OLSR_LOG_ERR, "ioctl socket: %m"); #endif olsr_exit(__func__, 0); } #ifdef LINUX_NETLINK_ROUTING olsr_cnf->rtnl_s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); if (olsr_cnf->rtnl_s < 0) { olsr_syslog(OLSR_LOG_ERR, "rtnetlink socket: %m"); olsr_exit(__func__, 0); } fcntl(olsr_cnf->rtnl_s, F_SETFL, O_NONBLOCK); if ((olsr_cnf->rt_monitor_socket = rtnetlink_register_socket(RTMGRP_LINK)) < 0) { olsr_syslog(OLSR_LOG_ERR, "rtmonitor socket: %m"); olsr_exit(__func__, 0); } #endif /* * create routing socket */ #if defined __FreeBSD__ || __FreeBSD_kernel__ || defined __MacOSX__ || defined __NetBSD__ || defined __OpenBSD__ olsr_cnf->rts = socket(PF_ROUTE, SOCK_RAW, 0); if (olsr_cnf->rts < 0) { olsr_syslog(OLSR_LOG_ERR, "routing socket: %m"); olsr_exit(__func__, 0); } #endif #ifdef LINUX_NETLINK_ROUTING /* initialize gateway system */ if (olsr_cnf->smart_gw_active) { if (olsr_init_gateways()) { olsr_exit("Cannot initialize gateway tunnels", 1); } } /* initialize niit if index */ if (olsr_cnf->use_niit) { olsr_init_niit(); } #endif /* Init empty TC timer */ set_empty_tc_timer(GET_TIMESTAMP(0)); /* enable ip forwarding on host */ /* Disable redirects globally */ #ifndef WIN32 net_os_set_global_ifoptions(); #endif /* Initialize parser */ olsr_init_parser(); /* Initialize route-exporter */ olsr_init_export_route(); /* Initialize message sequencnumber */ init_msg_seqno(); /* Initialize dynamic willingness calculation */ olsr_init_willingness(); /* *Set up willingness/APM */ if (olsr_cnf->willingness_auto) { if (apm_init() < 0) { OLSR_PRINTF(1, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT); olsr_syslog(OLSR_LOG_ERR, "Could not read APM info - setting default willingness(%d)\n", WILL_DEFAULT); olsr_cnf->willingness_auto = 0; olsr_cnf->willingness = WILL_DEFAULT; } else { olsr_cnf->willingness = olsr_calculate_willingness(); OLSR_PRINTF(1, "Willingness set to %d - next update in %.1f secs\n", olsr_cnf->willingness, olsr_cnf->will_int); } } /* Initialize net */ init_net(); /* Initializing networkinterfaces */ if (!olsr_init_interfacedb()) { if (olsr_cnf->allow_no_interfaces) { 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"); olsr_startup_sleep(5); } else { fprintf(stderr, "No interfaces detected!\nBailing out!\n"); olsr_exit(__func__, EXIT_FAILURE); } } olsr_do_startup_sleep(); /* Print heartbeat to stdout */ #if !defined WINCE if (olsr_cnf->debug_level > 0 && isatty(STDOUT_FILENO)) { olsr_start_timer(STDOUT_PULSE_INT, 0, OLSR_TIMER_PERIODIC, &generate_stdout_pulse, NULL, 0); } #endif /* Initialize the IPC socket */ if (olsr_cnf->ipc_connections > 0) { ipc_init(); } /* Initialisation of different tables to be used. */ olsr_init_tables(); /* daemon mode */ #ifndef WIN32 if (olsr_cnf->debug_level == 0 && !olsr_cnf->no_fork) { printf("%s detaching from the current process...\n", olsrd_version); if (daemon(0, 0) < 0) { printf("daemon(3) failed: %s\n", strerror(errno)); exit(EXIT_FAILURE); } } #endif /* * Create locking file for olsrd, will be cleared after olsrd exits */ for (i=5; i>=0; i--) { OLSR_PRINTF(3, "Trying to get olsrd lock...\n"); if (olsr_create_lock_file(i > 0) == 0) { /* lock sucessfully created */ break; } sleep (1); } /* Load plugins */ olsr_load_plugins(); OLSR_PRINTF(1, "Main address: %s\n\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr)); #ifdef LINUX_NETLINK_ROUTING /* create policy routing priorities if necessary */ if (DEF_RT_NONE != olsr_cnf->rt_table_pri) { olsr_os_policy_rule(olsr_cnf->ip_version, olsr_cnf->rt_table, olsr_cnf->rt_table_pri, NULL, true); } if (DEF_RT_NONE != olsr_cnf->rt_table_tunnel_pri) { olsr_os_policy_rule(olsr_cnf->ip_version, olsr_cnf->rt_table_tunnel, olsr_cnf->rt_table_tunnel_pri, NULL, true); } if (DEF_RT_NONE != olsr_cnf->rt_table_default_pri) { olsr_os_policy_rule(olsr_cnf->ip_version, olsr_cnf->rt_table_default, olsr_cnf->rt_table_default_pri, NULL, true); } /* OLSR sockets */ if (DEF_RT_NONE != olsr_cnf->rt_table_defaultolsr_pri) { for (ifn = ifnet; ifn; ifn = ifn->int_next) { olsr_os_policy_rule(olsr_cnf->ip_version, olsr_cnf->rt_table_default, olsr_cnf->rt_table_defaultolsr_pri, ifn->int_name, true); } } /* trigger gateway selection */ if (olsr_cnf->smart_gw_active) { olsr_trigger_inetgw_startup(); } /* trigger niit static route setup */ if (olsr_cnf->use_niit) { olsr_setup_niit_routes(); } /* create lo:olsr interface */ if (olsr_cnf->use_src_ip_routes) { olsr_os_localhost_if(&olsr_cnf->main_addr, true); } #endif /* Start syslog entry */ olsr_syslog(OLSR_LOG_INFO, "%s successfully started", olsrd_version); /* *signal-handlers */ /* ctrl-C and friends */ #ifdef WIN32 #ifndef WINCE SetConsoleCtrlHandler(SignalHandler, true); #endif #else signal(SIGHUP, olsr_reconfigure); signal(SIGINT, olsr_shutdown); signal(SIGQUIT, olsr_shutdown); signal(SIGILL, olsr_shutdown); signal(SIGABRT, olsr_shutdown); // signal(SIGSEGV, olsr_shutdown); signal(SIGTERM, olsr_shutdown); signal(SIGPIPE, SIG_IGN); // Ignoring SIGUSR1 and SIGUSR1 by default to be able to use them in plugins signal(SIGUSR1, SIG_IGN); signal(SIGUSR2, SIG_IGN); #endif link_changes = false; /* Starting scheduler */ olsr_scheduler(); /* Like we're ever going to reach this ;-) */ return 1; } /* main */
/** * Process command line arguments passed to olsrd * */ static int olsr_process_arguments(int argc, char *argv[], struct olsrd_config *cnf, struct if_config_options *ifcnf) { while (argc > 1) { NEXT_ARG; #ifdef WIN32 /* *Interface list */ if (strcmp(*argv, "-int") == 0) { ListInterfaces(); exit(0); } #endif /* *Configfilename */ if (strcmp(*argv, "-f") == 0) { fprintf(stderr, "Configfilename must ALWAYS be first argument!\n\n"); olsr_exit(__func__, EXIT_FAILURE); } /* *Use IP version 6 */ if (strcmp(*argv, "-ipv6") == 0) { cnf->ip_version = AF_INET6; continue; } /* *Broadcast address */ if (strcmp(*argv, "-bcast") == 0) { struct in_addr in; NEXT_ARG; CHECK_ARGC; if (inet_aton(*argv, &in) == 0) { printf("Invalid broadcast address! %s\nSkipping it!\n", *argv); continue; } memcpy(&ifcnf->ipv4_multicast.v4, &in.s_addr, sizeof(ifcnf->ipv4_multicast.v4)); continue; } /* * Set LQ level */ if (strcmp(*argv, "-lql") == 0) { int tmp_lq_level; NEXT_ARG; CHECK_ARGC; /* Sanity checking is done later */ sscanf(*argv, "%d", &tmp_lq_level); olsr_cnf->lq_level = tmp_lq_level; continue; } /* * Set LQ winsize */ if (strcmp(*argv, "-lqa") == 0) { float tmp_lq_aging; NEXT_ARG; CHECK_ARGC; sscanf(*argv, "%f", &tmp_lq_aging); if (tmp_lq_aging < MIN_LQ_AGING || tmp_lq_aging > MAX_LQ_AGING) { printf("LQ aging factor %f not allowed. Range [%f-%f]\n", tmp_lq_aging, MIN_LQ_AGING, MAX_LQ_AGING); olsr_exit(__func__, EXIT_FAILURE); } olsr_cnf->lq_aging = tmp_lq_aging; continue; } /* * Set NAT threshold */ if (strcmp(*argv, "-lqnt") == 0) { float tmp_lq_nat_thresh; NEXT_ARG; CHECK_ARGC; sscanf(*argv, "%f", &tmp_lq_nat_thresh); if (tmp_lq_nat_thresh < 0.1 || tmp_lq_nat_thresh > 1.0) { printf("NAT threshold %f not allowed. Range [%f-%f]\n", tmp_lq_nat_thresh, 0.1, 1.0); olsr_exit(__func__, EXIT_FAILURE); } olsr_cnf->lq_nat_thresh = tmp_lq_nat_thresh; continue; } /* * Enable additional debugging information to be logged. */ if (strcmp(*argv, "-d") == 0) { NEXT_ARG; CHECK_ARGC; sscanf(*argv, "%d", &cnf->debug_level); continue; } /* * Interfaces to be used by olsrd. */ if (strcmp(*argv, "-i") == 0) { NEXT_ARG; CHECK_ARGC; if (*argv[0] == '-') { fprintf(stderr, "You must provide an interface label!\n"); olsr_exit(__func__, EXIT_FAILURE); } printf("Queuing if %s\n", *argv); olsr_create_olsrif(*argv, false); while ((argc - 1) && (argv[1][0] != '-')) { NEXT_ARG; printf("Queuing if %s\n", *argv); olsr_create_olsrif(*argv, false); } continue; } /* * Set the hello interval to be used by olsrd. * */ if (strcmp(*argv, "-hint") == 0) { NEXT_ARG; CHECK_ARGC; sscanf(*argv, "%f", &ifcnf->hello_params.emission_interval); ifcnf->hello_params.validity_time = ifcnf->hello_params.emission_interval * 3; continue; } /* * Set the HNA interval to be used by olsrd. * */ if (strcmp(*argv, "-hnaint") == 0) { NEXT_ARG; CHECK_ARGC; sscanf(*argv, "%f", &ifcnf->hna_params.emission_interval); ifcnf->hna_params.validity_time = ifcnf->hna_params.emission_interval * 3; continue; } /* * Set the MID interval to be used by olsrd. * */ if (strcmp(*argv, "-midint") == 0) { NEXT_ARG; CHECK_ARGC; sscanf(*argv, "%f", &ifcnf->mid_params.emission_interval); ifcnf->mid_params.validity_time = ifcnf->mid_params.emission_interval * 3; continue; } /* * Set the tc interval to be used by olsrd. * */ if (strcmp(*argv, "-tcint") == 0) { NEXT_ARG; CHECK_ARGC; sscanf(*argv, "%f", &ifcnf->tc_params.emission_interval); ifcnf->tc_params.validity_time = ifcnf->tc_params.emission_interval * 3; continue; } /* * Set the polling interval to be used by olsrd. */ if (strcmp(*argv, "-T") == 0) { NEXT_ARG; CHECK_ARGC; sscanf(*argv, "%f", &cnf->pollrate); continue; } /* * Should we display the contents of packages beeing sent? */ if (strcmp(*argv, "-dispin") == 0) { parser_set_disp_pack_in(true); continue; } /* * Should we display the contents of incoming packages? */ if (strcmp(*argv, "-dispout") == 0) { net_set_disp_pack_out(true); continue; } /* * Should we set up and send on a IPC socket for the front-end? */ if (strcmp(*argv, "-ipc") == 0) { cnf->ipc_connections = 1; continue; } /* * IPv6 multicast addr */ if (strcmp(*argv, "-multi") == 0) { struct in6_addr in6; NEXT_ARG; CHECK_ARGC; if (inet_pton(AF_INET6, *argv, &in6) <= 0) { fprintf(stderr, "Failed converting IP address %s\n", *argv); exit(EXIT_FAILURE); } memcpy(&ifcnf->ipv6_multicast, &in6, sizeof(struct in6_addr)); continue; } /* * Host emulation */ if (strcmp(*argv, "-hemu") == 0) { struct in_addr in; struct olsr_if *ifa; NEXT_ARG; CHECK_ARGC; if (inet_pton(AF_INET, *argv, &in) <= 0) { fprintf(stderr, "Failed converting IP address %s\n", *argv); exit(EXIT_FAILURE); } /* Add hemu interface */ ifa = olsr_create_olsrif("hcif01", true); if (!ifa) continue; ifa->cnf = get_default_if_config(); ifa->host_emul = true; memcpy(&ifa->hemu_ip, &in, sizeof(union olsr_ip_addr)); cnf->host_emul = true; continue; } /* * Delete possible default GWs */ if (strcmp(*argv, "-delgw") == 0) { olsr_cnf->del_gws = true; continue; } if (strcmp(*argv, "-nofork") == 0) { cnf->no_fork = true; continue; } return -1; } return 0; }
int olsrd_sanity_check_cnf(struct olsrd_config *cnf) { struct olsr_if *in = cnf->interfaces; struct if_config_options *io; /* Debug level */ if (cnf->debug_level < MIN_DEBUGLVL || cnf->debug_level > MAX_DEBUGLVL) { fprintf(stderr, "Debuglevel %d is not allowed\n", cnf->debug_level); return -1; } /* IP version */ if (cnf->ip_version != AF_INET && cnf->ip_version != AF_INET6) { fprintf(stderr, "Ipversion %d not allowed!\n", cnf->ip_version); return -1; } /* TOS range */ if (cnf->tos > MAX_TOS) { fprintf(stderr, "TOS %d is not allowed\n", cnf->tos); return -1; } /* TOS ECN */ if (cnf->tos & 0x03) { fprintf(stderr, "TOS %d has set ECN bits, not allowed\n", cnf->tos); return -1; } if (cnf->willingness_auto == false && (cnf->willingness > MAX_WILLINGNESS)) { fprintf(stderr, "Willingness %d is not allowed\n", cnf->willingness); return -1; } /* Hysteresis */ if (cnf->use_hysteresis == true) { if (cnf->hysteresis_param.scaling < (float)MIN_HYST_PARAM || cnf->hysteresis_param.scaling > (float)MAX_HYST_PARAM) { fprintf(stderr, "Hyst scaling %0.2f is not allowed\n", (double)cnf->hysteresis_param.scaling); return -1; } if (cnf->hysteresis_param.thr_high <= cnf->hysteresis_param.thr_low) { fprintf(stderr, "Hyst upper(%0.2f) thr must be bigger than lower(%0.2f) threshold!\n", (double)cnf->hysteresis_param.thr_high, (double)cnf->hysteresis_param.thr_low); return -1; } if (cnf->hysteresis_param.thr_high < (float)MIN_HYST_PARAM || cnf->hysteresis_param.thr_high > (float)MAX_HYST_PARAM) { fprintf(stderr, "Hyst upper thr %0.2f is not allowed\n", (double)cnf->hysteresis_param.thr_high); return -1; } if (cnf->hysteresis_param.thr_low < (float)MIN_HYST_PARAM || cnf->hysteresis_param.thr_low > (float)MAX_HYST_PARAM) { fprintf(stderr, "Hyst lower thr %0.2f is not allowed\n", (double)cnf->hysteresis_param.thr_low); return -1; } } /* Pollrate */ if (cnf->pollrate < (float)MIN_POLLRATE || cnf->pollrate > (float)MAX_POLLRATE) { fprintf(stderr, "Pollrate %0.2f is not allowed\n", (double)cnf->pollrate); return -1; } /* NIC Changes Pollrate */ if (cnf->nic_chgs_pollrate < (float)MIN_NICCHGPOLLRT || cnf->nic_chgs_pollrate > (float)MAX_NICCHGPOLLRT) { fprintf(stderr, "NIC Changes Pollrate %0.2f is not allowed\n", (double)cnf->nic_chgs_pollrate); return -1; } /* TC redundancy */ if (cnf->tc_redundancy != 2) { fprintf(stderr, "Sorry, tc-redundancy 0/1 are not working on 0.5.6. " "It was discovered late in the stable tree development and cannot " "be solved without a difficult change in the dijkstra code. " "Feel free to contact the olsr-user mailinglist " "(http://www.olsr.org/?q=mailing-lists) to learn more " "about the problem. The next version of OLSR will have working " "tc-redundancy again.\n"); return -1; } /* MPR coverage */ if (cnf->mpr_coverage < MIN_MPR_COVERAGE || cnf->mpr_coverage > MAX_MPR_COVERAGE) { fprintf(stderr, "MPR coverage %d is not allowed\n", cnf->mpr_coverage); return -1; } /* Link Q and hysteresis cannot be activated at the same time */ if (cnf->use_hysteresis == true && cnf->lq_level) { fprintf(stderr, "Hysteresis and LinkQuality cannot both be active! Deactivate one of them.\n"); return -1; } /* Link quality level */ if (cnf->lq_level != 0 && cnf->lq_level != 2) { fprintf(stderr, "LQ level %d is not allowed\n", cnf->lq_level); return -1; } /* Link quality window size */ if (cnf->lq_level && (cnf->lq_aging < (float)MIN_LQ_AGING || cnf->lq_aging > (float)MAX_LQ_AGING)) { fprintf(stderr, "LQ aging factor %f is not allowed\n", (double)cnf->lq_aging); return -1; } /* NAT threshold value */ if (cnf->lq_level && (cnf->lq_nat_thresh < 0.1f || cnf->lq_nat_thresh > 1.0f)) { fprintf(stderr, "NAT threshold %f is not allowed\n", (double)cnf->lq_nat_thresh); return -1; } #ifdef __linux__ #if !defined LINUX_VERSION_CODE || !defined KERNEL_VERSION #error "Both LINUX_VERSION_CODE and KERNEL_VERSION need to be defined" #else /* !defined LINUX_VERSION_CODE || !defined KERNEL_VERSION */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) if (cnf->ip_version == AF_INET6 && cnf->smart_gw_active) { fprintf(stderr, "Smart gateways are not supported for linux kernel < 2.6.24 and ipv6\n"); return -1; } #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) */ #endif /* !defined LINUX_VERSION_CODE || !defined KERNEL_VERSION */ /* this rtpolicy settings are also currently only used in Linux */ if (olsrd_sanity_check_rtpolicy(cnf)) { return -1; } #endif /* __linux__ */ if (in == NULL) { fprintf(stderr, "No interfaces configured!\n"); return -1; } if (cnf->min_tc_vtime < 0.0f) { fprintf(stderr, "Error, negative minimal tc time not allowed.\n"); return -1; } if (cnf->min_tc_vtime > 0.0f) { fprintf(stderr, "Warning, you are using the min_tc_vtime hack. We hope you know what you are doing... contact olsr.org otherwise.\n"); } #ifdef __linux__ if ((cnf->smart_gw_use_count < MIN_SMARTGW_USE_COUNT_MIN) || (cnf->smart_gw_use_count > MAX_SMARTGW_USE_COUNT_MAX)) { fprintf(stderr, "Error, bad gateway use count %d, outside of range [%d, %d]\n", cnf->smart_gw_use_count, MIN_SMARTGW_USE_COUNT_MIN, MAX_SMARTGW_USE_COUNT_MAX); return -1; } if (cnf->smart_gw_use_count > 1) { struct sgw_egress_if * sgwegressif = cnf->smart_gw_egress_interfaces; if (!cnf->smart_gw_policyrouting_script) { fprintf(stderr, "Error, no policy routing script configured in multi-gateway mode\n"); return -1; } { struct stat statbuf; int r = stat(cnf->smart_gw_policyrouting_script, &statbuf); if (r) { fprintf(stderr, "Error, policy routing script not found: %s\n", strerror(errno)); return -1; } if (!S_ISREG(statbuf.st_mode)) { fprintf(stderr, "Error, policy routing script not a regular file\n"); return -1; } if (statbuf.st_uid) { fprintf(stderr, "Error, policy routing script must be owned by root\n"); return -1; } if (!(statbuf.st_mode & (S_IRUSR | S_IXUSR))) { fprintf(stderr, "Error, policy routing script is not executable\n"); return -1; } } /* egress interface(s) must be set */ if (!sgwegressif) { fprintf(stderr, "Error, no egress interfaces configured in multi-gateway mode\n"); return -1; } /* an egress interface must not be an OLSR interface */ while (sgwegressif) { struct olsr_if * olsrif = cnf->interfaces; while (olsrif) { if (!strcmp(olsrif->name, sgwegressif->name)) { fprintf(stderr, "Error, egress interface %s already is an OLSR interface\n", sgwegressif->name); return -1; } olsrif = olsrif->next; } cnf->smart_gw_egress_interfaces_count++; sgwegressif = sgwegressif->next; } if (cnf->smart_gw_egress_interfaces_count > MAX_SMARTGW_EGRESS_INTERFACE_COUNT_MAX) { fprintf(stderr, "Error, egress interface count %u not in range [1, %u]\n", cnf->smart_gw_egress_interfaces_count, MAX_SMARTGW_EGRESS_INTERFACE_COUNT_MAX); return -1; } { uint8_t egressLow = cnf->smart_gw_mark_offset_egress; uint8_t egressHigh = egressLow + cnf->smart_gw_egress_interfaces_count - 1; uint8_t tunnelsLow = cnf->smart_gw_mark_offset_tunnels; uint8_t tunnelsHigh = tunnelsLow + cnf->smart_gw_use_count - 1; bool overlap = false; /* check that the egress interface marks range does not overflow */ if (egressLow > (UINT8_MAX - cnf->smart_gw_egress_interfaces_count)) { fprintf(stderr, "Error, egress interface mark offset %u together with egress interface count %u overflows range [0, %u]\n", egressLow, cnf->smart_gw_egress_interfaces_count, UINT8_MAX); return -1; } /* check that the tunnel interface marks range does not overflow */ if (tunnelsLow > (UINT8_MAX - cnf->smart_gw_use_count)) { fprintf(stderr, "Error, tunnel interface mark offset %u together with use count %u overflows range [0, %u]\n", tunnelsLow, cnf->smart_gw_use_count, UINT8_MAX); return -1; } /* check that the egress and tunnel marks ranges do not overlap */ overlap = ((tunnelsLow <= egressLow) && (egressLow <= tunnelsHigh)); overlap = overlap || ((tunnelsLow <= egressHigh) && (egressHigh <= tunnelsHigh)); overlap = overlap || ((egressLow <= tunnelsLow) && (tunnelsLow <= egressHigh)); overlap = overlap || ((egressLow <= tunnelsHigh) && (tunnelsHigh <= egressHigh)); if (overlap) { fprintf(stderr, "Error, egress interface mark range [%u, %u] overlaps with tunnel interface mark range [%u, %u]\n", egressLow, egressHigh, tunnelsLow, tunnelsHigh); return -1; } } } if (cnf->smart_gw_period < MIN_SMARTGW_PERIOD || cnf->smart_gw_period > MAX_SMARTGW_PERIOD) { fprintf(stderr, "Error, bad gateway period: %d msec (should be %d-%d)\n", cnf->smart_gw_period, MIN_SMARTGW_PERIOD, MAX_SMARTGW_PERIOD); return -1; } if (cnf->smart_gw_stablecount < MIN_SMARTGW_STABLE || cnf->smart_gw_stablecount > MAX_SMARTGW_STABLE) { fprintf(stderr, "Error, bad gateway stable count: %d (should be %d-%d)\n", cnf->smart_gw_stablecount, MIN_SMARTGW_STABLE, MAX_SMARTGW_STABLE); return -1; } if (((cnf->smart_gw_thresh < MIN_SMARTGW_THRES) || (cnf->smart_gw_thresh > MAX_SMARTGW_THRES)) && (cnf->smart_gw_thresh != 0)) { fprintf(stderr, "Smart gateway threshold %d is not allowed (should be %d-%d)\n", cnf->smart_gw_thresh, MIN_SMARTGW_THRES, MAX_SMARTGW_THRES); return -1; } /* no checks are needed on: * - cnf->smart_gw_weight_exitlink_up * - cnf->smart_gw_weight_exitlink_down * - cnf->smart_gw_weight_etx * - cnf->smart_gw_divider_etx */ if (cnf->smart_gw_type >= GW_UPLINK_CNT) { fprintf(stderr, "Error, illegal gateway uplink type: %d\n", cnf->smart_gw_type); return -1; } if (cnf->smart_gw_downlink < MIN_SMARTGW_SPEED || cnf->smart_gw_downlink > MAX_SMARTGW_SPEED) { fprintf(stderr, "Error, bad gateway downlink speed: %d kbit/s (should be %d-%d)\n", cnf->smart_gw_downlink, MIN_SMARTGW_SPEED, MAX_SMARTGW_SPEED); return -1; } if (cnf->smart_gw_uplink < MIN_SMARTGW_SPEED || cnf->smart_gw_uplink > MAX_SMARTGW_SPEED) { fprintf(stderr, "Error, bad gateway uplink speed: %d kbit/s (should be %d-%d)\n", cnf->smart_gw_uplink, MIN_SMARTGW_SPEED, MAX_SMARTGW_SPEED); return -1; } #endif /* __linux__ */ if (cnf->interface_defaults == NULL) { /* get a default configuration if the user did not specify one */ cnf->interface_defaults = get_default_if_config(); } else { olsrd_print_interface_cnf(cnf->interface_defaults, cnf->interface_defaults, false); olsrd_sanity_check_interface_cnf(cnf->interface_defaults, cnf, interface_defaults_name); } /* Interfaces */ while (in) { struct olsr_lq_mult *mult, *mult_orig; assert(in->cnf); assert(in->cnfi); io = in->cnf; olsrd_print_interface_cnf(in->cnf, in->cnfi, false); /*apply defaults*/ { size_t pos; struct olsr_lq_mult *mult_temp, *mult_orig_walk; uint8_t *cnfptr = (uint8_t*)in->cnf; uint8_t *cnfiptr = (uint8_t*)in->cnfi; uint8_t *defptr = (uint8_t*)cnf->interface_defaults; /*save interface specific lqmults, as they are merged togehter later*/ mult_orig = io->lq_mult; for (pos = 0; pos < sizeof(*in->cnf); pos++) { if (cnfptr[pos] != cnfiptr[pos]) { cnfptr[pos] = defptr[pos]; cnfiptr[pos]=0x00; } else cnfiptr[pos]=0xFF; } io->lq_mult=NULL; /*copy default lqmults into this interface*/ for (mult = cnf->interface_defaults->lq_mult; mult; mult=mult->next) { /*search same lqmult in orig_list*/ for (mult_orig_walk = mult_orig; mult_orig_walk; mult_orig_walk=mult_orig_walk->next) { if (ipequal(&mult_orig_walk->addr,&mult->addr)) { break; } } if (mult_orig_walk == NULL) { mult_temp=malloc(sizeof(struct olsr_lq_mult)); memcpy(mult_temp,mult,sizeof(struct olsr_lq_mult)); mult_temp->next=io->lq_mult; io->lq_mult=mult_temp; } } } if (in->name == NULL || !strlen(in->name)) { fprintf(stderr, "Interface has no name!\n"); return -1; } if (io == NULL) { fprintf(stderr, "Interface %s has no configuration!\n", in->name); return -1; } /*merge lqmults*/ if (mult_orig!=NULL) { io->orig_lq_mult_cnt=1; /*search last of interface specific lqmults*/ mult = mult_orig; while (mult->next!=NULL) { mult=mult->next; } /*append default lqmults ath the end of the interface specific (to ensure they can overwrite them)*/ mult->next=io->lq_mult; io->lq_mult=mult_orig; } if (olsrd_sanity_check_interface_cnf(io, cnf, in->name)) return -1; in = in->next; } return 0; }