1 |
commit: 97da3ab2158db402fd20b440cefe7a7be7501d6d |
2 |
Author: Emeric Verschuur <emeric <AT> mbedsys <DOT> org> |
3 |
AuthorDate: Sun May 1 11:11:16 2016 +0000 |
4 |
Commit: Robin H. Johnson <robbat2 <AT> gentoo <DOT> org> |
5 |
CommitDate: Sun May 1 11:11:16 2016 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/netifrc.git/commit/?id=97da3ab2 |
7 |
|
8 |
Adding L2TP (v3) module (net/l2tp.sh) to support L2TPv3 link |
9 |
|
10 |
doc/net.example.Linux.in | 24 +++++++ |
11 |
net/l2tp.sh | 169 +++++++++++++++++++++++++++++++++++++++++++++++ |
12 |
2 files changed, 193 insertions(+) |
13 |
|
14 |
diff --git a/doc/net.example.Linux.in b/doc/net.example.Linux.in |
15 |
index f65c03d..72608bb 100644 |
16 |
--- a/doc/net.example.Linux.in |
17 |
+++ b/doc/net.example.Linux.in |
18 |
@@ -985,6 +985,30 @@ |
19 |
#relay_6to4="192.168.3.2" |
20 |
#suffix_6to4=":ff" |
21 |
|
22 |
+# For L2TP (v3) link |
23 |
+# WARNING: sys-apps/iproute2 is required to use this module |
24 |
+# You may have to add "l2tp" to modules list |
25 |
+# |
26 |
+# A L2 link between need a session within a tunnel |
27 |
+# 1 session <=> 1 interface and 1 tunnel <=> n session(s) |
28 |
+# a tunnel can host several session (shared by several interfaces) |
29 |
+# |
30 |
+# Example to create 3 L2TPv3 links where (see man ip, iproute2 manual for more details): |
31 |
+# * l2tpeth0 and l2tpeth1 are tho sessions into a same (shared) tunnel (encap IP) |
32 |
+# * l2tpeth2 is a session into an separate tunnel (encap UDP) |
33 |
+# |
34 |
+#l2tptunnel_l2tpeth0="remote 1.2.3.4 local 1.2.4.3 encap ip tunnel_id 1 peer_tunnel_id 1" |
35 |
+#l2tpsession_l2tpeth0="tunnel_id 1 session_id 1 peer_session_id 1" |
36 |
+#config_l2tpeth="10.100.0.1/24" |
37 |
+# |
38 |
+#l2tptunnel_l2tpeth1="remote 1.2.3.4 local 1.2.4.3 encap ip tunnel_id 1 peer_tunnel_id 1" |
39 |
+#l2tpsession_l2tpeth1="tunnel_id 1 session_id 2 peer_session_id 2" |
40 |
+#config_l2tpeth1="10.100.1.1/24" |
41 |
+# |
42 |
+#l2tptunnel_l2tpeth2="remote 1.2.3.4 local 1.2.4.3 encap udp tunnel_id 2 peer_tunnel_id 2 udp_sport 5000 udp_dport 6000" |
43 |
+#l2tpsession_l2tpeth2="tunnel_id 2 session_id 1 peer_session_id 1" |
44 |
+#config_l2tpeth2="10.100.2.1/24" |
45 |
+ |
46 |
#----------------------------------------------------------------------------- |
47 |
# Advanced Routing |
48 |
# WARNING: For advanced routing you MUST be using sys-apps/iproute2 |
49 |
|
50 |
diff --git a/net/l2tp.sh b/net/l2tp.sh |
51 |
new file mode 100644 |
52 |
index 0000000..24f5f8c |
53 |
--- /dev/null |
54 |
+++ b/net/l2tp.sh |
55 |
@@ -0,0 +1,169 @@ |
56 |
+# Copyright (c) 2016 Emeric Verschuur <emeric@×××××××.org> |
57 |
+# All rights reserved. Released under the 2-clause BSD license. |
58 |
+ |
59 |
+l2tp_depend() |
60 |
+{ |
61 |
+ program ip |
62 |
+ before bridge interface macchanger |
63 |
+} |
64 |
+ |
65 |
+# Extract parameter list to shell vars |
66 |
+# 1. variable prefix |
67 |
+# 2. string to parse |
68 |
+_l2tp_eval_props() { |
69 |
+ local prop_pref=$1 |
70 |
+ local prop_list=$2 |
71 |
+ eval set -- "$3" |
72 |
+ while [ -n "$1" ]; do |
73 |
+ eval "case $1 in |
74 |
+ $prop_list) |
75 |
+ $prop_pref$1=\"$2\" |
76 |
+ shift |
77 |
+ shift |
78 |
+ ;; |
79 |
+ *) |
80 |
+ l2tp_err=\"invalid property $1\" |
81 |
+ return 1 |
82 |
+ ;; |
83 |
+ |
84 |
+ esac" || return 1 |
85 |
+ done |
86 |
+ return 0 |
87 |
+} |
88 |
+ |
89 |
+_is_l2tp() { |
90 |
+ eval "$(ip l2tp show session | \ |
91 |
+ awk "match(\$0, /^Session ([0-9]+) in tunnel ([0-9]+)\$/, ret) {sid=ret[1]; tid=ret[2]} |
92 |
+ match(\$0, /^[ ]*interface name: ${IFACE}\$/) {print \"session_id=\"sid\";tunnel_id=\"tid; exit}")" |
93 |
+ test -n "$session_id" |
94 |
+} |
95 |
+ |
96 |
+# Get tunnel info |
97 |
+# 1. Output variable prefix |
98 |
+# 2. Tunnel ID to find |
99 |
+_l2tp_get_tunnel_info() { |
100 |
+ local found |
101 |
+ eval "$(ip l2tp show tunnel | \ |
102 |
+ awk -v id=$2 -v prefix=$1 ' |
103 |
+ match($0, /^Tunnel ([0-9]+), encap (IP|UDP)$/, ret) { |
104 |
+ if (found == "1") exit; |
105 |
+ if (ret[1] == id) { |
106 |
+ print "found=1;" |
107 |
+ print prefix "tunnel_id=" ret[1] ";" |
108 |
+ print prefix "encap=" ret[2] ";"; |
109 |
+ found="1" |
110 |
+ } |
111 |
+ } |
112 |
+ match($0, /^[ ]*From ([^ ]+) to ([^ ]+)$/, ret) { |
113 |
+ if (found == "1") { |
114 |
+ print prefix "local=" ret[1] ";"; |
115 |
+ print prefix "remote=" ret[2] ";"; |
116 |
+ } |
117 |
+ } |
118 |
+ match($0, /^[ ]*Peer tunnel ([0-9]+)$/, ret) { |
119 |
+ if (found == "1") { |
120 |
+ print prefix "peer_tunnel_id=" ret[1] ";"; |
121 |
+ } |
122 |
+ } |
123 |
+ match($0, /^[ ]*UDP source \/ dest ports: ([0-9]+)\/([0-9]+)$/, ret) { |
124 |
+ if (found == "1") { |
125 |
+ print prefix "udp_sport=" ret[1] ";"; |
126 |
+ print prefix "udp_dport=" ret[2] ";"; |
127 |
+ } |
128 |
+ }')" |
129 |
+ test -n "$found" |
130 |
+} |
131 |
+ |
132 |
+_ip_l2tp_add() { |
133 |
+ local e |
134 |
+ e="$(LC_ALL=C ip l2tp add $@ 2>&1 1>/dev/null)" |
135 |
+ case $e in |
136 |
+ "") |
137 |
+ return 0 |
138 |
+ ;; |
139 |
+ "RTNETLINK answers: No such process") |
140 |
+ # seems to not be a fatal error but I don't know why I have this error... hmmm |
141 |
+ ewarn "ip l2tp add $2 error: $e" |
142 |
+ return 0 |
143 |
+ ;; |
144 |
+ *) |
145 |
+ eend 1 "ip l2tp add $2 error: $e" |
146 |
+ return 1 |
147 |
+ ;; |
148 |
+ esac |
149 |
+ |
150 |
+} |
151 |
+ |
152 |
+l2tp_pre_start() |
153 |
+{ |
154 |
+ local l2tpsession= |
155 |
+ eval l2tpsession=\$l2tpsession_${IFVAR} |
156 |
+ test -n "${l2tpsession}" || return 0 |
157 |
+ |
158 |
+ ebegin "Creating L2TP tunnel ${IFVAR}" |
159 |
+ local l2tp_err s_name s_tunnel_id s_session_id s_peer_session_id s_cookie s_peer_cookie s_offset s_peer_offset s_l2spec_type |
160 |
+ if ! _l2tp_eval_props s_ "name|tunnel_id|session_id|peer_session_id|cookie|peer_cookie|offset|peer_offset|l2spec_type" "${l2tpsession}"; then |
161 |
+ eend 1 "l2tpsession_${IFVAR} syntax error: $l2tp_err" |
162 |
+ return 1 |
163 |
+ fi |
164 |
+ if [ -n "$s_name" ]; then |
165 |
+ eend 1 "l2tpsession_${IFVAR} error: please remove the \"name\" parameter (this parameter is managed by the system)" |
166 |
+ return 1 |
167 |
+ fi |
168 |
+ # Try to load mendatory l2tp_eth kernel module |
169 |
+ if ! modprobe l2tp_eth; then |
170 |
+ eend 1 "l2tp_eth module not present in your kernel (please enable CONFIG_L2TP_ETH option in your kernel config)" |
171 |
+ return 1 |
172 |
+ fi |
173 |
+ local l2tptunnel= |
174 |
+ eval l2tptunnel=\$l2tptunnel_${IFVAR} |
175 |
+ if [ -n "${l2tptunnel}" ]; then |
176 |
+ local t_tunnel_id t_encap t_local t_remote t_peer_tunnel_id t_udp_sport t_udp_dport |
177 |
+ _l2tp_eval_props t_ "remote|local|encap|tunnel_id|peer_tunnel_id|encap|udp_sport|udp_dport" "${l2tptunnel}" |
178 |
+ # if encap=ip we need l2tp_ip kernel module |
179 |
+ if [ "${t_encap^^}" = "IP" ] && ! modprobe l2tp_ip; then |
180 |
+ eend 1 "l2tp_ip module not present in your kernel (please enable CONFIG_L2TP_IP option in your kernel config)" |
181 |
+ return 1 |
182 |
+ fi |
183 |
+ # Search for an existing tunnel with the same ID |
184 |
+ local f_tunnel_id f_encap f_local f_remote f_peer_tunnel_id f_udp_sport f_udp_dport |
185 |
+ if _l2tp_get_tunnel_info f_ $t_tunnel_id; then |
186 |
+ # check if the existing tunnel has the same property than expected |
187 |
+ if [ "tunnel_id:$f_tunnel_id;encap:$f_encap;local:$f_local;remote:$f_remote; |
188 |
+ peer_tunnel_id:$f_peer_tunnel_id;udp_sport:$f_udp_sport;udp_dport:$f_udp_dport" \ |
189 |
+ != "tunnel_id:$t_tunnel_id;encap:${t_encap^^};local:$t_local;remote:$t_remote; |
190 |
+ peer_tunnel_id:$t_peer_tunnel_id;udp_sport:$t_udp_sport;udp_dport:$t_udp_dport" ]; then |
191 |
+ eend 1 "There are an existing tunnel with id=$s_tunnel_id, but the properties mismatch with the one you want to create" |
192 |
+ return 1 |
193 |
+ fi |
194 |
+ else |
195 |
+ veinfo ip l2tp add tunnel ${l2tptunnel} |
196 |
+ _ip_l2tp_add tunnel ${l2tptunnel} || return 1 |
197 |
+ fi |
198 |
+ elif ! ip l2tp show tunnel | grep -Eq "^Tunnel $s_tunnel_id,"; then |
199 |
+ # no l2tptunnel_<INTF> declaration, assume that the tunnel is already present |
200 |
+ # checking if tunnel_id exists otherwise raise an error |
201 |
+ eend 1 "Tunnel id=$s_tunnel_id no found (you may have to set l2tptunnel_${IFVAR})" |
202 |
+ return 1 |
203 |
+ fi |
204 |
+ veinfo ip l2tp add session ${l2tpsession} name "${IFACE}" |
205 |
+ _ip_l2tp_add session ${l2tpsession} name "${IFACE}" || return 1 |
206 |
+ _up |
207 |
+} |
208 |
+ |
209 |
+ |
210 |
+l2tp_post_stop() |
211 |
+{ |
212 |
+ local session_id tunnel_id |
213 |
+ _is_l2tp || return 0 |
214 |
+ |
215 |
+ ebegin "Destroying L2TP tunnel ${IFACE}" |
216 |
+ veinfo ip l2tp del session tunnel_id $tunnel_id session_id $session_id |
217 |
+ ip l2tp del session tunnel_id $tunnel_id session_id $session_id |
218 |
+ if ! ip l2tp show session | grep -Eq "^Session [0-9]+ in tunnel $tunnel_id\$"; then |
219 |
+ #tunnel $tunnel_id no longer used, destoying it... |
220 |
+ veinfo ip l2tp del tunnel tunnel_id $tunnel_id |
221 |
+ ip l2tp del tunnel tunnel_id $tunnel_id |
222 |
+ fi |
223 |
+ eend $? |
224 |
+} |