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