X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=senf%2FPackets%2F80211Bundle%2FRadiotapPacket.cc;h=521301e5c03de75e7ba23f353cc915bd55e875bb;hb=e3179a2123ad51d0d9eb63834a581145c4f77c92;hp=ceff4743351d3da4dc28fd0583906d94729fd16c;hpb=0d88f940c093ff9c34099c9ab5c43e340f60a1f0;p=senf.git diff --git a/senf/Packets/80211Bundle/RadiotapPacket.cc b/senf/Packets/80211Bundle/RadiotapPacket.cc index ceff474..521301e 100644 --- a/senf/Packets/80211Bundle/RadiotapPacket.cc +++ b/senf/Packets/80211Bundle/RadiotapPacket.cc @@ -4,6 +4,7 @@ // Fraunhofer Institute for Open Communication Systems (FOKUS) // Competence Center NETwork research (NET), St. Augustin, GERMANY // Christian Niephaus +// Stefan Bund // // 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 @@ -28,83 +29,271 @@ // Custom includes #include "WLANPacket.hh" #include +#include 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 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) { 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)) { + iter.this_arg_index <= int(RadiotapPacketParser::MAX_INDEX)) table[iter.this_arg_index] = iter.this_arg - data; - std::cerr << ">> " << iter.this_arg_index << " " << table[iter.this_arg_index] << "\n"; - } + // 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<> size " << table[MAX_INDEX+1] << "\n"; } prefix_ senf::RadiotapPacketParser::OffsetTable const & -senf::RadiotapPacketParser::offsetTable(boost::uint32_t presentFlags) +senf::RadiotapPacketParser::getTable(boost::uint32_t presentFlags) + const { - typedef std::map OffsetMap; - static OffsetMap offsetMap; + OffsetTable & table(offsetTable(presentFlags)); + if (! table[MAX_INDEX+1]) + buildOffsetTable(presentFlags, 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_ 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]; + } + length() += cumulativeNewBytes; + presentFlags() = flags; + currentTable_ = &newTable; +} -#define DUMP_OPTIONAL_FIELD(name, sign, desc) \ - if (p->name ## Present()) \ - os << senf::fieldName(desc) << sign(p->name()) \ - << std::endl; +//-///////////////////////////////////////////////////////////////////////////////////////////////// +// senf::RadiotapPacketType -prefix_ void senf::RadiotapPacketType::dump(packet p, std::ostream &os) +prefix_ void senf::RadiotapPacketType::dump(packet p, std::ostream & os) { boost::io::ios_all_saver ias(os); os << "Radiotap:\n" - << senf::fieldName("version") << unsigned(p->version()) << "\n" - << senf::fieldName("length") << unsigned(p->length()) << "\n"; - // TODO: flags, channelOptions - DUMP_OPTIONAL_FIELD( tsft, unsigned, "MAC timestamp" ); - DUMP_OPTIONAL_FIELD( rate, unsigned, "rate" ); - 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)" ); + << senf::fieldName("version") << unsigned(p->version()) << '\n' + << senf::fieldName("length") << unsigned(p->length()) << '\n'; + +# define FIELD(name, sign, desc) \ + if (p->name ## Present()) \ + os << senf::fieldName(desc) << sign(p->name()) << '\n'; + +# define ENTER(name) \ + if (p->name ## Present()) { \ + packet::Parser::name ## _t subparser (p->name()); + +# define SUBFIELD(name, sign, desc) \ + os << senf::fieldName(desc) << sign(subparser.name()) << '\n'; + +# define LEAVE() \ + } + +# define START_FLAGS(desc) \ + os << senf::fieldName(desc); + +# define FLAG(name, desc) \ + if (subparser.name()) os << desc " " + +# define END_FLAGS() \ + os << '\n'; + + 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 +} -prefix_ void senf::RadiotapPacketType::finalize(packet p) +prefix_ void senf::RadiotapPacketType::init(packet p) { - p->length() << p->calculateSize(); + // ?? Why the heck do we need the +0? Otherwise we get an + // 'undefined reference to 'RadiotapPacketParser_Header::fixed_bytes' + p->length() << RadiotapPacketParser_Header::fixed_bytes+0; } prefix_ senf::PacketInterpreterBase::factory_t senf::RadiotapPacketType::nextPacketType(packet p) @@ -119,14 +308,15 @@ prefix_ senf::PacketInterpreterBase::factory_t senf::RadiotapPacketType::nextPac prefix_ senf::RadiotapPacketType::optional_range senf::RadiotapPacketType::nextPacketRange(packet p) { - size_type h (senf::bytes(p.parser())); - size_type t (p->flagsPresent() && p->flags().fcsAtEnd() ? 4 : 0); - return p.size() < h+t + parser rtParser (p.parser()); + size_type h (senf::bytes(rtParser)); + size_type t (rtParser.flagsPresent() && rtParser.flags().fcsAtEnd() ? 4 : 0); + return p.size() <= h+t ? no_range() : optional_range( range(p.data().begin() + h, p.data().end() - t) ); } -///////////////////////////////cc.e//////////////////////////////////////// +//-///////////////////////////////////////////////////////////////////////////////////////////////// #undef prefix_