[packages] radvd: revert r25424 for now as it seems to cause problems in various...
[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         config_get clients "$cfg" client
163         if [ -n "$clients" ]; then
164                 printf '\n\tclients\n\t{\n'
165
166                 for client in $clients; do
167                         validate_ip6addr "$client" || continue
168                         printf '\t\t%s;\n' "$client"
169                 done
170
171                 printf '\t};\n'
172         fi
173
174         return 0
175 }
176
177 radvd_write_prefix() {
178         local cfg=$1
179         validate_varname "$cfg" || return 0
180         local ignore
181         local interfaces
182         local interface
183         local prefixes
184         local prefix
185         local name
186         local value
187         local cfgt
188
189         config_get_bool ignore "$cfg" ignore 0
190         [ "$ignore" -ne 0 ] && return 0
191
192         config_get interfaces "$cfg" interface
193         exist=0
194         for interface in $interfaces; do
195                 [ "$INTERFACE" = "$interface" ] && exist=1
196         done
197         [ "$exist" -eq 0 ] && return 0
198
199         config_get prefixes "$cfg" prefix
200         if [ -z "$prefixes" ]; then
201                 prefixes=$(get_ip6addr "$IFNAME") || return 0
202         fi
203
204         for prefix in $prefixes; do
205                 validate_ip6prefix "$prefix" || continue
206                 printf '\n\tprefix %s\n\t{\n' "$prefix"
207
208                 for name in $RADVD_PREFIX_STRING_OPTIONS; do
209                         config_get value "$cfg" "$name"
210                         validate_radvd_string "$value" || continue
211                         printf '\t\t%s %s;\n' "$name" "$value"
212                 done
213
214                 for name in $RADVD_PREFIX_BOOLEAN_OPTIONS; do
215                         config_get value "$cfg" "$name"
216                         [ -z "$value" ] && continue
217                         config_get_bool value "$cfg" "$name" 0
218                         if [ "$value" -ne 0 ]; then 
219                                 printf '\t\t%s on;\n' "$name"
220                         else
221                                 printf '\t\t%s off;\n' "$name"
222                         fi
223                 done
224
225                 config_get value "$cfg" Base6to4Interface
226                 if [ -n "$value" ]; then
227                         if ifname=$(get_ifname "$value"); then
228                                 printf '\t\t%s %s;\n' "Base6to4Interface" "$ifname"
229                         fi
230                 fi
231
232                 printf '\t};\n'
233         done
234
235         return 0
236 }
237
238 radvd_write_route() {
239         local cfg=$1
240         validate_varname "$cfg" || return 0
241         local ignore
242         local interfaces
243         local interface
244         local prefixes
245         local prefix
246         local name
247         local value
248
249         config_get_bool ignore "$cfg" ignore 0
250         [ "$ignore" -ne 0 ] && return 0
251
252         config_get interfaces "$cfg" interface
253         exist=0
254         for interface in $interfaces; do
255                 [ "$INTERFACE" = "$interface" ] && exist=1
256         done
257         [ "$exist" -eq 0 ] && return 0
258
259         config_get prefixes "$cfg" prefix
260         for prefix in $prefixes; do
261                 validate_ip6prefix "$prefix" || continue
262                 printf '\n\troute %s\n\t{\n' "$prefix"
263
264                 for name in $RADVD_ROUTE_STRING_OPTIONS; do
265                         config_get value "$cfg" "$name"
266                         validate_radvd_string "$value" || continue
267                         printf '\t\t%s %s;\n' "$name" "$value"
268                 done
269
270                 printf '\t};\n'
271         done
272
273         return 0
274 }
275
276 radvd_write_rdnss() {
277         local cfg=$1
278         validate_varname "$cfg" || return 0
279         local ignore
280         local interfaces
281         local interface
282         local addrs
283         local addr
284         local addr_list
285         local name
286         local value
287         local i
288
289         config_get_bool ignore "$cfg" ignore 0
290         [ "$ignore" -ne 0 ] && return 0
291
292         config_get interfaces "$cfg" interface
293         exist=0
294         for interface in $interfaces; do
295                 [ "$INTERFACE" = "$interface" ] && exist=1
296         done
297         [ "$exist" -eq 0 ] && return 0
298
299         config_get addrs "$cfg" addr
300         i=0
301         for addr in $addrs; do
302                 [ "$i" -ge 3 ] && break
303                 validate_ip6addr "$addr" || continue
304                 addr_list="$addr_list $addr"
305                 i=$(($i+1))
306         done
307
308         if [ -z "$addr_list" ]; then
309                 addr=$(get_ip6addr "$IFNAME" link) || return 0
310                 addr_list=" ${addr%%[/]*}"
311         fi
312
313         printf '\n\tRDNSS%s\n\t{\n' "$addr_list"
314
315         for name in $RADVD_RDNSS_STRING_OPTIONS; do
316                 config_get value "$cfg" "$name"
317                 validate_radvd_string "$value" || continue
318                 printf '\t\t%s %s;\n' "$name" "$value"
319         done
320
321         printf '\t};\n'
322
323         return 0
324 }
325
326 radvd_write_dnssl() {
327         local cfg=$1
328         validate_varname "$cfg" || return 0
329         local ignore
330         local interfaces
331         local interface
332         local suffixes
333         local suffix
334         local suffix_list
335         local name
336         local value
337
338         config_get_bool ignore "$cfg" ignore 0
339         [ "$ignore" -ne 0 ] && return 0
340
341         config_get interfaces "$cfg" interface
342         exist=0
343         for interface in $interfaces; do
344                 [ "$INTERFACE" = "$interface" ] && exist=1
345         done
346         [ "$exist" -eq 0 ] && return 0
347
348         config_get suffixes "$cfg" suffix
349         for suffix in $suffixes; do
350                 validate_radvd_string "$suffix" || continue
351                 suffix_list="$suffix_list $suffix"
352         done
353
354         printf '\n\tDNSSL%s\n\t{\n' "$suffix_list"
355
356         for name in $RADVD_DNSSL_STRING_OPTIONS; do
357                 config_get value "$cfg" "$name"
358                 validate_radvd_string "$value" || continue
359                 printf '\t\t%s %s;\n' "$name" "$value"
360         done
361
362         printf '\t};\n'
363
364         return 0
365 }
366
367 radvd_write_config() {
368         include /lib/network
369
370         RADVD_INTERFACES=
371         config_foreach radvd_add_interface interface
372         config_foreach radvd_add_interface prefix
373         config_foreach radvd_add_interface route
374         config_foreach radvd_add_interface RDNSS
375         config_foreach radvd_add_interface DNSSL
376
377         for INTERFACE in $RADVD_INTERFACES; do
378                 IFNAME=$(get_ifname "$INTERFACE") || continue
379                 printf 'interface %s\n{\n' "$IFNAME"
380                 config_foreach radvd_write_interface interface
381                 config_foreach radvd_write_prefix prefix
382                 config_foreach radvd_write_route route
383                 config_foreach radvd_write_rdnss rdnss
384                 config_foreach radvd_write_dnssl dnssl
385                 printf '};\n\n'
386         done
387
388         return 0
389 }
390
391 start() {
392         config_load radvd
393
394         RADVD_CONFIG_FILE=
395         config_foreach radvd_find_config_file radvd
396
397         if [ -z "$RADVD_CONFIG_FILE" ]; then
398                 mkdir -p -- /var/etc/
399                 radvd_write_config > /var/etc/radvd.conf
400                 if [ -s "/var/etc/radvd.conf" ]; then
401                         RADVD_CONFIG_FILE=/var/etc/radvd.conf
402                 fi
403         fi
404
405         [ -z "$RADVD_CONFIG_FILE" ] && return 1
406
407         sysctl -w net.ipv6.conf.all.forwarding=1 > /dev/null 2> /dev/null
408
409         radvd -C "$RADVD_CONFIG_FILE" -m stderr_syslog -p /var/run/radvd.pid
410 }
411
412 stop() {
413         killall radvd
414 }