[packages] l2tpv3tun: add /etc/config/network backend, supports briding, multiple...
authorJo-Philipp Wich <jow@openwrt.org>
Sun, 8 Aug 2010 21:24:53 +0000 (21:24 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Sun, 8 Aug 2010 21:24:53 +0000 (21:24 +0000)
SVN-Revision: 22549

net/l2tpv3tun/Makefile
net/l2tpv3tun/files/l2tp.sh [new file with mode: 0644]

index 36ad821..6a1a125 100644 (file)
@@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=l2tpv3tun
 PKG_VERSION:=0.1
-PKG_RELEASE:=2
+PKG_RELEASE:=3
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
 PKG_SOURCE_URL:=ftp://www.openl2tp.org/releases/
@@ -20,7 +20,7 @@ include $(INCLUDE_DIR)/package.mk
 define Package/l2tpv3tun
   SECTION:=net
   CATEGORY:=Network
-  DEPENDS:=+libnl @LINUX_2_6_35
+  DEPENDS:=+libnl +ip +kmod-l2tp +kmod-l2tp-ip +kmod-l2tp-eth
   TITLE:=Control utility for static L2TP v3 (Pseudowire) tunnels
   MAINTAINER:=Thomas Heil <heil@terminal-consulting.de>
   URL:=http://www.openl2tp.org
@@ -44,6 +44,8 @@ endef
 define Package/l2tpv3tun/install
                $(INSTALL_DIR) $(1)/usr/sbin
                $(INSTALL_BIN) $(PKG_BUILD_DIR)/l2tpv3tun $(1)/usr/sbin/
+               $(INSTALL_DIR) $(1)/lib/network
+               $(INSTALL_BIN) ./files/l2tp.sh $(1)/lib/network/
 endef
 
 $(eval $(call BuildPackage,l2tpv3tun))
diff --git a/net/l2tpv3tun/files/l2tp.sh b/net/l2tpv3tun/files/l2tp.sh
new file mode 100644 (file)
index 0000000..a3eeb1d
--- /dev/null
@@ -0,0 +1,213 @@
+# l2tp.sh - L2TPv3 tunnel backend
+# Copyright (c) 2010 OpenWrt.org
+
+l2tp_next_tunnel_id() {
+       local max=0
+       local val
+       for val in $(
+               local l
+               l2tpv3tun show tunnel | while read l; do
+                       case "$l" in
+                               Tunnel*,*encap*) l="${l#Tunnel }"; echo "${l%%,*}";;
+                       esac
+               done
+       ); do
+               [ "$val" -gt "$max" ] && max="$val"
+       done
+       echo $((max + 1))
+}
+
+l2tp_next_session_id() {
+       local tunnel="$1"
+       local max=0
+       local val
+       for val in $(
+               local l
+               l2tpv3tun show session${tunnel:+ tunnel_id "$tunnel"} | while read l; do
+                       case "$l" in
+                               Session*in*) l="${l#Session }"; echo "${l%% *}";;
+                       esac
+               done
+       ); do
+               [ "$val" -gt "$max" ] && max="$val"
+       done
+       echo $((max + 1))
+}
+
+l2tp_tunnel_exists() {
+       test -n "$(l2tpv3tun show tunnel tunnel_id "$1" 2>/dev/null)"
+}
+
+l2tp_session_exists() {
+       test -n "$(l2tpv3tun show session tunnel_id "$1" session_id "$2" 2>/dev/null)"
+}
+
+l2tp_ifname() {
+       l2tpv3tun show session tunnel_id "$1" session_id "$2" 2>/dev/null | \
+               sed -ne 's/^.*interface name: //p'
+}
+
+l2tp_lock() {
+       lock /var/lock/l2tp-setup
+}
+
+l2tp_unlock() {
+       lock -u /var/lock/l2tp-setup
+}
+
+l2tp_log() {
+       logger -t "ifup-l2tp" "$@"
+}
+
+
+# Hook into scan_interfaces() to synthesize a .device option
+# This is needed for /sbin/ifup to properly dispatch control
+# to setup_interface_l2tp() even if no .ifname is set in
+# the configuration.
+scan_l2tp() {
+       local dev
+       config_get dev "$1" device
+       config_set "$1" device "${dev:+$dev }l2tp-$1"
+}
+
+coldplug_interface_l2tp() {
+       setup_interface_l2tp "l2tp-$1" "$1"
+}
+
+setup_interface_l2tp() {
+       local iface="$1"
+       local cfg="$2"
+       local link="l2tp-$cfg"
+
+       l2tp_lock
+
+       # prevent recursion
+       local up="$(uci_get_state network "$cfg" up 0)"
+       [ "$up" = 0 ] || {
+               l2tp_unlock
+               return 0
+       }
+
+       local tunnel_id
+       config_get tunnel_id "$cfg" tunnel_id
+       [ -n "$tunnel_id" ] || {
+               tunnel_id="$(l2tp_next_tunnel_id)"
+               uci_set_state network "$cfg" tunnel_id "$tunnel_id"
+               l2tp_log "No tunnel ID specified, assuming $tunnel_id"
+       }
+
+       local peer_tunnel_id
+       config_get peer_tunnel_id "$cfg" peer_tunnel_id
+       [ -n "$peer_tunnel_id" ] || {
+               peer_tunnel_id="$tunnel_id"
+               uci_set_state network "$cfg" peer_tunnel_id "$peer_tunnel_id"
+               l2tp_log "No peer tunnel ID specified, assuming $peer_tunnel_id"
+       }
+
+       local encap
+       config_get encap "$cfg" encap udp
+
+       local sport dport
+       [ "$encap" = udp ] && {
+               config_get sport "$cfg" sport 1701
+               config_get dport "$cfg" dport 1701
+       }
+
+       local peeraddr
+       config_get peeraddr "$cfg" peeraddr
+       [ -z "$peeraddr" ] && config_get peeraddr "$cfg" peer6addr
+
+       local localaddr
+       case "$peeraddr" in
+               *:*) config_get localaddr "$cfg" local6addr ;;
+               *)   config_get localaddr "$cfg" localaddr  ;;
+       esac
+
+       [ -n "$localaddr" -a -n "$peeraddr" ] || {
+               l2tp_log "Missing local or peer address for tunnel $cfg - skipping"
+               return 1
+       }
+
+       (
+               while ! l2tp_tunnel_exists "$tunnel_id"; do
+                       [ -n "$sport" ] && l2tpv3tun show tunnel 2>/dev/null | grep -q "ports: $sport/" && {
+                               l2tp_log "There already is a tunnel with src port $sport - skipping"
+                               l2tp_unlock
+                               return 1
+                       }
+
+                       l2tpv3tun add tunnel tunnel_id "$tunnel_id" peer_tunnel_id "$peer_tunnel_id" \
+                               encap "$encap" local "$localaddr" remote "$peeraddr" \
+                               ${sport:+udp_sport "$sport"} ${dport:+udp_dport "$dport"}
+
+                       # Wait for tunnel
+                       sleep 1
+               done
+
+
+               local session_id
+               config_get session_id "$cfg" session_id
+               [ -n "$session_id" ] || {
+                       session_id="$(l2tp_next_session_id "$tunnel_id")"
+                       uci_set_state network "$cfg" session_id "$session_id"
+                       l2tp_log "No session ID specified, assuming $session_id"
+               }
+
+               local peer_session_id
+               config_get peer_session_id "$cfg" peer_session_id
+               [ -n "$peer_session_id" ] || {
+                       peer_session_id="$session_id"
+                       uci_set_state network "$cfg" peer_session_id "$peer_session_id"
+                       l2tp_log "No peer session ID specified, assuming $peer_session_id"
+               }
+
+
+               while ! l2tp_session_exists "$tunnel_id" "$session_id"; do
+                       l2tpv3tun add session ifname "$link" tunnel_id "$tunnel_id" \
+                               session_id "$session_id" peer_session_id "$peer_session_id"
+
+                       # Wait for session
+                       sleep 1
+               done
+
+
+               local dev
+               config_get dev "$cfg" device
+
+               local ifn
+               config_get ifn "$cfg" ifname
+
+               uci_set_state network "$cfg" ifname "${ifn:-$dev}"
+               uci_set_state network "$cfg" device "$dev"
+
+               local mtu
+               config_get mtu "$cfg" mtu 1462
+
+               local ttl
+               config_get ttl "$cfg" ttl
+
+               ip link set mtu "$mtu" ${ttl:+ ttl "$ttl"} dev "$link"
+
+               # IP setup inherited from proto static
+               prepare_interface "$link" "$cfg"
+               setup_interface_static "${ifn:-$dev}" "$cfg"
+
+               ip link set up dev "$link"
+
+               uci_set_state network "$cfg" up 1
+               l2tp_unlock
+       ) &
+}
+
+stop_interface_l2tp() {
+       local cfg="$1"
+       local link="l2tp-$cfg"
+
+       local tunnel=$(uci_get_state network "$cfg" tunnel_id)
+       local session=$(uci_get_state network "$cfg" session_id)
+
+       [ -n "$tunnel" ] && [ -n "$session" ] && {
+               l2tpv3tun del session tunnel_id "$tunnel" session_id "$session"
+               l2tpv3tun del tunnel tunnel_id "$tunnel"
+       }
+}