📄 bmf.c
字号:
skfd, rxBuffer, BMF_BUFFER_SIZE, 0, (struct sockaddr*)&pktAddr, &addrLen); if (nBytes < 0) { BmfPError("recvfrom() error on \"%s\"", walker->ifName); continue; /* for */ } /* if (nBytes < 0) */ /* Check if the received packet is actually directed to another * node on the LAN */ if (pktAddr.sll_pkttype != PACKET_OTHERHOST) { /* No, the packet is directed to this node. In that case it will * be, or will already have been received, via the encapsulating * socket. Discard it here. */ continue; /* for */ } /* if (pktAddr.sll_pkttype ...) */ /* Check if the received packet is UDP - BMF port */ ipHeader = (struct ip*)rxBuffer; if (ipHeader->ip_p != SOL_UDP) { /* Not UDP */ continue; /* for */ } udpHeader = (struct udphdr*)(rxBuffer + GetIpHeaderLength(rxBuffer)); destPort = ntohs(udpHeader->dest); if (destPort != BMF_ENCAP_PORT) { /* Not BMF */ continue; /* for */ } /* Check if the number of received bytes is large enough for a minimal BMF * encapsulation packet, at least: * - the IP header of the encapsulation IP packet * - the UDP header of the encapsulation IP packet * - the encapsulation header * - a minimum IP header inside the encapsulated packet * Note: 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. */ minimumLength = GetIpHeaderLength(rxBuffer) + sizeof(struct udphdr) + ENCAP_HDR_LEN + sizeof(struct ip); if (nBytes < minimumLength) { olsr_printf( 1, "%s: captured a too short encapsulation packet (%d bytes) on \"%s\"\n", PLUGIN_NAME, nBytes, walker->ifName); continue; /* for */ } COPY_IP(&forwardedBy, &ipHeader->ip_src); COPY_IP(&forwardedTo, &ipHeader->ip_dst); BmfEncapsulationPacketReceived( walker, &forwardedBy, &forwardedTo, rxBuffer + GetIpHeaderLength(rxBuffer) + sizeof(struct udphdr)); } /* if (skfd >= 0 && (FD_ISSET...)) */ } /* for */ /* Check if a packet was received on the encapsulating socket (if any) * of each network interface */ for (walker = BmfInterfaces; walker != NULL; walker = walker->next) { int skfd = walker->encapsulatingSkfd; if (skfd >= 0 && (FD_ISSET(skfd, &rxFdSet))) { struct sockaddr_in from; socklen_t fromLen = sizeof(from); int nBytes; int minimumLength; union olsr_ip_addr forwardedBy; /* An encapsulated packet was received */ nFdBitsSet--; nBytes = recvfrom( skfd, rxBuffer, BMF_BUFFER_SIZE, 0, (struct sockaddr*)&from, &fromLen); if (nBytes < 0) { BmfPError("recvfrom() error on \"%s\"", walker->ifName); continue; /* for */ } /* if (nBytes < 0) */ COPY_IP(&forwardedBy, &from.sin_addr.s_addr); /* Check if the number of received bytes is large enough for a minimal BMF * encapsulation packet, at least: * - the encapsulation header * - a minimum IP header inside the encapsulated packet */ minimumLength = ENCAP_HDR_LEN + sizeof(struct ip); if (nBytes < minimumLength) { olsr_printf( 1, "%s: received a too short encapsulation packet (%d bytes) from %s on \"%s\"\n", PLUGIN_NAME, nBytes, olsr_ip_to_string(&forwardedBy), walker->ifName); continue; /* for */ } /* Unfortunately, the recvfrom call does not return the destination * of the encapsulation packet (the destination may be either the * my unicast or my local broadcast address). Therefore we fill in 'NULL' * for the 'forwardedTo' parameter. */ BmfEncapsulationPacketReceived(walker, &forwardedBy, NULL, rxBuffer); } /* if (skfd >= 0 && (FD_ISSET...)) */ } /* for */ if (nFdBitsSet > 0 && FD_ISSET(EtherTunTapFd, &rxFdSet)) { /* Check if an application has sent a packet out via the tuntap * network interface */ int nBytes; unsigned char* ipPacket; unsigned char* bufferToRead; size_t nBytesToRead; nFdBitsSet--; /* Receive the packet, leaving space for the BMF encapsulation header */ ipPacket = GetIpPacket(rxBuffer); bufferToRead = ipPacket; nBytesToRead = BMF_BUFFER_SIZE - ENCAP_HDR_LEN; nBytes = read(EtherTunTapFd, bufferToRead, nBytesToRead); if (nBytes < 0) { BmfPError("recvfrom() error on \"%s\"", EtherTunTapIfName); } else { /* Check if the number of received bytes is large enough for an IP * packet which contains at least a minimum-size IP header */ if (nBytes < (int)sizeof(struct ip)) { olsr_printf( 1, "%s: captured packet too short (%d bytes) on \"%s\"\n", PLUGIN_NAME, nBytes, EtherTunTapIfName); } else { /* An outbound packet was captured */ BmfTunPacketCaptured(rxBuffer); } /* if (nBytes < ... */ } /* if (nBytes < 0) */ } /* if (nFdBitsSet > 0 && ... */ } /* while (nFdBitsSet > 0) */} /* DoBmf *//* ------------------------------------------------------------------------- * Function : BmfSignalHandler * Description: Signal handler function * Input : signo - signal being handled * Output : none * Return : none * Data Used : BmfThreadRunning * ------------------------------------------------------------------------- */static void BmfSignalHandler(int signo __attribute__((unused))){ BmfThreadRunning = 0;} /* BmfSignalHandler *//* ------------------------------------------------------------------------- * Function : BmfRun * Description: Receiver thread function * Input : useless - not used * Output : none * Return : not used * Data Used : BmfThreadRunning * Notes : Another thread can gracefully stop this thread by sending * a SIGALRM signal. * ------------------------------------------------------------------------- */static void* BmfRun(void* useless __attribute__((unused))){ /* Mask all signals except SIGALRM */ sigset_t blockedSigs; sigfillset(&blockedSigs); sigdelset(&blockedSigs, SIGALRM); if (pthread_sigmask(SIG_BLOCK, &blockedSigs, NULL) != 0) { BmfPError("pthread_sigmask() error"); } /* Set up the signal handler for the process: use SIGALRM to terminate * the BMF thread. Only if a signal handler is specified, does a blocking * system call return with errno set to EINTR; if a signal hander is not * specified, any system call in which the thread may be waiting will not * return. Note that the BMF thread is usually blocked in the select() * function (see DoBmf()). */ if (signal(SIGALRM, BmfSignalHandler) == SIG_ERR) { BmfPError("signal() error"); } /* Call the thread function until flagged to exit */ while (BmfThreadRunning != 0) { DoBmf(); } return NULL;} /* BmfRun *//* ------------------------------------------------------------------------- * Function : InterfaceChange * Description: Callback function passed to OLSRD for it to call whenever a * network interface has been added, removed or updated * Input : interf - the network interface to deal with * action - indicates if the specified network interface was * added, removed or updated. * Output : none * Return : always 0 * Data Used : none * ------------------------------------------------------------------------- */int InterfaceChange(struct interface* interf, int action){ switch (action) { case (IFCHG_IF_ADD): AddInterface(interf); olsr_printf(1, "%s: interface %s added\n", PLUGIN_NAME, interf->int_name); break; case (IFCHG_IF_REMOVE): /* We cannot just remove the interface, because the receive-thread is likely * to be waiting in select(...) for packets coming in via the interface. * Therefore we first close BMF (CloseBmf()), interrupting and kiling the * receive-thread so that it is safe to remove this (and all other) * interfaces. After that, BMF is re-started (InitBmf(interf)). */ CloseBmf(); InitBmf(interf); olsr_printf(1, "%s: interface %s removed\n", PLUGIN_NAME, interf->int_name); break; case (IFCHG_IF_UPDATE): olsr_printf(1, "%s: interface %s updated\n", PLUGIN_NAME, interf->int_name); break; default: olsr_printf( 1, "%s: interface %s: error - unknown action (%d)\n", PLUGIN_NAME, interf->int_name, action); break; } return 0;} /* InterfaceChange *//* ------------------------------------------------------------------------- * Function : InitBmf * Description: Initialize the BMF plugin * Input : skipThisIntf - specifies which network interface should not * be enabled for BMF. Pass NULL if not applicable. * Output : none * Return : fail (0) or success (1) * Data Used : BmfThreadRunning, BmfThread * ------------------------------------------------------------------------- */int InitBmf(struct interface* skipThisIntf){ CreateBmfNetworkInterfaces(skipThisIntf); /* Start running the multicast packet processing thread */ BmfThreadRunning = 1; if (pthread_create(&BmfThread, NULL, BmfRun, NULL) != 0) { BmfPError("pthread_create() error"); return 0; } if (EtherTunTapFd >= 0) { /* Deactivate IP spoof filter for EtherTunTap interface */ DeactivateSpoofFilter(); /* If the BMF network interface has a sensible IP address, it is a good idea * to route all multicast traffic through that interface */ if (EtherTunTapIp != ETHERTUNTAPDEFAULTIP) { AddMulticastRoute(); } } return 1;} /* InitBmf *//* ------------------------------------------------------------------------- * Function : CloseBmf * Description: Close the BMF plugin and clean up * Input : none * Output : none * Return : none * Data Used : BmfThread * ------------------------------------------------------------------------- */void CloseBmf(void){ if (EtherTunTapFd >= 0) { /* If there is a multicast route, try to delete it first */ DeleteMulticastRoute(); /* Restore IP spoof filter for EtherTunTap interface */ RestoreSpoofFilter(); } if (BmfThreadRunning) { /* Signal BmfThread to exit */ /* Strangely enough, all running threads receive the SIGALRM signal. But only the * BMF thread is affected by this signal, having specified a handler for this * signal in its thread entry function BmfRun(...). */ if (pthread_kill(BmfThread, SIGALRM) != 0) { BmfPError("pthread_kill() error"); } /* Wait for BmfThread to acknowledge */ if (pthread_join(BmfThread, NULL) != 0) { BmfPError("pthread_join() error"); } } /* Clean up after the BmfThread has been killed */ CloseBmfNetworkInterfaces();} /* CloseBmf */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -