📄 bmf.c
字号:
walker->nBmfPacketsTx++; OLSR_PRINTF( 8, "%s: --> unpacked and forwarded on \"%s\"\n", PLUGIN_NAME_SHORT, walker->ifName); } } /* if (walker->olsrIntf == NULL) */ /* To an OLSR interface: forward the packet, but only if this node is * selected as MPR by the forwarding node */ else if (iAmMpr) { struct TBestNeighbors bestNeighborLinks; int nPossibleNeighbors; int nBytesWritten; int nPacketsToSend; int i; /* Retrieve at most two best neigbors to forward the packet to */ GetBestTwoNeighbors( &bestNeighborLinks, walker, &mcSrc, forwardedBy, forwardedTo, &nPossibleNeighbors); if (nPossibleNeighbors <= 0) { OLSR_PRINTF( 8, "%s: --> not forwarding on \"%s\": there is no neighbor that needs my retransmission\n", PLUGIN_NAME_SHORT, walker->ifName); continue; /* for */ } /* Compose destination of encapsulation packet. * Start by filling in the local broadcast address. */ COPY_IP(&forwardTo.sin_addr.s_addr, &walker->broadAddr); /* - If the BMF mechanism is BM_UNICAST_PROMISCUOUS, always send just one * packet (to the best neighbor). Other neighbors listen promiscuously. * - If the BMF mechanism is BM_BROADCAST, * - send one unicast packet if there is one possible neighbor, * - send two unicast packets if there are two possible neighbors, and * - only if there are more than two possible neighbors, then send an * (WLAN-air-expensive, less reliable) broadcast packet. */ if (BmfMechanism == BM_UNICAST_PROMISCUOUS || nPossibleNeighbors < 2) { nPacketsToSend = 1; } else /* BmfMechanism == BM_BROADCAST && nPossibleNeighbors >= 2 */ { nPacketsToSend = 2; } for (i = 0; i < nPacketsToSend; i++) { if (BmfMechanism == BM_UNICAST_PROMISCUOUS || nPossibleNeighbors <= 2) { /* For unicast, overwrite the local broadcast address which was filled in * above */ COPY_IP(&forwardTo.sin_addr.s_addr, &bestNeighborLinks.links[i]->neighbor_iface_addr); } /* Forward the BMF packet via the encapsulation socket */ nBytesWritten = sendto( walker->encapsulatingSkfd, encapsulationUdpData, encapsulationUdpDataLen, MSG_DONTROUTE, (struct sockaddr*) &forwardTo, sizeof(forwardTo)); /* Evaluate and display result */ if (nBytesWritten != encapsulationUdpDataLen) { BmfPError("sendto() error forwarding encapsulated pkt on \"%s\"", walker->ifName); } else { /* Increase counter */ walker->nBmfPacketsTx++; OLSR_PRINTF( 8, "%s: --> forwarded on \"%s\" to %s\n", PLUGIN_NAME_SHORT, walker->ifName, inet_ntoa(forwardTo.sin_addr)); } /* if */ } /* for */ } /* else if (iAmMpr) */ else /* walker->olsrIntf != NULL && !iAmMpr */ { /* 'walker' is an OLSR interface, but I am not selected as MPR. In that * case, don't forward. */ OLSR_PRINTF( 8, "%s: --> not forwarding on \"%s\": I am not selected as MPR by %s\n", PLUGIN_NAME_SHORT, walker->ifName, olsr_ip_to_string(forwardedBy)); } /* else */ } /* for */} /* BmfEncapsulationPacketReceived *//* ------------------------------------------------------------------------- * 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; ipPacket = GetIpPacket(encapsulationUdpData); ipPacketLen = GetIpTotalLength(ipPacket); ipHeader = GetIpHeader(encapsulationUdpData); /* Only forward multicast packets. If configured, also forward local broadcast packets */ COPY_IP(&dstIp, &ipHeader->ip_dst); broadAddr.v4 = htonl(EtherTunTapIpBroadcast); if (IsMulticast(&dstIp) || (EnableLocalBroadcast != 0 && COMP_IP(&dstIp, &broadAddr))) { /* continue */ } else { return; } COPY_IP(&srcIp, &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(&srcIp), olsr_ip_to_string(&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); } 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. */ 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 to non-OLSR \"%s\"\n", PLUGIN_NAME_SHORT, walker->ifName); } /* if */ } /* if */ } /* for */} /* BmfTunPacketCaptured *//* ------------------------------------------------------------------------- * Function : DoBmf * Description: Wait (blocking) for IP packets, then call the handler for each * received packet * Input : none * Output : none * Return : none * Data Used : BmfInterfaces * ------------------------------------------------------------------------- */static void DoBmf(void){ int nFdBitsSet; unsigned char rxBuffer[BMF_BUFFER_SIZE]; fd_set rxFdSet; assert(HighestSkfd >= 0); /* Make a local copy of the set of file descriptors that select() can * modify to indicate which descriptors actually changed status */ rxFdSet = InputSet; /* Wait (blocking) for packets received on any of the sockets. * NOTE: don't use a timeout (last parameter). It causes a high system CPU load! */ nFdBitsSet = select(HighestSkfd + 1, &rxFdSet, NULL, NULL, NULL); if (nFdBitsSet < 0) { if (errno != EINTR) { BmfPError("select() error"); } return; } while (nFdBitsSet > 0) { struct TBmfInterface* walker; /* Check if a packet was received on the capturing socket (if any) * of each network interface */ for (walker = BmfInterfaces; walker != NULL; walker = walker->next) { int skfd = walker->capturingSkfd; if (skfd >= 0 && (FD_ISSET(skfd, &rxFdSet))) { struct sockaddr_ll pktAddr; socklen_t addrLen = sizeof(pktAddr); int nBytes; unsigned char* ipPacket; /* A packet was captured. */ nFdBitsSet--; /* Receive the captured Ethernet frame, leaving space for the BMF * encapsulation header */ ipPacket = GetIpPacket(rxBuffer); nBytes = recvfrom( skfd, ipPacket, BMF_BUFFER_SIZE - ENCAP_HDR_LEN, 0, (struct sockaddr*)&pktAddr, &addrLen); if (nBytes < 0) { BmfPError("recvfrom() error on \"%s\"", walker->ifName); continue; /* for */ } /* if (nBytes < 0) */ /* Check if the number of received bytes is large enough for an IP * packet which contains at least a minimum-size IP header. * Note: There is an apparent bug in the packet socket implementation in * combination with VLAN interfaces. On a VLAN interface, the value returned * by 'recvfrom' may (but need not) be 4 (bytes) larger than the value * returned on a non-VLAN interface, for the same ethernet frame. */ if (nBytes < (int)sizeof(struct ip)) { olsr_printf( 1, "%s: captured frame too short (%d bytes) on \"%s\"\n", PLUGIN_NAME, nBytes, walker->ifName); continue; /* for */ } if (pktAddr.sll_pkttype == PACKET_OUTGOING || pktAddr.sll_pkttype == PACKET_MULTICAST || pktAddr.sll_pkttype == PACKET_BROADCAST) { /* A multicast or broadcast packet was captured */ BmfPacketCaptured(walker, pktAddr.sll_pkttype, rxBuffer); } /* if (pktAddr.sll_pkttype == ...) */ } /* if (skfd >= 0 && (FD_ISSET...)) */ } /* for */ /* Check if a BMF encapsulation packet was received on the listening * socket (if any) of each network interface */ for (walker = BmfInterfaces; walker != NULL; walker = walker->next) { int skfd = walker->listeningSkfd; if (skfd >= 0 && (FD_ISSET(skfd, &rxFdSet))) { struct sockaddr_ll pktAddr; socklen_t addrLen = sizeof(pktAddr); int nBytes; int minimumLength; struct ip* ipHeader; struct udphdr* udpHeader; u_int16_t destPort; union olsr_ip_addr forwardedBy; union olsr_ip_addr forwardedTo; /* Heard a BMF packet */ nFdBitsSet--; nBytes = recvfrom(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -