[packages] radvd: update to 1.7
[packages.git] / ipv6 / radvd / files / radvd.init
1 #!/bin/sh /etc/rc.common
2 # Copyright (C) 2008  Alina Friedrichsen <x-alina@gmx.net>
3 START=50
4
5 RADVD_INTERFACE_STRING_OPTIONS='MaxRtrAdvInterval MinRtrAdvInterval MinDelayBetweenRAs AdvLinkMTU AdvReachableTime AdvRetransTimer AdvCurHopLimit AdvDefaultLifetime AdvDefaultPreference HomeAgentLifetime HomeAgentPreference'
6 RADVD_INTERFACE_BOOLEAN_OPTIONS='IgnoreIfMissing AdvSendAdvert UnicastOnly AdvManagedFlag AdvOtherConfigFlag AdvSourceLLAddress AdvHomeAgentFlag AdvHomeAgentInfo AdvMobRtrSupportFlag AdvIntervalOpt'
7
8 RADVD_PREFIX_STRING_OPTIONS='AdvValidLifetime AdvPreferredLifetime'
9 RADVD_PREFIX_BOOLEAN_OPTIONS='AdvOnLink AdvAutonomous AdvRouterAddr'
10
11 RADVD_ROUTE_STRING_OPTIONS='AdvRouteLifetime AdvRoutePreference'
12
13 RADVD_RDNSS_STRING_OPTIONS='AdvRDNSSLifetime'
14
15 RADVD_DNSSL_STRING_OPTIONS='AdvDNSSLLifetime'
16
17 validate_varname() {
18         local varname=$1
19         [ -z "$varname" -o "$varname" != "${varname%%[!A-Za-z0-9_]*}" ] && return 1
20         return 0
21 }
22
23 validate_ifname() {
24         local ifname=$1
25         [ -z "$ifname" -o "$ifname" != "${ifname%%[!A-Za-z0-9.:_-]*}" ] && return 1
26         return 0
27 }
28
29 validate_ip6addr() {
30         local ip6addr=$1
31         [ -z "$ip6addr" -o "$ip6addr" != "${ip6addr%%[!A-Fa-f0-9.:]*}" ] && return 1
32         return 0
33 }
34
35 validate_ip6prefix() {
36         local ip6prefix=$1
37         [ -z "$ip6prefix" -o "$ip6prefix" != "${ip6prefix%%[!A-Fa-f0-9./:]*}" ] && return 1
38         return 0
39 }
40
41 validate_radvd_string() {
42         local radvd_string=$1
43         [ -z "$radvd_string" -o "$radvd_string" != "${radvd_string%%[!a-z0-9.:_-]*}" ] && return 1
44         return 0
45 }
46
47 get_ifname() {
48         local interface=$1
49         validate_varname "$interface" || return 1
50         local cfgt
51         local ifname
52
53         scan_interfaces
54         config_get cfgt "$interface" TYPE
55         [ "$cfgt" != "interface" ] && return 1
56         config_get ifname "$interface" ifname
57         validate_ifname "$ifname" || return 1
58         printf '%s\n' "$ifname"
59
60         return 0
61 }
62
63 get_ip6addr() {
64         local ifname=$1
65         local scope=$2
66         local iproute2_scope
67         local ifconfig_scope
68         local ip6addr
69
70         case "$scope" in
71                 host) iproute2_scope=host ifconfig_scope=Host;;
72                 link) iproute2_scope=link ifconfig_scope=Link;;
73                 site) iproute2_scope=site ifconfig_scope=Site;;
74                 global) iproute2_scope=global ifconfig_scope=Global;;
75                 "") get_ip6addr "$ifname" global || get_ip6addr "$ifname" site; return;;
76                 *) return 1;;
77         esac
78
79         ip6addr=$(LANG=C ip -f inet6 -- addr show dev "$ifname" 2> /dev/null | sed -n -e 's/^  *inet6 \([A-Fa-f0-9.:]*[/][0-9]*\) scope '"$iproute2_scope"' $/\1/p' | head -n 1)
80         if [ -z "$ip6addr" ]; then
81                 ip6addr=$(LANG=C ifconfig "$ifname" 2> /dev/null | sed -n -e 's/^  *inet6 addr: \([A-Fa-f0-9.:]*[/][0-9]*\) Scope:'"$ifconfig_scope"'$/\1/p' | tail -n 1)
82                 [ -z "$ip6addr" ] && return 1
83         fi
84
85         printf '%s\n' "$ip6addr"
86
87         return 0
88 }
89
90 radvd_find_config_file() {
91         local cfg=$1
92         validate_varname "$cfg" || return 0
93
94         config_get_bool ignore "$cfg" ignore 0
95         [ "$ignore" -ne 0 ] && return 0
96         config_get RADVD_CONFIG_FILE "$cfg" config_file
97
98         return 0
99 }
100
101 radvd_add_interface() {
102         local cfg=$1
103         validate_varname "$cfg" || return 0
104         local ignore
105         local interfaces
106         local interface
107         local list_interface
108         local exist
109
110         config_get_bool ignore "$cfg" ignore 0
111         [ "$ignore" -ne 0 ] && return 0
112
113         config_get interfaces "$cfg" interface
114         for interface in $interfaces; do
115                 validate_varname "$interface" || continue
116                 exist=0
117                 for list_interface in $RADVD_INTERFACES; do
118                         [ "$interface" = "$list_interface" ] && exist=1
119                 done
120                 [ "$exist" -eq 0 ] && RADVD_INTERFACES="$RADVD_INTERFACES $interface"
121         done
122
123         return 0
124 }
125
126 radvd_write_interface() {
127         local cfg=$1
128         validate_varname "$cfg" || return 0
129         local ignore
130         local interfaces
131         local interface
132         local name
133         local value
134
135         config_get_bool ignore "$cfg" ignore 0
136         [ "$ignore" -ne 0 ] && return 0
137
138         config_get interfaces "$cfg" interface
139         exist=0
140         for interface in $interfaces; do
141                 [ "$INTERFACE" = "$interface" ] && exist=1
142         done
143         [ "$exist" -eq 0 ] && return 0
144
145         for name in $RADVD_INTERFACE_STRING_OPTIONS; do
146                 config_get value "$cfg" "$name"
147                 validate_radvd_string "$value" || continue
148                 printf '\t%s %s;\n' "$name" "$value"
149         done
150
151         for name in $RADVD_INTERFACE_BOOLEAN_OPTIONS; do
152                 config_get value "$cfg" "$name"
153                 [ -z "$value" ] && continue
154                 config_get_bool value "$cfg" "$name" 0
155                 if [ "$value" -ne 0 ]; then 
156                         printf '\t%s on;\n' "$name"
157                 else
158                         printf '\t%s off;\n' "$name"
159                 fi
160         done
161
162         return 0
163 }
164
165 radvd_write_prefix() {
166         local cfg=$1
167         validate_varname "$cfg" || return 0
168         local ignore
169         local interfaces
170         local interface
171         local prefixes
172         local prefix
173         local name
174         local value
175         local cfgt
176
177         config_get_bool ignore "$cfg" ignore 0
178         [ "$ignore" -ne 0 ] && return 0
179
180         config_get interfaces "$cfg" interface
181         exist=0
182         for interface in $interfaces; do
183                 [ "$INTERFACE" = "$interface" ] && exist=1
184         done
185         [ "$exist" -eq 0 ] && return 0
186
187         config_get prefixes "$cfg" prefix
188         if [ -z "$prefixes" ]; then
189                 prefixes=$(get_ip6addr "$IFNAME") || return 0
190         fi
191
192         for prefix in $prefixes; do
193                 validate_ip6prefix "$prefix" || continue
194                 printf '\n\tprefix %s\n\t{\n' "$prefix"
195
196                 for name in $RADVD_PREFIX_STRING_OPTIONS; do
197                         config_get value "$cfg" "$name"
198                         validate_radvd_string "$value" || continue
199                         printf '\t\t%s %s;\n' "$name" "$value"
200                 done
201
202                 for name in $RADVD_PREFIX_BOOLEAN_OPTIONS; do
203                         config_get value "$cfg" "$name"
204                         [ -z "$value" ] && continue
205                         config_get_bool value "$cfg" "$name" 0
206                         if [ "$value" -ne 0 ]; then 
207                                 printf '\t\t%s on;\n' "$name"
208                         else
209                                 printf '\t\t%s off;\n' "$name"
210                         fi
211                 done
212
213                 config_get value "$cfg" Base6to4Interface
214                 if [ -n "$value" ]; then
215                         if ifname=$(get_ifname "$value"); then
216                                 printf '\t\t%s %s;\n' "Base6to4Interface" "$ifname"
217                         fi
218                 fi
219
220                 printf '\t};\n'
221         done
222
223         return 0
224 }
225
226 radvd_write_route() {
227         local cfg=$1
228         validate_varname "$cfg" || return 0
229         local ignore
230         local interfaces
231         local interface
232         local prefixes
233         local prefix
234         local name
235         local value
236
237         config_get_bool ignore "$cfg" ignore 0
238         [ "$ignore" -ne 0 ] && return 0
239
240         config_get interfaces "$cfg" interface
241         exist=0
242         for interface in $interfaces; do
243                 [ "$INTERFACE" = "$interface" ] && exist=1
244         done
245         [ "$exist" -eq 0 ] && return 0
246
247         config_get prefixes "$cfg" prefix
248         for prefix in $prefixes; do
249                 validate_ip6prefix "$prefix" || continue
250                 printf '\n\troute %s\n\t{\n' "$prefix"
251
252                 for name in $RADVD_ROUTE_STRING_OPTIONS; do
253                         config_get value "$cfg" "$name"
254                         validate_radvd_string "$value" || continue
255                         printf '\t\t%s %s;\n' "$name" "$value"
256                 done
257
258                 printf '\t};\n'
259         done
260
261         return 0
262 }
263
264 radvd_write_rdnss() {
265         local cfg=$1
266         validate_varname "$cfg" || return 0
267         local ignore
268         local interfaces
269         local interface
270         local addrs
271         local addr
272         local addr_list
273         local name
274         local value
275         local i
276
277         config_get_bool ignore "$cfg" ignore 0
278         [ "$ignore" -ne 0 ] && return 0
279
280         config_get interfaces "$cfg" interface
281         exist=0
282         for interface in $interfaces; do
283                 [ "$INTERFACE" = "$interface" ] && exist=1
284         done
285         [ "$exist" -eq 0 ] && return 0
286
287         config_get addrs "$cfg" addr
288         i=0
289         for addr in $addrs; do
290                 [ "$i" -ge 3 ] && break
291                 validate_ip6addr "$addr" || continue
292                 addr_list="$addr_list $addr"
293                 i=$(($i+1))
294         done
295
296         if [ -z "$addr_list" ]; then
297                 addr=$(get_ip6addr "$IFNAME" link) || return 0
298                 addr_list=" ${addr%%[/]*}"
299         fi
300
301         printf '\n\tRDNSS%s\n\t{\n' "$addr_list"
302
303         for name in $RADVD_RDNSS_STRING_OPTIONS; do
304                 config_get value "$cfg" "$name"
305                 validate_radvd_string "$value" || continue
306                 printf '\t\t%s %s;\n' "$name" "$value"
307         done
308
309         printf '\t};\n'
310
311         return 0
312 }
313
314 radvd_write_dnssl() {
315         local cfg=$1
316         validate_varname "$cfg" || return 0
317         local ignore
318         local interfaces
319         local interface
320         local suffixes
321         local suffix
322         local suffix_list
323         local name
324         local value
325
326         config_get_bool ignore "$cfg" ignore 0
327         [ "$ignore" -ne 0 ] && return 0
328
329         config_get interfaces "$cfg" interface
330         exist=0
331         for interface in $interfaces; do
332                 [ "$INTERFACE" = "$interface" ] && exist=1
333         done
334         [ "$exist" -eq 0 ] && return 0
335
336         config_get suffixes "$cfg" suffix
337         for suffix in $suffixes; do
338                 validate_radvd_string "$suffix" || continue
339                 suffix_list="$suffix_list $suffix"
340         done
341
342         printf '\n\tDNSSL%s\n\t{\n' "$suffix_list"
343
344         for name in $RADVD_DNSSL_STRING_OPTIONS; do
345                 config_get value "$cfg" "$name"
346                 validate_radvd_string "$value" || continue
347                 printf '\t\t%s %s;\n' "$name" "$value"
348         done
349
350         printf '\t};\n'
351
352         return 0
353 }
354
355 radvd_write_clients() {
356         local cfg=$1
357         validate_varname "$cfg" || return 0
358         local ignore
359         local interfaces
360         local interface
361         local clients
362         local client
363
364         config_get_bool ignore "$cfg" ignore 0
365         [ "$ignore" -ne 0 ] && return 0
366
367         config_get interfaces "$cfg" interface
368         exist=0
369         for interface in $interfaces; do
370                 [ "$INTERFACE" = "$interface" ] && exist=1
371         done
372         [ "$exist" -eq 0 ] && return 0
373
374         printf '\n\tclients\n\t{\n'
375
376         config_get clients "$cfg" client
377         for client in $clients; do
378                 validate_ip6addr "$client" || continue
379                 printf '\t\t%s;\n' "$client"
380         done
381
382         printf '\t};\n'
383
384         return 0
385 }
386
387 radvd_write_config() {
388         include /lib/network
389
390         RADVD_INTERFACES=
391         config_foreach radvd_add_interface interface
392         config_foreach radvd_add_interface prefix
393         config_foreach radvd_add_interface route
394         config_foreach radvd_add_interface RDNSS
395         config_foreach radvd_add_interface DNSSL
396         config_foreach radvd_add_interface clients
397
398         for INTERFACE in $RADVD_INTERFACES; do
399                 IFNAME=$(get_ifname "$INTERFACE") || continue
400                 printf 'interface %s\n{\n' "$IFNAME"
401                 config_foreach radvd_write_interface interface
402                 config_foreach radvd_write_prefix prefix
403                 config_foreach radvd_write_route route
404                 config_foreach radvd_write_rdnss rdnss
405                 config_foreach radvd_write_dnssl dnssl
406                 config_foreach radvd_write_clients clients
407                 printf '};\n\n'
408         done
409
410         return 0
411 }
412
413 start() {
414         config_load radvd
415
416         RADVD_CONFIG_FILE=
417         config_foreach radvd_find_config_file radvd
418
419         if [ -z "$RADVD_CONFIG_FILE" ]; then
420                 mkdir -p -- /var/etc/
421                 radvd_write_config > /var/etc/radvd.conf
422                 if [ -s "/var/etc/radvd.conf" ]; then
423                         RADVD_CONFIG_FILE=/var/etc/radvd.conf
424                 fi
425         fi
426
427         [ -z "$RADVD_CONFIG_FILE" ] && return 1
428
429         sysctl -w net.ipv6.conf.all.forwarding=1 > /dev/null 2> /dev/null
430
431         radvd -C "$RADVD_CONFIG_FILE" -m stderr_syslog -p /var/run/radvd.pid
432 }
433
434 stop() {
435         killall radvd
436 }