2 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
3 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
4 // Stefan Bund <g0dil@berlios.be>
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the
18 // Free Software Foundation, Inc.,
19 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 \brief PacketParser public header */
24 /** \defgroup packetparser The PacketParser facility
26 The PacketParser facility provides a framework to implement very lightweight classes which parse
27 the raw content of a packet into meaningful values. PacketParsers are always passed around
28 <em>by value</em>, they can be understood as pointers into the packet data with added type
29 information providing parsing functions.
31 Parsers are built hierarchically. A high-level parser will return other parsers when accessing
32 an element (Example: Asking an EthernetParser for the ethertype field by calling the parsers \c
33 type() member will return an \c UInt16 parser). The lowest level building blocks then return the
34 values. This hierarchical structure greatly simplifies building complex parsers.
36 Since parsers are very lightweight and are passed by value, packet fields are accessed using the
37 corresponding accessor method:
42 // Assign new value to an integer parser
45 // Write out above value
46 std::cerr << p->someField() << "\n";
48 // Use the generic parser-assignment operator '<<' to copy field values
49 p->someVector()[1].someOtherField() << q->someField();
50 p->someVector() << q->someVector()
53 Here \c someField(), \c someOtherField() and \c someVector() are accessor methods named after
54 the field name. Each returns a parser object. Simple parsers can be used like their
55 corresponding basic type (e.g. a Parse_UInt16 field can be used like an unsigned integer), more
56 complex parsers provide type specific access members. Assigning a value to a parser will change
57 the underlying representation (the packet data).
59 More complex parsers (especially those representing a collection of values) provide an
60 additional wrapper class for mutating access (e.g. Parse_Vector provides a container wrapper
61 with am STL compatible random-access sequence interface). See the documentation of the specific
62 parser for the wrapper specification.
64 Every parser is derived from senf::PacketParserBase. This class provides the necessary
65 housekeeping information and provides the parsers with access to the data.
68 #ifndef HH_PacketParser_
69 #define HH_PacketParser_ 1
72 #include <boost/utility/enable_if.hpp>
73 #include <boost/type_traits.hpp>
74 #include <boost/optional.hpp>
75 #include "Utils/SafeBool.hh"
76 #include "PacketTypes.hh"
77 #define HH_PacketData_DeclOnly
78 #include "PacketData.hh"
79 #undef HH_PacketData_DeclOnly
81 #include "PacketParser.mpp"
82 ///////////////////////////////hh.p////////////////////////////////////////
86 /** \brief Parser Base class
88 Parsers come in two favors: fixed and dynamically sized parsers. A <em>fixed size
89 parser</em> has a constant size, it will always parse a fixed number of bytes. The low-level
90 'final' parsers (like the integer parsers) are fixed size parsers as are composite parsers
91 built up only of fixed-size fields.
93 A <em>dynamically sized</em> parser on the other hand infers it's size from the contents of
94 the data parsed. Any parser containing at least one dynamically sized sub-parser will itself
97 Both kinds of parser need to derive from PacketParserBase and implement several required
98 members. Which members to implement depends on the parsers flavor. There are two ways how to
100 \li If the parser just consists of a simple sequence of consecutive fields (sub-parsers),
101 the \ref SENF_PACKET_PARSER_DEFINE_FIELDS and \ref
102 SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS macros provide a simple and convenient way to
104 \li In more complex cases, you need to implement the necessary members manually.
106 This documentation is about the manual implementation. You should nevertheless read through
107 this to understand, what above macros are doing.
109 The following example documents the interface (which must be) provided by a parser:
111 struct FooParser : public PacketParserBase
113 FooParser(data_iterator i, state_type s) : PacketParserBase(i,s) {}
115 // If this parser has a fixed size, you must define this size here This definition
116 // allows the parser to be used within the list, vector and array parsers static
117 static const size_type fixed_bytes = some_constant_size;
119 // If the parser does not have a fixed size, you must implement the bytes() member to
120 // return the size. ONLY EVER DEFINE ONE OF fixed_bytes OR bytes().
121 size_type bytes() const;
123 // If you define bytes(), you also need to define the init_bytes. This is the number
124 // of bytes to allocate when creating a new object
125 static const size_type init_bytes = some_constant_size;
127 // You also may define an init() member. This will be called to initialize a newly
128 // created data object. The default implementation just does nothing.
131 // ////////////////////////////////////////////////////////////////////////
133 // Add here members returning (sub-)parsers for the fields. The 'parse' member is
134 // used to construct the sub-parsers. This member either takes an iterator to the
135 // data to be parsed or just an offset in bytes.
137 senf::Parse_UInt16 type() const { return parse<Parse_UInt16>( 0 ); }
138 senf::Parse_UInt16 size() const { return parse<Parse_UInt16>( 2 ); }
142 You should never call the \c bytes() member of a parser directly. Instead you should use the
143 freestanding senf::bytes() function. This function will return the correct size irrespective
144 of the parsers flavor. You may access \c fixed_bytes directly, however be aware that this
145 will restrict your code to fixed size parsers (which depending on the circumstances may be
146 exactly what you want).
148 In the same way, don't access \c init_bytes directly, always use the senf::init_bytes
149 meta-function class which correctly supports fixed size parsers.
151 \ingroup packetparser
153 class PacketParserBase
156 ///////////////////////////////////////////////////////////////////////////
159 typedef detail::packet::iterator data_iterator; ///< Raw data iterator type
160 typedef detail::packet::size_type size_type; ///< Unsigned integral type
161 typedef detail::packet::difference_type difference_type; ///< Signed integral type
162 typedef detail::packet::byte byte; ///< Unsigned 8bit value, the raw value type
163 typedef PacketData * state_type; ///< Type of the 'state' parameter
165 ///////////////////////////////////////////////////////////////////////////
166 ///\name Structors and default members
169 // no default constructor
171 // default destructor
172 // no conversion constructors
175 ///////////////////////////////////////////////////////////////////////////
177 data_iterator i() const; ///< Return beginning of data to parse
178 /**< The parser is expected to interpret the data beginning
179 here. The size of the interpreted is given by
180 <tt>senf::bytes(</tt><em>parser
181 instance</em><tt>)</tt>. */
182 state_type state() const; ///< Return state of this parser
183 /**< The value returned should be interpreted as an opaque
184 value provided just to be forwarded to other
186 PacketData & data() const; ///< Access the packets raw data container
187 /**< This member will return the raw data container holding
188 the data which is parsed by \c this parser. */
190 void init() const; ///< Default implementation
191 /**< This is just an empty default
192 implementation. Re-implement this member in your own
193 parsers if needed. */
196 PacketParserBase(data_iterator i, state_type s); ///< Standard constructor
197 /**< This is the constructor used by most parsers. The
198 parameters are just forwarded from the derived classes
199 constructor parameters. */
200 PacketParserBase(data_iterator i, state_type s, size_type size);
201 ///< Size checking constructor
202 /**< In addition to the standard constructor, this
203 constructor will validate, that there is enough data in
204 the raw data container to parse \a size bytes after \a
207 This constructor is called by all 'final' parsers
208 (e.g. the integer parsers) and \e only by those
209 parsers. Most parsers do \e not check the validity of
210 the iterator, this is delayed until the very last
211 parser. This allows to partial parse truncated
214 \throw TruncatedPacketException if the raw data
215 container does not hold at least \a size bytes
216 beginning at \a i. */
218 bool check(size_type size); ///< Check size of data container
219 /**< \returns \c true, if the data container holds at least
220 \a size beginning at i(), \c false otherwise. */
221 void validate(size_type size); ///< Validate size of data container
222 /**< \throws TruncatedPacketException if the raw data
223 container does not hold at least \a size bytes
226 template <class Parser> Parser parse(data_iterator i) const; ///< Create sub-parser
227 /**< Creates a new instance of \a Parser to parse data
228 beginning at \a i. Automatically passes \a state() to
230 template <class Parser> Parser parse(size_type n) const; ///< Create sub-parser
231 /**< Creates a new instance of \a Parser to parse data
232 * beginning at i()<tt> + </tt>\a n. Automatically passes \a
233 state() to the new parser. */
235 void defaultInit() const; ///< Default implementation
236 /**< This is just an empty default
237 implementation. Re-implement this member in your own
238 parsers if needed. */
246 template <class Parser> friend class SafePacketParser;
249 /** \brief Return raw size parsed by the given parser object
251 This function will either call <tt>p.bytes()</tt> or return <tt>Parser::fixed_bytes</tt>
252 depending on the type of parser.
254 The value returned does \e not take into account the amount of data actually available. So
255 you always need to validate this value against the packet size if you directly access the
256 data. The standard low-level parses all do this check automatically to guard against
259 \param[in] p Parser object to check
260 \returns number of bytes this parser expects to parser
261 \ingroup packetparser
263 template <class Parser>
264 PacketParserBase::size_type bytes(Parser p);
266 namespace detail { template <class Parser> class ParserInitBytes; }
268 /** \brief Return number of bytes to allocate to new object of given type
270 This meta-function is called like
272 senf::init_bytes<SomeParser>::value
275 This expression evaluates to a compile-time constant integral expression of type
276 senf::PacketParserBase::size_type. This meta-function will return \c Parser::fixed_bytes or
277 \c Parser::init_bytes depending on the type of parser.
279 \param[in] Parser The Parser to return init_bytes for
280 \returns Number of bytes to allocate to the new object
281 \ingroup packetparser
283 template <class Parser>
284 struct init_bytes : public detail::ParserInitBytes<Parser>
287 /** \brief Generic parser copying
289 This operator allows to copy the values of identical parsers. This operation does \e not
290 depend on the parsers detailed implementation, it will just replace the data bytes of the
291 target parser with those from the source parser. This allows to easily copy around complex
292 packet substructures.
294 This operation is different from the ordinary assignment operator: It does not change the \a
295 target parser, it changes the data referenced by the \a target parser.
297 \ingroup packetparser
299 template <class Parser>
300 typename boost::enable_if<
301 boost::is_base_of<PacketParserBase, Parser>,
303 operator<<(Parser target, Parser source);
305 /** \brief Generic parser value assignment
307 This operator allows to assign a value to parsers which implement a <tt>value(</tt>\a
308 value<tt>)</tt> member. This operator allows to use a common syntax for assigning values or
311 \ingroup packetparser
313 template <class Parser, class Value>
314 typename boost::enable_if_c <
315 boost::is_base_of<PacketParserBase, Parser>::value
316 && ! boost::is_base_of<PacketParserBase, Value>::value,
318 operator<<(Parser target, Value const & value);
320 /** \defgroup packetparsermacros Helper macros for defining new packet parsers
322 To simplify the definition of simple packet parsers, several macros are provided. Before
323 using these macros you should familiarize yourself with the packet parser interface as
324 described in senf::PacketParserBase.
326 These macros simplify providing the above defined interface. A typical packet declaration
327 using these macros has the following form (This is a concrete example from the definition of
328 the ethernet packet in <tt>DefaultBundle//EthernetPacket.hh</tt>)
330 struct Parse_EthVLan : public senf::PacketParserBase
332 SENF_PACKET_PARSER_INIT(Parse_EthVLan);
334 // ////////////////////////////////////////////////////////////////////////
336 typedef senf::Parse_UIntField < 0, 3 > Parse_Priority;
337 typedef senf::Parse_Flag < 3 > Parse_CFI;
338 typedef senf::Parse_UIntField < 4, 16 > Parse_VLanId;
339 typedef senf::Parse_UInt16 Parse_Type;
341 SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS(
342 ((OverlayField)( priority, Parse_Priority ))
343 ((OverlayField)( cfi, Parse_CFI ))
344 ((Field )( vlanId, Parse_VLanId ))
345 ((Field )( type, Parse_Type ))
350 The macros take care of the following:
351 \li They define the accessor functions returning parsers of the given type.
352 \li They automatically calculate the offset of the fields from the preceding fields.
353 \li The macros provide a definition for \c init()
354 \li The macros define the \c bytes(), \c fixed_bytes and \c init_bytes members as needed.
356 You may define either a fixed or a dynamically sized parser. Fixed size parsers are defined
357 using \ref SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS, dynamically sized parsers are defined
358 using \ref SENF_PACKET_PARSER_DEFINE_FIELDS. The different members are implemented such
361 \li The needed parser constructor is defined
362 \li \c init() calls \c defaultInit(). \c defaultInit() is defined to call \c init() on each
364 \li \c bytes() (on dynamically sized parser) respectively \c fixed_bytes (on fixed size
365 parsers) is defined to return the sum of the sizes of all fields.
366 \li On dynamically sized parsers, \c init_bytes is defined to return the sum of the
367 \c init_size's of all fields
369 The central definition macros are \ref SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS and \ref
370 SENF_PACKET_PARSER_DEFINE_FIELDS. The argument to both has the same structure. It is a
371 (boost preprocessor style) sequence of field definitions where each field definition
372 provides the builder macro to use and the name and type of the field to define:
374 SENF_PACKET_PARSER_DEFINE[_FIXED]_FIELDS(
375 (( <builder> )( <name>, <type> ))
380 For each field, this command will define
381 \li A method \a name() returning an instance of the \a type parser
382 \li \a name<tt>_t</tt> as a typedef for \a type, the fields value
383 \li \a name<tt>_offset</tt> to give the offset of the field from the beginning of the
384 parser. If the parser is a fixed size parser, this will be a static constant, otherwise
387 The \a builder argument selects, how the field is defined
388 \li <tt>Field</tt> defines a field and increments the current position by the size of the
390 \li <tt>OverlayField</tt> defines a field like <tt>Field</tt> but does \e not increment the
391 position. In the above example, this is used to overlay the different bitfield parsers:
392 All overlaying bitfield parser except the last one (the one with the highest bit
393 numbers) is marked as OverlayField.
395 The \a name argument defines the name of the accessor method.
397 The \a type argument is the parser to return for that field. Since none of the arguments may
398 contain a comma, <em>This argument cannot be a multi-parameter template</em>. Always use
399 typedefs to access templated parsers as shown above.
401 The \ref SENF_PACKET_PARSER_INIT macro defines the constructor and the \c init() member. If
402 you want to provide your own \c init() implementation, use \ref
403 SENF_PACKET_PARSER_NO_INIT. The first statement in your init method should probably to call
404 \c defaultInit(). This will call the \c init() member of all the fields. Afterwards you can
405 set up the field values as needed:
407 struct SomePacket : public senf::PacketParserBase
409 SENF_PACKET_PARSER_NO_INIT(SomePacket);
411 typedef senf::Parse_UInt8 Parse_Type;
412 typedef senf::Parse_Vector< senf::Parse_UInt32,
413 senf::SimpleVectorSizer<senf::Parse_UInt16>
416 SENF_PACKET_PARSER_DEFINE_FIELDS(
417 ((Field)( type, Parse_Type ))
418 ((Field)( elements, Parse_Elements ))
424 elements().push_back(0x01020304u);
429 \ingroup packetparser
432 /** \brief Define initialization members of a parser
434 This macro defines the packet parser constructor and the \c init() member. \c init() is
435 defined to just call \c defaultInit() which is defined by the other macros to call \c init()
436 on each of the parsers fields.
438 \ingroup packetparsermacros
441 # define SENF_PACKET_PARSER_INIT(name) \
442 name(data_iterator i, state_type s) : senf::PacketParserBase(i,s) {} \
443 void init() const { defaultInit(); }
445 /** \brief Define initialization members of a parser except init()
447 This macro is like SENF_PACKET_PARSER_INIT but does \e not define \c init(). This allows you
448 to provide your own implementation. You should call \c defaultInit() first before
449 initializing your data fields.
451 \ingroup packetparsermacros
454 # define SENF_PACKET_PARSER_NO_INIT(name) \
455 name(data_iterator i, state_type s) : senf::PacketParserBase(i,s) {}
457 /** \brief Define fields for a dynamically sized parser
459 Define the fields as specified in \a fields. This macro supports dynamically sized
460 subfields, the resulting parser will be dynamically sized.
462 \ingroup packetparsermacros
465 # define SENF_PACKET_PARSER_DEFINE_FIELDS(fields) \
466 SENF_PACKET_PARSER_I_DEFINE_FIELDS(0,fields)
468 /** \brief Define fields for a dynamically sized parser (with offset)
470 Define the fields as specified in \a fields. This macro supports dynamically sized
471 subfields, the resulting parser will be dynamically sized.
473 The \a offset argument gives the byte offset at which to start parsing the fields. This
474 helps defining extended parser deriving from a base parser:
476 struct ExtendedParser : public BaseParser
478 SENF_PACKET_PARSER_NO_INIT(ExtendedParser);
480 SENF_PACKET_PARSER_DEFINE_FIELDS_OFFSET(senf::bytes(BaseParser(*this)),
481 ( ... fields ... ) );
491 \ingroup packetparsermacros
494 # define SENF_PACKET_PARSER_DEFINE_FIELDS_OFFSET(offset,fields) \
495 SENF_PACKET_PARSER_I_DEFINE_FIELDS(offset,fields)
497 /** \brief Define fields for a fixed size parser
499 Define the fields as specified in \a fields. This macro only supports fixed size
500 subfields, the resulting parser will also be a fixed size parser.
502 \ingroup packetparsermacros
505 # define SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS(fields) \
506 SENF_PACKET_PARSER_I_DEFINE_FIXED_FIELDS(0,fields)
508 /** \brief Define fields for a fixed size parser
510 Define the fields as specified in \a fields. This macro only supports fixed size
511 subfields, the resulting parser will also be a fixed size parser.
513 The \a offset argument gives the byte offset at which to start parsing the fields. This
514 helps defining extended parser deriving from a base parser:
516 struct ExtendedParser : public BaseParser
518 SENF_PACKET_PARSER_NO_INIT(ExtendedParser);
520 SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS_OFFSET(BaseParser::fixed_bytes,
521 ( ... fields ... ) );
531 \ingroup packetparsermacros
534 # define SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS_OFFSET(offset,fields) \
535 SENF_PACKET_PARSER_I_DEFINE_FIXED_FIELDS(offset,fields)
537 struct VoidPacketParser
538 : public PacketParserBase
540 SENF_PACKET_PARSER_INIT(VoidPacketParser);
543 /** \brief Iterator re-validating Parser wrapper
545 An ordinary parser will be invalidated whenever the raw data container's size is
546 changed. This can complicate some algorithms considerably.
548 This wrapper will update the parsers iterator (the value returned by the i() member) on
549 every access. This ensures that the iterator will stay valid.
551 \attention Beware however, if you insert or remove data before the safe wrapper, the
552 location will \e not be updated accordingly and therefore the parser will be
555 Additionally a SafePacketparser has an uninitialized state. The only allowed operations in
556 this state are the boolean test for validity and assigning another parser.
558 template <class Parser>
559 class SafePacketParser
560 : public SafeBool< SafePacketParser<Parser> >
563 ///////////////////////////////////////////////////////////////////////////
566 ///////////////////////////////////////////////////////////////////////////
567 ///\name Structors and default members
570 // default copy constructor
571 // default copy assignment
572 // default destructor
573 SafePacketParser(); ///< Create an empty uninitialized SafePacketParser
575 // conversion constructors
576 SafePacketParser(Parser parser); ///< Initialize SafePacketParser from \a parser
578 SafePacketParser & operator=(Parser parser); ///< Assign \a parser to \c this
581 ///////////////////////////////////////////////////////////////////////////
583 Parser operator*() const; ///< Access the stored parser
584 /**< On every access, the stored parsers iterator will be
585 updated / re-validated. */
586 Parser const * operator->() const; ///< Access the stored parser
587 /**< On every access, the stored parsers iterator will be
588 updated / re-validated. */
589 bool boolean_test() const; ///< Check validity
594 mutable boost::optional<Parser> parser_;
595 senf::safe_data_iterator i_;
600 ///////////////////////////////hh.e////////////////////////////////////////
601 #include "PacketParser.cci"
602 #include "PacketParser.ct"
603 #include "PacketParser.cti"
610 // c-file-style: "senf"
611 // indent-tabs-mode: nil
612 // ispell-local-dictionary: "american"
613 // compile-command: "scons -u test"
614 // comment-column: 40
617 // LocalWords: templated PacketParser defgroup packetparser PacketParsers li
618 // LocalWords: EthernetParser ethertype UInt senf PacketParserBase tt
619 // LocalWords: struct FooParser const init endcode ingroup param SomeParser
620 // LocalWords: ethernet DefaultBundle EthernetPacket hh EthVLan UIntField CFI
621 // LocalWords: VLanId OverlayField cfi vlanId accessor defaultInit bitfield
622 // LocalWords: SomePacket SimpleVectorSizer packetparsermacros Fraunhofer std
623 // LocalWords: hideinitializer Institut fuer offene Kommunikationssysteme STL
624 // LocalWords: FOKUS Kompetenzzentrum Satelitenkommunikation SatCom Bund cerr
625 // LocalWords: berlios dil Structors someField someVector someOtherField
626 // LocalWords: TruncatedPacketException