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
735085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Bergstatic int parse_random_mac_addr(struct nl_msg *msg, char *arg)
745085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg{
755085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg	char *a_addr, *a_mask, *sep;
765085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg	unsigned char addr[ETH_ALEN], mask[ETH_ALEN];
775085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg	char *addrs = arg + 9;
785085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg
795085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg	if (*addrs != '=')
805085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg		return 0;
815085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg
825085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg	addrs++;
835085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg	sep = strchr(addrs, '/');
845085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg	a_addr = addrs;
855085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg
865085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg	if (!sep)
875085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg		return 1;
885085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg
895085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg	*sep = 0;
905085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg	a_mask = sep + 1;
915085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg	if (mac_addr_a2n(addr, a_addr) || mac_addr_a2n(mask, a_mask))
925085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg		return 1;
935085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg
945085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
955085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg	NLA_PUT(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN, mask);
965085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg
975085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg	return 0;
985085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg nla_put_failure:
995085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg	return -ENOBUFS;
1005085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg}
1015085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg
102b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelhoint parse_sched_scan(struct nl_msg *msg, int *argc, char ***argv)
103b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho{
104302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho	struct nl_msg *matchset = NULL, *freqs = NULL, *ssids = NULL;
105b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	struct nlattr *match = NULL;
106b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	enum {
107b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho		ND_TOPLEVEL,
108b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho		ND_MATCH,
109b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho		ND_FREQS,
110302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho		ND_ACTIVE,
111b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	} parse_state = ND_TOPLEVEL;
112b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	int c  = *argc;
113b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	char *end, **v = *argv;
114b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	int err = 0, i = 0;
115b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	unsigned int freq, interval = 0, delay = 0;
116302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho	bool have_matchset = false, have_freqs = false, have_ssids = false;
117302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho	bool have_active = false, have_passive = false;
1185130bba08d4697e8261c1013d92aba6513804f04Luciano Coelho	uint32_t flags = 0;
119b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho
120b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	matchset = nlmsg_alloc();
121b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	if (!matchset) {
122b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho		err = -ENOBUFS;
123b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho		goto out;
124b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	}
125b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho
126b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	freqs = nlmsg_alloc();
127b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	if (!freqs) {
128b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho		err = -ENOBUFS;
129b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho		goto out;
130b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	}
131b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho
132302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho	ssids = nlmsg_alloc();
133302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho	if (!ssids) {
134302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho		err = -ENOMEM;
135302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho		goto out;
136302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho	}
137302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho
138b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	while (c) {
139b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho		switch (parse_state) {
140b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho		case ND_TOPLEVEL:
141b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho			if (!strcmp(v[0], "interval")) {
142b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				c--; v++;
143b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				if (c == 0) {
144b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					err = -EINVAL;
145b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					goto nla_put_failure;
146b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				}
147b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho
148b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				if (interval) {
149b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					err = -EINVAL;
150b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					goto nla_put_failure;
151b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				}
152b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				interval = strtoul(v[0], &end, 10);
153b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				if (*end || !interval) {
154b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					err = -EINVAL;
155b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					goto nla_put_failure;
156b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				}
157b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				NLA_PUT_U32(msg,
158b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					    NL80211_ATTR_SCHED_SCAN_INTERVAL,
159b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					    interval);
160b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho			} else if (!strcmp(v[0], "delay")) {
161b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				c--; v++;
162b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				if (c == 0) {
163b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					err = -EINVAL;
164b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					goto nla_put_failure;
165b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				}
166b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho
167b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				if (delay) {
168b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					err = -EINVAL;
169b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					goto nla_put_failure;
170b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				}
171b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				delay = strtoul(v[0], &end, 10);
172b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				if (*end) {
173b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					err = -EINVAL;
174b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					goto nla_put_failure;
175b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				}
176b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				NLA_PUT_U32(msg,
177b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					    NL80211_ATTR_SCHED_SCAN_DELAY,
178b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					    delay);
179b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho			} else if (!strcmp(v[0], "matches")) {
180b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				parse_state = ND_MATCH;
181b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				if (have_matchset) {
182b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					err = -EINVAL;
183b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					goto nla_put_failure;
184b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				}
185b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho
186b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				i = 0;
187b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho			} else if (!strcmp(v[0], "freqs")) {
188b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				parse_state = ND_FREQS;
189b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				if (have_freqs) {
190b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					err = -EINVAL;
191b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					goto nla_put_failure;
192b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				}
193b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho
194b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				have_freqs = true;
195b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				i = 0;
196302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho			} else if (!strcmp(v[0], "active")) {
197302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				parse_state = ND_ACTIVE;
198302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				if (have_active || have_passive) {
199302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho					err = -EINVAL;
200302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho					goto nla_put_failure;
201302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				}
202302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho
203302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				have_active = true;
204302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				i = 0;
205302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho			} else if (!strcmp(v[0], "passive")) {
206302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				if (have_active || have_passive) {
207302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho					err = -EINVAL;
208302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho					goto nla_put_failure;
209302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				}
210302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho
211302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				have_passive = true;
2125130bba08d4697e8261c1013d92aba6513804f04Luciano Coelho			} else if (!strncmp(v[0], "randomise", 9) ||
2135130bba08d4697e8261c1013d92aba6513804f04Luciano Coelho				   !strncmp(v[0], "randomize", 9)) {
2145130bba08d4697e8261c1013d92aba6513804f04Luciano Coelho				flags |= NL80211_SCAN_FLAG_RANDOM_ADDR;
2155130bba08d4697e8261c1013d92aba6513804f04Luciano Coelho				if (c > 0) {
2165130bba08d4697e8261c1013d92aba6513804f04Luciano Coelho					err = parse_random_mac_addr(msg, v[0]);
2175130bba08d4697e8261c1013d92aba6513804f04Luciano Coelho					if (err)
2185130bba08d4697e8261c1013d92aba6513804f04Luciano Coelho						goto nla_put_failure;
2195130bba08d4697e8261c1013d92aba6513804f04Luciano Coelho				}
220b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho			} else {
221b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				/* this element is not for us, so
222b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				 * return to continue parsing.
223b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				 */
224b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				goto nla_put_failure;
225b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho			}
226b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho			c--; v++;
227b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho
228b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho			break;
229b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho		case ND_MATCH:
230b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho			if (!strcmp(v[0], "ssid")) {
231b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				c--; v++;
232b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				if (c == 0) {
233b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					err = -EINVAL;
234b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					goto nla_put_failure;
235b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				}
236b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho
237b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				/* TODO: for now we can only have an
238b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				 * SSID in the match, so we can start
239b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				 * the match nest here.
240b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				 */
241b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				match = nla_nest_start(matchset, i);
242b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				if (!match) {
243b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					err = -ENOBUFS;
244b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					goto nla_put_failure;
245b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				}
246b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho
247b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				NLA_PUT(matchset,
248b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
249b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					strlen(v[0]), v[0]);
250b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				nla_nest_end(matchset, match);
251b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				match = NULL;
252b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho
253b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				have_matchset = true;
254b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				i++;
255b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				c--; v++;
256b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho			} else {
257b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				/* other element that cannot be part
258b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				 * of a match indicates the end of the
259b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				 * match. */
260b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				/* need at least one match in the matchset */
261b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				if (i == 0) {
262b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					err = -EINVAL;
263b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					goto nla_put_failure;
264b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				}
265b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho
266b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				parse_state = ND_TOPLEVEL;
267b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho			}
268b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho
269b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho			break;
270b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho		case ND_FREQS:
271b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho			freq = strtoul(v[0], &end, 10);
272b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho			if (*end) {
273b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				if (i == 0) {
274b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					err = -EINVAL;
275b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho					goto nla_put_failure;
276b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				}
277b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho
278b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				parse_state = ND_TOPLEVEL;
279b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho			} else {
280b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				NLA_PUT_U32(freqs, i, freq);
281b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				i++;
282b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho				c--; v++;
283b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho			}
284b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho			break;
285302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho		case ND_ACTIVE:
286302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho			if (!strcmp(v[0], "ssid")) {
287302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				c--; v++;
288302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				if (c == 0) {
289302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho					err = -EINVAL;
290302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho					goto nla_put_failure;
291302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				}
292302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho
293302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				NLA_PUT(ssids,
294302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho					NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
295302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho					strlen(v[0]), v[0]);
296302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho
297302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				have_ssids = true;
298302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				i++;
299302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				c--; v++;
300302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho			} else {
301302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				/* other element that cannot be part
302302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				 * of a match indicates the end of the
303302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				 * active set. */
304302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				/* need at least one item in the set */
305302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				if (i == 0) {
306302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho					err = -EINVAL;
307302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho					goto nla_put_failure;
308302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				}
309302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho
310302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho				parse_state = ND_TOPLEVEL;
311302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho			}
312302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho			break;
313b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho		}
314b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	}
315b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho
316302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho	if (!have_ssids)
317302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho		NLA_PUT(ssids, 1, 0, "");
318302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho	if (!have_passive)
319302a378a6dd975d5d4c5627d8e1caff6df7906deLuciano Coelho		nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids);
320b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	if (have_freqs)
321b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho		nla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs);
322b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	if (have_matchset)
323b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho		nla_put_nested(msg, NL80211_ATTR_SCHED_SCAN_MATCH, matchset);
3245130bba08d4697e8261c1013d92aba6513804f04Luciano Coelho	if (flags)
3255130bba08d4697e8261c1013d92aba6513804f04Luciano Coelho		NLA_PUT_U32(msg, NL80211_ATTR_SCAN_FLAGS, flags);
326b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho
327b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelhonla_put_failure:
328b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	if (match)
329b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho		nla_nest_end(msg, match);
330b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	nlmsg_free(freqs);
331b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	nlmsg_free(matchset);
332b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho
333b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelhoout:
334b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	*argc = c;
335b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	*argv = v;
336b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho	return err;
337b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho}
338b1622287b09909886e578a66a09dfcb0417a33ceLuciano Coelho
3397c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Bergstatic int handle_scan(struct nl80211_state *state,
3407c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Berg		       struct nl_cb *cb,
3413563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		       struct nl_msg *msg,
34205514f9581f66b12ac9ee0f21c770ceb34310e9dJohannes Berg		       int argc, char **argv,
34305514f9581f66b12ac9ee0f21c770ceb34310e9dJohannes Berg		       enum id_input id)
3443563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
345559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	struct nl_msg *ssids = NULL, *freqs = NULL;
346559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	char *eptr;
3473563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	int err = -ENOBUFS;
348559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	int i;
349559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	enum {
350559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		NONE,
351559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		FREQ,
35264797a7fd7c49d95abc8540490c76bf493699176Johannes Berg		IES,
353559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		SSID,
354851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall		MESHID,
355559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		DONE,
356559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	} parse = NONE;
357559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	int freq;
358559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	bool passive = false, have_ssids = false, have_freqs = false;
359851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall	size_t ies_len = 0, meshid_len = 0;
360851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall	unsigned char *ies = NULL, *meshid = NULL, *tmpies;
3615085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg	unsigned int flags = 0;
3623563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
3633563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	ssids = nlmsg_alloc();
3643563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	if (!ssids)
3653563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		return -ENOMEM;
366559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg
367559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	freqs = nlmsg_alloc();
368559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	if (!freqs) {
369559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		nlmsg_free(ssids);
370559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		return -ENOMEM;
371559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	}
372559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg
373559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	for (i = 0; i < argc; i++) {
374559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		switch (parse) {
375559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		case NONE:
37664797a7fd7c49d95abc8540490c76bf493699176Johannes Berg			if (strcmp(argv[i], "freq") == 0) {
37764797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				parse = FREQ;
37864797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				have_freqs = true;
37964797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				break;
38064797a7fd7c49d95abc8540490c76bf493699176Johannes Berg			} else if (strcmp(argv[i], "ies") == 0) {
38164797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				parse = IES;
38264797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				break;
383fe862239636c303372184abc5635097b43777e77Sam Leffler			} else if (strcmp(argv[i], "lowpri") == 0) {
384fe862239636c303372184abc5635097b43777e77Sam Leffler				flags |= NL80211_SCAN_FLAG_LOW_PRIORITY;
385fe862239636c303372184abc5635097b43777e77Sam Leffler				break;
386fe862239636c303372184abc5635097b43777e77Sam Leffler			} else if (strcmp(argv[i], "flush") == 0) {
387fe862239636c303372184abc5635097b43777e77Sam Leffler				flags |= NL80211_SCAN_FLAG_FLUSH;
388fe862239636c303372184abc5635097b43777e77Sam Leffler				break;
389ced94d5f129e5d116b6a888f312deab081bb2231Antonio Quartulli			} else if (strcmp(argv[i], "ap-force") == 0) {
390ced94d5f129e5d116b6a888f312deab081bb2231Antonio Quartulli				flags |= NL80211_SCAN_FLAG_AP;
391ced94d5f129e5d116b6a888f312deab081bb2231Antonio Quartulli				break;
3925085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg			} else if (strncmp(argv[i], "randomise", 9) == 0 ||
3935085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg				   strncmp(argv[i], "randomize", 9) == 0) {
3945085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg				flags |= NL80211_SCAN_FLAG_RANDOM_ADDR;
3955085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg				err = parse_random_mac_addr(msg, argv[i]);
3965085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg				if (err)
3975085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg					goto nla_put_failure;
3985085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes Berg				break;
39964797a7fd7c49d95abc8540490c76bf493699176Johannes Berg			} else if (strcmp(argv[i], "ssid") == 0) {
40064797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				parse = SSID;
40164797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				have_ssids = true;
40264797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				break;
40364797a7fd7c49d95abc8540490c76bf493699176Johannes Berg			} else if (strcmp(argv[i], "passive") == 0) {
40464797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				parse = DONE;
40564797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				passive = true;
40664797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				break;
407851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall			} else if (strcmp(argv[i], "meshid") == 0) {
408851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall				parse = MESHID;
409851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall				break;
41064797a7fd7c49d95abc8540490c76bf493699176Johannes Berg			}
411559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		case DONE:
412559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			return 1;
413559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		case FREQ:
414559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			freq = strtoul(argv[i], &eptr, 10);
415cc12e895302aa7dc82229f12b21e61c52fba80f6Johannes Berg			if (eptr != argv[i] + strlen(argv[i])) {
416cc12e895302aa7dc82229f12b21e61c52fba80f6Johannes Berg				/* failed to parse as number -- maybe a tag? */
417cc12e895302aa7dc82229f12b21e61c52fba80f6Johannes Berg				i--;
418cc12e895302aa7dc82229f12b21e61c52fba80f6Johannes Berg				parse = NONE;
419cc12e895302aa7dc82229f12b21e61c52fba80f6Johannes Berg				continue;
420cc12e895302aa7dc82229f12b21e61c52fba80f6Johannes Berg			}
421559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			NLA_PUT_U32(freqs, i, freq);
42264797a7fd7c49d95abc8540490c76bf493699176Johannes Berg			break;
42364797a7fd7c49d95abc8540490c76bf493699176Johannes Berg		case IES:
424851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall			ies = parse_hex(argv[i], &ies_len);
42564797a7fd7c49d95abc8540490c76bf493699176Johannes Berg			if (!ies)
42664797a7fd7c49d95abc8540490c76bf493699176Johannes Berg				goto nla_put_failure;
42764797a7fd7c49d95abc8540490c76bf493699176Johannes Berg			parse = NONE;
428559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			break;
429559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		case SSID:
430559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			NLA_PUT(ssids, i, strlen(argv[i]), argv[i]);
431559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			break;
432851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall		case MESHID:
433851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall			meshid_len = strlen(argv[i]);
434851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall			meshid = (unsigned char *) malloc(meshid_len + 2);
435851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall			if (!meshid)
436851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall				goto nla_put_failure;
437851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall			meshid[0] = 114; /* mesh element id */
438851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall			meshid[1] = meshid_len;
439851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall			memcpy(&meshid[2], argv[i], meshid_len);
440851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall			meshid_len += 2;
441851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall			parse = NONE;
442851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall			break;
443851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall		}
444851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall	}
445851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall
446851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall	if (ies || meshid) {
447851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall		tmpies = (unsigned char *) malloc(ies_len + meshid_len);
448851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall		if (!tmpies)
449851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall			goto nla_put_failure;
450851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall		if (ies) {
451851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall			memcpy(tmpies, ies, ies_len);
452851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall			free(ies);
453851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall		}
454851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall		if (meshid) {
455851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall			memcpy(&tmpies[ies_len], meshid, meshid_len);
456851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall			free(meshid);
457559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		}
458851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall		NLA_PUT(msg, NL80211_ATTR_IE, ies_len + meshid_len, tmpies);
459851d35c2a3471b44d3546d07bac89e45741ad79fjacob minshall		free(tmpies);
460559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	}
461559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg
462559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	if (!have_ssids)
463559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		NLA_PUT(ssids, 1, 0, "");
464559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	if (!passive)
465559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids);
466559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg
467559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	if (have_freqs)
468559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		nla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs);
469fe862239636c303372184abc5635097b43777e77Sam Leffler	if (flags)
470fe862239636c303372184abc5635097b43777e77Sam Leffler		NLA_PUT_U32(msg, NL80211_ATTR_SCAN_FLAGS, flags);
4713563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
4723563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	err = 0;
4733563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg nla_put_failure:
4743563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	nlmsg_free(ssids);
475559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	nlmsg_free(freqs);
4763563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	return err;
4773563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
4783563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
479857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmannstatic void tab_on_first(bool *first)
480857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann{
481857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	if (!*first)
482857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf("\t");
483857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	else
484857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		*first = false;
485857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann}
486857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
48783b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_ssid(const uint8_t type, uint8_t len, const uint8_t *data)
4883563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
48983b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	printf(" ");
490748f8489caad151e01922f0ba26847aedfd36dafJohannes Berg	print_ssid_escaped(len, data);
4913563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	printf("\n");
4923563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
4933563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
494ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg#define BSS_MEMBERSHIP_SELECTOR_VHT_PHY 126
4951fd19c397234b604a553b8156bd46baa88404aabChristian Lamparter#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127
4961fd19c397234b604a553b8156bd46baa88404aabChristian Lamparter
49783b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_supprates(const uint8_t type, uint8_t len, const uint8_t *data)
4983563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
4993563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	int i;
5003563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
50183b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	printf(" ");
5023563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
50383b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	for (i = 0; i < len; i++) {
5043563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		int r = data[i] & 0x7f;
5051fd19c397234b604a553b8156bd46baa88404aabChristian Lamparter
506ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg		if (r == BSS_MEMBERSHIP_SELECTOR_VHT_PHY && data[i] & 0x80)
507ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg			printf("VHT");
508ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg		else if (r == BSS_MEMBERSHIP_SELECTOR_HT_PHY && data[i] & 0x80)
5091fd19c397234b604a553b8156bd46baa88404aabChristian Lamparter			printf("HT");
5101fd19c397234b604a553b8156bd46baa88404aabChristian Lamparter		else
5111fd19c397234b604a553b8156bd46baa88404aabChristian Lamparter			printf("%d.%d", r/2, 5*(r&1));
5121fd19c397234b604a553b8156bd46baa88404aabChristian Lamparter
5131fd19c397234b604a553b8156bd46baa88404aabChristian Lamparter		printf("%s ", data[i] & 0x80 ? "*" : "");
5143563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	}
5153563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	printf("\n");
5163563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
5173563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
51883b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_ds(const uint8_t type, uint8_t len, const uint8_t *data)
5193563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
52083b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	printf(" channel %d\n", data[0]);
5213563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
5223563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
5232b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguezstatic const char *country_env_str(char environment)
524b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann{
5252b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez	switch (environment) {
526b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann	case 'I':
5272b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		return "Indoor only";
528b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann	case 'O':
5292b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		return "Outdoor only";
530b6c0d6340dbc969b4c53f583775e7c49b440c403Johannes Berg	case ' ':
5312b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		return "Indoor/Outdoor";
532b6c0d6340dbc969b4c53f583775e7c49b440c403Johannes Berg	default:
5332b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		return "bogus";
534b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann	}
5352b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez}
5362b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
5372b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguezstatic void print_country(const uint8_t type, uint8_t len, const uint8_t *data)
5382b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez{
5392b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez	printf(" %.*s", 2, data);
5402b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
5412b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez	printf("\tEnvironment: %s\n", country_env_str(data[2]));
5422b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
5432b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez	data += 3;
5442b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez	len -= 3;
5452b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
5462b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez	if (len < 3) {
5472b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		printf("\t\tNo country IE triplets present\n");
5482b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		return;
5492b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez	}
5502b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
5512b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez	while (len >= 3) {
5522b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		int end_channel;
55372725719af644b0a3a673cc9f1c376a2c0ef62e2Johannes Berg		union ieee80211_country_ie_triplet *triplet = (void *) data;
5542b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
5552b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		if (triplet->ext.reg_extension_id >= IEEE80211_COUNTRY_EXTENSION_ID) {
5562b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez			printf("\t\tExtension ID: %d Regulatory Class: %d Coverage class: %d (up to %dm)\n",
5572b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez			       triplet->ext.reg_extension_id,
5582b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez			       triplet->ext.reg_class,
5592b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez			       triplet->ext.coverage_class,
5602b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez			       triplet->ext.coverage_class * 450);
5612b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
5622b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez			data += 3;
5632b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez			len -= 3;
5642b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez			continue;
5652b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		}
5662b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
5672b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		/* 2 GHz */
5682b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		if (triplet->chans.first_channel <= 14)
5692b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez			end_channel = triplet->chans.first_channel + (triplet->chans.num_channels - 1);
5702b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		else
5712b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez			end_channel =  triplet->chans.first_channel + (4 * (triplet->chans.num_channels - 1));
5722b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
573a9859d30ea1c19314d2d08285af9123714a4e6beLuis R. Rodriguez		printf("\t\tChannels [%d - %d] @ %d dBm\n", triplet->chans.first_channel, end_channel, triplet->chans.max_power);
5742b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
5752b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		data += 3;
5762b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez		len -= 3;
5772b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez	}
5782b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez
5792b690f0aba9d7365ad824ea5f932de8f2a80ba76Luis R. Rodriguez	return;
580b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann}
581b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann
582d1563a1b2d6e43fb12aeaa764c952cd2108b6862Marcel Holtmannstatic void print_powerconstraint(const uint8_t type, uint8_t len, const uint8_t *data)
583d1563a1b2d6e43fb12aeaa764c952cd2108b6862Marcel Holtmann{
584d1563a1b2d6e43fb12aeaa764c952cd2108b6862Marcel Holtmann	printf(" %d dB\n", data[0]);
585d1563a1b2d6e43fb12aeaa764c952cd2108b6862Marcel Holtmann}
586d1563a1b2d6e43fb12aeaa764c952cd2108b6862Marcel Holtmann
587792172b0f1dfbed179788e4944aaf4d4e0a91301Joerg Mayerstatic void print_tpcreport(const uint8_t type, uint8_t len, const uint8_t *data)
588792172b0f1dfbed179788e4944aaf4d4e0a91301Joerg Mayer{
589792172b0f1dfbed179788e4944aaf4d4e0a91301Joerg Mayer	printf(" TX power: %d dBm\n", data[0]);
590792172b0f1dfbed179788e4944aaf4d4e0a91301Joerg Mayer	/* printf(" Link Margin (%d dB) is reserved in Beacons\n", data[1]); */
591792172b0f1dfbed179788e4944aaf4d4e0a91301Joerg Mayer}
592792172b0f1dfbed179788e4944aaf4d4e0a91301Joerg Mayer
59383b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_erp(const uint8_t type, uint8_t len, const uint8_t *data)
594fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann{
595fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann	if (data[0] == 0x00)
59683b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		printf(" <no flags>");
597fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann	if (data[0] & 0x01)
598fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann		printf(" NonERP_Present");
599fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann	if (data[0] & 0x02)
600fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann		printf(" Use_Protection");
601fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann	if (data[0] & 0x04)
602fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann		printf(" Barker_Preamble_Mode");
603fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann	printf("\n");
604fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann}
605fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann
60683b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_cipher(const uint8_t *data)
607857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann{
6083bd60ef1276fc888fed699ee598b3b358d976f4cJohannes Berg	if (memcmp(data, ms_oui, 3) == 0) {
609857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		switch (data[3]) {
610510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 0:
611857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("Use group cipher suite");
612857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
613510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 1:
614857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("WEP-40");
615857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
616510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 2:
617857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("TKIP");
618857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
619510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 4:
620857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("CCMP");
621857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
622510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 5:
623857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("WEP-104");
624857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
625857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		default:
626332769c689e75f372bdae8ade290433b31eebc3eJohannes Berg			printf("%.02x-%.02x-%.02x:%d",
6275594fd2301775e7795899ed4ed3b8fff82551734Johannes Berg				data[0], data[1] ,data[2], data[3]);
628857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
629857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		}
630857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	} else if (memcmp(data, ieee80211_oui, 3) == 0) {
631857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		switch (data[3]) {
632510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 0:
633857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("Use group cipher suite");
634857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
635510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 1:
636857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("WEP-40");
637857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
638510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 2:
639857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("TKIP");
640857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
641510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 4:
642857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("CCMP");
643857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
644510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 5:
645857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("WEP-104");
646857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
647510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 6:
648857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("AES-128-CMAC");
649857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
650f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear		case 7:
651f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear			printf("NO-GROUP");
652f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear			break;
653a8b3da9df8d15b857b13887feccdd05c46c7347eVladimir Kondratiev		case 8:
654a8b3da9df8d15b857b13887feccdd05c46c7347eVladimir Kondratiev			printf("GCMP");
655a8b3da9df8d15b857b13887feccdd05c46c7347eVladimir Kondratiev			break;
656857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		default:
657332769c689e75f372bdae8ade290433b31eebc3eJohannes Berg			printf("%.02x-%.02x-%.02x:%d",
6585594fd2301775e7795899ed4ed3b8fff82551734Johannes Berg				data[0], data[1] ,data[2], data[3]);
659857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
660857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		}
661857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	} else
662332769c689e75f372bdae8ade290433b31eebc3eJohannes Berg		printf("%.02x-%.02x-%.02x:%d",
6635594fd2301775e7795899ed4ed3b8fff82551734Johannes Berg			data[0], data[1] ,data[2], data[3]);
664857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann}
665857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
66683b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_auth(const uint8_t *data)
667857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann{
6683bd60ef1276fc888fed699ee598b3b358d976f4cJohannes Berg	if (memcmp(data, ms_oui, 3) == 0) {
669857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		switch (data[3]) {
670510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 1:
671857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("IEEE 802.1X");
672857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
673510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 2:
674857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("PSK");
675857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
676857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		default:
677332769c689e75f372bdae8ade290433b31eebc3eJohannes Berg			printf("%.02x-%.02x-%.02x:%d",
6785594fd2301775e7795899ed4ed3b8fff82551734Johannes Berg				data[0], data[1] ,data[2], data[3]);
679857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
680857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		}
681857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	} else if (memcmp(data, ieee80211_oui, 3) == 0) {
682857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		switch (data[3]) {
683510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 1:
684857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("IEEE 802.1X");
685857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
686510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 2:
687857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("PSK");
688857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
6890fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg		case 3:
6900fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			printf("FT/IEEE 802.1X");
6910fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			break;
6920fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg		case 4:
6930fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			printf("FT/PSK");
6940fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			break;
6950fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg		case 5:
6960fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			printf("IEEE 802.1X/SHA-256");
6970fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			break;
6980fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg		case 6:
6990fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			printf("PSK/SHA-256");
7000fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			break;
7014361eef308869ae41395c8b32c5d9aa68d28e5aaJoerg Mayer		case 7:
7024361eef308869ae41395c8b32c5d9aa68d28e5aaJoerg Mayer			printf("TDLS/TPK");
7034361eef308869ae41395c8b32c5d9aa68d28e5aaJoerg Mayer			break;
704857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		default:
705332769c689e75f372bdae8ade290433b31eebc3eJohannes Berg			printf("%.02x-%.02x-%.02x:%d",
7065594fd2301775e7795899ed4ed3b8fff82551734Johannes Berg				data[0], data[1] ,data[2], data[3]);
707857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
708857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		}
709f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear	} else if (memcmp(data, wfa_oui, 3) == 0) {
710f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear		switch (data[3]) {
711f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear		case 1:
712f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear			printf("OSEN");
713f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear			break;
714f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear		default:
715f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear			printf("%.02x-%.02x-%.02x:%d",
716f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear				data[0], data[1] ,data[2], data[3]);
717f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear			break;
718f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear		}
719857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	} else
720332769c689e75f372bdae8ade290433b31eebc3eJohannes Berg		printf("%.02x-%.02x-%.02x:%d",
7215594fd2301775e7795899ed4ed3b8fff82551734Johannes Berg			data[0], data[1] ,data[2], data[3]);
722857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann}
723857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
724f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greearstatic void _print_rsn_ie(const char *defcipher, const char *defauth,
725f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear			  uint8_t len, const uint8_t *data, int is_osen)
726857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann{
727857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	bool first = true;
728f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear	__u16 count, capa;
729857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	int i;
730857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
731f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear	if (!is_osen) {
732f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear		__u16 version;
733f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear		version = data[0] + (data[1] << 8);
734f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear		tab_on_first(&first);
735f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear		printf("\t * Version: %d\n", version);
736857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
737f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear		data += 2;
738f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear		len -= 2;
739f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear	}
740857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
741857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	if (len < 4) {
742857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		tab_on_first(&first);
743857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf("\t * Group cipher: %s\n", defcipher);
744857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf("\t * Pairwise ciphers: %s\n", defcipher);
745857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		return;
746857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	}
747857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
748857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	tab_on_first(&first);
749857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	printf("\t * Group cipher: ");
750857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	print_cipher(data);
751857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	printf("\n");
752857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
753857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	data += 4;
754857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	len -= 4;
755857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
756857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	if (len < 2) {
757857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		tab_on_first(&first);
758857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf("\t * Pairwise ciphers: %s\n", defcipher);
759857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		return;
760857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	}
761857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
762857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	count = data[0] | (data[1] << 8);
76331d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann	if (2 + (count * 4) > len)
76431d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann		goto invalid;
76531d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann
766857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	tab_on_first(&first);
767857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	printf("\t * Pairwise ciphers:");
76831d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann	for (i = 0; i < count; i++) {
769857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf(" ");
770857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		print_cipher(data + 2 + (i * 4));
771857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	}
772857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	printf("\n");
773857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
774857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	data += 2 + (count * 4);
775857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	len -= 2 + (count * 4);
776857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
777857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	if (len < 2) {
778857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		tab_on_first(&first);
779857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf("\t * Authentication suites: %s\n", defauth);
780857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		return;
781857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	}
782857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
783857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	count = data[0] | (data[1] << 8);
78431d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann	if (2 + (count * 4) > len)
78531d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann		goto invalid;
78631d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann
787857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	tab_on_first(&first);
788857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	printf("\t * Authentication suites:");
78983b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	for (i = 0; i < count; i++) {
790857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf(" ");
791857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		print_auth(data + 2 + (i * 4));
792857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	}
793857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	printf("\n");
794857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
795857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	data += 2 + (count * 4);
796857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	len -= 2 + (count * 4);
797857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
7986a4f24e80e5e6d85bfd1c4d66b476b86e5fa35d3Johannes Berg	if (len >= 2) {
7996a4f24e80e5e6d85bfd1c4d66b476b86e5fa35d3Johannes Berg		capa = data[0] | (data[1] << 8);
8006a4f24e80e5e6d85bfd1c4d66b476b86e5fa35d3Johannes Berg		tab_on_first(&first);
801cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		printf("\t * Capabilities:");
802cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		if (capa & 0x0001)
803cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" PreAuth");
804cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		if (capa & 0x0002)
805cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" NoPairwise");
806cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		switch ((capa & 0x000c) >> 2) {
807cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 0:
8084361eef308869ae41395c8b32c5d9aa68d28e5aaJoerg Mayer			printf(" 1-PTKSA-RC");
809cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
810cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 1:
811cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" 2-PTKSA-RC");
812cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
813cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 2:
814cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" 4-PTKSA-RC");
815cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
816cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 3:
817cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" 16-PTKSA-RC");
818cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
819cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		}
820cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		switch ((capa & 0x0030) >> 4) {
821cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 0:
8224361eef308869ae41395c8b32c5d9aa68d28e5aaJoerg Mayer			printf(" 1-GTKSA-RC");
823cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
824cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 1:
825cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" 2-GTKSA-RC");
826cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
827cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 2:
828cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" 4-GTKSA-RC");
829cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
830cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 3:
831cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" 16-GTKSA-RC");
832cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
833cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		}
834cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		if (capa & 0x0040)
835cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" MFP-required");
836cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		if (capa & 0x0080)
837cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" MFP-capable");
838cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		if (capa & 0x0200)
839cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" Peerkey-enabled");
840cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		if (capa & 0x0400)
841cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" SPP-AMSDU-capable");
842cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		if (capa & 0x0800)
843cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" SPP-AMSDU-required");
844cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		printf(" (0x%.4x)\n", capa);
8456a4f24e80e5e6d85bfd1c4d66b476b86e5fa35d3Johannes Berg		data += 2;
8466a4f24e80e5e6d85bfd1c4d66b476b86e5fa35d3Johannes Berg		len -= 2;
8476a4f24e80e5e6d85bfd1c4d66b476b86e5fa35d3Johannes Berg	}
84831d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann
8495ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg	if (len >= 2) {
8505ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg		int pmkid_count = data[0] | (data[1] << 8);
8515ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg
8525ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg		if (len >= 2 + 16 * pmkid_count) {
8535ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg			tab_on_first(&first);
8545ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg			printf("\t * %d PMKIDs\n", pmkid_count);
8555ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg			/* not printing PMKID values */
8565ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg			data += 2 + 16 * pmkid_count;
8575ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg			len -= 2 + 16 * pmkid_count;
8585ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg		} else
8595ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg			goto invalid;
8605ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg	}
8615ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg
8625ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg	if (len >= 4) {
8635ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg		tab_on_first(&first);
8645ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg		printf("\t * Group mgmt cipher suite: ");
8655ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg		print_cipher(data);
8665ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg		printf("\n");
8675ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg		data += 4;
8685ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg		len -= 4;
8695ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg	}
8705ba3f5236af15d045c3278194fd198a1addd3868Johannes Berg
871cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg invalid:
87231d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann	if (len != 0) {
87331d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann		printf("\t\t * bogus tail data (%d):", len);
87431d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann		while (len) {
87531d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann			printf(" %.2x", *data);
87631d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann			data++;
87731d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann			len--;
87831d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann		}
87931d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann		printf("\n");
88031d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann	}
881857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann}
882857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
883f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greearstatic void print_rsn_ie(const char *defcipher, const char *defauth,
884f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear			 uint8_t len, const uint8_t *data)
885f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear{
886f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear	_print_rsn_ie(defcipher, defauth, len, data, 0);
887f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear}
888f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear
889f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greearstatic void print_osen_ie(const char *defcipher, const char *defauth,
890f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear			  uint8_t len, const uint8_t *data)
891f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear{
892f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear	printf("\n\t");
893f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear	_print_rsn_ie(defcipher, defauth, len, data, 1);
894f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear}
895f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear
89683b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_rsn(const uint8_t type, uint8_t len, const uint8_t *data)
897857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann{
89883b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	print_rsn_ie("CCMP", "IEEE 802.1X", len, data);
899857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann}
900857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
9010c445c24c51e634af042fd10aa87e558a53699daLuis R. Rodriguezstatic void print_ht_capa(const uint8_t type, uint8_t len, const uint8_t *data)
9020c445c24c51e634af042fd10aa87e558a53699daLuis R. Rodriguez{
903357c1a5df13f722027977a915cfd16a38bba3966Luis R. Rodriguez	printf("\n");
9047ddfb67953809357249e5a6f4293cebf59a4ad9bJohannes Berg	print_ht_capability(data[0] | (data[1] << 8));
9057ddfb67953809357249e5a6f4293cebf59a4ad9bJohannes Berg	print_ampdu_length(data[2] & 3);
906c79c746440d22401d0aa8522bed2820f60eed2cdChristian Lamparter	print_ampdu_spacing((data[2] >> 2) & 7);
9077ddfb67953809357249e5a6f4293cebf59a4ad9bJohannes Berg	print_ht_mcs(data + 3);
9080c445c24c51e634af042fd10aa87e558a53699daLuis R. Rodriguez}
9090c445c24c51e634af042fd10aa87e558a53699daLuis R. Rodriguez
910489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greearstatic const char* ntype_11u(uint8_t t)
911489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear{
912489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	switch (t) {
913489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	case 0: return "Private";
914489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	case 1: return "Private with Guest";
915489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	case 2: return "Chargeable Public";
916489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	case 3: return "Free Public";
917489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	case 4: return "Personal Device";
918489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	case 5: return "Emergency Services Only";
919489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	case 14: return "Test or Experimental";
920489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	case 15: return "Wildcard";
921489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	default: return "Reserved";
922489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	}
923489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear}
924489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear
925489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greearstatic const char* vgroup_11u(uint8_t t)
926489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear{
927489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	switch (t) {
928489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	case 0: return "Unspecified";
929489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	case 1: return "Assembly";
930489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	case 2: return "Business";
931489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	case 3: return "Educational";
932489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	case 4: return "Factory and Industrial";
933489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	case 5: return "Institutional";
934489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	case 6: return "Mercantile";
935489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	case 7: return "Residential";
936489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	case 8: return "Storage";
937489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	case 9: return "Utility and Miscellaneous";
938489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	case 10: return "Vehicular";
939489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	case 11: return "Outdoor";
940489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	default: return "Reserved";
941489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	}
942489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear}
943489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear
944489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greearstatic void print_interworking(const uint8_t type, uint8_t len, const uint8_t *data)
945489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear{
946489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	/* See Section 7.3.2.92 in the 802.11u spec. */
947489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	printf("\n");
948489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	if (len >= 1) {
949489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear		uint8_t ano = data[0];
950489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear		printf("\t\tNetwork Options: 0x%hx\n", (unsigned short)(ano));
951489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear		printf("\t\t\tNetwork Type: %i (%s)\n",
952489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear		       (int)(ano & 0xf), ntype_11u(ano & 0xf));
953489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear		if (ano & (1<<4))
954489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear			printf("\t\t\tInternet\n");
955489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear		if (ano & (1<<5))
956489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear			printf("\t\t\tASRA\n");
957489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear		if (ano & (1<<6))
958489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear			printf("\t\t\tESR\n");
959489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear		if (ano & (1<<7))
960489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear			printf("\t\t\tUESA\n");
961489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	}
962489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	if ((len == 3) || (len == 9)) {
963489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear		printf("\t\tVenue Group: %i (%s)\n",
964489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear		       (int)(data[1]), vgroup_11u(data[1]));
965489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear		printf("\t\tVenue Type: %i\n", (int)(data[2]));
966489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	}
967489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	if (len == 9)
968489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear		printf("\t\tHESSID: %02hx:%02hx:%02hx:%02hx:%02hx:%02hx\n",
969489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear		       data[3], data[4], data[5], data[6], data[7], data[8]);
970489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	else if (len == 7)
971489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear		printf("\t\tHESSID: %02hx:%02hx:%02hx:%02hx:%02hx:%02hx\n",
972489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear		       data[1], data[2], data[3], data[4], data[5], data[6]);
973489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear}
974489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear
9753f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greearstatic void print_11u_advert(const uint8_t type, uint8_t len, const uint8_t *data)
9763f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear{
9773f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear	/* See Section 7.3.2.93 in the 802.11u spec. */
9783f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear	/* TODO: This code below does not decode private protocol IDs */
9793f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear	int idx = 0;
9803f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear	printf("\n");
9813f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear	while (idx < (len - 1)) {
9823f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear		uint8_t qri = data[idx];
9833f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear		uint8_t proto_id = data[idx + 1];
9843f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear		printf("\t\tQuery Response Info: 0x%hx\n", (unsigned short)(qri));
9853f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear		printf("\t\t\tQuery Response Length Limit: %i\n",
9863f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear		       (qri & 0x7f));
9873f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear		if (qri & (1<<7))
9883f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear			printf("\t\t\tPAME-BI\n");
9893f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear		switch(proto_id) {
9903f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear		case 0:
9913f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear			printf("\t\t\tANQP\n"); break;
9923f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear		case 1:
9933f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear			printf("\t\t\tMIH Information Service\n"); break;
9943f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear		case 2:
9953f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear			printf("\t\t\tMIH Command and Event Services Capability Discovery\n"); break;
9963f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear		case 3:
9973f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear			printf("\t\t\tEmergency Alert System (EAS)\n"); break;
9983f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear		case 221:
9993f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear			printf("\t\t\tVendor Specific\n"); break;
10003f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear		default:
10013f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear			printf("\t\t\tReserved: %i\n", proto_id); break;
10023f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear		}
10033f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear		idx += 2;
10043f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear	}
10053f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear}
10063f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear
1007bc9e14f1271413bedf655750d09d7053df09279bBen Greearstatic void print_11u_rcon(const uint8_t type, uint8_t len, const uint8_t *data)
1008bc9e14f1271413bedf655750d09d7053df09279bBen Greear{
1009bc9e14f1271413bedf655750d09d7053df09279bBen Greear	/* See Section 7.3.2.96 in the 802.11u spec. */
1010bc9e14f1271413bedf655750d09d7053df09279bBen Greear	int idx = 0;
1011bc9e14f1271413bedf655750d09d7053df09279bBen Greear	int ln0 = data[1] & 0xf;
1012bc9e14f1271413bedf655750d09d7053df09279bBen Greear	int ln1 = ((data[1] & 0xf0) >> 4);
1013bc9e14f1271413bedf655750d09d7053df09279bBen Greear	int ln2 = 0;
1014bc9e14f1271413bedf655750d09d7053df09279bBen Greear	printf("\n");
1015bc9e14f1271413bedf655750d09d7053df09279bBen Greear
1016bc9e14f1271413bedf655750d09d7053df09279bBen Greear	if (ln1)
1017bc9e14f1271413bedf655750d09d7053df09279bBen Greear		ln2 = len - 2 - ln0 - ln1;
1018bc9e14f1271413bedf655750d09d7053df09279bBen Greear
1019bc9e14f1271413bedf655750d09d7053df09279bBen Greear	printf("\t\tANQP OIs: %i\n", data[0]);
1020bc9e14f1271413bedf655750d09d7053df09279bBen Greear
1021bc9e14f1271413bedf655750d09d7053df09279bBen Greear	if (ln0 > 0) {
1022bc9e14f1271413bedf655750d09d7053df09279bBen Greear		printf("\t\tOI 1: ");
1023bc9e14f1271413bedf655750d09d7053df09279bBen Greear		if (2 + ln0 > len) {
1024bc9e14f1271413bedf655750d09d7053df09279bBen Greear			printf("Invalid IE length.\n");
1025bc9e14f1271413bedf655750d09d7053df09279bBen Greear		} else {
1026bc9e14f1271413bedf655750d09d7053df09279bBen Greear			for (idx = 0; idx < ln0; idx++) {
1027bc9e14f1271413bedf655750d09d7053df09279bBen Greear				printf("%02hx", data[2 + idx]);
1028bc9e14f1271413bedf655750d09d7053df09279bBen Greear			}
1029bc9e14f1271413bedf655750d09d7053df09279bBen Greear			printf("\n");
1030bc9e14f1271413bedf655750d09d7053df09279bBen Greear		}
1031bc9e14f1271413bedf655750d09d7053df09279bBen Greear	}
1032bc9e14f1271413bedf655750d09d7053df09279bBen Greear
1033bc9e14f1271413bedf655750d09d7053df09279bBen Greear	if (ln1 > 0) {
1034bc9e14f1271413bedf655750d09d7053df09279bBen Greear		printf("\t\tOI 2: ");
1035bc9e14f1271413bedf655750d09d7053df09279bBen Greear		if (2 + ln0 + ln1 > len) {
1036bc9e14f1271413bedf655750d09d7053df09279bBen Greear			printf("Invalid IE length.\n");
1037bc9e14f1271413bedf655750d09d7053df09279bBen Greear		} else {
1038bc9e14f1271413bedf655750d09d7053df09279bBen Greear			for (idx = 0; idx < ln1; idx++) {
1039bc9e14f1271413bedf655750d09d7053df09279bBen Greear				printf("%02hx", data[2 + ln0 + idx]);
1040bc9e14f1271413bedf655750d09d7053df09279bBen Greear			}
1041bc9e14f1271413bedf655750d09d7053df09279bBen Greear			printf("\n");
1042bc9e14f1271413bedf655750d09d7053df09279bBen Greear		}
1043bc9e14f1271413bedf655750d09d7053df09279bBen Greear	}
1044bc9e14f1271413bedf655750d09d7053df09279bBen Greear
1045bc9e14f1271413bedf655750d09d7053df09279bBen Greear	if (ln2 > 0) {
1046bc9e14f1271413bedf655750d09d7053df09279bBen Greear		printf("\t\tOI 3: ");
1047bc9e14f1271413bedf655750d09d7053df09279bBen Greear		if (2 + ln0 + ln1 + ln2 > len) {
1048bc9e14f1271413bedf655750d09d7053df09279bBen Greear			printf("Invalid IE length.\n");
1049bc9e14f1271413bedf655750d09d7053df09279bBen Greear		} else {
1050bc9e14f1271413bedf655750d09d7053df09279bBen Greear			for (idx = 0; idx < ln2; idx++) {
1051bc9e14f1271413bedf655750d09d7053df09279bBen Greear				printf("%02hx", data[2 + ln0 + ln1 + idx]);
1052bc9e14f1271413bedf655750d09d7053df09279bBen Greear			}
1053bc9e14f1271413bedf655750d09d7053df09279bBen Greear			printf("\n");
1054bc9e14f1271413bedf655750d09d7053df09279bBen Greear		}
1055bc9e14f1271413bedf655750d09d7053df09279bBen Greear	}
1056bc9e14f1271413bedf655750d09d7053df09279bBen Greear}
1057bc9e14f1271413bedf655750d09d7053df09279bBen Greear
105829f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Bergstatic const char *ht_secondary_offset[4] = {
105929f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	"no secondary",
106029f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	"above",
106129f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	"[reserved!]",
106229f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	"below",
106329f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg};
106429f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg
1065be7602fb865fcef72924c926729650c0db9cf254Johannes Bergstatic void print_ht_op(const uint8_t type, uint8_t len, const uint8_t *data)
1066be7602fb865fcef72924c926729650c0db9cf254Johannes Berg{
1067be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	static const char *protection[4] = {
1068be7602fb865fcef72924c926729650c0db9cf254Johannes Berg		"no",
1069be7602fb865fcef72924c926729650c0db9cf254Johannes Berg		"nonmember",
1070be7602fb865fcef72924c926729650c0db9cf254Johannes Berg		"20 MHz",
1071be7602fb865fcef72924c926729650c0db9cf254Johannes Berg		"non-HT mixed",
1072be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	};
1073be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	static const char *sta_chan_width[2] = {
1074be7602fb865fcef72924c926729650c0db9cf254Johannes Berg		"20 MHz",
1075be7602fb865fcef72924c926729650c0db9cf254Johannes Berg		"any",
1076be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	};
1077be7602fb865fcef72924c926729650c0db9cf254Johannes Berg
1078be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\n");
1079be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * primary channel: %d\n", data[0]);
1080be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * secondary channel offset: %s\n",
108129f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg		ht_secondary_offset[data[1] & 0x3]);
1082be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * STA channel width: %s\n", sta_chan_width[(data[1] & 0x4)>>2]);
1083be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * RIFS: %d\n", (data[1] & 0x8)>>3);
1084be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * HT protection: %s\n", protection[data[2] & 0x3]);
1085be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * non-GF present: %d\n", (data[2] & 0x4) >> 2);
1086be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * OBSS non-GF present: %d\n", (data[2] & 0x10) >> 4);
1087be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * dual beacon: %d\n", (data[4] & 0x40) >> 6);
1088be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * dual CTS protection: %d\n", (data[4] & 0x80) >> 7);
1089be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * STBC beacon: %d\n", data[5] & 0x1);
1090be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * L-SIG TXOP Prot: %d\n", (data[5] & 0x2) >> 1);
1091be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * PCO active: %d\n", (data[5] & 0x4) >> 2);
1092be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	printf("\t\t * PCO phase: %d\n", (data[5] & 0x8) >> 3);
1093be7602fb865fcef72924c926729650c0db9cf254Johannes Berg}
1094be7602fb865fcef72924c926729650c0db9cf254Johannes Berg
109583b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_capabilities(const uint8_t type, uint8_t len, const uint8_t *data)
10969b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann{
109731d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg	int i, base, bit;
109831d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg	bool first = true;
109931d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg
110031d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg
110131d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg	for (i = 0; i < len; i++) {
110231d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg		base = i * 8;
110331d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg
110431d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg		for (bit = 0; bit < 8; bit++) {
110531d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			if (!(data[i] & (1 << bit)))
110631d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				continue;
110731d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg
110831d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			if (!first)
110931d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				printf(",");
111031d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			else
111131d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				first = false;
111231d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg
111370c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg#define CAPA(bit, name)		case bit: printf(" " name); break
111470c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg
111531d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			switch (bit + base) {
111670c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(0, "HT Information Exchange Supported");
111770c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(1, "reserved (On-demand Beacon)");
111870c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(2, "Extended Channel Switching");
111970c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(3, "reserved (Wave Indication)");
112070c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(4, "PSMP Capability");
112170c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(5, "reserved (Service Interval Granularity)");
112270c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(6, "S-PSMP Capability");
112370c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(7, "Event");
112470c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(8, "Diagnostics");
112570c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(9, "Multicast Diagnostics");
112670c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(10, "Location Tracking");
112770c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(11, "FMS");
112870c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(12, "Proxy ARP Service");
112970c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(13, "Collocated Interference Reporting");
113070c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(14, "Civic Location");
113170c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(15, "Geospatial Location");
113270c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(16, "TFS");
113370c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(17, "WNM-Sleep Mode");
113470c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(18, "TIM Broadcast");
113570c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(19, "BSS Transition");
113670c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(20, "QoS Traffic Capability");
113770c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(21, "AC Station Count");
113870c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(22, "Multiple BSSID");
113970c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(23, "Timing Measurement");
114070c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(24, "Channel Usage");
114170c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(25, "SSID List");
114270c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(26, "DMS");
114370c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(27, "UTC TSF Offset");
114470c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(28, "TDLS Peer U-APSD Buffer STA Support");
114570c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(29, "TDLS Peer PSM Support");
114670c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(30, "TDLS channel switching");
114770c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(31, "Interworking");
114870c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(32, "QoS Map");
114970c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(33, "EBR");
115070c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(34, "SSPN Interface");
115170c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(35, "Reserved");
115270c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(36, "MSGCF Capability");
115370c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(37, "TDLS Support");
115470c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(38, "TDLS Prohibited");
115570c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(39, "TDLS Channel Switching Prohibited");
115670c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(40, "Reject Unadmitted Frame");
115770c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(44, "Identifier Location");
115870c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(45, "U-APSD Coexistence");
115970c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(46, "WNM-Notification");
116070c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(47, "Reserved");
116170c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg			CAPA(48, "UTF-8 SSID");
116231d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			default:
116331d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				printf(" %d", bit);
116431d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				break;
116531d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			}
116670c649d290f8e7de7e88000e45e0982b876dd84fJohannes Berg#undef CAPA
116731d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg		}
116831d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg	}
11699b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann
11709b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann	printf("\n");
11719b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann}
11729b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann
1173575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinenstatic void print_tim(const uint8_t type, uint8_t len, const uint8_t *data)
1174575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen{
1175575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen	printf(" DTIM Count %u DTIM Period %u Bitmap Control 0x%x "
1176575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen	       "Bitmap[0] 0x%x",
1177575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen	       data[0], data[1], data[2], data[3]);
1178575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen	if (len - 4)
1179575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen		printf(" (+ %u octet%s)", len - 4, len - 4 == 1 ? "" : "s");
1180575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen	printf("\n");
1181575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen}
1182575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen
1183792172b0f1dfbed179788e4944aaf4d4e0a91301Joerg Mayerstatic void print_ibssatim(const uint8_t type, uint8_t len, const uint8_t *data)
1184792172b0f1dfbed179788e4944aaf4d4e0a91301Joerg Mayer{
1185792172b0f1dfbed179788e4944aaf4d4e0a91301Joerg Mayer	printf(" %d TUs", (data[1] << 8) + data[0]);
1186792172b0f1dfbed179788e4944aaf4d4e0a91301Joerg Mayer}
1187792172b0f1dfbed179788e4944aaf4d4e0a91301Joerg Mayer
118854eb1613e695d72a71d7210b238a30e0ab2d5a3fJohannes Bergstatic void print_vht_capa(const uint8_t type, uint8_t len, const uint8_t *data)
118954eb1613e695d72a71d7210b238a30e0ab2d5a3fJohannes Berg{
119054eb1613e695d72a71d7210b238a30e0ab2d5a3fJohannes Berg	printf("\n");
119154eb1613e695d72a71d7210b238a30e0ab2d5a3fJohannes Berg	print_vht_info(data[0] | (data[1] << 8) |
119254eb1613e695d72a71d7210b238a30e0ab2d5a3fJohannes Berg		       (data[2] << 16) | (data[3] << 24),
119354eb1613e695d72a71d7210b238a30e0ab2d5a3fJohannes Berg		       data + 4);
119454eb1613e695d72a71d7210b238a30e0ab2d5a3fJohannes Berg}
119554eb1613e695d72a71d7210b238a30e0ab2d5a3fJohannes Berg
1196ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Bergstatic void print_vht_oper(const uint8_t type, uint8_t len, const uint8_t *data)
1197ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg{
1198ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg	const char *chandwidths[] = {
1199ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg		[0] = "20 or 40 MHz",
1200ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg		[1] = "80 MHz",
1201ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg		[3] = "80+80 MHz",
1202ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg		[2] = "160 MHz",
1203ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg	};
1204ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg
1205ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg	printf("\n");
1206ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg	printf("\t\t * channel width: %d (%s)\n", data[0],
1207ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg		data[0] < ARRAY_SIZE(chandwidths) ? chandwidths[data[0]] : "unknown");
1208ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg	printf("\t\t * center freq segment 1: %d\n", data[1]);
1209ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg	printf("\t\t * center freq segment 2: %d\n", data[2]);
1210ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg	printf("\t\t * VHT basic MCS set: 0x%.2x%.2x\n", data[4], data[3]);
1211ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg}
1212ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg
121329f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Bergstatic void print_obss_scan_params(const uint8_t type, uint8_t len, const uint8_t *data)
121429f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg{
121529f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\n");
121629f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\t\t * passive dwell: %d TUs\n", (data[1] << 8) | data[0]);
121729f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\t\t * active dwell: %d TUs\n", (data[3] << 8) | data[2]);
121829f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\t\t * channel width trigger scan interval: %d s\n", (data[5] << 8) | data[4]);
121929f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\t\t * scan passive total per channel: %d TUs\n", (data[7] << 8) | data[6]);
122029f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\t\t * scan active total per channel: %d TUs\n", (data[9] << 8) | data[8]);
122129f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\t\t * BSS width channel transition delay factor: %d\n", (data[11] << 8) | data[10]);
122229f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\t\t * OBSS Scan Activity Threshold: %d.%02d %%\n",
122329f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg		((data[13] << 8) | data[12]) / 100, ((data[13] << 8) | data[12]) % 100);
122429f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg}
122529f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg
122629f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Bergstatic void print_secchan_offs(const uint8_t type, uint8_t len, const uint8_t *data)
122729f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg{
122829f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	if (data[0] < ARRAY_SIZE(ht_secondary_offset))
122929f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg		printf(" %s (%d)\n", ht_secondary_offset[data[0]], data[0]);
123029f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	else
123129f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg		printf(" %d\n", data[0]);
123229f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg}
123329f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg
123429f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Bergstatic void print_bss_load(const uint8_t type, uint8_t len, const uint8_t *data)
123529f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg{
123629f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\n");
123729f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\t\t * station count: %d\n", (data[1] << 8) | data[0]);
123829f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\t\t * channel utilisation: %d/255\n", data[2]);
123929f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	printf("\t\t * available admission capacity: %d [*32us]\n", (data[4] << 8) | data[3]);
124029f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg}
124129f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg
12422d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeohstatic void print_mesh_conf(const uint8_t type, uint8_t len, const uint8_t *data)
12432d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh{
12442d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh	printf("\n");
12452d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh	printf("\t\t * Active Path Selection Protocol ID: %d\n", data[0]);
12462d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh	printf("\t\t * Active Path Selection Metric ID: %d\n", data[1]);
12472d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh	printf("\t\t * Congestion Control Mode ID: %d\n", data[2]);
12482d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh	printf("\t\t * Synchronization Method ID: %d\n", data[3]);
12492d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh	printf("\t\t * Authentication Protocol ID: %d\n", data[4]);
12502d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh	printf("\t\t * Mesh Formation Info:\n");
12512d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh	printf("\t\t\t Number of Peerings: %d\n", (data[5] & 0x7E) >> 1);
12522d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh	if (data[5] & 0x01)
12532d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh		printf("\t\t\t Connected to Mesh Gate\n");
12542d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh	if (data[5] & 0x80)
12552d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh		printf("\t\t\t Connected to AS\n");
12562d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh	printf("\t\t * Mesh Capability\n");
12572d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh	if (data[6] & 0x01)
12582d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh		printf("\t\t\t Accepting Additional Mesh Peerings\n");
12592d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh	if (data[6] & 0x02)
12602d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh		printf("\t\t\t MCCA Supported\n");
12612d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh	if (data[6] & 0x04)
12622d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh		printf("\t\t\t MCCA Enabled\n");
12632d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh	if (data[6] & 0x08)
12642d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh		printf("\t\t\t Forwarding\n");
12652d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh	if (data[6] & 0x10)
12662d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh		printf("\t\t\t MBCA Supported\n");
12672d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh	if (data[6] & 0x20)
12682d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh		printf("\t\t\t TBTT Adjusting\n");
12692d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh	if (data[6] & 0x40)
12702d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh		printf("\t\t\t Mesh Power Save Level\n");
12712d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh}
12722d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh
127383b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstruct ie_print {
127483b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	const char *name;
127583b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	void (*print)(const uint8_t type, uint8_t len, const uint8_t *data);
127683b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	uint8_t minlen, maxlen;
1277febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	uint8_t flags;
1278764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg};
1279764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg
128083b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_ie(const struct ie_print *p, const uint8_t type,
128183b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		     uint8_t len, const uint8_t *data)
12824673a894dae2780e395204eab01af4d40220b9f5Johannes Berg{
128383b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	int i;
128483b4934c612b84c28a656d496bea056e37fccb99Johannes Berg
128583b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	if (!p->print)
128683b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		return;
128783b4934c612b84c28a656d496bea056e37fccb99Johannes Berg
128883b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	printf("\t%s:", p->name);
128983b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	if (len < p->minlen || len > p->maxlen) {
129083b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		if (len > 1) {
129183b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			printf(" <invalid: %d bytes:", len);
129283b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			for (i = 0; i < len; i++)
129383b4934c612b84c28a656d496bea056e37fccb99Johannes Berg				printf(" %.02x", data[i]);
129483b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			printf(">\n");
129583b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		} else if (len)
129683b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			printf(" <invalid: 1 byte: %.02x>\n", data[0]);
129783b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		else
129883b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			printf(" <invalid: no data>\n");
129983b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		return;
130083b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	}
130183b4934c612b84c28a656d496bea056e37fccb99Johannes Berg
130283b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	p->print(type, len, data);
130383b4934c612b84c28a656d496bea056e37fccb99Johannes Berg}
130483b4934c612b84c28a656d496bea056e37fccb99Johannes Berg
130583b4934c612b84c28a656d496bea056e37fccb99Johannes Berg#define PRINT_IGN {		\
130683b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	.name = "IGNORE",	\
130783b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	.print = NULL,		\
130883b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	.minlen = 0,		\
130983b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	.maxlen = 255,		\
13104673a894dae2780e395204eab01af4d40220b9f5Johannes Berg}
13114673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
131283b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic const struct ie_print ieprinters[] = {
1313febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[0] = { "SSID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), },
1314febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[1] = { "Supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), },
1315014d581a9292b35d54e76793ec216ba15c2ec69cJohannes Berg	[3] = { "DS Parameter set", print_ds, 1, 1, BIT(PRINT_SCAN), },
1316575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen	[5] = { "TIM", print_tim, 4, 255, BIT(PRINT_SCAN), },
1317792172b0f1dfbed179788e4944aaf4d4e0a91301Joerg Mayer	[6] = { "IBSS ATIM window", print_ibssatim, 2, 2, BIT(PRINT_SCAN), },
1318febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[7] = { "Country", print_country, 3, 255, BIT(PRINT_SCAN), },
131929f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	[11] = { "BSS Load", print_bss_load, 5, 5, BIT(PRINT_SCAN), },
1320febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[32] = { "Power constraint", print_powerconstraint, 1, 1, BIT(PRINT_SCAN), },
1321792172b0f1dfbed179788e4944aaf4d4e0a91301Joerg Mayer	[35] = { "TPC report", print_tpcreport, 2, 2, BIT(PRINT_SCAN), },
1322febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[42] = { "ERP", print_erp, 1, 255, BIT(PRINT_SCAN), },
1323a2e61861abd4037ab29ddf4382c5d2f925c1be66Johannes Berg	[45] = { "HT capabilities", print_ht_capa, 26, 26, BIT(PRINT_SCAN), },
1324792172b0f1dfbed179788e4944aaf4d4e0a91301Joerg Mayer	[47] = { "ERP D4.0", print_erp, 1, 255, BIT(PRINT_SCAN), },
132529f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	[74] = { "Overlapping BSS scan params", print_obss_scan_params, 14, 255, BIT(PRINT_SCAN), },
1326be7602fb865fcef72924c926729650c0db9cf254Johannes Berg	[61] = { "HT operation", print_ht_op, 22, 22, BIT(PRINT_SCAN), },
132729f7579e27e0027ae663a05b3072dbd07f30b78aJohannes Berg	[62] = { "Secondary Channel Offset", print_secchan_offs, 1, 1, BIT(PRINT_SCAN), },
132854eb1613e695d72a71d7210b238a30e0ab2d5a3fJohannes Berg	[191] = { "VHT capabilities", print_vht_capa, 12, 255, BIT(PRINT_SCAN), },
1329ca1599346b55aa4d9ca8ca85ec59036f15a8f686Johannes Berg	[192] = { "VHT operation", print_vht_oper, 5, 255, BIT(PRINT_SCAN), },
1330febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[48] = { "RSN", print_rsn, 2, 255, BIT(PRINT_SCAN), },
1331febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[50] = { "Extended supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), },
13322d86b0f3334801e4d63576096810d9c963c3413dChun-Yeow Yeoh	[113] = { "MESH Configuration", print_mesh_conf, 7, 7, BIT(PRINT_SCAN), },
1333720583e9a9fce9b760b8794118e7a5d54cb428f5Chun-Yeow Yeoh	[114] = { "MESH ID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), },
1334febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[127] = { "Extended capabilities", print_capabilities, 0, 255, BIT(PRINT_SCAN), },
1335489f0ea93ea4dd6f7cd6eea9eea6f6ff77e1d251Ben Greear	[107] = { "802.11u Interworking", print_interworking, 0, 255, BIT(PRINT_SCAN), },
13363f818f6d74a351d092ec18ecaa1118d2bcf7bf71Ben Greear	[108] = { "802.11u Advertisement", print_11u_advert, 0, 255, BIT(PRINT_SCAN), },
1337bc9e14f1271413bedf655750d09d7053df09279bBen Greear	[111] = { "802.11u Roaming Consortium", print_11u_rcon, 0, 255, BIT(PRINT_SCAN), },
133883b4934c612b84c28a656d496bea056e37fccb99Johannes Berg};
133983b4934c612b84c28a656d496bea056e37fccb99Johannes Berg
134083b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_wifi_wpa(const uint8_t type, uint8_t len, const uint8_t *data)
134183b4934c612b84c28a656d496bea056e37fccb99Johannes Berg{
134283b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	print_rsn_ie("TKIP", "IEEE 802.1X", len, data);
134383b4934c612b84c28a656d496bea056e37fccb99Johannes Berg}
134483b4934c612b84c28a656d496bea056e37fccb99Johannes Berg
1345f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greearstatic void print_wifi_osen(const uint8_t type, uint8_t len, const uint8_t *data)
1346f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear{
1347f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear	print_osen_ie("OSEN", "OSEN", len, data);
1348f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear}
1349f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear
13501cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Bergstatic bool print_wifi_wmm_param(const uint8_t *data, uint8_t len)
13511cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg{
13521cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	int i;
13531cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	static const char *aci_tbl[] = { "BE", "BK", "VI", "VO" };
13541cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg
13551cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	if (len < 19)
13561cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg		goto invalid;
13571cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg
13581cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	if (data[0] != 1) {
1359cee4fe2039a01208fbbae45dda1c7d3bbfbe5f36Johannes Berg		printf("Parameter: not version 1: ");
13601cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg		return false;
13611cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	}
13621cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg
136389ea706f0a177ff6e78b207bc08143d2d149dd08Marcel Holtmann	printf("\t * Parameter version 1");
13641cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg
13651cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	data++;
13661cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg
13671cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	if (data[0] & 0x80)
136889ea706f0a177ff6e78b207bc08143d2d149dd08Marcel Holtmann		printf("\n\t\t * u-APSD");
13691cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg
13701cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	data += 2;
13711cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg
13721cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	for (i = 0; i < 4; i++) {
137389ea706f0a177ff6e78b207bc08143d2d149dd08Marcel Holtmann		printf("\n\t\t * %s:", aci_tbl[(data[0] >> 5) & 3]);
137487181516675a6d6a2ce0d6ce53b4ba601b62d427Yoni Divinsky		if (data[0] & 0x10)
13751cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg			printf(" acm");
13761cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg		printf(" CW %d-%d", (1 << (data[1] & 0xf)) - 1,
13771cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg				    (1 << (data[1] >> 4)) - 1);
1378a2a4c265af2e322e245b4fc1962d93a38da61f7aJohannes Berg		printf(", AIFSN %d", data[0] & 0xf);
13791cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg		if (data[2] | data[3])
1380cee4fe2039a01208fbbae45dda1c7d3bbfbe5f36Johannes Berg			printf(", TXOP %d usec", (data[2] + (data[3] << 8)) * 32);
13811cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg		data += 4;
13821cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	}
13831cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg
13841cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	printf("\n");
13851cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	return true;
13861cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg
13871cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg invalid:
13881cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg 	printf("invalid: ");
13891cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg 	return false;
13901cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg}
13911cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg
139283b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_wifi_wmm(const uint8_t type, uint8_t len, const uint8_t *data)
13936ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann{
13946ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann	int i;
13956ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann
13966ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann	switch (data[0]) {
13976ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann	case 0x00:
139883b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		printf(" information:");
13996ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann		break;
14006ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann	case 0x01:
14011cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg		if (print_wifi_wmm_param(data + 1, len - 1))
14021cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg			return;
14036ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann		break;
14046ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann	default:
140583b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		printf(" type %d:", data[0]);
14066ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann		break;
14076ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann	}
14086ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann
14091cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg	for(i = 1; i < len; i++)
14101cab57eba4e42cc1dd26dd213807f58f98c71167Johannes Berg		printf(" %.02x", data[i]);
14116ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann	printf("\n");
14126ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann}
14136ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann
1414a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinenstatic const char * wifi_wps_dev_passwd_id(uint16_t id)
1415a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen{
1416a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen	switch (id) {
1417a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen	case 0:
1418a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		return "Default (PIN)";
1419a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen	case 1:
1420a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		return "User-specified";
1421a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen	case 2:
1422a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		return "Machine-specified";
1423a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen	case 3:
1424a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		return "Rekey";
1425a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen	case 4:
1426a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		return "PushButton";
1427a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen	case 5:
1428a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		return "Registrar-specified";
1429a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen	default:
1430a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		return "??";
1431a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen	}
1432a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen}
1433a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen
143483b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_wifi_wps(const uint8_t type, uint8_t len, const uint8_t *data)
14354673a894dae2780e395204eab01af4d40220b9f5Johannes Berg{
14364673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	bool first = true;
14374673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	__u16 subtype, sublen;
14384673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
14394673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	while (len >= 4) {
14404673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		subtype = (data[0] << 8) + data[1];
14414673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		sublen = (data[2] << 8) + data[3];
14424673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		if (sublen > len)
14434673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			break;
14444673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
14454673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		switch (subtype) {
14464673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		case 0x104a:
14474673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			tab_on_first(&first);
1448dffc6750fec6d97a4fc55a687836cd6437be76e2Johannes Berg			printf("\t * Version: %d.%d\n", data[4] >> 4, data[4] & 0xF);
14494673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			break;
14504673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		case 0x1011:
14514673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			tab_on_first(&first);
14524673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf("\t * Device name: %.*s\n", sublen, data + 4);
14534673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			break;
1454a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		case 0x1012: {
1455a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			uint16_t id;
1456a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			tab_on_first(&first);
1457a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			if (sublen != 2) {
1458a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen				printf("\t * Device Password ID: (invalid "
1459a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen				       "length %d)\n", sublen);
1460a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen				break;
1461a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			}
1462a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			id = data[4] << 8 | data[5];
1463a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			printf("\t * Device Password ID: %u (%s)\n",
1464a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			       id, wifi_wps_dev_passwd_id(id));
1465a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			break;
1466a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		}
14674673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		case 0x1021:
14684673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			tab_on_first(&first);
14694673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf("\t * Manufacturer: %.*s\n", sublen, data + 4);
14704673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			break;
14714673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		case 0x1023:
14724673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			tab_on_first(&first);
14734673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf("\t * Model: %.*s\n", sublen, data + 4);
14744673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			break;
1475a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		case 0x1024:
1476a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			tab_on_first(&first);
1477a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			printf("\t * Model Number: %.*s\n", sublen, data + 4);
1478a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			break;
1479a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		case 0x103b: {
1480a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			__u8 val = data[4];
1481a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			tab_on_first(&first);
1482a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			printf("\t * Response Type: %d%s\n",
1483a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			       val, val == 3 ? " (AP)" : "");
1484a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			break;
1485a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		}
1486a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		case 0x103c: {
1487a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			__u8 val = data[4];
1488a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			tab_on_first(&first);
1489a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			printf("\t * RF Bands: 0x%x\n", val);
1490a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			break;
1491a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		}
1492a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		case 0x1041: {
1493a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			__u8 val = data[4];
1494a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			tab_on_first(&first);
1495a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			printf("\t * Selected Registrar: 0x%x\n", val);
1496a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			break;
1497a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		}
1498a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		case 0x1042:
1499a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			tab_on_first(&first);
1500a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			printf("\t * Serial Number: %.*s\n", sublen, data + 4);
1501a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			break;
1502a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		case 0x1044: {
1503a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			__u8 val = data[4];
1504a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			tab_on_first(&first);
1505a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			printf("\t * Wi-Fi Protected Setup State: %d%s%s\n",
1506a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			       val,
1507a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			       val == 1 ? " (Unconfigured)" : "",
1508a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			       val == 2 ? " (Configured)" : "");
1509a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			break;
1510a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		}
151109fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg		case 0x1047:
151209fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg			tab_on_first(&first);
151309fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg			printf("\t * UUID: ");
151409fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg			if (sublen != 16) {
151509fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg				printf("(invalid, length=%d)\n", sublen);
151609fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg				break;
151709fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg			}
151809fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg			printf("%02x%02x%02x%02x-%02x%02x-%02x%02x-"
151909fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg				"%02x%02x-%02x%02x%02x%02x%02x%02x\n",
152009fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg				data[4], data[5], data[6], data[7],
152109fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg				data[8], data[9], data[10], data[11],
152209fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg				data[12], data[13], data[14], data[15],
152309fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg				data[16], data[17], data[18], data[19]);
152409fe09dc71e58b63ca9ba570cf6b24326ec9807aJohannes Berg			break;
1525a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		case 0x1054: {
1526a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			tab_on_first(&first);
1527a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			if (sublen != 8) {
1528a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen				printf("\t * Primary Device Type: (invalid "
1529a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen				       "length %d)\n", sublen);
1530a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen				break;
1531a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			}
1532a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			printf("\t * Primary Device Type: "
1533a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			       "%u-%02x%02x%02x%02x-%u\n",
1534a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			       data[4] << 8 | data[5],
1535a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			       data[6], data[7], data[8], data[9],
1536a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			       data[10] << 8 | data[11]);
1537a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			break;
1538a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		}
15397ee5a86565fcf11ea33356ae9b202bc0336e13d6Johannes Berg		case 0x1057: {
1540fe31a22e04f62839e8ba41e6fc9241abe64e07c2Johannes Berg			__u8 val = data[4];
15417ee5a86565fcf11ea33356ae9b202bc0336e13d6Johannes Berg			tab_on_first(&first);
1542fe31a22e04f62839e8ba41e6fc9241abe64e07c2Johannes Berg			printf("\t * AP setup locked: 0x%.2x\n", val);
15437ee5a86565fcf11ea33356ae9b202bc0336e13d6Johannes Berg			break;
15447ee5a86565fcf11ea33356ae9b202bc0336e13d6Johannes Berg		}
1545a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		case 0x1008:
1546a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen		case 0x1053: {
15474673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			__u16 meth = (data[4] << 8) + data[5];
15484673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			bool comma = false;
15494673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			tab_on_first(&first);
1550a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			printf("\t * %sConfig methods:",
1551a6816965269a84edf063b0e04255cd64405bc9a3Jouni Malinen			       subtype == 0x1053 ? "Selected Registrar ": "");
15524673a894dae2780e395204eab01af4d40220b9f5Johannes Berg#define T(bit, name) do {		\
15534673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	if (meth & (1<<bit)) {		\
15544673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		if (comma)		\
15554673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf(",");	\
15564673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		comma = true;		\
15574673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		printf(" " name);	\
15584673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	} } while (0)
15594673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(0, "USB");
15604673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(1, "Ethernet");
15614673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(2, "Label");
15624673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(3, "Display");
15634673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(4, "Ext. NFC");
15644673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(5, "Int. NFC");
15654673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(6, "NFC Intf.");
15664673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(7, "PBC");
15674673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(8, "Keypad");
15684673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf("\n");
15694673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			break;
15704673a894dae2780e395204eab01af4d40220b9f5Johannes Berg#undef T
15714673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		}
15722650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg		default: {
15732650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg			const __u8 *subdata = data + 4;
15742650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg			__u16 tmplen = sublen;
15752650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg
15762650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg			tab_on_first(&first);
15772650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg			printf("\t * Unknown TLV (%#.4x, %d bytes):",
15782650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg			       subtype, tmplen);
15792650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg			while (tmplen) {
15802650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg				printf(" %.2x", *subdata);
15812650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg				subdata++;
15822650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg				tmplen--;
15832650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg			}
15842650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg			printf("\n");
15854673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			break;
15864673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		}
15872650d46b45f727ca8ee49faa4c6bd65da2550c4eJohannes Berg		}
15884673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
15894673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		data += sublen + 4;
15904673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		len -= sublen + 4;
15914673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	}
15924673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
15934673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	if (len != 0) {
15944673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		printf("\t\t * bogus tail data (%d):", len);
15954673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		while (len) {
15964673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf(" %.2x", *data);
15974673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			data++;
15984673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			len--;
15994673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		}
16004673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		printf("\n");
16014673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	}
16024673a894dae2780e395204eab01af4d40220b9f5Johannes Berg}
16034673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
160483b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic const struct ie_print wifiprinters[] = {
1605febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[1] = { "WPA", print_wifi_wpa, 2, 255, BIT(PRINT_SCAN), },
1606febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[2] = { "WMM", print_wifi_wmm, 1, 255, BIT(PRINT_SCAN), },
1607febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	[4] = { "WPS", print_wifi_wps, 0, 255, BIT(PRINT_SCAN), },
16084673a894dae2780e395204eab01af4d40220b9f5Johannes Berg};
16094673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
16109a22374a56b394000cfb98acb649355f76beb3a3Johannes Bergstatic inline void print_p2p(const uint8_t type, uint8_t len, const uint8_t *data)
16119a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg{
16129a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg	bool first = true;
16139a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg	__u8 subtype;
16149a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg	__u16 sublen;
16159a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg
16169a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg	while (len >= 3) {
16179a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		subtype = data[0];
16189a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		sublen = (data[2] << 8) + data[1];
16199a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg
16209a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		if (sublen > len - 3)
16219a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			break;
16229a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg
16239a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		switch (subtype) {
16249a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x02: /* capability */
16259a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			tab_on_first(&first);
16269a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			if (sublen < 2) {
16279a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg				printf("\t * malformed capability\n");
16289a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg				break;
16299a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			}
16309a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			printf("\t * Group capa: 0x%.2x, Device capa: 0x%.2x\n",
16319a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg				data[3], data[4]);
16329a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			break;
16339a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x0d: /* device info */
16349a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			if (sublen < 6 + 2 + 8 + 1) {
16359a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg				printf("\t * malformed device info\n");
16369a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg				break;
16379a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			}
16389a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			/* fall through for now */
16399a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x00: /* status */
16409a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x01: /* minor reason */
16419a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x03: /* device ID */
16429a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x04: /* GO intent */
16439a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x05: /* configuration timeout */
16449a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x06: /* listen channel */
16459a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x07: /* group BSSID */
16469a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x08: /* ext listen timing */
16479a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x09: /* intended interface address */
16489a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x0a: /* manageability */
16499a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x0b: /* channel list */
16509a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x0c: /* NoA */
16519a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x0e: /* group info */
16529a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x0f: /* group ID */
16539a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x10: /* interface */
16549a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x11: /* operating channel */
16559a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0x12: /* invitation flags */
16569a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		case 0xdd: /* vendor specific */
16579a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		default: {
16589a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			const __u8 *subdata = data + 4;
16599a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			__u16 tmplen = sublen;
16609a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg
16619a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			tab_on_first(&first);
16629a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			printf("\t * Unknown TLV (%#.2x, %d bytes):",
16639a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			       subtype, tmplen);
16649a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			while (tmplen) {
16659a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg				printf(" %.2x", *subdata);
16669a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg				subdata++;
16679a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg				tmplen--;
16689a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			}
16699a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			printf("\n");
16709a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			break;
16719a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		}
16729a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		}
16739a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg
16749a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		data += sublen + 3;
16759a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		len -= sublen + 3;
16769a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg	}
16779a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg
16789a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg	if (len != 0) {
16799a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		tab_on_first(&first);
16809a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		printf("\t * bogus tail data (%d):", len);
16819a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		while (len) {
16829a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			printf(" %.2x", *data);
16839a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			data++;
16849a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			len--;
16859a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		}
16869a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		printf("\n");
16879a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg	}
16889a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg}
16899a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg
16907e10c4ab5e99f23c4d8e78dbcda56af71f9f1d56Ben Greearstatic inline void print_hs20_ind(const uint8_t type, uint8_t len, const uint8_t *data)
16917e10c4ab5e99f23c4d8e78dbcda56af71f9f1d56Ben Greear{
16927e10c4ab5e99f23c4d8e78dbcda56af71f9f1d56Ben Greear	/* I can't find the spec for this...just going off what wireshark uses. */
16937e10c4ab5e99f23c4d8e78dbcda56af71f9f1d56Ben Greear	printf("\n");
16947e10c4ab5e99f23c4d8e78dbcda56af71f9f1d56Ben Greear	if (len > 0)
16957e10c4ab5e99f23c4d8e78dbcda56af71f9f1d56Ben Greear		printf("\t\tDGAF: %i\n", (int)(data[0] & 0x1));
16967e10c4ab5e99f23c4d8e78dbcda56af71f9f1d56Ben Greear	else
16977e10c4ab5e99f23c4d8e78dbcda56af71f9f1d56Ben Greear		printf("\t\tUnexpected length: %i\n", len);
16987e10c4ab5e99f23c4d8e78dbcda56af71f9f1d56Ben Greear}
16997e10c4ab5e99f23c4d8e78dbcda56af71f9f1d56Ben Greear
17009a22374a56b394000cfb98acb649355f76beb3a3Johannes Bergstatic const struct ie_print wfa_printers[] = {
17019a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg	[9] = { "P2P", print_p2p, 2, 255, BIT(PRINT_SCAN), },
17027e10c4ab5e99f23c4d8e78dbcda56af71f9f1d56Ben Greear	[16] = { "HotSpot 2.0 Indication", print_hs20_ind, 1, 255, BIT(PRINT_SCAN), },
1703f188ab676a69a1fa0f318be13755fd288d52bcdaBen Greear	[18] = { "HotSpot 2.0 OSEN", print_wifi_osen, 1, 255, BIT(PRINT_SCAN), },
17049a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg};
17059a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg
1706764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Bergstatic void print_vendor(unsigned char len, unsigned char *data,
1707febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg			 bool unknown, enum print_ie_type ptype)
17083563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
17093563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	int i;
17103563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
1711fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg	if (len < 3) {
17124673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		printf("\tVendor specific: <too short> data:");
1713fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg		for(i = 0; i < len; i++)
1714fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg			printf(" %.02x", data[i]);
1715fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg		printf("\n");
1716fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg		return;
1717fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg	}
1718fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg
17193bd60ef1276fc888fed699ee598b3b358d976f4cJohannes Berg	if (len >= 4 && memcmp(data, ms_oui, 3) == 0) {
1720febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg		if (data[3] < ARRAY_SIZE(wifiprinters) &&
1721febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg		    wifiprinters[data[3]].name &&
1722febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg		    wifiprinters[data[3]].flags & BIT(ptype)) {
172383b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			print_ie(&wifiprinters[data[3]], data[3], len - 4, data + 4);
172483b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			return;
172583b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		}
1726febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg		if (!unknown)
17274673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			return;
17283bd60ef1276fc888fed699ee598b3b358d976f4cJohannes Berg		printf("\tMS/WiFi %#.2x, data:", data[3]);
17294673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		for(i = 0; i < len - 4; i++)
17304673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf(" %.02x", data[i + 4]);
17314673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		printf("\n");
17324673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		return;
17334673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	}
17344673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
17359a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg	if (len >= 4 && memcmp(data, wfa_oui, 3) == 0) {
17369a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		if (data[3] < ARRAY_SIZE(wfa_printers) &&
17379a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		    wfa_printers[data[3]].name &&
17389a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		    wfa_printers[data[3]].flags & BIT(ptype)) {
17399a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			print_ie(&wfa_printers[data[3]], data[3], len - 4, data + 4);
17409a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			return;
17419a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		}
17429a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		if (!unknown)
17439a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			return;
17449a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		printf("\tWFA %#.2x, data:", data[3]);
17459a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		for(i = 0; i < len - 4; i++)
17469a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg			printf(" %.02x", data[i + 4]);
17479a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		printf("\n");
17489a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg		return;
17499a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg	}
17509a22374a56b394000cfb98acb649355f76beb3a3Johannes Berg
1751febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	if (!unknown)
1752764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg		return;
1753764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg
1754fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg	printf("\tVendor specific: OUI %.2x:%.2x:%.2x, data:",
17553563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		data[0], data[1], data[2]);
1756fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg	for (i = 3; i < len; i++)
1757fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg		printf(" %.2x", data[i]);
17583563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	printf("\n");
17593563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
17603563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
1761febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Bergvoid print_ies(unsigned char *ie, int ielen, bool unknown,
1762febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	       enum print_ie_type ptype)
17633563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
17643563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	while (ielen >= 2 && ielen >= ie[1]) {
1765febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg		if (ie[0] < ARRAY_SIZE(ieprinters) &&
1766febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg		    ieprinters[ie[0]].name &&
1767febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg		    ieprinters[ie[0]].flags & BIT(ptype)) {
176883b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			print_ie(&ieprinters[ie[0]], ie[0], ie[1], ie + 2);
1769764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg		} else if (ie[0] == 221 /* vendor */) {
1770febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg			print_vendor(ie[1], ie + 2, unknown, ptype);
1771febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg		} else if (unknown) {
17723563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			int i;
17733563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
17748086b7007d8a7f9d2bc22d154e26e9060f0e9676Johannes Berg			printf("\tUnknown IE (%d):", ie[0]);
17753563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			for (i=0; i<ie[1]; i++)
17768086b7007d8a7f9d2bc22d154e26e9060f0e9676Johannes Berg				printf(" %.2x", ie[2+i]);
17773563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			printf("\n");
17783563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		}
17793563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		ielen -= ie[1] + 2;
17803563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		ie += ie[1] + 2;
17813563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	}
17823563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
17833563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
17842e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratievstatic void print_capa_dmg(__u16 capa)
17852e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev{
17862e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	switch (capa & WLAN_CAPABILITY_DMG_TYPE_MASK) {
17872e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	case WLAN_CAPABILITY_DMG_TYPE_AP:
17882e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" DMG_ESS");
17892e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		break;
17902e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	case WLAN_CAPABILITY_DMG_TYPE_PBSS:
17912e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" DMG_PCP");
17922e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		break;
17932e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	case WLAN_CAPABILITY_DMG_TYPE_IBSS:
17942e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" DMG_IBSS");
17952e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		break;
17962e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	}
17972e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev
17982e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_DMG_CBAP_ONLY)
17992e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" CBAP_Only");
18002e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_DMG_CBAP_SOURCE)
18012e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" CBAP_Src");
18022e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_DMG_PRIVACY)
18032e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" Privacy");
18042e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_DMG_ECPAC)
18052e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" ECPAC");
18062e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_DMG_SPECTRUM_MGMT)
18072e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" SpectrumMgmt");
18082e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_DMG_RADIO_MEASURE)
18092e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" RadioMeasure");
18102e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev}
18112e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev
18122e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratievstatic void print_capa_non_dmg(__u16 capa)
18132e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev{
18142e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_ESS)
18152e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" ESS");
18162e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_IBSS)
18172e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" IBSS");
18182e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_CF_POLLABLE)
18192e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" CfPollable");
18202e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_CF_POLL_REQUEST)
18212e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" CfPollReq");
18222e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_PRIVACY)
18232e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" Privacy");
18242e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_SHORT_PREAMBLE)
18252e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" ShortPreamble");
18262e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_PBCC)
18272e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" PBCC");
18282e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_CHANNEL_AGILITY)
18292e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" ChannelAgility");
18302e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_SPECTRUM_MGMT)
18312e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" SpectrumMgmt");
18322e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_QOS)
18332e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" QoS");
18342e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_SHORT_SLOT_TIME)
18352e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" ShortSlotTime");
18362e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_APSD)
18372e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" APSD");
18382e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_RADIO_MEASURE)
18392e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" RadioMeasure");
18402e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_DSSS_OFDM)
18412e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" DSSS-OFDM");
18422e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_DEL_BACK)
18432e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" DelayedBACK");
18442e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (capa & WLAN_CAPABILITY_IMM_BACK)
18452e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf(" ImmediateBACK");
18462e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev}
18472e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev
18483563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Bergstatic int print_bss_handler(struct nl_msg *msg, void *arg)
18493563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
18503563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	struct nlattr *tb[NL80211_ATTR_MAX + 1];
18513563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
18523563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	struct nlattr *bss[NL80211_BSS_MAX + 1];
18533563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	char mac_addr[20], dev[20];
18543563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
18553563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		[NL80211_BSS_TSF] = { .type = NLA_U64 },
18563563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		[NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
18573563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		[NL80211_BSS_BSSID] = { },
18583563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		[NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
18593563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		[NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
18603563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		[NL80211_BSS_INFORMATION_ELEMENTS] = { },
1861f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg		[NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
1862f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg		[NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
1863a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg		[NL80211_BSS_STATUS] = { .type = NLA_U32 },
1864c04a78dfa108063933d2c489896f8c7b417a0f3dHolger Schurig		[NL80211_BSS_SEEN_MS_AGO] = { .type = NLA_U32 },
1865575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen		[NL80211_BSS_BEACON_IES] = { },
18663563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	};
1867febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	struct scan_params *params = arg;
18681c5bcd9c76dad08e54c3e6604a529c53b62e76eaJohannes Berg	int show = params->show_both_ie_sets ? 2 : 1;
18692e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	bool is_dmg = false;
18703563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
18713563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
18723563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		  genlmsg_attrlen(gnlh, 0), NULL);
18733563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
18743563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	if (!tb[NL80211_ATTR_BSS]) {
18755fe70c0edb4bc3015d192977f4fb9a5d4fa07148Johannes Berg		fprintf(stderr, "bss info missing!\n");
18763563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		return NL_SKIP;
18773563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	}
18783563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	if (nla_parse_nested(bss, NL80211_BSS_MAX,
18793563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			     tb[NL80211_ATTR_BSS],
18803563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			     bss_policy)) {
18815fe70c0edb4bc3015d192977f4fb9a5d4fa07148Johannes Berg		fprintf(stderr, "failed to parse nested attributes!\n");
18823563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		return NL_SKIP;
18833563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	}
18843563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
18853563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	if (!bss[NL80211_BSS_BSSID])
18863563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		return NL_SKIP;
18873563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
18883563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	mac_addr_n2a(mac_addr, nla_data(bss[NL80211_BSS_BSSID]));
188900889fb26e914c7485e1bae42f88259183728f78Johannes Berg	printf("BSS %s", mac_addr);
189000889fb26e914c7485e1bae42f88259183728f78Johannes Berg	if (tb[NL80211_ATTR_IFINDEX]) {
189100889fb26e914c7485e1bae42f88259183728f78Johannes Berg		if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
189200889fb26e914c7485e1bae42f88259183728f78Johannes Berg		printf("(on %s)", dev);
189300889fb26e914c7485e1bae42f88259183728f78Johannes Berg	}
1894a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg
1895a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg	if (bss[NL80211_BSS_STATUS]) {
1896a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg		switch (nla_get_u32(bss[NL80211_BSS_STATUS])) {
1897a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg		case NL80211_BSS_STATUS_AUTHENTICATED:
1898a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg			printf(" -- authenticated");
1899a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg			break;
1900a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg		case NL80211_BSS_STATUS_ASSOCIATED:
1901a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg			printf(" -- associated");
1902a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg			break;
1903a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg		case NL80211_BSS_STATUS_IBSS_JOINED:
1904a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg			printf(" -- joined");
1905a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg			break;
1906a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg		default:
1907a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg			printf(" -- unknown status: %d",
1908a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg				nla_get_u32(bss[NL80211_BSS_STATUS]));
1909a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg			break;
1910a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg		}
1911a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg	}
1912a56117a695f4109b061134a76cca22f7a8ba8db7Johannes Berg	printf("\n");
19133563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
1914e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg	if (bss[NL80211_BSS_TSF]) {
1915e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg		unsigned long long tsf;
1916e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg		tsf = (unsigned long long)nla_get_u64(bss[NL80211_BSS_TSF]);
1917e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg		printf("\tTSF: %llu usec (%llud, %.2lld:%.2llu:%.2llu)\n",
1918e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg			tsf, tsf/1000/1000/60/60/24, (tsf/1000/1000/60/60) % 24,
1919e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg			(tsf/1000/1000/60) % 60, (tsf/1000/1000) % 60);
1920e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg	}
19212e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	if (bss[NL80211_BSS_FREQUENCY]) {
19222e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		int freq = nla_get_u32(bss[NL80211_BSS_FREQUENCY]);
19232e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		printf("\tfreq: %d\n", freq);
19242e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		if (freq > 45000)
19252e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev			is_dmg = true;
19262e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev	}
19273563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	if (bss[NL80211_BSS_BEACON_INTERVAL])
1928792172b0f1dfbed179788e4944aaf4d4e0a91301Joerg Mayer		printf("\tbeacon interval: %d TUs\n",
19293563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]));
193092a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann	if (bss[NL80211_BSS_CAPABILITY]) {
193192a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann		__u16 capa = nla_get_u16(bss[NL80211_BSS_CAPABILITY]);
193292a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann		printf("\tcapability:");
19332e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		if (is_dmg)
19342e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev			print_capa_dmg(capa);
19352e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev		else
19362e8b82c16a312608d530856f3ab2c72dfd0e5cd2Vladimir Kondratiev			print_capa_non_dmg(capa);
193792a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann		printf(" (0x%.4x)\n", capa);
193892a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann	}
1939f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg	if (bss[NL80211_BSS_SIGNAL_MBM]) {
1940f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg		int s = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]);
1941f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg		printf("\tsignal: %d.%.2d dBm\n", s/100, s%100);
1942f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg	}
1943f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg	if (bss[NL80211_BSS_SIGNAL_UNSPEC]) {
1944f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg		unsigned char s = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]);
1945f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg		printf("\tsignal: %d/100\n", s);
1946f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg	}
1947c04a78dfa108063933d2c489896f8c7b417a0f3dHolger Schurig	if (bss[NL80211_BSS_SEEN_MS_AGO]) {
1948c04a78dfa108063933d2c489896f8c7b417a0f3dHolger Schurig		int age = nla_get_u32(bss[NL80211_BSS_SEEN_MS_AGO]);
1949c04a78dfa108063933d2c489896f8c7b417a0f3dHolger Schurig		printf("\tlast seen: %d ms ago\n", age);
1950c04a78dfa108063933d2c489896f8c7b417a0f3dHolger Schurig	}
1951c551449a3271ca1db60856fc2af20e1f2d01cce8Johannes Berg
19521c5bcd9c76dad08e54c3e6604a529c53b62e76eaJohannes Berg	if (bss[NL80211_BSS_INFORMATION_ELEMENTS] && show--) {
1953575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen		if (bss[NL80211_BSS_BEACON_IES])
1954575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen			printf("\tInformation elements from Probe Response "
1955575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen			       "frame:\n");
19563563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		print_ies(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
1957764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg			  nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
1958febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg			  params->unknown, params->type);
1959575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen	}
19601c5bcd9c76dad08e54c3e6604a529c53b62e76eaJohannes Berg	if (bss[NL80211_BSS_BEACON_IES] && show--) {
1961575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen		printf("\tInformation elements from Beacon frame:\n");
1962575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen		print_ies(nla_data(bss[NL80211_BSS_BEACON_IES]),
1963575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen			  nla_len(bss[NL80211_BSS_BEACON_IES]),
1964575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen			  params->unknown, params->type);
1965575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen	}
19663563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
19673563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	return NL_SKIP;
19683563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
19693563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
1970764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Bergstatic struct scan_params scan_params;
19713563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
19727c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Bergstatic int handle_scan_dump(struct nl80211_state *state,
19737c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Berg			    struct nl_cb *cb,
19743563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			    struct nl_msg *msg,
197505514f9581f66b12ac9ee0f21c770ceb34310e9dJohannes Berg			    int argc, char **argv,
197605514f9581f66b12ac9ee0f21c770ceb34310e9dJohannes Berg			    enum id_input id)
19773563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
1978764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg	if (argc > 1)
1979764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg		return 1;
1980764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg
19811c5bcd9c76dad08e54c3e6604a529c53b62e76eaJohannes Berg	memset(&scan_params, 0, sizeof(scan_params));
19821c5bcd9c76dad08e54c3e6604a529c53b62e76eaJohannes Berg
1983764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg	if (argc == 1 && !strcmp(argv[0], "-u"))
1984764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg		scan_params.unknown = true;
1985575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen	else if (argc == 1 && !strcmp(argv[0], "-b"))
1986575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen		scan_params.show_both_ie_sets = true;
1987764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg
1988febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg	scan_params.type = PRINT_SCAN;
1989febeb0c05600f8ce6b18ec624c73de53970403e1Johannes Berg
1990764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_bss_handler,
1991764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg		  &scan_params);
19923563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	return 0;
19933563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
1994a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg
1995a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Bergstatic int handle_scan_combined(struct nl80211_state *state,
1996a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg				struct nl_cb *cb,
1997a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg				struct nl_msg *msg,
199805514f9581f66b12ac9ee0f21c770ceb34310e9dJohannes Berg				int argc, char **argv,
199905514f9581f66b12ac9ee0f21c770ceb34310e9dJohannes Berg				enum id_input id)
2000a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg{
2001559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	char **trig_argv;
2002a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	static char *dump_argv[] = {
2003a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		NULL,
2004a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		"scan",
2005a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		"dump",
200692649eab6b3ccb0be600b8501fa7b83e9467819cMarcel Holtmann		NULL,
2007a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	};
2008a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	static const __u32 cmds[] = {
2009a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		NL80211_CMD_NEW_SCAN_RESULTS,
2010a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		NL80211_CMD_SCAN_ABORTED,
2011a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	};
2012559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	int trig_argc, dump_argc, err;
2013a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg
2014559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	if (argc >= 3 && !strcmp(argv[2], "-u")) {
2015559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		dump_argc = 4;
2016559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		dump_argv[3] = "-u";
2017575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen	} else if (argc >= 3 && !strcmp(argv[2], "-b")) {
2018575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen		dump_argc = 4;
2019575280ccc907e98cc4146dbaeb7adabb6232e150Jouni Malinen		dump_argv[3] = "-b";
2020559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	} else
2021559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		dump_argc = 3;
2022559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg
2023559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	trig_argc = 3 + (argc - 2) + (3 - dump_argc);
2024559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	trig_argv = calloc(trig_argc, sizeof(*trig_argv));
2025559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	if (!trig_argv)
2026559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		return -ENOMEM;
2027a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	trig_argv[0] = argv[0];
2028559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	trig_argv[1] = "scan";
2029559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	trig_argv[2] = "trigger";
2030559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	int i;
2031559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	for (i = 0; i < argc - 2 - (dump_argc - 3); i++)
2032559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		trig_argv[i + 3] = argv[i + 2 + (dump_argc - 3)];
203375f4204cd7d27caa080d64f6f5cf3c4b366c839fJohannes Berg	err = handle_cmd(state, id, trig_argc, trig_argv);
2034559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	free(trig_argv);
2035a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	if (err)
2036a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		return err;
2037a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg
203861725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	/*
203961725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * WARNING: DO NOT COPY THIS CODE INTO YOUR APPLICATION
204061725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 *
204161725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * This code has a bug, which requires creating a separate
204261725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * nl80211 socket to fix:
204361725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * It is possible for a NL80211_CMD_NEW_SCAN_RESULTS or
204461725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * NL80211_CMD_SCAN_ABORTED message to be sent by the kernel
204561725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * before (!) we listen to it, because we only start listening
204661725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * after we send our scan request.
204761725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 *
204861725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * Doing it the other way around has a race condition as well,
204961725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * if you first open the events socket you may get a notification
205061725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * for a previous scan.
205161725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 *
205261725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * The only proper way to fix this would be to listen to events
205361725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * before sending the command, and for the kernel to send the
205461725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * scan request along with the event, so that you can match up
205561725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * whether the scan you requested was finished or aborted (this
205661725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * may result in processing a scan that another application
205761725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * requested, but that doesn't seem to be a problem).
205861725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 *
205961725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * Alas, the kernel doesn't do that (yet).
206061725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 */
206161725dbed6df376809e8dc3865640244d8f1d690Johannes Berg
2062a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	if (listen_events(state, ARRAY_SIZE(cmds), cmds) ==
2063a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg					NL80211_CMD_SCAN_ABORTED) {
2064a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		printf("scan aborted!\n");
2065a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		return 0;
2066a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	}
2067a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg
2068a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	dump_argv[0] = argv[0];
206975f4204cd7d27caa080d64f6f5cf3c4b366c839fJohannes Berg	return handle_cmd(state, id, dump_argc, dump_argv);
2070a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg}
20715085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes BergTOPLEVEL(scan, "[-u] [freq <freq>*] [ies <hex as 00:11:..>] [meshid <meshid>] [lowpri,flush,ap-force] [randomise[=<addr>/<mask>]] [ssid <ssid>*|passive]", 0, 0,
20726ca98d28b949d20cca2e158bef3e0cfd75b59672Johannes Berg	 CIB_NETDEV, handle_scan_combined,
20736ca98d28b949d20cca2e158bef3e0cfd75b59672Johannes Berg	 "Scan on the given frequencies and probe for the given SSIDs\n"
20746ca98d28b949d20cca2e158bef3e0cfd75b59672Johannes Berg	 "(or wildcard if not given) unless passive scanning is requested.\n"
207564797a7fd7c49d95abc8540490c76bf493699176Johannes Berg	 "If -u is specified print unknown data in the scan results.\n"
207664797a7fd7c49d95abc8540490c76bf493699176Johannes Berg	 "Specified (vendor) IEs must be well-formed.");
20774698bfc235c20e955466b6362df2a39f7478c13fJohannes BergCOMMAND(scan, dump, "[-u]",
20784698bfc235c20e955466b6362df2a39f7478c13fJohannes Berg	NL80211_CMD_GET_SCAN, NLM_F_DUMP, CIB_NETDEV, handle_scan_dump,
20794698bfc235c20e955466b6362df2a39f7478c13fJohannes Berg	"Dump the current scan results. If -u is specified, print unknown\n"
20804698bfc235c20e955466b6362df2a39f7478c13fJohannes Berg	"data in scan results.");
20815085aa2b7ed0cb5e89eb0c85c10218f552f579aaJohannes BergCOMMAND(scan, trigger, "[freq <freq>*] [ies <hex as 00:11:..>] [meshid <meshid>] [lowpri,flush,ap-force] [randomise[=<addr>/<mask>]] [ssid <ssid>*|passive]",
20824698bfc235c20e955466b6362df2a39f7478c13fJohannes Berg	NL80211_CMD_TRIGGER_SCAN, 0, CIB_NETDEV, handle_scan,
20834698bfc235c20e955466b6362df2a39f7478c13fJohannes Berg	 "Trigger a scan on the given frequencies with probing for the given\n"
20844698bfc235c20e955466b6362df2a39f7478c13fJohannes Berg	 "SSIDs (or wildcard if not given) unless passive scanning is requested.");
20853fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho
20863fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho
20873fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelhostatic int handle_start_sched_scan(struct nl80211_state *state,
20883fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho				   struct nl_cb *cb, struct nl_msg *msg,
20893fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho				   int argc, char **argv, enum id_input id)
20903fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho{
20913fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho	return parse_sched_scan(msg, &argc, &argv);
20923fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho}
20933fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho
20943fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelhostatic int handle_stop_sched_scan(struct nl80211_state *state, struct nl_cb *cb,
20953fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho				  struct nl_msg *msg, int argc, char **argv,
20963fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho				  enum id_input id)
20973fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho{
20983fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho	if (argc != 0)
20993fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho		return 1;
21003fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho
21013fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho	return 0;
21023fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho}
21033fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho
21043fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano CoelhoCOMMAND(scan, sched_start,
21053fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho	SCHED_SCAN_OPTIONS,
21063fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho	NL80211_CMD_START_SCHED_SCAN, 0, CIB_NETDEV, handle_start_sched_scan,
21073fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho	"Start a scheduled scan at the specified interval on the given frequencies\n"
21083fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho	"with probing for the given SSIDs (or wildcard if not given) unless passive\n"
21093fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho	"scanning is requested.  If matches are specified, only matching results\n"
21103fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho	"will be returned.");
21113fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano CoelhoCOMMAND(scan, sched_stop, "",
21123fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho	NL80211_CMD_STOP_SCHED_SCAN, 0, CIB_NETDEV, handle_stop_sched_scan,
21133fce58aafc3a28cbfbb496d7797e250eea99b6cbLuciano Coelho	"Stop an ongoing scheduled scan.");
2114