liburcu: Update to 0.8.6
[feed/packages.git] / net / fastd / files / fastd.init
1 #!/bin/sh /etc/rc.common
2 # Copyright (C) 2012-2013 OpenWrt.org
3
4 START=95
5
6 SERVICE_USE_PID=1
7
8 EXTRA_COMMANDS="up down show_key generate_key"
9
10 LIST_SEP="
11 "
12 TMP_FASTD=/tmp/fastd
13 FASTD_COMMAND=/usr/bin/fastd
14
15
16 section_enabled() {
17 config_get_bool enabled "$1" 'enabled' 0
18 [ $enabled -gt 0 ]
19 }
20
21 error() {
22 echo "${initscript}:" "$@" 1>&2
23 }
24
25 get_key_instance() {
26 local s="$1"
27
28 config_get secret "$s" secret
29 if [ "$secret" = 'generate' ]; then
30 secret=`"$FASTD_COMMAND" --generate-key --machine-readable`
31 uci -q set fastd."$s".secret="$secret" && uci -q commit fastd
32 fi
33
34 echo "$secret"
35 }
36
37
38 escape_string() {
39 local t=${1//\\/\\\\}
40 echo -n "\"${t//\"/\\\"}\""
41 }
42
43 guard_value() {
44 local t=${1//[^-a-z0-9\[\].:]/}
45 echo -n "$t"
46 }
47
48 guard_remote() {
49 local t=${1//[^-a-zA-Z0-9\[\].:\"% ]/}
50 local quotes=${t//[^\"]/}
51 if [ "${#quotes}" = 0 -o "${#quotes}" = 2 ]; then
52 echo -n "$t"
53 fi
54 }
55
56 yes_no() {
57 case "$1" in
58 0|no|off|false|disabled) echo -n no;;
59 *) echo -n yes;;
60 esac
61 }
62
63 config_string_config='include $(escape_string "$value");'
64 config_string_config_peer='include peer $(escape_string "$value");'
65 config_string_config_peer_dir='include peers from $(escape_string "$value");'
66 config_string_bind='bind $(guard_value "$value");'
67 config_string_method='method $(escape_string "$value");'
68 config_string_syslog_level='log to syslog level $(guard_value "$value");'
69 config_string_mode='mode $(guard_value "$value");'
70 config_string_interface='interface $(escape_string "$value");'
71 config_string_mtu='mtu $(guard_value "$value");'
72 config_string_peer_limit='peer limit $(guard_value "$value");'
73 config_string_user='user $(escape_string "$value");'
74 config_string_group='group $(escape_string "$value");'
75 config_string_pmtu='pmtu $(yes_no "$value");'
76 config_string_forward='forward $(yes_no "$value");'
77 config_string_hide_ip_addresses='hide ip addresses $(yes_no "$value");'
78 config_string_hide_mac_addresses='hide mac addresses $(yes_no "$value");'
79 config_string_secure_handshakes='secure handshakes $(yes_no "$value");'
80 config_string_packet_mark='packet mark $(guard_value "$value");'
81
82 config_string_peer='peer $(escape_string "$value") {'
83 config_string_peer_group='peer group $(escape_string "$value") {'
84
85 peer_string_key='key $(escape_string "$value");'
86 peer_string_float='float $(yes_no "$value");'
87 peer_string_remote='remote $(guard_remote "$value");'
88
89 generate_option() {
90 local __string=$(eval echo \"\$$2\")
91 local value="$1";
92 eval echo "\"$__string\""
93 }
94
95 append_option() {
96 local v; local len; local s="$1"; local prefix="$2"; local p="$3"
97
98 config_get len "$s" "${p}_LENGTH"
99
100 if [ -z "$len" ]; then
101 config_get v "$s" "$p"
102 [ -n "$v" ] && generate_option "$v" "${prefix}_string_${p}"
103 else
104 config_list_foreach "$s" "$p" generate_option "${prefix}_string_${p}"
105 fi
106 }
107
108 append_options() {
109 local p; local s="$1"; local prefix="$2"; shift; shift
110 for p in $*; do
111 append_option "$s" "$prefix" "$p"
112 done
113 }
114
115
116 generate_config_secret() {
117 echo "secret $(escape_string "$1");"
118 }
119
120
121 generate_peer_config() {
122 local peer="$1"
123
124 # These options are deprecated
125 config_get address "$peer" address
126 config_get hostname "$peer" hostname
127 config_get address_family "$peer" address_family
128 config_get port "$peer" port
129
130 if [ "$address" -o "$hostname" ]; then
131 if [ -z "$port" ]; then
132 error "peer $peer: address or hostname, but no port given"
133 return 1
134 fi
135
136 if [ "$hostname" ]; then
137 generate_option peer_string_remote "$address_family \"$hostname\" port $port"
138 fi
139
140 if [ "$address" ]; then
141 generate_option peer_string_remote "$address port $port"
142 fi
143 fi
144
145 append_options "$peer" peer \
146 key float remote
147 }
148
149 generate_single_peer_config() {
150 local peer="$1"; local net="$2"
151
152 config_get peer_net "$peer" net
153 config_get peer_group "$peer" group
154 [ "$net" = "$peer_net" -a "$peer_group" = '' ] || return 0
155
156 section_enabled "$peer" || return 0
157
158 generate_option "$peer" config_string_peer
159 generate_peer_config "$peer"
160 echo '}'
161 }
162
163 create_peer_config() {
164 local peer="$1"; local net="$2"; local group="$3"; local path="$4"
165
166 config_get peer_net "$peer" net
167 config_get peer_group "$peer" group
168 [ "$group" = "$peer_group" ] || return 0
169
170 if [ "$net" != "$peer_net" ]; then
171 [ -z "$group" ] || error "warning: the peer group of peer '$peer' doesn't match its net, the peer will be ignored"
172 return 0
173 fi
174
175 section_enabled "$peer" || return 0
176
177 generate_peer_config "$peer" >"$path/$peer"
178 }
179
180 update_peer_group() {
181 local net="$1"; local group_dir="$2"; local group="$3"; local update_only="$4"
182 local path="$TMP_FASTD/fastd.$net/$group_dir"
183
184 rm -rf "$path"
185 mkdir -p "$path"
186
187 config_foreach create_peer_config 'peer' "$net" "$group" "$path"
188
189 if [ -z "$update_only" ]; then
190 generate_option "$path" config_string_config_peer_dir
191 fi
192
193 config_foreach generate_peer_group_config 'peer_group' "$net" "$group_dir" "$update_only" "$group"
194 }
195
196 generate_peer_group_config() {
197 local group="$1"; local net="$2"; local group_dir="$3%$group"; local update_only="$4"; local parent="$5"
198
199 config_get group_net "$group" net
200 config_get group_parent "$group" parent
201 [ "$parent" = "$group_parent" ] || return 0
202
203 if [ "$net" != "$peer_net" ]; then
204 [ -z "$parent" ] || error "warning: the parent of peer group '$group' doesn't match its net, the peer group will be ignored"
205 return 0
206 fi
207
208 section_enabled "$group" || return 0
209
210 if [ -z "$update_only" ]; then
211 generate_option "$group" config_string_peer_group
212 append_options "$group" config \
213 config config_peer config_peer_dir peer_limit
214 fi
215
216 update_peer_group "$net" "$group_dir" "$group" "$update_only"
217
218 if [ -z "$update_only" ]; then
219 echo '}'
220 fi
221 }
222
223 update_peer_groups() {
224 local net="$1"; local update_only="$2"
225
226 update_peer_group "$net" 'peers' '' "$update_only"
227 }
228
229 generate_config() {
230 local s="$1"
231
232 generate_option 'info' config_string_syslog_level
233
234 append_options "$s" config \
235 config config_peer config_peer_dir bind method syslog_level mode interface mtu peer_limit \
236 user group pmtu forward hide_ip_addresses hide_mac_addresses secure_handshakes packet_mark
237
238 config_get mode "$s" mode
239
240 if [ "$mode" = "tun" ]; then
241 config_foreach generate_single_peer_config 'peer' "$s"
242 else
243 update_peer_groups "$s"
244 fi
245 }
246
247
248 generate_key_instance() {
249 local s="$1"
250
251 config_get secret "$s" secret
252 if [ -z "$secret" -o "$secret" = 'generate' ]; then
253 secret=`fastd --generate-key --machine-readable`
254 uci -q set fastd."$s".secret="$secret" && uci -q commit fastd
255 fi
256
257 generate_config_secret "$secret" | "$FASTD_COMMAND" --config - --show-key --machine-readable
258 }
259
260 show_key_instance() {
261 local s="$1"
262
263 local secret=`get_key_instance "$s"`
264 if [ -z "$secret" ]; then
265 error "$s: secret is not set"
266 return 1
267 fi
268
269 generate_config_secret "$secret" | "$FASTD_COMMAND" --config - --show-key --machine-readable
270 }
271
272 start_instance() {
273 local s="$1"
274
275 section_enabled "$s" || return 1
276
277 SERVICE_PID_FILE="/var/run/fastd.$s.pid"
278
279 config_get interface "$s" interface
280 if [ -z "$interface" ]; then
281 error "$s: interface is not set"
282 return 1
283 fi
284
285 if ifconfig "$interface" &>/dev/null; then
286 error "$s: interface '$interface' is already in use"
287 return 1
288 fi
289
290 config_get mode "$s" mode
291 if [ -z "$mode" ]; then
292 error "$s: mode is not set"
293 return 1
294 fi
295
296 local secret=`get_key_instance "$s"`
297 if [ -z "$secret" ]; then
298 error "$s: secret is not set"
299 return 1
300 fi
301
302 rm -f "$SERVICE_PID_FILE"
303 touch "$SERVICE_PID_FILE"
304
305 config_get user "$s" user
306 if [ "$user" ]; then
307 chown "$user" "$SERVICE_PID_FILE"
308 fi
309
310 (generate_config_secret "$secret"; generate_config "$s") | service_start "$FASTD_COMMAND" --config - --daemon --pid-file "$SERVICE_PID_FILE"
311
312 if ! ifconfig "$interface" >/dev/null 2>&1; then
313 error "$s: startup failed"
314 return 1
315 fi
316
317 config_get up "$s" up
318 [ -n "$up" ] && sh -c "$up" - "$interface"
319 }
320
321 stop_instance() {
322 local s="$1"
323
324 section_enabled "$s" || return 1
325
326 SERVICE_PID_FILE="/var/run/fastd.$s.pid"
327
328 config_get interface "$s" interface
329 if [ -z "$interface" ]; then
330 error "$s: interface is not set"
331 return 1
332 fi
333
334 if ! ifconfig "$interface" &>/dev/null; then
335 error "$s: interface '$interface' does not exist"
336 return 1
337 fi
338
339 config_get down "$s" down
340 [ -n "$down" ] && sh -c "$down" - "$interface"
341
342 service_stop "$FASTD_COMMAND"
343
344 rm -rf "$TMP_FASTD/fastd.$s"
345 }
346
347 reload_instance() {
348 local s="$1"
349
350 section_enabled "$s" || return 1
351
352 config_get mode "$s" mode
353 [ "$mode" = "tun" ] && return 1
354
355 update_peer_groups "$s" true
356
357 SERVICE_PID_FILE="/var/run/fastd.$s.pid"
358 service_reload "$FASTD_COMMAND"
359 }
360
361 start() {
362 config_load 'fastd'
363 config_foreach start_instance 'fastd'
364 return 0
365 }
366
367 stop() {
368 config_load 'fastd'
369 config_foreach stop_instance 'fastd'
370 return 0
371 }
372
373 reload() {
374 config_load 'fastd'
375 config_foreach reload_instance 'fastd'
376 return 0
377 }
378
379 up() {
380 local exists
381 local instance
382 config_load 'fastd'
383 for instance in "$@"; do
384 config_get exists "$instance" 'TYPE'
385 if [ "$exists" = 'fastd' ]; then
386 start_instance "$instance"
387 fi
388 done
389 }
390
391 down() {
392 local exists
393 local instance
394 config_load 'fastd'
395 for instance in "$@"; do
396 config_get exists "$instance" 'TYPE'
397 if [ "$exists" = 'fastd' ]; then
398 stop_instance "$instance"
399 fi
400 done
401 }
402
403 show_key() {
404 local exists
405 local instance
406 config_load 'fastd'
407 for instance in "$@"; do
408 config_get exists "$instance" 'TYPE'
409 if [ "$exists" = 'fastd' ]; then
410 show_key_instance "$instance"
411 fi
412 done
413 }
414
415 generate_key() {
416 local exists
417 local instance
418 config_load 'fastd'
419 for instance in "$@"; do
420 config_get exists "$instance" 'TYPE'
421 if [ "$exists" = 'fastd' ]; then
422 generate_key_instance "$instance"
423 fi
424 done
425 }