source: packages/net/l2tpv3tun/files/l2tp.sh @ 22549

Last change on this file since 22549 was 22549, checked in by jow, 6 years ago

[packages] l2tpv3tun: add /etc/config/network backend, supports briding, multiple tunnels, session and all options defined by proto static

File size: 4.8 KB
Line 
1# l2tp.sh - L2TPv3 tunnel backend
2# Copyright (c) 2010 OpenWrt.org
3
4l2tp_next_tunnel_id() {
5        local max=0
6        local val
7        for val in $(
8                local l
9                l2tpv3tun show tunnel | while read l; do
10                        case "$l" in
11                                Tunnel*,*encap*) l="${l#Tunnel }"; echo "${l%%,*}";;
12                        esac
13                done
14        ); do
15                [ "$val" -gt "$max" ] && max="$val"
16        done
17        echo $((max + 1))
18}
19
20l2tp_next_session_id() {
21        local tunnel="$1"
22        local max=0
23        local val
24        for val in $(
25                local l
26                l2tpv3tun show session${tunnel:+ tunnel_id "$tunnel"} | while read l; do
27                        case "$l" in
28                                Session*in*) l="${l#Session }"; echo "${l%% *}";;
29                        esac
30                done
31        ); do
32                [ "$val" -gt "$max" ] && max="$val"
33        done
34        echo $((max + 1))
35}
36
37l2tp_tunnel_exists() {
38        test -n "$(l2tpv3tun show tunnel tunnel_id "$1" 2>/dev/null)"
39}
40
41l2tp_session_exists() {
42        test -n "$(l2tpv3tun show session tunnel_id "$1" session_id "$2" 2>/dev/null)"
43}
44
45l2tp_ifname() {
46        l2tpv3tun show session tunnel_id "$1" session_id "$2" 2>/dev/null | \
47                sed -ne 's/^.*interface name: //p'
48}
49
50l2tp_lock() {
51        lock /var/lock/l2tp-setup
52}
53
54l2tp_unlock() {
55        lock -u /var/lock/l2tp-setup
56}
57
58l2tp_log() {
59        logger -t "ifup-l2tp" "$@"
60}
61
62
63# Hook into scan_interfaces() to synthesize a .device option
64# This is needed for /sbin/ifup to properly dispatch control
65# to setup_interface_l2tp() even if no .ifname is set in
66# the configuration.
67scan_l2tp() {
68        local dev
69        config_get dev "$1" device
70        config_set "$1" device "${dev:+$dev }l2tp-$1"
71}
72
73coldplug_interface_l2tp() {
74        setup_interface_l2tp "l2tp-$1" "$1"
75}
76
77setup_interface_l2tp() {
78        local iface="$1"
79        local cfg="$2"
80        local link="l2tp-$cfg"
81
82        l2tp_lock
83
84        # prevent recursion
85        local up="$(uci_get_state network "$cfg" up 0)"
86        [ "$up" = 0 ] || {
87                l2tp_unlock
88                return 0
89        }
90
91        local tunnel_id
92        config_get tunnel_id "$cfg" tunnel_id
93        [ -n "$tunnel_id" ] || {
94                tunnel_id="$(l2tp_next_tunnel_id)"
95                uci_set_state network "$cfg" tunnel_id "$tunnel_id"
96                l2tp_log "No tunnel ID specified, assuming $tunnel_id"
97        }
98
99        local peer_tunnel_id
100        config_get peer_tunnel_id "$cfg" peer_tunnel_id
101        [ -n "$peer_tunnel_id" ] || {
102                peer_tunnel_id="$tunnel_id"
103                uci_set_state network "$cfg" peer_tunnel_id "$peer_tunnel_id"
104                l2tp_log "No peer tunnel ID specified, assuming $peer_tunnel_id"
105        }
106
107        local encap
108        config_get encap "$cfg" encap udp
109
110        local sport dport
111        [ "$encap" = udp ] && {
112                config_get sport "$cfg" sport 1701
113                config_get dport "$cfg" dport 1701
114        }
115
116        local peeraddr
117        config_get peeraddr "$cfg" peeraddr
118        [ -z "$peeraddr" ] && config_get peeraddr "$cfg" peer6addr
119
120        local localaddr
121        case "$peeraddr" in
122                *:*) config_get localaddr "$cfg" local6addr ;;
123                *)   config_get localaddr "$cfg" localaddr  ;;
124        esac
125
126        [ -n "$localaddr" -a -n "$peeraddr" ] || {
127                l2tp_log "Missing local or peer address for tunnel $cfg - skipping"
128                return 1
129        }
130
131        (
132                while ! l2tp_tunnel_exists "$tunnel_id"; do
133                        [ -n "$sport" ] && l2tpv3tun show tunnel 2>/dev/null | grep -q "ports: $sport/" && {
134                                l2tp_log "There already is a tunnel with src port $sport - skipping"
135                                l2tp_unlock
136                                return 1
137                        }
138
139                        l2tpv3tun add tunnel tunnel_id "$tunnel_id" peer_tunnel_id "$peer_tunnel_id" \
140                                encap "$encap" local "$localaddr" remote "$peeraddr" \
141                                ${sport:+udp_sport "$sport"} ${dport:+udp_dport "$dport"}
142
143                        # Wait for tunnel
144                        sleep 1
145                done
146
147
148                local session_id
149                config_get session_id "$cfg" session_id
150                [ -n "$session_id" ] || {
151                        session_id="$(l2tp_next_session_id "$tunnel_id")"
152                        uci_set_state network "$cfg" session_id "$session_id"
153                        l2tp_log "No session ID specified, assuming $session_id"
154                }
155
156                local peer_session_id
157                config_get peer_session_id "$cfg" peer_session_id
158                [ -n "$peer_session_id" ] || {
159                        peer_session_id="$session_id"
160                        uci_set_state network "$cfg" peer_session_id "$peer_session_id"
161                        l2tp_log "No peer session ID specified, assuming $peer_session_id"
162                }
163
164
165                while ! l2tp_session_exists "$tunnel_id" "$session_id"; do
166                        l2tpv3tun add session ifname "$link" tunnel_id "$tunnel_id" \
167                                session_id "$session_id" peer_session_id "$peer_session_id"
168
169                        # Wait for session
170                        sleep 1
171                done
172
173
174                local dev
175                config_get dev "$cfg" device
176
177                local ifn
178                config_get ifn "$cfg" ifname
179
180                uci_set_state network "$cfg" ifname "${ifn:-$dev}"
181                uci_set_state network "$cfg" device "$dev"
182
183                local mtu
184                config_get mtu "$cfg" mtu 1462
185
186                local ttl
187                config_get ttl "$cfg" ttl
188
189                ip link set mtu "$mtu" ${ttl:+ ttl "$ttl"} dev "$link"
190
191                # IP setup inherited from proto static
192                prepare_interface "$link" "$cfg"
193                setup_interface_static "${ifn:-$dev}" "$cfg"
194
195                ip link set up dev "$link"
196
197                uci_set_state network "$cfg" up 1
198                l2tp_unlock
199        ) &
200}
201
202stop_interface_l2tp() {
203        local cfg="$1"
204        local link="l2tp-$cfg"
205
206        local tunnel=$(uci_get_state network "$cfg" tunnel_id)
207        local session=$(uci_get_state network "$cfg" session_id)
208
209        [ -n "$tunnel" ] && [ -n "$session" ] && {
210                l2tpv3tun del session tunnel_id "$tunnel" session_id "$session"
211                l2tpv3tun del tunnel tunnel_id "$tunnel"
212        }
213}
Note: See TracBrowser for help on using the repository browser.