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