package com.netifera.platform.net.wifi.packets; import java.nio.ByteOrder; import com.netifera.platform.net.packets.AbstractPacket; @SuppressWarnings("boxing") public class RadioTapHeader extends AbstractPacket { int version; int pad; int length; int presentFields; /* Value in microseconds of the MAC's 64-bit 802.11 Time * Synchronization Function timer when the first bit of the * MPDU arrived at the MAC. For received frames, only. */ long tsft; /* Tx/Rx frequency in MHz, followed by flags (see below). */ int channelFrequency; int channelFlags; /* For frequency-hopping radios, the hop set (first byte) * and pattern (second byte). */ int fhss; /* Tx/Rx data rate in 500kb/s */ int rate; /* RF signal power at the antenna, decibel difference from * one milliwatt. */ int dBmSignal; /* RF noise power at the antenna, decibel difference from one * milliwatt. */ int dBmNoise; /* RF signal power at the antenna, decibel difference from an * arbitrary, fixed reference. */ int dBSignal; /* RF noise power at the antenna, decibel difference from an * arbitrary, fixed reference. */ int dBNoise; /* Quality of Barker code lock. Unitless. Monotonically * nondecreasing with "better" lock strength. Called "Signal * Quality" in datasheets. (Is there a standard way to measure * this?) */ int lockQuality; /* Transmit power expressed as unitless distance from max * power set at factory calibration. 0 is max power. * Monotonically nondecreasing with lower power levels. */ int txAttenuation; /* Transmit power expressed as decibel distance from max power * set at factory calibration. 0 is max power. Monotonically * nondecreasing with lower power levels. */ int dBTxAttenuation; /* Transmit power expressed as dBm (decibels from a 1 milliwatt * reference). This is the absolute power level measured at * the antenna port. */ int dBmTxPower; /* Properties of transmitted and received frames. See flags * defined below. */ int flags; /* Unitless indication of the Rx/Tx antenna for this packet. * The first antenna is antenna 0. */ int antenna; /* Types */ static int IEEE80211_RADIOTAP_TSFT = 1<<0; static int IEEE80211_RADIOTAP_FLAGS = 1<<1; static int IEEE80211_RADIOTAP_RATE = 1<<2; static int IEEE80211_RADIOTAP_CHANNEL = 1<<3; static int IEEE80211_RADIOTAP_FHSS = 1<<4; static int IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 1<<5; static int IEEE80211_RADIOTAP_DBM_ANTNOISE = 1<<6; static int IEEE80211_RADIOTAP_LOCK_QUALITY = 1<<7; static int IEEE80211_RADIOTAP_TX_ATTENUATION = 1<<8; static int IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 1<<9; static int IEEE80211_RADIOTAP_DBM_TX_POWER = 1<<10; static int IEEE80211_RADIOTAP_ANTENNA = 1<<11; static int IEEE80211_RADIOTAP_DB_ANTSIGNAL = 1<<12; static int IEEE80211_RADIOTAP_DB_ANTNOISE = 1<<13; static int IEEE80211_RADIOTAP_EXT = 1<<31; /* Channel flags. */ static int IEEE80211_CHAN_TURBO = 0x0010; /* Turbo channel */ static int IEEE80211_CHAN_CCK = 0x0020; /* CCK channel */ static int IEEE80211_CHAN_OFDM = 0x0040; /* OFDM channel */ static int IEEE80211_CHAN_2GHZ = 0x0080; /* 2 GHz spectrum channel. */ static int IEEE80211_CHAN_5GHZ = 0x0100; /* 5 GHz spectrum channel */ static int IEEE80211_CHAN_PASSIVE = 0x0200; /* Only passive scan allowed */ static int IEEE80211_CHAN_DYN = 0x0400; /* Dynamic CCK-OFDM channel */ static int IEEE80211_CHAN_GFSK = 0x0800; /* GFSK channel (FHSS PHY) */ /* For IEEE80211_RADIOTAP_FLAGS */ static int IEEE80211_RADIOTAP_F_CFP = 0x01; /* sent/received during CFP */ static int IEEE80211_RADIOTAP_F_SHORTPRE = 0x02; /* sent/received with short preamble */ static int IEEE80211_RADIOTAP_F_WEP = 0x04; /* sent/received with WEP encryption */ static int IEEE80211_RADIOTAP_F_FRAG = 0x08; /* sent/received fragmentation */ static int IEEE80211_RADIOTAP_F_FCS = 0x10; /* frame includes FCS */ private final boolean nativeBigEndian = (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN); protected int hostOrderUnpack16() { if(nativeBigEndian) { return unpack16(); } else { return swap16(unpack16()); } } protected int hostOrderUnpack32() { if(nativeBigEndian) { return unpack32(); } else { return swap32(unpack32()); } } @Override protected int minimumHeaderLength() { return 8; } @Override protected void packHeader() { // TODO Auto-generated method stub } @Override protected void unpackHeader() { version = unpack8(); pad = unpack8(); length = hostOrderUnpack16(); presentFields = hostOrderUnpack32(); if ((presentFields & IEEE80211_RADIOTAP_EXT) != 0) { System.out.println(String.format("extra bits 0x%08x",hostOrderUnpack32())); } if ((presentFields & IEEE80211_RADIOTAP_TSFT) != 0) { // XXX host order? tsft = unpack64(); } if ((presentFields & IEEE80211_RADIOTAP_FLAGS) != 0) { flags = unpack8(); } if ((presentFields & IEEE80211_RADIOTAP_RATE) != 0) { rate = unpack8(); } if ((presentFields & IEEE80211_RADIOTAP_CHANNEL) != 0) { channelFrequency = hostOrderUnpack16(); channelFlags = hostOrderUnpack16(); } if ((presentFields & IEEE80211_RADIOTAP_FHSS) != 0) { fhss = hostOrderUnpack16(); } if ((presentFields & IEEE80211_RADIOTAP_DBM_ANTSIGNAL) != 0) { dBmSignal = (byte)unpack8(); } if ((presentFields & IEEE80211_RADIOTAP_DBM_ANTNOISE) != 0) { dBmNoise = (byte)unpack8(); } if ((presentFields & IEEE80211_RADIOTAP_LOCK_QUALITY) != 0) { lockQuality = hostOrderUnpack16(); } if ((presentFields & IEEE80211_RADIOTAP_TX_ATTENUATION) != 0) { txAttenuation = hostOrderUnpack16(); } if ((presentFields & IEEE80211_RADIOTAP_DB_TX_ATTENUATION) != 0) { dBTxAttenuation = -unpack8(); //XXX 16 or 8??? } if ((presentFields & IEEE80211_RADIOTAP_DBM_TX_POWER) != 0) { dBmTxPower = -unpack8(); } if ((presentFields & IEEE80211_RADIOTAP_ANTENNA) != 0) { antenna = unpack8(); } if ((presentFields & IEEE80211_RADIOTAP_DB_ANTSIGNAL) != 0) { dBSignal = -unpack8(); } if ((presentFields & IEEE80211_RADIOTAP_DB_ANTNOISE) != 0) { dBNoise = -unpack8(); } } @Override public int headerLength() { if (length==0) { return 8; //XXX } else { return length+pad; } } public Long tsft() { if ((presentFields & IEEE80211_RADIOTAP_TSFT) != 0) { return tsft; } return null; } public Integer flags() { if ((presentFields & IEEE80211_RADIOTAP_FLAGS) != 0) { return flags; } return null; } public Integer rate() { if ((presentFields & IEEE80211_RADIOTAP_RATE) != 0) { return rate; } return null; } public Integer channelFrequency() { if ((presentFields & IEEE80211_RADIOTAP_CHANNEL) != 0) { return channelFrequency; } return null; } public Integer channelFlags() { if ((presentFields & IEEE80211_RADIOTAP_CHANNEL) != 0) { return channelFlags; } return null; } public Integer channel() { Integer freq = channelFrequency(); if (freq == null) return null; if ((channelFlags & IEEE80211_CHAN_2GHZ) != 0) { if (freq == 2484) return 14; if (freq < 2484) return (freq - 2407) / 5; else return 15 + ((freq - 2512) / 20); } if ((channelFlags & IEEE80211_CHAN_5GHZ) != 0) { return (freq - 5000) / 5; } if (freq == 2484) return 14; if (freq < 2484) return (freq - 2407) / 5; if (freq < 5000) return 15 + ((freq - 2512) / 20); return (freq - 5000) / 5; } public Integer fhss() { if ((presentFields & IEEE80211_RADIOTAP_FHSS) != 0) { return fhss; } return null; } public Integer dBmSignal() { if ((presentFields & IEEE80211_RADIOTAP_DBM_ANTSIGNAL) != 0) { return dBmSignal; } return null; } public Integer dBmNoise() { if ((presentFields & IEEE80211_RADIOTAP_DBM_ANTNOISE) != 0) { return dBmNoise; } return null; } public Integer lockQuality() { if ((presentFields & IEEE80211_RADIOTAP_LOCK_QUALITY) != 0) { return lockQuality; } return null; } public Integer txAttenuation() { if ((presentFields & IEEE80211_RADIOTAP_TX_ATTENUATION) != 0) { return txAttenuation; } return null; } public Integer dBTxAttenuation() { if ((presentFields & IEEE80211_RADIOTAP_DB_TX_ATTENUATION) != 0) { return dBTxAttenuation; } return null; } public Integer dBmTxPower() { if ((presentFields & IEEE80211_RADIOTAP_DBM_TX_POWER) != 0) { return dBmTxPower; } return null; } public Integer antenna() { if ((presentFields & IEEE80211_RADIOTAP_ANTENNA) != 0) { return antenna; } return null; } public Integer dBSignal() { if ((presentFields & IEEE80211_RADIOTAP_DB_ANTSIGNAL) != 0) { return dBSignal; } return null; } public Integer dBNoise() { if ((presentFields & IEEE80211_RADIOTAP_DB_ANTNOISE) != 0) { return dBNoise; } return null; } @Override public String toString() { String answer = "RadioTap"; if (tsft() != null) { answer += " TSFT"; } if (channelFrequency() != null) { answer += " Channel="+channelFrequency()+"Mhz"; if ((channelFlags & IEEE80211_CHAN_TURBO) != 0) answer += " Turbo"; if ((channelFlags & IEEE80211_CHAN_CCK) != 0) answer += " CCK"; if ((channelFlags & IEEE80211_CHAN_OFDM) != 0) answer += " OFDM"; if ((channelFlags & IEEE80211_CHAN_2GHZ) != 0) answer += " 2GHz"; if ((channelFlags & IEEE80211_CHAN_5GHZ) != 0) answer += " 5GHz"; if ((channelFlags & IEEE80211_CHAN_PASSIVE) != 0) answer += " Passive"; if ((channelFlags & IEEE80211_CHAN_DYN) != 0) answer += " CCK-OFDM"; if ((channelFlags & IEEE80211_CHAN_GFSK) != 0) answer += " GFSK"; } if (rate() != null) { answer += " rate="+(rate()*500)+"kb/s"; } if (dBSignal() != null) { answer += " signal="+dBSignal()+ "dB"; } if (dBNoise() != null) { answer += " noise="+dBNoise()+ "dB"; } if (dBmSignal() != null) { answer += " signal="+dBmSignal()+ "dBm"; } if (dBmNoise() != null) { answer += " noise="+dBmNoise()+ "dBm"; } if (lockQuality() != null) { answer += " quality="+lockQuality(); } if (antenna() != null) { answer += " antenna="+antenna(); } if (flags() != null) { if ((flags & IEEE80211_RADIOTAP_F_CFP) != 0) { answer += " CFP"; } if ((flags & IEEE80211_RADIOTAP_F_SHORTPRE) != 0) { answer += " ShortPreamble"; } if ((flags & IEEE80211_RADIOTAP_F_WEP) != 0) { answer += " WEP"; } if ((flags & IEEE80211_RADIOTAP_F_FRAG) != 0) { answer += " Fragmentation"; } if ((flags & IEEE80211_RADIOTAP_F_FCS) != 0) { answer += " FCS"; //XXX } } return answer; } }