base-files: network.sh: gracefully handle missing network.interface ubus ns
[openwrt/openwrt.git] / package / base-files / files / lib / functions / network.sh
index f4cf2b53447148f169179b6a1df3c9f971cddb67..d7fd2dea57308721425f89d4b8c38c7b8f1ccc70 100644 (file)
@@ -6,10 +6,16 @@
 __network_ifstatus() {
        local __tmp
 
-       [ -z "$__NETWORK_CACHE" ] && \
-               export __NETWORK_CACHE="$(ubus call network.interface dump)"
+       [ -z "$__NETWORK_CACHE" ] && {
+               __tmp="$(ubus call network.interface dump 2>&1)"
+               case "$?" in
+                       4) : ;;
+                       0) export __NETWORK_CACHE="$__tmp" ;;
+                       *) echo "$__tmp" >&2 ;;
+               esac
+       }
 
-       __tmp="$(jsonfilter ${4:+-F "$4"} ${5:+-l "$5"} -s "$__NETWORK_CACHE" -e "$1=@.interface${2:+[@.interface='$2']}$3")"
+       __tmp="$(jsonfilter ${4:+-F "$4"} ${5:+-l "$5"} -s "${__NETWORK_CACHE:-{}}" -e "$1=@.interface${2:+[@.interface='$2']}$3")"
 
        [ -z "$__tmp" ] && \
                unset "$1" && \
@@ -29,18 +35,9 @@ network_get_ipaddr() {
 # 1: destination variable
 # 2: interface
 network_get_ipaddr6() {
-       local __addr
-
-       if __network_ifstatus "__addr" "$2" "['ipv6-address','ipv6-prefix-assignment'][0].address"; then
-               case "$__addr" in
-                       *:)     export "$1=${__addr}1" ;;
-                       *)      export "$1=${__addr}" ;;
-               esac
-               return 0
-       fi
-
-       unset $1
-       return 1
+       __network_ifstatus "$1" "$2" "['ipv6-address'][0].address" || \
+               __network_ifstatus "$1" "$2" "['ipv6-prefix-assignment'][0]['local-address'].address" || \
+               return 1
 }
 
 # determine first IPv4 subnet of given logical interface
@@ -54,7 +51,36 @@ network_get_subnet() {
 # 1: destination variable
 # 2: interface
 network_get_subnet6() {
-       __network_ifstatus "$1" "$2" "['ipv6-address'][0]['address','mask']" "/"
+       local __nets __addr
+
+       if network_get_subnets6 __nets "$2"; then
+               # Attempt to return first non-fe80::/10, non-fc::/7 range
+               for __addr in $__nets; do
+                       case "$__addr" in fe[8ab]?:*|f[cd]??:*)
+                               continue
+                       esac
+                       export "$1=$__addr"
+                       return 0
+               done
+
+               # Attempt to return first non-fe80::/10 range
+               for __addr in $__nets; do
+                       case "$__addr" in fe[8ab]?:*)
+                               continue
+                       esac
+                       export "$1=$__addr"
+                       return 0
+               done
+
+               # Return first item
+               for __addr in $__nets; do
+                       export "$1=$__addr"
+                       return 0
+               done
+       fi
+
+       unset "$1"
+       return 1
 }
 
 # determine first IPv6 prefix of given logical interface
@@ -78,14 +104,19 @@ network_get_ipaddrs6() {
        local __addr
        local __list=""
 
-       if __network_ifstatus "__addr" "$2" "['ipv6-address','ipv6-prefix-assignment'][*].address"; then
+       if __network_ifstatus "__addr" "$2" "['ipv6-address'][*].address"; then
                for __addr in $__addr; do
-                       case "$__addr" in
-                               *:)     __list="${__list:+$__list }${__addr}1" ;;
-                               *)  __list="${__list:+$__list }${__addr}"  ;;
-                       esac
+                       __list="${__list:+$__list }${__addr}"
+               done
+       fi
+
+       if __network_ifstatus "__addr" "$2" "['ipv6-prefix-assignment'][*]['local-address'].address"; then
+               for __addr in $__addr; do
+                       __list="${__list:+$__list }${__addr}"
                done
+       fi
 
+       if [ -n "$__list" ]; then
                export "$1=$__list"
                return 0
        fi
@@ -94,6 +125,24 @@ network_get_ipaddrs6() {
        return 1
 }
 
+# determine all IP addresses of given logical interface
+# 1: destination variable
+# 2: interface
+network_get_ipaddrs_all() {
+       local __addr __addr6
+
+       network_get_ipaddrs __addr "$2"
+       network_get_ipaddrs6 __addr6 "$2"
+
+       if [ -n "$__addr" -o -n "$__addr6" ]; then
+               export "$1=${__addr:+$__addr }$__addr6"
+               return 0
+       fi
+
+       unset "$1"
+       return 1
+}
+
 # determine all IPv4 subnets of given logical interface
 # 1: destination variable
 # 2: interface
@@ -105,17 +154,24 @@ network_get_subnets() {
 # 1: destination variable
 # 2: interface
 network_get_subnets6() {
-       local __addr
+       local __addr __mask
        local __list=""
 
-       if __network_ifstatus "__addr" "$2" "['ipv6-address','ipv6-prefix-assignment'][*]['address','mask']" "/ "; then
+       if __network_ifstatus "__addr" "$2" "['ipv6-address'][*]['address','mask']" "/ "; then
                for __addr in $__addr; do
-                       case "$__addr" in
-                               *:/*) __list="${__list:+$__list }${__addr%/*}1/${__addr##*/}" ;;
-                               *)    __list="${__list:+$__list }${__addr}"                   ;;
-                       esac
+                       __list="${__list:+$__list }${__addr}"
+               done
+       fi
+
+       if __network_ifstatus "__addr" "$2" "['ipv6-prefix-assignment'][*]['local-address'].address" && \
+          __network_ifstatus "__mask" "$2" "['ipv6-prefix-assignment'][*].mask"; then
+               for __addr in $__addr; do
+                       __list="${__list:+$__list }${__addr}/${__mask%% *}"
+                       __mask="${__mask#* }"
                done
+       fi
 
+       if [ -n "$__list" ]; then
                export "$1=$__list"
                return 0
        fi