xref: /freebsd-src/tests/sys/common/divert.py (revision d0b2dbfa0ecf2bbc9709efc5e20baf8e4b44bbbf)
12207447bSAlexander V. Chernikov#!/usr/bin/env python
22207447bSAlexander V. Chernikov# -
32207447bSAlexander V. Chernikov# SPDX-License-Identifier: BSD-2-Clause
42207447bSAlexander V. Chernikov#
52207447bSAlexander V. Chernikov# Copyright (c) 2020 Alexander V. Chernikov
62207447bSAlexander V. Chernikov#
72207447bSAlexander V. Chernikov# Redistribution and use in source and binary forms, with or without
82207447bSAlexander V. Chernikov# modification, are permitted provided that the following conditions
92207447bSAlexander V. Chernikov# are met:
102207447bSAlexander V. Chernikov# 1. Redistributions of source code must retain the above copyright
112207447bSAlexander V. Chernikov#    notice, this list of conditions and the following disclaimer.
122207447bSAlexander V. Chernikov# 2. Redistributions in binary form must reproduce the above copyright
132207447bSAlexander V. Chernikov#    notice, this list of conditions and the following disclaimer in the
142207447bSAlexander V. Chernikov#    documentation and/or other materials provided with the distribution.
152207447bSAlexander V. Chernikov#
162207447bSAlexander V. Chernikov# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
172207447bSAlexander V. Chernikov# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
182207447bSAlexander V. Chernikov# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
192207447bSAlexander V. Chernikov# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
202207447bSAlexander V. Chernikov# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
212207447bSAlexander V. Chernikov# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
222207447bSAlexander V. Chernikov# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
232207447bSAlexander V. Chernikov# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
242207447bSAlexander V. Chernikov# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
252207447bSAlexander V. Chernikov# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
262207447bSAlexander V. Chernikov# SUCH DAMAGE.
272207447bSAlexander V. Chernikov#
282207447bSAlexander V. Chernikov#
292207447bSAlexander V. Chernikov
302207447bSAlexander V. Chernikov
31*5e4ae306SGleb Smirnofffrom socket import socket, PF_DIVERT, SOCK_RAW
32a26e895fSKristof Provostimport logging
33a26e895fSKristof Provostlogging.getLogger("scapy").setLevel(logging.CRITICAL)
342207447bSAlexander V. Chernikovimport scapy.all as sc
352207447bSAlexander V. Chernikovimport argparse
362207447bSAlexander V. Chernikov
372207447bSAlexander V. Chernikov
382207447bSAlexander V. Chernikovdef parse_args():
392207447bSAlexander V. Chernikov    parser = argparse.ArgumentParser(description='divert socket tester')
402207447bSAlexander V. Chernikov    parser.add_argument('--dip', type=str, help='destination packet IP')
416913bf4cSGleb Smirnoff    parser.add_argument('--sip', type=str, help='source packet IP')
422207447bSAlexander V. Chernikov    parser.add_argument('--divert_port', type=int, default=6668,
432207447bSAlexander V. Chernikov                        help='divert port to use')
442207447bSAlexander V. Chernikov    parser.add_argument('--test_name', type=str, required=True,
452207447bSAlexander V. Chernikov                        help='test name to run')
462207447bSAlexander V. Chernikov    return parser.parse_args()
472207447bSAlexander V. Chernikov
482207447bSAlexander V. Chernikov
492207447bSAlexander V. Chernikovdef ipdivert_ip_output_remote_success(args):
502207447bSAlexander V. Chernikov    packet = sc.IP(dst=args.dip) / sc.ICMP(type='echo-request')
51*5e4ae306SGleb Smirnoff    with socket(PF_DIVERT, SOCK_RAW, 0) as s:
522207447bSAlexander V. Chernikov        s.bind(('0.0.0.0', args.divert_port))
532207447bSAlexander V. Chernikov        s.sendto(bytes(packet), ('0.0.0.0', 0))
542207447bSAlexander V. Chernikov
552207447bSAlexander V. Chernikov
562207447bSAlexander V. Chernikovdef ipdivert_ip6_output_remote_success(args):
572207447bSAlexander V. Chernikov    packet = sc.IPv6(dst=args.dip) / sc.ICMPv6EchoRequest()
58*5e4ae306SGleb Smirnoff    with socket(PF_DIVERT, SOCK_RAW, 0) as s:
592207447bSAlexander V. Chernikov        s.bind(('0.0.0.0', args.divert_port))
602207447bSAlexander V. Chernikov        s.sendto(bytes(packet), ('0.0.0.0', 0))
612207447bSAlexander V. Chernikov
622207447bSAlexander V. Chernikov
632207447bSAlexander V. Chernikovdef ipdivert_ip_input_local_success(args):
642207447bSAlexander V. Chernikov    """Sends IPv4 packet to OS stack as inbound local packet."""
656913bf4cSGleb Smirnoff    packet = sc.IP(dst=args.dip,src=args.sip) / sc.ICMP(type='echo-request')
66*5e4ae306SGleb Smirnoff    with socket(PF_DIVERT, SOCK_RAW, 0) as s:
672207447bSAlexander V. Chernikov        s.bind(('0.0.0.0', args.divert_port))
682207447bSAlexander V. Chernikov        s.sendto(bytes(packet), (args.dip, 0))
692207447bSAlexander V. Chernikov
702207447bSAlexander V. Chernikov
712207447bSAlexander V. Chernikov# XXX: IPv6 local divert is currently not supported
722207447bSAlexander V. Chernikov# TODO: add IPv4 ifname output verification
732207447bSAlexander V. Chernikov
742207447bSAlexander V. Chernikov
752207447bSAlexander V. Chernikovdef main():
762207447bSAlexander V. Chernikov    args = parse_args()
772207447bSAlexander V. Chernikov    test_ptr = globals()[args.test_name]
782207447bSAlexander V. Chernikov    test_ptr(args)
792207447bSAlexander V. Chernikov
802207447bSAlexander V. Chernikov
812207447bSAlexander V. Chernikovif __name__ == '__main__':
822207447bSAlexander V. Chernikov    main()
83