scan.c revision 6ff0c93ad7c73c16892dd261612a71255fdbf978
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 30764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Bergstruct scan_params { 31764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg bool unknown; 32764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg}; 33764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg 347c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Bergstatic int handle_scan(struct nl80211_state *state, 357c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Berg struct nl_cb *cb, 363563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg struct nl_msg *msg, 373563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg int argc, char **argv) 383563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{ 393563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg struct nl_msg *ssids = NULL; 403563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg int err = -ENOBUFS; 413563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 423563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg ssids = nlmsg_alloc(); 433563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg if (!ssids) 443563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg return -ENOMEM; 453563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg NLA_PUT(ssids, 1, 0, ""); 463563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids); 473563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 483563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg err = 0; 493563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg nla_put_failure: 503563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg nlmsg_free(ssids); 513563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg return err; 523563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg} 533563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes BergCOMMAND(scan, trigger, NULL, 543563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg NL80211_CMD_TRIGGER_SCAN, 0, CIB_NETDEV, handle_scan); 553563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 563563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Bergtypedef void (*printfn)(unsigned char type, unsigned char len, unsigned char *data); 573563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 583563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Bergstatic void print_ssid(unsigned char type, unsigned char len, unsigned char *data) 593563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{ 603563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg int i; 613563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\tSSID: "); 623563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg for (i=0; i<len; i++) { 633563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg if (isprint(data[i])) 643563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("%c", data[i]); 653563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg else 663563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\\x%.2x", data[i]); 673563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg } 683563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\n"); 693563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg} 703563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 713563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Bergstatic void print_supprates(unsigned char type, unsigned char len, unsigned char *data) 723563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{ 733563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg int i; 743563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 753563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg if (type == 1) 763563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\tSupported rates: "); 773563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg else 783563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\tExtended supported rates: "); 793563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 803563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg for (i=0; i<len; i++) { 813563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg int r = data[i] & 0x7f; 823563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("%d.%d%s ", r/2, 5*(r&1), data[i] & 0x80 ? "*":""); 833563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg } 843563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\n"); 853563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg} 863563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 873563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Bergstatic void print_ds(unsigned char type, unsigned char len, unsigned char *data) 883563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{ 893563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\tDS Parameter set: channel %d\n", data[0]); 903563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg} 913563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 923563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Bergstatic void print_ign(unsigned char type, unsigned char len, unsigned char *data) 933563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{ 943563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg /* ignore for now, not too useful */ 953563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg} 963563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 97b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmannstatic void print_country(unsigned char type, unsigned char len, unsigned char *data) 98b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann{ 99b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann int i; 100b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann 101b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann printf("\tCountry: %.*s", 2, data); 102b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann switch (data[2]) { 103b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann case 'I': 104b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann printf(" (indoor)"); 105b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann break; 106b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann case 'O': 107b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann printf(" (outdoor)"); 108b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann break; 109b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann } 110b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann printf(", data:"); 111b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann for(i=0; i<len-3; i++) 112b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann printf(" %.02x", data[i + 3]); 113b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann printf("\n"); 114b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann} 115b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann 116fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmannstatic void print_erp(unsigned char type, unsigned char len, unsigned char *data) 117fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann{ 118fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann if (data[0] == 0x00) 119fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann return; 120fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann 121fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann printf("\tERP:"); 122fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann if (data[0] & 0x01) 123fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann printf(" NonERP_Present"); 124fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann if (data[0] & 0x02) 125fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann printf(" Use_Protection"); 126fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann if (data[0] & 0x04) 127fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann printf(" Barker_Preamble_Mode"); 128fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann printf("\n"); 129fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann} 130fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann 1319b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmannstatic void print_capabilities(unsigned char type, unsigned char len, unsigned char *data) 1329b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann{ 1339b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann int i; 1349b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann 1359b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann printf("\tExtended capabilties:"); 1369b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann for(i=0; i<len; i++) 1379b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann printf(" %.02x", data[i]); 1389b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann printf("\n"); 1399b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann} 1409b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann 141764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Bergstatic const printfn ieprinters[] = { 142764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg [0] = print_ssid, 143764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg [1] = print_supprates, 144764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg [3] = print_ds, 145764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg [5] = print_ign, 146b7e8fa37d03cb17e69cdcf37041ffdc299c693dfMarcel Holtmann [7] = print_country, 147fc4d1484a18a2f67df901126123177ea94e8037bMarcel Holtmann [42] = print_erp, 148764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg [50] = print_supprates, 1499b880b00e4a3b4a9befbdf55f90c89568781cf73Marcel Holtmann [127] = print_capabilities, 150764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg}; 151764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg 1524673a894dae2780e395204eab01af4d40220b9f5Johannes Bergstatic void tab_on_first(bool *first) 1534673a894dae2780e395204eab01af4d40220b9f5Johannes Berg{ 1544673a894dae2780e395204eab01af4d40220b9f5Johannes Berg if (!*first) 1554673a894dae2780e395204eab01af4d40220b9f5Johannes Berg printf("\t"); 1564673a894dae2780e395204eab01af4d40220b9f5Johannes Berg else 1574673a894dae2780e395204eab01af4d40220b9f5Johannes Berg *first = false; 1584673a894dae2780e395204eab01af4d40220b9f5Johannes Berg} 1594673a894dae2780e395204eab01af4d40220b9f5Johannes Berg 1606ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmannstatic void print_wifi_wmm(unsigned char type, unsigned char len, unsigned char *data) 1616ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann{ 1626ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann int i; 1636ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann 1646ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann printf("\tWMM "); 1656ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann switch (data[0]) { 1666ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann case 0x00: 1676ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann printf("information:"); 1686ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann break; 1696ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann case 0x01: 1706ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann printf("parameter:"); 1716ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann break; 1726ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann default: 1736ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann printf("type %d:", data[0]); 1746ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann break; 1756ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann } 1766ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann 1776ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann for(i=0; i<len-1; i++) 1786ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann printf(" %.02x", data[i + 1]); 1796ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann printf("\n"); 1806ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann} 1816ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann 1824673a894dae2780e395204eab01af4d40220b9f5Johannes Bergstatic void print_wifi_wps(unsigned char type, unsigned char len, unsigned char *data) 1834673a894dae2780e395204eab01af4d40220b9f5Johannes Berg{ 1844673a894dae2780e395204eab01af4d40220b9f5Johannes Berg bool first = true; 1854673a894dae2780e395204eab01af4d40220b9f5Johannes Berg __u16 subtype, sublen; 1864673a894dae2780e395204eab01af4d40220b9f5Johannes Berg 1874673a894dae2780e395204eab01af4d40220b9f5Johannes Berg printf("\tWPS:"); 1884673a894dae2780e395204eab01af4d40220b9f5Johannes Berg 1894673a894dae2780e395204eab01af4d40220b9f5Johannes Berg while (len >= 4) { 1904673a894dae2780e395204eab01af4d40220b9f5Johannes Berg subtype = (data[0] << 8) + data[1]; 1914673a894dae2780e395204eab01af4d40220b9f5Johannes Berg sublen = (data[2] << 8) + data[3]; 1924673a894dae2780e395204eab01af4d40220b9f5Johannes Berg if (sublen > len) 1934673a894dae2780e395204eab01af4d40220b9f5Johannes Berg break; 1944673a894dae2780e395204eab01af4d40220b9f5Johannes Berg 1954673a894dae2780e395204eab01af4d40220b9f5Johannes Berg switch (subtype) { 1964673a894dae2780e395204eab01af4d40220b9f5Johannes Berg case 0x104a: 1974673a894dae2780e395204eab01af4d40220b9f5Johannes Berg tab_on_first(&first); 1984673a894dae2780e395204eab01af4d40220b9f5Johannes Berg printf("\t * Version: %#.2x\n", data[4]); 1994673a894dae2780e395204eab01af4d40220b9f5Johannes Berg break; 2004673a894dae2780e395204eab01af4d40220b9f5Johannes Berg case 0x1011: 2014673a894dae2780e395204eab01af4d40220b9f5Johannes Berg tab_on_first(&first); 2024673a894dae2780e395204eab01af4d40220b9f5Johannes Berg printf("\t * Device name: %.*s\n", sublen, data + 4); 2034673a894dae2780e395204eab01af4d40220b9f5Johannes Berg break; 2044673a894dae2780e395204eab01af4d40220b9f5Johannes Berg case 0x1021: 2054673a894dae2780e395204eab01af4d40220b9f5Johannes Berg tab_on_first(&first); 2064673a894dae2780e395204eab01af4d40220b9f5Johannes Berg printf("\t * Manufacturer: %.*s\n", sublen, data + 4); 2074673a894dae2780e395204eab01af4d40220b9f5Johannes Berg break; 2084673a894dae2780e395204eab01af4d40220b9f5Johannes Berg case 0x1023: 2094673a894dae2780e395204eab01af4d40220b9f5Johannes Berg tab_on_first(&first); 2104673a894dae2780e395204eab01af4d40220b9f5Johannes Berg printf("\t * Model: %.*s\n", sublen, data + 4); 2114673a894dae2780e395204eab01af4d40220b9f5Johannes Berg break; 2127ee5a86565fcf11ea33356ae9b202bc0336e13d6Johannes Berg case 0x1057: { 2137ee5a86565fcf11ea33356ae9b202bc0336e13d6Johannes Berg __u16 val = (data[4] << 8) | data[5]; 2147ee5a86565fcf11ea33356ae9b202bc0336e13d6Johannes Berg tab_on_first(&first); 2157ee5a86565fcf11ea33356ae9b202bc0336e13d6Johannes Berg printf("\t * AP setup locked: 0x%.4x\n", val); 2167ee5a86565fcf11ea33356ae9b202bc0336e13d6Johannes Berg break; 2177ee5a86565fcf11ea33356ae9b202bc0336e13d6Johannes Berg } 2184673a894dae2780e395204eab01af4d40220b9f5Johannes Berg case 0x1008: { 2194673a894dae2780e395204eab01af4d40220b9f5Johannes Berg __u16 meth = (data[4] << 8) + data[5]; 2204673a894dae2780e395204eab01af4d40220b9f5Johannes Berg bool comma = false; 2214673a894dae2780e395204eab01af4d40220b9f5Johannes Berg tab_on_first(&first); 2224673a894dae2780e395204eab01af4d40220b9f5Johannes Berg printf("\t * Config methods:"); 2234673a894dae2780e395204eab01af4d40220b9f5Johannes Berg#define T(bit, name) do { \ 2244673a894dae2780e395204eab01af4d40220b9f5Johannes Berg if (meth & (1<<bit)) { \ 2254673a894dae2780e395204eab01af4d40220b9f5Johannes Berg if (comma) \ 2264673a894dae2780e395204eab01af4d40220b9f5Johannes Berg printf(","); \ 2274673a894dae2780e395204eab01af4d40220b9f5Johannes Berg comma = true; \ 2284673a894dae2780e395204eab01af4d40220b9f5Johannes Berg printf(" " name); \ 2294673a894dae2780e395204eab01af4d40220b9f5Johannes Berg } } while (0) 2304673a894dae2780e395204eab01af4d40220b9f5Johannes Berg T(0, "USB"); 2314673a894dae2780e395204eab01af4d40220b9f5Johannes Berg T(1, "Ethernet"); 2324673a894dae2780e395204eab01af4d40220b9f5Johannes Berg T(2, "Label"); 2334673a894dae2780e395204eab01af4d40220b9f5Johannes Berg T(3, "Display"); 2344673a894dae2780e395204eab01af4d40220b9f5Johannes Berg T(4, "Ext. NFC"); 2354673a894dae2780e395204eab01af4d40220b9f5Johannes Berg T(5, "Int. NFC"); 2364673a894dae2780e395204eab01af4d40220b9f5Johannes Berg T(6, "NFC Intf."); 2374673a894dae2780e395204eab01af4d40220b9f5Johannes Berg T(7, "PBC"); 2384673a894dae2780e395204eab01af4d40220b9f5Johannes Berg T(8, "Keypad"); 2394673a894dae2780e395204eab01af4d40220b9f5Johannes Berg printf("\n"); 2404673a894dae2780e395204eab01af4d40220b9f5Johannes Berg break; 2414673a894dae2780e395204eab01af4d40220b9f5Johannes Berg#undef T 2424673a894dae2780e395204eab01af4d40220b9f5Johannes Berg } 2434673a894dae2780e395204eab01af4d40220b9f5Johannes Berg default: 2444673a894dae2780e395204eab01af4d40220b9f5Johannes Berg break; 2454673a894dae2780e395204eab01af4d40220b9f5Johannes Berg } 2464673a894dae2780e395204eab01af4d40220b9f5Johannes Berg 2474673a894dae2780e395204eab01af4d40220b9f5Johannes Berg data += sublen + 4; 2484673a894dae2780e395204eab01af4d40220b9f5Johannes Berg len -= sublen + 4; 2494673a894dae2780e395204eab01af4d40220b9f5Johannes Berg } 2504673a894dae2780e395204eab01af4d40220b9f5Johannes Berg 2514673a894dae2780e395204eab01af4d40220b9f5Johannes Berg if (len != 0) { 2524673a894dae2780e395204eab01af4d40220b9f5Johannes Berg printf("\t\t * bogus tail data (%d):", len); 2534673a894dae2780e395204eab01af4d40220b9f5Johannes Berg while (len) { 2544673a894dae2780e395204eab01af4d40220b9f5Johannes Berg printf(" %.2x", *data); 2554673a894dae2780e395204eab01af4d40220b9f5Johannes Berg data++; 2564673a894dae2780e395204eab01af4d40220b9f5Johannes Berg len--; 2574673a894dae2780e395204eab01af4d40220b9f5Johannes Berg } 2584673a894dae2780e395204eab01af4d40220b9f5Johannes Berg printf("\n"); 2594673a894dae2780e395204eab01af4d40220b9f5Johannes Berg } 2604673a894dae2780e395204eab01af4d40220b9f5Johannes Berg} 2614673a894dae2780e395204eab01af4d40220b9f5Johannes Berg 2624673a894dae2780e395204eab01af4d40220b9f5Johannes Bergstatic const printfn wifiprinters[] = { 2636ff0c93ad7c73c16892dd261612a71255fdbf978Marcel Holtmann [2] = print_wifi_wmm, 2644673a894dae2780e395204eab01af4d40220b9f5Johannes Berg [4] = print_wifi_wps, 2654673a894dae2780e395204eab01af4d40220b9f5Johannes Berg}; 2664673a894dae2780e395204eab01af4d40220b9f5Johannes Berg 267764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Bergstatic void print_vendor(unsigned char len, unsigned char *data, 268764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg struct scan_params *params) 2693563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{ 2703563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg int i; 2713563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 272fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg if (len < 3) { 2734673a894dae2780e395204eab01af4d40220b9f5Johannes Berg printf("\tVendor specific: <too short> data:"); 274fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg for(i = 0; i < len; i++) 275fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg printf(" %.02x", data[i]); 276fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg printf("\n"); 277fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg return; 278fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg } 279fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg 2804673a894dae2780e395204eab01af4d40220b9f5Johannes Berg if (len >= 4 && data[0] == 0x00 && data[1] == 0x50 && data[2] == 0xF2) { 2814673a894dae2780e395204eab01af4d40220b9f5Johannes Berg if (data[3] < ARRAY_SIZE(wifiprinters) && wifiprinters[data[3]]) 2824673a894dae2780e395204eab01af4d40220b9f5Johannes Berg return wifiprinters[data[3]](data[3], len - 4, data + 4); 2834673a894dae2780e395204eab01af4d40220b9f5Johannes Berg if (!params->unknown) 2844673a894dae2780e395204eab01af4d40220b9f5Johannes Berg return; 2854673a894dae2780e395204eab01af4d40220b9f5Johannes Berg printf("\tWiFi OUI %#.2x data:", data[3]); 2864673a894dae2780e395204eab01af4d40220b9f5Johannes Berg for(i = 0; i < len - 4; i++) 2874673a894dae2780e395204eab01af4d40220b9f5Johannes Berg printf(" %.02x", data[i + 4]); 2884673a894dae2780e395204eab01af4d40220b9f5Johannes Berg printf("\n"); 2894673a894dae2780e395204eab01af4d40220b9f5Johannes Berg return; 2904673a894dae2780e395204eab01af4d40220b9f5Johannes Berg } 2914673a894dae2780e395204eab01af4d40220b9f5Johannes Berg 292764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg if (!params->unknown) 293764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg return; 294764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg 295fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg printf("\tVendor specific: OUI %.2x:%.2x:%.2x, data:", 2963563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg data[0], data[1], data[2]); 297fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg for (i = 3; i < len; i++) 298fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg printf(" %.2x", data[i]); 2993563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\n"); 3003563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg} 3013563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 302764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Bergstatic void print_ies(unsigned char *ie, int ielen, struct scan_params *params) 3033563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{ 3043563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg while (ielen >= 2 && ielen >= ie[1]) { 30597ebbaf55e8729c28513d8a73f3e65e8d759ff80Johannes Berg if (ie[0] < ARRAY_SIZE(ieprinters) && ieprinters[ie[0]]) { 3063563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg ieprinters[ie[0]](ie[0], ie[1], ie + 2); 307764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg } else if (ie[0] == 221 /* vendor */) { 308764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg print_vendor(ie[1], ie + 2, params); 309764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg } else if (params->unknown) { 3103563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg int i; 3113563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 3128086b7007d8a7f9d2bc22d154e26e9060f0e9676Johannes Berg printf("\tUnknown IE (%d):", ie[0]); 3133563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg for (i=0; i<ie[1]; i++) 3148086b7007d8a7f9d2bc22d154e26e9060f0e9676Johannes Berg printf(" %.2x", ie[2+i]); 3153563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\n"); 3163563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg } 3173563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg ielen -= ie[1] + 2; 3183563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg ie += ie[1] + 2; 3193563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg } 3203563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg} 3213563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 3223563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Bergstatic int print_bss_handler(struct nl_msg *msg, void *arg) 3233563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{ 3243563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg struct nlattr *tb[NL80211_ATTR_MAX + 1]; 3253563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 3263563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg struct nlattr *bss[NL80211_BSS_MAX + 1]; 3273563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg char mac_addr[20], dev[20]; 3283563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = { 3293563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg [NL80211_BSS_TSF] = { .type = NLA_U64 }, 3303563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 }, 3313563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg [NL80211_BSS_BSSID] = { }, 3323563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 }, 3333563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 }, 3343563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg [NL80211_BSS_INFORMATION_ELEMENTS] = { }, 335f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 }, 336f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 }, 3373563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg }; 3383563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 3393563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 3403563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg genlmsg_attrlen(gnlh, 0), NULL); 3413563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 3423563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg if (!tb[NL80211_ATTR_BSS]) { 3433563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg fprintf(stderr, "bss info missing!"); 3443563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg return NL_SKIP; 3453563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg } 3463563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg if (nla_parse_nested(bss, NL80211_BSS_MAX, 3473563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg tb[NL80211_ATTR_BSS], 3483563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg bss_policy)) { 3493563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg fprintf(stderr, "failed to parse nested attributes!"); 3503563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg return NL_SKIP; 3513563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg } 3523563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 3533563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg if (!bss[NL80211_BSS_BSSID]) 3543563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg return NL_SKIP; 3553563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 3563563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg mac_addr_n2a(mac_addr, nla_data(bss[NL80211_BSS_BSSID])); 3573563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev); 3583563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("BSS %s (on %s)\n", mac_addr, dev); 3593563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 360e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg if (bss[NL80211_BSS_TSF]) { 361e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg unsigned long long tsf; 362e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg tsf = (unsigned long long)nla_get_u64(bss[NL80211_BSS_TSF]); 363e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg printf("\tTSF: %llu usec (%llud, %.2lld:%.2llu:%.2llu)\n", 364e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg tsf, tsf/1000/1000/60/60/24, (tsf/1000/1000/60/60) % 24, 365e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg (tsf/1000/1000/60) % 60, (tsf/1000/1000) % 60); 366e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg } 3673563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg if (bss[NL80211_BSS_FREQUENCY]) 3683563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\tfreq: %d\n", 3693563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg nla_get_u32(bss[NL80211_BSS_FREQUENCY])); 3703563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg if (bss[NL80211_BSS_BEACON_INTERVAL]) 3713563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\tbeacon interval: %d\n", 3723563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL])); 37392a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann if (bss[NL80211_BSS_CAPABILITY]) { 37492a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann __u16 capa = nla_get_u16(bss[NL80211_BSS_CAPABILITY]); 37592a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann printf("\tcapability:"); 37692a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann if (capa & WLAN_CAPABILITY_ESS) 37792a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann printf(" ESS"); 37892a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann if (capa & WLAN_CAPABILITY_IBSS) 37992a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann printf(" IBSS"); 38092a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann if (capa & WLAN_CAPABILITY_PRIVACY) 38192a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann printf(" Privacy"); 38292a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann if (capa & WLAN_CAPABILITY_SHORT_PREAMBLE) 38392a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann printf(" ShortPreamble"); 38492a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann if (capa & WLAN_CAPABILITY_PBCC) 38592a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann printf(" PBCC"); 38692a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann if (capa & WLAN_CAPABILITY_CHANNEL_AGILITY) 38792a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann printf(" ChannelAgility"); 38892a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann if (capa & WLAN_CAPABILITY_SPECTRUM_MGMT) 38992a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann printf(" SpectrumMgmt"); 39092a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann if (capa & WLAN_CAPABILITY_QOS) 39192a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann printf(" QoS"); 39292a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann if (capa & WLAN_CAPABILITY_SHORT_SLOT_TIME) 39392a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann printf(" ShortSlotTime"); 39492a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann if (capa & WLAN_CAPABILITY_APSD) 39592a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann printf(" APSD"); 39692a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann if (capa & WLAN_CAPABILITY_DSSS_OFDM) 39792a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann printf(" DSSS-OFDM"); 39892a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann printf(" (0x%.4x)\n", capa); 39992a04ecd916b20e151c4b40e740b6bd85131e31eMarcel Holtmann } 400f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg if (bss[NL80211_BSS_SIGNAL_MBM]) { 401f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg int s = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]); 402f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg printf("\tsignal: %d.%.2d dBm\n", s/100, s%100); 403f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg } 404f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg if (bss[NL80211_BSS_SIGNAL_UNSPEC]) { 405f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg unsigned char s = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]); 406f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg printf("\tsignal: %d/100\n", s); 407f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg } 4083563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) 4093563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg print_ies(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]), 410764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]), 411764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg arg); 4123563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 4133563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg return NL_SKIP; 4143563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg} 4153563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 416764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Bergstatic struct scan_params scan_params; 4173563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 4187c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Bergstatic int handle_scan_dump(struct nl80211_state *state, 4197c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Berg struct nl_cb *cb, 4203563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg struct nl_msg *msg, 4213563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg int argc, char **argv) 4223563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{ 423764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg if (argc > 1) 424764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg return 1; 425764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg 426764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg scan_params.unknown = false; 427764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg if (argc == 1 && !strcmp(argv[0], "-u")) 428764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg scan_params.unknown = true; 429764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg 430764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_bss_handler, 431764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg &scan_params); 4323563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg return 0; 4333563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg} 434764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes BergCOMMAND(scan, dump, "[-u]", 4353563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg NL80211_CMD_GET_SCAN, NLM_F_DUMP, CIB_NETDEV, handle_scan_dump); 436a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg 437a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Bergstatic int handle_scan_combined(struct nl80211_state *state, 438a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg struct nl_cb *cb, 439a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg struct nl_msg *msg, 440a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg int argc, char **argv) 441a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg{ 442a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg static char *trig_argv[] = { 443a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg NULL, 444a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg "scan", 445a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg "trigger", 446a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg }; 447a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg static char *dump_argv[] = { 448a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg NULL, 449a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg "scan", 450a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg "dump", 45192649eab6b3ccb0be600b8501fa7b83e9467819cMarcel Holtmann NULL, 452a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg }; 453a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg static const __u32 cmds[] = { 454a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg NL80211_CMD_NEW_SCAN_RESULTS, 455a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg NL80211_CMD_SCAN_ABORTED, 456a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg }; 45792649eab6b3ccb0be600b8501fa7b83e9467819cMarcel Holtmann int dump_argc, err; 458a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg 459a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg trig_argv[0] = argv[0]; 460a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg err = handle_cmd(state, II_NETDEV, ARRAY_SIZE(trig_argv), trig_argv); 461a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg if (err) 462a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg return err; 463a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg 46461725dbed6df376809e8dc3865640244d8f1d690Johannes Berg /* 46561725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * WARNING: DO NOT COPY THIS CODE INTO YOUR APPLICATION 46661725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * 46761725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * This code has a bug, which requires creating a separate 46861725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * nl80211 socket to fix: 46961725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * It is possible for a NL80211_CMD_NEW_SCAN_RESULTS or 47061725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * NL80211_CMD_SCAN_ABORTED message to be sent by the kernel 47161725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * before (!) we listen to it, because we only start listening 47261725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * after we send our scan request. 47361725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * 47461725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * Doing it the other way around has a race condition as well, 47561725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * if you first open the events socket you may get a notification 47661725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * for a previous scan. 47761725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * 47861725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * The only proper way to fix this would be to listen to events 47961725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * before sending the command, and for the kernel to send the 48061725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * scan request along with the event, so that you can match up 48161725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * whether the scan you requested was finished or aborted (this 48261725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * may result in processing a scan that another application 48361725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * requested, but that doesn't seem to be a problem). 48461725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * 48561725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * Alas, the kernel doesn't do that (yet). 48661725dbed6df376809e8dc3865640244d8f1d690Johannes Berg */ 48761725dbed6df376809e8dc3865640244d8f1d690Johannes Berg 488a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg if (listen_events(state, ARRAY_SIZE(cmds), cmds) == 489a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg NL80211_CMD_SCAN_ABORTED) { 490a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg printf("scan aborted!\n"); 491a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg return 0; 492a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg } 493a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg 49492649eab6b3ccb0be600b8501fa7b83e9467819cMarcel Holtmann if (argc == 3 && !strcmp(argv[2], "-u")) { 49592649eab6b3ccb0be600b8501fa7b83e9467819cMarcel Holtmann dump_argc = 4; 49692649eab6b3ccb0be600b8501fa7b83e9467819cMarcel Holtmann dump_argv[3] = "-u"; 49792649eab6b3ccb0be600b8501fa7b83e9467819cMarcel Holtmann } else 49892649eab6b3ccb0be600b8501fa7b83e9467819cMarcel Holtmann dump_argc = 3; 49992649eab6b3ccb0be600b8501fa7b83e9467819cMarcel Holtmann 500a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg dump_argv[0] = argv[0]; 50192649eab6b3ccb0be600b8501fa7b83e9467819cMarcel Holtmann return handle_cmd(state, II_NETDEV, dump_argc, dump_argv); 502a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg} 50392649eab6b3ccb0be600b8501fa7b83e9467819cMarcel HoltmannTOPLEVEL(scan, "[-u]", 0, 0, CIB_NETDEV, handle_scan_combined); 504