--- a/Makefile +++ b/Makefile @@ -154,7 +154,7 @@ # nameservice: no regex SUBDIRS := bmf dot_draw dyn_gw_plain httpinfo mini quagga secure tas txtinfo watchdog else -SUBDIRS := bmf dot_draw dyn_gw dyn_gw_plain httpinfo mini nameservice pgraph secure txtinfo watchdog +SUBDIRS := bmf dot_draw dyn_gw dyn_gw_plain httpinfo mini nameservice pgraph secure txtinfo watchdog mdns endif endif endif @@ -241,6 +241,11 @@ $(MAKECMD) -C lib/watchdog $(MAKECMD) -C lib/watchdog DESTDIR=$(DESTDIR) install +mdns: + $(MAKECMD) -C lib/mdns clean + $(MAKECMD) -C lib/mdns + $(MAKECMD) -C lib/mdns DESTDIR=$(DESTDIR) install + build_all: all switch libs install_all: install install_libs clean_all: uberclean clean_libs --- /dev/null +++ b/lib/mdns/Makefile @@ -0,0 +1,66 @@ +# +# 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. +# + +OLSRD_PLUGIN = true +PLUGIN_NAME = olsrd_mdns +PLUGIN_VER = 1.0.0 + +TOPDIR = ../.. +include $(TOPDIR)/Makefile.inc + +LIBS += $(OS_LIB_PTHREAD) + +# Must be specified along with -lpthread on linux +CPPFLAGS += $(OS_CFLAG_PTHREAD) + +ifneq ($(OS),linux) + +default_target install clean: + @echo "*** BMF Plugin only supported on Linux, sorry!" + +else + +default_target: $(PLUGIN_FULLNAME) + +$(PLUGIN_FULLNAME): $(OBJS) version-script.txt + $(CC) $(LDFLAGS) -o $(PLUGIN_FULLNAME) $(OBJS) $(LIBS) + +install: $(PLUGIN_FULLNAME) + $(STRIP) $(PLUGIN_FULLNAME) + $(INSTALL_LIB) + +clean: + rm -f $(OBJS) $(SRCS:%.c=%.d) $(PLUGIN_FULLNAME) + +endif --- /dev/null +++ b/lib/mdns/src/Address.c @@ -0,0 +1,164 @@ +/* + * OLSR Basic Multicast Forwarding (BMF) plugin. + * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands. + * Written by Erik Tromp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Thales, BMF nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* ------------------------------------------------------------------------- + * File : Address.c + * Description: IP packet characterization functions + * Created : 29 Jun 2006 + * + * ------------------------------------------------------------------------- */ + +#include "Address.h" + +/* System includes */ +#include /* NULL */ +#include /* strcmp */ +#include /* assert() */ +#include /* struct ip */ +#include /* struct udphdr */ + +/* OLSRD includes */ +#include "defs.h" /* ipequal */ +#include "olsr_protocol.h" /* OLSRPORT */ + +/* Plugin includes */ +#include "mdns.h" /* BMF_ENCAP_PORT */ +#include "NetworkInterfaces.h" /* TBmfInterface */ + +/* Whether or not to flood local broadcast packets (e.g. packets with IP + * destination 192.168.1.255). May be overruled by setting the plugin + * parameter "DoLocalBroadcast" to "no" */ +int EnableLocalBroadcast = 1; + +/* ------------------------------------------------------------------------- + * Function : DoLocalBroadcast + * Description: Overrule the default setting, enabling or disabling the + * flooding of local broadcast packets + * Input : enable - either "yes" or "no" + * data - not used + * addon - not used + * Output : none + * Return : success (0) or fail (1) + * Data Used : none + * ------------------------------------------------------------------------- */ +int DoLocalBroadcast( + const char* enable, + void* data __attribute__((unused)), + set_plugin_parameter_addon addon __attribute__((unused))) +{ + if (strcmp(enable, "yes") == 0) + { + EnableLocalBroadcast = 1; + return 0; + } + else if (strcmp(enable, "no") == 0) + { + EnableLocalBroadcast = 0; + return 0; + } + + /* Value not recognized */ + return 1; +} + +/* ------------------------------------------------------------------------- + * 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.s_addr) & 0xF0000000) == 0xE0000000; +} + +/* ------------------------------------------------------------------------- + * Function : IsOlsrOrBmfPacket + * Description: Check if an IP packet is either an OLSR packet or a BMF packet + * Input : ipPacket + * Output : none + * Return : true (1) or false (0) + * Data Used : none + * ------------------------------------------------------------------------- */ +//int IsOlsrOrBmfPacket(unsigned char* ipPacket) +//{//MODIFICATA +// struct ip* ipHeader; +// unsigned int ipHeaderLen; +// struct udphdr* udpHeader; +// u_int16_t destPort; +// +// assert(ipPacket != NULL); +// +// /* OLSR packets are UDP - port 698 +// * OLSR-BMF packets are UDP - port 50698 +// * OLSR-Autodetect probe packets are UDP - port 51698 */ +// +// /* Check if UDP */ +// ipHeader = (struct ip*) ipPacket; +// if (ipHeader->ip_p != SOL_UDP) +// { +// /* Not UDP */ +// return 0; +// } +// +// /* The total length must be at least large enough to store the UDP header */ +// ipHeaderLen = GetIpHeaderLength(ipPacket); +// if (GetIpTotalLength(ipPacket) < ipHeaderLen + sizeof(struct udphdr)) +// { +// /* Not long enough */ +// return 0; +// } +// +// /* Go into the UDP header and check port number */ +// udpHeader = (struct udphdr*) (ipPacket + ipHeaderLen); +// destPort = ntohs(udpHeader->dest); +// +// //if (destPort == OLSRPORT || destPort == BMF_ENCAP_PORT || destPort == 51698) +// if (destPort == 5353) +// /* TODO: #define for 51698 */ +// { +// return 1; +// } +// +// return 0; +//} +// +/* + * Local Variables: + * c-basic-offset: 2 + * indent-tabs-mode: nil + * End: + */ --- /dev/null +++ b/lib/mdns/src/Address.h @@ -0,0 +1,62 @@ +#ifndef _BMF_ADDRESS_H +#define _BMF_ADDRESS_H + +/* + * OLSR Basic Multicast Forwarding (BMF) plugin. + * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands. + * Written by Erik Tromp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Thales, BMF nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* ------------------------------------------------------------------------- + * File : Address.h + * Description: IP packet characterization functions + * Created : 29 Jun 2006 + * + * ------------------------------------------------------------------------- */ + +#include "olsr_types.h" /* olsr_ip_addr */ +#include "olsrd_plugin.h" /* union set_plugin_parameter_addon */ +#include "interfaces.h" /* struct interface */ + +struct TBmfInterface; + +extern int EnableLocalBroadcast; + +int DoLocalBroadcast(const char* enable, void* data, set_plugin_parameter_addon addon); +int IsMulticast(union olsr_ip_addr* ipAddress); +int IsOlsrOrBmfPacket(unsigned char* ipPacket); + +#endif /* _BMF_ADDRESS_H */ + +/* + * Local Variables: + * c-basic-offset: 2 + * indent-tabs-mode: nil + * End: + */ --- /dev/null +++ b/lib/mdns/src/NetworkInterfaces.c @@ -0,0 +1,1703 @@ +/* + * OLSR Basic Multicast Forwarding (BMF) plugin. + * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands. + * Written by Erik Tromp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Thales, BMF nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* ------------------------------------------------------------------------- + * File : NetworkInterfaces.c + * Description: Functions to open and close sockets + * Created : 29 Jun 2006 + * + * ------------------------------------------------------------------------- */ + +#include "NetworkInterfaces.h" + +/* System includes */ +#include /* NULL */ +#include /* syslog() */ +#include /* strerror(), strchr(), strcmp() */ +#include /* errno */ +#include /* close() */ +#include /* ioctl() */ +#include /* fcntl() */ +#include /* assert() */ +#include /* socket(), ifreq, if_indextoname(), if_nametoindex() */ +#include /* htons() */ +#include /* ETH_P_IP */ +#include /* packet_mreq, PACKET_MR_PROMISC, PACKET_ADD_MEMBERSHIP */ +#include /* IFF_TAP */ +#include /* struct ip */ +#include /* SOL_UDP */ +#include /* atoi, malloc */ + +/* OLSRD includes */ +#include "olsr.h" /* OLSR_PRINTF() */ +#include "ipcalc.h" +#include "defs.h" /* olsr_cnf */ +#include "link_set.h" /* get_link_set() */ +#include "tc_set.h" /* olsr_lookup_tc_entry(), olsr_lookup_tc_edge() */ +#include "net_olsr.h" /* ipequal */ +#include "lq_plugin.h" + + +/* Plugin includes */ +#include "Packet.h" /* IFHWADDRLEN */ +#include "mdns.h" /* PLUGIN_NAME, MainAddressOf() */ +#include "Address.h" /* IsMulticast() */ + +/* List of network interface objects used by BMF plugin */ +struct TBmfInterface* BmfInterfaces = NULL; +struct TBmfInterface* LastBmfInterface = NULL; + +/* Highest-numbered open socket file descriptor. To be used as first + * parameter in calls to select(...). */ +int HighestSkfd = -1; + +/* Set of socket file descriptors */ +fd_set InputSet; + +/* File descriptor of EtherTunTap interface */ +int EtherTunTapFd = -1; + +/* Network interface name of EtherTunTap interface. May be overruled by + * setting the plugin parameter "BmfInterface". */ +char EtherTunTapIfName[IFNAMSIZ] = "bmf0"; + +/* The underlying mechanism to forward multicast packets. Either: + * - BM_BROADCAST: BMF uses the IP local broadcast as destination address + * - BM_UNICAST_PROMISCUOUS: BMF uses the IP address of the best neighbor as + * destination address. The other neighbors listen promiscuously. */ +enum TBmfMechanism BmfMechanism = BM_BROADCAST; + +#define ETHERTUNTAPIPNOTSET 0 + +/* The IP address of the BMF network interface in host byte order. + * May be overruled by setting the plugin parameter "BmfInterfaceIp". */ +u_int32_t EtherTunTapIp = ETHERTUNTAPIPNOTSET; + +/* 255.255.255.255 in host byte order. May be overruled by + * setting the plugin parameter "BmfInterfaceIp". */ +u_int32_t EtherTunTapIpMask = 0xFFFFFFFF; + +/* The IP broadcast address of the BMF network interface in host byte order. + * May be overruled by setting the plugin parameter "BmfinterfaceIp". */ +u_int32_t EtherTunTapIpBroadcast = ETHERTUNTAPIPNOTSET; + +/* Whether or not the configuration has overruled the default IP + * configuration of the EtherTunTap interface */ +int TunTapIpOverruled = 0; + +/* Whether or not to capture packets on the OLSR-enabled + * interfaces (in promiscuous mode). May be overruled by setting the plugin + * parameter "CapturePacketsOnOlsrInterfaces" to "yes". */ +int CapturePacketsOnOlsrInterfaces = 0; + +/* ------------------------------------------------------------------------- + * Function : SetBmfInterfaceName + * Description: Overrule the default network interface name ("bmf0") of the + * EtherTunTap interface + * Input : ifname - network interface name (e.g. "mybmf0") + * data - not used + * addon - not used + * Output : none + * Return : success (0) or fail (1) + * Data Used : EtherTunTapIfName + * ------------------------------------------------------------------------- */ +int SetBmfInterfaceName( + const char* ifname, + void* data __attribute__((unused)), + set_plugin_parameter_addon addon __attribute__((unused))) +{ + strncpy(EtherTunTapIfName, ifname, IFNAMSIZ - 1); + EtherTunTapIfName[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */ + return 0; +} /* SetBmfInterfaceName */ + +/* ------------------------------------------------------------------------- + * Function : SetBmfInterfaceIp + * Description: Overrule the default IP address and prefix length + * ("10.255.255.253/30") of the EtherTunTap interface + * Input : ip - IP address string, followed by '/' and prefix length + * data - not used + * addon - not used + * Output : none + * Return : success (0) or fail (1) + * Data Used : EtherTunTapIp, EtherTunTapIpMask, EtherTunTapIpBroadcast, + * TunTapIpOverruled + * ------------------------------------------------------------------------- */ +int SetBmfInterfaceIp( + const char* ip, + void* data __attribute__((unused)), + set_plugin_parameter_addon addon __attribute__((unused))) +{ +#define IPV4_MAX_ADDRLEN 16 +#define IPV4_MAX_PREFIXLEN 32 + char* slashAt; + char ipAddr[IPV4_MAX_ADDRLEN]; + struct in_addr sinaddr; + int prefixLen; + int i; + + /* Inspired by function str2prefix_ipv4 as found in Quagga source + * file lib/prefix.c */ + + /* Find slash inside string. */ + slashAt = strchr(ip, '/'); + + /* String doesn't contain slash. */ + if (slashAt == NULL || slashAt - ip >= IPV4_MAX_ADDRLEN) + { + /* No prefix length specified, or IP address too long */ + return 1; + } + + strncpy(ipAddr, ip, slashAt - ip); + *(ipAddr + (slashAt - ip)) = '\0'; + if (inet_aton(ipAddr, &sinaddr) == 0) + { + /* Invalid address passed */ + return 1; + } + + EtherTunTapIp = ntohl(sinaddr.s_addr); + + /* Get prefix length. */ + prefixLen = atoi(++slashAt); + if (prefixLen <= 0 || prefixLen > IPV4_MAX_PREFIXLEN) + { + return 1; + } + + /* Compose IP subnet mask in host byte order */ + EtherTunTapIpMask = 0; + for (i = 0; i < prefixLen; i++) + { + EtherTunTapIpMask |= (1 << (IPV4_MAX_PREFIXLEN - 1 - i)); + } + + /* Compose IP broadcast address in host byte order */ + EtherTunTapIpBroadcast = EtherTunTapIp; + for (i = prefixLen; i < IPV4_MAX_PREFIXLEN; i++) + { + EtherTunTapIpBroadcast |= (1 << (IPV4_MAX_PREFIXLEN - 1 - i)); + } + + TunTapIpOverruled = 1; + + return 0; +} /* SetBmfInterfaceIp */ + +/* ------------------------------------------------------------------------- + * Function : SetCapturePacketsOnOlsrInterfaces + * Description: Overrule the default setting, enabling or disabling the + * capturing of packets on OLSR-enabled interfaces. + * Input : enable - either "yes" or "no" + * data - not used + * addon - not used + * Output : none + * Return : success (0) or fail (1) + * Data Used : none + * ------------------------------------------------------------------------- */ +int SetCapturePacketsOnOlsrInterfaces( + const char* enable, + void* data __attribute__((unused)), + set_plugin_parameter_addon addon __attribute__((unused))) +{ + if (strcmp(enable, "yes") == 0) + { + CapturePacketsOnOlsrInterfaces = 1; + return 0; + } + else if (strcmp(enable, "no") == 0) + { + CapturePacketsOnOlsrInterfaces = 0; + return 0; + } + + /* Value not recognized */ + return 1; +} /* SetCapturePacketsOnOlsrInterfaces */ + +/* ------------------------------------------------------------------------- + * Function : SetBmfMechanism + * Description: Overrule the default BMF mechanism to either BM_BROADCAST or + * BM_UNICAST_PROMISCUOUS. + * Input : mechanism - either "Broadcast" or "UnicastPromiscuous" + * data - not used + * addon - not used + * Output : none + * Return : success (0) or fail (1) + * Data Used : none + * ------------------------------------------------------------------------- */ +int SetBmfMechanism( + const char* mechanism, + void* data __attribute__((unused)), + set_plugin_parameter_addon addon __attribute__((unused))) +{ + if (strcmp(mechanism, "Broadcast") == 0) + { + BmfMechanism = BM_BROADCAST; + return 0; + } + else if (strcmp(mechanism, "UnicastPromiscuous") == 0) + { + BmfMechanism = BM_UNICAST_PROMISCUOUS; + return 0; + } + + /* Value not recognized */ + return 1; +} /* SetBmfMechanism */ + +/* ------------------------------------------------------------------------- + * Function : AddDescriptorToInputSet + * Description: Add a socket descriptor to the global set of socket file descriptors + * Input : skfd - socket file descriptor + * Output : none + * Return : none + * Data Used : HighestSkfd, InputSet + * Notes : Keeps track of the highest-numbered descriptor + * ------------------------------------------------------------------------- */ +static void AddDescriptorToInputSet(int skfd) +{ + /* Keep the highest-numbered descriptor */ + if (skfd > HighestSkfd) + { + HighestSkfd = skfd; + } + + /* Add descriptor to input set */ + FD_SET(skfd, &InputSet); +} /* AddDescriptorToInputSet */ + +/* To save the state of the IP spoof filter for the EtherTunTap interface */ +static char EthTapSpoofState = '1'; + +/* ------------------------------------------------------------------------- + * Function : DeactivateSpoofFilter + * Description: Deactivates the Linux anti-spoofing filter for the tuntap + * interface + * Input : none + * Output : none + * Return : fail (0) or success (1) + * Data Used : EtherTunTapIfName, EthTapSpoofState + * Notes : Saves the current filter state for later restoring + * ------------------------------------------------------------------------- */ +int DeactivateSpoofFilter(void) +{ + FILE* procSpoof; + char procFile[FILENAME_MAX]; + + /* Generate the procfile name */ + sprintf(procFile, "/proc/sys/net/ipv4/conf/%s/rp_filter", EtherTunTapIfName); + + /* Open procfile for reading */ + 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); + + /* Open procfile for writing */ + 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; +} /* DeactivateSpoofFilter */ + +/* ------------------------------------------------------------------------- + * Function : RestoreSpoofFilter + * Description: Restores the Linux anti-spoofing filter setting for the tuntap + * interface + * Input : none + * Output : none + * Return : none + * Data Used : EtherTunTapIfName, EthTapSpoofState + * ------------------------------------------------------------------------- */ +void RestoreSpoofFilter(void) +{ + FILE* procSpoof; + char procFile[FILENAME_MAX]; + + /* Generate the procfile name */ + sprintf(procFile, "/proc/sys/net/ipv4/conf/%s/rp_filter", EtherTunTapIfName); + + /* Open procfile for writing */ + 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); + } +} /* RestoreSpoofFilter */ + +/* ------------------------------------------------------------------------- + * Function : FindNeighbors + * Description: Find the neighbors on a network interface to forward a BMF + * packet to + * Input : intf - the network interface + * source - the source IP address of the BMF packet + * forwardedBy - the IP address of the node that forwarded the BMF + * packet + * forwardedTo - the IP address of the node to which the BMF packet + * was directed + * Output : neighbors - list of (up to a number of 'FanOutLimit') neighbors. + * bestNeighbor - the best neighbor (in terms of lowest cost or ETX + * value) + * nPossibleNeighbors - number of found possible neighbors + * Data Used : FanOutLimit + * ------------------------------------------------------------------------- */ +//void FindNeighbors( +// struct TBestNeighbors* neighbors, +// struct link_entry** bestNeighbor, +// struct TBmfInterface* intf, +// union olsr_ip_addr* source, +// union olsr_ip_addr* forwardedBy, +// union olsr_ip_addr* forwardedTo, +// int* nPossibleNeighbors) +//{ +// struct link_entry* walker; +// olsr_linkcost previousLinkEtx = LINK_COST_BROKEN; +// olsr_linkcost bestEtx = LINK_COST_BROKEN; +// +// int i; +// +// /* Initialize */ +// *bestNeighbor = NULL; +// for (i = 0; i < MAX_UNICAST_NEIGHBORS; i++) +// { +// neighbors->links[i] = NULL; +// } +// *nPossibleNeighbors = 0; +// +// if (forwardedBy != NULL) +// { +// /* Retrieve the cost of the link from 'forwardedBy' to myself */ +// struct link_entry* bestLinkFromForwarder = get_best_link_to_neighbor(forwardedBy); +// if (bestLinkFromForwarder != NULL) +// { +// previousLinkEtx = bestLinkFromForwarder->linkcost; +// } +// } +// +// OLSR_FOR_ALL_LINK_ENTRIES(walker) { +// struct ipaddr_str buf; +// union olsr_ip_addr* neighborMainIp; +// struct link_entry* bestLinkToNeighbor; +// struct tc_entry* tcLastHop; +// float currEtx; +// +// /* Consider only links from the specified interface */ +// if (! olsr_ipequal(&intf->intAddr, &walker->local_iface_addr)) +// { +// continue; /* for */ +// } +// +// OLSR_PRINTF( +// 9, +// "%s: ----> Considering forwarding pkt on \"%s\" to %s\n", +// PLUGIN_NAME_SHORT, +// intf->ifName, +// olsr_ip_to_string(&buf, &walker->neighbor_iface_addr)); +// +// neighborMainIp = MainAddressOf(&walker->neighbor_iface_addr); +// +// /* Consider only neighbors with an IP address that differs from the +// * passed IP addresses (if passed). Rely on short-circuit boolean evaluation. */ +// if (source != NULL && olsr_ipequal(neighborMainIp, MainAddressOf(source))) +// { +// OLSR_PRINTF( +// 9, +// "%s: ----> Not forwarding to %s: is source of pkt\n", +// PLUGIN_NAME_SHORT, +// olsr_ip_to_string(&buf, &walker->neighbor_iface_addr)); +// +// continue; /* for */ +// } +// +// /* Rely on short-circuit boolean evaluation */ +// if (forwardedBy != NULL && olsr_ipequal(neighborMainIp, MainAddressOf(forwardedBy))) +// { +// OLSR_PRINTF( +// 9, +// "%s: ----> Not forwarding to %s: is the node that forwarded the pkt\n", +// PLUGIN_NAME_SHORT, +// olsr_ip_to_string(&buf, &walker->neighbor_iface_addr)); +// +// continue; /* for */ +// } +// +// /* Rely on short-circuit boolean evaluation */ +// if (forwardedTo != NULL && olsr_ipequal(neighborMainIp, MainAddressOf(forwardedTo))) +// { +// OLSR_PRINTF( +// 9, +// "%s: ----> Not forwarding to %s: is the node to which the pkt was forwarded\n", +// PLUGIN_NAME_SHORT, +// olsr_ip_to_string(&buf, &walker->neighbor_iface_addr)); +// +// continue; /* for */ +// } +// +// /* Found a candidate neighbor to direct our packet to */ +// +// /* Calculate the link quality (ETX) of the link to the found neighbor */ +// currEtx = walker->linkcost; +// +// if (currEtx >= LINK_COST_BROKEN) +// { +// OLSR_PRINTF( +// 9, +// "%s: ----> Not forwarding to %s: link is timing out\n", +// PLUGIN_NAME_SHORT, +// olsr_ip_to_string(&buf, &walker->neighbor_iface_addr)); +// +// continue; /* for */ +// } +// +// /* Compare costs to check if the candidate neighbor is best reached via 'intf' */ +// OLSR_PRINTF( +// 9, +// "%s: ----> Forwarding pkt to %s will cost ETX %5.2f\n", +// PLUGIN_NAME_SHORT, +// olsr_ip_to_string(&buf, &walker->neighbor_iface_addr), +// currEtx); +// +// /* +// * If the candidate neighbor is best reached via another interface, then skip +// * the candidate neighbor; the candidate neighbor has been / will be selected via that +// * other interface. +// */ +// bestLinkToNeighbor = get_best_link_to_neighbor(&walker->neighbor_iface_addr); +// +// if (walker != bestLinkToNeighbor) +// { +// if (bestLinkToNeighbor == NULL) +// { +// OLSR_PRINTF( +// 9, +// "%s: ----> Not forwarding to %s: no link found\n", +// PLUGIN_NAME_SHORT, +// olsr_ip_to_string(&buf, &walker->neighbor_iface_addr)); +// } +// else +// { +//#ifndef NODEBUG +// struct interface* bestIntf = if_ifwithaddr(&bestLinkToNeighbor->local_iface_addr); +// struct lqtextbuffer lqbuffer; +//#endif +// OLSR_PRINTF( +// 9, +// "%s: ----> Not forwarding to %s: \"%s\" gives a better link to this neighbor, costing %s\n", +// PLUGIN_NAME_SHORT, +// olsr_ip_to_string(&buf, &walker->neighbor_iface_addr), +// bestIntf->int_name, +// get_linkcost_text(bestLinkToNeighbor->linkcost, 0, &lqbuffer)); +// } +// +// continue; /* for */ +// } +// +// if (forwardedBy != NULL) +// { +//#ifndef NODEBUG +// struct ipaddr_str forwardedByBuf, niaBuf; +// struct lqtextbuffer lqbuffer; +//#endif +// OLSR_PRINTF( +// 9, +// "%s: ----> 2-hop path from %s via me to %s will cost ETX %s\n", +// PLUGIN_NAME_SHORT, +// olsr_ip_to_string(&forwardedByBuf, forwardedBy), +// olsr_ip_to_string(&niaBuf, &walker->neighbor_iface_addr), +// get_linkcost_text(previousLinkEtx + currEtx, 1, &lqbuffer)); +// } +// +// /* Check the topology table whether the 'forwardedBy' node is itself a direct +// * neighbor of the candidate neighbor, at a lower cost than the 2-hop route +// * via myself. If so, we do not need to forward the BMF packet to the candidate +// * neighbor, because the 'forwardedBy' node will forward the packet. */ +// if (forwardedBy != NULL) +// { +// tcLastHop = olsr_lookup_tc_entry(MainAddressOf(forwardedBy)); +// if (tcLastHop != NULL) +// { +// struct tc_edge_entry* tc_edge; +// +// tc_edge = olsr_lookup_tc_edge(tcLastHop, MainAddressOf(&walker->neighbor_iface_addr)); +// +// /* We are not interested in dead-end edges. */ +// if (tc_edge) { +// olsr_linkcost tcEtx = tc_edge->cost; +// +// if (previousLinkEtx + currEtx > tcEtx) +// { +//#ifndef NODEBUG +// struct ipaddr_str neighbor_iface_buf, forw_buf; +// struct lqtextbuffer lqbuffer; +// olsr_ip_to_string(&neighbor_iface_buf, &walker->neighbor_iface_addr); +//#endif +// OLSR_PRINTF( +// 9, +// "%s: ----> Not forwarding to %s: I am not an MPR between %s and %s, direct link costs %s\n", +// PLUGIN_NAME_SHORT, +// neighbor_iface_buf.buf, +// olsr_ip_to_string(&forw_buf, forwardedBy), +// neighbor_iface_buf.buf, +// get_linkcost_text(tcEtx, 0, &lqbuffer)); +// +// continue; /* for */ +// } /* if */ +// } /* if */ +// } /* if */ +// } /* if */ +// +// /* Remember the best neighbor. If all are very bad, remember none. */ +// if (currEtx < bestEtx) +// { +// *bestNeighbor = walker; +// bestEtx = currEtx; +// } +// +// /* Fill the list with up to 'FanOutLimit' neighbors. If there +// * are more neighbors, broadcast is used instead of unicast. In that +// * case we do not need the list of neighbors. */ +// if (*nPossibleNeighbors < FanOutLimit) +// { +// neighbors->links[*nPossibleNeighbors] = walker; +// } +// +// *nPossibleNeighbors += 1; +// } OLSR_FOR_ALL_LINK_ENTRIES_END(walker); +// +// /* Display the result of the neighbor search */ +// if (*nPossibleNeighbors == 0) +// { +// OLSR_PRINTF( +// 9, +// "%s: ----> No suitable neighbor found to forward to on \"%s\"\n", +// PLUGIN_NAME_SHORT, +// intf->ifName); +// } +// else +// { +// struct ipaddr_str buf; +// OLSR_PRINTF( +// 9, +// "%s: ----> %d neighbors found on \"%s\"; best neighbor to forward to: %s\n", +// PLUGIN_NAME_SHORT, +// *nPossibleNeighbors, +// intf->ifName, +// olsr_ip_to_string(&buf, &(*bestNeighbor)->neighbor_iface_addr)); +// } /* if */ +// +//} /* FindNeighbors */ + +/* ------------------------------------------------------------------------- + * Function : CreateCaptureSocket + * Description: Create socket for promiscuously capturing multicast IP traffic + * Input : ifname - network interface (e.g. "eth0") + * Output : none + * Return : the socket descriptor ( >= 0), or -1 if an error occurred + * Data Used : none + * Notes : The socket is a cooked IP packet socket, bound to the specified + * network interface + * ------------------------------------------------------------------------- */ +static int CreateCaptureSocket(const char* ifName) +{ + int ifIndex = if_nametoindex(ifName); + struct packet_mreq mreq; + struct ifreq req; + struct sockaddr_ll bindTo; + int skfd = 0; + /* Open cooked IP packet socket */ + if (olsr_cnf->ip_version == AF_INET){ + skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); + } + else { + skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6)); + } + if (skfd < 0) + { + BmfPError("socket(PF_PACKET) error"); + return -1; + } + + /* Set interface to promiscuous mode */ + memset(&mreq, 0, sizeof(struct packet_mreq)); + mreq.mr_ifindex = ifIndex; + mreq.mr_type = PACKET_MR_PROMISC; + if (setsockopt(skfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) + { + BmfPError("setsockopt(PACKET_MR_PROMISC) error"); + close(skfd); + return -1; + } + + /* Get hardware (MAC) address */ + memset(&req, 0, sizeof(struct ifreq)); + strncpy(req.ifr_name, ifName, IFNAMSIZ - 1); + req.ifr_name[IFNAMSIZ-1] = '\0'; /* Ensures null termination */ + if (ioctl(skfd, SIOCGIFHWADDR, &req) < 0) + { + BmfPError("error retrieving MAC address"); + close(skfd); + return -1; + } + + /* Bind the socket to the specified interface */ + memset(&bindTo, 0, sizeof(bindTo)); + bindTo.sll_family = AF_PACKET; + if (olsr_cnf->ip_version == AF_INET){ + bindTo.sll_protocol = htons(ETH_P_IP); + } + else{ + bindTo.sll_protocol = htons(ETH_P_IPV6); + } + bindTo.sll_ifindex = ifIndex; + memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN); + bindTo.sll_halen = IFHWADDRLEN; + + if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0) + { + BmfPError("bind() error"); + close(skfd); + return -1; + } + + /* Set socket to blocking operation */ + if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0) + { + BmfPError("fcntl() error"); + close(skfd); + return -1; + } + + AddDescriptorToInputSet(skfd); + add_olsr_socket(skfd,&DoMDNS); + + return skfd; +} /* CreateCaptureSocket */ + +/* ------------------------------------------------------------------------- + * Function : CreateListeningSocket + * Description: Create socket for promiscuously listening to BMF packets. + * Used only when 'BmfMechanism' is BM_UNICAST_PROMISCUOUS + * Input : ifname - network interface (e.g. "eth0") + * Output : none + * Return : the socket descriptor ( >= 0), or -1 if an error occurred + * Data Used : none + * Notes : The socket is a cooked IP packet socket, bound to the specified + * network interface + * ------------------------------------------------------------------------- */ +//static int CreateListeningSocket(const char* ifName) +//{ +// int ifIndex = if_nametoindex(ifName); +// struct packet_mreq mreq; +// struct ifreq req; +// struct sockaddr_ll bindTo; +// +// /* Open cooked IP packet socket */ +// int skfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); +// if (skfd < 0) +// { +// BmfPError("socket(PF_PACKET) error"); +// return -1; +// } +// +// /* Set interface to promiscuous mode */ +// memset(&mreq, 0, sizeof(struct packet_mreq)); +// mreq.mr_ifindex = ifIndex; +// mreq.mr_type = PACKET_MR_PROMISC; +// if (setsockopt(skfd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) +// { +// BmfPError("setsockopt(PACKET_MR_PROMISC) error"); +// close(skfd); +// return -1; +// } +// +// /* Get hardware (MAC) address */ +// memset(&req, 0, sizeof(struct ifreq)); +// strncpy(req.ifr_name, ifName, IFNAMSIZ - 1); +// req.ifr_name[IFNAMSIZ-1] = '\0'; /* Ensures null termination */ +// if (ioctl(skfd, SIOCGIFHWADDR, &req) < 0) +// { +// BmfPError("error retrieving MAC address"); +// close(skfd); +// return -1; +// } +// +// /* Bind the socket to the specified interface */ +// memset(&bindTo, 0, sizeof(bindTo)); +// bindTo.sll_family = AF_PACKET; +// bindTo.sll_protocol = htons(ETH_P_IP); +// bindTo.sll_ifindex = ifIndex; +// memcpy(bindTo.sll_addr, req.ifr_hwaddr.sa_data, IFHWADDRLEN); +// bindTo.sll_halen = IFHWADDRLEN; +// +// if (bind(skfd, (struct sockaddr*)&bindTo, sizeof(bindTo)) < 0) +// { +// BmfPError("bind() error"); +// close(skfd); +// return -1; +// } +// +// /* Set socket to blocking operation */ +// if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0) +// { +// BmfPError("fcntl() error"); +// close(skfd); +// return -1; +// } +// +// AddDescriptorToInputSet(skfd); +// +// return skfd; +//} /* CreateListeningSocket */ + +/* ------------------------------------------------------------------------- + * 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) +// { +// BmfPError("socket(PF_INET) error"); +// return -1; +// } +// +// /* Enable sending to broadcast addresses */ +// if (setsockopt(skfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) +// { +// BmfPError("setsockopt(SO_BROADCAST) error"); +// 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) +// { +// BmfPError("setsockopt(SO_BINDTODEVICE) error"); +// close(skfd); +// return -1; +// } +// +// /* Bind to BMF 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) +// { +// BmfPError("bind() error"); +// close(skfd); +// return -1; +// } +// +// /* Set socket to blocking operation */ +// if (fcntl(skfd, F_SETFL, fcntl(skfd, F_GETFL, 0) & ~O_NONBLOCK) < 0) +// { +// BmfPError("fcntl() error"); +// close(skfd); +// return -1; +// } +// +// AddDescriptorToInputSet(skfd); +// +// return skfd; +//} /* CreateEncapsulateSocket */ + +/* ------------------------------------------------------------------------- + * Function : CreateLocalEtherTunTap + * Description: Creates and brings up an EtherTunTap interface + * Input : none + * Output : none + * Return : the socket file descriptor (>= 0), or -1 in case of failure + * Data Used : EtherTunTapIfName - name used for the tuntap interface (e.g. + * "bmf0") + * EtherTunTapIp + * EtherTunTapIpMask + * EtherTunTapIpBroadcast + * BmfInterfaces + * Note : Order dependency: call this function only if BmfInterfaces + * is filled with a list of network interfaces. + * ------------------------------------------------------------------------- */ +//static int CreateLocalEtherTunTap(void) +//{ +// static const char deviceName[] = "/dev/net/tun"; +// struct ifreq ifreq; +// int etfd; +// int ioctlSkfd; +// int ioctlres; +// +// etfd = open(deviceName, O_RDWR | O_NONBLOCK); +// if (etfd < 0) +// { +// BmfPError("error opening %s", deviceName); +// return -1; +// } +// +// memset(&ifreq, 0, sizeof(ifreq)); +// strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1); +// ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */ +// +// /* Specify the IFF_TUN flag for IP packets. +// * Specify IFF_NO_PI for not receiving extra meta packet information. */ +// ifreq.ifr_flags = IFF_TUN; +// ifreq.ifr_flags |= IFF_NO_PI; +// +// if (ioctl(etfd, TUNSETIFF, (void *)&ifreq) < 0) +// { +// BmfPError("ioctl(TUNSETIFF) error on %s", deviceName); +// close(etfd); +// return -1; +// } +// +// memset(&ifreq, 0, sizeof(ifreq)); +// strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1); +// ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */ +// ifreq.ifr_addr.sa_family = AF_INET; +// +// ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0); +// if (ioctlSkfd < 0) +// { +// BmfPError("socket(PF_INET) error on %s", deviceName); +// close(etfd); +// return -1; +// } +// +// /* Give the EtherTunTap interface an IP address. +// * The default IP address is the address of the first OLSR interface; +// * the default netmask is 255.255.255.255 . Having an all-ones netmask prevents +// * automatic entry of the BMF network interface in the routing table. */ +// if (EtherTunTapIp == ETHERTUNTAPIPNOTSET) +// { +// struct TBmfInterface* nextBmfIf = BmfInterfaces; +// while (nextBmfIf != NULL) +// { +// struct TBmfInterface* bmfIf = nextBmfIf; +// nextBmfIf = bmfIf->next; +// +// if (bmfIf->olsrIntf != NULL) +// { +// EtherTunTapIp = ntohl(bmfIf->intAddr.v4.s_addr); +// EtherTunTapIpBroadcast = EtherTunTapIp; +// } +// } +// } +// +// if (EtherTunTapIp == ETHERTUNTAPIPNOTSET) +// { +// /* No IP address configured for BMF network interface, and no OLSR interface found to +// * copy IP address from. Fall back to default: 10.255.255.253 . */ +// EtherTunTapIp = ETHERTUNTAPDEFAULTIP; +// } +// +// ((struct sockaddr_in*)&ifreq.ifr_addr)->sin_addr.s_addr = htonl(EtherTunTapIp); +// ioctlres = ioctl(ioctlSkfd, SIOCSIFADDR, &ifreq); +// if (ioctlres >= 0) +// { +// /* Set net mask */ +// ((struct sockaddr_in*)&ifreq.ifr_netmask)->sin_addr.s_addr = htonl(EtherTunTapIpMask); +// ioctlres = ioctl(ioctlSkfd, SIOCSIFNETMASK, &ifreq); +// if (ioctlres >= 0) +// { +// /* Set broadcast IP */ +// ((struct sockaddr_in*)&ifreq.ifr_broadaddr)->sin_addr.s_addr = htonl(EtherTunTapIpBroadcast); +// ioctlres = ioctl(ioctlSkfd, SIOCSIFBRDADDR, &ifreq); +// if (ioctlres >= 0) +// { +// /* Bring EtherTunTap interface up (if not already) */ +// ioctlres = ioctl(ioctlSkfd, SIOCGIFFLAGS, &ifreq); +// if (ioctlres >= 0) +// { +// ifreq.ifr_flags |= (IFF_UP | IFF_RUNNING | IFF_BROADCAST); +// ioctlres = ioctl(ioctlSkfd, SIOCSIFFLAGS, &ifreq); +// } +// } +// } +// } +// +// if (ioctlres < 0) +// { +// /* Any of the above ioctl() calls failed */ +// BmfPError("error bringing up EtherTunTap interface \"%s\"", EtherTunTapIfName); +// +// close(etfd); +// close(ioctlSkfd); +// return -1; +// } /* if (ioctlres < 0) */ +// +// /* Set the multicast flag on the interface */ +// memset(&ifreq, 0, sizeof(ifreq)); +// strncpy(ifreq.ifr_name, EtherTunTapIfName, IFNAMSIZ - 1); +// ifreq.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */ +// +// ioctlres = ioctl(ioctlSkfd, SIOCGIFFLAGS, &ifreq); +// if (ioctlres >= 0) +// { +// ifreq.ifr_flags |= IFF_MULTICAST; +// ioctlres = ioctl(ioctlSkfd, SIOCSIFFLAGS, &ifreq); +// } +// if (ioctlres < 0) +// { +// /* Any of the two above ioctl() calls failed */ +// BmfPError("error setting multicast flag on EtherTunTap interface \"%s\"", EtherTunTapIfName); +// +// /* Continue anyway */ +// } +// +// /* Use ioctl to make the tuntap persistent. Otherwise it will disappear +// * when this program exits. That is not desirable, since a multicast +// * daemon (e.g. mrouted) may be using the tuntap interface. */ +// if (ioctl(etfd, TUNSETPERSIST, (void *)&ifreq) < 0) +// { +// BmfPError("error making EtherTunTap interface \"%s\" persistent", EtherTunTapIfName); +// +// /* Continue anyway */ +// } +// +// OLSR_PRINTF(8, "%s: opened 1 socket on \"%s\"\n", PLUGIN_NAME_SHORT, EtherTunTapIfName); +// +// AddDescriptorToInputSet(etfd); +// +// /* If the user configured a specific IP address for the BMF network interface, +// * help the user and advertise the IP address of the BMF network interface +// * on the OLSR network via HNA */ +// if (TunTapIpOverruled != 0) +// { +// union olsr_ip_addr temp_net; +// +// temp_net.v4.s_addr = htonl(EtherTunTapIp); +// ip_prefix_list_add(&olsr_cnf->hna_entries, &temp_net, 32); +// } +// +// close(ioctlSkfd); +// +// return etfd; +//} /* CreateLocalEtherTunTap */ + +/* ------------------------------------------------------------------------- + * 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") + * : olsrIntf - OLSR interface object of the network interface, or + * NULL if the network interface is not OLSR-enabled + * Output : none + * Return : the number of opened sockets + * Data Used : BmfInterfaces, LastBmfInterface + * ------------------------------------------------------------------------- */ + +//FOR MDNS IS ALWAYS CALLED WITH NULL AS SECOND ARG + +static int CreateInterface( + const char* ifName, + struct interface* olsrIntf) +{ + int capturingSkfd = -1; + int encapsulatingSkfd = -1; + int listeningSkfd = -1; + int ioctlSkfd; + struct ifreq ifr; + int nOpened = 0; + struct TBmfInterface* newIf = malloc(sizeof(struct TBmfInterface)); + + assert(ifName != NULL); + + if (newIf == NULL) + { + return 0; + } + +//TODO: assert interface is not talking OLSR + +// if (olsrIntf != NULL) +// { +// /* On OLSR-enabled interfaces, create socket for encapsulating and forwarding +// * multicast packets */ +// encapsulatingSkfd = CreateEncapsulateSocket(ifName); +// if (encapsulatingSkfd < 0) +// { +// free(newIf); +// return 0; +// } +// nOpened++; +// } + + /* Create socket for capturing and sending of multicast packets on + * non-OLSR interfaces, and on OLSR-interfaces if configured. */ + if ((olsrIntf == NULL) || (CapturePacketsOnOlsrInterfaces != 0)) + { + capturingSkfd = CreateCaptureSocket(ifName); + if (capturingSkfd < 0) + { + close(encapsulatingSkfd); + free(newIf); + return 0; + } + + nOpened++; + } + +// /* Create promiscuous mode listening interface if BMF uses IP unicast +// * as underlying forwarding mechanism */ +// if (BmfMechanism == BM_UNICAST_PROMISCUOUS) +// { +// listeningSkfd = CreateListeningSocket(ifName); +// if (listeningSkfd < 0) +// { +// close(listeningSkfd); +// close(encapsulatingSkfd); /* no problem if 'encapsulatingSkfd' is -1 */ +// free(newIf); +// return 0; +// } +// +// nOpened++; +// } + + /* For ioctl operations on the network interface, use either capturingSkfd + * or encapsulatingSkfd, whichever is available */ + ioctlSkfd = (capturingSkfd >= 0) ? capturingSkfd : encapsulatingSkfd; + + /* Retrieve the MAC address of the interface. */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1); + ifr.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */ + if (ioctl(ioctlSkfd, SIOCGIFHWADDR, &ifr) < 0) + { + BmfPError("ioctl(SIOCGIFHWADDR) error for interface \"%s\"", ifName); + close(capturingSkfd); + close(encapsulatingSkfd); + free(newIf); + return 0; + } + + /* Copy data into TBmfInterface object */ + newIf->capturingSkfd = capturingSkfd; + newIf->encapsulatingSkfd = encapsulatingSkfd; + newIf->listeningSkfd = listeningSkfd; + memcpy(newIf->macAddr, ifr.ifr_hwaddr.sa_data, IFHWADDRLEN); + memcpy(newIf->ifName, ifName, IFNAMSIZ); + newIf->olsrIntf = olsrIntf; + if (olsrIntf != NULL) + { + /* For an OLSR-interface, copy the interface address and broadcast + * address from the OLSR interface object. Downcast to correct sockaddr + * subtype. */ + newIf->intAddr.v4 = olsrIntf->int_addr.sin_addr; + newIf->broadAddr.v4 = olsrIntf->int_broadaddr.sin_addr; + } + else + { + /* For a non-OLSR interface, retrieve the IP address ourselves */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1); + ifr.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */ + if (ioctl(ioctlSkfd, SIOCGIFADDR, &ifr) < 0) + { + BmfPError("ioctl(SIOCGIFADDR) error for interface \"%s\"", ifName); + + newIf->intAddr.v4.s_addr = inet_addr("0.0.0.0"); + } + else + { + /* Downcast to correct sockaddr subtype */ + newIf->intAddr.v4 = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; + } + + /* For a non-OLSR interface, retrieve the IP broadcast address ourselves */ + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_name, ifName, IFNAMSIZ - 1); + ifr.ifr_name[IFNAMSIZ - 1] = '\0'; /* Ensures null termination */ + if (ioctl(ioctlSkfd, SIOCGIFBRDADDR, &ifr) < 0) + { + BmfPError("ioctl(SIOCGIFBRDADDR) error for interface \"%s\"", ifName); + + newIf->broadAddr.v4.s_addr = inet_addr("0.0.0.0"); + } + else + { + /* Downcast to correct sockaddr subtype */ + newIf->broadAddr.v4 = ((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr; + } + } + + /* Initialize fragment history table */ + //memset(&newIf->fragmentHistory, 0, sizeof(newIf->fragmentHistory)); + //newIf->nextFragmentHistoryEntry = 0; + + /* Reset counters */ + //newIf->nBmfPacketsRx = 0; + //newIf->nBmfPacketsRxDup = 0; + //newIf->nBmfPacketsTx = 0; + + /* Add new TBmfInterface object to global list. OLSR interfaces are + * added at the front of the list, non-OLSR interfaces at the back. */ + if (BmfInterfaces == NULL) + { + /* First TBmfInterface object in list */ + BmfInterfaces = newIf; + LastBmfInterface = newIf; + } + else if (olsrIntf != NULL) + { + /* Add new TBmfInterface object at front of list */ + newIf->next = BmfInterfaces; + BmfInterfaces = newIf; + } + else + { + /* Add new TBmfInterface object at back of list */ + newIf->next = NULL; + LastBmfInterface->next= newIf; + LastBmfInterface = newIf; + } + + OLSR_PRINTF( + 8, + "%s: opened %d socket%s on %s interface \"%s\"\n", + PLUGIN_NAME_SHORT, + nOpened, + nOpened == 1 ? "" : "s", + olsrIntf != NULL ? "OLSR" : "non-OLSR", + ifName); + + return nOpened; +} /* CreateInterface */ + +/* ------------------------------------------------------------------------- + * Function : 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 : fail (-1) or success (0) + * Data Used : none + * ------------------------------------------------------------------------- */ +int CreateBmfNetworkInterfaces(struct interface* skipThisIntf) +{ + int skfd; + struct ifconf ifc; + int numreqs = 30; + struct ifreq* ifr; + int n; + int nOpenedSockets = 0; + + /* Clear input descriptor set */ + FD_ZERO(&InputSet); + + skfd = socket(PF_INET, SOCK_DGRAM, 0); + if (skfd < 0) + { + BmfPError("no inet socket available to retrieve interface list"); + return -1; + } + + /* Retrieve the network interface configuration list */ + ifc.ifc_buf = NULL; + for (;;) + { + ifc.ifc_len = sizeof(struct ifreq) * numreqs; + ifc.ifc_buf = realloc(ifc.ifc_buf, ifc.ifc_len); + + if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) + { + BmfPError("ioctl(SIOCGIFCONF) error"); + + close(skfd); + free(ifc.ifc_buf); + return -1; + } + if ((unsigned)ifc.ifc_len == sizeof(struct ifreq) * numreqs) + { + /* Assume it overflowed; double the space and try again */ + numreqs *= 2; + assert(numreqs < 1024); + continue; /* for (;;) */ + } + break; /* for (;;) */ + } /* for (;;) */ + + close(skfd); + + /* For each item in the interface configuration list... */ + ifr = ifc.ifc_req; + for (n = ifc.ifc_len / sizeof(struct ifreq); --n >= 0; ifr++) + { + struct interface* olsrIntf; + union olsr_ip_addr ipAddr; + + /* Skip the BMF network interface itself */ + //if (strncmp(ifr->ifr_name, EtherTunTapIfName, IFNAMSIZ) == 0) + //{ + // continue; /* for (n = ...) */ + //} + + /* ...find the OLSR interface structure, if any */ + ipAddr.v4 = ((struct sockaddr_in*)&ifr->ifr_addr)->sin_addr; + olsrIntf = if_ifwithaddr(&ipAddr); + + if (skipThisIntf != NULL && olsrIntf == skipThisIntf) + { + continue; /* for (n = ...) */ + } + + if (olsrIntf == NULL && ! 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 = ...) */ + } + + if (! IsNonOlsrBmfIf(ifr->ifr_name)) + { + //If the interface is not specified in the configuration file then go ahead + continue; /* for (n = ...) */ + } + //TODO: asser if->ifr_name is not talking OLSR + //nOpenedSockets += CreateInterface(ifr->ifr_name, olsrIntf); + nOpenedSockets += CreateInterface(ifr->ifr_name, NULL); + + } /* for (n = ...) */ + + free(ifc.ifc_buf); + + /* Create the BMF network interface */ + //EtherTunTapFd = CreateLocalEtherTunTap(); + //if (EtherTunTapFd >= 0) + //{ + // nOpenedSockets++; + //} + + if (BmfInterfaces == NULL) + { + OLSR_PRINTF(1, "%s: could not initialize any network interface\n", PLUGIN_NAME); + } + else + { + OLSR_PRINTF(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpenedSockets); + } + return 0; +} /* CreateBmfNetworkInterfaces */ + +/* ------------------------------------------------------------------------- + * Function : AddInterface + * Description: Add an OLSR-enabled network interface to the list of BMF-enabled + * network interfaces + * Input : newIntf - network interface to add + * Output : none + * Return : none + * Data Used : none + * ------------------------------------------------------------------------- */ +void AddInterface(struct interface* newIntf) +{ + int nOpened; + + assert(newIntf != NULL); + + nOpened = CreateInterface(newIntf->int_name, newIntf); + + OLSR_PRINTF(1, "%s: opened %d sockets\n", PLUGIN_NAME, nOpened); +} /* AddInterface */ + +/* ------------------------------------------------------------------------- + * Function : CloseBmfNetworkInterfaces + * Description: Closes every socket on each network interface used by BMF + * Input : none + * Output : none + * Return : none + * Data Used : none + * Notes : Closes + * - the local EtherTunTap interface (e.g. "tun0" or "tap0") + * - for each BMF-enabled interface, the socket used for + * capturing multicast packets + * - for each OLSR-enabled interface, the socket used for + * encapsulating packets + * Also restores the network state to the situation before BMF + * was started. + * ------------------------------------------------------------------------- */ +void CloseBmfNetworkInterfaces(void) +{ + int nClosed = 0; + u_int32_t totalOlsrBmfPacketsRx = 0; + u_int32_t totalOlsrBmfPacketsRxDup = 0; + u_int32_t totalOlsrBmfPacketsTx = 0; + u_int32_t totalNonOlsrBmfPacketsRx = 0; + u_int32_t totalNonOlsrBmfPacketsRxDup = 0; + u_int32_t totalNonOlsrBmfPacketsTx = 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( + 7, + "%s: %s interface \"%s\": RX pkts %u (%u dups); TX pkts %u\n", + PLUGIN_NAME_SHORT, + bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR", + bmfIf->ifName, + bmfIf->nBmfPacketsRx, + bmfIf->nBmfPacketsRxDup, + bmfIf->nBmfPacketsTx); + + OLSR_PRINTF( + 1, + "%s: closed %s interface \"%s\"\n", + PLUGIN_NAME_SHORT, + bmfIf->olsrIntf != NULL ? "OLSR" : "non-OLSR", + bmfIf->ifName); + + /* Add totals */ + if (bmfIf->olsrIntf != NULL) + { + totalOlsrBmfPacketsRx += bmfIf->nBmfPacketsRx; + totalOlsrBmfPacketsRxDup += bmfIf->nBmfPacketsRxDup; + totalOlsrBmfPacketsTx += bmfIf->nBmfPacketsTx; + } + else + { + totalNonOlsrBmfPacketsRx += bmfIf->nBmfPacketsRx; + totalNonOlsrBmfPacketsRxDup += bmfIf->nBmfPacketsRxDup; + totalNonOlsrBmfPacketsTx += bmfIf->nBmfPacketsTx; + } + + free(bmfIf); + } /* while */ + + if (EtherTunTapFd >= 0) + { + close(EtherTunTapFd); + nClosed++; + + OLSR_PRINTF(7, "%s: closed \"%s\"\n", PLUGIN_NAME_SHORT, EtherTunTapIfName); + } + + BmfInterfaces = NULL; + + OLSR_PRINTF(1, "%s: closed %d sockets\n", PLUGIN_NAME_SHORT, nClosed); + + OLSR_PRINTF( + 7, + "%s: Total all OLSR interfaces : RX pkts %u (%u dups); TX pkts %u\n", + PLUGIN_NAME_SHORT, + totalOlsrBmfPacketsRx, + totalOlsrBmfPacketsRxDup, + totalOlsrBmfPacketsTx); + OLSR_PRINTF( + 7, + "%s: Total all non-OLSR interfaces: RX pkts %u (%u dups); TX pkts %u\n", + PLUGIN_NAME_SHORT, + totalNonOlsrBmfPacketsRx, + totalNonOlsrBmfPacketsRxDup, + totalNonOlsrBmfPacketsTx); +} /* CloseBmfNetworkInterfaces */ + +#define MAX_NON_OLSR_IFS 32 +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") + * data - not used + * addon - not used + * Output : none + * Return : success (0) or fail (1) + * Data Used : NonOlsrIfNames + * ------------------------------------------------------------------------- */ +int AddNonOlsrBmfIf( + const char* ifName, + void* data __attribute__((unused)), + set_plugin_parameter_addon addon __attribute__((unused))) +{ + assert(ifName != NULL); + + if (nNonOlsrIfs >= MAX_NON_OLSR_IFS) + { + OLSR_PRINTF( + 1, + "%s: too many non-OLSR interfaces specified, maximum is %d\n", + PLUGIN_NAME, + MAX_NON_OLSR_IFS); + return 1; + } + + strncpy(NonOlsrIfNames[nNonOlsrIfs], ifName, IFNAMSIZ - 1); + NonOlsrIfNames[nNonOlsrIfs][IFNAMSIZ - 1] = '\0'; /* Ensures null termination */ + nNonOlsrIfs++; + return 0; +} /* AddNonOlsrBmfIf */ + +/* ------------------------------------------------------------------------- + * 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 : NonOlsrIfNames + * ------------------------------------------------------------------------- */ +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; +} /* IsNonOlsrBmfIf */ + +/* ------------------------------------------------------------------------- + * Function : CheckAndUpdateLocalBroadcast + * Description: For an IP packet, check if the destination address is not a + * multicast address. If it is not, the packet is assumed to be + * a local broadcast packet. In that case, set the destination + * address of the IP packet to the passed broadcast address. + * Input : ipPacket - the IP packet + * broadAddr - the broadcast address to fill in + * Output : none + * Return : none + * Data Used : none + * Notes : See also RFC1141 + * ------------------------------------------------------------------------- */ +void CheckAndUpdateLocalBroadcast(unsigned char* ipPacket, union olsr_ip_addr* broadAddr) +{ + struct iphdr* iph; + union olsr_ip_addr destIp; + + assert(ipPacket != NULL && broadAddr != NULL); + + iph = (struct iphdr*) ipPacket; + destIp.v4.s_addr = iph->daddr; + if (! IsMulticast(&destIp)) + { + u_int32_t origDaddr, newDaddr; + u_int32_t check; + + origDaddr = ntohl(iph->daddr); + + iph->daddr = broadAddr->v4.s_addr; + newDaddr = ntohl(iph->daddr); + + /* Re-calculate IP header checksum for new destination */ + check = ntohs(iph->check); + + check = ~ (~ check - ((origDaddr >> 16) & 0xFFFF) + ((newDaddr >> 16) & 0xFFFF)); + check = ~ (~ check - (origDaddr & 0xFFFF) + (newDaddr & 0xFFFF)); + + /* Add carry */ + check = check + (check >> 16); + + iph->check = htons(check); + + if (iph->protocol == SOL_UDP) + { + /* Re-calculate UDP/IP checksum for new destination */ + + int ipHeaderLen = GetIpHeaderLength(ipPacket); + struct udphdr* udph = (struct udphdr*) (ipPacket + ipHeaderLen); + + /* RFC 1624, Eq. 3: HC' = ~(~HC - m + m') */ + + check = ntohs(udph->check); + + check = ~ (~ check - ((origDaddr >> 16) & 0xFFFF) + ((newDaddr >> 16) & 0xFFFF)); + check = ~ (~ check - (origDaddr & 0xFFFF) + (newDaddr & 0xFFFF)); + + /* Add carry */ + check = check + (check >> 16); + + udph->check = htons(check); + } /* if */ + } /* if */ +} /* CheckAndUpdateLocalBroadcast */ + +/* ------------------------------------------------------------------------- + * Function : AddMulticastRoute + * Description: Insert a route to all multicast addresses in the kernel + * routing table. The route will be via the BMF network interface. + * Input : none + * Output : none + * Return : none + * Data Used : none + * ------------------------------------------------------------------------- */ +void AddMulticastRoute(void) +{ + struct rtentry kernel_route; + int ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0); + if (ioctlSkfd < 0) + { + BmfPError("socket(PF_INET) error"); + return; + } + + memset(&kernel_route, 0, sizeof(struct rtentry)); + + ((struct sockaddr_in*)&kernel_route.rt_dst)->sin_family = AF_INET; + ((struct sockaddr_in*)&kernel_route.rt_gateway)->sin_family = AF_INET; + ((struct sockaddr_in*)&kernel_route.rt_genmask)->sin_family = AF_INET; + + /* 224.0.0.0/4 */ + ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = htonl(0xE0000000); + ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = htonl(0xF0000000); + + kernel_route.rt_metric = 0; + kernel_route.rt_flags = RTF_UP; + + kernel_route.rt_dev = EtherTunTapIfName; + + if (ioctl(ioctlSkfd, SIOCADDRT, &kernel_route) < 0) + { + BmfPError("error setting multicast route via EtherTunTap interface \"%s\"", EtherTunTapIfName); + + /* Continue anyway */ + } + close(ioctlSkfd); +} /* AddMulticastRoute */ + +/* ------------------------------------------------------------------------- + * Function : DeleteMulticastRoute + * Description: Delete the route to all multicast addresses from the kernel + * routing table + * Input : none + * Output : none + * Return : none + * Data Used : none + * ------------------------------------------------------------------------- */ +void DeleteMulticastRoute(void) +{ + if (EtherTunTapIp != ETHERTUNTAPDEFAULTIP) + { + struct rtentry kernel_route; + int ioctlSkfd = socket(PF_INET, SOCK_DGRAM, 0); + if (ioctlSkfd < 0) + { + BmfPError("socket(PF_INET) error"); + return; + } + + memset(&kernel_route, 0, sizeof(struct rtentry)); + + ((struct sockaddr_in*)&kernel_route.rt_dst)->sin_family = AF_INET; + ((struct sockaddr_in*)&kernel_route.rt_gateway)->sin_family = AF_INET; + ((struct sockaddr_in*)&kernel_route.rt_genmask)->sin_family = AF_INET; + + /* 224.0.0.0/4 */ + ((struct sockaddr_in *)&kernel_route.rt_dst)->sin_addr.s_addr = htonl(0xE0000000); + ((struct sockaddr_in *)&kernel_route.rt_genmask)->sin_addr.s_addr = htonl(0xF0000000); + + kernel_route.rt_metric = 0; + kernel_route.rt_flags = RTF_UP; + + kernel_route.rt_dev = EtherTunTapIfName; + + if (ioctl(ioctlSkfd, SIOCDELRT, &kernel_route) < 0) + { + BmfPError("error deleting multicast route via EtherTunTap interface \"%s\"", EtherTunTapIfName); + + /* Continue anyway */ + } + close(ioctlSkfd); + } /* if */ +} /* DeleteMulticastRoute */ + +/* + * Local Variables: + * c-basic-offset: 2 + * indent-tabs-mode: nil + * End: + */ --- /dev/null +++ b/lib/mdns/src/NetworkInterfaces.h @@ -0,0 +1,162 @@ +#ifndef _BMF_NETWORKINTERFACES_H +#define _BMF_NETWORKINTERFACES_H + +/* + * OLSR Basic Multicast Forwarding (BMF) plugin. + * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands. + * Written by Erik Tromp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Thales, BMF nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* ------------------------------------------------------------------------- + * File : NetworkInterfaces.h + * Description: Functions to open and close sockets + * Created : 29 Jun 2006 + * + * ------------------------------------------------------------------------- */ + +/* System includes */ +#include /* struct in_addr */ + +/* OLSR includes */ +#include "olsr_types.h" /* olsr_ip_addr */ +#include "olsrd_plugin.h" /* union set_plugin_parameter_addon */ +#include "socket_parser.h" +/* Plugin includes */ +#include "Packet.h" /* IFHWADDRLEN */ +#include "mdns.h" +/* Size of buffer in which packets are received */ +#define BMF_BUFFER_SIZE 2048 + +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; + + /* File descriptor of UDP packet socket, used for listening to encapsulation packets. + * Used only when PlParam "BmfMechanism" is set to "UnicastPromiscuous". */ + int listeningSkfd; + + unsigned char macAddr[IFHWADDRLEN]; + + char ifName[IFNAMSIZ]; + + /* OLSRs idea of this network interface. NULL if this interface is not + * OLSR-enabled. */ + struct interface* olsrIntf; + + /* IP address of this network interface */ + union olsr_ip_addr intAddr; + + /* Broadcast address of this network interface */ + union olsr_ip_addr broadAddr; + + #define FRAGMENT_HISTORY_SIZE 10 + struct TFragmentHistory + { + u_int16_t ipId; + u_int8_t ipProto; + struct in_addr ipSrc; + struct in_addr ipDst; + } fragmentHistory [FRAGMENT_HISTORY_SIZE]; + + int nextFragmentHistoryEntry; + + /* Number of received and transmitted BMF packets on this interface */ + u_int32_t nBmfPacketsRx; + u_int32_t nBmfPacketsRxDup; + u_int32_t nBmfPacketsTx; + + /* Next element in list */ + struct TBmfInterface* next; +}; + +extern struct TBmfInterface* BmfInterfaces; + +extern int HighestSkfd; +extern fd_set InputSet; + +extern int EtherTunTapFd; + +extern char EtherTunTapIfName[]; + +/* 10.255.255.253 in host byte order */ +#define ETHERTUNTAPDEFAULTIP 0x0AFFFFFD + +extern u_int32_t EtherTunTapIp; +extern u_int32_t EtherTunTapIpMask; +extern u_int32_t EtherTunTapIpBroadcast; + +extern int CapturePacketsOnOlsrInterfaces; + +enum TBmfMechanism { BM_BROADCAST = 0, BM_UNICAST_PROMISCUOUS }; +extern enum TBmfMechanism BmfMechanism; + +int SetBmfInterfaceName(const char* ifname, void* data, set_plugin_parameter_addon addon); +int SetBmfInterfaceIp(const char* ip, void* data, set_plugin_parameter_addon addon); +int SetCapturePacketsOnOlsrInterfaces(const char* enable, void* data, set_plugin_parameter_addon addon); +int SetBmfMechanism(const char* mechanism, void* data, set_plugin_parameter_addon addon); +int DeactivateSpoofFilter(void); +void RestoreSpoofFilter(void); + +#define MAX_UNICAST_NEIGHBORS 10 +struct TBestNeighbors +{ + struct link_entry* links[MAX_UNICAST_NEIGHBORS]; +}; + +void FindNeighbors( + struct TBestNeighbors* neighbors, + struct link_entry** bestNeighbor, + struct TBmfInterface* intf, + union olsr_ip_addr* source, + union olsr_ip_addr* forwardedBy, + union olsr_ip_addr* forwardedTo, + int* nPossibleNeighbors); + +int CreateBmfNetworkInterfaces(struct interface* skipThisIntf); +void AddInterface(struct interface* newIntf); +void CloseBmfNetworkInterfaces(void); +int AddNonOlsrBmfIf(const char* ifName, void* data, set_plugin_parameter_addon addon); +int IsNonOlsrBmfIf(const char* ifName); +void CheckAndUpdateLocalBroadcast(unsigned char* ipPacket, union olsr_ip_addr* broadAddr); +void AddMulticastRoute(void); +void DeleteMulticastRoute(void); + +#endif /* _BMF_NETWORKINTERFACES_H */ + +/* + * Local Variables: + * c-basic-offset: 2 + * indent-tabs-mode: nil + * End: + */ --- /dev/null +++ b/lib/mdns/src/Packet.c @@ -0,0 +1,238 @@ +/* + * OLSR Basic Multicast Forwarding (BMF) plugin. + * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands. + * Written by Erik Tromp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Thales, BMF nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* ------------------------------------------------------------------------- + * File : Packet.c + * Description: IP packet and Ethernet frame processing functions + * Created : 29 Jun 2006 + * + * ------------------------------------------------------------------------- */ + +#include "Packet.h" + +/* System includes */ +#include /* NULL */ +#include /* assert() */ +#include /* memcpy() */ +#include /* u_int8_t, u_int16_t, u_int32_t */ +#include /* ntohs(), htons() */ +#include /* struct iphdr */ + +/* ------------------------------------------------------------------------- + * Function : IsIpFragment + * Description: Check if an IP packet is an IP fragment + * Input : ipPacket - the IP packet + * Output : none + * Return : true (1) or false (0) + * Data Used : none + * ------------------------------------------------------------------------- */ +int IsIpFragment(unsigned char* ipPacket) +{ + struct ip* iph; + + assert(ipPacket != NULL); + + iph = (struct ip*) ipPacket; + if ((ntohs(iph->ip_off) & IP_OFFMASK) != 0) + { + return 1; + } + return 0; +} /* IsIpFragment */ + +/* ------------------------------------------------------------------------- + * Function : GetIpTotalLength + * Description: Retrieve the total length of the IP packet (in bytes) of + * an IP packet + * Input : ipPacket - the IP packet + * Output : none + * Return : IP packet length + * Data Used : none + * ------------------------------------------------------------------------- */ +u_int16_t GetIpTotalLength(unsigned char* ipPacket) +{ + struct iphdr* iph; + + assert(ipPacket != NULL); + + iph = (struct iphdr*) ipPacket; + return ntohs(iph->tot_len); +} /* GetIpTotalLength */ + +/* ------------------------------------------------------------------------- + * Function : GetIpHeaderLength + * Description: Retrieve the IP header length (in bytes) of an IP packet + * Input : ipPacket - the IP packet + * Output : none + * Return : IP header length + * Data Used : none + * ------------------------------------------------------------------------- */ +unsigned int GetIpHeaderLength(unsigned char* ipPacket) +{ + struct iphdr* iph; + + assert(ipPacket != NULL); + + iph = (struct iphdr*) ipPacket; + return iph->ihl << 2; +} /* GetIpHeaderLength */ + +/* ------------------------------------------------------------------------- + * Function : GetTtl + * Description: Retrieve the TTL (Time To Live) value from the IP header of + * an IP packet + * Input : ipPacket - the IP packet + * Output : none + * Return : TTL value + * Data Used : none + * ------------------------------------------------------------------------- */ +u_int8_t GetTtl(unsigned char* ipPacket) +{ + struct iphdr* iph; + + assert(ipPacket != NULL); + + iph = (struct iphdr*) ipPacket; + return iph->ttl; +} /* GetTtl */ + +/* ------------------------------------------------------------------------- + * Function : SaveTtlAndChecksum + * Description: Save the TTL (Time To Live) value and IP checksum as found in + * the IP header of an IP packet + * Input : ipPacket - the IP packet + * Output : sttl - the TTL and checksum values + * Return : none + * Data Used : none + * ------------------------------------------------------------------------- */ +void SaveTtlAndChecksum(unsigned char* ipPacket, struct TSaveTtl* sttl) +{ + struct iphdr* iph; + + assert(ipPacket != NULL && sttl != NULL); + + iph = (struct iphdr*) ipPacket; + sttl->ttl = iph->ttl; + sttl->check = ntohs(iph->check); +} /* SaveTtlAndChecksum */ + +/* ------------------------------------------------------------------------- + * Function : RestoreTtlAndChecksum + * Description: Restore the TTL (Time To Live) value and IP checksum in + * the IP header of an IP packet + * Input : ipPacket - the IP packet + * sttl - the TTL and checksum values + * Output : none + * Return : none + * Data Used : none + * ------------------------------------------------------------------------- */ +void RestoreTtlAndChecksum(unsigned char* ipPacket, struct TSaveTtl* sttl) +{ + struct iphdr* iph; + + assert(ipPacket != NULL && sttl != NULL); + + iph = (struct iphdr*) ipPacket; + iph->ttl = sttl->ttl; + iph->check = htons(sttl->check); +} /* RestoreTtlAndChecksum */ + +/* ------------------------------------------------------------------------- + * Function : DecreaseTtlAndUpdateHeaderChecksum + * Description: For an IP packet, decrement the TTL value and update the IP header + * checksum accordingly. + * Input : ipPacket - the IP packet + * Output : none + * Return : none + * Data Used : none + * Notes : See also RFC1141 + * ------------------------------------------------------------------------- */ +void DecreaseTtlAndUpdateHeaderChecksum(unsigned char* ipPacket) +{ + struct iphdr* iph; + u_int32_t sum; + + assert(ipPacket != NULL); + + iph = (struct iphdr*) ipPacket; + + iph->ttl--; /* decrement ttl */ + sum = ntohs(iph->check) + 0x100; /* increment checksum high byte */ + iph->check = htons(sum + (sum>>16)); /* add carry */ +} /* DecreaseTtlAndUpdateHeaderChecksum */ + +/* ------------------------------------------------------------------------- + * Function : GetIpHeader + * Description: Retrieve the IP header from BMF encapsulation UDP data + * Input : encapsulationUdpData - the encapsulation UDP data + * Output : none + * Return : IP header + * Data Used : none + * ------------------------------------------------------------------------- */ +struct ip* GetIpHeader(unsigned char* encapsulationUdpData) +{ + return (struct ip*)(encapsulationUdpData + ENCAP_HDR_LEN); +} /* GetIpHeader */ + +/* ------------------------------------------------------------------------- + * Function : GetIpPacket + * Description: Retrieve the IP packet from BMF encapsulation UDP data + * Input : encapsulationUdpData - the encapsulation UDP data + * Output : none + * Return : The IP packet + * Data Used : none + * ------------------------------------------------------------------------- */ +unsigned char* GetIpPacket(unsigned char* encapsulationUdpData) +{ + return encapsulationUdpData + ENCAP_HDR_LEN; +} /* GetIpPacket */ + +/* ------------------------------------------------------------------------- + * Function : GetEncapsulationUdpDataLength + * Description: Return the length of BMF encapsulation UDP data + * Input : encapsulationUdpData - the encapsulation UDP data + * Output : none + * Return : The encapsulation data length + * Data Used : none + * ------------------------------------------------------------------------- */ +u_int16_t GetEncapsulationUdpDataLength(unsigned char* encapsulationUdpData) +{ + return GetIpTotalLength(GetIpPacket(encapsulationUdpData)) + ENCAP_HDR_LEN; +} /* GetEncapsulationUdpDataLength */ + + +/* + * Local Variables: + * c-basic-offset: 2 + * indent-tabs-mode: nil + * End: + */ --- /dev/null +++ b/lib/mdns/src/Packet.h @@ -0,0 +1,88 @@ +#ifndef _BMF_PACKET_H +#define _BMF_PACKET_H + +/* + * OLSR Basic Multicast Forwarding (BMF) plugin. + * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands. + * Written by Erik Tromp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Thales, BMF nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* ------------------------------------------------------------------------- + * File : Packet.h + * Description: BMF and IP packet processing functions + * Created : 29 Jun 2006 + * + * ------------------------------------------------------------------------- */ + +/* System includes */ +#include /* IFNAMSIZ, IFHWADDRLEN */ +#include /* u_int8_t, u_int16_t */ + +/* BMF-encapsulated packets are Ethernet-IP-UDP packets, which start + * with a 8-bytes BMF header (struct TEncapHeader), followed by the + * encapsulated Ethernet-IP packet itself */ + +struct TEncapHeader +{ + /* Use a standard Type-Length-Value (TLV) element */ + u_int8_t type; + u_int8_t len; + u_int16_t reserved; /* Always 0 */ + u_int32_t crc32; +} __attribute__((__packed__)); + +#define ENCAP_HDR_LEN ((int)sizeof(struct TEncapHeader)) +#define BMF_ENCAP_TYPE 1 +#define BMF_ENCAP_LEN 6 + +struct TSaveTtl +{ + u_int8_t ttl; + u_int16_t check; +} __attribute__((__packed__)); + +int IsIpFragment(unsigned char* ipPacket); +u_int16_t GetIpTotalLength(unsigned char* ipPacket); +unsigned int GetIpHeaderLength(unsigned char* ipPacket); +u_int8_t GetTtl(unsigned char* ipPacket); +void SaveTtlAndChecksum(unsigned char* ipPacket, struct TSaveTtl* sttl); +void RestoreTtlAndChecksum(unsigned char* ipPacket, struct TSaveTtl* sttl); +void DecreaseTtlAndUpdateHeaderChecksum(unsigned char* ipPacket); +struct ip* GetIpHeader(unsigned char* encapsulationUdpData); +unsigned char* GetIpPacket(unsigned char* encapsulationUdpData); +u_int16_t GetEncapsulationUdpDataLength(unsigned char* encapsulationUdpData); + +#endif /* _BMF_PACKET_H */ + +/* + * Local Variables: + * c-basic-offset: 2 + * indent-tabs-mode: nil + * End: + */ --- /dev/null +++ b/lib/mdns/src/PacketHistory.c @@ -0,0 +1,324 @@ +/* + * OLSR Basic Multicast Forwarding (BMF) plugin. + * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands. + * Written by Erik Tromp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Thales, BMF nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* ------------------------------------------------------------------------- + * File : PacketHistory.c + * Description: Functions for keeping and accessing the history of processed + * multicast IP packets. + * Created : 29 Jun 2006 + * + * ------------------------------------------------------------------------- */ + +#include "PacketHistory.h" + +/* System includes */ +#include /* NULL */ +#include /* assert() */ +#include /* memset */ +#include /* u_int16_t, u_int32_t */ +#include /* struct iphdr */ +#include /* atoi, malloc */ + +/* OLSRD includes */ +#include "defs.h" /* GET_TIMESTAMP, TIMED_OUT */ +#include "olsr.h" /* OLSR_PRINTF */ +#include "scheduler.h" /* now_times */ + +/* Plugin includes */ +#include "Packet.h" + +static struct TDupEntry* PacketHistory[HISTORY_HASH_SIZE]; + +#define CRC_UPTO_NBYTES 256 + +#if 0 +/* ------------------------------------------------------------------------- + * 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; +} /* CalcCrcCcitt */ +#endif + +/* ------------------------------------------------------------------------- + * 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; + } /* for */ +} /* GenerateCrc32Table */ + +/* ------------------------------------------------------------------------- + * 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++) + { + j = ((int) (crc & 0xFF) ^ *buffer++); + crc = (crc >> 8) ^ CrcTable[j]; + } + return crc ^ 0xffffffffUL; +} /* CalcCrc32 */ + +/* ------------------------------------------------------------------------- + * Function : PacketCrc32 + * Description: Calculates the CRC-32 value for an IP packet + * Input : ipPacket - the IP packet + * len - the number of octets in the IP packet + * Output : none + * Return : 32-bits CRC value + * Data Used : none + * ------------------------------------------------------------------------- */ +u_int32_t PacketCrc32(unsigned char* ipPacket, ssize_t len) +{ + struct TSaveTtl sttl; + struct ip* ipHeader; + u_int32_t result; + + assert(ipPacket != NULL); + + /* Skip TTL: in a multi-homed OLSR-network, the same multicast packet + * may enter the network multiple times, each copy differing only in its + * TTL value. BMF must not calculate a different CRC for packets that + * differ only in TTL. Skip also the IP-header checksum, because it changes + * along with TTL. Besides, it is not a good idea to calculate a CRC over + * data that already contains a checksum. + * + * Clip number of bytes over which CRC is calculated to prevent + * long packets from possibly claiming too much CPU resources. */ + assert(len > 0); + if (len > CRC_UPTO_NBYTES) + { + len = CRC_UPTO_NBYTES; + } + + SaveTtlAndChecksum(ipPacket, &sttl); + + ipHeader = (struct ip*)ipPacket; + ipHeader->ip_ttl = 0xFF; /* fixed value of TTL for CRC-32 calculation */ + ipHeader->ip_sum = 0x5A5A; /* fixed value of IP header checksum for CRC-32 calculation */ + + result = CalcCrc32(ipPacket, len); + + RestoreTtlAndChecksum(ipPacket, &sttl); + return result; +} /* PacketCrc32 */ + +/* ------------------------------------------------------------------------- + * Function : Hash + * Description: Calculates a hash value from a 32-bit value + * Input : from32 - 32-bit value + * Output : none + * Return : hash value + * Data Used : none + * ------------------------------------------------------------------------- */ +u_int32_t Hash(u_int32_t from32) +{ + return ((from32 >> N_HASH_BITS) + from32) & ((1 << N_HASH_BITS) - 1); +} /* Hash */ + +/* ------------------------------------------------------------------------- + * Function : InitPacketHistory + * Description: Initialize the packet history table and CRC-32 table + * Input : none + * Output : none + * Return : none + * Data Used : PacketHistory + * ------------------------------------------------------------------------- */ +void InitPacketHistory(void) +{ + int i; + + GenerateCrc32Table(); + + for(i = 0; i < HISTORY_HASH_SIZE; i++) + { + PacketHistory[i] = NULL; + } +} /* InitPacketHistory */ + +/* ------------------------------------------------------------------------- + * Function : CheckAndMarkRecentPacket + * Description: Check if this packet was seen recently, then record the fact + * that this packet was seen recently. + * Input : crc32 - 32-bits crc value of the packet + * Output : none + * Return : not recently seen (0), recently seen (1) + * Data Used : PacketHistory + * ------------------------------------------------------------------------- */ +int CheckAndMarkRecentPacket(u_int32_t crc32) +{ + u_int32_t idx; + struct TDupEntry* walker; + struct TDupEntry* newEntry; + + idx = Hash(crc32); + assert(idx < HISTORY_HASH_SIZE); + + for (walker = PacketHistory[idx]; walker != NULL; walker = walker->next) + { + if (walker->crc32 == crc32) + { + /* Found duplicate entry */ + + /* Always mark as "seen recently": refresh time-out */ + walker->timeOut = GET_TIMESTAMP(HISTORY_HOLD_TIME); + + return 1; + } /* if */ + } /* for */ + + /* No duplicate entry found: create one */ + newEntry = malloc(sizeof(struct TDupEntry)); + if (newEntry != NULL) + { + newEntry->crc32 = crc32; + newEntry->timeOut = GET_TIMESTAMP(HISTORY_HOLD_TIME); + + /* Add new entry at the front of the list */ + newEntry->next = PacketHistory[idx]; + PacketHistory[idx] = newEntry; + } + + return 0; +} /* CheckAndMarkRecentPacket */ + +/* ------------------------------------------------------------------------- + * Function : PrunePacketHistory + * Description: Prune the packet history table. + * Input : useless - not used + * Output : none + * Return : none + * Data Used : PacketHistory + * ------------------------------------------------------------------------- */ +void PrunePacketHistory(void* useless __attribute__((unused))) +{ + uint i; + for (i = 0; i < HISTORY_HASH_SIZE; i++) + { + if (PacketHistory[i] != NULL) + { + struct TDupEntry* nextEntry = PacketHistory[i]; + struct TDupEntry* prevEntry = NULL; + while (nextEntry != NULL) + { + struct TDupEntry* entry = nextEntry; + nextEntry = entry->next; + + if (TIMED_OUT(entry->timeOut)) + { + /* De-queue */ + if (prevEntry != NULL) + { + prevEntry->next = entry->next; + } + else + { + PacketHistory[i] = entry->next; + } /* if */ + + /* De-allocate memory */ + free(entry); + } + else + { + prevEntry = entry; + } /* if */ + } /* while */ + } /* if (PacketHistory[i] != NULL) */ + } /* for (i = ...) */ +} /* PrunePacketHistory */ + +/* + * Local Variables: + * c-basic-offset: 2 + * indent-tabs-mode: nil + * End: + */ --- /dev/null +++ b/lib/mdns/src/PacketHistory.h @@ -0,0 +1,75 @@ +#ifndef _BMF_PACKETHISTORY_H +#define _BMF_PACKETHISTORY_H + +/* + * OLSR Basic Multicast Forwarding (BMF) plugin. + * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands. + * Written by Erik Tromp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Thales, BMF nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* ------------------------------------------------------------------------- + * File : PacketHistory.h + * Description: Functions for keeping and accessing the history of processed + * multicast IP packets. + * Created : 29 Jun 2006 + * + * ------------------------------------------------------------------------- */ + +/* System includes */ +#include /* ssize_t */ +#include /* clock_t */ + +#define N_HASH_BITS 12 +#define HISTORY_HASH_SIZE (1 << N_HASH_BITS) + +/* Time-out of duplicate entries, in milliseconds */ +#define HISTORY_HOLD_TIME 3000 + +struct TDupEntry +{ + u_int32_t crc32; + clock_t timeOut; + struct TDupEntry* next; +}; + +void InitPacketHistory(void); +u_int32_t PacketCrc32(unsigned char* ipPkt, ssize_t len); +u_int32_t Hash(u_int32_t from32); +void MarkRecentPacket(u_int32_t crc32); +int CheckAndMarkRecentPacket(u_int32_t crc32); +void PrunePacketHistory(void*); + +#endif /* _BMF_PACKETHISTORY_H */ + +/* + * Local Variables: + * c-basic-offset: 2 + * indent-tabs-mode: nil + * End: + */ --- /dev/null +++ b/lib/mdns/src/mdns.c @@ -0,0 +1,1174 @@ +/* + * OLSR MDNS plugin. + * Written by Saverio Proto. + * + * 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. + */ + + +//#define _MULTI_THREADED + +#include "mdns.h" + +/* System includes */ +#include /* NULL */ +#include /* ssize_t */ +#include /* strerror() */ +#include /* va_list, va_start, va_end */ +#include /* errno */ +#include /* assert() */ +#include /* ETH_P_IP */ +#include /* struct sockaddr_ll, PACKET_MULTICAST */ +//#include /* pthread_t, pthread_create() */ +#include /* sigset_t, sigfillset(), sigdelset(), SIGINT */ +#include /* struct ip */ +#include /* struct udphdr */ +#include /* close() */ + +#include +#include + +/* OLSRD includes */ +#include "plugin_util.h" /* set_plugin_int */ +#include "defs.h" /* olsr_cnf, OLSR_PRINTF */ +#include "ipcalc.h" +#include "olsr.h" /* OLSR_PRINTF */ +#include "mid_set.h" /* mid_lookup_main_addr() */ +#include "mpr_selector_set.h" /* olsr_lookup_mprs_set() */ +#include "link_set.h" /* get_best_link_to_neighbor() */ +#include "net_olsr.h" /* ipequal */ + +/* plugin includes */ +#include "NetworkInterfaces.h" /* TBmfInterface, CreateBmfNetworkInterfaces(), CloseBmfNetworkInterfaces() */ +#include "Address.h" /* IsMulticast() */ +#include "Packet.h" /* ENCAP_HDR_LEN, BMF_ENCAP_TYPE, BMF_ENCAP_LEN etc. */ +#include "PacketHistory.h" /* InitPacketHistory() */ + +//static pthread_t mdnsThread; +//static int mdnsThreadRunning = 0; + +/* ------------------------------------------------------------------------- + * Function : PacketReceivedFromOLSR + * Description: Handle a received packet from a OLSR message + * Input : ipPacket into an unsigned char and the lenght of the packet + * Output : none + * Return : none + * Data Used : BmfInterfaces + * ------------------------------------------------------------------------- */ +static void PacketReceivedFromOLSR( + unsigned char* encapsulationUdpData, int len) +{ + struct ip* ipHeader; /* IP header inside the encapsulated IP packet */ + union olsr_ip_addr mcSrc; /* Original source of the encapsulated multicast packet */ + union olsr_ip_addr mcDst; /* Multicast destination of the encapsulated packet */ + struct TBmfInterface* walker; + ipHeader = (struct ip*) encapsulationUdpData; + mcSrc.v4 = ipHeader->ip_src; + mcDst.v4 = ipHeader->ip_dst; + + OLSR_PRINTF(3, "MDNS PLUGIN got packet from OLSR message\n"); + + + /* Check with each network interface what needs to be done on it */ + for (walker = BmfInterfaces; walker != NULL; walker = walker->next) + { + /* To a non-OLSR interface: unpack the encapsulated IP packet and forward it */ + if (walker->olsrIntf == NULL) + { + int nBytesWritten; + struct sockaddr_ll dest; + + memset(&dest, 0, sizeof(dest)); + dest.sll_family = AF_PACKET; + if ((encapsulationUdpData[0] & 0xf0) == 0x40) dest.sll_protocol = htons(ETH_P_IP); + if ((encapsulationUdpData[0] & 0xf0) == 0x60) dest.sll_protocol = htons(ETH_P_IPV6); + //TODO: if packet is not IP die here + dest.sll_ifindex = if_nametoindex(walker->ifName); + dest.sll_halen = IFHWADDRLEN; + + /* Use all-ones as destination MAC address. When the IP destination is + * a multicast address, the destination MAC address should normally also + * be a multicast address. E.g., when the destination IP is 224.0.0.1, + * the destination MAC should be 01:00:5e:00:00:01. However, it does not + * seem to matter when the destination MAC address is set to all-ones + * in that case. */ + memset(dest.sll_addr, 0xFF, IFHWADDRLEN); + + nBytesWritten = sendto( + walker->capturingSkfd, + encapsulationUdpData, + len, + 0, + (struct sockaddr*) &dest, + sizeof(dest)); + if (nBytesWritten != len) + { + BmfPError("sendto() error forwarding unpacked encapsulated pkt on \"%s\"", walker->ifName); + } + else + { + + OLSR_PRINTF( + 2, + "%s: --> unpacked and forwarded on \"%s\"\n", + PLUGIN_NAME_SHORT, + walker->ifName); + } + } /* if (walker->olsrIntf == NULL) */ +} +} /* PacketReceivedFromOLSR */ + + + +bool +olsr_parser(union olsr_message *m, + struct interface *in_if __attribute__((unused)), + union olsr_ip_addr *ipaddr) +{ + union olsr_ip_addr originator; + int size; + olsr_reltime vtime; + OLSR_PRINTF(2, "MDNS PLUGIN: Received msg in parser\n"); + /* Fetch the originator of the messsage */ + if(olsr_cnf->ip_version == AF_INET) { + memcpy(&originator, &m->v4.originator, olsr_cnf->ipsize); + vtime = me_to_reltime(m->v4.olsr_vtime); + size = ntohs(m->v4.olsr_msgsize); + } else { + memcpy(&originator, &m->v6.originator, olsr_cnf->ipsize); + vtime = me_to_reltime(m->v6.olsr_vtime); + size = ntohs(m->v6.olsr_msgsize); + } + + /* Check if message originated from this node. + * If so - back off */ + if(ipequal(&originator, &olsr_cnf->main_addr)) + return false; + + /* Check that the neighbor this message was received from is symmetric. + * If not - back off*/ + if(check_neighbor_link(ipaddr) != SYM_LINK) { + struct ipaddr_str strbuf; + OLSR_PRINTF(3, "NAME PLUGIN: Received msg from NON SYM neighbor %s\n", olsr_ip_to_string(&strbuf, ipaddr)); + return false; + } + + if(olsr_cnf->ip_version == AF_INET){ + PacketReceivedFromOLSR((unsigned char*) &m->v4.message,size-12); + } + else { + PacketReceivedFromOLSR((unsigned char*) &m->v6.message,size-12-96); + } + /* Forward the message */ + return 1; +} + +//Sends a packet in the OLSR network +void +olsr_mdns_gen(unsigned char* packet, int len) +{ + /* send buffer: huge */ + char buffer[10240]; + union olsr_message *message = (union olsr_message *)buffer; + struct interface *ifn; + //int namesize; + + /* fill message */ + if(olsr_cnf->ip_version == AF_INET) + { + /* IPv4 */ + message->v4.olsr_msgtype = MESSAGE_TYPE; + message->v4.olsr_vtime = reltime_to_me(MDNS_VALID_TIME * MSEC_PER_SEC); + memcpy(&message->v4.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize); + message->v4.ttl = MAX_TTL; + message->v4.hopcnt = 0; + message->v4.seqno = htons(get_msg_seqno()); + + message->v4.olsr_msgsize = htons(len+12); + + memcpy(&message->v4.message,packet,len); + len=len+12; + } + else + { + /* IPv6 */ + message->v6.olsr_msgtype = MESSAGE_TYPE; + message->v6.olsr_vtime = reltime_to_me(MDNS_VALID_TIME * MSEC_PER_SEC); + memcpy(&message->v6.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize); + message->v6.ttl = MAX_TTL; + message->v6.hopcnt = 0; + message->v6.seqno = htons(get_msg_seqno()); + + message->v6.olsr_msgsize = htons(len+12+96); + memcpy(&message->v6.message,packet,len); + len=len+12+96; + } + + /* looping trough interfaces */ + for (ifn = ifnet; ifn; ifn = ifn->int_next) { + OLSR_PRINTF(1, "MDNS PLUGIN: Generating packet - [%s]\n", ifn->int_name); + + if(net_outbuffer_push(ifn, message, len) != len) { + /* send data and try again */ + net_output(ifn); + if(net_outbuffer_push(ifn, message, len) != len) { + OLSR_PRINTF(1, "MDNS PLUGIN: could not send on interface: %s\n", ifn->int_name); + } + } + } +} + +/* ------------------------------------------------------------------------- + * Function : BmfPError + * Description: Prints an error message at OLSR debug level 1. + * First the plug-in name is printed. Then (if format is not NULL + * and *format is not empty) the arguments are printed, followed + * by a colon and a blank. Then the message and a new-line. + * Input : format, arguments + * Output : none + * Return : none + * Data Used : none + * ------------------------------------------------------------------------- */ + +void BmfPError(const char* format, ...) +{ +#define MAX_STR_DESC 255 +#ifndef NODEBUG + char* strErr = strerror(errno); +#endif + char strDesc[MAX_STR_DESC]; + + /* Rely on short-circuit boolean evaluation */ + if (format == NULL || *format == '\0') + { + OLSR_PRINTF(1, "%s: %s\n", PLUGIN_NAME, strErr); + } + else + { + va_list arglist; + + OLSR_PRINTF(1, "%s: ", PLUGIN_NAME); + + va_start(arglist, format); + vsnprintf(strDesc, MAX_STR_DESC, format, arglist); + va_end(arglist); + + strDesc[MAX_STR_DESC - 1] = '\0'; /* Ensures null termination */ + + OLSR_PRINTF(1, "%s: %s\n", strDesc, strErr); + } +} /* BmfPError */ + +/* ------------------------------------------------------------------------- + * Function : MainAddressOf + * Description: Lookup the main address of a node + * Input : ip - IP address of the node + * Output : none + * Return : The main IP address of the node + * Data Used : none + * ------------------------------------------------------------------------- */ +union olsr_ip_addr* MainAddressOf(union olsr_ip_addr* ip) +{ + union olsr_ip_addr* result; + + /* TODO: mid_lookup_main_addr() is not thread-safe! */ + result = mid_lookup_main_addr(ip); + if (result == NULL) + { + result = ip; + } + return result; +} /* MainAddressOf */ + +/* ------------------------------------------------------------------------- + * Function : EncapsulateAndForwardPacket + * Description: Encapsulate a captured raw IP packet and forward it + * Input : intf - the network interface on which to forward the packet + * encapsulationUdpData - The encapsulation header, followed by + * the encapsulated IP packet + * Output : none + * Return : none + * Data Used : none + * ------------------------------------------------------------------------- */ +//static void EncapsulateAndForwardPacket( +// struct TBmfInterface* intf, +// unsigned char* encapsulationUdpData) +//{ +//// /* The packet */ +// u_int16_t udpDataLen = GetEncapsulationUdpDataLength(encapsulationUdpData); +// +// /* The next destination(s) */ +// struct TBestNeighbors bestNeighborLinks; +// struct link_entry* bestNeighbor; +// +// int nPossibleNeighbors = 0; +// struct sockaddr_in forwardTo; /* Next destination of encapsulation packet */ +// int nPacketsToSend; +// int sendUnicast; /* 0 = send broadcast; 1 = send unicast */ +// +// int i; +// +// /* Find at most 'FanOutLimit' best neigbors to forward the packet to */ +// FindNeighbors(&bestNeighborLinks, &bestNeighbor, intf, NULL, NULL, NULL, &nPossibleNeighbors); +// +// if (nPossibleNeighbors <= 0) +// { +// OLSR_PRINTF( +// 8, +// "%s: --> not encap-forwarding on \"%s\": there is no neighbor that needs my retransmission\n", +// PLUGIN_NAME_SHORT, +// intf->ifName); +// return; +// } +// +// /* Compose destination of encapsulation packet */ +// +// memset(&forwardTo, 0, sizeof(forwardTo)); +// forwardTo.sin_family = AF_INET; +// forwardTo.sin_port = htons(BMF_ENCAP_PORT); +// +// /* Start by filling in the local broadcast address. This may be overwritten later. */ +// forwardTo.sin_addr = intf->broadAddr.v4; +// +// /* - If the BMF mechanism is BM_UNICAST_PROMISCUOUS, always send just one +// * unicast packet (to the best neighbor). +// * - But if the BMF mechanism is BM_BROADCAST, +// * - send 'nPossibleNeighbors' unicast packets if there are up to +// * 'FanOutLimit' possible neighbors, +// * - if there are more than 'FanOutLimit' possible neighbors, then +// * send a (WLAN-air-expensive, less reliable) broadcast packet. */ +// if (BmfMechanism == BM_UNICAST_PROMISCUOUS) +// { +// /* One unicast packet to the best neighbor */ +// nPacketsToSend = 1; +// sendUnicast = 1; +// bestNeighborLinks.links[0] = bestNeighbor; +// } +// else /* BmfMechanism == BM_BROADCAST */ +// { +// if (nPossibleNeighbors <= FanOutLimit) +// { +// /* 'nPossibleNeighbors' unicast packets */ +// nPacketsToSend = nPossibleNeighbors; +// sendUnicast = 1; +// } +// else /* nPossibleNeighbors > FanOutLimit */ +// { +// /* One broadcast packet, possibly retransmitted as specified in the +// * 'BroadcastRetransmitCount' plugin parameter */ +// nPacketsToSend = BroadcastRetransmitCount; +// sendUnicast = 0; +// } /* if */ +// } /* if */ +// +// for (i = 0; i < nPacketsToSend; i++) +// { +// int nBytesWritten; +// +// if (sendUnicast == 1) +// { +// /* For unicast, overwrite the local broadcast address which was filled in above */ +// forwardTo.sin_addr = bestNeighborLinks.links[i]->neighbor_iface_addr.v4; +// } +// +// /* Forward the BMF packet via the encapsulation socket */ +// nBytesWritten = sendto( +// intf->encapsulatingSkfd, +// encapsulationUdpData, +// udpDataLen, +// MSG_DONTROUTE, +// (struct sockaddr*) &forwardTo, +// sizeof(forwardTo)); +// +// /* Evaluate and display result */ +// if (nBytesWritten != udpDataLen) +// { +// BmfPError("sendto() error forwarding pkt on \"%s\"", intf->ifName); +// } +// else +// { +// /* Increase counter */ +// intf->nBmfPacketsTx++; +// +// OLSR_PRINTF( +// 8, +// "%s: --> encapsulated and forwarded on \"%s\" to %s\n", +// PLUGIN_NAME_SHORT, +// intf->ifName, +// inet_ntoa(forwardTo.sin_addr)); +// } /* if (nBytesWritten != udpDataLen) */ +// } /* for */ +//} /* EncapsulateAndForwardPacket */ + +/* ------------------------------------------------------------------------- + * Function : BmfPacketCaptured + * Description: Handle a captured IP packet + * Input : intf - the network interface on which the packet was captured + * sllPkttype - the type of packet. Either PACKET_OUTGOING, + * PACKET_BROADCAST or PACKET_MULTICAST. + * encapsulationUdpData - space for the encapsulation header, followed by + * the captured IP packet + * Output : none + * Return : none + * Data Used : BmfInterfaces + * Notes : The IP packet is assumed to be captured on a socket of family + * PF_PACKET and type SOCK_DGRAM (cooked). + * ------------------------------------------------------------------------- */ +static void BmfPacketCaptured( + //struct TBmfInterface* intf, + //unsigned char sllPkttype, + unsigned char* encapsulationUdpData, + int nBytes) +{ + union olsr_ip_addr src; /* Source IP address in captured packet */ + union olsr_ip_addr dst; /* Destination IP address in captured packet */ + union olsr_ip_addr* origIp; /* Main OLSR address of source of captured packet */ + //struct TBmfInterface* walker; + //int isFromOlsrIntf; + //int isFromOlsrNeighbor; + //int iAmMpr; + //unsigned char* ipPacket; /* The captured IP packet... */ + //u_int16_t ipPacketLen; /* ...and its length */ + struct ip* ipHeader; /* The IP header inside the captured IP packet */ + struct ip6_hdr* ipHeader6; /* The IP header inside the captured IP packet */ + //u_int32_t crc32; + //struct TEncapHeader* encapHdr; + //struct ipaddr_str srcBuf, dstBuf; + struct udphdr* udpHeader; + u_int16_t destPort; + + if ((encapsulationUdpData[0] & 0xf0) == 0x40) { //IPV4 + + ipHeader = (struct ip*) encapsulationUdpData; + + dst.v4 = ipHeader->ip_dst; + + /* Only forward multicast packets. If configured, also forward local broadcast packets */ + if (IsMulticast(&dst)) + { + /* continue */ + } + else + { + return; + } + if (ipHeader->ip_p != SOL_UDP) + { + /* Not UDP */ + OLSR_PRINTF(1,"NON UDP PACKET\n"); + return; /* for */ + } + udpHeader = (struct udphdr*)(encapsulationUdpData + GetIpHeaderLength(encapsulationUdpData)); + destPort = ntohs(udpHeader->dest); + if (destPort != 5353) + { + return; + } + }//END IPV4 + + else if ((encapsulationUdpData[0] & 0xf0) == 0x60) { //IPv6 + + ipHeader6 = (struct ip6_hdr*) encapsulationUdpData; + if (ipHeader6->ip6_dst.s6_addr[0] == 0xff) //Multicast + { + //Continua + } + else + { + return; //not multicast + } + if (ipHeader6->ip6_nxt != SOL_UDP) + { + /* Not UDP */ + OLSR_PRINTF(1,"NON UDP PACKET\n"); + return; /* for */ + } + udpHeader = (struct udphdr*)(encapsulationUdpData + 40); + destPort = ntohs(udpHeader->dest); + if (destPort != 5353) + { + return; + } + } //END IPV6 + else return; //Is not IP packet + + /* Check if the frame is captured on an OLSR-enabled interface */ + //isFromOlsrIntf = (intf->olsrIntf != NULL); TODO: put again this check + + /* Retrieve the length of the captured packet */ + //ipPacketLen = GetIpTotalLength(ipPacket); + + //src.v4 = ipHeader->ip_src; + + //OLSR_PRINTF( + // 1, + // "%s: %s pkt of %ld bytes captured on %s interface \"%s\": %s->%s\n", + // PLUGIN_NAME_SHORT, + // sllPkttype == PACKET_OUTGOING ? "outgoing" : "incoming", + // (long)ipPacketLen, + // isFromOlsrIntf ? "OLSR" : "non-OLSR", + // intf->ifName, + // olsr_ip_to_string(&srcBuf, &src), + // olsr_ip_to_string(&dstBuf, &dst)); + + /* Lookup main address of source in the MID table of OLSR */ + origIp = MainAddressOf(&src); + + // send the packet to OLSR forward mechanism + olsr_mdns_gen(encapsulationUdpData,nBytes); +} /* BmfPacketCaptured */ + + +/* ------------------------------------------------------------------------- + * Function : BmfEncapsulationPacketReceived + * Description: Handle a received BMF-encapsulation packet + * Input : intf - the network interface on which the packet was received + * forwardedBy - the IP node that forwarded the packet to me + * forwardedTo - the destination IP address of the encapsulation + * packet, in case the packet was received promiscuously. + * Pass NULL if the packet is received normally (unicast or + * broadcast). + * encapsulationUdpData - the encapsulating IP UDP data, containting + * the BMF encapsulation header, followed by the encapsulated + * IP packet + * Output : none + * Return : none + * Data Used : BmfInterfaces + * ------------------------------------------------------------------------- */ +//static void BmfEncapsulationPacketReceived( +// struct TBmfInterface* intf, +// union olsr_ip_addr* forwardedBy, +// union olsr_ip_addr* forwardedTo, +// unsigned char* encapsulationUdpData) +//{ +// int iAmMpr; /* True (1) if I am selected as MPR by 'forwardedBy' */ +// struct sockaddr_in forwardTo; /* Next destination of encapsulation packet */ +// unsigned char* ipPacket; /* The encapsulated IP packet */ +// u_int16_t ipPacketLen; /* Length of the encapsulated IP packet */ +// struct ip* ipHeader; /* IP header inside the encapsulated IP packet */ +// union olsr_ip_addr mcSrc; /* Original source of the encapsulated multicast packet */ +// union olsr_ip_addr mcDst; /* Multicast destination of the encapsulated packet */ +// struct TEncapHeader* encapsulationHdr; +// u_int16_t encapsulationUdpDataLen; +// struct TBmfInterface* walker; +// struct ipaddr_str mcSrcBuf, mcDstBuf, forwardedByBuf, forwardedToBuf; +// /* Are we talking to ourselves? */ +// if (if_ifwithaddr(forwardedBy) != NULL) +// { +// return; +// } +// +// /* Discard encapsulated packets received on a non-OLSR interface */ +// if (intf->olsrIntf == NULL) +// { +// return; +// } +// +// /* Retrieve details about the encapsulated IP packet */ +// ipPacket = GetIpPacket(encapsulationUdpData); +// ipPacketLen = GetIpTotalLength(ipPacket); +// ipHeader = GetIpHeader(encapsulationUdpData); +// +// mcSrc.v4 = ipHeader->ip_src; +// mcDst.v4 = ipHeader->ip_dst; +// +// /* Increase counter */ +// intf->nBmfPacketsRx++; +// +// /* Beware: not possible to call olsr_ip_to_string more than 4 times in same printf */ +// OLSR_PRINTF( +// 8, +// "%s: encapsulated pkt of %ld bytes incoming on \"%s\": %s->%s, forwarded by %s to %s\n", +// PLUGIN_NAME_SHORT, +// (long)ipPacketLen, +// intf->ifName, +// olsr_ip_to_string(&mcSrcBuf, &mcSrc), +// olsr_ip_to_string(&mcDstBuf, &mcDst), +// olsr_ip_to_string(&forwardedByBuf, forwardedBy), +// forwardedTo != NULL ? olsr_ip_to_string(&forwardedToBuf, forwardedTo) : "me"); +// +// /* Get encapsulation header */ +// encapsulationHdr = (struct TEncapHeader*) encapsulationUdpData; +// +// /* Verify correct format of BMF encapsulation header */ +// if (encapsulationHdr->type != BMF_ENCAP_TYPE || +// encapsulationHdr->len != BMF_ENCAP_LEN || +// ntohs(encapsulationHdr->reserved != 0)) +// { +// OLSR_PRINTF( +// 8, +// "%s: --> discarding: format of BMF encapsulation header not recognized\n", +// PLUGIN_NAME_SHORT); +// return; +// } +// +// /* Check if this packet was seen recently */ +// if (CheckAndMarkRecentPacket(ntohl(encapsulationHdr->crc32))) +// { +// /* Increase counter */ +// intf->nBmfPacketsRxDup++; +// +// OLSR_PRINTF( +// 8, +// "%s: --> discarding: packet is duplicate\n", +// PLUGIN_NAME_SHORT); +// return; +// } +// +// if (EtherTunTapFd >= 0) +// { +// /* Unpack the encapsulated IP packet and deliver it locally, by sending +// * a copy into the local IP stack via the EtherTunTap interface */ +// +// union olsr_ip_addr broadAddr; +// int nBytesToWrite, nBytesWritten; +// unsigned char* bufferToWrite; +// +// /* If the encapsulated IP packet is a local broadcast packet, +// * update its destination address to match the subnet of the EtherTunTap +// * interface */ +// broadAddr.v4.s_addr = htonl(EtherTunTapIpBroadcast); +// CheckAndUpdateLocalBroadcast(ipPacket, &broadAddr); +// +// bufferToWrite = ipPacket; +// nBytesToWrite = ipPacketLen; +// +// /* Write the packet into the EtherTunTap interface for local delivery */ +// nBytesWritten = write(EtherTunTapFd, bufferToWrite, nBytesToWrite); +// if (nBytesWritten != nBytesToWrite) +// { +// BmfPError("write() error forwarding encapsulated pkt on \"%s\"", EtherTunTapIfName); +// } +// else +// { +// OLSR_PRINTF( +// 8, +// "%s: --> unpacked and delivered locally on \"%s\"\n", +// PLUGIN_NAME_SHORT, +// EtherTunTapIfName); +// } +// } /* if (EtherTunTapFd >= 0) */ +// +// /* Check if I am MPR for the forwarder */ +// /* TODO: olsr_lookup_mprs_set() is not thread-safe! */ +// iAmMpr = (olsr_lookup_mprs_set(MainAddressOf(forwardedBy)) != NULL); +// +// /* Compose destination address for next hop */ +// memset(&forwardTo, 0, sizeof(forwardTo)); +// forwardTo.sin_family = AF_INET; +// forwardTo.sin_port = htons(BMF_ENCAP_PORT); +// +// /* Retrieve the number of bytes to be forwarded via the encapsulation socket */ +// encapsulationUdpDataLen = GetEncapsulationUdpDataLength(encapsulationUdpData); +// +// /* Check with each network interface what needs to be done on it */ +// for (walker = BmfInterfaces; walker != NULL; walker = walker->next) +// { +// /* What to do with the packet on a non-OLSR interface? Unpack +// * encapsulated packet, and forward it. +// * +// * What to do with the packet on an OLSR interface? Forward it only +// * if the forwarding node has selected us as MPR (iAmMpr). +// * +// * Note that the packet is always coming in on an OLSR interface, because +// * it is an encapsulated BMF packet. */ +// +// /* To a non-OLSR interface: unpack the encapsulated IP packet and forward it */ +// if (walker->olsrIntf == NULL) +// { +// int nBytesWritten; +// struct sockaddr_ll dest; +// +// /* If the encapsulated IP packet is a local broadcast packet, +// * update its destination address to match the subnet of the network +// * interface on which the packet is being sent. */ +// CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr); +// +// memset(&dest, 0, sizeof(dest)); +// dest.sll_family = AF_PACKET; +// dest.sll_protocol = htons(ETH_P_IP); +// dest.sll_ifindex = if_nametoindex(walker->ifName); +// dest.sll_halen = IFHWADDRLEN; +// +// /* Use all-ones as destination MAC address. When the IP destination is +// * a multicast address, the destination MAC address should normally also +// * be a multicast address. E.g., when the destination IP is 224.0.0.1, +// * the destination MAC should be 01:00:5e:00:00:01. However, it does not +// * seem to matter when the destination MAC address is set to all-ones +// * in that case. */ +// memset(dest.sll_addr, 0xFF, IFHWADDRLEN); +// +// nBytesWritten = sendto( +// walker->capturingSkfd, +// ipPacket, +// ipPacketLen, +// 0, +// (struct sockaddr*) &dest, +// sizeof(dest)); +// if (nBytesWritten != ipPacketLen) +// { +// BmfPError("sendto() error forwarding unpacked encapsulated pkt on \"%s\"", walker->ifName); +// } +// else +// { +// /* Increase counter */ +// walker->nBmfPacketsTx++; +// +// OLSR_PRINTF( +// 8, +// "%s: --> unpacked and forwarded on \"%s\"\n", +// PLUGIN_NAME_SHORT, +// walker->ifName); +// } +// } /* if (walker->olsrIntf == NULL) */ +// +// /* To an OLSR interface: forward the packet, but only if this node is +// * selected as MPR by the forwarding node */ +// else if (iAmMpr) +// { +// struct TBestNeighbors bestNeighborLinks; +// struct link_entry* bestNeighbor; +// int nPossibleNeighbors; +// int nPacketsToSend; +// int sendUnicast; /* 0 = send broadcast; 1 = send unicast */ +// int i; +// +// /* Retrieve at most two best neigbors to forward the packet to */ +// FindNeighbors( +// &bestNeighborLinks, +// &bestNeighbor, +// walker, +// &mcSrc, +// forwardedBy, +// forwardedTo, +// &nPossibleNeighbors); +// +// if (nPossibleNeighbors <= 0) +// { +// OLSR_PRINTF( +// 8, +// "%s: --> not forwarding on \"%s\": there is no neighbor that needs my retransmission\n", +// PLUGIN_NAME_SHORT, +// walker->ifName); +// +// continue; /* for */ +// } +// +// /* Compose destination of encapsulation packet. +// * Start by filling in the local broadcast address. This may be overwritten later. */ +// forwardTo.sin_addr = walker->broadAddr.v4; +// +// /* - If the BMF mechanism is BM_UNICAST_PROMISCUOUS, always send just one +// * unicast packet (to the best neighbor). +// * - But if the BMF mechanism is BM_BROADCAST, +// * - send 'nPossibleNeighbors' unicast packets if there are up to +// * 'FanOutLimit' possible neighbors, +// * - if there are more than 'FanOutLimit' possible neighbors, then +// * send a (WLAN-air-expensive, less reliable) broadcast packet. */ +// if (BmfMechanism == BM_UNICAST_PROMISCUOUS) +// { +// /* One unicast packet to the best neighbor */ +// nPacketsToSend = 1; +// sendUnicast = 1; +// bestNeighborLinks.links[0] = bestNeighbor; +// } +// else /* BmfMechanism == BM_BROADCAST */ +// { +// if (nPossibleNeighbors <= FanOutLimit) +// { +// /* 'nPossibleNeighbors' unicast packets */ +// nPacketsToSend = nPossibleNeighbors; +// sendUnicast = 1; +// } +// else /* nPossibleNeighbors > FanOutLimit */ +// { +// /* One broadcast packet, possibly retransmitted as specified in the +// * 'BroadcastRetransmitCount' plugin parameter */ +// nPacketsToSend = BroadcastRetransmitCount; +// sendUnicast = 0; +// } /* if */ +// } /* if */ +// +// for (i = 0; i < nPacketsToSend; i++) +// { +// int nBytesWritten; +// +// if (sendUnicast) +// { +// /* For unicast, overwrite the local broadcast address which was filled in above */ +// forwardTo.sin_addr = bestNeighborLinks.links[i]->neighbor_iface_addr.v4; +// } +// +// /* Forward the BMF packet via the encapsulation socket */ +// nBytesWritten = sendto( +// walker->encapsulatingSkfd, +// encapsulationUdpData, +// encapsulationUdpDataLen, +// MSG_DONTROUTE, +// (struct sockaddr*) &forwardTo, +// sizeof(forwardTo)); +// +// /* Evaluate and display result */ +// if (nBytesWritten != encapsulationUdpDataLen) +// { +// BmfPError("sendto() error forwarding encapsulated pkt on \"%s\"", walker->ifName); +// } +// else +// { +// /* Increase counter */ +// walker->nBmfPacketsTx++; +// +// OLSR_PRINTF( +// 8, +// "%s: --> forwarded on \"%s\" to %s\n", +// PLUGIN_NAME_SHORT, +// walker->ifName, +// inet_ntoa(forwardTo.sin_addr)); +// } /* if */ +// } /* for */ +// } /* else if (iAmMpr) */ +// +// else /* walker->olsrIntf != NULL && !iAmMpr */ +// { +// struct ipaddr_str buf; +// /* 'walker' is an OLSR interface, but I am not selected as MPR. In that +// * case, don't forward. */ +// OLSR_PRINTF( +// 8, +// "%s: --> not forwarding on \"%s\": I am not selected as MPR by %s\n", +// PLUGIN_NAME_SHORT, +// walker->ifName, +// olsr_ip_to_string(&buf, forwardedBy)); +// } /* else */ +// } /* for */ +//} /* BmfEncapsulationPacketReceived */ +// +/* ------------------------------------------------------------------------- + * Function : BmfTunPacketCaptured + * Description: Handle an IP packet, captured outgoing on the tuntap interface + * Input : encapsulationUdpData - space for the encapsulation header, followed by + * the captured outgoing IP packet + * Output : none + * Return : none + * Data Used : none + * Notes : The packet is assumed to be captured on a socket of family + * PF_PACKET and type SOCK_DGRAM (cooked). + * ------------------------------------------------------------------------- */ +//static void BmfTunPacketCaptured(unsigned char* encapsulationUdpData) +//{ +// union olsr_ip_addr srcIp; +// union olsr_ip_addr dstIp; +// union olsr_ip_addr broadAddr; +// struct TBmfInterface* walker; +// unsigned char* ipPacket; +// u_int16_t ipPacketLen; +// struct ip* ipHeader; +// u_int32_t crc32; +// struct TEncapHeader* encapHdr; +// struct ipaddr_str srcIpBuf, dstIpBuf; +// ipPacket = GetIpPacket(encapsulationUdpData); +// ipPacketLen = GetIpTotalLength(ipPacket); +// ipHeader = GetIpHeader(encapsulationUdpData); +// +// dstIp.v4 = ipHeader->ip_dst; +// broadAddr.v4.s_addr = htonl(EtherTunTapIpBroadcast); +// +// /* Only forward multicast packets. If configured, also forward local broadcast packets */ +// if (IsMulticast(&dstIp) || +// (EnableLocalBroadcast != 0 && olsr_ipequal(&dstIp, &broadAddr))) +// { +// /* continue */ +// } +// else +// { +// return; +// } +// +// srcIp.v4 = ipHeader->ip_src; +// +// OLSR_PRINTF( +// 8, +// "%s: outgoing pkt of %ld bytes captured on tuntap interface \"%s\": %s->%s\n", +// PLUGIN_NAME_SHORT, +// (long)ipPacketLen, +// EtherTunTapIfName, +// olsr_ip_to_string(&srcIpBuf, &srcIp), +// olsr_ip_to_string(&dstIpBuf, &dstIp)); +// +// /* Calculate packet fingerprint */ +// crc32 = PacketCrc32(ipPacket, ipPacketLen); +// +// /* Check if this packet was seen recently */ +// if (CheckAndMarkRecentPacket(crc32)) +// { +// OLSR_PRINTF( +// 8, +// "%s: --> discarding: packet is duplicate\n", +// PLUGIN_NAME_SHORT); +// return; +// } +// +// /* Compose encapsulation header */ +// encapHdr = (struct TEncapHeader*) encapsulationUdpData; +// memset (encapHdr, 0, ENCAP_HDR_LEN); +// encapHdr->type = BMF_ENCAP_TYPE; +// encapHdr->len = BMF_ENCAP_LEN; +// encapHdr->reserved = 0; +// encapHdr->crc32 = htonl(crc32); +// +// /* Check with each network interface what needs to be done on it */ +// for (walker = BmfInterfaces; walker != NULL; walker = walker->next) +// { +// /* Is the forwarding interface OLSR-enabled? */ +// if (walker->olsrIntf != NULL) +// { +// /* On an OLSR interface: encapsulate and forward packet. */ +// +// EncapsulateAndForwardPacket(walker, encapsulationUdpData); +// } +// else +// { +// /* On a non-OLSR interface: what to do? +// * Answer 1: nothing. Multicast routing between non-OLSR interfaces +// * is to be done by other protocols (e.g. PIM, DVMRP). +// * Answer 2 (better): Forward it. */ +// +// int nBytesWritten; +// struct sockaddr_ll dest; +// +// /* If the encapsulated IP packet is a local broadcast packet, +// * update its destination address to match the subnet of the network +// * interface on which the packet is being sent. */ +// CheckAndUpdateLocalBroadcast(ipPacket, &walker->broadAddr); +// +// memset(&dest, 0, sizeof(dest)); +// dest.sll_family = AF_PACKET; +// dest.sll_protocol = htons(ETH_P_IP); +// dest.sll_ifindex = if_nametoindex(walker->ifName); +// dest.sll_halen = IFHWADDRLEN; +// +// /* Use all-ones as destination MAC address. When the IP destination is +// * a multicast address, the destination MAC address should normally also +// * be a multicast address. E.g., when the destination IP is 224.0.0.1, +// * the destination MAC should be 01:00:5e:00:00:01. However, it does not +// * seem to matter when the destination MAC address is set to all-ones +// * in that case. */ +// memset(dest.sll_addr, 0xFF, IFHWADDRLEN); +// +// nBytesWritten = sendto( +// walker->capturingSkfd, +// ipPacket, +// ipPacketLen, +// 0, +// (struct sockaddr*) &dest, +// sizeof(dest)); +// if (nBytesWritten != ipPacketLen) +// { +// BmfPError("sendto() error forwarding pkt on \"%s\"", walker->ifName); +// } +// else +// { +// /* Increase counter */ +// walker->nBmfPacketsTx++; +// +// OLSR_PRINTF( +// 8, +// "%s: --> forwarded from non-OLSR to non-OLSR \"%s\"\n", +// PLUGIN_NAME_SHORT, +// walker->ifName); +// } /* if */ +// } /* if */ +// } /* for */ +//} /* BmfTunPacketCaptured */ +// +/* ------------------------------------------------------------------------- + * 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 + * ------------------------------------------------------------------------- */ +void DoMDNS(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused))) + +{ +// int nFdBitsSet; + unsigned char rxBuffer[BMF_BUFFER_SIZE]; +// fd_set rxFdSet; +// OLSR_PRINTF(1,"ENTERING DoMDNS\n"); +// assert(HighestSkfd >= 0); +// +// /* Make a local copy of the set of file descriptors that select() can +// * modify to indicate which descriptors actually changed status */ +// rxFdSet = InputSet; +// +// /* 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, &rxFdSet, NULL, NULL, NULL); +// if (nFdBitsSet < 0) +// { +// if (errno != EINTR) +// { +// BmfPError("select() error"); +// } +// return; +// } +// + //while (nFdBitsSet > 0) + //{ + //struct TBmfInterface* walker; + + /* Check if a packet was received on the capturing socket (if any) + * of each network interface */ + //for (walker = BmfInterfaces; walker != NULL; walker = walker->next) + //{ + //int skfd = walker->capturingSkfd; + //if (skfd >= 0 && (FD_ISSET(skfd, &rxFdSet))) + if (skfd >= 0) + { + struct sockaddr_ll pktAddr; + socklen_t addrLen = sizeof(pktAddr); + int nBytes; + unsigned char* ipPacket; + + /* Receive the captured Ethernet frame, leaving space for the BMF + * encapsulation header */ + ipPacket = GetIpPacket(rxBuffer); + nBytes = recvfrom( + skfd, + ipPacket, + //BMF_BUFFER_SIZE - ENCAP_HDR_LEN, //TODO: understand how to change this + BMF_BUFFER_SIZE, //TODO: understand how to change this + 0, + (struct sockaddr*)&pktAddr, + &addrLen); + if (nBytes < 0) + { + //BmfPError("recvfrom() error on \"%s\"", walker->ifName); + + return; /* for */ + } /* if (nBytes < 0) */ + + /* Check if the number of received bytes is large enough for an IP + * packet which contains at least a minimum-size IP header. + * Note: There is an apparent bug in the packet socket implementation in + * combination with VLAN interfaces. On a VLAN interface, the value returned + * by 'recvfrom' may (but need not) be 4 (bytes) larger than the value + * returned on a non-VLAN interface, for the same ethernet frame. */ + if (nBytes < (int)sizeof(struct ip)) + { + //OLSR_PRINTF( + // 1, + // "%s: captured frame too short (%d bytes) on \"%s\"\n", + // PLUGIN_NAME, + // nBytes, + // walker->ifName); + + return; /* for */ + } + + if (pktAddr.sll_pkttype == PACKET_OUTGOING || + pktAddr.sll_pkttype == PACKET_MULTICAST || + pktAddr.sll_pkttype == PACKET_BROADCAST) + { + /* A multicast or broadcast packet was captured */ + + //OLSR_PRINTF( + // 1, + // "%s: captured frame (%d bytes) on \"%s\"\n", + // PLUGIN_NAME, + // nBytes, + // walker->ifName); + //BmfPacketCaptured(walker, pktAddr.sll_pkttype, rxBuffer); + BmfPacketCaptured(ipPacket,nBytes); + + } /* if (pktAddr.sll_pkttype == ...) */ + } /* if (skfd >= 0 && (FD_ISSET...)) */ +// } /* for */ + +// } /* while (nFdBitsSet > 0) */ +} /* DoMDNS */ + +int InitMDNS(struct interface* skipThisIntf) +{ + + + //Tells OLSR to launch olsr_parser when the packets for this plugin arrive + olsr_parser_add_function(&olsr_parser, PARSER_TYPE); + CreateBmfNetworkInterfaces(skipThisIntf); + + return 0; +} /* InitBmf */ + +/* ------------------------------------------------------------------------- + * Function : CloseBmf + * Description: Close the BMF plugin and clean up + * Input : none + * Output : none + * Return : none + * Data Used : BmfThread + * ------------------------------------------------------------------------- */ +void CloseMDNS(void) +{ +// if (EtherTunTapFd >= 0) +// { +// /* If there is a multicast route, try to delete it first */ +// DeleteMulticastRoute(); +// +// /* Restore IP spoof filter for EtherTunTap interface */ +// RestoreSpoofFilter(); +// } +// +// if (mdnsThreadRunning) +// { +// /* Signal BmfThread to exit */ +// /* Strangely enough, all running threads receive the SIGALRM signal. But only the +// * BMF thread is affected by this signal, having specified a handler for this +// * signal in its thread entry function BmfRun(...). */ +// if (pthread_kill(mdnsThread, SIGALRM) != 0) +// { +// BmfPError("pthread_kill() error"); +// } +// +// /* Wait for BmfThread to acknowledge */ +// if (pthread_join(mdnsThread, NULL) != 0) +// { +// BmfPError("pthread_join() error"); +// } +// } +// +// /* Clean up after the BmfThread has been killed */ + CloseBmfNetworkInterfaces(); +} /* CloseBmf */ + + +/* + * Local Variables: + * c-basic-offset: 2 + * indent-tabs-mode: nil + * End: + */ --- /dev/null +++ b/lib/mdns/src/mdns.h @@ -0,0 +1,95 @@ +#ifndef _BMF_BMF_H +#define _BMF_BMF_H + +/* + * OLSR Basic Multicast Forwarding (BMF) plugin. + * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands. + * Written by Erik Tromp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Thales, BMF nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* ------------------------------------------------------------------------- + * File : Bmf.h + * Description: Multicast forwarding functions + * Created : 29 Jun 2006 + * + * ------------------------------------------------------------------------- */ + +#include "olsrd_plugin.h" /* union set_plugin_parameter_addon */ + +#include "parser.h" +#include + +#define MESSAGE_TYPE 132 +#define PARSER_TYPE MESSAGE_TYPE +#define EMISSION_INTERVAL 10 /* seconds */ +#define EMISSION_JITTER 25 /* percent */ +#define MDNS_VALID_TIME 1800 /* seconds */ + +/* BMF plugin data */ +#define PLUGIN_NAME "OLSRD MDNS plugin" +#define PLUGIN_NAME_SHORT "OLSRD MDNS" +#define PLUGIN_VERSION "1.0.0 (" __DATE__ " " __TIME__ ")" +#define PLUGIN_COPYRIGHT " (C) Ninux.org" +#define PLUGIN_AUTHOR " Saverio Proto (zioproto@gmail.com)" +#define MOD_DESC PLUGIN_NAME " " PLUGIN_VERSION "\n" PLUGIN_COPYRIGHT "\n" PLUGIN_AUTHOR +#define PLUGIN_INTERFACE_VERSION 5 + +/* UDP-Port on which multicast packets are encapsulated */ +//#define BMF_ENCAP_PORT 50698 + +/* Forward declaration of OLSR interface type */ +struct interface; + +//extern int FanOutLimit; +//extern int BroadcastRetransmitCount; + +void DoMDNS(int sd, void * x, unsigned int y); +void BmfPError(const char* format, ...) __attribute__((format(printf, 1, 2))); +union olsr_ip_addr* MainAddressOf(union olsr_ip_addr* ip); +//int InterfaceChange(struct interface* interf, int action); +//int SetFanOutLimit(const char* value, void* data, set_plugin_parameter_addon addon); +//int InitBmf(struct interface* skipThisIntf); +//void CloseBmf(void); +int InitMDNS(struct interface* skipThisIntf); +void CloseMDNS(void); + +void olsr_mdns_gen(unsigned char* packet, int len); + +/* Parser function to register with the scheduler */ +bool +olsr_parser(union olsr_message *, struct interface *, union olsr_ip_addr *); + +#endif /* _BMF_BMF_H */ + +/* + * Local Variables: + * c-basic-offset: 2 + * indent-tabs-mode: nil + * End: + */ --- /dev/null +++ b/lib/mdns/src/olsrd_plugin.c @@ -0,0 +1,185 @@ +/* + * OLSR Basic Multicast Forwarding (BMF) plugin. + * Copyright (c) 2005 - 2007, Thales Communications, Huizen, The Netherlands. + * Written by Erik Tromp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Thales, BMF nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* ------------------------------------------------------------------------- + * File : olsrd_plugin.c + * Description: Interface to the OLSRD plugin system + * Created : 29 Jun 2006 + * + * ------------------------------------------------------------------------- */ + +/* System includes */ +#include /* assert() */ +#include /* NULL */ + +/* OLSRD includes */ +#include "olsrd_plugin.h" +#include "plugin_util.h" +#include "defs.h" /* uint8_t, olsr_cnf */ +#include "scheduler.h" /* olsr_start_timer() */ +#include "olsr_cfg.h" /* olsr_cnf() */ +#include "olsr_cookie.h" /* olsr_alloc_cookie() */ + +/* BMF includes */ +#include "mdns.h" /* InitBmf(), CloseBmf() */ +#include "PacketHistory.h" /* InitPacketHistory() */ +#include "NetworkInterfaces.h" /* AddNonOlsrBmfIf(), SetBmfInterfaceIp(), ... */ +#include "Address.h" /* DoLocalBroadcast() */ + +static void __attribute__ ((constructor)) my_init(void); +static void __attribute__ ((destructor)) my_fini(void); + +//static struct olsr_cookie_info *prune_packet_history_timer_cookie; + +void olsr_plugin_exit(void); + +/* ------------------------------------------------------------------------- + * Function : olsrd_plugin_interface_version + * Description: Plugin interface version + * Input : none + * Output : none + * Return : 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(void) +{ + return PLUGIN_INTERFACE_VERSION; +} + +/* ------------------------------------------------------------------------- + * Function : olsrd_plugin_init + * Description: Plugin initialisation + * Input : none + * Output : none + * Return : fail (0) or success (1) + * Data Used : olsr_cnf + * Notes : Called by main OLSRD (init_olsr_plugin) to initialize plugin + * ------------------------------------------------------------------------- */ +int olsrd_plugin_init(void) +{ + /* Clear the packet history */ + //InitPacketHistory(); + + /* Register ifchange function */ + //add_ifchgf(&InterfaceChange); + + /* create the cookie */ + //prune_packet_history_timer_cookie = olsr_alloc_cookie("BMF: Prune Packet History", OLSR_COOKIE_TYPE_TIMER); + + /* Register the duplicate registration pruning process */ + //olsr_start_timer(3 * MSEC_PER_SEC, 0, OLSR_TIMER_PERIODIC, + // &PrunePacketHistory, NULL, prune_packet_history_timer_cookie->ci_id); + + + return InitMDNS(NULL); +} + +/* ------------------------------------------------------------------------- + * Function : olsr_plugin_exit + * Description: Plugin cleanup + * Input : none + * Output : none + * Return : none + * Data Used : none + * Notes : Called by my_fini() at unload of shared object + * ------------------------------------------------------------------------- */ +void olsr_plugin_exit(void) +{ + CloseMDNS(); +} + +static const struct olsrd_plugin_parameters plugin_parameters[] = { + { .name = "NonOlsrIf", .set_plugin_parameter = &AddNonOlsrBmfIf, .data = NULL }, + //{ .name = "DoLocalBroadcast", .set_plugin_parameter = &DoLocalBroadcast, .data = NULL }, + //{ .name = "BmfInterface", .set_plugin_parameter = &SetBmfInterfaceName, .data = NULL }, + //{ .name = "BmfInterfaceIp", .set_plugin_parameter = &SetBmfInterfaceIp, .data = NULL }, + //{ .name = "CapturePacketsOnOlsrInterfaces", .set_plugin_parameter = &SetCapturePacketsOnOlsrInterfaces, .data = NULL }, + //{ .name = "BmfMechanism", .set_plugin_parameter = &SetBmfMechanism, .data = NULL }, + //{ .name = "FanOutLimit", .set_plugin_parameter = &SetFanOutLimit, .data = NULL }, + //{ .name = "BroadcastRetransmitCount", .set_plugin_parameter = &set_plugin_int, .data = &BroadcastRetransmitCount}, +}; + +/* ------------------------------------------------------------------------- + * Function : olsrd_get_plugin_parameters + * Description: Return the parameter table and its size + * Input : none + * Output : params - the parameter table + * size - its size in no. of entries + * Return : none + * Data Used : plugin_parameters + * Notes : Called by main OLSR (init_olsr_plugin) for all plugins + * ------------------------------------------------------------------------- */ +void olsrd_get_plugin_parameters(const struct olsrd_plugin_parameters **params, int *size) +{ + *params = plugin_parameters; + *size = ARRAYSIZE(plugin_parameters); +} + +/* ------------------------------------------------------------------------- + * Function : my_init + * Description: Plugin constructor + * Input : none + * Output : none + * Return : none + * Data Used : none + * Notes : Called at load of shared object + * ------------------------------------------------------------------------- */ +static void my_init(void) +{ + /* Print plugin info to stdout */ + printf("%s\n", MOD_DESC); + + return; +} + +/* ------------------------------------------------------------------------- + * Function : my_fini + * Description: Plugin destructor + * Input : none + * Output : none + * Return : none + * Data Used : none + * Notes : Called at unload of shared object + * ------------------------------------------------------------------------- */ +static void my_fini(void) +{ + olsr_plugin_exit(); +} + +/* + * Local Variables: + * c-basic-offset: 2 + * indent-tabs-mode: nil + * End: + */ --- /dev/null +++ b/lib/mdns/version-script.txt @@ -0,0 +1,10 @@ +VERS_1.0 +{ + global: + olsrd_plugin_interface_version; + olsrd_plugin_init; + olsrd_get_plugin_parameters; + + local: + *; +};