1 #
2 # tshark module - refactored from test_scan.py
3 #
4 # Copyright (c) 2014, Qualcomm Atheros, Inc.
5 # Copyright (c) 2015, Intel Mobile Communications GmbH
6 #
7 # This software may be distributed under the terms of the BSD license.
8 # See README for more details.
9 
10 import time
11 import subprocess
12 import logging
13 logger = logging.getLogger()
14 
15 from utils import *
16 
17 class UnknownFieldsException(Exception):
18     def __init__(self, fields):
19         Exception.__init__(self, "unknown tshark fields %s" % ','.join(fields))
20         self.fields = fields
21 
22 _tshark_filter_arg = '-Y'
23 
24 def _run_tshark(filename, filter, display=None, wait=True):
25     global _tshark_filter_arg
26 
27     if wait:
28         # wait a bit to make it more likely for wlantest sniffer to have
29         # captured and written the results into a file that we can process here
30         time.sleep(0.1)
31 
32     try:
33         arg = ["tshark", "-r", filename,
34                _tshark_filter_arg, filter]
35         if display:
36             arg.append('-Tfields')
37             for d in display:
38                 arg.append('-e')
39                 arg.append(d)
40         else:
41             arg.append('-V')
42         cmd = subprocess.Popen(arg, stdout=subprocess.PIPE,
43                                stderr=subprocess.PIPE)
44     except Exception as e:
45         logger.info("Could run run tshark check: " + str(e))
46         if "No such file or directory: 'tshark'" in str(e):
47             raise HwsimSkip("No tshark available")
48         cmd = None
49         return None
50 
51     output = cmd.communicate()
52     out = output[0].decode(errors='ignore')
53     out1 = output[1].decode()
54     res = cmd.wait()
55     if res == 1:
56         errmsg = "Some fields aren't valid"
57         if errmsg in out1:
58             errors = out1.split('\n')
59             fields = []
60             collect = False
61             for f in errors:
62                 if collect:
63                     f = f.strip()
64                     if f:
65                         fields.append(f)
66                     continue
67                 if errmsg in f:
68                     collect = True
69                     continue
70             raise UnknownFieldsException(fields)
71         # remember this for efficiency
72         _tshark_filter_arg = '-R'
73         arg[3] = '-R'
74         cmd = subprocess.Popen(arg, stdout=subprocess.PIPE,
75                                stderr=open('/dev/null', 'w'))
76         out = cmd.communicate()[0].decode()
77         cmd.wait()
78     if res == 2:
79         if "tshark: Neither" in out1 and "are field or protocol names" in out1:
80             errors = out1.split('\n')
81             fields = []
82             for f in errors:
83                 if f.startswith("tshark: Neither "):
84                     f = f.split(' ')[2].strip('"')
85                     if f:
86                         fields.append(f)
87                     continue
88             raise UnknownFieldsException(fields)
89 
90     if res != 0:
91         raise AssertionError('tshark reported an error: ' + out1)
92 
93     return out
94 
95 def run_tshark(filename, filters, display=None, wait=True):
96     if display is None: display = []
97 
98     if not isinstance(filters, list) and not isinstance(filters, tuple):
99         filters = [filters]
100 
101     last_exception = None
102     for filter in filters:
103         try:
104             return _run_tshark(filename, filter.replace('wlan_mgt', 'wlan'),
105                                [x.replace('wlan_mgt', 'wlan') for x in display],
106                                wait)
107         except UnknownFieldsException as e:
108             all_wlan_mgt = True
109             for f in e.fields:
110                 if not f.startswith('wlan_mgt.'):
111                     all_wlan_mgt = False
112                     break
113             if not all_wlan_mgt:
114                 raise
115             return _run_tshark(filename, filter, display, wait)
116 
117         except AssertionError as e:
118             # Catch the error (and try the next provided filter)
119             last_exception = e
120 
121     raise last_exception
122 
123 def run_tshark_json(filename, filter):
124     arg = ["tshark", "-r", filename,
125            _tshark_filter_arg, filter]
126     arg.append('-Tjson')
127     arg.append('-x')
128     try:
129         cmd = subprocess.Popen(arg, stdout=subprocess.PIPE,
130                                stderr=subprocess.PIPE)
131     except Exception as e:
132         logger.info("Could run run tshark: " + str(e))
133         if "No such file or directory: 'tshark'" in str(e):
134             raise HwsimSkip("No tshark available")
135         return None
136     output = cmd.communicate()
137     out = output[0].decode()
138     res = cmd.wait()
139     return out
140