Initial addittion of the BMF multicast plugin
authorAndreas Tonnesen <andreto@olsr.org>
Wed, 3 May 2006 08:59:16 +0000 (08:59 +0000)
committerAndreas Tonnesen <andreto@olsr.org>
Wed, 3 May 2006 08:59:16 +0000 (08:59 +0000)
19 files changed:
Makefile
lib/Makefile
lib/bmf/Copyright-Disclaimer.txt [new file with mode: 0644]
lib/bmf/Makefile [new file with mode: 0644]
lib/bmf/README_BMF.txt [new file with mode: 0644]
lib/bmf/src/Address.c [new file with mode: 0644]
lib/bmf/src/Address.h [new file with mode: 0644]
lib/bmf/src/Bmf.c [new file with mode: 0644]
lib/bmf/src/Bmf.h [new file with mode: 0644]
lib/bmf/src/DropList.c [new file with mode: 0644]
lib/bmf/src/DropList.h [new file with mode: 0644]
lib/bmf/src/NetworkInterfaces.c [new file with mode: 0644]
lib/bmf/src/NetworkInterfaces.h [new file with mode: 0644]
lib/bmf/src/Packet.c [new file with mode: 0644]
lib/bmf/src/Packet.h [new file with mode: 0644]
lib/bmf/src/PacketHistory.c [new file with mode: 0644]
lib/bmf/src/PacketHistory.h [new file with mode: 0644]
lib/bmf/src/olsrd_plugin.c [new file with mode: 0644]
lib/bmf/version-script.txt [new file with mode: 0644]

index feb2c4d..548d17a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -35,7 +35,7 @@
 # to the project. For more information see the website or contact
 # the copyright holders.
 #
-# $Id: Makefile,v 1.69 2006/01/06 06:52:17 kattemat Exp $
+# $Id: Makefile,v 1.70 2006/05/03 08:59:16 kattemat Exp $
 
 VERS =         0.5.0pre
 
@@ -160,5 +160,10 @@ pgraph:
                $(MAKE) -C lib/pgraph 
                $(MAKE) -C lib/pgraph install 
 
+bmf:
+               $(MAKE) -C lib/bmf clean
+               $(MAKE) -C lib/bmf 
+               $(MAKE) -C lib/bmf install 
+
 build_all:     cfgparser olsrd libs
 install_all:   install install_libs
index 92e40ac..0f08ab2 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS = dot_draw dyn_gw httpinfo mini nameservice powerinfo secure tas
+SUBDIRS = dot_draw dyn_gw httpinfo mini nameservice powerinfo secure tas bmf
 
 .PHONY: $(SUBDIRS)
 
