diff --git a/shell-ip-address b/shell-ip-address index 46d5c27..7a6a1e7 100644 --- a/shell-ip-address +++ b/shell-ip-address @@ -88,6 +88,26 @@ __ipv4_hex() printf '%02x' "$@" } +__len2mask_32() +{ + local len + len="${1-}" + + [ -n "$len" ] || + return 2 + + local mask + local pos=0 n nbits + while [ "$len" -lt 32 ]; do + n=$(( ($len | 7) + 1 - $len )) + nbits=$(((1 << $n) - 1)) + len=$(($len + $n)) + pos=$(( ($pos << $n) | $nbits )) + done + mask=$((0xFFFFFFFF - $pos)) + printf '%s' "$mask" +} + ### Checks that IP address is in subnet ### Usage example: ### ipv4_ip_subnet 172.16.1.2 172.16.1.0/24; echo res=$? @@ -154,14 +174,15 @@ ipv4_mask2prefix() ### 255.255.255.0 ipv4_prefix2mask() { - local len + local len mask len="${1-}" - [ "$len" -ge 0 ] && [ "$len" -le 32 ] 2>/dev/null || + [ "$len" = 0 ] || shell_var_is_number "$len" || + return 1 + [ "$len" -ge 0 ] && [ "$len" -le 32 ] || return 1 - local position=$((0xFFFFFFFF)) - local mask=$(($position - ($position >> $len))) + mask="$(__len2mask_32 "$len")" printf '%s.%s.%s.%s\n' \ "$(($mask >> 24 & 0xFF))" \ diff --git a/tests/ip_address_mask b/tests/ip_address_mask new file mode 100644 index 0000000..88cac82 --- /dev/null +++ b/tests/ip_address_mask @@ -0,0 +1,189 @@ +#!/bin/ash -efu + +ip_address_mask_test400() { # UnitTest + . ../shell-ip-address + + local rc=0 out= + local plen=0 + ipv4_prefix2mask "$plen" || rc=1 + out="$(ipv4_prefix2mask "$plen")" + + assertTrue "/$plen" $rc + assertEquals "0.0.0.0" "$out" +} + +ip_address_mask_test401() { # UnitTest + . ../shell-ip-address + + local rc=0 out= + local plen=1 + ipv4_prefix2mask "$plen" || rc=1 + out="$(ipv4_prefix2mask "$plen")" + + assertTrue "/$plen" $rc + assertEquals "128.0.0.0" "$out" +} + +ip_address_mask_test402() { # UnitTest + . ../shell-ip-address + + local rc=0 out= + local plen=4 + ipv4_prefix2mask "$plen" || rc=1 + out="$(ipv4_prefix2mask "$plen")" + + assertTrue "/$plen" $rc + assertEquals "240.0.0.0" "$out" +} + +ip_address_mask_test403() { # UnitTest + . ../shell-ip-address + + local rc=0 out= + local plen=8 + ipv4_prefix2mask "$plen" || rc=1 + out="$(ipv4_prefix2mask "$plen")" + + assertTrue "/$plen" $rc + assertEquals "255.0.0.0" "$out" +} + +ip_address_mask_test404() { # UnitTest + . ../shell-ip-address + + local rc=0 out= + local plen=10 + ipv4_prefix2mask "$plen" || rc=1 + out="$(ipv4_prefix2mask "$plen")" + + assertTrue "/$plen" $rc + assertEquals "255.192.0.0" "$out" +} + +ip_address_mask_test405() { # UnitTest + . ../shell-ip-address + + local rc=0 out= + local plen=11 + ipv4_prefix2mask "$plen" || rc=1 + out="$(ipv4_prefix2mask "$plen")" + + assertTrue "/$plen" $rc + assertEquals "255.224.0.0" "$out" +} + +ip_address_mask_test406() { # UnitTest + . ../shell-ip-address + + local rc=0 out= + local plen=13 + ipv4_prefix2mask "$plen" || rc=1 + out="$(ipv4_prefix2mask "$plen")" + + assertTrue "/$plen" $rc + assertEquals "255.248.0.0" "$out" +} + +ip_address_mask_test407() { # UnitTest + . ../shell-ip-address + + local rc=0 out= + local plen=15 + ipv4_prefix2mask "$plen" || rc=1 + out="$(ipv4_prefix2mask "$plen")" + + assertTrue "/$plen" $rc + assertEquals "255.254.0.0" "$out" +} + +ip_address_mask_test408() { # UnitTest + . ../shell-ip-address + + local rc=0 out= + local plen=16 + ipv4_prefix2mask "$plen" || rc=1 + out="$(ipv4_prefix2mask "$plen")" + + assertTrue "/$plen" $rc + assertEquals "255.255.0.0" "$out" +} + +ip_address_mask_test409() { # UnitTest + . ../shell-ip-address + + local rc=0 out= + local plen=24 + ipv4_prefix2mask "$plen" || rc=1 + out="$(ipv4_prefix2mask "$plen")" + + assertTrue "/$plen" $rc + assertEquals "255.255.255.0" "$out" +} + +ip_address_mask_test410() { # UnitTest + . ../shell-ip-address + + local rc=0 out= + local plen=30 + ipv4_prefix2mask "$plen" || rc=1 + out="$(ipv4_prefix2mask "$plen")" + + assertTrue "/$plen" $rc + assertEquals "255.255.255.252" "$out" +} + +ip_address_mask_test411() { # UnitTest + . ../shell-ip-address + + local rc=0 out= + local plen=32 + ipv4_prefix2mask "$plen" || rc=1 + out="$(ipv4_prefix2mask "$plen")" + + assertTrue "/$plen" $rc + assertEquals "255.255.255.255" "$out" +} + +ip_address_mask_test412() { # UnitTest + . ../shell-ip-address + + local rc=0 + local plen=33 + ipv4_prefix2mask "$plen" || rc=1 + + assertFalse "prefix length too large: $plen" $rc + assertNull "$(ipv4_prefix2mask "$plen")" +} + +ip_address_mask_test413() { # UnitTest + . ../shell-ip-address + + local rc=0 + local plen='' + ipv4_prefix2mask "$plen" || rc=1 + + assertFalse "empty prefix length" $rc + assertNull "$(ipv4_prefix2mask "$plen")" +} + +ip_address_mask_test414() { # UnitTest + . ../shell-ip-address + + local rc=0 + local plen=xyz + ipv4_prefix2mask "$plen" || rc=1 + + assertFalse "garbage prefix length: $plen" $rc + assertNull "$(ipv4_prefix2mask "$plen")" +} + +ip_address_mask_test416() { # UnitTest + . ../shell-ip-address + + local rc=0 + local plen=255.255.224.0 + ipv4_prefix2mask "$plen" || rc=1 + + assertFalse "passed netmask: $plen" $rc + assertNull "$(ipv4_prefix2mask "$plen")" +} diff --git a/tests/runtests b/tests/runtests index 5ac4212..9b8fc52 100755 --- a/tests/runtests +++ b/tests/runtests @@ -36,7 +36,7 @@ for s in \ git_config_foreach git_config_get git_config_count git_config_list git_config_set git_config_unset git_config_append \ shell_var_unquote shell_var_trim \ fill_mask \ - ip_address \ + ip_address ip_address_mask \ cmdline_foreach \ cmdline_get \ run_scripts \