diff -Nur olsrd-0.4.10.orig/lib/bmf/Makefile olsrd-0.4.10/lib/bmf/Makefile --- olsrd-0.4.10.orig/lib/bmf/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ olsrd-0.4.10/lib/bmf/Makefile 2006-12-01 08:26:58.000000000 +0100 @@ -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.10 2005/05/25 13:50:22 br1 Exp $ + +OLSRD_PLUGIN = true +PLUGIN_NAME = olsrd_bmf +PLUGIN_VER = 1.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 \ Kein Zeilenumbruch am Dateiende. diff -Nur olsrd-0.4.10.orig/lib/bmf/PluginBmf.prj olsrd-0.4.10/lib/bmf/PluginBmf.prj --- olsrd-0.4.10.orig/lib/bmf/PluginBmf.prj 1970-01-01 01:00:00.000000000 +0100 +++ olsrd-0.4.10/lib/bmf/PluginBmf.prj 2006-12-01 08:26:58.000000000 +0100 @@ -0,0 +1,83 @@ +#DO NOT EDIT THIS FILE!!! +[APPTYPE@DEBUG] +APPTYPE = 0 +[APPTYPE@RELEASE] +APPTYPE = 0 +[COMPILE@DEBUG] +COMPILEOPTION = -c -g +[COMPILE@RELEASE] +COMPILEOPTION = -c +[CVS] +INITDIR = $CVSROOT +REMOTELOGIN = 0 +[DEBUG@DEBUG] +EXEPOS = PluginSmf2 +WORKDIR = +[DEBUG@RELEASE] +EXEPOS = PluginSmf2 +WORKDIR = +[DEPENDENCY] +FILENAME = README_BMF.txt +FILENAME = ../../olsrd.conf +FILENAME = README_BMF +FILENAME = version-script.txt +FILENAME = README_SMF +FILENAME = Makefile +[GDBSERVER] +ISGDBSERVER = 0 +[HEADER] +FILENAME = src/Bmf.h +FILENAME = src/PacketHistory.h +FILENAME = src/Packet.h +FILENAME = src/Address.h +FILENAME = src/NetworkInterfaces.h +FILENAME = src/DropList.h +[LANTYPE@DEBUG] +LANTYPE = 0 +[LANTYPE@RELEASE] +LANTYPE = 0 +[LINK@DEBUG] +LINKOPTION = -g -o PluginSmf2 +OUTPUT = PluginSmf2 +[LINK@RELEASE] +LINKOPTION = -o PluginSmf2 +OUTPUT = PluginSmf2 +[MAIN] +CONFIG = RELEASE,DEBUG +DEFAULTCONFIG = DEBUG +DEVTYPE = 0 +ONLINE = 1 +VERSION = 3.0 +WATCH = +[MAKE@DEBUG] +CUSTOMMAKE = Makefile +CUSTOMMAKEBUILDPARAM = +CUSTOMMAKECLEANPARAM = clean +CUSTOMMAKEDIR = +CUSTOMSHELL = +MAKEFILE = Makefile_DEBUG.mk +MANUALDEFAULT = 1 +REGENMAKEFILE = 1 +[MAKE@RELEASE] +CUSTOMMAKE = Makefile +CUSTOMMAKEBUILDPARAM = +CUSTOMMAKECLEANPARAM = clean +CUSTOMMAKEDIR = +CUSTOMSHELL = +MAKEFILE = Makefile_DEBUG.mk +MANUALDEFAULT = 1 +REGENMAKEFILE = 1 +[PRECOMPILE@DEBUG] +ESQL_OPTION = -g +PROC_OPTION = DEFINE=_PROC_ MODE=ORACLE LINES=true +[PRECOMPILE@RELEASE] +ESQL_OPTION = +PROC_OPTION = DEFINE=_PROC_ MODE=ORACLE +[SOURCE] +FILENAME = src/Bmf.c +FILENAME = src/Packet.c +FILENAME = src/PacketHistory.c +FILENAME = src/DropList.c +FILENAME = src/olsrd_plugin.c +FILENAME = src/Address.c +FILENAME = src/NetworkInterfaces.c diff -Nur olsrd-0.4.10.orig/lib/bmf/README_BMF.txt olsrd-0.4.10/lib/bmf/README_BMF.txt --- olsrd-0.4.10.orig/lib/bmf/README_BMF.txt 1970-01-01 01:00:00.000000000 +0100 +++ olsrd-0.4.10/lib/bmf/README_BMF.txt 2006-12-01 08:26:58.000000000 +0100 @@ -0,0 +1,233 @@ +BASIC MULTICAST FORWARDING PLUGIN FOR OLSRD +by Erik Tromp (erik.tromp@nl.thalesgroup.com) + +12 Jul 2006: Version 1.1 +* Major updates in code forwarding from and to non-OLSR enabled + network interfaces. +* Debug level 9 gives a better indication of what happens to each + handled multicast/broadcast packet. +* Can now deal with network interface removal ("ifdown eth1") and + addition ("ifup eth1"). +* CRC-calculation for duplicate detection is done over first 256 + bytes in packet instead of over full packet length. +* CRC calculated only on captured packets, and is subsequently + passed on in a special OLSR-BMF encapsulation header. +* Deals correctly with fragmented packets + +27 Apr 2006: Version 1.0.1 +* First release. + +1. Introduction +--------------- + +The Basic Multicast Forwarding Plugin floods IP-multicast and +IP-local-broadcast 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, changing 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 myself, 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 interface 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.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.1 + OLSRD Basic Multicast Forwarding plugin 1.1 (Jul 12 2006 04:12:42) + (C) Thales Communications Huizen, Netherlands + Erik Tromp (erik.tromp@nl.thalesgroup.com) + Checking plugin interface version... 4 - OK + Trying to fetch plugin init function... OK + Trying to fetch param function... OK + Sending parameters... + "NonOlsrIf"/"eth0"... OK + Running plugin_init function... + OLSRD Basic Multicast Forwarding plugin: opened 6 sockets + ---------- LIBRARY LOADED ---------- + + +4. How to check if it works +--------------------------- + +To check that BMF is working, enter the following 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.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. + +Note that when BMF receives or sends a packet via a non-OLSR interface, +the TTL is decremented. TTL is NOT decremented on packets traveling +within the OLSR-BMF MANET, since that is considered to be one (repaired) +broadcast domain. + +Packets are not forwarded from one non-OLSR interface to another non-OLSR +interface, only from non-OLSR interfaces to OLSR interfaces and vice versa. +Packet forwarding between non-OLSR interfaces should be the result of +other multicast routing protocols. + + +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.1" + { + # Drop all packets received from the following MAC sources + PlParam "DropMac" "00:0C:29:C6:E2:61" # RemoteClient1 + PlParam "DropMac" "00:0C:29:61:34:B7" # SimpleClient1 + PlParam "DropMac" "00:0C:29:28:0E:CC" # SimpleClient2 + } + + + +7. Common problems, FAQ +----------------------- + +Question: +On which platforms does BMF currently compile? + +Answer: +Only on Linux. No compilation on Windows (yet). The oldest Linux +kernel on which the BMF plugin was tested was version 2.4.18. + + +Question: +When starting OLSRD with the BMF plugin, I can see the following +error message: + +OLSRD Basic Multicast Forwarding plugin: error opening /dev/net/tun: No such file or directory + +Wat to do? + +Answer: +Turn on the possibility to create a tuntap device; see section 2 of this +file. + diff -Nur olsrd-0.4.10.orig/lib/bmf/src/Address.c olsrd-0.4.10/lib/bmf/src/Address.c --- olsrd-0.4.10.orig/lib/bmf/src/Address.c 1970-01-01 01:00:00.000000000 +0100 +++ olsrd-0.4.10/lib/bmf/src/Address.c 2006-12-01 08:26:58.000000000 +0100 @@ -0,0 +1,194 @@ +/* + * 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. + */ + +/* ------------------------------------------------------------------------- + * File : Address.c + * Description: IP packet characterization functions + * Created : 29 Jun 2006 + * + * $Id$ + * + * $Log$ + * ------------------------------------------------------------------------- */ + +#include "Address.h" + +/* System includes */ +#include /* assert() */ +#include /* struct ip */ +#include /* struct udphdr */ + +/* OLSRD includes */ +#include "defs.h" /* COMP_IP */ + +/* Plugin includes */ +#include "Bmf.h" /* BMF_ENCAP_PORT */ +#include "NetworkInterfaces.h" /* TBmfInterface */ + +/* ------------------------------------------------------------------------- + * Function : IsMulticast + * Description: Check if an IP address is a multicast address + * Input : ipAddress + * Output : none + * Return : true (1) or false (0) + * Data Used : none + * ------------------------------------------------------------------------- */ +int IsMulticast(union olsr_ip_addr* ipAddress) +{ + assert(ipAddress != NULL); + + return (ntohl(ipAddress->v4) & 0xF0000000) == 0xE0000000; +} + +/* ------------------------------------------------------------------------- + * Function : IsLocalBroadcast + * Description: Check if an IP address is a local broadcast address for a + * given network interface + * Input : destIp, ifFrom + * Output : none + * Return : true (1) or false (0) + * Data Used : none + * ------------------------------------------------------------------------- */ +int IsLocalBroadcast(union olsr_ip_addr* destIp, struct TBmfInterface* ifFrom) +{ + struct sockaddr_in* sin; + + assert(destIp != NULL && ifFrom != NULL); + + /* Cast down to correct sockaddr subtype */ + sin = (struct sockaddr_in*)&(ifFrom->broadAddr); + + return COMP_IP(&(sin->sin_addr.s_addr), destIp); +} + +/* ------------------------------------------------------------------------- + * Function : IsOlsrOrBmfPacket + * Description: Check if an ethernet packet is an OLSR packet or a BMF packet + * Input : intf, ethPkt, len + * Output : none + * Return : true (1) or false (0) + * Data Used : none + * ------------------------------------------------------------------------- */ +int IsOlsrOrBmfPacket(struct TBmfInterface* intf, unsigned char* ethPkt, size_t len) +{ + struct ip* ipData; + unsigned int ipHeaderLen; + + assert(ethPkt != NULL); + + /* Consider OLSR and BMF packets not to be local broadcast + * OLSR packets are UDP - port 698 + * OLSR-BMF packets are UDP - port 50698 + * OLSR-Autodetect probe packets are UDP - port 51698 + * Fragments of the above packets are also not local broadcast */ + + ipData = (struct ip*) (ethPkt + IP_HDR_OFFSET); + ipHeaderLen = ipData->ip_hl << 2; + if (len < IP_HDR_OFFSET + ipHeaderLen) + { + return 0; + } + + if (ipData->ip_p != SOL_UDP) + { + return 0; + } + + /* Check if the packet is a fragment */ + if ((ntohs(ipData->ip_off) & IP_OFFMASK) != 0) + { + int i; + for (i = 0; i < FRAGMENT_HISTORY_SIZE; i++) + { + /* Quick-access pointer */ + struct TFragmentHistory* entry = &intf->fragmentHistory[i]; + + /* Match */ + if (entry->ipId == ntohs(ipData->ip_id) && + entry->ipProto == ipData->ip_p && + entry->ipSrc.s_addr == ntohl(ipData->ip_src.s_addr) && + entry->ipDst.s_addr == ntohl(ipData->ip_dst.s_addr)) + { + /* Found matching history entry, so packet is assumed to be a fragment + * of an earlier OLSR/OLSR-BMF/OLSR-Autodetect packet */ + + /* More fragments? If not, invalidate entry */ + if (((ntohs(ipData->ip_off) & IP_MF) == 0)) + { + memset(entry, 0, sizeof(struct TFragmentHistory)); + } + + return 1; + } + } + + /* Matching history entry not found, so packet is not assumed to be a fragment + * of an earlier OLSR/OLSR-BMF/OLSR-Autodetect packet */ + return 0; + } + + /* The packet is the first (or only) fragment */ + + /* Check length first */ + if (len < IP_HDR_OFFSET + ipHeaderLen + sizeof(struct udphdr )) + { + return 0; + } + + /* Go into the UDP header and check port number */ + struct udphdr* udpData = (struct udphdr*) (ethPkt + IP_HDR_OFFSET + ipHeaderLen); + u_int16_t port = ntohs(udpData->source); + + if (port == OLSRPORT || port == BMF_ENCAP_PORT || port == 51698) + /* TODO define for 51698 */ + { + /* If more fragments are expected, keep a record in the fragment history */ + if ((ntohs(ipData->ip_off) & IP_MF) != 0) + { + /* Quick-access pointer */ + struct TFragmentHistory* entry = &intf->fragmentHistory[intf->nextFragmentHistoryEntry]; + + /* Store in fragment history */ + entry->ipId = ntohs(ipData->ip_id); + entry->ipProto = ipData->ip_p; + entry->ipSrc.s_addr = ntohl(ipData->ip_src.s_addr); + entry->ipDst.s_addr = ntohl(ipData->ip_dst.s_addr); + + /* Advance to next entry */ + intf->nextFragmentHistoryEntry++; + intf->nextFragmentHistoryEntry %= FRAGMENT_HISTORY_SIZE; + } + return 1; + } + + return 0; +} diff -Nur olsrd-0.4.10.orig/lib/bmf/src/Address.h olsrd-0.4.10/lib/bmf/src/Address.h --- olsrd-0.4.10.orig/lib/bmf/src/Address.h 1970-01-01 01:00:00.000000000 +0100 +++ olsrd-0.4.10/lib/bmf/src/Address.h 2006-12-01 08:26:58.000000000 +0100 @@ -0,0 +1,55 @@ +#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. + */ + +/* ------------------------------------------------------------------------- + * File : Address.h + * Description: IP packet characterization functions + * Created : 29 Jun 2006 + * + * $Id$ + * + * $Log$ + * ------------------------------------------------------------------------- */ + +#include "olsr_types.h" /* olsr_ip_addr */ +#include "interfaces.h" /* struct interface */ + +struct TBmfInterface; + +int IsMulticast(union olsr_ip_addr* ipAddress); +int IsLocalBroadcast(union olsr_ip_addr* destIp, struct TBmfInterface* ifFrom); +int IsOlsrOrBmfPacket(struct TBmfInterface* intf, unsigned char* ethPkt, size_t len); + +#endif /* _BMF_ADDRESS_H */ diff -Nur olsrd-0.4.10.orig/lib/bmf/src/Bmf.c olsrd-0.4.10/lib/bmf/src/Bmf.c --- olsrd-0.4.10.orig/lib/bmf/src/Bmf.c 1970-01-01 01:00:00.000000000 +0100 +++ olsrd-0.4.10/lib/bmf/src/Bmf.c 2006-12-01 08:26:58.000000000 +0100 @@ -0,0 +1,935 @@ +/* + * 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. + */ + +/* ------------------------------------------------------------------------- + * File : Bmf.c + * Description: Multicast forwarding functions + * Created : 29 Jun 2006 + * + * $Id$ + * + * $Log$ + * ------------------------------------------------------------------------- */ + +#define _MULTI_THREADED + +#include "Bmf.h" + +/* System includes */ +#include /* NULL */ +#include /* ssize_t */ +#include /* strerror() */ +#include /* errno */ +#include /* assert() */ +#include /* struct sockaddr_ll, PACKET_MULTICAST */ +#include /* pthread_t, pthread_create() */ +#include /* sigset_t, sigfillset(), sigdelset(), SIGINT */ +#include /* struct ip */ + +/* 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() */ +#include "link_set.h" /* get_best_link_to_neighbor() */ + +/* 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; + + +/* ------------------------------------------------------------------------- + * Function : BmfPacketCaptured + * Description: Handle a captured raw IP packet + * Input : intf - the network interface on which the packet was captured + * buffer - space for the encapsulation header, followed by + * the captured packet + * len - the number of octets in the encapsulation header plus + * captured packet + * Output : none + * Return : none + * Data Used : BmfInterfaces + * Notes : The packet is assumed to be captured on a socket of family + * PF_PACKET and type SOCK_RAW. + * ------------------------------------------------------------------------- */ +static void BmfPacketCaptured(struct TBmfInterface* intf, unsigned char* buffer, ssize_t len) +{ + unsigned char* srcMac; + union olsr_ip_addr srcIp; + union olsr_ip_addr destIp; + union olsr_ip_addr* origIp; + struct sockaddr_in encapDest; + struct TBmfInterface* nextFwIntf; + int isFromOlsrIntf; /* Boolean indicating if packet captured on OLSR-enabled interface */ + int iAmNotMpr; + unsigned char* ethPkt = buffer + ENCAP_HDR_LEN; + ssize_t ethPktLen = len - ENCAP_HDR_LEN; + struct ip* ipData; + + /* Only forward IPv4 packets */ + u_int16_t type; + memcpy(&type, ethPkt + ETH_TYPE_OFFSET, 2); + if (ntohs(type) != IPV4_TYPE) + { + return; + } + + ipData = (struct ip*)(ethPkt + IP_HDR_OFFSET); + + /* Only forward multicast or local broadcast packets */ + COPY_IP(&destIp, &ipData->ip_dst); + if (! IsMulticast(&destIp) && ! IsLocalBroadcast(&destIp, intf)) + { + return; + } + + /* Discard OLSR packets (UDP port 698) and BMF encapsulated packets */ + if (IsOlsrOrBmfPacket(intf, ethPkt, ethPktLen)) + { + return; + } + + COPY_IP(&srcIp, &ipData->ip_src); + olsr_printf( + 9, + "%s: pkt of %d bytes incoming on \"%s\": %s->%s\n", + PLUGIN_NAME_SHORT, + ethPktLen, + intf->ifName, + olsr_ip_to_string(&srcIp), + olsr_ip_to_string(&destIp)); + + /* Apply drop list for testing purposes. */ + srcMac = ethPkt + IFHWADDRLEN; + if (IsInDropList(srcMac)) + { + olsr_printf( + 9, + "%s: --> discarding: source MAC (%.2x:%.2x:%.2x:%.2x:%.2x:%.2x) found in drop list\n", + PLUGIN_NAME_SHORT, + srcMac, srcMac + 1, srcMac + 2, srcMac + 3, srcMac + 4, srcMac + 5); + return; + } + + /* Lookup main address of source in the MID table of OLSR */ + origIp = mid_lookup_main_addr(&srcIp); + if (origIp == NULL) + { + origIp = &srcIp; + } + + /* Check if this packet is received on an OLSR-enabled interface */ + isFromOlsrIntf = (intf->olsrIntf != NULL); + + /* If this packet is captured on a non-OLSR interface, it will be forwarded + * only to OLSR interfaces, thereby crossing the boundary between the external + * network and the OLSR network. So decrease the TTL and re-calculate the IP header + * checksum. */ + if (! isFromOlsrIntf) + { + DecreaseTtlAndUpdateHeaderChecksum(ethPkt); + } + + /* If the resulting TTL is <= 0, this packet life has ended, so do not forward it */ + if (GetIpTtl(ethPkt) <= 0) + { + olsr_printf( + 9, + "%s: --> discarding: TTL=0\n", + PLUGIN_NAME_SHORT); + return; + } + + /* Check if this packet was seen recently */ + u_int32_t crc32 = PacketCrc32(ethPkt, ethPktLen); + if (CheckAndMarkRecentPacket(Hash16(crc32))) + { + olsr_printf( + 9, + "%s: --> discarding: packet is duplicate\n", + PLUGIN_NAME_SHORT); + return; + } + + /* Compose encapsulation header */ + struct TEncapHeader* encapHdr = (struct TEncapHeader*) buffer; + memset (encapHdr, 0, ENCAP_HDR_LEN); + encapHdr->crc32 = htonl(crc32); + + /* If this packet is captured on an OLSR interface from an OLSR neighbor, + * check with OLSR if I am MPR for that neighbor */ + iAmNotMpr = + (isFromOlsrIntf /* captured on an OLSR interface */ + && get_best_link_to_neighbor(origIp) != NULL /* from an OLSR neighbor */ + && olsr_lookup_mprs_set(origIp) == NULL); /* but not selected as MPR */ + + memset(&encapDest, 0, sizeof(encapDest)); + encapDest.sin_family = AF_INET; + encapDest.sin_port = htons(BMF_ENCAP_PORT); + + /* Check with each interface what needs to be done on it */ + nextFwIntf = BmfInterfaces; + while (nextFwIntf != NULL) + { + int isToOlsrIntf; /* Boolean indicating if forwarding interface is OLSR-enabled */ + + struct TBmfInterface* fwIntf = nextFwIntf; + nextFwIntf = fwIntf->next; + + isToOlsrIntf = (fwIntf->olsrIntf != NULL); + + /* The following if-else statement seems very complicated. Let's + * draw a Karnaugh-diagram of it for some clarification. + * + * ------- isFromOlsrIntf + * -------- isToOlsrIntf + * +---+---+---+---+ + * | 3 | 2 | 2 | 1 | + * +---+---+---+---+ + * | | X | X | 4 | 1 | + * +---+---+---+---+ + * iAmNotMpr + * + * X = does not occur (iAmNotMpr = isFromOlsrIntf && ...) + * 1 = handled in first if-clause: if (isFromOlsrIntf && !isToOlsrIntf)... + * 2 = handled in second if-clause: if (isToOlsrIntf && !iAmNotMpr)... + * 3 = handled in third if-clause: if (!isFromOlsrIntf && !isToOlsrIntf)... + * 4 = handled in else-clause. + */ + + /* Forward from OLSR-interface to non-OLSR interface */ + if (isFromOlsrIntf && !isToOlsrIntf) + { + struct TSaveTtl sttl; + + /* Save IP header checksum and the TTL-value of the packet */ + SaveTtlAndChecksum(ethPkt, &sttl); + + /* Save IP header checksum and the TTL-value of the packet, then + * decrease the TTL by 1 before writing */ + DecreaseTtlAndUpdateHeaderChecksum(ethPkt); + + /* If the TTL is <= 0, do not forward this packet */ + if (GetIpTtl(ethPkt) <= 0) + { + OLSR_PRINTF( + 9, + "%s: --> not forwarding on \"%s\": TTL=0\n", + PLUGIN_NAME_SHORT, + fwIntf->ifName); + } + else + { + /* Change source MAC address to that of sending interface */ + memcpy(ethPkt + IFHWADDRLEN, fwIntf->macAddr, IFHWADDRLEN); + + int nBytesWritten = write(fwIntf->capturingSkfd, ethPkt, ethPktLen); + if (nBytesWritten != ethPktLen) + { + olsr_printf( + 1, + "%s: write() error forwarding pkt for %s to \"%s\": %s\n", + PLUGIN_NAME, + olsr_ip_to_string(&destIp), + fwIntf->ifName, + strerror(errno)); + } + else + { + OLSR_PRINTF( + 9, + "%s: --> forwarded to \"%s\"\n", + PLUGIN_NAME_SHORT, + fwIntf->ifName); + } + } + + /* Restore the IP header checksum and the TTL-value of the packet */ + RestoreTtlAndChecksum(ethPkt, &sttl); + + } /* if (isFromOlsrIntf && !isToOlsrIntf) */ + + /* Forward from any interface to OLSR interface. Packets from non-OLSR interfaces + * already had their TTL decreased. */ + else /* !isFromOlsrIntf || isToOlsrIntf */ + if (isToOlsrIntf && !iAmNotMpr) + { + int nBytesWritten; + + /* Change encapsulated source MAC address to that of sending interface */ + memcpy(ethPkt + IFHWADDRLEN, fwIntf->macAddr, IFHWADDRLEN); + + /* Destination address is local broadcast */ + encapDest.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*) &encapDest, + sizeof(encapDest)); + + if (nBytesWritten != len) + { + olsr_printf( + 1, + "%s: sendto() error forwarding pkt for %s to \"%s\": %s\n", + PLUGIN_NAME, + olsr_ip_to_string(&destIp), + fwIntf->ifName, + strerror(errno)); + } + else + { + OLSR_PRINTF( + 9, + "%s: --> encapsulated and forwarded to \"%s\"\n", + PLUGIN_NAME_SHORT, + fwIntf->ifName); + } /* if (nBytesWritten != len) */ + } /* else if (isToOlsrIntf && !iAmNotMpr) */ + + else /* (!isFromOlsrIntf || isToOlsrIntf) && (!isToOlsrIntf || iAmNotMpr) */ + if (!isFromOlsrIntf && !isToOlsrIntf) + { + OLSR_PRINTF( + 9, + "%s: --> not forwarding from \"%s\" to \"%s\": both non-OLSR interfaces\n", + PLUGIN_NAME_SHORT, + intf->ifName, + fwIntf->ifName); + } + + else /* (!isFromOlsrIntf || isToOlsrIntf) && (!isToOlsrIntf || iAmNotMpr) && (isFromOlsrIntf || isToOlsrIntf) */ + { + OLSR_PRINTF( + 9, + "%s: --> not forwarding from \"%s\" to \"%s\": I am not selected as MPR by %s\n", + PLUGIN_NAME_SHORT, + intf->ifName, + fwIntf->ifName, + olsr_ip_to_string(&srcIp)); + } + } /* while (nextFwIntf != NULL) */ +} + +/* ------------------------------------------------------------------------- + * Function : BmfEncapsulatedPacketReceived + * Description: Handle a received BMF-encapsulated IP packet + * Input : intf - the network interface on which the packet was received + * fromIp - the IP node that forwarded the packet to us + * buffer - the received encapsulated packet + * len - the number of octets in the received encapsulated packet + * Output : none + * Return : none + * Data Used : BmfInterfaces + * Notes : The packet is assumed to be received on a socket of family + * PF_INET and type SOCK_DGRAM (UDP). + * ------------------------------------------------------------------------- */ +static void BmfEncapsulatedPacketReceived( + struct TBmfInterface* intf, + union olsr_ip_addr* fromIp, + unsigned char* buffer, + ssize_t len) +{ + union olsr_ip_addr* forwarder; + int nBytesToWrite; + unsigned char* bufferToWrite; + int nBytesWritten; + int iAmMpr; + struct sockaddr_in encapDest; + struct TBmfInterface* nextFwIntf; + struct ip* ipData; + unsigned char* ethPkt; + ssize_t ethPktLen; + + /* Are we talking to ourselves? */ + if (if_ifwithaddr(fromIp) != NULL) + { + return; + } + + /* Encapsulated packet received on non-OLSR interface? Then discard */ + if (intf->olsrIntf == 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 */ + + ethPkt = buffer + ENCAP_HDR_LEN; + ethPktLen = len - ENCAP_HDR_LEN; + + ipData = (struct ip*) (ethPkt + IP_HDR_OFFSET); + + OLSR_PRINTF( + 9, + "%s: encapsulated pkt of %d bytes incoming on \"%s\": %s->", + PLUGIN_NAME_SHORT, + ethPktLen, + intf->ifName, + inet_ntoa(ipData->ip_src)); + OLSR_PRINTF( + 9, + "%s, forwarded by %s\n", + inet_ntoa(ipData->ip_dst), /* not possible to call inet_ntoa twice in same printf */ + olsr_ip_to_string(fromIp)); + + /* Get encapsulation header */ + struct TEncapHeader* encapHdr = (struct TEncapHeader*) buffer; + + /* Check if this packet was seen recently */ + if (CheckAndMarkRecentPacket(Hash16(ntohl(encapHdr->crc32)))) + { + OLSR_PRINTF( + 9, + "%s: --> discarding: packet is duplicate\n", + PLUGIN_NAME_SHORT); + return; + } + + /* Unpack encapsulated packet and send a copy to myself via the EtherTunTap device */ + bufferToWrite = ethPkt; + nBytesToWrite = ethPktLen; + if (TunOrTap == TT_TUN) + { + bufferToWrite += IP_HDR_OFFSET; + nBytesToWrite -= IP_HDR_OFFSET; + } + nBytesWritten = write(EtherTunTapFd, bufferToWrite, nBytesToWrite); + if (nBytesWritten != nBytesToWrite) + { + olsr_printf( + 1, + "%s: write() error forwarding encapsulated pkt to \"%s\": %s\n", + PLUGIN_NAME, + EtherTunTapIfName, + strerror(errno)); + } + else + { + OLSR_PRINTF( + 9, + "%s: --> unpacked and forwarded to \"%s\"\n", + PLUGIN_NAME_SHORT, + EtherTunTapIfName); + } + + /* Lookup main address of forwarding node */ + forwarder = mid_lookup_main_addr(fromIp); + if (forwarder == NULL) + { + forwarder = fromIp; + } + + /* Check if I am MPR for the forwarder */ + iAmMpr = (olsr_lookup_mprs_set(forwarder) != NULL); + + memset(&encapDest, 0, sizeof(encapDest)); + encapDest.sin_family = AF_INET; + encapDest.sin_port = htons(BMF_ENCAP_PORT); + + nextFwIntf = BmfInterfaces; + while (nextFwIntf != NULL) + { + struct TBmfInterface* fwIntf = nextFwIntf; + nextFwIntf = fwIntf->next; + + /* Forward from OLSR interface to non-OLSR interface: unpack encapsulated + * packet, decrease TTL and forward */ + if (fwIntf->olsrIntf == NULL) + { + struct TSaveTtl sttl; + + /* Save IP header checksum and the TTL-value of the packet, then + * decrease the TTL by 1 before writing */ + SaveTtlAndChecksum(ethPkt, &sttl); + DecreaseTtlAndUpdateHeaderChecksum(ethPkt); + + /* If the TTL is <= 0, do not forward this packet */ + if (GetIpTtl(ethPkt) <= 0) + { + OLSR_PRINTF( + 9, + "%s: --> not forwarding on \"%s\": TTL=0\n", + PLUGIN_NAME_SHORT, + fwIntf->ifName); + } + else + { + nBytesWritten = write(fwIntf->capturingSkfd, ethPkt, ethPktLen); + if (nBytesWritten != ethPktLen) + { + olsr_printf( + 1, + "%s: write() error forwarding unpacked encapsulated MC pkt to \"%s\": %s\n", + PLUGIN_NAME, + fwIntf->ifName, + strerror(errno)); + } + else + { + OLSR_PRINTF( + 9, + "%s: --> unpacked and forwarded to \"%s\"\n", + PLUGIN_NAME_SHORT, + fwIntf->ifName); + } + } + + /* Restore the IP header checksum and the TTL-value of the packet */ + RestoreTtlAndChecksum(ethPkt, &sttl); + + } /* if (fwIntf->olsrIntf == NULL) */ + + /* Forward from OLSR interface to OLSR interface: 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 */ + encapDest.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*) &encapDest, + sizeof(encapDest)); + + if (nBytesWritten != len) + { + olsr_printf( + 1, + "%s: sendto() error forwarding encapsulated pkt via \"%s\": %s\n", + PLUGIN_NAME, + fwIntf->ifName, + strerror(errno)); + } + else + { + OLSR_PRINTF( + 9, + "%s: --> forwarded to \"%s\"\n", + PLUGIN_NAME_SHORT, + fwIntf->ifName); + } + } /* else if (iAmMpr) */ + else /* fwIntf->olsrIntf != NULL && !iAmMpr */ + { + /* fwIntf is an OLSR interface and I am not selected as MPR */ + OLSR_PRINTF( + 9, + "%s: --> not forwarding to \"%s\": I am not selected as MPR by %s\n", + PLUGIN_NAME_SHORT, + fwIntf->ifName, + olsr_ip_to_string(fromIp)); + } + } /* while (nextFwIntf != NULL) */ +} + +/* ------------------------------------------------------------------------- + * Function : DoBmf + * Description: Wait (blocking) for IP packets, then call the handler for each + * received packet + * Input : none + * Output : none + * Return : none + * Data Used : BmfInterfaces + * ------------------------------------------------------------------------- */ +static void DoBmf(void) +{ +#define BUFFER_MAX 2048 + struct TBmfInterface* currIf; + int nFdBitsSet; + + /* Compose set of socket file descriptors. + * Keep the highest descriptor seen. */ + int highestSkfd = -1; + fd_set input_set; + FD_ZERO(&input_set); + + currIf = BmfInterfaces; + while (currIf != NULL) + { + FD_SET(currIf->capturingSkfd, &input_set); + if (currIf->capturingSkfd > highestSkfd) + { + highestSkfd = currIf->capturingSkfd; + } + + if (currIf->encapsulatingSkfd >= 0) + { + FD_SET(currIf->encapsulatingSkfd, &input_set); + if (currIf->encapsulatingSkfd > highestSkfd) + { + highestSkfd = currIf->encapsulatingSkfd; + } + } + + currIf = currIf->next; + } + + assert(highestSkfd >= 0); + + /* Wait (blocking) for packets received on any of the sockets. + * NOTE: don't use a timeout (last parameter). It causes a high system CPU load! */ + nFdBitsSet = select(highestSkfd + 1, &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) + { + struct TBmfInterface* nextIf = BmfInterfaces; + while (nextIf != NULL) + { + int skfd; + currIf = nextIf; + nextIf = currIf->next; + + skfd = currIf->capturingSkfd; + if (FD_ISSET(skfd, &input_set)) + { + unsigned char buffer[BUFFER_MAX]; + struct sockaddr_ll pktAddr; + socklen_t addrLen; + int nBytes; + unsigned char* ethPkt = buffer + ENCAP_HDR_LEN; + struct ip* ipData; + + /* A packet was captured. */ + + nFdBitsSet--; + + memset(&pktAddr, 0, sizeof(struct sockaddr_ll)); + addrLen = sizeof(pktAddr); + + /* Receive the packet, leaving space for the BMF encap header */ + nBytes = recvfrom( + skfd, + ethPkt, + BUFFER_MAX - ENCAP_HDR_LEN, + 0, + (struct sockaddr*)&pktAddr, + &addrLen); + if (nBytes < 0) + { + olsr_printf( + 1, + "%s: recvfrom() error on \"%s\": %s\n", + PLUGIN_NAME, + currIf->ifName, + strerror(errno)); + } + else + { + /* Don't let BMF crash by sending too short packets */ + int ipHeaderLen; + ipData = (struct ip*) (ethPkt + IP_HDR_OFFSET); + ipHeaderLen = ipData->ip_hl << 2; + if (nBytes >= IP_HDR_OFFSET + ipHeaderLen) + { + if (pktAddr.sll_pkttype == PACKET_OUTGOING) + { + union olsr_ip_addr destIp; + COPY_IP(&destIp, &ipData->ip_dst); + if (IsMulticast(&destIp) || IsLocalBroadcast(&destIp, currIf)) + { + if (! IsOlsrOrBmfPacket(currIf, ethPkt, nBytes)) + { + /* For outbound packets, just record the fact that the packet was + * seen recently */ + u_int32_t crc32 = PacketCrc32(ethPkt, nBytes); + MarkRecentPacket(Hash16(crc32)); + } + } + } + else if (pktAddr.sll_pkttype == PACKET_MULTICAST || + pktAddr.sll_pkttype == PACKET_BROADCAST) + { + /* An inbound multicast or broadcast packet was captured */ + BmfPacketCaptured(currIf, buffer, nBytes + ENCAP_HDR_LEN); + } + } /* if (nBytes >= IP_HDR_OFFSET + ipHeaderLen) */ + } /* if (nBytes < 0) */ + } /* if (FD_ISSET...) */ + + skfd = currIf->encapsulatingSkfd; + if (skfd >= 0 && (FD_ISSET(skfd, &input_set))) + { + unsigned char buffer[BUFFER_MAX]; + struct sockaddr_in from; + socklen_t fromLen = sizeof(from); + int nBytes; + struct ip* ipData; + + /* An encapsulated packet was received */ + + nFdBitsSet--; + + nBytes = recvfrom(skfd, buffer, BUFFER_MAX, 0, (struct sockaddr*)&from, &fromLen); + if (nBytes < 0) + { + olsr_printf( + 1, + "%s: recvfrom() error on \"%s\": %s\n", + PLUGIN_NAME, + currIf->ifName, + strerror(errno)); + } + else + { + /* Don't let BMF crash by sending too short packets. */ + int ipHeaderLen; + ipData = (struct ip *) (buffer + IP_HDR_OFFSET); + ipHeaderLen = ipData->ip_hl << 2; + if (nBytes >= IP_HDR_OFFSET + ipHeaderLen) + { + union olsr_ip_addr srcIp; + COPY_IP(&srcIp, &from.sin_addr.s_addr); + BmfEncapsulatedPacketReceived(currIf, &srcIp, buffer, nBytes); + } + else + { + olsr_printf( + 1, + "%s: encapsulated packet too short (%d bytes) from %s on \"%s\"\n", + PLUGIN_NAME, + nBytes, + inet_ntoa(from.sin_addr), + currIf->ifName); + } + } /* if (nBytes < 0) */ + } /* if (skfd >= 0 && (FD_ISSET...) */ + } /* while (intf != NULL) */ + } /* while (nFdBitsSet > 0) */ +} + +/* ------------------------------------------------------------------------- + * Function : BmfSignalHandler + * Description: Dummy signal handler function + * Input : signo - signal being handled + * Output : none + * Return : none + * Data Used : none + * ------------------------------------------------------------------------- */ +static void BmfSignalHandler(int signo) +{ + /* Dummy handler function */ + return; +} + +/* ------------------------------------------------------------------------- + * Function : BmfRun + * Description: Receiver thread function + * Input : useless - not used + * Output : none + * Return : not used + * Data Used : BmfThreadRunning + * Notes : Another thread can gracefully stop this thread by writing a + * '0' into global variable 'BmfThreadRunning' followed by sending + * a SIGALRM signal. + * ------------------------------------------------------------------------- */ +static void* BmfRun(void* useless) +{ + /* Mask all signals except SIGALRM */ + 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(); + } + + return NULL; +} + +/* ------------------------------------------------------------------------- + * Function : InterfaceChange + * Description: Callback function passed to OLSRD for it to call whenever a + * network interface has been added, removed or updated + * Input : interf - the network interface to deal with + * action - indicates if the specified network interface was + * added, removed or updated. + * Output : none + * Return : always 0 + * Data Used : none + * ------------------------------------------------------------------------- */ +int InterfaceChange(struct interface* interf, int action) +{ + switch (action) + { + case (IFCHG_IF_ADD): + AddInterface(interf); + olsr_printf(1, "%s: interface %s added\n", PLUGIN_NAME, interf->int_name); + break; + + case (IFCHG_IF_REMOVE): + CloseBmf(); + InitBmf(interf); + olsr_printf(1, "%s: interface %s removed\n", PLUGIN_NAME, interf->int_name); + break; + + case (IFCHG_IF_UPDATE): + olsr_printf(1, "%s: interface %s updated\n", PLUGIN_NAME, interf->int_name); + break; + + default: + break; + } + return 0; +} + +/* ------------------------------------------------------------------------- + * Function : InitBmf + * Description: Initialize the BMF plugin + * Input : skipThisIntf - specifies which network interface should not + * be enabled for BMF. Pass NULL to indicate all. + * Output : none + * Return : fail (0) or success (1) + * Data Used : BmfThreadRunning, BmfThread + * ------------------------------------------------------------------------- */ +int InitBmf(struct interface* skipThisIntf) +{ + if (CreateBmfNetworkInterfaces(skipThisIntf) < 0) + { + olsr_printf(1, "%s: Could not initialize any network interface!\n", PLUGIN_NAME); + /* Continue anyway; maybe an interface will be added later */ + } + + /* Start running the multicast packet processing thread */ + BmfThreadRunning = 1; + if (pthread_create(&BmfThread, NULL, BmfRun, NULL) == 0) + { + return 1; + } + return 0; +} + +/* ------------------------------------------------------------------------- + * Function : CloseBmf + * Description: Close the BMF plugin and clean up + * Input : none + * Output : none + * Return : none + * Data Used : BmfThreadRunning, BmfThread + * ------------------------------------------------------------------------- */ +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(); +} + +/* ------------------------------------------------------------------------- + * Function : RegisterBmfParameter + * Description: Register a configuration parameter with the BMF process + * Input : key - the parameter name: "DropMac" or "NonOlsrIf" + * value - the parameter value + * Output : none + * Return : fatal error (<0), minor error (0) or success (>0) + * Data Used : none + * ------------------------------------------------------------------------- */ +int RegisterBmfParameter(char* key, char* value) +{ + if (strcmp(key, "DropMac") == 0) + { + return DropMac(value); + } + else if (strcmp(key, "NonOlsrIf") == 0) + { + return AddNonOlsrBmfIf(value); + } + + /* Key not recognized */ + return 0; +} diff -Nur olsrd-0.4.10.orig/lib/bmf/src/Bmf.h olsrd-0.4.10/lib/bmf/src/Bmf.h --- olsrd-0.4.10.orig/lib/bmf/src/Bmf.h 1970-01-01 01:00:00.000000000 +0100 +++ olsrd-0.4.10/lib/bmf/src/Bmf.h 2006-12-01 08:26:58.000000000 +0100 @@ -0,0 +1,64 @@ +#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. + */ + +/* ------------------------------------------------------------------------- + * File : Bmf.h + * Description: Multicast forwarding functions + * Created : 29 Jun 2006 + * + * $Id$ + * + * $Log$ + * ------------------------------------------------------------------------- */ + +/* BMF plugin data */ +#define PLUGIN_NAME "OLSRD Basic Multicast Forwarding plugin" +#define PLUGIN_NAME_SHORT "OLSRD BMF" +#define PLUGIN_VERSION "1.1 (" __DATE__ " " __TIME__ ")" +#define PLUGIN_COPYRIGHT " (C) Thales Communications Huizen, Netherlands" +#define PLUGIN_AUTHOR " Erik Tromp (erik.tromp@nl.thalesgroup.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 50698 + +struct interface; + +int InterfaceChange(struct interface* interf, int action); +int InitBmf(struct interface* skipThisIntf); +void CloseBmf(void); +int RegisterBmfParameter(char* key, char* value); + +#endif /* _BMF_BMF_H */ diff -Nur olsrd-0.4.10.orig/lib/bmf/src/DropList.c olsrd-0.4.10/lib/bmf/src/DropList.c --- olsrd-0.4.10.orig/lib/bmf/src/DropList.c 1970-01-01 01:00:00.000000000 +0100 +++ olsrd-0.4.10/lib/bmf/src/DropList.c 2006-12-01 08:26:58.000000000 +0100 @@ -0,0 +1,129 @@ +/* + * 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. + */ + +/* ------------------------------------------------------------------------- + * File : DropList.c + * Description: List of MAC addresses of hosts from which all packets are dropped. + * Created : 29 Jun 2006 + * + * $Id$ + * + * $Log$ + * ------------------------------------------------------------------------- */ + + +#include "DropList.h" + +/* System includes */ +#include /* assert() */ +#include /* NULL */ +#include /* malloc */ +#include /* 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. + */ +/* ------------------------------------------------------------------------- + * Function : DropMac + * Description: Register a MAC address in the drop list + * Input : macStr - MAC address as string + * Output : none + * Return : success (1) or fail (0) + * Data Used : DroppedMacAddresses + * Notes : 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 helper and --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; +} + +/* ------------------------------------------------------------------------- + * Function : IsInDropList + * Description: Check if a MAC address is in the drop list + * Input : macAddress + * Output : none + * Return : true (1) or false (0) + * Data Used : DroppedMacAddresses + * ------------------------------------------------------------------------- */ +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 -Nur olsrd-0.4.10.orig/lib/bmf/src/DropList.h olsrd-0.4.10/lib/bmf/src/DropList.h --- olsrd-0.4.10.orig/lib/bmf/src/DropList.h 1970-01-01 01:00:00.000000000 +0100 +++ olsrd-0.4.10/lib/bmf/src/DropList.h 2006-12-01 08:26:58.000000000 +0100 @@ -0,0 +1,55 @@ +#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. + */ + +/* ------------------------------------------------------------------------- + * File : DropList.h + * Description: List of MAC addresses of hosts from which all packets are dropped. + * Created : 29 Jun 2006 + * + * $Id$ + * + * $Log$ + * ------------------------------------------------------------------------- */ + +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 -Nur olsrd-0.4.10.orig/lib/bmf/src/NetworkInterfaces.c olsrd-0.4.10/lib/bmf/src/NetworkInterfaces.c --- olsrd-0.4.10.orig/lib/bmf/src/NetworkInterfaces.c 1970-01-01 01:00:00.000000000 +0100 +++ olsrd-0.4.10/lib/bmf/src/NetworkInterfaces.c 2006-12-01 08:26:58.000000000 +0100 @@ -0,0 +1,818 @@ +/* + * 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. + */ + +/* ------------------------------------------------------------------------- + * File : NetworkInterfaces.c + * Description: Functions to open and close sockets + * Created : 29 Jun 2006 + * + * $Id$ + * + * $Log$ + * ------------------------------------------------------------------------- */ + +#include "NetworkInterfaces.h" + +/* System includes */ +#include /* syslog() */ +#include /* strerror() */ +#include /* errno */ +#include /* close() */ +#include /* ioctl() */ +#include /* fcntl() */ +#include /* assert() */ +#include /* socket(), ifreq, if_indextoname(), if_nametoindex() */ +#include /* htons() */ +#include /* ETH_P_ALL */ +#include /* packet_mreq, PACKET_MR_PROMISC, PACKET_ADD_MEMBERSHIP */ +#include /* 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; + +/* ------------------------------------------------------------------------- + * 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 raw packet socket, bound to the specified + * network interface + * ------------------------------------------------------------------------- */ +static int CreateCaptureSocket(const char* ifName) +{ + int ifIndex = if_nametoindex(ifName); + struct packet_mreq mreq; + struct ifreq req; + struct sockaddr_ll bindTo; + + /* 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)); + strncpy(req.ifr_name, ifName, IFNAMSIZ); + if (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(&bindTo, 0, sizeof(bindTo)); + bindTo.sll_protocol = htons(ETH_P_ALL); + bindTo.sll_ifindex = ifIndex; + bindTo.sll_family = AF_PACKET; + memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN); + bindTo.sll_halen = IFHWADDRLEN; + + if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 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; +} + +/* ------------------------------------------------------------------------- + * Function : CreateEncapsulateSocket + * Description: Create a socket for sending and receiving encapsulated + * multicast packets + * 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 an UDP (datagram) over IP socket, bound to the + * specified network interface + * ------------------------------------------------------------------------- */ +static int CreateEncapsulateSocket(const char* ifName) +{ + int on = 1; + struct sockaddr_in bindTo; + + /* 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 ifName. */ + /* When using Kernel 2.6 this must happer prior to the port binding! */ + if (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; + } + + /* Bind to port */ + memset(&bindTo, 0, sizeof(bindTo)); + bindTo.sin_family = AF_INET; + bindTo.sin_port = htons(BMF_ENCAP_PORT); + bindTo.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 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'; + +/* ------------------------------------------------------------------------- + * Function : DeactivateSpoofFilter + * Description: Deactivates the Linux anti-spoofing filter for the tuntap + * interface + * Input : tunTapName - name used for the tuntap interface (e.g. "tun0" or "tap1") + * Output : none + * Return : success (1) or fail (0) + * Data Used : EthTapSpoofState + * Notes : Saves the current filter state for later restoring + * ------------------------------------------------------------------------- */ +static int DeactivateSpoofFilter(const char* tunTapName) +{ + FILE* procSpoof; + char procFile[FILENAME_MAX]; + + assert(tunTapName != NULL); + + /* Generate the procfile name */ + sprintf(procFile, "/proc/sys/net/ipv4/conf/%s/rp_filter", tunTapName); + + 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; +} + +/* ------------------------------------------------------------------------- + * Function : RestoreSpoofFilter + * Description: Restores the Linux anti-spoofing filter setting for the tuntap + * interface + * Input : tunTapName - name used for the tuntap interface (e.g. "tun0" or "tap1") + * Output : none + * Return : none + * Data Used : EthTapSpoofState + * ------------------------------------------------------------------------- */ +static void RestoreSpoofFilter(const char* tunTapName) +{ + FILE* procSpoof; + char procFile[FILENAME_MAX]; + + assert(tunTapName != NULL); + + /* Generate the procfile name */ + sprintf(procFile, "/proc/sys/net/ipv4/conf/%s/rp_filter", tunTapName); + + 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); + } +} + +/* ------------------------------------------------------------------------- + * Function : CreateLocalEtherTunTap + * Description: Creates and brings up an EtherTunTap device + * Input : none + * Output : none + * Return : success (0) or fail (<0) + * Data Used : EtherTunTapIfName - name used for the tuntap interface (e.g. + * "tun0" or "tap1") + * ------------------------------------------------------------------------- */ +static int CreateLocalEtherTunTap(void) +{ + static char* deviceName = "/dev/net/tun"; + struct ifreq ifreq; + int etfd = open(deviceName, O_RDWR); + int skfd; + int ioctlres = 0; + + if (etfd < 0) + { + olsr_printf(1, "%s: error opening %s: %s\n", PLUGIN_NAME, deviceName, 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(TUNSETIFF) error on %s: %s\n", PLUGIN_NAME, deviceName, 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) + { + olsr_printf(1, "%s: socket(PF_INET) error on %s: %s\n", PLUGIN_NAME, deviceName, strerror(errno)); + close(etfd); + return -1; + } + + 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) + { + /* Any of the three above ioctl() calls failed */ + olsr_printf( + 1, + "%s: error bringing up EtherTunTap interface \"%s\": %s\n", + PLUGIN_NAME, + EtherTunTapIfName, + strerror(errno)); + + close(etfd); + close(skfd); + return -1; + } /* if (ioctlres < 0) */ + } /* if (ioctl...) */ + + /* 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) + { + /* Any of the two above ioctl() calls failed */ + olsr_printf( + 1, + "%s: error setting multicast flag on EtherTunTap interface \"%s\": %s\n", + PLUGIN_NAME, + EtherTunTapIfName, + strerror(errno)); + /* Continue anyway */ + } + close(skfd); + + /* Deactivate IP spoof filter for EtherTunTap device */ + DeactivateSpoofFilter(ifreq.ifr_name); + + olsr_printf(9, "%s: opened \"%s\"\n", PLUGIN_NAME_SHORT, EtherTunTapIfName); + + return etfd; +} + +/* ------------------------------------------------------------------------- + * Function : IsNullMacAddress + * Description: Checks if a MAC address is all-zeroes + * Input : mac - address to check + * Output : none + * Return : true (1) or false (0) + * Data Used : none + * ------------------------------------------------------------------------- */ +static int IsNullMacAddress(char* mac) +{ + int i; + + assert(mac != NULL); + + for (i = 0; i < IFHWADDRLEN; i++) + { + if (mac[i] != 0) return 0; + } + return 1; +} + +/* ------------------------------------------------------------------------- + * Function : CreateInterface + * Description: Create a new TBmfInterface object and adds it to the global + * BmfInterfaces list + * Input : ifName - name of the network interface (e.g. "eth0") + * Output : none + * Return : the number of opened sockets + * Data Used : none + * ------------------------------------------------------------------------- */ +static int CreateInterface( + const char* ifName, + struct interface* olsrIntf) +{ + int capturingSkfd; + int encapsulatingSkfd = -1; + struct ifreq ifr; + int nOpened = 0; + struct TBmfInterface* newIf = malloc(sizeof(struct TBmfInterface)); + + assert(ifName != NULL); + + if (newIf == NULL) + { + return 0; + } + + if (olsrIntf != NULL) + { + /* On OLSR interfaces, create socket for encapsulating and forwarding + * multicast packets */ + encapsulatingSkfd = CreateEncapsulateSocket(ifName); + if (encapsulatingSkfd < 0) + { + free(newIf); + return 0; + } + nOpened++; + } + + /* On all interfaces, create socket for capturing and sending multicast packets */ + capturingSkfd = CreateCaptureSocket(ifName); + if (capturingSkfd < 0) + { + close(encapsulatingSkfd); + free(newIf); + return 0; + } + nOpened++; + + /* Retrieve the MAC address */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_name, ifName, IFNAMSIZ); + if (ioctl(capturingSkfd, SIOCGIFHWADDR, &ifr) < 0) + { + olsr_printf( + 1, + "%s: ioctl(SIOCGIFHWADDR) error for device \"%s\": %s\n", + PLUGIN_NAME, + ifName, + strerror(errno)); + close(capturingSkfd); + close(encapsulatingSkfd); + free(newIf); + return 0; + } + + /* If null-interface, cancel the whole creation and return NULL */ + if (IsNullMacAddress(ifr.ifr_hwaddr.sa_data)) + { + close(capturingSkfd); + close(encapsulatingSkfd); + free(newIf); + return 0; + } + + newIf->capturingSkfd = capturingSkfd; + newIf->encapsulatingSkfd = encapsulatingSkfd; + memcpy(newIf->macAddr, ifr.ifr_hwaddr.sa_data, IFHWADDRLEN); + memcpy(newIf->ifName, ifName, IFNAMSIZ); + newIf->olsrIntf = olsrIntf; + if (olsrIntf != NULL) + { + /* Copy broadcast address from OLSR interface */ + newIf->broadAddr = olsrIntf->int_broadaddr; + } + else + { + /* Non-OLSR interface: retrieve the IP broadcast address */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_name, ifName, IFNAMSIZ); + if (ioctl(capturingSkfd, SIOCGIFBRDADDR, &ifr) < 0) + { + olsr_printf( + 1, + "%s: ioctl(SIOCGIFBRDADDR) error for device \"%s\": %s\n", + PLUGIN_NAME, + ifName, + strerror(errno)); + + ((struct sockaddr_in*)&newIf->broadAddr)->sin_addr.s_addr = inet_addr("0.0.0.0"); + } + else + { + newIf->broadAddr = ifr.ifr_broadaddr; + } + } + + memset(&newIf->fragmentHistory, 0, sizeof(newIf->fragmentHistory)); + newIf->nextFragmentHistoryEntry = 0; + + newIf->next = BmfInterfaces; + BmfInterfaces = newIf; + + OLSR_PRINTF( + 9, + "%s: opened %s interface \"%s\"\n", + PLUGIN_NAME_SHORT, + olsrIntf != NULL ? "OLSR" : "non-OLSR", + ifName); + + return nOpened; +} + +/* ------------------------------------------------------------------------- + * Function : CreateBmfNetworkInterfaces + * Description: Create a list of TBmfInterface objects, one for each network + * interface on which BMF runs + * Input : skipThisIntf - network interface to skip, if seen + * Output : none + * Return : success (0) or fail (<0) + * Data Used : none + * ------------------------------------------------------------------------- */ +int CreateBmfNetworkInterfaces(struct interface* skipThisIntf) +{ + int skfd; + struct ifconf ifc; + int numreqs = 30; + struct ifreq* ifr; + int n; + int nOpened = 0; + + EtherTunTapFd = CreateLocalEtherTunTap(); + if (EtherTunTapFd >=0) + { + nOpened++; + } + + skfd = socket(PF_INET, SOCK_DGRAM, 0); + if (skfd < 0) + { + olsr_printf( + 1, + "%s: no inet socket available to retrieve interface list: %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: ioctl(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 (;;) */ + + 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; + + /* ...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 (skipThisIntf != NULL && olsrIntf == skipThisIntf) + { + continue; /* for (n = ...) */ + } + + 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 = ...) */ + } + + nOpened += CreateInterface(ifr->ifr_name, olsrIntf); + + } /* for (n = ...) */ + + free(ifc.ifc_buf); + + if (BmfInterfaces == NULL) + { + olsr_printf(1, "%s: could not initialize any network interface\n", PLUGIN_NAME); + return -1; + } + + olsr_printf(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpened); + + return 0; +} + +/* ------------------------------------------------------------------------- + * 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); +} + +/* ------------------------------------------------------------------------- + * Function : CloseBmfNetworkInterfaces + * Description: Closes every socket on each network interface used by BMF + * Input : newIntf - network interface to add + * 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 CloseBmfNetworkInterfaces() +{ + int nClosed = 0; + + /* Close all opened sockets */ + struct TBmfInterface* nextBmfIf = BmfInterfaces; + while (nextBmfIf != NULL) + { + struct TBmfInterface* bmfIf = nextBmfIf; + nextBmfIf = bmfIf->next; + + if (bmfIf->capturingSkfd >= 0) + { + close(bmfIf->capturingSkfd); + nClosed++; + } + if (bmfIf->encapsulatingSkfd >= 0) + { + close(bmfIf->encapsulatingSkfd); + nClosed++; + } + + OLSR_PRINTF( + 9, + "%s: closed %s interface \"%s\"\n", + PLUGIN_NAME_SHORT, + bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR", + bmfIf->ifName); + + free(bmfIf); + } + + if (EtherTunTapFd >= 0) + { + /* Restore IP spoof filter for EtherTunTap device */ + RestoreSpoofFilter(EtherTunTapIfName); + + close(EtherTunTapFd); + nClosed++; + + OLSR_PRINTF(9, "%s: closed \"%s\"\n", PLUGIN_NAME_SHORT, EtherTunTapIfName); + } + + BmfInterfaces = NULL; + + 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; + +/* ------------------------------------------------------------------------- + * Function : AddNonOlsrBmfIf + * Description: Add an non-OLSR enabled network interface to the list of BMF-enabled + * network interfaces + * Input : ifName - network interface (e.g. "eth0") + * Output : none + * Return : success (1) or fail (0) + * Data Used : none + * ------------------------------------------------------------------------- */ +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 is %d\n", + PLUGIN_NAME, + MAX_NON_OLSR_IFS); + return 0; + } + + strncpy(NonOlsrIfNames[nNonOlsrIfs], ifName, IFNAMSIZ); + nNonOlsrIfs++; + return 1; +} + +/* ------------------------------------------------------------------------- + * Function : IsNonOlsrBmfIf + * 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 : none + * ------------------------------------------------------------------------- */ +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 -Nur olsrd-0.4.10.orig/lib/bmf/src/NetworkInterfaces.h olsrd-0.4.10/lib/bmf/src/NetworkInterfaces.h --- olsrd-0.4.10.orig/lib/bmf/src/NetworkInterfaces.h 1970-01-01 01:00:00.000000000 +0100 +++ olsrd-0.4.10/lib/bmf/src/NetworkInterfaces.h 2006-12-01 08:26:58.000000000 +0100 @@ -0,0 +1,106 @@ +#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. + */ + +/* ------------------------------------------------------------------------- + * File : NetworkInterfaces.h + * Description: Functions to open and close sockets + * Created : 29 Jun 2006 + * + * $Id$ + * + * $Log$ + * ------------------------------------------------------------------------- */ + +/* System includes */ +#include /* struct in_addr */ + +/* 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. + * Only used for OLSR-enabled interfaces; 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; + + /* Broadcast address of this network interface */ + struct sockaddr 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; + + /* 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(struct interface* skipThisIntf); +void AddInterface(struct interface* newIntf); +void CloseBmfNetworkInterfaces(void); +int AddNonOlsrBmfIf(const char* ifName); +int IsNonOlsrBmfIf(const char* ifName); + +#endif /* _BMF_NETWORKINTERFACES_H */ diff -Nur olsrd-0.4.10.orig/lib/bmf/src/olsrd_plugin.c olsrd-0.4.10/lib/bmf/src/olsrd_plugin.c --- olsrd-0.4.10.orig/lib/bmf/src/olsrd_plugin.c 1970-01-01 01:00:00.000000000 +0100 +++ olsrd-0.4.10/lib/bmf/src/olsrd_plugin.c 2006-12-01 08:26:58.000000000 +0100 @@ -0,0 +1,166 @@ +/* + * 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. + */ + +/* ------------------------------------------------------------------------- + * File : olsrd_plugin.c + * Description: Interface to the OLSRD plugin system + * Created : 29 Jun 2006 + * + * $Id$ + * + * $Log$ + * ------------------------------------------------------------------------- */ + +/* System includes */ +#include /* assert() */ +#include + +/* OLSRD includes */ +#include "olsrd_plugin.h" +#include "defs.h" /* olsr_u8_t, olsr_cnf */ +#include "scheduler.h" /* olsr_register_scheduler_event */ + +/* BMF includes */ +#include "Bmf.h" /* InitBmf(), CloseBmf(), RegisterBmfParameter() */ +#include "PacketHistory.h" /* InitPacketHistory() */ + +static void __attribute__ ((constructor)) my_init(void); +static void __attribute__ ((destructor)) my_fini(void); + +void olsr_plugin_exit(void); + +/* ------------------------------------------------------------------------- + * Function : olsrd_plugin_interface_version + * Description: Plugin interface version + * Input : none + * Output : none + * Return : BMF 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() +{ + return OLSRD_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() +{ + /* 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(); + + /* Register ifchange function */ + add_ifchgf(&InterfaceChange); + + /* Register the duplicate registration pruning process */ + olsr_register_scheduler_event(&PrunePacketHistory, NULL, 3.0, 2.0, NULL); + + return InitBmf(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() +{ + CloseBmf(); +} + +/* ------------------------------------------------------------------------- + * Function : olsrd_plugin_register_param + * Description: Register parameters from config file + * Input : key - the parameter name + * value - the parameter value + * Output : none + * Return : fatal error (<0), minor error (0) or success (>0) + * Data Used : none + * Notes : Called by main OLSR (init_olsr_plugin) for all plugin parameters + * ------------------------------------------------------------------------- */ +int olsrd_plugin_register_param(char* key, char* value) +{ + assert(key != NULL && value != NULL); + + return RegisterBmfParameter(key, value); +} + +/* ------------------------------------------------------------------------- + * 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() +{ + /* 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() +{ + olsr_plugin_exit(); +} diff -Nur olsrd-0.4.10.orig/lib/bmf/src/Packet.c olsrd-0.4.10/lib/bmf/src/Packet.c --- olsrd-0.4.10.orig/lib/bmf/src/Packet.c 1970-01-01 01:00:00.000000000 +0100 +++ olsrd-0.4.10/lib/bmf/src/Packet.c 2006-12-01 08:26:58.000000000 +0100 @@ -0,0 +1,133 @@ +/* + * 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. + */ + +/* ------------------------------------------------------------------------- + * File : Packet.c + * Description: BMF and IP packet processing functions + * Created : 29 Jun 2006 + * + * $Id$ + * + * $Log$ + * ------------------------------------------------------------------------- */ + +#include "Packet.h" + +/* System includes */ +#include /* assert() */ +#include /* u_int32_t */ +#include /* ntohs(), htons() */ +#include + +/* ------------------------------------------------------------------------- + * Function : GetIpTtl + * Description: Retrieve the TTL (Time To Live) value from the IP header of + * the passed ethernet-IP packet + * Input : buffer - the ethernet-IP packet + * Output : none + * Return : TTL value + * Data Used : none + * ------------------------------------------------------------------------- */ +int GetIpTtl(unsigned char* buffer) +{ + struct iphdr* iph; + + assert(buffer != NULL); + + iph = (struct iphdr*) (buffer + IP_HDR_OFFSET); + return iph->ttl; +} + +/* ------------------------------------------------------------------------- + * Function : SaveTtlAndChecksum + * Description: Save the TTL (Time To Live) value and IP checksum as found in + * the IP header of the passed ethernet-IP packet + * Input : buffer - the ethernet-IP packet + * Output : sttl - the TTL and checksum values + * Return : none + * Data Used : none + * ------------------------------------------------------------------------- */ +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); +} + +/* ------------------------------------------------------------------------- + * Function : RestoreTtlAndChecksum + * Description: Restore the TTL (Time To Live) value and IP checksum in + * the IP header of the passed ethernet-IP packet + * Input : buffer - the ethernet-IP packet + * sttl - the TTL and checksum values + * Output : none + * Return : none + * Data Used : none + * ------------------------------------------------------------------------- */ +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); +} + +/* ------------------------------------------------------------------------- + * Function : DecreaseTtlAndUpdateHeaderChecksum + * Description: For an IP packet, decrement the TTL value and update the IP header + * checksum accordingly. + * Input : buffer - the ethernet-IP packet + * Output : none + * Return : none + * Data Used : none + * Notes : See also RFC1141 + * ------------------------------------------------------------------------- */ +void DecreaseTtlAndUpdateHeaderChecksum(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 -Nur olsrd-0.4.10.orig/lib/bmf/src/Packet.h olsrd-0.4.10/lib/bmf/src/Packet.h --- olsrd-0.4.10.orig/lib/bmf/src/Packet.h 1970-01-01 01:00:00.000000000 +0100 +++ olsrd-0.4.10/lib/bmf/src/Packet.h 2006-12-01 08:26:58.000000000 +0100 @@ -0,0 +1,85 @@ +#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. + */ + +/* ------------------------------------------------------------------------- + * File : Packet.h + * Description: BMF and IP packet processing functions + * Created : 29 Jun 2006 + * + * $Id$ + * + * $Log$ + * ------------------------------------------------------------------------- */ + +/* System includes */ +#include /* IFNAMSIZ, IFHWADDRLEN */ +#include /* 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 + +/* BMF-encapsulated packets are Ethernet-IP-UDP packets, which start + * with a 16-bytes BMF header (struct TEncapHeader), followed by the + * encapsulated Ethernet-IP packet itself */ + +struct TEncapHeader +{ + u_int32_t crc32; + u_int32_t futureExpansion1; + u_int32_t futureExpansion2; + u_int32_t futureExpansion3; +} __attribute__((__packed__)); + +#define ENCAP_HDR_LEN sizeof(struct TEncapHeader) + +struct TSaveTtl +{ + u_int8_t ttl; + u_int16_t check; +} __attribute__((__packed__)); + +int GetIpTtl(unsigned char* buffer); +void SaveTtlAndChecksum(unsigned char* buffer, struct TSaveTtl* sttl); +void RestoreTtlAndChecksum(unsigned char* buffer, struct TSaveTtl* sttl); +void DecreaseTtlAndUpdateHeaderChecksum(unsigned char* buffer); + +#endif /* _BMF_PACKET_H */ diff -Nur olsrd-0.4.10.orig/lib/bmf/src/PacketHistory.c olsrd-0.4.10/lib/bmf/src/PacketHistory.c --- olsrd-0.4.10.orig/lib/bmf/src/PacketHistory.c 1970-01-01 01:00:00.000000000 +0100 +++ olsrd-0.4.10/lib/bmf/src/PacketHistory.c 2006-12-01 08:26:58.000000000 +0100 @@ -0,0 +1,293 @@ +/* + * 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. + */ + +/* ------------------------------------------------------------------------- + * File : PacketHistory.c + * Description: Functions for keeping and accessing the history of processed + * multicast IP packets. + * Created : 29 Jun 2006 + * + * $Id$ + * + * $Log$ + * ------------------------------------------------------------------------- */ + +#include "PacketHistory.h" + +/* System includes */ +#include /* assert() */ +#include /* u_int16_t, u_int32_t */ +#include /* memset */ + +/* OLSRD includes */ +#include "olsr.h" /* olsr_printf */ + +/* Plugin includes */ +#include "Packet.h" + +static u_int32_t PacketHistory[HISTORY_TABLE_SIZE]; + +#define CRC_UPTO_NBYTES 256 + +/* ------------------------------------------------------------------------- + * Function : CalcCrcCcitt + * Description: Calculate 16-bits CRC according to CRC-CCITT specification + * Input : buffer - the bytes to calculate the CRC value over + * len - the number of bytes to calculate the CRC value over + * Output : none + * Return : CRC-16 value + * Data Used : none + * ------------------------------------------------------------------------- */ +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++) + { + 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; +} + + +/* ------------------------------------------------------------------------- + * Function : GenerateCrc32Table + * Description: Generate the table of CRC remainders for all possible bytes, + * according to CRC-32-IEEE 802.3 + * Input : none + * Output : none + * Return : none + * Data Used : none + * ------------------------------------------------------------------------- */ +#define CRC32_POLYNOMIAL 0xedb88320UL /* bit-inverse of 0x04c11db7UL */ + +static unsigned long CrcTable[256]; + +static void GenerateCrc32Table(void) +{ + int i, j; + u_int32_t crc; + for (i = 0; i < 256; i++) + { + crc = (u_int32_t) i; + for (j = 0; j < 8; j++) + { + if (crc & 1) + { + crc = (crc >> 1) ^ CRC32_POLYNOMIAL; + } + else + { + crc = (crc >> 1); + } + } + CrcTable[i] = crc; + } +} + +/* ------------------------------------------------------------------------- + * Function : CalcCrc32 + * Description: Calculate CRC-32 according to CRC-32-IEEE 802.3 + * Input : buffer - the bytes to calculate the CRC value over + * len - the number of bytes to calculate the CRC value over + * Output : none + * Return : CRC-32 value + * Data Used : none + * ------------------------------------------------------------------------- */ +static u_int32_t CalcCrc32(unsigned char* buffer, ssize_t len) +{ + int i, j; + u_int32_t crc = 0xffffffffUL; + 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; + + j = ((int) (crc & 0xFF) ^ *buffer++); + crc = (crc >> 8) ^ CrcTable[j]; + } + return crc ^ 0xffffffffUL; +} + +/* */ +/* ------------------------------------------------------------------------- + * Function : PacketCrc32 + * Description: Calculates the CRC-32 value for an Ethernet packet + * Input : ethPkt - the Ethernet packet + * len - the number of octets in the Ethernet packet + * Output : none + * Return : 32-bits hash value + * Data Used : none + * Notes : The source and destination MAC address are not taken into account + * in the CRC calculation. + * ------------------------------------------------------------------------- */ +u_int32_t PacketCrc32(unsigned char* ethPkt, ssize_t len) +{ + assert(ethPkt != NULL); + assert(len > ETH_TYPE_OFFSET); + + /* Start CRC calculation at ethertype; skip source and destination MAC + * addresses. Clip number of bytes over which CRC is calculated to prevent + * long packets from possibly claiming too much CPU resources. */ + ssize_t nCrcBytes = len - ETH_TYPE_OFFSET; + if (nCrcBytes > CRC_UPTO_NBYTES) + { + nCrcBytes = CRC_UPTO_NBYTES; + } + return CalcCrc32(ethPkt + ETH_TYPE_OFFSET, nCrcBytes); +} + +/* Calculates a 16-bit hash value from a 32-bit hash value */ +u_int16_t Hash16(u_int32_t hash32) +{ + return ((hash32 >> 16) + hash32) & 0xFFFFU; +} + +/* ------------------------------------------------------------------------- + * Function : InitPacketHistory + * Description: Initialize the packet history table and CRC-32 table + * Input : none + * Output : none + * Return : none + * Data Used : PacketHistory + * ------------------------------------------------------------------------- */ +void InitPacketHistory() +{ + memset(PacketHistory, 0, sizeof(PacketHistory)); + GenerateCrc32Table(); +} + +/* ------------------------------------------------------------------------- + * Function : MarkRecentPacket + * Description: Record the fact that this packet was seen recently + * Input : hash16 + * Output : none + * Return : none + * Data Used : PacketHistory + * ------------------------------------------------------------------------- */ +void MarkRecentPacket(u_int16_t hash16) +{ + u_int32_t index; + uint offset; + + index = hash16 / NPACKETS_PER_ENTRY; + assert(index < HISTORY_TABLE_SIZE); + + offset = (hash16 % NPACKETS_PER_ENTRY) * NBITS_PER_PACKET; + assert(offset <= NBITS_IN_UINT32 - NBITS_PER_PACKET); + + /* Mark as "seen recently" */ + PacketHistory[index] = PacketHistory[index] | (0x3u << offset); +} + +/* ------------------------------------------------------------------------- + * Function : CheckAndMarkRecentPacket + * Description: Check if this packet was seen recently, then record the fact + * that this packet was seen recently. + * Input : hash16 + * Output : none + * Return : not recently seen (0), recently seen (1) + * Data Used : PacketHistory + * ------------------------------------------------------------------------- */ +int CheckAndMarkRecentPacket(u_int16_t hash16) +{ + u_int32_t index; + uint offset; + u_int32_t bitMask; + int result; + + index = hash16 / NPACKETS_PER_ENTRY; + assert(index < HISTORY_TABLE_SIZE); + + offset = (hash16 % NPACKETS_PER_ENTRY) * NBITS_PER_PACKET; + assert(offset <= NBITS_IN_UINT32 - NBITS_PER_PACKET); + + bitMask = 0x1u << offset; + result = ((PacketHistory[index] & bitMask) == bitMask); + + /* Always mark as "seen recently" */ + PacketHistory[index] = PacketHistory[index] | (0x3u << offset); + + return result; +} + +/* ------------------------------------------------------------------------- + * Function : PrunePacketHistory + * Description: Prune the packet history table. + * Input : useless - not used + * Output : none + * Return : none + * Data Used : PacketHistory + * ------------------------------------------------------------------------- */ +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 -Nur olsrd-0.4.10.orig/lib/bmf/src/PacketHistory.h olsrd-0.4.10/lib/bmf/src/PacketHistory.h --- olsrd-0.4.10.orig/lib/bmf/src/PacketHistory.h 1970-01-01 01:00:00.000000000 +0100 +++ olsrd-0.4.10/lib/bmf/src/PacketHistory.h 2006-12-01 08:26:58.000000000 +0100 @@ -0,0 +1,67 @@ +#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. + */ + +/* ------------------------------------------------------------------------- + * File : PacketHistory.h + * Description: Functions for keeping and accessing the history of processed + * multicast IP packets. + * Created : 29 Jun 2006 + * + * $Id$ + * + * $Log$ + * ------------------------------------------------------------------------- */ + +#include /* ssize_t */ + +/* 2 bits per seen packet: + * 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); +u_int32_t PacketCrc32(unsigned char* ethPkt, ssize_t len); +u_int16_t Hash16(u_int32_t hash32); +void MarkRecentPacket(u_int16_t hash16); +int CheckAndMarkRecentPacket(u_int16_t hash16); +void PrunePacketHistory(void*); + +#endif /* _BMF_PACKETHISTORY_H */ diff -Nur olsrd-0.4.10.orig/lib/bmf/version-script.txt olsrd-0.4.10/lib/bmf/version-script.txt --- olsrd-0.4.10.orig/lib/bmf/version-script.txt 1970-01-01 01:00:00.000000000 +0100 +++ olsrd-0.4.10/lib/bmf/version-script.txt 2006-12-01 08:26:58.000000000 +0100 @@ -0,0 +1,10 @@ +VERS_1.0 +{ + global: + olsrd_plugin_interface_version; + olsrd_plugin_register_param; + olsrd_plugin_init; + + local: + *; +}; diff -Nur olsrd-0.4.10.orig/Makefile olsrd-0.4.10/Makefile --- olsrd-0.4.10.orig/Makefile 2006-12-01 08:26:58.000000000 +0100 +++ olsrd-0.4.10/Makefile 2006-12-01 08:26:58.000000000 +0100 @@ -164,5 +164,10 @@ $(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