Files
ocserv/tests/test-fw-normalize-route
Nikos Mavrogiannopoulos 9c44e09356 ocserv-fw-nftables: replace ipcalc with pure-shell mask_to_prefix
ipcalc was used only to convert dotted-decimal subnet masks to CIDR
prefix lengths (e.g. 255.255.0.0 -> 16), replaced with a POSIX shell
script.

Relates: #709

Signed-off-by: Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com>
2026-05-02 17:21:38 +02:00

183 lines
5.7 KiB
Bash
Executable File

#!/bin/sh
#
# Copyright (C) 2026 Nikos Mavrogiannopoulos
#
# This file is part of ocserv.
#
# ocserv is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at
# your option) any later version.
#
# ocserv is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Unit test for the mask_to_prefix / normalize_route shell functions in
# ocserv-fw-nftables. The functions are extracted directly from the script
# so this test always exercises the real implementation.
srcdir=${srcdir:-.}
FW_SCRIPT="${srcdir}/../src/ocserv-fw-nftables"
if ! test -f "${FW_SCRIPT}"; then
echo "cannot find ${FW_SCRIPT}"
exit 1
fi
echo "Testing mask_to_prefix and normalize_route from ${FW_SCRIPT}..."
# Load the two functions directly from the firewall script. awk extracts
# each function body (from "funcname() {" to the closing "}" at column 0).
eval "$(awk '/^mask_to_prefix\(\)/,/^\}/' "${FW_SCRIPT}")"
eval "$(awk '/^normalize_route\(\)/,/^\}/' "${FW_SCRIPT}")"
if ! type mask_to_prefix > /dev/null 2>&1 || \
! type normalize_route > /dev/null 2>&1; then
echo "failed to load functions from ${FW_SCRIPT}"
exit 1
fi
# ---- test harness -----------------------------------------------------------
FAIL=0
check() {
input="$1"
expected="$2"
got=$(normalize_route "$input")
if test "$got" != "$expected"; then
echo "FAIL: normalize_route '$input' -> '$got', expected '$expected'"
FAIL=1
fi
}
check_mask() {
mask="$1"
expected="$2"
got=$(mask_to_prefix "$mask")
if test "$got" != "$expected"; then
echo "FAIL: mask_to_prefix '$mask' -> '$got', expected '$expected'"
FAIL=1
fi
}
# Expect mask_to_prefix to fail (return non-zero, produce no output)
check_mask_invalid() {
mask="$1"
got=$(mask_to_prefix "$mask" 2>/dev/null)
if test $? = 0 || test -n "$got"; then
echo "FAIL: mask_to_prefix '$mask' should have failed but returned '$got'"
FAIL=1
fi
}
# Expect normalize_route to fail (return non-zero, produce no output)
check_route_invalid() {
route="$1"
got=$(normalize_route "$route" 2>/dev/null)
if test $? = 0 || test -n "$got"; then
echo "FAIL: normalize_route '$route' should have failed but returned '$got'"
FAIL=1
fi
}
# ---- mask_to_prefix: all 33 valid prefix lengths ----------------------------
check_mask "0.0.0.0" 0
check_mask "128.0.0.0" 1
check_mask "192.0.0.0" 2
check_mask "224.0.0.0" 3
check_mask "240.0.0.0" 4
check_mask "248.0.0.0" 5
check_mask "252.0.0.0" 6
check_mask "254.0.0.0" 7
check_mask "255.0.0.0" 8
check_mask "255.128.0.0" 9
check_mask "255.192.0.0" 10
check_mask "255.224.0.0" 11
check_mask "255.240.0.0" 12
check_mask "255.248.0.0" 13
check_mask "255.252.0.0" 14
check_mask "255.254.0.0" 15
check_mask "255.255.0.0" 16
check_mask "255.255.128.0" 17
check_mask "255.255.192.0" 18
check_mask "255.255.224.0" 19
check_mask "255.255.240.0" 20
check_mask "255.255.248.0" 21
check_mask "255.255.252.0" 22
check_mask "255.255.254.0" 23
check_mask "255.255.255.0" 24
check_mask "255.255.255.128" 25
check_mask "255.255.255.192" 26
check_mask "255.255.255.224" 27
check_mask "255.255.255.240" 28
check_mask "255.255.255.248" 29
check_mask "255.255.255.252" 30
check_mask "255.255.255.254" 31
check_mask "255.255.255.255" 32
# ---- normalize_route: dotted-decimal mask conversion ------------------------
check "10.0.0.0/255.0.0.0" "10.0.0.0/8"
check "172.16.0.0/255.240.0.0" "172.16.0.0/12"
check "192.168.0.0/255.255.0.0" "192.168.0.0/16"
check "192.168.1.0/255.255.255.0" "192.168.1.0/24"
check "192.168.1.128/255.255.255.128" "192.168.1.128/25"
check "192.168.1.192/255.255.255.192" "192.168.1.192/26"
check "0.0.0.0/0.0.0.0" "0.0.0.0/0"
check "192.168.1.1/255.255.255.255" "192.168.1.1/32"
# ---- normalize_route: already-CIDR IPv4 passed through ---------------------
check "10.0.0.0/8" "10.0.0.0/8"
check "192.168.1.0/24" "192.168.1.0/24"
check "0.0.0.0/0" "0.0.0.0/0"
check "192.168.1.1/32" "192.168.1.1/32"
# ---- normalize_route: IPv6 passed through unchanged ------------------------
check "fd00::/48" "fd00::/48"
check "2001:db8::/32" "2001:db8::/32"
check "fd91:6d14:7241:dc6a::/112" "fd91:6d14:7241:dc6a::/112"
check "fc7d:b139:f7ba:5f53:c634::/80" "fc7d:b139:f7ba:5f53:c634::/80"
check "::/0" "::/0"
check "::1/128" "::1/128"
# ---- mask_to_prefix: invalid octet values -----------------------------------
check_mask_invalid "255.300.0.0"
check_mask_invalid "255.255.127.0"
check_mask_invalid "255.1.0.0"
# ---- mask_to_prefix: non-contiguous masks -----------------------------------
check_mask_invalid "254.192.128.0"
check_mask_invalid "255.0.255.0"
check_mask_invalid "0.255.0.0"
check_mask_invalid "255.255.0.255"
# ---- mask_to_prefix: wrong number of octets ---------------------------------
check_mask_invalid "255.255.0"
check_mask_invalid "255.255.255.0.0"
# ---- normalize_route: propagates mask_to_prefix failure ---------------------
check_route_invalid "10.0.0.0/255.0.255.0"
check_route_invalid "10.0.0.0/255.255.255.0.0"
# ---- result -----------------------------------------------------------------
if test "$FAIL" = "0"; then
echo "All tests passed."
exit 0
else
exit 1
fi