/** *Insert a plc peer entry in the table * *@param main_addr the main address of the new node * *@return 0 if plc peer already exists 1 if inserted */ struct plc_peer_entry * insert_plc_peer_neighbor(const union olsr_ip_addr *main_addr, unsigned char *mac) { uint32_t hash; struct plc_peer_entry *new_peer; hash = olsr_ip_hashing(main_addr); /* Check if entry exists */ for (new_peer = plc_peer_neighbors[hash].next; new_peer != &plc_peer_neighbors[hash]; new_peer = new_peer->next) { if (ipequal(&new_peer->plc_peer_main_addr, main_addr)) return 0; } //olsr_printf(3, "inserting peer\n"); new_peer = olsr_malloc(sizeof(struct plc_peer_entry), "New peer entry"); /* Set address, willingness and status */ new_peer->plc_peer_main_addr = *main_addr; memcpy(new_peer->plc_data.mac, mac, 6); /* Queue */ QUEUE_ELEM(plc_peer_neighbors[hash], new_peer); table_size++; return 1; }
int delete_plc_peer_neighbor(const union olsr_ip_addr *peer_addr) { uint32_t hash; struct plc_peer_entry *entry; //olsr_printf(3, "inserting neighbor\n"); hash = olsr_ip_hashing(peer_addr); entry = plc_peer_neighbors[hash].next; /* * Find neighbor entry */ while (entry != &plc_peer_neighbors[hash]) { if (ipequal(&entry->plc_peer_main_addr, peer_addr)) break; entry = entry->next; } if (entry == &plc_peer_neighbors[hash]) return 0; /* Dequeue */ DEQUEUE_ELEM(entry); free(entry); table_size--; return 1; }
/** * Check if there is an interface or gateway change. */ bool olsr_nh_change(const struct rt_nexthop *nh1, const struct rt_nexthop *nh2) { if (!ipequal(&nh1->gateway, &nh2->gateway) || (nh1->iif_index != nh2->iif_index)) { return true; } return false; }
/** * Check if there is an interface or gateway change. */ olsr_bool olsr_nh_change(const struct rt_nexthop *nh1, const struct rt_nexthop *nh2) { if (!ipequal(&nh1->gateway, &nh2->gateway) || (nh1->iif_index != nh2->iif_index)) { return OLSR_TRUE; } return OLSR_FALSE; }
void dev_send_init(void) { union olsr_ip_addr* addr, mask; struct interface* ifs; //------------------------------ // reset sereadmo iptable module //------------------------------ dev_add_cmd(DEV_CMD_RESET_TC,NULL,NULL,0); //------------------ // send local config //------------------ //main addr (ie. addr used by olsrd in links for local node) addr = &olsr_cnf->main_addr; // retreive IP mask for the main addr for(ifs = ifnet; ifs != NULL; ifs = ifs->int_next) { if(ipequal(addr,&ifs->ip_addr) != 0) { mask.v4.s_addr = ifs->int_netmask.sin_addr.s_addr; break; } } dev_add_cmd(DEV_CMD_SET_LOCAL_ADDR,addr,&mask,0); //---------------- // send addr alias //---------------- for(ifs = ifnet; ifs != NULL; ifs = ifs->int_next) { if(ipequal(addr,&ifs->ip_addr) == 0) { mask.v4.s_addr = ifs->int_netmask.sin_addr.s_addr; dev_add_cmd(DEV_CMD_SET_ALIAS_ADDR,&ifs->ip_addr,&mask,0); } } dev_send(); }
void olsr_cleanup_hna(union olsr_ip_addr *orig) { struct hna_entry *hna; OLSR_FOR_ALL_HNA_ENTRIES(hna) { if (hna->networks.next != &hna->networks && ipequal(&hna->A_gateway_addr, orig)) { while (!olsr_delete_hna_net_entry(hna->networks.next)); } } OLSR_FOR_ALL_HNA_ENTRIES_END(hna) }
struct ip_prefix_list * ip_prefix_list_find(struct ip_prefix_list *list, const union olsr_ip_addr *net, uint8_t prefix_len) { struct ip_prefix_list *h; for (h = list; h != NULL; h = h->next) { if (prefix_len == h->net.prefix_len && ipequal(net, &h->net.prefix)) { return h; } } return NULL; }
/** *Check if a two hop neighbor is reachable via a given *neighbor. * *@param neighbor neighbor-entry to check via *@param neighbor_main_address the addres of the two hop neighbor *to find. * *@return a pointer to the neighbor_2_list_entry struct *representing the two hop neighbor if found. NULL if not found. */ struct neighbor_2_list_entry * olsr_lookup_my_neighbors(const struct neighbor_entry *neighbor, const union olsr_ip_addr *neighbor_main_address) { struct neighbor_2_list_entry *entry; for (entry = neighbor->neighbor_2_list.next; entry != &neighbor->neighbor_2_list; entry = entry->next) { if (ipequal(&entry->neighbor_2->neighbor_2_addr, neighbor_main_address)) return entry; } return NULL; }
int olsr_delete_neighbor_table(const union olsr_ip_addr *neighbor_addr) { struct neighbor_2_list_entry *two_hop_list, *two_hop_to_delete; olsr_u32_t hash; struct neighbor_entry *entry; //printf("inserting neighbor\n"); hash = olsr_ip_hashing(neighbor_addr); entry = neighbortable[hash].next; /* * Find neighbor entry */ while(entry != &neighbortable[hash]) { if(ipequal(&entry->neighbor_main_addr, neighbor_addr)) break; entry = entry->next; } if(entry == &neighbortable[hash]) return 0; two_hop_list = entry->neighbor_2_list.next; while (two_hop_list != &entry->neighbor_2_list) { two_hop_to_delete = two_hop_list; two_hop_list = two_hop_list->next; two_hop_to_delete->neighbor_2->neighbor_2_pointer--; olsr_delete_neighbor_pointer(two_hop_to_delete->neighbor_2, &entry->neighbor_main_addr); olsr_del_nbr2_list(two_hop_to_delete); } /* Dequeue */ DEQUEUE_ELEM(entry); free(entry); changes_neighborhood = OLSR_TRUE; return 1; }
/** * Lookup a network entry in a networkentry list. * * @param nets the network list to look in * @param net the network to look for * @param prefixlen the prefix length * * @return the localized entry or NULL of not found */ struct hna_net * olsr_lookup_hna_net(const struct hna_net *nets, const union olsr_ip_addr *net, uint8_t prefixlen) { struct hna_net *tmp; /* Loop trough entrys */ for (tmp = nets->next; tmp != nets; tmp = tmp->next) { if (tmp->hna_prefix.prefix_len == prefixlen && ipequal(&tmp->hna_prefix.prefix, net)) { return tmp; } } /* Not found */ return NULL; }
/** * lookup a nodes position */ static char* lookup_position_latlon(union olsr_ip_addr *ip) { int hash; struct db_entry *entry; struct list_node *list_head, *list_node; if (ipequal(ip, &olsr_cnf->main_addr)) { return my_latlon_str; } for (hash = 0; hash < HASHSIZE; hash++) { list_head = &latlon_list[hash]; for (list_node = list_head->next; list_node != list_head; list_node = list_node->next) { entry = list2db(list_node); if (entry->names && ipequal(&entry->originator, ip)) { return entry->names->name; } } } return NULL; }
/** * Delete a two hop neighbor from a neighbors two hop neighbor list. * * @param neighbor the neighbor to delete the two hop neighbor from. * @param address the IP address of the two hop neighbor to delete. * * @return positive if entry deleted */ int olsr_delete_neighbor_2_pointer(struct neighbor_entry *neighbor, union olsr_ip_addr *address) { struct neighbor_2_list_entry *nbr2_list; nbr2_list = neighbor->neighbor_2_list.next; while (nbr2_list != &neighbor->neighbor_2_list) { if (ipequal(&nbr2_list->neighbor_2->neighbor_2_addr, address)) { olsr_del_nbr2_list(nbr2_list); return 1; } nbr2_list = nbr2_list->next; } return 0; }
bool olsr_validate_address(const union olsr_ip_addr *adr) { const struct deny_address_entry *deny_entry; for (deny_entry = deny_entries; deny_entry != NULL; deny_entry = deny_entry->next) { if (ipequal(adr, &deny_entry->addr)) { struct ipaddr_str buf; OLSR_PRINTF(1, "Validation of address %s failed!\n", olsr_ip_to_string(&buf, adr)); return false; } if (&deny_entry->addr == &olsr_cnf->main_addr) break; } return true; }
/** * Lookup a gateway entry * * @param gw the address of the gateway * @return the located entry or NULL if not found */ struct hna_entry * olsr_lookup_hna_gw(const union olsr_ip_addr *gw) { struct hna_entry *tmp_hna; uint32_t hash = olsr_ip_hashing(gw); /* Check for registered entry */ for (tmp_hna = hna_set[hash].next; tmp_hna != &hna_set[hash]; tmp_hna = tmp_hna->next) { if (ipequal(&tmp_hna->A_gateway_addr, gw)) { return tmp_hna; } } /* Not found */ return NULL; }
/** * Add a new tc_entry to the tc tree * * @param adr (last)adr address of the entry * @return a pointer to the created entry */ static struct tc_entry * olsr_add_tc_entry(union olsr_ip_addr *adr) { #ifdef DEBUG struct ipaddr_str buf; #endif /* DEBUG */ struct tc_entry *tc; /* * Safety net against loss of the last main IP address. */ if (ipequal(&olsr_cnf->main_addr, &all_zero)) { return NULL; } #ifdef DEBUG OLSR_PRINTF(1, "TC: add entry %s\n", olsr_ip_to_string(&buf, adr)); #endif /* DEBUG */ tc = olsr_cookie_malloc(tc_mem_cookie); if (!tc) { return NULL; } /* Fill entry */ tc->addr = *adr; tc->vertex_node.key = &tc->addr; /* * Insert into the global tc tree. */ avl_insert(&tc_tree, &tc->vertex_node, AVL_DUP_NO); olsr_lock_tc_entry(tc); /* * Initialize subtrees for edges and prefixes. */ avl_init(&tc->edge_tree, avl_comp_default); avl_init(&tc->prefix_tree, avl_comp_prefix_default); /* * Add a rt_path for ourselves. */ olsr_insert_routing_table(adr, olsr_cnf->maxplen, adr, OLSR_RT_ORIGIN_INT); return tc; }
/** *Lookup a peer entry in the plc_peer_neighbors based on an address. * *@param dst the IP address of the peer to look up * *@return a pointer to the neighbor struct registered on the given *address. NULL if not found. */ struct plc_peer_entry * lookup_plc_peer_by_ip(const union olsr_ip_addr *dst) { struct plc_peer_entry *entry; uint32_t hash = olsr_ip_hashing(dst); //olsr_printf(3, "\nLookup %s\n", olsr_ip_to_string(&buf, dst)); for (entry = plc_peer_neighbors[hash].next; entry != &plc_peer_neighbors[hash]; entry = entry->next) { //olsr_printf(3, "Checking %s\n", olsr_ip_to_string(&buf, &entry->plc_peer_main_addr)); if (ipequal(&entry->plc_peer_main_addr, dst)) return entry; } //olsr_printf(3, "NOPE\n\n"); return NULL; }
/** *Lookup an entry in the MPR selector table *based on address * *@param addr the addres to check for * *@return a pointer to the entry or NULL */ struct mpr_selector * olsr_lookup_mprs_set(const union olsr_ip_addr *addr) { struct mpr_selector *mprs; if (addr == NULL) return NULL; //OLSR_PRINTF(1, "MPRS: Lookup...."); for (mprs = mprs_list.next; mprs != &mprs_list; mprs = mprs->next) { if (ipequal(&mprs->MS_main_addr, addr)) { //OLSR_PRINTF(1, "MATCH\n"); return mprs; } } //OLSR_PRINTF(1, "NO MACH\n"); return NULL; }
/** *Lookup a neighbor entry in the neighbortable based on an address. * *@param dst the IP address of the neighbor to look up * *@return a pointer to the neighbor struct registered on the given *address. NULL if not found. */ struct neighbor_entry * olsr_lookup_neighbor_table_alias(const union olsr_ip_addr *dst) { struct neighbor_entry *entry; uint32_t hash = olsr_ip_hashing(dst); //printf("\nLookup %s\n", olsr_ip_to_string(&buf, dst)); for (entry = neighbortable[hash].next; entry != &neighbortable[hash]; entry = entry->next) { //printf("Checking %s\n", olsr_ip_to_string(&buf, &entry->neighbor_main_addr)); if (ipequal(&entry->neighbor_main_addr, dst)) return entry; } //printf("NOPE\n\n"); return NULL; }
/** * * Calculate the kernel route flags. * Called before enqueuing a change/delete operation * */ uint8_t olsr_rt_flags(const struct rt_entry *rt) { const struct rt_nexthop *nh; uint8_t flags = RTF_UP; /* destination is host */ if (rt->rt_dst.prefix_len == olsr_cnf->maxplen) { flags |= RTF_HOST; } nh = olsr_get_nh(rt); if (!ipequal(&rt->rt_dst.prefix, &nh->gateway)) { flags |= RTF_GATEWAY; } return flags; }
/** *Insert a neighbor entry in the neighbor table * *@param main_addr the main address of the new node * *@return 0 if neighbor already exists 1 if inserted */ struct neighbor_entry * olsr_insert_neighbor_table(const union olsr_ip_addr *main_addr) { olsr_u32_t hash; struct neighbor_entry *new_neigh; hash = olsr_ip_hashing(main_addr); /* Check if entry exists */ for(new_neigh = neighbortable[hash].next; new_neigh != &neighbortable[hash]; new_neigh = new_neigh->next) { if(ipequal(&new_neigh->neighbor_main_addr, main_addr)) return new_neigh; } //printf("inserting neighbor\n"); new_neigh = olsr_malloc(sizeof(struct neighbor_entry), "New neighbor entry"); /* Set address, willingness and status */ new_neigh->neighbor_main_addr = *main_addr; new_neigh->willingness = WILL_NEVER; new_neigh->status = NOT_SYM; new_neigh->neighbor_2_list.next = &new_neigh->neighbor_2_list; new_neigh->neighbor_2_list.prev = &new_neigh->neighbor_2_list; new_neigh->linkcount = 0; new_neigh->is_mpr = OLSR_FALSE; new_neigh->was_mpr = OLSR_FALSE; /* Queue */ QUEUE_ELEM(neighbortable[hash], new_neigh); return new_neigh; }
/** * Enqueue a route on a kernel add/chg/del queue. */ static void olsr_enqueue_rt(struct list_node *head_node, struct rt_entry *rt) { const struct rt_nexthop *nh; /* if this node is already on some changelist we are done */ if (list_node_on_list(&rt->rt_change_node)) { return; } /* * For easier route dependency tracking we enqueue nexthop routes * at the head of the queue and non-nexthop routes at the tail of the queue. */ nh = olsr_get_nh(rt); if (ipequal(&rt->rt_dst.prefix, &nh->gateway)) { list_add_after(head_node, &rt->rt_change_node); } else { list_add_before(head_node, &rt->rt_change_node); } }
/** * The main ip address has changed. * Do the needful. */ void olsr_change_myself_tc(void) { if (tc_myself) { /* * Check if there was a change. */ if (ipequal(&tc_myself->addr, &olsr_cnf->main_addr)) { return; } /* * Flush our own tc_entry. */ olsr_delete_tc_entry(tc_myself); } /* * The old entry for ourselves is gone, generate a new one and trigger SPF. */ tc_myself = olsr_add_tc_entry(&olsr_cnf->main_addr); changes_topology = true; }
int ip_prefix_list_remove(struct ip_prefix_list **list, const union olsr_ip_addr *net, uint8_t prefix_len) { struct ip_prefix_list *h = *list, *prev = NULL; while (h != NULL) { if (ipequal(net, &h->net.prefix) && h->net.prefix_len == prefix_len) { /* Dequeue */ if (prev == NULL) { *list = h->next; } else { prev->next = h->next; } free(h); /* update gateway flags */ update_has_gateway_fields(); return 1; } prev = h; h = h->next; } return 0; }
static bool serialize_mid6(struct interface *ifp) { uint16_t remainsize, curr_size, needsize; /* preserve existing data in output buffer */ union olsr_message *m; struct midaddr6 *addrs6; struct interface *ifs; //printf("\t\tGenerating mid on %s\n", ifn->int_name); if ((olsr_cnf->ip_version != AF_INET6) || (!ifp) || (ifnet == NULL) || ((ifnet->int_next == NULL) && (ipequal(&olsr_cnf->main_addr, &ifnet->ip_addr)))) return false; remainsize = net_outbuffer_bytes_left(ifp); curr_size = OLSR_MID_IPV6_HDRSIZE; /* calculate size needed for HNA */ needsize = curr_size; for (ifs = ifnet; ifs != NULL; ifs = ifs->int_next) { needsize += olsr_cnf->ipsize*2; } /* Send pending packet if not room in buffer */ if (needsize > remainsize) { net_output(ifp); remainsize = net_outbuffer_bytes_left(ifp); } check_buffspace(curr_size, remainsize, "MID"); m = (union olsr_message *)msg_buffer; /* Build header */ m->v6.hopcnt = 0; m->v6.ttl = MAX_TTL; m->v6.olsr_msgtype = MID_MESSAGE; m->v6.olsr_vtime = ifp->valtimes.mid; /* Set main(first) address */ m->v6.originator = olsr_cnf->main_addr.v6; addrs6 = m->v6.message.mid.mid_addr; /* Don't add the main address... it's already there */ for (ifs = ifnet; ifs != NULL; ifs = ifs->int_next) { if (!ipequal(&olsr_cnf->main_addr, &ifs->ip_addr)) { #ifdef DEBUG struct ipaddr_str buf; #endif if ((curr_size + olsr_cnf->ipsize) > remainsize) { /* Only add MID message if it contains data */ if (curr_size > OLSR_MID_IPV6_HDRSIZE) { #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "Sending partial(size: %d, buff left:%d)\n", curr_size, remainsize); #endif /* set size */ m->v6.olsr_msgsize = htons(curr_size); m->v6.seqno = htons(get_msg_seqno()); /* seqnumber */ net_outbuffer_push(ifp, msg_buffer, curr_size); curr_size = OLSR_MID_IPV6_HDRSIZE; addrs6 = m->v6.message.mid.mid_addr; } net_output(ifp); remainsize = net_outbuffer_bytes_left(ifp); check_buffspace(curr_size + olsr_cnf->ipsize, remainsize, "MID2"); } #ifdef DEBUG OLSR_PRINTF(BMSG_DBGLVL, "\t%s(%s)\n", olsr_ip_to_string(&buf, &ifs->ip_addr), ifs->int_name); #endif addrs6->addr = ifs->ip_addr.v6; addrs6++; curr_size += olsr_cnf->ipsize; } } m->v6.olsr_msgsize = htons(curr_size); m->v6.seqno = htons(get_msg_seqno()); /* seqnumber */ //printf("Sending MID (%d bytes)...\n", outputsize); if (curr_size > OLSR_MID_IPV6_HDRSIZE) net_outbuffer_push(ifp, msg_buffer, curr_size); return true; }
void olsr_remove_interface(struct olsr_if * iface) { struct interface *ifp, *tmp_ifp; ifp = iface->interf; OLSR_PRINTF(1, "Removing interface %s (%d)\n", iface->name, ifp->if_index); olsr_syslog(OLSR_LOG_INFO, "Removing interface %s\n", iface->name); olsr_delete_link_entry_by_ip(&ifp->ip_addr); /* *Call possible ifchange functions registered by plugins */ olsr_trigger_ifchange(ifp->if_index, ifp, IFCHG_IF_REMOVE); /* cleanup routes over this interface */ olsr_delete_interface_routes(ifp->if_index); /* Dequeue */ if (ifp == ifnet) { ifnet = ifp->int_next; } else { tmp_ifp = ifnet; while (tmp_ifp->int_next != ifp) { tmp_ifp = tmp_ifp->int_next; } tmp_ifp->int_next = ifp->int_next; } /* Remove output buffer */ net_remove_buffer(ifp); /* Check main addr */ /* deactivated to prevent change of originator IP */ #if 0 if (ipequal(&olsr_cnf->main_addr, &ifp->ip_addr)) { if (ifnet == NULL) { /* No more interfaces */ memset(&olsr_cnf->main_addr, 0, olsr_cnf->ipsize); OLSR_PRINTF(1, "No more interfaces...\n"); } else { struct ipaddr_str buf; olsr_cnf->main_addr = ifnet->ip_addr; OLSR_PRINTF(1, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr)); olsr_syslog(OLSR_LOG_INFO, "New main address: %s\n", olsr_ip_to_string(&buf, &olsr_cnf->main_addr)); } } #endif /* 0 */ /* * Deregister functions for periodic message generation */ olsr_stop_timer(ifp->hello_gen_timer); olsr_stop_timer(ifp->tc_gen_timer); olsr_stop_timer(ifp->mid_gen_timer); olsr_stop_timer(ifp->hna_gen_timer); iface->configured = 0; iface->interf = NULL; /* Close olsr socket */ remove_olsr_socket(ifp->olsr_socket, &olsr_input, NULL); close(ifp->olsr_socket); remove_olsr_socket(ifp->send_socket, &olsr_input, NULL); close(ifp->send_socket); /* Free memory */ free(ifp->int_name); free(ifp); if ((ifnet == NULL) && (!olsr_cnf->allow_no_interfaces)) { olsr_syslog(OLSR_LOG_INFO, "No more active interfaces - exiting.\n"); olsr_exit("No more active interfaces - exiting.\n", EXIT_FAILURE); } }
/* ------------------------------------------------------------------------- * Function : BmfTunPacketCaptured * Description: Handle an IP packet, captured outgoing on the tuntap interface * Input : encapsulationUdpData - space for the encapsulation header, followed by * the captured outgoing IP packet * Output : none * Return : none * Data Used : none * Notes : The packet is assumed to be captured on a socket of family * PF_PACKET and type SOCK_DGRAM (cooked). * ------------------------------------------------------------------------- */ static void BmfTunPacketCaptured(unsigned char* encapsulationUdpData) { union olsr_ip_addr srcIp; union olsr_ip_addr dstIp; union olsr_ip_addr broadAddr; struct TBmfInterface* walker; unsigned char* ipPacket; u_int16_t ipPacketLen; struct ip* ipHeader; u_int32_t crc32; struct TEncapHeader* encapHdr; #ifndef NODEBUG struct ipaddr_str srcIpBuf, dstIpBuf; #endif ipPacket = GetIpPacket(encapsulationUdpData); ipPacketLen = GetIpTotalLength(ipPacket); ipHeader = GetIpHeader(encapsulationUdpData); dstIp.v4 = ipHeader->ip_dst; broadAddr.v4.s_addr = htonl(EtherTunTapIpBroadcast); /* Only forward multicast packets. If configured, also forward local broadcast packets */ if (IsMulticast(&dstIp) || (EnableLocalBroadcast != 0 && ipequal(&dstIp, &broadAddr))) { /* continue */ } else { return; } srcIp.v4 = ipHeader->ip_src; OLSR_PRINTF( 8, "%s: outgoing pkt of %ld bytes captured on tuntap interface \"%s\": %s->%s\n", PLUGIN_NAME_SHORT, (long)ipPacketLen, EtherTunTapIfName, olsr_ip_to_string(&srcIpBuf, &srcIp), olsr_ip_to_string(&dstIpBuf, &dstIp)); /* Calculate packet fingerprint */ crc32 = PacketCrc32(ipPacket, ipPacketLen); /* Check if this packet was seen recently */ if (CheckAndMarkRecentPacket(crc32)) { OLSR_PRINTF( 8, "%s: --> discarding: packet is duplicate\n", PLUGIN_NAME_SHORT); return; } /* Compose encapsulation header */ encapHdr = (struct TEncapHeader*) encapsulationUdpData; memset (encapHdr, 0, ENCAP_HDR_LEN); encapHdr->type = BMF_ENCAP_TYPE; encapHdr->len = BMF_ENCAP_LEN; encapHdr->reserved = 0; encapHdr->crc32 = htonl(crc32); /* Check with each network interface what needs to be done on it */ for (walker = BmfInterfaces; walker != NULL; walker = walker->next) { /* Is the forwarding interface OLSR-enabled? */ if (walker->olsrIntf != NULL) { /* On an OLSR interface: encapsulate and forward packet. */ EncapsulateAndForwardPacket(walker, encapsulationUdpData, NULL, NULL, NULL); } else { /* On a non-OLSR interface: what to do? * Answer 1: nothing. Multicast routing between non-OLSR interfaces * is to be done by other protocols (e.g. PIM, DVMRP). * Answer 2 (better): Forward it. */ ForwardPacket (walker, ipPacket, ipPacketLen, "forwarded from non-OLSR to non-OLSR interface"); } /* if */ } /* for */ } /* BmfTunPacketCaptured */
/* ------------------------------------------------------------------------- * Function : BmfPacketCaptured * Description: Handle a captured IP packet * Input : intf - the network interface on which the packet was captured * sllPkttype - the type of packet. Either PACKET_OUTGOING, * PACKET_BROADCAST or PACKET_MULTICAST. * encapsulationUdpData - space for the encapsulation header, followed by * the captured IP packet * Output : none * Return : none * Data Used : BmfInterfaces * Notes : The IP packet is assumed to be captured on a socket of family * PF_PACKET and type SOCK_DGRAM (cooked). * ------------------------------------------------------------------------- */ static void BmfPacketCaptured( struct TBmfInterface* intf, unsigned char sllPkttype, unsigned char* encapsulationUdpData) { union olsr_ip_addr src; /* Source IP address in captured packet */ union olsr_ip_addr dst; /* Destination IP address in captured packet */ union olsr_ip_addr* origIp; /* Main OLSR address of source of captured packet */ struct TBmfInterface* walker; int isFromOlsrIntf; int isFromOlsrNeighbor; int iAmMpr; unsigned char* ipPacket; /* The captured IP packet... */ u_int16_t ipPacketLen; /* ...and its length */ struct ip* ipHeader; /* The IP header inside the captured IP packet */ u_int32_t crc32; struct TEncapHeader* encapHdr; #ifndef NODEBUG struct ipaddr_str srcBuf, dstBuf; #endif ipHeader = GetIpHeader(encapsulationUdpData); dst.v4 = ipHeader->ip_dst; /* Only forward multicast packets. If configured, also forward local broadcast packets */ if (IsMulticast(&dst) || (EnableLocalBroadcast != 0 && ipequal(&dst, &intf->broadAddr))) { /* continue */ } else { return; } ipPacket = GetIpPacket(encapsulationUdpData); /* Don't forward fragments of IP packets: there is no way to distinguish fragments * of BMF encapsulation packets from other fragments. * Well yes, there is the IP-ID, which can be kept in a list to relate a fragment * to earlier sent BMF packets, but... sometimes the second fragment comes in earlier * than the first fragment, so that the list is not yet up to date and the second * fragment is not recognized as a BMF packet. * Also, don't forward OLSR packets (UDP port 698) and BMF encapsulated packets */ if (IsIpFragment(ipPacket) || IsOlsrOrBmfPacket(ipPacket)) { return; } /* Increase counter */ intf->nBmfPacketsRx++; /* Check if the frame is captured on an OLSR-enabled interface */ isFromOlsrIntf = (intf->olsrIntf != NULL); /* Retrieve the length of the captured packet */ ipPacketLen = GetIpTotalLength(ipPacket); src.v4 = ipHeader->ip_src; OLSR_PRINTF( 8, "%s: %s pkt of %ld bytes captured on %s interface \"%s\": %s->%s\n", PLUGIN_NAME_SHORT, sllPkttype == PACKET_OUTGOING ? "outgoing" : "incoming", (long)ipPacketLen, isFromOlsrIntf ? "OLSR" : "non-OLSR", intf->ifName, olsr_ip_to_string(&srcBuf, &src), olsr_ip_to_string(&dstBuf, &dst)); /* Lookup main address of source in the MID table of OLSR */ origIp = MainAddressOf(&src); /* Calculate packet fingerprint */ crc32 = PacketCrc32(ipPacket, ipPacketLen); /* Check if this packet was seen recently */ if (CheckAndMarkRecentPacket(crc32)) { /* Increase counter */ intf->nBmfPacketsRxDup++; OLSR_PRINTF( 8, "%s: --> discarding: packet is duplicate\n", PLUGIN_NAME_SHORT); return; } /* Compose encapsulation header */ encapHdr = (struct TEncapHeader*) encapsulationUdpData; memset (encapHdr, 0, ENCAP_HDR_LEN); encapHdr->type = BMF_ENCAP_TYPE; encapHdr->len = BMF_ENCAP_LEN; encapHdr->reserved = 0; encapHdr->crc32 = htonl(crc32); /* Check if the frame is captured on an OLSR interface from an OLSR neighbor. * TODO: get_best_link_to_neighbor() may be very CPU-expensive, a simpler call * would do here (something like 'get_any_link_to_neighbor()'). */ isFromOlsrNeighbor = (isFromOlsrIntf /* The frame is captured on an OLSR interface... */ && get_best_link_to_neighbor(origIp) != NULL); /* ...from an OLSR neighbor */ /* Check with OLSR if I am MPR for that neighbor */ iAmMpr = olsr_lookup_mprs_set(origIp) != NULL; /* Check with each network interface what needs to be done on it */ for (walker = BmfInterfaces; walker != NULL; walker = walker->next) { /* Is the forwarding interface OLSR-enabled? */ int isToOlsrIntf = (walker->olsrIntf != NULL); /* Depending on certain conditions, we decide whether or not to forward * the packet, and if it is forwarded, in which form (encapsulated * or not, TTL decreased or not). These conditions are: * - is the packet is coming in on an OLSR interface or not? (isFromOlsrIntf) * - is the packet going out on an OLSR interface or not? (isToOlsrIntf) * - if the packet if coming in on an OLSR interface: * - is the node that forwarded the packet my OLSR-neighbor? (isFromOlsrNeighbor) * - has the node that forwarded the packet selected me as MPR? (iAmMpr) * * Based on these conditions, the following cases can be distinguished: * * - Case 1: Packet coming in on an OLSR interface. What to * do with it on an OLSR interface? * Answer: * - Case 1.1: If the forwarding node is an OLSR neighbor that has *not* * selected me as MPR: don't forward the packet. * - Case 1.2: If the forwarding node is an OLSR neighbor that has selected * me as MPR: encapsulate and forward the packet. * - Case 1.3: If the forwarding node is not an OLSR neighbor: encapsulate * and forward the packet. * NOTE: Case 1.3 is a special case. In the perfect world, we expect to * see only OLSR-neighbors on OLSR-enabled interfaces. Sometimes, however, * ignorant users will connect a host not running OLSR, to a LAN in * which there are hosts running OLSR. Of course these ignorant users, * expecting magic, want to see their multicast packets being forwarded * through the network. * * - Case 2: Packet coming in on an OLSR interface. What to do with it on a * non-OLSR interface? * Answer: Forward it. * * - Case 3: Packet coming in on a non-OLSR interface. What to * do with it on an OLSR interface? * Answer: Encapsulate and forward it. * * - Case 4: Packet coming in on non-OLSR interface. What to do with it on a * non-OLSR interface? * Answer 1: nothing. Multicast routing between non-OLSR interfaces * is to be done by other protocols (e.g. PIM, DVMRP). * Answer 2 (better): Forward it. */ if (isFromOlsrIntf && isToOlsrIntf) { /* Case 1: Forward from an OLSR interface to an OLSR interface */ if (isFromOlsrNeighbor && !iAmMpr) { /* Case 1.1 */ { #ifndef NODEBUG struct ipaddr_str buf; #endif OLSR_PRINTF( 8, "%s: --> not encap-forwarding on \"%s\": I am not selected as MPR by neighbor %s\n", PLUGIN_NAME_SHORT, walker->ifName, olsr_ip_to_string(&buf, &src)); } } else if (sllPkttype == PACKET_OUTGOING && intf == walker) { OLSR_PRINTF( 8, "%s: --> not encap-forwarding on \"%s\": pkt was captured on that interface\n", PLUGIN_NAME_SHORT, walker->ifName); } else { /* Case 1.2 and 1.3 */ EncapsulateAndForwardPacket(walker, encapsulationUdpData, NULL, NULL, NULL); } } /* if (isFromOlsrIntf && isToOlsrIntf) */ else if (isFromOlsrIntf && !isToOlsrIntf) { /* Case 2: Forward from OLSR interface to non-OLSR interface */ ForwardPacket (walker, ipPacket, ipPacketLen, "forwarded to non-OLSR interface"); } /* else if (isFromOlsrIntf && !isToOlsrIntf) */ else if (!isFromOlsrIntf && isToOlsrIntf) { /* Case 3: Forward from a non-OLSR interface to an OLSR interface. * Encapsulate and forward packet. */ EncapsulateAndForwardPacket(walker, encapsulationUdpData, NULL, NULL, NULL); } /* else if (!isFromOlsrIntf && isToOlsrIntf) */ else { /* Case 4: Forward from non-OLSR interface to non-OLSR interface. */ /* Don't forward on interface on which packet was received */ if (intf == walker) { OLSR_PRINTF( 8, "%s: --> not forwarding on \"%s\": pkt was captured on that interface\n", PLUGIN_NAME_SHORT, walker->ifName); } else { ForwardPacket (walker, ipPacket, ipPacketLen, "forwarded from non-OLSR to non-OLSR interface"); } /* if (intf == walker) */ } /* if */ } /* for */ } /* BmfPacketCaptured */
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; }
void olsr_hello_tap(struct hello_message *message, struct interface *in_if, const union olsr_ip_addr *from_addr) { struct neighbor_entry *neighbor; /* * Update link status */ struct link_entry *lnk = update_link_entry(&in_if->ip_addr, from_addr, message, in_if); /*check alias message->source_addr*/ if (!ipequal(&message->source_addr,from_addr)){ /*new alias of new neighbour are thrown in the mid table to speed up routing*/ if (olsr_validate_address(from_addr)) { union olsr_ip_addr * main_addr = mid_lookup_main_addr(from_addr); if ((main_addr==NULL)||(ipequal(&message->source_addr, main_addr))){ /*struct ipaddr_str srcbuf, origbuf; olsr_syslog(OLSR_LOG_INFO, "got hello from unknown alias ip of direct neighbour: ip: %s main-ip: %s", olsr_ip_to_string(&origbuf,&message->source_addr), olsr_ip_to_string(&srcbuf,from_addr));*/ insert_mid_alias(&message->source_addr, from_addr, message->vtime); } else { struct ipaddr_str srcbuf, origbuf; olsr_syslog(OLSR_LOG_INFO, "got hello with invalid from and originator adress pair (%s, %s) Duplicate Ips?\n", olsr_ip_to_string(&origbuf,&message->source_addr), olsr_ip_to_string(&srcbuf,from_addr)); } } } if (olsr_cnf->lq_level > 0) { struct hello_neighbor *walker; /* just in case our neighbor has changed its HELLO interval */ olsr_update_packet_loss_hello_int(lnk, message->htime); /* find the input interface in the list of neighbor interfaces */ for (walker = message->neighbors; walker != NULL; walker = walker->next) { if (walker->link != UNSPEC_LINK && ipequal(&walker->address, &in_if->ip_addr)) { break; } } /* * memorize our neighbour's idea of the link quality, so that we * know the link quality in both directions * * walker is NULL if there the current interface was not included in * the message (or was included as an UNSPEC_LINK) */ olsr_memorize_foreign_hello_lq(lnk, walker); /* update packet loss for link quality calculation */ olsr_received_hello_handler(lnk); } neighbor = lnk->neighbor; /* * Hysteresis */ if (olsr_cnf->use_hysteresis) { /* Update HELLO timeout */ /* printf("MESSAGE HTIME: %f\n", message->htime); */ olsr_update_hysteresis_hello(lnk, message->htime); } /* Check if we are chosen as MPR */ if (lookup_mpr_status(message, in_if)) /* source_addr is always the main addr of a node! */ olsr_update_mprs_set(&message->source_addr, message->vtime); /* Check willingness */ if (neighbor->willingness != message->willingness) { struct ipaddr_str buf; OLSR_PRINTF(1, "Willingness for %s changed from %d to %d - UPDATING\n", olsr_ip_to_string(&buf, &neighbor->neighbor_main_addr), neighbor->willingness, message->willingness); /* *If willingness changed - recalculate */ neighbor->willingness = message->willingness; changes_neighborhood = true; changes_topology = true; } /* Don't register neighbors of neighbors that announces WILL_NEVER */ if (neighbor->willingness != WILL_NEVER) process_message_neighbors(neighbor, message); /* Process changes immedeatly in case of MPR updates */ olsr_process_changes(); olsr_free_hello_packet(message); return; }
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; }