xref: /aosp_15_r20/external/openthread/tools/harness-sniffer/OT_Sniffer.py (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1*cfb92d14SAndroid Build Coastguard Worker#!/usr/bin/env python
2*cfb92d14SAndroid Build Coastguard Worker#
3*cfb92d14SAndroid Build Coastguard Worker# Copyright (c) 2019, The OpenThread Authors.
4*cfb92d14SAndroid Build Coastguard Worker# All rights reserved.
5*cfb92d14SAndroid Build Coastguard Worker#
6*cfb92d14SAndroid Build Coastguard Worker# Redistribution and use in source and binary forms, with or without
7*cfb92d14SAndroid Build Coastguard Worker# modification, are permitted provided that the following conditions are met:
8*cfb92d14SAndroid Build Coastguard Worker# 1. Redistributions of source code must retain the above copyright
9*cfb92d14SAndroid Build Coastguard Worker#    notice, this list of conditions and the following disclaimer.
10*cfb92d14SAndroid Build Coastguard Worker# 2. Redistributions in binary form must reproduce the above copyright
11*cfb92d14SAndroid Build Coastguard Worker#    notice, this list of conditions and the following disclaimer in the
12*cfb92d14SAndroid Build Coastguard Worker#    documentation and/or other materials provided with the distribution.
13*cfb92d14SAndroid Build Coastguard Worker# 3. Neither the name of the copyright holder nor the
14*cfb92d14SAndroid Build Coastguard Worker#    names of its contributors may be used to endorse or promote products
15*cfb92d14SAndroid Build Coastguard Worker#    derived from this software without specific prior written permission.
16*cfb92d14SAndroid Build Coastguard Worker#
17*cfb92d14SAndroid Build Coastguard Worker# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18*cfb92d14SAndroid Build Coastguard Worker# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*cfb92d14SAndroid Build Coastguard Worker# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*cfb92d14SAndroid Build Coastguard Worker# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21*cfb92d14SAndroid Build Coastguard Worker# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22*cfb92d14SAndroid Build Coastguard Worker# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23*cfb92d14SAndroid Build Coastguard Worker# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*cfb92d14SAndroid Build Coastguard Worker# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25*cfb92d14SAndroid Build Coastguard Worker# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26*cfb92d14SAndroid Build Coastguard Worker# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27*cfb92d14SAndroid Build Coastguard Worker# POSSIBILITY OF SUCH DAMAGE.
28*cfb92d14SAndroid Build Coastguard Worker''''OpenThread Sniffer API implementation'''
29*cfb92d14SAndroid Build Coastguard Worker
30*cfb92d14SAndroid Build Coastguard Workerimport os
31*cfb92d14SAndroid Build Coastguard Workerimport subprocess
32*cfb92d14SAndroid Build Coastguard Workerfrom GRLLibs.UtilityModules.ModuleHelper import ModuleHelper
33*cfb92d14SAndroid Build Coastguard Workerfrom ISniffer import ISniffer
34*cfb92d14SAndroid Build Coastguard Worker
35*cfb92d14SAndroid Build Coastguard Worker
36*cfb92d14SAndroid Build Coastguard Workerclass OT_Sniffer(ISniffer):
37*cfb92d14SAndroid Build Coastguard Worker
38*cfb92d14SAndroid Build Coastguard Worker    def __init__(self, **kwargs):
39*cfb92d14SAndroid Build Coastguard Worker        try:
40*cfb92d14SAndroid Build Coastguard Worker            self.channel = kwargs.get('channel', 11)
41*cfb92d14SAndroid Build Coastguard Worker            self.port = kwargs.get('addressofDevice')
42*cfb92d14SAndroid Build Coastguard Worker            self.subprocess = None
43*cfb92d14SAndroid Build Coastguard Worker            self.is_active = False
44*cfb92d14SAndroid Build Coastguard Worker
45*cfb92d14SAndroid Build Coastguard Worker        except Exception as e:
46*cfb92d14SAndroid Build Coastguard Worker            ModuleHelper.WriteIntoDebugLogger('OT_Sniffer: [initialize] --> ' + str(e))
47*cfb92d14SAndroid Build Coastguard Worker
48*cfb92d14SAndroid Build Coastguard Worker    def discoverSniffer(self):
49*cfb92d14SAndroid Build Coastguard Worker        sniffers = []
50*cfb92d14SAndroid Build Coastguard Worker
51*cfb92d14SAndroid Build Coastguard Worker        p_discover = subprocess.Popen('extcap_ot.bat --extcap-interfaces', stdout=subprocess.PIPE, shell=True)
52*cfb92d14SAndroid Build Coastguard Worker        for line in p_discover.stdout.readlines():
53*cfb92d14SAndroid Build Coastguard Worker            if line.startswith('interface'):
54*cfb92d14SAndroid Build Coastguard Worker                try:
55*cfb92d14SAndroid Build Coastguard Worker                    # e.g. interface {value=COM10:460800}{display=OpenThread Sniffer COM10}
56*cfb92d14SAndroid Build Coastguard Worker                    interface_port = line[line.index('value=') + 6:line.index('}{display')]
57*cfb92d14SAndroid Build Coastguard Worker                    sniffers.append(OT_Sniffer(addressofDevice=interface_port, channel=ModuleHelper.Default_Channel))
58*cfb92d14SAndroid Build Coastguard Worker                except Exception as e:
59*cfb92d14SAndroid Build Coastguard Worker                    ModuleHelper.WriteIntoDebugLogger('OT_Sniffer: [discoverSniffer] --> Error: ' + str(e))
60*cfb92d14SAndroid Build Coastguard Worker
61*cfb92d14SAndroid Build Coastguard Worker        p_discover.wait()
62*cfb92d14SAndroid Build Coastguard Worker        return sniffers
63*cfb92d14SAndroid Build Coastguard Worker
64*cfb92d14SAndroid Build Coastguard Worker    def startSniffer(self, channelToCapture, captureFileLocation):
65*cfb92d14SAndroid Build Coastguard Worker        """
66*cfb92d14SAndroid Build Coastguard Worker        Method for starting the sniffer capture on given channel and this should create wireshark 'pcapng' file at the
67*cfb92d14SAndroid Build Coastguard Worker        given location. Capture should happen in background so that method call will be non-blocking and asynchronous.
68*cfb92d14SAndroid Build Coastguard Worker        @param channelToCapture : int : channel number to start the capture
69*cfb92d14SAndroid Build Coastguard Worker        @param captureFileLocation : string : Full path with the filename with extension is passed.
70*cfb92d14SAndroid Build Coastguard Worker        """
71*cfb92d14SAndroid Build Coastguard Worker        try:
72*cfb92d14SAndroid Build Coastguard Worker            # start sniffer
73*cfb92d14SAndroid Build Coastguard Worker            self.setChannel(channelToCapture)
74*cfb92d14SAndroid Build Coastguard Worker            p_where = subprocess.Popen(
75*cfb92d14SAndroid Build Coastguard Worker                'py -3 -c "import sys; print(sys.executable)"',
76*cfb92d14SAndroid Build Coastguard Worker                stdout=subprocess.PIPE,
77*cfb92d14SAndroid Build Coastguard Worker                shell=True,
78*cfb92d14SAndroid Build Coastguard Worker            )
79*cfb92d14SAndroid Build Coastguard Worker            # python_exe: e.g. C:\Python37\python.exe
80*cfb92d14SAndroid Build Coastguard Worker            python_exe = p_where.stdout.readline().strip()
81*cfb92d14SAndroid Build Coastguard Worker
82*cfb92d14SAndroid Build Coastguard Worker            if python_exe.endswith(".exe"):
83*cfb92d14SAndroid Build Coastguard Worker                # sniffer_py: e.g. C:\Python37\Scripts\sniffer.py
84*cfb92d14SAndroid Build Coastguard Worker                sniffer_py = str(os.path.dirname(python_exe)) + '\\Scripts\\sniffer.py'
85*cfb92d14SAndroid Build Coastguard Worker
86*cfb92d14SAndroid Build Coastguard Worker                cmd = [
87*cfb92d14SAndroid Build Coastguard Worker                    python_exe,
88*cfb92d14SAndroid Build Coastguard Worker                    sniffer_py,
89*cfb92d14SAndroid Build Coastguard Worker                    '-c',
90*cfb92d14SAndroid Build Coastguard Worker                    str(self.channel),
91*cfb92d14SAndroid Build Coastguard Worker                    '-u',
92*cfb92d14SAndroid Build Coastguard Worker                    str(self.port.split(':')[0]),
93*cfb92d14SAndroid Build Coastguard Worker                    '-b',
94*cfb92d14SAndroid Build Coastguard Worker                    str(self.port.split(':')[1]),
95*cfb92d14SAndroid Build Coastguard Worker                    '--crc',
96*cfb92d14SAndroid Build Coastguard Worker                    '-o',
97*cfb92d14SAndroid Build Coastguard Worker                    captureFileLocation,
98*cfb92d14SAndroid Build Coastguard Worker                ]
99*cfb92d14SAndroid Build Coastguard Worker                self.is_active = True
100*cfb92d14SAndroid Build Coastguard Worker                ModuleHelper.WriteIntoDebugLogger('OT_Sniffer: [cmd] --> %s' % str(cmd))
101*cfb92d14SAndroid Build Coastguard Worker                self.subprocess = subprocess.Popen(cmd)
102*cfb92d14SAndroid Build Coastguard Worker
103*cfb92d14SAndroid Build Coastguard Worker        except Exception as e:
104*cfb92d14SAndroid Build Coastguard Worker            ModuleHelper.WriteIntoDebugLogger('OT_Sniffer: [startSniffer] --> Error: ' + str(e))
105*cfb92d14SAndroid Build Coastguard Worker
106*cfb92d14SAndroid Build Coastguard Worker    def stopSniffer(self):
107*cfb92d14SAndroid Build Coastguard Worker        """
108*cfb92d14SAndroid Build Coastguard Worker        Method for ending the sniffer capture.
109*cfb92d14SAndroid Build Coastguard Worker        Should stop background capturing, No further file I/O in capture file.
110*cfb92d14SAndroid Build Coastguard Worker        """
111*cfb92d14SAndroid Build Coastguard Worker        if self.is_active:
112*cfb92d14SAndroid Build Coastguard Worker            self.is_active = False
113*cfb92d14SAndroid Build Coastguard Worker            if self.subprocess:
114*cfb92d14SAndroid Build Coastguard Worker                self.subprocess.terminate()
115*cfb92d14SAndroid Build Coastguard Worker                self.subprocess.wait()
116*cfb92d14SAndroid Build Coastguard Worker
117*cfb92d14SAndroid Build Coastguard Worker    def setChannel(self, channelToCapture):
118*cfb92d14SAndroid Build Coastguard Worker        """
119*cfb92d14SAndroid Build Coastguard Worker        Method for changing sniffer capture
120*cfb92d14SAndroid Build Coastguard Worker        @param channelToCapture : int :
121*cfb92d14SAndroid Build Coastguard Worker            channel number is passed to change the channel which is set during the constructor call.
122*cfb92d14SAndroid Build Coastguard Worker        """
123*cfb92d14SAndroid Build Coastguard Worker        self.channel = channelToCapture
124*cfb92d14SAndroid Build Coastguard Worker
125*cfb92d14SAndroid Build Coastguard Worker    def getChannel(self):
126*cfb92d14SAndroid Build Coastguard Worker        """
127*cfb92d14SAndroid Build Coastguard Worker        Method to query sniffer for the channel it is sniffing on
128*cfb92d14SAndroid Build Coastguard Worker        @return : int : current capture channel of this sniffer instance.
129*cfb92d14SAndroid Build Coastguard Worker        """
130*cfb92d14SAndroid Build Coastguard Worker        return self.channel
131*cfb92d14SAndroid Build Coastguard Worker
132*cfb92d14SAndroid Build Coastguard Worker    def validateFirmwareVersion(self, addressofDevice):
133*cfb92d14SAndroid Build Coastguard Worker        """
134*cfb92d14SAndroid Build Coastguard Worker        Method to query sniffer firmware version details.
135*cfb92d14SAndroid Build Coastguard Worker        Shall be used while discoverSniffer() to validate the sniffer firmware.
136*cfb92d14SAndroid Build Coastguard Worker        @param addressofDevice : string :
137*cfb92d14SAndroid Build Coastguard Worker            serial com port or IP address,shall be None if need to verify own fireware version.
138*cfb92d14SAndroid Build Coastguard Worker        @return : bool : True if expected firmware is found , False if not
139*cfb92d14SAndroid Build Coastguard Worker        """
140*cfb92d14SAndroid Build Coastguard Worker        return True
141*cfb92d14SAndroid Build Coastguard Worker
142*cfb92d14SAndroid Build Coastguard Worker    def isSnifferCapturing(self):
143*cfb92d14SAndroid Build Coastguard Worker        """
144*cfb92d14SAndroid Build Coastguard Worker        method that will return true when sniffer device is capturing
145*cfb92d14SAndroid Build Coastguard Worker        @return : bool
146*cfb92d14SAndroid Build Coastguard Worker        """
147*cfb92d14SAndroid Build Coastguard Worker        return self.is_active
148*cfb92d14SAndroid Build Coastguard Worker
149*cfb92d14SAndroid Build Coastguard Worker    def getSnifferAddress(self):
150*cfb92d14SAndroid Build Coastguard Worker        """
151*cfb92d14SAndroid Build Coastguard Worker        Method to return the current sniffer's COM/IP address
152*cfb92d14SAndroid Build Coastguard Worker        @return : string
153*cfb92d14SAndroid Build Coastguard Worker        """
154*cfb92d14SAndroid Build Coastguard Worker        return self.port
155*cfb92d14SAndroid Build Coastguard Worker
156*cfb92d14SAndroid Build Coastguard Worker    def globalReset(self):
157*cfb92d14SAndroid Build Coastguard Worker        """Method to reset all the global and class varibaled"""
158*cfb92d14SAndroid Build Coastguard Worker        pass
159