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