Packets/80211Bundle: Read-only radiotap reimplementation
[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
56     /** \brief Parse in Radiotap Header channel frequency and flag field
57
58         <b>Re-ordering of bits due to LSB byte order</b>
59      */
60     struct RadiotapPacketParser_ChannelOptions : public PacketParserBase
61     {
62 #       include SENF_FIXED_PARSER()
63
64         SENF_PARSER_FIELD     ( freq,          UInt16LSBParser );
65
66         SENF_PARSER_BITFIELD  ( flag2ghz,             1, bool  );
67         SENF_PARSER_BITFIELD  ( ofdm,                 1, bool  );
68         SENF_PARSER_BITFIELD  ( cck,                  1, bool  );
69         SENF_PARSER_BITFIELD  ( turbo,                1, bool  );
70         SENF_PARSER_SKIP_BITS ( 4                              ); //currently unused in radiotap
71         SENF_PARSER_BITFIELD  ( quarterRateChannel,   1, bool  );
72         SENF_PARSER_BITFIELD  ( halfRateChannel,      1, bool  );
73         SENF_PARSER_BITFIELD  ( gsm,                  1, bool  );
74         SENF_PARSER_BITFIELD  ( staticTurbo,          1, bool  );
75         SENF_PARSER_BITFIELD  ( gfsk,                 1, bool  );
76         SENF_PARSER_BITFIELD  ( cckOfdm,              1, bool  );
77         SENF_PARSER_BITFIELD  ( passive,              1, bool  );
78         SENF_PARSER_BITFIELD  ( flag5ghz,             1, bool  );
79
80         SENF_PARSER_FINALIZE ( RadiotapPacketParser_ChannelOptions );
81     };
82
83     /** \brief Parse an Radiotap header
84
85         Parser implementing the Radiotap header
86
87         Radiotap requires that all fields in the radiotap header
88         are aligned to natural boundaries. For radiotap,
89         that means all 8-, 16-, 32-, and 64-bit fields
90         must begin on 8-, 16-, 32-, and 64-bit boundaries, respectively.
91         In this way, generators and parsers can avoid unaligned
92         accesses to radiotap capture fields. Radiotap-compliant
93         generators must insert padding before a capture field
94         to ensure its natural alignment.
95
96         \see <a href="http://www.radiotap.org">Radiotap.org</a>
97
98         \todo extended present field (bit 31 of present field is set)
99     */
100     struct RadiotapPacketParser_Header : public PacketParserBase
101     {
102 #       include SENF_FIXED_PARSER()
103
104         /*
105          * mandatory fields
106          */
107         SENF_PARSER_FIELD ( version, UInt8Parser     );
108         //padding bits, currently unused, it simply aligns the fields onto natural word boundaries.
109         SENF_PARSER_SKIP  ( 1                        );
110         SENF_PARSER_FIELD ( length,  UInt16LSBParser );
111
112         SENF_PARSER_PRIVATE_FIELD ( presentFlags, UInt32LSBParser );
113         SENF_PARSER_GOTO( presentFlags );
114
115         /*
116          * present flags
117          * indicate which data field are contained in the packet
118          */
119         SENF_PARSER_BITFIELD_RO ( lockQualityPresent,      1, bool );
120         SENF_PARSER_BITFIELD_RO ( dbmAntennaNoisePresent,  1, bool );
121         SENF_PARSER_BITFIELD_RO ( dbmAntennaSignalPresent, 1, bool );
122         SENF_PARSER_BITFIELD_RO ( fhssPresent,             1, bool );
123         SENF_PARSER_BITFIELD_RO ( channelOptionsPresent,   1, bool );
124         SENF_PARSER_BITFIELD_RO ( ratePresent,             1, bool );
125         SENF_PARSER_BITFIELD_RO ( flagsPresent,            1, bool );
126         SENF_PARSER_BITFIELD_RO ( tsftPresent,             1, bool );
127         SENF_PARSER_SKIP_BITS   ( 1                                ); //currently unused bits
128         SENF_PARSER_BITFIELD_RO ( headerFcsPresent,        1, bool );
129         SENF_PARSER_BITFIELD_RO ( dbAntennaNoisePresent,   1, bool );
130         SENF_PARSER_BITFIELD_RO ( dbAntennaSignalPresent,  1, bool );
131         SENF_PARSER_BITFIELD_RO ( antennaPresent,          1, bool );
132         SENF_PARSER_BITFIELD_RO ( dbmTxAttenuationPresent, 1, bool );
133         SENF_PARSER_BITFIELD_RO ( dbTxAttenuationPresent,  1, bool );
134         SENF_PARSER_BITFIELD_RO ( txAttenuationPresent,    1, bool );
135         SENF_PARSER_SKIP_BITS   ( 8                                ); //currently unused bits
136         //if bit is set,another 32 bit present flag is attached (not implemented yet)
137         SENF_PARSER_BITFIELD_RO ( extendedBitmaskPresent,  1, bool );
138         SENF_PARSER_SKIP_BITS   ( 7                                ); //currently unused bits
139
140         SENF_PARSER_FINALIZE ( RadiotapPacketParser_Header );
141     };
142
143     struct RadiotapPacketParser_FrameType : public PacketParserBase
144     {
145 #       include SENF_FIXED_PARSER()
146
147         SENF_PARSER_SKIP_BITS(4);
148         SENF_PARSER_BITFIELD_RO( frameType, 2, unsigned );
149         SENF_PARSER_SKIP_BITS(2);
150
151         SENF_PARSER_FINALIZE(RadiotapPacketParser_FrameType);
152     };
153
154     struct RadiotapPacketParser : public RadiotapPacketParser_Header
155     {
156         RadiotapPacketParser(data_iterator i, state_type s) : RadiotapPacketParser_Header(i,s) {}
157
158         static const size_type init_bytes = RadiotapPacketParser_Header::fixed_bytes;
159
160         size_type bytes() const { return length(); }
161
162         // ////////////////////////////////////////////////////////////////////////
163
164         UInt64LSBParser            tsft()
165             { return parseField<UInt64LSBParser>             (0); }
166         RadiotapPacketParser_Flags flags()
167             { return parseField<RadiotapPacketParser_Flags>  (1); }
168         UInt8Parser                rate()
169             { return parseField<UInt8Parser>                 (2); }
170         RadiotapPacketParser_ChannelOptions channelOptions()
171             { return parseField<RadiotapPacketParser_ChannelOptions>(3); }
172         UInt16LSBParser            fhss()
173             { return parseField<UInt16LSBParser>             (4); }
174         Int8Parser                 dbmAntennaSignal()
175             { return parseField<Int8Parser>                  (5); }
176         Int8Parser                 dbmAntennaNoise()
177             { return parseField<Int8Parser>                  (6); }
178         UInt16LSBParser            lockQuality()
179             { return parseField<UInt16LSBParser>             (7); }
180         UInt16LSBParser            txAttenuation()
181             { return parseField<UInt16LSBParser>             (8); }
182         UInt16LSBParser            dbTxAttenuation()
183             { return parseField<UInt16LSBParser>             (9); }
184         Int8Parser                 dbmTxAttenuation()
185             { return parseField<Int8Parser>                 (10); }
186         UInt8Parser                antenna()
187             { return parseField<UInt8Parser>                (11); }
188         UInt8Parser                dbAntennaSignal()
189             { return parseField<UInt8Parser>                (12); }
190         UInt8Parser                dbAntennaNoise()
191             { return parseField<UInt8Parser>                (13); }
192         UInt32Parser               headerFcs()
193             { return parseField<UInt32Parser>               (14); }
194
195         unsigned frameType()
196             { return parse<RadiotapPacketParser_FrameType>(length()).frameType(); }
197
198         UInt32Parser fcs()
199             { return parse<senf::UInt32Parser>(data().end()-4); }
200
201     private:
202         static const size_type fixed_bytes = 0; // 'remove' this member ...
203         static const unsigned MAX_INDEX = 14;
204
205         typedef boost::array<size_type,MAX_INDEX+2> OffsetTable;
206
207         OffsetTable const & offsetTable(boost::uint32_t presentFlags);
208         static void fillOffsetTable(boost::uint8_t * data, int maxLength, OffsetTable & table);
209
210         template <class Parser>
211         Parser parseField(unsigned index)
212             { return parse<Parser>(offsetTable(presentFlags())[index]); }
213
214         size_type calculateSize()
215             { return offsetTable(presentFlags())[MAX_INDEX+1]; }
216
217         friend class RadiotapPacketType;
218     };
219
220     /** \brief Radiotap packet
221
222         \par Packet type (typedef):
223             \ref RadiotapPacket
224
225         \par Fields:
226             \ref RadiotapPacketParser
227             \image html RadiotapPacket.png
228
229         \see http://www.radiotap.org/
230
231         \ingroup protocolbundle_80211
232      */
233     struct RadiotapPacketType
234         : public PacketTypeBase,
235           public PacketTypeMixin<RadiotapPacketType>
236     {
237         typedef PacketTypeMixin<RadiotapPacketType> mixin;
238         typedef ConcretePacket<RadiotapPacketType> packet;
239         typedef RadiotapPacketParser parser;
240
241         using mixin::init;
242         using mixin::initSize;
243
244         static void dump(packet p, std::ostream &os);
245         static void finalize(packet p);
246         static factory_t nextPacketType(packet p);
247         static optional_range nextPacketRange(packet p);
248     };
249
250     typedef ConcretePacket<RadiotapPacketType> RadiotapPacket;
251 }
252
253 ///////////////////////////////hh.e////////////////////////////////////////
254 //#include "RadiotapPacket.cci"
255 //#include "RadiotapPacket.ct"
256 //#include "RadiotapPacket.cti"
257 #endif
258
259 \f
260 // Local Variables:
261 // mode: c++
262 // fill-column: 100
263 // comment-column: 40
264 // c-file-style: "senf"
265 // indent-tabs-mode: nil
266 // ispell-local-dictionary: "american"
267 // compile-command: "scons -u test"
268 // End: