scan.c revision 00889fb26e914c7485e1bae42f88259183728f78
13563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg#include <net/if.h>
23563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg#include <errno.h>
33563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg#include <string.h>
43563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg#include <ctype.h>
5764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg#include <stdbool.h>
63563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
73563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg#include <netlink/genl/genl.h>
83563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg#include <netlink/genl/family.h>
93563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg#include <netlink/genl/ctrl.h>
103563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg#include <netlink/msg.h>
113563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg#include <netlink/attr.h>
123563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
133563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg#include "nl80211.h"
143563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg#include "iw.h"
153563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
1692a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann#define WLAN_CAPABILITY_ESS		(1<<0)
1792a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann#define WLAN_CAPABILITY_IBSS		(1<<1)
1892a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann#define WLAN_CAPABILITY_CF_POLLABLE	(1<<2)
1992a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann#define WLAN_CAPABILITY_CF_POLL_REQUEST	(1<<3)
2092a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann#define WLAN_CAPABILITY_PRIVACY		(1<<4)
2192a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann#define WLAN_CAPABILITY_SHORT_PREAMBLE	(1<<5)
2292a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann#define WLAN_CAPABILITY_PBCC		(1<<6)
2392a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann#define WLAN_CAPABILITY_CHANNEL_AGILITY	(1<<7)
2492a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann#define WLAN_CAPABILITY_SPECTRUM_MGMT	(1<<8)
2592a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann#define WLAN_CAPABILITY_QOS		(1<<9)
2692a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann#define WLAN_CAPABILITY_SHORT_SLOT_TIME	(1<<10)
2792a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann#define WLAN_CAPABILITY_APSD		(1<<11)
282e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev#define WLAN_CAPABILITY_RADIO_MEASURE	(1<<12)
2992a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann#define WLAN_CAPABILITY_DSSS_OFDM	(1<<13)
302e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev#define WLAN_CAPABILITY_DEL_BACK	(1<<14)
312e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev#define WLAN_CAPABILITY_IMM_BACK	(1<<15)
322e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev/* DMG (60gHz) 802.11ad */
332e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev/* type - bits 0..1 */
342e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev#define WLAN_CAPABILITY_DMG_TYPE_MASK		(3<<0)
352e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev
362e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev#define WLAN_CAPABILITY_DMG_TYPE_IBSS		(1<<0) /* Tx by: STA */
372e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev#define WLAN_CAPABILITY_DMG_TYPE_PBSS		(2<<0) /* Tx by: PCP */
382e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev#define WLAN_CAPABILITY_DMG_TYPE_AP		(3<<0) /* Tx by: AP */
392e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev
402e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev#define WLAN_CAPABILITY_DMG_CBAP_ONLY		(1<<2)
412e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev#define WLAN_CAPABILITY_DMG_CBAP_SOURCE		(1<<3)
422e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev#define WLAN_CAPABILITY_DMG_PRIVACY		(1<<4)
432e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev#define WLAN_CAPABILITY_DMG_ECPAC		(1<<5)
442e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev
452e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev#define WLAN_CAPABILITY_DMG_SPECTRUM_MGMT	(1<<8)
462e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev#define WLAN_CAPABILITY_DMG_RADIO_MEASURE	(1<<12)
4792a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann
483bd60ef1276fc888fed699ee598b3b358d976f4cJohannes Bergstatic unsigned char ms_oui[3]		= { 0x00, 0x50, 0xf2 };
493bd60ef1276fc888fed699ee598b3b358d976f4cJohannes Bergstatic unsigned char ieee80211_oui[3]	= { 0x00, 0x0f, 0xac };
509a22374a56b394000cfb98acb649355f76beb3a3Johannes Bergstatic unsigned char wfa_oui[3]		= { 0x50, 0x6f, 0x9a };
51857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
52764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Bergstruct scan_params {
53764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg	bool unknown;
54febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	enum print_ie_type type;
55575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen	bool show_both_ie_sets;
56764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg};
57764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg
582b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez#define IEEE80211_COUNTRY_EXTENSION_ID 201
592b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
6072725719af644b0a3a673cc9f1c376a2c0ef62e2Johannes Bergunion ieee80211_country_ie_triplet {
6172725719af644b0a3a673cc9f1c376a2c0ef62e2Johannes Berg	struct {
6272725719af644b0a3a673cc9f1c376a2c0ef62e2Johannes Berg		__u8 first_channel;
6372725719af644b0a3a673cc9f1c376a2c0ef62e2Johannes Berg		__u8 num_channels;
6472725719af644b0a3a673cc9f1c376a2c0ef62e2Johannes Berg		__s8 max_power;
6572725719af644b0a3a673cc9f1c376a2c0ef62e2Johannes Berg	} __attribute__ ((packed)) chans;
6672725719af644b0a3a673cc9f1c376a2c0ef62e2Johannes Berg	struct {
6772725719af644b0a3a673cc9f1c376a2c0ef62e2Johannes Berg		__u8 reg_extension_id;
6872725719af644b0a3a673cc9f1c376a2c0ef62e2Johannes Berg		__u8 reg_class;
6972725719af644b0a3a673cc9f1c376a2c0ef62e2Johannes Berg		__u8 coverage_class;
7072725719af644b0a3a673cc9f1c376a2c0ef62e2Johannes Berg	} __attribute__ ((packed)) ext;
712b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez} __attribute__ ((packed));
722b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
737c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Bergstatic int handle_scan(struct nl80211_state *state,
747c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Berg		       struct nl_cb *cb,
753563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		       struct nl_msg *msg,
7605514f9581f66b12ac9ee0f21c770ceb34310e9dJohannes Berg		       int argc, char **argv,
7705514f9581f66b12ac9ee0f21c770ceb34310e9dJohannes Berg		       enum id_input id)
783563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
79559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	struct nl_msg *ssids = NULL, *freqs = NULL;
80559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	char *eptr;
813563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	int err = -ENOBUFS;
82559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	int i;
83559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	enum {
84559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		NONE,
85559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		FREQ,
8664797a7fd7c49d95abc8540490c76bf493699176Johannes Berg		IES,
87559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		SSID,
88559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		DONE,
89559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	} parse = NONE;
90559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	int freq;
91559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	bool passive = false, have_ssids = false, have_freqs = false;
9264797a7fd7c49d95abc8540490c76bf493699176Johannes Berg	size_t tmp;
9364797a7fd7c49d95abc8540490c76bf493699176Johannes Berg	unsigned char *ies;
94fe862239636c303372184abc5635097b43777e77Sam Leffler	int flags = 0;
953563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
963563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	ssids = nlmsg_alloc();
973563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	if (!ssids)
983563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		return -ENOMEM;
99559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg
100559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	freqs = nlmsg_alloc();
101559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	if (!freqs) {
102559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		nlmsg_free(ssids);
103559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		return -ENOMEM;
104559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	}
105559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg
106559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	for (i = 0; i < argc; i++) {
107559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		switch (parse) {
108559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		case NONE:
10964797a7fd7c49d95abc8540490c76bf493699176Johannes Berg			if (strcmp(argv[i], "freq") == 0) {
11064797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				parse = FREQ;
11164797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				have_freqs = true;
11264797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				break;
11364797a7fd7c49d95abc8540490c76bf493699176Johannes Berg			} else if (strcmp(argv[i], "ies") == 0) {
11464797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				parse = IES;
11564797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				break;
116fe862239636c303372184abc5635097b43777e77Sam Leffler			} else if (strcmp(argv[i], "lowpri") == 0) {
117fe862239636c303372184abc5635097b43777e77Sam Leffler				parse = NONE;
118fe862239636c303372184abc5635097b43777e77Sam Leffler				flags |= NL80211_SCAN_FLAG_LOW_PRIORITY;
119fe862239636c303372184abc5635097b43777e77Sam Leffler				break;
120fe862239636c303372184abc5635097b43777e77Sam Leffler			} else if (strcmp(argv[i], "flush") == 0) {
121fe862239636c303372184abc5635097b43777e77Sam Leffler				parse = NONE;
122fe862239636c303372184abc5635097b43777e77Sam Leffler				flags |= NL80211_SCAN_FLAG_FLUSH;
123fe862239636c303372184abc5635097b43777e77Sam Leffler				break;
124ced94d5f129e5d116b6a888f312deab081bb2231Antonio Quartulli			} else if (strcmp(argv[i], "ap-force") == 0) {
125ced94d5f129e5d116b6a888f312deab081bb2231Antonio Quartulli				parse = NONE;
126ced94d5f129e5d116b6a888f312deab081bb2231Antonio Quartulli				flags |= NL80211_SCAN_FLAG_AP;
127ced94d5f129e5d116b6a888f312deab081bb2231Antonio Quartulli				break;
12864797a7fd7c49d95abc8540490c76bf493699176Johannes Berg			} else if (strcmp(argv[i], "ssid") == 0) {
12964797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				parse = SSID;
13064797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				have_ssids = true;
13164797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				break;
13264797a7fd7c49d95abc8540490c76bf493699176Johannes Berg			} else if (strcmp(argv[i], "passive") == 0) {
13364797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				parse = DONE;
13464797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				passive = true;
13564797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				break;
13664797a7fd7c49d95abc8540490c76bf493699176Johannes Berg			}
137559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		case DONE:
138559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			return 1;
139559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		case FREQ:
140559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			freq = strtoul(argv[i], &eptr, 10);
141cc12e895302aa7dc82229f12b21e61c52fba80f6Johannes Berg			if (eptr != argv[i] + strlen(argv[i])) {
142cc12e895302aa7dc82229f12b21e61c52fba80f6Johannes Berg				/* failed to parse as number -- maybe a tag? */
143cc12e895302aa7dc82229f12b21e61c52fba80f6Johannes Berg				i--;
144cc12e895302aa7dc82229f12b21e61c52fba80f6Johannes Berg				parse = NONE;
145cc12e895302aa7dc82229f12b21e61c52fba80f6Johannes Berg				continue;
146cc12e895302aa7dc82229f12b21e61c52fba80f6Johannes Berg			}
147559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			NLA_PUT_U32(freqs, i, freq);
14864797a7fd7c49d95abc8540490c76bf493699176Johannes Berg			break;
14964797a7fd7c49d95abc8540490c76bf493699176Johannes Berg		case IES:
15064797a7fd7c49d95abc8540490c76bf493699176Johannes Berg			ies = parse_hex(argv[i], &tmp);
15164797a7fd7c49d95abc8540490c76bf493699176Johannes Berg			if (!ies)
15264797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				goto nla_put_failure;
15364797a7fd7c49d95abc8540490c76bf493699176Johannes Berg			NLA_PUT(msg, NL80211_ATTR_IE, tmp, ies);
15464797a7fd7c49d95abc8540490c76bf493699176Johannes Berg			free(ies);
15564797a7fd7c49d95abc8540490c76bf493699176Johannes Berg			parse = NONE;
156559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			break;
157559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		case SSID:
158559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			NLA_PUT(ssids, i, strlen(argv[i]), argv[i]);
159559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			break;
160559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		}
161559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	}
162559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg
163559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	if (!have_ssids)
164559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		NLA_PUT(ssids, 1, 0, "");
165559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	if (!passive)
166559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids);
167559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg
168559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	if (have_freqs)
169559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		nla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs);
170fe862239636c303372184abc5635097b43777e77Sam Leffler	if (flags)
171fe862239636c303372184abc5635097b43777e77Sam Leffler		NLA_PUT_U32(msg, NL80211_ATTR_SCAN_FLAGS, flags);
1723563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
1733563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	err = 0;
1743563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg nla_put_failure:
1753563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	nlmsg_free(ssids);
176559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	nlmsg_free(freqs);
1773563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	return err;
1783563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
1793563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
180857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmannstatic void tab_on_first(bool *first)
181857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann{
182857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	if (!*first)
183857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf("\t");
184857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	else
185857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		*first = false;
186857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann}
187857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
18883b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_ssid(const uint8_t type, uint8_t len, const uint8_t *data)
1893563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
19083b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	printf(" ");
191748f8489caad151e01922f0ba26847aedfd36dafJohannes Berg	print_ssid_escaped(len, data);
1923563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	printf("\n");
1933563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
1943563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
195ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg#define BSS_MEMBERSHIP_SELECTOR_VHT_PHY 126
1961fd19c397234b604a553b8156bd46baa88404aabChristian Lamparter#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127
1971fd19c397234b604a553b8156bd46baa88404aabChristian Lamparter
19883b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_supprates(const uint8_t type, uint8_t len, const uint8_t *data)
1993563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
2003563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	int i;
2013563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
20283b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	printf(" ");
2033563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
20483b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	for (i = 0; i < len; i++) {
2053563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		int r = data[i] & 0x7f;
2061fd19c397234b604a553b8156bd46baa88404aabChristian Lamparter
207ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg		if (r == BSS_MEMBERSHIP_SELECTOR_VHT_PHY && data[i] & 0x80)
208ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg			printf("VHT");
209ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg		else if (r == BSS_MEMBERSHIP_SELECTOR_HT_PHY && data[i] & 0x80)
2101fd19c397234b604a553b8156bd46baa88404aabChristian Lamparter			printf("HT");
2111fd19c397234b604a553b8156bd46baa88404aabChristian Lamparter		else
2121fd19c397234b604a553b8156bd46baa88404aabChristian Lamparter			printf("%d.%d", r/2, 5*(r&1));
2131fd19c397234b604a553b8156bd46baa88404aabChristian Lamparter
2141fd19c397234b604a553b8156bd46baa88404aabChristian Lamparter		printf("%s ", data[i] & 0x80 ? "*" : "");
2153563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	}
2163563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	printf("\n");
2173563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
2183563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
21983b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_ds(const uint8_t type, uint8_t len, const uint8_t *data)
2203563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
22183b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	printf(" channel %d\n", data[0]);
2223563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
2233563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
2242b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguezstatic const char *country_env_str(char environment)
225b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann{
2262b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez	switch (environment) {
227b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann	case 'I':
2282b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		return "Indoor only";
229b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann	case 'O':
2302b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		return "Outdoor only";
231b6c0d6340dbc969b4c53f583775e7c49b440c403Johannes Berg	case ' ':
2322b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		return "Indoor/Outdoor";
233b6c0d6340dbc969b4c53f583775e7c49b440c403Johannes Berg	default:
2342b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		return "bogus";
235b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann	}
2362b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez}
2372b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
2382b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguezstatic void print_country(const uint8_t type, uint8_t len, const uint8_t *data)
2392b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez{
2402b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez	printf(" %.*s", 2, data);
2412b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
2422b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez	printf("\tEnvironment: %s\n", country_env_str(data[2]));
2432b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
2442b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez	data += 3;
2452b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez	len -= 3;
2462b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
2472b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez	if (len < 3) {
2482b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		printf("\t\tNo country IE triplets present\n");
2492b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		return;
2502b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez	}
2512b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
2522b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez	while (len >= 3) {
2532b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		int end_channel;
25472725719af644b0a3a673cc9f1c376a2c0ef62e2Johannes Berg		union ieee80211_country_ie_triplet *triplet = (void *) data;
2552b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
2562b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		if (triplet->ext.reg_extension_id >= IEEE80211_COUNTRY_EXTENSION_ID) {
2572b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez			printf("\t\tExtension ID: %d Regulatory Class: %d Coverage class: %d (up to %dm)\n",
2582b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez			       triplet->ext.reg_extension_id,
2592b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez			       triplet->ext.reg_class,
2602b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez			       triplet->ext.coverage_class,
2612b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez			       triplet->ext.coverage_class * 450);
2622b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
2632b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez			data += 3;
2642b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez			len -= 3;
2652b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez			continue;
2662b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		}
2672b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
2682b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		/* 2 GHz */
2692b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		if (triplet->chans.first_channel <= 14)
2702b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez			end_channel = triplet->chans.first_channel + (triplet->chans.num_channels - 1);
2712b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		else
2722b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez			end_channel =  triplet->chans.first_channel + (4 * (triplet->chans.num_channels - 1));
2732b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
274a9859d30ea1c19314d2d08285af9123714a4e6beLuis R. Rodriguez		printf("\t\tChannels [%d - %d] @ %d dBm\n", triplet->chans.first_channel, end_channel, triplet->chans.max_power);
2752b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
2762b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		data += 3;
2772b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		len -= 3;
2782b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez	}
2792b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
2802b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez	return;
281b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann}
282b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann
283d1563a1b2d6e43fb12aeaa764c952cd2108b6862Marcel Holtmannstatic void print_powerconstraint(const uint8_t type, uint8_t len, const uint8_t *data)
284d1563a1b2d6e43fb12aeaa764c952cd2108b6862Marcel Holtmann{
285d1563a1b2d6e43fb12aeaa764c952cd2108b6862Marcel Holtmann	printf(" %d dB\n", data[0]);
286d1563a1b2d6e43fb12aeaa764c952cd2108b6862Marcel Holtmann}
287d1563a1b2d6e43fb12aeaa764c952cd2108b6862Marcel Holtmann
28883b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_erp(const uint8_t type, uint8_t len, const uint8_t *data)
289fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann{
290fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann	if (data[0] == 0x00)
29183b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		printf(" <no flags>");
292fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann	if (data[0] & 0x01)
293fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann		printf(" NonERP_Present");
294fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann	if (data[0] & 0x02)
295fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann		printf(" Use_Protection");
296fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann	if (data[0] & 0x04)
297fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann		printf(" Barker_Preamble_Mode");
298fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann	printf("\n");
299fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann}
300fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann
30183b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_cipher(const uint8_t *data)
302857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann{
3033bd60ef1276fc888fed699ee598b3b358d976f4cJohannes Berg	if (memcmp(data, ms_oui, 3) == 0) {
304857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		switch (data[3]) {
305510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 0:
306857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("Use group cipher suite");
307857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
308510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 1:
309857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("WEP-40");
310857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
311510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 2:
312857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("TKIP");
313857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
314510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 4:
315857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("CCMP");
316857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
317510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 5:
318857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("WEP-104");
319857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
320857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		default:
321332769c689e75f372bdae8ade290433b31eebc3eJohannes Berg			printf("%.02x-%.02x-%.02x:%d",
3225594fd2301775e7795899ed4ed3b8fff82551734Johannes Berg				data[0], data[1] ,data[2], data[3]);
323857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
324857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		}
325857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	} else if (memcmp(data, ieee80211_oui, 3) == 0) {
326857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		switch (data[3]) {
327510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 0:
328857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("Use group cipher suite");
329857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
330510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 1:
331857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("WEP-40");
332857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
333510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 2:
334857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("TKIP");
335857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
336510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 4:
337857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("CCMP");
338857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
339510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 5:
340857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("WEP-104");
341857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
342510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 6:
343857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("AES-128-CMAC");
344857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
345a8b3da9df8d15b857b13887feccdd05c46c7347eVladimir Kondratiev		case 8:
346a8b3da9df8d15b857b13887feccdd05c46c7347eVladimir Kondratiev			printf("GCMP");
347a8b3da9df8d15b857b13887feccdd05c46c7347eVladimir Kondratiev			break;
348857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		default:
349332769c689e75f372bdae8ade290433b31eebc3eJohannes Berg			printf("%.02x-%.02x-%.02x:%d",
3505594fd2301775e7795899ed4ed3b8fff82551734Johannes Berg				data[0], data[1] ,data[2], data[3]);
351857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
352857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		}
353857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	} else
354332769c689e75f372bdae8ade290433b31eebc3eJohannes Berg		printf("%.02x-%.02x-%.02x:%d",
3555594fd2301775e7795899ed4ed3b8fff82551734Johannes Berg			data[0], data[1] ,data[2], data[3]);
356857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann}
357857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
35883b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_auth(const uint8_t *data)
359857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann{
3603bd60ef1276fc888fed699ee598b3b358d976f4cJohannes Berg	if (memcmp(data, ms_oui, 3) == 0) {
361857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		switch (data[3]) {
362510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 1:
363857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("IEEE 802.1X");
364857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
365510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 2:
366857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("PSK");
367857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
368857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		default:
369332769c689e75f372bdae8ade290433b31eebc3eJohannes Berg			printf("%.02x-%.02x-%.02x:%d",
3705594fd2301775e7795899ed4ed3b8fff82551734Johannes Berg				data[0], data[1] ,data[2], data[3]);
371857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
372857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		}
373857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	} else if (memcmp(data, ieee80211_oui, 3) == 0) {
374857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		switch (data[3]) {
375510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 1:
376857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("IEEE 802.1X");
377857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
378510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 2:
379857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("PSK");
380857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
3810fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg		case 3:
3820fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			printf("FT/IEEE 802.1X");
3830fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			break;
3840fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg		case 4:
3850fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			printf("FT/PSK");
3860fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			break;
3870fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg		case 5:
3880fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			printf("IEEE 802.1X/SHA-256");
3890fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			break;
3900fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg		case 6:
3910fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			printf("PSK/SHA-256");
3920fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			break;
393857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		default:
394332769c689e75f372bdae8ade290433b31eebc3eJohannes Berg			printf("%.02x-%.02x-%.02x:%d",
3955594fd2301775e7795899ed4ed3b8fff82551734Johannes Berg				data[0], data[1] ,data[2], data[3]);
396857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
397857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		}
398857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	} else
399332769c689e75f372bdae8ade290433b31eebc3eJohannes Berg		printf("%.02x-%.02x-%.02x:%d",
4005594fd2301775e7795899ed4ed3b8fff82551734Johannes Berg			data[0], data[1] ,data[2], data[3]);
401857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann}
402857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
40383b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_rsn_ie(const char *defcipher, const char *defauth,
40483b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			 uint8_t len, const uint8_t *data)
405857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann{
406857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	bool first = true;
407857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	__u16 version, count, capa;
408857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	int i;
409857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
410857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	version = data[0] + (data[1] << 8);
411857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	tab_on_first(&first);
412857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	printf("\t * Version: %d\n", version);
413857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
414857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	data += 2;
415857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	len -= 2;
416857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
417857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	if (len < 4) {
418857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		tab_on_first(&first);
419857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf("\t * Group cipher: %s\n", defcipher);
420857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf("\t * Pairwise ciphers: %s\n", defcipher);
421857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		return;
422857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	}
423857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
424857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	tab_on_first(&first);
425857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	printf("\t * Group cipher: ");
426857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	print_cipher(data);
427857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	printf("\n");
428857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
429857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	data += 4;
430857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	len -= 4;
431857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
432857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	if (len < 2) {
433857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		tab_on_first(&first);
434857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf("\t * Pairwise ciphers: %s\n", defcipher);
435857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		return;
436857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	}
437857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
438857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	count = data[0] | (data[1] << 8);
43931d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann	if (2 + (count * 4) > len)
44031d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann		goto invalid;
44131d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann
442857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	tab_on_first(&first);
443857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	printf("\t * Pairwise ciphers:");
44431d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann	for (i = 0; i < count; i++) {
445857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf(" ");
446857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		print_cipher(data + 2 + (i * 4));
447857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	}
448857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	printf("\n");
449857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
450857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	data += 2 + (count * 4);
451857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	len -= 2 + (count * 4);
452857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
453857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	if (len < 2) {
454857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		tab_on_first(&first);
455857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf("\t * Authentication suites: %s\n", defauth);
456857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		return;
457857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	}
458857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
459857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	count = data[0] | (data[1] << 8);
46031d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann	if (2 + (count * 4) > len)
46131d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann		goto invalid;
46231d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann
463857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	tab_on_first(&first);
464857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	printf("\t * Authentication suites:");
46583b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	for (i = 0; i < count; i++) {
466857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf(" ");
467857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		print_auth(data + 2 + (i * 4));
468857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	}
469857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	printf("\n");
470857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
471857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	data += 2 + (count * 4);
472857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	len -= 2 + (count * 4);
473857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
4746a4f24e80e5e6d85bfd1c4d66b476b86e5fa35d3Johannes Berg	if (len >= 2) {
4756a4f24e80e5e6d85bfd1c4d66b476b86e5fa35d3Johannes Berg		capa = data[0] | (data[1] << 8);
4766a4f24e80e5e6d85bfd1c4d66b476b86e5fa35d3Johannes Berg		tab_on_first(&first);
477cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		printf("\t * Capabilities:");
478cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		if (capa & 0x0001)
479cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" PreAuth");
480cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		if (capa & 0x0002)
481cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" NoPairwise");
482cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		switch ((capa & 0x000c) >> 2) {
483cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 0:
484cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
485cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 1:
486cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" 2-PTKSA-RC");
487cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
488cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 2:
489cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" 4-PTKSA-RC");
490cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
491cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 3:
492cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" 16-PTKSA-RC");
493cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
494cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		}
495cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		switch ((capa & 0x0030) >> 4) {
496cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 0:
497cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
498cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 1:
499cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" 2-GTKSA-RC");
500cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
501cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 2:
502cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" 4-GTKSA-RC");
503cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
504cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 3:
505cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" 16-GTKSA-RC");
506cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
507cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		}
508cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		if (capa & 0x0040)
509cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" MFP-required");
510cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		if (capa & 0x0080)
511cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" MFP-capable");
512cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		if (capa & 0x0200)
513cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" Peerkey-enabled");
514cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		if (capa & 0x0400)
515cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" SPP-AMSDU-capable");
516cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		if (capa & 0x0800)
517cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" SPP-AMSDU-required");
518cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		printf(" (0x%.4x)\n", capa);
5196a4f24e80e5e6d85bfd1c4d66b476b86e5fa35d3Johannes Berg		data += 2;
5206a4f24e80e5e6d85bfd1c4d66b476b86e5fa35d3Johannes Berg		len -= 2;
5216a4f24e80e5e6d85bfd1c4d66b476b86e5fa35d3Johannes Berg	}
52231d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann
5235ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg	if (len >= 2) {
5245ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg		int pmkid_count = data[0] | (data[1] << 8);
5255ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg
5265ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg		if (len >= 2 + 16 * pmkid_count) {
5275ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg			tab_on_first(&first);
5285ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg			printf("\t * %d PMKIDs\n", pmkid_count);
5295ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg			/* not printing PMKID values */
5305ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg			data += 2 + 16 * pmkid_count;
5315ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg			len -= 2 + 16 * pmkid_count;
5325ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg		} else
5335ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg			goto invalid;
5345ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg	}
5355ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg
5365ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg	if (len >= 4) {
5375ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg		tab_on_first(&first);
5385ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg		printf("\t * Group mgmt cipher suite: ");
5395ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg		print_cipher(data);
5405ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg		printf("\n");
5415ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg		data += 4;
5425ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg		len -= 4;
5435ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg	}
5445ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg
545cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg invalid:
54631d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann	if (len != 0) {
54731d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann		printf("\t\t * bogus tail data (%d):", len);
54831d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann		while (len) {
54931d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann			printf(" %.2x", *data);
55031d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann			data++;
55131d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann			len--;
55231d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann		}
55331d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann		printf("\n");
55431d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann	}
555857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann}
556857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
55783b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_rsn(const uint8_t type, uint8_t len, const uint8_t *data)
558857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann{
55983b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	print_rsn_ie("CCMP", "IEEE 802.1X", len, data);
560857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann}
561857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
5620c445c24c51e634af042fd10aa87e558a53699daLuis R. Rodriguezstatic void print_ht_capa(const uint8_t type, uint8_t len, const uint8_t *data)
5630c445c24c51e634af042fd10aa87e558a53699daLuis R. Rodriguez{
564357c1a5df13f722027977a915cfd16a38bba3966Luis R. Rodriguez	printf("\n");
5657ddfb67953809357249e5a6f4293cebf59a4ad9bJohannes Berg	print_ht_capability(data[0] | (data[1] << 8));
5667ddfb67953809357249e5a6f4293cebf59a4ad9bJohannes Berg	print_ampdu_length(data[2] & 3);
567c79c746440d22401d0aa8522bed2820f60eed2cdChristian Lamparter	print_ampdu_spacing((data[2] >> 2) & 7);
5687ddfb67953809357249e5a6f4293cebf59a4ad9bJohannes Berg	print_ht_mcs(data + 3);
5690c445c24c51e634af042fd10aa87e558a53699daLuis R. Rodriguez}
5700c445c24c51e634af042fd10aa87e558a53699daLuis R. Rodriguez
57129f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Bergstatic const char *ht_secondary_offset[4] = {
57229f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	"no secondary",
57329f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	"above",
57429f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	"[reserved!]",
57529f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	"below",
57629f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg};
57729f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg
578be7602fb865fcef72924c926729650c0db9cf254Johannes Bergstatic void print_ht_op(const uint8_t type, uint8_t len, const uint8_t *data)
579be7602fb865fcef72924c926729650c0db9cf254Johannes Berg{
580be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	static const char *protection[4] = {
581be7602fb865fcef72924c926729650c0db9cf254Johannes Berg		"no",
582be7602fb865fcef72924c926729650c0db9cf254Johannes Berg		"nonmember",
583be7602fb865fcef72924c926729650c0db9cf254Johannes Berg		"20 MHz",
584be7602fb865fcef72924c926729650c0db9cf254Johannes Berg		"non-HT mixed",
585be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	};
586be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	static const char *sta_chan_width[2] = {
587be7602fb865fcef72924c926729650c0db9cf254Johannes Berg		"20 MHz",
588be7602fb865fcef72924c926729650c0db9cf254Johannes Berg		"any",
589be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	};
590be7602fb865fcef72924c926729650c0db9cf254Johannes Berg
591be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\n");
592be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * primary channel: %d\n", data[0]);
593be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * secondary channel offset: %s\n",
59429f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg		ht_secondary_offset[data[1] & 0x3]);
595be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * STA channel width: %s\n", sta_chan_width[(data[1] & 0x4)>>2]);
596be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * RIFS: %d\n", (data[1] & 0x8)>>3);
597be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * HT protection: %s\n", protection[data[2] & 0x3]);
598be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * non-GF present: %d\n", (data[2] & 0x4) >> 2);
599be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * OBSS non-GF present: %d\n", (data[2] & 0x10) >> 4);
600be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * dual beacon: %d\n", (data[4] & 0x40) >> 6);
601be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * dual CTS protection: %d\n", (data[4] & 0x80) >> 7);
602be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * STBC beacon: %d\n", data[5] & 0x1);
603be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * L-SIG TXOP Prot: %d\n", (data[5] & 0x2) >> 1);
604be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * PCO active: %d\n", (data[5] & 0x4) >> 2);
605be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * PCO phase: %d\n", (data[5] & 0x8) >> 3);
606be7602fb865fcef72924c926729650c0db9cf254Johannes Berg}
607be7602fb865fcef72924c926729650c0db9cf254Johannes Berg
60883b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_capabilities(const uint8_t type, uint8_t len, const uint8_t *data)
6099b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann{
61031d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg	int i, base, bit;
61131d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg	bool first = true;
61231d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg
61331d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg
61431d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg	for (i = 0; i < len; i++) {
61531d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg		base = i * 8;
61631d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg
61731d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg		for (bit = 0; bit < 8; bit++) {
61831d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			if (!(data[i] & (1 << bit)))
61931d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				continue;
62031d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg
62131d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			if (!first)
62231d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				printf(",");
62331d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			else
62431d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				first = false;
62531d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg
62670c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg#define CAPA(bit, name)		case bit: printf(" " name); break
62770c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg
62831d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			switch (bit + base) {
62970c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(0, "HT Information Exchange Supported");
63070c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(1, "reserved (On-demand Beacon)");
63170c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(2, "Extended Channel Switching");
63270c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(3, "reserved (Wave Indication)");
63370c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(4, "PSMP Capability");
63470c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(5, "reserved (Service Interval Granularity)");
63570c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(6, "S-PSMP Capability");
63670c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(7, "Event");
63770c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(8, "Diagnostics");
63870c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(9, "Multicast Diagnostics");
63970c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(10, "Location Tracking");
64070c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(11, "FMS");
64170c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(12, "Proxy ARP Service");
64270c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(13, "Collocated Interference Reporting");
64370c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(14, "Civic Location");
64470c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(15, "Geospatial Location");
64570c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(16, "TFS");
64670c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(17, "WNM-Sleep Mode");
64770c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(18, "TIM Broadcast");
64870c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(19, "BSS Transition");
64970c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(20, "QoS Traffic Capability");
65070c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(21, "AC Station Count");
65170c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(22, "Multiple BSSID");
65270c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(23, "Timing Measurement");
65370c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(24, "Channel Usage");
65470c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(25, "SSID List");
65570c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(26, "DMS");
65670c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(27, "UTC TSF Offset");
65770c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(28, "TDLS Peer U-APSD Buffer STA Support");
65870c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(29, "TDLS Peer PSM Support");
65970c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(30, "TDLS channel switching");
66070c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(31, "Interworking");
66170c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(32, "QoS Map");
66270c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(33, "EBR");
66370c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(34, "SSPN Interface");
66470c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(35, "Reserved");
66570c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(36, "MSGCF Capability");
66670c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(37, "TDLS Support");
66770c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(38, "TDLS Prohibited");
66870c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(39, "TDLS Channel Switching Prohibited");
66970c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(40, "Reject Unadmitted Frame");
67070c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(44, "Identifier Location");
67170c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(45, "U-APSD Coexistence");
67270c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(46, "WNM-Notification");
67370c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(47, "Reserved");
67470c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(48, "UTF-8 SSID");
67531d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			default:
67631d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				printf(" %d", bit);
67731d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				break;
67831d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			}
67970c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg#undef CAPA
68031d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg		}
68131d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg	}
6829b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann
6839b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann	printf("\n");
6849b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann}
6859b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann
686575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinenstatic void print_tim(const uint8_t type, uint8_t len, const uint8_t *data)
687575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen{
688575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen	printf(" DTIM Count %u DTIM Period %u Bitmap Control 0x%x "
689575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen	       "Bitmap[0] 0x%x",
690575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen	       data[0], data[1], data[2], data[3]);
691575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen	if (len - 4)
692575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen		printf(" (+ %u octet%s)", len - 4, len - 4 == 1 ? "" : "s");
693575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen	printf("\n");
694575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen}
695575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen
69654eb1613e695d72a71d7210b238a30e0ab2d5a3fJohannes Bergstatic void print_vht_capa(const uint8_t type, uint8_t len, const uint8_t *data)
69754eb1613e695d72a71d7210b238a30e0ab2d5a3fJohannes Berg{
69854eb1613e695d72a71d7210b238a30e0ab2d5a3fJohannes Berg	printf("\n");
69954eb1613e695d72a71d7210b238a30e0ab2d5a3fJohannes Berg	print_vht_info(data[0] | (data[1] << 8) |
70054eb1613e695d72a71d7210b238a30e0ab2d5a3fJohannes Berg		       (data[2] << 16) | (data[3] << 24),
70154eb1613e695d72a71d7210b238a30e0ab2d5a3fJohannes Berg		       data + 4);
70254eb1613e695d72a71d7210b238a30e0ab2d5a3fJohannes Berg}
70354eb1613e695d72a71d7210b238a30e0ab2d5a3fJohannes Berg
704ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Bergstatic void print_vht_oper(const uint8_t type, uint8_t len, const uint8_t *data)
705ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg{
706ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg	const char *chandwidths[] = {
707ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg		[0] = "20 or 40 MHz",
708ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg		[1] = "80 MHz",
709ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg		[3] = "80+80 MHz",
710ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg		[2] = "160 MHz",
711ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg	};
712ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg
713ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg	printf("\n");
714ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg	printf("\t\t * channel width: %d (%s)\n", data[0],
715ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg		data[0] < ARRAY_SIZE(chandwidths) ? chandwidths[data[0]] : "unknown");
716ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg	printf("\t\t * center freq segment 1: %d\n", data[1]);
717ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg	printf("\t\t * center freq segment 2: %d\n", data[2]);
718ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg	printf("\t\t * VHT basic MCS set: 0x%.2x%.2x\n", data[4], data[3]);
719ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg}
720ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg
72129f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Bergstatic void print_obss_scan_params(const uint8_t type, uint8_t len, const uint8_t *data)
72229f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg{
72329f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\n");
72429f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\t\t * passive dwell: %d TUs\n", (data[1] << 8) | data[0]);
72529f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\t\t * active dwell: %d TUs\n", (data[3] << 8) | data[2]);
72629f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\t\t * channel width trigger scan interval: %d s\n", (data[5] << 8) | data[4]);
72729f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\t\t * scan passive total per channel: %d TUs\n", (data[7] << 8) | data[6]);
72829f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\t\t * scan active total per channel: %d TUs\n", (data[9] << 8) | data[8]);
72929f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\t\t * BSS width channel transition delay factor: %d\n", (data[11] << 8) | data[10]);
73029f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\t\t * OBSS Scan Activity Threshold: %d.%02d %%\n",
73129f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg		((data[13] << 8) | data[12]) / 100, ((data[13] << 8) | data[12]) % 100);
73229f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg}
73329f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg
73429f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Bergstatic void print_secchan_offs(const uint8_t type, uint8_t len, const uint8_t *data)
73529f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg{
73629f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	if (data[0] < ARRAY_SIZE(ht_secondary_offset))
73729f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg		printf(" %s (%d)\n", ht_secondary_offset[data[0]], data[0]);
73829f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	else
73929f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg		printf(" %d\n", data[0]);
74029f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg}
74129f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg
74229f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Bergstatic void print_bss_load(const uint8_t type, uint8_t len, const uint8_t *data)
74329f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg{
74429f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\n");
74529f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\t\t * station count: %d\n", (data[1] << 8) | data[0]);
74629f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\t\t * channel utilisation: %d/255\n", data[2]);
74729f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\t\t * available admission capacity: %d [*32us]\n", (data[4] << 8) | data[3]);
74829f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg}
74929f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg
75083b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstruct ie_print {
75183b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	const char *name;
75283b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	void (*print)(const uint8_t type, uint8_t len, const uint8_t *data);
75383b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	uint8_t minlen, maxlen;
754febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	uint8_t flags;
755764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg};
756764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg
75783b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_ie(const struct ie_print *p, const uint8_t type,
75883b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		     uint8_t len, const uint8_t *data)
7594673a894dae2780e395204eab01af4d40220b9f5Johannes Berg{
76083b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	int i;
76183b4934c612b84c28a656d496bea056e37fccb99Johannes Berg
76283b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	if (!p->print)
76383b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		return;
76483b4934c612b84c28a656d496bea056e37fccb99Johannes Berg
76583b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	printf("\t%s:", p->name);
76683b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	if (len < p->minlen || len > p->maxlen) {
76783b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		if (len > 1) {
76883b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			printf(" <invalid: %d bytes:", len);
76983b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			for (i = 0; i < len; i++)
77083b4934c612b84c28a656d496bea056e37fccb99Johannes Berg				printf(" %.02x", data[i]);
77183b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			printf(">\n");
77283b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		} else if (len)
77383b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			printf(" <invalid: 1 byte: %.02x>\n", data[0]);
77483b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		else
77583b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			printf(" <invalid: no data>\n");
77683b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		return;
77783b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	}
77883b4934c612b84c28a656d496bea056e37fccb99Johannes Berg
77983b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	p->print(type, len, data);
78083b4934c612b84c28a656d496bea056e37fccb99Johannes Berg}
78183b4934c612b84c28a656d496bea056e37fccb99Johannes Berg
78283b4934c612b84c28a656d496bea056e37fccb99Johannes Berg#define PRINT_IGN {		\
78383b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	.name = "IGNORE",	\
78483b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	.print = NULL,		\
78583b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	.minlen = 0,		\
78683b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	.maxlen = 255,		\
7874673a894dae2780e395204eab01af4d40220b9f5Johannes Berg}
7884673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
78983b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic const struct ie_print ieprinters[] = {
790febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[0] = { "SSID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), },
791febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[1] = { "Supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), },
792014d581a9292b35d54e76793ec216ba15c2ec69cJohannes Berg	[3] = { "DS Parameter set", print_ds, 1, 1, BIT(PRINT_SCAN), },
793575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen	[5] = { "TIM", print_tim, 4, 255, BIT(PRINT_SCAN), },
794febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[7] = { "Country", print_country, 3, 255, BIT(PRINT_SCAN), },
79529f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	[11] = { "BSS Load", print_bss_load, 5, 5, BIT(PRINT_SCAN), },
796febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[32] = { "Power constraint", print_powerconstraint, 1, 1, BIT(PRINT_SCAN), },
797febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[42] = { "ERP", print_erp, 1, 255, BIT(PRINT_SCAN), },
798a2e61861abd4037ab29ddf4382c5d2f925c1be66Johannes Berg	[45] = { "HT capabilities", print_ht_capa, 26, 26, BIT(PRINT_SCAN), },
79929f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	[74] = { "Overlapping BSS scan params", print_obss_scan_params, 14, 255, BIT(PRINT_SCAN), },
800be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	[61] = { "HT operation", print_ht_op, 22, 22, BIT(PRINT_SCAN), },
80129f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	[62] = { "Secondary Channel Offset", print_secchan_offs, 1, 1, BIT(PRINT_SCAN), },
80254eb1613e695d72a71d7210b238a30e0ab2d5a3fJohannes Berg	[191] = { "VHT capabilities", print_vht_capa, 12, 255, BIT(PRINT_SCAN), },
803ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg	[192] = { "VHT operation", print_vht_oper, 5, 255, BIT(PRINT_SCAN), },
804febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[48] = { "RSN", print_rsn, 2, 255, BIT(PRINT_SCAN), },
805febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[50] = { "Extended supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), },
806720583e9a9fce9b760b8794118e7a5d54cb428f5Chun-Yeow Yeoh	[114] = { "MESH ID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), },
807febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[127] = { "Extended capabilities", print_capabilities, 0, 255, BIT(PRINT_SCAN), },
80883b4934c612b84c28a656d496bea056e37fccb99Johannes Berg};
80983b4934c612b84c28a656d496bea056e37fccb99Johannes Berg
81083b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_wifi_wpa(const uint8_t type, uint8_t len, const uint8_t *data)
81183b4934c612b84c28a656d496bea056e37fccb99Johannes Berg{
81283b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	print_rsn_ie("TKIP", "IEEE 802.1X", len, data);
81383b4934c612b84c28a656d496bea056e37fccb99Johannes Berg}
81483b4934c612b84c28a656d496bea056e37fccb99Johannes Berg
8151cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Bergstatic bool print_wifi_wmm_param(const uint8_t *data, uint8_t len)
8161cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg{
8171cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	int i;
8181cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	static const char *aci_tbl[] = { "BE", "BK", "VI", "VO" };
8191cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg
8201cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	if (len < 19)
8211cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg		goto invalid;
8221cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg
8231cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	if (data[0] != 1) {
824cee4fe2039a01208fbbae45dda1c7d3bbfbe5f36Johannes Berg		printf("Parameter: not version 1: ");
8251cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg		return false;
8261cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	}
8271cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg
82889ea706f0a177ff6e78b207bc08143d2d149dd08Marcel Holtmann	printf("\t * Parameter version 1");
8291cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg
8301cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	data++;
8311cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg
8321cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	if (data[0] & 0x80)
83389ea706f0a177ff6e78b207bc08143d2d149dd08Marcel Holtmann		printf("\n\t\t * u-APSD");
8341cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg
8351cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	data += 2;
8361cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg
8371cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	for (i = 0; i < 4; i++) {
83889ea706f0a177ff6e78b207bc08143d2d149dd08Marcel Holtmann		printf("\n\t\t * %s:", aci_tbl[(data[0] >> 5) & 3]);
83987181516675a6d6a2ce0d6ce53b4ba601b62d427Yoni Divinsky		if (data[0] & 0x10)
8401cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg			printf(" acm");
8411cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg		printf(" CW %d-%d", (1 << (data[1] & 0xf)) - 1,
8421cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg				    (1 << (data[1] >> 4)) - 1);
843a2a4c265af2e322e245b4fc1962d93a38da61f7aJohannes Berg		printf(", AIFSN %d", data[0] & 0xf);
8441cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg		if (data[2] | data[3])
845cee4fe2039a01208fbbae45dda1c7d3bbfbe5f36Johannes Berg			printf(", TXOP %d usec", (data[2] + (data[3] << 8)) * 32);
8461cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg		data += 4;
8471cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	}
8481cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg
8491cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	printf("\n");
8501cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	return true;
8511cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg
8521cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg invalid:
8531cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg 	printf("invalid: ");
8541cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg 	return false;
8551cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg}
8561cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg
85783b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_wifi_wmm(const uint8_t type, uint8_t len, const uint8_t *data)
8586ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann{
8596ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann	int i;
8606ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann
8616ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann	switch (data[0]) {
8626ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann	case 0x00:
86383b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		printf(" information:");
8646ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann		break;
8656ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann	case 0x01:
8661cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg		if (print_wifi_wmm_param(data + 1, len - 1))
8671cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg			return;
8686ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann		break;
8696ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann	default:
87083b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		printf(" type %d:", data[0]);
8716ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann		break;
8726ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann	}
8736ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann
8741cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	for(i = 1; i < len; i++)
8751cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg		printf(" %.02x", data[i]);
8766ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann	printf("\n");
8776ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann}
8786ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann
879a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinenstatic const char * wifi_wps_dev_passwd_id(uint16_t id)
880a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen{
881a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen	switch (id) {
882a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen	case 0:
883a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		return "Default (PIN)";
884a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen	case 1:
885a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		return "User-specified";
886a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen	case 2:
887a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		return "Machine-specified";
888a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen	case 3:
889a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		return "Rekey";
890a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen	case 4:
891a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		return "PushButton";
892a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen	case 5:
893a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		return "Registrar-specified";
894a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen	default:
895a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		return "??";
896a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen	}
897a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen}
898a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen
89983b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_wifi_wps(const uint8_t type, uint8_t len, const uint8_t *data)
9004673a894dae2780e395204eab01af4d40220b9f5Johannes Berg{
9014673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	bool first = true;
9024673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	__u16 subtype, sublen;
9034673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
9044673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	while (len >= 4) {
9054673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		subtype = (data[0] << 8) + data[1];
9064673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		sublen = (data[2] << 8) + data[3];
9074673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		if (sublen > len)
9084673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			break;
9094673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
9104673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		switch (subtype) {
9114673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		case 0x104a:
9124673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			tab_on_first(&first);
913dffc6750fec6d97a4fc55a687836cd6437be76e2Johannes Berg			printf("\t * Version: %d.%d\n", data[4] >> 4, data[4] & 0xF);
9144673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			break;
9154673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		case 0x1011:
9164673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			tab_on_first(&first);
9174673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf("\t * Device name: %.*s\n", sublen, data + 4);
9184673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			break;
919a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		case 0x1012: {
920a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			uint16_t id;
921a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			tab_on_first(&first);
922a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			if (sublen != 2) {
923a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen				printf("\t * Device Password ID: (invalid "
924a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen				       "length %d)\n", sublen);
925a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen				break;
926a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			}
927a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			id = data[4] << 8 | data[5];
928a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			printf("\t * Device Password ID: %u (%s)\n",
929a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			       id, wifi_wps_dev_passwd_id(id));
930a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			break;
931a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		}
9324673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		case 0x1021:
9334673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			tab_on_first(&first);
9344673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf("\t * Manufacturer: %.*s\n", sublen, data + 4);
9354673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			break;
9364673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		case 0x1023:
9374673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			tab_on_first(&first);
9384673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf("\t * Model: %.*s\n", sublen, data + 4);
9394673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			break;
940a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		case 0x1024:
941a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			tab_on_first(&first);
942a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			printf("\t * Model Number: %.*s\n", sublen, data + 4);
943a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			break;
944a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		case 0x103b: {
945a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			__u8 val = data[4];
946a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			tab_on_first(&first);
947a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			printf("\t * Response Type: %d%s\n",
948a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			       val, val == 3 ? " (AP)" : "");
949a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			break;
950a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		}
951a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		case 0x103c: {
952a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			__u8 val = data[4];
953a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			tab_on_first(&first);
954a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			printf("\t * RF Bands: 0x%x\n", val);
955a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			break;
956a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		}
957a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		case 0x1041: {
958a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			__u8 val = data[4];
959a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			tab_on_first(&first);
960a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			printf("\t * Selected Registrar: 0x%x\n", val);
961a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			break;
962a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		}
963a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		case 0x1042:
964a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			tab_on_first(&first);
965a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			printf("\t * Serial Number: %.*s\n", sublen, data + 4);
966a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			break;
967a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		case 0x1044: {
968a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			__u8 val = data[4];
969a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			tab_on_first(&first);
970a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			printf("\t * Wi-Fi Protected Setup State: %d%s%s\n",
971a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			       val,
972a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			       val == 1 ? " (Unconfigured)" : "",
973a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			       val == 2 ? " (Configured)" : "");
974a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			break;
975a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		}
97609fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg		case 0x1047:
97709fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg			tab_on_first(&first);
97809fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg			printf("\t * UUID: ");
97909fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg			if (sublen != 16) {
98009fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg				printf("(invalid, length=%d)\n", sublen);
98109fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg				break;
98209fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg			}
98309fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg			printf("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
98409fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg				"%02x%02x-%02x%02x%02x%02x%02x%02x\n",
98509fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg				data[4], data[5], data[6], data[7],
98609fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg				data[8], data[9], data[10], data[11],
98709fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg				data[12], data[13], data[14], data[15],
98809fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg				data[16], data[17], data[18], data[19]);
98909fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg			break;
990a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		case 0x1054: {
991a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			tab_on_first(&first);
992a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			if (sublen != 8) {
993a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen				printf("\t * Primary Device Type: (invalid "
994a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen				       "length %d)\n", sublen);
995a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen				break;
996a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			}
997a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			printf("\t * Primary Device Type: "
998a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			       "%u-%02x%02x%02x%02x-%u\n",
999a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			       data[4] << 8 | data[5],
1000a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			       data[6], data[7], data[8], data[9],
1001a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			       data[10] << 8 | data[11]);
1002a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			break;
1003a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		}
10047ee5a86565fcf11ea33356ae9b202bc0336e13d6Johannes Berg		case 0x1057: {
1005fe31a22e04f62839e8ba41e6fc9241abe64e07c2Johannes Berg			__u8 val = data[4];
10067ee5a86565fcf11ea33356ae9b202bc0336e13d6Johannes Berg			tab_on_first(&first);
1007fe31a22e04f62839e8ba41e6fc9241abe64e07c2Johannes Berg			printf("\t * AP setup locked: 0x%.2x\n", val);
10087ee5a86565fcf11ea33356ae9b202bc0336e13d6Johannes Berg			break;
10097ee5a86565fcf11ea33356ae9b202bc0336e13d6Johannes Berg		}
1010a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		case 0x1008:
1011a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		case 0x1053: {
10124673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			__u16 meth = (data[4] << 8) + data[5];
10134673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			bool comma = false;
10144673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			tab_on_first(&first);
1015a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			printf("\t * %sConfig methods:",
1016a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			       subtype == 0x1053 ? "Selected Registrar ": "");
10174673a894dae2780e395204eab01af4d40220b9f5Johannes Berg#define T(bit, name) do {		\
10184673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	if (meth & (1<<bit)) {		\
10194673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		if (comma)		\
10204673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf(",");	\
10214673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		comma = true;		\
10224673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		printf(" " name);	\
10234673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	} } while (0)
10244673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(0, "USB");
10254673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(1, "Ethernet");
10264673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(2, "Label");
10274673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(3, "Display");
10284673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(4, "Ext. NFC");
10294673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(5, "Int. NFC");
10304673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(6, "NFC Intf.");
10314673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(7, "PBC");
10324673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(8, "Keypad");
10334673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf("\n");
10344673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			break;
10354673a894dae2780e395204eab01af4d40220b9f5Johannes Berg#undef T
10364673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		}
10372650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg		default: {
10382650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg			const __u8 *subdata = data + 4;
10392650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg			__u16 tmplen = sublen;
10402650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg
10412650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg			tab_on_first(&first);
10422650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg			printf("\t * Unknown TLV (%#.4x, %d bytes):",
10432650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg			       subtype, tmplen);
10442650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg			while (tmplen) {
10452650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg				printf(" %.2x", *subdata);
10462650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg				subdata++;
10472650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg				tmplen--;
10482650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg			}
10492650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg			printf("\n");
10504673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			break;
10514673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		}
10522650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg		}
10534673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
10544673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		data += sublen + 4;
10554673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		len -= sublen + 4;
10564673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	}
10574673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
10584673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	if (len != 0) {
10594673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		printf("\t\t * bogus tail data (%d):", len);
10604673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		while (len) {
10614673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf(" %.2x", *data);
10624673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			data++;
10634673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			len--;
10644673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		}
10654673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		printf("\n");
10664673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	}
10674673a894dae2780e395204eab01af4d40220b9f5Johannes Berg}
10684673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
106983b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic const struct ie_print wifiprinters[] = {
1070febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[1] = { "WPA", print_wifi_wpa, 2, 255, BIT(PRINT_SCAN), },
1071febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[2] = { "WMM", print_wifi_wmm, 1, 255, BIT(PRINT_SCAN), },
1072febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[4] = { "WPS", print_wifi_wps, 0, 255, BIT(PRINT_SCAN), },
10734673a894dae2780e395204eab01af4d40220b9f5Johannes Berg};
10744673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
10759a22374a56b394000cfb98acb649355f76beb3a3Johannes Bergstatic inline void print_p2p(const uint8_t type, uint8_t len, const uint8_t *data)
10769a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg{
10779a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg	bool first = true;
10789a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg	__u8 subtype;
10799a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg	__u16 sublen;
10809a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg
10819a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg	while (len >= 3) {
10829a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		subtype = data[0];
10839a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		sublen = (data[2] << 8) + data[1];
10849a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg
10859a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		if (sublen > len - 3)
10869a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			break;
10879a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg
10889a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		switch (subtype) {
10899a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x02: /* capability */
10909a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			tab_on_first(&first);
10919a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			if (sublen < 2) {
10929a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg				printf("\t * malformed capability\n");
10939a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg				break;
10949a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			}
10959a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			printf("\t * Group capa: 0x%.2x, Device capa: 0x%.2x\n",
10969a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg				data[3], data[4]);
10979a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			break;
10989a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x0d: /* device info */
10999a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			if (sublen < 6 + 2 + 8 + 1) {
11009a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg				printf("\t * malformed device info\n");
11019a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg				break;
11029a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			}
11039a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			/* fall through for now */
11049a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x00: /* status */
11059a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x01: /* minor reason */
11069a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x03: /* device ID */
11079a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x04: /* GO intent */
11089a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x05: /* configuration timeout */
11099a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x06: /* listen channel */
11109a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x07: /* group BSSID */
11119a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x08: /* ext listen timing */
11129a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x09: /* intended interface address */
11139a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x0a: /* manageability */
11149a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x0b: /* channel list */
11159a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x0c: /* NoA */
11169a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x0e: /* group info */
11179a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x0f: /* group ID */
11189a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x10: /* interface */
11199a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x11: /* operating channel */
11209a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x12: /* invitation flags */
11219a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0xdd: /* vendor specific */
11229a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		default: {
11239a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			const __u8 *subdata = data + 4;
11249a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			__u16 tmplen = sublen;
11259a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg
11269a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			tab_on_first(&first);
11279a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			printf("\t * Unknown TLV (%#.2x, %d bytes):",
11289a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			       subtype, tmplen);
11299a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			while (tmplen) {
11309a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg				printf(" %.2x", *subdata);
11319a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg				subdata++;
11329a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg				tmplen--;
11339a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			}
11349a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			printf("\n");
11359a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			break;
11369a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		}
11379a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		}
11389a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg
11399a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		data += sublen + 3;
11409a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		len -= sublen + 3;
11419a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg	}
11429a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg
11439a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg	if (len != 0) {
11449a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		tab_on_first(&first);
11459a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		printf("\t * bogus tail data (%d):", len);
11469a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		while (len) {
11479a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			printf(" %.2x", *data);
11489a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			data++;
11499a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			len--;
11509a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		}
11519a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		printf("\n");
11529a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg	}
11539a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg}
11549a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg
11559a22374a56b394000cfb98acb649355f76beb3a3Johannes Bergstatic const struct ie_print wfa_printers[] = {
11569a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg	[9] = { "P2P", print_p2p, 2, 255, BIT(PRINT_SCAN), },
11579a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg};
11589a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg
1159764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Bergstatic void print_vendor(unsigned char len, unsigned char *data,
1160febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg			 bool unknown, enum print_ie_type ptype)
11613563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
11623563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	int i;
11633563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
1164fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg	if (len < 3) {
11654673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		printf("\tVendor specific: <too short> data:");
1166fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg		for(i = 0; i < len; i++)
1167fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg			printf(" %.02x", data[i]);
1168fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg		printf("\n");
1169fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg		return;
1170fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg	}
1171fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg
11723bd60ef1276fc888fed699ee598b3b358d976f4cJohannes Berg	if (len >= 4 && memcmp(data, ms_oui, 3) == 0) {
1173febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg		if (data[3] < ARRAY_SIZE(wifiprinters) &&
1174febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg		    wifiprinters[data[3]].name &&
1175febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg		    wifiprinters[data[3]].flags & BIT(ptype)) {
117683b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			print_ie(&wifiprinters[data[3]], data[3], len - 4, data + 4);
117783b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			return;
117883b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		}
1179febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg		if (!unknown)
11804673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			return;
11813bd60ef1276fc888fed699ee598b3b358d976f4cJohannes Berg		printf("\tMS/WiFi %#.2x, data:", data[3]);
11824673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		for(i = 0; i < len - 4; i++)
11834673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf(" %.02x", data[i + 4]);
11844673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		printf("\n");
11854673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		return;
11864673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	}
11874673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
11889a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg	if (len >= 4 && memcmp(data, wfa_oui, 3) == 0) {
11899a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		if (data[3] < ARRAY_SIZE(wfa_printers) &&
11909a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		    wfa_printers[data[3]].name &&
11919a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		    wfa_printers[data[3]].flags & BIT(ptype)) {
11929a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			print_ie(&wfa_printers[data[3]], data[3], len - 4, data + 4);
11939a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			return;
11949a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		}
11959a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		if (!unknown)
11969a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			return;
11979a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		printf("\tWFA %#.2x, data:", data[3]);
11989a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		for(i = 0; i < len - 4; i++)
11999a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			printf(" %.02x", data[i + 4]);
12009a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		printf("\n");
12019a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		return;
12029a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg	}
12039a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg
1204febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	if (!unknown)
1205764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg		return;
1206764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg
1207fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg	printf("\tVendor specific: OUI %.2x:%.2x:%.2x, data:",
12083563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		data[0], data[1], data[2]);
1209fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg	for (i = 3; i < len; i++)
1210fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg		printf(" %.2x", data[i]);
12113563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	printf("\n");
12123563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
12133563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
1214febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Bergvoid print_ies(unsigned char *ie, int ielen, bool unknown,
1215febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	       enum print_ie_type ptype)
12163563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
12173563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	while (ielen >= 2 && ielen >= ie[1]) {
1218febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg		if (ie[0] < ARRAY_SIZE(ieprinters) &&
1219febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg		    ieprinters[ie[0]].name &&
1220febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg		    ieprinters[ie[0]].flags & BIT(ptype)) {
122183b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			print_ie(&ieprinters[ie[0]], ie[0], ie[1], ie + 2);
1222764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg		} else if (ie[0] == 221 /* vendor */) {
1223febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg			print_vendor(ie[1], ie + 2, unknown, ptype);
1224febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg		} else if (unknown) {
12253563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			int i;
12263563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
12278086b7007d8a7f9d2bc22d154e26e9060f0e9676Johannes Berg			printf("\tUnknown IE (%d):", ie[0]);
12283563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			for (i=0; i<ie[1]; i++)
12298086b7007d8a7f9d2bc22d154e26e9060f0e9676Johannes Berg				printf(" %.2x", ie[2+i]);
12303563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			printf("\n");
12313563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		}
12323563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		ielen -= ie[1] + 2;
12333563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		ie += ie[1] + 2;
12343563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	}
12353563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
12363563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
12372e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratievstatic void print_capa_dmg(__u16 capa)
12382e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev{
12392e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	switch (capa & WLAN_CAPABILITY_DMG_TYPE_MASK) {
12402e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	case WLAN_CAPABILITY_DMG_TYPE_AP:
12412e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" DMG_ESS");
12422e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		break;
12432e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	case WLAN_CAPABILITY_DMG_TYPE_PBSS:
12442e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" DMG_PCP");
12452e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		break;
12462e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	case WLAN_CAPABILITY_DMG_TYPE_IBSS:
12472e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" DMG_IBSS");
12482e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		break;
12492e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	}
12502e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev
12512e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_DMG_CBAP_ONLY)
12522e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" CBAP_Only");
12532e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_DMG_CBAP_SOURCE)
12542e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" CBAP_Src");
12552e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_DMG_PRIVACY)
12562e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" Privacy");
12572e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_DMG_ECPAC)
12582e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" ECPAC");
12592e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_DMG_SPECTRUM_MGMT)
12602e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" SpectrumMgmt");
12612e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_DMG_RADIO_MEASURE)
12622e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" RadioMeasure");
12632e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev}
12642e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev
12652e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratievstatic void print_capa_non_dmg(__u16 capa)
12662e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev{
12672e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_ESS)
12682e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" ESS");
12692e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_IBSS)
12702e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" IBSS");
12712e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_CF_POLLABLE)
12722e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" CfPollable");
12732e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_CF_POLL_REQUEST)
12742e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" CfPollReq");
12752e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_PRIVACY)
12762e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" Privacy");
12772e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_SHORT_PREAMBLE)
12782e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" ShortPreamble");
12792e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_PBCC)
12802e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" PBCC");
12812e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_CHANNEL_AGILITY)
12822e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" ChannelAgility");
12832e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_SPECTRUM_MGMT)
12842e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" SpectrumMgmt");
12852e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_QOS)
12862e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" QoS");
12872e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_SHORT_SLOT_TIME)
12882e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" ShortSlotTime");
12892e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_APSD)
12902e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" APSD");
12912e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_RADIO_MEASURE)
12922e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" RadioMeasure");
12932e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_DSSS_OFDM)
12942e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" DSSS-OFDM");
12952e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_DEL_BACK)
12962e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" DelayedBACK");
12972e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_IMM_BACK)
12982e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" ImmediateBACK");
12992e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev}
13002e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev
13013563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Bergstatic int print_bss_handler(struct nl_msg *msg, void *arg)
13023563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
13033563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	struct nlattr *tb[NL80211_ATTR_MAX + 1];
13043563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
13053563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	struct nlattr *bss[NL80211_BSS_MAX + 1];
13063563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	char mac_addr[20], dev[20];
13073563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
13083563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		[NL80211_BSS_TSF] = { .type = NLA_U64 },
13093563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		[NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
13103563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		[NL80211_BSS_BSSID] = { },
13113563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		[NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
13123563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		[NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
13133563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		[NL80211_BSS_INFORMATION_ELEMENTS] = { },
1314f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg		[NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
1315f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg		[NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
1316a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg		[NL80211_BSS_STATUS] = { .type = NLA_U32 },
1317c04a78dfa108063933d2c489896f8c7b417a0f3dHolger Schurig		[NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },
1318575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen		[NL80211_BSS_BEACON_IES] = { },
13193563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	};
1320febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	struct scan_params *params = arg;
13211c5bcd9c76dad08e54c3e6604a529c53b62e76eaJohannes Berg	int show = params->show_both_ie_sets ? 2 : 1;
13222e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	bool is_dmg = false;
13233563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
13243563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
13253563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		  genlmsg_attrlen(gnlh, 0), NULL);
13263563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
13273563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	if (!tb[NL80211_ATTR_BSS]) {
13285fe70c0edb4bc3015d192977f4fb9a5d4fa07148Johannes Berg		fprintf(stderr, "bss info missing!\n");
13293563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		return NL_SKIP;
13303563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	}
13313563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	if (nla_parse_nested(bss, NL80211_BSS_MAX,
13323563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			     tb[NL80211_ATTR_BSS],
13333563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			     bss_policy)) {
13345fe70c0edb4bc3015d192977f4fb9a5d4fa07148Johannes Berg		fprintf(stderr, "failed to parse nested attributes!\n");
13353563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		return NL_SKIP;
13363563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	}
13373563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
13383563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	if (!bss[NL80211_BSS_BSSID])
13393563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		return NL_SKIP;
13403563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
13413563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	mac_addr_n2a(mac_addr, nla_data(bss[NL80211_BSS_BSSID]));
134200889fb26e914c7485e1bae42f88259183728f78Johannes Berg	printf("BSS %s", mac_addr);
134300889fb26e914c7485e1bae42f88259183728f78Johannes Berg	if (tb[NL80211_ATTR_IFINDEX]) {
134400889fb26e914c7485e1bae42f88259183728f78Johannes Berg		if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
134500889fb26e914c7485e1bae42f88259183728f78Johannes Berg		printf("(on %s)", dev);
134600889fb26e914c7485e1bae42f88259183728f78Johannes Berg	}
1347a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg
1348a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg	if (bss[NL80211_BSS_STATUS]) {
1349a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg		switch (nla_get_u32(bss[NL80211_BSS_STATUS])) {
1350a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg		case NL80211_BSS_STATUS_AUTHENTICATED:
1351a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg			printf(" -- authenticated");
1352a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg			break;
1353a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg		case NL80211_BSS_STATUS_ASSOCIATED:
1354a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg			printf(" -- associated");
1355a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg			break;
1356a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg		case NL80211_BSS_STATUS_IBSS_JOINED:
1357a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg			printf(" -- joined");
1358a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg			break;
1359a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg		default:
1360a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg			printf(" -- unknown status: %d",
1361a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg				nla_get_u32(bss[NL80211_BSS_STATUS]));
1362a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg			break;
1363a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg		}
1364a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg	}
1365a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg	printf("\n");
13663563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
1367e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg	if (bss[NL80211_BSS_TSF]) {
1368e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg		unsigned long long tsf;
1369e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg		tsf = (unsigned long long)nla_get_u64(bss[NL80211_BSS_TSF]);
1370e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg		printf("\tTSF: %llu usec (%llud, %.2lld:%.2llu:%.2llu)\n",
1371e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg			tsf, tsf/1000/1000/60/60/24, (tsf/1000/1000/60/60) % 24,
1372e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg			(tsf/1000/1000/60) % 60, (tsf/1000/1000) % 60);
1373e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg	}
13742e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (bss[NL80211_BSS_FREQUENCY]) {
13752e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		int freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
13762e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf("\tfreq: %d\n", freq);
13772e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		if (freq > 45000)
13782e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev			is_dmg = true;
13792e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	}
13803563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	if (bss[NL80211_BSS_BEACON_INTERVAL])
13813563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		printf("\tbeacon interval: %d\n",
13823563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]));
138392a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann	if (bss[NL80211_BSS_CAPABILITY]) {
138492a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann		__u16 capa = nla_get_u16(bss[NL80211_BSS_CAPABILITY]);
138592a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann		printf("\tcapability:");
13862e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		if (is_dmg)
13872e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev			print_capa_dmg(capa);
13882e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		else
13892e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev			print_capa_non_dmg(capa);
139092a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann		printf(" (0x%.4x)\n", capa);
139192a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann	}
1392f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg	if (bss[NL80211_BSS_SIGNAL_MBM]) {
1393f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg		int s = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]);
1394f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg		printf("\tsignal: %d.%.2d dBm\n", s/100, s%100);
1395f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg	}
1396f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg	if (bss[NL80211_BSS_SIGNAL_UNSPEC]) {
1397f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg		unsigned char s = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]);
1398f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg		printf("\tsignal: %d/100\n", s);
1399f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg	}
1400c04a78dfa108063933d2c489896f8c7b417a0f3dHolger Schurig	if (bss[NL80211_BSS_SEEN_MS_AGO]) {
1401c04a78dfa108063933d2c489896f8c7b417a0f3dHolger Schurig		int age = nla_get_u32(bss[NL80211_BSS_SEEN_MS_AGO]);
1402c04a78dfa108063933d2c489896f8c7b417a0f3dHolger Schurig		printf("\tlast seen: %d ms ago\n", age);
1403c04a78dfa108063933d2c489896f8c7b417a0f3dHolger Schurig	}
1404c551449a3271ca1db60856fc2af20e1f2d01cce8Johannes Berg
14051c5bcd9c76dad08e54c3e6604a529c53b62e76eaJohannes Berg	if (bss[NL80211_BSS_INFORMATION_ELEMENTS] && show--) {
1406575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen		if (bss[NL80211_BSS_BEACON_IES])
1407575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen			printf("\tInformation elements from Probe Response "
1408575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen			       "frame:\n");
14093563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		print_ies(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
1410764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg			  nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
1411febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg			  params->unknown, params->type);
1412575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen	}
14131c5bcd9c76dad08e54c3e6604a529c53b62e76eaJohannes Berg	if (bss[NL80211_BSS_BEACON_IES] && show--) {
1414575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen		printf("\tInformation elements from Beacon frame:\n");
1415575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen		print_ies(nla_data(bss[NL80211_BSS_BEACON_IES]),
1416575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen			  nla_len(bss[NL80211_BSS_BEACON_IES]),
1417575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen			  params->unknown, params->type);
1418575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen	}
14193563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
14203563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	return NL_SKIP;
14213563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
14223563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
1423764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Bergstatic struct scan_params scan_params;
14243563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
14257c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Bergstatic int handle_scan_dump(struct nl80211_state *state,
14267c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Berg			    struct nl_cb *cb,
14273563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			    struct nl_msg *msg,
142805514f9581f66b12ac9ee0f21c770ceb34310e9dJohannes Berg			    int argc, char **argv,
142905514f9581f66b12ac9ee0f21c770ceb34310e9dJohannes Berg			    enum id_input id)
14303563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
1431764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg	if (argc > 1)
1432764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg		return 1;
1433764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg
14341c5bcd9c76dad08e54c3e6604a529c53b62e76eaJohannes Berg	memset(&scan_params, 0, sizeof(scan_params));
14351c5bcd9c76dad08e54c3e6604a529c53b62e76eaJohannes Berg
1436764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg	if (argc == 1 && !strcmp(argv[0], "-u"))
1437764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg		scan_params.unknown = true;
1438575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen	else if (argc == 1 && !strcmp(argv[0], "-b"))
1439575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen		scan_params.show_both_ie_sets = true;
1440764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg
1441febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	scan_params.type = PRINT_SCAN;
1442febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg
1443764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_bss_handler,
1444764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg		  &scan_params);
14453563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	return 0;
14463563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
1447a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg
1448a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Bergstatic int handle_scan_combined(struct nl80211_state *state,
1449a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg				struct nl_cb *cb,
1450a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg				struct nl_msg *msg,
145105514f9581f66b12ac9ee0f21c770ceb34310e9dJohannes Berg				int argc, char **argv,
145205514f9581f66b12ac9ee0f21c770ceb34310e9dJohannes Berg				enum id_input id)
1453a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg{
1454559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	char **trig_argv;
1455a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	static char *dump_argv[] = {
1456a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		NULL,
1457a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		"scan",
1458a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		"dump",
145992649eab6b3ccb0be600b8501fa7b83e9467819cMarcel Holtmann		NULL,
1460a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	};
1461a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	static const __u32 cmds[] = {
1462a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		NL80211_CMD_NEW_SCAN_RESULTS,
1463a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		NL80211_CMD_SCAN_ABORTED,
1464a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	};
1465559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	int trig_argc, dump_argc, err;
1466a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg
1467559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	if (argc >= 3 && !strcmp(argv[2], "-u")) {
1468559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		dump_argc = 4;
1469559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		dump_argv[3] = "-u";
1470575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen	} else if (argc >= 3 && !strcmp(argv[2], "-b")) {
1471575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen		dump_argc = 4;
1472575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen		dump_argv[3] = "-b";
1473559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	} else
1474559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		dump_argc = 3;
1475559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg
1476559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	trig_argc = 3 + (argc - 2) + (3 - dump_argc);
1477559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	trig_argv = calloc(trig_argc, sizeof(*trig_argv));
1478559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	if (!trig_argv)
1479559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		return -ENOMEM;
1480a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	trig_argv[0] = argv[0];
1481559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	trig_argv[1] = "scan";
1482559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	trig_argv[2] = "trigger";
1483559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	int i;
1484559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	for (i = 0; i < argc - 2 - (dump_argc - 3); i++)
1485559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		trig_argv[i + 3] = argv[i + 2 + (dump_argc - 3)];
148675f4204cd7d27caa080d64f6f5cf3c4b366c839fJohannes Berg	err = handle_cmd(state, id, trig_argc, trig_argv);
1487559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	free(trig_argv);
1488a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	if (err)
1489a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		return err;
1490a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg
149161725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	/*
149261725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * WARNING: DO NOT COPY THIS CODE INTO YOUR APPLICATION
149361725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 *
149461725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * This code has a bug, which requires creating a separate
149561725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * nl80211 socket to fix:
149661725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * It is possible for a NL80211_CMD_NEW_SCAN_RESULTS or
149761725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * NL80211_CMD_SCAN_ABORTED message to be sent by the kernel
149861725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * before (!) we listen to it, because we only start listening
149961725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * after we send our scan request.
150061725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 *
150161725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * Doing it the other way around has a race condition as well,
150261725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * if you first open the events socket you may get a notification
150361725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * for a previous scan.
150461725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 *
150561725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * The only proper way to fix this would be to listen to events
150661725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * before sending the command, and for the kernel to send the
150761725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * scan request along with the event, so that you can match up
150861725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * whether the scan you requested was finished or aborted (this
150961725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * may result in processing a scan that another application
151061725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * requested, but that doesn't seem to be a problem).
151161725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 *
151261725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * Alas, the kernel doesn't do that (yet).
151361725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 */
151461725dbed6df376809e8dc3865640244d8f1d690Johannes Berg
1515a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	if (listen_events(state, ARRAY_SIZE(cmds), cmds) ==
1516a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg					NL80211_CMD_SCAN_ABORTED) {
1517a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		printf("scan aborted!\n");
1518a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		return 0;
1519a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	}
1520a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg
1521a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	dump_argv[0] = argv[0];
152275f4204cd7d27caa080d64f6f5cf3c4b366c839fJohannes Berg	return handle_cmd(state, id, dump_argc, dump_argv);
1523a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg}
1524ced94d5f129e5d116b6a888f312deab081bb2231Antonio QuartulliTOPLEVEL(scan, "[-u] [freq <freq>*] [ies <hex as 00:11:..>] [lowpri,flush,ap-force] [ssid <ssid>*|passive]", 0, 0,
15256ca98d28b949d20cca2e158bef3e0cfd75b59672Johannes Berg	 CIB_NETDEV, handle_scan_combined,
15266ca98d28b949d20cca2e158bef3e0cfd75b59672Johannes Berg	 "Scan on the given frequencies and probe for the given SSIDs\n"
15276ca98d28b949d20cca2e158bef3e0cfd75b59672Johannes Berg	 "(or wildcard if not given) unless passive scanning is requested.\n"
152864797a7fd7c49d95abc8540490c76bf493699176Johannes Berg	 "If -u is specified print unknown data in the scan results.\n"
152964797a7fd7c49d95abc8540490c76bf493699176Johannes Berg	 "Specified (vendor) IEs must be well-formed.");
15304698bfc235c20e955466b6362df2a39f7478c13fJohannes BergCOMMAND(scan, dump, "[-u]",
15314698bfc235c20e955466b6362df2a39f7478c13fJohannes Berg	NL80211_CMD_GET_SCAN, NLM_F_DUMP, CIB_NETDEV, handle_scan_dump,
15324698bfc235c20e955466b6362df2a39f7478c13fJohannes Berg	"Dump the current scan results. If -u is specified, print unknown\n"
15334698bfc235c20e955466b6362df2a39f7478c13fJohannes Berg	"data in scan results.");
1534ced94d5f129e5d116b6a888f312deab081bb2231Antonio QuartulliCOMMAND(scan, trigger, "[freq <freq>*] [ies <hex as 00:11:..>] [lowpri,flush,ap-force] [ssid <ssid>*|passive]",
15354698bfc235c20e955466b6362df2a39f7478c13fJohannes Berg	NL80211_CMD_TRIGGER_SCAN, 0, CIB_NETDEV, handle_scan,
15364698bfc235c20e955466b6362df2a39f7478c13fJohannes Berg	 "Trigger a scan on the given frequencies with probing for the given\n"
15374698bfc235c20e955466b6362df2a39f7478c13fJohannes Berg	 "SSIDs (or wildcard if not given) unless passive scanning is requested.");
1538