xref: /aosp_15_r20/external/ot-br-posix/tools/reference_device/testharness-discovery (revision 4a64e381480ef79f0532b2421e44e6ee336b8e0d)
1*4a64e381SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*4a64e381SAndroid Build Coastguard Worker#
3*4a64e381SAndroid Build Coastguard Worker#  Copyright (c) 2021, The OpenThread Authors.
4*4a64e381SAndroid Build Coastguard Worker#  All rights reserved.
5*4a64e381SAndroid Build Coastguard Worker#
6*4a64e381SAndroid Build Coastguard Worker#  Redistribution and use in source and binary forms, with or without
7*4a64e381SAndroid Build Coastguard Worker#  modification, are permitted provided that the following conditions are met:
8*4a64e381SAndroid Build Coastguard Worker#  1. Redistributions of source code must retain the above copyright
9*4a64e381SAndroid Build Coastguard Worker#     notice, this list of conditions and the following disclaimer.
10*4a64e381SAndroid Build Coastguard Worker#  2. Redistributions in binary form must reproduce the above copyright
11*4a64e381SAndroid Build Coastguard Worker#     notice, this list of conditions and the following disclaimer in the
12*4a64e381SAndroid Build Coastguard Worker#     documentation and/or other materials provided with the distribution.
13*4a64e381SAndroid Build Coastguard Worker#  3. Neither the name of the copyright holder nor the
14*4a64e381SAndroid Build Coastguard Worker#     names of its contributors may be used to endorse or promote products
15*4a64e381SAndroid Build Coastguard Worker#     derived from this software without specific prior written permission.
16*4a64e381SAndroid Build Coastguard Worker#
17*4a64e381SAndroid Build Coastguard Worker#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18*4a64e381SAndroid Build Coastguard Worker#  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*4a64e381SAndroid Build Coastguard Worker#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*4a64e381SAndroid Build Coastguard Worker#  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21*4a64e381SAndroid Build Coastguard Worker#  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22*4a64e381SAndroid Build Coastguard Worker#  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23*4a64e381SAndroid Build Coastguard Worker#  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*4a64e381SAndroid Build Coastguard Worker#  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25*4a64e381SAndroid Build Coastguard Worker#  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26*4a64e381SAndroid Build Coastguard Worker#  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27*4a64e381SAndroid Build Coastguard Worker#  POSSIBILITY OF SUCH DAMAGE.
28*4a64e381SAndroid Build Coastguard Worker#
29*4a64e381SAndroid Build Coastguard Workerimport ctypes
30*4a64e381SAndroid Build Coastguard Workerimport ctypes.util
31*4a64e381SAndroid Build Coastguard Workerimport json
32*4a64e381SAndroid Build Coastguard Workerimport os
33*4a64e381SAndroid Build Coastguard Workerimport socket
34*4a64e381SAndroid Build Coastguard Workerimport struct
35*4a64e381SAndroid Build Coastguard Workerimport logging
36*4a64e381SAndroid Build Coastguard Worker
37*4a64e381SAndroid Build Coastguard WorkerPORT = 12345
38*4a64e381SAndroid Build Coastguard WorkerIFNAME = 'eth0'
39*4a64e381SAndroid Build Coastguard WorkerGROUP = 'ff02::114'
40*4a64e381SAndroid Build Coastguard Worker
41*4a64e381SAndroid Build Coastguard Workerlibc = ctypes.CDLL(ctypes.util.find_library('c'))
42*4a64e381SAndroid Build Coastguard Worker
43*4a64e381SAndroid Build Coastguard Workerlogging.basicConfig(level=logging.INFO)
44*4a64e381SAndroid Build Coastguard Worker
45*4a64e381SAndroid Build Coastguard Worker
46*4a64e381SAndroid Build Coastguard Workerdef if_nametoindex(name):
47*4a64e381SAndroid Build Coastguard Worker    if not isinstance(name, str):
48*4a64e381SAndroid Build Coastguard Worker        raise TypeError('name must be a string.')
49*4a64e381SAndroid Build Coastguard Worker    ret = libc.if_nametoindex(name.encode('ascii'))
50*4a64e381SAndroid Build Coastguard Worker    if not ret:
51*4a64e381SAndroid Build Coastguard Worker        raise RuntimeError("Invalid Name")
52*4a64e381SAndroid Build Coastguard Worker    return ret
53*4a64e381SAndroid Build Coastguard Worker
54*4a64e381SAndroid Build Coastguard Worker
55*4a64e381SAndroid Build Coastguard Workerdef get_ipaddr():
56*4a64e381SAndroid Build Coastguard Worker    for line in os.popen(f'ip addr list dev {IFNAME} | grep inet6 | grep \'scope link\' '):
57*4a64e381SAndroid Build Coastguard Worker        addr = line.strip().split()[1]
58*4a64e381SAndroid Build Coastguard Worker        return addr.split('/')[0]
59*4a64e381SAndroid Build Coastguard Worker
60*4a64e381SAndroid Build Coastguard Worker
61*4a64e381SAndroid Build Coastguard Workerdef advertise_bbr(s: socket.socket, src):
62*4a64e381SAndroid Build Coastguard Worker    bbr_info = {
63*4a64e381SAndroid Build Coastguard Worker        'ven': 'OpenThread_BR',
64*4a64e381SAndroid Build Coastguard Worker        'mod': 'OpenThread_BR',
65*4a64e381SAndroid Build Coastguard Worker        'ver': '1.0',
66*4a64e381SAndroid Build Coastguard Worker        'add': get_ipaddr(),
67*4a64e381SAndroid Build Coastguard Worker        'por': 22,
68*4a64e381SAndroid Build Coastguard Worker    }
69*4a64e381SAndroid Build Coastguard Worker
70*4a64e381SAndroid Build Coastguard Worker    logging.info("Advertise: %r", bbr_info)
71*4a64e381SAndroid Build Coastguard Worker    s.sendto(json.dumps(bbr_info).encode('utf8'), src)
72*4a64e381SAndroid Build Coastguard Worker
73*4a64e381SAndroid Build Coastguard Worker
74*4a64e381SAndroid Build Coastguard Workerdef main():
75*4a64e381SAndroid Build Coastguard Worker    # Look up multicast group address in name server and find out IP version
76*4a64e381SAndroid Build Coastguard Worker    addrinfo = socket.getaddrinfo(GROUP, None)[0]
77*4a64e381SAndroid Build Coastguard Worker    assert addrinfo[0] == socket.AF_INET6
78*4a64e381SAndroid Build Coastguard Worker
79*4a64e381SAndroid Build Coastguard Worker    # Create a socket
80*4a64e381SAndroid Build Coastguard Worker    s = socket.socket(addrinfo[0], socket.SOCK_DGRAM)
81*4a64e381SAndroid Build Coastguard Worker    s.setsockopt(socket.SOL_SOCKET, socket.SO_BINDTODEVICE, (IFNAME + '\0').encode('ascii'))
82*4a64e381SAndroid Build Coastguard Worker
83*4a64e381SAndroid Build Coastguard Worker    # Bind it to the port
84*4a64e381SAndroid Build Coastguard Worker    s.bind(('', PORT))
85*4a64e381SAndroid Build Coastguard Worker
86*4a64e381SAndroid Build Coastguard Worker    group_bin = socket.inet_pton(addrinfo[0], addrinfo[4][0])
87*4a64e381SAndroid Build Coastguard Worker    # Join group
88*4a64e381SAndroid Build Coastguard Worker    interface_index = if_nametoindex(IFNAME)
89*4a64e381SAndroid Build Coastguard Worker    mreq = group_bin + struct.pack('@I', interface_index)
90*4a64e381SAndroid Build Coastguard Worker    s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, mreq)
91*4a64e381SAndroid Build Coastguard Worker
92*4a64e381SAndroid Build Coastguard Worker    logging.info("Advertising BBR on interface %s group %s ...", IFNAME, GROUP)
93*4a64e381SAndroid Build Coastguard Worker
94*4a64e381SAndroid Build Coastguard Worker    # Loop, printing any data we receive
95*4a64e381SAndroid Build Coastguard Worker    while True:
96*4a64e381SAndroid Build Coastguard Worker        data, src = s.recvfrom(100)
97*4a64e381SAndroid Build Coastguard Worker        if data == b'BBR':
98*4a64e381SAndroid Build Coastguard Worker            logging.info('Received BBR query, advertising')
99*4a64e381SAndroid Build Coastguard Worker            advertise_bbr(s, src)
100*4a64e381SAndroid Build Coastguard Worker        else:
101*4a64e381SAndroid Build Coastguard Worker            logging.warn('Received %r, but ignored', data)
102*4a64e381SAndroid Build Coastguard Worker
103*4a64e381SAndroid Build Coastguard Worker
104*4a64e381SAndroid Build Coastguard Workerif __name__ == '__main__':
105*4a64e381SAndroid Build Coastguard Worker    main()
106