g++/final: don't add extra code to check for buffer overflows (-fno-stack-protector)
[senf.git] / senf / Packets / 80211Bundle / RadiotapPacket.cc
1 // $Id$
2 //
3 // Copyright (C) 2008
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
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
10 //
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.
14 //
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.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
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.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27 //   Christian Niephaus <cni@berlios.de>
28
29
30 // Definition of RadiotapPacket non-inline non-template functions
31
32 #include "RadiotapPacket.hh"
33 //#include "RadiotapPacket.ih"
34
35 // Custom includes
36 #include "WLANPacket.hh"
37 #include <boost/io/ios_state.hpp>
38 #include <memory.h>
39
40 extern "C" {
41 #   include "radiotap/radiotap_iter.h"
42 }
43
44 #define prefix_
45 //-/////////////////////////////////////////////////////////////////////////////////////////////////
46
47 //-/////////////////////////////////////////////////////////////////////////////////////////////////
48 // Offset table management
49
50 senf::RadiotapPacketParser::OffsetMap senf::RadiotapPacketParser::offsetMap_;
51
52 prefix_ senf::RadiotapPacketParser::OffsetTable &
53 senf::RadiotapPacketParser::offsetTable(boost::uint32_t presentFlags)
54 {
55     OffsetMap::iterator i (offsetMap_.find(presentFlags));
56     if (i == offsetMap_.end())
57         i = offsetMap_.insert(std::make_pair(presentFlags, OffsetTable())).first;
58     return i->second;
59 }
60
61 prefix_ void senf::RadiotapPacketParser::parseOffsetTable(boost::uint8_t * data, int maxLength,
62                                                           OffsetTable & table)
63 {
64     struct ieee80211_radiotap_iterator iter;
65     ieee80211_radiotap_iterator_init(&iter,
66                                      (struct ieee80211_radiotap_header *)data,
67                                      maxLength,
68                                      0);
69     unsigned size (8u);
70     while (ieee80211_radiotap_iterator_next(&iter) == 0) {
71         if (iter.is_radiotap_ns &&
72             iter.this_arg_index <= int(RadiotapPacketParser::MAX_INDEX))
73             table[iter.this_arg_index] = iter.this_arg - data;
74         // We need to set size here in the loop since the iter fields are only valid
75         // when at least one present bit is set ...
76         size = iter.this_arg - data + iter.this_arg_size;
77     }
78     table[MAX_INDEX+1] = size;
79 }
80
81 prefix_ void senf::RadiotapPacketParser::buildOffsetTable(boost::uint32_t presentFlags,
82                                                           OffsetTable & table)
83 {
84     SENF_ASSERT(!(presentFlags & ( (1<<IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE) |
85                                    (1<<IEEE80211_RADIOTAP_VENDOR_NAMESPACE) |
86                                    (1<<IEEE80211_RADIOTAP_EXT) )),
87                 "Extended or vendor fields not supported");
88
89     struct ieee80211_radiotap_header header;
90     memset(&header, 0, sizeof(header));
91     // header.it_version = 0;
92
93     // Iterating this packet will generate invalid addresses but we don't care since neither
94     // radiotap.c nor we will ever dereference those pointers, we just calculate the offsets.
95     // This works, as long as we don't support extension headers ...
96     header.it_len = 0xFFFF;
97     // Note that all data in the header is little endian!
98     header.it_present = htole32(presentFlags);
99
100     parseOffsetTable((boost::uint8_t*)&header, header.it_len, table);
101 }
102
103 //-/////////////////////////////////////////////////////////////////////////////////////////////////
104 // senf::RadiotapPacketParser
105
106 unsigned const senf::RadiotapPacketParser_Header::FIELD_SIZE[] = {
107     8, 1, 1, 4, 2, 1, 1, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1 };
108
109 prefix_ senf::UInt32Parser senf::RadiotapPacketParser::init_fcs()
110 {
111     if (!has_fcs()) {
112         protect(), data().insert(data().end(), 4u, 0u);
113         init_flags().fcsAtEnd_() = true;
114     }
115     return fcs();
116 }
117
118 prefix_ void senf::RadiotapPacketParser::disable_fcs()
119 {
120     if (has_fcs()) {
121         validate(RadiotapPacketParser_Header::fixed_bytes+4);
122         data().erase(data().end()-4, data().end());
123         flags().fcsAtEnd_() = false;
124     }
125 }
126
127 prefix_ senf::RadiotapPacketParser::OffsetTable const &
128 senf::RadiotapPacketParser::getTable(boost::uint32_t presentFlags)
129     const
130 {
131     OffsetTable & table(offsetTable(presentFlags));
132     if (! table[MAX_INDEX+1])
133         buildOffsetTable(presentFlags, table);
134     return table;
135 }
136
137 prefix_ void senf::RadiotapPacketParser::insertRemoveBytes(unsigned from , unsigned to, int bytes)
138 {
139     data_iterator b (i() + from);
140     data_iterator e (i() + to);
141     if (bytes >= 0) {
142         // Insert some bytes cleaning the old bytes to 0 first
143         std::fill(b, e,  0u);
144         if (bytes > 0)
145             // need to protect the parser since data().insert() invalidates iterators
146             protect(), data().insert(e, bytes, 0u);
147     }
148     else { // bytes < 0
149         // Remove some bytes ...
150         // remember: bytes is negative ...
151         if (b < e + bytes)
152             std::fill(b, e + bytes, 0u);
153         data().erase(e + bytes, e);
154     }
155 }
156
157 prefix_ void senf::RadiotapPacketParser::updatePresentFlags(boost::uint32_t flags)
158 {
159     if (flags == presentFlags())
160         return;
161     validate(bytes());
162
163     OffsetTable const & oldTable (currentTable());
164     OffsetTable const & newTable (getTable(flags));
165     unsigned b (RadiotapPacketParser_Header::fixed_bytes);
166     int cumulativeNewBytes (0);
167
168     for (unsigned index (0); index <= MAX_INDEX; ++index) {
169         // Skip any unchanged fields
170         for (; index <= MAX_INDEX+1
171                  && ((oldTable[index] == 0 && newTable[index] == 0)
172                      || (oldTable[index]+cumulativeNewBytes == newTable[index])); ++index)
173             if (newTable[index] != 0)
174                 b = newTable[index] + FIELD_SIZE[index];
175         if (index > MAX_INDEX+1)
176             break;
177         // Now skip over all changed fields
178         // (The condition index <= MAX_INDEX is not needed here since the last
179         // table entry MAX_INDEX+1 is always != 0 in both tables)
180         for (; ! (oldTable[index]!=0 && newTable[index]!=0); ++index) ;
181         // index now either points to
182         // a) an entry set in both tables
183         // b) at the end of the table which contains the total length
184         // (remember: the table has a size of MAX_INDEX+2 entries !!)
185         // in both cases, the difference between the new and old size
186         // is found from the difference between the old and the new table
187         // entry
188         int newBytes (newTable[index] - oldTable[index] - cumulativeNewBytes);
189         insertRemoveBytes(b, oldTable[index] + cumulativeNewBytes, newBytes);
190         cumulativeNewBytes += newBytes;
191         b = newTable[index] + FIELD_SIZE[index];
192     }
193     length() += cumulativeNewBytes;
194     presentFlags() = flags;
195     currentTable_ = &newTable;
196 }
197
198 //-/////////////////////////////////////////////////////////////////////////////////////////////////
199 // senf::RadiotapPacketType
200
201 prefix_ void senf::RadiotapPacketType::dump(packet p, std::ostream & os)
202 {
203     boost::io::ios_all_saver ias(os);
204     os << "Radiotap:\n"
205        << senf::fieldName("version") << unsigned(p->version()) << '\n'
206        << senf::fieldName("length")  << unsigned(p->length()) << '\n';
207
208 #   define FIELD(name, sign, desc)                                      \
209         if (p->name ## Present())                                       \
210             os << senf::fieldName(desc) << sign(p->name()) << '\n';
211
212 #   define ENTER(name)                                                  \
213         if (p->name ## Present()) {                                     \
214             packet::Parser::name ## _t subparser (p->name());
215
216 #   define SUBFIELD(name, sign, desc)                                   \
217         os << senf::fieldName(desc) << sign(subparser.name()) << '\n';
218
219 #   define LEAVE()                                                      \
220         }
221
222 #   define START_FLAGS(desc)                                            \
223         os << senf::fieldName(desc);
224
225 #   define FLAG(name, desc)                                             \
226         if (subparser.name()) os << desc " "
227
228 #   define END_FLAGS()                                                  \
229         os << '\n';
230
231     FIELD           ( tsft,              boost::uint64_t, "MAC timestamp"        );
232     ENTER           ( flags                                                      );
233       START_FLAGS   (                                     "flags"                );
234         FLAG        (     shortGI,                            "ShortGI"          );
235         FLAG        (     badFCS,                             "BadFCS"           );
236         FLAG        (     fcsAtEnd,                           "FCSatEnd"         );
237         FLAG        (     fragmentation,                      "Frag"             );
238         FLAG        (     wep,                                "WEP"              );
239         FLAG        (     shortPreamble,                      "ShortPreamble"    );
240         FLAG        (     cfp,                                "CFP"              );
241       END_FLAGS     (                                                            );
242     LEAVE           (                                                            );
243     FIELD           ( rate,              unsigned,        "rate"                 );
244     ENTER           ( channelOptions                                             );
245       SUBFIELD      (     freq,          unsigned,        "channel frequency"    );
246       START_FLAGS   (                                     "channel flags"        );
247         FLAG        (     flag2ghz,                           "2GHz"             );
248         FLAG        (     ofdm,                               "OFDM"             );
249         FLAG        (     cck,                                "CCK"              );
250         FLAG        (     turbo,                              "Turbo"            );
251         FLAG        (     quarterRateChannel,                 "Rate/4"           );
252         FLAG        (     halfRateChannel,                    "Rate/2"           );
253         FLAG        (     gsm,                                "GSM"              );
254         FLAG        (     staticTurbo,                        "StaticTurbo"      );
255         FLAG        (     gfsk,                               "GFSK"             );
256         FLAG        (     cckOfdm,                            "CCK+OFDM"         );
257         FLAG        (     passive,                            "Passive"          );
258         FLAG        (     flag5ghz,                           "5GHz"             );
259       END_FLAGS     (                                                            );
260     LEAVE           (                                                            );
261     FIELD           ( fhss,              unsigned,        "FHSS"                 );
262     FIELD           ( dbmAntennaSignal,  signed,          "antenna signal (dBm)" );
263     FIELD           ( dbmAntennaNoise,   signed,          "antenna noise (dBm)"  );
264     FIELD           ( lockQuality,       unsigned,        "lock quality"         );
265     FIELD           ( txAttenuation,     unsigned,        "tx attenuation"       );
266     FIELD           ( dbTxAttenuation,   unsigned,        "tx attenuation (dB)"  );
267     FIELD           ( dbmTxAttenuation,  signed,          "tx attenuation (dBm)" );
268     FIELD           ( antenna,           unsigned,        "antenna"              );
269     FIELD           ( dbAntennaSignal,   unsigned,        "antenna signal (dB)"  );
270     FIELD           ( dbAntennaNoise,    unsigned,        "antenna noise (dB)"   );
271     ENTER           ( rxFlags                                                    );
272       START_FLAGS   (                                     "rx flags"             );
273         FLAG        (     badPlcp,                            "BadPLCP"          );
274       END_FLAGS     (                                                            );
275     LEAVE           (                                                            );
276     ENTER           ( txFlags                                                    );
277       START_FLAGS   (                                     "tx flags"             );
278         FLAG        (     fail,                               "Fail"             );
279         FLAG        (     txRts,                              "RTS"              );
280         FLAG        (     txCts,                              "CTS"              );
281       END_FLAGS     (                                                            );
282     LEAVE           (                                                            );
283     FIELD           ( rtsRetries,        unsigned,        "rts retries"          );
284     FIELD           ( dataRetries,       unsigned,        "data retries"         );
285
286     if (p->flagsPresent() && p->flags().fcsAtEnd())
287         os << senf::fieldName("fcs") << unsigned(p->fcs()) << '\n';
288
289 #   undef END_FLAGS
290 #   undef FLAG
291 #   undef START_FLAGS
292 #   undef LEAVE
293 #   undef SUBFIELD
294 #   undef ENTER
295 #   undef FIELD
296 }
297
298 prefix_ void senf::RadiotapPacketType::init(packet p)
299 {
300     // ?? Why the heck do we need the +0? Otherwise we get an
301     // 'undefined reference to 'RadiotapPacketParser_Header::fixed_bytes'
302     p->length() << RadiotapPacketParser_Header::fixed_bytes+0;
303 }
304
305 prefix_ senf::PacketInterpreterBase::factory_t senf::RadiotapPacketType::nextPacketType(packet p)
306 {
307     static factory_t frameTypeFactory[] = { WLANPacket_MgtFrame::factory(),
308                                             WLANPacket_CtrlFrame::factory(),
309                                             WLANPacket_DataFrame::factory(),
310                                             no_factory() };
311     return frameTypeFactory[p->frameType()];
312 }
313
314 prefix_ senf::RadiotapPacketType::optional_range
315 senf::RadiotapPacketType::nextPacketRange(packet const & p)
316 {
317     parser rtParser (p.parser());
318     size_type h (senf::bytes(rtParser));
319     size_type t (rtParser.flagsPresent() && rtParser.flags().fcsAtEnd() ? 4 : 0);
320     return p.size() <= h+t
321         ? no_range()
322         : optional_range( range(p.data().begin() + h, p.data().end() - t) );
323 }
324
325 //-/////////////////////////////////////////////////////////////////////////////////////////////////
326 #undef prefix_
327
328 \f
329 // Local Variables:
330 // mode: c++
331 // fill-column: 100
332 // c-file-style: "senf"
333 // indent-tabs-mode: nil
334 // ispell-local-dictionary: "american"
335 // compile-command: "scons -u test"
336 // comment-column: 40
337 // End: