Skip to content

Instantly share code, notes, and snippets.

@dangowrt

dangowrt/l2tpv3.sh

Created May 2, 2015
Embed
What would you like to do?
/etc/network/l2tpv3.sh
#!/bin/sh
# l2tpv3.sh - L2TPv3 tunnel backend using ip-full
# Copyright (c) 2010-2015 OpenWrt.org
# This file was part of l2tpv3tun and ported to use ip-full.
ip l2tp show tunnel 2>/dev/null 1>/dev/null || exit 0
l2tpv3_next_tunnel_id() {
local max=0
local val
for val in $(
local l
ip l2tp 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))
}
l2tpv3_next_session_id() {
local tunnel="$1"
local max=0
local val
for val in $(
local l
ip l2tp 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))
}
l2tpv3_tunnel_exists() {
test -n "$(ip l2tp show tunnel tunnel_id "$1" 2>/dev/null)"
}
l2tpv3_session_exists() {
test -n "$(ip l2tp show session tunnel_id "$1" session_id "$2" 2>/dev/null)"
}
l2tpv3_ifname() {
ip l2tp show session tunnel_id "$1" session_id "$2" 2>/dev/null | \
sed -ne 's/^.*interface name: //p'
}
l2tpv3_lock() {
lock /var/lock/l2tpv3-setup
}
l2tpv3_unlock() {
lock -u /var/lock/l2tpv3-setup
}
l2tpv3_log() {
logger -t "ifup-l2tpv3" "$@"
}
# Hook into scan_interfaces() to synthesize a .device option
# This is needed for /sbin/ifup to properly dispatch control
# to setup_interface_l2tpv3() even if no .ifname is set in
# the configuration.
scan_l2tpv3() {
local dev
config_get dev "$1" device
config_set "$1" device "${dev:+$dev }l2tpv3-$1"
}
coldplug_interface_l2tpv3() {
setup_interface_l2tpv3 "l2tpv3-$1" "$1"
}
setup_interface_l2tpv3() {
local iface="$1"
local cfg="$2"
local link="l2tpv3-$cfg"
l2tpv3_lock
# prevent recursion
local up="$(uci_get_state network "$cfg" up 0)"
[ "$up" = 0 ] || {
l2tpv3_unlock
return 0
}
local tunnel_id
config_get tunnel_id "$cfg" tunnel_id
[ -n "$tunnel_id" ] || {
tunnel_id="$(l2tpv3_next_tunnel_id)"
uci_set_state network "$cfg" tunnel_id "$tunnel_id"
l2tpv3_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"
l2tpv3_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" ] || {
l2tpv3_log "Missing local or peer address for tunnel $cfg - skipping"
return 1
}
(
while ! l2tpv3_tunnel_exists "$tunnel_id"; do
[ -n "$sport" ] && ip l2tp show tunnel 2>/dev/null | grep -q "ports: $sport/" && {
l2tpv3_log "There already is a tunnel with src port $sport - skipping"
l2tpv3_unlock
return 1
}
ip l2tp 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="$(l2tpv3_next_session_id "$tunnel_id")"
uci_set_state network "$cfg" session_id "$session_id"
l2tpv3_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"
l2tpv3_log "No peer session ID specified, assuming $peer_session_id"
}
while ! l2tpv3_session_exists "$tunnel_id" "$session_id"; do
ip l2tp add session name "$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
l2tpv3_unlock
) &
}
stop_interface_l2tpv3() {
local cfg="$1"
local link="l2tpv3-$cfg"
local tunnel=$(uci_get_state network "$cfg" tunnel_id)
local session=$(uci_get_state network "$cfg" session_id)
[ -n "$tunnel" ] && [ -n "$session" ] && {
ip l2tp del session tunnel_id "$tunnel" session_id "$session"
ip l2tp del tunnel tunnel_id "$tunnel"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.