diff --git a/package/base-files/files/lib/functions/network.sh b/package/base-files/files/lib/functions/network.sh index 9366e5937..d242abbe6 100644 --- a/package/base-files/files/lib/functions/network.sh +++ b/package/base-files/files/lib/functions/network.sh @@ -1,67 +1,153 @@ . /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'" + if [ -n "$3" ]; then + eval "export -- __NETWORK_CV_$1='$3'" + __NETWORK_CACHE="${__NETWORK_CACHE:+$__NETWORK_CACHE }__NETWORK_CV_$1" + elif json_get_var "__NETWORK_CV_$1" "$2"; then + __NETWORK_CACHE="${__NETWORK_CACHE:+$__NETWORK_CACHE }__NETWORK_CV_$1" + fi } -__network_get_cache() +__network_export() { - eval "[ -n \"\${__NETWORK_CV_$1+x}\" ] && export -- \"$2=\$__NETWORK_CV_$1\"" + local __v="__NETWORK_CV_$2" + eval "export -- \"$1=\${$__v:+\$$__v$3}\"; [ -n \"\${$__v+x}\" ]" } +__network_parse_ifstatus() +{ + local __iface="$1" + local __key="${__iface}" + local __tmp + local __old_ns + + __network_export __tmp "${__key}__parsed" && return 0 + __tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)" + [ -n "$__tmp" ] || return 1 + + json_set_namespace "network" __old_ns + json_load "$__tmp" + + __network_set_cache "${__key}__parsed" "" "1" + + for __tmp in "" "_inactive"; do + + __key="${__key}${__tmp}" + + # parse addresses + local __family + for __family in 4 6; do + if json_get_type __tmp "ipv${__family}_address" && [ "$__tmp" = array ]; then + + json_select "ipv${__family}_address" + + if json_get_type __tmp 1 && [ "$__tmp" = object ]; then + + json_select 1 + __network_set_cache "${__key}_address${__family}" address + __network_set_cache "${__key}_mask${__family}" mask + json_select ".." + + fi + + json_select ".." + + fi + done + + # parse routes + if json_get_type __tmp route && [ "$__tmp" = array ]; then + + json_select "route" + + local __idx=1 + while json_get_type __tmp "$__idx" && [ "$__tmp" = object ]; do + + json_select "$((__idx++))" + json_get_var __tmp target + + case "${__tmp}" in + 0.0.0.0) + __network_set_cache "${__key}_gateway4" nexthop + ;; + ::) + __network_set_cache "${__key}_gateway6" nexthop + ;; + esac + + json_select ".." + + done + + json_select ".." + + fi + + # parse dns info + local __field + for __field in "dns_server" "dns_search"; do + if json_get_type __tmp "$__field" && [ "$__tmp" = array ]; then + + json_select "$__field" + + local __idx=1 + local __dns="" + + while json_get_type __tmp "$__idx" && [ "$__tmp" = string ]; do + + json_get_var __tmp "$((__idx++))" + __dns="${__dns:+$__dns }$__tmp" + + done + + json_select ".." + + if [ -n "$__dns" ]; then + __network_set_cache "${__key}_${__field}" "" "$__dns" + fi + fi + done + + # parse up state, device and physdev + for __field in "up" "l3_device" "device"; do + if json_get_type __tmp "$__field"; then + __network_set_cache "${__key}_${__field}" "$__field" + fi + done + + # descend into inactive table + json_get_type __tmp "inactive" && [ "$__tmp" = object ] && json_select "inactive" + + done + + json_cleanup + json_set_namespace "$__old_ns" + + return 0 +} + + __network_ipaddr() { local __var="$1" local __iface="$2" local __family="$3" local __prefix="$4" - local __key="ipaddr_${2}_${3}_${4}" + local __tmp - __network_get_cache "$__key" "$__var" && return 0 + __network_parse_ifstatus "$__iface" || return 1 - local __tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)" - - json_load "${__tmp:-{}}" - json_get_type __tmp "ipv${__family}_address" - - if [ "$__tmp" = array ]; then - - json_select "ipv${__family}_address" - json_get_type __tmp 1 - - if [ "$__tmp" = object ]; then - - json_select 1 - json_get_var $__var address - - [ $__prefix -gt 0 ] && { - json_get_var __tmp mask - eval "export -- \"$__var=\${$__var}/$__tmp\"" - } - - __network_set_cache "$__key" "$__var" - return 0 - fi + if [ $__prefix -eq 1 ]; then + __network_export __tmp "${__iface}_mask${__family}" && \ + __network_export "$__var" "${__iface}_address${__family}" "/$__tmp" + return $? fi - return 1 + __network_export "$__var" "${__iface}_address${__family}" + return $? + } # determine IPv4 address of given logical interface @@ -90,47 +176,17 @@ __network_gateway() local __var="$1" local __iface="$2" local __family="$3" - local __key="gateway_${2}_${3}" + local __inactive="$4" - __network_get_cache "$__key" "$__var" && return 0 + __network_parse_ifstatus "$__iface" || return 1 - local __tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)" + if [ "$__inactive" = 1 -o "$__inactive" = "true" ]; then + __network_export "$__var" "${__iface}_inactive_gateway${__family}" && \ + return 0 + fi - json_load "${__tmp:-{}}" - - for __tmp in 0 1; do - - if json_get_type __tmp route && [ "$__tmp" = array ]; then - - json_select route - - local __idx=1 - while json_get_type __tmp "$__idx" && [ "$__tmp" = object ]; do - - 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 ".." - - fi - - __network_switch_inactive "$4" || break - - done - - return 1 + __network_export "$__var" "${__iface}_gateway${__family}" + return $? } # determine IPv4 gateway of given logical interface @@ -150,40 +206,17 @@ __network_dns() { local __var="$1" local __iface="$2" local __field="$3" - local __key="dns_${2}_${3}" + local __inactive="$4" - __network_get_cache "$__key" "$__var" && return 0 + __network_parse_ifstatus "$__iface" || return 1 - local __tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)" - local __dns="" - - json_load "${__tmp:-{}}" - - for __tmp in 0 1; do - - if json_get_type __tmp "$__field" && [ "$__tmp" = array ]; then - - json_select "$__field" - - local __idx=1 - while json_get_type __tmp "$__idx" && [ "$__tmp" = string ]; do - - json_get_var __tmp "$((__idx++))" - __dns="${__dns:+$__dns }$__tmp" - - done - - json_select ".." - fi - - __network_switch_inactive "$4" || break - - done - - if [ -n "$__dns" ]; then - eval "export -- \"$__var=$__dns\"" - __network_set_cache "$__key" "$__var" + if [ "$__inactive" = 1 -o "$__inactive" = "true" ]; then + __network_export "$__var" "${__iface}_inactive_${__field}" && \ + return 0 fi + + __network_export "$__var" "${__iface}_${__field}" + return $? } # determine the DNS servers of the given logical interface @@ -195,23 +228,23 @@ 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) +# 3: consider inactive domains if "true" (optional) network_get_dnssearch() { __network_dns "$1" "$2" dns_search "${3:-0}"; } -__network_wan() { +__network_wan() +{ local __var="$1" local __family="$2" - local __key="wan_${2}" + local __inactive="$3" 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 + if [ "$__iface" != loopback ]; then + if __network_gateway "$__var" "$__iface" "$__family" "$__inactive"; then + eval "export -- \"$__var=$__iface\"" + return 0 + fi fi done @@ -221,11 +254,13 @@ __network_wan() { # find the logical interface which holds the current IPv4 default route # 1: destination variable -network_find_wan() { __network_wan "$1" 4; } +# 2: consider inactive default routes if "true" (optional) +network_find_wan() { __network_wan "$1" 4 "${2:-0}"; } # find the logical interface which holds the current IPv6 default route # 1: destination variable -network_find_wan6() { __network_wan "$1" 6; } +# 2: consider inactive dafault routes if "true" (optional) +network_find_wan6() { __network_wan "$1" 6 "${2:-0}"; } __network_device() @@ -233,15 +268,10 @@ __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" && __network_set_cache "$__key" "$__var" + __network_parse_ifstatus "$__iface" || return 1 + __network_export "$__var" "${__iface}_${__field}" + return $? } # test whether the given logical interface is running