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