Move sourcecode into 'senf/' directory
[senf.git] / senf / Packets / 80211Bundle / RadiotapPacket.hh
diff --git a/senf/Packets/80211Bundle/RadiotapPacket.hh b/senf/Packets/80211Bundle/RadiotapPacket.hh
new file mode 100644 (file)
index 0000000..c6fe53c
--- /dev/null
@@ -0,0 +1,247 @@
+// $Id$
+//
+// Copyright (C) 2008
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Christian Niephaus <cni@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 Radiotap header */
+
+#ifndef HH_SENF_Packets_80211Bundle_RadiotapPacket_
+#define HH_SENF_Packets_80211Bundle_RadiotapPacket_ 1
+
+#include "../../Packets/Packets.hh"
+
+namespace senf
+{
+
+    /** \brief Parse Flag field in Radiotap header
+
+        <b>Re-ordering of bits due to LSB byte order</b>
+     */
+    struct RadiotapPacketParser_Flags : public PacketParserBase
+    {
+    #   include SENF_FIXED_PARSER()
+
+        SENF_PARSER_BITFIELD ( shortGI,        1, bool );
+        SENF_PARSER_BITFIELD ( badFCS,         1, bool );
+        SENF_PARSER_BITFIELD ( padding,        1, bool );
+        SENF_PARSER_BITFIELD_RO ( fcsAtEnd,    1, bool ); // Cannot change this (change packet size)
+        SENF_PARSER_BITFIELD ( fragmentation,  1, bool );
+        SENF_PARSER_BITFIELD ( wep,            1, bool );
+        SENF_PARSER_BITFIELD ( shortPreamble,  1, bool );
+        SENF_PARSER_BITFIELD ( cfp,            1, bool );
+
+        SENF_PARSER_FINALIZE ( RadiotapPacketParser_Flags );
+    };
+
+    /** \brief Parse in Radiotap Header channel frequency and flag field
+
+        <b>Re-ordering of bits due to LSB byte order</b>
+     */
+    struct RadiotapPacketParser_ChannelOptions : public PacketParserBase
+    {
+    #   include SENF_FIXED_PARSER()
+
+        SENF_PARSER_FIELD     ( freq,          UInt16LSBParser );
+
+        SENF_PARSER_BITFIELD  ( flag2ghz,             1, bool  );
+        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_BITFIELD  ( quarterRateChannel,   1, bool  );
+        SENF_PARSER_BITFIELD  ( halfRateChannel,      1, bool  );
+        SENF_PARSER_BITFIELD  ( gsm,                  1, bool  );
+        SENF_PARSER_BITFIELD  ( staticTurbo,          1, bool  );
+        SENF_PARSER_BITFIELD  ( gfsk,                 1, bool  );
+        SENF_PARSER_BITFIELD  ( cckOfdm,              1, bool  );
+        SENF_PARSER_BITFIELD  ( passive,              1, bool  );
+        SENF_PARSER_BITFIELD  ( flag5ghz,             1, bool  );
+
+        SENF_PARSER_FINALIZE ( RadiotapPacketParser_ChannelOptions );
+    };
+
+    /** \brief Parse an Radiotap header
+
+        Parser implementing the Radiotap header
+
+        Radiotap requires that all fields in the radiotap header
+        are aligned to natural boundaries. For radiotap,
+        that means all 8-, 16-, 32-, and 64-bit fields
+        must begin on 8-, 16-, 32-, and 64-bit boundaries, respectively.
+        In this way, generators and parsers can avoid unaligned
+        accesses to radiotap capture fields. Radiotap-compliant
+        generators must insert padding before a capture field
+        to ensure its natural alignment.
+
+        \see <a href="http://www.radiotap.org">Radiotap.org</a>
+
+        \todo extended present field (bit 31 of present field is set)
+    */
+    struct RadiotapPacketParser : public PacketParserBase
+    {
+    #   include SENF_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_FIELD ( length,  UInt16LSBParser );
+
+        /*
+         * present flags
+         * indicate which data field are contained in the packet
+         */
+        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 ( fhssPresent,             1, bool );
+        SENF_PARSER_BITFIELD_RO ( channelOptionsPresent,   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 );
+        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)
+        SENF_PARSER_BITFIELD    ( extendedBitmaskPresent,  1, bool );
+        SENF_PARSER_SKIP_BITS   ( 7                                ); //currently unused bits
+
+        SENF_PARSER_LABEL( headerEnd_ );
+
+        /*
+         * Radiotap data
+         * parsing data according to present flags
+         *
+         * PARSER_SKIP required to skip correct length of padding bits
+         */
+
+        /* 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 );
+            
+    };
+
+    /** \brief Radiotap packet
+
+        \par Packet type (typedef):
+            \ref RadiotapPacket
+
+        \par Fields:
+            \ref RadiotapPacketParser
+            \image html RadiotapPacket.png
+        
+        \see http://www.radiotap.org/
+        
+        \ingroup protocolbundle_80211
+     */
+    struct RadiotapPacketType
+        : public PacketTypeBase,
+          public PacketTypeMixin<RadiotapPacketType>
+    {
+        typedef PacketTypeMixin<RadiotapPacketType> mixin;
+        typedef ConcretePacket<RadiotapPacketType> packet;
+        typedef RadiotapPacketParser parser;
+
+        using mixin::init;
+        using mixin::initSize;
+
+        static void dump(packet p, std::ostream &os);
+        static void finalize(packet p);
+        static factory_t nextPacketType(packet p);
+        static optional_range nextPacketRange(packet p);
+    };
+
+    typedef ConcretePacket<RadiotapPacketType> RadiotapPacket;
+}
+
+#endif
+
+\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: