From 70264b98c0362f850c3122966995db8ce4e8f0e8 Mon Sep 17 00:00:00 2001 From: "William A. Kennington III" Date: Fri, 7 May 2021 03:07:31 -0700 Subject: meta-google: network-sh: Add ip_to_bytes function This will be used to compare parts of addresses instead of applying regexes to them. Change-Id: Ide7366cab967e31a74cbb4002bad1046432037e3 Signed-off-by: William A. Kennington III --- .../recipes-google/networking/network-sh/lib.sh | 96 ++++++++++++++++++++++ .../recipes-google/networking/network-sh/test.sh | 73 +++++++++++++++- 2 files changed, 166 insertions(+), 3 deletions(-) (limited to 'meta-google') diff --git a/meta-google/recipes-google/networking/network-sh/lib.sh b/meta-google/recipes-google/networking/network-sh/lib.sh index f37f7196d7..2dc5103e08 100644 --- a/meta-google/recipes-google/networking/network-sh/lib.sh +++ b/meta-google/recipes-google/networking/network-sh/lib.sh @@ -57,6 +57,102 @@ mac_to_eui64() { printf '%02x%02x:%02x%02x:%02x%02x:%02x%02x\n' "${suffix_bytes[@]}" } +ip_to_bytes() { + local -n bytes_out="$1" + local str="$2" + + local bytes=() + local oldifs="$IFS" + # Heuristic for V4 / V6, validity will be checked as it is parsed + if [[ "$str" == *.* ]]; then + # Ensure we don't start or end with IFS + [ "${str:0:1}" != '.' ] || return 1 + [ "${str: -1}" != '.' ] || return 1 + + local v + # Split IPv4 address into octets + IFS=. + for v in $str; do + # IPv4 digits are always decimal numbers + if ! [[ "$v" =~ ^[0-9]+$ ]]; then + IFS="$oldifs" + return 1 + fi + # Each octet is a single byte, make sure the number isn't larger + if (( v > 0xff )); then + IFS="$oldifs" + return 1 + fi + bytes+=($v) + done + # IPv4 addresses must have all 4 bytes present + if (( "${#bytes[@]}" != 4 )); then + IFS="$oldifs" + return 1 + fi + else + # Ensure we bound the padding in an outer byte for + # IFS splitting to work correctly + [ "${str:0:2}" = '::' ] && str="0$str" + [ "${str: -2}" = '::' ] && str="${str}0" + + # Ensure we don't start or end with IFS + [ "${str:0:1}" != ':' ] || return 1 + [ "${str: -1}" != ':' ] || return 1 + + # Stores the bytes that come before ::, if it exists + local bytesBeforePad=() + local v + # Split the Address into hextets + IFS=: + for v in $str; do + # Handle ::, which translates to an empty string + if [ -z "$v" ]; then + # Only allow a single :: sequence in an address + if (( "${#bytesBeforePad[@]}" > 0 )); then + IFS="$oldifs" + return 1 + fi + # Store the already parsed upper bytes separately + # This allows us to calculate and insert padding + bytesBeforePad=("${bytes[@]}") + bytes=() + continue + fi + # IPv6 digits are always hex + if ! [[ "$v" =~ ^[[:xdigit:]]+$ ]]; then + IFS="$oldifs" + return 1 + fi + # Ensure the number is no larger than a hextet + v="0x$v" + if (( v > 0xffff )); then + IFS="$oldifs" + return 1 + fi + # Split the hextet into 2 bytes + bytes+=($(( v >> 8 ))) + bytes+=($(( v & 0xff ))) + done + # If we have ::, add padding + if (( "${#bytesBeforePad[@]}" > 0 )); then + # Fill the middle bytes with padding and store in `bytes` + while (( "${#bytes[@]}" + "${#bytesBeforePad[@]}" < 16 )); do + bytesBeforePad+=(0) + done + bytes=("${bytesBeforePad[@]}" "${bytes[@]}") + fi + # IPv6 addresses must have all 16 bytes present + if (( "${#bytes[@]}" != 16 )); then + IFS="$oldifs" + return 1 + fi + fi + + IFS="$oldifs" + bytes_out=("${bytes[@]}") +} + ipv6_pfx_concat() { local pfx="$1" local sfx="$2" diff --git a/meta-google/recipes-google/networking/network-sh/test.sh b/meta-google/recipes-google/networking/network-sh/test.sh index 57387c47cc..2361cfe3e8 100755 --- a/meta-google/recipes-google/networking/network-sh/test.sh +++ b/meta-google/recipes-google/networking/network-sh/test.sh @@ -21,6 +21,21 @@ else fi source lib.sh +expect_array_numeq() { + local -n a1="$1" + local -n a2="$2" + + if (( "${#a1[@]}" != "${#a2[@]}" )); then + echo " Line ${BASH_LINENO[0]} Array Size ${#a1[@]} != ${#a2[@]}" >&2 + test_err=1 + else + local i + for (( i=0; i < ${#a1[@]}; ++i )); do + expect_numeq "${a1[$i]}" "${a2[$i]}" + done + fi +} + test_mac_to_bytes() { out=() expect_err 1 mac_to_bytes out '' @@ -32,9 +47,7 @@ test_mac_to_bytes() { expect_err 0 mac_to_bytes out 'a2:0:f:de:0:29' expected=(0xa2 0 0xf 0xde 0 0x29) - for (( i=0; i < ${#expected[@]}; ++i )); do - expect_numeq "${out[$i]}" "${expected[$i]}" - done + expect_array_numeq out expected } test_mac_to_eui_48() { @@ -47,6 +60,60 @@ test_eui_64() { expect_streq "$str" '1334:56ff:fe78:90af' } +test_ip4_to_bytes() { + out=() + expect_err 1 ip_to_bytes out '' + expect_err 1 ip_to_bytes out '10.0.0.' + expect_err 1 ip_to_bytes out '.0.1.1' + expect_err 1 ip_to_bytes out '10.0.0' + expect_err 1 ip_to_bytes out '10.0..0' + expect_err 1 ip_to_bytes out '.10.0.0.0' + expect_err 1 ip_to_bytes out '10.0.0.0.' + expect_err 1 ip_to_bytes out '10.0.0.256' + expect_err 1 ip_to_bytes out '10.0.0.0.256' + expect_err 1 ip_to_bytes out '10.0.0.0.1' + + expect_err 0 ip_to_bytes out '10.0.0.1' + expected=(10 0 0 1) + expect_array_numeq out expected +} + +test_ip6_to_bytes() { + out=() + expect_err 1 ip_to_bytes out '' + expect_err 1 ip_to_bytes out ':::' + expect_err 1 ip_to_bytes out '::z' + expect_err 1 ip_to_bytes out '1::1::1' + expect_err 1 ip_to_bytes out '1:1:1' + expect_err 1 ip_to_bytes out ':1::1' + expect_err 1 ip_to_bytes out '1::1:' + + expect_err 0 ip_to_bytes out '::' + expected=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + expect_array_numeq out expected + out=() + + expect_err 0 ip_to_bytes out '::1' + expected=(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1) + expect_array_numeq out expected + out=() + + expect_err 0 ip_to_bytes out 'fd00::' + expected=(0xfd 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + expect_array_numeq out expected + out=() + + expect_err 0 ip_to_bytes out 'fd00:ffee::ddff:22' + expected=(0xfd 0 0xff 0xee 0 0 0 0 0 0 0 0 0xdd 0xff 0 0x22) + expect_array_numeq out expected + out=() + + expect_err 0 ip_to_bytes out '1:2:3:4:5:6:7:8' + expected=(0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8) + expect_array_numeq out expected + out=() +} + test_ipv6_pfx_concat() { # Invalid inputs expect_err 1 ipv6_pfx_concat 'fd/64' '1234:5678:90af' -- cgit v1.2.3