From 4fd7d28f62db3a7b771d129909eef0c02e45d1e8 Mon Sep 17 00:00:00 2001 From: Steven Barth Date: Tue, 25 Mar 2014 15:19:51 +0100 Subject: [PATCH] mcproxy: add initial --- mcproxy/Makefile | 51 +++ mcproxy/files/mcproxy.conf | 28 ++ mcproxy/files/mcproxy.init | 14 + ...ake-and-uclibc-compatibility-support.patch | 306 ++++++++++++++++++ 4 files changed, 399 insertions(+) create mode 100644 mcproxy/Makefile create mode 100644 mcproxy/files/mcproxy.conf create mode 100644 mcproxy/files/mcproxy.init create mode 100644 mcproxy/patches/0001-Add-CMake-and-uclibc-compatibility-support.patch diff --git a/mcproxy/Makefile b/mcproxy/Makefile new file mode 100644 index 0000000..b96268a --- /dev/null +++ b/mcproxy/Makefile @@ -0,0 +1,51 @@ +# +# Copyright (C) 2006-2011 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +PKG_NAME:=mcproxy +PKG_SOURCE_VERSION:=986523a5d714be5cf6f65e4399045cbfecd415fd +PKG_VERSION:=2014-03-25-$(PKG_SOURCE_VERSION) +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL:=git://github.com/mcproxy/mcproxy.git +PKG_MAINTAINER:=Steven Barth + +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 +PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +define Package/mcproxy + SECTION:=net + CATEGORY:=Network + TITLE:=Multicast Proxy for IGMP/MLD + URL:=http://mcproxy.realmv6.org + DEPENDS:=+libpthread +libstdcpp +endef + +define Package/mcproxy/description + mcproxy is a free & open source implementation of the IGMP/MLD proxy function (see RFC 4605) for Linux systems. + It operates on the kernel tables for multicast routing and allows for multiple instantiations, + as well as dynamically changing downstream interfaces. +endef + +define Package/mcproxy/conffiles +/etc/mcproxy.conf +endef + +define Package/mcproxy/install + $(INSTALL_DIR) $(1)/etc/init.d + $(INSTALL_CONF) ./files/mcproxy.conf $(1)/etc + $(INSTALL_BIN) ./files/mcproxy.init $(1)/etc/init.d/mcproxy + $(INSTALL_DIR) $(1)/usr/sbin + $(INSTALL_BIN) $(PKG_BUILD_DIR)/mcproxy-bin $(1)/usr/sbin/mcproxy +endef + +$(eval $(call BuildPackage,mcproxy)) diff --git a/mcproxy/files/mcproxy.conf b/mcproxy/files/mcproxy.conf new file mode 100644 index 0000000..533c0f9 --- /dev/null +++ b/mcproxy/files/mcproxy.conf @@ -0,0 +1,28 @@ +###################################### +##-- mcproxy configuration script --## +###################################### + +protocol MLDv2; #IPv6 +protocol IGMPv3; #IPv4 + +#pinstance myProxy: eth0 ==> eth1 eth2; +#pinstance my_second_instance: tun1 ==> "vlan-eth0.2"; + +# +# This confiugration example creates +# a multicast proxy for ipv4 with the +# upstream eth0 and two downstreams. +# +# | +# | +# +------+-----+ +# | eth0 | +# | | +# | myProxy | +# | | +# | eth1 eth2 | +# +---+----+---+ +# | | +# | | +# + diff --git a/mcproxy/files/mcproxy.init b/mcproxy/files/mcproxy.init new file mode 100644 index 0000000..7a33030 --- /dev/null +++ b/mcproxy/files/mcproxy.init @@ -0,0 +1,14 @@ +#!/bin/sh /etc/rc.common + +START=50 +USE_PROCD=1 + +start_service() { + procd_open_instance + + procd_set_param command /usr/sbin/mcproxy + procd_append_param command -f /etc/mcproxy.conf + + procd_set_param respawn + procd_close_instance +} diff --git a/mcproxy/patches/0001-Add-CMake-and-uclibc-compatibility-support.patch b/mcproxy/patches/0001-Add-CMake-and-uclibc-compatibility-support.patch new file mode 100644 index 0000000..01571e9 --- /dev/null +++ b/mcproxy/patches/0001-Add-CMake-and-uclibc-compatibility-support.patch @@ -0,0 +1,306 @@ +From 7618500760e3c9c0d831714fdedb497c0738e131 Mon Sep 17 00:00:00 2001 +From: Steven Barth +Date: Tue, 25 Mar 2014 15:09:11 +0100 +Subject: [PATCH] Add CMake and uclibc support + +--- + CMakeLists.txt | 51 +++++++++++ + mcproxy/src/parser/parser.cpp | 6 +- + mcproxy/src/utils/addr_storage.cpp | 2 +- + mcproxy/src/utils/mc_socket.cpp | 2 + + mcproxy/src/utils/sourcefilter.cpp | 168 +++++++++++++++++++++++++++++++++++++ + 5 files changed, 225 insertions(+), 4 deletions(-) + create mode 100644 CMakeLists.txt + create mode 100644 mcproxy/src/utils/sourcefilter.cpp + +diff --git a/CMakeLists.txt b/CMakeLists.txt +new file mode 100644 +index 0000000..7499c19 +--- /dev/null ++++ b/CMakeLists.txt +@@ -0,0 +1,51 @@ ++cmake_minimum_required(VERSION 2.8) ++ ++# Project Definition ++project(mcproxy CXX) ++set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") ++set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -std=c++11") ++add_definitions(-Wall -Wextra -pedantic) ++include_directories(${CMAKE_SOURCE_DIR}/mcproxy) ++ ++ ++add_executable(mcproxy-bin mcproxy/src/main.cpp ++ mcproxy/src/hamcast_logging.cpp ++ #utils ++ mcproxy/src/utils/mc_socket.cpp ++ mcproxy/src/utils/addr_storage.cpp ++ mcproxy/src/utils/mroute_socket.cpp ++ mcproxy/src/utils/if_prop.cpp ++ mcproxy/src/utils/reverse_path_filter.cpp ++ #proxy ++ mcproxy/src/proxy/proxy.cpp ++ mcproxy/src/proxy/sender.cpp ++ mcproxy/src/proxy/receiver.cpp ++ mcproxy/src/proxy/mld_receiver.cpp ++ mcproxy/src/proxy/igmp_receiver.cpp ++ mcproxy/src/proxy/mld_sender.cpp ++ mcproxy/src/proxy/igmp_sender.cpp ++ mcproxy/src/proxy/proxy_instance.cpp ++ mcproxy/src/proxy/routing.cpp ++ mcproxy/src/proxy/worker.cpp ++ mcproxy/src/proxy/timing.cpp ++ mcproxy/src/proxy/check_if.cpp ++ mcproxy/src/proxy/check_kernel.cpp ++ mcproxy/src/proxy/membership_db.cpp ++ mcproxy/src/proxy/querier.cpp ++ mcproxy/src/proxy/timers_values.cpp ++ mcproxy/src/proxy/interfaces.cpp ++ mcproxy/src/proxy/def.cpp ++ mcproxy/src/proxy/simple_mc_proxy_routing.cpp ++ mcproxy/src/proxy/simple_routing_data.cpp ++ #parser ++ mcproxy/src/parser/scanner.cpp ++ mcproxy/src/parser/token.cpp ++ mcproxy/src/parser/configuration.cpp ++ mcproxy/src/parser/parser.cpp ++ mcproxy/src/parser/interface.cpp ++) ++target_link_libraries(mcproxy-bin pthread) ++ ++# Installation ++install(TARGETS mcproxy-bin DESTINATION bin/) ++ +diff --git a/mcproxy/src/parser/parser.cpp b/mcproxy/src/parser/parser.cpp +index c196be9..516a700 100644 +--- a/mcproxy/src/parser/parser.cpp ++++ b/mcproxy/src/parser/parser.cpp +@@ -125,7 +125,7 @@ void parser::parse_instance_definition(inst_def_set& ids) + get_next_token(); + if (m_current_token.get_type() == TT_STRING) { + try { +- table_number = std::stoi(m_current_token.get_string()); ++ table_number = atoi(m_current_token.get_string().c_str()); + user_selected_table_number = true; + } catch (std::logic_error e) { + HC_LOG_ERROR("failed to parse line " << m_current_line << " table number: " << table_number << " is not a number"); +@@ -298,7 +298,7 @@ std::unique_ptr parser::parse_rule_part(group_mem_protocol gmp) + get_next_token(); + if (m_current_token.get_type() == TT_STRING) { + try { +- unsigned int prefix = std::stoi(m_current_token.get_string()); ++ unsigned int prefix = atoi(m_current_token.get_string().c_str()); + if (prefix > 128) { + throw; + } +@@ -560,7 +560,7 @@ void parser::parse_interface_rule_match_binding( + get_next_token(); + if (m_current_token.get_type() == TT_STRING) { + try { +- int tmp_timeout = std::stoi(m_current_token.get_string()); ++ int tmp_timeout = atoi(m_current_token.get_string().c_str()); + timeout = std::chrono::milliseconds(tmp_timeout); + } catch (...) { + error_notification(); +diff --git a/mcproxy/src/utils/addr_storage.cpp b/mcproxy/src/utils/addr_storage.cpp +index 125ccbf..e812ac9 100644 +--- a/mcproxy/src/utils/addr_storage.cpp ++++ b/mcproxy/src/utils/addr_storage.cpp +@@ -298,7 +298,7 @@ addr_storage& addr_storage::set_port(uint16_t port) + + addr_storage& addr_storage::set_port(const std::string& port) + { +- set_port(std::stoi(port.c_str())); ++ set_port(atoi(port.c_str())); + return *this; + } + +diff --git a/mcproxy/src/utils/mc_socket.cpp b/mcproxy/src/utils/mc_socket.cpp +index b8fb3ae..8c32e08 100644 +--- a/mcproxy/src/utils/mc_socket.cpp ++++ b/mcproxy/src/utils/mc_socket.cpp +@@ -37,6 +37,8 @@ + #include + #include + ++#include "sourcefilter.cpp" ++ + std::string ipAddrResolver(std::string ipAddr) + { + std::string str[][2] = { +diff --git a/mcproxy/src/utils/sourcefilter.cpp b/mcproxy/src/utils/sourcefilter.cpp +new file mode 100644 +index 0000000..64aafde +--- /dev/null ++++ b/mcproxy/src/utils/sourcefilter.cpp +@@ -0,0 +1,168 @@ ++/* Get source filter. Linux version. ++ Copyright (C) 2004-2014 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ Contributed by Ulrich Drepper , 2004. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define getsourcefilter getsourcefilter2 ++#define setsourcefilter setsourcefilter2 ++ ++static const struct ++{ ++ int sol; ++ int af; ++ socklen_t size; ++} sol_map[] = ++ { ++ /* Sort the array according to importance of the protocols. Add ++ more protocols when they become available. */ ++ { SOL_IP, AF_INET, sizeof (struct sockaddr_in) }, ++ { SOL_IPV6, AF_INET6, sizeof (struct sockaddr_in6) }, ++ { SOL_PACKET, AF_PACKET, sizeof (struct sockaddr_ll) } ++ }; ++#define NSOL_MAP (sizeof (sol_map) / sizeof (sol_map[0])) ++ ++ ++/* Try to determine the socket level value. Ideally both side and ++ family are set. But sometimes only the size is correct and the ++ family value might be bogus. Loop over the array entries and look ++ for a perfect match or the first match based on size. */ ++static int ++__get_sol (int af, socklen_t len) ++{ ++ int first_size_sol = -1; ++ ++ for (size_t cnt = 0; cnt < NSOL_MAP; ++cnt) ++ { ++ /* Just a test so that we make sure the special value used to ++ signal the "we have so far no socket level value" is OK. */ ++ assert (sol_map[cnt].sol != -1); ++ ++ if (len == sol_map[cnt].size) ++ { ++ /* The size matches, which is a requirement. If the family ++ matches, too, we have a winner. Otherwise we remember the ++ socket level value for this protocol if it is the first ++ match. */ ++ if (af == sol_map[cnt].af) ++ /* Bingo! */ ++ return sol_map[cnt].sol; ++ ++ if (first_size_sol == -1) ++ first_size_sol = sol_map[cnt].sol; ++ } ++ } ++ ++ return first_size_sol; ++} ++ ++ ++int ++getsourcefilter2 (int s, uint32_t interface, const struct sockaddr *group, ++ socklen_t grouplen, uint32_t *fmode, uint32_t *numsrc, ++ struct sockaddr_storage *slist) ++{ ++ /* We have to create an struct ip_msfilter object which we can pass ++ to the kernel. */ ++ socklen_t needed = GROUP_FILTER_SIZE (*numsrc); ++ struct group_filter *gf; ++ gf = (struct group_filter *) malloc (needed); ++ if (gf == NULL) ++ return -1; ++ ++ gf->gf_interface = interface; ++ memcpy (&gf->gf_group, group, grouplen); ++ gf->gf_numsrc = *numsrc; ++ ++ /* We need to provide the appropriate socket level value. */ ++ int result; ++ int sol = __get_sol (group->sa_family, grouplen); ++ if (sol == -1) ++ { ++ errno = EINVAL; ++ result = -1; ++ } ++ else ++ { ++ result = getsockopt (s, sol, MCAST_MSFILTER, gf, &needed); ++ ++ /* If successful, copy the results to the places the caller wants ++ them in. */ ++ if (result == 0) ++ { ++ *fmode = gf->gf_fmode; ++ memcpy (slist, gf->gf_slist, ++ MIN (*numsrc, gf->gf_numsrc) ++ * sizeof (struct sockaddr_storage)); ++ *numsrc = gf->gf_numsrc; ++ } ++ } ++ ++ int save_errno = errno; ++ free (gf); ++ errno = save_errno; ++ ++ return result; ++} ++ ++ ++int ++setsourcefilter2 (int s, uint32_t interface, const struct sockaddr *group, ++ socklen_t grouplen, uint32_t fmode, uint32_t numsrc, ++ const struct sockaddr_storage *slist) ++{ ++ /* We have to create an struct ip_msfilter object which we can pass ++ to the kernel. */ ++ size_t needed = GROUP_FILTER_SIZE (numsrc); ++ ++ struct group_filter *gf; ++ gf = (struct group_filter *) malloc (needed); ++ if (gf == NULL) ++ return -1; ++ ++ gf->gf_interface = interface; ++ memcpy (&gf->gf_group, group, grouplen); ++ gf->gf_fmode = fmode; ++ gf->gf_numsrc = numsrc; ++ memcpy (gf->gf_slist, slist, numsrc * sizeof (struct sockaddr_storage)); ++ ++ /* We need to provide the appropriate socket level value. */ ++ int result; ++ int sol = __get_sol (group->sa_family, grouplen); ++ if (sol == -1) ++ { ++ errno = EINVAL; ++ result = -1; ++ } ++ else ++ result = setsockopt (s, sol, MCAST_MSFILTER, gf, needed); ++ ++ int save_errno = errno; ++ free (gf); ++ errno = save_errno; ++ ++ return result; ++} +-- +1.8.3.2 + -- 2.35.1