/* return packet length or -1 on error */ static int parse_prism_header(unsigned char** buf, int len, struct packet_info* p) { wlan_ng_prism2_header* ph; DEBUG("PRISM2 HEADER\n"); if (len > 0 && (size_t)len < sizeof(wlan_ng_prism2_header)) return -1; ph = (wlan_ng_prism2_header*)*buf; /* * different drivers report S/N and rssi values differently */ if (((int)ph->noise.data) < 0) { /* new madwifi */ p->phy_signal = ph->signal.data; } else if (((int)ph->rssi.data) < 0) { /* broadcom hack */ p->phy_signal = ph->rssi.data; } else { /* assume hostap */ p->phy_signal = ph->signal.data; } p->phy_rate = ph->rate.data * 10; /* just in case...*/ if (p->phy_rate == 0 || p->phy_rate > 1080) { /* assume min rate, guess mode from channel */ DEBUG("*** fixing wrong rate\n"); if (ph->channel.data > 14) p->phy_rate = 120; /* 6 * 2 */ else p->phy_rate = 20; /* 1 * 2 */ } p->phy_rate_idx = rate_to_index(p->phy_rate); /* guess phy mode */ if (ph->channel.data > 14) p->phy_flags |= PHY_FLAG_A; else p->phy_flags |= PHY_FLAG_G; /* always assume shortpre */ p->phy_flags |= PHY_FLAG_SHORTPRE; DEBUG("devname: %s\n", ph->devname); DEBUG("signal: %d -> %d\n", ph->signal.data, p->phy_signal); DEBUG("rate: %d\n", ph->rate.data); DEBUG("rssi: %d\n", ph->rssi.data); *buf = *buf + sizeof(wlan_ng_prism2_header); return len - sizeof(wlan_ng_prism2_header); }
static void get_radiotap_info(struct ieee80211_radiotap_iterator *iter, struct packet_info* p) { uint16_t x; char c; unsigned char known, flags, ht20, lgi; switch (iter->this_arg_index) { /* ignoring these */ case IEEE80211_RADIOTAP_TSFT: case IEEE80211_RADIOTAP_FHSS: case IEEE80211_RADIOTAP_LOCK_QUALITY: case IEEE80211_RADIOTAP_TX_ATTENUATION: case IEEE80211_RADIOTAP_DB_TX_ATTENUATION: case IEEE80211_RADIOTAP_DBM_TX_POWER: case IEEE80211_RADIOTAP_TX_FLAGS: case IEEE80211_RADIOTAP_RX_FLAGS: case IEEE80211_RADIOTAP_RTS_RETRIES: case IEEE80211_RADIOTAP_DATA_RETRIES: case IEEE80211_RADIOTAP_AMPDU_STATUS: break; case IEEE80211_RADIOTAP_FLAGS: /* short preamble */ DEBUG("[flags %0x", *iter->this_arg); if (*iter->this_arg & IEEE80211_RADIOTAP_F_SHORTPRE) { p->phy_flags |= PHY_FLAG_SHORTPRE; DEBUG(" shortpre"); } if (*iter->this_arg & IEEE80211_RADIOTAP_F_BADFCS) { p->phy_flags |= PHY_FLAG_BADFCS; p->pkt_types |= PKT_TYPE_BADFCS; DEBUG(" badfcs"); } DEBUG("]"); break; case IEEE80211_RADIOTAP_RATE: //TODO check! //printf("\trate: %lf\n", (double)*iter->this_arg/2); DEBUG("[rate %0x]", *iter->this_arg); p->phy_rate = (*iter->this_arg)*5; /* rate is in 500kbps */ p->phy_rate_idx = rate_to_index(p->phy_rate); break; #define IEEE80211_CHAN_A \ (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM) #define IEEE80211_CHAN_B \ (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK) #define IEEE80211_CHAN_G \ (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN) case IEEE80211_RADIOTAP_CHANNEL: /* channel & channel type */ p->phy_freq = le16toh(*(uint16_t*)iter->this_arg); DEBUG("[freq %d", p->phy_freq); iter->this_arg = iter->this_arg + 2; x = le16toh(*(uint16_t*)iter->this_arg); if (x & IEEE80211_CHAN_A) { p->phy_flags |= PHY_FLAG_A; DEBUG("A]"); } else if (x & IEEE80211_CHAN_G) { p->phy_flags |= PHY_FLAG_G; DEBUG("G]"); } else if (x & IEEE80211_CHAN_B) { p->phy_flags |= PHY_FLAG_B; DEBUG("B]"); } break; case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: c = *(char*)iter->this_arg; DEBUG("[sig %0d]", c); /* we get the signal per rx chain with newer drivers. * save the highest value, but make sure we don't override * with invalid values */ if (c < 0 && (p->phy_signal == 0 || c > p->phy_signal)) p->phy_signal = c; break; case IEEE80211_RADIOTAP_DBM_ANTNOISE: DEBUG("[noi %0x]", *(char*)iter->this_arg); p->phy_noise = *(char*)iter->this_arg; break; case IEEE80211_RADIOTAP_ANTENNA: DEBUG("[ant %0x]", *iter->this_arg); break; case IEEE80211_RADIOTAP_DB_ANTSIGNAL: DEBUG("[snr %0x]", *iter->this_arg); p->phy_snr = *iter->this_arg; break; case IEEE80211_RADIOTAP_DB_ANTNOISE: //printf("\tantnoise: %02d\n", *iter->this_arg); break; case IEEE80211_RADIOTAP_MCS: /* Ref http://www.radiotap.org/defined-fields/MCS */ known = *iter->this_arg++; flags = *iter->this_arg++; DEBUG("[MCS known %0x flags %0x index %0x]", known, flags, *iter->this_arg); if (known & IEEE80211_RADIOTAP_MCS_HAVE_BW) ht20 = (flags & IEEE80211_RADIOTAP_MCS_BW_MASK) == IEEE80211_RADIOTAP_MCS_BW_20; else ht20 = 1; /* assume HT20 if not present */ if (known & IEEE80211_RADIOTAP_MCS_HAVE_GI) lgi = !(flags & IEEE80211_RADIOTAP_MCS_SGI); else lgi = 1; /* assume long GI if not present */ DEBUG(" %s %s", ht20 ? "HT20" : "HT40", lgi ? "LGI" : "SGI"); p->phy_rate_idx = 12 + *iter->this_arg; p->phy_rate_flags = flags; p->phy_rate = mcs_index_to_rate(*iter->this_arg, ht20, lgi); DEBUG(" RATE %d ", p->phy_rate); break; default: printlog("UNKNOWN RADIOTAP field %d", iter->this_arg_index); break; } }