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