]> git.ipfire.org Git - thirdparty/iw.git/commitdiff
iw: add country IE parsing
authorLuis R. Rodriguez <lrodriguez@atheros.com>
Fri, 19 Feb 2010 18:55:58 +0000 (13:55 -0500)
committerJohannes Berg <johannes@sipsolutions.net>
Fri, 19 Feb 2010 19:02:17 +0000 (20:02 +0100)
Spits out the channels as seen on the IE, useful when debugging
issues with APs. When found the equivalent distance of the
coverage class is printed out.

Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
scan.c

diff --git a/scan.c b/scan.c
index ec63e61691b09a3a0cee448c74e639fb5252ba8e..3253d9b85f4b6c217ebb4e71bfc5b91592b65d4f 100644 (file)
--- a/scan.c
+++ b/scan.c
@@ -36,6 +36,23 @@ struct scan_params {
        bool show_both_ie_sets;
 };
 
+#define IEEE80211_COUNTRY_EXTENSION_ID 201
+
+struct ieee80211_country_ie_triplet {
+       union {
+               struct {
+                       __u8 first_channel;
+                       __u8 num_channels;
+                       __s8 max_power;
+               } __attribute__ ((packed)) chans;
+               struct {
+                       __u8 reg_extension_id;
+                       __u8 reg_class;
+                       __u8 coverage_class;
+               } __attribute__ ((packed)) ext;
+       };
+} __attribute__ ((packed));
+
 static int handle_scan(struct nl80211_state *state,
                       struct nl_cb *cb,
                       struct nl_msg *msg,
@@ -143,29 +160,64 @@ static void print_ds(const uint8_t type, uint8_t len, const uint8_t *data)
        printf(" channel %d\n", data[0]);
 }
 
-static void print_country(const uint8_t type, uint8_t len, const uint8_t *data)
+static const char *country_env_str(char environment)
 {
-       int i;
-
-       printf(" %.*s", 2, data);
-       switch (data[2]) {
+       switch (environment) {
        case 'I':
-               printf(" (indoor)");
-               break;
+               return "Indoor only";
        case 'O':
-               printf(" (outdoor)");
-               break;
+               return "Outdoor only";
        case ' ':
-               printf(" (in/outdoor)");
-               break;
+               return "Indoor/Outdoor";
        default:
-               printf(" (invalid environment)");
-               break;
+               return "bogus";
        }
-       printf(", data:");
-       for(i=0; i<len-3; i++)
-               printf(" %.02x", data[i + 3]);
-       printf("\n");
+}
+
+static void print_country(const uint8_t type, uint8_t len, const uint8_t *data)
+{
+       printf(" %.*s", 2, data);
+
+       printf("\tEnvironment: %s\n", country_env_str(data[2]));
+
+       data += 3;
+       len -= 3;
+
+       if (len < 3) {
+               printf("\t\tNo country IE triplets present\n");
+               return;
+       }
+
+       while (len >= 3) {
+               int end_channel;
+               struct ieee80211_country_ie_triplet *triplet =
+                       (struct ieee80211_country_ie_triplet *) data;
+
+               if (triplet->ext.reg_extension_id >= IEEE80211_COUNTRY_EXTENSION_ID) {
+                       printf("\t\tExtension ID: %d Regulatory Class: %d Coverage class: %d (up to %dm)\n",
+                              triplet->ext.reg_extension_id,
+                              triplet->ext.reg_class,
+                              triplet->ext.coverage_class,
+                              triplet->ext.coverage_class * 450);
+
+                       data += 3;
+                       len -= 3;
+                       continue;
+               }
+
+               /* 2 GHz */
+               if (triplet->chans.first_channel <= 14)
+                       end_channel = triplet->chans.first_channel + (triplet->chans.num_channels - 1);
+               else
+                       end_channel =  triplet->chans.first_channel + (4 * (triplet->chans.num_channels - 1));
+
+               printf("\t\tChannels [%d - %d]\n", triplet->chans.first_channel, end_channel);
+
+               data += 3;
+               len -= 3;
+       }
+
+       return;
 }
 
 static void print_powerconstraint(const uint8_t type, uint8_t len, const uint8_t *data)