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