1 # Monitor support
2 # Copyright (c) 2016, Tieto Corporation
3 #
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
6 
7 import time
8 from remotehost import Host
9 import config
10 import rutils
11 import re
12 import traceback
13 import logging
14 logger = logging.getLogger()
15 import hostapd
16 
17 # standalone monitor with multi iface support
18 def create(devices, setup_params, refs, duts, monitors):
19     mons = []
20     mhosts = []
21     hosts = duts + refs
22 
23     # choose only standalone monitors
24     for monitor in monitors:
25         if monitor not in hosts and monitor != "all":
26             mons.append(monitor)
27 
28     for mon in mons:
29         word = mon.split(":")
30         dev = config.get_device(devices, word[0])
31         if dev is None:
32             continue
33 
34         host = Host(host=dev['hostname'],
35                     ifname=dev['ifname'],
36                     port=dev['port'],
37                     name=dev['name'])
38 
39         for iface_param in word[1:]:
40             params = iface_param.split(",")
41             if len(params) > 3:
42                 monitor_param = { "freq" : rutils.c2f(params[0]),
43                                   "bw" : params[1],
44                                   "center_freq1" : rutils.c2f(params[2]),
45                                   "center_freq2" : rutils.c2f(params[3]) }
46                 host.monitor_params.append(monitor_param)
47 
48         try:
49             host.execute(["iw", "reg", "set", setup_params['country']])
50             rutils.setup_hw_host(host, setup_params, True)
51         except:
52             pass
53         mhosts.append(host)
54 
55     return mhosts
56 
57 def destroy(devices, hosts):
58     for host in hosts:
59         stop(host)
60         for monitor in host.monitors:
61             host.execute(["ifconfig", monitor, "down"])
62         host.monitor_params = []
63 
64 def setup(host, monitor_params=None):
65     if host is None:
66         return
67 
68     if monitor_params == None:
69         monitor_params = host.monitor_params
70 
71     ifaces = re.split('; | |, ', host.ifname)
72     count = 0
73     for param in monitor_params:
74         try:
75             iface = ifaces[count]
76         except:
77             logger.debug(traceback.format_exc())
78             break
79         host.execute(["ifconfig", iface, " down"])
80         host.execute(["rfkill", "unblock", "wifi"])
81         host.execute(["iw", iface, "set type monitor"])
82         host.execute(["ifconfig", iface, "up"])
83         status, buf = host.execute(["iw", iface, "set", "freq", param['freq'],
84                                     param['bw'], param['center_freq1'],
85                                     param['center_freq2']])
86         if status != 0:
87             logger.debug("Could not setup monitor interface: " + buf)
88             continue
89         host.monitors.append(iface)
90         count = count + 1
91 
92 def run(host, setup_params):
93     monitor_res = []
94     log_monitor = ""
95     if host is None:
96         return None
97     if len(host.monitors) == 0:
98         return None
99     try:
100         log_dir = setup_params['log_dir']
101         tc_name = setup_params['tc_name']
102     except:
103         return None
104 
105     tshark = "tshark"
106     for monitor in host.monitors:
107         host.execute(["ifconfig", monitor, "up"])
108         tshark = tshark + " -i " + monitor
109         log_monitor = log_monitor + "_" + monitor
110 
111     log = log_dir + tc_name + "_" + host.name + log_monitor + ".pcap"
112     host.add_log(log)
113     thread = host.thread_run([tshark, "-w", log], monitor_res)
114     host.thread = thread
115 
116 
117 def stop(host):
118     if host is None:
119         return
120     if len(host.monitors) == 0:
121         return
122     if host.thread is None:
123         return
124 
125     host.thread_stop(host.thread)
126     host.thread = None
127 
128 # Add monitor to existing interface
129 def add(host, monitors):
130     if host is None:
131         return
132 
133     for monitor in monitors:
134         if monitor != "all" and monitor != host.name:
135             continue
136         mon = "mon_" + host.ifname
137         status, buf = host.execute(["iw", host.ifname, "interface", "add", mon,
138                                     "type", "monitor"])
139         if status == 0:
140             host.monitors.append(mon)
141             host.execute(["ifconfig", mon, "up"])
142         else:
143             logger.debug("Could not add monitor for " + host.name)
144 
145 def remove(host):
146     stop(host)
147     for monitor in host.monitors:
148         host.execute(["iw", monitor, "del"])
149         host.monitors.remove(monitor)
150 
151 
152 # get monitor params from hostapd/wpa_supplicant
153 def get_monitor_params(wpa, is_p2p=False):
154     if is_p2p:
155         get_status_field_f = wpa.get_group_status_field
156     else:
157         get_status_field_f = wpa.get_status_field
158     freq = get_status_field_f("freq")
159     bw = "20"
160     center_freq1 = ""
161     center_freq2 = ""
162 
163     vht_oper_chwidth = get_status_field_f("vht_oper_chwidth")
164     secondary_channel = get_status_field_f("secondary_channel")
165     vht_oper_centr_freq_seg0_idx = get_status_field_f("vht_oper_centr_freq_seg0_idx")
166     vht_oper_centr_freq_seg1_idx = get_status_field_f("vht_oper_centr_freq_seg1_idx")
167     if vht_oper_chwidth == "0" or vht_oper_chwidth is None:
168         if secondary_channel == "1":
169             bw = "40"
170             center_freq1 = str(int(freq) + 10)
171         elif secondary_channel == "-1":
172             center_freq1 = str(int(freq) - 10)
173         else:
174             pass
175     elif vht_oper_chwidth == "1":
176         bw = "80"
177         center_freq1 = str(int(vht_oper_centr_freq_seg0_idx) * 5 + 5000)
178     elif vht_oper_chwidth == "2":
179         bw = "160"
180         center_freq1 = str(int(vht_oper_centr_freq_seg0_idx) * 5 + 5000)
181     elif vht_oper_chwidth == "3":
182         bw = "80+80"
183         center_freq1 = str(int(vht_oper_centr_freq_seg0_idx) * 5 + 5000)
184         center_freq2 = str(int(vht_oper_centr_freq_seg1_idx) * 5 + 5000)
185     else:
186         pass
187 
188     monitor_params = {"freq" : freq,
189                       "bw" : bw,
190                       "center_freq1" : center_freq1,
191                       "center_freq2" : center_freq2}
192 
193     return monitor_params
194