]> git.ipfire.org Git - thirdparty/iw.git/commitdiff
iw: scan: add eht capability parsing
authorDylan Eskew <dylan.eskew@candelatech.com>
Wed, 19 Mar 2025 18:39:18 +0000 (11:39 -0700)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 23 Apr 2025 14:37:15 +0000 (16:37 +0200)
Add ability to print out EHT capabilities from
AP beacons.

Signed-off-by: Dylan Eskew <dylan.eskew@candelatech.com>
Link: https://patch.msgid.link/20250319183918.1215853-3-dylan.eskew@candelatech.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
ieee80211.h
iw.h
link.c
scan.c

index de05844c73972b4504dde7c0516810a583592dd7..1e29371df28709ccca213ff60698a236afacfb7f 100644 (file)
@@ -99,6 +99,7 @@ enum elem_id {
 enum elem_id_ext {
        EID_EXT_HE_CAPABILITY           = 35,
        EID_EXT_HE_OPERATION            = 36,
+       EID_EXT_EHT_CAPABILITY          = 108,
 };
 
 #define SUITE(oui, id)  (((oui) << 8) | (id))
diff --git a/iw.h b/iw.h
index 8cbb971db6402194bd24e36553fadd379a3f1005..b8caccd3bf2a97b94f05f7f580ad9f89eb800fe6 100644 (file)
--- a/iw.h
+++ b/iw.h
@@ -277,7 +277,7 @@ enum print_ie_type {
 #define BIT(x) (1ULL<<(x))
 
 void print_ies(unsigned char *ie, int ielen, bool unknown,
-              enum print_ie_type ptype);
+              enum print_ie_type ptype, bool from_ap);
 
 void parse_bitrate(struct nlattr *bitrate_attr, char *buf, int buflen);
 void iw_hexdump(const char *prefix, const __u8 *data, size_t len);
diff --git a/link.c b/link.c
index a7ee9636af2f0d3da0b2ad426b5ee7b7e0d0a57b..20ab92784a164cc1db68b72ead9f37b2c264c3b2 100644 (file)
--- a/link.c
+++ b/link.c
@@ -93,7 +93,7 @@ static int link_bss_handler(struct nl_msg *msg, void *arg)
                        if (bss[NL80211_BSS_INFORMATION_ELEMENTS])
                                print_ies(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
                                          nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
-                                         false, PRINT_LINK_MLO_MLD);
+                                         false, PRINT_LINK_MLO_MLD, false);
                }
        } else {
                memcpy(result->sta_addr, nla_data(bss[NL80211_BSS_BSSID]), 6);
@@ -121,7 +121,8 @@ static int link_bss_handler(struct nl_msg *msg, void *arg)
        if (bss[NL80211_BSS_INFORMATION_ELEMENTS])
                print_ies(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
                          nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]),
-                         false, result->mld ? PRINT_LINK_MLO_LINK : PRINT_LINK);
+                         false, result->mld ? PRINT_LINK_MLO_LINK : PRINT_LINK,
+                         false);
 
        if (bss[NL80211_BSS_FREQUENCY_OFFSET])
                freq_offset = nla_get_u32(bss[NL80211_BSS_FREQUENCY_OFFSET]);
