[packages] radvd: fix a config_get_bool call in initscript, fixes "sh: bad number...
[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 RADVD_ROUTE_BOOLEAN_OPTIONS=''
13
14 RADVD_RDNSS_STRING_OPTIONS='AdvRDNSSPreference AdvRDNSSLifetime'
15 RADVD_RDNSS_BOOLEAN_OPTIONS='AdvRDNSSOpen'
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                 for name in $RADVD_ROUTE_BOOLEAN_OPTIONS; do
259                         config_get value "$cfg" "$name"
260                         [ -z "$value" ] && continue
261                         config_get_bool value "$cfg" "$name" 0
262                         if [ "$value" -ne 0 ]; then 
263                                 printf '\t\t%s on;\n' "$name"
264                         else
265                                 printf '\t\t%s off;\n' "$name"
266                         fi
267                 done
268
269                 printf '\t};\n'
270         done
271
272         return 0
273 }
274
275 radvd_write_rdnss() {
276         local cfg=$1
277         validate_varname "$cfg" || return 0
278         local ignore
279         local interfaces
280         local interface
281         local addrs
282         local addr
283         local addr_list
284         local name
285         local value
286         local i
287
288         config_get_bool ignore "$cfg" ignore 0
289         [ "$ignore" -ne 0 ] && return 0
290
291         config_get interfaces "$cfg" interface
292         exist=0
293         for interface in $interfaces; do
294                 [ "$INTERFACE" = "$interface" ] && exist=1
295         done
296         [ "$exist" -eq 0 ] && return 0
297
298         config_get addrs "$cfg" addr
299         i=0
300         for addr in $addrs; do
301                 [ "$i" -ge 3 ] && break
302                 validate_ip6addr "$addr" || continue
303                 addr_list="$addr_list $addr"
304                 i=$(($i+1))
305         done
306
307         if [ -z "$addr_list" ]; then
308                 addr=$(get_ip6addr "$IFNAME" link) || return 0
309                 addr_list=" ${addr%%[/]*}"
310         fi
311
312         printf '\n\tRDNSS%s\n\t{\n' "$addr_list"
313
314         for name in $RADVD_RDNSS_STRING_OPTIONS; do
315                 config_get value "$cfg" "$name"
316                 validate_radvd_string "$value" || continue
317                 printf '\t\t%s %s;\n' "$name" "$value"
318         done
319
320         for name in $RADVD_RDNSS_BOOLEAN_OPTIONS; do
321                 config_get value "$cfg" "$name"
322                 [ -z "$value" ] && continue
323                 config_get_bool value "$cfg" "$name" 0
324                 if [ "$value" -ne 0 ]; then 
325                         printf '\t\t%s on;\n' "$name"
326                 else
327                         printf '\t\t%s off;\n' "$name"
328                 fi
329         done
330
331         printf '\t};\n'
332
333         return 0
334 }
335
336 radvd_write_config() {
337         include /lib/network
338
339         RADVD_INTERFACES=
340         config_foreach radvd_add_interface interface
341         config_foreach radvd_add_interface prefix
342         config_foreach radvd_add_interface route
343         config_foreach radvd_add_interface RDNSS
344
345         for INTERFACE in $RADVD_INTERFACES; do
346                 IFNAME=$(get_ifname "$INTERFACE") || continue
347                 printf 'interface %s\n{\n' "$IFNAME"
348                 config_foreach radvd_write_interface interface
349                 config_foreach radvd_write_prefix prefix
350                 config_foreach radvd_write_route route
351                 config_foreach radvd_write_rdnss rdnss
352                 printf '};\n\n'
353         done
354
355         return 0
356 }
357
358 start() {
359         config_load radvd
360
361         RADVD_CONFIG_FILE=
362         config_foreach radvd_find_config_file radvd
363
364         if [ -z "$RADVD_CONFIG_FILE" ]; then
365                 mkdir -p -- /var/etc/
366                 radvd_write_config > /var/etc/radvd.conf
367                 if [ -s "/var/etc/radvd.conf" ]; then
368                         RADVD_CONFIG_FILE=/var/etc/radvd.conf
369                 fi
370         fi
371
372         [ -z "$RADVD_CONFIG_FILE" ] && return 1
373
374         sysctl -w net.ipv6.conf.all.forwarding=1 > /dev/null 2> /dev/null
375
376         radvd -C "$RADVD_CONFIG_FILE" -m stderr_syslog -p /var/run/radvd.pid
377 }
378
379 stop() {
380         killall radvd
381 }