/* return length of packet, 0 for bad FCS, -1 on error */ static int parse_radiotap_header(unsigned char** buf, int len, struct packet_info* p) { struct ieee80211_radiotap_header* rh; struct ieee80211_radiotap_iterator iter; int err, rt_len; rh = (struct ieee80211_radiotap_header*)*buf; rt_len = le16toh(rh->it_len); err = ieee80211_radiotap_iterator_init(&iter, rh, rt_len, NULL); if (err) { DEBUG("malformed radiotap header (init returns %d)\n", err); return -1; } DEBUG("Radiotap: "); while (!(err = ieee80211_radiotap_iterator_next(&iter))) { if (iter.is_radiotap_ns) { get_radiotap_info(&iter, p); } } DEBUG("\nSIG %d", p->phy_signal); /* sanitize */ if (p->phy_rate == 0 || p->phy_rate > 6000) { /* assume min rate for mode */ DEBUG("*** fixing wrong rate\n"); if (p->phy_flags & PHY_FLAG_A) p->phy_rate = 120; /* 6 * 2 */ else if (p->phy_flags & PHY_FLAG_B) p->phy_rate = 20; /* 1 * 2 */ else if (p->phy_flags & PHY_FLAG_G) p->phy_rate = 120; /* 6 * 2 */ else p->phy_rate = 20; } DEBUG("\nrate: %.2f = idx %d\n", (float)p->phy_rate/10, p->phy_rate_idx); DEBUG("signal: %d\n", p->phy_signal); if (p->phy_flags & PHY_FLAG_BADFCS) { /* we can't trust frames with a bad FCS - stop parsing */ DEBUG("=== bad FCS, stop ===\n"); return 0; } else { *buf = *buf + rt_len; return len - rt_len; } }
static void parse_radiotap(struct ieee80211_radiotap_header * buf, int * rate, char * rssi, char * noise) { int pkt_rate_100kHz = 0, antenna = 0, pwr = 0; char rssi_dbm = 0, noise_dbm = 0; struct ieee80211_radiotap_iterator iterator; int ret = ieee80211_radiotap_iterator_init(&iterator, buf, buf->it_len,0); while (!ret) { ret = ieee80211_radiotap_iterator_next(&iterator); if (ret) continue; /* see if this argument is something we can use */ switch (iterator.this_arg_index) { /* * You must take care when dereferencing iterator.this_arg * for multibyte types... the pointer is not aligned. Use * get_unaligned((type *)iterator.this_arg) to dereference * iterator.this_arg for type "type" safely on all arches. */ case IEEE80211_RADIOTAP_RATE: /* radiotap "rate" u8 is in * 500kbps units, eg, 0x02=1Mbps */ pkt_rate_100kHz = (*iterator.this_arg) * 5; break; case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: rssi_dbm = (*iterator.this_arg); break; case IEEE80211_RADIOTAP_ANTENNA: /* radiotap uses 0 for 1st ant */ antenna = (*iterator.this_arg); break; case IEEE80211_RADIOTAP_DBM_TX_POWER: pwr = *iterator.this_arg; break; case IEEE80211_RADIOTAP_DB_ANTNOISE: noise_dbm = *iterator.this_arg; break; default: break; } } /* while more rt headers */ *noise = noise_dbm; *rssi = rssi_dbm; *rate = pkt_rate_100kHz; }
int get_rtap_signal(int caplen) { struct ieee80211_radiotap_iterator iterator; struct ieee80211_radiotap_header *rthdr; rthdr = (struct ieee80211_radiotap_header *)buffer; if (ieee80211_radiotap_iterator_init(&iterator, rthdr, caplen, NULL) < 0) return 0; while (ieee80211_radiotap_iterator_next(&iterator) >= 0) { if (iterator.this_arg_index == IEEE80211_RADIOTAP_DBM_ANTSIGNAL) return *iterator.this_arg; if (iterator.this_arg_index == IEEE80211_RADIOTAP_DB_ANTSIGNAL) return *iterator.this_arg; if (iterator.this_arg_index == IEEE80211_RADIOTAP_LOCK_QUALITY) return *iterator.this_arg; } return 0; }
/* return length of packet, 0 for bad FCS, -1 on error */ static int parse_radiotap_header(unsigned char** buf, int len, struct packet_info* p) { struct ieee80211_radiotap_header* rh; struct ieee80211_radiotap_iterator iter; int err, rt_len; rh = (struct ieee80211_radiotap_header*)*buf; rt_len = le16toh(rh->it_len); err = ieee80211_radiotap_iterator_init(&iter, rh, rt_len, NULL); if (err) { DEBUG("malformed radiotap header (init returns %d)\n", err); return -1; } while (!(err = ieee80211_radiotap_iterator_next(&iter))) { if (iter.is_radiotap_ns) { get_radiotap_info(&iter, p); } } DEBUG("\n"); DEBUG("SIG %d NOI %d SNR %d\n", p->phy_signal, p->phy_noise, p->phy_snr); if (p->phy_signal > 0 || p->phy_signal < -95) p->phy_signal = 0; /* no SNR from radiotap, try to calculate, normal case nowadays */ if (p->phy_snr == 0 && p->phy_signal < 0) { if (p->phy_noise < 0) { p->phy_snr = p->phy_signal - p->phy_noise; } else { /* HACK: here we just assume noise to be -95dBm */ p->phy_snr = p->phy_signal + 95; } } /* sanitize */ if (p->phy_snr > 99) p->phy_snr = 99; if (p->phy_rate == 0 || p->phy_rate > 6000) { /* assume min rate for mode */ DEBUG("*** fixing wrong rate\n"); if (p->phy_flags & PHY_FLAG_A) p->phy_rate = 120; /* 6 * 2 */ else if (p->phy_flags & PHY_FLAG_B) p->phy_rate = 20; /* 1 * 2 */ else if (p->phy_flags & PHY_FLAG_G) p->phy_rate = 120; /* 6 * 2 */ else p->phy_rate = 20; } DEBUG("\nrate: %.2f\n", (float)p->phy_rate/10); DEBUG("rate_idx: %d\n", p->phy_rate_idx); DEBUG("signal: %d\n", p->phy_signal); DEBUG("noise: %d\n", p->phy_noise); DEBUG("snr: %d\n", p->phy_snr); if (p->phy_flags & PHY_FLAG_BADFCS) { /* we can't trust frames with a bad FCS - stop parsing */ DEBUG("=== bad FCS, stop ===\n"); return 0; } else { *buf = *buf + rt_len; return len - rt_len; } }
int radiotap_parse(struct moep80211_radiotap *moep_hdr, struct ieee80211_radiotap_header *ieee_hdr, int len) { struct ieee80211_radiotap_iterator it; int err; if ((err = ieee80211_radiotap_iterator_init(&it, ieee_hdr, len, NULL))) { errno = -err; return -1; } while (!(err = ieee80211_radiotap_iterator_next(&it))) { switch (it.this_arg_index) { case IEEE80211_RADIOTAP_TSFT: moep_hdr->mactime = le64toh(*(u64 *)it.this_arg); break; case IEEE80211_RADIOTAP_FLAGS: moep_hdr->flags = *(u8 *)it.this_arg; break; case IEEE80211_RADIOTAP_RATE: moep_hdr->rate = *(u8 *)it.this_arg; break; case IEEE80211_RADIOTAP_CHANNEL: moep_hdr->channel.frequency = le16toh(*(u16 *)it.this_arg); moep_hdr->channel.flags = le16toh(*(u16 *)(it.this_arg + 2)); break; case IEEE80211_RADIOTAP_FHSS: moep_hdr->fhss.hop_set = *(u8 *)it.this_arg; moep_hdr->fhss.hop_pattern = *(u8 *)(it.this_arg + 1); break; case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: moep_hdr->signal = *(s8 *)it.this_arg; break; case IEEE80211_RADIOTAP_DBM_ANTNOISE: moep_hdr->noise = *(s8 *)it.this_arg; break; case IEEE80211_RADIOTAP_LOCK_QUALITY: moep_hdr->lock_quality = le16toh(*(u16 *)it.this_arg); break; case IEEE80211_RADIOTAP_TX_ATTENUATION: moep_hdr->tx_attenuation = le16toh(*(u16 *)it.this_arg); break; case IEEE80211_RADIOTAP_DB_TX_ATTENUATION: moep_hdr->tx_attenuation_dB = le16toh(*(u16 *)it.this_arg); break; case IEEE80211_RADIOTAP_DBM_TX_POWER: moep_hdr->tx_power = *(s8 *)it.this_arg; break; case IEEE80211_RADIOTAP_ANTENNA: moep_hdr->antenna = *(u8 *)it.this_arg; break; case IEEE80211_RADIOTAP_DB_ANTSIGNAL: moep_hdr->signal_dB = *(u8 *)it.this_arg; break; case IEEE80211_RADIOTAP_DB_ANTNOISE: moep_hdr->noise_dB = *(u8 *)it.this_arg; break; case IEEE80211_RADIOTAP_RX_FLAGS: moep_hdr->rx_flags = le16toh(*(u16 *)it.this_arg); break; case IEEE80211_RADIOTAP_TX_FLAGS: moep_hdr->tx_flags = le16toh(*(u16 *)it.this_arg); break; case IEEE80211_RADIOTAP_RTS_RETRIES: moep_hdr->rts_retries = *(u8 *)it.this_arg; break; case IEEE80211_RADIOTAP_DATA_RETRIES: moep_hdr->data_retries = *(u8 *)it.this_arg; break; case IEEE80211_RADIOTAP_MCS: moep_hdr->mcs.known = *(u8 *)it.this_arg; moep_hdr->mcs.flags = *(u8 *)(it.this_arg + 1); moep_hdr->mcs.mcs = *(u8 *)(it.this_arg + 2); break; case IEEE80211_RADIOTAP_AMPDU_STATUS: moep_hdr->ampdu.reference = le32toh(*(u32 *)it.this_arg); moep_hdr->ampdu.flags = le16toh(*(u16 *)(it.this_arg + 4)); moep_hdr->ampdu.crc = *(u8 *)(it.this_arg + 6); moep_hdr->ampdu.reserved = *(u8 *)(it.this_arg + 7); break; case IEEE80211_RADIOTAP_VHT: moep_hdr->vht.known = le16toh(*(u16 *)it.this_arg); moep_hdr->vht.flags = *(u8 *)(it.this_arg + 2); moep_hdr->vht.bandwidth = *(u8 *)(it.this_arg + 3); memcpy(moep_hdr->vht.mcs_nss, it.this_arg + 4, 4); moep_hdr->vht.coding = *(u8 *)(it.this_arg + 8); moep_hdr->vht.group_id = *(u8 *)(it.this_arg + 9); moep_hdr->vht.partial_aid = le16toh(*(u16 *)(it.this_arg + 10)); break; default: break; } } if (err != -ENOENT) { errno = -err; return -1; } moep_hdr->hdr.it_version = ieee_hdr->it_version; moep_hdr->hdr.it_len = le16toh(ieee_hdr->it_len); moep_hdr->hdr.it_present = le32toh(ieee_hdr->it_present) & BIT_MASK(radiotap_ns.n_bits); return 0; }
int radiotap_build(struct moep80211_radiotap *moep_hdr, struct ieee80211_radiotap_header *ieee_hdr, int len) { struct ieee80211_radiotap_iterator it; int err; ieee_hdr->it_version = moep_hdr->hdr.it_version; ieee_hdr->it_len = htole16(radiotap_len(moep_hdr->hdr.it_present)); ieee_hdr->it_present = htole32(moep_hdr->hdr.it_present & BIT_MASK(radiotap_ns.n_bits)); if ((err = ieee80211_radiotap_iterator_init(&it, ieee_hdr, len, NULL))) { errno = -err; return -1; } while (!(err = ieee80211_radiotap_iterator_next(&it))) { switch (it.this_arg_index) { case IEEE80211_RADIOTAP_TSFT: *(u64 *)it.this_arg = htole64(moep_hdr->mactime); break; case IEEE80211_RADIOTAP_FLAGS: *(u8 *)it.this_arg = moep_hdr->flags; break; case IEEE80211_RADIOTAP_RATE: *(u8 *)it.this_arg = moep_hdr->rate; break; case IEEE80211_RADIOTAP_CHANNEL: *(u16 *)it.this_arg = htole16(moep_hdr->channel.frequency); *(u16 *)(it.this_arg + 2) = htole16(moep_hdr->channel.flags); break; case IEEE80211_RADIOTAP_FHSS: *(u8 *)it.this_arg = moep_hdr->fhss.hop_set; *(u8 *)(it.this_arg + 1) = moep_hdr->fhss.hop_pattern; break; case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: *(s8 *)it.this_arg = moep_hdr->signal; break; case IEEE80211_RADIOTAP_DBM_ANTNOISE: *(s8 *)it.this_arg = moep_hdr->noise; break; case IEEE80211_RADIOTAP_LOCK_QUALITY: *(u16 *)it.this_arg = htole16(moep_hdr->lock_quality); break; case IEEE80211_RADIOTAP_TX_ATTENUATION: *(u16 *)it.this_arg = htole16(moep_hdr->tx_attenuation); break; case IEEE80211_RADIOTAP_DB_TX_ATTENUATION: *(u16 *)it.this_arg = htole16(moep_hdr->tx_attenuation_dB); break; case IEEE80211_RADIOTAP_DBM_TX_POWER: *(s8 *)it.this_arg = moep_hdr->tx_power; break; case IEEE80211_RADIOTAP_ANTENNA: *(u8 *)it.this_arg = moep_hdr->antenna; break; case IEEE80211_RADIOTAP_DB_ANTSIGNAL: *(u8 *)it.this_arg = moep_hdr->signal_dB; break; case IEEE80211_RADIOTAP_DB_ANTNOISE: *(u8 *)it.this_arg = moep_hdr->noise_dB; break; case IEEE80211_RADIOTAP_RX_FLAGS: *(u16 *)it.this_arg = htole16(moep_hdr->rx_flags); break; case IEEE80211_RADIOTAP_TX_FLAGS: *(u16 *)it.this_arg = htole16(moep_hdr->tx_flags); break; case IEEE80211_RADIOTAP_RTS_RETRIES: *(u8 *)it.this_arg = moep_hdr->rts_retries; break; case IEEE80211_RADIOTAP_DATA_RETRIES: *(u8 *)it.this_arg = moep_hdr->data_retries; break; case IEEE80211_RADIOTAP_MCS: *(u8 *)it.this_arg = moep_hdr->mcs.known; *(u8 *)(it.this_arg + 1) = moep_hdr->mcs.flags; *(u8 *)(it.this_arg + 2) = moep_hdr->mcs.mcs; break; case IEEE80211_RADIOTAP_AMPDU_STATUS: *(u32 *)it.this_arg = htole32(moep_hdr->ampdu.reference); *(u16 *)(it.this_arg + 4) = htole16(moep_hdr->ampdu.flags); *(u8 *)(it.this_arg + 6) = moep_hdr->ampdu.crc; *(u8 *)(it.this_arg + 7) = moep_hdr->ampdu.reserved; case IEEE80211_RADIOTAP_VHT: *(u16 *)it.this_arg = htole16(moep_hdr->vht.known); *(u8 *)(it.this_arg + 2) = moep_hdr->vht.flags; *(u8 *)(it.this_arg + 3) = moep_hdr->vht.bandwidth; memcpy(it.this_arg + 4, moep_hdr->vht.mcs_nss, 4); *(u8 *)(it.this_arg + 8) = moep_hdr->vht.coding; *(u8 *)(it.this_arg + 9) = moep_hdr->vht.group_id; *(u16 *)(it.this_arg + 10) = htole16(moep_hdr->vht.partial_aid); default: break; } } if (err != -ENOENT) { errno = -err; return -1; } return 0; }
static int file_read(struct wif *wi, unsigned char *h80211, int len, struct rx_info *ri) { struct priv_file *pf = wi_priv(wi); struct pcap_pkthdr pkh; int rc; unsigned char buf[4096]; int off = 0; struct ieee80211_radiotap_header *rh; struct ieee80211_radiotap_iterator iter; rc = read(pf->pf_fd, &pkh, sizeof(pkh)); if (rc != sizeof(pkh)) return -1; if (pkh.caplen > sizeof(buf)) { printf("Bad caplen %d\n", pkh.caplen); return 0; } assert(pkh.caplen <= sizeof(buf)); rc = read(pf->pf_fd, buf, pkh.caplen); if (rc != (int) pkh.caplen) return -1; if (ri) memset(ri, 0, sizeof(*ri)); switch (pf->pf_dtl) { case LINKTYPE_IEEE802_11: off = 0; break; case LINKTYPE_RADIOTAP_HDR: rh = (struct ieee80211_radiotap_header*) buf; off = le16_to_cpu(rh->it_len); if (ieee80211_radiotap_iterator_init(&iter, rh, rc) < 0) return -1; while (ieee80211_radiotap_iterator_next(&iter) >= 0) { switch (iter.this_arg_index) { case IEEE80211_RADIOTAP_FLAGS: if (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS) rc -= 4; break; } } break; case LINKTYPE_PRISM_HEADER: if (buf[7] == 0x40) off = 0x40; else off = *((int *)(buf + 4)); rc -= 4; break; case LINKTYPE_PPI_HDR: off = le16_to_cpu(*(unsigned short *)(buf + 2)); /* for a while Kismet logged broken PPI headers */ if (off == 24 && le16_to_cpu(*(unsigned short *)(buf + 8)) == 2 ) off = 32; break; case LINKTYPE_ETHERNET: printf("Ethernet packets\n"); return 0; default: errx(1, "Unknown DTL %d", pf->pf_dtl); break; } rc -= off; assert(rc >= 0); if (rc > len) rc = len; memcpy(h80211, &buf[off], rc); return rc; }
uint16_t radiotap_get(struct pkg_util_info *rd,const u_char *packet,uint32_t len) { struct ieee80211_radiotap_header *radiotap; struct ieee80211_radiotap_iterator iterator; radiotap=(struct ieee80211_radiotap_header *)packet; if (radiotap->it_version>PKTHDR_RADIOTAP_VERSION){ return 0; } if (radiotap->it_len<8 || radiotap->it_len>len){ return 0; } ieee80211_radiotap_iterator_init(&iterator,radiotap,radiotap->it_len); while (ieee80211_radiotap_iterator_next(&iterator)>=0){ switch (iterator.this_arg_index){ case IEEE80211_RADIOTAP_TSFT: rd->Tsft=(uint64_t)*iterator.this_arg; break; case IEEE80211_RADIOTAP_FLAGS: rd->Flag=(uint8_t)*iterator.this_arg; break; case IEEE80211_RADIOTAP_RATE: rd->Rate=(uint8_t)*iterator.this_arg; break; case IEEE80211_RADIOTAP_CHANNEL: rd->Channel=(uint8_t)ieee80211mhz2chan((uint32_t)((iterator.this_arg[1])*256+(iterator.this_arg[0]))) | 0x80; break; case IEEE80211_RADIOTAP_FHSS: rd->Fhss=(uint8_t)*iterator.this_arg; break; case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: rd->Antenna_signal=(uint8_t)*iterator.this_arg-256; break; case IEEE80211_RADIOTAP_DBM_ANTNOISE: rd->Antenna_noise=(uint8_t)*iterator.this_arg-256; break; case IEEE80211_RADIOTAP_LOCK_QUALITY: rd->Lock_quality=(uint16_t)*iterator.this_arg; break; case IEEE80211_RADIOTAP_TX_ATTENUATION: rd->Tx_attenuation=(uint16_t)*iterator.this_arg; break; case IEEE80211_RADIOTAP_DB_TX_ATTENUATION: rd->Db_tx_attenuation=(uint16_t)*iterator.this_arg; break; case IEEE80211_RADIOTAP_DBM_TX_POWER: rd->Dbm_tx_power=(int)*iterator.this_arg; break; case IEEE80211_RADIOTAP_ANTENNA: rd->Antenna=(uint8_t)*iterator.this_arg; break; case IEEE80211_RADIOTAP_DB_ANTSIGNAL: rd->Db_antenna_signal=(uint8_t)*iterator.this_arg; break; case IEEE80211_RADIOTAP_DB_ANTNOISE: rd->Db_antenna_noise=(uint8_t)*iterator.this_arg; break; } } return radiotap->it_len; }
static void handle_monitor_read(int sock, void *eloop_ctx, void *sock_ctx) { struct nl80211_data* ctx = eloop_ctx; int len; unsigned char buf[3000]; struct ieee80211_radiotap_iterator iter; int ret; int datarate = 0, ssi_signal = 0; int injected = 0, failed = 0, rxflags = 0; len = recv(sock, buf, sizeof(buf), 0); if (len < 0) { fprintf(stderr, "nl80211: Monitor socket recv failed: %s\n", strerror(errno)); return; } if (ieee80211_radiotap_iterator_init(&iter, (void *) buf, len, NULL)) { fprintf(stderr, "nl80211: received invalid radiotap frame\n"); return; } while (1) { ret = ieee80211_radiotap_iterator_next(&iter); if (ret == -ENOENT) break; if (ret) { fprintf(stderr, "nl80211: received invalid radiotap frame (%d)\n", ret); return; } switch (iter.this_arg_index) { case IEEE80211_RADIOTAP_FLAGS: if (*iter.this_arg & IEEE80211_RADIOTAP_F_FCS) len -= 4; break; case IEEE80211_RADIOTAP_RX_FLAGS: rxflags = 1; break; case IEEE80211_RADIOTAP_TX_FLAGS: injected = 1; failed = le_to_host16((*(uint16_t *) iter.this_arg)) &IEEE80211_RADIOTAP_F_TX_FAIL; break; case IEEE80211_RADIOTAP_DATA_RETRIES: break; case IEEE80211_RADIOTAP_CHANNEL: /* TODO: convert from freq/flags to channel number */ break; case IEEE80211_RADIOTAP_RATE: datarate = *iter.this_arg * 5; break; case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: ssi_signal = (s8) *iter.this_arg; break; } } if (rxflags && injected) return; if (!injected) handle_rx_frame(ctx, buf + iter._max_length, len - iter._max_length, datarate, ssi_signal); else handle_tx_frame(ctx, buf + iter._max_length, len - iter._max_length, !failed); }
int main(int argc, char *argv[]) { struct ieee80211_radiotap_iterator iter; struct stat statbuf; int fd, err, fnidx = 1, i; void *data; if (argc != 2 && argc != 3) { fprintf(stderr, "usage: parse [--fcshdr] <file>\n"); fprintf(stderr, " --fcshdr: read bit 14 as FCS\n"); return 2; } if (strcmp(argv[1], "--fcshdr") == 0) { fcshdr = 1; fnidx++; } fd = open(argv[fnidx], O_RDONLY); if (fd < 0) { fprintf(stderr, "cannot open file %s\n", argv[fnidx]); return 2; } if (fstat(fd, &statbuf)) { perror("fstat"); return 2; } data = mmap(NULL, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0); err = ieee80211_radiotap_iterator_init(&iter, data, statbuf.st_size, &vns); if (err) { printf("malformed radiotap header (init returns %d)\n", err); return 3; } if (fcshdr) { iter.overrides = overrides; iter.n_overrides = sizeof(overrides)/sizeof(overrides[0]); } while (!(err = ieee80211_radiotap_iterator_next(&iter))) { if (iter.this_arg_index == IEEE80211_RADIOTAP_VENDOR_NAMESPACE) { printf("\tvendor NS (%.2x-%.2x-%.2x:%d, %d bytes)\n", iter.this_arg[0], iter.this_arg[1], iter.this_arg[2], iter.this_arg[3], iter.this_arg_size - 6); for (i = 6; i < iter.this_arg_size; i++) { if (i % 8 == 6) printf("\t\t"); else printf(" "); printf("%.2x", iter.this_arg[i]); } printf("\n"); } else if (iter.is_radiotap_ns) print_radiotap_namespace(&iter); else if (iter.current_namespace == &vns_array[0]) print_test_namespace(&iter); } if (err != -ENOENT) { printf("malformed radiotap data\n"); return 3; } return 0; }
static void handle_packet(u_char *argc, const struct pcap_pkthdr *pkthdr, const u_char *pkt) { u16 hlen, pos1, pos2, pos3, b_pos; u_int8_t nlen; int n80211HeaderLength = HEADERLENGTH; int bytes, n, ssid = 0; PENUMBRA_RADIOTAP_DATA prd; struct ieee80211_radiotap_iterator rti; const u_char *rtpkt = pkt; // extract radiotap headder // based on packetspammer by andy green hlen = rtpkt[2] + (rtpkt[3] << 8); bytes = pkthdr->len - (hlen + n80211HeaderLength); ieee80211_radiotap_iterator_init(&rti, (struct ieee80211_radiotap_header *)rtpkt, bytes); while ((n = ieee80211_radiotap_iterator_next(&rti)) == 0) { switch (rti.this_arg_index) { case IEEE80211_RADIOTAP_RATE: prd.m_nRate = (*rti.this_arg); break; case IEEE80211_RADIOTAP_CHANNEL: prd.m_nChannel = le16_to_cpu(*((u16 *)rti.this_arg)); break; case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: prd.m_ndBmsignal = (*rti.this_arg); break; case IEEE80211_RADIOTAP_DBM_ANTNOISE: prd.m_ndBmnoise = (*rti.this_arg); break; } } do_debug("RX: Rate: %2d.%dMbps, Freq: %dMHz, Signal:% ddBm, Noise: %ddBm ", prd.m_nRate / 2, 5 * (prd.m_nRate & 1), prd.m_nChannel,prd.m_ndBmsignal, prd.m_ndBmnoise); // extract subtype from 802.11 header if (pkthdr->len >= 24) { nlen = pkt[2] + (pkt[3] << 8); pos1 = nlen + 4; // frame control + Duration ID pos2 = nlen + 10; // frame control + Duration ID + Address 1 pos3 = nlen + 16; // frame control + Duration ID + Address 1 + Address 2 switch (pkt[nlen]) { case 0x00: do_debug("Recdived frame type is association request "); print_mgmt_header(pkt, pos1, pos2 ,pos3); do_debug("\n"); break; case 0x10: do_debug("Recdived frame type is association response "); print_mgmt_header(pkt, pos1, pos2 ,pos3); b_pos = nlen + 30; ssid = 1; break; case 0x40: do_debug("Recdived frame type is probe request "); print_mgmt_header(pkt, pos1, pos2 ,pos3); b_pos = nlen + 24; ssid = 1; break; case 0x50: do_debug("Recdived frame type is probe response "); print_mgmt_header(pkt, pos1, pos2 ,pos3); b_pos = nlen + 36; ssid = 1; break; case 0x80: do_debug("Recdived frame type is beacon "); print_mgmt_header(pkt, pos1, pos2 ,pos3); b_pos = nlen + 36; ssid = 1; break; case 0xB0: do_debug("Recdived frame type is authentication "); print_mgmt_header(pkt, pos1, pos2 ,pos3); do_debug("\n"); break; case 0xD4: do_debug("Recdived frame type is ack\n"); break; case 0x08: do_debug("Recdived frame type is data\n"); break; case 0x48: do_debug("Recdived frame type is null\n"); break; default: do_debug("Unknown frame type is %x\n", pkt[nlen]); break; } } // extract ssid from 802.11 frame body if (ssid) essid_print(pkt + b_pos); }