[packages] l2tpv3tun: add /etc/config/network backend, supports briding, multiple...
[openwrt/svn-archive/archive.git] / net / l2tpv3tun / files / l2tp.sh
1 # l2tp.sh - L2TPv3 tunnel backend
2 # Copyright (c) 2010 OpenWrt.org
3
4 l2tp_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
20 l2tp_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
37 l2tp_tunnel_exists() {
38 test -n "$(l2tpv3tun show tunnel tunnel_id "$1" 2>/dev/null)"
39 }
40
41 l2tp_session_exists() {
42 test -n "$(l2tpv3tun show session tunnel_id "$1" session_id "$2" 2>/dev/null)"
43 }
44
45 l2tp_ifname() {
46 l2tpv3tun show session tunnel_id "$1" session_id "$2" 2>/dev/null | \
47 sed -ne 's/^.*interface name: //p'
48 }
49
50 l2tp_lock() {
51 lock /var/lock/l2tp-setup
52 }
53
54 l2tp_unlock() {
55 lock -u /var/lock/l2tp-setup
56 }
57
58 l2tp_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.
67 scan_l2tp() {
68 local dev
69 config_get dev "$1" device
70 config_set "$1" device "${dev:+$dev }l2tp-$1"
71 }
72
73 coldplug_interface_l2tp() {
74 setup_interface_l2tp "l2tp-$1" "$1"
75 }
76
77 setup_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
202 stop_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 }