static void ipc_print_neigh_link(struct autobuf *abuf, const struct neighbor_entry *neighbor) { static const char DASHED[] = "dashed"; static const char SOLID[] = "solid"; struct ipaddr_str mainaddrstrbuf, strbuf; olsr_linkcost etx = 0.0; const char *style; const char *adr = olsr_ip_to_string(&mainaddrstrbuf, &olsr_cnf->main_addr); struct link_entry *the_link; struct lqtextbuffer lqbuffer; if (neighbor->status == 0) { /* non SYM */ style = DASHED; } else { the_link = get_best_link_to_neighbor(&neighbor->neighbor_main_addr); if (the_link) { etx = the_link->linkcost; } style = SOLID; } abuf_appendf(abuf, "\"%s\" -> \"%s\"[label=\"%s\", style=%s];\n", adr, olsr_ip_to_string(&strbuf, &neighbor->neighbor_main_addr), get_linkcost_text(etx, false, &lqbuffer), style); if (neighbor->is_mpr) { abuf_appendf(abuf, "\"%s\"[shape=box];\n", adr); } }
/** *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_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); } } } }
/* ------------------------------------------------------------------------- * 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 */
/** *Processes an list of neighbors from an incoming HELLO message. *@param neighbor the neighbor who sent the message. *@param message the HELLO message *@return nada */ static void process_message_neighbors(struct neighbor_entry *neighbor, const struct hello_message *message) { struct hello_neighbor *message_neighbors; for (message_neighbors = message->neighbors; message_neighbors != NULL; message_neighbors = message_neighbors->next) { union olsr_ip_addr *neigh_addr; struct neighbor_2_entry *two_hop_neighbor; /* *check all interfaces *so that we don't add ourselves to the *2 hop list *IMPORTANT! */ if (if_ifwithaddr(&message_neighbors->address) != NULL) continue; /* Get the main address */ neigh_addr = mid_lookup_main_addr(&message_neighbors->address); if (neigh_addr != NULL) { message_neighbors->address = *neigh_addr; } if (((message_neighbors->status == SYM_NEIGH) || (message_neighbors->status == MPR_NEIGH))) { struct neighbor_2_list_entry *two_hop_neighbor_yet = olsr_lookup_my_neighbors(neighbor, &message_neighbors->address); if (two_hop_neighbor_yet != NULL) { /* Updating the holding time for this neighbor */ olsr_set_timer(&two_hop_neighbor_yet->nbr2_list_timer, message->vtime, OLSR_NBR2_LIST_JITTER, OLSR_TIMER_ONESHOT, &olsr_expire_nbr2_list, two_hop_neighbor_yet, 0); two_hop_neighbor = two_hop_neighbor_yet->neighbor_2; /* * For link quality OLSR, reset the path link quality here. * The path link quality will be calculated in the second pass, below. * Keep the saved_path_link_quality for reference. */ if (olsr_cnf->lq_level > 0) { /* * loop through the one-hop neighbors that see this * 'two_hop_neighbor' */ struct neighbor_list_entry *walker; for (walker = two_hop_neighbor->neighbor_2_nblist.next; walker != &two_hop_neighbor->neighbor_2_nblist; walker = walker->next) { /* * have we found the one-hop neighbor that sent the * HELLO message that we're current processing? */ if (walker->neighbor == neighbor) { walker->path_linkcost = LINK_COST_BROKEN; } } } } else { two_hop_neighbor = olsr_lookup_two_hop_neighbor_table(&message_neighbors->address); if (two_hop_neighbor == NULL) { changes_neighborhood = true; changes_topology = true; two_hop_neighbor = olsr_malloc(sizeof(struct neighbor_2_entry), "Process HELLO"); two_hop_neighbor->neighbor_2_nblist.next = &two_hop_neighbor->neighbor_2_nblist; two_hop_neighbor->neighbor_2_nblist.prev = &two_hop_neighbor->neighbor_2_nblist; two_hop_neighbor->neighbor_2_pointer = 0; two_hop_neighbor->neighbor_2_addr = message_neighbors->address; olsr_insert_two_hop_neighbor_table(two_hop_neighbor); linking_this_2_entries(neighbor, two_hop_neighbor, message->vtime); } else { /* linking to this two_hop_neighbor entry */ changes_neighborhood = true; changes_topology = true; linking_this_2_entries(neighbor, two_hop_neighbor, message->vtime); } } } } /* Separate, second pass for link quality OLSR */ /* Separate, second and third pass for link quality OLSR */ if (olsr_cnf->lq_level > 0) { olsr_linkcost first_hop_pathcost; struct link_entry *lnk = get_best_link_to_neighbor(&neighbor->neighbor_main_addr); if (!lnk) return; /* calculate first hop path quality */ first_hop_pathcost = lnk->linkcost; /* * Second pass for link quality OLSR: calculate the best 2-hop * path costs to all the 2-hop neighbors indicated in the * HELLO message. Since the same 2-hop neighbor may be listed * more than once in the same HELLO message (each at a possibly * different quality) we want to select only the best one, not just * the last one listed in the HELLO message. */ for (message_neighbors = message->neighbors; message_neighbors != NULL; message_neighbors = message_neighbors->next) { if (if_ifwithaddr(&message_neighbors->address) != NULL) continue; if (((message_neighbors->status == SYM_NEIGH) || (message_neighbors->status == MPR_NEIGH))) { struct neighbor_list_entry *walker; struct neighbor_2_entry *two_hop_neighbor; struct neighbor_2_list_entry *two_hop_neighbor_yet = olsr_lookup_my_neighbors(neighbor, &message_neighbors->address); if (!two_hop_neighbor_yet) continue; two_hop_neighbor = two_hop_neighbor_yet->neighbor_2; /* * loop through the one-hop neighbors that see this * 'two_hop_neighbor' */ for (walker = two_hop_neighbor->neighbor_2_nblist.next; walker != &two_hop_neighbor->neighbor_2_nblist; walker = walker->next) { /* * have we found the one-hop neighbor that sent the * HELLO message that we're current processing? */ if (walker->neighbor == neighbor) { olsr_linkcost new_second_hop_linkcost, new_path_linkcost; // the link cost between the 1-hop neighbour and the // 2-hop neighbour new_second_hop_linkcost = message_neighbors->cost; // the total cost for the route // "us --- 1-hop --- 2-hop" new_path_linkcost = first_hop_pathcost + new_second_hop_linkcost; // Only copy the link quality if it is better than what we have // for this 2-hop neighbor if (new_path_linkcost < walker->path_linkcost) { walker->second_hop_linkcost = new_second_hop_linkcost; walker->path_linkcost = new_path_linkcost; walker->saved_path_linkcost = new_path_linkcost; changes_neighborhood = true; changes_topology = true; } } } } } } }