From nobody Tue May 12 07:48:45 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gF7y63R1sz6dDjq for ; Tue, 12 May 2026 07:48:46 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gF7y616pxz427m for ; Tue, 12 May 2026 07:48:46 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1778572126; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=R80TsFeuiyXKqvh5FI6LLoM36jzfPpXgs+VO0v2a/fE=; b=t6OTqK4zL7thaNpKLvhUSo/pZXIHwrhB0bKOGnH49hZoOPRRiMgKsrFewjlX0k7BaeVP/D /dnCd4sXeiEk3RCGzhXleSQQn9qVNYRugRRbkDR4Wvm2vEsgxYwrhqfSn66eXl7/928EUD 2kCgAFY9ByItoyWLRdV7OJzJwEM/ohTSfo2xpi3gN3J1bGNCNm3q/msv1SsBwrkGgIaJKb 6Ue4LqjeMbVnIS+aGbrGcTRhL7yuaKhWzjsO1UlDHs5e5Ey2Ll+ZMJOf1zygeYR0UBqR08 pHpzJM0Wb1n70JfzhajZxIwNfEp2QP5To38dZaqT7skZKw7aUILAvrHG+FwHXg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1778572126; a=rsa-sha256; cv=none; b=MAC5pPUpulJE5m3hOB2ikMsMhTqZd+F9Kn/Mh4RXcAQgARPcYx610QVC7mP4XEW9KZmgoi KJULvOu9WqUmfjwWFuI7BgYjHggCEX0DzO4X/766sZgMTmDlSr+JXKIihEDX4R4ZlAEWUB vKEftXtYTrok54YL8A1CRsgNVLF16mbYCTR7rIyXsvdKO/JoVYzu2syrcAWH2pNrZkA0iB zTEHOQ1+1c3wBDlHuAEDAGXoI6AZXQou22R4hjW7zZfdEUGqtwnbBQ3Mty+VS31RtbQA/o oS6WW09EoU/mq+PmwVr9unp2sUWMtBxxMGcd2RGe+sDirnPL6wsA3saFzXmsOw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1778572126; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=R80TsFeuiyXKqvh5FI6LLoM36jzfPpXgs+VO0v2a/fE=; b=adwU898V49cSL7jrewy7UFnWOT6HERl3zVOiU1JvWNpqu80MBM+jFOWJLLhLH8r5dHCdAA lrbT+mJdCJBaUoc0epf86sZidwt9YhDiCqeyxbflMgcyBNVFqMn8TqkH91Ar5MJTvMnTdd tpN0jVOJPJWxz9lUEF4Qrq/rHQ232bXT1UOpLM2P1lRzHi03fW79fhC5wvFoz1/iJFSb+F 6E/oA5GlNjo9OoMAjH2SaDAH6zJV9MIXR20XLR86LQO+RqD8mBXtz/69nR1//P9soOq/64 Ct/0AunLgYjBsti0qt/G+Ukv0ou4eso4MwcBJjAhxiyFL/OIZwdWChoDE1ziZg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gF7y56ycczvBQ for ; Tue, 12 May 2026 07:48:45 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 23ba8 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 12 May 2026 07:48:45 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: Boris Lytochkin From: Andrey V. Elsukov Subject: git: 3d39eadcdeb3 - main - ipfw: fix IPv6 flow label matching List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: ae X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 3d39eadcdeb301e95abdc94b1ad5d1255fa0f446 Auto-Submitted: auto-generated Date: Tue, 12 May 2026 07:48:45 +0000 Message-Id: <6a02db5d.23ba8.7e41e5d9@gitrepo.freebsd.org> The branch main has been updated by ae: URL: https://cgit.FreeBSD.org/src/commit/?id=3d39eadcdeb301e95abdc94b1ad5d1255fa0f446 commit 3d39eadcdeb301e95abdc94b1ad5d1255fa0f446 Author: Boris Lytochkin AuthorDate: 2026-05-12 07:44:10 +0000 Commit: Andrey V. Elsukov CommitDate: 2026-05-12 07:44:10 +0000 ipfw: fix IPv6 flow label matching * do not require just only ip6 proto for flow-id opcode in ipfw(8). ipv6-icmp, tcp, udp should be fine too. * fix off-by-one bug leading to out-of-bounds read. * apply IPV6_FLOWLABEL_MASK before comparison in flow6id_match(), so flow-id opcode will match a specified flow label. No need to take protocol version and traffic class into account. * add the test to verify that opcode is working correctly. Reviewed by: pouria Obtained from: Yandex LLC MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D56869 --- sbin/ipfw/ipfw2.c | 5 +-- sys/netpfil/ipfw/ip_fw2.c | 4 +- tests/sys/netpfil/common/pft_ping.py | 13 +++++- tests/sys/netpfil/ipfw/Makefile | 1 + tests/sys/netpfil/ipfw/ipv6-flow-id.sh | 78 ++++++++++++++++++++++++++++++++++ 5 files changed, 95 insertions(+), 6 deletions(-) diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c index e0e1339a1dce..06a1ee937cd7 100644 --- a/sbin/ipfw/ipfw2.c +++ b/sbin/ipfw/ipfw2.c @@ -5515,10 +5515,7 @@ read_options: break; case TOK_FLOWID: - if (proto != IPPROTO_IPV6 ) - errx( EX_USAGE, "flow-id filter is active " - "only for ipv6 protocol\n"); - fill_flow6( (ipfw_insn_u32 *) cmd, *av, cblen); + fill_flow6(insntod(cmd, u32), *av, cblen); av++; break; diff --git a/sys/netpfil/ipfw/ip_fw2.c b/sys/netpfil/ipfw/ip_fw2.c index 10690920e6fd..133aeeb969a6 100644 --- a/sys/netpfil/ipfw/ip_fw2.c +++ b/sys/netpfil/ipfw/ip_fw2.c @@ -780,7 +780,9 @@ static int flow6id_match(int curr_flow, ipfw_insn_u32 *cmd) { int i; - for (i=0; i <= cmd->o.arg1; ++i) + /* Mask proto version and traffic class out before comparing flow-id */ + curr_flow &= ntohl(IPV6_FLOWLABEL_MASK); + for (i=0; i < cmd->o.arg1; ++i) if (curr_flow == cmd->d[i]) return 1; return 0; diff --git a/tests/sys/netpfil/common/pft_ping.py b/tests/sys/netpfil/common/pft_ping.py index a2a1d9c7f4ec..ada4f8607ab0 100644 --- a/tests/sys/netpfil/common/pft_ping.py +++ b/tests/sys/netpfil/common/pft_ping.py @@ -63,6 +63,7 @@ def prepare_ipv6(send_params): dst_address = send_params.get('dst_address') hlim = send_params.get('hlim') tc = send_params.get('tc') + fl = send_params.get('fl') ip6 = sp.IPv6(dst=dst_address) if src_address: ip6.src = src_address @@ -70,6 +71,8 @@ def prepare_ipv6(send_params): ip6.hlim = hlim if tc: ip6.tc = tc + if fl: + ip6.fl = fl return ip6 @@ -224,6 +227,7 @@ def check_ipv6(expect_params, packet): flags = expect_params.get('flags') hlim = expect_params.get('hlim') tc = expect_params.get('tc') + fl = expect_params.get('fl') ip6 = packet.getlayer(sp.IPv6) if not ip6: LOGGER.debug('Packet is not IPv6!') @@ -245,6 +249,9 @@ def check_ipv6(expect_params, packet): if tc and ip6.tc != tc: LOGGER.debug(f'Wrong TC value {ip6.tc}, expected {tc}') return False + if fl and ip6.fl != fl: + LOGGER.debug(f'Wrong Flow Label value {ip6.fl}, expected {fl}') + return False return True @@ -635,6 +642,8 @@ def parse_args(): help='ICMP Echo Request payload size') parser_send.add_argument('--send-tc', type=int, help='IPv6 Traffic Class or IPv4 DiffServ / ToS') + parser_send.add_argument('--send-fl', type=int, + help='IPv6 Flow label') parser_send.add_argument('--send-tcpopt-unaligned', action='store_true', help='Include unaligned TCP options') parser_send.add_argument('--send-nop', action='store_true', @@ -652,6 +661,8 @@ def parse_args(): help='TCP sequence number') parser_expect.add_argument('--expect-tc', type=int, help='IPv6 Traffic Class or IPv4 DiffServ / ToS') + parser_expect.add_argument('--expect-fl', type=int, + help='IPv6 Flow Label') parser.add_argument('-v', '--verbose', action='store_true', help=('Enable verbose logging. Apart of potentially useful information ' @@ -673,7 +684,7 @@ def main(): send_params = {} expect_params = {} for param_name in ( - 'flags', 'hlim', 'length', 'mss', 'seq', 'tc', 'frag_length', + 'flags', 'hlim', 'length', 'mss', 'seq', 'tc', 'fl', 'frag_length', 'sport', 'dport', ): param_arg = vars(args).get(f'send_{param_name}') diff --git a/tests/sys/netpfil/ipfw/Makefile b/tests/sys/netpfil/ipfw/Makefile index 52f898050267..0be870945891 100644 --- a/tests/sys/netpfil/ipfw/Makefile +++ b/tests/sys/netpfil/ipfw/Makefile @@ -4,6 +4,7 @@ TESTSDIR= ${TESTSBASE}/sys/netpfil/ipfw ATF_TESTS_SH+= fwd \ divert \ + ipv6-flow-id \ log \ lookup \ table diff --git a/tests/sys/netpfil/ipfw/ipv6-flow-id.sh b/tests/sys/netpfil/ipfw/ipv6-flow-id.sh new file mode 100644 index 000000000000..fd3ef2f6cd81 --- /dev/null +++ b/tests/sys/netpfil/ipfw/ipv6-flow-id.sh @@ -0,0 +1,78 @@ +# +# Copyright (c) 2026 Boris Lytochkin +# +# SPDX-License-Identifier: BSD-2-Clause +# + +common_dir="$(atf_get_srcdir)/../common" +. ${common_dir}/utils.subr + +NC="nc -w 1 -dnN" + +setup_network_v6() +{ + epair="$1" + + ifconfig ${epair}a inet6 2001:db8:42::1/64 up no_dad -ifdisabled + + vnet_mkjail alcatraz ${epair}b + + ifconfig -j alcatraz ${epair}b inet6 2001:db8:42::2/64 up no_dad -ifdisabled + + jexec alcatraz /usr/sbin/inetd -p /dev/null $(atf_get_srcdir)/lookup_inetd.conf + + # Sanity checks + atf_check -s exit:0 -o ignore ping6 -i .1 -c 3 -s 1200 2001:db8:42::2 + atf_check -o "inline:GOOD 82\n" ${NC} 2001:db8:42::2 82 +} + +atf_test_case "ipv6fl" "cleanup" + +ipv6fl_head() +{ + atf_set descr 'flow-id test' + atf_set require.user root + atf_set require.progs python3 scapy +} + +ipv6fl_body() +{ + + firewall_init "ipfw" + + epair=$(vnet_mkepair) + + setup_network_v6 ${epair} + + # Check if the firewall is able to match exact IPv6 flow label + firewall_config "alcatraz" ipfw ipfw \ + "ipfw -q add 100 allow ip6 from any to any flow-id 0xbaad" \ + "ipfw -q add 200 deny ipv6-icmp from any to any icmp6types 128 in" + + # Check Flow Label matches + atf_check -s exit:0 ${common_dir}/pft_ping.py \ + --sendif ${epair}a \ + --fromaddr 2001:db8:42::1 \ + --to 2001:db8:42::2 \ + --send-fl $((0xbaad)) \ + --replyif ${epair}a + + # Check Flow Label mismatch + atf_check -s exit:1 ${common_dir}/pft_ping.py \ + --sendif ${epair}a \ + --fromaddr 2001:db8:42::1 \ + --to 2001:db8:42::2 \ + --send-fl $((0xf001)) \ + --replyif ${epair}a + +} + +ipv6fl_cleanup() +{ + firewall_cleanup $1 +} + +atf_init_test_cases() +{ + atf_add_test_case "ipv6fl" +}