scan.c revision fbf80af54408799f7e3c03430b798759019dd79b
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 16764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Bergstruct scan_params { 17764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg bool unknown; 18764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg}; 19764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg 207c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Bergstatic int handle_scan(struct nl80211_state *state, 217c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Berg struct nl_cb *cb, 223563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg struct nl_msg *msg, 233563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg int argc, char **argv) 243563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{ 253563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg struct nl_msg *ssids = NULL; 263563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg int err = -ENOBUFS; 273563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 283563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg ssids = nlmsg_alloc(); 293563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg if (!ssids) 303563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg return -ENOMEM; 313563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg NLA_PUT(ssids, 1, 0, ""); 323563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg nla_put_nested(msg, NL80211_ATTR_SCAN_SSIDS, ssids); 333563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 343563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg err = 0; 353563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg nla_put_failure: 363563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg nlmsg_free(ssids); 373563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg return err; 383563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg} 393563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes BergCOMMAND(scan, trigger, NULL, 403563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg NL80211_CMD_TRIGGER_SCAN, 0, CIB_NETDEV, handle_scan); 413563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 423563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Bergtypedef void (*printfn)(unsigned char type, unsigned char len, unsigned char *data); 433563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 443563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Bergstatic void print_ssid(unsigned char type, unsigned char len, unsigned char *data) 453563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{ 463563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg int i; 473563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\tSSID: "); 483563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg for (i=0; i<len; i++) { 493563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg if (isprint(data[i])) 503563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("%c", data[i]); 513563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg else 523563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\\x%.2x", data[i]); 533563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg } 543563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\n"); 553563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg} 563563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 573563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Bergstatic void print_supprates(unsigned char type, unsigned char len, unsigned char *data) 583563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{ 593563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg int i; 603563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 613563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg if (type == 1) 623563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\tSupported rates: "); 633563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg else 643563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\tExtended supported rates: "); 653563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 663563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg for (i=0; i<len; i++) { 673563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg int r = data[i] & 0x7f; 683563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("%d.%d%s ", r/2, 5*(r&1), data[i] & 0x80 ? "*":""); 693563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg } 703563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\n"); 713563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg} 723563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 733563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Bergstatic void print_ds(unsigned char type, unsigned char len, unsigned char *data) 743563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{ 753563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\tDS Parameter set: channel %d\n", data[0]); 763563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg} 773563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 783563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Bergstatic void print_ign(unsigned char type, unsigned char len, unsigned char *data) 793563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{ 803563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg /* ignore for now, not too useful */ 813563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg} 823563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 83764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Bergstatic const printfn ieprinters[] = { 84764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg [0] = print_ssid, 85764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg [1] = print_supprates, 86764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg [3] = print_ds, 87764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg [5] = print_ign, 88764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg [50] = print_supprates, 89764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg}; 90764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg 91764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Bergstatic void print_vendor(unsigned char len, unsigned char *data, 92764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg struct scan_params *params) 933563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{ 943563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg int i; 953563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 96fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg if (len < 3) { 97fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg printf("\tVendor specific: <too short> data:\n"); 98fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg for(i = 0; i < len; i++) 99fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg printf(" %.02x", data[i]); 100fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg printf("\n"); 101fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg return; 102fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg } 103fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg 104764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg /* currently _all_ vendor IEs are unknown (not parsed) */ 105764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg if (!params->unknown) 106764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg return; 107764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg 108fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg printf("\tVendor specific: OUI %.2x:%.2x:%.2x, data:", 1093563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg data[0], data[1], data[2]); 110fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg for (i = 3; i < len; i++) 111fbf80af54408799f7e3c03430b798759019dd79bJohannes Berg printf(" %.2x", data[i]); 1123563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\n"); 1133563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg} 1143563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 115764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Bergstatic void print_ies(unsigned char *ie, int ielen, struct scan_params *params) 1163563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{ 1173563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg while (ielen >= 2 && ielen >= ie[1]) { 11897ebbaf55e8729c28513d8a73f3e65e8d759ff80Johannes Berg if (ie[0] < ARRAY_SIZE(ieprinters) && ieprinters[ie[0]]) { 1193563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg ieprinters[ie[0]](ie[0], ie[1], ie + 2); 120764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg } else if (ie[0] == 221 /* vendor */) { 121764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg print_vendor(ie[1], ie + 2, params); 122764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg } else if (params->unknown) { 1233563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg int i; 1243563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 1253563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\tUnknown IE (%d): ", ie[0]); 1263563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg for (i=0; i<ie[1]; i++) 1273563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\\x%.2x", ie[2+i]); 1283563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\n"); 1293563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg } 1303563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg ielen -= ie[1] + 2; 1313563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg ie += ie[1] + 2; 1323563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg } 1333563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg} 1343563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 1353563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Bergstatic int print_bss_handler(struct nl_msg *msg, void *arg) 1363563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{ 1373563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg struct nlattr *tb[NL80211_ATTR_MAX + 1]; 1383563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); 1393563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg struct nlattr *bss[NL80211_BSS_MAX + 1]; 1403563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg char mac_addr[20], dev[20]; 1413563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg static struct nla_policy bss_policy[NL80211_BSS_MAX + 1] = { 1423563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg [NL80211_BSS_TSF] = { .type = NLA_U64 }, 1433563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg [NL80211_BSS_FREQUENCY] = { .type = NLA_U32 }, 1443563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg [NL80211_BSS_BSSID] = { }, 1453563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg [NL80211_BSS_BEACON_INTERVAL] = { .type = NLA_U16 }, 1463563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg [NL80211_BSS_CAPABILITY] = { .type = NLA_U16 }, 1473563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg [NL80211_BSS_INFORMATION_ELEMENTS] = { }, 148f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg [NL80211_BSS_SIGNAL_MBM] = { .type = NLA_U32 }, 149f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg [NL80211_BSS_SIGNAL_UNSPEC] = { .type = NLA_U8 }, 1503563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg }; 1513563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 1523563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), 1533563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg genlmsg_attrlen(gnlh, 0), NULL); 1543563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 1553563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg if (!tb[NL80211_ATTR_BSS]) { 1563563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg fprintf(stderr, "bss info missing!"); 1573563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg return NL_SKIP; 1583563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg } 1593563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg if (nla_parse_nested(bss, NL80211_BSS_MAX, 1603563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg tb[NL80211_ATTR_BSS], 1613563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg bss_policy)) { 1623563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg fprintf(stderr, "failed to parse nested attributes!"); 1633563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg return NL_SKIP; 1643563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg } 1653563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 1663563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg if (!bss[NL80211_BSS_BSSID]) 1673563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg return NL_SKIP; 1683563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 1693563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg mac_addr_n2a(mac_addr, nla_data(bss[NL80211_BSS_BSSID])); 1703563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev); 1713563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("BSS %s (on %s)\n", mac_addr, dev); 1723563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 173e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg if (bss[NL80211_BSS_TSF]) { 174e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg unsigned long long tsf; 175e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg tsf = (unsigned long long)nla_get_u64(bss[NL80211_BSS_TSF]); 176e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg printf("\tTSF: %llu usec (%llud, %.2lld:%.2llu:%.2llu)\n", 177e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg tsf, tsf/1000/1000/60/60/24, (tsf/1000/1000/60/60) % 24, 178e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg (tsf/1000/1000/60) % 60, (tsf/1000/1000) % 60); 179e7109a8aa93fab514d0c71803df622bec6dd23d4Johannes Berg } 1803563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg if (bss[NL80211_BSS_FREQUENCY]) 1813563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\tfreq: %d\n", 1823563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg nla_get_u32(bss[NL80211_BSS_FREQUENCY])); 1833563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg if (bss[NL80211_BSS_BEACON_INTERVAL]) 1843563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\tbeacon interval: %d\n", 1853563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg nla_get_u16(bss[NL80211_BSS_BEACON_INTERVAL])); 1863563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg if (bss[NL80211_BSS_CAPABILITY]) 1873563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg printf("\tcapability: 0x%.4x\n", 1883563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg nla_get_u16(bss[NL80211_BSS_CAPABILITY])); 189f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg if (bss[NL80211_BSS_SIGNAL_MBM]) { 190f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg int s = nla_get_u32(bss[NL80211_BSS_SIGNAL_MBM]); 191f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg printf("\tsignal: %d.%.2d dBm\n", s/100, s%100); 192f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg } 193f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg if (bss[NL80211_BSS_SIGNAL_UNSPEC]) { 194f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg unsigned char s = nla_get_u8(bss[NL80211_BSS_SIGNAL_UNSPEC]); 195f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg printf("\tsignal: %d/100\n", s); 196f2e17e1fa6d4b2634564e2a8819cd4ce5f8469edJohannes Berg } 1973563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg if (bss[NL80211_BSS_INFORMATION_ELEMENTS]) 1983563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg print_ies(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]), 199764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]), 200764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg arg); 2013563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 2023563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg return NL_SKIP; 2033563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg} 2043563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 205764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Bergstatic struct scan_params scan_params; 2063563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg 2077c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Bergstatic int handle_scan_dump(struct nl80211_state *state, 2087c37a24d7570cd9ff6b89d6fa8c1846c9b66969dJohannes Berg struct nl_cb *cb, 2093563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg struct nl_msg *msg, 2103563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg int argc, char **argv) 2113563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg{ 212764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg if (argc > 1) 213764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg return 1; 214764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg 215764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg scan_params.unknown = false; 216764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg if (argc == 1 && !strcmp(argv[0], "-u")) 217764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg scan_params.unknown = true; 218764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg 219764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_bss_handler, 220764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes Berg &scan_params); 2213563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg return 0; 2223563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg} 223764fe7533b74fb064f112497c9a1d5651a1ee5b8Johannes BergCOMMAND(scan, dump, "[-u]", 2243563f4c510e0afbf18bf616f7e35a9b05a535ec2Johannes Berg NL80211_CMD_GET_SCAN, NLM_F_DUMP, CIB_NETDEV, handle_scan_dump); 225a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg 226a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Bergstatic int handle_scan_combined(struct nl80211_state *state, 227a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg struct nl_cb *cb, 228a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg struct nl_msg *msg, 229a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg int argc, char **argv) 230a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg{ 231a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg static char *trig_argv[] = { 232a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg NULL, 233a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg "scan", 234a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg "trigger", 235a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg }; 236a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg static char *dump_argv[] = { 237a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg NULL, 238a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg "scan", 239a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg "dump", 240a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg }; 241a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg static const __u32 cmds[] = { 242a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg NL80211_CMD_NEW_SCAN_RESULTS, 243a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg NL80211_CMD_SCAN_ABORTED, 244a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg }; 245a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg int err; 246a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg 247a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg trig_argv[0] = argv[0]; 248a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg err = handle_cmd(state, II_NETDEV, ARRAY_SIZE(trig_argv), trig_argv); 249a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg if (err) 250a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg return err; 251a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg 25261725dbed6df376809e8dc3865640244d8f1d690Johannes Berg /* 25361725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * WARNING: DO NOT COPY THIS CODE INTO YOUR APPLICATION 25461725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * 25561725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * This code has a bug, which requires creating a separate 25661725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * nl80211 socket to fix: 25761725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * It is possible for a NL80211_CMD_NEW_SCAN_RESULTS or 25861725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * NL80211_CMD_SCAN_ABORTED message to be sent by the kernel 25961725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * before (!) we listen to it, because we only start listening 26061725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * after we send our scan request. 26161725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * 26261725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * Doing it the other way around has a race condition as well, 26361725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * if you first open the events socket you may get a notification 26461725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * for a previous scan. 26561725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * 26661725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * The only proper way to fix this would be to listen to events 26761725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * before sending the command, and for the kernel to send the 26861725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * scan request along with the event, so that you can match up 26961725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * whether the scan you requested was finished or aborted (this 27061725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * may result in processing a scan that another application 27161725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * requested, but that doesn't seem to be a problem). 27261725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * 27361725dbed6df376809e8dc3865640244d8f1d690Johannes Berg * Alas, the kernel doesn't do that (yet). 27461725dbed6df376809e8dc3865640244d8f1d690Johannes Berg */ 27561725dbed6df376809e8dc3865640244d8f1d690Johannes Berg 276a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg if (listen_events(state, ARRAY_SIZE(cmds), cmds) == 277a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg NL80211_CMD_SCAN_ABORTED) { 278a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg printf("scan aborted!\n"); 279a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg return 0; 280a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg } 281a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg 282a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg dump_argv[0] = argv[0]; 283a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg return handle_cmd(state, II_NETDEV, ARRAY_SIZE(dump_argv), dump_argv); 284a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes Berg} 285a5fe4ef2f3e282a789c86edee838f338b07d5033Johannes BergTOPLEVEL(scan, NULL, 0, 0, CIB_NETDEV, handle_scan_combined); 286