diff --git a/scan.c b/scan.c
index 6cf44d2501625f8256573c80db95fd17022fe605..a366184c7bed4ad9a6b63922940338002e2780fe 100644 (file)
--- a/scan.c
+++ b/scan.c
@@ -555,7 +555,9 @@ static void tab_on_first(bool *first)
 }
 
 struct ie_context {
+       bool from_ap;
        bool is_vht_cap;
+       const uint8_t *he_cap;
 };
 
 static void print_ssid(const uint8_t type, uint8_t len, const uint8_t *data,
@@ -2393,12 +2395,21 @@ static void print_he_oper(const uint8_t type, uint8_t len, const uint8_t *data,
        print_he_operation(data, len);
 }
 
+static void print_eht_capa(const uint8_t type, uint8_t len,
+                          const uint8_t *data, const struct ie_context *ctx)
+{
+       printf("\n");
+       print_eht_capability(data, len, ctx->he_cap, ctx->from_ap);
+}
+
 static const struct ie_print ext_printers[] = {
        [EID_EXT_HE_CAPABILITY] = { "HE capabilities", print_he_capa, 21, 54, BIT(PRINT_SCAN), },
        [EID_EXT_HE_OPERATION] = { "HE Operation", print_he_oper, 6, 15, BIT(PRINT_SCAN), },
+       [EID_EXT_EHT_CAPABILITY] = { "EHT capabilities", print_eht_capa, 13, 30, BIT(PRINT_SCAN), },
 };
 
 static void print_extension(unsigned char len, unsigned char *ie,
+                           const struct ie_context *ctx,
                            bool unknown, enum print_ie_type ptype)
 {
        unsigned char tag;
@@ -2411,7 +2422,7 @@ static void print_extension(unsigned char len, unsigned char *ie,
        tag = ie[0];
        if (tag < ARRAY_SIZE(ext_printers) && ext_printers[tag].name &&
            ext_printers[tag].flags & BIT(ptype)) {
-               print_ie(&ext_printers[tag], tag, len - 1, ie + 1, NULL);
+               print_ie(&ext_printers[tag], tag, len - 1, ie + 1, ctx);
                return;
        }
 
@@ -2426,7 +2437,7 @@ static void print_extension(unsigned char len, unsigned char *ie,
 }
 
 static void init_context(struct ie_context *ctx,
-                        unsigned char *ie, int ielen)
+                        unsigned char *ie, int ielen, bool from_ap)
 {
        unsigned char *pos = ie;
        int remaining = ielen;
@@ -2436,11 +2447,20 @@ static void init_context(struct ie_context *ctx,
        if (!ie || !ielen)
                return;
 
+       ctx->from_ap = from_ap;
+
        while (remaining >= 2 && remaining - 2 >= pos[1]) {
                switch (pos[0]) {
                case EID_VHT_CAPABILITY:
                        ctx->is_vht_cap = true;
                        break;
+               case EID_EXTENSION:
+                       switch (pos[2]) {
+                       case EID_EXT_HE_CAPABILITY:
+                               ctx->he_cap = pos + 3;
+                               break;
+                       }
+                       break;
                }
 
                remaining -= pos[1] + 2;
@@ -2449,14 +2469,14 @@ static void init_context(struct ie_context *ctx,
 }
 
 void print_ies(unsigned char *ie, int ielen, bool unknown,
-              enum print_ie_type ptype)
+              enum print_ie_type ptype, bool from_ap)
 {
        struct ie_context ctx;
 
        if (!ie)
                return;
 
-       init_context(&ctx, ie, ielen);
+       init_context(&ctx, ie, ielen, from_ap);
 
        while (ielen >= 2 && ielen - 2 >= ie[1]) {
                if (ie[0] < ARRAY_SIZE(ieprinters) &&
@@ -2468,7 +2488,7 @@ void print_ies(unsigned char *ie, int ielen, bool unknown,
                } else if (ie[0] == 221 /* vendor */) {
                        print_vendor(ie[1], ie + 2, unknown, ptype);
                } else if (ie[0] == 255 /* extension */) {
-                       print_extension(ie[1], ie + 2, unknown, ptype);
+                       print_extension(ie[1], ie + 2, &ctx, unknown, ptype);
                } else if (unknown) {
                        int i;
 
@@ -2673,13 +2693,13 @@ static int print_bss_handler(struct nl_msg *msg, void *arg)
                        printf("\tInformation elements from Probe Response "
                               "frame:\n");
                print_ies(nla_data(ies), nla_len(ies),
-                         params->unknown, params->type);
+                         params->unknown, params->type, true);
        }
        if (bss[NL80211_BSS_BEACON_IES] && show--) {
                printf("\tInformation elements from Beacon frame:\n");
                print_ies(nla_data(bss[NL80211_BSS_BEACON_IES]),
                          nla_len(bss[NL80211_BSS_BEACON_IES]),
-                         params->unknown, params->type);
+                         params->unknown, params->type, true);
        }
 
        return NL_SKIP;