scan.c revision 748f8489caad151e01922f0ba26847aedfd36daf
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)
2892a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann#define WLAN_CAPABILITY_DSSS_OFDM	(1<<13)
2992a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann
30857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmannstatic unsigned char wifi_oui[3]      = { 0x00, 0x50, 0xf2 };
31857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmannstatic unsigned char ieee80211_oui[3] = { 0x00, 0x0f, 0xac };
32857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
33764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Bergstruct scan_params {
34764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg	bool unknown;
35764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg};
36764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg
377c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Bergstatic int handle_scan(struct nl80211_state *state,
387c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Berg		       struct nl_cb *cb,
393563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		       struct nl_msg *msg,
403563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		       int argc, char **argv)
413563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
42559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	struct nl_msg *ssids = NULL, *freqs = NULL;
43559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	char *eptr;
443563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	int err = -ENOBUFS;
45559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	int i;
46559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	enum {
47559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		NONE,
48559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		FREQ,
49559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		SSID,
50559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		DONE,
51559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	} parse = NONE;
52559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	int freq;
53559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	bool passive = false, have_ssids = false, have_freqs = false;
543563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
553563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	ssids = nlmsg_alloc();
563563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	if (!ssids)
573563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		return -ENOMEM;
58559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg
59559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	freqs = nlmsg_alloc();
60559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	if (!freqs) {
61559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		nlmsg_free(ssids);
62559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		return -ENOMEM;
63559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	}
64559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg
65559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	for (i = 0; i < argc; i++) {
661ddf11ebe3cfaab8b5e426c9e4ae1b50ccfcc3d4Johannes Berg		if (parse == NONE && strcmp(argv[i], "freq") == 0) {
67559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			parse = FREQ;
68559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			have_freqs = true;
69559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			continue;
701ddf11ebe3cfaab8b5e426c9e4ae1b50ccfcc3d4Johannes Berg		} else if (parse < SSID && strcmp(argv[i], "ssid") == 0) {
71559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			parse = SSID;
72559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			have_ssids = true;
73559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			continue;
741ddf11ebe3cfaab8b5e426c9e4ae1b50ccfcc3d4Johannes Berg		} else if (parse < SSID && strcmp(argv[i], "passive") == 0) {
75559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			parse = DONE;
76559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			passive = true;
77559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			continue;
78559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		}
79559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg
80559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		switch (parse) {
81559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		case NONE:
82559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		case DONE:
83559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			return 1;
84559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		case FREQ:
85559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			freq = strtoul(argv[i], &eptr, 10);
86559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			if (eptr != argv[i] + strlen(argv[i]))
87559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg				return 1;
88559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			NLA_PUT_U32(freqs, i, freq);
89559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			break;
90559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		case SSID:
91559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			NLA_PUT(ssids, i, strlen(argv[i]), argv[i]);
92559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg			break;
93559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		}
94559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	}
95559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg
96559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	if (!have_ssids)
97559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		NLA_PUT(ssids, 1, 0, "");
98559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	if (!passive)
99559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids);
100559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg
101559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	if (have_freqs)
102559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		nla_put_nested(msg, NL80211_ATTR_SCAN_FREQUENCIES, freqs);
1033563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
1043563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	err = 0;
1053563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg nla_put_failure:
1063563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	nlmsg_free(ssids);
107559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	nlmsg_free(freqs);
1083563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	return err;
1093563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
110559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes BergCOMMAND(scan, trigger, "[freq <freq>*] [ssid <ssid>*|passive]",
1116ca98d28b949d20cca2e158bef3e0cfd75b59672Johannes Berg	NL80211_CMD_TRIGGER_SCAN, 0, CIB_NETDEV, handle_scan,
1126ca98d28b949d20cca2e158bef3e0cfd75b59672Johannes Berg	 "Trigger a scan on the given frequencies with probing for the given\n"
1136ca98d28b949d20cca2e158bef3e0cfd75b59672Johannes Berg	 "SSIDs (or wildcard if not given) unless passive scanning is requested.");
1143563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
115857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmannstatic void tab_on_first(bool *first)
116857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann{
117857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	if (!*first)
118857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf("\t");
119857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	else
120857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		*first = false;
121857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann}
122857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
12383b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_ssid(const uint8_t type, uint8_t len, const uint8_t *data)
1243563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
12583b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	printf(" ");
126748f8489caad151e01922f0ba26847aedfd36dafJohannes Berg	print_ssid_escaped(len, data);
1273563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	printf("\n");
1283563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
1293563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
13083b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_supprates(const uint8_t type, uint8_t len, const uint8_t *data)
1313563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
1323563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	int i;
1333563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
13483b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	printf(" ");
1353563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
13683b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	for (i = 0; i < len; i++) {
1373563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		int r = data[i] & 0x7f;
1383563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		printf("%d.%d%s ", r/2, 5*(r&1), data[i] & 0x80 ? "*":"");
1393563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	}
1403563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	printf("\n");
1413563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
1423563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
14383b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_ds(const uint8_t type, uint8_t len, const uint8_t *data)
1443563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
14583b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	printf(" channel %d\n", data[0]);
1463563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
1473563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
14883b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_country(const uint8_t type, uint8_t len, const uint8_t *data)
149b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann{
150b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann	int i;
151b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann
15283b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	printf(" %.*s", 2, data);
153b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann	switch (data[2]) {
154b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann	case 'I':
155b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann		printf(" (indoor)");
156b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann		break;
157b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann	case 'O':
158b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann		printf(" (outdoor)");
159b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann		break;
160b6c0d6340dbc969b4c53f583775e7c49b440c403Johannes Berg	case ' ':
161b6c0d6340dbc969b4c53f583775e7c49b440c403Johannes Berg		printf(" (in/outdoor)");
162b6c0d6340dbc969b4c53f583775e7c49b440c403Johannes Berg		break;
163b6c0d6340dbc969b4c53f583775e7c49b440c403Johannes Berg	default:
164b6c0d6340dbc969b4c53f583775e7c49b440c403Johannes Berg		printf(" (invalid environment)");
165b6c0d6340dbc969b4c53f583775e7c49b440c403Johannes Berg		break;
166b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann	}
167b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann	printf(", data:");
168b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann	for(i=0; i<len-3; i++)
169b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann		printf(" %.02x", data[i + 3]);
170b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann	printf("\n");
171b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann}
172b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann
173d1563a1b2d6e43fb12aeaa764c952cd2108b6862Marcel Holtmannstatic void print_powerconstraint(const uint8_t type, uint8_t len, const uint8_t *data)
174d1563a1b2d6e43fb12aeaa764c952cd2108b6862Marcel Holtmann{
175d1563a1b2d6e43fb12aeaa764c952cd2108b6862Marcel Holtmann	printf(" %d dB\n", data[0]);
176d1563a1b2d6e43fb12aeaa764c952cd2108b6862Marcel Holtmann}
177d1563a1b2d6e43fb12aeaa764c952cd2108b6862Marcel Holtmann
17883b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_erp(const uint8_t type, uint8_t len, const uint8_t *data)
179fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann{
180fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann	if (data[0] == 0x00)
18183b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		printf(" <no flags>");
182fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann	if (data[0] & 0x01)
183fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann		printf(" NonERP_Present");
184fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann	if (data[0] & 0x02)
185fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann		printf(" Use_Protection");
186fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann	if (data[0] & 0x04)
187fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann		printf(" Barker_Preamble_Mode");
188fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann	printf("\n");
189fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann}
190fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann
19183b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_cipher(const uint8_t *data)
192857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann{
193857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	if (memcmp(data, wifi_oui, 3) == 0) {
194857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		switch (data[3]) {
195510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 0:
196857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("Use group cipher suite");
197857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
198510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 1:
199857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("WEP-40");
200857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
201510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 2:
202857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("TKIP");
203857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
204510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 4:
205857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("CCMP");
206857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
207510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 5:
208857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("WEP-104");
209857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
210857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		default:
211332769c689e75f372bdae8ade290433b31eebc3eJohannes Berg			printf("%.02x-%.02x-%.02x:%d",
2125594fd2301775e7795899ed4ed3b8fff82551734Johannes Berg				data[0], data[1] ,data[2], data[3]);
213857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
214857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		}
215857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	} else if (memcmp(data, ieee80211_oui, 3) == 0) {
216857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		switch (data[3]) {
217510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 0:
218857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("Use group cipher suite");
219857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
220510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 1:
221857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("WEP-40");
222857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
223510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 2:
224857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("TKIP");
225857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
226510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 4:
227857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("CCMP");
228857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
229510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 5:
230857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("WEP-104");
231857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
232510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 6:
233857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("AES-128-CMAC");
234857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
235857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		default:
236332769c689e75f372bdae8ade290433b31eebc3eJohannes Berg			printf("%.02x-%.02x-%.02x:%d",
2375594fd2301775e7795899ed4ed3b8fff82551734Johannes Berg				data[0], data[1] ,data[2], data[3]);
238857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
239857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		}
240857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	} else
241332769c689e75f372bdae8ade290433b31eebc3eJohannes Berg		printf("%.02x-%.02x-%.02x:%d",
2425594fd2301775e7795899ed4ed3b8fff82551734Johannes Berg			data[0], data[1] ,data[2], data[3]);
243857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann}
244857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
24583b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_auth(const uint8_t *data)
246857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann{
247857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	if (memcmp(data, wifi_oui, 3) == 0) {
248857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		switch (data[3]) {
249510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 1:
250857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("IEEE 802.1X");
251857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
252510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 2:
253857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("PSK");
254857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
255857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		default:
256332769c689e75f372bdae8ade290433b31eebc3eJohannes Berg			printf("%.02x-%.02x-%.02x:%d",
2575594fd2301775e7795899ed4ed3b8fff82551734Johannes Berg				data[0], data[1] ,data[2], data[3]);
258857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
259857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		}
260857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	} else if (memcmp(data, ieee80211_oui, 3) == 0) {
261857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		switch (data[3]) {
262510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 1:
263857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("IEEE 802.1X");
264857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
265510e0e2faa8947de1bc97fea541d0182afeac0b7Johannes Berg		case 2:
266857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			printf("PSK");
267857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
2680fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg		case 3:
2690fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			printf("FT/IEEE 802.1X");
2700fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			break;
2710fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg		case 4:
2720fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			printf("FT/PSK");
2730fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			break;
2740fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg		case 5:
2750fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			printf("IEEE 802.1X/SHA-256");
2760fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			break;
2770fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg		case 6:
2780fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			printf("PSK/SHA-256");
2790fe1c41537d2e7fbfcf70360198eddbb13bf7d07Johannes Berg			break;
280857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		default:
281332769c689e75f372bdae8ade290433b31eebc3eJohannes Berg			printf("%.02x-%.02x-%.02x:%d",
2825594fd2301775e7795899ed4ed3b8fff82551734Johannes Berg				data[0], data[1] ,data[2], data[3]);
283857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann			break;
284857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		}
285857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	} else
286332769c689e75f372bdae8ade290433b31eebc3eJohannes Berg		printf("%.02x-%.02x-%.02x:%d",
2875594fd2301775e7795899ed4ed3b8fff82551734Johannes Berg			data[0], data[1] ,data[2], data[3]);
288857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann}
289857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
29083b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_rsn_ie(const char *defcipher, const char *defauth,
29183b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			 uint8_t len, const uint8_t *data)
292857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann{
293857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	bool first = true;
294857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	__u16 version, count, capa;
295857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	int i;
296857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
297857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	version = data[0] + (data[1] << 8);
298857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	tab_on_first(&first);
299857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	printf("\t * Version: %d\n", version);
300857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
301857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	data += 2;
302857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	len -= 2;
303857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
304857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	if (len < 4) {
305857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		tab_on_first(&first);
306857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf("\t * Group cipher: %s\n", defcipher);
307857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf("\t * Pairwise ciphers: %s\n", defcipher);
308857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		return;
309857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	}
310857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
311857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	tab_on_first(&first);
312857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	printf("\t * Group cipher: ");
313857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	print_cipher(data);
314857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	printf("\n");
315857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
316857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	data += 4;
317857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	len -= 4;
318857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
319857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	if (len < 2) {
320857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		tab_on_first(&first);
321857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf("\t * Pairwise ciphers: %s\n", defcipher);
322857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		return;
323857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	}
324857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
325857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	count = data[0] | (data[1] << 8);
32631d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann	if (2 + (count * 4) > len)
32731d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann		goto invalid;
32831d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann
329857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	tab_on_first(&first);
330857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	printf("\t * Pairwise ciphers:");
33131d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann	for (i = 0; i < count; i++) {
332857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf(" ");
333857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		print_cipher(data + 2 + (i * 4));
334857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	}
335857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	printf("\n");
336857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
337857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	data += 2 + (count * 4);
338857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	len -= 2 + (count * 4);
339857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
340857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	if (len < 2) {
341857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		tab_on_first(&first);
342857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf("\t * Authentication suites: %s\n", defauth);
343857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		return;
344857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	}
345857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
346857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	count = data[0] | (data[1] << 8);
34731d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann	if (2 + (count * 4) > len)
34831d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann		goto invalid;
34931d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann
350857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	tab_on_first(&first);
351857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	printf("\t * Authentication suites:");
35283b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	for (i = 0; i < count; i++) {
353857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf(" ");
354857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		print_auth(data + 2 + (i * 4));
355857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	}
356857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	printf("\n");
357857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
358857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	data += 2 + (count * 4);
359857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	len -= 2 + (count * 4);
360857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
3616a4f24e80e5e6d85bfd1c4d66b476b86e5fa35d3Johannes Berg	if (len >= 2) {
3626a4f24e80e5e6d85bfd1c4d66b476b86e5fa35d3Johannes Berg		capa = data[0] | (data[1] << 8);
3636a4f24e80e5e6d85bfd1c4d66b476b86e5fa35d3Johannes Berg		tab_on_first(&first);
364cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		printf("\t * Capabilities:");
365cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		if (capa & 0x0001)
366cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" PreAuth");
367cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		if (capa & 0x0002)
368cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" NoPairwise");
369cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		switch ((capa & 0x000c) >> 2) {
370cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 0:
371cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
372cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 1:
373cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" 2-PTKSA-RC");
374cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
375cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 2:
376cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" 4-PTKSA-RC");
377cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
378cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 3:
379cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" 16-PTKSA-RC");
380cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
381cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		}
382cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		switch ((capa & 0x0030) >> 4) {
383cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 0:
384cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
385cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 1:
386cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" 2-GTKSA-RC");
387cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
388cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 2:
389cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" 4-GTKSA-RC");
390cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
391cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		case 3:
392cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" 16-GTKSA-RC");
393cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			break;
394cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		}
395cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		if (capa & 0x0040)
396cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" MFP-required");
397cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		if (capa & 0x0080)
398cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" MFP-capable");
399cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		if (capa & 0x0200)
400cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" Peerkey-enabled");
401cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		if (capa & 0x0400)
402cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" SPP-AMSDU-capable");
403cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		if (capa & 0x0800)
404cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg			printf(" SPP-AMSDU-required");
405cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg		printf(" (0x%.4x)\n", capa);
4066a4f24e80e5e6d85bfd1c4d66b476b86e5fa35d3Johannes Berg		data += 2;
4076a4f24e80e5e6d85bfd1c4d66b476b86e5fa35d3Johannes Berg		len -= 2;
4086a4f24e80e5e6d85bfd1c4d66b476b86e5fa35d3Johannes Berg	}
40931d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann
410cadbe89ab7b00d146a34419145bc8c0db948f977Johannes Berg invalid:
41131d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann	if (len != 0) {
41231d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann		printf("\t\t * bogus tail data (%d):", len);
41331d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann		while (len) {
41431d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann			printf(" %.2x", *data);
41531d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann			data++;
41631d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann			len--;
41731d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann		}
41831d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann		printf("\n");
41931d477fb191d14e3860d2d0b162d33ea87237bdbMarcel Holtmann	}
420857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann}
421857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
42283b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_rsn(const uint8_t type, uint8_t len, const uint8_t *data)
423857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann{
42483b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	print_rsn_ie("CCMP", "IEEE 802.1X", len, data);
425857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann}
426857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann
42783b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_capabilities(const uint8_t type, uint8_t len, const uint8_t *data)
4289b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann{
42931d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg	int i, base, bit;
43031d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg	bool first = true;
43131d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg
43231d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg
43331d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg	for (i = 0; i < len; i++) {
43431d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg		base = i * 8;
43531d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg
43631d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg		for (bit = 0; bit < 8; bit++) {
43731d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			if (!(data[i] & (1 << bit)))
43831d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				continue;
43931d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg
44031d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			if (!first)
44131d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				printf(",");
44231d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			else
44331d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				first = false;
44431d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg
44531d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			switch (bit + base) {
44631d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			case 0:
44731d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				printf(" HT Information Exchange Supported");
44831d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				break;
44931d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			case 1:
45031d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				printf(" On-demand Beacon");
45131d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				break;
45231d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			case 2:
45331d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				printf(" Extended Channel Switching");
45431d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				break;
45531d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			case 3:
45631d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				printf(" Wave Indication");
45731d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				break;
45831d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			case 4:
45931d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				printf(" PSMP Capability");
46031d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				break;
46131d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			case 5:
46231d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				printf(" Service Interval Granularity");
46331d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				break;
46431d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			case 6:
46531d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				printf(" S-PSMP Capability");
46631d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				break;
46731d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			default:
46831d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				printf(" %d", bit);
46931d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg				break;
47031d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg			}
47131d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg		}
47231d2d2599ee4ece941596e00e3bde3a15a514781Johannes Berg	}
4739b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann
4749b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann	printf("\n");
4759b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann}
4769b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann
47783b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstruct ie_print {
47883b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	const char *name;
47983b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	void (*print)(const uint8_t type, uint8_t len, const uint8_t *data);
48083b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	uint8_t minlen, maxlen;
481764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg};
482764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg
48383b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_ie(const struct ie_print *p, const uint8_t type,
48483b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		     uint8_t len, const uint8_t *data)
4854673a894dae2780e395204eab01af4d40220b9f5Johannes Berg{
48683b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	int i;
48783b4934c612b84c28a656d496bea056e37fccb99Johannes Berg
48883b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	if (!p->print)
48983b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		return;
49083b4934c612b84c28a656d496bea056e37fccb99Johannes Berg
49183b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	printf("\t%s:", p->name);
49283b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	if (len < p->minlen || len > p->maxlen) {
49383b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		if (len > 1) {
49483b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			printf(" <invalid: %d bytes:", len);
49583b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			for (i = 0; i < len; i++)
49683b4934c612b84c28a656d496bea056e37fccb99Johannes Berg				printf(" %.02x", data[i]);
49783b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			printf(">\n");
49883b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		} else if (len)
49983b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			printf(" <invalid: 1 byte: %.02x>\n", data[0]);
50083b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		else
50183b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			printf(" <invalid: no data>\n");
50283b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		return;
50383b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	}
50483b4934c612b84c28a656d496bea056e37fccb99Johannes Berg
50583b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	p->print(type, len, data);
50683b4934c612b84c28a656d496bea056e37fccb99Johannes Berg}
50783b4934c612b84c28a656d496bea056e37fccb99Johannes Berg
50883b4934c612b84c28a656d496bea056e37fccb99Johannes Berg#define PRINT_IGN {		\
50983b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	.name = "IGNORE",	\
51083b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	.print = NULL,		\
51183b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	.minlen = 0,		\
51283b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	.maxlen = 255,		\
5134673a894dae2780e395204eab01af4d40220b9f5Johannes Berg}
5144673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
51583b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic const struct ie_print ieprinters[] = {
51683b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	[0] = { "SSID", print_ssid, 0, 32, },
51783b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	[1] = { "Supported rates", print_supprates, 0, 255, },
51883b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	[3] = { "DS Paramater set", print_ds, 1, 1, },
51983b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	[5] = PRINT_IGN,
52083b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	[7] = { "Country", print_country, 3, 255, },
521d1563a1b2d6e43fb12aeaa764c952cd2108b6862Marcel Holtmann	[32] = { "Power constraint", print_powerconstraint, 1, 1, },
52283b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	[42] = { "ERP", print_erp, 1, 255, },
52383b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	[48] = { "RSN", print_rsn, 2, 255, },
52483b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	[50] = { "Extended supported rates", print_supprates, 0, 255, },
52583b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	[127] = { "Extended capabilities", print_capabilities, 0, 255, },
52683b4934c612b84c28a656d496bea056e37fccb99Johannes Berg};
52783b4934c612b84c28a656d496bea056e37fccb99Johannes Berg
52883b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_wifi_wpa(const uint8_t type, uint8_t len, const uint8_t *data)
52983b4934c612b84c28a656d496bea056e37fccb99Johannes Berg{
53083b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	print_rsn_ie("TKIP", "IEEE 802.1X", len, data);
53183b4934c612b84c28a656d496bea056e37fccb99Johannes Berg}
53283b4934c612b84c28a656d496bea056e37fccb99Johannes Berg
53383b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_wifi_wmm(const uint8_t type, uint8_t len, const uint8_t *data)
5346ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann{
5356ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann	int i;
5366ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann
5376ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann	switch (data[0]) {
5386ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann	case 0x00:
53983b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		printf(" information:");
5406ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann		break;
5416ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann	case 0x01:
54283b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		printf(" parameter:");
5436ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann		break;
5446ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann	default:
54583b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		printf(" type %d:", data[0]);
5466ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann		break;
5476ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann	}
5486ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann
54983b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	for(i = 0; i < len - 1; i++)
5506ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann		printf(" %.02x", data[i + 1]);
5516ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann	printf("\n");
5526ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann}
5536ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann
55483b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic void print_wifi_wps(const uint8_t type, uint8_t len, const uint8_t *data)
5554673a894dae2780e395204eab01af4d40220b9f5Johannes Berg{
5564673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	bool first = true;
5574673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	__u16 subtype, sublen;
5584673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
5594673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	while (len >= 4) {
5604673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		subtype = (data[0] << 8) + data[1];
5614673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		sublen = (data[2] << 8) + data[3];
5624673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		if (sublen > len)
5634673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			break;
5644673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
5654673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		switch (subtype) {
5664673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		case 0x104a:
5674673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			tab_on_first(&first);
568dffc6750fec6d97a4fc55a687836cd6437be76e2Johannes Berg			printf("\t * Version: %d.%d\n", data[4] >> 4, data[4] & 0xF);
5694673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			break;
5704673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		case 0x1011:
5714673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			tab_on_first(&first);
5724673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf("\t * Device name: %.*s\n", sublen, data + 4);
5734673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			break;
5744673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		case 0x1021:
5754673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			tab_on_first(&first);
5764673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf("\t * Manufacturer: %.*s\n", sublen, data + 4);
5774673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			break;
5784673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		case 0x1023:
5794673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			tab_on_first(&first);
5804673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf("\t * Model: %.*s\n", sublen, data + 4);
5814673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			break;
5827ee5a86565fcf11ea33356ae9b202bc0336e13d6Johannes Berg		case 0x1057: {
5837ee5a86565fcf11ea33356ae9b202bc0336e13d6Johannes Berg			__u16 val = (data[4] << 8) | data[5];
5847ee5a86565fcf11ea33356ae9b202bc0336e13d6Johannes Berg			tab_on_first(&first);
5857ee5a86565fcf11ea33356ae9b202bc0336e13d6Johannes Berg			printf("\t * AP setup locked: 0x%.4x\n", val);
5867ee5a86565fcf11ea33356ae9b202bc0336e13d6Johannes Berg			break;
5877ee5a86565fcf11ea33356ae9b202bc0336e13d6Johannes Berg		}
5884673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		case 0x1008: {
5894673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			__u16 meth = (data[4] << 8) + data[5];
5904673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			bool comma = false;
5914673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			tab_on_first(&first);
5924673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf("\t * Config methods:");
5934673a894dae2780e395204eab01af4d40220b9f5Johannes Berg#define T(bit, name) do {		\
5944673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	if (meth & (1<<bit)) {		\
5954673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		if (comma)		\
5964673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf(",");	\
5974673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		comma = true;		\
5984673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		printf(" " name);	\
5994673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	} } while (0)
6004673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(0, "USB");
6014673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(1, "Ethernet");
6024673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(2, "Label");
6034673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(3, "Display");
6044673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(4, "Ext. NFC");
6054673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(5, "Int. NFC");
6064673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(6, "NFC Intf.");
6074673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(7, "PBC");
6084673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			T(8, "Keypad");
6094673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf("\n");
6104673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			break;
6114673a894dae2780e395204eab01af4d40220b9f5Johannes Berg#undef T
6124673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		}
6134673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		default:
6144673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			break;
6154673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		}
6164673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
6174673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		data += sublen + 4;
6184673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		len -= sublen + 4;
6194673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	}
6204673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
6214673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	if (len != 0) {
6224673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		printf("\t\t * bogus tail data (%d):", len);
6234673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		while (len) {
6244673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf(" %.2x", *data);
6254673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			data++;
6264673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			len--;
6274673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		}
6284673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		printf("\n");
6294673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	}
6304673a894dae2780e395204eab01af4d40220b9f5Johannes Berg}
6314673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
63283b4934c612b84c28a656d496bea056e37fccb99Johannes Bergstatic const struct ie_print wifiprinters[] = {
63383b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	[1] = { "WPA", print_wifi_wpa, 2, 255, },
63483b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	[2] = { "WMM", print_wifi_wmm, 1, 255, },
63583b4934c612b84c28a656d496bea056e37fccb99Johannes Berg	[4] = { "WPS", print_wifi_wps, 0, 255, },
6364673a894dae2780e395204eab01af4d40220b9f5Johannes Berg};
6374673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
638764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Bergstatic void print_vendor(unsigned char len, unsigned char *data,
639764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg			 struct scan_params *params)
6403563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
6413563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	int i;
6423563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
643fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg	if (len < 3) {
6444673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		printf("\tVendor specific: <too short> data:");
645fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg		for(i = 0; i < len; i++)
646fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg			printf(" %.02x", data[i]);
647fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg		printf("\n");
648fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg		return;
649fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg	}
650fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg
651857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann	if (len >= 4 && memcmp(data, wifi_oui, 3) == 0) {
65283b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		if (data[3] < ARRAY_SIZE(wifiprinters) && wifiprinters[data[3]].name) {
65383b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			print_ie(&wifiprinters[data[3]], data[3], len - 4, data + 4);
65483b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			return;
65583b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		}
6564673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		if (!params->unknown)
6574673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			return;
658857d966ea902a23112697c93ec2dc3b919757c59Marcel Holtmann		printf("\tWiFi OUI %#.2x, data:", data[3]);
6594673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		for(i = 0; i < len - 4; i++)
6604673a894dae2780e395204eab01af4d40220b9f5Johannes Berg			printf(" %.02x", data[i + 4]);
6614673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		printf("\n");
6624673a894dae2780e395204eab01af4d40220b9f5Johannes Berg		return;
6634673a894dae2780e395204eab01af4d40220b9f5Johannes Berg	}
6644673a894dae2780e395204eab01af4d40220b9f5Johannes Berg
665764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg	if (!params->unknown)
666764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg		return;
667764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg
668fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg	printf("\tVendor specific: OUI %.2x:%.2x:%.2x, data:",
6693563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		data[0], data[1], data[2]);
670fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg	for (i = 3; i < len; i++)
671fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg		printf(" %.2x", data[i]);
6723563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	printf("\n");
6733563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
6743563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
675764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Bergstatic void print_ies(unsigned char *ie, int ielen, struct scan_params *params)
6763563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
6773563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	while (ielen >= 2 && ielen >= ie[1]) {
67883b4934c612b84c28a656d496bea056e37fccb99Johannes Berg		if (ie[0] < ARRAY_SIZE(ieprinters) && ieprinters[ie[0]].name) {
67983b4934c612b84c28a656d496bea056e37fccb99Johannes Berg			print_ie(&ieprinters[ie[0]], ie[0], ie[1], ie + 2);
680764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg		} else if (ie[0] == 221 /* vendor */) {
681764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg			print_vendor(ie[1], ie + 2, params);
682764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg		} else if (params->unknown) {
6833563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			int i;
6843563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
6858086b7007d8a7f9d2bc22d154e26e9060f0e9676Johannes Berg			printf("\tUnknown IE (%d):", ie[0]);
6863563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			for (i=0; i<ie[1]; i++)
6878086b7007d8a7f9d2bc22d154e26e9060f0e9676Johannes Berg				printf(" %.2x", ie[2+i]);
6883563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			printf("\n");
6893563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		}
6903563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		ielen -= ie[1] + 2;
6913563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		ie += ie[1] + 2;
6923563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	}
6933563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
6943563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
6953563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Bergstatic int print_bss_handler(struct nl_msg *msg, void *arg)
6963563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
6973563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	struct nlattr *tb[NL80211_ATTR_MAX + 1];
6983563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
6993563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	struct nlattr *bss[NL80211_BSS_MAX + 1];
7003563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	char mac_addr[20], dev[20];
7013563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = {
7023563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		[NL80211_BSS_TSF] = { .type = NLA_U64 },
7033563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		[NL80211_BSS_FREQUENCY] = { .type = NLA_U32 },
7043563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		[NL80211_BSS_BSSID] = { },
7053563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		[NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 },
7063563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		[NL80211_BSS_CAPABILITY] = { .type = NLA_U16 },
7073563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		[NL80211_BSS_INFORMATION_ELEMENTS] = { },
708f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg		[NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 },
709f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg		[NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 },
7103563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	};
7113563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
7123563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
7133563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		  genlmsg_attrlen(gnlh, 0), NULL);
7143563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
7153563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	if (!tb[NL80211_ATTR_BSS]) {
7163563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		fprintf(stderr, "bss info missing!");
7173563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		return NL_SKIP;
7183563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	}
7193563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	if (nla_parse_nested(bss, NL80211_BSS_MAX,
7203563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			     tb[NL80211_ATTR_BSS],
7213563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			     bss_policy)) {
7223563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		fprintf(stderr, "failed to parse nested attributes!");
7233563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		return NL_SKIP;
7243563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	}
7253563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
7263563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	if (!bss[NL80211_BSS_BSSID])
7273563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		return NL_SKIP;
7283563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
7293563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	mac_addr_n2a(mac_addr, nla_data(bss[NL80211_BSS_BSSID]));
7303563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
7313563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	printf("BSS %s (on %s)\n", mac_addr, dev);
7323563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
733e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg	if (bss[NL80211_BSS_TSF]) {
734e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg		unsigned long long tsf;
735e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg		tsf = (unsigned long long)nla_get_u64(bss[NL80211_BSS_TSF]);
736e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg		printf("\tTSF: %llu usec (%llud, %.2lld:%.2llu:%.2llu)\n",
737e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg			tsf, tsf/1000/1000/60/60/24, (tsf/1000/1000/60/60) % 24,
738e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg			(tsf/1000/1000/60) % 60, (tsf/1000/1000) % 60);
739e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg	}
7403563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	if (bss[NL80211_BSS_FREQUENCY])
7413563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		printf("\tfreq: %d\n",
7423563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			nla_get_u32(bss[NL80211_BSS_FREQUENCY]));
7433563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	if (bss[NL80211_BSS_BEACON_INTERVAL])
7443563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		printf("\tbeacon interval: %d\n",
7453563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL]));
74692a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann	if (bss[NL80211_BSS_CAPABILITY]) {
74792a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann		__u16 capa = nla_get_u16(bss[NL80211_BSS_CAPABILITY]);
74892a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann		printf("\tcapability:");
74992a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann		if (capa & WLAN_CAPABILITY_ESS)
75092a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann			printf(" ESS");
75192a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann		if (capa & WLAN_CAPABILITY_IBSS)
75292a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann			printf(" IBSS");
75392a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann		if (capa & WLAN_CAPABILITY_PRIVACY)
75492a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann			printf(" Privacy");
75592a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann		if (capa & WLAN_CAPABILITY_SHORT_PREAMBLE)
75692a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann			printf(" ShortPreamble");
75792a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann		if (capa & WLAN_CAPABILITY_PBCC)
75892a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann			printf(" PBCC");
75992a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann		if (capa & WLAN_CAPABILITY_CHANNEL_AGILITY)
76092a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann			printf(" ChannelAgility");
76192a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann		if (capa & WLAN_CAPABILITY_SPECTRUM_MGMT)
76292a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann			printf(" SpectrumMgmt");
76392a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann		if (capa & WLAN_CAPABILITY_QOS)
76492a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann			printf(" QoS");
76592a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann		if (capa & WLAN_CAPABILITY_SHORT_SLOT_TIME)
76692a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann			printf(" ShortSlotTime");
76792a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann		if (capa & WLAN_CAPABILITY_APSD)
76892a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann			printf(" APSD");
76992a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann		if (capa & WLAN_CAPABILITY_DSSS_OFDM)
77092a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann			printf(" DSSS-OFDM");
77192a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann		printf(" (0x%.4x)\n", capa);
77292a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann	}
773f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg	if (bss[NL80211_BSS_SIGNAL_MBM]) {
774f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg		int s = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]);
775f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg		printf("\tsignal: %d.%.2d dBm\n", s/100, s%100);
776f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg	}
777f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg	if (bss[NL80211_BSS_SIGNAL_UNSPEC]) {
778f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg		unsigned char s = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]);
779f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg		printf("\tsignal: %d/100\n", s);
780f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg	}
7813563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	if (bss[NL80211_BSS_INFORMATION_ELEMENTS])
7823563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg		print_ies(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
783764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg			  nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
784764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg			  arg);
7853563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
7863563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	return NL_SKIP;
7873563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
7883563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
789764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Bergstatic struct scan_params scan_params;
7903563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg
7917c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Bergstatic int handle_scan_dump(struct nl80211_state *state,
7927c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Berg			    struct nl_cb *cb,
7933563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			    struct nl_msg *msg,
7943563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg			    int argc, char **argv)
7953563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{
796764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg	if (argc > 1)
797764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg		return 1;
798764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg
799764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg	scan_params.unknown = false;
800764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg	if (argc == 1 && !strcmp(argv[0], "-u"))
801764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg		scan_params.unknown = true;
802764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg
803764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_bss_handler,
804764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg		  &scan_params);
8053563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg	return 0;
8063563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg}
807764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes BergCOMMAND(scan, dump, "[-u]",
8086ca98d28b949d20cca2e158bef3e0cfd75b59672Johannes Berg	NL80211_CMD_GET_SCAN, NLM_F_DUMP, CIB_NETDEV, handle_scan_dump,
8096ca98d28b949d20cca2e158bef3e0cfd75b59672Johannes Berg	"Dump the current scan results. If -u is specified, print unknown\n"
8106ca98d28b949d20cca2e158bef3e0cfd75b59672Johannes Berg	"data in scan results.");
811a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg
812a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Bergstatic int handle_scan_combined(struct nl80211_state *state,
813a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg				struct nl_cb *cb,
814a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg				struct nl_msg *msg,
815a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg				int argc, char **argv)
816a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg{
817559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	char **trig_argv;
818a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	static char *dump_argv[] = {
819a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		NULL,
820a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		"scan",
821a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		"dump",
82292649eab6b3ccb0be600b8501fa7b83e9467819cMarcel Holtmann		NULL,
823a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	};
824a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	static const __u32 cmds[] = {
825a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		NL80211_CMD_NEW_SCAN_RESULTS,
826a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		NL80211_CMD_SCAN_ABORTED,
827a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	};
828559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	int trig_argc, dump_argc, err;
829a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg
830559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	if (argc >= 3 && !strcmp(argv[2], "-u")) {
831559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		dump_argc = 4;
832559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		dump_argv[3] = "-u";
833559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	} else
834559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		dump_argc = 3;
835559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg
836559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	trig_argc = 3 + (argc - 2) + (3 - dump_argc);
837559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	trig_argv = calloc(trig_argc, sizeof(*trig_argv));
838559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	if (!trig_argv)
839559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		return -ENOMEM;
840a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	trig_argv[0] = argv[0];
841559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	trig_argv[1] = "scan";
842559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	trig_argv[2] = "trigger";
843559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	int i;
844559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	for (i = 0; i < argc - 2 - (dump_argc - 3); i++)
845559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg		trig_argv[i + 3] = argv[i + 2 + (dump_argc - 3)];
846559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	err = handle_cmd(state, II_NETDEV, trig_argc, trig_argv);
847559a1713eba3ce41d260e01e2b68f2e28f71d3cdJohannes Berg	free(trig_argv);
848a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	if (err)
849a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		return err;
850a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg
85161725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	/*
85261725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * WARNING: DO NOT COPY THIS CODE INTO YOUR APPLICATION
85361725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 *
85461725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * This code has a bug, which requires creating a separate
85561725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * nl80211 socket to fix:
85661725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * It is possible for a NL80211_CMD_NEW_SCAN_RESULTS or
85761725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * NL80211_CMD_SCAN_ABORTED message to be sent by the kernel
85861725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * before (!) we listen to it, because we only start listening
85961725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * after we send our scan request.
86061725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 *
86161725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * Doing it the other way around has a race condition as well,
86261725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * if you first open the events socket you may get a notification
86361725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * for a previous scan.
86461725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 *
86561725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * The only proper way to fix this would be to listen to events
86661725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * before sending the command, and for the kernel to send the
86761725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * scan request along with the event, so that you can match up
86861725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * whether the scan you requested was finished or aborted (this
86961725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * may result in processing a scan that another application
87061725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * requested, but that doesn't seem to be a problem).
87161725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 *
87261725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 * Alas, the kernel doesn't do that (yet).
87361725dbed6df376809e8dc3865640244d8f1d690Johannes Berg	 */
87461725dbed6df376809e8dc3865640244d8f1d690Johannes Berg
875a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	if (listen_events(state, ARRAY_SIZE(cmds), cmds) ==
876a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg					NL80211_CMD_SCAN_ABORTED) {
877a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		printf("scan aborted!\n");
878a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg		return 0;
879a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	}
880a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg
881a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg	dump_argv[0] = argv[0];
88292649eab6b3ccb0be600b8501fa7b83e9467819cMarcel Holtmann	return handle_cmd(state, II_NETDEV, dump_argc, dump_argv);
883a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg}
8846ca98d28b949d20cca2e158bef3e0cfd75b59672Johannes BergTOPLEVEL(scan, "[-u] [freq <freq>*] [ssid <ssid>*|passive]", 0, 0,
8856ca98d28b949d20cca2e158bef3e0cfd75b59672Johannes Berg	 CIB_NETDEV, handle_scan_combined,
8866ca98d28b949d20cca2e158bef3e0cfd75b59672Johannes Berg	 "Scan on the given frequencies and probe for the given SSIDs\n"
8876ca98d28b949d20cca2e158bef3e0cfd75b59672Johannes Berg	 "(or wildcard if not given) unless passive scanning is requested.\n"
8886ca98d28b949d20cca2e158bef3e0cfd75b59672Johannes Berg	 "If -u is specified print unknown data in the scan results.");
889