4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at
9 // http://senf.berlios.de/license.html
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on,
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
15 // Software distributed under the License is distributed on an "AS IS" basis,
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
17 // for the specific language governing rights and limitations under the License.
19 // The Original Code is Fraunhofer FOKUS code.
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V.
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
26 // Stefan Bund <g0dil@berlios.de>
27 // Christian Niephaus <cni@berlios.de>
30 // Definition of RadiotapPacket non-inline non-template functions
32 #include "RadiotapPacket.hh"
33 //#include "RadiotapPacket.ih"
36 #include "WLANPacket.hh"
37 #include <boost/io/ios_state.hpp>
41 # include "radiotap/radiotap_iter.h"
45 //-/////////////////////////////////////////////////////////////////////////////////////////////////
47 //-/////////////////////////////////////////////////////////////////////////////////////////////////
48 // Offset table management
50 prefix_ senf::RadiotapPacketParser::OffsetTable &
51 senf::RadiotapPacketParser::offsetTable(boost::uint32_t presentFlags)
53 typedef std::map<boost::uint32_t, OffsetTable> OffsetMap;
54 static OffsetMap offsetMap;
56 OffsetMap::iterator i (offsetMap.find(presentFlags));
57 if (i == offsetMap.end())
58 i = offsetMap.insert(std::make_pair(presentFlags, OffsetTable())).first;
62 prefix_ void senf::RadiotapPacketParser::parseOffsetTable(boost::uint8_t * data, int maxLength,
65 struct ieee80211_radiotap_iterator iter;
66 ieee80211_radiotap_iterator_init(&iter,
67 (struct ieee80211_radiotap_header *)data,
71 while (ieee80211_radiotap_iterator_next(&iter) == 0) {
72 if (iter.is_radiotap_ns &&
73 iter.this_arg_index <= int(RadiotapPacketParser::MAX_INDEX))
74 table[iter.this_arg_index] = iter.this_arg - data;
75 // We need to set size here in the loop since the iter fields are only valid
76 // when at least one present bit is set ...
77 size = iter.this_arg - data + iter.this_arg_size;
79 table[MAX_INDEX+1] = size;
82 prefix_ void senf::RadiotapPacketParser::buildOffsetTable(boost::uint32_t presentFlags,
85 SENF_ASSERT(!(presentFlags & ( (1<<IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE) |
86 (1<<IEEE80211_RADIOTAP_VENDOR_NAMESPACE) |
87 (1<<IEEE80211_RADIOTAP_EXT) )),
88 "Extended or vendor fields not supported");
90 struct ieee80211_radiotap_header header;
91 memset(&header, 0, sizeof(header));
92 // header.it_version = 0;
94 // Iterating this packet will generate invalid addresses but we don't care since neither
95 // radiotap.c nor we will ever dereference those pointers, we just calculate the offsets.
96 // This works, as long as we don't support extension headers ...
97 header.it_len = 0xFFFF;
98 // Note that all data in the header is little endian!
99 header.it_present = htole32(presentFlags);
101 parseOffsetTable((boost::uint8_t*)&header, header.it_len, table);
104 //-/////////////////////////////////////////////////////////////////////////////////////////////////
105 // senf::RadiotapPacketParser
107 unsigned const senf::RadiotapPacketParser_Header::FIELD_SIZE[] = {
108 8, 1, 1, 4, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1 };
110 prefix_ senf::UInt32Parser senf::RadiotapPacketParser::init_fcs()
113 protect(), data().insert(data().end(), 4u, 0u);
114 init_flags().fcsAtEnd_() = true;
119 prefix_ void senf::RadiotapPacketParser::disable_fcs()
122 validate(RadiotapPacketParser_Header::fixed_bytes+4);
123 data().erase(data().end()-4, data().end());
124 flags().fcsAtEnd_() = false;
128 prefix_ senf::RadiotapPacketParser::OffsetTable const &
129 senf::RadiotapPacketParser::getTable(boost::uint32_t presentFlags)
132 OffsetTable & table(offsetTable(presentFlags));
133 if (! table[MAX_INDEX+1])
134 buildOffsetTable(presentFlags, table);
138 prefix_ void senf::RadiotapPacketParser::insertRemoveBytes(unsigned from , unsigned to, int bytes)
140 data_iterator b (i() + from);
141 data_iterator e (i() + to);
143 // Insert some bytes cleaning the old bytes to 0 first
146 // need to protect the parser since data().insert() invalidates iterators
147 protect(), data().insert(e, bytes, 0u);
150 // Remove some bytes ...
151 // remember: bytes is negative ...
153 std::fill(b, e + bytes, 0u);
154 data().erase(e + bytes, e);
158 prefix_ void senf::RadiotapPacketParser::updatePresentFlags(boost::uint32_t flags)
160 if (flags == presentFlags())
164 OffsetTable const & oldTable (currentTable());
165 OffsetTable const & newTable (getTable(flags));
166 unsigned b (RadiotapPacketParser_Header::fixed_bytes);
167 int cumulativeNewBytes (0);
169 for (unsigned index (0); index <= MAX_INDEX; ++index) {
170 // Skip any unchanged fields
171 for (; index <= MAX_INDEX+1
172 && ((oldTable[index] == 0 && newTable[index] == 0)
173 || (oldTable[index]+cumulativeNewBytes == newTable[index])); ++index)
174 if (newTable[index] != 0)
175 b = newTable[index] + FIELD_SIZE[index];
176 if (index > MAX_INDEX+1)
178 // Now skip over all changed fields
179 // (The condition index <= MAX_INDEX is not needed here since the last
180 // table entry MAX_INDEX+1 is always != 0 in both tables)
181 for (; ! (oldTable[index]!=0 && newTable[index]!=0); ++index) ;
182 // index now either points to
183 // a) an entry set in both tables
184 // b) at the end of the table which contains the total length
185 // (remember: the table has a size of MAX_INDEX+2 entries !!)
186 // in both cases, the difference between the new and old size
187 // is found from the difference between the old and the new table
189 int newBytes (newTable[index] - oldTable[index] - cumulativeNewBytes);
190 insertRemoveBytes(b, oldTable[index] + cumulativeNewBytes, newBytes);
191 cumulativeNewBytes += newBytes;
192 b = newTable[index] + FIELD_SIZE[index];
194 length() += cumulativeNewBytes;
195 presentFlags() = flags;
196 currentTable_ = &newTable;
199 //-/////////////////////////////////////////////////////////////////////////////////////////////////
200 // senf::RadiotapPacketType
202 prefix_ void senf::RadiotapPacketType::dump(packet p, std::ostream & os)
204 boost::io::ios_all_saver ias(os);
206 << senf::fieldName("version") << unsigned(p->version()) << '\n'
207 << senf::fieldName("length") << unsigned(p->length()) << '\n';
209 # define FIELD(name, sign, desc) \
210 if (p->name ## Present()) \
211 os << senf::fieldName(desc) << sign(p->name()) << '\n';
213 # define ENTER(name) \
214 if (p->name ## Present()) { \
215 packet::Parser::name ## _t subparser (p->name());
217 # define SUBFIELD(name, sign, desc) \
218 os << senf::fieldName(desc) << sign(subparser.name()) << '\n';
223 # define START_FLAGS(desc) \
224 os << senf::fieldName(desc);
226 # define FLAG(name, desc) \
227 if (subparser.name()) os << desc " "
229 # define END_FLAGS() \
232 FIELD ( tsft, boost::uint64_t, "MAC timestamp" );
234 START_FLAGS ( "flags" );
235 FLAG ( shortGI, "ShortGI" );
236 FLAG ( badFCS, "BadFCS" );
237 FLAG ( fcsAtEnd, "FCSatEnd" );
238 FLAG ( fragmentation, "Frag" );
240 FLAG ( shortPreamble, "ShortPreamble" );
244 FIELD ( rate, unsigned, "rate" );
245 ENTER ( channelOptions );
246 SUBFIELD ( freq, unsigned, "channel frequency" );
247 START_FLAGS ( "channel flags" );
248 FLAG ( flag2ghz, "2GHz" );
249 FLAG ( ofdm, "OFDM" );
251 FLAG ( turbo, "Turbo" );
252 FLAG ( quarterRateChannel, "Rate/4" );
253 FLAG ( halfRateChannel, "Rate/2" );
255 FLAG ( staticTurbo, "StaticTurbo" );
256 FLAG ( gfsk, "GFSK" );
257 FLAG ( cckOfdm, "CCK+OFDM" );
258 FLAG ( passive, "Passive" );
259 FLAG ( flag5ghz, "5GHz" );
262 FIELD ( fhss, unsigned, "FHSS" );
263 FIELD ( dbmAntennaSignal, signed, "antenna signal (dBm)" );
264 FIELD ( dbmAntennaNoise, signed, "antenna noise (dBm)" );
265 FIELD ( lockQuality, unsigned, "lock quality" );
266 FIELD ( txAttenuation, unsigned, "tx attenuation" );
267 FIELD ( dbTxAttenuation, unsigned, "tx attenuation (dB)" );
268 FIELD ( dbmTxAttenuation, signed, "tx attenuation (dBm)" );
269 FIELD ( antenna, unsigned, "antenna" );
270 FIELD ( dbAntennaSignal, unsigned, "antenna signal (dB)" );
271 FIELD ( dbAntennaNoise, unsigned, "antenna noise (dB)" );
273 START_FLAGS ( "rx flags" );
274 FLAG ( badPlcp, "BadPLCP" );
278 START_FLAGS ( "tx flags" );
279 FLAG ( fail, "Fail" );
280 FLAG ( txRts, "RTS" );
281 FLAG ( txCts, "CTS" );
284 FIELD ( rtsRetries, unsigned, "rts retries" );
285 FIELD ( dataRetries, unsigned, "data retries" );
287 if (p->flagsPresent() && p->flags().fcsAtEnd())
288 os << senf::fieldName("fcs") << unsigned(p->fcs()) << '\n';
299 prefix_ void senf::RadiotapPacketType::init(packet p)
301 // ?? Why the heck do we need the +0? Otherwise we get an
302 // 'undefined reference to 'RadiotapPacketParser_Header::fixed_bytes'
303 p->length() << RadiotapPacketParser_Header::fixed_bytes+0;
306 prefix_ senf::PacketInterpreterBase::factory_t senf::RadiotapPacketType::nextPacketType(packet p)
308 static factory_t frameTypeFactory[] = { WLANPacket_MgtFrame::factory(),
309 WLANPacket_CtrlFrame::factory(),
310 WLANPacket_DataFrame::factory(),
312 return frameTypeFactory[p->frameType()];
315 prefix_ senf::RadiotapPacketType::optional_range
316 senf::RadiotapPacketType::nextPacketRange(packet const & p)
318 parser rtParser (p.parser());
319 size_type h (senf::bytes(rtParser));
320 size_type t (rtParser.flagsPresent() && rtParser.flags().fcsAtEnd() ? 4 : 0);
321 return p.size() <= h+t
323 : optional_range( range(p.data().begin() + h, p.data().end() - t) );
326 //-/////////////////////////////////////////////////////////////////////////////////////////////////
333 // c-file-style: "senf"
334 // indent-tabs-mode: nil
335 // ispell-local-dictionary: "american"
336 // compile-command: "scons -u test"
337 // comment-column: 40