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