X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fopenwrt.git;a=blobdiff_plain;f=package%2Fbase-files%2Ffiles%2Flib%2Ffunctions%2Fnetwork.sh;h=1b0c717204d69ec0f89dd02282be6f279a673b6e;hp=7d06aa40e94b8d55b30c17504bc627b515f13df0;hb=14e6559eee9202d17f99493b5c7603b369c56294;hpb=fe230cac1807fe6e595672d566e20d341211fbcf diff --git a/package/base-files/files/lib/functions/network.sh b/package/base-files/files/lib/functions/network.sh index 7d06aa40e9..1b0c717204 100644 --- a/package/base-files/files/lib/functions/network.sh +++ b/package/base-files/files/lib/functions/network.sh @@ -1,427 +1,268 @@ -. /usr/share/libubox/jshn.sh - -__network_set_cache() -{ - 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_export() -{ - local __v="__NETWORK_CV_$2" - eval "export -- \"$1=\${$__v:+\${$__v$4}$3}\"; [ -n \"\${$__v+x}\" ]" -} - -__network_parse_ifstatus() -{ - local __iface="$1" - local __key="${__iface}" +# 1: destination variable +# 2: interface +# 3: path +# 4: separator +# 5: limit +__network_ifstatus() { local __tmp - local __idx - local __list - local __old_ns - - case "$__iface" in - *[^a-zA-Z0-9_]*) return 1 ;; - esac - - __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 - - __list="" - - if json_is_a "ipv${__family}_address" array; then - - json_select "ipv${__family}_address" - - __idx=1 - - while json_is_a "$__idx" object; do - - json_select "$((__idx++))" - json_get_var __tmp "address" && __list="${__list:+$__list }$__tmp" - json_get_var __tmp "mask" && __list="${__list:+$__list/}$__tmp" - json_select ".." - - done - - json_select ".." - - fi - - if json_is_a "ipv${__family}_prefix_assignment" array; then - - json_select "ipv${__family}_prefix_assignment" - - __idx=1 - - while json_is_a "$__idx" object; do - - json_select "$((__idx++))" - json_get_var __tmp "address" && __list="${__list:+$__list }${__tmp}1" - json_get_var __tmp "mask" && __list="${__list:+$__list/}$__tmp" - json_select ".." - - done - - json_select ".." - - fi - - if [ -n "$__list" ]; then - __network_set_cache "${__key}_address${__family}" "" "$__list" - fi - - done - - # parse prefixes - if json_is_a "ipv6_prefix" array; then - json_select "ipv6_prefix" - - __idx=1 - __list="" - - while json_is_a "$__idx" object; do - - json_select "$((__idx++))" - json_get_var __tmp "address" && __list="${__list:+$__list }$__tmp" - json_get_var __tmp "mask" && __list="${__list:+$__list/}$__tmp" - json_select ".." - - done - - json_select ".." - - - if [ -n "$__list" ]; then - __network_set_cache "${__key}_prefix6" "" "$__list" - fi - - fi - - # parse routes - if json_is_a route array; then - - json_select "route" - - local __idx=1 - while json_is_a "$__idx" object; do - - json_select "$((__idx++))" - json_get_var __tmp table - - if [ -z "$__tmp" ]; then - 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 - fi - - json_select ".." - - done - - json_select ".." - - fi - - # parse dns info - local __field - for __field in "dns_server" "dns_search"; do - if json_is_a "$__field" array; then - - json_select "$__field" - - __idx=1 - __list="" - - while json_is_a "$__idx" string; do - - json_get_var __tmp "$((__idx++))" - __list="${__list:+$__list }$__tmp" - - done - - json_select ".." - - if [ -n "$__list" ]; then - __network_set_cache "${__key}_${__field}" "" "$__list" - fi - fi - done - - # parse up state, proto, device and physdev - for __field in "up" "proto" "l3_device" "device"; do - if json_get_type __tmp "$__field"; then - __network_set_cache "${__key}_${__field}" "$__field" - fi - done - - # descend into inactive table - json_is_a "inactive" object && json_select "inactive" - - done - - json_cleanup - json_set_namespace "$__old_ns" - - return 0 -} - - -__network_ipaddr() -{ - local __var="$1" - local __iface="$2" - local __field="$3" - local __subst="$4" - local __list="$5" - local __tmp="" - __network_parse_ifstatus "$__iface" || return 1 + [ -z "$__NETWORK_CACHE" ] && \ + export __NETWORK_CACHE="$(ubus call network.interface dump)" - if [ $__list = 1 ] && [ -n "$__subst" ]; then - __network_export "__list" "${__iface}_${__field}" + __tmp="$(jsonfilter ${4:+-F "$4"} ${5:+-l "$5"} -s "$__NETWORK_CACHE" -e "$1=@.interface${2:+[@.interface='$2']}$3")" - for __list in $__list; do - eval "__tmp=\"${__tmp:+$__tmp }\${__list$__subst}\"" - done - - export -- "$__var=$__tmp"; [ -n "$__tmp" ] - return $? - fi + [ -z "$__tmp" ] && \ + unset "$1" && \ + return 1 - __network_export "$__var" "${__iface}_${__field}" "" "$__subst" - return $? + eval "$__tmp" } # determine first IPv4 address of given logical interface # 1: destination variable # 2: interface -network_get_ipaddr() { __network_ipaddr "$1" "$2" "address4" "%%/*" 0; } +network_get_ipaddr() { + __network_ifstatus "$1" "$2" "['ipv4-address'][0].address"; +} # determine first IPv6 address of given logical interface # 1: destination variable # 2: interface -network_get_ipaddr6() { __network_ipaddr "$1" "$2" "address6" "%%/*" 0; } +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 +} # determine first IPv4 subnet of given logical interface # 1: destination variable # 2: interface -network_get_subnet() { __network_ipaddr "$1" "$2" "address4" "%% *" 0; } +network_get_subnet() { + __network_ifstatus "$1" "$2" "['ipv4-address'][0]['address','mask']" "/" +} # determine first IPv6 subnet of given logical interface # 1: destination variable # 2: interface -network_get_subnet6() { __network_ipaddr "$1" "$2" "address6" "%% *" 0; } +network_get_subnet6() { + __network_ifstatus "$1" "$2" "['ipv6-address'][0]['address','mask']" "/" +} # determine first IPv6 prefix of given logical interface # 1: destination variable # 2: interface -network_get_prefix6() { __network_ipaddr "$1" "$2" "prefix6" "%% *" 0; } +network_get_prefix6() { + __network_ifstatus "$1" "$2" "['ipv6-prefix'][0]['address','mask']" "/" +} # determine all IPv4 addresses of given logical interface # 1: destination variable # 2: interface -network_get_ipaddrs() { __network_ipaddr "$1" "$2" "address4" "%%/*" 1; } +network_get_ipaddrs() { + __network_ifstatus "$1" "$2" "['ipv4-address'][*].address" +} # determine all IPv6 addresses of given logical interface # 1: destination variable # 2: interface -network_get_ipaddrs6() { __network_ipaddr "$1" "$2" "address6" "%%/*" 1; } +network_get_ipaddrs6() { + local __addr + local __list="" + + if __network_ifstatus "__addr" "$2" "['ipv6-address','ipv6-prefix-assignment'][*].address"; then + for __addr in $__addr; do + case "$__addr" in + *:) __list="${__list:+$__list }${__addr}1" ;; + *) __list="${__list:+$__list }${__addr}" ;; + esac + done -# determine all IPv4 subnets of given logical interface + export "$1=$__list" + return 0 + fi + + unset "$1" + return 1 +} + +# determine all IP addresses of given logical interface # 1: destination variable # 2: interface -network_get_subnets() { __network_ipaddr "$1" "$2" "address4" "" 1; } +network_get_ipaddrs_all() { + local __addr + local __list="" + + if __network_ifstatus "__addr" "$2" "['ipv4-address','ipv6-address','ipv6-prefix-assignment'][*].address"; then + for __addr in $__addr; do + case "$__addr" in + *:) __list="${__list:+$__list }${__addr}1" ;; + *) __list="${__list:+$__list }${__addr}" ;; + esac + done -# determine all IPv6 subnets of given logical interface + export "$1=$__list" + return 0 + fi + + unset "$1" + return 1 +} + +# determine all IPv4 subnets of given logical interface # 1: destination variable # 2: interface -network_get_subnets6() { __network_ipaddr "$1" "$2" "address6" "" 1; } +network_get_subnets() { + __network_ifstatus "$1" "$2" "['ipv4-address'][*]['address','mask']" "/ " +} -# determine all IPv6 prefixes of given logical interface +# determine all IPv6 subnets of given logical interface # 1: destination variable # 2: interface -network_get_prefixes6() { __network_ipaddr "$1" "$2" "prefix6" "" 1; } - - -__network_gateway() -{ - local __var="$1" - local __iface="$2" - local __family="$3" - local __inactive="$4" - - __network_parse_ifstatus "$__iface" || return 1 +network_get_subnets6() { + local __addr + local __list="" + + if __network_ifstatus "__addr" "$2" "['ipv6-address','ipv6-prefix-assignment'][*]['address','mask']" "/ "; then + for __addr in $__addr; do + case "$__addr" in + *:/*) __list="${__list:+$__list }${__addr%/*}1/${__addr##*/}" ;; + *) __list="${__list:+$__list }${__addr}" ;; + esac + done - if [ "$__inactive" = 1 -o "$__inactive" = "true" ]; then - __network_export "$__var" "${__iface}_inactive_gateway${__family}" && \ - return 0 + export "$1=$__list" + return 0 fi - __network_export "$__var" "${__iface}_gateway${__family}" - return $? + unset "$1" + return 1 +} + +# determine all IPv6 prefixes of given logical interface +# 1: destination variable +# 2: interface +network_get_prefixes6() { + __network_ifstatus "$1" "$2" "['ipv6-prefix'][*]['address','mask']" "/ " } # 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}"; } +network_get_gateway() { + __network_ifstatus "$1" "$2" ".route[@.target='0.0.0.0' && !@.table].nexthop" "" 1 && \ + return 0 + + [ "$3" = 1 -o "$3" = "true" ] && \ + __network_ifstatus "$1" "$2" ".inactive.route[@.target='0.0.0.0' && !@.table].nexthop" "" 1 +} # 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 __inactive="$4" +network_get_gateway6() { + __network_ifstatus "$1" "$2" ".route[@.target='::' && !@.table].nexthop" "" 1 && \ + return 0 - __network_parse_ifstatus "$__iface" || return 1 - - if [ "$__inactive" = 1 -o "$__inactive" = "true" ]; then - __network_export "$__var" "${__iface}_inactive_${__field}" && \ - return 0 - fi - - __network_export "$__var" "${__iface}_${__field}" - return $? + [ "$3" = 1 -o "$3" = "true" ] && \ + __network_ifstatus "$1" "$2" ".inactive.route[@.target='::' && !@.table].nexthop" "" 1 } # 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}"; } +network_get_dnsserver() { + __network_ifstatus "$1" "$2" "['dns-server'][*]" && return 0 + + [ "$3" = 1 -o "$3" = "true" ] && \ + __network_ifstatus "$1" "$2" ".inactive['dns-server'][*]" +} # determine the domains of the given logical interface # 1: destination variable # 2: interface # 3: consider inactive domains if "true" (optional) -network_get_dnssearch() { __network_dns "$1" "$2" dns_search "${3:-0}"; } +network_get_dnssearch() { + __network_ifstatus "$1" "$2" "['dns-search'][*]" && return 0 + [ "$3" = 1 -o "$3" = "true" ] && \ + __network_ifstatus "$1" "$2" ".inactive['dns-search'][*]" +} + +# 1: destination variable +# 2: addr +# 3: inactive __network_wan() { - local __var="$1" - local __family="$2" - local __inactive="$3" - local __iface - - for __iface in $(ubus list | sed -ne 's/^network\.interface\.//p'); do - if [ "$__iface" != loopback ]; then - if __network_gateway "$__var" "$__iface" "$__family" "$__inactive"; then - eval "export -- \"$__var=$__iface\"" - return 0 - fi - fi - done - - eval "export -- \"$__var=\"" - return 1 + __network_ifstatus "$1" "" \ + "[@.route[@.target='$2' && !@.table]].interface" "" 1 && \ + return 0 + + [ "$3" = 1 -o "$3" = "true" ] && \ + __network_ifstatus "$1" "" \ + "[@.inactive.route[@.target='$2' && !@.table]].interface" "" 1 } # find the logical interface which holds the current IPv4 default route # 1: destination variable # 2: consider inactive default routes if "true" (optional) -network_find_wan() { __network_wan "$1" 4 "${2:-0}"; } +network_find_wan() { __network_wan "$1" "0.0.0.0" "$2"; } # find the logical interface which holds the current IPv6 default route # 1: destination variable # 2: consider inactive dafault routes if "true" (optional) -network_find_wan6() { __network_wan "$1" 6 "${2:-0}"; } - - -__network_device() -{ - local __var="$1" - local __iface="$2" - local __field="$3" - - __network_parse_ifstatus "$__iface" || return 1 - __network_export "$__var" "${__iface}_${__field}" - return $? -} +network_find_wan6() { __network_wan "$1" "::" "$2"; } # test whether the given logical interface is running # 1: interface network_is_up() { local __up - __network_device __up "$1" up && [ $__up -eq 1 ] + __network_ifstatus "__up" "$1" ".up" && [ "$__up" = 1 ] } # determine the protocol of the given logical interface # 1: destination variable # 2: interface -network_get_protocol() { __network_device "$1" "$2" proto; } +network_get_protocol() { __network_ifstatus "$1" "$2" ".proto"; } # 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; } +network_get_device() { __network_ifstatus "$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; } - - -__network_defer() -{ - local __device="$1" - local __defer="$2" - - json_init - json_add_string name "$__device" - json_add_boolean defer "$__defer" - - ubus call network.device set_state "$(json_dump)" 2>/dev/null -} +network_get_physdev() { __network_ifstatus "$1" "$2" ".device"; } # defer netifd actions on the given linux network device # 1: device name -network_defer_device() { __network_defer "$1" 1; } +network_defer_device() +{ + ubus call network.device set_state \ + "$(printf '{ "name": "%s", "defer": true }' "$1")" 2>/dev/null +} # 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() +network_ready_device() { - local __tmp - for __tmp in $__NETWORK_CACHE __NETWORK_CACHE; do - unset "$__tmp" - done + ubus call network.device set_state \ + "$(printf '{ "name": "%s", "defer": false }' "$1")" 2>/dev/null } + +# flush the internal value cache to force re-reading values from ubus +network_flush_cache() { unset __NETWORK_CACHE; }