1*92022041SSam Saccone #include <stdint.h>
2*92022041SSam Saccone #include <stdbool.h>
3*92022041SSam Saccone #include <net/if.h>
4*92022041SSam Saccone #include <errno.h>
5*92022041SSam Saccone #include <inttypes.h>
6*92022041SSam Saccone #include <time.h>
7*92022041SSam Saccone #include "iw.h"
8*92022041SSam Saccone
no_seq_check(struct nl_msg * msg,void * arg)9*92022041SSam Saccone static int no_seq_check(struct nl_msg *msg, void *arg)
10*92022041SSam Saccone {
11*92022041SSam Saccone return NL_OK;
12*92022041SSam Saccone }
13*92022041SSam Saccone
14*92022041SSam Saccone struct ieee80211_beacon_channel {
15*92022041SSam Saccone __u16 center_freq;
16*92022041SSam Saccone bool no_ir;
17*92022041SSam Saccone bool no_ibss;
18*92022041SSam Saccone };
19*92022041SSam Saccone
parse_beacon_hint_chan(struct nlattr * tb,struct ieee80211_beacon_channel * chan)20*92022041SSam Saccone static int parse_beacon_hint_chan(struct nlattr *tb,
21*92022041SSam Saccone struct ieee80211_beacon_channel *chan)
22*92022041SSam Saccone {
23*92022041SSam Saccone struct nlattr *tb_freq[NL80211_FREQUENCY_ATTR_MAX + 1];
24*92022041SSam Saccone static struct nla_policy beacon_freq_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
25*92022041SSam Saccone [NL80211_FREQUENCY_ATTR_FREQ] = { .type = NLA_U32 },
26*92022041SSam Saccone [NL80211_FREQUENCY_ATTR_NO_IR] = { .type = NLA_FLAG },
27*92022041SSam Saccone [__NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG },
28*92022041SSam Saccone };
29*92022041SSam Saccone
30*92022041SSam Saccone if (nla_parse_nested(tb_freq,
31*92022041SSam Saccone NL80211_FREQUENCY_ATTR_MAX,
32*92022041SSam Saccone tb,
33*92022041SSam Saccone beacon_freq_policy))
34*92022041SSam Saccone return -EINVAL;
35*92022041SSam Saccone
36*92022041SSam Saccone chan->center_freq = nla_get_u32(tb_freq[NL80211_FREQUENCY_ATTR_FREQ]);
37*92022041SSam Saccone
38*92022041SSam Saccone if (tb_freq[NL80211_FREQUENCY_ATTR_NO_IR])
39*92022041SSam Saccone chan->no_ir = true;
40*92022041SSam Saccone if (tb_freq[__NL80211_FREQUENCY_ATTR_NO_IBSS])
41*92022041SSam Saccone chan->no_ibss = true;
42*92022041SSam Saccone
43*92022041SSam Saccone return 0;
44*92022041SSam Saccone }
45*92022041SSam Saccone
print_frame(struct print_event_args * args,struct nlattr * attr)46*92022041SSam Saccone static void print_frame(struct print_event_args *args, struct nlattr *attr)
47*92022041SSam Saccone {
48*92022041SSam Saccone uint8_t *frame;
49*92022041SSam Saccone size_t len;
50*92022041SSam Saccone unsigned int i;
51*92022041SSam Saccone char macbuf[6*3];
52*92022041SSam Saccone uint16_t tmp;
53*92022041SSam Saccone
54*92022041SSam Saccone if (!attr) {
55*92022041SSam Saccone printf(" [no frame]");
56*92022041SSam Saccone return;
57*92022041SSam Saccone }
58*92022041SSam Saccone
59*92022041SSam Saccone frame = nla_data(attr);
60*92022041SSam Saccone len = nla_len(attr);
61*92022041SSam Saccone
62*92022041SSam Saccone if (len < 26) {
63*92022041SSam Saccone printf(" [invalid frame: ");
64*92022041SSam Saccone goto print_frame;
65*92022041SSam Saccone }
66*92022041SSam Saccone
67*92022041SSam Saccone mac_addr_n2a(macbuf, frame + 10);
68*92022041SSam Saccone printf(" %s -> ", macbuf);
69*92022041SSam Saccone mac_addr_n2a(macbuf, frame + 4);
70*92022041SSam Saccone printf("%s", macbuf);
71*92022041SSam Saccone
72*92022041SSam Saccone switch (frame[0] & 0xfc) {
73*92022041SSam Saccone case 0x10: /* assoc resp */
74*92022041SSam Saccone case 0x30: /* reassoc resp */
75*92022041SSam Saccone /* status */
76*92022041SSam Saccone tmp = (frame[27] << 8) + frame[26];
77*92022041SSam Saccone printf(" status: %d: %s", tmp, get_status_str(tmp));
78*92022041SSam Saccone break;
79*92022041SSam Saccone case 0x00: /* assoc req */
80*92022041SSam Saccone case 0x20: /* reassoc req */
81*92022041SSam Saccone break;
82*92022041SSam Saccone case 0xb0: /* auth */
83*92022041SSam Saccone /* status */
84*92022041SSam Saccone tmp = (frame[29] << 8) + frame[28];
85*92022041SSam Saccone printf(" status: %d: %s", tmp, get_status_str(tmp));
86*92022041SSam Saccone break;
87*92022041SSam Saccone case 0xa0: /* disassoc */
88*92022041SSam Saccone case 0xc0: /* deauth */
89*92022041SSam Saccone /* reason */
90*92022041SSam Saccone tmp = (frame[25] << 8) + frame[24];
91*92022041SSam Saccone printf(" reason %d: %s", tmp, get_reason_str(tmp));
92*92022041SSam Saccone break;
93*92022041SSam Saccone }
94*92022041SSam Saccone
95*92022041SSam Saccone if (!args->frame)
96*92022041SSam Saccone return;
97*92022041SSam Saccone
98*92022041SSam Saccone printf(" [frame:");
99*92022041SSam Saccone
100*92022041SSam Saccone print_frame:
101*92022041SSam Saccone for (i = 0; i < len; i++)
102*92022041SSam Saccone printf(" %.02x", frame[i]);
103*92022041SSam Saccone printf("]");
104*92022041SSam Saccone }
105*92022041SSam Saccone
parse_cqm_event(struct nlattr ** attrs)106*92022041SSam Saccone static void parse_cqm_event(struct nlattr **attrs)
107*92022041SSam Saccone {
108*92022041SSam Saccone static struct nla_policy cqm_policy[NL80211_ATTR_CQM_MAX + 1] = {
109*92022041SSam Saccone [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 },
110*92022041SSam Saccone [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 },
111*92022041SSam Saccone [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
112*92022041SSam Saccone };
113*92022041SSam Saccone struct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1];
114*92022041SSam Saccone struct nlattr *cqm_attr = attrs[NL80211_ATTR_CQM];
115*92022041SSam Saccone
116*92022041SSam Saccone printf("CQM event: ");
117*92022041SSam Saccone
118*92022041SSam Saccone if (!cqm_attr ||
119*92022041SSam Saccone nla_parse_nested(cqm, NL80211_ATTR_CQM_MAX, cqm_attr, cqm_policy)) {
120*92022041SSam Saccone printf("missing data!\n");
121*92022041SSam Saccone return;
122*92022041SSam Saccone }
123*92022041SSam Saccone
124*92022041SSam Saccone if (cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]) {
125*92022041SSam Saccone enum nl80211_cqm_rssi_threshold_event rssi_event;
126*92022041SSam Saccone int32_t rssi_level = -1;
127*92022041SSam Saccone bool found_one = false;
128*92022041SSam Saccone
129*92022041SSam Saccone rssi_event = nla_get_u32(cqm[NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT]);
130*92022041SSam Saccone if (cqm[NL80211_ATTR_CQM_RSSI_LEVEL])
131*92022041SSam Saccone rssi_level = nla_get_u32(cqm[NL80211_ATTR_CQM_RSSI_LEVEL]);
132*92022041SSam Saccone
133*92022041SSam Saccone switch (rssi_event) {
134*92022041SSam Saccone case NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH:
135*92022041SSam Saccone printf("RSSI (%i dBm) went above threshold\n", rssi_level);
136*92022041SSam Saccone found_one = true;
137*92022041SSam Saccone break;
138*92022041SSam Saccone case NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW:
139*92022041SSam Saccone printf("RSSI (%i dBm) went below threshold\n", rssi_level);
140*92022041SSam Saccone found_one = true;
141*92022041SSam Saccone break;
142*92022041SSam Saccone case NL80211_CQM_RSSI_BEACON_LOSS_EVENT:
143*92022041SSam Saccone printf("Beacon loss detected\n");
144*92022041SSam Saccone found_one = true;
145*92022041SSam Saccone break;
146*92022041SSam Saccone }
147*92022041SSam Saccone
148*92022041SSam Saccone if (!found_one)
149*92022041SSam Saccone printf("Unknown event type: %i\n", rssi_event);
150*92022041SSam Saccone } else if (cqm[NL80211_ATTR_CQM_PKT_LOSS_EVENT]) {
151*92022041SSam Saccone if (attrs[NL80211_ATTR_MAC]) {
152*92022041SSam Saccone uint32_t frames;
153*92022041SSam Saccone char buf[3*6];
154*92022041SSam Saccone
155*92022041SSam Saccone frames = nla_get_u32(cqm[NL80211_ATTR_CQM_PKT_LOSS_EVENT]);
156*92022041SSam Saccone mac_addr_n2a(buf, nla_data(attrs[NL80211_ATTR_MAC]));
157*92022041SSam Saccone printf("peer %s didn't ACK %d packets\n", buf, frames);
158*92022041SSam Saccone } else {
159*92022041SSam Saccone printf("PKT-LOSS-EVENT did not have MAC attribute!\n");
160*92022041SSam Saccone }
161*92022041SSam Saccone } else if (cqm[NL80211_ATTR_CQM_BEACON_LOSS_EVENT]) {
162*92022041SSam Saccone printf("beacon loss\n");
163*92022041SSam Saccone } else {
164*92022041SSam Saccone printf("unknown event\n");
165*92022041SSam Saccone }
166*92022041SSam Saccone }
167*92022041SSam Saccone
key_type_str(enum nl80211_key_type key_type)168*92022041SSam Saccone static const char * key_type_str(enum nl80211_key_type key_type)
169*92022041SSam Saccone {
170*92022041SSam Saccone static char buf[30];
171*92022041SSam Saccone switch (key_type) {
172*92022041SSam Saccone case NL80211_KEYTYPE_GROUP:
173*92022041SSam Saccone return "Group";
174*92022041SSam Saccone case NL80211_KEYTYPE_PAIRWISE:
175*92022041SSam Saccone return "Pairwise";
176*92022041SSam Saccone case NL80211_KEYTYPE_PEERKEY:
177*92022041SSam Saccone return "PeerKey";
178*92022041SSam Saccone default:
179*92022041SSam Saccone snprintf(buf, sizeof(buf), "unknown(%d)", key_type);
180*92022041SSam Saccone return buf;
181*92022041SSam Saccone }
182*92022041SSam Saccone }
183*92022041SSam Saccone
parse_mic_failure(struct nlattr ** attrs)184*92022041SSam Saccone static void parse_mic_failure(struct nlattr **attrs)
185*92022041SSam Saccone {
186*92022041SSam Saccone printf("Michael MIC failure event:");
187*92022041SSam Saccone
188*92022041SSam Saccone if (attrs[NL80211_ATTR_MAC]) {
189*92022041SSam Saccone char addr[3 * ETH_ALEN];
190*92022041SSam Saccone mac_addr_n2a(addr, nla_data(attrs[NL80211_ATTR_MAC]));
191*92022041SSam Saccone printf(" source MAC address %s", addr);
192*92022041SSam Saccone }
193*92022041SSam Saccone
194*92022041SSam Saccone if (attrs[NL80211_ATTR_KEY_SEQ] &&
195*92022041SSam Saccone nla_len(attrs[NL80211_ATTR_KEY_SEQ]) == 6) {
196*92022041SSam Saccone unsigned char *seq = nla_data(attrs[NL80211_ATTR_KEY_SEQ]);
197*92022041SSam Saccone printf(" seq=%02x%02x%02x%02x%02x%02x",
198*92022041SSam Saccone seq[0], seq[1], seq[2], seq[3], seq[4], seq[5]);
199*92022041SSam Saccone }
200*92022041SSam Saccone if (attrs[NL80211_ATTR_KEY_TYPE]) {
201*92022041SSam Saccone enum nl80211_key_type key_type =
202*92022041SSam Saccone nla_get_u32(attrs[NL80211_ATTR_KEY_TYPE]);
203*92022041SSam Saccone printf(" Key Type %s", key_type_str(key_type));
204*92022041SSam Saccone }
205*92022041SSam Saccone
206*92022041SSam Saccone if (attrs[NL80211_ATTR_KEY_IDX]) {
207*92022041SSam Saccone __u8 key_id = nla_get_u8(attrs[NL80211_ATTR_KEY_IDX]);
208*92022041SSam Saccone printf(" Key Id %d", key_id);
209*92022041SSam Saccone }
210*92022041SSam Saccone
211*92022041SSam Saccone printf("\n");
212*92022041SSam Saccone }
213*92022041SSam Saccone
parse_wowlan_wake_event(struct nlattr ** attrs)214*92022041SSam Saccone static void parse_wowlan_wake_event(struct nlattr **attrs)
215*92022041SSam Saccone {
216*92022041SSam Saccone struct nlattr *tb[NUM_NL80211_WOWLAN_TRIG],
217*92022041SSam Saccone *tb_match[NUM_NL80211_ATTR];
218*92022041SSam Saccone
219*92022041SSam Saccone printf("WoWLAN wakeup\n");
220*92022041SSam Saccone if (!attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) {
221*92022041SSam Saccone printf("\twakeup not due to WoWLAN\n");
222*92022041SSam Saccone return;
223*92022041SSam Saccone }
224*92022041SSam Saccone
225*92022041SSam Saccone nla_parse(tb, MAX_NL80211_WOWLAN_TRIG,
226*92022041SSam Saccone nla_data(attrs[NL80211_ATTR_WOWLAN_TRIGGERS]),
227*92022041SSam Saccone nla_len(attrs[NL80211_ATTR_WOWLAN_TRIGGERS]), NULL);
228*92022041SSam Saccone
229*92022041SSam Saccone if (tb[NL80211_WOWLAN_TRIG_DISCONNECT])
230*92022041SSam Saccone printf("\t* was disconnected\n");
231*92022041SSam Saccone if (tb[NL80211_WOWLAN_TRIG_MAGIC_PKT])
232*92022041SSam Saccone printf("\t* magic packet received\n");
233*92022041SSam Saccone if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN])
234*92022041SSam Saccone printf("\t* pattern index: %u\n",
235*92022041SSam Saccone nla_get_u32(tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]));
236*92022041SSam Saccone if (tb[NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE])
237*92022041SSam Saccone printf("\t* GTK rekey failure\n");
238*92022041SSam Saccone if (tb[NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST])
239*92022041SSam Saccone printf("\t* EAP identity request\n");
240*92022041SSam Saccone if (tb[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE])
241*92022041SSam Saccone printf("\t* 4-way handshake\n");
242*92022041SSam Saccone if (tb[NL80211_WOWLAN_TRIG_RFKILL_RELEASE])
243*92022041SSam Saccone printf("\t* RF-kill released\n");
244*92022041SSam Saccone if (tb[NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS]) {
245*92022041SSam Saccone struct nlattr *match, *freq;
246*92022041SSam Saccone int rem_nst, rem_nst2;
247*92022041SSam Saccone
248*92022041SSam Saccone printf("\t* network detected\n");
249*92022041SSam Saccone nla_for_each_nested(match,
250*92022041SSam Saccone tb[NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS],
251*92022041SSam Saccone rem_nst) {
252*92022041SSam Saccone nla_parse_nested(tb_match, NL80211_ATTR_MAX, match,
253*92022041SSam Saccone NULL);
254*92022041SSam Saccone printf("\t\tSSID: \"");
255*92022041SSam Saccone print_ssid_escaped(nla_len(tb_match[NL80211_ATTR_SSID]),
256*92022041SSam Saccone nla_data(tb_match[NL80211_ATTR_SSID]));
257*92022041SSam Saccone printf("\"");
258*92022041SSam Saccone if (tb_match[NL80211_ATTR_SCAN_FREQUENCIES]) {
259*92022041SSam Saccone printf(" freq(s):");
260*92022041SSam Saccone nla_for_each_nested(freq,
261*92022041SSam Saccone tb_match[NL80211_ATTR_SCAN_FREQUENCIES],
262*92022041SSam Saccone rem_nst2)
263*92022041SSam Saccone printf(" %d", nla_get_u32(freq));
264*92022041SSam Saccone }
265*92022041SSam Saccone printf("\n");
266*92022041SSam Saccone }
267*92022041SSam Saccone }
268*92022041SSam Saccone if (tb[NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211]) {
269*92022041SSam Saccone uint8_t *d = nla_data(tb[NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211]);
270*92022041SSam Saccone int l = nla_len(tb[NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211]);
271*92022041SSam Saccone int i;
272*92022041SSam Saccone printf("\t* packet (might be truncated): ");
273*92022041SSam Saccone for (i = 0; i < l; i++) {
274*92022041SSam Saccone if (i > 0)
275*92022041SSam Saccone printf(":");
276*92022041SSam Saccone printf("%.2x", d[i]);
277*92022041SSam Saccone }
278*92022041SSam Saccone printf("\n");
279*92022041SSam Saccone }
280*92022041SSam Saccone if (tb[NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023]) {
281*92022041SSam Saccone uint8_t *d = nla_data(tb[NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023]);
282*92022041SSam Saccone int l = nla_len(tb[NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023]);
283*92022041SSam Saccone int i;
284*92022041SSam Saccone printf("\t* packet (might be truncated): ");
285*92022041SSam Saccone for (i = 0; i < l; i++) {
286*92022041SSam Saccone if (i > 0)
287*92022041SSam Saccone printf(":");
288*92022041SSam Saccone printf("%.2x", d[i]);
289*92022041SSam Saccone }
290*92022041SSam Saccone printf("\n");
291*92022041SSam Saccone }
292*92022041SSam Saccone if (tb[NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH])
293*92022041SSam Saccone printf("\t* TCP connection wakeup received\n");
294*92022041SSam Saccone if (tb[NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST])
295*92022041SSam Saccone printf("\t* TCP connection lost\n");
296*92022041SSam Saccone if (tb[NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS])
297*92022041SSam Saccone printf("\t* TCP connection ran out of tokens\n");
298*92022041SSam Saccone }
299*92022041SSam Saccone
300*92022041SSam Saccone extern struct vendor_event *__start_vendor_event[];
301*92022041SSam Saccone extern struct vendor_event *__stop_vendor_event;
302*92022041SSam Saccone
303*92022041SSam Saccone // Dummy to force the section to exist
304*92022041SSam Saccone VENDOR_EVENT(0xffffffff, 0xffffffff, NULL);
305*92022041SSam Saccone
parse_vendor_event(struct nlattr ** attrs,bool dump)306*92022041SSam Saccone static void parse_vendor_event(struct nlattr **attrs, bool dump)
307*92022041SSam Saccone {
308*92022041SSam Saccone __u32 vendor_id, subcmd;
309*92022041SSam Saccone unsigned int i;
310*92022041SSam Saccone
311*92022041SSam Saccone if (!attrs[NL80211_ATTR_VENDOR_ID] ||
312*92022041SSam Saccone !attrs[NL80211_ATTR_VENDOR_SUBCMD])
313*92022041SSam Saccone return;
314*92022041SSam Saccone
315*92022041SSam Saccone vendor_id = nla_get_u32(attrs[NL80211_ATTR_VENDOR_ID]);
316*92022041SSam Saccone subcmd = nla_get_u32(attrs[NL80211_ATTR_VENDOR_SUBCMD]);
317*92022041SSam Saccone
318*92022041SSam Saccone printf("vendor event %.6x:%d", vendor_id, subcmd);
319*92022041SSam Saccone
320*92022041SSam Saccone for (i = 0; i < &__stop_vendor_event - __start_vendor_event; i++) {
321*92022041SSam Saccone struct vendor_event *ev = __start_vendor_event[i];
322*92022041SSam Saccone
323*92022041SSam Saccone if (!ev)
324*92022041SSam Saccone continue;
325*92022041SSam Saccone
326*92022041SSam Saccone if (ev->vendor_id != vendor_id)
327*92022041SSam Saccone continue;
328*92022041SSam Saccone if (ev->subcmd != subcmd)
329*92022041SSam Saccone continue;
330*92022041SSam Saccone if (!ev->callback)
331*92022041SSam Saccone continue;
332*92022041SSam Saccone
333*92022041SSam Saccone ev->callback(vendor_id, subcmd, attrs[NL80211_ATTR_VENDOR_DATA]);
334*92022041SSam Saccone goto out;
335*92022041SSam Saccone }
336*92022041SSam Saccone
337*92022041SSam Saccone if (dump && attrs[NL80211_ATTR_VENDOR_DATA])
338*92022041SSam Saccone iw_hexdump("vendor event",
339*92022041SSam Saccone nla_data(attrs[NL80211_ATTR_VENDOR_DATA]),
340*92022041SSam Saccone nla_len(attrs[NL80211_ATTR_VENDOR_DATA]));
341*92022041SSam Saccone out:
342*92022041SSam Saccone printf("\n");
343*92022041SSam Saccone }
344*92022041SSam Saccone
parse_nan_term(struct nlattr ** attrs)345*92022041SSam Saccone static void parse_nan_term(struct nlattr **attrs)
346*92022041SSam Saccone {
347*92022041SSam Saccone struct nlattr *func[NL80211_NAN_FUNC_ATTR_MAX + 1];
348*92022041SSam Saccone
349*92022041SSam Saccone static struct nla_policy
350*92022041SSam Saccone nan_func_policy[NL80211_NAN_FUNC_ATTR_MAX + 1] = {
351*92022041SSam Saccone [NL80211_NAN_FUNC_TYPE] = { .type = NLA_U8 },
352*92022041SSam Saccone [NL80211_NAN_FUNC_SERVICE_ID] = { },
353*92022041SSam Saccone [NL80211_NAN_FUNC_PUBLISH_TYPE] = { .type = NLA_U8 },
354*92022041SSam Saccone [NL80211_NAN_FUNC_PUBLISH_BCAST] = { .type = NLA_FLAG },
355*92022041SSam Saccone [NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE] = { .type = NLA_FLAG },
356*92022041SSam Saccone [NL80211_NAN_FUNC_FOLLOW_UP_ID] = { .type = NLA_U8 },
357*92022041SSam Saccone [NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] = { .type = NLA_U8 },
358*92022041SSam Saccone [NL80211_NAN_FUNC_FOLLOW_UP_DEST] = { },
359*92022041SSam Saccone [NL80211_NAN_FUNC_CLOSE_RANGE] = { .type = NLA_FLAG },
360*92022041SSam Saccone [NL80211_NAN_FUNC_TTL] = { .type = NLA_U32 },
361*92022041SSam Saccone [NL80211_NAN_FUNC_SERVICE_INFO] = { },
362*92022041SSam Saccone [NL80211_NAN_FUNC_SRF] = { .type = NLA_NESTED },
363*92022041SSam Saccone [NL80211_NAN_FUNC_RX_MATCH_FILTER] = { .type = NLA_NESTED },
364*92022041SSam Saccone [NL80211_NAN_FUNC_TX_MATCH_FILTER] = { .type = NLA_NESTED },
365*92022041SSam Saccone [NL80211_NAN_FUNC_INSTANCE_ID] = { .type = NLA_U8},
366*92022041SSam Saccone };
367*92022041SSam Saccone
368*92022041SSam Saccone if (!attrs[NL80211_ATTR_COOKIE]) {
369*92022041SSam Saccone printf("Bad NAN func termination format - cookie is missing\n");
370*92022041SSam Saccone return;
371*92022041SSam Saccone }
372*92022041SSam Saccone
373*92022041SSam Saccone if (nla_parse_nested(func, NL80211_NAN_FUNC_ATTR_MAX,
374*92022041SSam Saccone attrs[NL80211_ATTR_NAN_FUNC],
375*92022041SSam Saccone nan_func_policy)) {
376*92022041SSam Saccone printf("NAN: failed to parse nan func\n");
377*92022041SSam Saccone return;
378*92022041SSam Saccone }
379*92022041SSam Saccone
380*92022041SSam Saccone if (!func[NL80211_NAN_FUNC_INSTANCE_ID]) {
381*92022041SSam Saccone printf("Bad NAN func termination format-instance id missing\n");
382*92022041SSam Saccone return;
383*92022041SSam Saccone }
384*92022041SSam Saccone
385*92022041SSam Saccone if (!func[NL80211_NAN_FUNC_TERM_REASON]) {
386*92022041SSam Saccone printf("Bad NAN func termination format - reason is missing\n");
387*92022041SSam Saccone return;
388*92022041SSam Saccone }
389*92022041SSam Saccone printf("NAN(cookie=0x%llx): Termination event: id = %d, reason = ",
390*92022041SSam Saccone (long long int)nla_get_u64(attrs[NL80211_ATTR_COOKIE]),
391*92022041SSam Saccone nla_get_u8(func[NL80211_NAN_FUNC_INSTANCE_ID]));
392*92022041SSam Saccone switch (nla_get_u8(func[NL80211_NAN_FUNC_TERM_REASON])) {
393*92022041SSam Saccone case NL80211_NAN_FUNC_TERM_REASON_USER_REQUEST:
394*92022041SSam Saccone printf("user request\n");
395*92022041SSam Saccone break;
396*92022041SSam Saccone case NL80211_NAN_FUNC_TERM_REASON_TTL_EXPIRED:
397*92022041SSam Saccone printf("expired\n");
398*92022041SSam Saccone break;
399*92022041SSam Saccone case NL80211_NAN_FUNC_TERM_REASON_ERROR:
400*92022041SSam Saccone printf("error\n");
401*92022041SSam Saccone break;
402*92022041SSam Saccone default:
403*92022041SSam Saccone printf("unknown\n");
404*92022041SSam Saccone }
405*92022041SSam Saccone }
406*92022041SSam Saccone
ftm_fail_reason(unsigned int reason)407*92022041SSam Saccone static const char *ftm_fail_reason(unsigned int reason)
408*92022041SSam Saccone {
409*92022041SSam Saccone #define FTM_FAIL_REASON(x) case NL80211_PMSR_FTM_FAILURE_##x: return #x
410*92022041SSam Saccone switch (reason) {
411*92022041SSam Saccone FTM_FAIL_REASON(UNSPECIFIED);
412*92022041SSam Saccone FTM_FAIL_REASON(NO_RESPONSE);
413*92022041SSam Saccone FTM_FAIL_REASON(REJECTED);
414*92022041SSam Saccone FTM_FAIL_REASON(WRONG_CHANNEL);
415*92022041SSam Saccone FTM_FAIL_REASON(PEER_NOT_CAPABLE);
416*92022041SSam Saccone FTM_FAIL_REASON(INVALID_TIMESTAMP);
417*92022041SSam Saccone FTM_FAIL_REASON(PEER_BUSY);
418*92022041SSam Saccone FTM_FAIL_REASON(BAD_CHANGED_PARAMS);
419*92022041SSam Saccone default:
420*92022041SSam Saccone return "unknown";
421*92022041SSam Saccone }
422*92022041SSam Saccone }
423*92022041SSam Saccone
parse_pmsr_ftm_data(struct nlattr * data)424*92022041SSam Saccone static void parse_pmsr_ftm_data(struct nlattr *data)
425*92022041SSam Saccone {
426*92022041SSam Saccone struct nlattr *ftm[NL80211_PMSR_FTM_RESP_ATTR_MAX + 1];
427*92022041SSam Saccone
428*92022041SSam Saccone printf(" FTM");
429*92022041SSam Saccone nla_parse_nested(ftm, NL80211_PMSR_FTM_RESP_ATTR_MAX, data, NULL);
430*92022041SSam Saccone
431*92022041SSam Saccone if (ftm[NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON]) {
432*92022041SSam Saccone printf(" failed: %s (%d)",
433*92022041SSam Saccone ftm_fail_reason(nla_get_u32(ftm[NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON])),
434*92022041SSam Saccone nla_get_u32(ftm[NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON]));
435*92022041SSam Saccone if (ftm[NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME])
436*92022041SSam Saccone printf(" retry after %us",
437*92022041SSam Saccone nla_get_u32(ftm[NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME]));
438*92022041SSam Saccone printf("\n");
439*92022041SSam Saccone return;
440*92022041SSam Saccone }
441*92022041SSam Saccone
442*92022041SSam Saccone printf("\n");
443*92022041SSam Saccone
444*92022041SSam Saccone #define PFTM(tp, attr, sign) \
445*92022041SSam Saccone do { \
446*92022041SSam Saccone if (ftm[NL80211_PMSR_FTM_RESP_ATTR_##attr]) \
447*92022041SSam Saccone printf(" " #attr ": %lld\n", \
448*92022041SSam Saccone (sign long long)nla_get_##tp( \
449*92022041SSam Saccone ftm[NL80211_PMSR_FTM_RESP_ATTR_##attr])); \
450*92022041SSam Saccone } while (0)
451*92022041SSam Saccone
452*92022041SSam Saccone PFTM(u32, BURST_INDEX, unsigned);
453*92022041SSam Saccone PFTM(u32, NUM_FTMR_ATTEMPTS, unsigned);
454*92022041SSam Saccone PFTM(u32, NUM_FTMR_SUCCESSES, unsigned);
455*92022041SSam Saccone PFTM(u8, NUM_BURSTS_EXP, unsigned);
456*92022041SSam Saccone PFTM(u8, BURST_DURATION, unsigned);
457*92022041SSam Saccone PFTM(u8, FTMS_PER_BURST, unsigned);
458*92022041SSam Saccone PFTM(u32, RSSI_AVG, signed);
459*92022041SSam Saccone PFTM(u32, RSSI_SPREAD, unsigned);
460*92022041SSam Saccone PFTM(u64, RTT_AVG, signed);
461*92022041SSam Saccone PFTM(u64, RTT_VARIANCE, unsigned);
462*92022041SSam Saccone PFTM(u64, RTT_SPREAD, unsigned);
463*92022041SSam Saccone PFTM(u64, DIST_AVG, signed);
464*92022041SSam Saccone PFTM(u64, DIST_VARIANCE, unsigned);
465*92022041SSam Saccone PFTM(u64, DIST_SPREAD, unsigned);
466*92022041SSam Saccone
467*92022041SSam Saccone if (ftm[NL80211_PMSR_FTM_RESP_ATTR_TX_RATE]) {
468*92022041SSam Saccone char buf[100];
469*92022041SSam Saccone
470*92022041SSam Saccone parse_bitrate(ftm[NL80211_PMSR_FTM_RESP_ATTR_TX_RATE],
471*92022041SSam Saccone buf, sizeof(buf));
472*92022041SSam Saccone printf(" TX bitrate: %s\n", buf);
473*92022041SSam Saccone }
474*92022041SSam Saccone
475*92022041SSam Saccone if (ftm[NL80211_PMSR_FTM_RESP_ATTR_RX_RATE]) {
476*92022041SSam Saccone char buf[100];
477*92022041SSam Saccone
478*92022041SSam Saccone parse_bitrate(ftm[NL80211_PMSR_FTM_RESP_ATTR_RX_RATE],
479*92022041SSam Saccone buf, sizeof(buf));
480*92022041SSam Saccone printf(" RX bitrate: %s\n", buf);
481*92022041SSam Saccone }
482*92022041SSam Saccone
483*92022041SSam Saccone if (ftm[NL80211_PMSR_FTM_RESP_ATTR_LCI])
484*92022041SSam Saccone iw_hexdump(" LCI",
485*92022041SSam Saccone nla_data(ftm[NL80211_PMSR_FTM_RESP_ATTR_LCI]),
486*92022041SSam Saccone nla_len(ftm[NL80211_PMSR_FTM_RESP_ATTR_LCI]));
487*92022041SSam Saccone
488*92022041SSam Saccone if (ftm[NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC])
489*92022041SSam Saccone iw_hexdump(" civic location",
490*92022041SSam Saccone nla_data(ftm[NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC]),
491*92022041SSam Saccone nla_len(ftm[NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC]));
492*92022041SSam Saccone }
493*92022041SSam Saccone
pmsr_status(unsigned int status)494*92022041SSam Saccone static const char *pmsr_status(unsigned int status)
495*92022041SSam Saccone {
496*92022041SSam Saccone #define PMSR_STATUS(x) case NL80211_PMSR_STATUS_##x: return #x
497*92022041SSam Saccone switch (status) {
498*92022041SSam Saccone PMSR_STATUS(SUCCESS);
499*92022041SSam Saccone PMSR_STATUS(REFUSED);
500*92022041SSam Saccone PMSR_STATUS(TIMEOUT);
501*92022041SSam Saccone PMSR_STATUS(FAILURE);
502*92022041SSam Saccone default:
503*92022041SSam Saccone return "unknown";
504*92022041SSam Saccone }
505*92022041SSam Saccone #undef PMSR_STATUS
506*92022041SSam Saccone }
507*92022041SSam Saccone
parse_pmsr_peer(struct nlattr * peer)508*92022041SSam Saccone static void parse_pmsr_peer(struct nlattr *peer)
509*92022041SSam Saccone {
510*92022041SSam Saccone struct nlattr *tb[NL80211_PMSR_PEER_ATTR_MAX + 1];
511*92022041SSam Saccone struct nlattr *resp[NL80211_PMSR_RESP_ATTR_MAX + 1];
512*92022041SSam Saccone struct nlattr *data[NL80211_PMSR_TYPE_MAX + 1];
513*92022041SSam Saccone char macbuf[6*3];
514*92022041SSam Saccone int err;
515*92022041SSam Saccone
516*92022041SSam Saccone err = nla_parse_nested(tb, NL80211_PMSR_PEER_ATTR_MAX, peer, NULL);
517*92022041SSam Saccone if (err) {
518*92022041SSam Saccone printf(" Peer: failed to parse!\n");
519*92022041SSam Saccone return;
520*92022041SSam Saccone }
521*92022041SSam Saccone
522*92022041SSam Saccone if (!tb[NL80211_PMSR_PEER_ATTR_ADDR]) {
523*92022041SSam Saccone printf(" Peer: no MAC address\n");
524*92022041SSam Saccone return;
525*92022041SSam Saccone }
526*92022041SSam Saccone
527*92022041SSam Saccone mac_addr_n2a(macbuf, nla_data(tb[NL80211_PMSR_PEER_ATTR_ADDR]));
528*92022041SSam Saccone printf(" Peer %s:", macbuf);
529*92022041SSam Saccone
530*92022041SSam Saccone if (!tb[NL80211_PMSR_PEER_ATTR_RESP]) {
531*92022041SSam Saccone printf(" no response!\n");
532*92022041SSam Saccone return;
533*92022041SSam Saccone }
534*92022041SSam Saccone
535*92022041SSam Saccone err = nla_parse_nested(resp, NL80211_PMSR_RESP_ATTR_MAX,
536*92022041SSam Saccone tb[NL80211_PMSR_PEER_ATTR_RESP], NULL);
537*92022041SSam Saccone if (err) {
538*92022041SSam Saccone printf(" failed to parse response!\n");
539*92022041SSam Saccone return;
540*92022041SSam Saccone }
541*92022041SSam Saccone
542*92022041SSam Saccone if (resp[NL80211_PMSR_RESP_ATTR_STATUS])
543*92022041SSam Saccone printf(" status=%d (%s)",
544*92022041SSam Saccone nla_get_u32(resp[NL80211_PMSR_RESP_ATTR_STATUS]),
545*92022041SSam Saccone pmsr_status(nla_get_u32(resp[NL80211_PMSR_RESP_ATTR_STATUS])));
546*92022041SSam Saccone if (resp[NL80211_PMSR_RESP_ATTR_HOST_TIME])
547*92022041SSam Saccone printf(" @%llu",
548*92022041SSam Saccone (unsigned long long)nla_get_u64(resp[NL80211_PMSR_RESP_ATTR_HOST_TIME]));
549*92022041SSam Saccone if (resp[NL80211_PMSR_RESP_ATTR_AP_TSF])
550*92022041SSam Saccone printf(" tsf=%llu",
551*92022041SSam Saccone (unsigned long long)nla_get_u64(resp[NL80211_PMSR_RESP_ATTR_AP_TSF]));
552*92022041SSam Saccone if (resp[NL80211_PMSR_RESP_ATTR_FINAL])
553*92022041SSam Saccone printf(" (final)");
554*92022041SSam Saccone
555*92022041SSam Saccone if (!resp[NL80211_PMSR_RESP_ATTR_DATA]) {
556*92022041SSam Saccone printf(" - no data!\n");
557*92022041SSam Saccone return;
558*92022041SSam Saccone }
559*92022041SSam Saccone
560*92022041SSam Saccone printf("\n");
561*92022041SSam Saccone
562*92022041SSam Saccone nla_parse_nested(data, NL80211_PMSR_TYPE_MAX,
563*92022041SSam Saccone resp[NL80211_PMSR_RESP_ATTR_DATA], NULL);
564*92022041SSam Saccone
565*92022041SSam Saccone if (data[NL80211_PMSR_TYPE_FTM])
566*92022041SSam Saccone parse_pmsr_ftm_data(data[NL80211_PMSR_TYPE_FTM]);
567*92022041SSam Saccone }
568*92022041SSam Saccone
parse_pmsr_result(struct nlattr ** tb,struct print_event_args * pargs)569*92022041SSam Saccone static void parse_pmsr_result(struct nlattr **tb,
570*92022041SSam Saccone struct print_event_args *pargs)
571*92022041SSam Saccone {
572*92022041SSam Saccone struct nlattr *pmsr[NL80211_PMSR_ATTR_MAX + 1];
573*92022041SSam Saccone struct nlattr *peer;
574*92022041SSam Saccone unsigned long long cookie;
575*92022041SSam Saccone int err, i;
576*92022041SSam Saccone
577*92022041SSam Saccone if (!tb[NL80211_ATTR_COOKIE]) {
578*92022041SSam Saccone printf("Peer measurements: no cookie!\n");
579*92022041SSam Saccone return;
580*92022041SSam Saccone }
581*92022041SSam Saccone cookie = nla_get_u64(tb[NL80211_ATTR_COOKIE]);
582*92022041SSam Saccone
583*92022041SSam Saccone if (!tb[NL80211_ATTR_PEER_MEASUREMENTS]) {
584*92022041SSam Saccone printf("Peer measurements: no measurement data!\n");
585*92022041SSam Saccone return;
586*92022041SSam Saccone }
587*92022041SSam Saccone
588*92022041SSam Saccone err = nla_parse_nested(pmsr, NL80211_PMSR_ATTR_MAX,
589*92022041SSam Saccone tb[NL80211_ATTR_PEER_MEASUREMENTS], NULL);
590*92022041SSam Saccone if (err) {
591*92022041SSam Saccone printf("Peer measurements: failed to parse measurement data!\n");
592*92022041SSam Saccone return;
593*92022041SSam Saccone }
594*92022041SSam Saccone
595*92022041SSam Saccone if (!pmsr[NL80211_PMSR_ATTR_PEERS]) {
596*92022041SSam Saccone printf("Peer measurements: no peer data!\n");
597*92022041SSam Saccone return;
598*92022041SSam Saccone }
599*92022041SSam Saccone
600*92022041SSam Saccone printf("Peer measurements (cookie %llu):\n", cookie);
601*92022041SSam Saccone
602*92022041SSam Saccone nla_for_each_nested(peer, pmsr[NL80211_PMSR_ATTR_PEERS], i)
603*92022041SSam Saccone parse_pmsr_peer(peer);
604*92022041SSam Saccone }
605*92022041SSam Saccone
parse_nan_match(struct nlattr ** attrs)606*92022041SSam Saccone static void parse_nan_match(struct nlattr **attrs)
607*92022041SSam Saccone {
608*92022041SSam Saccone char macbuf[6*3];
609*92022041SSam Saccone __u64 cookie;
610*92022041SSam Saccone struct nlattr *match[NL80211_NAN_MATCH_ATTR_MAX + 1];
611*92022041SSam Saccone struct nlattr *local_func[NL80211_NAN_FUNC_ATTR_MAX + 1];
612*92022041SSam Saccone struct nlattr *peer_func[NL80211_NAN_FUNC_ATTR_MAX + 1];
613*92022041SSam Saccone
614*92022041SSam Saccone static struct nla_policy
615*92022041SSam Saccone nan_match_policy[NL80211_NAN_MATCH_ATTR_MAX + 1] = {
616*92022041SSam Saccone [NL80211_NAN_MATCH_FUNC_LOCAL] = { .type = NLA_NESTED },
617*92022041SSam Saccone [NL80211_NAN_MATCH_FUNC_PEER] = { .type = NLA_NESTED },
618*92022041SSam Saccone };
619*92022041SSam Saccone
620*92022041SSam Saccone static struct nla_policy
621*92022041SSam Saccone nan_func_policy[NL80211_NAN_FUNC_ATTR_MAX + 1] = {
622*92022041SSam Saccone [NL80211_NAN_FUNC_TYPE] = { .type = NLA_U8 },
623*92022041SSam Saccone [NL80211_NAN_FUNC_SERVICE_ID] = { },
624*92022041SSam Saccone [NL80211_NAN_FUNC_PUBLISH_TYPE] = { .type = NLA_U8 },
625*92022041SSam Saccone [NL80211_NAN_FUNC_PUBLISH_BCAST] = { .type = NLA_FLAG },
626*92022041SSam Saccone [NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE] = { .type = NLA_FLAG },
627*92022041SSam Saccone [NL80211_NAN_FUNC_FOLLOW_UP_ID] = { .type = NLA_U8 },
628*92022041SSam Saccone [NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] = { .type = NLA_U8 },
629*92022041SSam Saccone [NL80211_NAN_FUNC_FOLLOW_UP_DEST] = { },
630*92022041SSam Saccone [NL80211_NAN_FUNC_CLOSE_RANGE] = { .type = NLA_FLAG },
631*92022041SSam Saccone [NL80211_NAN_FUNC_TTL] = { .type = NLA_U32 },
632*92022041SSam Saccone [NL80211_NAN_FUNC_SERVICE_INFO] = { },
633*92022041SSam Saccone [NL80211_NAN_FUNC_SRF] = { .type = NLA_NESTED },
634*92022041SSam Saccone [NL80211_NAN_FUNC_RX_MATCH_FILTER] = { .type = NLA_NESTED },
635*92022041SSam Saccone [NL80211_NAN_FUNC_TX_MATCH_FILTER] = { .type = NLA_NESTED },
636*92022041SSam Saccone [NL80211_NAN_FUNC_INSTANCE_ID] = { .type = NLA_U8},
637*92022041SSam Saccone };
638*92022041SSam Saccone
639*92022041SSam Saccone cookie = nla_get_u64(attrs[NL80211_ATTR_COOKIE]);
640*92022041SSam Saccone mac_addr_n2a(macbuf, nla_data(attrs[NL80211_ATTR_MAC]));
641*92022041SSam Saccone
642*92022041SSam Saccone if (nla_parse_nested(match, NL80211_NAN_MATCH_ATTR_MAX,
643*92022041SSam Saccone attrs[NL80211_ATTR_NAN_MATCH],
644*92022041SSam Saccone nan_match_policy)) {
645*92022041SSam Saccone printf("NAN: failed to parse nan match event\n");
646*92022041SSam Saccone return;
647*92022041SSam Saccone }
648*92022041SSam Saccone
649*92022041SSam Saccone if (nla_parse_nested(local_func, NL80211_NAN_FUNC_ATTR_MAX,
650*92022041SSam Saccone match[NL80211_NAN_MATCH_FUNC_LOCAL],
651*92022041SSam Saccone nan_func_policy)) {
652*92022041SSam Saccone printf("NAN: failed to parse nan local func\n");
653*92022041SSam Saccone return;
654*92022041SSam Saccone }
655*92022041SSam Saccone
656*92022041SSam Saccone if (nla_parse_nested(peer_func, NL80211_NAN_FUNC_ATTR_MAX,
657*92022041SSam Saccone match[NL80211_NAN_MATCH_FUNC_PEER],
658*92022041SSam Saccone nan_func_policy)) {
659*92022041SSam Saccone printf("NAN: failed to parse nan local func\n");
660*92022041SSam Saccone return;
661*92022041SSam Saccone }
662*92022041SSam Saccone
663*92022041SSam Saccone if (nla_get_u8(peer_func[NL80211_NAN_FUNC_TYPE]) ==
664*92022041SSam Saccone NL80211_NAN_FUNC_PUBLISH) {
665*92022041SSam Saccone printf(
666*92022041SSam Saccone "NAN(cookie=0x%llx): DiscoveryResult, peer_id=%d, local_id=%d, peer_mac=%s",
667*92022041SSam Saccone cookie,
668*92022041SSam Saccone nla_get_u8(peer_func[NL80211_NAN_FUNC_INSTANCE_ID]),
669*92022041SSam Saccone nla_get_u8(local_func[NL80211_NAN_FUNC_INSTANCE_ID]),
670*92022041SSam Saccone macbuf);
671*92022041SSam Saccone if (peer_func[NL80211_NAN_FUNC_SERVICE_INFO])
672*92022041SSam Saccone printf(", info=%.*s",
673*92022041SSam Saccone nla_len(peer_func[NL80211_NAN_FUNC_SERVICE_INFO]),
674*92022041SSam Saccone (char *)nla_data(peer_func[NL80211_NAN_FUNC_SERVICE_INFO]));
675*92022041SSam Saccone } else if (nla_get_u8(peer_func[NL80211_NAN_FUNC_TYPE]) ==
676*92022041SSam Saccone NL80211_NAN_FUNC_SUBSCRIBE) {
677*92022041SSam Saccone printf(
678*92022041SSam Saccone "NAN(cookie=0x%llx): Replied, peer_id=%d, local_id=%d, peer_mac=%s",
679*92022041SSam Saccone cookie,
680*92022041SSam Saccone nla_get_u8(peer_func[NL80211_NAN_FUNC_INSTANCE_ID]),
681*92022041SSam Saccone nla_get_u8(local_func[NL80211_NAN_FUNC_INSTANCE_ID]),
682*92022041SSam Saccone macbuf);
683*92022041SSam Saccone } else if (nla_get_u8(peer_func[NL80211_NAN_FUNC_TYPE]) ==
684*92022041SSam Saccone NL80211_NAN_FUNC_FOLLOW_UP) {
685*92022041SSam Saccone printf(
686*92022041SSam Saccone "NAN(cookie=0x%llx): FollowUpReceive, peer_id=%d, local_id=%d, peer_mac=%s",
687*92022041SSam Saccone cookie,
688*92022041SSam Saccone nla_get_u8(peer_func[NL80211_NAN_FUNC_INSTANCE_ID]),
689*92022041SSam Saccone nla_get_u8(local_func[NL80211_NAN_FUNC_INSTANCE_ID]),
690*92022041SSam Saccone macbuf);
691*92022041SSam Saccone if (peer_func[NL80211_NAN_FUNC_SERVICE_INFO])
692*92022041SSam Saccone printf(", info=%.*s",
693*92022041SSam Saccone nla_len(peer_func[NL80211_NAN_FUNC_SERVICE_INFO]),
694*92022041SSam Saccone (char *)nla_data(peer_func[NL80211_NAN_FUNC_SERVICE_INFO]));
695*92022041SSam Saccone } else {
696*92022041SSam Saccone printf("NaN: Malformed event");
697*92022041SSam Saccone }
698*92022041SSam Saccone
699*92022041SSam Saccone printf("\n");
700*92022041SSam Saccone }
701*92022041SSam Saccone
parse_new_peer_candidate(struct nlattr ** attrs)702*92022041SSam Saccone static void parse_new_peer_candidate(struct nlattr **attrs)
703*92022041SSam Saccone {
704*92022041SSam Saccone char macbuf[ETH_ALEN * 3];
705*92022041SSam Saccone int32_t sig_dbm;
706*92022041SSam Saccone
707*92022041SSam Saccone printf("new peer candidate");
708*92022041SSam Saccone if (attrs[NL80211_ATTR_MAC]) {
709*92022041SSam Saccone mac_addr_n2a(macbuf, nla_data(attrs[NL80211_ATTR_MAC]));
710*92022041SSam Saccone printf(" %s", macbuf);
711*92022041SSam Saccone }
712*92022041SSam Saccone if (attrs[NL80211_ATTR_RX_SIGNAL_DBM]) {
713*92022041SSam Saccone sig_dbm = nla_get_u32(attrs[NL80211_ATTR_RX_SIGNAL_DBM]);
714*92022041SSam Saccone printf(" %d dBm", sig_dbm);
715*92022041SSam Saccone }
716*92022041SSam Saccone
717*92022041SSam Saccone printf("\n");
718*92022041SSam Saccone }
719*92022041SSam Saccone
parse_recv_interface(struct nlattr ** attrs,int command)720*92022041SSam Saccone static void parse_recv_interface(struct nlattr **attrs, int command)
721*92022041SSam Saccone {
722*92022041SSam Saccone switch (command) {
723*92022041SSam Saccone case NL80211_CMD_NEW_INTERFACE:
724*92022041SSam Saccone printf("new interface");
725*92022041SSam Saccone break;
726*92022041SSam Saccone case NL80211_CMD_DEL_INTERFACE:
727*92022041SSam Saccone printf("del interface");
728*92022041SSam Saccone break;
729*92022041SSam Saccone case NL80211_CMD_SET_INTERFACE:
730*92022041SSam Saccone printf("set interface");
731*92022041SSam Saccone break;
732*92022041SSam Saccone default:
733*92022041SSam Saccone printf("unknown interface command (%i) received\n", command);
734*92022041SSam Saccone return;
735*92022041SSam Saccone }
736*92022041SSam Saccone
737*92022041SSam Saccone if (attrs[NL80211_ATTR_IFTYPE]) {
738*92022041SSam Saccone printf(" type ");
739*92022041SSam Saccone switch (nla_get_u32(attrs[NL80211_ATTR_IFTYPE])) {
740*92022041SSam Saccone case NL80211_IFTYPE_STATION:
741*92022041SSam Saccone printf("station");
742*92022041SSam Saccone break;
743*92022041SSam Saccone case NL80211_IFTYPE_AP:
744*92022041SSam Saccone printf("access point");
745*92022041SSam Saccone break;
746*92022041SSam Saccone case NL80211_IFTYPE_MESH_POINT:
747*92022041SSam Saccone printf("mesh point");
748*92022041SSam Saccone break;
749*92022041SSam Saccone case NL80211_IFTYPE_ADHOC:
750*92022041SSam Saccone printf("IBSS");
751*92022041SSam Saccone break;
752*92022041SSam Saccone case NL80211_IFTYPE_MONITOR:
753*92022041SSam Saccone printf("monitor");
754*92022041SSam Saccone break;
755*92022041SSam Saccone case NL80211_IFTYPE_AP_VLAN:
756*92022041SSam Saccone printf("AP-VLAN");
757*92022041SSam Saccone break;
758*92022041SSam Saccone case NL80211_IFTYPE_WDS:
759*92022041SSam Saccone printf("WDS");
760*92022041SSam Saccone break;
761*92022041SSam Saccone case NL80211_IFTYPE_P2P_CLIENT:
762*92022041SSam Saccone printf("P2P-client");
763*92022041SSam Saccone break;
764*92022041SSam Saccone case NL80211_IFTYPE_P2P_GO:
765*92022041SSam Saccone printf("P2P-GO");
766*92022041SSam Saccone break;
767*92022041SSam Saccone case NL80211_IFTYPE_P2P_DEVICE:
768*92022041SSam Saccone printf("P2P-Device");
769*92022041SSam Saccone break;
770*92022041SSam Saccone case NL80211_IFTYPE_OCB:
771*92022041SSam Saccone printf("OCB");
772*92022041SSam Saccone break;
773*92022041SSam Saccone case NL80211_IFTYPE_NAN:
774*92022041SSam Saccone printf("NAN");
775*92022041SSam Saccone break;
776*92022041SSam Saccone default:
777*92022041SSam Saccone printf("unknown (%d)",
778*92022041SSam Saccone nla_get_u32(attrs[NL80211_ATTR_IFTYPE]));
779*92022041SSam Saccone break;
780*92022041SSam Saccone }
781*92022041SSam Saccone }
782*92022041SSam Saccone
783*92022041SSam Saccone if (attrs[NL80211_ATTR_MESH_ID]) {
784*92022041SSam Saccone printf(" meshid ");
785*92022041SSam Saccone print_ssid_escaped(nla_len(attrs[NL80211_ATTR_MESH_ID]),
786*92022041SSam Saccone nla_data(attrs[NL80211_ATTR_MESH_ID]));
787*92022041SSam Saccone }
788*92022041SSam Saccone
789*92022041SSam Saccone if (attrs[NL80211_ATTR_4ADDR]) {
790*92022041SSam Saccone printf(" use 4addr %d", nla_get_u8(attrs[NL80211_ATTR_4ADDR]));
791*92022041SSam Saccone }
792*92022041SSam Saccone
793*92022041SSam Saccone printf("\n");
794*92022041SSam Saccone }
795*92022041SSam Saccone
parse_sta_opmode_changed(struct nlattr ** attrs)796*92022041SSam Saccone static void parse_sta_opmode_changed(struct nlattr **attrs)
797*92022041SSam Saccone {
798*92022041SSam Saccone char macbuf[ETH_ALEN*3];
799*92022041SSam Saccone
800*92022041SSam Saccone printf("sta opmode changed");
801*92022041SSam Saccone
802*92022041SSam Saccone if (attrs[NL80211_ATTR_MAC]) {
803*92022041SSam Saccone mac_addr_n2a(macbuf, nla_data(attrs[NL80211_ATTR_MAC]));
804*92022041SSam Saccone printf(" %s", macbuf);
805*92022041SSam Saccone }
806*92022041SSam Saccone
807*92022041SSam Saccone if (attrs[NL80211_ATTR_SMPS_MODE])
808*92022041SSam Saccone printf(" smps mode %d", nla_get_u8(attrs[NL80211_ATTR_SMPS_MODE]));
809*92022041SSam Saccone
810*92022041SSam Saccone if (attrs[NL80211_ATTR_CHANNEL_WIDTH])
811*92022041SSam Saccone printf(" chan width %d", nla_get_u8(attrs[NL80211_ATTR_CHANNEL_WIDTH]));
812*92022041SSam Saccone
813*92022041SSam Saccone if (attrs[NL80211_ATTR_NSS])
814*92022041SSam Saccone printf(" nss %d", nla_get_u8(attrs[NL80211_ATTR_NSS]));
815*92022041SSam Saccone
816*92022041SSam Saccone printf("\n");
817*92022041SSam Saccone }
818*92022041SSam Saccone
parse_ch_switch_notify(struct nlattr ** attrs,int command)819*92022041SSam Saccone static void parse_ch_switch_notify(struct nlattr **attrs, int command)
820*92022041SSam Saccone {
821*92022041SSam Saccone switch (command) {
822*92022041SSam Saccone case NL80211_CMD_CH_SWITCH_STARTED_NOTIFY:
823*92022041SSam Saccone printf("channel switch started");
824*92022041SSam Saccone break;
825*92022041SSam Saccone case NL80211_CMD_CH_SWITCH_NOTIFY:
826*92022041SSam Saccone printf("channel switch");
827*92022041SSam Saccone break;
828*92022041SSam Saccone default:
829*92022041SSam Saccone printf("unknown channel switch command (%i) received\n", command);
830*92022041SSam Saccone return;
831*92022041SSam Saccone }
832*92022041SSam Saccone
833*92022041SSam Saccone if (attrs[NL80211_ATTR_CH_SWITCH_COUNT])
834*92022041SSam Saccone printf(" (count=%d)", nla_get_u32(attrs[NL80211_ATTR_CH_SWITCH_COUNT]));
835*92022041SSam Saccone
836*92022041SSam Saccone if (attrs[NL80211_ATTR_WIPHY_FREQ])
837*92022041SSam Saccone printf(" freq=%d", nla_get_u32(attrs[NL80211_ATTR_WIPHY_FREQ]));
838*92022041SSam Saccone
839*92022041SSam Saccone if (attrs[NL80211_ATTR_CHANNEL_WIDTH]) {
840*92022041SSam Saccone printf(" width=");
841*92022041SSam Saccone switch(nla_get_u32(attrs[NL80211_ATTR_CHANNEL_WIDTH])) {
842*92022041SSam Saccone case NL80211_CHAN_WIDTH_20_NOHT:
843*92022041SSam Saccone case NL80211_CHAN_WIDTH_20:
844*92022041SSam Saccone printf("\"20 MHz\"");
845*92022041SSam Saccone break;
846*92022041SSam Saccone case NL80211_CHAN_WIDTH_40:
847*92022041SSam Saccone printf("\"40 MHz\"");
848*92022041SSam Saccone break;
849*92022041SSam Saccone case NL80211_CHAN_WIDTH_80:
850*92022041SSam Saccone printf("\"80 MHz\"");
851*92022041SSam Saccone break;
852*92022041SSam Saccone case NL80211_CHAN_WIDTH_80P80:
853*92022041SSam Saccone printf("\"80+80 MHz\"");
854*92022041SSam Saccone break;
855*92022041SSam Saccone case NL80211_CHAN_WIDTH_160:
856*92022041SSam Saccone printf("\"160 MHz\"");
857*92022041SSam Saccone break;
858*92022041SSam Saccone case NL80211_CHAN_WIDTH_5:
859*92022041SSam Saccone printf("\"5 MHz\"");
860*92022041SSam Saccone break;
861*92022041SSam Saccone case NL80211_CHAN_WIDTH_10:
862*92022041SSam Saccone printf("\"10 MHz\"");
863*92022041SSam Saccone break;
864*92022041SSam Saccone default:
865*92022041SSam Saccone printf("\"unknown\"");
866*92022041SSam Saccone }
867*92022041SSam Saccone }
868*92022041SSam Saccone
869*92022041SSam Saccone if (attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
870*92022041SSam Saccone printf(" type=");
871*92022041SSam Saccone switch(nla_get_u32(attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE])) {
872*92022041SSam Saccone case NL80211_CHAN_NO_HT:
873*92022041SSam Saccone printf("\"No HT\"");
874*92022041SSam Saccone break;
875*92022041SSam Saccone case NL80211_CHAN_HT20:
876*92022041SSam Saccone printf("\"HT20\"");
877*92022041SSam Saccone break;
878*92022041SSam Saccone case NL80211_CHAN_HT40MINUS:
879*92022041SSam Saccone printf("\"HT40-\"");
880*92022041SSam Saccone break;
881*92022041SSam Saccone case NL80211_CHAN_HT40PLUS:
882*92022041SSam Saccone printf("\"HT40+\"");
883*92022041SSam Saccone break;
884*92022041SSam Saccone }
885*92022041SSam Saccone }
886*92022041SSam Saccone
887*92022041SSam Saccone if (attrs[NL80211_ATTR_CENTER_FREQ1])
888*92022041SSam Saccone printf(" freq1=%d", nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ1]));
889*92022041SSam Saccone
890*92022041SSam Saccone if (attrs[NL80211_ATTR_CENTER_FREQ2])
891*92022041SSam Saccone printf(" freq2=%d", nla_get_u32(attrs[NL80211_ATTR_CENTER_FREQ2]));
892*92022041SSam Saccone
893*92022041SSam Saccone printf("\n");
894*92022041SSam Saccone }
895*92022041SSam Saccone
parse_assoc_comeback(struct nlattr ** attrs,int command)896*92022041SSam Saccone static void parse_assoc_comeback(struct nlattr **attrs, int command)
897*92022041SSam Saccone {
898*92022041SSam Saccone __u32 timeout = 0;
899*92022041SSam Saccone char macbuf[6 * 3] = "<unset>";
900*92022041SSam Saccone
901*92022041SSam Saccone if (attrs[NL80211_ATTR_MAC])
902*92022041SSam Saccone mac_addr_n2a(macbuf, nla_data(attrs[NL80211_ATTR_MAC]));
903*92022041SSam Saccone
904*92022041SSam Saccone if (attrs[NL80211_ATTR_TIMEOUT])
905*92022041SSam Saccone timeout = nla_get_u32(attrs[NL80211_ATTR_TIMEOUT]);
906*92022041SSam Saccone
907*92022041SSam Saccone printf("assoc comeback bssid %s timeout %d\n",
908*92022041SSam Saccone macbuf, timeout);
909*92022041SSam Saccone }
910*92022041SSam Saccone
print_event(struct nl_msg * msg,void * arg)911*92022041SSam Saccone static int print_event(struct nl_msg *msg, void *arg)
912*92022041SSam Saccone {
913*92022041SSam Saccone struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
914*92022041SSam Saccone struct nlattr *tb[NL80211_ATTR_MAX + 1], *nst;
915*92022041SSam Saccone struct print_event_args *args = arg;
916*92022041SSam Saccone char ifname[100];
917*92022041SSam Saccone char macbuf[6*3];
918*92022041SSam Saccone __u8 reg_type;
919*92022041SSam Saccone struct ieee80211_beacon_channel chan_before_beacon, chan_after_beacon;
920*92022041SSam Saccone __u32 wiphy_idx = 0;
921*92022041SSam Saccone int rem_nst;
922*92022041SSam Saccone __u16 status;
923*92022041SSam Saccone
924*92022041SSam Saccone if (args->time || args->reltime || args->ctime) {
925*92022041SSam Saccone unsigned long long usecs, previous;
926*92022041SSam Saccone
927*92022041SSam Saccone previous = 1000000ULL * args->ts.tv_sec + args->ts.tv_usec;
928*92022041SSam Saccone gettimeofday(&args->ts, NULL);
929*92022041SSam Saccone usecs = 1000000ULL * args->ts.tv_sec + args->ts.tv_usec;
930*92022041SSam Saccone
931*92022041SSam Saccone if (args->reltime) {
932*92022041SSam Saccone if (!args->have_ts) {
933*92022041SSam Saccone usecs = 0;
934*92022041SSam Saccone args->have_ts = true;
935*92022041SSam Saccone } else
936*92022041SSam Saccone usecs -= previous;
937*92022041SSam Saccone }
938*92022041SSam Saccone
939*92022041SSam Saccone if (args->ctime) {
940*92022041SSam Saccone struct tm *tm = localtime(&args->ts.tv_sec);
941*92022041SSam Saccone char buf[255];
942*92022041SSam Saccone
943*92022041SSam Saccone memset(buf, 0, 255);
944*92022041SSam Saccone strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm);
945*92022041SSam Saccone printf("[%s.%06lu]: ", buf, args->ts.tv_usec);
946*92022041SSam Saccone } else {
947*92022041SSam Saccone printf("%llu.%06llu: ", usecs/1000000, usecs % 1000000);
948*92022041SSam Saccone }
949*92022041SSam Saccone }
950*92022041SSam Saccone
951*92022041SSam Saccone nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
952*92022041SSam Saccone genlmsg_attrlen(gnlh, 0), NULL);
953*92022041SSam Saccone
954*92022041SSam Saccone if (tb[NL80211_ATTR_IFINDEX] && tb[NL80211_ATTR_WIPHY]) {
955*92022041SSam Saccone /* if_indextoname may fails on delete interface/wiphy event */
956*92022041SSam Saccone if (if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), ifname))
957*92022041SSam Saccone printf("%s (phy #%d): ", ifname, nla_get_u32(tb[NL80211_ATTR_WIPHY]));
958*92022041SSam Saccone else
959*92022041SSam Saccone printf("phy #%d: ", nla_get_u32(tb[NL80211_ATTR_WIPHY]));
960*92022041SSam Saccone } else if (tb[NL80211_ATTR_WDEV] && tb[NL80211_ATTR_WIPHY]) {
961*92022041SSam Saccone printf("wdev 0x%llx (phy #%d): ",
962*92022041SSam Saccone (unsigned long long)nla_get_u64(tb[NL80211_ATTR_WDEV]),
963*92022041SSam Saccone nla_get_u32(tb[NL80211_ATTR_WIPHY]));
964*92022041SSam Saccone } else if (tb[NL80211_ATTR_IFINDEX]) {
965*92022041SSam Saccone if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), ifname);
966*92022041SSam Saccone printf("%s: ", ifname);
967*92022041SSam Saccone } else if (tb[NL80211_ATTR_WDEV]) {
968*92022041SSam Saccone printf("wdev 0x%llx: ", (unsigned long long)nla_get_u64(tb[NL80211_ATTR_WDEV]));
969*92022041SSam Saccone } else if (tb[NL80211_ATTR_WIPHY]) {
970*92022041SSam Saccone printf("phy #%d: ", nla_get_u32(tb[NL80211_ATTR_WIPHY]));
971*92022041SSam Saccone }
972*92022041SSam Saccone
973*92022041SSam Saccone switch (gnlh->cmd) {
974*92022041SSam Saccone case NL80211_CMD_NEW_WIPHY:
975*92022041SSam Saccone printf("renamed to %s\n", nla_get_string(tb[NL80211_ATTR_WIPHY_NAME]));
976*92022041SSam Saccone break;
977*92022041SSam Saccone case NL80211_CMD_TRIGGER_SCAN:
978*92022041SSam Saccone printf("scan started\n");
979*92022041SSam Saccone break;
980*92022041SSam Saccone case NL80211_CMD_NEW_SCAN_RESULTS:
981*92022041SSam Saccone printf("scan finished:");
982*92022041SSam Saccone /* fall through */
983*92022041SSam Saccone case NL80211_CMD_SCAN_ABORTED:
984*92022041SSam Saccone if (gnlh->cmd == NL80211_CMD_SCAN_ABORTED)
985*92022041SSam Saccone printf("scan aborted:");
986*92022041SSam Saccone if (tb[NL80211_ATTR_SCAN_FREQUENCIES]) {
987*92022041SSam Saccone nla_for_each_nested(nst, tb[NL80211_ATTR_SCAN_FREQUENCIES], rem_nst)
988*92022041SSam Saccone printf(" %d", nla_get_u32(nst));
989*92022041SSam Saccone printf(",");
990*92022041SSam Saccone }
991*92022041SSam Saccone if (tb[NL80211_ATTR_SCAN_SSIDS]) {
992*92022041SSam Saccone nla_for_each_nested(nst, tb[NL80211_ATTR_SCAN_SSIDS], rem_nst) {
993*92022041SSam Saccone printf(" \"");
994*92022041SSam Saccone print_ssid_escaped(nla_len(nst), nla_data(nst));
995*92022041SSam Saccone printf("\"");
996*92022041SSam Saccone }
997*92022041SSam Saccone }
998*92022041SSam Saccone printf("\n");
999*92022041SSam Saccone break;
1000*92022041SSam Saccone case NL80211_CMD_START_SCHED_SCAN:
1001*92022041SSam Saccone printf("scheduled scan started\n");
1002*92022041SSam Saccone break;
1003*92022041SSam Saccone case NL80211_CMD_SCHED_SCAN_STOPPED:
1004*92022041SSam Saccone printf("sched scan stopped\n");
1005*92022041SSam Saccone break;
1006*92022041SSam Saccone case NL80211_CMD_SCHED_SCAN_RESULTS:
1007*92022041SSam Saccone printf("got scheduled scan results\n");
1008*92022041SSam Saccone break;
1009*92022041SSam Saccone case NL80211_CMD_WIPHY_REG_CHANGE:
1010*92022041SSam Saccone case NL80211_CMD_REG_CHANGE:
1011*92022041SSam Saccone if (gnlh->cmd == NL80211_CMD_WIPHY_REG_CHANGE)
1012*92022041SSam Saccone printf("regulatory domain change (phy): ");
1013*92022041SSam Saccone else
1014*92022041SSam Saccone printf("regulatory domain change: ");
1015*92022041SSam Saccone
1016*92022041SSam Saccone reg_type = nla_get_u8(tb[NL80211_ATTR_REG_TYPE]);
1017*92022041SSam Saccone
1018*92022041SSam Saccone switch (reg_type) {
1019*92022041SSam Saccone case NL80211_REGDOM_TYPE_COUNTRY:
1020*92022041SSam Saccone printf("set to %s by %s request",
1021*92022041SSam Saccone nla_get_string(tb[NL80211_ATTR_REG_ALPHA2]),
1022*92022041SSam Saccone reg_initiator_to_string(nla_get_u8(tb[NL80211_ATTR_REG_INITIATOR])));
1023*92022041SSam Saccone if (tb[NL80211_ATTR_WIPHY])
1024*92022041SSam Saccone printf(" on phy%d", nla_get_u32(tb[NL80211_ATTR_WIPHY]));
1025*92022041SSam Saccone break;
1026*92022041SSam Saccone case NL80211_REGDOM_TYPE_WORLD:
1027*92022041SSam Saccone printf("set to world roaming by %s request",
1028*92022041SSam Saccone reg_initiator_to_string(nla_get_u8(tb[NL80211_ATTR_REG_INITIATOR])));
1029*92022041SSam Saccone break;
1030*92022041SSam Saccone case NL80211_REGDOM_TYPE_CUSTOM_WORLD:
1031*92022041SSam Saccone printf("custom world roaming rules in place on phy%d by %s request",
1032*92022041SSam Saccone nla_get_u32(tb[NL80211_ATTR_WIPHY]),
1033*92022041SSam Saccone reg_initiator_to_string(nla_get_u32(tb[NL80211_ATTR_REG_INITIATOR])));
1034*92022041SSam Saccone break;
1035*92022041SSam Saccone case NL80211_REGDOM_TYPE_INTERSECTION:
1036*92022041SSam Saccone printf("intersection used due to a request made by %s",
1037*92022041SSam Saccone reg_initiator_to_string(nla_get_u32(tb[NL80211_ATTR_REG_INITIATOR])));
1038*92022041SSam Saccone if (tb[NL80211_ATTR_WIPHY])
1039*92022041SSam Saccone printf(" on phy%d", nla_get_u32(tb[NL80211_ATTR_WIPHY]));
1040*92022041SSam Saccone break;
1041*92022041SSam Saccone default:
1042*92022041SSam Saccone printf("unknown source (upgrade this utility)");
1043*92022041SSam Saccone break;
1044*92022041SSam Saccone }
1045*92022041SSam Saccone
1046*92022041SSam Saccone printf("\n");
1047*92022041SSam Saccone break;
1048*92022041SSam Saccone case NL80211_CMD_REG_BEACON_HINT:
1049*92022041SSam Saccone
1050*92022041SSam Saccone wiphy_idx = nla_get_u32(tb[NL80211_ATTR_WIPHY]);
1051*92022041SSam Saccone
1052*92022041SSam Saccone memset(&chan_before_beacon, 0, sizeof(chan_before_beacon));
1053*92022041SSam Saccone memset(&chan_after_beacon, 0, sizeof(chan_after_beacon));
1054*92022041SSam Saccone
1055*92022041SSam Saccone if (parse_beacon_hint_chan(tb[NL80211_ATTR_FREQ_BEFORE],
1056*92022041SSam Saccone &chan_before_beacon))
1057*92022041SSam Saccone break;
1058*92022041SSam Saccone if (parse_beacon_hint_chan(tb[NL80211_ATTR_FREQ_AFTER],
1059*92022041SSam Saccone &chan_after_beacon))
1060*92022041SSam Saccone break;
1061*92022041SSam Saccone
1062*92022041SSam Saccone if (chan_before_beacon.center_freq != chan_after_beacon.center_freq)
1063*92022041SSam Saccone break;
1064*92022041SSam Saccone
1065*92022041SSam Saccone /* A beacon hint is sent _only_ if something _did_ change */
1066*92022041SSam Saccone printf("beacon hint:\n");
1067*92022041SSam Saccone
1068*92022041SSam Saccone printf("phy%d %d MHz [%d]:\n",
1069*92022041SSam Saccone wiphy_idx,
1070*92022041SSam Saccone chan_before_beacon.center_freq,
1071*92022041SSam Saccone ieee80211_frequency_to_channel(chan_before_beacon.center_freq));
1072*92022041SSam Saccone
1073*92022041SSam Saccone if (chan_before_beacon.no_ir && !chan_after_beacon.no_ir) {
1074*92022041SSam Saccone if (chan_before_beacon.no_ibss && !chan_after_beacon.no_ibss)
1075*92022041SSam Saccone printf("\to Initiating radiation enabled\n");
1076*92022041SSam Saccone else
1077*92022041SSam Saccone printf("\to active scan enabled\n");
1078*92022041SSam Saccone } else if (chan_before_beacon.no_ibss && !chan_after_beacon.no_ibss) {
1079*92022041SSam Saccone printf("\to ibss enabled\n");
1080*92022041SSam Saccone }
1081*92022041SSam Saccone
1082*92022041SSam Saccone break;
1083*92022041SSam Saccone case NL80211_CMD_NEW_STATION:
1084*92022041SSam Saccone mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
1085*92022041SSam Saccone printf("new station %s\n", macbuf);
1086*92022041SSam Saccone break;
1087*92022041SSam Saccone case NL80211_CMD_DEL_STATION:
1088*92022041SSam Saccone mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
1089*92022041SSam Saccone printf("del station %s\n", macbuf);
1090*92022041SSam Saccone break;
1091*92022041SSam Saccone case NL80211_CMD_JOIN_IBSS:
1092*92022041SSam Saccone mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
1093*92022041SSam Saccone printf("IBSS %s joined\n", macbuf);
1094*92022041SSam Saccone break;
1095*92022041SSam Saccone case NL80211_CMD_AUTHENTICATE:
1096*92022041SSam Saccone printf("auth");
1097*92022041SSam Saccone if (tb[NL80211_ATTR_FRAME])
1098*92022041SSam Saccone print_frame(args, tb[NL80211_ATTR_FRAME]);
1099*92022041SSam Saccone else if (tb[NL80211_ATTR_TIMED_OUT])
1100*92022041SSam Saccone printf(": timed out");
1101*92022041SSam Saccone else
1102*92022041SSam Saccone printf(": unknown event");
1103*92022041SSam Saccone printf("\n");
1104*92022041SSam Saccone break;
1105*92022041SSam Saccone case NL80211_CMD_ASSOCIATE:
1106*92022041SSam Saccone printf("assoc");
1107*92022041SSam Saccone if (tb[NL80211_ATTR_FRAME])
1108*92022041SSam Saccone print_frame(args, tb[NL80211_ATTR_FRAME]);
1109*92022041SSam Saccone else if (tb[NL80211_ATTR_TIMED_OUT])
1110*92022041SSam Saccone printf(": timed out");
1111*92022041SSam Saccone else
1112*92022041SSam Saccone printf(": unknown event");
1113*92022041SSam Saccone printf("\n");
1114*92022041SSam Saccone break;
1115*92022041SSam Saccone case NL80211_CMD_DEAUTHENTICATE:
1116*92022041SSam Saccone printf("deauth");
1117*92022041SSam Saccone print_frame(args, tb[NL80211_ATTR_FRAME]);
1118*92022041SSam Saccone printf("\n");
1119*92022041SSam Saccone break;
1120*92022041SSam Saccone case NL80211_CMD_DISASSOCIATE:
1121*92022041SSam Saccone printf("disassoc");
1122*92022041SSam Saccone print_frame(args, tb[NL80211_ATTR_FRAME]);
1123*92022041SSam Saccone printf("\n");
1124*92022041SSam Saccone break;
1125*92022041SSam Saccone case NL80211_CMD_UNPROT_DEAUTHENTICATE:
1126*92022041SSam Saccone printf("unprotected deauth");
1127*92022041SSam Saccone print_frame(args, tb[NL80211_ATTR_FRAME]);
1128*92022041SSam Saccone printf("\n");
1129*92022041SSam Saccone break;
1130*92022041SSam Saccone case NL80211_CMD_UNPROT_DISASSOCIATE:
1131*92022041SSam Saccone printf("unprotected disassoc");
1132*92022041SSam Saccone print_frame(args, tb[NL80211_ATTR_FRAME]);
1133*92022041SSam Saccone printf("\n");
1134*92022041SSam Saccone break;
1135*92022041SSam Saccone case NL80211_CMD_CONNECT:
1136*92022041SSam Saccone status = 0;
1137*92022041SSam Saccone if (tb[NL80211_ATTR_TIMED_OUT])
1138*92022041SSam Saccone printf("timed out");
1139*92022041SSam Saccone else if (!tb[NL80211_ATTR_STATUS_CODE])
1140*92022041SSam Saccone printf("unknown connect status");
1141*92022041SSam Saccone else if (nla_get_u16(tb[NL80211_ATTR_STATUS_CODE]) == 0)
1142*92022041SSam Saccone printf("connected");
1143*92022041SSam Saccone else {
1144*92022041SSam Saccone status = nla_get_u16(tb[NL80211_ATTR_STATUS_CODE]);
1145*92022041SSam Saccone printf("failed to connect");
1146*92022041SSam Saccone }
1147*92022041SSam Saccone if (tb[NL80211_ATTR_MAC]) {
1148*92022041SSam Saccone mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
1149*92022041SSam Saccone printf(" to %s", macbuf);
1150*92022041SSam Saccone }
1151*92022041SSam Saccone if (status)
1152*92022041SSam Saccone printf(", status: %d: %s", status, get_status_str(status));
1153*92022041SSam Saccone printf("\n");
1154*92022041SSam Saccone break;
1155*92022041SSam Saccone case NL80211_CMD_ROAM:
1156*92022041SSam Saccone printf("roamed");
1157*92022041SSam Saccone if (tb[NL80211_ATTR_MAC]) {
1158*92022041SSam Saccone mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
1159*92022041SSam Saccone printf(" to %s", macbuf);
1160*92022041SSam Saccone }
1161*92022041SSam Saccone printf("\n");
1162*92022041SSam Saccone break;
1163*92022041SSam Saccone case NL80211_CMD_DISCONNECT:
1164*92022041SSam Saccone printf("disconnected");
1165*92022041SSam Saccone if (tb[NL80211_ATTR_DISCONNECTED_BY_AP])
1166*92022041SSam Saccone printf(" (by AP)");
1167*92022041SSam Saccone else
1168*92022041SSam Saccone printf(" (local request)");
1169*92022041SSam Saccone if (tb[NL80211_ATTR_REASON_CODE])
1170*92022041SSam Saccone printf(" reason: %d: %s", nla_get_u16(tb[NL80211_ATTR_REASON_CODE]),
1171*92022041SSam Saccone get_reason_str(nla_get_u16(tb[NL80211_ATTR_REASON_CODE])));
1172*92022041SSam Saccone printf("\n");
1173*92022041SSam Saccone break;
1174*92022041SSam Saccone case NL80211_CMD_REMAIN_ON_CHANNEL:
1175*92022041SSam Saccone printf("remain on freq %d (%dms, cookie %llx)\n",
1176*92022041SSam Saccone nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]),
1177*92022041SSam Saccone nla_get_u32(tb[NL80211_ATTR_DURATION]),
1178*92022041SSam Saccone (unsigned long long)nla_get_u64(tb[NL80211_ATTR_COOKIE]));
1179*92022041SSam Saccone break;
1180*92022041SSam Saccone case NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL:
1181*92022041SSam Saccone printf("done with remain on freq %d (cookie %llx)\n",
1182*92022041SSam Saccone nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]),
1183*92022041SSam Saccone (unsigned long long)nla_get_u64(tb[NL80211_ATTR_COOKIE]));
1184*92022041SSam Saccone break;
1185*92022041SSam Saccone case NL80211_CMD_FRAME_WAIT_CANCEL:
1186*92022041SSam Saccone printf("frame wait cancel on freq %d (cookie %llx)\n",
1187*92022041SSam Saccone nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]),
1188*92022041SSam Saccone (unsigned long long)nla_get_u64(tb[NL80211_ATTR_COOKIE]));
1189*92022041SSam Saccone break;
1190*92022041SSam Saccone case NL80211_CMD_NOTIFY_CQM:
1191*92022041SSam Saccone parse_cqm_event(tb);
1192*92022041SSam Saccone break;
1193*92022041SSam Saccone case NL80211_CMD_MICHAEL_MIC_FAILURE:
1194*92022041SSam Saccone parse_mic_failure(tb);
1195*92022041SSam Saccone break;
1196*92022041SSam Saccone case NL80211_CMD_FRAME_TX_STATUS:
1197*92022041SSam Saccone printf("mgmt TX status (cookie %llx): %s\n",
1198*92022041SSam Saccone (unsigned long long)nla_get_u64(tb[NL80211_ATTR_COOKIE]),
1199*92022041SSam Saccone tb[NL80211_ATTR_ACK] ? "acked" : "no ack");
1200*92022041SSam Saccone break;
1201*92022041SSam Saccone case NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS:
1202*92022041SSam Saccone printf("ctrl. port TX status (cookie %llx): %s\n",
1203*92022041SSam Saccone (unsigned long long)nla_get_u64(tb[NL80211_ATTR_COOKIE]),
1204*92022041SSam Saccone tb[NL80211_ATTR_ACK] ? "acked" : "no ack");
1205*92022041SSam Saccone break;
1206*92022041SSam Saccone case NL80211_CMD_PMKSA_CANDIDATE:
1207*92022041SSam Saccone printf("PMKSA candidate found\n");
1208*92022041SSam Saccone break;
1209*92022041SSam Saccone case NL80211_CMD_SET_WOWLAN:
1210*92022041SSam Saccone parse_wowlan_wake_event(tb);
1211*92022041SSam Saccone break;
1212*92022041SSam Saccone case NL80211_CMD_PROBE_CLIENT:
1213*92022041SSam Saccone if (tb[NL80211_ATTR_MAC])
1214*92022041SSam Saccone mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC]));
1215*92022041SSam Saccone else
1216*92022041SSam Saccone strcpy(macbuf, "??");
1217*92022041SSam Saccone printf("probe client %s (cookie %llx): %s\n",
1218*92022041SSam Saccone macbuf,
1219*92022041SSam Saccone (unsigned long long)nla_get_u64(tb[NL80211_ATTR_COOKIE]),
1220*92022041SSam Saccone tb[NL80211_ATTR_ACK] ? "acked" : "no ack");
1221*92022041SSam Saccone break;
1222*92022041SSam Saccone case NL80211_CMD_VENDOR:
1223*92022041SSam Saccone parse_vendor_event(tb, args->frame);
1224*92022041SSam Saccone break;
1225*92022041SSam Saccone case NL80211_CMD_RADAR_DETECT: {
1226*92022041SSam Saccone enum nl80211_radar_event event_type;
1227*92022041SSam Saccone uint32_t freq;
1228*92022041SSam Saccone
1229*92022041SSam Saccone if (!tb[NL80211_ATTR_RADAR_EVENT] ||
1230*92022041SSam Saccone !tb[NL80211_ATTR_WIPHY_FREQ]) {
1231*92022041SSam Saccone printf("BAD radar event\n");
1232*92022041SSam Saccone break;
1233*92022041SSam Saccone }
1234*92022041SSam Saccone
1235*92022041SSam Saccone freq = nla_get_u32(tb[NL80211_ATTR_WIPHY_FREQ]);
1236*92022041SSam Saccone event_type = nla_get_u32(tb[NL80211_ATTR_RADAR_EVENT]);
1237*92022041SSam Saccone
1238*92022041SSam Saccone switch (event_type) {
1239*92022041SSam Saccone case NL80211_RADAR_DETECTED:
1240*92022041SSam Saccone printf("%d MHz: radar detected\n", freq);
1241*92022041SSam Saccone break;
1242*92022041SSam Saccone case NL80211_RADAR_CAC_FINISHED:
1243*92022041SSam Saccone printf("%d MHz: CAC finished\n", freq);
1244*92022041SSam Saccone break;
1245*92022041SSam Saccone case NL80211_RADAR_CAC_ABORTED:
1246*92022041SSam Saccone printf("%d MHz: CAC was aborted\n", freq);
1247*92022041SSam Saccone break;
1248*92022041SSam Saccone case NL80211_RADAR_NOP_FINISHED:
1249*92022041SSam Saccone printf("%d MHz: NOP finished\n", freq);
1250*92022041SSam Saccone break;
1251*92022041SSam Saccone case NL80211_RADAR_PRE_CAC_EXPIRED:
1252*92022041SSam Saccone printf("%d MHz: PRE-CAC expired\n", freq);
1253*92022041SSam Saccone break;
1254*92022041SSam Saccone case NL80211_RADAR_CAC_STARTED:
1255*92022041SSam Saccone printf("%d MHz: CAC started\n", freq);
1256*92022041SSam Saccone break;
1257*92022041SSam Saccone default:
1258*92022041SSam Saccone printf("%d MHz: unknown radar event\n", freq);
1259*92022041SSam Saccone }
1260*92022041SSam Saccone }
1261*92022041SSam Saccone break;
1262*92022041SSam Saccone case NL80211_CMD_DEL_WIPHY:
1263*92022041SSam Saccone printf("delete wiphy\n");
1264*92022041SSam Saccone break;
1265*92022041SSam Saccone case NL80211_CMD_PEER_MEASUREMENT_RESULT:
1266*92022041SSam Saccone parse_pmsr_result(tb, args);
1267*92022041SSam Saccone break;
1268*92022041SSam Saccone case NL80211_CMD_PEER_MEASUREMENT_COMPLETE:
1269*92022041SSam Saccone printf("peer measurement complete\n");
1270*92022041SSam Saccone break;
1271*92022041SSam Saccone case NL80211_CMD_DEL_NAN_FUNCTION:
1272*92022041SSam Saccone parse_nan_term(tb);
1273*92022041SSam Saccone break;
1274*92022041SSam Saccone case NL80211_CMD_NAN_MATCH:
1275*92022041SSam Saccone parse_nan_match(tb);
1276*92022041SSam Saccone break;
1277*92022041SSam Saccone case NL80211_CMD_NEW_PEER_CANDIDATE:
1278*92022041SSam Saccone parse_new_peer_candidate(tb);
1279*92022041SSam Saccone break;
1280*92022041SSam Saccone case NL80211_CMD_NEW_INTERFACE:
1281*92022041SSam Saccone case NL80211_CMD_SET_INTERFACE:
1282*92022041SSam Saccone case NL80211_CMD_DEL_INTERFACE:
1283*92022041SSam Saccone parse_recv_interface(tb, gnlh->cmd);
1284*92022041SSam Saccone break;
1285*92022041SSam Saccone case NL80211_CMD_STA_OPMODE_CHANGED:
1286*92022041SSam Saccone parse_sta_opmode_changed(tb);
1287*92022041SSam Saccone break;
1288*92022041SSam Saccone case NL80211_CMD_STOP_AP:
1289*92022041SSam Saccone printf("stop ap\n");
1290*92022041SSam Saccone break;
1291*92022041SSam Saccone case NL80211_CMD_CH_SWITCH_STARTED_NOTIFY:
1292*92022041SSam Saccone case NL80211_CMD_CH_SWITCH_NOTIFY:
1293*92022041SSam Saccone parse_ch_switch_notify(tb, gnlh->cmd);
1294*92022041SSam Saccone break;
1295*92022041SSam Saccone case NL80211_CMD_ASSOC_COMEBACK: /* 147 */
1296*92022041SSam Saccone parse_assoc_comeback(tb, gnlh->cmd);
1297*92022041SSam Saccone break;
1298*92022041SSam Saccone default:
1299*92022041SSam Saccone printf("unknown event %d (%s)\n",
1300*92022041SSam Saccone gnlh->cmd, command_name(gnlh->cmd));
1301*92022041SSam Saccone break;
1302*92022041SSam Saccone }
1303*92022041SSam Saccone
1304*92022041SSam Saccone fflush(stdout);
1305*92022041SSam Saccone return NL_SKIP;
1306*92022041SSam Saccone }
1307*92022041SSam Saccone
1308*92022041SSam Saccone struct wait_event {
1309*92022041SSam Saccone int n_cmds, n_prints;
1310*92022041SSam Saccone const __u32 *cmds;
1311*92022041SSam Saccone const __u32 *prints;
1312*92022041SSam Saccone __u32 cmd;
1313*92022041SSam Saccone struct print_event_args *pargs;
1314*92022041SSam Saccone };
1315*92022041SSam Saccone
wait_event(struct nl_msg * msg,void * arg)1316*92022041SSam Saccone static int wait_event(struct nl_msg *msg, void *arg)
1317*92022041SSam Saccone {
1318*92022041SSam Saccone struct wait_event *wait = arg;
1319*92022041SSam Saccone struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
1320*92022041SSam Saccone int i;
1321*92022041SSam Saccone
1322*92022041SSam Saccone if (wait->pargs) {
1323*92022041SSam Saccone for (i = 0; i < wait->n_prints; i++) {
1324*92022041SSam Saccone if (gnlh->cmd == wait->prints[i])
1325*92022041SSam Saccone print_event(msg, wait->pargs);
1326*92022041SSam Saccone }
1327*92022041SSam Saccone }
1328*92022041SSam Saccone
1329*92022041SSam Saccone for (i = 0; i < wait->n_cmds; i++) {
1330*92022041SSam Saccone if (gnlh->cmd == wait->cmds[i])
1331*92022041SSam Saccone wait->cmd = gnlh->cmd;
1332*92022041SSam Saccone }
1333*92022041SSam Saccone
1334*92022041SSam Saccone return NL_SKIP;
1335*92022041SSam Saccone }
1336*92022041SSam Saccone
__prepare_listen_events(struct nl80211_state * state)1337*92022041SSam Saccone int __prepare_listen_events(struct nl80211_state *state)
1338*92022041SSam Saccone {
1339*92022041SSam Saccone int mcid, ret;
1340*92022041SSam Saccone
1341*92022041SSam Saccone /* Configuration multicast group */
1342*92022041SSam Saccone mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "config");
1343*92022041SSam Saccone if (mcid < 0)
1344*92022041SSam Saccone return mcid;
1345*92022041SSam Saccone
1346*92022041SSam Saccone ret = nl_socket_add_membership(state->nl_sock, mcid);
1347*92022041SSam Saccone if (ret)
1348*92022041SSam Saccone return ret;
1349*92022041SSam Saccone
1350*92022041SSam Saccone /* Scan multicast group */
1351*92022041SSam Saccone mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "scan");
1352*92022041SSam Saccone if (mcid >= 0) {
1353*92022041SSam Saccone ret = nl_socket_add_membership(state->nl_sock, mcid);
1354*92022041SSam Saccone if (ret)
1355*92022041SSam Saccone return ret;
1356*92022041SSam Saccone }
1357*92022041SSam Saccone
1358*92022041SSam Saccone /* Regulatory multicast group */
1359*92022041SSam Saccone mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "regulatory");
1360*92022041SSam Saccone if (mcid >= 0) {
1361*92022041SSam Saccone ret = nl_socket_add_membership(state->nl_sock, mcid);
1362*92022041SSam Saccone if (ret)
1363*92022041SSam Saccone return ret;
1364*92022041SSam Saccone }
1365*92022041SSam Saccone
1366*92022041SSam Saccone /* MLME multicast group */
1367*92022041SSam Saccone mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "mlme");
1368*92022041SSam Saccone if (mcid >= 0) {
1369*92022041SSam Saccone ret = nl_socket_add_membership(state->nl_sock, mcid);
1370*92022041SSam Saccone if (ret)
1371*92022041SSam Saccone return ret;
1372*92022041SSam Saccone }
1373*92022041SSam Saccone
1374*92022041SSam Saccone mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "vendor");
1375*92022041SSam Saccone if (mcid >= 0) {
1376*92022041SSam Saccone ret = nl_socket_add_membership(state->nl_sock, mcid);
1377*92022041SSam Saccone if (ret)
1378*92022041SSam Saccone return ret;
1379*92022041SSam Saccone }
1380*92022041SSam Saccone
1381*92022041SSam Saccone mcid = nl_get_multicast_id(state->nl_sock, "nl80211", "nan");
1382*92022041SSam Saccone if (mcid >= 0) {
1383*92022041SSam Saccone ret = nl_socket_add_membership(state->nl_sock, mcid);
1384*92022041SSam Saccone if (ret)
1385*92022041SSam Saccone return ret;
1386*92022041SSam Saccone }
1387*92022041SSam Saccone
1388*92022041SSam Saccone return 0;
1389*92022041SSam Saccone }
1390*92022041SSam Saccone
__do_listen_events(struct nl80211_state * state,const int n_waits,const __u32 * waits,const int n_prints,const __u32 * prints,struct print_event_args * args)1391*92022041SSam Saccone __u32 __do_listen_events(struct nl80211_state *state,
1392*92022041SSam Saccone const int n_waits, const __u32 *waits,
1393*92022041SSam Saccone const int n_prints, const __u32 *prints,
1394*92022041SSam Saccone struct print_event_args *args)
1395*92022041SSam Saccone {
1396*92022041SSam Saccone struct nl_cb *cb = nl_cb_alloc(iw_debug ? NL_CB_DEBUG : NL_CB_DEFAULT);
1397*92022041SSam Saccone struct wait_event wait_ev;
1398*92022041SSam Saccone
1399*92022041SSam Saccone if (!cb) {
1400*92022041SSam Saccone fprintf(stderr, "failed to allocate netlink callbacks\n");
1401*92022041SSam Saccone return -ENOMEM;
1402*92022041SSam Saccone }
1403*92022041SSam Saccone
1404*92022041SSam Saccone /* no sequence checking for multicast messages */
1405*92022041SSam Saccone nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
1406*92022041SSam Saccone nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, valid_handler, NULL);
1407*92022041SSam Saccone
1408*92022041SSam Saccone if (n_waits && waits) {
1409*92022041SSam Saccone wait_ev.cmds = waits;
1410*92022041SSam Saccone wait_ev.n_cmds = n_waits;
1411*92022041SSam Saccone wait_ev.prints = prints;
1412*92022041SSam Saccone wait_ev.n_prints = n_prints;
1413*92022041SSam Saccone wait_ev.pargs = args;
1414*92022041SSam Saccone register_handler(wait_event, &wait_ev);
1415*92022041SSam Saccone } else
1416*92022041SSam Saccone register_handler(print_event, args);
1417*92022041SSam Saccone
1418*92022041SSam Saccone wait_ev.cmd = 0;
1419*92022041SSam Saccone
1420*92022041SSam Saccone while (!wait_ev.cmd)
1421*92022041SSam Saccone nl_recvmsgs(state->nl_sock, cb);
1422*92022041SSam Saccone
1423*92022041SSam Saccone nl_cb_put(cb);
1424*92022041SSam Saccone
1425*92022041SSam Saccone return wait_ev.cmd;
1426*92022041SSam Saccone }
1427*92022041SSam Saccone
listen_events(struct nl80211_state * state,const int n_waits,const __u32 * waits)1428*92022041SSam Saccone __u32 listen_events(struct nl80211_state *state,
1429*92022041SSam Saccone const int n_waits, const __u32 *waits)
1430*92022041SSam Saccone {
1431*92022041SSam Saccone int ret;
1432*92022041SSam Saccone
1433*92022041SSam Saccone ret = __prepare_listen_events(state);
1434*92022041SSam Saccone if (ret)
1435*92022041SSam Saccone return ret;
1436*92022041SSam Saccone
1437*92022041SSam Saccone return __do_listen_events(state, n_waits, waits, 0, NULL, NULL);
1438*92022041SSam Saccone }
1439*92022041SSam Saccone
print_events(struct nl80211_state * state,struct nl_msg * msg,int argc,char ** argv,enum id_input id)1440*92022041SSam Saccone static int print_events(struct nl80211_state *state,
1441*92022041SSam Saccone struct nl_msg *msg,
1442*92022041SSam Saccone int argc, char **argv,
1443*92022041SSam Saccone enum id_input id)
1444*92022041SSam Saccone {
1445*92022041SSam Saccone struct print_event_args args;
1446*92022041SSam Saccone int num_time_formats = 0;
1447*92022041SSam Saccone int ret;
1448*92022041SSam Saccone
1449*92022041SSam Saccone memset(&args, 0, sizeof(args));
1450*92022041SSam Saccone
1451*92022041SSam Saccone argc--;
1452*92022041SSam Saccone argv++;
1453*92022041SSam Saccone
1454*92022041SSam Saccone while (argc > 0) {
1455*92022041SSam Saccone if (strcmp(argv[0], "-f") == 0)
1456*92022041SSam Saccone args.frame = true;
1457*92022041SSam Saccone else if (strcmp(argv[0], "-t") == 0) {
1458*92022041SSam Saccone num_time_formats++;
1459*92022041SSam Saccone args.time = true;
1460*92022041SSam Saccone } else if (strcmp(argv[0], "-T") == 0) {
1461*92022041SSam Saccone num_time_formats++;
1462*92022041SSam Saccone args.ctime = true;
1463*92022041SSam Saccone } else if (strcmp(argv[0], "-r") == 0) {
1464*92022041SSam Saccone num_time_formats++;
1465*92022041SSam Saccone args.reltime = true;
1466*92022041SSam Saccone } else
1467*92022041SSam Saccone return 1;
1468*92022041SSam Saccone argc--;
1469*92022041SSam Saccone argv++;
1470*92022041SSam Saccone }
1471*92022041SSam Saccone
1472*92022041SSam Saccone if (num_time_formats > 1)
1473*92022041SSam Saccone return 1;
1474*92022041SSam Saccone
1475*92022041SSam Saccone if (argc)
1476*92022041SSam Saccone return 1;
1477*92022041SSam Saccone
1478*92022041SSam Saccone ret = __prepare_listen_events(state);
1479*92022041SSam Saccone if (ret)
1480*92022041SSam Saccone return ret;
1481*92022041SSam Saccone
1482*92022041SSam Saccone return __do_listen_events(state, 0, NULL, 0, NULL, &args);
1483*92022041SSam Saccone }
1484*92022041SSam Saccone TOPLEVEL(event, "[-t|-T|-r] [-f]", 0, 0, CIB_NONE, print_events,
1485*92022041SSam Saccone "Monitor events from the kernel.\n"
1486*92022041SSam Saccone "-t - print timestamp\n"
1487*92022041SSam Saccone "-T - print absolute, human-readable timestamp\n"
1488*92022041SSam Saccone "-r - print relative timestamp\n"
1489*92022041SSam Saccone "-f - print full frame for auth/assoc etc.");
1490