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 #include "PacketData.hh"
79 #include "PacketParser.mpp"
80 ///////////////////////////////hh.p////////////////////////////////////////
84 /** \brief Parser Base class
86 Parsers come in two favors: fixed and dynamically sized parsers. A <em>fixed size
87 parser</em> has a constant size, it will always parse a fixed number of bytes. The low-level
88 'final' parsers (like the integer parsers) are fixed size parsers as are composite parsers
89 built up only of fixed-size fields.
91 A <em>dynamically sized</em> parser on the other hand infers it's size from the contents of
92 the data parsed. Any parser containing at least one dynamically sized sub-parser will itself
95 Both kinds of parser need to derive from PacketParserBase and implement several required
96 members. Which members to implement depends on the parsers flavor. There are two ways how to
98 \li If the parser just consists of a simple sequence of consecutive fields (sub-parsers),
99 the \ref SENF_PACKET_PARSER_DEFINE_FIELDS and \ref
100 SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS macros provide a simple and convenient way to
102 \li In more complex cases, you need to implement the necessary members manually.
104 This documentation is about the manual implementation. You should nevertheless read through
105 this to understand, what above macros are doing.
107 The following example documents the interface (which must be) provided by a parser:
109 struct FooParser : public PacketParserBase
111 FooParser(data_iterator i, state_type s) : PacketParserBase(i,s) {}
113 // If this parser has a fixed size, you must define this size here This definition
114 // allows the parser to be used within the list, vector and array parsers static
115 static const size_type fixed_bytes = some_constant_size;
117 // If the parser does not have a fixed size, you must implement the bytes() member to
118 // return the size. ONLY EVER DEFINE ONE OF fixed_bytes OR bytes().
119 size_type bytes() const;
121 // If you define bytes(), you also need to define the init_bytes. This is the number
122 // of bytes to allocate when creating a new object
123 static const size_type init_bytes = some_constant_size;
125 // You also may define an init() member. This will be called to initialize a newly
126 // created data object. The default implementation just does nothing.
129 // ////////////////////////////////////////////////////////////////////////
131 // Add here members returning (sub-)parsers for the fields. The 'parse' member is
132 // used to construct the sub-parsers. This member either takes an iterator to the
133 // data to be parsed or just an offset in bytes.
135 senf::Parse_UInt16 type() const { return parse<Parse_UInt16>( 0 ); }
136 senf::Parse_UInt16 size() const { return parse<Parse_UInt16>( 2 ); }
140 You should never call the \c bytes() member of a parser directly. Instead you should use the
141 freestanding senf::bytes() function. This function will return the correct size irrespective
142 of the parsers flavor. You may access \c fixed_bytes directly, however be aware that this
143 will restrict your code to fixed size parsers (which depending on the circumstances may be
144 exactly what you want).
146 In the same way, don't access \c init_bytes directly, always use the senf::init_bytes
147 meta-function class which correctly supports fixed size parsers.
149 \ingroup packetparser
151 class PacketParserBase
154 ///////////////////////////////////////////////////////////////////////////
157 typedef detail::packet::iterator data_iterator; ///< Raw data iterator type
158 typedef detail::packet::size_type size_type; ///< Unsigned integral type
159 typedef detail::packet::difference_type difference_type; ///< Signed integral type
160 typedef detail::packet::byte byte; ///< Unsigned 8bit value, the raw value type
161 typedef PacketData * state_type; ///< Type of the 'state' parameter
163 ///////////////////////////////////////////////////////////////////////////
164 ///\name Structors and default members
167 // no default constructor
169 // default destructor
170 // no conversion constructors
173 ///////////////////////////////////////////////////////////////////////////
175 data_iterator i() const; ///< Return beginning of data to parse
176 /**< The parser is expected to interpret the data beginning
177 here. The size of the interpreted is given by
178 <tt>senf::bytes(</tt><em>parser
179 instance</em><tt>)</tt>. */
180 state_type state() const; ///< Return state of this parser
181 /**< The value returned should be interpreted as an opaque
182 value provided just to be forwarded to other
184 PacketData & data() const; ///< Access the packets raw data container
185 /**< This member will return the raw data container holding
186 the data which is parsed by \c this parser. */
188 void init() const; ///< Default implementation
189 /**< This is just an empty default
190 implementation. Re-implement this member in your own
191 parsers if needed. */
194 PacketParserBase(data_iterator i, state_type s); ///< Standard constructor
195 /**< This is the constructor used by most parsers. The
196 parameters are just forwarded from the derived classes
197 constructor parameters. */
198 PacketParserBase(data_iterator i, state_type s, size_type size);
199 ///< Size checking constructor
200 /**< In addition to the standard constructor, this
201 constructor will validate, that there is enough data in
202 the raw data container to parse \a size bytes after \a
205 This constructor is called by all 'final' parsers
206 (e.g. the integer parsers) and \e only by those
207 parsers. Most parsers do \e not check the validity of
208 the iterator, this is delayed until the very last
209 parser. This allows to partial parse truncated
212 \throw TruncatedPacketException if the raw data
213 container does not hold at least \a size bytes
214 beginning at \a i. */
216 bool check(size_type size); ///< Check size of data container
217 /**< \returns \c true, if the data container holds at least
218 \a size beginning at i(), \c false otherwise. */
219 void validate(size_type size); ///< Validate size of data container
220 /**< \throws TruncatedPacketException if the raw data
221 container does not hold at least \a size bytes
224 template <class Parser> Parser parse(data_iterator i) const; ///< Create sub-parser
225 /**< Creates a new instance of \a Parser to parse data
226 beginning at \a i. Automatically passes \a state() to
228 template <class Parser> Parser parse(size_type n) const; ///< Create sub-parser
229 /**< Creates a new instance of \a Parser to parse data
230 * beginning at i()<tt> + </tt>\a n. Automatically passes \a
231 state() to the new parser. */
233 void defaultInit() const; ///< Default implementation
234 /**< This is just an empty default
235 implementation. Re-implement this member in your own
236 parsers if needed. */
244 template <class Parser> friend class SafePacketParser;
247 /** \brief Return raw size parsed by the given parser object
249 This function will either call <tt>p.bytes()</tt> or return <tt>Parser::fixed_bytes</tt>
250 depending on the type of parser.
252 The value returned does \e not take into account the amount of data actually available. So
253 you always need to validate this value against the packet size if you directly access the
254 data. The standard low-level parses all do this check automatically to guard against
257 \param[in] p Parser object to check
258 \returns number of bytes this parser expects to parser
259 \ingroup packetparser
261 template <class Parser>
262 PacketParserBase::size_type bytes(Parser p);
264 namespace detail { template <class Parser> class ParserInitBytes; }
266 /** \brief Return number of bytes to allocate to new object of given type
268 This meta-function is called like
270 senf::init_bytes<SomeParser>::value
273 This expression evaluates to a compile-time constant integral expression of type
274 senf::PacketParserBase::size_type. This meta-function will return \c Parser::fixed_bytes or
275 \c Parser::init_bytes depending on the type of parser.
277 \param[in] Parser The Parser to return init_bytes for
278 \returns Number of bytes to allocate to the new object
279 \ingroup packetparser
281 template <class Parser>
282 struct init_bytes : public detail::ParserInitBytes<Parser>
285 /** \brief Generic parser copying
287 This operator allows to copy the values of identical parsers. This operation does \e not
288 depend on the parsers detailed implementation, it will just replace the data bytes of the
289 target parser with those from the source parser. This allows to easily copy around complex
290 packet substructures.
292 This operation is different from the ordinary assignment operator: It does not change the \a
293 target parser, it changes the data referenced by the \a target parser.
295 \ingroup packetparser
297 template <class Parser>
298 typename boost::enable_if<
299 boost::is_base_of<PacketParserBase, Parser>,
301 operator<<(Parser target, Parser source);
303 /** \brief Generic parser value assignment
305 This operator allows to assign a value to parsers which implement a <tt>value(</tt>\a
306 value<tt>)</tt> member. This operator allows to use a common syntax for assigning values or
309 \ingroup packetparser
311 template <class Parser, class Value>
312 typename boost::enable_if_c <
313 boost::is_base_of<PacketParserBase, Parser>::value
314 && ! boost::is_base_of<PacketParserBase, Value>::value,
316 operator<<(Parser target, Value const & value);
318 /** \defgroup packetparsermacros Helper macros for defining new packet parsers
320 To simplify the definition of simple packet parsers, several macros are provided. Before
321 using these macros you should familiarize yourself with the packet parser interface as
322 described in senf::PacketParserBase.
324 These macros simplify providing the above defined interface. A typical packet declaration
325 using these macros has the following form (This is a concrete example from the definition of
326 the ethernet packet in <tt>DefaultBundle/EthernetPacket.hh</tt>)
328 \dontinclude EthernetPacket.hh
329 \skipline struct Parse_EthVLan : public PacketParserBase
332 The macros take care of the following:
333 \li They define the accessor functions returning parsers of the given type.
334 \li They automatically calculate the offset of the fields from the preceding fields.
335 \li The macros provide a definition for \c init()
336 \li The macros define the \c bytes(), \c fixed_bytes and \c init_bytes members as needed.
338 You may define either a fixed or a dynamically sized parser. Fixed size parsers are defined
339 using \ref SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS, dynamically sized parsers are defined
340 using \ref SENF_PACKET_PARSER_DEFINE_FIELDS. The different members are implemented such
343 \li The needed parser constructor is defined
344 \li \c init() calls \c defaultInit(). \c defaultInit() is defined to call \c init() on each
346 \li \c bytes() (on dynamically sized parser) respectively \c fixed_bytes (on fixed size
347 parsers) is defined to return the sum of the sizes of all fields.
348 \li On dynamically sized parsers, \c init_bytes is defined to return the sum of the
349 \c init_size's of all fields
351 The central definition macros are \ref SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS and \ref
352 SENF_PACKET_PARSER_DEFINE_FIELDS. The argument to both has the same structure. It is a
353 (boost preprocessor style) sequence of field definitions where each field definition
354 provides the builder macro to use and the name and type of the field to define:
356 SENF_PACKET_PARSER_DEFINE[_FIXED]_FIELDS(
357 (( <builder> )( <name>, <type> ))
362 For each field, this command will define
363 \li A method \a name() returning an instance of the \a type parser
364 \li \a name<tt>_t</tt> as a typedef for \a type, the fields value
365 \li \a name<tt>_offset</tt> to give the offset of the field from the beginning of the
366 parser. If the parser is a fixed size parser, this will be a static constant, otherwise
369 The \a builder argument selects, how the field is defined
370 \li <tt>Field</tt> defines a field and increments the current position by the size of the
372 \li <tt>OverlayField</tt> defines a field like <tt>Field</tt> but does \e not increment the
373 position. In the above example, this is used to overlay the different bitfield parsers:
374 All overlaying bitfield parser except the last one (the one with the highest bit
375 numbers) is marked as OverlayField.
377 The \a name argument defines the name of the accessor method.
379 The \a type argument is the parser to return for that field. Since none of the arguments may
380 contain a comma, <em>This argument cannot be a multi-parameter template</em>. Always use
381 typedefs to access templated parsers as shown above.
383 The \ref SENF_PACKET_PARSER_INIT macro defines the constructor and the \c init() member. If
384 you want to provide your own \c init() implementation, use \ref
385 SENF_PACKET_PARSER_NO_INIT. The first statement in your init method should probably to call
386 \c defaultInit(). This will call the \c init() member of all the fields. Afterwards you can
387 set up the field values as needed:
389 struct SomePacket : public senf::PacketParserBase
391 SENF_PACKET_PARSER_NO_INIT(SomePacket);
393 typedef senf::Parse_UInt8 Parse_Type;
394 typedef senf::Parse_Vector< senf::Parse_UInt32,
395 senf::SimpleVectorSizer<senf::Parse_UInt16>
398 SENF_PACKET_PARSER_DEFINE_FIELDS(
399 ((Field)( type, Parse_Type ))
400 ((Field)( elements, Parse_Elements ))
406 elements().push_back(0x01020304u);
411 \ingroup packetparser
414 /** \brief Define initialization members of a parser
416 This macro defines the packet parser constructor and the \c init() member. \c init() is
417 defined to just call \c defaultInit() which is defined by the other macros to call \c init()
418 on each of the parsers fields.
420 \ingroup packetparsermacros
423 # define SENF_PACKET_PARSER_INIT(name) \
424 name(data_iterator i, state_type s) : senf::PacketParserBase(i,s) {} \
425 void init() const { defaultInit(); }
427 /** \brief Define initialization members of a parser except init()
429 This macro is like SENF_PACKET_PARSER_INIT but does \e not define \c init(). This allows you
430 to provide your own implementation. You should call \c defaultInit() first before
431 initializing your data fields.
433 \ingroup packetparsermacros
436 # define SENF_PACKET_PARSER_NO_INIT(name) \
437 name(data_iterator i, state_type s) : senf::PacketParserBase(i,s) {}
439 /** \brief Define fields for a dynamically sized parser
441 Define the fields as specified in \a fields. This macro supports dynamically sized
442 subfields, the resulting parser will be dynamically sized.
444 \ingroup packetparsermacros
447 # define SENF_PACKET_PARSER_DEFINE_FIELDS(fields) \
448 SENF_PACKET_PARSER_I_DEFINE_FIELDS(0,fields)
450 /** \brief Define fields for a dynamically sized parser (with offset)
452 Define the fields as specified in \a fields. This macro supports dynamically sized
453 subfields, the resulting parser will be dynamically sized.
455 The \a offset argument gives the byte offset at which to start parsing the fields. This
456 helps defining extended parser deriving from a base parser:
458 struct ExtendedParser : public BaseParser
460 ExtendedParser(data_iterator i, state_type s) : BaseParser(i,s) {}
462 SENF_PACKET_PARSER_DEFINE_FIELDS_OFFSET(senf::bytes(BaseParser(*this)),
463 ( ... fields ... ) );
473 \ingroup packetparsermacros
476 # define SENF_PACKET_PARSER_DEFINE_FIELDS_OFFSET(offset,fields) \
477 SENF_PACKET_PARSER_I_DEFINE_FIELDS(offset,fields)
479 /** \brief Define fields for a fixed size parser
481 Define the fields as specified in \a fields. This macro only supports fixed size
482 subfields, the resulting parser will also be a fixed size parser.
484 \ingroup packetparsermacros
487 # define SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS(fields) \
488 SENF_PACKET_PARSER_I_DEFINE_FIXED_FIELDS(0,fields)
490 /** \brief Define fields for a fixed size parser
492 Define the fields as specified in \a fields. This macro only supports fixed size
493 subfields, the resulting parser will also be a fixed size parser.
495 The \a offset argument gives the byte offset at which to start parsing the fields. This
496 helps defining extended parser deriving from a base parser:
498 struct ExtendedParser : public BaseParser
500 ExtendedParser(data_iterator i, state_type s) : BaseParser(i,s) {}
502 SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS_OFFSET(BaseParser::fixed_bytes,
503 ( ... fields ... ) );
513 \ingroup packetparsermacros
516 # define SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS_OFFSET(offset,fields) \
517 SENF_PACKET_PARSER_I_DEFINE_FIXED_FIELDS(offset,fields)
519 struct VoidPacketParser
520 : public PacketParserBase
522 SENF_PACKET_PARSER_INIT(VoidPacketParser);
525 /** \brief Iterator re-validating Parser wrapper
527 An ordinary parser will be invalidated whenever the raw data container's size is
528 changed. This can complicate some algorithms considerably.
530 This wrapper will update the parsers iterator (the value returned by the i() member) on
531 every access. This ensures that the iterator will stay valid.
533 \attention Beware however, if you insert or remove data before the safe wrapper, the
534 location will \e not be updated accordingly and therefore the parser will be
537 Additionally a SafePacketparser has an uninitialized state. The only allowed operations in
538 this state are the boolean test for validity and assigning another parser.
540 template <class Parser>
541 class SafePacketParser
542 : public SafeBool< SafePacketParser<Parser> >
545 ///////////////////////////////////////////////////////////////////////////
548 ///////////////////////////////////////////////////////////////////////////
549 ///\name Structors and default members
552 // default copy constructor
553 // default copy assignment
554 // default destructor
555 SafePacketParser(); ///< Create an empty uninitialized SafePacketParser
557 // conversion constructors
558 SafePacketParser(Parser parser); ///< Initialize SafePacketParser from \a parser
560 SafePacketParser & operator=(Parser parser); ///< Assign \a parser to \c this
563 ///////////////////////////////////////////////////////////////////////////
565 Parser operator*() const; ///< Access the stored parser
566 /**< On every access, the stored parsers iterator will be
567 updated / re-validated. */
568 Parser const * operator->() const; ///< Access the stored parser
569 /**< On every access, the stored parsers iterator will be
570 updated / re-validated. */
571 bool boolean_test() const; ///< Check validity
576 mutable boost::optional<Parser> parser_;
577 senf::safe_data_iterator i_;
582 ///////////////////////////////hh.e////////////////////////////////////////
584 #if !defined(SENF_PACKETS_DECL_ONLY) && !defined(HH_PacketParser_i_)
585 #define HH_PacketParser_i_
586 #include "PacketParser.cci"
587 #include "PacketParser.ct"
588 #include "PacketParser.cti"
595 // c-file-style: "senf"
596 // indent-tabs-mode: nil
597 // ispell-local-dictionary: "american"
598 // compile-command: "scons -u test"
599 // comment-column: 40
602 // LocalWords: templated PacketParser defgroup packetparser PacketParsers li
603 // LocalWords: EthernetParser ethertype UInt senf PacketParserBase tt
604 // LocalWords: struct FooParser const init endcode ingroup param SomeParser
605 // LocalWords: ethernet DefaultBundle EthernetPacket hh EthVLan UIntField CFI
606 // LocalWords: VLanId OverlayField cfi vlanId accessor defaultInit bitfield
607 // LocalWords: SomePacket SimpleVectorSizer packetparsermacros Fraunhofer std
608 // LocalWords: hideinitializer Institut fuer offene Kommunikationssysteme STL
609 // LocalWords: FOKUS Kompetenzzentrum Satelitenkommunikation SatCom Bund cerr
610 // LocalWords: berlios dil Structors someField someVector someOtherField
611 // LocalWords: TruncatedPacketException