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