xref: /freebsd/tests/sys/common/net_receiver.py (revision d0b2dbfa0ecf2bbc9709efc5e20baf8e4b44bbbf)
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