int olsr_if_set_state(const char *dev, bool up) { int oldflags; struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strscpy(ifr.ifr_name, dev, IFNAMSIZ); if (ioctl(olsr_cnf->ioctl_s, SIOCGIFFLAGS, &ifr) < 0) { OLSR_PRINTF(1, "ioctl SIOCGIFFLAGS (get flags) error on device %s: %s (%d)\n", dev, strerror(errno), errno); return 1; } oldflags = ifr.ifr_flags; if (up) { ifr.ifr_flags |= IFF_UP; } else { ifr.ifr_flags &= ~IFF_UP; } if (oldflags == ifr.ifr_flags) { /* interface is already up/down */ return 0; } if (ioctl(olsr_cnf->ioctl_s, SIOCSIFFLAGS, &ifr) < 0) { OLSR_PRINTF(1, "ioctl SIOCSIFFLAGS (set flags %s) error on device %s: %s (%d)\n", up ? "up" : "down", dev, strerror(errno), errno); return 1; } return 0; }
bool is_if_link_up(char *ifname) { if (check_wireless_interface(ifname)) { /* No link checking on wireless devices */ return true; } else { /* Mii wizardry */ struct ifreq ifr; struct mii_data *mii = (struct mii_data *)&ifr.ifr_data; int bmsr; memset(&ifr, 0, sizeof(ifr)); strscpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); if (ioctl(olsr_cnf->ioctl_s, SIOCGMIIPHY, &ifr) < 0) { if (errno != ENODEV) OLSR_PRINTF(1, "SIOCGMIIPHY on '%s' failed: %s\n", ifr.ifr_name, strerror(errno)); return WEIGHT_ETHERNET_DEFAULT; } mii->reg_num = MII_BMSR; if (ioctl(olsr_cnf->ioctl_s, SIOCGMIIREG, &ifr) < 0) { OLSR_PRINTF(1, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name, strerror(errno)); return WEIGHT_ETHERNET_DEFAULT; } bmsr = mii->val_out; OLSR_PRINTF(1, "%s: ", ifr.ifr_name); OLSR_PRINTF(1, "%s\n", (bmsr & MII_BMSR_LINK_VALID) ? "link ok " : "no link "); return (bmsr & MII_BMSR_LINK_VALID); } }
/** * Print the routingtree to STDOUT * */ void olsr_print_routing_table(struct avl_tree *tree) { #ifndef NODEBUG /* The whole function makes no sense without it. */ struct avl_node *rt_tree_node; struct lqtextbuffer lqbuffer; OLSR_PRINTF(6, "ROUTING TABLE\n"); for (rt_tree_node = avl_walk_first(tree); rt_tree_node != NULL; rt_tree_node = avl_walk_next(rt_tree_node)) { struct avl_node *rtp_tree_node; struct ipaddr_str prefixstr, origstr, gwstr; struct rt_entry *rt = rt_tree2rt(rt_tree_node); /* first the route entry */ OLSR_PRINTF(6, "%s/%u, via %s, best-originator %s\n", olsr_ip_to_string(&prefixstr, &rt->rt_dst.prefix), rt->rt_dst.prefix_len, olsr_ip_to_string(&origstr, &rt->rt_nexthop.gateway), olsr_ip_to_string(&gwstr, &rt->rt_best->rtp_originator)); /* walk the per-originator path tree of routes */ for (rtp_tree_node = avl_walk_first(&rt->rt_path_tree); rtp_tree_node != NULL; rtp_tree_node = avl_walk_next(rtp_tree_node)) { struct rt_path *rtp = rtp_tree2rtp(rtp_tree_node); OLSR_PRINTF(6, "\tfrom %s, cost %s, metric %u, via %s, %s, v %u\n", olsr_ip_to_string(&origstr, &rtp->rtp_originator), get_linkcost_text(rtp->rtp_metric.cost, true, &lqbuffer), rtp->rtp_metric.hops, olsr_ip_to_string(&gwstr, &rtp-> rtp_nexthop. gateway), if_ifwithindex_name(rt->rt_nexthop.iif_index), rtp->rtp_version); } } #endif /* NODEBUG */ tree = NULL; /* squelch compiler warnings */ }
/** * Adds all nodes with willingness set to WILL_ALWAYS */ static uint16_t add_will_always_nodes(void) { struct neighbor_entry *a_neighbor; uint16_t count = 0; #if 0 printf("\nAdding WILL ALWAYS nodes....\n"); #endif OLSR_FOR_ALL_NBR_ENTRIES(a_neighbor) { struct ipaddr_str buf; if ((a_neighbor->status == NOT_SYM) || (a_neighbor->willingness != WILL_ALWAYS)) { continue; } olsr_chosen_mpr(a_neighbor, &count); OLSR_PRINTF(3, "Adding WILL_ALWAYS: %s\n", olsr_ip_to_string(&buf, &a_neighbor->neighbor_main_addr)); } OLSR_FOR_ALL_NBR_ENTRIES_END(a_neighbor); #if 0 OLSR_PRINTF(1, "Count: %d\n", count); #endif return count; }
static bool is_at_least_linuxkernel_2_6_31(void) { struct utsname uts; char *next; int first = 0, second = 0, third = 0; memset(&uts, 0, sizeof(uts)); if (uname(&uts)) { OLSR_PRINTF(1, "Error, could not read kernel version: %s (%d)\n", strerror(errno), errno); return false; } first = strtol(uts.release, &next, 10); /* check for linux 3.x */ if (first >= 3) { return true; } if (*next != '.') { goto kernel_parse_error; } second = strtol(next+1, &next, 10); if (*next != '.') { goto kernel_parse_error; } third = strtol(next+1, NULL, 10); /* better or equal than linux 2.6.31 ? */ return first == 2 && second == 6 && third >= 31; kernel_parse_error: OLSR_PRINTF(1, "Error, cannot parse kernel version: %s\n", uts.release); return false; }
/** * Setup global interface options (icmp redirect, ip forwarding, rp_filter) * @return 1 on success 0 on failure */ void net_os_set_global_ifoptions(void) { if (writeToProc(olsr_cnf->ip_version == AF_INET ? PROC_IPFORWARD_V4 : PROC_IPFORWARD_V6, &orig_fwd_state, olsr_cnf->set_ip_forward ? OLSRD_FORWARD_VALUE : 0 )) { OLSR_PRINTF(1, "Warning, could not enable IP forwarding!\n" "you should manually ensure that IP forwarding is enabled!\n\n"); olsr_startup_sleep(3); } else if ((!olsr_cnf->set_ip_forward) && (orig_fwd_state != OLSRD_FORWARD_VALUE)) { olsr_exit("IP forwarding not activated, shutting down.\n", 1); } if (olsr_cnf->smart_gw_active) { char procfile[FILENAME_MAX]; /* Generate the procfile name */ if (olsr_cnf->ip_version == AF_INET || olsr_cnf->use_niit) { snprintf(procfile, sizeof(procfile), PROC_IF_SPOOF, TUNNEL_ENDPOINT_IF); if (writeToProc(procfile, &orig_tunnel_rp_filter, OLSRD_SPOOF_VALUE)) { OLSR_PRINTF(0, "WARNING! Could not disable the IP spoof filter for tunnel!\n" "you should manually ensure that IP spoof filtering is disabled!\n\n"); olsr_startup_sleep(3); } } #if 0 // should not be necessary for IPv6 if (olsr_cnf->ip_version == AF_INET6) { snprintf(procfile, sizeof(procfile), PROC_IF_SPOOF, TUNNEL_ENDPOINT_IF6); if (writeToProc(procfile, &orig_tunnel6_rp_filter, OLSRD_SPOOF_VALUE)) { OLSR_PRINTF(0, "WARNING! Could not disable the IP spoof filter for tunnel6!\n" "you should manually ensure that IP spoof filtering is disabled!\n\n"); olsr_startup_sleep(3); } } #endif } if (olsr_cnf->ip_version == AF_INET) { if (writeToProc(PROC_ALL_REDIRECT, &orig_global_redirect_state, OLSRD_REDIRECT_VALUE)) { OLSR_PRINTF(1, "WARNING! Could not disable ICMP redirects!\n" "you should manually ensure that ICMP redirects are disabled!\n\n"); olsr_startup_sleep(3); } /* check kernel version and disable global rp_filter */ if (is_at_least_linuxkernel_2_6_31()) { if (writeToProc(PROC_ALL_SPOOF, &orig_global_rp_filter, OLSRD_SPOOF_VALUE)) { OLSR_PRINTF(1, "WARNING! Could not disable global rp_filter (necessary for kernel 2.6.31 and higher!\n" "you should manually ensure that rp_filter is disabled!\n\n"); olsr_startup_sleep(3); } } } return; }
/** * *@return 1 on sucess 0 on failiure */ int net_os_set_ifoptions(const char *if_name, struct interface *iface) { char procfile[FILENAME_MAX]; if (olsr_cnf->ip_version == AF_INET6) return -1; /* Generate the procfile name */ snprintf(procfile, sizeof(procfile), PROC_IF_REDIRECT, if_name); if (writeToProc(procfile, &iface->nic_state.redirect, OLSRD_REDIRECT_VALUE)) { OLSR_PRINTF(0, "WARNING! Could not disable ICMP redirects!\n" "you should manually ensure that ICMP redirects are disabled!\n\n"); olsr_startup_sleep(3); return 0; } /* Generate the procfile name */ snprintf(procfile, sizeof(procfile), PROC_IF_SPOOF, if_name); if (writeToProc(procfile, &iface->nic_state.spoof, OLSRD_SPOOF_VALUE)) { OLSR_PRINTF(0, "WARNING! Could not disable the IP spoof filter!\n" "you should manually ensure that IP spoof filtering is disabled!\n\n"); olsr_startup_sleep(3); return 0; } return 1; }
olsr_u8_t netmask_to_prefix(const olsr_u8_t *adr, int len) { struct ipaddr_str buf; const olsr_u8_t * const a_end = adr+len; olsr_u16_t prefix = 0; const olsr_u8_t *a; for (a = adr; a < a_end && *a == 0xff; a++) { prefix += 8; } if (a < a_end) { /* handle the last byte */ switch (*a) { case 0: prefix += 0; break; case 128: prefix += 1; break; case 192: prefix += 2; break; case 224: prefix += 3; break; case 240: prefix += 4; break; case 248: prefix += 5; break; case 252: prefix += 6; break; case 254: prefix += 7; break; case 255: prefix += 8; break; /* Shouldn't happen */ default: OLSR_PRINTF(0, "%s: Got bogus netmask %s\n", __func__, olsr_ip_to_string(&buf, (const union olsr_ip_addr *)adr)); prefix = UCHAR_MAX; *(int *)0 = 0; break; } } #ifdef DEBUG OLSR_PRINTF(3, "Netmask: %s = Prefix %d\n", olsr_ip_to_string(&buf, (const union olsr_ip_addr *)adr), prefix); #endif return prefix; }
/** *Prints the registered neighbors and two hop neighbors *to STDOUT. * *@return nada */ void olsr_print_neighbor_table(void) { #ifdef NODEBUG /* The whole function doesn't do anything else. */ #ifndef NODEBUG const int iplen = olsr_cnf->ip_version == AF_INET ? 15 : 39; #endif int idx; OLSR_PRINTF(1, "\n--- %02d:%02d:%02d.%02d ------------------------------------------------ NEIGHBORS\n\n" "%*s LQ NLQ SYM MPR MPRS will\n", nowtm->tm_hour, nowtm->tm_min, nowtm->tm_sec, (int)now.tv_usec / 10000, iplen, "IP address"); for (idx = 0; idx < HASHSIZE; idx++) { struct neighbor_entry *neigh; for (neigh = neighbortable[idx].next; neigh != &neighbortable[idx]; neigh = neigh->next) { struct link_entry *lnk = get_best_link_to_neighbor(&neigh->neighbor_main_addr); if (lnk) { struct ipaddr_str buf; OLSR_PRINTF(1, "%-*s %5.3f %5.3f %s %s %s %d\n", iplen, olsr_ip_to_string(&buf, &neigh->neighbor_main_addr), lnk->loss_link_quality, lnk->neigh_link_quality, neigh->status == SYM ? "YES " : "NO ", neigh->is_mpr ? "YES " : "NO ", olsr_lookup_mprs_set(&neigh->neighbor_main_addr) == NULL ? "NO " : "YES ", neigh->willingness); } } } #endif }
void olsr_init_niit(void) { if (olsr_cnf->ip_version == AF_INET) { olsr_cnf->use_niit = false; return; } olsr_cnf->niit4to6_if_index = if_nametoindex(DEF_NIIT4TO6_IFNAME); if (olsr_cnf->niit4to6_if_index <= 0) { OLSR_PRINTF(1, "Warning, %s device is not available, deactivating NIIT\n", DEF_NIIT4TO6_IFNAME); olsr_cnf->use_niit = false; return; } olsr_cnf->niit6to4_if_index = if_nametoindex(DEF_NIIT6TO4_IFNAME); if (olsr_cnf->niit6to4_if_index <= 0) { OLSR_PRINTF(1, "Warning, %s device is not available, deactivating NIIT\n", DEF_NIIT6TO4_IFNAME); olsr_cnf->use_niit = false; return; } niit4to6_active = olsr_if_isup(DEF_NIIT4TO6_IFNAME); niit6to4_active = olsr_if_isup(DEF_NIIT6TO4_IFNAME); olsr_add_ifchange_handler(&handle_niit_ifchange); olsr_add_ifchange_handler(&handle_niit_ifchange); return; }
void olsr_print_neighbor_table(void) { /* The whole function doesn't do anything else. */ const int iplen = olsr_cnf->ip_version == AF_INET ? (INET_ADDRSTRLEN - 1) : (INET6_ADDRSTRLEN - 1); int idx; OLSR_PRINTF(1, "\n--- %s ------------------------------------------------ NEIGHBORS\n\n" "%*s\tHyst\tLQ\tETX\tSYM MPR MPRS will\n", olsr_wallclock_string(), iplen, "IP address"); for (idx = 0; idx < HASHSIZE; idx++) { struct neighbor_entry *neigh; for (neigh = neighbortable[idx].next; neigh != &neighbortable[idx]; neigh = neigh->next) { struct link_entry *lnk = get_best_link_to_neighbor(&neigh->neighbor_main_addr); if (lnk) { struct ipaddr_str buf; struct lqtextbuffer lqbuffer1, lqbuffer2; OLSR_PRINTF(1, "%-*s\t%5.3f\t%s\t%s\t%s %s %s %d\n", iplen, olsr_ip_to_string(&buf, &neigh->neighbor_main_addr), (double)lnk->L_link_quality, get_link_entry_text(lnk, '/', &lqbuffer1), get_linkcost_text(lnk->linkcost,false, &lqbuffer2), neigh->status == SYM ? "YES " : "NO ", neigh->is_mpr ? "YES " : "NO ", olsr_lookup_mprs_set(&neigh->neighbor_main_addr) == NULL ? "NO " : "YES ", neigh->willingness); } } } }
void ipc_accept(int fd) { socklen_t addrlen; struct sockaddr_in pin; char *addr; addrlen = sizeof (struct sockaddr_in); if ((ipc_conn = accept(fd, (struct sockaddr *) &pin, &addrlen)) == -1) { perror("IPC accept"); olsr_exit("IPC accept", EXIT_FAILURE); } else { OLSR_PRINTF(1, "Front end connected\n"); addr = inet_ntoa(pin.sin_addr); if(ipc_check_allowed_ip((union olsr_ip_addr *)&pin.sin_addr.s_addr)) { ipc_active = OLSR_TRUE; ipc_send_net_info(ipc_conn); ipc_send_all_routes(ipc_conn); OLSR_PRINTF(1, "Connection from %s\n",addr); } else { OLSR_PRINTF(1, "Front end-connection from foregin host(%s) not allowed!\n", addr); olsr_syslog(OLSR_LOG_ERR, "OLSR: Front end-connection from foregin host(%s) not allowed!\n", addr); CLOSE(ipc_conn); } } }
static int delete_all_inet_gws(void) { int s; char buf[BUFSIZ], *cp, *cplim; struct ifconf ifc; struct ifreq *ifr; OLSR_PRINTF(1, "Internet gateway detected...\nTrying to delete default gateways\n"); /* Get a socket */ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { olsr_syslog(OLSR_LOG_ERR, "socket: %m"); return -1; } ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { olsr_syslog(OLSR_LOG_ERR, "ioctl (get interface configuration)"); close(s); return -1; } ifr = ifc.ifc_req; cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */ for (cp = buf; cp < cplim; cp += sizeof(ifr->ifr_name) + sizeof(ifr->ifr_addr)) { struct rtentry kernel_route; ifr = (struct ifreq *)cp; if (strcmp(ifr->ifr_ifrn.ifrn_name, "lo") == 0) { OLSR_PRINTF(1, "Skipping loopback...\n"); continue; } OLSR_PRINTF(1, "Trying 0.0.0.0/0 %s...", ifr->ifr_ifrn.ifrn_name); memset(&kernel_route, 0, sizeof(struct rtentry)); ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = 0; ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_family = AF_INET; ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = 0; ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_family = AF_INET; ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_addr.s_addr = INADDR_ANY; ((struct sockaddr_in *)&kernel_route.rt_gateway)->sin_family = AF_INET; kernel_route.rt_flags = RTF_UP | RTF_GATEWAY; kernel_route.rt_dev = ifr->ifr_ifrn.ifrn_name; if ((ioctl(s, SIOCDELRT, &kernel_route)) < 0) OLSR_PRINTF(1, "NO\n"); else OLSR_PRINTF(1, "YES\n"); } close(s); return 0; }
int olsr_process_hysteresis(struct link_entry *entry) { //printf("PROCESSING QUALITY: %f\n", entry->L_link_quality); if (entry->L_link_quality > hhigh) { if (entry->L_link_pending == 1) { struct ipaddr_str buf; OLSR_PRINTF(1, "HYST[%s] link set to NOT pending!\n", olsr_ip_to_string(&buf, &entry->neighbor_iface_addr)); changes_neighborhood = true; } /* Pending = false */ entry->L_link_pending = 0; if (!TIMED_OUT(entry->L_LOST_LINK_time)) changes_neighborhood = true; /* time = now -1 */ entry->L_LOST_LINK_time = now_times - 1; return 1; } if (entry->L_link_quality < hlow) { if (entry->L_link_pending == 0) { struct ipaddr_str buf; OLSR_PRINTF(1, "HYST[%s] link set to pending!\n", olsr_ip_to_string(&buf, &entry->neighbor_iface_addr)); changes_neighborhood = true; } /* Pending = true */ entry->L_link_pending = 1; if (TIMED_OUT(entry->L_LOST_LINK_time)) changes_neighborhood = true; /* Timer = min (L_time, current time + NEIGHB_HOLD_TIME) */ entry->L_LOST_LINK_time = MIN(GET_TIMESTAMP(NEIGHB_HOLD_TIME * MSEC_PER_SEC), entry->link_timer->timer_clock); /* (the link is then considered as lost according to section 8.5 and this may produce a neighbor loss). WTF? */ return -1; } /* *If we get here then: *(HYST_THRESHOLD_LOW <= entry->L_link_quality <= HYST_THRESHOLD_HIGH) */ /* L_link_pending and L_LOST_LINK_time remain unchanged. */ return 0; }
/** *Create the socket to use for IPC to the *GUI front-end * *@return the socket FD */ int ipc_init(void) { //int flags; struct sockaddr_in sin; int yes = 1; /* Add parser function */ olsr_parser_add_function(&frontend_msgparser, PROMISCUOUS, 0); /* get an internet domain socket */ if ((ipc_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("IPC socket"); olsr_exit("IPC socket", EXIT_FAILURE); } if(setsockopt(ipc_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) { perror("SO_REUSEADDR failed"); return 0; } /* complete the socket structure */ memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = htons(IPC_PORT); /* bind the socket to the port number */ if(bind(ipc_sock, (struct sockaddr *) &sin, sizeof(sin)) == -1) { perror("IPC bind"); OLSR_PRINTF(1, "Will retry in 10 seconds...\n"); sleep(10); if(bind(ipc_sock, (struct sockaddr *) &sin, sizeof(sin)) == -1) { perror("IPC bind"); olsr_exit("IPC bind", EXIT_FAILURE); } OLSR_PRINTF(1, "OK\n"); } /* show that we are willing to listen */ if(listen(ipc_sock, olsr_cnf->ipc_connections) == -1) { perror("IPC listen"); olsr_exit("IPC listen", EXIT_FAILURE); } /* Register the socket with the socket parser */ add_olsr_socket(ipc_sock, &ipc_accept); return ipc_sock; }
/** *Print the current MPR selector set to STDOUT */ void olsr_print_mprs_set(void) { struct mpr_selector *mprs; OLSR_PRINTF(1, "MPR SELECTORS: "); for (mprs = mprs_list.next; mprs != &mprs_list; mprs = mprs->next) { struct ipaddr_str buf; OLSR_PRINTF(1, "%s ", olsr_ip_to_string(&buf, &mprs->MS_main_addr)); } OLSR_PRINTF(1, "\n"); }
static int set_nameservice_float(const char *value, void *data, set_plugin_parameter_addon addon __attribute__((unused))) { if (data != NULL) { sscanf(value, "%f", (float*)data); OLSR_PRINTF(1, "%s float %f\n", "Got", *(float*)data); } else { OLSR_PRINTF(0, "%s float %s\n", "Ignored", value); } return 0; }
/** * Setup global interface options (icmp redirect, ip forwarding, rp_filter) * @return 1 on success 0 on failure */ void net_os_set_global_ifoptions(void) { if (writeToProc(olsr_cnf->ip_version == AF_INET ? PROC_IPFORWARD_V4 : PROC_IPFORWARD_V6, &orig_fwd_state, '1')) { OLSR_PRINTF(1, "Warning, could not enable IP forwarding!\n" "you should manually ensure that IP forwarding is enabled!\n\n"); olsr_startup_sleep(3); } if (olsr_cnf->smart_gw_active) { char procfile[FILENAME_MAX]; /* Generate the procfile name */ snprintf(procfile, sizeof(procfile), PROC_IF_SPOOF, TUNNEL_ENDPOINT_IF); if (writeToProc(procfile, &orig_tunnel_rp_filter, '0')) { OLSR_PRINTF(0, "WARNING! Could not disable the IP spoof filter for tunnel!\n" "you should mannually ensure that IP spoof filtering is disabled!\n\n"); olsr_startup_sleep(3); } if (olsr_cnf->ip_version == AF_INET6) { snprintf(procfile, sizeof(procfile), PROC_IF_SPOOF, TUNNEL_ENDPOINT_IF6); if (writeToProc(procfile, &orig_tunnel6_rp_filter, '0')) { OLSR_PRINTF(0, "WARNING! Could not disable the IP spoof filter for tunnel6!\n" "you should mannually ensure that IP spoof filtering is disabled!\n\n"); olsr_startup_sleep(3); } } } if (olsr_cnf->ip_version == AF_INET) { if (writeToProc(PROC_ALL_REDIRECT, &orig_global_redirect_state, '0')) { OLSR_PRINTF(1, "WARNING! Could not disable ICMP redirects!\n" "you should manually ensure that ICMP redirects are disabled!\n\n"); olsr_startup_sleep(3); } /* check kernel version and disable global rp_filter */ if (is_at_least_linuxkernel_2_6_31()) { if (writeToProc(PROC_ALL_SPOOF, &orig_global_rp_filter, '0')) { OLSR_PRINTF(1, "WARNING! Could not disable global rp_filter (necessary for kernel 2.6.31 and higher!\n" "you should manually ensure that rp_filter is disabled!\n\n"); olsr_startup_sleep(3); } } } return; }
/** *Resets the spoof filter and ICMP redirect settings */ int net_os_restore_ifoptions(void) { struct interface *ifs; char procfile[FILENAME_MAX]; OLSR_PRINTF(1, "Restoring network state\n"); /* Restore IP forwarding to "off" */ if (writeToProc(olsr_cnf->ip_version == AF_INET ? PROC_IPFORWARD_V4 : PROC_IPFORWARD_V6, NULL, orig_fwd_state)) { OLSR_PRINTF(1, "Error, could not restore ip_forward settings\n"); } if (olsr_cnf->smart_gw_active) { /* Generate the procfile name */ snprintf(procfile, sizeof(procfile), PROC_IF_SPOOF, TUNNEL_ENDPOINT_IF); if (writeToProc(procfile, NULL, orig_tunnel_rp_filter)) { OLSR_PRINTF(0, "WARNING! Could not restore the IP spoof filter for tunnel!\n"); } if (olsr_cnf->ip_version == AF_INET6) { snprintf(procfile, sizeof(procfile), PROC_IF_SPOOF, TUNNEL_ENDPOINT_IF6); if (writeToProc(procfile, NULL, orig_tunnel6_rp_filter)) { OLSR_PRINTF(0, "WARNING! Could not restore the IP spoof filter for tunnel6!\n"); } } } if (olsr_cnf->ip_version == AF_INET) { /* Restore global ICMP redirect setting */ if (writeToProc(PROC_ALL_REDIRECT, NULL, orig_global_redirect_state)) { OLSR_PRINTF(1, "Error, could not restore global icmp_redirect setting\n"); } /* Restore global rp_filter setting for linux 2.6.31+ */ if (is_at_least_linuxkernel_2_6_31()) { if (writeToProc(PROC_ALL_SPOOF, NULL, orig_global_rp_filter)) { OLSR_PRINTF(1, "Error, could not restore global rp_filter setting\n"); } } for (ifs = ifnet; ifs != NULL; ifs = ifs->int_next) { /* Discard host-emulation interfaces */ if (ifs->is_hcif) continue; /* ICMP redirects */ snprintf(procfile, sizeof(procfile), PROC_IF_REDIRECT, ifs->int_name); if (writeToProc(procfile, NULL, ifs->nic_state.redirect)) { OLSR_PRINTF(1, "Error, could not restore icmp_redirect for interface %s\n", ifs->int_name); } /* Spoof filter */ sprintf(procfile, PROC_IF_SPOOF, ifs->int_name); if (writeToProc(procfile, NULL, ifs->nic_state.spoof)) { OLSR_PRINTF(1, "Error, could not restore rp_filter for interface %s\n", ifs->int_name); } } } return 1; }
/** * Activate a LQ handler * @param name */ static void activate_lq_handler(const char *name) { struct lq_handler_node *node; node = (struct lq_handler_node *)avl_find(&lq_handler_tree, name); if (node == NULL) { OLSR_PRINTF(1, "Error, unknown lq_handler '%s'\n", name); olsr_exit("", 1); } OLSR_PRINTF(1, "Using '%s' algorithm for lq calculation.\n", name); active_lq_handler = node->handler; active_lq_handler->initialize(); }
static int set_nameservice_name(const char *value, void *data, set_plugin_parameter_addon addon) { struct name_entry **v = data; if (0 < strlen(value)) { *v = add_name_to_list(*v, value, addon.ui, NULL); OLSR_PRINTF(1, "%s got %s (main address)\n", "Got", value); return 0; } else { OLSR_PRINTF(0, "Illegal name \"%s\"", value); } return 1; }
/** * Process a route from the kernel addition list. * *@return nada */ static void olsr_add_kernel_route(struct rt_entry *rt) { if (rt->rt_best->rtp_metric.hops > 1) { /* multihop route */ if (ip_is_linklocal(&rt->rt_best->rtp_dst.prefix)) { /* do not create a route with a LL IP as a destination */ return; } } if (!olsr_cnf->host_emul) { int16_t error = (olsr_cnf->ip_version == AF_INET) ? olsr_addroute_function(rt) : olsr_addroute6_function(rt); if (error != 0) { const char *const err_msg = strerror(errno); const char *const routestr = olsr_rtp_to_string(rt->rt_best); OLSR_PRINTF(1, "KERN: ERROR adding %s: %s\n", routestr, err_msg); olsr_syslog(OLSR_LOG_ERR, "Add route %s: %s", routestr, err_msg); } else { /* route addition has suceeded */ /* save the nexthop and metric in the route entry */ rt->rt_nexthop = rt->rt_best->rtp_nexthop; rt->rt_metric = rt->rt_best->rtp_metric; #ifdef linux /* call NIIT handler */ if (olsr_cnf->use_niit) { olsr_niit_handle_route(rt, true); } #endif } } }
int gethemusocket(struct sockaddr_in *pin) { int sock; OLSR_PRINTF(1, " Connecting to switch daemon port 10150..."); if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("hcsocket"); return (-1); } /* connect to PORT on HOST */ if (connect(sock, (struct sockaddr *)pin, sizeof(*pin)) < 0) { printf("FAILED\n"); fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno)); printf("connection refused\n"); closesocket(sock); return (-1); } printf("OK\n"); /* Keep TCP socket blocking */ return (sock); }
/** * Change a timer_entry. * * @param timer_entry to be changed. * @param new relative time expressed in units of milliseconds. * @param new jitter expressed in percent. * @return nada */ void olsr_change_timer(struct timer_entry *timer, unsigned int rel_time, uint8_t jitter_pct, bool periodical) { /* Sanity check. */ if (!timer) { return; } assert(timer->timer_cookie); /* we want timer cookies everywhere */ /* Singleshot or periodical timer ? */ timer->timer_period = periodical ? rel_time : 0; timer->timer_clock = calc_jitter(rel_time, jitter_pct, timer->timer_random); timer->timer_jitter_pct = jitter_pct; /* * Changes are easy: Remove timer from the exisiting timer_wheel slot * and reinsert into the new slot. */ list_remove(&timer->timer_list); list_add_before(&timer_wheel[timer->timer_clock & TIMER_WHEEL_MASK], &timer->timer_list); OLSR_PRINTF(7, "TIMER: change %s timer %p, firing to %s, ctx %p\n", timer->timer_cookie->ci_name, timer, olsr_clock_string(timer->timer_clock), timer->timer_cb_context); }
/** * Process a route from the kernel deletion list. * *@return -1 on error, else 0 */ static int olsr_delete_kernel_route(struct rt_entry *rt) { if (rt->rt_metric.hops > 1) { /* multihop route */ if (ip_is_linklocal(&rt->rt_dst.prefix)) { /* do not delete a route with a LL IP as a destination */ return 0; } } if (!olsr_cnf->host_emul) { int16_t error = olsr_cnf->ip_version == AF_INET ? olsr_delroute_function(rt) : olsr_delroute6_function(rt); if (error != 0) { const char *const err_msg = strerror(errno); const char *const routestr = olsr_rt_to_string(rt); OLSR_PRINTF(1, "KERN: ERROR deleting %s: %s\n", routestr, err_msg); olsr_syslog(OLSR_LOG_ERR, "Delete route %s: %s", routestr, err_msg); return -1; } #ifdef linux /* call NIIT handler (always)*/ if (olsr_cnf->use_niit) { olsr_niit_handle_route(rt, false); } #endif } return 0; }
/* * A wrapper around times(2). Note, that this function has some * portability problems, so do not rely on absolute values returned. * Under Linux, uclibc and libc directly call the sys_times() located * in kernel/sys.c and will only return an error if the tms_buf is * not writeable. */ static uint32_t olsr_times(void) { struct timeval tv; uint32_t t; if (gettimeofday(&tv, NULL) != 0) { olsr_exit("OS clock is not working, have to shut down OLSR", 1); } /* test if time jumped backward or more than 60 seconds forward */ if (tv.tv_sec < last_tv.tv_sec || (tv.tv_sec == last_tv.tv_sec && tv.tv_usec < last_tv.tv_usec) || tv.tv_sec - last_tv.tv_sec > 60) { OLSR_PRINTF(1, "Time jump (%d.%06d to %d.%06d)\n", (int32_t) (last_tv.tv_sec), (int32_t) (last_tv.tv_usec), (int32_t) (tv.tv_sec), (int32_t) (tv.tv_usec)); t = (last_tv.tv_sec - first_tv.tv_sec) * 1000 + (last_tv.tv_usec - first_tv.tv_usec) / 1000; t++; /* advance time by one millisecond */ first_tv = tv; first_tv.tv_sec -= (t / 1000); first_tv.tv_usec -= ((t % 1000) * 1000); if (first_tv.tv_usec < 0) { first_tv.tv_sec--; first_tv.tv_usec += 1000000; } last_tv = tv; return t; } last_tv = tv; return (tv.tv_sec - first_tv.tv_sec) * 1000 + (tv.tv_usec - first_tv.tv_usec) / 1000; }
/** * Init datastructures for maintaining timers. */ void olsr_init_timers(void) { int idx; OLSR_PRINTF(3, "Initializing scheduler.\n"); /* Grab initial timestamp */ if (gettimeofday(&first_tv, NULL)) { olsr_exit("OS clock is not working, have to shut down OLSR", 1); } last_tv = first_tv; now_times = olsr_times(); for (idx = 0; idx < TIMER_WHEEL_SLOTS; idx++) { list_head_init(&timer_wheel[idx]); } /* * Reset the last timer run. */ timer_last_run = now_times; /* Allocate a cookie for the block based memeory manager. */ timer_mem_cookie = olsr_alloc_cookie("timer_entry", OLSR_COOKIE_TYPE_MEMORY); olsr_cookie_set_memory_size(timer_mem_cookie, sizeof(struct timer_entry)); }
/** *Creates a blocking tcp socket for communication with switch daemon. *@param sa sockaddr struct. Used for bind(2). *@return the FD of the socket or -1 on error. */ int gethemusocket(struct sockaddr_in *pin) { int sock, on = 1; OLSR_PRINTF(1, " Connecting to switch daemon port 10150..."); if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("hcsocket"); syslog(LOG_ERR, "hcsocket: %m"); return -1; } if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) { perror("SO_REUSEADDR failed"); close(sock); return -1; } /* connect to PORT on HOST */ if (connect(sock, (struct sockaddr *)pin, sizeof(*pin)) < 0) { printf("FAILED\n"); fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno)); printf("connection refused\n"); close(sock); return -1; } printf("OK\n"); /* Keep TCP socket blocking */ return sock; }
/** *Remove a route from the kernel * *@param destination the route to remove * *@return negative on error */ int olsr_ioctl_del_route6(const struct rt_entry *rt) { struct in6_rtmsg kernel_route; int rslt; OLSR_PRINTF(2, "KERN: Deleting %s\n", olsr_rt_to_string(rt)); memset(&kernel_route, 0, sizeof(struct in6_rtmsg)); kernel_route.rtmsg_dst = rt->rt_dst.prefix.v6; kernel_route.rtmsg_dst_len = rt->rt_dst.prefix_len; kernel_route.rtmsg_gateway = rt->rt_best->rtp_nexthop.gateway.v6; kernel_route.rtmsg_flags = olsr_rt_flags(rt); kernel_route.rtmsg_metric = olsr_fib_metric(&rt->rt_best->rtp_metric); if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCDELRT, &kernel_route) >= 0)) { /* * Send IPC route update message */ ipc_route_send_rtentry(&rt->rt_dst.prefix, NULL, 0, 0, NULL); } return rslt; }
/** *Insert a route in the kernel routing table * *@param destination the route to add * *@return negative on error */ int olsr_ioctl_add_route6(const struct rt_entry *rt) { struct in6_rtmsg kernel_route; int rslt; OLSR_PRINTF(2, "KERN: Adding %s\n", olsr_rtp_to_string(rt->rt_best)); memset(&kernel_route, 0, sizeof(struct in6_rtmsg)); kernel_route.rtmsg_dst = rt->rt_dst.prefix.v6; kernel_route.rtmsg_dst_len = rt->rt_dst.prefix_len; kernel_route.rtmsg_gateway = rt->rt_best->rtp_nexthop.gateway.v6; kernel_route.rtmsg_flags = olsr_rt_flags(rt); kernel_route.rtmsg_metric = olsr_fib_metric(&rt->rt_best->rtp_metric); /* * set interface */ kernel_route.rtmsg_ifindex = rt->rt_best->rtp_nexthop.iif_index; /* XXX delete 0/0 route before ? */ if ((rslt = ioctl(olsr_cnf->ioctl_s, SIOCADDRT, &kernel_route)) >= 0) { /* * Send IPC route update message */ ipc_route_send_rtentry(&rt->rt_dst.prefix, &rt->rt_best->rtp_nexthop.gateway, rt->rt_best->rtp_metric.hops, 1, if_ifwithindex_name(rt->rt_best->rtp_nexthop.iif_index)); } return rslt; }