4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Christian Niephaus <cni@berlios.de>
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 // Definition of RadiotapPacket non-inline non-template functions
25 #include "RadiotapPacket.hh"
26 //#include "RadiotapPacket.ih"
29 #include "WLANPacket.hh"
30 #include <boost/io/ios_state.hpp>
34 # include "radiotap/radiotap_iter.h"
38 ///////////////////////////////cc.p//////////////////////////////////////
40 ///////////////////////////////////////////////////////////////////////////
41 // Offset table management
43 prefix_ senf::RadiotapPacketParser::OffsetTable &
44 senf::RadiotapPacketParser::offsetTable(boost::uint32_t presentFlags)
46 typedef std::map<boost::uint32_t, OffsetTable> OffsetMap;
47 static OffsetMap offsetMap;
49 OffsetMap::iterator i (offsetMap.find(presentFlags));
50 if (i == offsetMap.end())
51 i = offsetMap.insert(std::make_pair(presentFlags, OffsetTable())).first;
55 prefix_ void senf::RadiotapPacketParser::parseOffsetTable(boost::uint8_t * data, int maxLength,
58 struct ieee80211_radiotap_iterator iter;
59 ieee80211_radiotap_iterator_init(&iter,
60 (struct ieee80211_radiotap_header *)data,
64 while (ieee80211_radiotap_iterator_next(&iter) == 0) {
65 if (iter.is_radiotap_ns &&
66 iter.this_arg_index <= int(senf::RadiotapPacketParser::MAX_INDEX))
67 table[iter.this_arg_index] = iter.this_arg - data;
68 // We need to set size here in the loop since the iter fields are only valid
69 // when at least one present bit is set ...
70 size = iter.this_arg - data + iter.this_arg_size;
72 table[MAX_INDEX+1] = size;
75 prefix_ void senf::RadiotapPacketParser::buildOffsetTable(boost::uint32_t presentFlags,
78 SENF_ASSERT(!(presentFlags & ( (1<<IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE) |
79 (1<<IEEE80211_RADIOTAP_VENDOR_NAMESPACE) |
80 (1<<IEEE80211_RADIOTAP_EXT) )),
81 "Extended or vendor fields not supported");
83 struct ieee80211_radiotap_header header;
84 memset(&header, 0, sizeof(header));
85 // header.it_version = 0;
87 // Iterating this packet will generate invalid addresses but we don't care since neither
88 // radiotap.c nor we will ever dereference those pointers, we just calculate the offsets.
89 // This works, as long as we don't support extension headers ...
90 header.it_len = 0xFFFF;
91 header.it_present = presentFlags;
93 parseOffsetTable((boost::uint8_t*)&header, header.it_len, table);
96 ///////////////////////////////////////////////////////////////////////////
97 // senf::RadiotapPacketParser
99 unsigned const senf::RadiotapPacketParser_Header::FIELD_SIZE[] = {
100 8, 1, 1, 4, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1 };
102 prefix_ senf::UInt32Parser senf::RadiotapPacketParser::init_fcs()
105 protect(), data().insert(data().end(), 4u, 0u);
106 init_flags().fcsAtEnd_() = true;
111 prefix_ void senf::RadiotapPacketParser::disable_fcs()
114 validate(RadiotapPacketParser_Header::fixed_bytes+4);
115 data().erase(data().end()-4, data().end());
116 flags().fcsAtEnd_() = false;
120 prefix_ senf::RadiotapPacketParser::OffsetTable const &
121 senf::RadiotapPacketParser::getTable(boost::uint32_t presentFlags)
124 OffsetTable & table(offsetTable(presentFlags));
125 if (! table[MAX_INDEX+1])
126 buildOffsetTable(presentFlags, table);
130 prefix_ void senf::RadiotapPacketParser::insertRemoveBytes(unsigned from , unsigned to, int bytes)
132 data_iterator b (i() + from);
133 data_iterator e (i() + to);
135 // Insert some bytes cleaning the old bytes to 0 first
138 // need to protect the parser since data().insert() invalidates iterators
139 protect(), data().insert(e, bytes, 0u);
142 // Remove some bytes ...
143 // remember: bytes is negative ...
145 std::fill(b, e + bytes, 0u);
146 data().erase(e + bytes, e);
150 prefix_ void senf::RadiotapPacketParser::updatePresentFlags(boost::uint32_t flags)
152 if (flags == presentFlags())
156 OffsetTable const & oldTable (currentTable());
157 OffsetTable const & newTable (getTable(flags));
158 unsigned b (RadiotapPacketParser_Header::fixed_bytes);
159 int cumulativeNewBytes (0);
161 for (unsigned index (0); index <= MAX_INDEX; ++index) {
162 // Skip any unchanged fields
163 for (; index <= MAX_INDEX+1
164 && ((oldTable[index] == 0 && newTable[index] == 0)
165 || (oldTable[index]+cumulativeNewBytes == newTable[index])); ++index)
166 if (newTable[index] != 0)
167 b = newTable[index] + FIELD_SIZE[index];
168 if (index > MAX_INDEX+1)
170 // Now skip over all changed fields
171 // (The condition index <= MAX_INDEX is not needed here since the last
172 // table entry MAX_INDEX+1 is always != 0 in both tables)
173 for (; ! (oldTable[index]!=0 && newTable[index]!=0); ++index) ;
174 // index now either points to
175 // a) an entry set in both tables
176 // b) at the end of the table which contains the total length
177 // (remember: the table has a size of MAX_INDEX+2 entries !!)
178 // in both cases, the difference between the new and old size
179 // is found from the difference between the old and the new table
181 int newBytes (newTable[index] - oldTable[index] - cumulativeNewBytes);
182 insertRemoveBytes(b, oldTable[index] + cumulativeNewBytes, newBytes);
183 cumulativeNewBytes += newBytes;
184 b = newTable[index] + FIELD_SIZE[index];
186 presentFlags() = flags;
187 currentTable_ = &newTable;
190 ///////////////////////////////////////////////////////////////////////////
191 // senf::RadiotapPacketType
193 prefix_ void senf::RadiotapPacketType::dump(packet p, std::ostream &os)
195 boost::io::ios_all_saver ias(os);
197 << senf::fieldName("version") << unsigned(p->version()) << '\n'
198 << senf::fieldName("length") << unsigned(p->length()) << '\n';
200 # define FIELD(name, sign, desc) \
201 if (p->name ## Present()) \
202 os << senf::fieldName(desc) << sign(p->name()) << '\n';
204 # define ENTER(name) \
205 if (p->name ## Present()) { \
206 packet::Parser::name ## _t subparser (p->name());
208 # define SUBFIELD(name, sign, desc) \
209 os << senf::fieldName(desc) << sign(subparser.name()) << '\n';
214 # define START_FLAGS(desc) \
215 os << senf::fieldName(desc);
217 # define FLAG(name, desc) \
218 if (subparser.name()) os << desc " "
220 # define END_FLAGS() \
223 FIELD ( tsft, boost::uint64_t, "MAC timestamp" );
225 START_FLAGS ( "flags" );
226 FLAG ( shortGI, "ShortGI" );
227 FLAG ( badFCS, "BadFCS" );
228 FLAG ( fcsAtEnd, "FCSatEnd" );
229 FLAG ( fragmentation, "Frag" );
231 FLAG ( shortPreamble, "ShortPreamble" );
235 FIELD ( rate, unsigned, "rate" );
236 ENTER ( channelOptions );
237 SUBFIELD ( freq, unsigned, "channel frequency" );
238 START_FLAGS ( "channel flags" );
239 FLAG ( flag2ghz, "2GHz" );
240 FLAG ( ofdm, "OFDM" );
242 FLAG ( turbo, "Turbo" );
243 FLAG ( quarterRateChannel, "Rate/4" );
244 FLAG ( halfRateChannel, "Rate/2" );
246 FLAG ( staticTurbo, "StaticTurbo" );
247 FLAG ( gfsk, "GFSK" );
248 FLAG ( cckOfdm, "CCK+OFDM" );
249 FLAG ( passive, "Passive" );
250 FLAG ( flag5ghz, "5GHz" );
253 FIELD ( fhss, unsigned, "FHSS" );
254 FIELD ( dbmAntennaSignal, signed, "antenna signal (dBm)" );
255 FIELD ( dbmAntennaNoise, signed, "antenna noise (dBm)" );
256 FIELD ( lockQuality, unsigned, "lock quality" );
257 FIELD ( txAttenuation, unsigned, "tx attenuation" );
258 FIELD ( dbTxAttenuation, unsigned, "tx attenuation (dB)" );
259 FIELD ( dbmTxAttenuation, signed, "tx attenuation (dBm)" );
260 FIELD ( antenna, unsigned, "antenna" );
261 FIELD ( dbAntennaSignal, unsigned, "antenna signal (dB)" );
262 FIELD ( dbAntennaNoise, unsigned, "antenna noise (dB)" );
264 START_FLAGS ( "rx flags" );
265 FLAG ( badPlcp, "BadPLCP" );
269 START_FLAGS ( "tx flags" );
270 FLAG ( fail, "Fail" );
271 FLAG ( txRts, "RTS" );
272 FLAG ( txCts, "CTS" );
275 FIELD ( rtsRetries, unsigned, "rts retries" );
276 FIELD ( dataRetries, unsigned, "data retries" );
278 if (p->flagsPresent() && p->flags().fcsAtEnd())
279 os << senf::fieldName("fcs") << unsigned(p->fcs()) << '\n';
291 prefix_ void senf::RadiotapPacketType::finalize(packet p)
293 ///\fixme Is this really correct ? shouldn't I use nextPacket.begin() - begin() here ?
294 p->length() << p->calculateSize();
297 prefix_ senf::PacketInterpreterBase::factory_t senf::RadiotapPacketType::nextPacketType(packet p)
299 static factory_t frameTypeFactory[] = { WLANPacket_MgtFrame::factory(),
300 WLANPacket_CtrlFrame::factory(),
301 WLANPacket_DataFrame::factory(),
303 return frameTypeFactory[p->frameType()];
306 prefix_ senf::RadiotapPacketType::optional_range
307 senf::RadiotapPacketType::nextPacketRange(packet p)
309 size_type h (senf::bytes(p.parser()));
310 size_type t (p->flagsPresent() && p->flags().fcsAtEnd() ? 4 : 0);
311 return p.size() <= h+t
313 : optional_range( range(p.data().begin() + h, p.data().end() - t) );
316 ///////////////////////////////cc.e////////////////////////////////////////
323 // c-file-style: "senf"
324 // indent-tabs-mode: nil
325 // ispell-local-dictionary: "american"
326 // compile-command: "scons -u test"
327 // comment-column: 40