a29242890755379b828c11e4d56f19d6004625ce
[senf.git] / senf / Packets / 80211Bundle / RadiotapPacket.hh
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 /** \file
30     \brief Radiotap header */
31
32 #ifndef HH_SENF_Packets_80211Bundle_RadiotapPacket_
33 #define HH_SENF_Packets_80211Bundle_RadiotapPacket_ 1
34
35 // Custom includes
36 #include <senf/Packets/Packets.hh>
37 #include <boost/array.hpp>
38
39 //-/////////////////////////////////////////////////////////////////////////////////////////////////
40 namespace senf {
41
42     /** \brief Parse Flag field in Radiotap header
43
44         <b>Re-ordering of bits due to LSB byte order</b>
45      */
46     struct RadiotapPacketParser_Flags : public PacketParserBase
47     {
48 #       include SENF_FIXED_PARSER()
49
50         SENF_PARSER_BITFIELD ( shortGI,        1, bool );
51         SENF_PARSER_BITFIELD ( badFCS,         1, bool );
52         SENF_PARSER_BITFIELD ( padding,        1, bool );
53         SENF_PARSER_BITFIELD_RO ( fcsAtEnd,    1, bool ); // Cannot change this (change packet size)
54         SENF_PARSER_BITFIELD ( fragmentation,  1, bool );
55         SENF_PARSER_BITFIELD ( wep,            1, bool );
56         SENF_PARSER_BITFIELD ( shortPreamble,  1, bool );
57         SENF_PARSER_BITFIELD ( cfp,            1, bool );
58
59         SENF_PARSER_FINALIZE ( RadiotapPacketParser_Flags );
60
61         friend class RadiotapPacketParser;
62     };
63
64     /** \brief Parse in Radiotap Header channel frequency and flag field
65
66         <b>Re-ordering of bits due to LSB byte order</b>
67      */
68     struct RadiotapPacketParser_ChannelOptions : public PacketParserBase
69     {
70 #       include SENF_FIXED_PARSER()
71
72         SENF_PARSER_FIELD     ( freq,          UInt16LSBParser );
73
74         SENF_PARSER_BITFIELD  ( flag2ghz,             1, bool  );
75         SENF_PARSER_BITFIELD  ( ofdm,                 1, bool  );
76         SENF_PARSER_BITFIELD  ( cck,                  1, bool  );
77         SENF_PARSER_BITFIELD  ( turbo,                1, bool  );
78         SENF_PARSER_SKIP_BITS ( 4                              );
79         SENF_PARSER_BITFIELD  ( quarterRateChannel,   1, bool  );
80         SENF_PARSER_BITFIELD  ( halfRateChannel,      1, bool  );
81         SENF_PARSER_BITFIELD  ( gsm,                  1, bool  );
82         SENF_PARSER_BITFIELD  ( staticTurbo,          1, bool  );
83         SENF_PARSER_BITFIELD  ( gfsk,                 1, bool  );
84         SENF_PARSER_BITFIELD  ( cckOfdm,              1, bool  );
85         SENF_PARSER_BITFIELD  ( passive,              1, bool  );
86         SENF_PARSER_BITFIELD  ( flag5ghz,             1, bool  );
87
88         SENF_PARSER_FINALIZE ( RadiotapPacketParser_ChannelOptions );
89     };
90
91     struct RadiotapPacketParser_RxFlags : public PacketParserBase
92     {
93 #       include SENF_FIXED_PARSER()
94
95         SENF_PARSER_SKIP_BITS ( 6                              );
96         SENF_PARSER_BITFIELD  ( badPlcp,              1, bool  );
97         SENF_PARSER_SKIP_BITS ( 1                              );
98
99         SENF_PARSER_FINALIZE( RadiotapPacketParser_RxFlags );
100     };
101
102     struct RadiotapPacketParser_TxFlags : public PacketParserBase
103     {
104 #       include SENF_FIXED_PARSER()
105
106         SENF_PARSER_SKIP_BITS ( 5                              );
107         SENF_PARSER_BITFIELD  ( txRts,                1, bool  );
108         SENF_PARSER_BITFIELD  ( txCts,                1, bool  );
109         SENF_PARSER_BITFIELD  ( fail,                 1, bool  );
110
111         SENF_PARSER_FINALIZE( RadiotapPacketParser_TxFlags );
112     };
113
114     /** \brief Parse an Radiotap header
115
116         Parser implementing the Radiotap header
117
118         Radiotap requires that all fields in the radiotap header
119         are aligned to natural boundaries. For radiotap,
120         that means all 8-, 16-, 32-, and 64-bit fields
121         must begin on 8-, 16-, 32-, and 64-bit boundaries, respectively.
122         In this way, generators and parsers can avoid unaligned
123         accesses to radiotap capture fields. Radiotap-compliant
124         generators must insert padding before a capture field
125         to ensure its natural alignment.
126
127         \see <a href="http://www.radiotap.org">Radiotap.org</a>
128
129         \todo extended present field (bit 31 of present field is set)
130     */
131     struct RadiotapPacketParser_Header : public PacketParserBase
132     {
133 #       include SENF_FIXED_PARSER()
134
135         /*
136          * mandatory fields
137          */
138         SENF_PARSER_FIELD ( version, UInt8Parser     );
139         //padding bits, currently unused, it simply aligns the fields onto natural word boundaries.
140         SENF_PARSER_SKIP  ( 1                        );
141         SENF_PARSER_FIELD ( length,  UInt16LSBParser );
142
143         SENF_PARSER_PRIVATE_FIELD ( presentFlags, UInt32LSBParser );
144
145         SENF_PARSER_FINALIZE ( RadiotapPacketParser_Header );
146
147         enum PresentIndex {
148             // Could use the the entries from radiotap.h but I don't know,
149             // if I want to pollute the global and macro namespace even more ...
150             TSFT_INDEX              =  0,
151             FLAGS_INDEX             =  1,
152             RATE_INDEX              =  2,
153             CHANNEL_INDEX           =  3,
154             FHSS_INDEX              =  4,
155             DBM_ANTSIGNAL_INDEX     =  5,
156             DBM_ANTNOISE_INDEX      =  6,
157             LOCK_QUALITY_INDEX      =  7,
158             TX_ATTENUATION_INDEX    =  8,
159             DB_TX_ATTENUATION_INDEX =  9,
160             DBM_TX_POWER_INDEX      = 10,
161             ANTENNA_INDEX           = 11,
162             DB_ANTSIGNAL_INDEX      = 12,
163             DB_ANTNOISE_INDEX       = 13,
164             RX_FLAGS_INDEX          = 14,
165             TX_FLAGS_INDEX          = 15,
166             RTS_RETRIES_INDEX       = 16,
167             DATA_RETRIES_INDEX      = 17,
168
169             MAX_INDEX               = 17,
170
171             RADIOTOP_NS_INDEX       = 29,
172             VENDOR_NS_INDEX         = 30,
173             EXTENDED_BITMASK_INDEX  = 31
174         };
175
176         enum PresentFlag {
177             TSFT_FLAG               = (1<<TSFT_INDEX),
178             FLAGS_FLAG              = (1<<FLAGS_INDEX),
179             RATE_FLAG               = (1<<RATE_INDEX),
180             CHANNEL_FLAG            = (1<<CHANNEL_INDEX),
181             FHSS_FLAG               = (1<<FHSS_INDEX),
182             DBM_ANTSIGNAL_FLAG      = (1<<DBM_ANTSIGNAL_INDEX),
183             DBM_ANTNOISE_FLAG       = (1<<DBM_ANTNOISE_INDEX),
184             LOCK_QUALITY_FLAG       = (1<<LOCK_QUALITY_INDEX),
185             TX_ATTENUATION_FLAG     = (1<<TX_ATTENUATION_INDEX),
186             DB_TX_ATTENUATION_FLAG  = (1<<DB_TX_ATTENUATION_INDEX),
187             DBM_TX_POWER_FLAG       = (1<<DBM_TX_POWER_INDEX),
188             ANTENNA_FLAG            = (1<<ANTENNA_INDEX),
189             DB_ANTSIGNAL_FLAG       = (1<<DB_ANTSIGNAL_INDEX),
190             DB_ANTNOISE_FLAG        = (1<<DB_ANTNOISE_INDEX),
191             RX_FLAGS_FLAG           = (1<<RX_FLAGS_INDEX),
192             TX_FLAGS_FLAG           = (1<<TX_FLAGS_INDEX),
193             RTS_RETRIES_FLAG        = (1<<RTS_RETRIES_INDEX),
194             DATA_RETRIES_FLAG       = (1<<DATA_RETRIES_INDEX),
195
196             RADIOTOP_NS_FLAG        = (1<<RADIOTOP_NS_INDEX),
197             VENDOR_NS_FLAG          = (1<<VENDOR_NS_INDEX),
198             EXTENDED_BITMASK_FLAG   = (1<<EXTENDED_BITMASK_INDEX)
199         };
200
201         static unsigned const FIELD_SIZE[MAX_INDEX+2];
202     };
203
204     struct RadiotapPacketParser_FrameType : public PacketParserBase
205     {
206 #       include SENF_FIXED_PARSER()
207
208         SENF_PARSER_SKIP_BITS(4);
209         SENF_PARSER_BITFIELD_RO( frameType, 2, unsigned );
210         SENF_PARSER_SKIP_BITS(2);
211
212         SENF_PARSER_FINALIZE(RadiotapPacketParser_FrameType);
213     };
214
215     struct RadiotapPacketParser : public RadiotapPacketParser_Header
216     {
217         RadiotapPacketParser(data_iterator i, state_type s);
218
219         static const size_type init_bytes = RadiotapPacketParser_Header::fixed_bytes;
220
221         size_type bytes() const;
222
223         //-////////////////////////////////////////////////////////////////////////
224
225 #       define FIELD(name,type,index)                                   \
226             typedef type name ## _t;                                    \
227             type name() { return parseField<type>(index); }             \
228             bool has_ ## name() { return currentTable()[index]; }       \
229             bool name ## Present() { return has_ ## name(); }           \
230             type init_ ## name() { initField(index); return name(); }   \
231             void disable_ ## name() { disableField(index); }
232
233         FIELD( tsft,              UInt64LSBParser,                      TSFT_INDEX              );
234
235         // flags is special: disabling 'flags' must also disable the 'fcs' field
236         typedef RadiotapPacketParser_Flags flags_t;
237         flags_t flags() { return parseField<flags_t>(FLAGS_INDEX); }
238         bool has_flags() { return currentTable()[FLAGS_INDEX]; }
239         bool flagsPresent() { return has_flags(); }
240         flags_t init_flags() { initField(FLAGS_INDEX); return flags(); }
241         void disable_flags() { disable_fcs(); disableField(FLAGS_INDEX); }
242
243         FIELD( rate,              UInt8Parser,                          RATE_INDEX              );
244         FIELD( channelOptions,    RadiotapPacketParser_ChannelOptions,  CHANNEL_INDEX           );
245         FIELD( fhss,              UInt16LSBParser,                      FHSS_INDEX              );
246         FIELD( dbmAntennaSignal,  Int8Parser,                           DBM_ANTSIGNAL_INDEX     );
247         FIELD( dbmAntennaNoise,   Int8Parser,                           DBM_ANTNOISE_INDEX      );
248         FIELD( lockQuality,       UInt16LSBParser,                      LOCK_QUALITY_INDEX      );
249         FIELD( txAttenuation,     UInt16LSBParser,                      TX_ATTENUATION_INDEX    );
250         FIELD( dbTxAttenuation,   UInt16LSBParser,                      DB_TX_ATTENUATION_INDEX );
251         FIELD( dbmTxAttenuation,  Int8Parser,                           DBM_TX_POWER_INDEX      );
252         FIELD( antenna,           UInt8Parser,                          ANTENNA_INDEX           );
253         FIELD( dbAntennaSignal,   UInt8Parser,                          DB_ANTSIGNAL_INDEX      );
254         FIELD( dbAntennaNoise,    UInt8Parser,                          DB_ANTNOISE_INDEX       );
255         FIELD( rxFlags,           RadiotapPacketParser_RxFlags,         RX_FLAGS_INDEX          );
256         FIELD( txFlags,           RadiotapPacketParser_TxFlags,         TX_FLAGS_INDEX          );
257         FIELD( rtsRetries,        UInt8Parser,                          RTS_RETRIES_INDEX       );
258         FIELD( dataRetries,       UInt8Parser,                          DATA_RETRIES_INDEX      );
259
260 #       undef FIELD
261
262         typedef UInt32Parser fcs_t;
263         UInt32Parser fcs();
264         bool has_fcs();
265         UInt32Parser init_fcs();
266         void disable_fcs();
267
268         unsigned frameType();
269
270     private:
271         static const size_type fixed_bytes = 0; // hide this member, just in case
272
273         typedef boost::array<size_type,MAX_INDEX+2> OffsetTable;
274         typedef std::map<boost::uint32_t, OffsetTable> OffsetMap;
275
276         //-////////////////////////////////////////////////////////////////////////
277         // Offset table handling
278
279         static OffsetTable & offsetTable(boost::uint32_t presentFlags);
280         // Fills the offset table based on a packet
281         static void parseOffsetTable(boost::uint8_t * data, int maxLength, OffsetTable & table);
282         // Generate an offset table just from the present flags
283         static void buildOffsetTable(boost::uint32_t presentFlags, OffsetTable & table);
284
285         //-////////////////////////////////////////////////////////////////////////
286
287         OffsetTable const & currentTable() const;
288         OffsetTable const & getTable(boost::uint32_t presentFlags) const;
289
290         template <class Parser>
291         Parser parseField(unsigned index);
292         void initField(unsigned index);
293         void disableField(unsigned index);
294
295         size_type calculateSize() const;
296
297         void updatePresentFlags(boost::uint32_t flags);
298         void insertRemoveBytes(unsigned from, unsigned to, int bytes);
299
300         static OffsetMap offsetMap_;
301         OffsetTable const * currentTable_;
302
303         friend class RadiotapPacketType;
304     };
305
306     /** \brief Radiotap packet
307
308         \par Packet type (typedef):
309             \ref RadiotapPacket
310
311         \par Fields:
312             \ref RadiotapPacketParser
313             \image html RadiotapPacket.png
314
315         \see http://www.radiotap.org/
316
317         \ingroup protocolbundle_80211
318      */
319     struct RadiotapPacketType
320         : public PacketTypeBase,
321           public PacketTypeMixin<RadiotapPacketType>
322     {
323         typedef PacketTypeMixin<RadiotapPacketType> mixin;
324         typedef ConcretePacket<RadiotapPacketType> packet;
325         typedef RadiotapPacketParser parser;
326
327         using mixin::initSize;
328
329         static void init(packet p);
330         static void dump(packet p, std::ostream & os);
331         static factory_t nextPacketType(packet p);
332         static optional_range nextPacketRange(packet const & p);
333     };
334
335     typedef ConcretePacket<RadiotapPacketType> RadiotapPacket;
336 }
337
338 //-/////////////////////////////////////////////////////////////////////////////////////////////////
339 #include "RadiotapPacket.cci"
340 //#include "RadiotapPacket.ct"
341 #include "RadiotapPacket.cti"
342 #endif
343
344 \f
345 // Local Variables:
346 // mode: c++
347 // fill-column: 100
348 // comment-column: 40
349 // c-file-style: "senf"
350 // indent-tabs-mode: nil
351 // ispell-local-dictionary: "american"
352 // compile-command: "scons -u test"
353 // End: