Browse Source

base-files: ipcalc.sh: Add netmask2prefix function

Also add is_contiguous to check if it's a valid netmask.

Signed-off-by: Philip Prindeville <[email protected]>
Philip Prindeville 1 year ago
parent
commit
dd256099c3

+ 2 - 5
package/base-files/files/bin/ipcalc.sh

@@ -44,6 +44,7 @@ case "$1" in
     # data is n.n.n.n/m.m.m.m format, like on a Cisco router
     # data is n.n.n.n/m.m.m.m format, like on a Cisco router
     str2ip ipaddr "${1%/*}" || exit 1
     str2ip ipaddr "${1%/*}" || exit 1
     str2ip netmask "${1#*/}" || exit 1
     str2ip netmask "${1#*/}" || exit 1
+    netmask2prefix prefix "$netmask" || exit 1
     shift
     shift
     ;;
     ;;
 */*)
 */*)
@@ -62,6 +63,7 @@ case "$1" in
     # address and netmask as two separate arguments
     # address and netmask as two separate arguments
     str2ip ipaddr "$1" || exit 1
     str2ip ipaddr "$1" || exit 1
     str2ip netmask "$2" || exit 1
     str2ip netmask "$2" || exit 1
+    netmask2prefix prefix "$netmask" || exit 1
     shift 2
     shift 2
     ;;
     ;;
 esac
 esac
@@ -71,11 +73,6 @@ if [ $# -ne 0 ] && [ $# -ne 2 ]; then
     usage
     usage
 fi
 fi
 
 
-if ! bitcount prefix "$netmask"; then
-    printf "Invalid netmask (%s)\n" "$netmask" >&2
-    exit 1
-fi
-
 # complement of the netmask, i.e. the hostmask
 # complement of the netmask, i.e. the hostmask
 hostmask=$((netmask ^ 0xffffffff))
 hostmask=$((netmask ^ 0xffffffff))
 network=$((ipaddr & netmask))
 network=$((ipaddr & netmask))

+ 39 - 0
package/base-files/files/lib/functions/ipv4.sh

@@ -157,3 +157,42 @@ prefix2netmask() {
     export -- "$__var=$(((~(uint_max >> __n)) & uint_max))"
     export -- "$__var=$(((~(uint_max >> __n)) & uint_max))"
 }
 }
 
 
+_is_contiguous() {
+    local __x="$1"	# no checking done
+    local __y=$((~__x & uint_max))
+    local __z=$(((__y + 1) & uint_max))
+
+    [ $((__z & __y)) -eq 0 ]
+}
+
+# check argument as being contiguous upper bits (and yes,
+# 0 doesn't have any discontiguous bits).
+is_contiguous() {
+    local __var="$1" __x="$2" __val=0
+    assert_uint32 "$__x" || return 1
+
+    local __y=$((~__x & uint_max))
+    local __z=$(((__y + 1) & uint_max))
+
+    [ $((__z & __y)) -eq 0 ] && __val=1
+
+    export -- "$__var=$__val"
+}
+
+# convert mask to prefix, validating that it's a conventional
+# (contiguous) netmask.
+netmask2prefix() {
+    local __var="$1" __n="$2" __cont __bits
+    assert_uint32 "$__n" || return 1
+
+    is_contiguous __cont "$__n" || return 1
+    if [ $__cont -eq 0 ]; then
+	printf "Not a contiguous netmask (%08x)\n" "$__n" >&2
+	return 1
+    fi
+
+    bitcount __bits "$__n"		# already checked
+
+    export -- "$__var=$__bits"
+}
+