1*b4a4a3b8SAlexander V. Chernikov#!/usr/bin/env python 2*b4a4a3b8SAlexander V. Chernikov# - 3*b4a4a3b8SAlexander V. Chernikov# SPDX-License-Identifier: BSD-2-Clause 4*b4a4a3b8SAlexander V. Chernikov# 5*b4a4a3b8SAlexander V. Chernikov# Copyright (c) 2020 Alexander V. Chernikov 6*b4a4a3b8SAlexander V. Chernikov# 7*b4a4a3b8SAlexander V. Chernikov# Redistribution and use in source and binary forms, with or without 8*b4a4a3b8SAlexander V. Chernikov# modification, are permitted provided that the following conditions 9*b4a4a3b8SAlexander V. Chernikov# are met: 10*b4a4a3b8SAlexander V. Chernikov# 1. Redistributions of source code must retain the above copyright 11*b4a4a3b8SAlexander V. Chernikov# notice, this list of conditions and the following disclaimer. 12*b4a4a3b8SAlexander V. Chernikov# 2. Redistributions in binary form must reproduce the above copyright 13*b4a4a3b8SAlexander V. Chernikov# notice, this list of conditions and the following disclaimer in the 14*b4a4a3b8SAlexander V. Chernikov# documentation and/or other materials provided with the distribution. 15*b4a4a3b8SAlexander V. Chernikov# 16*b4a4a3b8SAlexander V. Chernikov# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17*b4a4a3b8SAlexander V. Chernikov# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18*b4a4a3b8SAlexander V. Chernikov# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19*b4a4a3b8SAlexander V. Chernikov# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20*b4a4a3b8SAlexander V. Chernikov# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21*b4a4a3b8SAlexander V. Chernikov# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22*b4a4a3b8SAlexander V. Chernikov# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23*b4a4a3b8SAlexander V. Chernikov# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24*b4a4a3b8SAlexander V. Chernikov# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25*b4a4a3b8SAlexander V. Chernikov# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26*b4a4a3b8SAlexander V. Chernikov# SUCH DAMAGE. 27*b4a4a3b8SAlexander V. Chernikov# 28*b4a4a3b8SAlexander V. Chernikov# 29*b4a4a3b8SAlexander V. Chernikov 30*b4a4a3b8SAlexander V. Chernikov 31*b4a4a3b8SAlexander V. Chernikovfrom functools import partial 32*b4a4a3b8SAlexander V. Chernikovimport socket 33*b4a4a3b8SAlexander V. Chernikovimport select 34*b4a4a3b8SAlexander V. Chernikovimport argparse 35*b4a4a3b8SAlexander V. Chernikovimport time 36*b4a4a3b8SAlexander V. Chernikov 37*b4a4a3b8SAlexander V. Chernikov 38*b4a4a3b8SAlexander V. Chernikovdef parse_args(): 39*b4a4a3b8SAlexander V. Chernikov parser = argparse.ArgumentParser(description='divert socket tester') 40*b4a4a3b8SAlexander V. Chernikov parser.add_argument('--sip', type=str, default='', help='IP to listen on') 41*b4a4a3b8SAlexander V. Chernikov parser.add_argument('--family', type=str, help='inet/inet6') 42*b4a4a3b8SAlexander V. Chernikov parser.add_argument('--ports', type=str, help='packet ports 1,2,3') 43*b4a4a3b8SAlexander V. Chernikov parser.add_argument('--match_str', type=str, help='match string to use') 44*b4a4a3b8SAlexander V. Chernikov parser.add_argument('--count', type=int, default=1, 45*b4a4a3b8SAlexander V. Chernikov help='Number of messages to receive') 46*b4a4a3b8SAlexander V. Chernikov parser.add_argument('--test_name', type=str, required=True, 47*b4a4a3b8SAlexander V. Chernikov help='test name to run') 48*b4a4a3b8SAlexander V. Chernikov return parser.parse_args() 49*b4a4a3b8SAlexander V. Chernikov 50*b4a4a3b8SAlexander V. Chernikov 51*b4a4a3b8SAlexander V. Chernikovdef test_listen_tcp(args): 52*b4a4a3b8SAlexander V. Chernikov if args.family == 'inet6': 53*b4a4a3b8SAlexander V. Chernikov fam = socket.AF_INET6 54*b4a4a3b8SAlexander V. Chernikov else: 55*b4a4a3b8SAlexander V. Chernikov fam = socket.AF_INET 56*b4a4a3b8SAlexander V. Chernikov sockets = [] 57*b4a4a3b8SAlexander V. Chernikov ports = [int(port) for port in args.ports.split(',')] 58*b4a4a3b8SAlexander V. Chernikov for port in ports: 59*b4a4a3b8SAlexander V. Chernikov s = socket.socket(fam, socket.SOCK_STREAM) 60*b4a4a3b8SAlexander V. Chernikov s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 61*b4a4a3b8SAlexander V. Chernikov s.setblocking(0) 62*b4a4a3b8SAlexander V. Chernikov s.bind((args.sip, port)) 63*b4a4a3b8SAlexander V. Chernikov print('binding on {}:{}'.format(args.sip, port)) 64*b4a4a3b8SAlexander V. Chernikov s.listen(5) 65*b4a4a3b8SAlexander V. Chernikov sockets.append(s) 66*b4a4a3b8SAlexander V. Chernikov inputs = sockets 67*b4a4a3b8SAlexander V. Chernikov count = 0 68*b4a4a3b8SAlexander V. Chernikov while count < args.count: 69*b4a4a3b8SAlexander V. Chernikov readable, writable, exceptional = select.select(inputs, [], inputs) 70*b4a4a3b8SAlexander V. Chernikov for s in readable: 71*b4a4a3b8SAlexander V. Chernikov (c, address) = s.accept() 72*b4a4a3b8SAlexander V. Chernikov print('C: {}'.format(address)) 73*b4a4a3b8SAlexander V. Chernikov data = c.recv(9000) 74*b4a4a3b8SAlexander V. Chernikov if args.match_str and args.match_str.encode('utf-8') != data: 75*b4a4a3b8SAlexander V. Chernikov raise Exception('Expected "{}" but got "{}"'.format( 76*b4a4a3b8SAlexander V. Chernikov args.match_str, data.decode('utf-8'))) 77*b4a4a3b8SAlexander V. Chernikov count += 1 78*b4a4a3b8SAlexander V. Chernikov c.close() 79*b4a4a3b8SAlexander V. Chernikov 80*b4a4a3b8SAlexander V. Chernikov 81*b4a4a3b8SAlexander V. Chernikovdef test_listen_udp(args): 82*b4a4a3b8SAlexander V. Chernikov if args.family == 'inet6': 83*b4a4a3b8SAlexander V. Chernikov fam = socket.AF_INET6 84*b4a4a3b8SAlexander V. Chernikov else: 85*b4a4a3b8SAlexander V. Chernikov fam = socket.AF_INET 86*b4a4a3b8SAlexander V. Chernikov sockets = [] 87*b4a4a3b8SAlexander V. Chernikov ports = [int(port) for port in args.ports.split(',')] 88*b4a4a3b8SAlexander V. Chernikov for port in ports: 89*b4a4a3b8SAlexander V. Chernikov s = socket.socket(fam, socket.SOCK_DGRAM) 90*b4a4a3b8SAlexander V. Chernikov s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 91*b4a4a3b8SAlexander V. Chernikov s.setblocking(0) 92*b4a4a3b8SAlexander V. Chernikov s.bind((args.sip, port)) 93*b4a4a3b8SAlexander V. Chernikov print('binding on {}:{}'.format(args.sip, port)) 94*b4a4a3b8SAlexander V. Chernikov sockets.append(s) 95*b4a4a3b8SAlexander V. Chernikov inputs = sockets 96*b4a4a3b8SAlexander V. Chernikov count = 0 97*b4a4a3b8SAlexander V. Chernikov while count < args.count: 98*b4a4a3b8SAlexander V. Chernikov readable, writable, exceptional = select.select(inputs, [], inputs) 99*b4a4a3b8SAlexander V. Chernikov for s in readable: 100*b4a4a3b8SAlexander V. Chernikov (data, address) = s.recvfrom(9000) 101*b4a4a3b8SAlexander V. Chernikov print('C: {}'.format(address)) 102*b4a4a3b8SAlexander V. Chernikov if args.match_str and args.match_str.encode('utf-8') != data: 103*b4a4a3b8SAlexander V. Chernikov raise Exception('Expected "{}" but got "{}"'.format( 104*b4a4a3b8SAlexander V. Chernikov args.match_str, data.decode('utf-8'))) 105*b4a4a3b8SAlexander V. Chernikov count += 1 106*b4a4a3b8SAlexander V. Chernikov 107*b4a4a3b8SAlexander V. Chernikov 108*b4a4a3b8SAlexander V. Chernikovdef main(): 109*b4a4a3b8SAlexander V. Chernikov args = parse_args() 110*b4a4a3b8SAlexander V. Chernikov test_ptr = globals()[args.test_name] 111*b4a4a3b8SAlexander V. Chernikov test_ptr(args) 112*b4a4a3b8SAlexander V. Chernikov 113*b4a4a3b8SAlexander V. Chernikov 114*b4a4a3b8SAlexander V. Chernikovif __name__ == '__main__': 115*b4a4a3b8SAlexander V. Chernikov main() 116