[PATCH] IPv6 Router Advertisement Daemon 1.1 with UCI Support
[openwrt/svn-archive/archive.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 ignore "$cfg" ignore
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 if grep '^net.ipv6.conf.all.forwarding=1$' /etc/sysctl.conf > /dev/null 2> /dev/null; then
375 sysctl -w net.ipv6.conf.all.forwarding=1 > /dev/null 2> /dev/null
376 fi
377
378 radvd -C "$RADVD_CONFIG_FILE" -m stderr_syslog -p /var/run/radvd.pid
379 }
380
381 stop() {
382 killall radvd
383 }