Merge pull request #20494 from edsantiago/systest_subnet_check

CI: systest: safer random_rfc1918_subnet
This commit is contained in:
openshift-ci[bot] 2023-10-26 20:40:19 +00:00 committed by GitHub
commit c3fae01368
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 109 additions and 4 deletions

View File

@ -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
@ -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() {

View File

@ -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
@ -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