Search:

SENF Extensible Network Framework

  • Home
  • Download
  • Wiki
  • BerliOS
  • ChangeLog
  • Browse SVN
  • Bug Tracker
  • Overview
  • Examples
  • HowTos
  • Glossary
  • PPI
  • Packets
  • Scheduler
  • Socket
  • Utils
  • Console
  • Daemon
  • Logger
  • Termlib
  • Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

80211Bundle/RadiotapPacket.cc

Go to the documentation of this file.
00001 // $Id: RadiotapPacket.cc 1772 2011-03-10 12:45:21Z tho $
00002 //
00003 // Copyright (C) 2008
00004 // Fraunhofer (FOKUS)
00005 // Competence Center NETwork research (NET), St. Augustin, GERMANY
00006 //     Christian Niephaus <cni@berlios.de>
00007 //     Stefan Bund <g0dil@berlios.de>
00008 //
00009 // This program is free software; you can redistribute it and/or modify
00010 // it under the terms of the GNU General Public License as published by
00011 // the Free Software Foundation; either version 2 of the License, or
00012 // (at your option) any later version.
00013 //
00014 // This program is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU General Public License
00020 // along with this program; if not, write to the
00021 // Free Software Foundation, Inc.,
00022 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 
00024 // Definition of RadiotapPacket non-inline non-template functions
00025 
00026 #include "RadiotapPacket.hh"
00027 //#include "RadiotapPacket.ih"
00028 
00029 // Custom includes
00030 #include "WLANPacket.hh"
00031 #include <boost/io/ios_state.hpp>
00032 #include <memory.h>
00033 
00034 extern "C" {
00035 #   include "radiotap/radiotap_iter.h"
00036 }
00037 
00038 #define prefix_
00039 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00040 
00041 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00042 // Offset table management
00043 
00044 prefix_ senf::RadiotapPacketParser::OffsetTable &
00045 senf::RadiotapPacketParser::offsetTable(boost::uint32_t presentFlags)
00046 {
00047     typedef std::map<boost::uint32_t, OffsetTable> OffsetMap;
00048     static OffsetMap offsetMap;
00049 
00050     OffsetMap::iterator i (offsetMap.find(presentFlags));
00051     if (i == offsetMap.end())
00052         i = offsetMap.insert(std::make_pair(presentFlags, OffsetTable())).first;
00053     return i->second;
00054 }
00055 
00056 prefix_ void senf::RadiotapPacketParser::parseOffsetTable(boost::uint8_t * data, int maxLength,
00057                                                           OffsetTable & table)
00058 {
00059     struct ieee80211_radiotap_iterator iter;
00060     ieee80211_radiotap_iterator_init(&iter,
00061                                      (struct ieee80211_radiotap_header *)data,
00062                                      maxLength,
00063                                      0);
00064     unsigned size (8u);
00065     while (ieee80211_radiotap_iterator_next(&iter) == 0) {
00066         if (iter.is_radiotap_ns &&
00067             iter.this_arg_index <= int(RadiotapPacketParser::MAX_INDEX))
00068             table[iter.this_arg_index] = iter.this_arg - data;
00069         // We need to set size here in the loop since the iter fields are only valid
00070         // when at least one present bit is set ...
00071         size = iter.this_arg - data + iter.this_arg_size;
00072     }
00073     table[MAX_INDEX+1] = size;
00074 }
00075 
00076 prefix_ void senf::RadiotapPacketParser::buildOffsetTable(boost::uint32_t presentFlags,
00077                                                           OffsetTable & table)
00078 {
00079     SENF_ASSERT(!(presentFlags & ( (1<<IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE) |
00080                                    (1<<IEEE80211_RADIOTAP_VENDOR_NAMESPACE) |
00081                                    (1<<IEEE80211_RADIOTAP_EXT) )),
00082                 "Extended or vendor fields not supported");
00083 
00084     struct ieee80211_radiotap_header header;
00085     memset(&header, 0, sizeof(header));
00086     // header.it_version = 0;
00087 
00088     // Iterating this packet will generate invalid addresses but we don't care since neither
00089     // radiotap.c nor we will ever dereference those pointers, we just calculate the offsets.
00090     // This works, as long as we don't support extension headers ...
00091     header.it_len = 0xFFFF;
00092     header.it_present = presentFlags;
00093 
00094     parseOffsetTable((boost::uint8_t*)&header, header.it_len, table);
00095 }
00096 
00097 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00098 // senf::RadiotapPacketParser
00099 
00100 unsigned const senf::RadiotapPacketParser_Header::FIELD_SIZE[] = {
00101     8, 1, 1, 4, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1 };
00102 
00103 prefix_ senf::UInt32Parser senf::RadiotapPacketParser::init_fcs()
00104 {
00105     if (!has_fcs()) {
00106         protect(), data().insert(data().end(), 4u, 0u);
00107         init_flags().fcsAtEnd_() = true;
00108     }
00109     return fcs();
00110 }
00111 
00112 prefix_ void senf::RadiotapPacketParser::disable_fcs()
00113 {
00114     if (has_fcs()) {
00115         validate(RadiotapPacketParser_Header::fixed_bytes+4);
00116         data().erase(data().end()-4, data().end());
00117         flags().fcsAtEnd_() = false;
00118     }
00119 }
00120 
00121 prefix_ senf::RadiotapPacketParser::OffsetTable const &
00122 senf::RadiotapPacketParser::getTable(boost::uint32_t presentFlags)
00123     const
00124 {
00125     OffsetTable & table(offsetTable(presentFlags));
00126     if (! table[MAX_INDEX+1])
00127         buildOffsetTable(presentFlags, table);
00128     return table;
00129 }
00130 
00131 prefix_ void senf::RadiotapPacketParser::insertRemoveBytes(unsigned from , unsigned to, int bytes)
00132 {
00133     data_iterator b (i() + from);
00134     data_iterator e (i() + to);
00135     if (bytes >= 0) {
00136         // Insert some bytes cleaning the old bytes to 0 first
00137         std::fill(b, e,  0u);
00138         if (bytes > 0)
00139             // need to protect the parser since data().insert() invalidates iterators
00140             protect(), data().insert(e, bytes, 0u);
00141     }
00142     else { // bytes < 0
00143         // Remove some bytes ...
00144         // remember: bytes is negative ...
00145         if (b < e + bytes)
00146             std::fill(b, e + bytes, 0u);
00147         data().erase(e + bytes, e);
00148     }
00149 }
00150 
00151 prefix_ void senf::RadiotapPacketParser::updatePresentFlags(boost::uint32_t flags)
00152 {
00153     if (flags == presentFlags())
00154         return;
00155     validate(bytes());
00156 
00157     OffsetTable const & oldTable (currentTable());
00158     OffsetTable const & newTable (getTable(flags));
00159     unsigned b (RadiotapPacketParser_Header::fixed_bytes);
00160     int cumulativeNewBytes (0);
00161 
00162     for (unsigned index (0); index <= MAX_INDEX; ++index) {
00163         // Skip any unchanged fields
00164         for (; index <= MAX_INDEX+1
00165                  && ((oldTable[index] == 0 && newTable[index] == 0)
00166                      || (oldTable[index]+cumulativeNewBytes == newTable[index])); ++index)
00167             if (newTable[index] != 0)
00168                 b = newTable[index] + FIELD_SIZE[index];
00169         if (index > MAX_INDEX+1)
00170             break;
00171         // Now skip over all changed fields
00172         // (The condition index <= MAX_INDEX is not needed here since the last
00173         // table entry MAX_INDEX+1 is always != 0 in both tables)
00174         for (; ! (oldTable[index]!=0 && newTable[index]!=0); ++index) ;
00175         // index now either points to
00176         // a) an entry set in both tables
00177         // b) at the end of the table which contains the total length
00178         // (remember: the table has a size of MAX_INDEX+2 entries !!)
00179         // in both cases, the difference between the new and old size
00180         // is found from the difference between the old and the new table
00181         // entry
00182         int newBytes (newTable[index] - oldTable[index] - cumulativeNewBytes);
00183         insertRemoveBytes(b, oldTable[index] + cumulativeNewBytes, newBytes);
00184         cumulativeNewBytes += newBytes;
00185         b = newTable[index] + FIELD_SIZE[index];
00186     }
00187     length() += cumulativeNewBytes;
00188     presentFlags() = flags;
00189     currentTable_ = &newTable;
00190 }
00191 
00192 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00193 // senf::RadiotapPacketType
00194 
00195 prefix_ void senf::RadiotapPacketType::dump(packet p, std::ostream & os)
00196 {
00197     boost::io::ios_all_saver ias(os);
00198     os << "Radiotap:\n"
00199        << senf::fieldName("version") << unsigned(p->version()) << '\n'
00200        << senf::fieldName("length")  << unsigned(p->length()) << '\n';
00201 
00202 #   define FIELD(name, sign, desc)                                      \
00203         if (p->name ## Present())                                       \
00204             os << senf::fieldName(desc) << sign(p->name()) << '\n';
00205 
00206 #   define ENTER(name)                                                  \
00207         if (p->name ## Present()) {                                     \
00208             packet::Parser::name ## _t subparser (p->name());
00209 
00210 #   define SUBFIELD(name, sign, desc)                                   \
00211         os << senf::fieldName(desc) << sign(subparser.name()) << '\n';
00212 
00213 #   define LEAVE()                                                      \
00214         }
00215 
00216 #   define START_FLAGS(desc)                                            \
00217         os << senf::fieldName(desc);
00218 
00219 #   define FLAG(name, desc)                                             \
00220         if (subparser.name()) os << desc " "
00221 
00222 #   define END_FLAGS()                                                  \
00223         os << '\n';
00224 
00225     FIELD           ( tsft,              boost::uint64_t, "MAC timestamp"        );
00226     ENTER           ( flags                                                      );
00227       START_FLAGS   (                                     "flags"                );
00228         FLAG        (     shortGI,                            "ShortGI"          );
00229         FLAG        (     badFCS,                             "BadFCS"           );
00230         FLAG        (     fcsAtEnd,                           "FCSatEnd"         );
00231         FLAG        (     fragmentation,                      "Frag"             );
00232         FLAG        (     wep,                                "WEP"              );
00233         FLAG        (     shortPreamble,                      "ShortPreamble"    );
00234         FLAG        (     cfp,                                "CFP"              );
00235       END_FLAGS     (                                                            );
00236     LEAVE           (                                                            );
00237     FIELD           ( rate,              unsigned,        "rate"                 );
00238     ENTER           ( channelOptions                                             );
00239       SUBFIELD      (     freq,          unsigned,        "channel frequency"    );
00240       START_FLAGS   (                                     "channel flags"        );
00241         FLAG        (     flag2ghz,                           "2GHz"             );
00242         FLAG        (     ofdm,                               "OFDM"             );
00243         FLAG        (     cck,                                "CCK"              );
00244         FLAG        (     turbo,                              "Turbo"            );
00245         FLAG        (     quarterRateChannel,                 "Rate/4"           );
00246         FLAG        (     halfRateChannel,                    "Rate/2"           );
00247         FLAG        (     gsm,                                "GSM"              );
00248         FLAG        (     staticTurbo,                        "StaticTurbo"      );
00249         FLAG        (     gfsk,                               "GFSK"             );
00250         FLAG        (     cckOfdm,                            "CCK+OFDM"         );
00251         FLAG        (     passive,                            "Passive"          );
00252         FLAG        (     flag5ghz,                           "5GHz"             );
00253       END_FLAGS     (                                                            );
00254     LEAVE           (                                                            );
00255     FIELD           ( fhss,              unsigned,        "FHSS"                 );
00256     FIELD           ( dbmAntennaSignal,  signed,          "antenna signal (dBm)" );
00257     FIELD           ( dbmAntennaNoise,   signed,          "antenna noise (dBm)"  );
00258     FIELD           ( lockQuality,       unsigned,        "lock quality"         );
00259     FIELD           ( txAttenuation,     unsigned,        "tx attenuation"       );
00260     FIELD           ( dbTxAttenuation,   unsigned,        "tx attenuation (dB)"  );
00261     FIELD           ( dbmTxAttenuation,  signed,          "tx attenuation (dBm)" );
00262     FIELD           ( antenna,           unsigned,        "antenna"              );
00263     FIELD           ( dbAntennaSignal,   unsigned,        "antenna signal (dB)"  );
00264     FIELD           ( dbAntennaNoise,    unsigned,        "antenna noise (dB)"   );
00265     ENTER           ( rxFlags                                                    );
00266       START_FLAGS   (                                     "rx flags"             );
00267         FLAG        (     badPlcp,                            "BadPLCP"          );
00268       END_FLAGS     (                                                            );
00269     LEAVE           (                                                            );
00270     ENTER           ( txFlags                                                    );
00271       START_FLAGS   (                                     "tx flags"             );
00272         FLAG        (     fail,                               "Fail"             );
00273         FLAG        (     txRts,                              "RTS"              );
00274         FLAG        (     txCts,                              "CTS"              );
00275       END_FLAGS     (                                                            );
00276     LEAVE           (                                                            );
00277     FIELD           ( rtsRetries,        unsigned,        "rts retries"          );
00278     FIELD           ( dataRetries,       unsigned,        "data retries"         );
00279 
00280     if (p->flagsPresent() && p->flags().fcsAtEnd())
00281         os << senf::fieldName("fcs") << unsigned(p->fcs()) << '\n';
00282 
00283 #   undef END_FLAGS
00284 #   undef FLAG
00285 #   undef START_FLAGS
00286 #   undef LEAVE
00287 #   undef SUBFIELD
00288 #   undef ENTER
00289 #   undef FIELD
00290 }
00291 
00292 prefix_ void senf::RadiotapPacketType::init(packet p)
00293 {
00294     // ?? Why the heck do we need the +0? Otherwise we get an
00295     // 'undefined reference to 'RadiotapPacketParser_Header::fixed_bytes'
00296     p->length() << RadiotapPacketParser_Header::fixed_bytes+0;
00297 }
00298 
00299 prefix_ senf::PacketInterpreterBase::factory_t senf::RadiotapPacketType::nextPacketType(packet p)
00300 {
00301     static factory_t frameTypeFactory[] = { WLANPacket_MgtFrame::factory(),
00302                                             WLANPacket_CtrlFrame::factory(),
00303                                             WLANPacket_DataFrame::factory(),
00304                                             no_factory() };
00305     return frameTypeFactory[p->frameType()];
00306 }
00307 
00308 prefix_ senf::RadiotapPacketType::optional_range
00309 senf::RadiotapPacketType::nextPacketRange(packet p)
00310 {
00311     parser rtParser (p.parser());
00312     size_type h (senf::bytes(rtParser));
00313     size_type t (rtParser.flagsPresent() && rtParser.flags().fcsAtEnd() ? 4 : 0);
00314     return p.size() <= h+t
00315         ? no_range()
00316         : optional_range( range(p.data().begin() + h, p.data().end() - t) );
00317 }
00318 
00319 //-/////////////////////////////////////////////////////////////////////////////////////////////////
00320 #undef prefix_
00321 
00322 
00323 // Local Variables:
00324 // mode: c++
00325 // fill-column: 100
00326 // c-file-style: "senf"
00327 // indent-tabs-mode: nil
00328 // ispell-local-dictionary: "american"
00329 // compile-command: "scons -u test"
00330 // comment-column: 40
00331 // End:

Contact: senf-dev@lists.berlios.de | © 2006-2010 Fraunhofer Institute for Open Communication Systems, Network Research