diff options
-rw-r--r-- | package/base-files/Makefile | 2 | ||||
-rw-r--r-- | package/base-files/files/lib/functions/network.sh | 183 |
2 files changed, 154 insertions, 31 deletions
diff --git a/package/base-files/Makefile b/package/base-files/Makefile index 7a2e216e81..6452a3ecb0 100644 --- a/package/base-files/Makefile +++ b/package/base-files/Makefile @@ -11,7 +11,7 @@ include $(INCLUDE_DIR)/kernel.mk include $(INCLUDE_DIR)/version.mk PKG_NAME:=base-files -PKG_RELEASE:=120 +PKG_RELEASE:=121 PKG_FILE_DEPENDS:=$(PLATFORM_DIR)/ $(GENERIC_PLATFORM_DIR)/base-files/ PKG_BUILD_DEPENDS:=opkg/host diff --git a/package/base-files/files/lib/functions/network.sh b/package/base-files/files/lib/functions/network.sh index a4652569b6..9366e5937a 100644 --- a/package/base-files/files/lib/functions/network.sh +++ b/package/base-files/files/lib/functions/network.sh @@ -1,11 +1,40 @@ . /usr/share/libubox/jshn.sh +__network_switch_inactive() +{ + local __tmp + + if [ "$1" = 0 ] || [ "$1" = false ]; then + return 1 + fi + + json_get_type __tmp "inactive" + + if [ "$__tmp" = object ]; then + json_select "inactive" + fi +} + +__network_set_cache() +{ + __NETWORK_CACHE="${__NETWORK_CACHE:+$__NETWORK_CACHE }__NETWORK_CV_$1" + eval "__NETWORK_CV_$1='\$$2'" +} + +__network_get_cache() +{ + eval "[ -n \"\${__NETWORK_CV_$1+x}\" ] && export -- \"$2=\$__NETWORK_CV_$1\"" +} + __network_ipaddr() { local __var="$1" local __iface="$2" local __family="$3" - local __prefix="${4:-0}" + local __prefix="$4" + local __key="ipaddr_${2}_${3}_${4}" + + __network_get_cache "$__key" "$__var" && return 0 local __tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)" @@ -27,6 +56,7 @@ __network_ipaddr() eval "export -- \"$__var=\${$__var}/$__tmp\"" } + __network_set_cache "$__key" "$__var" return 0 fi fi @@ -34,10 +64,24 @@ __network_ipaddr() return 1 } +# determine IPv4 address of given logical interface +# 1: destination variable +# 2: interface network_get_ipaddr() { __network_ipaddr "$1" "$2" 4 0; } + +# determine IPv6 address of given logical interface +# 1: destination variable +# 2: interface network_get_ipaddr6() { __network_ipaddr "$1" "$2" 6 0; } +# determine IPv4 subnet of given logical interface +# 1: destination variable +# 2: interface network_get_subnet() { __network_ipaddr "$1" "$2" 4 1; } + +# determine IPv6 subnet of given logical interface +# 1: destination variable +# 2: interface network_get_subnet6() { __network_ipaddr "$1" "$2" 6 1; } @@ -46,79 +90,127 @@ __network_gateway() local __var="$1" local __iface="$2" local __family="$3" + local __key="gateway_${2}_${3}" + + __network_get_cache "$__key" "$__var" && return 0 local __tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)" - local __idx=1 json_load "${__tmp:-{}}" - if json_get_type __tmp route && [ "$__tmp" = array ]; then + for __tmp in 0 1; do - json_select route + if json_get_type __tmp route && [ "$__tmp" = array ]; then - while json_get_type __tmp "$__idx" && [ "$__tmp" = object ]; do + json_select route - json_select "$((__idx++))" - json_get_var __tmp target + local __idx=1 + while json_get_type __tmp "$__idx" && [ "$__tmp" = object ]; do - case "${__family}/${__tmp}" in - 4/0.0.0.0|6/::) - json_get_var "$__var" nexthop - return $? - ;; - esac + json_select "$((__idx++))" + json_get_var __tmp target + + case "${__family}/${__tmp}" in + 4/0.0.0.0|6/::) + json_get_var "$__var" nexthop + __network_set_cache "$__key" "$__var" + return $? + ;; + esac + + json_select ".." + + done json_select ".." - done - fi + fi + + __network_switch_inactive "$4" || break + + done return 1 } -network_get_gateway() { __network_gateway "$1" "$2" 4; } -network_get_gateway6() { __network_gateway "$1" "$2" 6; } +# determine IPv4 gateway of given logical interface +# 1: destination variable +# 2: interface +# 3: consider inactive gateway if "true" (optional) +network_get_gateway() { __network_gateway "$1" "$2" 4 "${3:-0}"; } + +# determine IPv6 gateway of given logical interface +# 1: destination variable +# 2: interface +# 3: consider inactive gateway if "true" (optional) +network_get_gateway6() { __network_gateway "$1" "$2" 6 "${3:-0}"; } __network_dns() { local __var="$1" local __iface="$2" local __field="$3" + local __key="dns_${2}_${3}" + + __network_get_cache "$__key" "$__var" && return 0 local __tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)" local __dns="" - local __idx=1 json_load "${__tmp:-{}}" - if json_get_type __tmp "$__field" && [ "$__tmp" = array ]; then + for __tmp in 0 1; do - json_select "$__field" + if json_get_type __tmp "$__field" && [ "$__tmp" = array ]; then - while json_get_type __tmp "$__idx" && [ "$__tmp" = string ]; do + json_select "$__field" - json_get_var __tmp "$((__idx++))" - __dns="${__dns:+$__dns }$__tmp" + local __idx=1 + while json_get_type __tmp "$__idx" && [ "$__tmp" = string ]; do - done - fi + json_get_var __tmp "$((__idx++))" + __dns="${__dns:+$__dns }$__tmp" + + done + + json_select ".." + fi + + __network_switch_inactive "$4" || break + + done - eval "export -- \"$__var=$__dns\"" - [ -n "$__dns" ] + if [ -n "$__dns" ]; then + eval "export -- \"$__var=$__dns\"" + __network_set_cache "$__key" "$__var" + fi } -network_get_dnsserver() { __network_dns "$1" "$2" dns_server; } -network_get_dnssearch() { __network_dns "$1" "$2" dns_search; } +# determine the DNS servers of the given logical interface +# 1: destination variable +# 2: interface +# 3: consider inactive servers if "true" (optional) +network_get_dnsserver() { __network_dns "$1" "$2" dns_server "${3:-0}"; } + +# determine the domains of the given logical interface +# 1: destination variable +# 2: interface +# 3: consider inactive servers if "true" (optional) +network_get_dnssearch() { __network_dns "$1" "$2" dns_search "${3:-0}"; } __network_wan() { local __var="$1" local __family="$2" + local __key="wan_${2}" local __iface + __network_get_cache "$__key" "$__var" && return 0 + for __iface in $(ubus list | sed -ne 's/^network\.interface\.//p'); do if __network_gateway "$__var" "$__iface" "$__family"; then eval "export -- \"$__var=$__iface\"" + __network_set_cache "$__key" "$__var" return 0 fi done @@ -127,7 +219,12 @@ __network_wan() { return 1 } +# find the logical interface which holds the current IPv4 default route +# 1: destination variable network_find_wan() { __network_wan "$1" 4; } + +# find the logical interface which holds the current IPv6 default route +# 1: destination variable network_find_wan6() { __network_wan "$1" 6; } @@ -136,21 +233,33 @@ __network_device() local __var="$1" local __iface="$2" local __field="$3" + local __key="device_${2}_${3}" + + __network_get_cache "$__key" "$__var" && return 0 local __tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)" [ -n "$__tmp" ] || return 1 json_load "$__tmp" - json_get_var "$__var" "$__field" + json_get_var "$__var" "$__field" && __network_set_cache "$__key" "$__var" } +# test whether the given logical interface is running +# 1: interface network_is_up() { local __up __network_device __up "$1" up && [ $__up -eq 1 ] } +# determine the layer 3 linux network device of the given logical interface +# 1: destination variable +# 2: interface network_get_device() { __network_device "$1" "$2" l3_device; } + +# determine the layer 2 linux network device of the given logical interface +# 1: destination variable +# 2: interface network_get_physdev() { __network_device "$1" "$2" device; } @@ -166,5 +275,19 @@ __network_defer() ubus call network.device set_state "$(json_dump)" 2>/dev/null } +# defer netifd actions on the given linux network device +# 1: device name network_defer_device() { __network_defer "$1" 1; } + +# continue netifd actions on the given linux network device +# 1: device name network_ready_device() { __network_defer "$1" 0; } + +# flush the internal value cache to force re-reading values from ubus +network_flush_cache() +{ + local __tmp + for __tmp in $__NETWORK_CACHE __NETWORK_CACHE; do + unset "$__tmp" + done +} |