Add p2dp plugin (generalized mdns), thanks to Teco Boot <teco@inf-net.nl>
authorHenning Rogge <hrogge@googlemail.com>
Sun, 7 Mar 2010 13:46:50 +0000 (14:46 +0100)
committerHenning Rogge <hrogge@googlemail.com>
Sun, 7 Mar 2010 13:46:50 +0000 (14:46 +0100)
13 files changed:
lib/p2pd/Makefile [new file with mode: 0644]
lib/p2pd/README [new file with mode: 0644]
lib/p2pd/src/NetworkInterfaces.c [new file with mode: 0644]
lib/p2pd/src/NetworkInterfaces.h [new file with mode: 0644]
lib/p2pd/src/Packet.c [new file with mode: 0644]
lib/p2pd/src/Packet.h [new file with mode: 0644]
lib/p2pd/src/dllist.c [new file with mode: 0644]
lib/p2pd/src/dllist.h [new file with mode: 0644]
lib/p2pd/src/olsrd_plugin.c [new file with mode: 0644]
lib/p2pd/src/p2pd.c [new file with mode: 0644]
lib/p2pd/src/p2pd.h [new file with mode: 0644]
lib/p2pd/src/version-script.txt [new file with mode: 0644]
lib/p2pd/version-script.txt [new file with mode: 0644]

