📄 bmf.c
字号:
* 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 */ { 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(&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); } } /* if (isFromOlsrIntf && isToOlsrIntf) */ else if (isFromOlsrIntf && !isToOlsrIntf) { /* Case 2: Forward from OLSR interface to non-OLSR interface */ int nBytesWritten; struct sockaddr_ll dest; /* If the encapsulated IP packet is a local broadcast packet, * update its destination address to match the subnet of the network * interface on which the packet is being sent. */ CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr); memset(&dest, 0, sizeof(dest)); dest.sll_family = AF_PACKET; dest.sll_protocol = htons(ETH_P_IP); dest.sll_ifindex = if_nametoindex(walker->ifName); dest.sll_halen = IFHWADDRLEN; /* Use all-ones as destination MAC address. When the IP destination is * a multicast address, the destination MAC address should normally also * be a multicast address. E.g., when the destination IP is 224.0.0.1, * the destination MAC should be 01:00:5e:00:00:01. However, it does not * seem to matter when the destination MAC address is set to all-ones * in that case. */ memset(dest.sll_addr, 0xFF, IFHWADDRLEN); nBytesWritten = sendto( walker->capturingSkfd, ipPacket, ipPacketLen, 0, (struct sockaddr*) &dest, sizeof(dest)); if (nBytesWritten != ipPacketLen) { BmfPError("sendto() error forwarding pkt on \"%s\"", walker->ifName); } else { /* Increase counter */ walker->nBmfPacketsTx++; OLSR_PRINTF(8, "%s: --> forwarded on \"%s\"\n", PLUGIN_NAME_SHORT, walker->ifName); } } /* 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); } /* 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 { int nBytesWritten; struct sockaddr_ll dest; /* If the encapsulated IP packet is a local broadcast packet, * update its destination address to match the subnet of the network * interface on which the packet is being sent. */ CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr); memset(&dest, 0, sizeof(dest)); dest.sll_family = AF_PACKET; dest.sll_protocol = htons(ETH_P_IP); dest.sll_ifindex = if_nametoindex(walker->ifName); dest.sll_halen = IFHWADDRLEN; /* Use all-ones as destination MAC address. When the IP destination is * a multicast address, the destination MAC address should normally also * be a multicast address. E.g., when the destination IP is 224.0.0.1, * the destination MAC should be 01:00:5e:00:00:01. However, it does not * seem to matter when the destination MAC address is set to all-ones * in that case. */ memset(dest.sll_addr, 0xFF, IFHWADDRLEN); nBytesWritten = sendto( walker->capturingSkfd, ipPacket, ipPacketLen, 0, (struct sockaddr*) &dest, sizeof(dest)); if (nBytesWritten != ipPacketLen) { BmfPError("sendto() error forwarding pkt on \"%s\"", walker->ifName); } else { /* Increase counter */ walker->nBmfPacketsTx++; OLSR_PRINTF( 8, "%s: --> forwarded from non-OLSR on non-OLSR \"%s\"\n", PLUGIN_NAME_SHORT, walker->ifName); } } /* if (intf == walker) */ } /* if */ } /* for */} /* BmfPacketCaptured *//* ------------------------------------------------------------------------- * Function : BmfEncapsulationPacketReceived * Description: Handle a received BMF-encapsulation packet * Input : intf - the network interface on which the packet was received * forwardedBy - the IP node that forwarded the packet to me * forwardedTo - the destination IP address of the encapsulation * packet, in case the packet was received promiscuously. * Pass NULL if the packet is received normally (unicast or * broadcast). * encapsulationUdpData - the encapsulating IP UDP data, containting * the BMF encapsulation header, followed by the encapsulated * IP packet * Output : none * Return : none * Data Used : BmfInterfaces * ------------------------------------------------------------------------- */static void BmfEncapsulationPacketReceived( struct TBmfInterface* intf, union olsr_ip_addr* forwardedBy, union olsr_ip_addr* forwardedTo, unsigned char* encapsulationUdpData){ int iAmMpr; /* True (1) if I am selected as MPR by 'forwardedBy' */ struct sockaddr_in forwardTo; /* Next destination of encapsulation packet */ unsigned char* ipPacket; /* The encapsulated IP packet */ u_int16_t ipPacketLen; /* Length of the encapsulated IP packet */ struct ip* ipHeader; /* IP header inside the encapsulated IP packet */ union olsr_ip_addr mcSrc; /* Original source of the encapsulated multicast packet */ union olsr_ip_addr mcDst; /* Multicast destination of the encapsulated packet */ struct TEncapHeader* encapsulationHdr; u_int16_t encapsulationUdpDataLen; struct TBmfInterface* walker; /* Are we talking to ourselves? */ if (if_ifwithaddr(forwardedBy) != NULL) { return; } /* Discard encapsulated packets received on a non-OLSR interface */ if (intf->olsrIntf == NULL) { return; } /* Retrieve details about the encapsulated IP packet */ ipPacket = GetIpPacket(encapsulationUdpData); ipPacketLen = GetIpTotalLength(ipPacket); ipHeader = GetIpHeader(encapsulationUdpData); COPY_IP(&mcSrc, &ipHeader->ip_src); COPY_IP(&mcDst, &ipHeader->ip_dst); /* Increase counter */ intf->nBmfPacketsRx++; /* Beware: not possible to call olsr_ip_to_string more than 4 times in same printf */ OLSR_PRINTF( 8, "%s: encapsulated pkt of %ld bytes incoming on \"%s\": %s->%s, forwarded by %s to %s\n", PLUGIN_NAME_SHORT, (long)ipPacketLen, intf->ifName, olsr_ip_to_string(&mcSrc), olsr_ip_to_string(&mcDst), olsr_ip_to_string(forwardedBy), forwardedTo != NULL ? olsr_ip_to_string(forwardedTo) : "me"); /* Get encapsulation header */ encapsulationHdr = (struct TEncapHeader*) encapsulationUdpData; /* Verify correct format of BMF encapsulation header */ if (encapsulationHdr->type != BMF_ENCAP_TYPE || encapsulationHdr->len != BMF_ENCAP_LEN || ntohs(encapsulationHdr->reserved != 0)) { OLSR_PRINTF( 8, "%s: --> discarding: format of BMF encapsulation header not recognized\n", PLUGIN_NAME_SHORT); return; } /* Check if this packet was seen recently */ if (CheckAndMarkRecentPacket(ntohl(encapsulationHdr->crc32))) { /* Increase counter */ intf->nBmfPacketsRxDup++; OLSR_PRINTF( 8, "%s: --> discarding: packet is duplicate\n", PLUGIN_NAME_SHORT); return; } if (EtherTunTapFd >= 0) { /* Unpack the encapsulated IP packet and deliver it locally, by sending * a copy into the local IP stack via the EtherTunTap interface */ union olsr_ip_addr broadAddr; int nBytesToWrite, nBytesWritten; unsigned char* bufferToWrite; /* If the encapsulated IP packet is a local broadcast packet, * update its destination address to match the subnet of the EtherTunTap * interface */ broadAddr.v4 = htonl(EtherTunTapIpBroadcast); CheckAndUpdateLocalBroadcast(ipPacket, &broadAddr); bufferToWrite = ipPacket; nBytesToWrite = ipPacketLen; /* Write the packet into the EtherTunTap interface for local delivery */ nBytesWritten = write(EtherTunTapFd, bufferToWrite, nBytesToWrite); if (nBytesWritten != nBytesToWrite) { BmfPError("write() error forwarding encapsulated pkt on \"%s\"", EtherTunTapIfName); } else { OLSR_PRINTF( 8, "%s: --> unpacked and delivered locally on \"%s\"\n", PLUGIN_NAME_SHORT, EtherTunTapIfName); } } /* if (EtherTunTapFd >= 0) */ /* Check if I am MPR for the forwarder */ /* TODO: olsr_lookup_mprs_set() is not thread-safe! */ iAmMpr = (olsr_lookup_mprs_set(MainAddressOf(forwardedBy)) != NULL); /* Compose destination address for next hop */ memset(&forwardTo, 0, sizeof(forwardTo)); forwardTo.sin_family = AF_INET; forwardTo.sin_port = htons(BMF_ENCAP_PORT); /* Retrieve the number of bytes to be forwarded via the encapsulation socket */ encapsulationUdpDataLen = GetEncapsulationUdpDataLength(encapsulationUdpData); /* Check with each network interface what needs to be done on it */ for (walker = BmfInterfaces; walker != NULL; walker = walker->next) { /* What to do with the packet on a non-OLSR interface? Unpack * encapsulated packet, and forward it. * * What to do with the packet on an OLSR interface? Forward it only * if the forwarding node has selected us as MPR (iAmMpr). * * Note that the packet is always coming in on an OLSR interface, because * it is an encapsulated BMF packet. */ /* To a non-OLSR interface: unpack the encapsulated IP packet and forward it */ if (walker->olsrIntf == NULL) { int nBytesWritten; struct sockaddr_ll dest; /* If the encapsulated IP packet is a local broadcast packet, * update its destination address to match the subnet of the network * interface on which the packet is being sent. */ CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr); memset(&dest, 0, sizeof(dest)); dest.sll_family = AF_PACKET; dest.sll_protocol = htons(ETH_P_IP); dest.sll_ifindex = if_nametoindex(walker->ifName); dest.sll_halen = IFHWADDRLEN; /* Use all-ones as destination MAC address. When the IP destination is * a multicast address, the destination MAC address should normally also * be a multicast address. E.g., when the destination IP is 224.0.0.1, * the destination MAC should be 01:00:5e:00:00:01. However, it does not * seem to matter when the destination MAC address is set to all-ones * in that case. */ memset(dest.sll_addr, 0xFF, IFHWADDRLEN); nBytesWritten = sendto( walker->capturingSkfd, ipPacket, ipPacketLen, 0, (struct sockaddr*) &dest, sizeof(dest)); if (nBytesWritten != ipPacketLen) { BmfPError("sendto() error forwarding unpacked encapsulated pkt on \"%s\"", walker->ifName); } else { /* Increase counter */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -