Packets/80211Bundle: fix problems with dynamic padding due to byte alignment in Radio...
cni [Tue, 9 Dec 2008 16:28:24 +0000 (16:28 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1009 270642c3-0616-0410-b53a-bc976706d245

Packets/80211Bundle/RadiotapPacket.cc
Packets/80211Bundle/RadiotapPacket.hh
Packets/80211Bundle/RadiotapPacket.test.cc

index 22cd2a9..a67514c 100644 (file)
@@ -24,6 +24,7 @@
 
 // Custom includes
 #include "RadiotapPacket.hh"
+#include "WLANPacket.hh"
 #include "../../Packets/Packets.hh"
 #include <boost/io/ios_state.hpp>
 
 prefix_ void senf::RadiotapPacketType::dump(packet p, std::ostream &os)
 {
     boost::io::ios_all_saver ias(os);
-    os         << "Radiotap:\n"
-        << "  Version                  : " << p->version() << "\n"
-        << "  Length                   : " << p->length() << "\n";
+    os             << "Radiotap:\n"
+            << "  Version             : " << unsigned (p->version()) << "\n"
+            << "  Length              : " << unsigned (p->length()) << "\n";
+    if (p->has_dbmAntennaSignal())
+        os  << "  Signal              : " << signed (p-> dbmAntennaSignal()) << "\n";
+    if (p->has_tsft())
+        os  << "  MAC timestamp       : " << unsigned (p->tsft()) << "\n";
+    if (p->has_dbmAntennaNoise())
+        os  << "  Noise               : " << signed (p-> dbmAntennaNoise()) << "\n";
+
+
+
 }
 
 prefix_ void senf::RadiotapPacketType::finalize(packet p)
 {
+    //TODO
     p->length() << p.size();
 }
 
+prefix_ senf::PacketInterpreterBase::factory_t senf::RadiotapPacketType::nextPacketType(packet p)
+{
+    return WLANPacket::factory();
+}
+
 
 #undef prefix_
index 48d020b..ea6eee4 100644 (file)
@@ -35,6 +35,7 @@ namespace senf
 
     /** \brief Parse Flag field in Radiotap header
      * <b>Re-ordering of bits due to LSB byte order</b>
+     * (see http://www.radiotap.org/)
 
      */
     struct RadiotapPacketParser_Flags : public senf::PacketParserBase
@@ -84,6 +85,15 @@ namespace senf
 
         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)
@@ -112,7 +122,8 @@ namespace senf
         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   ( 2                                ); //currently unused bits
+        SENF_PARSER_SKIP_BITS   ( 1                                ); //currently unused bits
+        SENF_PARSER_BITFIELD_RO ( fcsPresent,              1, bool );
         SENF_PARSER_BITFIELD_RO ( dbAntennaNoisePresent,   1, bool );
         SENF_PARSER_BITFIELD_RO ( dbAntennaSignalPresent,  1, bool );
         SENF_PARSER_BITFIELD_RO ( antennaPresent,          1, bool );
@@ -127,24 +138,43 @@ namespace senf
         /*
          * 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           )) );
 
+        /*  */
+        #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          );
         OPTIONAL_FIELD ( rate,             UInt8Parser                         );
-        OPTIONAL_FIELD ( channelOptions,   RadiotapPacketParser_ChannelOptions );
+        SKIP_OPTIONAL_PADDING(channelOptionsPresent(), rate, 2);
+        OPTIONAL_FIELD ( channelOptions,   RadiotapPacketParser_ChannelOptions ) ;
+        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(fcsPresent(), dbAntennaNoise, 4)
+        OPTIONAL_FIELD ( fcs,              UInt32Parser                        );
 
         SENF_PARSER_INIT() {
             version() = 0;
@@ -177,6 +207,8 @@ namespace senf
 
         static void dump(packet p, std::ostream &os);
         static void finalize(packet p);
+        static factory_t nextPacketType(packet p);
+
     };
 
     typedef senf::ConcretePacket<RadiotapPacketType> RadiotapPacket;
index f304f02..b94efc4 100644 (file)
@@ -148,3 +148,25 @@ BOOST_AUTO_UNIT_TEST(RadiotapPacket_create)
     BOOST_CHECK_EQUAL( p->length(), 26u );
     BOOST_CHECK( equal( p.data().begin(), p.data().end(), data ));
 }
+
+BOOST_AUTO_UNIT_TEST(RadiotapPacket_packet_ath9k)
+{
+    /* radiotap packet from ath9k with atheros card*/
+    unsigned char data[] = {
+            0x00, 0x00, 0x20, 0x00, 0x6f, 0x48, 0x00, 0x00, 0x87, 0xbb, 0x91, 0x7c, 0x3b, 0x00, 0x00, 0x00,
+            0x00, 0x04, 0x85, 0x09, 0x80, 0x04, 0xb2, 0xa1, 0x00, 0x00, 0x00, 0x00, 0xd5, 0x1a, 0xf7, 0x94
+    };
+    senf::RadiotapPacket p (senf::RadiotapPacket::create(data));
+
+    /* mandatory fields*/
+    BOOST_CHECK_EQUAL( p->version(), 0u);
+    BOOST_CHECK_EQUAL( p->length(), 32u);
+
+    BOOST_CHECK_EQUAL( p->dbmAntennaSignal(), -78);
+    BOOST_CHECK_EQUAL( p->dbmAntennaNoise(), -95);
+    BOOST_CHECK_EQUAL( p->fcs(), 0xd51af794);
+    BOOST_CHECK_EQUAL( p->antenna(), 0u);
+
+
+}
+