git: 6eba055fcf5b - main - ipfw: fix parsing error in nat config port_range

From: Andrey V. Elsukov <ae_at_FreeBSD.org>
Date: Thu, 21 May 2026 08:11:00 UTC
The branch main has been updated by ae:

URL: https://cgit.FreeBSD.org/src/commit/?id=6eba055fcf5b0bbfbebcac59f5982d13815001b0

commit 6eba055fcf5b0bbfbebcac59f5982d13815001b0
Author:     Vyacheslav Terehov <terehovv@mail.ru>
AuthorDate: 2026-05-21 07:15:22 +0000
Commit:     Andrey V. Elsukov <ae@FreeBSD.org>
CommitDate: 2026-05-21 07:15:22 +0000

    ipfw: fix parsing error in nat config port_range
    
    Also fix the corresponding tests.
    
    PR:             263240
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D57010
---
 sbin/ipfw/ipfw.8                |  3 ++-
 sbin/ipfw/nat.c                 | 29 ++++++++++++++++-------------
 tests/sys/netpfil/common/nat.sh | 26 ++++++++++++++------------
 3 files changed, 32 insertions(+), 26 deletions(-)

diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8
index 2d3b0722cc42..b01982ff4c53 100644
--- a/sbin/ipfw/ipfw.8
+++ b/sbin/ipfw/ipfw.8
@@ -1,5 +1,5 @@
 .\"
-.Dd March 1, 2026
+.Dd May 21, 2026
 .Dt IPFW 8
 .Os
 .Sh NAME
@@ -3519,6 +3519,7 @@ Obey transparent proxy rules only, packet aliasing is not performed.
 Skip instance in case of global state lookup (see below).
 .It Cm port_range Ar lower-upper
 Set the aliasing ports between the ranges given.
+Ports must be in the range 1024-65535.
 Upper port has to be greater than lower.
 .It Cm udp_eim
 When enabled, UDP packets use endpoint-independent mapping (EIM) from RFC 4787
diff --git a/sbin/ipfw/nat.c b/sbin/ipfw/nat.c
index db74abaab233..a5691200943c 100644
--- a/sbin/ipfw/nat.c
+++ b/sbin/ipfw/nat.c
@@ -757,25 +757,28 @@ nat_show_cfg(struct nat44_cfg_nat *n, void *arg __unused)
 }
 
 static int
-nat_port_alias_parse(char *str, u_short *lpout, u_short *hpout) {
+nat_port_alias_parse(char *str, u_short *lpout, u_short *hpout)
+{
 	long lp, hp;
-	char *ptr;
+	char *ptr, *substr;
+
+	substr = strsep(&str, "-");
+	if (substr == NULL || str == NULL)
+		return (0);
+
 	/* Lower port parsing */
-	lp = (long) strtol(str, &ptr, 10);
-	if (lp < 1024 || lp > 65535)
-		return 0;
-	if (!ptr || *ptr != '-')
-		return 0;
+	lp = (long) strtol(substr, &ptr, 0);
+	if (*ptr != '\0' || lp < 1024 || lp > 65535)
+		return (0);
+
 	/* Upper port parsing */
-	hp = (long) strtol(ptr, &ptr, 10);
-	if (hp < 1024 || hp > 65535)
-		return 0;
-	if (ptr)
-		return 0;
+	hp = (long) strtol(str, &ptr, 0);
+	if (*ptr != '\0' || hp < 1024 || hp > 65535)
+		return (0);
 
 	*lpout = (u_short) lp;
 	*hpout = (u_short) hp;
-	return 1;
+	return (1);
 }
 
 void
diff --git a/tests/sys/netpfil/common/nat.sh b/tests/sys/netpfil/common/nat.sh
index 023b0742ec6b..2b828dc03fdc 100644
--- a/tests/sys/netpfil/common/nat.sh
+++ b/tests/sys/netpfil/common/nat.sh
@@ -26,6 +26,8 @@
 #
 #
 
+set -e
+
 . $(atf_get_srcdir)/utils.subr
 . $(atf_get_srcdir)/runner.subr
 
@@ -178,13 +180,13 @@ common_cgn() {
 	atf_check -s exit:2 -o ignore jexec client1 ping -t 1 -c 1 198.51.100.2
 	atf_check -s exit:2 -o ignore jexec client2 ping -t 1 -c 1 198.51.100.2
 
-	if [[ $portalias ]]; then
+	if [ ${portalias} = "true" ]; then
 		firewall_config nat $firewall \
 			"ipfw" \
-				"ipfw -q nat 123 config if ${epair_host_nat}b unreg_cgn port_alias 2000-2999" \
-				"ipfw -q nat 456 config if ${epair_host_nat}b unreg_cgn port_alias 3000-3999" \
-				"ipfw -q add 1000 nat 123 all from any to 198.51.100.2 2000-2999 in via ${epair_host_nat}b" \
-				"ipfw -q add 2000 nat 456 all from any to 198.51.100.2 3000-3999 in via ${epair_host_nat}b" \
+				"ipfw -q nat 123 config if ${epair_host_nat}b unreg_cgn port_range 2000-2999" \
+				"ipfw -q nat 456 config if ${epair_host_nat}b unreg_cgn port_range 3000-3999" \
+				"ipfw -q add 1000 nat 123 all from any to 198.51.100.0/24 2000-2999 in via ${epair_host_nat}b" \
+				"ipfw -q add 2000 nat 456 all from any to 198.51.100.0/24 3000-3999 in via ${epair_host_nat}b" \
 				"ipfw -q add 3000 nat 123 all from 100.64.0.2 to any out via ${epair_host_nat}b" \
 				"ipfw -q add 4000 nat 456 all from 100.64.1.2 to any out via ${epair_host_nat}b"
 	else
@@ -194,16 +196,16 @@ common_cgn() {
 				"ipfw -q add 1000 nat 123 all from any to any"
 	fi
 
-	# ping is successful now
-	atf_check -s exit:0 -o ignore jexec client1 ping -t 1 -c 1 198.51.100.2
-	atf_check -s exit:0 -o ignore jexec client2 ping -t 1 -c 1 198.51.100.2
-
 	# if portalias, test a tcp server/client with nc
-	if [[ $portalias ]]; then
+	if [ ${portalias} = "true" ]; then
 		for inst in 1 2; do
-			daemon nc -p 198.51.100.2 7
-			atf_check -s exit:0 -o ignore jexec client$inst sh -c "echo | nc -N 198.51.100.2 7"
+			daemon nc -l 198.51.100.2 7
+			atf_check -s exit:0 -o ignore -e ignore jexec client$inst nc -z 198.51.100.2 7
 		done
+	else
+		# ping is successful now
+		atf_check -s exit:0 -o ignore jexec client1 ping -t 1 -c 1 198.51.100.2
+		atf_check -s exit:0 -o ignore jexec client2 ping -t 1 -c 1 198.51.100.2
 	fi
 }