--- /dev/null
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=tunneldigger-broker
+PKG_RELEASE:=1
+
+PKG_SOURCE_URL:=https://github.com/wlanslovenija/tunneldigger.git
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_VERSION:=4f72b30578ac3dbc5482f4a54054bf870355bdf5
+PKG_MIRROR_HASH:=e93b986b60475c16b0022ba4f5da981929cc3d6992c632f41264804912825473
+
+PKG_MAINTAINER:=Nick Hainke <vincent@systemli.org>
+PKG_LICENSE:=AGPL-3.0
+PKG_LICENSE_FILES:=COPYING
+
+PKG_BUILD_DEPENDS:=python-cffi/host
+
+include ../../lang/python/pypi.mk
+include $(INCLUDE_DIR)/package.mk
+include ../../lang/python/python3-package.mk
+
+define Package/tunneldigger-broker
+ SECTION:=net
+ CATEGORY:=Network
+ DEPENDS:= \
+ +ip-full \
+ +kmod-l2tp \
+ +kmod-l2tp-ip \
+ +kmod-l2tp-eth \
+ +kmod-sched \
+ +libnetfilter-conntrack \
+ +libnfnetlink \
+ +libnl-tiny \
+ +libpthread \
+ +librt \
+ +python3-cffi \
+ +python3-ctypes \
+ +python3-light \
+ +python3-logging \
+ +python3-six \
+ +tc-full
+ TITLE:=Broker for L2TPv3 tunnels using tunneldigger
+ URL:=https://github.com/wlanslovenija/tunneldigger
+endef
+
+define Package/tunneldigger-broker/description
+Tunneldigger is a simple VPN tunneling solution based on the Linux kernel
+support for L2TPv3 tunnels over UDP. This package contains the broker.
+endef
+
+PYTHON3_PKG_SETUP_DIR:=broker
+PYTHON3_PKG_WHEEL_VERSION:=0.4.0.dev1
+
+define Py3Package/tunneldigger-broker/install
+ $(INSTALL_DIR) $(1)/lib/functions
+ $(INSTALL_DATA) ./files/tunneldigger.sh $(1)/lib/functions/tunneldigger.sh
+ $(INSTALL_DIR) $(1)/usr/lib/tunneldigger-broker/hooks
+ $(INSTALL_BIN) ./files/hook-setup $(1)/usr/lib/tunneldigger-broker/hooks/setup
+ $(INSTALL_BIN) ./files/hook-teardown $(1)/usr/lib/tunneldigger-broker/hooks/teardown
+ $(INSTALL_BIN) ./files/hook-mtu-changed $(1)/usr/lib/tunneldigger-broker/hooks/mtu-changed
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/tunneldigger-broker.init $(1)/etc/init.d/tunneldigger-broker
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/config.default $(1)/etc/config/tunneldigger-broker
+endef
+
+define Package/tunneldigger-broker/conffiles
+/etc/config/tunneldigger-broker
+endef
+
+$(eval $(call Py3Package,tunneldigger-broker))
+$(eval $(call BuildPackage,tunneldigger-broker))
+$(eval $(call BuildPackage,tunneldigger-broker-src))
--- /dev/null
+config broker
+ list port '53'
+ list port '123'
+ list port '8942'
+ option interface 'loopback'
+ option max_cookies '1024'
+ option max_tunnels '1024'
+ option port_base '20000'
+ option tunnel_id_base '100'
+ option tunnel_timeout '60'
+ option pmtu '0'
+ option namespace 'production'
+ option connection_rate_limit '0.2'
+
+config log
+ option filename '/dev/null'
+ option verbosity 'INFO'
+ option log_ip_addresses '0'
--- /dev/null
+#!/bin/sh
+
+. /lib/functions/tunneldigger.sh
+
+TUNNEL_ID="$1"
+INTERFACE="$3"
+OLD_MTU="$4"
+NEW_MTU="$5"
+
+# Get the bridge interface name for the old and new MTUs.
+tunneldigger_get_bridge old_bridge "${OLD_MTU}"
+tunneldigger_get_bridge new_bridge "${NEW_MTU}"
+
+if [ -z "$old_bridge" ]; then
+ echo "Unable to determine which bridge to use for MTU ${OLD_MTU}."
+ exit 1
+fi
+
+if [ -z "$new_bridge" ]; then
+ echo "Unable to determine which bridge to use for MTU ${NEW_MTU}."
+ exit 1
+fi
+
+# Remove interface from old bridge.
+ip link set dev ${INTERFACE} nomaster
+ip link set dev ${old_bridge} mtu ${OLD_MTU}
+
+# Change interface bridge and MTU.
+ip link set dev ${INTERFACE} master ${new_bridge} mtu ${NEW_MTU}
+ip link set dev ${new_bridge} mtu ${NEW_MTU}
--- /dev/null
+#!/bin/sh
+
+. /lib/functions/tunneldigger.sh
+
+TUNNEL_ID="$1"
+INTERFACE="$3"
+MTU="$4"
+
+# Get the bridge interface name for this MTU.
+tunneldigger_get_bridge bridge "${MTU}"
+if [ -z "$bridge" ]; then
+ echo "Unable to determine which bridge to use for MTU ${MTU}."
+ exit 1
+fi
+
+# Disable IPv6 on this interface as it will be bridged.
+echo 1 > /proc/sys/net/ipv6/conf/${INTERFACE}/disable_ipv6
+# Add the interface to the proper bridge and bring it up.
+ip link set dev ${INTERFACE} master ${bridge} mtu ${MTU} up
+# Ensure bridge MTU.
+ip link set dev ${bridge} mtu ${MTU}
--- /dev/null
+#!/bin/sh
+
+TUNNEL_ID="$1"
+INTERFACE="$3"
+MTU="$4"
+
+# Remove interface from the bridge.
+ip link set dev ${INTERFACE} nomaster
--- /dev/null
+#!/bin/sh /etc/rc.common
+
+. $IPKG_INSTROOT/lib/functions/network.sh
+
+START=90
+USE_PROCD=1
+NAME=tunneldigger-broker
+
+PIDPATH=/var/run
+CONFIGFILE=/var/etc/tunneldigger-broker.cfg
+HOOKPATH=/usr/lib/tunneldigger-broker/hooks
+
+missing() {
+ echo "Not starting tunneldigger-broker - missing $1" >&2
+ exit 1
+}
+
+cfg_append() {
+ local value="$1"
+ echo "$value" >> $CONFIGFILE
+}
+
+cfg_append_section() {
+ local name="$1"
+ cfg_append "[${name}]"
+}
+
+cfg_append_kv() {
+ local key="$1"
+ local value="$2"
+ cfg_append "${key}=${value}"
+}
+
+cfg_append_option() {
+ local cfg="$1"
+ local option="$2"
+ local key="$3"
+ config_get value "$cfg" "${option}"
+ [ -z "${value}" ] && missing ${option}
+ cfg_append_kv "${key}" "${value}"
+}
+
+parse_broker() {
+ local section="$1"
+ cfg_append_section broker
+ config_get interface "$section" interface
+
+ [ ! -z "${interface}" ] && {
+ # Resolve logical interface name.
+ unset _interface address
+ network_get_device _interface "${interface}" || _interface="${interface}"
+ cfg_append_kv interface "${_interface}"
+ network_get_ipaddr address "${interface}"
+ cfg_append_kv address "${address}"
+ }
+
+ OPTIONS="max_cookies max_tunnels port_base tunnel_id_base tunnel_timeout namespace connection_rate_limit pmtu"
+ for option in ${OPTIONS}; do
+ cfg_append_option "$section" "${option}" "${option}"
+ done
+
+ config_get port "$section" port
+ cfg_append_kv "port" "${port// /,}"
+
+ cfg_append_section hooks
+ cfg_append_kv "session.up" "${HOOKPATH}/setup"
+ cfg_append_kv "session.pre-down" "${HOOKPATH}/teardown"
+ cfg_append_kv "session.mtu-changed" "${HOOKPATH}/mtu-changed"
+}
+
+parse_log() {
+ local section="$1"
+ cfg_append_section log
+
+ OPTIONS="filename verbosity"
+ for option in ${OPTIONS}; do
+ cfg_append_option "$section" "${option}" "${option}"
+ done
+
+ config_get_bool log_ip_addresses "$section" log_ip_addresses 1
+ if [ "${log_ip_addresses}" -eq 1 ]; then
+ cfg_append_kv "log_ip_addresses" "true"
+ else
+ cfg_append_kv "log_ip_addresses" "false"
+ fi
+}
+
+start_service() {
+ # Prepare the configuration file from UCI settings.
+ rm -f ${CONFIGFILE}
+ config_load tunneldigger-broker
+ config_foreach parse_broker broker
+ config_foreach parse_log log
+
+ # Start the service using procd.
+ procd_open_instance
+ procd_set_param command "/usr/bin/python"
+ procd_append_param command -m tunneldigger_broker.main
+ procd_append_param command "${CONFIGFILE}"
+ procd_set_param respawn
+ procd_set_param stdout 1
+ procd_set_param stderr 1
+ procd_close_instance
+}
--- /dev/null
+. /lib/functions.sh
+. /lib/functions/network.sh
+
+tunneldigger_get_bridge() {
+ local variable="$1"
+ local mtu="$2"
+
+ # Overwrite the destination variable.
+ unset $variable
+
+ # Discover the configured bridge.
+ unset _td_bridge
+ _td_bridge=""
+ config_cb() {
+ local cfg="$CONFIG_SECTION"
+ config_get configname "$cfg" TYPE
+ if [ "$configname" != "bridge" ]; then
+ return
+ fi
+
+ config_get cfg_mtu "$cfg" mtu
+ config_get interface "$cfg" interface
+
+ if [ "$cfg_mtu" != "$mtu" ]; then
+ return
+ fi
+
+ _td_bridge="$interface"
+ }
+
+ config_load tunneldigger-broker
+ reset_cb
+ if [ -z "$_td_bridge" ]; then
+ return
+ fi
+
+ eval $variable=$_td_bridge
+ # network_get_device $variable $_td_bridge
+}