diff --git a/lib/p2pd/Makefile b/lib/p2pd/Makefile
new file mode 100644 (file)
index 0000000..e0157fb
--- /dev/null
@@ -0,0 +1,33 @@
+
+OLSRD_PLUGIN = true
+PLUGIN_NAME =  olsrd_p2pd
+PLUGIN_VER =   0.1.0
+
+TOPDIR = ../..
+include $(TOPDIR)/Makefile.inc
+
+LIBS +=        $(OS_LIB_PTHREAD)
+
+# Must be specified along with -lpthread on linux
+CPPFLAGS += $(OS_CFLAG_PTHREAD)
+
+ifneq ($(OS),linux)
+
+default_target install clean:
+       @echo "*** p2pd Plugin only supported on Linux, sorry!"
+
+else
+
+default_target: $(PLUGIN_FULLNAME)
+
+$(PLUGIN_FULLNAME): $(OBJS) version-script.txt
+               $(CC) $(LDFLAGS) -o $(PLUGIN_FULLNAME) $(OBJS) $(LIBS)
+
+install:       $(PLUGIN_FULLNAME)
+               $(STRIP) $(PLUGIN_FULLNAME)
+               $(INSTALL_LIB)
+
+clean:
+               rm -f $(OBJS) $(SRCS:%.c=%.d) $(PLUGIN_FULLNAME)
+
+endif
diff --git a/lib/p2pd/README b/lib/p2pd/README
new file mode 100644 (file)
index 0000000..c89f292
--- /dev/null
@@ -0,0 +1,116 @@
+= OLSR P2PD plugin =
+
+This README file is the main documentation source for the OLSR P2PD plugin
+
+Last update 01/03/2010
+
+== Description ==
+
+This plugin goal is the distribution of Peer to Peer Discovery messages over an
+OLSR Wireless Mesh Network.
+
+In a wireless mesh network, the usage of wireless interfaces in ad-hoc mode and
+the OLSR routing protocol prevent UDP messages to be distributed all over the
+network.
+
+We are especially interested in the distribution of UDP messages, used for host-
+based service discovery, over the networks that do not directly participate in
+the OLSR mesh cloud.
+
+This task is achieved in the following way: 
+ 1. the local router picks up from the local non-OLSR (HNA) network UDP messages
+    and encapsulates them in a new type of OLSR messages,
+ 2. the OLSR infrastructure is exploited for the transport of these messages,
+ 3. remote routers decapsulate UDP messages from received OLSR messages and send
+    them over their attached non-OLSR networks.
+
+The work could have its practical and immediate application in wireless network
+communities that employ the OLSR protocol.
+
+The plugin captures the traffic (only IPv4 if OLSR is running IPv4 and only IPv6
+if OLSR is running IPv6) and encapsulates this traffic in OLSR messages that are
+forwarded to all the other nodes in the mesh.
+
+Other nodes running the plugin will decapsulate the packets and will send them
+to the interfaces specified in the configuration file
+
+Let's get this example topology
+
+pc1->eth0 ----- eth0<-r1->ath0 -------ath0<-r2->eth0 ---------eth0<-pc2
+
+r1 and r2 are OLSR routers with p2pd plugin enabled. pc1 will be able to receive
+UDP traffic generated at pc2 and vice versa
+
+The most interesting feature is that messages are forwarded also by OLSR routers
+without the plugin. For example:
+
+pc1->eth0 ----- eth0<-r1->ath0 ---r3----ath0<-r2->eth0 ---------eth0<-pc2
+
+also in this topology UDP traffic between pc1 and pc2 is possible because r3
+forwards UDP plugin OLSR packets even if it is not aware of the new application.
+
+== Configuration ==
+
+To enable the Plugin use the following syntax
+
+LoadPlugin "olsrd_p2pd.so.0.1.0"
+{
+# Specify interfaces where the hosts running Peer to Peer applications are
+# attached
+PlParam     "NonOlsrIf"   "eth0"
+PlParam     "NonOlsrIf"   "eth1"
+# P2pdTtl is the time to live given to the P2PD OLSR messages
+PlParam     "P2pdTtl"     "5"
+# Specify the UDP destination address/port for P2P node discovery
+# Allowed: IPv4 broadcast and multicast, IPv6 multicast only
+#   MS Groove
+PlParam     "UdpDestPort" "255.255.255.255 1211"
+#   MDNS multicast (draft-cheshire-dnsext-multicastdns)
+PlParam     "UdpDestPort" "224.0.0.251 5353"
+}
+
+Where eth0 and eth1 are the names of the interfaces where you want to capture
+traffic (and decapsulate incoming traffic).
+
+Note that this interfaces must not talk OLSR and also the subnets on this
+interfaces must be announced with an appropriate HNA entry.
+This version of the plugin will not chech this stuff to be properly configured!
+
+P2pdTtl is the time to live given to the P2PD OLSR messages. It makes no sense
+to announce your services to hosts that are too many hops away, because they
+will experience a very bad unicast connection.
+With this TTL setting we can tune how far we announce our services and we make
+the protocol scale much better
+
+=== References ===
+
+ * OLSR Optimized Link State Routing:
+     [http://tools.ietf.org/html/rfc3626 IETF RFC 3626]
+
+=== Contact ===
+ * Caspar van Zon CHW.van.Zon@mindef.nl
+
+Revision history
+================
+
+01/03/2010 - Changes relative to olsr_mdns plug-in which was used as a base
+ * A new plug-in called olsrd_p2pd has been created based on the olsrd_mdns
+   plug-in.
+ * The initial version number for this plug-in has been set to v 0.1.0
+ * A parameter 'UdpDestPort' was added to allow for specification of a UDP IP
+   address/port pair.
+ * A number of obsolete functions have been removed from the source to decrease
+   the plug-in footprint.
+ * A mechanism has been added to check whether duplicate messages are received
+   and to allow them to be filtered out of the message stream. This is a new
+   mechanism and not the one provided within OLSR because the old mechanism
+   seems to hold a single list and this should not be contaminated. At this time
+   the list holds tuples with information conforming draft-ietf-manet-olsrv2-10.
+   Older non-duplicate messages are forwarded to NonOlsrIf interfaces.
+ * Some of the return values in the olsr_parser function (p2pdc) have been
+   changed so the related messages will not be forwarded if that is not
+   desired.
+ * Fragmented packets not supported.
+ * TTL for outgoing packets are not modified.
+ * Parameter 'UdpDestPort' is checked so only IPv4 broadcast and multicast and
+   IPv6 multicast values are allowed as the destination address.
\ No newline at end of file
diff --git a/lib/p2pd/src/NetworkInterfaces.c b/lib/p2pd/src/NetworkInterfaces.c
new file mode 100644 (file)
index 0000000..c767b16
--- /dev/null
@@ -0,0 +1,555 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
+ * 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 olsr.org, olsrd 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.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+
+
+#include "NetworkInterfaces.h"
+
+/* System includes */
+#include <stddef.h>             /* NULL */
+#include <syslog.h>             /* syslog() */
+#include <string.h>             /* strerror(), strchr(), strcmp() */
+#include <errno.h>              /* errno */
+#include <unistd.h>             /* close() */
+#include <sys/ioctl.h>          /* ioctl() */
+#include <fcntl.h>              /* fcntl() */
+#include <assert.h>             /* assert() */
+#include <net/if.h>             /* socket(), ifreq, if_indextoname(), if_nametoindex() */
+#include <netinet/in.h>         /* htons() */
+#include <linux/if_ether.h>     /* ETH_P_IP */
+#include <linux/if_packet.h>    /* packet_mreq, PACKET_MR_PROMISC, PACKET_ADD_MEMBERSHIP */
+#include <linux/if_tun.h>       /* IFF_TAP */
+#include <netinet/ip.h>         /* struct ip */
+#include <netinet/udp.h>        /* SOL_UDP */
+#include <stdlib.h>             /* atoi, malloc */
+
+/* OLSRD includes */
+#include "olsr.h"               /* OLSR_PRINTF() */
+#include "ipcalc.h"
+#include "defs.h"               /* olsr_cnf */
+#include "link_set.h"           /* get_link_set() */
+#include "tc_set.h"             /* olsr_lookup_tc_entry(), olsr_lookup_tc_edge() */
+#include "net_olsr.h"           /* ipequal */
+#include "lq_plugin.h"
+//#include "olsr_ip_prefix_list.h"
+
+/* Plugin includes */
+#include "Packet.h"             /* IFHWADDRLEN */
+#include "p2pd.h"               /* PLUGIN_NAME, MainAddressOf() */
+//#include "Address.h"            /* IsMulticast() */
+
+
+/* List of network interface objects used by BMF plugin */
+struct NonOlsrInterface *nonOlsrInterfaces = NULL;
+struct NonOlsrInterface *lastNonOlsrInterface = NULL;
+
+/* -------------------------------------------------------------------------
+ * Function   : CreateCaptureSocket
+ * Description: Create socket for promiscuously capturing multicast IP traffic
+ * Input      : ifname - network interface (e.g. "eth0")
+ * Output     : none
+ * Return     : the socket descriptor ( >= 0), or -1 if an error occurred
+ * Data Used  : none
+ * Notes      : The socket is a cooked IP packet socket, bound to the specified
+ *              network interface
+ * ------------------------------------------------------------------------- */
+int
+CreateCaptureSocket(const char *ifName)
+{
+  int ifIndex = if_nametoindex(ifName);
+  struct packet_mreq mreq;
+  struct ifreq req;
+  struct sockaddr_ll bindTo;
+  int skfd = 0;
+  /* Open cooked IP packet socket */
+  if (olsr_cnf->ip_version == AF_INET) {
+    skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP));
+  } else {
+    skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6));
+  }
+  if (skfd < 0) {
+    P2pdPError("socket(PF_PACKET) error");
+    return -1;
+  }
+
+  /* Set interface to promiscuous mode */
+  memset(&mreq, 0, sizeof(struct packet_mreq));
+  mreq.mr_ifindex = ifIndex;
+  mreq.mr_type = PACKET_MR_PROMISC;
+  if (setsockopt(skfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
+    P2pdPError("setsockopt(PACKET_MR_PROMISC) error");
+    close(skfd);
+    return -1;
+  }
+
+  /* Get hardware (MAC) address */
+  memset(&req, 0, sizeof(struct ifreq));
+  strncpy(req.ifr_name, ifName, IFNAMSIZ - 1);
+  req.ifr_name[IFNAMSIZ - 1] = '\0';    /* Ensures null termination */
+  if (ioctl(skfd, SIOCGIFHWADDR, &req) < 0) {
+    P2pdPError("error retrieving MAC address");
+    close(skfd);
+    return -1;
+  }
+
+  /* Bind the socket to the specified interface */
+  memset(&bindTo, 0, sizeof(bindTo));
+  bindTo.sll_family = AF_PACKET;
+  if (olsr_cnf->ip_version == AF_INET) {
+    bindTo.sll_protocol = htons(ETH_P_IP);
+  } else {
+    bindTo.sll_protocol = htons(ETH_P_IPV6);
+  }
+  bindTo.sll_ifindex = ifIndex;
+  memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
+  bindTo.sll_halen = IFHWADDRLEN;
+
+  if (bind(skfd, (struct sockaddr *)&bindTo, sizeof(bindTo)) < 0) {
+    P2pdPError("bind() error");
+    close(skfd);
+    return -1;
+  }
+
+  /* Set socket to blocking operation */
+  if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0) {
+    P2pdPError("fcntl() error");
+    close(skfd);
+    return -1;
+  }
+  //AddDescriptorToInputSet(skfd);
+  add_olsr_socket(skfd, (socket_handler_func)&DoP2pd, NULL, NULL, SP_PR_READ);
+
+  return skfd;
+}                               /* CreateCaptureSocket */
+
+/* -------------------------------------------------------------------------
+ * Function   : CreateInterface
+ * Description: Create a new NonOlsrInterface object and adds it to the global
+ *              nonOlsrInterfaces list
+ * Input      : ifName - name of the network interface (e.g. "eth0")
+ *            : olsrIntf - OLSR interface object of the network interface, or
+ *                NULL if the network interface is not OLSR-enabled
+ * Output     : none
+ * Return     : the number of opened sockets
+ * Data Used  : nonOlsrInterfaces, lastNonOlsrInterface
+ * ------------------------------------------------------------------------- */
+
+//FOR MDNS IS ALWAYS CALLED WITH NULL AS SECOND ARG
+
+static int
+CreateInterface(const char *ifName, struct interface *olsrIntf)
+{
+  int capturingSkfd = -1;
+  int encapsulatingSkfd = -1;
+  int listeningSkfd = -1;
+  int ioctlSkfd;
+  struct ifreq ifr;
+  int nOpened = 0;
+  struct NonOlsrInterface *newIf = malloc(sizeof(struct NonOlsrInterface));
+
+  assert(ifName != NULL);
+
+  if (newIf == NULL) {
+    return 0;
+  }
+//TODO: assert interface is not talking OLSR
+
+
+  /* Create socket for capturing and sending of multicast packets on
+   * non-OLSR interfaces, and on OLSR-interfaces if configured. */
+  if ((olsrIntf == NULL)) {
+    capturingSkfd = CreateCaptureSocket(ifName);
+    if (capturingSkfd < 0) {
+      close(encapsulatingSkfd);
+      free(newIf);
+      return 0;
+    }
+
+    nOpened++;
+  }
+
+  /* For ioctl operations on the network interface, use either capturingSkfd
+   * or encapsulatingSkfd, whichever is available */
+  ioctlSkfd = (capturingSkfd >= 0) ? capturingSkfd : encapsulatingSkfd;
+
+  /* Retrieve the MAC address of the interface. */
+  memset(&ifr, 0, sizeof(struct ifreq));
+  strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
+  ifr.ifr_name[IFNAMSIZ - 1] = '\0';    /* Ensures null termination */
+  if (ioctl(ioctlSkfd, SIOCGIFHWADDR, &ifr) < 0) {
+    P2pdPError("ioctl(SIOCGIFHWADDR) error for interface \"%s\"", ifName);
+    close(capturingSkfd);
+    close(encapsulatingSkfd);
+    free(newIf);
+    return 0;
+  }
+
+  /* Copy data into NonOlsrInterface object */
+  newIf->capturingSkfd = capturingSkfd;
+  newIf->encapsulatingSkfd = encapsulatingSkfd;
+  newIf->listeningSkfd = listeningSkfd;
+  memcpy(newIf->macAddr, ifr.ifr_hwaddr.sa_data, IFHWADDRLEN);
+  memcpy(newIf->ifName, ifName, IFNAMSIZ);
+  newIf->olsrIntf = olsrIntf;
+  if (olsrIntf != NULL) {
+    /* For an OLSR-interface, copy the interface address and broadcast
+     * address from the OLSR interface object. Downcast to correct sockaddr
+     * subtype. */
+    newIf->intAddr.v4 = olsrIntf->int_addr.sin_addr;
+    newIf->broadAddr.v4 = olsrIntf->int_broadaddr.sin_addr;
+  } else {
+    /* For a non-OLSR interface, retrieve the IP address ourselves */
+    memset(&ifr, 0, sizeof(struct ifreq));
+    strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
+    ifr.ifr_name[IFNAMSIZ - 1] = '\0';  /* Ensures null termination */
+    if (ioctl(ioctlSkfd, SIOCGIFADDR, &ifr) < 0) {
+      P2pdPError("ioctl(SIOCGIFADDR) error for interface \"%s\"", ifName);
+
+      newIf->intAddr.v4.s_addr = inet_addr("0.0.0.0");
+    } else {
+      /* Downcast to correct sockaddr subtype */
+      newIf->intAddr.v4 = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
+    }
+
+    /* For a non-OLSR interface, retrieve the IP broadcast address ourselves */
+    memset(&ifr, 0, sizeof(struct ifreq));
+    strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1);
+    ifr.ifr_name[IFNAMSIZ - 1] = '\0';  /* Ensures null termination */
+    if (ioctl(ioctlSkfd, SIOCGIFBRDADDR, &ifr) < 0) {
+      P2pdPError("ioctl(SIOCGIFBRDADDR) error for interface \"%s\"", ifName);
+
+      newIf->broadAddr.v4.s_addr = inet_addr("0.0.0.0");
+    } else {
+      /* Downcast to correct sockaddr subtype */
+      newIf->broadAddr.v4 = ((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr;
+    }
+  }
+
+  /* Initialize fragment history table */
+  //memset(&newIf->fragmentHistory, 0, sizeof(newIf->fragmentHistory));
+  //newIf->nextFragmentHistoryEntry = 0;
+
+  /* Reset counters */
+  //newIf->nNonOlsrPacketsRx = 0;
+  //newIf->nNonOlsrPacketsRxDup = 0;
+  //newIf->nNonOlsrPacketsTx = 0;
+
+  /* Add new NonOlsrInterface object to global list. OLSR interfaces are
+   * added at the front of the list, non-OLSR interfaces at the back. */
+  if (nonOlsrInterfaces == NULL) {
+    /* First NonOlsrInterface object in list */
+    nonOlsrInterfaces = newIf;
+    lastNonOlsrInterface = newIf;
+  } else if (olsrIntf != NULL) {
+    /* Add new NonOlsrInterface object at front of list */
+    newIf->next = nonOlsrInterfaces;
+    nonOlsrInterfaces = newIf;
+  } else {
+    /* Add new NonOlsrInterface object at back of list */
+    newIf->next = NULL;
+    lastNonOlsrInterface->next = newIf;
+    lastNonOlsrInterface = newIf;
+  }
+
+  //OLSR_PRINTF(
+  //  8,
+  //  "%s: opened %d socket%s on %s interface \"%s\"\n",
+  //  PLUGIN_NAME_SHORT,
+  //  nOpened,
+  //  nOpened == 1 ? "" : "s",
+  //  olsrIntf != NULL ? "OLSR" : "non-OLSR",
+  //  ifName);
+
+  return nOpened;
+}                               /* CreateInterface */
+
+/* -------------------------------------------------------------------------
+ * Function   : CreateNonOlsrNetworkInterfaces
+ * Description: Create a list of NonOlsrInterface objects, one for each network
+ *              interface on which BMF runs
+ * Input      : skipThisIntf - network interface to skip, if seen
+ * Output     : none
+ * Return     : fail (-1) or success (0)
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+int
+CreateNonOlsrNetworkInterfaces(struct interface *skipThisIntf)
+{
+  int skfd;
+  struct ifconf ifc;
+  int numreqs = 30;
+  struct ifreq *ifr;
+  int n;
+  int nOpenedSockets = 0;
+
+  /* Clear input descriptor set */
+  FD_ZERO(&InputSet);
+
+  skfd = socket(PF_INET, SOCK_DGRAM, 0);
+  if (skfd < 0) {
+    P2pdPError("no inet socket available to retrieve interface list");
+    return -1;
+  }
+
+  /* Retrieve the network interface configuration list */
+  ifc.ifc_buf = NULL;
+  for (;;) {
+    ifc.ifc_len = sizeof(struct ifreq) * numreqs;
+    ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len);
+
+    if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
+      P2pdPError("ioctl(SIOCGIFCONF) error");
+
+      close(skfd);
+      free(ifc.ifc_buf);
+      return -1;
+    }
+    if ((unsigned)ifc.ifc_len == sizeof(struct ifreq) * numreqs) {
+      /* Assume it overflowed; double the space and try again */
+      numreqs *= 2;
+      assert(numreqs < 1024);
+      continue;                 /* for (;;) */
+    }
+    break;                      /* for (;;) */
+  }                             /* for (;;) */
+
+  close(skfd);
+
+  /* For each item in the interface configuration list... */
+  ifr = ifc.ifc_req;
+  for (n = ifc.ifc_len / sizeof(struct ifreq); --n >= 0; ifr++) {
+    struct interface *olsrIntf;
+    union olsr_ip_addr ipAddr;
+
+    /* Skip the BMF network interface itself */
+    //if (strncmp(ifr->ifr_name, EtherTunTapIfName, IFNAMSIZ) == 0)
+    //{
+    //  continue; /* for (n = ...) */
+    //}
+
+    /* ...find the OLSR interface structure, if any */
+    ipAddr.v4 = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
+    olsrIntf = if_ifwithaddr(&ipAddr);
+
+    if (skipThisIntf != NULL && olsrIntf == skipThisIntf) {
+      continue;                 /* for (n = ...) */
+    }
+
+    if (olsrIntf == NULL && !IsNonOlsrIf(ifr->ifr_name)) {
+      /* Interface is neither OLSR interface, nor specified as non-OLSR
+       * interface in the plugin parameter list */
+      continue;                 /* for (n = ...) */
+    }
+
+    if (!IsNonOlsrIf(ifr->ifr_name)) {
+      //If the interface is not specified in the configuration file then go ahead
+      continue;                 /* for (n = ...) */
+    }
+    //TODO: asser if->ifr_name is not talking OLSR
+    //nOpenedSockets += CreateInterface(ifr->ifr_name, olsrIntf);
+    nOpenedSockets += CreateInterface(ifr->ifr_name, NULL);
+
+  }                             /* for (n = ...) */
+
+  free(ifc.ifc_buf);
+
+  if (nonOlsrInterfaces == NULL) {
+    //OLSR_PRINTF(1, "%s: could not initialize any network interface\n", PLUGIN_NAME);
+  } else {
+    //OLSR_PRINTF(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpenedSockets);
+  }
+  return 0;
+}                               /* CreateNonOlsrNetworkInterfaces */
+
+/* -------------------------------------------------------------------------
+ * Function   : AddInterface
+ * Description: Add an OLSR-enabled network interface to the list of BMF-enabled
+ *              network interfaces
+ * Input      : newIntf - network interface to add
+ * Output     : none
+ * Return     : none
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+void
+AddInterface(struct interface *newIntf)
+{
+  int nOpened;
+
+  assert(newIntf != NULL);
+
+  nOpened = CreateInterface(newIntf->int_name, newIntf);
+
+  //OLSR_PRINTF(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpened);
+}                               /* AddInterface */
+
+/* -------------------------------------------------------------------------
+ * Function   : CloseNonOlsrNetworkInterfaces
+ * Description: Closes every socket on each network interface used by BMF
+ * Input      : none
+ * Output     : none
+ * Return     : none
+ * Data Used  : none
+ * Notes      : Closes
+ *              - the local EtherTunTap interface (e.g. "tun0" or "tap0")
+ *              - for each BMF-enabled interface, the socket used for
+ *                capturing multicast packets
+ *              - for each OLSR-enabled interface, the socket used for
+ *                encapsulating packets
+ *              Also restores the network state to the situation before BMF
+ *              was started.
+ * ------------------------------------------------------------------------- */
+void
+CloseNonOlsrNetworkInterfaces(void)
+{
+  int nClosed = 0;
+  u_int32_t totalOlsrPacketsRx = 0;
+  u_int32_t totalOlsrPacketsRxDup = 0;
+  u_int32_t totalOlsrPacketsTx = 0;
+  u_int32_t totalNonOlsrPacketsRx = 0;
+  u_int32_t totalNonOlsrPacketsRxDup = 0;
+  u_int32_t totalNonOlsrPacketsTx = 0;
+
+  /* Close all opened sockets */
+  struct NonOlsrInterface *nextIf = nonOlsrInterfaces;
+  while (nextIf != NULL) {
+    struct NonOlsrInterface *ifc = nextIf;
+    nextIf = ifc->next;
+
+    if (ifc->capturingSkfd >= 0) {
+      close(ifc->capturingSkfd);
+      nClosed++;
+    }
+    if (ifc->encapsulatingSkfd >= 0) {
+      close(ifc->encapsulatingSkfd);
+      nClosed++;
+    }
+    //OLSR_PRINTF(
+    //  7,
+    //  "%s: %s interface \"%s\": RX pkts %u (%u dups); TX pkts %u\n",
+    //  PLUGIN_NAME_SHORT,
+    //  ifc->olsrIntf != NULL ? "OLSR" : "non-OLSR",
+    //  ifc->ifName,
+    //  ifc->nPacketsRx,
+    //  ifc->nPacketsRxDup,
+    //  ifc->nPacketsTx);
+
+    //OLSR_PRINTF(
+    //  1,
+    //  "%s: closed %s interface \"%s\"\n",
+    //  PLUGIN_NAME_SHORT,
+    //  ifc->olsrIntf != NULL ? "OLSR" : "non-OLSR",
+    //  ifc->ifName);
+
+    /* Add totals */
+    if (ifc->olsrIntf != NULL) {
+      totalOlsrPacketsRx                               += ifc->nPacketsRx;
+      totalOlsrPacketsRxDup                    += ifc->nPacketsRxDup;
+      totalOlsrPacketsTx                               += ifc->nPacketsTx;
+    } else {
+      totalNonOlsrPacketsRx            += ifc->nPacketsRx;
+      totalNonOlsrPacketsRxDup += ifc->nPacketsRxDup;
+      totalNonOlsrPacketsTx                    += ifc->nPacketsTx;
+    }
+
+    free(ifc);
+  }                             /* while */
+
+  nonOlsrInterfaces = NULL;
+
+  //OLSR_PRINTF(1, "%s: closed %d sockets\n", PLUGIN_NAME_SHORT, nClosed);
+
+}                               /* CloseNonOlsrNetworkInterfaces */
+
+#define MAX_NON_OLSR_IFS 32
+static char NonOlsrIfNames[MAX_NON_OLSR_IFS][IFNAMSIZ];
+static int nNonOlsrIfs = 0;
+/* -------------------------------------------------------------------------
+ * Function   : AddNonOlsrIf
+ * Description: Add an non-OLSR enabled network interface to the list of BMF-enabled
+ *              network interfaces
+ * Input      : ifName - network interface (e.g. "eth0")
+ *              data - not used
+ *              addon - not used
+ * Output     : none
+ * Return     : success (0) or fail (1)
+ * Data Used  : NonOlsrIfNames
+ * ------------------------------------------------------------------------- */
+int
+AddNonOlsrIf(const char *ifName, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
+{
+  assert(ifName != NULL);
+
+  if (nNonOlsrIfs >= MAX_NON_OLSR_IFS) {
+    //OLSR_PRINTF(
+    //  1,
+    //  "%s: too many non-OLSR interfaces specified, maximum is %d\n",
+    //  PLUGIN_NAME,
+    //  MAX_NON_OLSR_IFS);
+    return 1;
+  }
+
+  olsr_printf(1, "\nAdding interface '%s' to list of interface\n", ifName);
+  
+  strncpy(NonOlsrIfNames[nNonOlsrIfs], ifName, IFNAMSIZ - 1);
+  NonOlsrIfNames[nNonOlsrIfs][IFNAMSIZ - 1] = '\0';     /* Ensures null termination */
+  nNonOlsrIfs++;
+  return 0;
+}                               /* AddNonOlsrIf */
+
+/* -------------------------------------------------------------------------
+ * Function   : IsNonOlsrIf
+ * Description: Checks if a network interface is OLSR-enabled
+ * Input      : ifName - network interface (e.g. "eth0")
+ * Output     : none
+ * Return     : true (1) or false (0)
+ * Data Used  : NonOlsrIfNames
+ * ------------------------------------------------------------------------- */
+int
+IsNonOlsrIf(const char *ifName)
+{
+  int i;
+
+  assert(ifName != NULL);
+
+  for (i = 0; i < nNonOlsrIfs; i++) {
+    if (strncmp(NonOlsrIfNames[i], ifName, IFNAMSIZ) == 0)
+      return 1;
+  }
+  return 0;
+}                               /* IsNonOlsrIf */
diff --git a/lib/p2pd/src/NetworkInterfaces.h b/lib/p2pd/src/NetworkInterfaces.h
new file mode 100644 (file)
index 0000000..46a1a0b
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
+ * 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 olsr.org, olsrd 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.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+
+
+#ifndef _NETWORKINTERFACES_H
+#define _NETWORKINTERFACES_H
+
+/* System includes */
+#include <netinet/in.h>         /* struct in_addr */
+
+/* OLSR includes */
+#include "olsr_types.h"         /* olsr_ip_addr */
+#include "olsrd_plugin.h"             /* union set_plugin_parameter_addon */
+
+/* Plugin includes */
+#include "Packet.h"             /* IFHWADDRLEN */
+#include "p2pd.h"
+
+/* Size of buffer in which packets are received */
+#define P2PD_BUFFER_SIZE 2048
+
+struct NonOlsrInterface {
+  /* File descriptor of raw packet socket, used for capturing multicast packets */
+  int capturingSkfd;
+
+  /* File descriptor of UDP (datagram) socket for encapsulated multicast packets.
+   * Only used for OLSR-enabled interfaces; set to -1 if interface is not OLSR-enabled. */
+  int encapsulatingSkfd;
+
+  /* File descriptor of UDP packet socket, used for listening to encapsulation packets.
+   * Used only when PlParam "P2pdMechanism" is set to "UnicastPromiscuous". */
+  int listeningSkfd;
+
+  unsigned char macAddr[IFHWADDRLEN];
+
+  char ifName[IFNAMSIZ];
+
+  /* OLSRs idea of this network interface. NULL if this interface is not
+   * OLSR-enabled. */
+  struct interface *olsrIntf;
+
+  /* IP address of this network interface */
+  union olsr_ip_addr intAddr;
+
+  /* Broadcast address of this network interface */
+  union olsr_ip_addr broadAddr;
+
+#define FRAGMENT_HISTORY_SIZE 10
+  struct TFragmentHistory {
+    u_int16_t ipId;
+    u_int8_t ipProto;
+    struct in_addr ipSrc;
+    struct in_addr ipDst;
+  } fragmentHistory[FRAGMENT_HISTORY_SIZE];
+
+  int nextFragmentHistoryEntry;
+
+  /* Number of received and transmitted BMF packets on this interface */
+  u_int32_t nPacketsRx;
+  u_int32_t nPacketsRxDup;
+  u_int32_t nPacketsTx;
+
+  /* Next element in list */
+  struct NonOlsrInterface *next;
+};
+
+extern struct NonOlsrInterface *nonOlsrInterfaces;
+
+extern int HighestSkfd;
+extern fd_set InputSet;
+
+extern int EtherTunTapFd;
+
+extern char EtherTunTapIfName[];
+
+/* 10.255.255.253 in host byte order */
+#define ETHERTUNTAPDEFAULTIP 0x0AFFFFFD
+
+extern u_int32_t EtherTunTapIp;
+extern u_int32_t EtherTunTapIpMask;
+extern u_int32_t EtherTunTapIpBroadcast;
+
+
+enum P2pdMechanism { BM_BROADCAST = 0, BM_UNICAST_PROMISCUOUS };
+extern enum P2pdMechanism P2pdMechanism;
+
+int SetNonOlsrInterfaceName(const char *ifname, void *data, set_plugin_parameter_addon addon);
+int SetNonOlsrInterfaceIp(const char *ip, void *data, set_plugin_parameter_addon addon);
+int SetCapturePacketsOnOlsrInterfaces(const char *enable, void *data, set_plugin_parameter_addon addon);
+int SetP2pdMechanism(const char *mechanism, void *data, set_plugin_parameter_addon addon);
+int DeactivateSpoofFilter(void);
+void RestoreSpoofFilter(void);
+
+#define MAX_UNICAST_NEIGHBORS 10
+struct TBestNeighbors {
+  struct link_entry *links[MAX_UNICAST_NEIGHBORS];
+};
+
+void FindNeighbors(struct TBestNeighbors *neighbors,
+                   struct link_entry **bestNeighbor,
+                   struct NonOlsrInterface *intf,
+                   union olsr_ip_addr *source,
+                   union olsr_ip_addr *forwardedBy, union olsr_ip_addr *forwardedTo, int *nPossibleNeighbors);
+
+int CreateNonOlsrNetworkInterfaces(struct interface *skipThisIntf);
+void AddInterface(struct interface *newIntf);
+void CloseNonOlsrNetworkInterfaces(void);
+int AddNonOlsrIf(const char *ifName, void *data, set_plugin_parameter_addon addon);
+int IsNonOlsrIf(const char *ifName);
+void CheckAndUpdateLocalBroadcast(unsigned char *ipPacket, union olsr_ip_addr *broadAddr);
+void AddMulticastRoute(void);
+void DeleteMulticastRoute(void);
+int CreateCaptureSocket(const char *ifName);
+
+#endif /* _BMF_NETWORKINTERFACES_H */
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/lib/p2pd/src/Packet.c b/lib/p2pd/src/Packet.c
new file mode 100644 (file)
index 0000000..011c0d1
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
+ * 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 olsr.org, olsrd 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.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+
+#include "Packet.h"
+
+/* System includes */
+#include <stddef.h>             /* NULL */
+#include <assert.h>             /* assert() */
+#include <string.h>             /* memcpy() */
+#include <sys/types.h>          /* u_int8_t, u_int16_t, u_int32_t */
+#include <netinet/in.h>         /* ntohs(), htons() */
+#include <netinet/ip.h>         /* struct iphdr */
+
+/* -------------------------------------------------------------------------
+ * Function   : IsIpv4Fragment
+ * Description: Check if an IP packet is an IP fragment
+ * Input      : ipPacket - the IP packet
+ * Output     : none
+ * Return     : true (1) or false (0)
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+int IsIpv4Fragment(struct ip* hdr)
+{
+  assert(hdr != NULL);
+
+  if ((ntohs(hdr->ip_off) & IP_OFFMASK) != 0)
+  {
+    return 1;
+  }
+  return 0;
+} /* IsIpv4Fragment */
+
+int IsMulticastv4(struct ip* hdr)
+{
+  uint32_t addr;
+
+  assert(hdr != NULL);
+
+  memcpy(&addr, &hdr->ip_dst.s_addr, sizeof(addr));
+  if ((addr & 0xE0000000) == 0xE0000000)
+    return 1;
+  
+  return 0;
+}
+
+int IsBroadcast(struct ip* hdr)
+{
+  uint32_t addr;
+
+  assert(hdr != NULL);
+
+  memcpy(&addr, &hdr->ip_dst.s_addr, sizeof(addr));
+  if (addr == 0xFFFFFFFF)
+    return 1;
+    
+  return 0;
+}
+
+/* -------------------------------------------------------------------------
+ * Function   : IsIpv6Fragment
+ * Description: Check if an IP packet is an IP fragment
+ * Input      : ipPacket - the IP packet
+ * Output     : none
+ * Return     : true (1) or false (0)
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+int IsIpv6Fragment(struct ip6_hdr* hdr)
+{
+  assert(hdr != NULL);
+  
+//#error Implementation required
+  if (0)
+    return 1;
+    
+  return 0;
+}
+
+int IsMulticastv6(struct ip6_hdr* hdr)
+{
+  assert(hdr != NULL);
+
+
+  return 0;
+}
+
+/* -------------------------------------------------------------------------
+ * Function   : GetIpHeaderLength
+ * Description: Retrieve the IP header length (in bytes) of an IP packet
+ * Input      : ipPacket - the IP packet
+ * Output     : none
+ * Return     : IP header length
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+unsigned int
+GetIpHeaderLength(unsigned char *ipPacket)
+{
+  struct iphdr *iph;
+
+  assert(ipPacket != NULL);
+
+  iph = (struct iphdr *)ipPacket;
+  return iph->ihl << 2;
+}                               /* GetIpHeaderLength */
+
+/* -------------------------------------------------------------------------
+ * Function   : GetIpPacket
+ * Description: Retrieve the IP packet from BMF encapsulation UDP data
+ * Input      : encapsulationUdpData - the encapsulation UDP data
+ * Output     : none
+ * Return     : The IP packet
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+unsigned char *
+GetIpPacket(unsigned char *encapsulationUdpData)
+{
+  return encapsulationUdpData + ENCAP_HDR_LEN;
+}                               /* GetIpPacket */
+
+
+
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/lib/p2pd/src/Packet.h b/lib/p2pd/src/Packet.h
new file mode 100644 (file)
index 0000000..bc97111
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
+ * 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 olsr.org, olsrd 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.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+
+
+#ifndef _P2PD_PACKET_H
+#define _P2PD_PACKET_H
+
+/* System includes */
+#include <netinet/ip.h>         /* struct ip */
+#include <netinet/ip6.h>         /* struct ip6_hdr */
+#include <net/if.h>             /* IFNAMSIZ, IFHWADDRLEN */
+#include <sys/types.h>          /* u_int8_t, u_int16_t */
+
+/* P2PD-encapsulated packets are Ethernet-IP-UDP packets, which start
+ * with a 8-bytes header (struct TEncapHeader), followed by the
+ * encapsulated Ethernet-IP packet itself */
+
+struct TEncapHeader {
+  /* Use a standard Type-Length-Value (TLV) element */
+  u_int8_t type;
+  u_int8_t len;
+  u_int16_t reserved;                  /* Always 0 */
+  u_int32_t crc32;
+} __attribute__ ((__packed__));
+
+#define ENCAP_HDR_LEN ((int)sizeof(struct TEncapHeader))
+
+int IsIpv4Fragment(struct ip*);
+int IsMulticastv4(struct ip*);
+int IsBroadcast(struct ip*);
+int IsIpv6Fragment(struct ip6_hdr*);
+int IsMulticastv6(struct ip6_hdr*);
+unsigned int GetIpHeaderLength(unsigned char *ipPacket);
+unsigned char *GetIpPacket(unsigned char *encapsulationUdpData);
+
+#endif /* _P2PD_PACKET_H */
diff --git a/lib/p2pd/src/dllist.c b/lib/p2pd/src/dllist.c
new file mode 100644 (file)
index 0000000..c133762
--- /dev/null
@@ -0,0 +1,98 @@
+#include <stdlib.h>
+
+#include "olsr_types.h"
+#include "dllist.h"
+
+/*------------------------------------------------------------------------------
+ * Description : appends a node to the list specified by the head and tail
+ *               elements
+ * Parameters  : head - pointer to the head of the list
+ *               tail - pointer to the tail of the list
+ *               data - pointer to the data to store in the list
+ * Returns     : pointer to the newly created element in the list
+ * Uses data   : none
+ *------------------------------------------------------------------------------
+ */
+struct node * append_node(struct node ** head, struct node ** tail, void * data)
+{
+  struct node * new = calloc(1, sizeof(struct node));
+
+  if (*head == NULL) {
+    *head = new;
+  } else {
+    new->prev = *tail;
+    (*tail)->next = new;
+  }
+
+  new->data = data;
+  *tail = new;
+
+  return new;
+}
+
+/*------------------------------------------------------------------------------
+ * Description : removes the specified element from the list specified by the
+ *               head and tail elements
+ * Parameters  : head - pointer to the head of the list
+ *               tail - pointer to the tail of the list
+ *               node - the element to remove from the list
+ *               free_data - indicator whether to free the content of the data
+ *               element
+ * Returns     : nothing
+ * Uses data   : none
+ *------------------------------------------------------------------------------
+ */
+void remove_node(struct node ** head, struct node **tail, struct node * node, bool free_data)
+{
+  struct node * curr = NULL;
+
+  for (curr = *head; curr; curr = curr->next) {
+    if (curr == node) {
+      // Now we found the proper node so we can remove it
+
+      if (free_data)
+        free(curr->data);
+
+      if (curr == *head) {
+        // Head node
+        *head = curr->next;
+      } else if (curr == *tail) {
+        // Tail node
+        *tail = curr->prev;
+      } else {
+        // Middle node
+        curr->prev->next = curr->next;
+        curr->next->prev = curr->prev;
+      }
+
+      if (*head != NULL)
+        (*head)->prev = NULL;
+
+      if (*tail != NULL)
+        (*tail)->next = NULL;
+
+      if (curr != NULL) {
+        curr->next = curr->prev = NULL;
+        free(curr);
+      }
+      break; // Bail out if we handled a remove
+    }
+  }
+}
+
+/*------------------------------------------------------------------------------
+ * Description : clears the entire list specified by the head and tail elements
+ * Parameters  : head - pointer to the head of the list
+ *               tail - pointer to the tail of the list
+ *               free_data - indicator whether to free the data pointer
+ * Returns     : nothing
+ * Uses data   : none
+ *------------------------------------------------------------------------------
+ */
+void clear_list(struct node **head, struct node **tail, bool free_data)
+{
+  while (*head)
+    remove_node(head, tail, *head, free_data);
+}
+
+
diff --git a/lib/p2pd/src/dllist.h b/lib/p2pd/src/dllist.h
new file mode 100644 (file)
index 0000000..64a867d
--- /dev/null
@@ -0,0 +1,22 @@
+/* 
+ * File:   dllist.h
+ * Author: Caspar
+ *
+ * Created on February 28, 2010, 1:59 PM
+ */
+
+#ifndef _DLLIST_H
+#define        _DLLIST_H
+
+struct node {
+  void * data;
+  struct node * next;
+  struct node * prev;
+};
+
+struct node * append_node(struct node ** head, struct node ** tail, void * data);
+void remove_node(struct node ** head, struct node **tail, struct node * node, bool free_data);
+void clear_list(struct node **head, struct node **tail, bool free_data);
+
+#endif /* _DLLIST_H */
+
diff --git a/lib/p2pd/src/olsrd_plugin.c b/lib/p2pd/src/olsrd_plugin.c
new file mode 100644 (file)
index 0000000..7900d34
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
+ * 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 olsr.org, olsrd 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.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+
+/* System includes */
+#include <assert.h>             /* assert() */
+#include <stddef.h>             /* NULL */
+
+/* OLSRD includes */
+#include "olsrd_plugin.h"
+#include "plugin_util.h"
+#include "defs.h"               /* uint8_t, olsr_cnf */
+#include "scheduler.h"          /* olsr_start_timer() */
+#include "olsr_cfg.h"           /* olsr_cnf() */
+#include "olsr_cookie.h"        /* olsr_alloc_cookie() */
+
+/* P2PD includes */
+#include "p2pd.h"               /* InitP2pd(), CloseP2pd() */
+#include "NetworkInterfaces.h" /* AddNonOlsrIf */
+
+static void __attribute__ ((constructor)) my_init(void);
+static void __attribute__ ((destructor)) my_fini(void);
+
+//static struct olsr_cookie_info *prune_packet_history_timer_cookie;
+
+void olsr_plugin_exit(void);
+
+/* -------------------------------------------------------------------------
+ * Function   : olsrd_plugin_interface_version
+ * Description: Plugin interface version
+ * Input      : none
+ * Output     : none
+ * Return     : P2PD plugin interface version number
+ * Data Used  : none
+ * Notes      : Called by main OLSRD (olsr_load_dl) to check plugin interface
+ *              version
+ * ------------------------------------------------------------------------- */
+int
+olsrd_plugin_interface_version(void)
+{
+  return PLUGIN_INTERFACE_VERSION;
+}
+
+/* -------------------------------------------------------------------------
+ * Function   : olsrd_plugin_init
+ * Description: Plugin initialisation
+ * Input      : none
+ * Output     : none
+ * Return     : fail (0) or success (1)
+ * Data Used  : olsr_cnf
+ * Notes      : Called by main OLSRD (init_olsr_plugin) to initialize plugin
+ * ------------------------------------------------------------------------- */
+int
+olsrd_plugin_init(void)
+{
+  return InitP2pd(NULL);
+}
+
+/* -------------------------------------------------------------------------
+ * Function   : olsr_plugin_exit
+ * Description: Plugin cleanup
+ * Input      : none
+ * Output     : none
+ * Return     : none
+ * Data Used  : none
+ * Notes      : Called by my_fini() at unload of shared object
+ * ------------------------------------------------------------------------- */
+void
+olsr_plugin_exit(void)
+{
+  CloseP2pd();
+}
+
+static const struct olsrd_plugin_parameters plugin_parameters[] = {
+  {.name = "NonOlsrIf",.set_plugin_parameter = &AddNonOlsrIf,.data = NULL},
+  {.name = "P2pdTtl", .set_plugin_parameter = &SetP2pdTtl, .data = NULL },
+  {.name = "UdpDestPort",.set_plugin_parameter = &AddUdpDestPort,.data = NULL},
+};
+
+/* -------------------------------------------------------------------------
+ * Function   : olsrd_get_plugin_parameters
+ * Description: Return the parameter table and its size
+ * Input      : none
+ * Output     : params - the parameter table
+ *              size - its size in no. of entries
+ * Return     : none
+ * Data Used  : plugin_parameters
+ * Notes      : Called by main OLSR (init_olsr_plugin) for all plugins
+ * ------------------------------------------------------------------------- */
+void
+olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size)
+{
+  *params = plugin_parameters;
+  *size = ARRAYSIZE(plugin_parameters);
+}
+
+/* -------------------------------------------------------------------------
+ * Function   : my_init
+ * Description: Plugin constructor
+ * Input      : none
+ * Output     : none
+ * Return     : none
+ * Data Used  : none
+ * Notes      : Called at load of shared object
+ * ------------------------------------------------------------------------- */
+static void
+my_init(void)
+{
+  /* Print plugin info to stdout */
+  printf("%s\n", MOD_DESC);
+
+  return;
+}
+
+/* -------------------------------------------------------------------------
+ * Function   : my_fini
+ * Description: Plugin destructor
+ * Input      : none
+ * Output     : none
+ * Return     : none
+ * Data Used  : none
+ * Notes      : Called at unload of shared object
+ * ------------------------------------------------------------------------- */
+static void
+my_fini(void)
+{
+  olsr_plugin_exit();
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/lib/p2pd/src/p2pd.c b/lib/p2pd/src/p2pd.c
new file mode 100644 (file)
index 0000000..8a42c8c
--- /dev/null
@@ -0,0 +1,783 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
+ * 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 olsr.org, olsrd 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.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+
+
+#include "p2pd.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 <unistd.h>
+#include <fcntl.h>
+#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 */
+#include <unistd.h>             /* close() */
+
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+
+#include <time.h>
+
+/* OLSRD includes */
+#include "plugin_util.h"        /* set_plugin_int */
+#include "defs.h"               /* olsr_cnf, //OLSR_PRINTF */
+#include "ipcalc.h"
+#include "olsr.h"               /* //OLSR_PRINTF */
+#include "mid_set.h"            /* mid_lookup_main_addr() */
+#include "link_set.h"           /* get_best_link_to_neighbor() */
+#include "net_olsr.h"           /* ipequal */
+#include "log.h"                /* Teco: syslog */
+#include "parser.h"
+
+/* plugin includes */
+#include "NetworkInterfaces.h"  /* NonOlsrInterface, CreateBmfNetworkInterfaces(), CloseBmfNetworkInterfaces() */
+//#include "Address.h"            /* IsMulticast() */
+#include "Packet.h"             /* ENCAP_HDR_LEN, BMF_ENCAP_TYPE, BMF_ENCAP_LEN etc. */
+#include "dllist.h"
+
+int P2pdTtl=0;
+int P2pdDuplicateTimeout           = P2PD_VALID_TIME;
+
+/* List of UDP destination address and port information */
+struct UdpDestPort *                 UdpDestPortList = NULL;
+
+/* List of filter entries to check for duplicate messages
+ */
+struct node *                        dupFilterHead = NULL;
+struct node *                        dupFilterTail = NULL;
+
+clockid_t clockid = CLOCK_MONOTONIC;
+
+bool is_broadcast(const struct sockaddr_in addr);
+bool is_multicast(const struct sockaddr_in addr);
+
+/* -------------------------------------------------------------------------
+ * Function   : PacketReceivedFromOLSR
+ * Description: Handle a received packet from a OLSR message
+ * Input      : ipPacket into an unsigned char and the lenght of the packet
+ * Output     : none
+ * Return     : none
+ * Data Used  : BmfInterfaces
+ * ------------------------------------------------------------------------- */
+static void
+PacketReceivedFromOLSR(unsigned char *encapsulationUdpData, int len)
+{
+  struct ip *ipHeader;        /* IP header inside the encapsulated IP packet */
+  struct ip6_hdr *ip6Header;  /* IP header inside the encapsulated IP packet */
+  struct NonOlsrInterface *walker;
+  int stripped_len = 0;
+  ipHeader = (struct ip *)encapsulationUdpData;
+  ip6Header = (struct ip6_hdr *)encapsulationUdpData;
+  //OLSR_DEBUG(LOG_PLUGINS, "P2PD PLUGIN got packet from OLSR message\n");
+
+  /* Check with each network interface what needs to be done on it */
+  for (walker = nonOlsrInterfaces; walker != NULL; walker = walker->next) {
+    /* To a non-OLSR interface: unpack the encapsulated IP packet and forward it */
+    if (walker->olsrIntf == NULL) {
+      int nBytesWritten;
+      struct sockaddr_ll dest;
+
+      memset(&dest, 0, sizeof(dest));
+      dest.sll_family = AF_PACKET;
+      if ((encapsulationUdpData[0] & 0xf0) == 0x40) {
+        dest.sll_protocol = htons(ETH_P_IP);
+        stripped_len = ntohs(ipHeader->ip_len);
+      }
+      
+      if ((encapsulationUdpData[0] & 0xf0) == 0x60) {
+        dest.sll_protocol = htons(ETH_P_IPV6);
+        stripped_len = 40 + ntohs(ip6Header->ip6_plen); //IPv6 Header size (40) + payload_len 
+      }
+      
+      // Sven-Ola: Don't know how to handle the "stripped_len is uninitialized" condition, maybe exit(1) is better...?
+      if (0 == stripped_len)
+        return;
+      
+      //TODO: if packet is not IP die here
+      
+      if (stripped_len > len) {
+      }
+      
+      dest.sll_ifindex = if_nametoindex(walker->ifName);
+      dest.sll_halen = IFHWADDRLEN;
+
+      if (olsr_cnf->ip_version == AF_INET) {
+        /* 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. */
+
+        if (IsMulticastv4(ipHeader)) {
+          dest.sll_addr[0] = 0x01;
+          dest.sll_addr[1] = 0x00;
+          dest.sll_addr[2] = 0x5E;
+          dest.sll_addr[3] = (ipHeader->ip_dst.s_addr >> 16) & 0xFF;
+          dest.sll_addr[4] = (ipHeader->ip_dst.s_addr >> 8) & 0xFF;
+          dest.sll_addr[5] = ipHeader->ip_dst.s_addr & 0xFF;
+        } else /* if (IsBroadcast(ipHeader)) */ {
+          memset(dest.sll_addr, 0xFF, IFHWADDRLEN);
+        }
+      } else /*(olsr_cnf->ip_version == AF_INET6) */ {
+        if (IsMulticastv6(ip6Header)) {
+          dest.sll_addr[0] = 0x33;
+          dest.sll_addr[1] = 0x33;
+          dest.sll_addr[2] = ip6Header->ip6_dst.s6_addr[12];
+          dest.sll_addr[3] = ip6Header->ip6_dst.s6_addr[13];
+          dest.sll_addr[4] = ip6Header->ip6_dst.s6_addr[14];
+          dest.sll_addr[5] = ip6Header->ip6_dst.s6_addr[15];
+        }
+      }
+
+      nBytesWritten = sendto(walker->capturingSkfd,
+                             encapsulationUdpData,
+                             stripped_len,
+                             0,
+                             (struct sockaddr *)&dest,
+                             sizeof(dest));
+      if (nBytesWritten != stripped_len) {
+        P2pdPError("sendto() error forwarding unpacked encapsulated pkt on \"%s\"", walker->ifName);
+      } else {
+
+        //OLSR_PRINTF(
+        //  2,
+        //  "%s: --> unpacked and forwarded on \"%s\"\n",
+        //  PLUGIN_NAME_SHORT,
+        //  walker->ifName);
+      }
+    }                           /* if (walker->olsrIntf == NULL) */
+  }
+}                               /* PacketReceivedFromOLSR */
+
+/* Highest-numbered open socket file descriptor. To be used as first
+ * parameter in calls to select(...). */
+int HighestSkfd = -1;
+
+/* Set of socket file descriptors */
+fd_set InputSet;
+
+bool
+p2pd_message_seen(struct node **head, struct node **tail, union olsr_message *m)
+{
+  struct node * curr;
+  time_t now;
+
+  now = time(NULL);
+  
+  // Check whether any entries have aged
+  curr = *head;
+  while (curr) {
+    struct DupFilterEntry *filter;
+    struct node * next = curr->next; // Save the current pointer since curr may be destroyed
+    
+    filter = (struct DupFilterEntry*)curr->data;
+    
+    if ((filter->creationtime + P2pdDuplicateTimeout) < now)
+      remove_node(head, tail, curr, true);
+      
+    // Skip to the next element
+    curr = next;
+  }
+  
+  // Now check whether there are any duplicates
+  for (curr = *head; curr; curr = curr->next) {
+    struct DupFilterEntry *filter = (struct DupFilterEntry*)curr->data;
+    
+    if (olsr_cnf->ip_version == AF_INET) {
+      if (filter->address.v4.s_addr  == m->v4.originator &&
+          filter->msgtype            == m->v4.olsr_msgtype &&
+          filter->seqno              == m->v4.seqno) {
+          return true;
+      }
+    } else /* if (olsr_cnf->ip_version == AF_INET6) */ {
+      if (memcmp(filter->address.v6.s6_addr,
+                 m->v6.originator.s6_addr,
+                 sizeof(m->v6.originator.s6_addr)) == 0 &&
+          filter->msgtype            == m->v6.olsr_msgtype &&
+          filter->seqno              == m->v6.seqno) {
+          return true;
+      }
+    }
+  }
+  
+  return false;
+}
+
+void
+p2pd_store_message(struct node **head, struct node **tail, union olsr_message *m)
+{
+  time_t now;
+
+  // Store a message into the database
+  struct DupFilterEntry *new_dup = calloc(1, sizeof(struct DupFilterEntry));
+  if (new_dup == NULL) {
+    olsr_printf(1, "P2PD: Out of memory\n");
+    return;
+  }
+
+  now = time(NULL);
+  
+  new_dup->creationtime = now;
+  if (olsr_cnf->ip_version == AF_INET) {
+    new_dup->address.v4.s_addr = m->v4.originator;
+    new_dup->msgtype = m->v4.olsr_msgtype;
+    new_dup->seqno = m->v4.seqno;
+  } else /* if (olsr_cnf->ip_version == AF_INET6) */ {
+    memcpy(new_dup->address.v6.s6_addr,
+           m->v6.originator.s6_addr,
+           sizeof(m->v6.originator.s6_addr));
+    new_dup->msgtype = m->v6.olsr_msgtype;
+    new_dup->seqno = m->v6.seqno;
+  }
+  
+  // Add the element to the head of the list
+  append_node(head, tail, new_dup);
+}
+
+bool
+p2pd_is_duplicate_message(union olsr_message *msg)
+{
+  if(p2pd_message_seen(&dupFilterHead, &dupFilterTail, msg)) {
+    return true;
+  }
+
+  p2pd_store_message(&dupFilterHead, &dupFilterTail, msg);
+  
+  return false;
+}
+
+bool
+olsr_parser(union olsr_message *m, struct interface *in_if __attribute__ ((unused)), union olsr_ip_addr *ipaddr __attribute__ ((unused)))
+{
+  union olsr_ip_addr originator;
+  int size;
+  uint32_t vtime;
+
+  //OLSR_DEBUG(LOG_PLUGINS, "P2PD PLUGIN: Received msg in parser\n");
+  
+       /* Fetch the originator of the messsage */
+  if (olsr_cnf->ip_version == AF_INET) {
+    memcpy(&originator, &m->v4.originator, olsr_cnf->ipsize);
+    vtime = me_to_reltime(m->v4.olsr_vtime);
+    size = ntohs(m->v4.olsr_msgsize);
+  } else {
+    memcpy(&originator, &m->v6.originator, olsr_cnf->ipsize);
+    vtime = me_to_reltime(m->v6.olsr_vtime);
+    size = ntohs(m->v6.olsr_msgsize);
+  }
+
+  /* Check if message originated from this node.
+   *         If so - back off */
+  if (ipequal(&originator, &olsr_cnf->main_addr))
+    return false;          /* Don't forward either */
+
+  /* Check for duplicates for processing */
+  if (p2pd_is_duplicate_message(m))
+    return true;  /* Don't process but allow to be forwarded */
+
+  if (olsr_cnf->ip_version == AF_INET) {
+    PacketReceivedFromOLSR((unsigned char *)&m->v4.message, size - 12);
+  } else {
+    PacketReceivedFromOLSR((unsigned char *)&m->v6.message, size - 12 - 96);
+  }
+
+       return true;
+}
+
+//Sends a packet in the OLSR network
+void
+olsr_p2pd_gen(unsigned char *packet, int len)
+{
+  /* send buffer: huge */
+  char buffer[10240];
+  int aligned_size;
+  union olsr_message *message = (union olsr_message *)buffer;
+  struct interface *ifn;
+  
+  aligned_size=len;
+
+  if ((aligned_size % 4) != 0) {
+    aligned_size = (aligned_size - (aligned_size % 4)) + 4;
+  }
+
+  /* fill message */
+  if (olsr_cnf->ip_version == AF_INET) {
+    /* IPv4 */
+    message->v4.olsr_msgtype  = P2PD_MESSAGE_TYPE;
+    message->v4.olsr_vtime    = reltime_to_me(P2PD_VALID_TIME * MSEC_PER_SEC);
+    memcpy(&message->v4.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
+    message->v4.ttl           = P2pdTtl ? P2pdTtl : MAX_TTL;
+    message->v4.hopcnt        = 0;
+    message->v4.seqno         = htons(get_msg_seqno());
+    message->v4.olsr_msgsize  = htons(aligned_size + 12);
+    memset(&message->v4.message, 0, aligned_size);
+    memcpy(&message->v4.message, packet, len);
+    aligned_size = aligned_size + 12;
+  } else /* if (olsr_cnf->ip_version == AF_INET6) */ {
+    /* IPv6 */
+    message->v6.olsr_msgtype  = P2PD_MESSAGE_TYPE;
+    message->v6.olsr_vtime    = reltime_to_me(P2PD_VALID_TIME * MSEC_PER_SEC);
+    memcpy(&message->v6.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
+    message->v6.ttl           = P2pdTtl ? P2pdTtl : MAX_TTL;
+    message->v6.hopcnt        = 0;
+    message->v6.seqno         = htons(get_msg_seqno());
+    message->v6.olsr_msgsize  = htons(aligned_size + 12 + 96);
+    memset(&message->v6.message, 0, aligned_size);
+    memcpy(&message->v6.message, packet, len);
+    aligned_size = aligned_size + 12 + 96;
+  }
+
+  /* looping trough interfaces */
+  for (ifn = ifnet; ifn; ifn = ifn->int_next) {
+    //OLSR_PRINTF(1, "P2PD PLUGIN: Generating packet - [%s]\n", ifn->int_name);
+
+    if (net_outbuffer_push(ifn, message, aligned_size) != aligned_size) {
+      /* send data and try again */
+      net_output(ifn);
+      if (net_outbuffer_push(ifn, message, aligned_size) != aligned_size) {
+        //OLSR_PRINTF(1, "P2PD PLUGIN: could not send on interface: %s\n", ifn->int_name);
+      }
+    }
+  }
+}
+
+/* -------------------------------------------------------------------------
+ * Function   : P2pdPError
+ * 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
+P2pdPError(const char *format, ...)
+{
+#define MAX_STR_DESC 255
+  char strDesc[MAX_STR_DESC];
+
+#if !defined REMOVE_LOG_DEBUG
+  char *stringErr = strerror(errno);
+#endif
+
+  /* Rely on short-circuit boolean evaluation */
+  if (format == NULL || *format == '\0') {
+    //OLSR_DEBUG(LOG_PLUGINS, "%s: %s\n", PLUGIN_NAME, stringErr);
+  } else {
+    va_list arglist;
+
+    va_start(arglist, format);
+    vsnprintf(strDesc, MAX_STR_DESC, format, arglist);
+    va_end(arglist);
+
+    strDesc[MAX_STR_DESC - 1] = '\0';   /* Ensures null termination */
+    
+#if !defined REMOVE_LOG_DEBUG
+    OLSR_DEBUG(LOG_PLUGINS, "%s: %s\n", strDesc, stringErr);
+#endif
+  }
+}                               /* P2pdPError */
+
+/* -------------------------------------------------------------------------
+ * 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   : InUdpDestPortList
+ * Description: Check whether the specified address and port is in the list of
+ *              configured UDP destination/port entries
+ * Input      : ip_version  - IP version to use for this check
+ *              addr        - address to check for in the list
+ *              port        - port to check for in the list
+ * Output     : none
+ * Return     : true if destination/port combination was found, false otherwise
+ * Data Used  : UdpDestPortList
+ * ------------------------------------------------------------------------- */
+bool
+InUdpDestPortList(int ip_version, union olsr_ip_addr *addr, uint16_t port)
+{
+  struct UdpDestPort *walker;
+  
+  for (walker = UdpDestPortList; walker; walker = walker->next) {
+    if (walker->ip_version == ip_version) {
+      if (ip_version == AF_INET) {
+        if (addr->v4.s_addr == walker->address.v4.s_addr &&
+            walker->port == port)
+          return true;  // Found so we can stop here
+      } else /* ip_version == AF_INET6 */ {
+        if (memcmp(addr->v6.s6_addr,
+                   walker->address.v6.s6_addr,
+                   sizeof(addr->v6.s6_addr) == 0) &&
+            walker->port == port)
+          return true;  // Found so we can stop here
+      }
+    }
+  }
+  return false;
+}
+
+/* -------------------------------------------------------------------------
+ * Function   : P2pdPacketCaptured
+ * Description: Handle a captured IP packet
+ * Input      : encapsulationUdpData - space for the encapsulation header, 
+ *                                                     followed by the captured IP packet
+ *                                                     nBytes - The number of bytes in the data packet 
+ * Output     : none
+ * Return     : none
+ * Data Used  : P2pdInterfaces
+ * Notes      : The IP packet is assumed to be captured on a socket of family
+ *              PF_PACKET and type SOCK_DGRAM (cooked).
+ * ------------------------------------------------------------------------- */
+static void
+P2pdPacketCaptured(unsigned char *encapsulationUdpData, int nBytes)
+{
+  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 ip *ipHeader;         /* The IP header inside the captured IP packet */
+  struct ip6_hdr *ipHeader6;   /* The IP header inside the captured IP packet */
+  struct udphdr *udpHeader;
+  u_int16_t destPort;
+
+  if ((encapsulationUdpData[0] & 0xf0) == 0x40) {       //IPV4
+
+    ipHeader = (struct ip *)encapsulationUdpData;
+
+    dst.v4 = ipHeader->ip_dst;
+
+    if (ipHeader->ip_p != SOL_UDP) {
+      /* Not UDP */
+      //OLSR_PRINTF(1,"NON UDP PACKET\n");
+      return;                   /* for */
+    }
+
+    // If we're dealing with a fragment we bail out here since there's no valid
+    // UDP header in this message
+    if (IsIpv4Fragment(ipHeader)) {
+      return;
+    }
+    
+    udpHeader = (struct udphdr *)(encapsulationUdpData +
+                                  GetIpHeaderLength(encapsulationUdpData));
+    destPort = ntohs(udpHeader->dest);
+    
+    if (!InUdpDestPortList(AF_INET, &dst, destPort))
+       return;
+  }                            //END IPV4
+  else if ((encapsulationUdpData[0] & 0xf0) == 0x60) {  //IPv6
+
+    ipHeader6 = (struct ip6_hdr *)encapsulationUdpData;
+    
+    memcpy(&dst.v6, &ipHeader6->ip6_dst, sizeof(struct in6_addr));
+    
+    if (ipHeader6->ip6_dst.s6_addr[0] == 0xff)  //Multicast
+    {
+      //Continue
+    } else {
+      return;                   //not multicast
+    }
+    if (ipHeader6->ip6_nxt != SOL_UDP) {
+      /* Not UDP */
+      //OLSR_PRINTF(1,"NON UDP PACKET\n");
+      return;                   /* for */
+    }
+    
+    // Check whether this is a IPv6 fragment
+    if (IsIpv6Fragment(ipHeader6)) {
+      return;
+    }
+    
+    udpHeader = (struct udphdr *)(encapsulationUdpData + 40);
+    destPort = ntohs(udpHeader->dest);
+
+    if (!InUdpDestPortList(AF_INET6, &dst, destPort))
+      return;
+  }                             //END IPV6
+  else {
+    return;                     //Is not IP packet
+  }
+
+  /* Lookup main address of source in the MID table of OLSR */
+  origIp = MainAddressOf(&src);
+
+  // send the packet to OLSR forward mechanism
+  olsr_p2pd_gen(encapsulationUdpData, nBytes);
+}                               /* P2pdPacketCaptured */
+
+
+/* -------------------------------------------------------------------------
+ * Function   : DoP2pd
+ * Description: This function is registered with the OLSR scheduler and called when something is captured
+ * Input      : none
+ * Output     : none
+ * Return     : none
+ * Data Used  :
+ * ------------------------------------------------------------------------- */
+void
+DoP2pd(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused)))
+{
+  unsigned char rxBuffer[P2PD_BUFFER_SIZE];
+  if (skfd >= 0) {
+    struct sockaddr_ll pktAddr;
+    socklen_t addrLen = sizeof(pktAddr);
+    int nBytes;
+    unsigned char *ipPacket;
+
+    /* Receive the captured Ethernet frame, leaving space for the BMF
+     * encapsulation header */
+    ipPacket = GetIpPacket(rxBuffer);
+    nBytes = recvfrom(skfd, ipPacket, P2PD_BUFFER_SIZE,  //TODO: understand how to change this
+                      0, (struct sockaddr *)&pktAddr, &addrLen);
+    if (nBytes < 0) {
+
+      return;                   /* 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);
+
+      return;                   /* for */
+    }
+
+    if (pktAddr.sll_pkttype == PACKET_OUTGOING ||
+        pktAddr.sll_pkttype == PACKET_MULTICAST ||
+        pktAddr.sll_pkttype == PACKET_BROADCAST) {
+      /* A multicast or broadcast packet was captured */
+
+      P2pdPacketCaptured(ipPacket, nBytes);
+
+    }                           /* if (pktAddr.sll_pkttype == ...) */
+  }                             /* if (skfd >= 0 && (FD_ISSET...)) */
+}                               /* DoP2pd */
+
+/* -------------------------------------------------------------------------
+ * Function   : InitP2pd
+ * Description: Initialize the P2pd plugin
+ * Input      : skipThisInterface - pointer to interface to skip
+ * Output     : none
+ * Return     : Always 0
+ * Data Used  : none
+ * ------------------------------------------------------------------------- */
+int
+InitP2pd(struct interface *skipThisIntf)
+{
+  //Tells OLSR to launch olsr_parser when the packets for this plugin arrive
+  //olsr_parser_add_function(&olsr_parser, PARSER_TYPE,1);
+  olsr_parser_add_function(&olsr_parser, PARSER_TYPE);
+  
+  //Creates captures sockets and register them to the OLSR scheduler
+  CreateNonOlsrNetworkInterfaces(skipThisIntf);
+
+  return 0;
+}                               /* InitP2pd */
+
+/* -------------------------------------------------------------------------
+ * Function   : CloseP2pd
+ * Description: Close the P2pd plugin and clean up
+ * Input      : none
+ * Output     : none
+ * Return     : none
+ * Data Used  :
+ * ------------------------------------------------------------------------- */
+void
+CloseP2pd(void)
+{
+  CloseNonOlsrNetworkInterfaces();
+}
+
+/* -------------------------------------------------------------------------
+ * Function   : SetP2pdTtl
+ * Description: Set the TTL for message from this plugin
+ * Input      : value - parameter value to evaluate
+ * Output     : none
+ * Return     : Always 0
+ * Data Used  : P2pdTtl
+ * ------------------------------------------------------------------------- */
+int
+SetP2pdTtl(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
+{
+  assert(value != NULL);
+  P2pdTtl = atoi(value);
+
+  return 0;
+}
+
+bool is_broadcast(const struct sockaddr_in addr)
+{
+  if (addr.sin_addr.s_addr == 0xFFFFFFFF)
+    return true;
+    
+  return false;
+}
+
+bool is_multicast(const struct sockaddr_in addr)
+{
+  if ((htonl(addr.sin_addr.s_addr) & 0xE0000000) == 0xE0000000)
+    return true;
+
+  return false;
+}
+
+/* -------------------------------------------------------------------------
+ * Function   : AddUdpDestPort
+ * Description: Set the UDP destination/port combination as an entry in the
+ *              UdpDestPortList
+ * Input      : value - parameter value to evaluate
+ * Output     : none
+ * Return     : -1 on error condition, 0 if all is ok
+ * Data Used  : UdpDestPortList
+ * ------------------------------------------------------------------------- */
+int
+AddUdpDestPort(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)))
+{
+  char destAddr[INET6_ADDRSTRLEN];
+  uint16_t destPort;
+  int num;
+  struct UdpDestPort *    new;
+  struct sockaddr_in      addr4;
+  struct sockaddr_in6     addr6;
+  int                     ip_version   = AF_INET;
+  int                     res;
+  
+  assert(value != NULL);
+  
+  // Retrieve the data from the argument string passed
+  memset(destAddr, 0, sizeof(destAddr));
+  num = sscanf(value, "%45s %hd", destAddr, &destPort);
+  if (num != 2) {
+    olsr_printf(1, "Invalid argument for \"UdpDestPort\"");
+    return -1;
+  }
+       
+  // Check whether we're dealing with an IPv4 or IPv6 address
+  // When the string contains a ':' we can assume we're dealing with IPv6
+  if (strchr(destAddr, (int)':')) {
+    ip_version = AF_INET6;
+  }
+
+  // Check whether the specified address was either IPv4 multicast,
+  // IPv4 broadcast or IPv6 multicast.
+
+  switch (ip_version) {
+  case AF_INET:
+    res = inet_pton(AF_INET, destAddr, &addr4.sin_addr);
+    if (!is_broadcast(addr4) && !is_multicast(addr4)) {
+      olsr_printf(1, "WARNING: IPv4 address must be multicast or broadcast... ");
+    }
+    break;
+  case AF_INET6:
+    res = inet_pton(AF_INET6, destAddr, &addr6.sin6_addr);
+    if (addr6.sin6_addr.s6_addr[0] != 0xFF) {
+      olsr_printf(1, "WARNING: IPv6 address must be multicast... ");
+      return -1;
+    }
+    break;
+  }
+  // Determine whether it is a valid IP address
+  if (res == 0) {
+    olsr_printf(1, "Invalid address specified for \"UdpDestPort\"");
+    return -1;
+  }
+       
+  // Create a new entry and link it into the chain
+  new = calloc(1, sizeof(struct UdpDestPort));
+  if (new == NULL) {
+    olsr_printf(1, "P2PD: Out of memory");
+    return -1;
+  }
+       
+  new->ip_version = ip_version;
+  switch (ip_version) {
+  case AF_INET:
+    new->address.v4.s_addr = addr4.sin_addr.s_addr;
+    break;
+  case AF_INET6:
+    memcpy(&new->address.v6.s6_addr, &addr6.sin6_addr.s6_addr, sizeof(sizeof(addr6.sin6_addr.s6_addr)));
+    break;
+  }
+  new->port = destPort;
+  new->next = UdpDestPortList;
+  UdpDestPortList = new;
+       
+  // And then we're done
+  return 0;
+}
+
diff --git a/lib/p2pd/src/p2pd.h b/lib/p2pd/src/p2pd.h
new file mode 100644 (file)
index 0000000..f59fe84
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
+ * 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 olsr.org, olsrd 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.
+ *
+ * Visit http://www.olsr.org for more information.
+ *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ */
+
+
+#ifndef _P2PD_H
+#define _P2PD_H
+
+#define REMOVE_LOG_DEBUG
+
+#include "olsrd_plugin.h"             /* union set_plugin_parameter_addon */
+#include "duplicate_set.h"
+//#include "socket_parser.h"
+#include "dllist.h"
+
+#define P2PD_MESSAGE_TYPE         132
+#define PARSER_TYPE               P2PD_MESSAGE_TYPE
+#define P2PD_VALID_TIME           180          /* seconds */
+
+/* P2PD plugin data */
+#define PLUGIN_NAME               "OLSRD P2PD plugin"
+#define PLUGIN_NAME_SHORT         "OLSRD P2PD"
+#define PLUGIN_VERSION            "0.1.0 (" __DATE__ " " __TIME__ ")"
+#define MOD_DESC PLUGIN_NAME      " " PLUGIN_VERSION
+#define PLUGIN_INTERFACE_VERSION  5
+#define IPHDR_FRAGMENT_MASK       0xC000
+
+/* Forward declaration of OLSR interface type */
+struct interface;
+
+struct DupFilterEntry {
+  int                            ip_version;
+  union olsr_ip_addr             address;
+  uint16_t                       seqno;
+  uint8_t                        msgtype;
+  time_t                         creationtime;
+};
+
+struct UdpDestPort {
+  int                            ip_version;
+  union olsr_ip_addr             address;
+  uint16_t                       port;
+  struct UdpDestPort *           next;
+};
+
+extern int P2pdTtl;
+extern int P2pdDuplicateTimeout;
+extern int HighestSkfd;
+extern fd_set InputSet;
+extern struct UdpDestPort * UdpDestPortList;
+extern struct DuplicateFilterEntry * FilterList;
+
+void DoP2pd(int sd, void *x, unsigned int y);
+void P2pdPError(const char *format, ...) __attribute__ ((format(printf, 1, 2)));
+union olsr_ip_addr *MainAddressOf(union olsr_ip_addr *ip);
+int InitP2pd(struct interface *skipThisIntf);
+void CloseP2pd(void);
+int SetP2pdTtl(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)));
+int AddUdpDestPort(const char *value, void *data __attribute__ ((unused)), set_plugin_parameter_addon addon __attribute__ ((unused)));
+bool InUdpDestPortList(int ip_version, union olsr_ip_addr *addr, uint16_t port);
+bool p2pd_message_seen(struct node **head, struct node **tail, union olsr_message *m);
+void p2pd_store_message(struct node **head, struct node **tail, union olsr_message *m);
+bool p2pd_is_duplicate_message(union olsr_message *msg);
+
+void olsr_p2pd_gen(unsigned char *packet, int len);
+
+/* Parser function to register with the scheduler */
+bool olsr_parser(union olsr_message *, struct interface *, union olsr_ip_addr *);
+
+#endif /* _P2PD_H */
+
+/*
+ * Local Variables:
+ * c-basic-offset: 2
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/lib/p2pd/src/version-script.txt b/lib/p2pd/src/version-script.txt
new file mode 100644 (file)
index 0000000..a145659
--- /dev/null
@@ -0,0 +1,10 @@
+VERS_1.0
+{
+  global:
+    olsrd_plugin_interface_version;
+    olsrd_plugin_init;
+    olsrd_get_plugin_parameters;
+
+  local:
+    *;
+};
diff --git a/lib/p2pd/version-script.txt b/lib/p2pd/version-script.txt
new file mode 100644 (file)
index 0000000..a145659
--- /dev/null
@@ -0,0 +1,10 @@
+VERS_1.0
+{
+  global:
+    olsrd_plugin_interface_version;
+    olsrd_plugin_init;
+    olsrd_get_plugin_parameters;
+
+  local:
+    *;
+};