diff --git a/lib/bmf/Copyright-Disclaimer.txt b/lib/bmf/Copyright-Disclaimer.txt
new file mode 100644 (file)
index 0000000..6a06efd
--- /dev/null
@@ -0,0 +1,31 @@
+/*\r
+ * OLSR Basic Multicast Forwarding (BMF) plugin.\r
+ * Copyright (c) 2005, 2006, Thales Communications, Huizen, The Netherlands.\r
+ * Written by Erik Tromp.\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without \r
+ * modification, are permitted provided that the following conditions \r
+ * are met:\r
+ *\r
+ * * Redistributions of source code must retain the above copyright \r
+ *   notice, this list of conditions and the following disclaimer.\r
+ * * Redistributions in binary form must reproduce the above copyright \r
+ *   notice, this list of conditions and the following disclaimer in \r
+ *   the documentation and/or other materials provided with the \r
+ *   distribution.\r
+ * * Neither the name of Thales, BMF nor the names of its \r
+ *   contributors may be used to endorse or promote products derived \r
+ *   from this software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND \r
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED \r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. \r
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, \r
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, \r
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, \r
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY \r
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE \r
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED \r
+ * OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
diff --git a/lib/bmf/Makefile b/lib/bmf/Makefile
new file mode 100644 (file)
index 0000000..e9f6adc
--- /dev/null
@@ -0,0 +1,64 @@
+#
+# OLSR Basic Multicast Forwarding (BMF) plugin.
+# Copyright (c) 2005, 2006, 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.
+#
+# $Id: Makefile,v 1.1 2006/05/03 08:59:04 kattemat Exp $
+
+OLSRD_PLUGIN = true
+PLUGIN_NAME =  olsrd_bmf
+PLUGIN_VER =   1.0.1
+
+TOPDIR = ../..
+include $(TOPDIR)/Makefile.inc
+
+LIBS +=        -lpthread
+
+ifneq ($(OS),linux)
+
+default_target install clean: 
+       @echo "*** BMF Plugin only supported on Linux, sorry!"
+
+else
+
+default_target: $(PLUGIN_FULLNAME)
+
+$(PLUGIN_FULLNAME): $(OBJS)
+               $(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
\ No newline at end of file
diff --git a/lib/bmf/README_BMF.txt b/lib/bmf/README_BMF.txt
new file mode 100644 (file)
index 0000000..bafacd1
--- /dev/null
@@ -0,0 +1,205 @@
+BASIC MULTICAST FORWARDING PLUGIN FOR OLSRD
+by Erik Tromp (erik_tromp@hotmail.com)
+
+27-04-2006: Version 1.0.1 - First release.
+
+
+1. Introduction
+---------------
+
+The Basic Multicast Flooding Plugin forwards IP-multicast and
+IP-local-broacast traffic over an OLSRD network. It uses the
+Multi-Point Relays (MPRs) as identified by the OLSR protocol
+to optimize the flooding of multicast and local broadcast packets
+to all the nodes in the network. To prevent broadcast storms, a
+history of packets is kept; only packets that have not been seen
+in the past 3-6 seconds are forwarded.
+
+In the IP header there is room for only two IP-addresses:
+* the destination IP address (in our case either a multicast
+  IP-address 224.0.0.0...239.255.255.255, or a local broadcast
+  address e.g. 192.168.1.255), and
+* the source IP address (the originator).
+
+For optimized flooding, however, we need more information. Let's
+assume we are the BMF process on one node. We will need to know which
+node forwarded the IP packet to us. Since OLSR keeps track of which
+nodes select our node as MPR (see the olsr_lookup_mprs_set function),
+we can determine if the node that forwarded the packet, has selected us as
+MPR. If so, we must also forward the packet, replacing the 'forwarded-by'
+IP-address to that of us.
+
+Because we need more information than fits in a normal IP-header, the
+original packets are encapsulated into a new IP packet. Encapsulated
+packets are transported in UDP, port 50505. The source address of the
+encapsulation packet is set to the address of the forwarder instead of
+the originator. Of course, the payload of the encapsulation packet is
+the original IP packet.
+
+For local reception, each received encapsulated packets is unpacked
+and passed into a tuntap interface which is specially created for
+this purpose.
+
+Here is in short how the flooding works (see also the
+BmfEncapsulatedPacketReceived(...) function; details with respect to
+the forwarding towards non-OLSR enabled nodes are omitted):
+  
+  On all OLSR-enabled interfaces, setup reception of packets
+    on UDP port 50505.
+  Upon reception of such a packet:
+    If the received packet was sent by ourselves, drop it.
+    If the packet was recently seen, drop it.
+    Unpack the encapsulated packet and send a copy to myself via the
+      TunTap device.
+    If I am an MPR for the node that forwarded the packet to me,
+      forward the packet to all OLSR-enabled interfaces *including*
+      the one on which it was received.
+
+As with all good things in life, it's so simple you could have
+thought of it yourself.
+    
+
+2. How to build and install
+---------------------------
+
+Follow the instructions in the base directory README file under
+section II. - BUILDING AND RUNNING OLSRD. To be sure to install
+the BMF plugin, cd to the base directory and issue the follwing
+command at the shell prompt:
+
+  make install_all
+
+Next, turn on the possibility to create a tuntap device (see also
+/usr/src/linux/Documentation/networking/tuntap.txt)
+
+  mkdir /dev/net # if it doesn't exist already
+  mknod /dev/net/tun c 10 200
+  
+Set permissions, e.g.:
+  chmod 0700 /dev/net/tun
+     
+Edit the file /etc/olsrd.conf to load the BMF plugin. For example:
+
+  LoadPlugin "olsrd_bmf.so.1.0.1"
+  {
+    # No PlParam entries required for basic operation
+  }
+
+
+3. How to run
+-------------
+
+After building and installing OLSRD with the BMF plugin, run the
+olsrd deamon by entering at the shell prompt:
+  olsrd
+
+Look at the output; it should list the BMF plugin, e.g.:
+
+  ---------- Plugin loader ----------
+  Library: olsrd_bmf.so.1.0.1
+  OLSRD Basic Multicast Forwarding plugin 1.0.1 (Apr 29 2006 12:57:57)
+    (C) Thales Communications Huizen, Netherlands
+    Erik Tromp (erik_tromp@hotmail.com)
+  Checking plugin interface version...  4 - OK
+  Trying to fetch plugin init function... OK
+  Trying to fetch param function... OK
+  Sending parameters...
+  "NonOlsrIf"/"eth2"... OK
+  "Drop"/"00:0C:29:28:0E:CC"... OK
+  Running plugin_init function...
+  ---------- LIBRARY LOADED ----------
+
+
+4. How to check if it works
+---------------------------
+
+To check that BMF is working, enter the folliwing command on the
+command prompt:
+  
+  ping -I eth1 224.0.0.1
+    
+Replace eth1 with the name of any OLSR-enabled network interface.
+
+All OLSR-BMF nodes in the MANET should respond. For example:
+
+root@IsdbServer:~# ping -I eth1 224.0.0.1
+PING 224.0.0.1 (224.0.0.1) from 192.168.151.50 eth1: 56(84) bytes of data.
+64 bytes from 192.168.151.50: icmp_seq=1 ttl=64 time=0.511 ms
+64 bytes from 192.168.151.53: icmp_seq=1 ttl=64 time=4.67 ms (DUP!)
+64 bytes from 192.168.151.55: icmp_seq=1 ttl=63 time=10.7 ms (DUP!)
+64 bytes from 192.168.151.50: icmp_seq=2 ttl=64 time=0.076 ms
+64 bytes from 192.168.151.53: icmp_seq=2 ttl=64 time=1.23 ms (DUP!)
+64 bytes from 192.168.151.55: icmp_seq=2 ttl=63 time=1.23 ms (DUP!)
+64 bytes from 192.168.151.50: icmp_seq=3 ttl=64 time=0.059 ms
+64 bytes from 192.168.151.53: icmp_seq=3 ttl=64 time=2.94 ms (DUP!)
+64 bytes from 192.168.151.55: icmp_seq=3 ttl=63 time=5.62 ms (DUP!)
+64 bytes from 192.168.151.50: icmp_seq=4 ttl=64 time=0.158 ms
+64 bytes from 192.168.151.53: icmp_seq=4 ttl=64 time=1.14 ms (DUP!)
+64 bytes from 192.168.151.55: icmp_seq=4 ttl=63 time=1.16 ms (DUP!)
+
+
+5. Adding non-OLSR interfaces to the multicast flooding
+-------------------------------------------------------
+
+As a special feature, it is possible to have multicast and local-broadcast
+IP packets forwarded also on non-OLSR interfaces.
+
+If you have network interfaces on which OLSR is *not* running, but you *do*
+want to forward multicast and local-broadcast IP packets, specify these
+interfaces one by one as "NonOlsrIf" parameters in the BMF plugin section
+of /etc/olsrd.conf. For example:
+
+  LoadPlugin "olsrd_bmf.so.1.0.1"
+  {
+    # Non-OLSR interfaces to participate in the multicast flooding
+    PlParam     "NonOlsrIf"  "eth2"
+    PlParam     "NonOlsrIf"  "eth3"
+  }
+
+If an interface is listed both as NonOlsrIf for BMF, and in the
+Interfaces { ... } section of olsrd.conf, it will be seen by BMF
+as an OLSR-enabled interface. Duh....
+  
+
+6. Testing in a lab environment
+-------------------------------
+
+Setup IP-tables to drop packets from nodes which are not
+direct (1-hop) neigbors. For example, to drop all packets from
+a host with MAC address 00:0C:29:28:0E:CC, enter at the shell prompt:
+
+  iptables -A INPUT -m mac --mac-source 00:0C:29:28:0E:CC -j DROP
+
+Edit the file /etc/olsrd.conf, and specify the MAC addresses of the nodes
+we do not want to see; even though packets from these nodes are dropped
+by iptables, they are still received on network interfaces which are in
+promiscuous mode. For example:
+
+  LoadPlugin "olsrd_bmf.so.1.0.1"
+  {
+    # Drop all packets received from the following MAC sources
+    PlParam     "Drop"       "00:0C:29:C6:E2:61" # RemoteClient1
+    PlParam     "Drop"       "00:0C:29:61:34:B7" # SimpleClient1
+    PlParam     "Drop"       "00:0C:29:28:0E:CC" # SimpleClient2
+  }
+
+
+
+7. Common problems, FAQ
+-----------------------
+
+Question:
+When starting OLSRD with the BMF plugin, I can see the following
+error messages:
+
+OLSRD Basic Multicast Forwarding plugin: open() error: No such file or directory
+OLSRD Basic Multicast Forwarding plugin: error creating local EtherTunTap
+OLSRD Basic Multicast Forwarding plugin: could not initialize network interfaces!
+
+Wat to do?
+
+Answer:
+
+Turn on the possibility to create a tuntap device; see section 2 of this
+file.
+
diff --git a/lib/bmf/src/Address.c b/lib/bmf/src/Address.c
new file mode 100644 (file)
index 0000000..a902175
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005, 2006, 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.
+ */
+
+/* $Id: Address.c,v 1.1 2006/05/03 08:59:04 kattemat Exp $ */
+
+#include "Address.h"
+
+/* System includes */
+#include <assert.h> /* assert() */
+
+/* OLSRD includes */
+#include "defs.h" /* COMP_IP */
+
+/* Plugin includes */
+#include "Bmf.h" /* BMF_ENCAP_PORT */
+
+int IsMulticast(union olsr_ip_addr* ipAddress)
+{
+  assert(ipAddress != NULL);
+
+  return (ntohl(ipAddress->v4) & 0xF0000000) == 0xE0000000;
+}
+
+int IsLocalBroadcast(union olsr_ip_addr* destIp, struct interface* ifFrom)
+{
+  struct sockaddr_in* sin;
+  
+  assert(destIp != NULL);
+
+  /* Protect ourselves against bogus input */
+  if (ifFrom == NULL) return 0;
+
+  /* Cast down to correct sockaddr subtype */
+  sin = (struct sockaddr_in*)&(ifFrom->int_broadaddr);
+
+  /* Just in case OLSR does not have int_broadaddr filled in for this
+   * interface. */
+  if (sin == NULL) return 0;
+
+  return COMP_IP(&(sin->sin_addr.s_addr), destIp);
+}
+
+int IsOlsrOrBmfPacket(unsigned char* buffer, ssize_t len)
+{
+  u_int16_t port;
+
+  assert(buffer != NULL);
+
+  /* Consider OLSR and BMF packets not to be local broadcast
+   * OLSR packets are UDP - port 698
+   * BMF packets are UDP - port 50505 */
+
+  memcpy(&port, buffer + 0x24, 2);
+  port = ntohs(port);
+
+  if (len > 0x25 &&
+      buffer[0x17] == 0x11 && /* UDP */
+      (port == OLSRPORT || port == BMF_ENCAP_PORT))
+  {
+    return 1;
+  }
+  return 0;
+}
diff --git a/lib/bmf/src/Address.h b/lib/bmf/src/Address.h
new file mode 100644 (file)
index 0000000..fd8fc3f
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef _BMF_ADDRESS_H
+#define _BMF_ADDRESS_H
+
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005, 2006, 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.
+ */
+
+/* $Id: Address.h,v 1.1 2006/05/03 08:59:04 kattemat Exp $ */
+
+#include "olsr_types.h" /* olsr_ip_addr */
+#include "interfaces.h" /* struct interface */
+
+int IsMulticast(union olsr_ip_addr* ipAddress);
+int IsLocalBroadcast(union olsr_ip_addr* destIp, struct interface* ifFrom);
+int IsOlsrOrBmfPacket(unsigned char* buffer, ssize_t len);
+
+#endif /* _BMF_ADDRESS_H */
diff --git a/lib/bmf/src/Bmf.c b/lib/bmf/src/Bmf.c
new file mode 100644 (file)
index 0000000..7cefe69
--- /dev/null
@@ -0,0 +1,636 @@
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005, 2006, 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.
+ */
+
+/* $Id: Bmf.c,v 1.1 2006/05/03 08:59:04 kattemat Exp $ */
+
+#define _MULTI_THREADED
+
+#include "Bmf.h"
+
+/* System includes */
+#include <stdio.h> /* NULL */
+#include <sys/types.h> /* ssize_t */
+#include <string.h> /* strerror() */
+#include <errno.h> /* errno */
+#include <assert.h> /* assert() */
+#include <linux/if_packet.h> /* struct sockaddr_ll, PACKET_MULTICAST */
+#include <pthread.h> /* pthread_create() */
+#include <signal.h> /* SIGINT */
+
+/* OLSRD includes */
+#include "defs.h" /* olsr_cnf */
+#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() */
+
+/* Plugin includes */
+#include "NetworkInterfaces.h" /* TBmfInterface, CreateBmfNetworkInterfaces(), CloseBmfNetworkInterfaces() */
+#include "Address.h" /* IsMulticast(), IsLocalBroadcast() */
+#include "Packet.h" /* ETH_TYPE_OFFSET, IFHWADDRLEN etc. */
+#include "PacketHistory.h" /* InitPacketHistory() */
+#include "DropList.h" /* DropMac() */
+
+static pthread_t BmfThread;
+static int BmfThreadRunning = 0;
+
+
+static void BmfPacketCaptured(struct TBmfInterface* intf, unsigned char* buffer, ssize_t len)
+{
+  struct interface* ifFrom;
+  unsigned char* srcMac;
+  union olsr_ip_addr srcIp;
+  union olsr_ip_addr destIp;
+  union olsr_ip_addr* originator;
+  struct sockaddr_in sin;
+  struct TBmfInterface* nextFwIntf;
+
+  /* Only forward IPv4 packets */
+  u_int16_t type;
+  memcpy(&type, buffer + ETH_TYPE_OFFSET, 2);
+  if (ntohs(type) != IPV4_TYPE)
+  {
+    return;
+  }
+
+  /* Lookup the OLSR interface on which this packet is received */
+  ifFrom = intf->olsrIntf;
+
+  /* Only forward multicast or local broadcast packets */
+  COPY_IP(&destIp, buffer + IP_HDR_OFFSET + IPV4_OFFSET_DSTIP);
+  if (! IsMulticast(&destIp) && ! IsLocalBroadcast(&destIp, ifFrom))
+  {
+    return;
+  }
+  
+  /* Discard OLSR packets (UDP port 698) and BMF encapsulated packets
+   * (UDP port 50505) */
+  if (IsOlsrOrBmfPacket(buffer, len))
+  {
+    return;
+  }
+
+  /* Apply drop list for testing purposes. */
+  srcMac = buffer + IFHWADDRLEN;
+  if (IsInDropList(srcMac))
+  {
+    return;
+  }
+
+  /* Lookup main address of source */
+       COPY_IP(&srcIp, buffer + IP_HDR_OFFSET + IPV4_OFFSET_SRCIP);
+  originator = mid_lookup_main_addr(&srcIp);
+  if (originator == NULL)
+  {
+    originator = &srcIp;
+  }
+
+  olsr_printf(
+    9,
+    "MC pkt to %s received from originator %s (%s) via \"%s\"\n",
+    olsr_ip_to_string(&destIp),
+    olsr_ip_to_string(originator),
+    olsr_ip_to_string(&srcIp),
+    intf->ifName);
+
+  /* Check if I am MPR for that originator */
+  if (ifFrom != NULL && olsr_lookup_mprs_set(originator) == NULL)
+  {
+    olsr_printf(
+      9,
+      "--> Discarding pkt: I am not selected as MPR by that originator\n");
+    return;
+  }
+
+  /* If this packet is captured on a non-OLSR interface, decrease
+   * the TTL and re-calculate the IP header checksum */
+  if (ifFrom == NULL)
+  {
+    PacketDecreaseTtlAndUpdateHeaderChecksum(buffer);
+  }
+
+  /* If the TTL is <= 0, do not forward this packet */
+  if (GetIpTtl(buffer) <= 0)
+  {
+    return;
+  }
+
+  /* Check if this packet was seen recently */
+  if (CheckMarkRecentPacket(buffer, len))
+  {
+    olsr_printf(
+      9,
+      "--> Discarding pkt: was a duplicate\n");
+    return;
+  }
+
+  /* Encapsulate and forward packet on all OLSR interfaces */
+  memset(&sin, 0, sizeof(sin));
+  sin.sin_family = AF_INET;
+  sin.sin_port = htons(BMF_ENCAP_PORT);
+
+  nextFwIntf = BmfInterfaces;
+  while (nextFwIntf != NULL)
+  {
+    struct TBmfInterface* fwIntf = nextFwIntf;
+    nextFwIntf = fwIntf->next;
+
+    if (fwIntf->olsrIntf != NULL)
+    {
+      int nBytesWritten;
+
+      /* Change source MAC address to that of myself */
+      memcpy(buffer + IFHWADDRLEN, fwIntf->macAddr, IFHWADDRLEN);
+
+      /* Destination address is local broadcast */
+      sin.sin_addr.s_addr = ((struct sockaddr_in*)&fwIntf->olsrIntf->int_broadaddr)->sin_addr.s_addr;
+
+      nBytesWritten = sendto(
+        fwIntf->encapsulatingSkfd,
+        buffer,
+        len,
+        MSG_DONTROUTE,
+        (struct sockaddr*) &sin,
+        sizeof(sin));                   
+
+      if (nBytesWritten != len)
+      {
+        olsr_printf(
+          1,
+          "%s: sendto() error forwarding MC pkt for %s to \"%s\": %s\n",
+          PLUGIN_NAME,
+          olsr_ip_to_string(&destIp),
+          fwIntf->olsrIntf->int_name,
+          strerror(errno));
+      }
+      else
+      {
+        olsr_printf(
+          9,
+          "Successfully encapsulated one MC pkt for %s to \"%s\"\n",
+          olsr_ip_to_string(&destIp),
+          fwIntf->olsrIntf->int_name);
+      } /* if (nBytesWritten != len) */
+    } /* if (fwIntf->olsrIntf != NULL) */
+  } /* while (nextFwIntf != NULL) */
+}
+
+static void BmfEncapsulatedPacketReceived(
+  struct TBmfInterface* intf, 
+  struct in_addr srcIp,
+  unsigned char* buffer,
+  ssize_t len)
+{
+  union olsr_ip_addr fromAddr;
+  struct interface* ifFrom;
+  union olsr_ip_addr* forwarder;
+  int nBytesToWrite;
+  unsigned char* bufferToWrite;
+  int nBytesWritten;
+  int iAmMpr;
+  struct sockaddr_in sin;
+  struct TBmfInterface* nextFwIntf;
+
+  COPY_IP(&fromAddr, &srcIp.s_addr);
+
+  /* Are we talking to ourselves? */
+  if (if_ifwithaddr(&fromAddr) != NULL)
+  {
+    return;
+  }
+
+  /* Lookup the OLSR interface on which this packet is received */
+  ifFrom = intf->olsrIntf;
+
+  /* Encapsulated packet received on non-OLSR interface? Then discard */
+  if (ifFrom == NULL)
+  {
+    return;
+  }
+
+  /* Apply drop list? No, not needed: encapsulated packets are routed,
+   * so filtering should be done by adding a rule to the iptables FORWARD
+   * chain, e.g.:
+   * iptables -A FORWARD -m mac --mac-source 00:0C:29:28:0E:CC -j DROP */
+
+  /* Lookup main address of forwarding node */
+  forwarder = mid_lookup_main_addr(&fromAddr);
+  if (forwarder == NULL)
+  {
+    forwarder = &fromAddr;
+    olsr_printf(
+      9,
+      "Encapsulated MC pkt received; forwarder to me by %s on \"%s\"\n",
+      olsr_ip_to_string(forwarder),
+      intf->ifName);
+  }
+  else
+  {
+    olsr_printf(
+      9,
+      "Encapsulated MC pkt received; forwarder to me by %s (thru %s) on \"%s\"\n",
+      olsr_ip_to_string(forwarder),
+      olsr_ip_to_string(&fromAddr),
+      intf->ifName);
+  }
+
+  /* Check if this packet was seen recently */
+  if (CheckMarkRecentPacket(buffer, len))
+  {
+    olsr_printf(
+      9,
+      "--> Discarding encapsulated pkt: was a duplicate\n");
+    return;
+  }
+
+  /* Unpack encapsulated packet and send a copy to myself via the EtherTunTap device */
+  nBytesToWrite = len;
+  bufferToWrite = buffer;
+  if (TunOrTap == TT_TUN)
+  {
+    nBytesToWrite -= IP_HDR_OFFSET;
+    bufferToWrite += IP_HDR_OFFSET;
+  }
+  nBytesWritten = write(EtherTunTapFd, bufferToWrite, nBytesToWrite);
+  if (nBytesWritten != nBytesToWrite)
+  {
+    olsr_printf(
+      1,
+      "%s: write() error sending encapsulated MC pkt to \"%s\": %s\n",
+      PLUGIN_NAME,
+      EtherTunTapIfName,
+      strerror(errno));
+  }
+  else
+  {
+    olsr_printf(
+      9,
+      "Successfully unpacked and sent encapsulated MC pkt to \"%s\"\n",
+      EtherTunTapIfName);
+  }
+
+  /* Check if I am MPR for the forwarder */
+  iAmMpr = (olsr_lookup_mprs_set(forwarder) != NULL);
+  if (! iAmMpr)
+  {
+    olsr_printf(
+      9,
+      "--> Not forwarding encapsulated pkt: I am not selected as MPR by that forwarder\n");
+  }
+
+  memset(&sin, 0, sizeof(sin));
+  sin.sin_family = AF_INET;
+  sin.sin_port = htons(BMF_ENCAP_PORT);
+
+  nextFwIntf = BmfInterfaces;
+  while (nextFwIntf != NULL)
+  {
+    struct TBmfInterface* fwIntf = nextFwIntf;
+    nextFwIntf = fwIntf->next;
+
+    /* On non-OLSR interfaces: unpack encapsulated packet, decrease TTL
+     * and send */
+    if (fwIntf->olsrIntf == NULL)
+    {
+      struct TSaveTtl sttl;
+
+      /* Change source MAC address to that of sending interface */
+      memcpy(buffer + IFHWADDRLEN, fwIntf->macAddr, IFHWADDRLEN);
+
+      /* Save IP header checksum and the TTL-value of the packet, then 
+       * decrease the TTL by 1 before writing */
+      SaveTtlAndChecksum(buffer, &sttl);
+      PacketDecreaseTtlAndUpdateHeaderChecksum(buffer);
+
+      /* If the TTL is <= 0, do not forward this packet */
+      if (GetIpTtl(buffer) <= 0)
+      {
+        return;
+      }
+
+      nBytesWritten = write(fwIntf->capturingSkfd, buffer, len);
+      if (nBytesWritten != len)
+      {
+        olsr_printf(
+          1,
+          "%s: write() error sending unpacked encapsulated MC pkt to \"%s\": %s\n",
+          PLUGIN_NAME,
+          fwIntf->ifName,
+          strerror(errno));
+      }
+      else
+      {
+        olsr_printf(
+          9,
+          "Successfully unpacked and sent one encapsulated MC pkt to \"%s\"\n",
+          fwIntf->ifName);
+      }
+
+      /* Restore the IP header checksum and the TTL-value of the packet */
+      RestoreTtlAndChecksum(buffer, &sttl);
+    } /* if (fwIntf->olsrIntf == NULL) */
+
+    /* On OLSR interfaces, forward the packet if this node is selected as MPR by the 
+     * forwarding node */
+    else if (iAmMpr)
+    {
+      /* Change source MAC address to that of sending interface */
+      memcpy(buffer + IFHWADDRLEN, fwIntf->macAddr, IFHWADDRLEN);
+
+      /* Destination address is local broadcast */
+      sin.sin_addr.s_addr = ((struct sockaddr_in*)&fwIntf->olsrIntf->int_broadaddr)->sin_addr.s_addr;
+
+      nBytesWritten = sendto(
+        fwIntf->encapsulatingSkfd,
+        buffer,
+        len,
+        MSG_DONTROUTE,
+        (struct sockaddr*) &sin,
+        sizeof(sin));                   
+
+      if (nBytesWritten != len)
+      {
+        olsr_printf(
+          1,
+          "%s: sendto() error forwarding encapsulated MC pkt to \"%s\": %s\n",
+          PLUGIN_NAME,
+          fwIntf->olsrIntf->int_name,
+          strerror(errno));
+      }
+      else
+      {
+        olsr_printf(
+          9,
+          "Successfully forwarded one encapsulated MC pkt to \"%s\"\n",
+          fwIntf->olsrIntf->int_name);
+      }
+    } /* else if (iAmMpr) */
+  } /* while (nextFwIntf != NULL) */
+}
+
+static void DoBmf(void* useless)
+{
+#define BUFFER_MAX 2048
+  struct TBmfInterface* intf;
+  int nFdBitsSet;
+
+  /* Compose set of socket file descriptors. 
+   * Keep the highest descriptor seen. */
+  int highestSkfd = -1;
+  fd_set input_set;
+  FD_ZERO(&input_set);
+
+  intf = BmfInterfaces;
+  while (intf != NULL)
+  {
+    FD_SET(intf->capturingSkfd, &input_set);
+    if (intf->capturingSkfd > highestSkfd)
+    {
+      highestSkfd = intf->capturingSkfd;
+    }
+
+    if (intf->encapsulatingSkfd >= 0)
+    {
+      FD_SET(intf->encapsulatingSkfd, &input_set);
+      if (intf->encapsulatingSkfd > highestSkfd)
+      {
+        highestSkfd = intf->encapsulatingSkfd;
+      }
+    }
+
+    intf = intf->next;    
+  }
+
+  assert(highestSkfd >= 0);
+
+  /* Wait (blocking) for packets received on any of the sockets */
+  nFdBitsSet = select(highestSkfd + 1, &input_set, NULL, NULL, NULL);
+  if (nFdBitsSet < 0)
+  {
+    if (errno != EINTR)
+    {
+      olsr_printf(1, "%s: select() error: %s\n", PLUGIN_NAME, strerror(errno));
+    }
+    return;
+  }
+    
+  if (nFdBitsSet == 0)
+  {
+    /* No packets waiting. This is unexpected; normally we would excpect select(...)
+     * to return only if at least one packet was received (so nFdBitsSet > 0), or
+     * if this thread received a signal (so nFdBitsSet < 0). */
+    return;
+  }
+
+  while (nFdBitsSet > 0)
+  {
+    intf = BmfInterfaces;
+    while (intf != NULL)
+    {
+      int skfd = intf->capturingSkfd;
+      if (FD_ISSET(skfd, &input_set))
+      {
+        unsigned char buffer[BUFFER_MAX];
+        struct sockaddr_ll pktAddr;
+        socklen_t addrLen;
+        int nBytes;
+
+        /* A packet was captured */
+
+        nFdBitsSet--;
+
+        memset(&pktAddr, 0, sizeof(struct sockaddr_ll));
+        addrLen = sizeof(pktAddr);
+
+        nBytes = recvfrom(skfd, buffer, BUFFER_MAX, 0, (struct sockaddr*)&pktAddr, &addrLen);
+        if (nBytes < 0)
+        {
+          olsr_printf(1, "%s: recvfrom() error: %s\n", PLUGIN_NAME, strerror(errno));
+        }
+
+        /* Don't let BMF crash by sending too short packets. IP packets are always
+         * at least 14 (Ethernet header) + 20 (IP header) = 34 bytes long. */
+        if (nBytes >= 34)
+        {
+          if (pktAddr.sll_pkttype == PACKET_OUTGOING)
+          {
+            union olsr_ip_addr destIp;
+            COPY_IP(&destIp, buffer + IP_HDR_OFFSET + IPV4_OFFSET_DSTIP);
+            if (IsMulticast(&destIp) || IsLocalBroadcast(&destIp, intf->olsrIntf))
+            {
+              if (! IsOlsrOrBmfPacket(buffer, nBytes))
+              {
+                MarkRecentPacket(buffer, nBytes);
+              }
+            }
+          }
+          else if (pktAddr.sll_pkttype == PACKET_MULTICAST ||
+                   pktAddr.sll_pkttype == PACKET_BROADCAST)
+          {
+            BmfPacketCaptured(intf, buffer, nBytes);
+          }
+        } /* if (nBytes >= 34) */
+      } /* if (FD_ISSET...) */
+
+      skfd = intf->encapsulatingSkfd;
+      if (skfd >= 0 && (FD_ISSET(skfd, &input_set)))
+      {
+        unsigned char buffer[BUFFER_MAX];
+        struct sockaddr_in addr;
+        socklen_t addrLen = sizeof(addr);
+        int nBytes;
+
+        /* An encapsulated packet was received */
+
+        nFdBitsSet--;
+
+        memset(&addr, 0, sizeof(addr));
+
+        nBytes = recvfrom(skfd, buffer, BUFFER_MAX, 0, (struct sockaddr*)&addr, &addrLen);
+        if (nBytes < 0)
+        {
+          olsr_printf(1, "%s: recvfrom() error: %s\n", PLUGIN_NAME, strerror(errno));
+        }
+        if (nBytes > 0)
+        {
+          BmfEncapsulatedPacketReceived(intf, addr.sin_addr, buffer, nBytes);
+        }
+      } /* if (skfd >= 0 && (FD_ISSET...) */
+
+      intf = intf->next;    
+    } /* while (intf != NULL) */
+  } /* while (nFdBitsSet > 0) */
+}
+
+static void BmfSignalHandler(int signo)
+{
+  /* Dummy handler function */
+  return;
+}
+
+/* Thread entry function. Another thread can gracefully stop this thread by writing a
+ * '0' into global variable 'BmfThreadRunning' followed by sending a SIGALRM signal. */
+static void* BmfRun(void* useless)
+{
+  sigset_t blockedSigs;
+  sigfillset(&blockedSigs);
+  sigdelset(&blockedSigs, SIGALRM);
+  if (pthread_sigmask(SIG_BLOCK, &blockedSigs, NULL) < 0)
+  {
+    olsr_printf(1, "%s: pthread_sigmask() error: %s\n", PLUGIN_NAME, strerror(errno));
+  }
+
+  /* Set up the signal handler for the process: use SIGALRM to terminate
+   * the BMF thread. Only if a signal handler is specified, does a blocking
+   * system call return with errno set to EINTR; if a signal hander is not
+   * specified, any system call in which the thread may be waiting will not
+   * return. Note that the BMF thread is usually blocked in the select()
+   * function (see DoBmf()). */
+  if (signal(SIGALRM, BmfSignalHandler) == SIG_ERR)
+  {
+    olsr_printf(1, "%s: signal() error: %s\n", PLUGIN_NAME, strerror(errno));
+  }
+
+  /* Call the thread function until flagged to exit */
+  while (BmfThreadRunning != 0)
+  {
+    DoBmf(useless);
+  }
+  
+  return NULL;
+}
+
+/* Initialize the BMF plugin */
+int InitBmf()
+{
+  /* Check validity */
+  if (olsr_cnf->ip_version != AF_INET)
+  {
+    fprintf(stderr, PLUGIN_NAME ": This plugin only supports IPv4!\n");
+    return 0;
+  }
+
+  /* Clear the packet history */
+  InitPacketHistory();
+
+  if (CreateBmfNetworkInterfaces() < 0)
+  {
+    fprintf(stderr, PLUGIN_NAME ": could not initialize network interfaces!\n");
+    return 0;
+  }
+  
+  /* Run the multicast packet processing thread */
+  BmfThreadRunning = 1;
+  pthread_create(&BmfThread, NULL, BmfRun, NULL);
+
+  /* Register the duplicate registration pruning process */
+  olsr_register_scheduler_event(&PrunePacketHistory, NULL, 3.0, 2.0, NULL);
+
+  return 1;
+}
+
+/* Close the BMF plugin */
+void CloseBmf()
+{
+  /* Signal BmfThread to exit */
+  BmfThreadRunning = 0;
+  if (pthread_kill(BmfThread, SIGALRM) < 0)
+  /* Strangely enough, all running threads receive the SIGALRM signal. But only the
+   * BMF thread is affected by this signal, having specified a handler for this
+   * signal in its thread entry function BmfRun(...). */
+  {
+    olsr_printf(1, "%s: pthread_kill() error: %s\n", PLUGIN_NAME, strerror(errno));
+  }
+
+  /* Wait for BmfThread to acknowledge */
+  if (pthread_join(BmfThread, NULL) < 0)
+  {
+    olsr_printf(1, "%s: pthread_join() error: %s\n", PLUGIN_NAME, strerror(errno));
+  }
+
+  /* Time to clean up */
+  CloseBmfNetworkInterfaces();
+}
+
+int RegisterBmfParameter(char* key, char* value)
+{
+  if (strcmp(key, "Drop") == 0)
+  {
+    return DropMac(value);
+  }
+  else if (strcmp(key, "NonOlsrIf") == 0)
+  {
+    return AddNonOlsrBmfIf(value);
+  }
+
+  return 0;
+}
diff --git a/lib/bmf/src/Bmf.h b/lib/bmf/src/Bmf.h
new file mode 100644 (file)
index 0000000..24c78e6
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef _BMF_BMF_H
+#define _BMF_BMF_H
+
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005, 2006, 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.
+ */
+
+/* $Id: Bmf.h,v 1.1 2006/05/03 08:59:04 kattemat Exp $ */
+
+/* BMF plugin data */
+#define PLUGIN_NAME "OLSRD Basic Multicast Forwarding plugin"
+#define PLUGIN_VERSION "1.0.1 (" __DATE__ " " __TIME__ ")"
+#define PLUGIN_COPYRIGHT "  (C) Thales Communications Huizen, Netherlands"
+#define PLUGIN_AUTHOR "  Erik Tromp (erik_tromp@hotmail.com)"
+#define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION "\n" PLUGIN_COPYRIGHT "\n" PLUGIN_AUTHOR
+
+/* UDP-Port on which multicast packets are encapsulated */
+#define BMF_ENCAP_PORT 50505
+
+int InitBmf(void);
+void CloseBmf(void);
+int RegisterBmfParameter(char* key, char* value);
+
+#endif /* _BMF_BMF_H */
diff --git a/lib/bmf/src/DropList.c b/lib/bmf/src/DropList.c
new file mode 100644 (file)
index 0000000..57beafe
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005, 2006, 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.
+ */
+
+/* $Id: DropList.c,v 1.1 2006/05/03 08:59:04 kattemat Exp $ */
+
+
+#include "DropList.h"
+
+/* System includes */
+#include <assert.h> /* assert() */
+#include <stdio.h> /* NULL */
+#include <stdlib.h> /* malloc */
+#include <string.h> /* memcmp */
+
+/* OLSRD includes */
+#include "olsr.h" /* olsr_printf */
+
+/* Plugin includes */
+#include "Bmf.h" /* PLUGIN_NAME */
+#include "Packet.h" /* IFHWADDRLEN */
+
+static struct TMacAddress* DroppedMacAddresses = NULL;
+
+/* Register a MAC address in the drop list. The registered MAC address will be matched
+ * to the source MAC address of incoming multicast packets. If matched, the multicast
+ * packet will be silently dropped.
+ * The drop list is needed only in lab environments, where hidden nodes are simulated
+ * by using iptables with the -m mac --mac-source option (as in:
+ * "iptables -A INPUT -m mac --mac-source 00:0C:29:EE:C9:D0 -j DROP")
+ * The drop list is needed because network interfaces in promiscuous mode will still
+ * capture packets even if they are specified to be dropped by iptables.
+ */
+int DropMac(const char* macStr)
+{
+  unsigned int mac[6];
+  int n;
+  struct TMacAddress* newMacAddress;
+  int i;
+
+  assert(macStr != NULL);
+
+  n = sscanf(macStr, "%x:%x:%x:%x:%x:%x", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
+  if (n != 6)
+  {
+    olsr_printf(1, "%s: Invalid Ethernet address '%s'\n", PLUGIN_NAME, macStr);
+    return 0;
+  }
+
+  newMacAddress = malloc(sizeof(struct TMacAddress));
+  for (i = 0; i < 6; i++)
+  {
+    newMacAddress->addr[i] = (unsigned char) mac[i];
+  }
+  newMacAddress->next = DroppedMacAddresses;
+  DroppedMacAddresses = newMacAddress;
+
+  return 1;
+}
+
+/* Return 1 if macAddress is in the drop list, else 0 */
+int IsInDropList(const unsigned char* macAddress)
+{
+  struct TMacAddress* ma = DroppedMacAddresses;
+
+  assert(macAddress != NULL);
+
+  while (ma != NULL)
+  {
+    if (memcmp(ma->addr, macAddress, IFHWADDRLEN) == 0) return 1;
+    ma = ma->next;
+  }
+  return 0;
+}
+
diff --git a/lib/bmf/src/DropList.h b/lib/bmf/src/DropList.h
new file mode 100644 (file)
index 0000000..02e0932
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef _BMF_DROPLIST_H
+#define _BMF_DROPLIST_H
+
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005, 2006, 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.
+ */
+
+/* $Id: DropList.h,v 1.1 2006/05/03 08:59:04 kattemat Exp $ */
+
+struct TMacAddress
+{
+  unsigned char addr[6];
+  struct TMacAddress* next;
+};
+
+int DropMac(const char* macStr);
+int IsInDropList(const unsigned char* macAddress);
+
+#endif /* _BMF_DROPLIST_H */
diff --git a/lib/bmf/src/NetworkInterfaces.c b/lib/bmf/src/NetworkInterfaces.c
new file mode 100644 (file)
index 0000000..8bbad8b
--- /dev/null
@@ -0,0 +1,599 @@
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005, 2006, 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.
+ */
+
+/* $Id: NetworkInterfaces.c,v 1.1 2006/05/03 08:59:04 kattemat Exp $ */
+
+#include "NetworkInterfaces.h"
+
+/* System includes */
+#include <syslog.h> /* syslog() */
+#include <string.h> /* strerror() */
+#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> /* if_indextoname() */
+#include <netinet/in.h> /* htons() */
+#include <linux/if_ether.h> /* ETH_P_ALL */
+#include <linux/if_packet.h> /* packet_mreq, PACKET_MR_PROMISC, PACKET_ADD_MEMBERSHIP */
+#include <linux/if_tun.h> /* IFF_TAP */
+
+/* OLSRD includes */
+#include "olsr.h" /* olsr_printf */
+#include "defs.h" /* olsr_cnf */
+
+/* Plugin includes */
+#include "Packet.h" /* IFHWADDRLEN */
+#include "Bmf.h" /* PLUGIN_NAME */
+
+/* List of network interfaces used by BMF plugin */
+struct TBmfInterface* BmfInterfaces = NULL;
+
+/* File descriptor of EtherTunTap device */
+int EtherTunTapFd = -1;
+
+/* Network interface name of EtherTunTap device. If the name starts with "tun", an
+ * IP tunnel interface will be used. Otherwise, an EtherTap device will be used. */
+const char* EtherTunTapIfName = "tun0"; /* "tap0"; */
+
+/* If the network interface name starts with "tun", an IP tunnel interface will be
+ * used, and this variable will be set to TUN. Otherwise, an EtherTap device will
+ * be used, and this variable will be set to TAP. */
+enum TTunOrTap TunOrTap;
+
+/* Create raw packet socket for capturing multicast IP traffic. Returns
+ * the socket descriptor, or -1 if an error occurred. */
+static int CreateCaptureSocket(int ifIndex)
+{
+  struct packet_mreq mreq;
+  struct ifreq req;
+  struct sockaddr_ll iface_addr;
+
+  /* Open raw packet socket */
+  int skfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+  if (skfd < 0)
+  {
+    olsr_printf(1, "%s: socket(PF_PACKET) error: %s\n", PLUGIN_NAME, strerror(errno));
+    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)
+  {
+    olsr_printf(1, "%s: setsockopt(PACKET_MR_PROMISC) error: %s\n", PLUGIN_NAME, strerror(errno));
+    close(skfd);
+    return -1;
+  }
+
+  /* Get hardware (MAC) address */
+  memset(&req, 0, sizeof(struct ifreq));
+  if (if_indextoname(ifIndex, req.ifr_name) == NULL ||
+      ioctl(skfd, SIOCGIFHWADDR, &req) < 0)
+  {
+    olsr_printf(1, "%s: error retrieving MAC address: %s\n", PLUGIN_NAME, strerror(errno));
+    close(skfd);
+    return -1;
+  }
+   
+  /* Bind the socket to the specified interface */
+  memset(&iface_addr, 0, sizeof(iface_addr));
+  iface_addr.sll_protocol = htons(ETH_P_ALL);
+  iface_addr.sll_ifindex = ifIndex;
+  iface_addr.sll_family = AF_PACKET;
+  memcpy(iface_addr.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN);
+  iface_addr.sll_halen = IFHWADDRLEN;
+    
+  if (bind(skfd, (struct sockaddr*)&iface_addr, sizeof(iface_addr)) < 0)
+  {
+    olsr_printf(1, "%s: bind() error: %s\n", PLUGIN_NAME, strerror(errno));
+    close(skfd);
+    return -1;
+  }
+
+  /* Set socket to blocking operation */
+  if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
+  {
+    olsr_printf(1, "%s: fcntl() error: %s\n", PLUGIN_NAME, strerror(errno));
+    close(skfd);
+    return -1;
+  }
+
+  return skfd;
+}
+
+/* Create UDP (datagram) over IP socket to send encapsulated multicast packets over.
+ * Returns the socket descriptor, or -1 if an error occurred. */
+static int CreateEncapsulateSocket(int ifIndex)
+{
+  int on = 1;
+  char ifName[IFNAMSIZ];
+  struct sockaddr_in sin;
+
+  /* Open UDP-IP socket */
+  int skfd = socket(PF_INET, SOCK_DGRAM, 0);
+  if (skfd < 0)
+  {
+    olsr_printf(1, "%s: socket(PF_INET) error: %s\n", PLUGIN_NAME, strerror(errno));
+    return -1;
+  }
+
+  /* Enable sending to broadcast addresses */
+  if (setsockopt(skfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0)
+  {
+    olsr_printf(1, "%s: setsockopt() error: %s\n", PLUGIN_NAME, strerror(errno));
+    close(skfd);
+    return -1;
+  }
+       
+  /* Bind to the specific network interfaces indicated by ifIndex */
+  if (if_indextoname(ifIndex, ifName) == NULL ||
+      setsockopt(skfd, SOL_SOCKET, SO_BINDTODEVICE, ifName, strlen(ifName) + 1) < 0)
+  {
+    olsr_printf(1, "%s: setsockopt() error: %s\n", PLUGIN_NAME, strerror(errno));
+    close(skfd);
+    return -1;
+  }
+    
+  memset(&sin, 0, sizeof(sin));
+  sin.sin_family = AF_INET;
+  sin.sin_port = htons(BMF_ENCAP_PORT);
+  sin.sin_addr.s_addr = htonl(INADDR_ANY);
+      
+  if (bind(skfd, (struct sockaddr*)&sin, sizeof(sin)) < 0) 
+  {
+    olsr_printf(1, "%s: bind() error: %s\n", PLUGIN_NAME, strerror(errno));
+    close(skfd);
+    return -1;
+  }
+
+  /* Set socket to blocking operation */
+  if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0)
+  {
+    olsr_printf(1, "%s: fcntl() error: %s\n", PLUGIN_NAME, strerror(errno));
+    close(skfd);
+    return -1;
+  }
+
+  return skfd;
+}
+
+/* To save the state of the IP spoof filter for the EtherTunTap device */
+static char EthTapSpoofState = '1';
+
+static int DeactivateSpoofFilter(const char* ifName)
+{
+  FILE* procSpoof;
+  char procFile[FILENAME_MAX];
+
+  assert(ifName != NULL);
+
+  /* Generate the procfile name */
+  sprintf(procFile, "/proc/sys/net/ipv4/conf/%s/rp_filter", ifName);
+
+  procSpoof = fopen(procFile, "r");
+  if (procSpoof == NULL)
+  {
+    fprintf(
+      stderr,
+      "WARNING! Could not open the %s file to check/disable the IP spoof filter!\n"
+      "Are you using the procfile filesystem?\n"
+      "Does your system support IPv4?\n"
+      "I will continue (in 3 sec) - but you should manually ensure that IP spoof\n"
+      "filtering is disabled!\n\n",
+      procFile);
+      
+    sleep(3);
+    return 0;
+  }
+
+  EthTapSpoofState = fgetc(procSpoof);
+  fclose(procSpoof);
+
+  procSpoof = fopen(procFile, "w");
+  if (procSpoof == NULL)
+  {
+    fprintf(stderr, "Could not open %s for writing!\n", procFile);
+    fprintf(
+      stderr,
+      "I will continue (in 3 sec) - but you should manually ensure that IP"
+      " spoof filtering is disabled!\n\n");
+    sleep(3);
+    return 0;
+  }
+
+  syslog(LOG_INFO, "Writing \"0\" to %s", procFile);
+  fputs("0", procSpoof);
+
+  fclose(procSpoof);
+
+  return 1;
+}
+
+static void RestoreSpoofFilter(const char* ifName)
+{
+  FILE* procSpoof;
+  char procFile[FILENAME_MAX];
+
+  assert(ifName != NULL);
+
+  /* Generate the procfile name */
+  sprintf(procFile, "/proc/sys/net/ipv4/conf/%s/rp_filter", ifName);
+
+  procSpoof = fopen(procFile, "w");
+  if (procSpoof == NULL)
+  {
+    fprintf(stderr, "Could not open %s for writing!\nSettings not restored!\n", procFile);
+  }
+  else
+  {
+    syslog(LOG_INFO, "Resetting %s to %c\n", procFile, EthTapSpoofState);
+
+    fputc(EthTapSpoofState, procSpoof);
+    fclose(procSpoof);
+  }
+}
+
+/* Creates and brings up an EtherTunTap device e.g. "tun0" or "tap0"
+ * (as specified in const char* EtherTunTapIfName) */
+static int CreateLocalEtherTunTap(void)
+{
+  struct ifreq ifreq;
+  int etfd = open("/dev/net/tun", O_RDWR);
+  int skfd;
+  int ioctlres = 0;
+
+  if (etfd < 0)
+  {
+    olsr_printf(1, "%s: open() error: %s\n", PLUGIN_NAME, strerror(errno));
+    return -1;
+  }
+
+  memset(&ifreq, 0, sizeof(ifreq));
+
+  /* Specify either the IFF_TAP flag for Ethernet frames, or the IFF_TUN flag for IP.
+   * Specify IFF_NO_PI for not receiving extra meta packet information. */
+  if (strncmp(EtherTunTapIfName, "tun", 3) == 0)
+  {
+    ifreq.ifr_flags = IFF_TUN;
+    TunOrTap = TT_TUN;
+  }
+  else
+  {
+    ifreq.ifr_flags = IFF_TAP;
+    TunOrTap = TT_TAP;
+  }
+  ifreq.ifr_flags |= IFF_NO_PI;
+
+  strcpy(ifreq.ifr_name, EtherTunTapIfName);
+  if (ioctl(etfd, TUNSETIFF, (void *)&ifreq) < 0)
+  {
+    olsr_printf(1, "%s: ioctl() error: %s\n", PLUGIN_NAME, strerror(errno));
+    close(etfd);
+    return -1;
+  }
+
+  memset(&ifreq, 0, sizeof(ifreq));
+  strcpy(ifreq.ifr_name, EtherTunTapIfName);
+  ifreq.ifr_addr.sa_family = AF_INET;
+  skfd = socket(PF_INET, SOCK_DGRAM, 0);
+  if (skfd >= 0)
+  {
+    if (ioctl(skfd, SIOCGIFADDR, &ifreq) < 0)
+    {
+      /* EtherTunTap interface does not yet have an IP address.
+       * Give it a dummy IP address "1.2.3.4". */
+      struct sockaddr_in *inaddr = (struct sockaddr_in *)&ifreq.ifr_addr;
+      inet_aton("1.2.3.4", &inaddr->sin_addr);
+      ioctlres = ioctl(skfd, SIOCSIFADDR, &ifreq);
+
+      if (ioctlres >= 0)
+      {
+        /* Bring EtherTunTap interface up (if not already) */
+        ioctlres = ioctl(skfd, SIOCGIFFLAGS, &ifreq);
+        if (ioctlres >= 0)
+        {
+          ifreq.ifr_flags |= (IFF_UP | IFF_RUNNING);
+          ioctlres = ioctl(skfd, SIOCSIFFLAGS, &ifreq);
+        }
+      } /* if (ioctlres >= 0) */
+    } /* if (ioctl...) */
+  } /* if (skfd >= 0) */
+  if (skfd < 0 || ioctlres < 0)
+  {
+    olsr_printf(
+      1,
+      "%s: Error bringing up EtherTunTap interface: %s\n",
+      PLUGIN_NAME,
+      strerror(errno));
+
+    close(etfd);
+    if (skfd >= 0)
+    {
+      close(skfd);
+    }
+    return -1;
+  } /* if (skfd < 0 || ioctlres < 0) */
+
+  /* Set the multicast flag on the interface. TODO: Maybe also set
+   * IFF_ALLMULTI. */
+  memset(&ifreq, 0, sizeof(ifreq));
+  strcpy(ifreq.ifr_name, EtherTunTapIfName);
+  ioctlres = ioctl(skfd, SIOCGIFFLAGS, &ifreq);
+  if (ioctlres >= 0)
+  {
+    ifreq.ifr_flags |= IFF_MULTICAST;
+    ioctlres = ioctl(skfd, SIOCSIFFLAGS, &ifreq);
+  }
+  if (ioctlres < 0)
+  {
+    olsr_printf(
+      1,
+      "%s: Error setting the multicast flag on EtherTunTap interface: %s\n",
+      PLUGIN_NAME,
+      strerror(errno));
+  }
+  close(skfd);
+  
+  /* Deactivate IP spoof filter for EtherTunTap device */
+  DeactivateSpoofFilter(ifreq.ifr_name);
+
+  return etfd;
+}
+
+static int IsNullMacAddress(char* mac)
+{
+  int i;
+
+  assert(mac != NULL);
+
+  for (i = 0; i < IFHWADDRLEN; i++)
+  {
+    if (mac[i] != 0) return 0;
+  }
+  return 1;
+}
+
+int CreateBmfNetworkInterfaces(void)
+{
+  int skfd;
+  struct ifconf ifc;
+  int numreqs = 30;
+  struct ifreq* ifr;
+  int n;
+
+  EtherTunTapFd = CreateLocalEtherTunTap();
+  if (EtherTunTapFd < 0)
+  {
+    olsr_printf(1, "%s: error creating local EtherTunTap\n", PLUGIN_NAME);
+    return -1;    
+  }
+
+  skfd = socket(PF_INET, SOCK_DGRAM, 0);
+  if (skfd < 0)
+  {
+    olsr_printf(
+      1,
+      "%s: No inet socket available: %s\n",
+      PLUGIN_NAME,
+      strerror(errno));
+    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)
+    {
+      olsr_printf(1, "%s: SIOCGIFCONF error: %s\n", PLUGIN_NAME, strerror(errno));
+
+      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 (;;) */
+
+  /* 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;
+    struct ifreq ifrAddr;
+    int capturingSkfd;
+    int encapsulatingSkfd = -1;
+    struct TBmfInterface* newBmfInterface;
+
+    /* ...find the OLSR interface structure, if any */
+    union olsr_ip_addr ipAddr;
+    COPY_IP(&ipAddr, &((struct sockaddr_in*)&ifr->ifr_addr)->sin_addr.s_addr);
+    olsrIntf = if_ifwithaddr(&ipAddr);
+
+    if (olsrIntf == NULL && ! IsNonOlsrBmfIf(ifr->ifr_name))
+    {
+      /* Interface is neither OLSR interface, nor specified as non-OLSR BMF
+       * interface in the BMF plugin parameter list */
+      continue; /* for (n = ...) */
+    }
+
+    /* Retrieve the MAC address */
+    memset(&ifrAddr, 0, sizeof(struct ifreq));
+    strcpy(ifrAddr.ifr_name, ifr->ifr_name); 
+    if (ioctl(skfd, SIOCGIFHWADDR, &ifrAddr) < 0)
+    {
+      olsr_printf(
+        1,
+        "%s: SIOCGIFHWADDR error for device \"%s\": %s\n",
+        PLUGIN_NAME,
+        ifrAddr.ifr_name,
+        strerror(errno));
+      continue; /* for (n = ...) */
+    }
+
+    if (IsNullMacAddress(ifrAddr.ifr_hwaddr.sa_data))
+    {
+      continue; /* for (n = ...) */
+    }
+
+    /* Create socket for capturing and sending multicast packets */
+    capturingSkfd = CreateCaptureSocket(if_nametoindex(ifr->ifr_name));
+    if (capturingSkfd < 0)
+    {
+      continue; /* for (n = ...) */
+    }
+
+    if (olsrIntf != NULL)
+    {
+      /* Create socket for encapsulating and forwarding multicast packets */
+      encapsulatingSkfd = CreateEncapsulateSocket(olsrIntf->if_index);
+      if (encapsulatingSkfd < 0)
+      {
+        close(capturingSkfd);
+        continue; /* for (n = ...) */
+      }
+    }
+
+    newBmfInterface = malloc(sizeof(struct TBmfInterface));
+    if (newBmfInterface == NULL)
+    {
+      close(capturingSkfd);
+      close(encapsulatingSkfd);
+      continue; /* for (n = ...) */
+    }
+
+    newBmfInterface->capturingSkfd = capturingSkfd;
+    newBmfInterface->encapsulatingSkfd = encapsulatingSkfd;
+    memcpy(newBmfInterface->macAddr, ifrAddr.ifr_hwaddr.sa_data, IFHWADDRLEN);
+    memcpy(newBmfInterface->ifName, ifr->ifr_name, IFNAMSIZ);
+    newBmfInterface->olsrIntf = olsrIntf;
+    newBmfInterface->next = BmfInterfaces;
+    BmfInterfaces = newBmfInterface;
+  } /* for (n = ...) */
+  
+  if (BmfInterfaces == NULL)
+  {
+    olsr_printf(1, "%s: could not initialize any network interface\n", PLUGIN_NAME);
+    return -1;
+  }
+
+  close(skfd);
+  free(ifc.ifc_buf);
+  return 0;
+}
+
+/* Closes every socket on each network interface used by BMF:
+ * -- the local EtherTunTap interface (e.g. "tun0" or "tap0")
+ * -- for each OLSR-enabled interface:
+ *    - the socket used for capturing multicast packets
+ *    - the socket used for encapsulating packets
+ * Also restores the network state to the situation before OLSR was
+ * started */
+void CloseBmfNetworkInterfaces()
+{
+  int nClosed = 0;
+  
+  /* Close all opened sockets */
+  struct TBmfInterface* nextBmfIf = BmfInterfaces;
+  while (nextBmfIf != NULL)
+  {
+    struct TBmfInterface* bmfIf = nextBmfIf;
+    nextBmfIf = bmfIf->next;
+
+    close(bmfIf->capturingSkfd);
+    nClosed++;
+    if (bmfIf->encapsulatingSkfd >= 0) 
+    {
+      close(bmfIf->encapsulatingSkfd);
+      nClosed++;
+    }
+
+    free(bmfIf);
+  }
+  
+  /* Restore IP spoof filter for EtherTunTap device */
+  RestoreSpoofFilter(EtherTunTapIfName);
+
+  close(EtherTunTapFd);
+  nClosed++;
+
+  olsr_printf(1, "%s: closed %d sockets\n", PLUGIN_NAME, nClosed);
+}
+
+#define MAX_NON_OLSR_IFS 10
+static char NonOlsrIfNames[MAX_NON_OLSR_IFS][IFNAMSIZ];
+static int nNonOlsrIfs = 0;
+
+int AddNonOlsrBmfIf(const char* ifName)
+{
+  assert(ifName != NULL);
+
+  if (nNonOlsrIfs >= MAX_NON_OLSR_IFS)
+  {
+    olsr_printf(
+      1,
+      "%s: too many non-OLSR interfaces specified, maximum %d\n",
+      PLUGIN_NAME,
+      MAX_NON_OLSR_IFS);
+    return 0;
+  }
+
+  strncpy(NonOlsrIfNames[nNonOlsrIfs], ifName, IFNAMSIZ);
+  nNonOlsrIfs++;
+  return 1;
+}
+
+int IsNonOlsrBmfIf(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;
+}
diff --git a/lib/bmf/src/NetworkInterfaces.h b/lib/bmf/src/NetworkInterfaces.h
new file mode 100644 (file)
index 0000000..0a3c754
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef _BMF_NETWORKINTERFACES_H
+#define _BMF_NETWORKINTERFACES_H
+
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005, 2006, 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.
+ */
+
+/* $Id: NetworkInterfaces.h,v 1.1 2006/05/03 08:59:04 kattemat Exp $ */
+
+/* Plugin includes */
+#include "Packet.h" /* IFHWADDRLEN */
+
+struct TBmfInterface
+{
+  /* File descriptor of raw packet socket, used for capturing multicast packets */
+  int capturingSkfd;
+
+  /* File descriptor of UDP (datagram) socket for encapsulated multicast packets. 
+   * Set to -1 if interface is not OLSR-enabled. */
+  int encapsulatingSkfd;
+
+  unsigned char macAddr[IFHWADDRLEN];
+
+  char ifName[IFNAMSIZ];
+
+  /* OLSRs idea of this network interface. NULL if this interface is not
+   * OLSR-enabled. */
+  struct interface* olsrIntf;
+
+  /* Kernels index of this network interface */
+  int ifIndex;
+  
+  /* Next element in list */
+  struct TBmfInterface* next; 
+};
+
+extern struct TBmfInterface* BmfInterfaces;
+
+extern int EtherTunTapFd;
+
+extern const char* EtherTunTapIfName;
+
+enum TTunOrTap { TT_TUN = 0, TT_TAP };
+extern enum TTunOrTap TunOrTap;
+
+int CreateBmfNetworkInterfaces(void);
+void CloseBmfNetworkInterfaces(void);
+int AddNonOlsrBmfIf(const char* ifName);
+int IsNonOlsrBmfIf(const char* ifName);
+
+#endif /* _BMF_NETWORKINTERFACES_H */
diff --git a/lib/bmf/src/Packet.c b/lib/bmf/src/Packet.c
new file mode 100644 (file)
index 0000000..901149c
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005, 2006, 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.
+ */
+
+/* $Id: Packet.c,v 1.1 2006/05/03 08:59:04 kattemat Exp $ */
+
+#include "Packet.h"
+
+/* System includes */
+#include <assert.h> /* assert() */
+#include <sys/types.h> /* u_int32_t */
+#include <netinet/in.h> /* ntohs(), htons() */
+#include <linux/ip.h>
+
+/* Retrieve the TTL (Time To Live) value from the IP header of the
+ * passed ethernet packet */
+int GetIpTtl(unsigned char* buffer)
+{
+  struct iphdr* iph;
+
+  assert(buffer != NULL);
+
+  iph = (struct iphdr*) (buffer + IP_HDR_OFFSET);
+  return iph->ttl;
+}
+
+void SaveTtlAndChecksum(unsigned char* buffer, struct TSaveTtl* sttl)
+{
+  struct iphdr* iph;
+
+  assert(buffer != NULL && sttl != NULL);
+
+  iph = (struct iphdr*) (buffer + IP_HDR_OFFSET);
+  sttl->ttl = iph->ttl;
+  sttl->check = ntohs(iph->check);
+}
+
+void RestoreTtlAndChecksum(unsigned char* buffer, struct TSaveTtl* sttl)
+{
+  struct iphdr* iph;
+
+  assert(buffer != NULL && sttl != NULL);
+
+  iph = (struct iphdr*) (buffer + IP_HDR_OFFSET);
+  iph->ttl = sttl->ttl;
+  iph->check = htons(sttl->check);
+}
+
+/* For an IP packet, decrement the TTL value and update the IP header
+ * checksum accordingly. See also RFC1141. */
+void PacketDecreaseTtlAndUpdateHeaderChecksum(unsigned char* buffer)
+{
+  struct iphdr* iph;
+  u_int32_t sum;
+
+  assert(buffer != NULL);
+
+  iph = (struct iphdr*) (buffer + IP_HDR_OFFSET);
+
+  iph->ttl--; /* decrement ttl */
+  sum = ntohs(iph->check) + 0x100; /* increment checksum high byte */
+  iph->check = htons(sum + (sum>>16)); /* add carry */
+}
diff --git a/lib/bmf/src/Packet.h b/lib/bmf/src/Packet.h
new file mode 100644 (file)
index 0000000..2897766
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef _BMF_PACKET_H
+#define _BMF_PACKET_H
+
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005, 2006, 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.
+ */
+
+/* $Id: Packet.h,v 1.1 2006/05/03 08:59:04 kattemat Exp $ */
+
+/* System includes */
+#include <net/if.h> /* IFNAMSIZ, IFHWADDRLEN */
+#include <sys/types.h> /* u_int8_t, u_int16_t */
+
+/* Offsets and sizes into IP-ethernet packets */
+#define IPV4_ADDR_SIZE 4
+#define ETH_TYPE_OFFSET (2*IFHWADDRLEN)
+#define ETH_TYPE_LEN 2
+#define IP_HDR_OFFSET (ETH_TYPE_OFFSET + ETH_TYPE_LEN)
+#define IPV4_OFFSET_SRCIP 12
+#define IPV4_OFFSET_DSTIP (IPV4_OFFSET_SRCIP + IPV4_ADDR_SIZE)
+
+#define IPV4_TYPE 0x0800
+
+struct TSaveTtl
+{
+  u_int8_t ttl;
+  u_int16_t check;
+};
+
+int GetIpTtl(unsigned char* buffer);
+void SaveTtlAndChecksum(unsigned char* buffer, struct TSaveTtl* sttl);
+void RestoreTtlAndChecksum(unsigned char* buffer, struct TSaveTtl* sttl);
+void PacketDecreaseTtlAndUpdateHeaderChecksum(unsigned char* buffer);
+
+#endif /* _BMF_PACKET_H */
diff --git a/lib/bmf/src/PacketHistory.c b/lib/bmf/src/PacketHistory.c
new file mode 100644 (file)
index 0000000..1bd5bb2
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005, 2006, 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.
+ */
+
+/* $Id: PacketHistory.c,v 1.1 2006/05/03 08:59:04 kattemat Exp $ */
+
+#include "PacketHistory.h"
+
+/* System includes */
+#include <assert.h> /* assert() */
+#include <sys/types.h> /* u_int16_t, u_int32_t */
+#include <string.h> /* memset */
+
+/* OLSRD includes */
+#include "olsr.h" /* olsr_printf */
+
+/* Plugin includes */
+#include "Packet.h"
+
+static u_int32_t PacketHistory[HISTORY_TABLE_SIZE];
+
+/* Calculate 16-bits CRC according to CRC-CCITT specification, modified
+ * to leave out some parts of the packet. */
+static u_int16_t CalcCrcCcitt(unsigned char* buffer, ssize_t len)
+{
+  /* Initial value of 0xFFFF should be 0x1D0F according to
+   * www.joegeluso.com/software/articles/ccitt.htm */
+  u_int16_t crc = 0xFFFF; 
+  int i;
+
+  assert(buffer != NULL);
+
+  for (i = 0; i < len; i++)
+  {
+    /* Skip IP header checksum; we want to avoid as much as possible
+     * calculating a checksum over data containing a checksum */
+    if (i >= 12 && i < 14) continue;
+
+    crc  = (unsigned char)(crc >> 8) | (crc << 8);
+    crc ^= buffer[i];
+    crc ^= (unsigned char)(crc & 0xff) >> 4;
+    crc ^= (crc << 8) << 4;
+    crc ^= ((crc & 0xff) << 4) << 1;
+  }
+  return crc;
+
+#if 0
+  /* Alternative, simpler and perhaps just as good: add source IP address,
+   * destination IP address and IP identification, in 16-bit */
+  return
+    ((buffer[0x0E] << 8) + buffer[0x0F]) + ((buffer[0x10] << 8) + buffer[0x11]) +
+    ((buffer[0x12] << 8) + buffer[0x13]) + ((buffer[0x14] << 8) + buffer[0x15]) +
+    ((buffer[0x06] << 8) + buffer[0x07]);
+#endif
+}
+
+void InitPacketHistory()
+{
+  memset(PacketHistory, 0, sizeof(PacketHistory));
+}
+
+/* Record the fact that this packet was seen recently */
+void MarkRecentPacket(unsigned char* buffer, ssize_t len)
+{
+  u_int16_t crc;
+  u_int32_t index;
+  uint offset;
+
+  assert(buffer != NULL);
+
+  /* Start CRC calculation at ethertype; skip source and destination MAC 
+   * addresses */
+  crc = CalcCrcCcitt(buffer + ETH_TYPE_OFFSET, len - ETH_TYPE_OFFSET);
+
+  index = crc / NPACKETS_PER_ENTRY;
+  assert(index < HISTORY_TABLE_SIZE);
+
+  offset = (crc % NPACKETS_PER_ENTRY) * NBITS_PER_PACKET;
+  assert(offset <= NBITS_IN_UINT32 - NBITS_PER_PACKET);
+
+  /* Mark "seen recently" */
+  PacketHistory[index] = PacketHistory[index] | (0x3u << offset);
+}
+
+/* Check if this packet was seen recently */
+int CheckMarkRecentPacket(unsigned char* buffer, ssize_t len)
+{
+  u_int16_t crc;
+  u_int32_t index;
+  uint offset;
+  u_int32_t bitMask;
+  int result;
+
+  assert(buffer != NULL);
+
+  /* Start CRC calculation at ethertype; skip source and destination MAC 
+   * addresses */
+  crc = CalcCrcCcitt(buffer + ETH_TYPE_OFFSET, len - ETH_TYPE_OFFSET);
+
+  index = crc / NPACKETS_PER_ENTRY;
+  assert(index < HISTORY_TABLE_SIZE);
+
+  offset =  (crc % NPACKETS_PER_ENTRY) * NBITS_PER_PACKET;
+  assert(offset <= NBITS_IN_UINT32 - NBITS_PER_PACKET);
+
+  bitMask = 0x1u << offset;
+  result = ((PacketHistory[index] & bitMask) == bitMask);
+  
+  /* Always mark "seen recently" */
+  PacketHistory[index] = PacketHistory[index] | (0x3u << offset);
+
+  return result;
+}
+  
+void PrunePacketHistory(void* useless)
+{
+  uint i;
+  for (i = 0; i < HISTORY_TABLE_SIZE; i++)
+  {
+    if (PacketHistory[i] > 0)
+    {
+      uint j;
+      for (j = 0; j < NPACKETS_PER_ENTRY; j++)
+      {
+        uint offset = j * NBITS_PER_PACKET;
+
+        u_int32_t bitMask = 0x3u << offset;
+        u_int32_t bitsSeenRecenty = 0x3u << offset;
+        u_int32_t bitsTimingOut = 0x1u << offset;
+
+        /* 10 should never occur */
+        assert ((PacketHistory[i] & bitMask) != (0x2u << offset));
+        
+        if ((PacketHistory[i] & bitMask) == bitsSeenRecenty)
+        {
+          /* 11 -> 01 */
+          PacketHistory[i] &= ~bitMask | bitsTimingOut;
+        }
+        else if ((PacketHistory[i] & bitMask) == bitsTimingOut)
+        {
+          /* 01 -> 00 */
+          PacketHistory[i] &= ~bitMask;
+        }
+      } /* for (j = ...) */
+    } /* if (PacketHistory[i] > 0) */
+  } /* for (i = ...) */
+}
diff --git a/lib/bmf/src/PacketHistory.h b/lib/bmf/src/PacketHistory.h
new file mode 100644 (file)
index 0000000..d4c39fb
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef _BMF_PACKETHISTORY_H
+#define _BMF_PACKETHISTORY_H
+
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005, 2006, 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.
+ */
+
+/* $Id: PacketHistory.h,v 1.1 2006/05/03 08:59:04 kattemat Exp $ */
+
+#include <sys/types.h> /* ssize_t */
+
+/* 2 bits per seen packet fingerping: 
+ * 11 = "seen recently",
+ * 01 = "timing out"
+ * 00 = "not seen recently"
+ * Note that 10 is unused */
+#define NBITS_PER_PACKET 2
+#define NBITS_IN_UINT16 (sizeof(u_int16_t) * 8)
+#define NBITS_IN_UINT32 (sizeof(u_int32_t) * 8)
+#define NPACKETS_PER_ENTRY (NBITS_IN_UINT32 / NBITS_PER_PACKET)
+#define HISTORY_TABLE_SIZE ((1 << NBITS_IN_UINT16) / NPACKETS_PER_ENTRY)
+
+void InitPacketHistory(void);
+void MarkRecentPacket(unsigned char* buffer, ssize_t len);
+int CheckMarkRecentPacket(unsigned char* buffer, ssize_t len);
+void PrunePacketHistory(void*);
+
+#endif /* _BMF_PACKETHISTORY_H */
diff --git a/lib/bmf/src/olsrd_plugin.c b/lib/bmf/src/olsrd_plugin.c
new file mode 100644 (file)
index 0000000..ae6afe6
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * OLSR Basic Multicast Forwarding (BMF) plugin.
+ * Copyright (c) 2005, 2006, 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.
+ */
+
+/* $Id: olsrd_plugin.c,v 1.1 2006/05/03 08:59:04 kattemat Exp $ */
+
+/*
+ * Dynamic linked library for olsr.org olsrd
+ */
+
+/* System includes */
+#include <assert.h> /* assert() */
+#include <stdio.h>
+
+/* OLSRD includes */
+#include "olsrd_plugin.h"
+
+/* BMF includes */
+#include "Bmf.h" /* InitBmf(), CloseBmf(), RegisterBmfParameter() */
+
+static void __attribute__ ((constructor)) my_init(void);
+static void __attribute__ ((destructor)) my_fini(void);
+
+void olsr_plugin_exit(void);
+
+/* Plugin interface version
+ * Used by main olsrd to check plugin interface version */
+int olsrd_plugin_interface_version()
+{
+  return OLSRD_PLUGIN_INTERFACE_VERSION;
+}
+
+int olsrd_plugin_init()
+{
+  return InitBmf();
+}
+
+/* destructor - called at unload */
+void olsr_plugin_exit()
+{
+  CloseBmf();
+}
+
+/* Register parameters from config file
+ * Called for all plugin parameters */
+int olsrd_plugin_register_param(char* key, char* value)
+{
+  assert(key != NULL && value != NULL);
+
+  return RegisterBmfParameter(key, value);
+}
+static void my_init()
+{
+  /* Print plugin info to stdout */
+  printf("%s\n", MOD_DESC);
+
+  return;
+}
+
+static void my_fini()
+{
+  olsr_plugin_exit();
+}
diff --git a/lib/bmf/version-script.txt b/lib/bmf/version-script.txt
new file mode 100644 (file)
index 0000000..3d09da3
--- /dev/null
@@ -0,0 +1,10 @@
+VERS_1.0
+{
+  global:
+    olsrd_plugin_interface_version;
+    olsrd_plugin_register_param;
+    olsrd_plugin_init;
+
+  local:
+    *;
+};