// Custom includes
#include "WLANPacket.hh"
#include <boost/io/ios_state.hpp>
+#include <memory.h>
extern "C" {
# include "radiotap/radiotap_iter.h"
#define prefix_
///////////////////////////////cc.p//////////////////////////////////////
-prefix_ void senf::RadiotapPacketParser::fillOffsetTable(boost::uint8_t * data, int maxLength,
- OffsetTable & table)
+///////////////////////////////////////////////////////////////////////////
+// Offset table management
+
+prefix_ senf::RadiotapPacketParser::OffsetTable &
+senf::RadiotapPacketParser::offsetTable(boost::uint32_t presentFlags)
+{
+ typedef std::map<boost::uint32_t, OffsetTable> OffsetMap;
+ static OffsetMap offsetMap;
+
+ OffsetMap::iterator i (offsetMap.find(presentFlags));
+ if (i == offsetMap.end())
+ i = offsetMap.insert(std::make_pair(presentFlags, OffsetTable())).first;
+ return i->second;
+}
+
+prefix_ void senf::RadiotapPacketParser::parseOffsetTable(boost::uint8_t * data, int maxLength,
+ OffsetTable & table)
{
- memset(&table, 0, sizeof(table));
struct ieee80211_radiotap_iterator iter;
ieee80211_radiotap_iterator_init(&iter,
(struct ieee80211_radiotap_header *)data,
maxLength,
0);
- while (ieee80211_radiotap_iterator_next(&iter)==0) {
+ unsigned size (8u);
+ while (ieee80211_radiotap_iterator_next(&iter) == 0) {
if (iter.is_radiotap_ns &&
iter.this_arg_index <= int(senf::RadiotapPacketParser::MAX_INDEX))
table[iter.this_arg_index] = iter.this_arg - data;
+ // We need to set size here in the loop since the iter fields are only valid
+ // when at least one present bit is set ...
+ size = iter.this_arg - data + iter.this_arg_size;
+ }
+ table[MAX_INDEX+1] = size;
+}
+
+prefix_ void senf::RadiotapPacketParser::buildOffsetTable(boost::uint32_t presentFlags,
+ OffsetTable & table)
+{
+ SENF_ASSERT(!(presentFlags & ( (1<<IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE) |
+ (1<<IEEE80211_RADIOTAP_VENDOR_NAMESPACE) |
+ (1<<IEEE80211_RADIOTAP_EXT) )),
+ "Extended or vendor fields not supported");
+
+ struct ieee80211_radiotap_header header;
+ memset(&header, 0, sizeof(header));
+ // header.it_version = 0;
+
+ // Iterating this packet will generate invalid addresses but we don't care since neither
+ // radiotap.c nor we will ever dereference those pointers, we just calculate the offsets.
+ // This works, as long as we don't support extension headers ...
+ header.it_len = 0xFFFF;
+ header.it_present = presentFlags;
+
+ parseOffsetTable((boost::uint8_t*)&header, header.it_len, table);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::RadiotapPacketParser
+
+unsigned const senf::RadiotapPacketParser_Header::FIELD_SIZE[] = {
+ 8, 1, 1, 4, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1 };
+
+prefix_ senf::UInt32Parser senf::RadiotapPacketParser::init_fcs()
+{
+ if (!has_fcs()) {
+ protect(), data().insert(data().end(), 4u, 0u);
+ init_flags().fcsAtEnd_() = true;
+ }
+ return fcs();
+}
+
+prefix_ void senf::RadiotapPacketParser::disable_fcs()
+{
+ if (has_fcs()) {
+ validate(RadiotapPacketParser_Header::fixed_bytes+4);
+ data().erase(data().end()-4, data().end());
+ flags().fcsAtEnd_() = false;
}
- table[MAX_INDEX+1] = iter.this_arg - data + iter.this_arg_size;
}
prefix_ senf::RadiotapPacketParser::OffsetTable const &
-senf::RadiotapPacketParser::offsetTable(boost::uint32_t presentFlags)
+senf::RadiotapPacketParser::currentTable()
+ const
{
- typedef std::map<boost::uint32_t, OffsetTable> OffsetMap;
- static OffsetMap offsetMap;
+ OffsetTable & table (offsetTable(presentFlags()));
+ if (! table[MAX_INDEX+1])
+ parseOffsetTable(&(*data().begin()), data().size(), table);
+ return table;
+}
- OffsetMap::iterator i (offsetMap.find(presentFlags));
- if (i == offsetMap.end()) {
- OffsetTable table;
- fillOffsetTable(&(*data().begin()), data().size(), table);
- i = offsetMap.insert(std::make_pair(presentFlags, table)).first;
+prefix_ senf::RadiotapPacketParser::OffsetTable const &
+senf::RadiotapPacketParser::getTable(boost::uint32_t presentFlags)
+ const
+{
+ OffsetTable & table(offsetTable(presentFlags));
+ if (! table[MAX_INDEX+1])
+ buildOffsetTable(presentFlags, table);
+ return table;
+}
+
+prefix_ void senf::RadiotapPacketParser::insertRemoveBytes(unsigned from , unsigned to, int bytes)
+{
+ data_iterator b (i() + from);
+ data_iterator e (i() + to);
+ if (bytes >= 0) {
+ // Insert some bytes cleaning the old bytes to 0 first
+ std::fill(b, e, 0u);
+ if (bytes > 0)
+ // need to protect the parser since data().insert() invalidates iterators
+ protect(), data().insert(e, bytes, 0u);
+ }
+ else { // bytes < 0
+ // Remove some bytes ...
+ // remember: bytes is negative ...
+ if (b < e + bytes)
+ std::fill(b, e + bytes, 0u);
+ data().erase(e + bytes, e);
}
- return i->second;
}
+prefix_ void senf::RadiotapPacketParser::updatePresentFlags(boost::uint32_t flags)
+{
+ if (flags == presentFlags())
+ return;
+ validate(bytes());
+
+ OffsetTable const & oldTable (currentTable());
+ OffsetTable const & newTable (getTable(flags));
+ unsigned b (RadiotapPacketParser_Header::fixed_bytes);
+ int cumulativeNewBytes (0);
+
+ for (unsigned index (0); index <= MAX_INDEX; ++index) {
+ // Skip any unchanged fields
+ for (; index <= MAX_INDEX+1
+ && ((oldTable[index] == 0 && newTable[index] == 0)
+ || (oldTable[index]+cumulativeNewBytes == newTable[index])); ++index)
+ if (newTable[index] != 0)
+ b = newTable[index] + FIELD_SIZE[index];
+ if (index > MAX_INDEX+1)
+ break;
+ // Now skip over all changed fields
+ // (The condition index <= MAX_INDEX is not needed here since the last
+ // table entry MAX_INDEX+1 is always != 0 in both tables)
+ for (; ! (oldTable[index]!=0 && newTable[index]!=0); ++index) ;
+ // index now either points to
+ // a) an entry set in both tables
+ // b) at the end of the table which contains the total length
+ // (remember: the table has a size of MAX_INDEX+2 entries !!)
+ // in both cases, the difference between the new and old size
+ // is found from the difference between the old and the new table
+ // entry
+ int newBytes (newTable[index] - oldTable[index] - cumulativeNewBytes);
+ insertRemoveBytes(b, oldTable[index] + cumulativeNewBytes, newBytes);
+ cumulativeNewBytes += newBytes;
+ b = newTable[index] + FIELD_SIZE[index];
+ }
+ presentFlags() = flags;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::RadiotapPacketType
prefix_ void senf::RadiotapPacketType::dump(packet p, std::ostream &os)
{
<< senf::fieldName("version") << unsigned(p->version()) << '\n'
<< senf::fieldName("length") << unsigned(p->length()) << '\n';
-# define DUMP_OPTIONAL_FIELD(name, sign, desc) \
+# define FIELD(name, sign, desc) \
if (p->name ## Present()) \
os << senf::fieldName(desc) << sign(p->name()) << '\n';
- DUMP_OPTIONAL_FIELD( tsft, boost::uint64_t, "MAC timestamp" );
+# define ENTER(name) \
+ if (p->name ## Present()) { \
+ packet::Parser::name ## _t subparser (p->name());
- if (p->flagsPresent()) {
- os << senf::fieldName("flags");
+# define SUBFIELD(name, sign, desc) \
+ os << senf::fieldName(desc) << sign(subparser.name()) << '\n';
-# define DUMP_FLAG(name,desc) if (p->flags().name()) os << desc " "
- DUMP_FLAG(shortGI, "ShortGI");
- DUMP_FLAG(badFCS, "BadFCS");
- DUMP_FLAG(fcsAtEnd, "FCSatEnd");
- DUMP_FLAG(fragmentation, "Frag");
- DUMP_FLAG(wep, "WEP");
- DUMP_FLAG(shortPreamble, "ShortPreamble");
- DUMP_FLAG(cfp, "CFP");
-# undef DUMP_FLAG
+# define LEAVE() \
+ }
- os << '\n';
- }
+# define START_FLAGS(desc) \
+ os << senf::fieldName(desc);
- DUMP_OPTIONAL_FIELD( rate, unsigned, "rate" );
-
- if (p->channelOptionsPresent()) {
- os << senf::fieldName("channel frequency")
- << unsigned(p->channelOptions().freq()) << '\n'
- << senf::fieldName("channel flags");
-
-# define DUMP_FLAG(name,desc) if (p->channelOptions().name()) os << desc " "
- DUMP_FLAG(flag2ghz, "2GHz");
- DUMP_FLAG(ofdm, "OFDM");
- DUMP_FLAG(cck, "CCK");
- DUMP_FLAG(turbo, "Turbo");
- DUMP_FLAG(quarterRateChannel, "Rate/4");
- DUMP_FLAG(halfRateChannel, "Rate/2");
- DUMP_FLAG(gsm, "GSM");
- DUMP_FLAG(staticTurbo, "StaticTurbo");
- DUMP_FLAG(gfsk, "GFSK");
- DUMP_FLAG(cckOfdm, "CCKOFDM");
- DUMP_FLAG(passive, "Passive");
- DUMP_FLAG(flag5ghz, "5GHz");
-# undef DUMP_FLAG
+# define FLAG(name, desc) \
+ if (subparser.name()) os << desc " "
+# define END_FLAGS() \
os << '\n';
- }
- DUMP_OPTIONAL_FIELD( fhss, unsigned, "FHSS" );
- DUMP_OPTIONAL_FIELD( dbmAntennaSignal, signed, "antenna signal (dBm)" );
- DUMP_OPTIONAL_FIELD( dbmAntennaNoise, signed, "antenna noise (dBm)" );
- DUMP_OPTIONAL_FIELD( lockQuality, unsigned, "lock quality" );
- DUMP_OPTIONAL_FIELD( txAttenuation, unsigned, "tx attenuation" );
- DUMP_OPTIONAL_FIELD( dbTxAttenuation, unsigned, "tx attenuation (dB)" );
- DUMP_OPTIONAL_FIELD( dbmTxAttenuation, signed, "tx attenuation (dBm)" );
- DUMP_OPTIONAL_FIELD( antenna, unsigned, "antenna" );
- DUMP_OPTIONAL_FIELD( dbAntennaSignal, unsigned, "antenna signal (dB)" );
- DUMP_OPTIONAL_FIELD( dbAntennaNoise, unsigned, "antenna noise (dB)" );
- DUMP_OPTIONAL_FIELD( headerFcs, unsigned, "FCS (in header)" );
+ FIELD ( tsft, boost::uint64_t, "MAC timestamp" );
+ ENTER ( flags );
+ START_FLAGS ( "flags" );
+ FLAG ( shortGI, "ShortGI" );
+ FLAG ( badFCS, "BadFCS" );
+ FLAG ( fcsAtEnd, "FCSatEnd" );
+ FLAG ( fragmentation, "Frag" );
+ FLAG ( wep, "WEP" );
+ FLAG ( shortPreamble, "ShortPreamble" );
+ FLAG ( cfp, "CFP" );
+ END_FLAGS ( );
+ LEAVE ( );
+ FIELD ( rate, unsigned, "rate" );
+ ENTER ( channelOptions );
+ SUBFIELD ( freq, unsigned, "channel frequency" );
+ START_FLAGS ( "channel flags" );
+ FLAG ( flag2ghz, "2GHz" );
+ FLAG ( ofdm, "OFDM" );
+ FLAG ( cck, "CCK" );
+ FLAG ( turbo, "Turbo" );
+ FLAG ( quarterRateChannel, "Rate/4" );
+ FLAG ( halfRateChannel, "Rate/2" );
+ FLAG ( gsm, "GSM" );
+ FLAG ( staticTurbo, "StaticTurbo" );
+ FLAG ( gfsk, "GFSK" );
+ FLAG ( cckOfdm, "CCK+OFDM" );
+ FLAG ( passive, "Passive" );
+ FLAG ( flag5ghz, "5GHz" );
+ END_FLAGS ( );
+ LEAVE ( );
+ FIELD ( fhss, unsigned, "FHSS" );
+ FIELD ( dbmAntennaSignal, signed, "antenna signal (dBm)" );
+ FIELD ( dbmAntennaNoise, signed, "antenna noise (dBm)" );
+ FIELD ( lockQuality, unsigned, "lock quality" );
+ FIELD ( txAttenuation, unsigned, "tx attenuation" );
+ FIELD ( dbTxAttenuation, unsigned, "tx attenuation (dB)" );
+ FIELD ( dbmTxAttenuation, signed, "tx attenuation (dBm)" );
+ FIELD ( antenna, unsigned, "antenna" );
+ FIELD ( dbAntennaSignal, unsigned, "antenna signal (dB)" );
+ FIELD ( dbAntennaNoise, unsigned, "antenna noise (dB)" );
+ ENTER ( rxFlags );
+ START_FLAGS ( "rx flags" );
+ FLAG ( badPlcp, "BadPLCP" );
+ END_FLAGS ( );
+ LEAVE ( );
+ ENTER ( txFlags );
+ START_FLAGS ( "tx flags" );
+ FLAG ( fail, "Fail" );
+ FLAG ( txRts, "RTS" );
+ FLAG ( txCts, "CTS" );
+ END_FLAGS ( );
+ LEAVE ( );
+ FIELD ( rtsRetries, unsigned, "rts retries" );
+ FIELD ( dataRetries, unsigned, "data retries" );
if (p->flagsPresent() && p->flags().fcsAtEnd())
- os << senf::fieldName("FCS (at end)") << unsigned(p->fcs()) << '\n';
+ os << senf::fieldName("fcs") << unsigned(p->fcs()) << '\n';
-# undef DUMP_OPTIONAL_FIELD
+# undef END_FLAGS
+# undef FLAG
+# undef START_FLAGS
+# undef LEAVE
+# undef SUBFIELD
+# undef ENTER
+# undef FIELD
}
{
size_type h (senf::bytes(p.parser()));
size_type t (p->flagsPresent() && p->flags().fcsAtEnd() ? 4 : 0);
- return p.size() < h+t
+ return p.size() <= h+t
? no_range()
: optional_range( range(p.data().begin() + h, p.data().end() - t) );
}
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2010
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief RadiotapPacket inline non-template implementation */
+
+//#include "RadiotapPacket.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::RadiotapPacketParser
+
+prefix_ senf::RadiotapPacketParser::RadiotapPacketParser(data_iterator i, state_type s)
+ : RadiotapPacketParser_Header(i,s)
+{}
+
+prefix_ senf::RadiotapPacketParser::size_type senf::RadiotapPacketParser::bytes()
+ const
+{
+ return calculateSize();
+}
+
+prefix_ senf::UInt32Parser senf::RadiotapPacketParser::fcs()
+{
+ validate(RadiotapPacketParser_Header::fixed_bytes+4);
+ return parse<senf::UInt32Parser>(data().end()-4);
+}
+
+prefix_ bool senf::RadiotapPacketParser::has_fcs()
+{
+ return flagsPresent() && flags().fcsAtEnd();
+}
+
+prefix_ unsigned senf::RadiotapPacketParser::frameType()
+{
+ return parse<RadiotapPacketParser_FrameType>(length()).frameType();
+}
+////////////////////////////////////////
+// private members
+
+prefix_ void senf::RadiotapPacketParser::initField(unsigned index)
+{
+ updatePresentFlags( presentFlags() | (1<<index) );
+}
+
+prefix_ void senf::RadiotapPacketParser::disableField(unsigned index)
+{
+ updatePresentFlags( presentFlags() & ~(1<<index) );
+}
+
+prefix_ senf::RadiotapPacketParser::size_type senf::RadiotapPacketParser::calculateSize()
+ const
+{
+ return currentTable()[MAX_INDEX+1];
+}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2010
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief RadiotapPacket inline template implementation */
+
+//#include "RadiotapPacket.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cti.p///////////////////////////////////////
+
+template <class Parser>
+prefix_ Parser senf::RadiotapPacketParser::parseField(unsigned index)
+{
+ return parse<Parser>(currentTable()[index]);
+}
+
+///////////////////////////////cti.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
SENF_PARSER_BITFIELD ( cfp, 1, bool );
SENF_PARSER_FINALIZE ( RadiotapPacketParser_Flags );
+
+ friend class RadiotapPacketParser;
};
/** \brief Parse in Radiotap Header channel frequency and flag field
SENF_PARSER_BITFIELD ( ofdm, 1, bool );
SENF_PARSER_BITFIELD ( cck, 1, bool );
SENF_PARSER_BITFIELD ( turbo, 1, bool );
- SENF_PARSER_SKIP_BITS ( 4 ); //currently unused in radiotap
+ SENF_PARSER_SKIP_BITS ( 4 );
SENF_PARSER_BITFIELD ( quarterRateChannel, 1, bool );
SENF_PARSER_BITFIELD ( halfRateChannel, 1, bool );
SENF_PARSER_BITFIELD ( gsm, 1, bool );
SENF_PARSER_FINALIZE ( RadiotapPacketParser_ChannelOptions );
};
+ struct RadiotapPacketParser_RxFlags : public PacketParserBase
+ {
+# include SENF_FIXED_PARSER()
+
+ SENF_PARSER_SKIP_BITS ( 6 );
+ SENF_PARSER_BITFIELD ( badPlcp, 1, bool );
+ SENF_PARSER_SKIP_BITS ( 1 );
+
+ SENF_PARSER_FINALIZE( RadiotapPacketParser_RxFlags );
+ };
+
+ struct RadiotapPacketParser_TxFlags : public PacketParserBase
+ {
+# include SENF_FIXED_PARSER()
+
+ SENF_PARSER_SKIP_BITS ( 5 );
+ SENF_PARSER_BITFIELD ( txRts, 1, bool );
+ SENF_PARSER_BITFIELD ( txCts, 1, bool );
+ SENF_PARSER_BITFIELD ( fail, 1, bool );
+
+ SENF_PARSER_FINALIZE( RadiotapPacketParser_TxFlags );
+ };
+
/** \brief Parse an Radiotap header
Parser implementing the Radiotap header
SENF_PARSER_PRIVATE_FIELD ( presentFlags, UInt32LSBParser );
SENF_PARSER_GOTO( presentFlags );
- /*
- * present flags
- * indicate which data field are contained in the packet
- */
+ // present flags indicate which data fields are contained in the packet
+ // BEWARE: LSB-first bit-order !!
+
+ // index: 7 - 0
SENF_PARSER_BITFIELD_RO ( lockQualityPresent, 1, bool );
SENF_PARSER_BITFIELD_RO ( dbmAntennaNoisePresent, 1, bool );
SENF_PARSER_BITFIELD_RO ( dbmAntennaSignalPresent, 1, bool );
SENF_PARSER_BITFIELD_RO ( ratePresent, 1, bool );
SENF_PARSER_BITFIELD_RO ( flagsPresent, 1, bool );
SENF_PARSER_BITFIELD_RO ( tsftPresent, 1, bool );
- SENF_PARSER_SKIP_BITS ( 1 ); //currently unused bits
- SENF_PARSER_BITFIELD_RO ( headerFcsPresent, 1, bool );
+
+ // index: 15 - 8
+ SENF_PARSER_BITFIELD_RO ( txFlagsPresent, 1, bool );
+ SENF_PARSER_BITFIELD_RO ( rxFlagsPresent, 1, bool );
SENF_PARSER_BITFIELD_RO ( dbAntennaNoisePresent, 1, bool );
SENF_PARSER_BITFIELD_RO ( dbAntennaSignalPresent, 1, bool );
SENF_PARSER_BITFIELD_RO ( antennaPresent, 1, bool );
SENF_PARSER_BITFIELD_RO ( dbmTxAttenuationPresent, 1, bool );
SENF_PARSER_BITFIELD_RO ( dbTxAttenuationPresent, 1, bool );
SENF_PARSER_BITFIELD_RO ( txAttenuationPresent, 1, bool );
- SENF_PARSER_SKIP_BITS ( 8 ); //currently unused bits
- //if bit is set,another 32 bit present flag is attached (not implemented yet)
+
+ // index: 23 - 16
+ SENF_PARSER_SKIP_BITS ( 6 );
+ SENF_PARSER_BITFIELD_RO ( dataRetriesPresent, 1, bool );
+ SENF_PARSER_BITFIELD_RO ( rtsRetriesPresent, 1, bool );
+
+ // index: 31 - 24
SENF_PARSER_BITFIELD_RO ( extendedBitmaskPresent, 1, bool );
- SENF_PARSER_SKIP_BITS ( 7 ); //currently unused bits
+ SENF_PARSER_BITFIELD_RO ( vendorNamespacePresent, 1, bool );
+ SENF_PARSER_BITFIELD_RO ( resetRadiotapNamespace, 1, bool )
+ SENF_PARSER_SKIP_BITS ( 5 );
SENF_PARSER_FINALIZE ( RadiotapPacketParser_Header );
+
+ enum PresentIndex {
+ // Could use the the entries from radiotap.h but I don't know,
+ // if I want to pollute the global and macro namespace even more ...
+ TSFT_INDEX = 0,
+ FLAGS_INDEX = 1,
+ RATE_INDEX = 2,
+ CHANNEL_INDEX = 3,
+ FHSS_INDEX = 4,
+ DBM_ANTSIGNAL_INDEX = 5,
+ DBM_ANTNOISE_INDEX = 6,
+ LOCK_QUALITY_INDEX = 7,
+ TX_ATTENUATION_INDEX = 8,
+ DB_TX_ATTENUATION_INDEX = 9,
+ DBM_TX_POWER_INDEX = 10,
+ ANTENNA_INDEX = 11,
+ DB_ANTSIGNAL_INDEX = 12,
+ DB_ANTNOISE_INDEX = 13,
+ RX_FLAGS_INDEX = 14,
+ TX_FLAGS_INDEX = 15,
+ RTS_RETRIES_INDEX = 16,
+ DATA_RETRIES_INDEX = 17,
+
+ MAX_INDEX = 17
+ };
+
+ enum PresentFlag {
+ TSFT_FLAG = (1<<TSFT_INDEX),
+ FLAGS_FLAG = (1<<FLAGS_INDEX),
+ RATE_FLAG = (1<<RATE_INDEX),
+ CHANNEL_FLAG = (1<<CHANNEL_INDEX),
+ FHSS_FLAG = (1<<FHSS_INDEX),
+ DBM_ANTSIGNAL_FLAG = (1<<DBM_ANTSIGNAL_INDEX),
+ DBM_ANTNOISE_FLAG = (1<<DBM_ANTNOISE_INDEX),
+ LOCK_QUALITY_FLAG = (1<<LOCK_QUALITY_INDEX),
+ TX_ATTENUATION_FLAG = (1<<TX_ATTENUATION_INDEX),
+ DB_TX_ATTENUATION_FLAG = (1<<DB_TX_ATTENUATION_INDEX),
+ DBM_TX_POWER_FLAG = (1<<DBM_TX_POWER_INDEX),
+ ANTENNA_FLAG = (1<<ANTENNA_INDEX),
+ DB_ANTSIGNAL_FLAG = (1<<DB_ANTSIGNAL_INDEX),
+ DB_ANTNOISE_FLAG = (1<<DB_ANTNOISE_INDEX),
+ RX_FLAGS_FLAG = (1<<RX_FLAGS_INDEX),
+ TX_FLAGS_FLAG = (1<<TX_FLAGS_INDEX),
+ RTS_RETRIES_FLAG = (1<<RTS_RETRIES_INDEX),
+ DATA_RETRIES_FLAG = (1<<DATA_RETRIES_INDEX)
+ };
+
+ static unsigned const FIELD_SIZE[MAX_INDEX+2];
};
struct RadiotapPacketParser_FrameType : public PacketParserBase
struct RadiotapPacketParser : public RadiotapPacketParser_Header
{
- RadiotapPacketParser(data_iterator i, state_type s) : RadiotapPacketParser_Header(i,s) {}
+ RadiotapPacketParser(data_iterator i, state_type s);
static const size_type init_bytes = RadiotapPacketParser_Header::fixed_bytes;
- size_type bytes() const { return length(); }
+ size_type bytes() const;
// ////////////////////////////////////////////////////////////////////////
- UInt64LSBParser tsft()
- { return parseField<UInt64LSBParser> (0); }
- RadiotapPacketParser_Flags flags()
- { return parseField<RadiotapPacketParser_Flags> (1); }
- UInt8Parser rate()
- { return parseField<UInt8Parser> (2); }
- RadiotapPacketParser_ChannelOptions channelOptions()
- { return parseField<RadiotapPacketParser_ChannelOptions>(3); }
- UInt16LSBParser fhss()
- { return parseField<UInt16LSBParser> (4); }
- Int8Parser dbmAntennaSignal()
- { return parseField<Int8Parser> (5); }
- Int8Parser dbmAntennaNoise()
- { return parseField<Int8Parser> (6); }
- UInt16LSBParser lockQuality()
- { return parseField<UInt16LSBParser> (7); }
- UInt16LSBParser txAttenuation()
- { return parseField<UInt16LSBParser> (8); }
- UInt16LSBParser dbTxAttenuation()
- { return parseField<UInt16LSBParser> (9); }
- Int8Parser dbmTxAttenuation()
- { return parseField<Int8Parser> (10); }
- UInt8Parser antenna()
- { return parseField<UInt8Parser> (11); }
- UInt8Parser dbAntennaSignal()
- { return parseField<UInt8Parser> (12); }
- UInt8Parser dbAntennaNoise()
- { return parseField<UInt8Parser> (13); }
- UInt32Parser headerFcs()
- { return parseField<UInt32Parser> (14); }
-
- unsigned frameType()
- { return parse<RadiotapPacketParser_FrameType>(length()).frameType(); }
-
- UInt32Parser fcs()
- { return parse<senf::UInt32Parser>(data().end()-4); }
+# define FIELD(name,type,index) \
+ typedef type name ## _t; \
+ type name() { return parseField<type>(index); } \
+ bool has_ ## name() { return name ## Present(); } \
+ type init_ ## name() { initField(index); return name(); } \
+ void disable_ ## name() { disableField(index); }
+
+ FIELD( tsft, UInt64LSBParser, TSFT_INDEX );
+
+ // flags is special: disabling 'flags' must also disable the 'fcs' field
+ typedef RadiotapPacketParser_Flags flags_t;
+ flags_t flags() { return parseField<flags_t>(FLAGS_INDEX); }
+ bool has_flags() { return flagsPresent(); }
+ flags_t init_flags() { initField(FLAGS_INDEX); return flags(); }
+ void disable_flags() { disable_fcs(); disableField(FLAGS_INDEX); }
+
+ FIELD( rate, UInt8Parser, RATE_INDEX );
+ FIELD( channelOptions, RadiotapPacketParser_ChannelOptions, CHANNEL_INDEX );
+ FIELD( fhss, UInt16LSBParser, FHSS_INDEX );
+ FIELD( dbmAntennaSignal, Int8Parser, DBM_ANTSIGNAL_INDEX );
+ FIELD( dbmAntennaNoise, Int8Parser, DBM_ANTNOISE_INDEX );
+ FIELD( lockQuality, UInt16LSBParser, LOCK_QUALITY_INDEX );
+ FIELD( txAttenuation, UInt16LSBParser, TX_ATTENUATION_INDEX );
+ FIELD( dbTxAttenuation, UInt16LSBParser, DB_TX_ATTENUATION_INDEX );
+ FIELD( dbmTxAttenuation, Int8Parser, DBM_TX_POWER_INDEX );
+ FIELD( antenna, UInt8Parser, ANTENNA_INDEX );
+ FIELD( dbAntennaSignal, UInt8Parser, DB_ANTSIGNAL_INDEX );
+ FIELD( dbAntennaNoise, UInt8Parser, DB_ANTNOISE_INDEX );
+ FIELD( rxFlags, RadiotapPacketParser_RxFlags, RX_FLAGS_INDEX );
+ FIELD( txFlags, RadiotapPacketParser_TxFlags, TX_FLAGS_INDEX );
+ FIELD( rtsRetries, UInt8Parser, RTS_RETRIES_INDEX );
+ FIELD( dataRetries, UInt8Parser, DATA_RETRIES_INDEX );
+
+# undef FIELD
+
+ typedef UInt32Parser fcs_t;
+ UInt32Parser fcs();
+ bool has_fcs();
+ UInt32Parser init_fcs();
+ void disable_fcs();
+
+ unsigned frameType();
private:
- static const size_type fixed_bytes = 0; // 'remove' this member ...
- static const unsigned MAX_INDEX = 14;
+ static const size_type fixed_bytes = 0; // hide this member, just in case
typedef boost::array<size_type,MAX_INDEX+2> OffsetTable;
- OffsetTable const & offsetTable(boost::uint32_t presentFlags);
- static void fillOffsetTable(boost::uint8_t * data, int maxLength, OffsetTable & table);
+ ///////////////////////////////////////////////////////////////////////////
+ // Offset table handling
+
+ static OffsetTable & offsetTable(boost::uint32_t presentFlags);
+ // Fills the offset table based on a packet
+ static void parseOffsetTable(boost::uint8_t * data, int maxLength, OffsetTable & table);
+ // Generate an offset table just from the present flags
+ static void buildOffsetTable(boost::uint32_t presentFlags, OffsetTable & table);
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ OffsetTable const & currentTable() const;
+ OffsetTable const & getTable(boost::uint32_t presentFlags) const;
template <class Parser>
- Parser parseField(unsigned index)
- { return parse<Parser>(offsetTable(presentFlags())[index]); }
+ Parser parseField(unsigned index);
+ void initField(unsigned index);
+ void disableField(unsigned index);
+
+ size_type calculateSize() const;
- size_type calculateSize()
- { return offsetTable(presentFlags())[MAX_INDEX+1]; }
+ void updatePresentFlags(boost::uint32_t flags);
+ void insertRemoveBytes(unsigned from, unsigned to, int bytes);
friend class RadiotapPacketType;
};
}
///////////////////////////////hh.e////////////////////////////////////////
-//#include "RadiotapPacket.cci"
+#include "RadiotapPacket.cci"
//#include "RadiotapPacket.ct"
-//#include "RadiotapPacket.cti"
+#include "RadiotapPacket.cti"
#endif
\f
#include <boost/test/test_tools.hpp>
///////////////////////////////cc.p////////////////////////////////////////
+
+SENF_AUTO_UNIT_TEST(RadiotapPacket_fieldSizes)
+{
+ // This test only asserts, that nobody forgot to update the FIELD_SIZE table
+ // when chaning MAX_INDEX
+ BOOST_CHECK( senf::RadiotapPacketParser_Header::FIELD_SIZE[
+ senf::RadiotapPacketParser_Header::MAX_INDEX] != 0 );
+}
+
SENF_AUTO_UNIT_TEST(RadiotapPacket_packet)
{
/* used madwifi 0.9.4 */
" antenna noise (dBm) : -96\n"
" antenna : 2\n"
" antenna signal (dB) : 35\n"
- " FCS (at end) : 0\n" );
+ " fcs : 0\n" );
}
-#if 0
SENF_AUTO_UNIT_TEST(RadiotapPacket_create)
{
- unsigned char data[] = {
- 0x00 ,0x00 ,0x1a ,0x00, 0x6f, 0x18, 0x00, 0x00,
- 0x02, 0xe6, 0x8a, 0xdf, 0x12, 0x00, 0x00, 0x00,
- 0x02, 0x0c, 0xc8, 0x14, 0x40, 0x01, 0xc3, 0xa0,
- 0x02, 0x23
- };
-
senf::RadiotapPacket p (senf::RadiotapPacket::create());
- SENF_CHECK_NO_THROW( p->init_tsft());
- SENF_CHECK_NO_THROW( p->tsft()=81059833346uLL);
+ BOOST_CHECK_EQUAL( p.size(), senf::RadiotapPacketParser_Header::fixed_bytes+0 );
- SENF_CHECK_NO_THROW( p->init_rate());
- SENF_CHECK_NO_THROW( p->rate() = 12u);
- SENF_CHECK_NO_THROW( p->init_dbmAntennaSignal());
- SENF_CHECK_NO_THROW( p->dbmAntennaSignal() = -61);
- SENF_CHECK_NO_THROW( p->init_dbmAntennaNoise());
- SENF_CHECK_NO_THROW( p->dbmAntennaNoise() = -96);
- SENF_CHECK_NO_THROW( p->init_antenna());
- SENF_CHECK_NO_THROW( p->antenna() = 2u);
- SENF_CHECK_NO_THROW( p->init_dbAntennaSignal());
- SENF_CHECK_NO_THROW( p->dbAntennaSignal() = 35);
+ SENF_CHECK_NO_THROW( p->init_tsft() = 81059833346uLL );
+ SENF_CHECK_NO_THROW( p->init_rate() = 12u );
+ SENF_CHECK_NO_THROW( p->init_dbmAntennaSignal() = -61 );
+ SENF_CHECK_NO_THROW( p->init_dbmAntennaNoise() = -96 );
+ SENF_CHECK_NO_THROW( p->init_antenna() = 2u );
+ SENF_CHECK_NO_THROW( p->init_dbAntennaSignal() = 35 );
SENF_CHECK_NO_THROW( p->init_flags());
- SENF_CHECK_NO_THROW( p->flags().cfp() = false);
SENF_CHECK_NO_THROW( p->flags().shortPreamble() = true);
- SENF_CHECK_NO_THROW( p->flags().wep() = false);
- SENF_CHECK_NO_THROW( p->flags().fragmentation() = false);
- // SENF_CHECK_NO_THROW( p->flags().fcsAtEnd() = true);
- SENF_CHECK_NO_THROW( p->flags().padding() = false);
- SENF_CHECK_NO_THROW( p->flags().badFCS() = false);
- SENF_CHECK_NO_THROW( p->flags().shortGI() = false);
SENF_CHECK_NO_THROW( p->init_channelOptions());
SENF_CHECK_NO_THROW( p->channelOptions().freq() = 5320u)
SENF_CHECK_NO_THROW( p->channelOptions().ofdm() = true);
- SENF_CHECK_NO_THROW( p->channelOptions().turbo() = false);
- SENF_CHECK_NO_THROW( p->channelOptions().cck() = false);
SENF_CHECK_NO_THROW( p->channelOptions().flag5ghz() = true);
- SENF_CHECK_NO_THROW( p->channelOptions().passive() = false);
- SENF_CHECK_NO_THROW( p->channelOptions().cckOfdm() = false);
- SENF_CHECK_NO_THROW( p->channelOptions().gfsk() = false);
- SENF_CHECK_NO_THROW( p->channelOptions().gsm() = false);
- SENF_CHECK_NO_THROW( p->channelOptions().staticTurbo() = false);
- SENF_CHECK_NO_THROW( p->channelOptions().halfRateChannel() = false);
- SENF_CHECK_NO_THROW( p->channelOptions().quarterRateChannel() = false);
+
+ SENF_CHECK_NO_THROW( p->init_fcs() );
p.finalizeAll();
BOOST_CHECK_EQUAL( p->length(), 26u );
- BOOST_CHECK_EQUAL_COLLECTIONS( p.data().begin(), p.data().end(),
- data, data+sizeof(data)/sizeof(data[0]) );
+ BOOST_CHECK_EQUAL( p.size(), 30u );
+
+ std::stringstream ss;
+ p.dump(ss);
+ BOOST_CHECK_EQUAL( ss.str(),
+ "Radiotap:\n"
+ " version : 0\n"
+ " length : 26\n"
+ " MAC timestamp : 81059833346\n"
+ " flags : FCSatEnd ShortPreamble \n"
+ " rate : 12\n"
+ " channel frequency : 5320\n"
+ " channel flags : OFDM 5GHz \n"
+ " antenna signal (dBm) : -61\n"
+ " antenna noise (dBm) : -96\n"
+ " antenna : 2\n"
+ " antenna signal (dB) : 35\n"
+ " fcs : 0\n" );
+
+ {
+ unsigned char data[] = {
+ /* 0 */ 0x00, // version
+ /* */ 0x00,
+ /* 2 */ 0x1a, 0x00, // length
+ /* 4 */ 0x6f, 0x18, 0x00, 0x00, // presentFlags
+ /* 8 */ 0x02, 0xe6, 0x8a, 0xdf, 0x12, 0x00, 0x00, 0x00, // tsft
+ /* 16 */ 0x12, // flags
+ /* 17 */ 0x0c, // rate
+ /* 18 */ 0xc8, 0x14, // channel frequency
+ /* 20 */ 0x40, 0x01, // channel flags
+ /* 22 */ 0xc3, // dbmAntennaSignal
+ /* 23 */ 0xa0, // dbmAntennaNoise
+ /* 24 */ 0x02, // antenna
+ /* 25 */ 0x23, // dbAntennaSignal
+ /* 26 */ 0x0, 0x0, 0x0, 0x0 // FCS
+ };
+
+ BOOST_CHECK_EQUAL_COLLECTIONS( p.data().begin(), p.data().end(),
+ data, data+sizeof(data)/sizeof(data[0]) );
+ }
+
+ SENF_CHECK_NO_THROW( p->disable_flags() );
+ SENF_CHECK_NO_THROW( p->disable_dbmAntennaSignal() );
+
+ p.finalizeAll();
+
+ {
+ unsigned char data[] = {
+ /* 0 */ 0x00, // version
+ /* */ 0x00,
+ /* 2 */ 0x19, 0x00, // length
+ /* 4 */ 0x4d, 0x18, 0x00, 0x00, // presentFlags
+ /* 8 */ 0x02, 0xe6, 0x8a, 0xdf, 0x12, 0x00, 0x00, 0x00, // tsft
+ /* 16 */ 0x0c, // rate
+ /* */ 0x00,
+ /* 18 */ 0xc8, 0x14, // channel frequency
+ /* 20 */ 0x40, 0x01, // channel flags
+ /* 22 */ 0xa0, // dbmAntennaNoise
+ /* 23 */ 0x02, // antenna
+ /* 24 */ 0x23 // dbAntennaSignal
+ };
+ BOOST_CHECK_EQUAL_COLLECTIONS( p.data().begin(), p.data().end(),
+ data, data+sizeof(data)/sizeof(data[0]) );
+ }
}
-#endif
SENF_AUTO_UNIT_TEST(RadiotapPacket_packet_ath9k)
{