From a06be29d4e91a4c00c0bd737e5da7c888edebdcc Mon Sep 17 00:00:00 2001
From: jow <jow@3c298f89-4303-0410-b956-a3cf2f4a3e73>
Date: Sun, 16 Dec 2012 20:17:18 +0000
Subject: base-files: rework cache handling in network.sh to keep the entire
 parsed ifstatus, use jshn namespaces to support using it concurrently with
 other jshn users

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@34725 3c298f89-4303-0410-b956-a3cf2f4a3e73
---
 package/base-files/files/lib/functions/network.sh | 288 ++++++++++++----------
 1 file changed, 159 insertions(+), 129 deletions(-)

(limited to 'package/base-files')

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()
+__network_set_cache()
 {
-	local __tmp
-
-	if [ "$1" = 0 ] || [ "$1" = false ]; then
-		return 1
-	fi
-
-	json_get_type __tmp "inactive"
-
-	if [ "$__tmp" = object ]; then
-		json_select "inactive"
+	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_set_cache()
+__network_export()
 {
-	__NETWORK_CACHE="${__NETWORK_CACHE:+$__NETWORK_CACHE }__NETWORK_CV_$1"
-	eval "__NETWORK_CV_$1='\$$2'"
+	local __v="__NETWORK_CV_$2"
+	eval "export -- \"$1=\${$__v:+\$$__v$3}\"; [ -n \"\${$__v+x}\" ]"
 }
 
-__network_get_cache()
+__network_parse_ifstatus()
 {
-	eval "[ -n \"\${__NETWORK_CV_$1+x}\" ] && export -- \"$2=\$__NETWORK_CV_$1\""
-}
+	local __iface="$1"
+	local __key="${__iface}"
+	local __tmp
+	local __old_ns
 
-__network_ipaddr()
-{
-	local __var="$1"
-	local __iface="$2"
-	local __family="$3"
-	local __prefix="$4"
-	local __key="ipaddr_${2}_${3}_${4}"
+	__network_export __tmp "${__key}__parsed" && return 0
+	__tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)"
+	[ -n "$__tmp" ] || return 1
 
-	__network_get_cache "$__key" "$__var" && return 0
+	json_set_namespace "network" __old_ns
+	json_load "$__tmp"
 
-	local __tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)"
+	__network_set_cache "${__key}__parsed" "" "1"
 
-	json_load "${__tmp:-{}}"
-	json_get_type __tmp "ipv${__family}_address"
+	for __tmp in "" "_inactive"; do
 
-	if [ "$__tmp" = array ]; then
+		__key="${__key}${__tmp}"
 
-		json_select "ipv${__family}_address"
-		json_get_type __tmp 1
+		# parse addresses
+		local __family
+		for __family in 4 6; do
+			if json_get_type __tmp "ipv${__family}_address" && [ "$__tmp" = array ]; then
 
-		if [ "$__tmp" = object ]; then
+				json_select "ipv${__family}_address"
 
-			json_select 1
-			json_get_var $__var address
+				if json_get_type __tmp 1 && [ "$__tmp" = object ]; then
 
-			[ $__prefix -gt 0 ] && {
-				json_get_var __tmp mask
-				eval "export -- \"$__var=\${$__var}/$__tmp\""
-			}
+					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 ".."
 
-			__network_set_cache "$__key" "$__var"
-			return 0
 		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 __tmp
+
+	__network_parse_ifstatus "$__iface" || return 1
+
+	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}"
-
-	__network_get_cache "$__key" "$__var" && return 0
-
-	local __tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)"
-
-	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
+	local __inactive="$4"
 
-		__network_switch_inactive "$4" || break
+	__network_parse_ifstatus "$__iface" || return 1
 
-	done
+	if [ "$__inactive" = 1 -o "$__inactive" = "true" ]; then
+		__network_export "$__var" "${__iface}_inactive_gateway${__family}" && \
+			return 0
+	fi
 
-	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}"
-
-	__network_get_cache "$__key" "$__var" && return 0
-
-	local __tmp="$(ubus call network.interface."$__iface" status 2>/dev/null)"
-	local __dns=""
-
-	json_load "${__tmp:-{}}"
+	local __inactive="$4"
 
-	for __tmp in 0 1; do
+	__network_parse_ifstatus "$__iface" || return 1
 
-		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
-- 
cgit v1.2.3