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