⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bmf.c

📁 wifi 无线网络路由协议OLSR linux下C代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * OLSR Basic Multicast Forwarding (BMF) plugin. * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands. * Written by Erik Tromp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met: * * * Redistributions of source code must retain the above copyright  *   notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright  *   notice, this list of conditions and the following disclaimer in  *   the documentation and/or other materials provided with the  *   distribution. * * Neither the name of Thales, BMF nor the names of its  *   contributors may be used to endorse or promote products derived  *   from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  * OF THE POSSIBILITY OF SUCH DAMAGE. *//* ------------------------------------------------------------------------- * File       : Bmf.c * Description: Multicast forwarding functions * Created    : 29 Jun 2006 * * ------------------------------------------------------------------------- */#define _MULTI_THREADED#include "Bmf.h"/* System includes */#include <stddef.h> /* NULL */#include <sys/types.h> /* ssize_t */#include <string.h> /* strerror() */#include <stdarg.h> /* va_list, va_start, va_end */#include <errno.h> /* errno */#include <assert.h> /* assert() */#include <linux/if_ether.h> /* ETH_P_IP */#include <linux/if_packet.h> /* struct sockaddr_ll, PACKET_MULTICAST */#include <pthread.h> /* pthread_t, pthread_create() */#include <signal.h> /* sigset_t, sigfillset(), sigdelset(), SIGINT */#include <netinet/ip.h> /* struct ip */#include <netinet/udp.h> /* struct udphdr *//* OLSRD includes */#include "defs.h" /* olsr_cnf, OLSR_PRINTF */#include "olsr.h" /* olsr_printf */#include "scheduler.h" /* olsr_register_scheduler_event */#include "mid_set.h" /* mid_lookup_main_addr() */#include "mpr_selector_set.h" /* olsr_lookup_mprs_set() */#include "link_set.h" /* get_best_link_to_neighbor() *//* BMF includes */#include "NetworkInterfaces.h" /* TBmfInterface, CreateBmfNetworkInterfaces(), CloseBmfNetworkInterfaces() */#include "Address.h" /* IsMulticast() */#include "Packet.h" /* ENCAP_HDR_LEN, BMF_ENCAP_TYPE, BMF_ENCAP_LEN etc. */#include "PacketHistory.h" /* InitPacketHistory() */static pthread_t BmfThread;static int BmfThreadRunning = 0;/* ------------------------------------------------------------------------- * Function   : BmfPError * Description: Prints an error message at OLSR debug level 1. *              First the plug-in name is printed. Then (if format is not NULL *              and *format is not empty) the arguments are printed, followed *              by a colon and a blank. Then the message and a new-line. * Input      : format, arguments * Output     : none * Return     : none * Data Used  : none * ------------------------------------------------------------------------- */void BmfPError(char* format, ...){#define MAX_STR_DESC 255  char* strErr = strerror(errno);  char strDesc[MAX_STR_DESC];  /* Rely on short-circuit boolean evaluation */  if (format == NULL || *format == '\0')  {    olsr_printf(1, "%s: %s\n", PLUGIN_NAME, strErr);  }  else  {    va_list arglist;    olsr_printf(1, "%s: ", PLUGIN_NAME);    va_start(arglist, format);    vsnprintf(strDesc, MAX_STR_DESC, format, arglist);    va_end(arglist);    strDesc[MAX_STR_DESC - 1] = '\0'; /* Ensures null termination */    olsr_printf(1, "%s: %s\n", strDesc, strErr);  }} /* BmfPError *//* ------------------------------------------------------------------------- * Function   : MainAddressOf * Description: Lookup the main address of a node * Input      : ip - IP address of the node * Output     : none * Return     : The main IP address of the node * Data Used  : none * ------------------------------------------------------------------------- */union olsr_ip_addr* MainAddressOf(union olsr_ip_addr* ip){  union olsr_ip_addr* result;  /* TODO: mid_lookup_main_addr() is not thread-safe! */  result = mid_lookup_main_addr(ip);  if (result == NULL)  {    result = ip;  }  return result;} /* MainAddressOf *//* ------------------------------------------------------------------------- * Function   : EncapsulateAndForwardPacket * Description: Encapsulate a captured raw IP packet and forward it * Input      : intf - the network interface on which to forward the packet *              encapsulationUdpData - The encapsulation header, followed by *                the encapsulated IP packet * Output     : none * Return     : none * Data Used  : none * ------------------------------------------------------------------------- */static void EncapsulateAndForwardPacket(  struct TBmfInterface* intf,  unsigned char* encapsulationUdpData){  /* The packet */  u_int16_t udpDataLen = GetEncapsulationUdpDataLength(encapsulationUdpData);  /* The next destination(s) */  struct TBestNeighbors bestNeighborLinks;  int nPossibleNeighbors;  struct sockaddr_in forwardTo; /* Next destination of encapsulation packet */  int nPacketsToSend;  int nBytesWritten;  int i;  /* Retrieve at most two best neigbors to forward the packet to */  GetBestTwoNeighbors(&bestNeighborLinks, intf, NULL, NULL, NULL, &nPossibleNeighbors);  if (nPossibleNeighbors <= 0)  {    OLSR_PRINTF(      8,      "%s: --> not encap-forwarding on \"%s\": there is no neighbor that needs my retransmission\n",      PLUGIN_NAME_SHORT,      intf->ifName);    return;  }  /* Compose destination of encapsulation packet */  memset(&forwardTo, 0, sizeof(forwardTo));  forwardTo.sin_family = AF_INET;  forwardTo.sin_port = htons(BMF_ENCAP_PORT);  /* Start by filling in the local broadcast address */  COPY_IP(&forwardTo.sin_addr.s_addr, &intf->broadAddr);  /* - If the BMF mechanism is BM_UNICAST_PROMISCUOUS, always send just one   *   packet (to the best neighbor).   * - 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)    {      COPY_IP(&forwardTo.sin_addr.s_addr, &bestNeighborLinks.links[i]->neighbor_iface_addr);    }    /* Forward the BMF packet via the encapsulation socket */    nBytesWritten = sendto(      intf->encapsulatingSkfd,      encapsulationUdpData,      udpDataLen,      MSG_DONTROUTE,      (struct sockaddr*) &forwardTo,      sizeof(forwardTo));                       /* Evaluate and display result */    if (nBytesWritten != udpDataLen)    {      BmfPError("sendto() error forwarding pkt on \"%s\"", intf->ifName);    }    else    {      /* Increase counter */      intf->nBmfPacketsTx++;      OLSR_PRINTF(        8,        "%s: --> encapsulated and forwarded on \"%s\" to %s\n",        PLUGIN_NAME_SHORT,        intf->ifName,        inet_ntoa(forwardTo.sin_addr));    } /* if (nBytesWritten != udpDataLen) */  } /* for */} /* EncapsulateAndForwardPacket *//* ------------------------------------------------------------------------- * 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;  ipHeader = GetIpHeader(encapsulationUdpData);  COPY_IP(&dst, &ipHeader->ip_dst);  /* Only forward multicast packets. If configured, also forward local broadcast packets */  if (IsMulticast(&dst) ||      (EnableLocalBroadcast != 0 && COMP_IP(&dst, &intf->broadAddr)))  {    /* continue */  }  else  {    return;  }  ipPacket = GetIpPacket(encapsulationUdpData);  /* Don't forward fragments of IP packets. 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);  COPY_IP(&src, &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(&src),    olsr_ip_to_string(&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.   * TODO1: get_best_link_to_neighbor() is not thread-safe.   * TODO2: 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 */  /* TODO: olsr_lookup_mprs_set() is not thread-safe! */  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*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -