IPv6: add class support to regular IPv6 addresses
[project/netifd.git] / scripts / netifd-proto.sh
1 NETIFD_MAIN_DIR="${NETIFD_MAIN_DIR:-/lib/netifd}"
2
3 . /usr/share/libubox/jshn.sh
4 . $NETIFD_MAIN_DIR/utils.sh
5
6 proto_config_add_int() {
7 config_add_int "$@"
8 }
9
10 proto_config_add_string() {
11 config_add_string "$@"
12 }
13
14 proto_config_add_boolean() {
15 config_add_boolean "$@"
16 }
17
18 _proto_do_teardown() {
19 json_load "$data"
20 eval "proto_$1_teardown \"$interface\" \"$ifname\""
21 }
22
23 _proto_do_setup() {
24 json_load "$data"
25 _EXPORT_VAR=0
26 _EXPORT_VARS=
27 eval "proto_$1_setup \"$interface\" \"$ifname\""
28 }
29
30 proto_init_update() {
31 local ifname="$1"
32 local up="$2"
33 local external="$3"
34
35 PROTO_KEEP=0
36 PROTO_INIT=1
37 PROTO_TUNNEL_OPEN=
38 PROTO_IPADDR=
39 PROTO_IP6ADDR=
40 PROTO_ROUTE=
41 PROTO_ROUTE6=
42 PROTO_PREFIX6=
43 PROTO_DNS=
44 PROTO_DNS_SEARCH=
45 json_init
46 json_add_int action 0
47 [ -n "$ifname" -a "*" != "$ifname" ] && json_add_string "ifname" "$ifname"
48 json_add_boolean "link-up" "$up"
49 [ -n "$3" ] && json_add_boolean "address-external" "$external"
50 }
51
52 proto_set_keep() {
53 PROTO_KEEP="$1"
54 }
55
56 proto_close_nested() {
57 [ -n "$PROTO_NESTED_OPEN" ] && json_close_object
58 PROTO_NESTED_OPEN=
59 }
60
61 proto_add_nested() {
62 PROTO_NESTED_OPEN=1
63 json_add_object "$1"
64 }
65
66 proto_add_tunnel() {
67 proto_add_nested "tunnel"
68 }
69
70 proto_close_tunnel() {
71 proto_close_nested
72 }
73
74 proto_add_data() {
75 proto_add_nested "data"
76 }
77
78 proto_close_data() {
79 proto_close_nested
80 }
81
82 proto_add_dns_server() {
83 local address="$1"
84
85 append PROTO_DNS "$address"
86 }
87
88 proto_add_dns_search() {
89 local address="$1"
90
91 append PROTO_DNS_SEARCH "$address"
92 }
93
94 proto_add_ipv4_address() {
95 local address="$1"
96 local mask="$2"
97 local broadcast="$3"
98 local ptp="$4"
99
100 append PROTO_IPADDR "$address/$mask/$broadcast/$ptp"
101 }
102
103 proto_add_ipv6_address() {
104 local address="$1"
105 local mask="$2"
106 local preferred="$3"
107 local valid="$4"
108 local offlink="$5"
109 local class="$6"
110
111 append PROTO_IP6ADDR "$address/$mask/$preferred/$valid/$offlink/$class"
112 }
113
114 proto_add_ipv4_route() {
115 local target="$1"
116 local mask="$2"
117 local gw="$3"
118
119 append PROTO_ROUTE "$target/$mask/$gw//"
120 }
121
122 proto_add_ipv6_route() {
123 local target="$1"
124 local mask="$2"
125 local gw="$3"
126 local metric="$4"
127 local valid="$5"
128 local source="$6"
129
130 append PROTO_ROUTE6 "$target/$mask/$gw/$metric/$valid/$source"
131 }
132
133 proto_add_ipv6_prefix() {
134 local prefix="$1"
135 local valid="$2"
136 local preferred="$3"
137
138 if [ -z "$valid" ]; then
139 append PROTO_PREFIX6 "$prefix"
140 else
141 [ -z "$preferred" ] && preferred="$valid"
142 append PROTO_PREFIX6 "$prefix,$valid,$preferred"
143 fi
144 }
145
146 _proto_push_ipv4_addr() {
147 local str="$1"
148 local address mask broadcast ptp
149
150 address="${str%%/*}"
151 str="${str#*/}"
152 mask="${str%%/*}"
153 str="${str#*/}"
154 broadcast="${str%%/*}"
155 str="${str#*/}"
156 ptp="$str"
157
158 json_add_object ""
159 json_add_string ipaddr "$address"
160 [ -n "$mask" ] && json_add_string mask "$mask"
161 [ -n "$broadcast" ] && json_add_string broadcast "$broadcast"
162 [ -n "$ptp" ] && json_add_string ptp "$ptp"
163 json_close_object
164 }
165
166 _proto_push_ipv6_addr() {
167 local str="$1"
168 local address mask preferred valid offlink
169
170 address="${str%%/*}"
171 str="${str#*/}"
172 mask="${str%%/*}"
173 str="${str#*/}"
174 preferred="${str%%/*}"
175 str="${str#*/}"
176 valid="${str%%/*}"
177 str="${str#*/}"
178 offlink="${str%%/*}"
179 str="${str#*/}"
180 class="${str%%/*}"
181
182 json_add_object ""
183 json_add_string ipaddr "$address"
184 [ -n "$mask" ] && json_add_string mask "$mask"
185 [ -n "$preferred" ] && json_add_int preferred "$preferred"
186 [ -n "$valid" ] && json_add_int valid "$valid"
187 [ -n "$offlink" ] && json_add_boolean offlink "$offlink"
188 [ -n "$class" ] && json_add_string class "$class"
189 json_close_object
190 }
191
192 _proto_push_string() {
193 json_add_string "" "$1"
194 }
195
196 _proto_push_route() {
197 local str="$1";
198 local target="${str%%/*}"
199 str="${str#*/}"
200 local mask="${str%%/*}"
201 str="${str#*/}"
202 local gw="${str%%/*}"
203 str="${str#*/}"
204 local metric="${str%%/*}"
205 str="${str#*/}"
206 local valid="${str%%/*}"
207 str="${str#*/}"
208 local source="${str}"
209
210 json_add_object ""
211 json_add_string target "$target"
212 json_add_string netmask "$mask"
213 [ -n "$gw" ] && json_add_string gateway "$gw"
214 [ -n "$metric" ] && json_add_int metric "$metric"
215 [ -n "$valid" ] && json_add_int valid "$valid"
216 [ -n "$source" ] && json_add_string source "$source"
217 json_close_object
218 }
219
220 _proto_push_array() {
221 local name="$1"
222 local val="$2"
223 local cb="$3"
224
225 [ -n "$val" ] || return 0
226 json_add_array "$name"
227 for item in $val; do
228 eval "$cb \"\$item\""
229 done
230 json_close_array
231 }
232
233 _proto_notify() {
234 local interface="$1"
235 local options="$2"
236 json_add_string "interface" "$interface"
237 ubus $options call network.interface notify_proto "$(json_dump)"
238 }
239
240 proto_send_update() {
241 local interface="$1"
242
243 proto_close_nested
244 json_add_boolean keep "$PROTO_KEEP"
245 _proto_push_array "ipaddr" "$PROTO_IPADDR" _proto_push_ipv4_addr
246 _proto_push_array "ip6addr" "$PROTO_IP6ADDR" _proto_push_ipv6_addr
247 _proto_push_array "routes" "$PROTO_ROUTE" _proto_push_route
248 _proto_push_array "routes6" "$PROTO_ROUTE6" _proto_push_route
249 _proto_push_array "ip6prefix" "$PROTO_PREFIX6" _proto_push_string
250 _proto_push_array "dns" "$PROTO_DNS" _proto_push_string
251 _proto_push_array "dns_search" "$PROTO_DNS_SEARCH" _proto_push_string
252 _proto_notify "$interface"
253 }
254
255 proto_export() {
256 local var="VAR${_EXPORT_VAR}"
257 _EXPORT_VAR="$(($_EXPORT_VAR + 1))"
258 export -- "$var=$1"
259 append _EXPORT_VARS "$var"
260 }
261
262 proto_run_command() {
263 local interface="$1"; shift
264
265 json_init
266 json_add_int action 1
267 json_add_array command
268 while [ $# -gt 0 ]; do
269 json_add_string "" "$1"
270 shift
271 done
272 json_close_array
273 [ -n "$_EXPORT_VARS" ] && {
274 json_add_array env
275 for var in $_EXPORT_VARS; do
276 eval "json_add_string \"\" \"\${$var}\""
277 done
278 json_close_array
279 }
280 _proto_notify "$interface"
281 }
282
283 proto_kill_command() {
284 local interface="$1"; shift
285
286 json_init
287 json_add_int action 2
288 [ -n "$1" ] && json_add_int signal "$1"
289 _proto_notify "$interface"
290 }
291
292 proto_notify_error() {
293 local interface="$1"; shift
294
295 json_init
296 json_add_int action 3
297 json_add_array error
298 while [ $# -gt 0 ]; do
299 json_add_string "" "$1"
300 shift
301 done
302 json_close_array
303 _proto_notify "$interface"
304 }
305
306 proto_block_restart() {
307 local interface="$1"; shift
308
309 json_init
310 json_add_int action 4
311 _proto_notify "$interface"
312 }
313
314 proto_set_available() {
315 local interface="$1"
316 local state="$2"
317 json_init
318 json_add_int action 5
319 json_add_boolean available "$state"
320 _proto_notify "$interface"
321 }
322
323 proto_add_host_dependency() {
324 local interface="$1"
325 local host="$2"
326 local ifname="$3"
327
328 # execute in subshell to not taint callers env
329 # see tickets #11046, #11545, #11570
330 (
331 json_init
332 json_add_int action 6
333 json_add_string host "$host"
334 [ -n "$ifname" ] && json_add_string ifname "$ifname"
335 _proto_notify "$interface" -S
336 )
337 }
338
339 proto_setup_failed() {
340 local interface="$1"
341 json_init
342 json_add_int action 7
343 _proto_notify "$interface"
344 }
345
346 init_proto() {
347 proto="$1"; shift
348 cmd="$1"; shift
349
350 case "$cmd" in
351 dump)
352 add_protocol() {
353 no_device=0
354 available=0
355
356 add_default_handler "proto_$1_init_config"
357
358 json_init
359 json_add_string "name" "$1"
360 json_add_array "config"
361 eval "proto_$1_init_config"
362 json_close_array
363 json_add_boolean no-device "$no_device"
364 json_add_boolean available "$available"
365 json_dump
366 }
367 ;;
368 setup|teardown)
369 interface="$1"; shift
370 data="$1"; shift
371 ifname="$1"; shift
372
373 add_protocol() {
374 [[ "$proto" == "$1" ]] || return 0
375
376 case "$cmd" in
377 setup) _proto_do_setup "$1";;
378 teardown) _proto_do_teardown "$1" ;;
379 *) return 1 ;;
380 esac
381 }
382 ;;
383 esac
384 }