From nobody Thu Oct 26 14:16:53 2023 X-Original-To: dev-commits-src-main@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 4SGSXj4l42z4xsBV; Thu, 26 Oct 2023 14:16:53 +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 "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4SGSXj4BwMz4G3P; Thu, 26 Oct 2023 14:16:53 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1698329813; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=6rOXXM5l/islqA/RKU5VWJUByqS3vhoAAsyqqZnKbjs=; b=o3xjpc6Xgg5Jbj72lqSPJ9r8OWoUibCWHcHpNpjq/LNFD2l8BESHoz5sn/Bf3nOefyhAj5 jFsrvPCDOlYsPTLH3yTrI84emhmv2lvEKIGSTqZYYT3huKs9zgx3FfZLZM8JccL/lSc9Dn Axb3U3GFrcw1wavUuPih+vSVPJnQMCticgIlRfBjxxHXxKKDflkituxD6hUEPR+8NIxt1V 97TkN+p0oOuBEPs+8tWECfwEZrrA097qFF1PbjTMRjIbfJMIxBrD5Z/ZbjNfPitP/jGJix a79yGrOTn1oEThrIJFaXEdkzHlugRenqQTvSW5unbLaRmGjbc0rWSvcklKjJiA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1698329813; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=6rOXXM5l/islqA/RKU5VWJUByqS3vhoAAsyqqZnKbjs=; b=jVFZWD4eTqOVml6ZJBxRNr18dWaQdMBvRoN/bgr+YUgrylHo9hBT51S+Mu0+koYCH0mCpp ER9pZMxL1qaat1JJhF68Oc0HwKINzeJ5sJNdT3tMto1Vx5ufiN6c+BbmgtQZXYNsYQVtYG vkbdSwyBdZa+SydFrB7TVKx+BupZaXk/9HMqdqM9ZaQXb1+cfUE79tqV4qcv4BV3tOX7SY lbd1Ot/heanJbgoWAlEz7KL1TeD9Vo/eMpqOepe8alV8JUznorsME1TOdfR9G2FAE+PutE fr3jQHARKTb1Nl41LVdTaqpfAaTFcdOSPckRTzQf1+J+DV9nY4rSHXNIMrgMvw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1698329813; a=rsa-sha256; cv=none; b=E56DNWkDN4BupBGn/CiyX7RaflwpHyA7Uva+e4rVwaoK1xffjboIZ/1QCTMKZ0AP8dL4ca DGG6851eZuBg6sjC5h4qum90kkI/xpHnCoSd2RvXLaPEc7lFMMPP9aXyYIlXR/PP8w09fb sphBjlZgjEZA+iejlg8H7vS02rU0YlUCbWy21fka2HQkHP5f29LC9mGT2ht05xAIv+D0Fz F8foiZsAZCQIwHNVotgMuIBtf4qHo2s8306X4yclYwKXlgAq0QKRRnBnMKlC9/crpTWT+2 2oJvhrn9oBh6oSAnB0wVgPMadU91UW2CpM1TD/JuoBZCDOdXbbvdiTjR8MyJLQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (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 did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4SGSXj3BDRzb0D; Thu, 26 Oct 2023 14:16:53 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 39QEGrgx055043; Thu, 26 Oct 2023 14:16:53 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 39QEGrnK055040; Thu, 26 Oct 2023 14:16:53 GMT (envelope-from git) Date: Thu, 26 Oct 2023 14:16:53 GMT Message-Id: <202310261416.39QEGrnK055040@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kristof Provost Subject: git: d7c9de2d68ca - main - pf tests: Add option to send fragmented packets List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kp X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: d7c9de2d68ca81c557e069c2b431529cf597886c Auto-Submitted: auto-generated The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=d7c9de2d68ca81c557e069c2b431529cf597886c commit d7c9de2d68ca81c557e069c2b431529cf597886c Author: Kajetan Staszkiewicz AuthorDate: 2023-10-26 09:14:14 +0000 Commit: Kristof Provost CommitDate: 2023-10-26 13:25:20 +0000 pf tests: Add option to send fragmented packets Add option to send fragmented packets and to properly sniff them by reassembling them by the sniffer itself. Reviewed by: kp Sponsored by: InnoGames GmbH Differential Revision: https://reviews.freebsd.org/D42354 --- tests/sys/netpfil/common/pft_ping.py | 39 +++++++++++++++++++++++++++--------- tests/sys/netpfil/common/sniffer.py | 18 +++++++++++++---- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/tests/sys/netpfil/common/pft_ping.py b/tests/sys/netpfil/common/pft_ping.py index af5b84e34c67..1abf4f609832 100644 --- a/tests/sys/netpfil/common/pft_ping.py +++ b/tests/sys/netpfil/common/pft_ping.py @@ -82,17 +82,29 @@ def prepare_ipv4(dst_address, send_params): def send_icmp_ping(dst_address, sendif, send_params): send_length = send_params['length'] + send_frag_length = send_params['frag_length'] + packets = [] ether = sp.Ether() if ':' in dst_address: ip6 = prepare_ipv6(dst_address, send_params) icmp = sp.ICMPv6EchoRequest(data=sp.raw(build_payload(send_length))) - req = ether / ip6 / icmp + if send_frag_length: + for packet in sp.fragment(ip6 / icmp, fragsize=send_frag_length): + packets.append(ether / packet) + else: + packets.append(ether / ip6 / icmp) + else: ip = prepare_ipv4(dst_address, send_params) icmp = sp.ICMP(type='echo-request') raw = sp.raw(build_payload(send_length)) - req = ether / ip / icmp / raw - sp.sendp(req, sendif, verbose=False) + if send_frag_length: + for packet in sp.fragment(ip / icmp / raw, fragsize=send_frag_length): + packets.append(ether / packet) + else: + packets.append(ether / ip / icmp / raw) + for packet in packets: + sp.sendp(packet, sendif, verbose=False) def send_tcp_syn(dst_address, sendif, send_params): @@ -372,7 +384,7 @@ def check_tcp_syn_reply(expect_params, packet): return check_tcp_syn_reply_4(expect_params, packet) -def setup_sniffer(recvif, ping_type, sniff_type, expect_params): +def setup_sniffer(recvif, ping_type, sniff_type, expect_params, defrag): if ping_type == 'icmp' and sniff_type == 'request': checkfn = check_ping_request elif ping_type == 'icmp' and sniff_type == 'reply': @@ -384,7 +396,7 @@ def setup_sniffer(recvif, ping_type, sniff_type, expect_params): else: raise Exception('Unspported ping or sniff type') - return Sniffer(expect_params, checkfn, recvif) + return Sniffer(expect_params, checkfn, recvif, defrag=defrag) def parse_args(): @@ -417,6 +429,8 @@ def parse_args(): parser_send = parser.add_argument_group('Values set in transmitted packets') parser_send.add_argument('--send-flags', nargs=1, type=str, help='IPv4 fragmentation flags') + parser_send.add_argument('--send-frag-length', nargs=1, type=int, + help='Force IP fragmentation with given fragment length') parser_send.add_argument('--send-hlim', nargs=1, type=int, help='IPv6 Hop Limit or IPv4 Time To Live') parser_send.add_argument('--send-mss', nargs=1, type=int, @@ -428,7 +442,7 @@ def parse_args(): parser_send.add_argument('--send-tc', nargs=1, type=int, help='IPv6 Traffic Class or IPv4 DiffServ / ToS') parser_send.add_argument('--send-tcpopt-unaligned', action='store_true', - help='Include unaligned TCP options') + help='Include unaligned TCP options') # Expectations parser_expect = parser.add_argument_group('Values expected in sniffed packets') @@ -467,7 +481,7 @@ def main(): # Standardize parameters which have nargs=1. send_params = {} expect_params = {} - for param_name in ('flags', 'hlim', 'length', 'mss', 'seq', 'tc'): + for param_name in ('flags', 'hlim', 'length', 'mss', 'seq', 'tc', 'frag_length'): param_arg = vars(args).get(f'send_{param_name}') send_params[param_name] = param_arg[0] if param_arg else None param_arg = vars(args).get(f'expect_{param_name}') @@ -488,6 +502,11 @@ def main(): sniffers = [] + if send_params['frag_length']: + defrag = True + else: + defrag = False + if recv_ifs: sniffer_params = copy(expect_params) sniffer_params['src_address'] = None @@ -495,7 +514,8 @@ def main(): for iface in recv_ifs: LOGGER.debug(f'Installing receive sniffer on {iface}') sniffers.append( - setup_sniffer(iface, args.ping_type, 'request', sniffer_params, + setup_sniffer(iface, args.ping_type, 'request', + sniffer_params, defrag, )) if reply_ifs: @@ -505,7 +525,8 @@ def main(): for iface in reply_ifs: LOGGER.debug(f'Installing reply sniffer on {iface}') sniffers.append( - setup_sniffer(iface, args.ping_type, 'reply', sniffer_params, + setup_sniffer(iface, args.ping_type, 'reply', + sniffer_params, defrag, )) LOGGER.debug(f'Installed {len(sniffers)} sniffers') diff --git a/tests/sys/netpfil/common/sniffer.py b/tests/sys/netpfil/common/sniffer.py index ab3ddc0aea3c..14305a37278c 100644 --- a/tests/sys/netpfil/common/sniffer.py +++ b/tests/sys/netpfil/common/sniffer.py @@ -30,7 +30,7 @@ import scapy.all as sp import sys class Sniffer(threading.Thread): - def __init__(self, args, check_function, recvif, timeout=3): + def __init__(self, args, check_function, recvif, timeout=3, defrag=False): threading.Thread.__init__(self) self._sem = threading.Semaphore(0) @@ -38,6 +38,7 @@ class Sniffer(threading.Thread): self._timeout = timeout self._recvif = recvif self._check_function = check_function + self._defrag = defrag self.correctPackets = 0 self.start() @@ -55,6 +56,15 @@ class Sniffer(threading.Thread): def run(self): self.packets = [] - self.packets = sp.sniff(iface=self._recvif, - stop_filter=self._checkPacket, timeout=self._timeout, - started_callback=self._startedCb) + if self._defrag: + # With fragment reassembly we can't stop the sniffer after catching + # the good packets, as those have not been reassembled. We must + # wait for sniffer to finish and check returned packets instead. + self.packets = sp.sniff(session=sp.IPSession, iface=self._recvif, + timeout=self._timeout, started_callback=self._startedCb) + for p in self.packets: + self._checkPacket(p) + else: + self.packets = sp.sniff(iface=self._recvif, + stop_filter=self._checkPacket, timeout=self._timeout, + started_callback=self._startedCb)