X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=scan.c;h=bb84a6776d055ca392e0650e31733820be572e19;hb=d8880179da0a04fcbe6759497be5a3513582cb9f;hp=e7be07105a6d86f96a124ab957b6aa518c170632;hpb=3bd60ef1276fc888fed699ee598b3b358d976f4c;p=thirdparty%2Fiw.git diff --git a/scan.c b/scan.c index e7be071..bb84a67 100644 --- a/scan.c +++ b/scan.c @@ -29,6 +29,7 @@ static unsigned char ms_oui[3] = { 0x00, 0x50, 0xf2 }; static unsigned char ieee80211_oui[3] = { 0x00, 0x0f, 0xac }; +static unsigned char wfa_oui[3] = { 0x50, 0x6f, 0x9a }; struct scan_params { bool unknown; @@ -54,7 +55,8 @@ union ieee80211_country_ie_triplet { static int handle_scan(struct nl80211_state *state, struct nl_cb *cb, struct nl_msg *msg, - int argc, char **argv) + int argc, char **argv, + enum id_input id) { struct nl_msg *ssids = NULL, *freqs = NULL; char *eptr; @@ -157,6 +159,8 @@ static void print_ssid(const uint8_t type, uint8_t len, const uint8_t *data) printf("\n"); } +#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127 + static void print_supprates(const uint8_t type, uint8_t len, const uint8_t *data) { int i; @@ -165,7 +169,13 @@ static void print_supprates(const uint8_t type, uint8_t len, const uint8_t *data for (i = 0; i < len; i++) { int r = data[i] & 0x7f; - printf("%d.%d%s ", r/2, 5*(r&1), data[i] & 0x80 ? "*":""); + + if (r == BSS_MEMBERSHIP_SELECTOR_HT_PHY && data[i] & 0x80) + printf("HT"); + else + printf("%d.%d", r/2, 5*(r&1)); + + printf("%s ", data[i] & 0x80 ? "*" : ""); } printf("\n"); } @@ -296,6 +306,9 @@ static void print_cipher(const uint8_t *data) case 6: printf("AES-128-CMAC"); break; + case 8: + printf("GCMP"); + break; default: printf("%.02x-%.02x-%.02x:%d", data[0], data[1] ,data[2], data[3]); @@ -666,6 +679,7 @@ static const struct ie_print ieprinters[] = { [61] = { "HT operation", print_ht_op, 22, 22, BIT(PRINT_SCAN), }, [48] = { "RSN", print_rsn, 2, 255, BIT(PRINT_SCAN), }, [50] = { "Extended supported rates", print_supprates, 0, 255, BIT(PRINT_SCAN), }, + [114] = { "MESH ID", print_ssid, 0, 32, BIT(PRINT_SCAN) | BIT(PRINT_LINK), }, [127] = { "Extended capabilities", print_capabilities, 0, 255, BIT(PRINT_SCAN), }, }; @@ -698,7 +712,7 @@ static bool print_wifi_wmm_param(const uint8_t *data, uint8_t len) for (i = 0; i < 4; i++) { printf("\n\t\t * %s:", aci_tbl[(data[0] >> 5) & 3]); - if (data[4] & 0x10) + if (data[0] & 0x10) printf(" acm"); printf(" CW %d-%d", (1 << (data[1] & 0xf)) - 1, (1 << (data[1] >> 4)) - 1); @@ -934,6 +948,90 @@ static const struct ie_print wifiprinters[] = { [4] = { "WPS", print_wifi_wps, 0, 255, BIT(PRINT_SCAN), }, }; +static inline void print_p2p(const uint8_t type, uint8_t len, const uint8_t *data) +{ + bool first = true; + __u8 subtype; + __u16 sublen; + + while (len >= 3) { + subtype = data[0]; + sublen = (data[2] << 8) + data[1]; + + if (sublen > len - 3) + break; + + switch (subtype) { + case 0x02: /* capability */ + tab_on_first(&first); + if (sublen < 2) { + printf("\t * malformed capability\n"); + break; + } + printf("\t * Group capa: 0x%.2x, Device capa: 0x%.2x\n", + data[3], data[4]); + break; + case 0x0d: /* device info */ + if (sublen < 6 + 2 + 8 + 1) { + printf("\t * malformed device info\n"); + break; + } + /* fall through for now */ + case 0x00: /* status */ + case 0x01: /* minor reason */ + case 0x03: /* device ID */ + case 0x04: /* GO intent */ + case 0x05: /* configuration timeout */ + case 0x06: /* listen channel */ + case 0x07: /* group BSSID */ + case 0x08: /* ext listen timing */ + case 0x09: /* intended interface address */ + case 0x0a: /* manageability */ + case 0x0b: /* channel list */ + case 0x0c: /* NoA */ + case 0x0e: /* group info */ + case 0x0f: /* group ID */ + case 0x10: /* interface */ + case 0x11: /* operating channel */ + case 0x12: /* invitation flags */ + case 0xdd: /* vendor specific */ + default: { + const __u8 *subdata = data + 4; + __u16 tmplen = sublen; + + tab_on_first(&first); + printf("\t * Unknown TLV (%#.2x, %d bytes):", + subtype, tmplen); + while (tmplen) { + printf(" %.2x", *subdata); + subdata++; + tmplen--; + } + printf("\n"); + break; + } + } + + data += sublen + 3; + len -= sublen + 3; + } + + if (len != 0) { + tab_on_first(&first); + printf("\t * bogus tail data (%d):", len); + while (len) { + printf(" %.2x", *data); + data++; + len--; + } + printf("\n"); + } +} + +static const struct ie_print wfa_printers[] = { + [9] = { "P2P", print_p2p, 2, 255, BIT(PRINT_SCAN), }, +}; + static void print_vendor(unsigned char len, unsigned char *data, bool unknown, enum print_ie_type ptype) { @@ -963,6 +1061,22 @@ static void print_vendor(unsigned char len, unsigned char *data, return; } + if (len >= 4 && memcmp(data, wfa_oui, 3) == 0) { + if (data[3] < ARRAY_SIZE(wfa_printers) && + wfa_printers[data[3]].name && + wfa_printers[data[3]].flags & BIT(ptype)) { + print_ie(&wfa_printers[data[3]], data[3], len - 4, data + 4); + return; + } + if (!unknown) + return; + printf("\tWFA %#.2x, data:", data[3]); + for(i = 0; i < len - 4; i++) + printf(" %.02x", data[i + 4]); + printf("\n"); + return; + } + if (!unknown) return; @@ -1110,7 +1224,7 @@ static int print_bss_handler(struct nl_msg *msg, void *arg) int age = nla_get_u32(bss[NL80211_BSS_SEEN_MS_AGO]); printf("\tlast seen: %d ms ago\n", age); } - + if (bss[NL80211_BSS_INFORMATION_ELEMENTS] && show--) { if (bss[NL80211_BSS_BEACON_IES]) printf("\tInformation elements from Probe Response " @@ -1134,7 +1248,8 @@ static struct scan_params scan_params; static int handle_scan_dump(struct nl80211_state *state, struct nl_cb *cb, struct nl_msg *msg, - int argc, char **argv) + int argc, char **argv, + enum id_input id) { if (argc > 1) return 1; @@ -1156,7 +1271,8 @@ static int handle_scan_dump(struct nl80211_state *state, static int handle_scan_combined(struct nl80211_state *state, struct nl_cb *cb, struct nl_msg *msg, - int argc, char **argv) + int argc, char **argv, + enum id_input id) { char **trig_argv; static char *dump_argv[] = { @@ -1190,7 +1306,7 @@ static int handle_scan_combined(struct nl80211_state *state, int i; for (i = 0; i < argc - 2 - (dump_argc - 3); i++) trig_argv[i + 3] = argv[i + 2 + (dump_argc - 3)]; - err = handle_cmd(state, II_NETDEV, trig_argc, trig_argv); + err = handle_cmd(state, id, trig_argc, trig_argv); free(trig_argv); if (err) return err; @@ -1226,7 +1342,7 @@ static int handle_scan_combined(struct nl80211_state *state, } dump_argv[0] = argv[0]; - return handle_cmd(state, II_NETDEV, dump_argc, dump_argv); + return handle_cmd(state, id, dump_argc, dump_argv); } TOPLEVEL(scan, "[-u] [freq *] [ies ] [ssid *|passive]", 0, 0, CIB_NETDEV, handle_scan_combined,