📄 iwlist.c
字号:
/* * Wireless Tools * * Jean II - HPLB '99 - HPL 99->07 * * This tool can access various piece of information on the card * not part of iwconfig... * You need to link this code against "iwlist.c" and "-lm". * * This file is released under the GPL license. * Copyright (c) 1997-2007 Jean Tourrilhes <jt@hpl.hp.com> */#include "iwlib.h" /* Header */#include <sys/time.h>/****************************** TYPES ******************************//* * Scan state and meta-information, used to decode events... */typedef struct iwscan_state{ /* State */ int ap_num; /* Access Point number 1->N */ int val_index; /* Value in table 0->(N-1) */} iwscan_state;/* * Bit to name mapping */typedef struct iwmask_name{ unsigned int mask; /* bit mask for the value */ const char * name; /* human readable name for the value */} iwmask_name;/* * Types of authentication parameters */typedef struct iw_auth_descr{ int value; /* Type of auth value */ const char * label; /* User readable version */ const struct iwmask_name * names; /* Names for this value */ const int num_names; /* Number of names */} iw_auth_descr;/**************************** CONSTANTS ****************************/#define IW_SCAN_HACK 0x8000#define IW_EXTKEY_SIZE (sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX)/* ------------------------ WPA CAPA NAMES ------------------------ *//* * This is the user readable name of a bunch of WPA constants in wireless.h * Maybe this should go in iwlib.c ? */#ifndef WE_ESSENTIAL#define IW_ARRAY_LEN(x) (sizeof(x)/sizeof((x)[0]))//static const struct iwmask_name iw_enc_mode_name[] = {// { IW_ENCODE_RESTRICTED, "restricted" },// { IW_ENCODE_OPEN, "open" },//};//#define IW_ENC_MODE_NUM IW_ARRAY_LEN(iw_enc_mode_name)static const struct iwmask_name iw_auth_capa_name[] = { { IW_ENC_CAPA_WPA, "WPA" }, { IW_ENC_CAPA_WPA2, "WPA2" }, { IW_ENC_CAPA_CIPHER_TKIP, "CIPHER-TKIP" }, { IW_ENC_CAPA_CIPHER_CCMP, "CIPHER-CCMP" },};#define IW_AUTH_CAPA_NUM IW_ARRAY_LEN(iw_auth_capa_name)static const struct iwmask_name iw_auth_cypher_name[] = { { IW_AUTH_CIPHER_NONE, "none" }, { IW_AUTH_CIPHER_WEP40, "WEP-40" }, { IW_AUTH_CIPHER_TKIP, "TKIP" }, { IW_AUTH_CIPHER_CCMP, "CCMP" }, { IW_AUTH_CIPHER_WEP104, "WEP-104" },};#define IW_AUTH_CYPHER_NUM IW_ARRAY_LEN(iw_auth_cypher_name)static const struct iwmask_name iw_wpa_ver_name[] = { { IW_AUTH_WPA_VERSION_DISABLED, "disabled" }, { IW_AUTH_WPA_VERSION_WPA, "WPA" }, { IW_AUTH_WPA_VERSION_WPA2, "WPA2" },};#define IW_WPA_VER_NUM IW_ARRAY_LEN(iw_wpa_ver_name)static const struct iwmask_name iw_auth_key_mgmt_name[] = { { IW_AUTH_KEY_MGMT_802_1X, "802.1x" }, { IW_AUTH_KEY_MGMT_PSK, "PSK" },};#define IW_AUTH_KEY_MGMT_NUM IW_ARRAY_LEN(iw_auth_key_mgmt_name)static const struct iwmask_name iw_auth_alg_name[] = { { IW_AUTH_ALG_OPEN_SYSTEM, "open" }, { IW_AUTH_ALG_SHARED_KEY, "shared-key" }, { IW_AUTH_ALG_LEAP, "LEAP" },};#define IW_AUTH_ALG_NUM IW_ARRAY_LEN(iw_auth_alg_name)static const struct iw_auth_descr iw_auth_settings[] = { { IW_AUTH_WPA_VERSION, "WPA version", iw_wpa_ver_name, IW_WPA_VER_NUM }, { IW_AUTH_KEY_MGMT, "Key management", iw_auth_key_mgmt_name, IW_AUTH_KEY_MGMT_NUM }, { IW_AUTH_CIPHER_PAIRWISE, "Pairwise cipher", iw_auth_cypher_name, IW_AUTH_CYPHER_NUM }, { IW_AUTH_CIPHER_GROUP, "Pairwise cipher", iw_auth_cypher_name, IW_AUTH_CYPHER_NUM }, { IW_AUTH_TKIP_COUNTERMEASURES, "TKIP countermeasures", NULL, 0 }, { IW_AUTH_DROP_UNENCRYPTED, "Drop unencrypted", NULL, 0 }, { IW_AUTH_80211_AUTH_ALG, "Authentication algorithm", iw_auth_alg_name, IW_AUTH_ALG_NUM }, { IW_AUTH_RX_UNENCRYPTED_EAPOL, "Receive unencrypted EAPOL", NULL, 0 }, { IW_AUTH_ROAMING_CONTROL, "Roaming control", NULL, 0 }, { IW_AUTH_PRIVACY_INVOKED, "Privacy invoked", NULL, 0 },};#define IW_AUTH_SETTINGS_NUM IW_ARRAY_LEN(iw_auth_settings)/* Values for the IW_ENCODE_ALG_* returned by SIOCSIWENCODEEXT */static const char * iw_encode_alg_name[] = { "none", "WEP", "TKIP", "CCMP", "unknown"};#define IW_ENCODE_ALG_NUM IW_ARRAY_LEN(iw_encode_alg_name)#ifndef IW_IE_CIPHER_NONE/* Cypher values in GENIE (pairwise and group) */#define IW_IE_CIPHER_NONE 0#define IW_IE_CIPHER_WEP40 1#define IW_IE_CIPHER_TKIP 2#define IW_IE_CIPHER_WRAP 3#define IW_IE_CIPHER_CCMP 4#define IW_IE_CIPHER_WEP104 5/* Key management in GENIE */#define IW_IE_KEY_MGMT_NONE 0#define IW_IE_KEY_MGMT_802_1X 1#define IW_IE_KEY_MGMT_PSK 2#endif /* IW_IE_CIPHER_NONE *//* Values for the IW_IE_CIPHER_* in GENIE */static const char * iw_ie_cypher_name[] = { "none", "WEP-40", "TKIP", "WRAP", "CCMP", "WEP-104",};#define IW_IE_CYPHER_NUM IW_ARRAY_LEN(iw_ie_cypher_name)/* Values for the IW_IE_KEY_MGMT_* in GENIE */static const char * iw_ie_key_mgmt_name[] = { "none", "802.1x", "PSK",};#define IW_IE_KEY_MGMT_NUM IW_ARRAY_LEN(iw_ie_key_mgmt_name)#endif /* WE_ESSENTIAL *//************************* WPA SUBROUTINES *************************/#ifndef WE_ESSENTIAL/*------------------------------------------------------------------*//* * Print all names corresponding to a mask. * This may want to be used in iw_print_retry_value() ? */static void iw_print_mask_name(unsigned int mask, const struct iwmask_name names[], const unsigned int num_names, const char * sep){ unsigned int i; /* Print out all names for the bitmask */ for(i = 0; i < num_names; i++) { if(mask & names[i].mask) { /* Print out */ printf("%s%s", sep, names[i].name); /* Remove the bit from the mask */ mask &= ~names[i].mask; } } /* If there is unconsumed bits... */ if(mask != 0) printf("%sUnknown", sep);}/*------------------------------------------------------------------*//* * Print the name corresponding to a value, with overflow check. */static voidiw_print_value_name(unsigned int value, const char * names[], const unsigned int num_names){ if(value >= num_names) printf(" unknown (%d)", value); else printf(" %s", names[value]);}/*------------------------------------------------------------------*//* * Parse, and display the results of an unknown 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");}/*------------------------------------------------------------------*//* * 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;#ifdef DEBUG /* Debugging code. In theory useless, because it's debugged ;-) */ printf("IE raw value %d [%02X", buflen, iebuf[0]); for(i = 1; i < buflen; i++) printf(":%02X", iebuf[i]); printf("]\n");#endif 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. 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; 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_value_name(iebuf[offset+3], iw_ie_cypher_name, IW_IE_CYPHER_NUM); 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 : 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_value_name(iebuf[offset+3], iw_ie_cypher_name, IW_IE_CYPHER_NUM); } 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 { iw_print_value_name(iebuf[offset+3], iw_ie_key_mgmt_name, IW_IE_KEY_MGMT_NUM); } 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 voidiw_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; }}#endif /* WE_ESSENTIAL *//***************************** SCANNING *****************************//* * This one behave quite differently from the others * * Note that we don't use the scanning capability of iwlib (functions * iw_process_scan() and iw_scan()). The main reason is that * iw_process_scan() return only a subset of the scan data to the caller, * for example custom elements and bitrates are ommited. Here, we * do the complete job... *//*------------------------------------------------------------------*//* * Print one element from the scanning results */static inline voidprint_scanning_token(struct stream_descr * stream, /* Stream of events */ struct iw_event * event, /* Extracted token */ struct iwscan_state * state, struct iw_range * iw_range, /* Range info */ int has_range){ char buffer[128]; /* Temporary buffer */ /* Now, let's decode the event */ switch(event->cmd) { case SIOCGIWAP: printf(" Cell %02d - Address: %s\n", state->ap_num, iw_saether_ntop(&event->u.ap_addr, buffer)); state->ap_num++; break; case SIOCGIWNWID: if(event->u.nwid.disabled) printf(" NWID:off/any\n"); else printf(" NWID:%X\n", event->u.nwid.value); break; case SIOCGIWFREQ: { double freq; /* Frequency/channel */ int channel = -1; /* Converted to channel */ freq = iw_freq2float(&(event->u.freq)); /* Convert to channel if possible */ if(has_range) channel = iw_freq_to_channel(freq, iw_range); iw_print_freq(buffer, sizeof(buffer), freq, channel, event->u.freq.flags); printf(" %s\n", buffer); } break; case SIOCGIWMODE: /* Note : event->u.mode is unsigned, no need to check <= 0 */ if(event->u.mode >= IW_NUM_OPER_MODE) event->u.mode = IW_NUM_OPER_MODE; printf(" Mode:%s\n", iw_operation_mode[event->u.mode]); break; case SIOCGIWNAME: printf(" Protocol:%-1.16s\n", event->u.name); break; case SIOCGIWESSID: { char essid[IW_ESSID_MAX_SIZE+1]; memset(essid, '\0', sizeof(essid)); if((event->u.essid.pointer) && (event->u.essid.length)) memcpy(essid, event->u.essid.pointer, event->u.essid.length); if(event->u.essid.flags) { /* Does it have an ESSID index ? */ if((event->u.essid.flags & IW_ENCODE_INDEX) > 1) printf(" ESSID:\"%s\" [%d]\n", essid, (event->u.essid.flags & IW_ENCODE_INDEX)); else printf(" ESSID:\"%s\"\n", essid); } else printf(" ESSID:off/any/hidden\n"); } break; case SIOCGIWENCODE: { unsigned char key[IW_ENCODING_TOKEN_MAX]; if(event->u.data.pointer) memcpy(key, event->u.data.pointer, event->u.data.length); else event->u.data.flags |= IW_ENCODE_NOKEY; printf(" Encryption key:"); if(event->u.data.flags & IW_ENCODE_DISABLED) printf("off\n"); else { /* Display the key */ iw_print_key(buffer, sizeof(buffer), key, event->u.data.length, event->u.data.flags); printf("%s", buffer); /* Other info... */ if((event->u.data.flags & IW_ENCODE_INDEX) > 1) printf(" [%d]", event->u.data.flags & IW_ENCODE_INDEX); if(event->u.data.flags & IW_ENCODE_RESTRICTED) printf(" Security mode:restricted"); if(event->u.data.flags & IW_ENCODE_OPEN) printf(" Security mode:open"); printf("\n"); } } break; case SIOCGIWRATE: if(state->val_index == 0) printf(" Bit Rates:"); else if((state->val_index % 5) == 0) printf("\n "); else printf("; "); iw_print_bitrate(buffer, sizeof(buffer), event->u.bitrate.value); printf("%s", buffer); /* Check for termination */ if(stream->value == NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -