// Custom includes
#include <senf/Packets/Packets.hh>
+#include <boost/array.hpp>
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
*/
struct RadiotapPacketParser_Flags : public PacketParserBase
{
- # include SENF_FIXED_PARSER()
+# include SENF_FIXED_PARSER()
SENF_PARSER_BITFIELD ( shortGI, 1, bool );
SENF_PARSER_BITFIELD ( badFCS, 1, bool );
*/
struct RadiotapPacketParser_ChannelOptions : public PacketParserBase
{
- # include SENF_FIXED_PARSER()
+# include SENF_FIXED_PARSER()
SENF_PARSER_FIELD ( freq, UInt16LSBParser );
\todo extended present field (bit 31 of present field is set)
*/
- struct RadiotapPacketParser : public PacketParserBase
+ struct RadiotapPacketParser_Header : public PacketParserBase
{
- # include SENF_PARSER()
+# include SENF_FIXED_PARSER()
/*
* mandatory fields
*/
SENF_PARSER_FIELD ( version, UInt8Parser );
//padding bits, currently unused, it simply aligns the fields onto natural word boundaries.
- SENF_PARSER_SKIP ( 1,1 );
+ SENF_PARSER_SKIP ( 1 );
SENF_PARSER_FIELD ( length, UInt16LSBParser );
+ SENF_PARSER_PRIVATE_FIELD ( presentFlags, UInt32LSBParser );
+ SENF_PARSER_GOTO( presentFlags );
+
/*
* present flags
* indicate which data field are contained in the packet
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)
- SENF_PARSER_BITFIELD ( extendedBitmaskPresent, 1, bool );
+ SENF_PARSER_BITFIELD_RO ( extendedBitmaskPresent, 1, bool );
SENF_PARSER_SKIP_BITS ( 7 ); //currently unused bits
- SENF_PARSER_LABEL( headerEnd_ );
+ SENF_PARSER_FINALIZE ( RadiotapPacketParser_Header );
+ };
- /*
- * Radiotap data
- * parsing data according to present flags
- *
- * PARSER_SKIP required to skip correct length of padding bits
- */
+ struct RadiotapPacketParser_FrameType : public PacketParserBase
+ {
+# include SENF_FIXED_PARSER()
- /* macro to create required variant parser */
- #define OPTIONAL_FIELD(name, parser) SENF_PARSER_VARIANT \
- ( name##_, name##Present, \
- ( novalue( disable_##name, VoidPacketParser )) \
- ( id( name, parser )) )
-
- /* macro to create padding parser */
- #define SKIP_OPTIONAL_PADDING(cond, parser, size) \
- SENF_PARSER_SKIP( \
- (cond ? (size - (parser##__offset() + \
- senf::bytes(parser##_())) % size) % size : 0) , 0 );
-
- OPTIONAL_FIELD ( tsft, UInt64LSBParser );
- OPTIONAL_FIELD ( flags, RadiotapPacketParser_Flags ); //<pkgdraw: size=8
- OPTIONAL_FIELD ( rate, UInt8Parser );
- SKIP_OPTIONAL_PADDING ( channelOptionsPresent(), rate, 2 );
- OPTIONAL_FIELD ( channelOptions, RadiotapPacketParser_ChannelOptions ); //<pkgdraw: size=32
- SKIP_OPTIONAL_PADDING ( fhssPresent(), channelOptions, 2 );
- OPTIONAL_FIELD ( fhss, UInt16LSBParser );
- OPTIONAL_FIELD ( dbmAntennaSignal, Int8Parser );
- OPTIONAL_FIELD ( dbmAntennaNoise, Int8Parser );
- SKIP_OPTIONAL_PADDING ( lockQualityPresent(), dbmAntennaNoise, 2 );
- OPTIONAL_FIELD ( lockQuality, UInt16LSBParser );
- SKIP_OPTIONAL_PADDING ( txAttenuationPresent(), lockQuality, 2 );
- OPTIONAL_FIELD ( txAttenuation, UInt16LSBParser );
- SKIP_OPTIONAL_PADDING ( dbTxAttenuationPresent(), txAttenuation, 2 );
- OPTIONAL_FIELD ( dbTxAttenuation, UInt16LSBParser );
- OPTIONAL_FIELD ( dbmTxAttenuation, Int8Parser );
- OPTIONAL_FIELD ( antenna, UInt8Parser );
- OPTIONAL_FIELD ( dbAntennaSignal, UInt8Parser );
- OPTIONAL_FIELD ( dbAntennaNoise, UInt8Parser );
- SKIP_OPTIONAL_PADDING ( headerFcsPresent(), dbAntennaNoise, 4 );
- OPTIONAL_FIELD ( headerFcs, UInt32Parser );
-
- SENF_PARSER_LABEL( packetEnd_ );
-
- size_type calculateSize() { return packetEnd__offset(); }
-
- // Ouch ... changing the flags().fcsAtEnd() field needs to resize the packet ... !!!
- // Need to think, if I can do this with a variant parser ...
- SENF_PARSER_CUSTOM_FIELD( fcs, senf::UInt32Parser, 0, 0 ) {
- return parse<senf::UInt32Parser>(data().end()-4);
- }
-
- SENF_PARSER_INIT() {
- version() = 0;
- }
-
- // The headers length is to be taken from the 'length' value
- SENF_PARSER_GOTO_OFFSET( length(), headerEnd__init_bytes );
-
- SENF_PARSER_FINALIZE( RadiotapPacketParser );
-
- SENF_PARSER_SKIP_BITS( 4 );
- SENF_PARSER_BITFIELD_RO ( frameType, 2, unsigned );
- SENF_PARSER_SKIP_BITS( 2 );
+ SENF_PARSER_SKIP_BITS(4);
+ SENF_PARSER_BITFIELD_RO( frameType, 2, unsigned );
+ SENF_PARSER_SKIP_BITS(2);
+
+ SENF_PARSER_FINALIZE(RadiotapPacketParser_FrameType);
+ };
+
+ struct RadiotapPacketParser : public RadiotapPacketParser_Header
+ {
+ RadiotapPacketParser(data_iterator i, state_type s) : RadiotapPacketParser_Header(i,s) {}
+
+ static const size_type init_bytes = RadiotapPacketParser_Header::fixed_bytes;
+
+ size_type bytes() const { return length(); }
+
+ // ////////////////////////////////////////////////////////////////////////
+
+ 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); }
+
+ private:
+ static const size_type fixed_bytes = 0; // 'remove' this member ...
+ static const unsigned MAX_INDEX = 14;
+
+ 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);
+
+ template <class Parser>
+ Parser parseField(unsigned index)
+ { return parse<Parser>(offsetTable(presentFlags())[index]); }
+
+ size_type calculateSize()
+ { return offsetTable(presentFlags())[MAX_INDEX+1]; }
+
+ friend class RadiotapPacketType;
};
/** \brief Radiotap packet