X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=senf%2FPackets%2F80211Bundle%2FRadiotapPacket.cc;h=5f515042f2382939f116b61e8c6759085491799e;hb=51b24c3227717ce5ad8111a99c2d7eea5fa0bd8d;hp=b27bd133abe7d7f99903d3f077e41de09c573156;hpb=82e794070d4f3ae8aacb1827b21a93b9d48ce57f;p=senf.git diff --git a/senf/Packets/80211Bundle/RadiotapPacket.cc b/senf/Packets/80211Bundle/RadiotapPacket.cc index b27bd13..5f51504 100644 --- a/senf/Packets/80211Bundle/RadiotapPacket.cc +++ b/senf/Packets/80211Bundle/RadiotapPacket.cc @@ -2,74 +2,304 @@ // // Copyright (C) 2008 // Fraunhofer Institute for Open Communication Systems (FOKUS) -// Competence Center NETwork research (NET), St. Augustin, GERMANY -// Christian Niephaus // -// 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. +// The contents of this file are subject to the Fraunhofer FOKUS Public License +// Version 1.0 (the "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// http://senf.berlios.de/license.html // -// 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. +// The Fraunhofer FOKUS Public License Version 1.0 is based on, +// but modifies the Mozilla Public License Version 1.1. +// See the full license text for the amendments. // -// 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. +// Software distributed under the License is distributed on an "AS IS" basis, +// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +// for the specific language governing rights and limitations under the License. +// +// The Original Code is Fraunhofer FOKUS code. +// +// The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. +// (registered association), Hansastraße 27 c, 80686 Munich, Germany. +// All Rights Reserved. +// +// Contributor(s): +// Stefan Bund +// Christian Niephaus -// Definition of non-inline non-template functions -// Custom includes +// Definition of RadiotapPacket non-inline non-template functions + #include "RadiotapPacket.hh" +//#include "RadiotapPacket.ih" + +// Custom includes #include "WLANPacket.hh" -#include #include +#include + +extern "C" { +# include "radiotap/radiotap_iter.h" +} #define prefix_ +//-///////////////////////////////////////////////////////////////////////////////////////////////// + +//-///////////////////////////////////////////////////////////////////////////////////////////////// +// 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); + unsigned size (8u); + while (ieee80211_radiotap_iterator_next(&iter) == 0) { + if (iter.is_radiotap_ns && + iter.this_arg_index <= int(RadiotapPacketParser::MAX_INDEX)) + table[iter.this_arg_index] = iter.this_arg - data; + // 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<= 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); + } +} + +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; +} + +//-///////////////////////////////////////////////////////////////////////////////////////////////// +// senf::RadiotapPacketType + +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"; - if (p->has_tsft()) - os << senf::fieldName("MAC timestamp") << unsigned( p->tsft()) << "\n"; - // TODO: flags - if (p->has_rate()) - os << senf::fieldName("rate") << unsigned( p->rate()) << "\n"; - // TODO: channelOptions - if (p->has_fhss()) - os << senf::fieldName("FHSS") << unsigned( p->fhss()) << "\n"; - if (p->has_dbmAntennaSignal()) - os << senf::fieldName("antenna signal (dBm)") << signed( p->dbmAntennaSignal()) << "\n"; - if (p->has_dbmAntennaNoise()) - os << senf::fieldName("antenna noise (dBm)") << signed( p->dbmAntennaNoise()) << "\n"; - if (p->has_lockQuality()) - os << senf::fieldName("lock quality") << unsigned( p->lockQuality()) << "\n"; - if (p->has_txAttenuation()) - os << senf::fieldName("tx attenuation") << unsigned( p->txAttenuation()) << "\n"; - if (p->has_dbTxAttenuation()) - os << senf::fieldName("tx attenuation (dB)") << unsigned( p->dbTxAttenuation()) << "\n"; - if (p->has_dbmTxAttenuation()) - os << senf::fieldName("tx attenuation (dBm)") << signed( p->dbmTxAttenuation()) << "\n"; - if (p->has_antenna()) - os << senf::fieldName("antenna") << unsigned( p->antenna()) << "\n"; - if (p->has_dbAntennaSignal()) - os << senf::fieldName("antenna signal (dB)") << unsigned( p->dbAntennaSignal()) << "\n"; - if (p->has_dbAntennaNoise()) - os << senf::fieldName("antenna noise (dB)") << unsigned( p->dbAntennaNoise()) << "\n"; - if (p->has_headerFcs()) - os << senf::fieldName("FCS") << unsigned( p->fcs()) << "\n"; + << 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") << unsigned(p->fcs()) << '\n'; + +# 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) @@ -82,13 +312,26 @@ prefix_ senf::PacketInterpreterBase::factory_t senf::RadiotapPacketType::nextPac } prefix_ senf::RadiotapPacketType::optional_range -senf::RadiotapPacketType::nextPacketRange(packet p) +senf::RadiotapPacketType::nextPacketRange(packet const & p) { - size_type h (senf::bytes(p.parser())); - size_type t (p->flagsPresent() && p->flags().fcsAtEnd() ? 4 : 0); - return p.size() < h+t - ? no_range() + 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) ); } +//-///////////////////////////////////////////////////////////////////////////////////////////////// #undef prefix_ + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// comment-column: 40 +// End: