Package: wireless-tools Version: 30~pre9-8 Severity: wishlist Tags: upstream patch
Hi, Please find attached a patch that I wrote to decode many more Information Elements; I picked out the ones that I felt were the most useful from what I could see in my apartment and implemented those (with good help from Wireshark). Since the information amount is now so great, I've hidden everything but the IE names behind a new “verbose” option; otherwise there would just be too much clutter. -- System Information: Debian Release: jessie/sid APT prefers unstable APT policy: (500, 'unstable'), (1, 'experimental') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 3.16.1 (SMP w/4 CPU cores) Locale: LANG=nb_NO.utf8, LC_CTYPE=nb_NO.utf8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Versions of packages wireless-tools depends on: ii libc6 2.19-9 ii libiw30 30~pre9-8 wireless-tools recommends no packages. wireless-tools suggests no packages. -- no debconf information
diff -ur wireless-tools-30~pre9.orig/iwlist.8 wireless-tools-30~pre9/iwlist.8 --- wireless-tools-30~pre9.orig/iwlist.8 2008-08-30 01:48:19.000000000 +0200 +++ wireless-tools-30~pre9/iwlist.8 2014-08-23 15:23:18.214764995 +0200 @@ -76,6 +76,9 @@ this enables to see hidden networks. The option .B last does not trigger a scan and read left-over scan results. +The option +.B verbose +decodes and outputs much more information about each beacon. .TP .BR freq [uency]/ channel Give the list of available frequencies in the device and the number of diff -ur wireless-tools-30~pre9.orig/iwlist.c wireless-tools-30~pre9/iwlist.c --- wireless-tools-30~pre9.orig/iwlist.c 2009-11-24 01:05:41.000000000 +0100 +++ wireless-tools-30~pre9/iwlist.c 2014-08-23 22:03:49.411953899 +0200 @@ -9,11 +9,23 @@ * * This file is released under the GPL license. * Copyright (c) 1997-2007 Jean Tourrilhes <[email protected]> + * + * Parts based on the IEEE 802.11 dissector from Wireshark, which + * is licensed under the GPL v2 or later. + * + * Copyright 2000, Axis Communications AB + * Copyright 1998 Gerald Combs + * Copyright 2014 Steinar H. Gunderson */ #include "iwlib-private.h" /* Private header */ +#include <math.h> #include <sys/time.h> +/************************* GLOBAL OPTIONS **************************/ + +static int verbose = 0; + /****************************** TYPES ******************************/ /* @@ -225,10 +237,15 @@ if(ielen > buflen) ielen = buflen; - printf("Unknown: "); - for(i = 0; i < ielen; i++) - printf("%02X", iebuf[i]); - printf("\n"); + if(verbose) + { + printf("Unknown: "); + for(i = 0; i < ielen; i++) + printf("%02X", iebuf[i]); + printf("\n"); + } + else + printf("Unknown (0x%02x)\n", iebuf[0]); } /*------------------------------------------------------------------*/ @@ -273,19 +290,9 @@ wpa_oui = wpa2_oui; break; - case 0xdd: /* WPA or else */ + case 0xdd: /* WPA1 (already checked in iw_print_ie_vs) */ wpa_oui = wpa1_oui; - /* Not all IEs that start with 0xdd are WPA. - * So check that the OUI is valid. Note : offset==2 */ - if((ielen < 8) - || (memcmp(&iebuf[offset], wpa_oui, 3) != 0) - || (iebuf[offset + 3] != 0x01)) - { - iw_print_ie_unknown(iebuf, buflen); - return; - } - /* Skip the OUI type */ offset += 4; break; @@ -303,6 +310,9 @@ if(iebuf[0] == 0x30) printf("IEEE 802.11i/WPA2 Version %d\n", ver); + if(!verbose) + return; + /* From here, everything is technically optional. */ /* Check if we are done */ @@ -399,10 +409,1080 @@ printf(" Preauthentication Supported\n"); } } + +/*------------------------------------------------------------------*/ +/* + * Parse, and display the results of a TIM IE. + * + */ +static inline void +iw_print_ie_tim(unsigned char * iebuf, + int buflen) +{ + int ielen = iebuf[1] + 2; + int offset = 2; /* Skip the IE id, and the length. */ + int bmapctl; + int i; + + if(ielen > buflen) + ielen = buflen; + + if(ielen < 6) + { + iw_print_ie_unknown(iebuf, buflen); + return; + } + + printf("Traffic Information Map\n"); + if(!verbose) + return; + + printf(" DTIM Count: %d\n", iebuf[offset++]); + printf(" DTIM Period: %d\n", iebuf[offset++]); + + bmapctl = iebuf[offset++]; + if (bmapctl & 0x01) + printf(" Multicast Traffic Indicator Set\n"); + printf(" Bitmap Offset: 0x%02x\n", bmapctl >> 1); + + printf(" Partial Virtual Bitmap: "); + for(i = offset; i < ielen; i++) + printf("%02X", iebuf[i]); + printf("\n"); +} + +/*------------------------------------------------------------------*/ +/* + * Parse, and display the results of a QBSS Load IE. + * + */ +static inline void +iw_print_ie_qbss_load(unsigned char * iebuf, + int buflen) +{ + int ielen = iebuf[1] + 2; + int offset = 2; /* Skip the IE id, and the length. */ + int scount; + int chan_util; + int avg_adm; + + if(ielen > buflen) + ielen = buflen; + + if(ielen != 7) /* We only support 802.11e, not the shorter Cisco version. */ + { + iw_print_ie_unknown(iebuf, buflen); + return; + } + + printf("QBSS Load (802.11e)\n"); + if(!verbose) + return; + + scount = iebuf[offset] | (iebuf[offset + 1] << 8); + offset += 2; + printf(" Station Count: %d\n", scount); + + chan_util = iebuf[offset++]; + printf(" Channel Utilization: %d%%\n", + (int)lrint(100.0 * chan_util / 255.0)); + + avg_adm = iebuf[offset] | (iebuf[offset + 1] << 8); + offset += 2; + printf(" Average Admission Capabilities: %d us/s\n", + 32 * avg_adm); +} + +/*------------------------------------------------------------------*/ +/* + * Parse, and display the results of a power constraint IE. + * + */ +static inline void +iw_print_ie_power_constraint(unsigned char * iebuf, + int buflen) +{ + int ielen = iebuf[1] + 2; + int offset = 2; /* Skip the IE id, and the length. */ + + if(ielen > buflen) + ielen = buflen; + + if(ielen != 3) + { + iw_print_ie_unknown(iebuf, buflen); + return; + } + + printf("Power Constraint\n"); + if(verbose) + printf(" Clients Should Reduce Transmit Power by %d dB\n", iebuf[offset]); +} + +static inline void +iw_print_mcs_set(unsigned char * mcsbuf) +{ + /* TODO: Decode */ + int i; + printf(" MCS Set: "); + for(i = 0; i < 16; i++) + printf("%02X", mcsbuf[i]); + printf("\n"); +} + +/*------------------------------------------------------------------*/ +/* + * Parse, and display the results of a country IE. + * + */ +static inline void +iw_print_ie_country(unsigned char * iebuf, + int buflen) +{ + int ielen = iebuf[1] + 2; + int offset = 2; /* Skip the IE id, and the length. */ + + if(ielen > buflen) + ielen = buflen; + + if(ielen < 6) + { + iw_print_ie_unknown(iebuf, buflen); + return; + } + + printf("Country (802.11d/802.11j)\n"); + if(!verbose) + return; + + printf(" Country Code: %c%c\n", + isprint(iebuf[offset]) ? iebuf[offset]: '?', + isprint(iebuf[offset + 1]) ? iebuf[offset + 1]: '?'); + offset += 2; + + printf(" Environment: "); + switch (iebuf[offset]) + { + case 0x20: + printf("Any\n"); + break; + case 0x4f: + printf("Outdoor\n"); + break; + case 0x49: + printf("Indoor\n"); + break; + default: + printf("Unknown (0x%02x)\n", iebuf[offset]); + break; + } + ++offset; + + while(ielen >= (offset + 3)) + { + if(iebuf[offset] <= 200) + { + printf(" 802.11d Power Limits\n"); + printf(" First Channel Number: %d\n", + iebuf[offset]); + printf(" Number of Channels: %d\n", + iebuf[offset + 1]); + printf(" Maximum Transmit Power Level: %d dBm\n", + iebuf[offset + 2]); + } + else + { + printf(" 802.11j Power Limits\n"); + printf(" Operating Extension Identifier: %d\n", + iebuf[offset]); + printf(" Operating Class: %d\n", + iebuf[offset + 1]); + printf(" Coverage Class: %d\n", + iebuf[offset + 2]); + } + offset += 3; + } +} + +/*------------------------------------------------------------------*/ +/* + * Parse, and display the results of an ERP IE. + * + */ +static inline void +iw_print_ie_erp(unsigned char * iebuf, + int buflen) +{ + int ielen = iebuf[1] + 2; + int offset = 2; /* Skip the IE id, and the length. */ + + if(ielen > buflen) + ielen = buflen; + + if(ielen != 3) + { + iw_print_ie_unknown(iebuf, buflen); + return; + } + + printf("ERP\n"); + if(!verbose) + return; + + if(iebuf[offset] & 0x01) + printf(" ERP Present\n"); + + if(iebuf[offset] & 0x02) + printf(" Use Protection\n"); + + if(iebuf[offset] & 0x04) + printf(" Preamble Mode\n"); + + if(iebuf[offset] & 0xf8) + printf(" Unknown bits (0x%02x)\n", + iebuf[offset]); +} + +/*------------------------------------------------------------------*/ +/* + * Parse, and display the results of an HT capability IE. + * + */ +static inline void +iw_print_ie_ht_cap(unsigned char * iebuf, + int buflen) +{ + int ielen = iebuf[1] + 2; + int offset = 2; /* Skip the IE id, and the length. */ + int ht_cap; + int ht_ext_cap; + unsigned int txbf_cap; + int asel_cap; + int ampdu; + + if(ielen > buflen) + ielen = buflen; + + if(ielen != 28) + { + iw_print_ie_unknown(iebuf, buflen); + return; + } + + printf("HT Capabilities (802.11n D1.10)\n"); + if(!verbose) + return; + + /* Decode capabilities field (little endian) */ + ht_cap = iebuf[offset] | (iebuf[offset + 1] << 8); + offset += 2; + + if(ht_cap & 0x0001) + printf(" LDPC Coded Packets Supported\n"); + + if(ht_cap & 0x0002) + printf(" 20 MHz and 40 MHz Channel Width Supported\n"); + else + printf(" Only 20 MHz Channel Width Supported\n"); + + printf(" SM Power Save: "); + switch((ht_cap & 0x000c) >> 2) + { + case 0x00: + printf("Static\n"); + break; + case 0x01: + printf("Dynamic\n"); + break; + case 0x02: + printf("Reserved\n"); + break; + case 0x03: + printf("Disabled\n"); + break; + } + + if(ht_cap & 0x0010) + printf(" Can Receive PPDUs with Green Field (GF) Preamble\n"); + + if(ht_cap & 0x0020) + printf(" Short GI for 20 MHz Supported\n"); + + if(ht_cap & 0x0040) + printf(" Short GI for 40 MHz Supported\n"); + + if(ht_cap & 0x0080) + printf(" Tx STBC: Supported\n"); + else + printf(" Tx STBC: Not Supported\n"); + + printf(" Rx STBC: "); + switch((ht_cap & 0x0300) >> 8) + { + case 0x00: + printf("Not Supported\n"); + break; + case 0x01: + printf("One Spatial Stream\n"); + break; + case 0x02: + printf("Up to Two Spatial Streams\n"); + break; + case 0x03: + printf("Up to Three Spatial Streams\n"); + break; + } + + if(ht_cap & 0x0400) + printf(" HT-Delayed BlockAck Supported\n"); + + if(ht_cap & 0x0800) + printf(" HT Max A-MSDU Length: 7935 bytes\n"); + else + printf(" HT Max A-MSDU Length: 3839 bytes\n"); + + if(ht_cap & 0x1000) + printf(" Will/Can Use DSSS/CCK in 40 MHz\n"); + + if(ht_cap & 0x2000) + printf(" Will/Can Support PSMP Operation\n"); + + if(ht_cap & 0x4000) + printf(" 40 MHz Transmissions Restricted/Disallowed\n"); + else + printf(" 40 MHz Transmissions Unrestricted/Allowed\n"); + + if(ht_cap & 0x8000) + printf(" HT L-SIG TXOP Protection Supported\n"); + + /* Decode A-MPDU Parameters */ + ampdu = iebuf[offset++]; + printf(" Maximum Rx A-MPDU Length: %d bytes\n", + (1 << (13 + (ampdu & 0x3)))); + + printf(" MPDU Density: "); + switch((ampdu & 0x1c) >> 2) + { + case 0x00: + printf("No Restriction\n"); + break; + case 0x01: + printf("1/4 usec\n"); + break; + case 0x02: + printf("1/2 usec\n"); + break; + case 0x03: + printf("1 usec\n"); + break; + case 0x04: + printf("2 usec\n"); + break; + case 0x05: + printf("4 usec\n"); + break; + case 0x06: + printf("8 usec\n"); + break; + case 0x07: + printf("16 usec\n"); + break; + } + + /* Ignore reserved bits (0xe0) of ampdu. */ + + iw_print_mcs_set(iebuf + offset); + offset += 16; + + /* HT Extended Capabilities (little endian) */ + ht_ext_cap = iebuf[offset] | (iebuf[offset + 1] << 8); + offset += 2; + + if(ht_ext_cap & 0x0001) + printf(" Transmitter Supports PCO\n"); + + printf(" 20/40 MHz Transition Time: "); + switch((ht_ext_cap & 0x0006) >> 1) + { + case 0x00: + printf("No Transition\n"); + break; + case 0x01: + printf("400 usec\n"); + break; + case 0x02: + printf("1.5 msec\n"); + break; + case 0x03: + printf("5 msec\n"); + break; + } + + printf(" MCS Feedback Capability: "); + switch((ht_ext_cap & 0x0300) >> 8) + { + case 0x00: + printf("No MCS Feedback\n"); + break; + case 0x01: + printf("Reserved\n"); + break; + case 0x02: + printf("Only Unsolicited Feedback\n"); + break; + case 0x03: + printf("Both Unsolicited And in Response to MRQ\n"); + break; + } + + if(ht_ext_cap & 0x0400) + printf(" High Throughput Supported\n"); + + if(ht_ext_cap & 0x0800) + printf(" Reverse Direction Responder Supported\n"); + + /* TxBF (Transmit Beamforming) Capabilities (little endian) */ + txbf_cap = iebuf[offset] | (iebuf[offset + 1] << 8) | + (iebuf[offset + 2] << 16) | (iebuf[offset + 3] << 24); + offset += 2; + + if(txbf_cap & 0x00000001) + printf(" Transmit Beamforming Supported\n"); + else + printf(" Transmit Beamforming Not Supported\n"); + + if(txbf_cap & 0x00000002) + printf(" Receive Staggered Sounding Supported\n"); + + if(txbf_cap & 0x00000004) + printf(" Transmit Staggered Sounding Supported\n"); + + if(txbf_cap & 0x00000008) + printf(" Receive Null Data Packet Supported\n"); + + if(txbf_cap & 0x00000010) + printf(" Transmit Null Data Packet Supported\n"); + + if(txbf_cap & 0x00000020) + printf(" Implicit TxBF Capable\n"); + + printf(" TxBF Calibration: "); + switch((txbf_cap & 0x000000c0) >> 6) + { + case 0x00: + printf("Incapable\n"); + break; + case 0x01: + printf("Limited Involvement, Cannot Initiate\n"); + break; + case 0x02: + printf("Limited Involvement, Can Initiate\n"); + break; + case 0x03: + printf("Fully Capable\n"); + break; + } + + if(txbf_cap & 0x00000100) + printf(" Can Apply TxBF Using CSI Explicit Feedback\n"); + + if(txbf_cap & 0x00000200) + printf(" Can Apply TxBF Using Uncompressed Matrix\n"); + + if(txbf_cap & 0x00000400) + printf(" Can Apply TxBF Using Compressed Matrix\n"); + + printf(" Return CSI Explicit Feedback: "); + switch((txbf_cap & 0x00001800) >> 11) + { + case 0x00: + printf("Not Supported\n"); + break; + case 0x01: + printf("Delayed Feedback Capable\n"); + break; + case 0x02: + printf("Immediate Feedback Capable\n"); + break; + case 0x03: + printf("Delayed And Immediate Feedback Capable\n"); + break; + } + + printf(" Return Explicit Uncompressed Matrix: "); + switch((txbf_cap & 0x00006000) >> 13) + { + case 0x00: + printf("Not Supported\n"); + break; + case 0x01: + printf("Delayed Feedback Capable\n"); + break; + case 0x02: + printf("Immediate Feedback Capable\n"); + break; + case 0x03: + printf("Delayed And Immediate Feedback Capable\n"); + break; + } + + printf(" Return Explicit Compressed Matrix: "); + switch((txbf_cap & 0x00018000) >> 15) + { + case 0x00: + printf("Not Supported\n"); + break; + case 0x01: + printf("Delayed Feedback Capable\n"); + break; + case 0x02: + printf("Immediate Feedback Capable\n"); + break; + case 0x03: + printf("Delayed And Immediate Feedback Capable\n"); + break; + } + + printf(" Minimal Grouping Used For Explicit Feedback: "); + switch((txbf_cap & 0x00060000) >> 17) + { + case 0x00: + printf("No Grouping Supported\n"); + break; + case 0x01: + printf("Groups of 1,2 Supported\n"); + break; + case 0x02: + printf("Groups of 1,4 Supported\n"); + break; + case 0x03: + printf("Groups of 1,2,4 Supported\n"); + break; + } + + printf(" Max Antennae With CSI Explicit Feedback: %d\n", + (txbf_cap & 0x00180000) >> 19); + printf(" Max Antennae With Uncompressed Matrix Feedback: %d\n", + (txbf_cap & 0x00600000) >> 21); + printf(" Max Antennae With Compressed Matrix Feedback: %d\n", + (txbf_cap & 0x01800000) >> 23); + printf(" Max Rows of CSI Explicit Feedback: %d\n", + (txbf_cap & 0x06000000) >> 25); + printf(" Max Simultaneously Estimated Streams: %d\n", + (txbf_cap & 0x18000000) >> 27); + + /* Antenna Selection (ASEL) capabilities */ + asel_cap = iebuf[offset++]; + + if(asel_cap & 0x01) + printf(" Antenna Selection Capable\n"); + + if(asel_cap & 0x02) + printf(" Explicit CSI Feedback Tx ASEL Supported\n"); + + if(asel_cap & 0x04) + printf(" Antenna Indices Feedback Tx ASEL Supported\n"); + + if(asel_cap & 0x08) + printf(" Explicit CSI Feedback ASEL Supported\n"); + + if(asel_cap & 0x10) + printf(" Antenna Indices Feedback ASEL Supported\n"); + + if(asel_cap & 0x20) + printf(" Rx ASEL Supported\n"); + + if(asel_cap & 0x40) + printf(" Tx Sounding PPDUs Supported\n"); +} + +/*------------------------------------------------------------------*/ +/* + * Parse, and display the results of a secondary channel offset IE. + * + */ +static inline void +iw_print_ie_secondary_channel_offset(unsigned char * iebuf, + int buflen) +{ + int ielen = iebuf[1] + 2; + int offset = 2; /* Skip the IE id, and the length. */ + + if(ielen > buflen) + ielen = buflen; + + if(ielen != 3) + { + iw_print_ie_unknown(iebuf, buflen); + return; + } + + printf("Secondary Channel Offset\n"); + if(!verbose) + return; + + switch(iebuf[offset]) + { + case 0x00: + printf(" No Secondary Channel\n"); + break; + case 0x01: + printf(" Above Primary Channel\n"); + break; + case 0x02: + printf(" Reserved\n"); + break; + case 0x03: + printf(" Below Primary Channel\n"); + break; + default: + printf(" Unknown (0x%02x)\n", iebuf[offset]); + break; + } +} + +/*------------------------------------------------------------------*/ +/* + * Parse, and display the results of a Cisco Aironet IE. + * + */ +static inline void +iw_print_ie_aironet(unsigned char * iebuf, + int buflen) +{ + int ielen = iebuf[1] + 2; + int offset = 2; /* Skip the IE id, and the length. */ + int cwmin; + int cwmax; + int i; + int num_assoc; + int radio_type; + + if(ielen > buflen) + ielen = buflen; + + if(ielen < 28) + { + iw_print_ie_unknown(iebuf, buflen); + return; + } + + printf("Cisco Aironet\n"); + if(!verbose) + return; + + printf(" Load: %d\n", iebuf[offset++]); + printf(" Hops: %d\n", iebuf[offset++]); + printf(" Device ID: %d\n", iebuf[offset++]); + printf(" Refresh Rate: %d seconds\n", iebuf[offset++]); + + cwmin = iebuf[offset] | (iebuf[offset + 1] << 8); + offset += 2; + cwmax = iebuf[offset] | (iebuf[offset + 1] << 8); + offset += 2; + printf(" CW: %d to %d\n", cwmin, cwmax); + + printf(" Flags: 0x%02x\n", iebuf[offset++]); + printf(" Distance: %d\n", iebuf[offset++]); + + printf(" Access Point Name: "); + for (i = offset; i < offset + 16; ++i) + { + if(iebuf[i] == 0) + break; + else if(isprint(iebuf[i])) + putchar(iebuf[i]); + else + putchar('?'); + } + printf("\n"); + offset += 16; + + num_assoc = iebuf[offset] | (iebuf[offset + 1] << 8); + offset += 2; + printf(" Number of Associations: %d\n", num_assoc); + + radio_type = iebuf[offset] | (iebuf[offset + 1] << 8); + offset += 2; + printf(" Radio Type: 0x%04x\n", radio_type); +} + +/*------------------------------------------------------------------*/ +/* + * Parse, and display the results of an AP channel report IE. + * + */ +static inline void +iw_print_ie_ap_chan_report(unsigned char * iebuf, + int buflen) +{ + int ielen = iebuf[1] + 2; + int offset = 2; /* Skip the IE id, and the length. */ + int opclass; + int i; + + if(ielen > buflen) + ielen = buflen; + + if(ielen < 3) + { + iw_print_ie_unknown(iebuf, buflen); + return; + } + + printf("AP Channel Report\n"); + if(!verbose) + return; + + opclass = iebuf[offset++]; + printf(" Operating Class: %d\n", opclass); + printf(" Channel List: "); + + for(i = offset; i < ielen; i++) + { + if(i == offset) + printf("%d", iebuf[i]); + else + printf(", %d", iebuf[i]); + } + printf("\n"); +} + +/*------------------------------------------------------------------*/ +/* + * Parse, and display the results of an HT info IE. + * + */ +static inline void +iw_print_ie_ht_info(unsigned char * iebuf, + int buflen) +{ + int ielen = iebuf[1] + 2; + int offset = 2; /* Skip the IE id, and the length. */ + int pri_chan; + int flags1; + int flags2; + int flags3; + + if(ielen > buflen) + ielen = buflen; + + if(ielen < 24) + { + iw_print_ie_unknown(iebuf, buflen); + return; + } + + printf("HT Information (802.11n D1.10)\n"); + if(!verbose) + return; + + pri_chan = iebuf[offset++]; + printf(" Primary Channel: %d\n", pri_chan); + + flags1 = iebuf[offset++]; + printf(" Secondary Channel: "); + switch(flags1 & 0x03) + { + case 0x00: + printf("No Secondary Channel\n"); + break; + case 0x01: + printf("Above Primary Channel\n"); + break; + case 0x02: + printf("Reserved\n"); + break; + case 0x03: + printf("Below Primary Channel\n"); + break; + } + + if(flags1 & 0x04) + printf(" Any Channel Width Supported\n"); + else + printf(" Only 20 MHz Supported\n"); + + if(flags1 & 0x08) + printf(" Reduced Interframe Spacing Permitted\n"); + + if(flags1 & 0x10) + printf(" Association From Only PSMP Capable Clients\n"); + else + printf(" Association Regardless of PSMP Capability\n"); + + printf(" Shortest Service Interval: %d ms\n", + 5 * (((flags1 & 0xe0) >> 5) + 1)); + + flags2 = iebuf[offset] | (iebuf[offset + 1] << 8); + offset += 2; + + printf(" BSS Operating Mode: "); + switch(flags2 & 0x0003) + { + case 0x00: + printf("All Clients 20/40 MHz HT, in 20/40 MHz BSS or 20 MHz HT in 20 MHz BSS\n"); + break; + case 0x01: + printf("HT Non-Member Protection Mode\n"); + break; + case 0x02: + printf("Only HT STAs in BSS, but 20 MHz STAs Exist\n"); + break; + case 0x03: + printf("HT Mixed Mode\n"); + break; + } + + if(flags2 & 0x0004) + printf(" Non-Greenfield Clients Present\n"); + + printf(" Transmit Burst Limit: "); + if(flags2 & 0x0008) + printf("2.4 GHz 6.16 ms, All Other 3.08 ms\n"); + else + printf("No Limit\n"); + + if(flags2 & 0x0010) + printf(" Protection for Non-HT Clients by Overlapping BSSs Needed\n"); + + flags3 = iebuf[offset] | (iebuf[offset + 1] << 8); + + if(flags3 & 0x0040) + printf(" AP Transmits Secondary Beacon\n"); + + if(flags3 & 0x0080) + printf(" Dual CTS Protection Required\n"); + + if(flags3 & 0x0100) + printf(" Secondary Beacon\n"); + else + printf(" Primary Beacon\n"); + + if(flags3 & 0x0200) + printf(" All Clients Support L-SIG TXOP Protection\n"); + else + printf(" Not All Clients Support L-SIG TXOP Protection\n"); + + if(flags3 & 0x0400) + { + printf(" Phased Coexistence Operation Active\n"); + printf(" PCO Phase: "); + if(flags3 & 0x0800) + printf("40 MHz\n"); + else + printf("20 MHz\n"); + } + + iw_print_mcs_set(iebuf); +} + +/*------------------------------------------------------------------*/ +/* + * Parse, and display the results of a Cisco DTPC IE. + * + */ +static inline void +iw_print_ie_cisco_dtpc(unsigned char * iebuf, + int buflen) +{ + int ielen = iebuf[1] + 2; + int offset = 6; /* Skip the IE id, the length, the OUI, the sub-ID. */ + int power_level; + + if(ielen > buflen) + ielen = buflen; + + if(ielen != 8) + { + iw_print_ie_unknown(iebuf, buflen); + return; + } + + printf("Cisco Aironet DTPC Power Level\n"); + if(!verbose) + return; + + power_level = iebuf[offset] | (iebuf[offset + 1] << 8); + printf(" Client Power Level: %d dBm\n", power_level); +} /*------------------------------------------------------------------*/ /* - * Process a generic IE and display the info in human readable form + * Parse, and display the results of a Cisco CCX version IE. + * + */ +static inline void +iw_print_ie_cisco_ccx_version(unsigned char * iebuf, + int buflen) +{ + int ielen = iebuf[1] + 2; + int offset = 6; /* Skip the IE id, the length, the OUI, the sub-ID. */ + + if(ielen > buflen) + ielen = buflen; + + if(ielen != 7) + { + iw_print_ie_unknown(iebuf, buflen); + return; + } + + printf("Cisco CCX Version\n"); + if(!verbose) + return; + + printf(" Highest CCX Version Supported: %d\n", iebuf[offset]); +} + +/*------------------------------------------------------------------*/ +/* + * Parse, and display the results of a Cisco Client SFA IE. + * + */ +static inline void +iw_print_ie_cisco_sfa(unsigned char * iebuf, + int buflen) +{ + int ielen = iebuf[1] + 2; + int offset = 6; /* Skip the IE id, the length, the OUI, the sub-ID. */ + int flags; + + if(ielen > buflen) + ielen = buflen; + + if(ielen != 7) + { + iw_print_ie_unknown(iebuf, buflen); + return; + } + + printf("Cisco Supported Features Advertisement\n"); + if(!verbose) + return; + + flags = iebuf[offset++]; + + printf(" Management Frame Protection: "); + if(flags & 0x01) + printf("Supported\n"); + else + printf("Not Supported\n"); + + printf(" Diagnostic Channel: "); + if(flags & 0x02) + printf("Supported\n"); + else + printf("Not Supported\n"); + + printf(" Location Services: "); + if(flags & 0x04) + printf("Supported\n"); + else + printf("Not Supported\n"); + + printf(" Expedited Bandwidth Requests: "); + if(flags & 0x08) + printf("Supported\n"); + else + printf("Not Supported\n"); + + if(flags & 0xf0) + printf(" Unknown Flags Set (0x%02x)\n", flags); +} + +/*------------------------------------------------------------------*/ +/* + * Parse, and display the results of a vendor-specific IE. + * + */ +static inline void +iw_print_ie_vs(unsigned char * iebuf, + int buflen) +{ + int ielen = iebuf[1] + 2; + int offset = 2; /* Skip the IE id, and the length. */ + int i; + unsigned char wfa_oui[3] = {0x00, 0x50, 0xf2}; + unsigned char rsn_oui[3] = {0x00, 0x0f, 0xac}; + unsigned char cisco_oui[3] = {0x00, 0x40, 0x96}; + unsigned char pre11n_oui[3] = {0x00, 0x90, 0x4C}; + unsigned char atheros_oui[3] = {0x00, 0x03, 0x7F}; + unsigned char avm_oui[3] = {0x00, 0x04, 0x0e}; + unsigned char broadcom_oui[3] = {0x00, 0x10, 0x18}; + unsigned char ralinkte_oui[3] = {0x00, 0x0c, 0x43}; + + if(ielen > buflen) + ielen = buflen; + if(ielen < 5) + { + iw_print_ie_unknown(iebuf, buflen); + return; + } + + /* Check for WPA1 */ + if(memcmp(&iebuf[offset], wfa_oui, 3) == 0 && + ielen >= 6 && + iebuf[offset + 3] == 0x01) + { + iw_print_ie_wpa(iebuf, ielen); + return; + } + + /* Check for known Cisco extensions */ + if(memcmp(&iebuf[offset], cisco_oui, 3) == 0 && + ielen >= 6) + { + if(iebuf[offset + 3] == 0x00) + { + iw_print_ie_cisco_dtpc(iebuf, ielen); + return; + } + else if(iebuf[offset + 3] == 0x03) + { + iw_print_ie_cisco_ccx_version(iebuf, ielen); + return; + } + else if(iebuf[offset + 3] == 0x14) + { + iw_print_ie_cisco_sfa(iebuf, ielen); + return; + } + } + + printf("Vendor-specific ("); + if (memcmp(&iebuf[offset], rsn_oui, 3) == 0) + printf("IEEE 802.11"); + else if (memcmp(&iebuf[offset], wfa_oui, 3) == 0) + printf("WPA/WME"); + else if (memcmp(&iebuf[offset], pre11n_oui, 3) == 0) + printf("802.11 Pre-N"); + else if (memcmp(&iebuf[offset], cisco_oui, 3) == 0) + printf("Cisco Wireless"); + else if (memcmp(&iebuf[offset], atheros_oui, 3) == 0) + printf("Atheros"); + else if (memcmp(&iebuf[offset], avm_oui, 3) == 0) + printf("AVM"); + else if (memcmp(&iebuf[offset], broadcom_oui, 3) == 0) + printf("Broadcom"); + else if (memcmp(&iebuf[offset], ralinkte_oui, 3) == 0) + printf("RalinkTe"); + else + printf("Unknown vendor %02X:%02X:%02X", + iebuf[offset], iebuf[offset + 1], iebuf[offset + 2]); + printf(")"); + + if(verbose) + { + printf(": "); + for(i = offset + 3; i < ielen; i++) + printf("%02X", iebuf[i]); + } + printf("\n"); +} + +/*------------------------------------------------------------------*/ +/* Process a generic IE and display the info in human readable form * for some of the most interesting ones. * For now, we only decode the WPA IEs. */ @@ -410,27 +1490,67 @@ iw_print_gen_ie(unsigned char * buffer, int buflen) { - int offset = 0; + int offset; /* Loop on each IE, each IE is minimum 2 bytes */ - while(offset <= (buflen - 2)) + for(offset = 0; offset <= (buflen - 2); offset += buffer[offset+1] + 2) { + if (buffer[offset] == 0x00 || buffer[offset] == 0x01 || + buffer[offset] == 0x03 || buffer[offset] == 0x32) { + /* Skip ESSID (0x00), supported rates (0x01), current channel (0x03), + * and extended supported rates (0x32); they are already + * decoded and displayed. (Basic rates are not shown, though.) */ + continue; + } printf(" IE: "); /* Check IE type */ switch(buffer[offset]) { - case 0xdd: /* WPA1 (and other) */ + case 0x05: /* Traffic indication map */ + iw_print_ie_tim(buffer + offset, buflen); + break; + case 0x07: /* Country */ + iw_print_ie_country(buffer + offset, buflen); + break; + case 0x0B: /* QBSS load */ + iw_print_ie_qbss_load(buffer + offset, buflen); + break; + case 0x20: /* Power constraint */ + iw_print_ie_power_constraint(buffer + offset, buflen); + break; + case 0x2a: /* ERP info */ + case 0x2f: /* ERP info (old code) */ + iw_print_ie_erp(buffer + offset, buflen); + break; + case 0x2d: /* HT capability */ + iw_print_ie_ht_cap(buffer + offset, buflen); + break; case 0x30: /* WPA2 */ iw_print_ie_wpa(buffer + offset, buflen); break; + case 0x33: /* AP channel report */ + iw_print_ie_ap_chan_report(buffer + offset, buflen); + break; + case 0x3d: /* HT info */ + iw_print_ie_ht_info(buffer + offset, buflen); + break; + case 0x3e: /* Secondary channel offset */ + iw_print_ie_secondary_channel_offset(buffer + offset, buflen); + break; + case 0x85: /* Cisco Aironet (used e.g. in CCX) */ + iw_print_ie_aironet(buffer + offset, buflen); + break; + case 0x96: /* Cisco Vendor Specific, same pattern */ + case 0xdd: /* Vendor Specific (includes WPA1) */ + iw_print_ie_vs(buffer + offset, buflen); + break; default: iw_print_ie_unknown(buffer + offset, buflen); } - /* Skip over this IE to the next one in the list. */ - offset += buffer[offset+1] + 2; } } + #endif /* WE_ESSENTIAL */ /***************************** SCANNING *****************************/ @@ -598,7 +1718,8 @@ if((event->u.data.pointer) && (event->u.data.length)) memcpy(custom, event->u.data.pointer, event->u.data.length); custom[event->u.data.length] = '\0'; - printf(" Extra:%s\n", custom); + if(verbose) + printf(" Extra:%s\n", custom); } break; default: @@ -698,6 +1819,10 @@ /* Hack */ scanflags |= IW_SCAN_HACK; } + else if(!strncmp(args[0], "verbose", 7)) + { + verbose = 1; + } else { fprintf(stderr, "Invalid scanning option [%s]\n", args[0]); @@ -2079,7 +3204,7 @@ } iwlist_cmd; static const struct iwlist_entry iwlist_cmds[] = { - { "scanning", print_scanning_info, -1, "[essid NNN] [last]" }, + { "scanning", print_scanning_info, -1, "[essid NNN] [last] [verbose]" }, { "frequency", print_freq_info, 0, NULL }, { "channel", print_freq_info, 0, NULL }, { "bitrate", print_bitrate_info, 0, NULL }, diff -ur wireless-tools-30~pre9.orig/Makefile wireless-tools-30~pre9/Makefile --- wireless-tools-30~pre9.orig/Makefile 2014-08-23 15:51:00.000000000 +0200 +++ wireless-tools-30~pre9/Makefile 2014-08-23 15:48:57.123446011 +0200 @@ -116,7 +116,7 @@ all:: $(IWLIB) $(PROGS) %: %.o - $(CC) $(LDFLAGS) $(STRIPFLAGS) $(XCFLAGS) -o $@ $^ + $(CC) $(LDFLAGS) $(STRIPFLAGS) $(XCFLAGS) -o $@ $^ $(LIBS) %.o: %.c wireless.h $(CC) $(XCFLAGS) -c $< %.so: %.c wireless.h

