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

Reply via email to