base-files: various enhancements to network.sh
[openwrt.git] / package / base-files / files / lib / functions / network.sh
1 . /usr/share/libubox/jshn.sh
2
3 __network_switch_inactive()
4 {
5         local __tmp
6
7         if [ "$1" = 0 ] || [ "$1" = false ]; then
8                 return 1
9         fi
10
11         json_get_type __tmp "inactive"
12
13         if [ "$__tmp" = object ]; then
14                 json_select "inactive"
15         fi
16 }
17
18 __network_set_cache()
19 {
20         __NETWORK_CACHE="${__NETWORK_CACHE:+$__NETWORK_CACHE }__NETWORK_CV_$1"
21         eval "__NETWORK_CV_$1='\$$2'"
22 }
23
24 __network_get_cache()
25 {
26         eval "[ -n \"\${__NETWORK_CV_$1+x}\" ] && export -- \"$2=\$__NETWORK_CV_$1\""
27 }
28
29 __network_ipaddr()
30 {
31         local __var="$1"
32         local __iface="$2"
33         local __family="$3"
34         local __prefix="$4"
35         local __key="ipaddr_${2}_${3}_${4}"
36
37         __network_get_cache "$__key" "$__var" && return 0
38
39         local __tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)"
40
41         json_load "${__tmp:-{}}"
42         json_get_type __tmp "ipv${__family}_address"
43
44         if [ "$__tmp" = array ]; then
45
46                 json_select "ipv${__family}_address"
47                 json_get_type __tmp 1
48
49                 if [ "$__tmp" = object ]; then
50
51                         json_select 1
52                         json_get_var $__var address
53
54                         [ $__prefix -gt 0 ] && {
55                                 json_get_var __tmp mask
56                                 eval "export -- \"$__var=\${$__var}/$__tmp\""
57                         }
58
59                         __network_set_cache "$__key" "$__var"
60                         return 0
61                 fi
62         fi
63
64         return 1
65 }
66
67 # determine IPv4 address of given logical interface
68 # 1: destination variable
69 # 2: interface
70 network_get_ipaddr()  { __network_ipaddr "$1" "$2" 4 0; }
71
72 # determine IPv6 address of given logical interface
73 # 1: destination variable
74 # 2: interface
75 network_get_ipaddr6() { __network_ipaddr "$1" "$2" 6 0; }
76
77 # determine IPv4 subnet of given logical interface
78 # 1: destination variable
79 # 2: interface
80 network_get_subnet()  { __network_ipaddr "$1" "$2" 4 1; }
81
82 # determine IPv6 subnet of given logical interface
83 # 1: destination variable
84 # 2: interface
85 network_get_subnet6() { __network_ipaddr "$1" "$2" 6 1; }
86
87
88 __network_gateway()
89 {
90         local __var="$1"
91         local __iface="$2"
92         local __family="$3"
93         local __key="gateway_${2}_${3}"
94
95         __network_get_cache "$__key" "$__var" && return 0
96
97         local __tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)"
98
99         json_load "${__tmp:-{}}"
100
101         for __tmp in 0 1; do
102
103                 if json_get_type __tmp route && [ "$__tmp" = array ]; then
104
105                         json_select route
106
107                         local __idx=1
108                         while json_get_type __tmp "$__idx" && [ "$__tmp" = object ]; do
109
110                                 json_select "$((__idx++))"
111                                 json_get_var __tmp target
112
113                                 case "${__family}/${__tmp}" in
114                                         4/0.0.0.0|6/::)
115                                                 json_get_var "$__var" nexthop
116                                                 __network_set_cache "$__key" "$__var"
117                                                 return $?
118                                         ;;
119                                 esac
120
121                                 json_select ".."
122
123                         done
124
125                         json_select ".."
126
127                 fi
128
129                 __network_switch_inactive "$4" || break
130
131         done
132
133         return 1
134 }
135
136 # determine IPv4 gateway of given logical interface
137 # 1: destination variable
138 # 2: interface
139 # 3: consider inactive gateway if "true" (optional)
140 network_get_gateway()  { __network_gateway "$1" "$2" 4 "${3:-0}"; }
141
142 # determine  IPv6 gateway of given logical interface
143 # 1: destination variable
144 # 2: interface
145 # 3: consider inactive gateway if "true" (optional)
146 network_get_gateway6() { __network_gateway "$1" "$2" 6 "${3:-0}"; }
147
148
149 __network_dns() {
150         local __var="$1"
151         local __iface="$2"
152         local __field="$3"
153         local __key="dns_${2}_${3}"
154
155         __network_get_cache "$__key" "$__var" && return 0
156
157         local __tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)"
158         local __dns=""
159
160         json_load "${__tmp:-{}}"
161
162         for __tmp in 0 1; do
163
164                 if json_get_type __tmp "$__field" && [ "$__tmp" = array ]; then
165
166                         json_select "$__field"
167
168                         local __idx=1
169                         while json_get_type __tmp "$__idx" && [ "$__tmp" = string ]; do
170
171                                 json_get_var __tmp "$((__idx++))"
172                                 __dns="${__dns:+$__dns }$__tmp"
173
174                         done
175
176                         json_select ".."
177                 fi
178
179                 __network_switch_inactive "$4" || break
180
181         done
182
183         if [ -n "$__dns" ]; then
184                 eval "export -- \"$__var=$__dns\""
185                 __network_set_cache "$__key" "$__var"
186         fi
187 }
188
189 # determine the DNS servers of the given logical interface
190 # 1: destination variable
191 # 2: interface
192 # 3: consider inactive servers if "true" (optional)
193 network_get_dnsserver() { __network_dns "$1" "$2" dns_server "${3:-0}"; }
194
195 # determine the domains of the given logical interface
196 # 1: destination variable
197 # 2: interface
198 # 3: consider inactive servers if "true" (optional)
199 network_get_dnssearch() { __network_dns "$1" "$2" dns_search "${3:-0}"; }
200
201
202 __network_wan() {
203         local __var="$1"
204         local __family="$2"
205         local __key="wan_${2}"
206         local __iface
207
208         __network_get_cache "$__key" "$__var" && return 0
209
210         for __iface in $(ubus list | sed -ne 's/^network\.interface\.//p'); do
211                 if __network_gateway "$__var" "$__iface" "$__family"; then
212                         eval "export -- \"$__var=$__iface\""
213                         __network_set_cache "$__key" "$__var"
214                         return 0
215                 fi
216         done
217
218         eval "export -- \"$__var=\""
219         return 1
220 }
221
222 # find the logical interface which holds the current IPv4 default route
223 # 1: destination variable
224 network_find_wan()  { __network_wan "$1" 4; }
225
226 # find the logical interface which holds the current IPv6 default route
227 # 1: destination variable
228 network_find_wan6() { __network_wan "$1" 6; }
229
230
231 __network_device()
232 {
233         local __var="$1"
234         local __iface="$2"
235         local __field="$3"
236         local __key="device_${2}_${3}"
237
238         __network_get_cache "$__key" "$__var" && return 0
239
240         local __tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)"
241         [ -n "$__tmp" ] || return 1
242
243         json_load "$__tmp"
244         json_get_var "$__var" "$__field" && __network_set_cache "$__key" "$__var"
245 }
246
247 # test whether the given logical interface is running
248 # 1: interface
249 network_is_up()
250 {
251         local __up
252         __network_device __up "$1" up && [ $__up -eq 1 ]
253 }
254
255 # determine the layer 3 linux network device of the given logical interface
256 # 1: destination variable
257 # 2: interface
258 network_get_device()  { __network_device "$1" "$2" l3_device; }
259
260 # determine the layer 2 linux network device of the given logical interface
261 # 1: destination variable
262 # 2: interface
263 network_get_physdev() { __network_device "$1" "$2" device;    }
264
265
266 __network_defer()
267 {
268         local __device="$1"
269         local __defer="$2"
270
271         json_init
272         json_add_string name "$__device"
273         json_add_boolean defer "$__defer"
274
275         ubus call network.device set_state "$(json_dump)" 2>/dev/null
276 }
277
278 # defer netifd actions on the given linux network device
279 # 1: device name
280 network_defer_device() { __network_defer "$1" 1; }
281
282 # continue netifd actions on the given linux network device
283 # 1: device name
284 network_ready_device() { __network_defer "$1" 0; }
285
286 # flush the internal value cache to force re-reading values from ubus
287 network_flush_cache()
288 {
289         local __tmp
290         for __tmp in $__NETWORK_CACHE __NETWORK_CACHE; do
291                 unset "$__tmp"
292         done
293 }