6to4: load the network config to fix radvd announce (#11467)
[openwrt.git] / package / 6to4 / files / 6to4.sh
1 #!/bin/sh
2 # 6to4.sh - IPv6-in-IPv4 tunnel backend
3 # Copyright (c) 2010-2012 OpenWrt.org
4
5 [ -n "$INCLUDE_ONLY" ] || {
6         . /etc/functions.sh
7         . ../netifd-proto.sh
8         init_proto "$@"
9 }
10
11 find_6to4_wanif() {
12         local if=$(ip -4 r l e 0.0.0.0/0); if="${if#default* dev }"; if="${if%% *}"
13         [ -n "$if" ] && grep -qs "^ *$if:" /proc/net/dev && echo "$if"
14 }
15
16 find_6to4_wanip() {
17         local ip=$(ip -4 a s dev "$1"); ip="${ip#*inet }"
18         echo "${ip%%[^0-9.]*}"
19 }
20
21 find_6to4_prefix() {
22         local ip4="$1"
23         local oIFS="$IFS"; IFS="."; set -- $ip4; IFS="$oIFS"
24
25         printf "2002:%02x%02x:%02x%02x\n" $1 $2 $3 $4
26 }
27
28 test_6to4_rfc1918()
29 {
30         local oIFS="$IFS"; IFS="."; set -- $1; IFS="$oIFS"
31         [ $1 -eq  10 ] && return 0
32         [ $1 -eq 192 ] && [ $2 -eq 168 ] && return 0
33         [ $1 -eq 172 ] && [ $2 -ge  16 ] && [ $2 -le  31 ] && return 0
34
35         # RFC 6598
36         [ $1 -eq 100 ] && [ $2 -ge  64 ] && [ $2 -le 127 ] && return 0
37
38         return 1
39 }
40
41 set_6to4_radvd_interface() {
42         local cfgid="$1"
43         local lanif="${2:-lan}"
44         local ifmtu="${3:-1280}"
45         local ifsection=""
46
47         find_ifsection() {
48                 local net
49                 local cfg="$1"
50                 config_get net "$cfg" interface
51
52                 [ "$net" = "$lanif" ] && {
53                         ifsection="$cfg"
54                         return 1
55                 }
56         }
57
58         config_foreach find_ifsection interface
59
60         [ -z "$ifsection" ] && {
61                 ifsection="iface_$sid"
62                 uci_set_state radvd "$ifsection" "" interface
63                 uci_set_state radvd "$ifsection" interface "$lanif"
64         }
65
66         uci_set_state radvd "$ifsection" ignore            0
67         uci_set_state radvd "$ifsection" IgnoreIfMissing   1
68         uci_set_state radvd "$ifsection" AdvSendAdvert     1
69         uci_set_state radvd "$ifsection" MaxRtrAdvInterval 30
70         uci_set_state radvd "$ifsection" AdvLinkMTU        "$ifmtu"
71 }
72
73 set_6to4_radvd_prefix() {
74         local cfgid="$1"
75         local lanif="${2:-lan}"
76         local wanif="${3:-wan}"
77         local prefix="${4:-0:0:0:1::/64}"
78         local vlt="${5:-300}"
79         local plt="${6:-120}"
80         local pfxsection=""
81
82         find_pfxsection() {
83                 local net base
84                 local cfg="$1"
85                 config_get net  "$cfg" interface
86                 config_get base "$cfg" Base6to4Interface
87
88                 [ "$net" = "$lanif" ] && [ "$base" = "$wanif" ] && {
89                         pfxsection="$cfg"
90                         return 1
91                 }
92         }
93
94         config_foreach find_pfxsection prefix
95
96         [ -z "$pfxsection" ] && {
97                 pfxsection="prefix_${sid}_${lanif}"
98                 uci_set_state radvd "$pfxsection" ""                   prefix
99                 uci_set_state radvd "$pfxsection" ignore               0
100                 uci_set_state radvd "$pfxsection" interface            "$lanif"
101                 uci_set_state radvd "$pfxsection" prefix               "$prefix"
102                 uci_set_state radvd "$pfxsection" AdvOnLink            1
103                 uci_set_state radvd "$pfxsection" AdvAutonomous        1
104                 uci_set_state radvd "$pfxsection" AdvValidLifetime     "$vlt"
105                 uci_set_state radvd "$pfxsection" AdvPreferredLifetime "$plt"
106                 uci_set_state radvd "$pfxsection" Base6to4Interface    "$wanif"
107         }
108 }
109
110 tun_error() {
111         local cfg="$1"; shift;
112
113         [ -n "$1" ] && proto_notify_error "$cfg" "$@"
114         proto_block_restart "$cfg"
115 }
116
117 proto_6to4_setup() {
118         local cfg="$1"
119         local iface="$2"
120         local link="6to4-$cfg"
121
122         json_get_var mtu mtu
123         json_get_var ttl ttl
124         json_get_var local4 ipaddr
125
126         json_get_var adv_subnet adv_subnet
127         json_get_var adv_interface adv_interface
128         json_get_var adv_valid_lifetime adv_valid_lifetime
129         json_get_var adv_preferred_lifetime adv_preferred_lifetime
130
131         local wanif=$(find_6to4_wanif)
132         [ -z "$wanif" ] && {
133                 tun_error "$cfg" "NO_WAN_LINK"
134                 return
135         }
136
137         . /lib/network/config.sh
138         local wancfg="$(find_config "$wanif")"
139         [ -z "$wancfg" ] && {
140                 tun_error "$cfg" "NO_WAN_LINK"
141                 return
142         }
143
144         # If local4 is unset, guess local IPv4 address from the
145         # interface used by the default route.
146         [ -z "$local4" ] && {
147                 [ -n "$wanif" ] && local4=$(find_6to4_wanip "$wanif")
148         }
149
150         [ -z "$local4" ] && {
151                 tun_error "$cfg" "NO_WAN_LINK"
152                 return
153         }
154
155         test_6to4_rfc1918 "$local4" && {
156                 tun_error "$cfg" "INVALID_LOCAL_ADDRESS"
157                 return
158         }
159
160         # find our local prefix
161         local prefix6=$(find_6to4_prefix "$local4")
162         local local6="$prefix6::1"
163
164         proto_init_update "$link" 1
165         proto_add_ipv6_address "$local6" 16
166         proto_add_ipv6_route "::" 0 "::192.88.99.1"
167
168         proto_add_tunnel
169         json_add_string mode sit
170         json_add_int mtu "${mtu:-1280}"
171         json_add_int ttl "${ttl:-64}"
172         json_add_string local "$local4"
173         proto_close_tunnel
174
175         proto_send_update "$cfg"
176
177         [ -f /etc/config/radvd ] && /etc/init.d/radvd enabled && {
178                 local sid="6to4_$cfg"
179
180                 uci_revert_state radvd
181                 config_load radvd
182                 config_load network
183
184                 adv_subnet=$((0x${adv_subnet:-1}))
185
186                 local adv_subnets=""
187
188                 for adv_interface in ${adv_interface:-lan}; do
189                         local adv_ifname
190                         config_get adv_ifname "${adv_interface:-lan}" ifname
191
192                         grep -qs "^ *$adv_ifname:" /proc/net/dev && {
193                                 local subnet6="$(printf "%s:%x::1/64" "$prefix6" $adv_subnet)"
194
195                                 logger -t "$link" " * Advertising IPv6 subnet $subnet6 on ${adv_interface:-lan} ($adv_ifname)"
196                                 ip -6 addr add $subnet6 dev $adv_ifname
197
198                                 set_6to4_radvd_interface "$sid" "$adv_interface" "$mtu"
199                                 set_6to4_radvd_prefix    "$sid" "$adv_interface" \
200                                         "$wancfg" "$(printf "0:0:0:%x::/64" $adv_subnet)" \
201                                         "$adv_valid_lifetime" "$adv_preferred_lifetime"
202
203                                 adv_subnets="${adv_subnets:+$adv_subnets }$adv_ifname:$subnet6"
204                                 adv_subnet=$(($adv_subnet + 1))
205                         }
206                 done
207
208                 uci_set_state network "$cfg" adv_subnets "$adv_subnets"
209
210                 /etc/init.d/radvd restart
211         }
212 }
213
214 proto_6to4_teardown() {
215         local cfg="$1"
216         local link="6to4-$cfg"
217
218         local adv_subnets=$(uci_get_state network "$cfg" adv_subnets)
219
220         grep -qs "^ *$link:" /proc/net/dev && {
221                 [ -n "$adv_subnets" ] && {
222                         uci_revert_state radvd
223                         /etc/init.d/radvd enabled && /etc/init.d/radvd restart
224                 }
225         }
226 }
227
228 proto_6to4_init_config() {
229         no_device=1
230         available=1
231
232         proto_config_add_string "ipaddr"
233         proto_config_add_int "mtu"
234         proto_config_add_int "ttl"
235         proto_config_add_string "adv_interface"
236         proto_config_add_string "adv_subnet"
237         proto_config_add_int "adv_valid_lifetime"
238         proto_config_add_int "adv_preferred_lifetime"
239 }
240
241 [ -n "$INCLUDE_ONLY" ] || {
242         add_protocol 6to4
243 }