/* Given the tagged parameter sets from a beacon packet, locate the AP's SSID and return its current channel number */ int parse_beacon_tags(const u_char *packet, size_t len) { char *ssid = NULL; const u_char *tag_data = NULL; unsigned char *ie = NULL, *channel_data = NULL; size_t ie_len = 0, ie_offset = 0, tag_len = 0, tag_offset = 0; int channel = 0; struct radio_tap_header *rt_header = NULL; rt_header = (struct radio_tap_header *) radio_header(packet, len); tag_offset = rt_header->len + sizeof(struct dot11_frame_header) + sizeof(struct beacon_management_frame); if(tag_offset < len) { tag_len = (len - tag_offset); tag_data = (const u_char *) (packet + tag_offset); /* If no SSID was manually specified, parse and save the AP SSID */ if(get_ssid() == NULL) { ie = parse_ie_data(tag_data, tag_len, (uint8_t) SSID_TAG_NUMBER, &ie_len, &ie_offset); if(ie) { /* Return data is not null terminated; allocate ie_len+1 and memcpy string */ ssid = malloc(ie_len+1); if(ssid) { memset(ssid, 0, (ie_len+1)); memcpy(ssid, ie, ie_len); set_ssid(ssid); free(ssid); } free(ie); } } ie = parse_ie_data(tag_data, tag_len, (uint8_t) RATES_TAG_NUMBER, &ie_len, &ie_offset); if(ie) { set_ap_rates(ie, ie_len); free(ie); } channel_data = parse_ie_data(tag_data, tag_len, (uint8_t) CHANNEL_TAG_NUMBER, &ie_len, &ie_offset); if(channel_data) { if(ie_len == 1) { memcpy((int *) &channel, channel_data, ie_len); } free(channel_data); } } return channel; }
/* Given a beacon / probe response packet, returns the reported encryption type (WPA, WEP, NONE) THIS IS BROKE!!! DO NOT USE!!! */ enum encryption_type supported_encryption(const unsigned char *packet, size_t len) { enum encryption_type enc = NONE; const unsigned char *tag_data = NULL; struct radio_tap_header *rt_header = NULL; size_t vlen = 0, voff = 0, tag_offset = 0, tag_len = 0, offset = 0; struct beacon_management_frame *beacon = NULL; if(len > MIN_BEACON_SIZE) { rt_header = (struct radio_tap_header *) radio_header(packet, len); size_t rt_header_len = end_le16toh(rt_header->len); beacon = (struct beacon_management_frame *) (packet + rt_header_len + sizeof(struct dot11_frame_header)); offset = tag_offset = rt_header_len + sizeof(struct dot11_frame_header) + sizeof(struct beacon_management_frame); tag_len = len - tag_offset; tag_data = (const unsigned char *) (packet + tag_offset); if((end_le16toh(beacon->capability) & CAPABILITY_WEP) == CAPABILITY_WEP) { enc = WEP; tag_data = parse_ie_data(tag_data, tag_len, (uint8_t) RSN_TAG_NUMBER, &vlen, &voff); if(tag_data && vlen > 0) { enc = WPA; free((void *) tag_data); } else { while(offset < len) { tag_len = len - offset; tag_data = (const unsigned char *) (packet + offset); tag_data = parse_ie_data(tag_data, tag_len, (uint8_t) VENDOR_SPECIFIC_TAG, &vlen, &voff); if(vlen > WPA_IE_ID_LEN) { if(memcmp(tag_data, WPA_IE_ID, WPA_IE_ID_LEN) == 0) { enc = WPA; break; } free((void *) tag_data); } offset = tag_offset + voff + vlen; } } } } return enc; }
/* Given the tagged parameter sets from a beacon packet, locate the AP's SSID and return its current channel number */ int parse_beacon_tags(const unsigned char *packet, size_t len) { set_vendor(0, "\0\0\0"); char *ssid = NULL; const unsigned char *tag_data = NULL; unsigned char *ie = NULL, *channel_data = NULL; size_t ie_len = 0, ie_offset = 0, tag_len = 0, tag_offset = 0; int channel = 0; struct radio_tap_header *rt_header = NULL; rt_header = (struct radio_tap_header *) radio_header(packet, len); tag_offset = end_le16toh(rt_header->len) + sizeof(struct dot11_frame_header) + sizeof(struct beacon_management_frame); if(tag_offset < len) { tag_len = (len - tag_offset); /* this actually denotes length of the entire tag data area */ tag_data = (const unsigned char *) (packet + tag_offset); /* If no SSID was manually specified, parse and save the AP SSID */ if(get_ssid() == NULL) { ie = parse_ie_data(tag_data, tag_len, (uint8_t) SSID_TAG_NUMBER, &ie_len, &ie_offset); if(ie) { /* Return data is not null terminated; allocate ie_len+1 and memcpy string */ ssid = malloc(ie_len+1); if(ssid) { memset(ssid, 0, (ie_len+1)); memcpy(ssid, ie, ie_len); set_ssid(ssid); free(ssid); } free(ie); } } ie = parse_ie_data(tag_data, tag_len, HT_CAPS_TAG_NUMBER, &ie_len, &ie_offset); if(ie) { set_ap_htcaps(ie, ie_len); free(ie); } ie = parse_ie_data(tag_data, tag_len, (uint8_t) RATES_TAG_NUMBER, &ie_len, &ie_offset); if(ie) { set_ap_rates(ie, ie_len); free(ie); } ie = parse_ie_data(tag_data, tag_len, (uint8_t) ERATES_TAG_NUMBER, &ie_len, &ie_offset); if(ie) { set_ap_ext_rates(ie, ie_len); free(ie); } channel_data = parse_ie_data(tag_data, tag_len, (uint8_t) CHANNEL_TAG_NUMBER, &ie_len, &ie_offset); if(channel_data) { if(ie_len == 1) { channel = *(uint8_t*)channel_data; } free(channel_data); } size_t ie_iterator = 0; do { const unsigned char *tag = tag_data + ie_iterator; // check for the length of the tag, and that its not microsoft if(tag[0] == VENDOR_SPECIFIC_TAG && ie_iterator+2+3 < tag_len && ((tag[1] < 11 && memcmp(tag+2, "\x00\x14\x6c", 3) && memcmp(tag+2, "\x00\x50\xf2", 3)) || (tag[1] == 30 && !(memcmp(tag+2, "\x00\x26\x86", 3))))) { set_vendor(1, tag + 2); break; } } while(get_next_ie(tag_data, tag_len, &ie_iterator)); } return channel; }