dba6cc4831671c88e243b6f2c16e3df25ac1dc72
[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_DNS=
62         PROTO_DNS_SEARCH=
63         json_init
64         json_add_int action 0
65         [ -n "$ifname" -a "*" != "$ifname" ] && json_add_string "ifname" "$ifname"
66         json_add_boolean "link-up" "$up"
67         [ -n "$3" ] && json_add_boolean "address-external" "$external"
68 }
69
70 proto_set_keep() {
71         PROTO_KEEP="$1"
72 }
73
74 proto_close_nested() {
75         [ -n "$PROTO_NESTED_OPEN" ] && json_close_object
76         PROTO_NESTED_OPEN=
77 }
78
79 proto_add_nested() {
80         PROTO_NESTED_OPEN=1
81         json_add_object "$1"
82 }
83
84 proto_add_tunnel() {
85         proto_add_nested "tunnel"
86 }
87
88 proto_close_tunnel() {
89         proto_close_nested
90 }
91
92 proto_add_data() {
93         proto_add_nested "data"
94 }
95
96 proto_close_data() {
97         proto_close_nested
98 }
99
100 proto_add_dns_server() {
101         local address="$1"
102
103         append PROTO_DNS "$address"
104 }
105
106 proto_add_dns_search() {
107         local address="$1"
108
109         append PROTO_DNS_SEARCH "$address"
110 }
111
112 proto_add_ipv4_address() {
113         local address="$1"
114         local mask="$2"
115         local broadcast="$3"
116         local ptp="$4"
117
118         append PROTO_IPADDR "$address/$mask/$broadcast/$ptp"
119 }
120
121 proto_add_ipv6_address() {
122         local address="$1"
123         local mask="$2"
124
125         append PROTO_IP6ADDR "$address/$mask"
126 }
127
128 proto_add_ipv4_route() {
129         local target="$1"
130         local mask="$2"
131         local gw="$3"
132
133         append PROTO_ROUTE "$target/$mask/$gw"
134 }
135
136 proto_add_ipv6_route() {
137         local target="$1"
138         local mask="$2"
139         local gw="$3"
140
141         append PROTO_ROUTE6 "$target/$mask/$gw"
142 }
143
144 _proto_push_ipv4_addr() {
145         local str="$1"
146         local address mask broadcast ptp
147
148         address="${str%%/*}"
149         str="${str#*/}"
150         mask="${str%%/*}"
151         str="${str#*/}"
152         broadcast="${str%%/*}"
153         str="${str#*/}"
154         ptp="$str"
155
156         json_add_object ""
157         json_add_string ipaddr "$address"
158         [ -n "$mask" ] && json_add_string mask "$mask"
159         [ -n "$broadcast" ] && json_add_string broadcast "$broadcast"
160         [ -n "$ptp" ] && json_add_string ptp "$ptp"
161         json_close_object
162 }
163
164 _proto_push_ipv6_addr() {
165         local str="$1"
166         local address mask
167
168         address="${str%%/*}"
169         str="${str#*/}"
170         mask="$str"
171
172         json_add_object ""
173         json_add_string ipaddr "$address"
174         [ -n "$mask" ] && json_add_string mask "$mask"
175         json_close_object
176 }
177
178 _proto_push_string() {
179         json_add_string "" "$1"
180 }
181
182 _proto_push_route() {
183         local str="$1";
184         local target="${str%%/*}"
185         str="${str#*/}"
186         local mask="${str%%/*}"
187         local gw="${str#*/}"
188
189         json_add_object ""
190         json_add_string target "$target"
191         json_add_string netmask "$mask"
192         [ -n "$gw" ] && json_add_string gateway "$gw"
193         json_close_object
194 }
195
196 _proto_push_array() {
197         local name="$1"
198         local val="$2"
199         local cb="$3"
200
201         [ -n "$val" ] || return 0
202         json_add_array "$name"
203         for item in $val; do
204                 eval "$cb \"\$item\""
205         done
206         json_close_array
207 }
208
209 _proto_notify() {
210         local interface="$1"
211         local options="$2"
212         ubus $options call network.interface."$interface" notify_proto "$(json_dump)"
213 }
214
215 proto_send_update() {
216         local interface="$1"
217
218         proto_close_nested
219         json_add_boolean keep "$PROTO_KEEP"
220         _proto_push_array "ipaddr" "$PROTO_IPADDR" _proto_push_ipv4_addr
221         _proto_push_array "ip6addr" "$PROTO_IP6ADDR" _proto_push_ipv6_addr
222         _proto_push_array "routes" "$PROTO_ROUTE" _proto_push_route
223         _proto_push_array "routes6" "$PROTO_ROUTE6" _proto_push_route
224         _proto_push_array "dns" "$PROTO_DNS" _proto_push_string
225         _proto_push_array "dns_search" "$PROTO_DNS_SEARCH" _proto_push_string
226         _proto_notify "$interface"
227 }
228
229 proto_export() {
230         local var="VAR${_EXPORT_VAR}"
231         _EXPORT_VAR="$(($_EXPORT_VAR + 1))"
232         export -- "$var=$1"
233         append _EXPORT_VARS "$var"
234 }
235
236 proto_run_command() {
237         local interface="$1"; shift
238
239         json_init
240         json_add_int action 1
241         json_add_array command
242         while [ $# -gt 0 ]; do
243                 json_add_string "" "$1"
244                 shift
245         done
246         json_close_array
247         [ -n "$_EXPORT_VARS" ] && {
248                 json_add_array env
249                 for var in $_EXPORT_VARS; do
250                         eval "json_add_string \"\" \"\${$var}\""
251                 done
252                 json_close_array
253         }
254         _proto_notify "$interface"
255 }
256
257 proto_kill_command() {
258         local interface="$1"; shift
259
260         json_init
261         json_add_int action 2
262         [ -n "$1" ] && json_add_int signal "$1"
263         _proto_notify "$interface"
264 }
265
266 proto_notify_error() {
267         local interface="$1"; shift
268
269         json_init
270         json_add_int action 3
271         json_add_array error
272         while [ $# -gt 0 ]; do
273                 json_add_string "" "$1"
274                 shift
275         done
276         json_close_array
277         _proto_notify "$interface"
278 }
279
280 proto_block_restart() {
281         local interface="$1"; shift
282
283         json_init
284         json_add_int action 4
285         _proto_notify "$interface"
286 }
287
288 proto_set_available() {
289         local interface="$1"
290         local state="$2"
291         json_init
292         json_add_int action 5
293         json_add_boolean available "$state"
294         _proto_notify "$interface"
295 }
296
297 proto_add_host_dependency() {
298         local interface="$1"
299         local host="$2"
300
301         # execute in subshell to not taint callers env
302         # see tickets #11046, #11545, #11570
303         (
304                 json_init
305                 json_add_int action 6
306                 json_add_string host "$host"
307                 _proto_notify "$interface" -S
308         )
309 }
310
311 proto_setup_failed() {
312         local interface="$1"
313         json_init
314         json_add_int action 7
315         _proto_notify "$interface"
316 }
317
318 init_proto() {
319         proto="$1"; shift
320         cmd="$1"; shift
321
322         case "$cmd" in
323                 dump)
324                         add_protocol() {
325                                 no_device=0
326                                 available=0
327
328                                 add_default_handler "proto_$1_init_config"
329
330                                 json_init
331                                 json_add_string "name" "$1"
332                                 json_add_array "config"
333                                 eval "proto_$1_init_config"
334                                 json_close_array
335                                 json_add_boolean no-device "$no_device"
336                                 json_add_boolean available "$available"
337                                 json_dump
338                         }
339                 ;;
340                 setup|teardown)
341                         interface="$1"; shift
342                         data="$1"; shift
343                         ifname="$1"; shift
344
345                         add_protocol() {
346                                 [[ "$proto" == "$1" ]] || return 0
347
348                                 case "$cmd" in
349                                         setup) _proto_do_setup "$1";;
350                                         teardown) _proto_do_teardown "$1" ;;
351                                         *) return 1 ;;
352                                 esac
353                         }
354                 ;;
355         esac
356 }