Created
May 2, 2015 17:48
-
-
Save dangowrt/a1b816b509a8def28c0e to your computer and use it in GitHub Desktop.
/etc/network/l2tpv3.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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