+ * Parse, and display the results of a WPA or WPA2 IE.
+ *
+ */
+static void
+iw_print_ie_unknown(unsigned char * iebuf,
+ int buflen)
+{
+ int ielen = iebuf[1] + 2;
+ int i;
+
+ if(ielen > buflen)
+ ielen = buflen;
+
+ printf("Unknown: ");
+ for(i = 0; i < ielen; i++)
+ printf("%02X", iebuf[i]);
+ printf("\n");
+}
+
+/*-----------------------------------------------------------------*/
+/*
+ * Display the cipher type for the value passed in.
+ *
+ */
+static inline void
+iw_print_ie_cipher(unsigned char csuite)
+{
+ switch (csuite)
+ {
+ case 0x00:
+ printf("None or same as Group ");
+ break;
+
+ case 0x01:
+ printf("WEP-40 ");
+ break;
+
+ case 0x02:
+ printf("TKIP ");
+ break;
+
+ case 0x03:
+ printf("WRAP ");
+ break;
+
+ case 0x04:
+ printf("CCMP ");
+ break;
+
+ case 0x05:
+ printf("WEP-104 ");
+ break;
+
+ default:
+ printf("Unknown ");
+ break;
+ }
+ }
+
+/*------------------------------------------------------------------*/
+/*
+ * Parse, and display the results of a WPA or WPA2 IE.
+ *
+ */
+static inline void
+iw_print_ie_wpa(unsigned char * iebuf,
+ int buflen)
+{
+ int ielen = iebuf[1] + 2;
+ int offset = 2; /* Skip the IE id, and the length. */
+ unsigned char wpa1_oui[3] = {0x00, 0x50, 0xf2};
+ unsigned char wpa2_oui[3] = {0x00, 0x0f, 0xac};
+ unsigned char * wpa_oui;
+ int i;
+ uint16_t ver = 0;
+ uint16_t cnt = 0;
+
+ if(ielen > buflen)
+ ielen = buflen;
+
+ switch(iebuf[0])
+ {
+ case 0x30: /* WPA2 */
+ /* Check if we have enough data */
+ if(ielen < 4)
+ {
+ iw_print_ie_unknown(iebuf, buflen);
+ return;
+ }
+
+ wpa_oui = wpa2_oui;
+ break;
+
+ case 0xdd: /* WPA or else */
+ wpa_oui = wpa1_oui;
+
+ /* Not all IEs that start with 0xdd are WPA.
+ * So check that the OUI is valid. */
+ if((ielen < 8)
+ || ((memcmp(&iebuf[offset], wpa_oui, 3) != 0)
+ && (iebuf[offset+3] == 0x01)))
+ {
+ iw_print_ie_unknown(iebuf, buflen);
+ return;
+ }
+
+ offset += 4;
+ break;
+
+ default:
+ return;
+ }
+
+ /* Pick version number (little endian) */
+ ver = iebuf[offset] | (iebuf[offset + 1] << 8);
+ offset += 2;
+
+ if(iebuf[0] == 0xdd)
+ printf("WPA Version %d\n", ver);
+ if(iebuf[0] == 0x30)
+ printf("IEEE 802.11i/WPA2 Version %d\n", ver);
+
+ /* From here, everything is technically optional. */
+
+ /* Check if we are done */
+ if(ielen < (offset + 4))
+ {
+ /* We have a short IE. So we should assume TKIP/TKIP. */
+ printf(" Group Cipher : TKIP\n");
+ printf(" Pairwise Cipher : TKIP\n");
+ return;
+ }
+
+ /* Next we have our group cipher. */
+ if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
+ {
+ printf(" Group Cipher : Proprietary\n");
+ }
+ else
+ {
+ printf(" Group Cipher : ");
+ iw_print_ie_cipher(iebuf[offset+3]);
+ printf("\n");
+ }
+ offset += 4;
+
+ /* Check if we are done */
+ if(ielen < (offset + 2))
+ {
+ /* We don't have a pairwise cipher, or auth method. Assume TKIP. */
+ printf(" Pairwise Ciphers (1) : TKIP\n");
+ return;
+ }
+
+ /* Otherwise, we have some number of pairwise ciphers. */
+ cnt = iebuf[offset] | (iebuf[offset + 1] << 8);
+ offset += 2;
+ printf(" Pairwise Ciphers (%d) : ", cnt);
+
+ if(ielen < (offset + 4*cnt))
+ return;
+
+ for(i = 0; i < cnt; i++)
+ {
+ if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
+ {
+ printf("Proprietary ");
+ }
+ else
+ {
+ iw_print_ie_cipher(iebuf[offset+3]);
+ }
+ offset+=4;
+ }
+ printf("\n");
+
+ /* Check if we are done */
+ if(ielen < (offset + 2))
+ return;
+
+ /* Now, we have authentication suites. */
+ cnt = iebuf[offset] | (iebuf[offset + 1] << 8);
+ offset += 2;
+ printf(" Authentication Suites (%d) : ", cnt);
+
+ if(ielen < (offset + 4*cnt))
+ return;
+
+ for(i = 0; i < cnt; i++)
+ {
+ if(memcmp(&iebuf[offset], wpa_oui, 3) != 0)
+ {
+ printf("Proprietary ");
+ }
+ else
+ {
+ switch(iebuf[offset+3])
+ {
+ case 0x00:
+ printf("Reserved ");
+ break;
+
+ case 0x01:
+ printf("802.1X ");
+ break;
+
+ case 0x02:
+ printf("PSK ");
+ break;
+
+ default:
+ printf("Unknown ");
+ break;
+ }
+ }
+ offset+=4;
+ }
+ printf("\n");
+
+ /* Check if we are done */
+ if(ielen < (offset + 1))
+ return;
+
+ /* Otherwise, we have capabilities bytes.
+ * For now, we only care about preauth which is in bit position 1 of the
+ * first byte. (But, preauth with WPA version 1 isn't supposed to be
+ * allowed.) 8-) */
+ if(iebuf[offset] & 0x01)
+ {
+ printf(" Preauthentication Supported\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.
+ */
+static inline void
+iw_print_gen_ie(unsigned char * buffer,
+ int buflen)
+{
+ int offset = 0;
+
+ /* Loop on each IE, each IE is minimum 2 bytes */
+ while(offset <= (buflen - 2))
+ {
+ printf(" IE: ");
+
+ /* Check IE type */
+ switch(buffer[offset])
+ {
+ case 0xdd: /* WPA1 (and other) */
+ case 0x30: /* WPA2 */
+ iw_print_ie_wpa(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;
+ }
+}
+
+/*------------------------------------------------------------------*/
+/*