Skip to content

Commit

Permalink
Merge pull request #20494 from edsantiago/systest_subnet_check
Browse files Browse the repository at this point in the history
CI: systest: safer random_rfc1918_subnet
  • Loading branch information
openshift-ci[bot] authored Oct 26, 2023
2 parents e5101b2 + 9e3363c commit c3fae01
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 4 deletions.
73 changes: 69 additions & 4 deletions test/system/helpers.network.bash
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,13 @@ function random_rfc1918_subnet() {
local retries=1024

while [ "$retries" -gt 0 ];do
local cidr=172.$(( 16 + $RANDOM % 16 )).$(( $RANDOM & 255 ))
# 172.16.0.0 -> 172.31.255.255
local n1=172
local n2=$(( 16 + $RANDOM & 15 ))
local n3=$(( $RANDOM & 255 ))

in_use=$(ip route list | grep -F $cidr)
if [ -z "$in_use" ]; then
echo "$cidr"
if ! subnet_in_use $n1 $n2 $n3; then
echo "$n1.$n2.$n3"
return
fi

Expand All @@ -140,6 +142,69 @@ function random_rfc1918_subnet() {
die "Could not find a random not-in-use rfc1918 subnet"
}

# subnet_in_use() - true if subnet already routed on host
function subnet_in_use() {
local subnet_script=${PODMAN_TMPDIR-/var/tmp}/subnet-in-use
rm -f $subnet_script

# This would be a nightmare to do in bash. ipcalc, ipcalc-ng, sipcalc
# would be nice but are unavailable some environments (cough RHEL).
# Likewise python/perl netmask modules. So, use bare-bones perl.
cat >$subnet_script <<"EOF"
#!/usr/bin/env perl
use strict;
use warnings;
# 3 octets, in binary: 172.16.x -> 1010 1100 0000 1000 xxxx xxxx ...
my $subnet_to_check = sprintf("%08b%08b%08b", @ARGV);
my $found = 0;
# Input is "ip route list", one or more lines like '10.0.0.0/8 via ...'
while (<STDIN>) {
# Only interested in x.x.x.x/n lines
if (m!^([\d.]+)/(\d+)!) {
my ($ip, $bits) = ($1, $2);
# Our caller has /24 granularity, so treat /30 on host as /24.
$bits = 24 if $bits > 24;
# Temporary: entire subnet as binary string. 4 octets, split,
# then represented as a 32-bit binary string.
my $net = sprintf("%08b%08b%08b%08b", split(/\./, $ip));
# Now truncate those 32 bits down to the route's netmask size.
# This is the actual subnet range in use on the host.
my $net_truncated = sprintf("%.*s", $bits, $net);
# Desired subnet is in use if it matches a host route prefix
# print STDERR "--- $subnet_to_check in $net_truncated (@ARGV in $ip/$bits)\n";
$found = 1 if $subnet_to_check =~ /^$net_truncated/;
}
}
# Convert to shell exit status (0 = success)
exit !$found;
EOF

chmod 755 $subnet_script

# This runs 'ip route list', converts x.x.x.x/n to its binary prefix,
# then checks if our desired subnet matches that prefix (i.e. is in
# that range). Existing routes with size greater than 24 are
# normalized to /24 because that's the granularity of our
# random_rfc1918_subnet code.
#
# Contrived examples:
# 127.0.0.0/1 -> 0
# 128.0.0.0/1 -> 1
# 10.0.0.0/8 -> 00001010
#
# I'm so sorry for the ugliness.
ip route list | $subnet_script $*
}

# ipv4_get_route_default() - Print first default IPv4 route reported by netlink
# $1: Optional output of 'ip -j -4 route show' from a different context
function ipv4_get_route_default() {
Expand Down
40 changes: 40 additions & 0 deletions test/system/helpers.t
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ die() {
testnum=0
rc=0

# Possibly used by the code we're testing
PODMAN_TMPDIR=$(mktemp -d --tmpdir=${TMPDIR:-/tmp} podman_helper_tests.XXXXXX)
trap 'rm -rf $PODMAN_TMPDIR' 0

###############################################################################
# BEGIN test the parse_table helper

Expand Down Expand Up @@ -242,6 +246,42 @@ done < <(parse_table "$table")

# END ipv6_to_procfs
###############################################################################
# BEGIN subnet_in_use ... because that's complicated

# Override ip command
function ip() {
echo "default foo"
echo "192.168.0.0/16"
echo "172.17.2.3/30"
echo "172.128.0.0/9"
}

# x.y.z | result (1 = in use, 0 = not in use - opposite of exit code)
table="
172 | 0 | 0 | 0
172 | 0 | 255 | 0
172 | 1 | 1 | 0
172 | 1 | 2 | 0
172 | 1 | 3 | 0
172 | 17 | 1 | 0
172 | 17 | 2 | 1
172 | 17 | 3 | 0
172 | 127 | 0 | 0
172 | 128 | 0 | 1
172 | 255 | 2 | 1
192 | 168 | 1 | 1
"

while read n1 n2 n3 expect; do
subnet_in_use $n1 $n2 $n3
actual=$?
check_result "$((1 - $actual))" "$expect" "subnet_in_use $n1.$n2.$n3"
done < <(parse_table "$table")

unset -f ip

# END subnet_in_use
###############################################################################
# BEGIN check_assert
#
# This is way, way more complicated than it should be. The purpose is
Expand Down

0 comments on commit c3fae01

Please sign in to comment.