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