netifd: add metric argument for proto_add_ipv4_route
[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         local metric="$5"
125
126         append PROTO_ROUTE "$target/$mask/$gw/$metric///$source"
127 }
128
129 proto_add_ipv6_route() {
130         local target="$1"
131         local mask="$2"
132         local gw="$3"
133         local metric="$4"
134         local valid="$5"
135         local source="$6"
136         local table="$7"
137
138         append PROTO_ROUTE6 "$target/$mask/$gw/$metric/$valid/$table/$source"
139 }
140
141 proto_add_ipv6_prefix() {
142         local prefix="$1"
143         local valid="$2"
144         local preferred="$3"
145
146         if [ -z "$valid" ]; then
147                 append PROTO_PREFIX6 "$prefix"
148         else
149                 [ -z "$preferred" ] && preferred="$valid"
150                 append PROTO_PREFIX6 "$prefix,$valid,$preferred"
151         fi
152 }
153
154 _proto_push_ipv4_addr() {
155         local str="$1"
156         local address mask broadcast ptp
157
158         address="${str%%/*}"
159         str="${str#*/}"
160         mask="${str%%/*}"
161         str="${str#*/}"
162         broadcast="${str%%/*}"
163         str="${str#*/}"
164         ptp="$str"
165
166         json_add_object ""
167         json_add_string ipaddr "$address"
168         [ -n "$mask" ] && json_add_string mask "$mask"
169         [ -n "$broadcast" ] && json_add_string broadcast "$broadcast"
170         [ -n "$ptp" ] && json_add_string ptp "$ptp"
171         json_close_object
172 }
173
174 _proto_push_ipv6_addr() {
175         local str="$1"
176         local address mask preferred valid offlink
177
178         address="${str%%/*}"
179         str="${str#*/}"
180         mask="${str%%/*}"
181         str="${str#*/}"
182         preferred="${str%%/*}"
183         str="${str#*/}"
184         valid="${str%%/*}"
185         str="${str#*/}"
186         offlink="${str%%/*}"
187         str="${str#*/}"
188         class="${str%%/*}"
189
190         json_add_object ""
191         json_add_string ipaddr "$address"
192         [ -n "$mask" ] && json_add_string mask "$mask"
193         [ -n "$preferred" ] && json_add_int preferred "$preferred"
194         [ -n "$valid" ] && json_add_int valid "$valid"
195         [ -n "$offlink" ] && json_add_boolean offlink "$offlink"
196         [ -n "$class" ] && json_add_string class "$class"
197         json_close_object
198 }
199
200 _proto_push_string() {
201         json_add_string "" "$1"
202 }
203
204 _proto_push_route() {
205         local str="$1";
206         local target="${str%%/*}"
207         str="${str#*/}"
208         local mask="${str%%/*}"
209         str="${str#*/}"
210         local gw="${str%%/*}"
211         str="${str#*/}"
212         local metric="${str%%/*}"
213         str="${str#*/}"
214         local valid="${str%%/*}"
215         str="${str#*/}"
216         local table="${str%%/*}"
217         str="${str#*/}"
218         local source="${str}"
219
220         json_add_object ""
221         json_add_string target "$target"
222         json_add_string netmask "$mask"
223         [ -n "$gw" ] && json_add_string gateway "$gw"
224         [ -n "$metric" ] && json_add_int metric "$metric"
225         [ -n "$valid" ] && json_add_int valid "$valid"
226         [ -n "$source" ] && json_add_string source "$source"
227         [ -n "$table" ] && json_add_string table "$table"
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                                 renew_handler=0
367
368                                 add_default_handler "proto_$1_init_config"
369
370                                 json_init
371                                 json_add_string "name" "$1"
372                                 json_add_array "config"
373                                 eval "proto_$1_init_config"
374                                 json_close_array
375                                 json_add_boolean no-device "$no_device"
376                                 json_add_boolean available "$available"
377                                 json_add_boolean renew-handler "$renew_handler"
378                                 json_dump
379                         }
380                 ;;
381                 setup|teardown|renew)
382                         interface="$1"; shift
383                         data="$1"; shift
384                         ifname="$1"; shift
385
386                         add_protocol() {
387                                 [[ "$proto" == "$1" ]] || return 0
388
389                                 case "$cmd" in
390                                         setup) _proto_do_setup "$1";;
391                                         teardown) _proto_do_teardown "$1" ;;
392                                         renew) _proto_do_renew "$1" ;;
393                                         *) return 1 ;;
394                                 esac
395                         }
396                 ;;
397         esac
398 }