scripts: reorganize directory layout
[project/netifd.git] / scripts / 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 local source="$6"
147
148 append PROTO_ROUTE6 "$target/$mask/$gw/$metric/$valid/$source"
149 }
150
151 proto_add_ipv6_prefix() {
152 local prefix="$1"
153 local valid="$2"
154 local preferred="$3"
155
156 if [ -z "$valid" ]; then
157 append PROTO_PREFIX6 "$prefix"
158 else
159 [ -z "$preferred" ] && preferred="$valid"
160 append PROTO_PREFIX6 "$prefix,$valid,$preferred"
161 fi
162 }
163
164 _proto_push_ipv4_addr() {
165 local str="$1"
166 local address mask broadcast ptp
167
168 address="${str%%/*}"
169 str="${str#*/}"
170 mask="${str%%/*}"
171 str="${str#*/}"
172 broadcast="${str%%/*}"
173 str="${str#*/}"
174 ptp="$str"
175
176 json_add_object ""
177 json_add_string ipaddr "$address"
178 [ -n "$mask" ] && json_add_string mask "$mask"
179 [ -n "$broadcast" ] && json_add_string broadcast "$broadcast"
180 [ -n "$ptp" ] && json_add_string ptp "$ptp"
181 json_close_object
182 }
183
184 _proto_push_ipv6_addr() {
185 local str="$1"
186 local address mask preferred valid offlink
187
188 address="${str%%/*}"
189 str="${str#*/}"
190 mask="${str%%/*}"
191 str="${str#*/}"
192 preferred="${str%%/*}"
193 str="${str#*/}"
194 valid="${str%%/*}"
195 str="${str#*/}"
196 offlink="${str%%/*}"
197
198 json_add_object ""
199 json_add_string ipaddr "$address"
200 [ -n "$mask" ] && json_add_string mask "$mask"
201 [ -n "$preferred" ] && json_add_int preferred "$preferred"
202 [ -n "$valid" ] && json_add_int valid "$valid"
203 [ -n "$offlink" ] && json_add_boolean offlink "$offlink"
204 json_close_object
205 }
206
207 _proto_push_string() {
208 json_add_string "" "$1"
209 }
210
211 _proto_push_route() {
212 local str="$1";
213 local target="${str%%/*}"
214 str="${str#*/}"
215 local mask="${str%%/*}"
216 str="${str#*/}"
217 local gw="${str%%/*}"
218 str="${str#*/}"
219 local metric="${str%%/*}"
220 str="${str#*/}"
221 local valid="${str%%/*}"
222 str="${str#*/}"
223 local source="${str}"
224
225 json_add_object ""
226 json_add_string target "$target"
227 json_add_string netmask "$mask"
228 [ -n "$gw" ] && json_add_string gateway "$gw"
229 [ -n "$metric" ] && json_add_int metric "$metric"
230 [ -n "$valid" ] && json_add_int valid "$valid"
231 [ -n "$source" ] && json_add_string source "$source"
232 json_close_object
233 }
234
235 _proto_push_array() {
236 local name="$1"
237 local val="$2"
238 local cb="$3"
239
240 [ -n "$val" ] || return 0
241 json_add_array "$name"
242 for item in $val; do
243 eval "$cb \"\$item\""
244 done
245 json_close_array
246 }
247
248 _proto_notify() {
249 local interface="$1"
250 local options="$2"
251 json_add_string "interface" "$interface"
252 ubus $options call network.interface notify_proto "$(json_dump)"
253 }
254
255 proto_send_update() {
256 local interface="$1"
257
258 proto_close_nested
259 json_add_boolean keep "$PROTO_KEEP"
260 _proto_push_array "ipaddr" "$PROTO_IPADDR" _proto_push_ipv4_addr
261 _proto_push_array "ip6addr" "$PROTO_IP6ADDR" _proto_push_ipv6_addr
262 _proto_push_array "routes" "$PROTO_ROUTE" _proto_push_route
263 _proto_push_array "routes6" "$PROTO_ROUTE6" _proto_push_route
264 _proto_push_array "ip6prefix" "$PROTO_PREFIX6" _proto_push_string
265 _proto_push_array "dns" "$PROTO_DNS" _proto_push_string
266 _proto_push_array "dns_search" "$PROTO_DNS_SEARCH" _proto_push_string
267 _proto_notify "$interface"
268 }
269
270 proto_export() {
271 local var="VAR${_EXPORT_VAR}"
272 _EXPORT_VAR="$(($_EXPORT_VAR + 1))"
273 export -- "$var=$1"
274 append _EXPORT_VARS "$var"
275 }
276
277 proto_run_command() {
278 local interface="$1"; shift
279
280 json_init
281 json_add_int action 1
282 json_add_array command
283 while [ $# -gt 0 ]; do
284 json_add_string "" "$1"
285 shift
286 done
287 json_close_array
288 [ -n "$_EXPORT_VARS" ] && {
289 json_add_array env
290 for var in $_EXPORT_VARS; do
291 eval "json_add_string \"\" \"\${$var}\""
292 done
293 json_close_array
294 }
295 _proto_notify "$interface"
296 }
297
298 proto_kill_command() {
299 local interface="$1"; shift
300
301 json_init
302 json_add_int action 2
303 [ -n "$1" ] && json_add_int signal "$1"
304 _proto_notify "$interface"
305 }
306
307 proto_notify_error() {
308 local interface="$1"; shift
309
310 json_init
311 json_add_int action 3
312 json_add_array error
313 while [ $# -gt 0 ]; do
314 json_add_string "" "$1"
315 shift
316 done
317 json_close_array
318 _proto_notify "$interface"
319 }
320
321 proto_block_restart() {
322 local interface="$1"; shift
323
324 json_init
325 json_add_int action 4
326 _proto_notify "$interface"
327 }
328
329 proto_set_available() {
330 local interface="$1"
331 local state="$2"
332 json_init
333 json_add_int action 5
334 json_add_boolean available "$state"
335 _proto_notify "$interface"
336 }
337
338 proto_add_host_dependency() {
339 local interface="$1"
340 local host="$2"
341 local ifname="$3"
342
343 # execute in subshell to not taint callers env
344 # see tickets #11046, #11545, #11570
345 (
346 json_init
347 json_add_int action 6
348 json_add_string host "$host"
349 [ -n "$ifname" ] && json_add_string ifname "$ifname"
350 _proto_notify "$interface" -S
351 )
352 }
353
354 proto_setup_failed() {
355 local interface="$1"
356 json_init
357 json_add_int action 7
358 _proto_notify "$interface"
359 }
360
361 init_proto() {
362 proto="$1"; shift
363 cmd="$1"; shift
364
365 case "$cmd" in
366 dump)
367 add_protocol() {
368 no_device=0
369 available=0
370
371 add_default_handler "proto_$1_init_config"
372
373 json_init
374 json_add_string "name" "$1"
375 json_add_array "config"
376 eval "proto_$1_init_config"
377 json_close_array
378 json_add_boolean no-device "$no_device"
379 json_add_boolean available "$available"
380 json_dump
381 }
382 ;;
383 setup|teardown)
384 interface="$1"; shift
385 data="$1"; shift
386 ifname="$1"; shift
387
388 add_protocol() {
389 [[ "$proto" == "$1" ]] || return 0
390
391 case "$cmd" in
392 setup) _proto_do_setup "$1";;
393 teardown) _proto_do_teardown "$1" ;;
394 *) return 1 ;;
395 esac
396 }
397 ;;
398 esac
399 }