From 1ee23334b9033d1d5471ce5695d575146a9773eb Mon Sep 17 00:00:00 2001
From: g0dil <g0dil@wiback.org>
Date: Mon, 8 Oct 2007 09:35:33 +0000
Subject: [PATCH] Utils: Implement IpChecksum helper class Packets: Implemnet
 generic assignment of boost::optional's to parsers Packets: Fix <n>_offset
 field definition in BOOST_PACKET_PARSER_DEFINE_FIELDS Packets: Implement
 PacketTypeMixin::key() helper Packets: Clarify documentation regiarding
 valid()/in-valid() packets Packets/DefaultBundle: Implement EthernetPacket,
 EthVLanPacket and IpV4Packet's finalize()

---
 Packets/DefaultBundle/EthernetPacket.cc      | 14 +++-
 Packets/DefaultBundle/EthernetPacket.hh      |  2 +
 Packets/DefaultBundle/EthernetPacket.test.cc | 21 +++++
 Packets/DefaultBundle/IpV4Packet.cc          | 32 +++++++-
 Packets/DefaultBundle/IpV4Packet.hh          | 12 ++-
 Packets/DefaultBundle/IpV4Packet.test.cc     | 27 +++++-
 Packets/Packet.hh                            | 32 +++++---
 Packets/PacketParser.cti                     | 18 ++++
 Packets/PacketParser.hh                      | 23 ++++++
 Packets/PacketParser.mpp                     |  8 +-
 Packets/PacketType.cti                       |  7 ++
 Packets/PacketType.hh                        | 26 +++++-
 SConstruct                                   | 10 ++-
 Utils/IpChecksum.cci                         | 62 ++++++++++++++
 Utils/IpChecksum.cti                         | 52 ++++++++++++
 Utils/IpChecksum.hh                          | 86 ++++++++++++++++++++
 Utils/IpChecksum.test.cc                     | 62 ++++++++++++++
 17 files changed, 470 insertions(+), 24 deletions(-)
 create mode 100644 Utils/IpChecksum.cci
 create mode 100644 Utils/IpChecksum.cti
 create mode 100644 Utils/IpChecksum.hh
 create mode 100644 Utils/IpChecksum.test.cc

diff --git a/Packets/DefaultBundle/EthernetPacket.cc b/Packets/DefaultBundle/EthernetPacket.cc
index 937f21978..907d4bfd4 100644
--- a/Packets/DefaultBundle/EthernetPacket.cc
+++ b/Packets/DefaultBundle/EthernetPacket.cc
@@ -53,10 +53,15 @@ prefix_ void senf::EthernetPacketType::dump(packet p, std::ostream & os)
     os << ": \n"
        << "  destination   : " << p->destination() << "\n"
        << "  source        : " << p->source() << "\n"
-       << "  ethertype     : " 
+       << "  ethertype     : 0x" 
        << std::hex << std::setw(4) << std::setfill('0') << p->type() << "\n";
 }
 
+prefix_ void senf::EthernetPacketType::finalize(packet p)
+{
+    p->type() << key(p.next());
+}
+
 prefix_ void senf::EthVLanPacketType::dump(packet p, std::ostream & os)
 {
     boost::io::ios_all_saver ias(os);
@@ -64,10 +69,15 @@ prefix_ void senf::EthVLanPacketType::dump(packet p, std::ostream & os)
        << "  priority      : " << p->priority() << "\n"
        << "  cfi           : " << p->cfi() << "\n"
        << "  vlan-ID       : " << p->vlanId() << "\n"
-       << "  ethertype     : " 
+       << "  ethertype     : 0x" 
        << std::hex << std::setw(4) << std::setfill('0') << p->type() << "\n";
 }
 
+prefix_ void senf::EthVLanPacketType::finalize(packet p)
+{
+    p->type() << key(p.next());
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 
diff --git a/Packets/DefaultBundle/EthernetPacket.hh b/Packets/DefaultBundle/EthernetPacket.hh
index 18f37a99a..359f05dd1 100644
--- a/Packets/DefaultBundle/EthernetPacket.hh
+++ b/Packets/DefaultBundle/EthernetPacket.hh
@@ -132,6 +132,7 @@ namespace senf {
             { return p->type(); }
 
         static void dump(packet p, std::ostream & os);
+        static void finalize(packet p);
     };
 
     /** \brief Ethernet packet typedef */
@@ -202,6 +203,7 @@ namespace senf {
             { return p->type(); }
 
         static void dump(packet p, std::ostream & os);
+        static void finalize(packet p);
     };
 
     /** \brief Ethernet VLAN tag typedef */
diff --git a/Packets/DefaultBundle/EthernetPacket.test.cc b/Packets/DefaultBundle/EthernetPacket.test.cc
index 48f5500ff..397f6f5f1 100644
--- a/Packets/DefaultBundle/EthernetPacket.test.cc
+++ b/Packets/DefaultBundle/EthernetPacket.test.cc
@@ -27,6 +27,7 @@
 
 // Custom includes
 #include "EthernetPacket.hh"
+#include "IpV4Packet.hh"
 
 #include <boost/test/auto_unit_test.hpp>
 #include <boost/test/test_tools.hpp>
@@ -68,6 +69,26 @@ BOOST_AUTO_UNIT_TEST(ethernetPacket_chain)
     BOOST_CHECK_EQUAL( *v.next().data().begin(), 0xf0 );
 }
 
+BOOST_AUTO_UNIT_TEST(ethernetPacket_create)
+{
+    senf::EthernetPacket eth (senf::EthernetPacket::create());
+    eth->source() = senf::MACAddress::from_string("01:02:03:04:05:06");
+    eth->destination() = senf::MACAddress::from_string("07:08:09:0a:0b:0c");
+    
+    senf::EthVLanPacket vlan (senf::EthVLanPacket::createAfter(eth));
+    vlan->priority() = 9u;
+    vlan->cfi() = true;
+    vlan->vlanId() = 0x234u;
+
+    eth.finalize();
+    BOOST_CHECK_EQUAL(eth->type(), 0x8100u);
+    BOOST_CHECK_EQUAL(vlan->type(), 0u);
+
+    senf::IpV4Packet ip (senf::IpV4Packet::createAfter(vlan));
+    eth.finalize();
+    BOOST_CHECK_EQUAL(vlan->type(), 0x0800u);
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 
diff --git a/Packets/DefaultBundle/IpV4Packet.cc b/Packets/DefaultBundle/IpV4Packet.cc
index b88987bc8..8c55752da 100644
--- a/Packets/DefaultBundle/IpV4Packet.cc
+++ b/Packets/DefaultBundle/IpV4Packet.cc
@@ -27,9 +27,12 @@
 //#include "IpV4Packet.ih"
 
 // Custom includes
+#include <iomanip>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <boost/io/ios_state.hpp>
+#include "../../Utils/IpChecksum.hh"
 #include "EthernetPacket.hh"
 
 #define prefix_
@@ -43,8 +46,27 @@ namespace {
         regsiterIpV4Packet2 (4); // IP-in-IP encapsulation
 }
 
+///////////////////////////////////////////////////////////////////////////
+// senf::Parse_IpV4
+
+prefix_ boost::uint16_t senf::Parse_IpV4::calcChecksum()
+    const
+{
+    IpChecksum summer;
+    summer.feed( i(),                   i()+checksum_offset );
+    // Not needed since the number of 0-bytes is even
+    // summer.feed( 0u );
+    // summer.feed( 0u );
+    summer.feed( i()+checksum_offset+2, i()+bytes(*this)    );
+    return summer.sum();
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::IpV4PacketType
+
 prefix_ void senf::IpV4PacketType::dump(packet p, std::ostream & os)
 {
+    boost::io::ios_all_saver ias(os);
     os << "Internet protocol Version 4:\n"
        << "  version       : " << p->version() << "\n"
        << "  IHL           : " << p->ihl() << "\n"
@@ -56,11 +78,19 @@ prefix_ void senf::IpV4PacketType::dump(packet p, std::ostream & os)
        << "  fragment      : " << p->frag() << "\n"
        << "  TTL           : " << unsigned(p->ttl()) << "\n"
        << "  protocol      : " << unsigned(p->protocol()) << "\n"
-       << "  CRC           : " << std::hex << p->crc() << std::dec << "\n"
+       << "  checksum      : 0x" 
+         << std::hex << std::setw(4) << std::setfill('0') << p->checksum() << std::dec << "\n"
        << "  source        : " << p->source() << "\n"
        << "  destination   : " << p->destination() << "\n";
 }
 
+prefix_ void senf::IpV4PacketType::finalize(packet p)
+{
+    p->length()   << p.size();
+    p->protocol() << key(p.next());
+    p->checksum() << p->calcChecksum();
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 
diff --git a/Packets/DefaultBundle/IpV4Packet.hh b/Packets/DefaultBundle/IpV4Packet.hh
index 5fc143ead..855f957d9 100644
--- a/Packets/DefaultBundle/IpV4Packet.hh
+++ b/Packets/DefaultBundle/IpV4Packet.hh
@@ -94,7 +94,7 @@ namespace senf {
             ((Field       )( frag,        Parse_Frag    ))
             ((Field       )( ttl,         Parse_8bit    ))
             ((Field       )( protocol,    Parse_8bit    ))
-            ((Field       )( crc,         Parse_16bit   ))
+            ((Field       )( checksum,    Parse_16bit   ))
             ((Field       )( source,      Parse_Addr    ))
             ((Field       )( destination, Parse_Addr    )) );
 
@@ -111,7 +111,7 @@ namespace senf {
         Parse_Frag    frag() const;
         Parse_8bit    ttl() const;
         Parse_8bit    protocol() const;
-        Parse_16bit   crc() const;
+        Parse_16bit   checksum() const;
         Parse_Addr    source() const;
         Parse_Addr    destination() const;
 
@@ -119,6 +119,13 @@ namespace senf {
 
         void init() {
             version() = 4;
+            // We don't support option headers at the moment ...
+            ihl() = 5;
+        }
+        
+        boost::uint16_t calcChecksum() const;
+        bool validateChecksum() const {
+            return checksum() == calcChecksum();
         }
     };
 
@@ -163,6 +170,7 @@ namespace senf {
             { return p->protocol(); }
 
         static void dump(packet p, std::ostream & os);
+        static void finalize(packet p);
     };
         
     /** \brief IpV4 packet typedef */
diff --git a/Packets/DefaultBundle/IpV4Packet.test.cc b/Packets/DefaultBundle/IpV4Packet.test.cc
index 9cc976ba1..eee06a11a 100644
--- a/Packets/DefaultBundle/IpV4Packet.test.cc
+++ b/Packets/DefaultBundle/IpV4Packet.test.cc
@@ -27,6 +27,7 @@
 
 // Custom includes
 #include "IpV4Packet.hh"
+#include "UDPPacket.hh"
 
 #include <boost/test/auto_unit_test.hpp>
 #include <boost/test/test_tools.hpp>
@@ -59,11 +60,35 @@ BOOST_AUTO_UNIT_TEST(ipV4Packet_packet)
     BOOST_CHECK_EQUAL( p->frag(),        0x0708u     );
     BOOST_CHECK_EQUAL( p->ttl(),         0x09u       );
     BOOST_CHECK_EQUAL( p->protocol(),    0x0Au       );
-    BOOST_CHECK_EQUAL( p->crc(),         0x0B0Cu     );
+    BOOST_CHECK_EQUAL( p->checksum(),    0x0B0Cu     );
     BOOST_CHECK_EQUAL( p->source().value(), senf::INet4Address(0x11121314u) );
     BOOST_CHECK_EQUAL( p->destination().value(), senf::INet4Address(0x15161718u) );
 }
 
+BOOST_AUTO_UNIT_TEST(ipV4Packet_create)
+{
+    senf::IpV4Packet ip (senf::IpV4Packet::create());
+
+    BOOST_CHECK_EQUAL( ip->version(), 4u );
+    BOOST_CHECK_EQUAL( ip->ihl(), 5u );
+    BOOST_CHECK_EQUAL( ip.size(), 20u );
+
+    senf::UDPPacket udp (senf::UDPPacket::createAfter(ip));
+
+    BOOST_CHECK( ! ip->validateChecksum() );
+
+    ip.finalize();
+    BOOST_CHECK_EQUAL( ip->length(), 28u );
+    BOOST_CHECK_EQUAL( ip->protocol(), 17u );
+    BOOST_CHECK_EQUAL( ip->checksum(), 0xbad2 );
+
+    // Check, that the checksum field is correctly skipped
+    ip.finalize();
+    BOOST_CHECK_EQUAL( ip->checksum(), 0xbad2 );
+
+    BOOST_CHECK( ip->validateChecksum() );
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 
diff --git a/Packets/Packet.hh b/Packets/Packet.hh
index 8f8dad567..206b8c820 100644
--- a/Packets/Packet.hh
+++ b/Packets/Packet.hh
@@ -184,6 +184,8 @@ namespace senf {
 
                                      Packet      next() const; 
                                         ///< Get next packet in chain
+                                        /**< \returns in - valid() packet, if no next packet 
+                                             exists */
         template <class OtherPacket> OtherPacket next() const; 
                                         ///< Get next packet of given type in chain
                                         /**< \throws InvalidPacketChainException if no such packet
@@ -192,7 +194,8 @@ namespace senf {
                                         ///< Get next packet of given type in chain
                                         /**< \param[in] nothrow This argument always has the value
                                              \c senf::nothrow
-                                             \returns in-valid() packet, if no such packet is found */
+                                             \returns in - valid() packet, if no such packet is
+                                             found */
         template <class OtherPacket> OtherPacket findNext() const;
                                         ///< Find next packet of given type in chain
                                         /**< findNext() is like next(), it will however return \c
@@ -205,11 +208,14 @@ namespace senf {
                                              *this if it is of the given type.
                                              \param[in] nothrow This argument always has the value
                                              \c senf::nothrow
-                                             \returns in-valid() packet, if no such packet is found */
+                                             \returns in - valid() packet, if no such packet is
+                                             found */
         
 
                                      Packet      prev() const; 
                                         ///< Get previous packet in chain
+                                        /**< \returns in - valid() packet, if no previous packet 
+                                             exists */
         template <class OtherPacket> OtherPacket prev() const; 
                                         ///< Get previous packet of given type in chain
                                         /**< \throws InvalidPacketChainException if no such packet
@@ -218,7 +224,8 @@ namespace senf {
                                         ///< Get previous packet of given type in chain
                                         /**< \param[in] nothrow This argument always has the value
                                              \c senf::nothrow
-                                             \returns in-valid() packet, if no such packet is found */
+                                             \returns in - valid() packet, if no such packet is
+                                             found */
         template <class OtherPacket> OtherPacket findPrev() const;
                                         ///< Find previous packet of given type in chain
                                         /**< findPrev() is like prev(), it will however return \c
@@ -231,7 +238,8 @@ namespace senf {
                                              *this if it is of the type 
                                              \param[in] nothrow This argument always has the value
                                              \c senf::nothrow
-                                             \returns in-valid() packet, if no such packet is found */
+                                             \returns in - valid() packet, if no such packet is
+                                             found */
 
 
                                      Packet      first() const;
@@ -244,7 +252,8 @@ namespace senf {
                                         ///< Return first packet of given type in chain
                                         /**< \param[in] nothrow This argument always has the value
                                              \c senf::nothrow
-                                             \returns in-valid() packet, if no such packet is found */
+                                             \returns in - valid() packet, if no such packet is
+                                             found */
 
                                      Packet      last() const;
                                         ///< Return last packet in chain
@@ -256,7 +265,8 @@ namespace senf {
                                         ///< Return last packet of given type in chain
                                         /**< \param[in] nothrow This argument always has the value
                                              \c senf::nothrow
-                                             \returns in-valid() packet, if no such packet is found */
+                                             \returns in - valid() packet, if no such packet is
+                                             found */
 
 
         template <class OtherPacket> OtherPacket parseNextAs() const;
@@ -321,10 +331,12 @@ namespace senf {
         bool boolean_test() const;      ///< Check, whether the packet is valid()
                                         /**< \see valid() */
         bool valid() const;             ///< Check, whether the packet is valid()
-                                        /**< An in-valid() packet does not allow any operation
-                                             except checking for validity and assignment. in-valid()
-                                             packets serve the same role as 0-pointers. */
-        
+                                        /**< An in - valid() packet does not allow any operation
+                                             except checking for validity and assignment. in -
+                                             valid() packets serve the same role as 0-pointers. 
+                                             
+                                             This is an alias for boolean_test() which is called
+                                             when using a packet in a boolean context. */
 
         void finalize() const;          ///< Update calculated fields
                                         /**< This call will update all calculated fields of the
diff --git a/Packets/PacketParser.cti b/Packets/PacketParser.cti
index 741303755..28b71c2ef 100644
--- a/Packets/PacketParser.cti
+++ b/Packets/PacketParser.cti
@@ -75,6 +75,24 @@ prefix_ Parser senf::operator<<(Parser target, Value const & value)
 {}
 #endif
 
+#ifndef DOXYGEN
+template <class Parser, class Value>
+prefix_ typename boost::enable_if_c < 
+        boost::is_base_of<senf::PacketParserBase, Parser>::value 
+            && ! boost::is_base_of<senf::PacketParserBase, Value>::value,
+        Parser >::type senf::operator<<(Parser target, boost::optional<Value> const & value)
+{
+    if (value)
+        target.value(*value);
+    return target;
+}
+#else
+template <class Parser, class Value>
+prefix_ Parser senf::operator<<(Parser target, Value const & value)
+{}
+#endif
+
+
 template <class Parser>
 prefix_ senf::PacketParserBase::size_type
 senf::detail::packetParserSize(Parser p, int, senf::mpl::take_uint<Parser::fixed_bytes> *)
diff --git a/Packets/PacketParser.hh b/Packets/PacketParser.hh
index 6871d1dcd..c6a38e82a 100644
--- a/Packets/PacketParser.hh
+++ b/Packets/PacketParser.hh
@@ -370,6 +370,7 @@ namespace senf {
 #   else
     /** \brief Generic parser copying
 
+
         This operator allows to copy the values of identical parsers. This operation does \e not
         depend on the parsers detailed implementation, it will just replace the data bytes of the
         target parser with those from the source parser. This allows to easily copy around complex
@@ -404,6 +405,28 @@ namespace senf {
     Parser operator<<(Parser target, Value const & value);
 #   endif
 
+#   ifndef DOXYGEN
+    template <class Parser, class Value>
+    typename boost::enable_if_c < 
+        boost::is_base_of<PacketParserBase, Parser>::value 
+            && ! boost::is_base_of<PacketParserBase, Value>::value,
+        Parser >::type
+    operator<<(Parser target, boost::optional<Value> const & value);
+#   else 
+    /** \brief Generic parser value assignment
+
+        This operator allows to assign a value to parsers which implement a <tt>value(</tt>\a
+        value<tt>)</tt> member. This special version allows to assign optional values: IF the
+        optional value is not set, the assignment will be skipped. 
+
+        This operator allows to use a common syntax for assigning values or parsers to a parser.
+
+        \ingroup packetparser
+     */
+    template <class Parser, class Value>
+    Parser operator<<(Parser target, boost::optional<Value> const & value);
+#   endif
+
     /** \defgroup packetparsermacros Helper macros for defining new packet parsers
         
         To simplify the definition of simple packet parsers, several macros are provided. Before
diff --git a/Packets/PacketParser.mpp b/Packets/PacketParser.mpp
index d445ebfdf..c9c112e0c 100644
--- a/Packets/PacketParser.mpp
+++ b/Packets/PacketParser.mpp
@@ -101,7 +101,7 @@
          return BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_)) () + senf::bytes( name () );              \
      }                                                                                            \
      size_type BOOST_PP_CAT(name, _offset) () const {                                             \
-         return BOOST_PP_CAT(offset_,BOOST_PP_CAT(BOOST_PP_INC(n),_)) () ;                        \
+         return BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_)) () ;                                      \
      }
 # 
 # define SENF_PACKET_PARSER_I_FIXED_Field(n,name,type)                                            \
@@ -112,7 +112,7 @@
      static const size_type BOOST_PP_CAT(offset_,BOOST_PP_CAT(BOOST_PP_INC(n),_)) =               \
          BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_)) + type::fixed_bytes;                             \
      static const size_type BOOST_PP_CAT(name,_offset) =                                          \
-         BOOST_PP_CAT(offset_,BOOST_PP_CAT(BOOST_PP_INC(n),_));
+         BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_));
 # 
 # define SENF_PACKET_PARSER_I_OverlayField(n,name,type)                                           \
      typedef type BOOST_PP_CAT(name,_t) ;                                                         \
@@ -123,7 +123,7 @@
          return BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_)) ();                                       \
      }                                                                                            \
      size_type BOOST_PP_CAT(name, _offset) () const {                                             \
-         return BOOST_PP_CAT(offset_,BOOST_PP_CAT(BOOST_PP_INC(n),_)) () ;                        \
+         return BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_)) () ;                        \
      }
 # 
 # define SENF_PACKET_PARSER_I_FIXED_OverlayField(n,name,type)                                     \
@@ -134,7 +134,7 @@
      static const size_type BOOST_PP_CAT(offset_,BOOST_PP_CAT(BOOST_PP_INC(n),_)) =               \
          BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_));                                                 \
      static const size_type BOOST_PP_CAT(name,_offset) =                                          \
-         BOOST_PP_CAT(offset_,BOOST_PP_CAT(BOOST_PP_INC(n),_));
+         BOOST_PP_CAT(offset_,BOOST_PP_CAT(n,_));
 # 
 # ///////////////////////////////mpp.e///////////////////////////////////////
 # endif
diff --git a/Packets/PacketType.cti b/Packets/PacketType.cti
index 4f01389a1..e79d6b8d3 100644
--- a/Packets/PacketType.cti
+++ b/Packets/PacketType.cti
@@ -73,6 +73,13 @@ prefix_ void senf::PacketTypeMixin<Self,Registry>::init(Packet p)
     p.as< ConcretePacket<Self> >()->init();
 }
 
+template <class Self, class Registry>
+prefix_ typename senf::PacketTypeMixin<Self,Registry>::optional_registry_key_t
+senf::PacketTypeMixin<Self,Registry>::key(Packet p)
+{
+    return p ? PacketRegistry<Registry>::key(p, nothrow) : optional_registry_key_t();
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::PacketTypeMixin<Self,void>
 
diff --git a/Packets/PacketType.hh b/Packets/PacketType.hh
index 7146d0826..53c17c1aa 100644
--- a/Packets/PacketType.hh
+++ b/Packets/PacketType.hh
@@ -271,6 +271,11 @@ namespace senf {
 
             static void finalize(packet p)
             {
+                // Set the type field by querying the type of the next packet. This is an 
+                // optional assignment: If the key is not found, the value returned by 'key'
+                // is an empty optional and the assignment will be skipped.
+                p->typeField << key(p.next());
+
                 // optionally complete the packet by generating auto-generated information
                 // (like checksums)
             }
@@ -300,7 +305,7 @@ namespace senf {
             using mixin::init;         
 
             static registry_key_t nextPacketKey(packet p)
-            { return i.fields().typeField(); }
+            { return p->typeField(); }
         };
         \endcode
 
@@ -314,11 +319,30 @@ namespace senf {
     {
     public:
         typedef typename Registry::key_t registry_key_t;
+        typedef boost::optional<registry_key_t> optional_registry_key_t;
+
+        static optional_registry_key_t key (Packet p); ///< Find key of packet from registry
+                                        /**< key() will query the registry to find the key of the
+                                             given packet. Whereas \c nextPacketKey() as implemented
+                                             by the mixin user will provide the registry key of the
+                                             next packet from information stored in the current
+                                             packets header, the key() member will look up the type
+                                             of packet \a p in the registry and return it's
+                                             key. 
+                                             
+                                             If either \a p is an in - valid() packet or the packet
+                                             type is not found in the registry, the returned
+                                             optional value will be empty. */
+
+        ///@{
+        ///\name PacketType interface implementation
 
         static PacketInterpreterBase::optional_range nextPacketRange (Packet p);
         static PacketInterpreterBase::factory_t      nextPacketType  (Packet p);
         static PacketInterpreterBase::size_type      initSize        ();
         static void                                  init            (Packet p);
+        
+        ///@}
     };
 
 #   ifndef DOXYGEN
diff --git a/SConstruct b/SConstruct
index 5fd8c8811..9870f209c 100644
--- a/SConstruct
+++ b/SConstruct
@@ -41,12 +41,16 @@ def nonemptyFile(f):
 def checkLocalConf(target, source, env):
     if [ True for f in env['CONFIG_FILES'] if nonemptyFile(f) ]:
         print
-        print "You have made local modifications to 'SConfig' and/or 'Doxyfile.local'."
+        print "You have made local modifications to one of the following local configuration"
+        print "files:"
+        for f in env['CONFIG_FILES']:
+            print "    ",f
+        print
         print "Building a debian package would remove those files."
         print
         print "To continue, remove the offending file(s) and try again. Alternatively,"
         print "build a source package using 'scons debsrc' and may then build debian"
-        print "binary packages from this source-package without disrupting your print local"
+        print "binary packages from this source-package without disrupting your local"
         print "configuration."
         print
         return 1
@@ -172,7 +176,7 @@ PhonyTarget(env, 'debbin', [
 
 PhonyTarget(env, 'linklint', [
     'rm -rf linklint',
-    'linklint -doc linklint -net -limit 99999999 `find -type d -name html -printf "/%P/@ "`',
+    'linklint -doc linklint -limit 99999999 `find -type d -name html -printf "/%P/@ "`',
     '[ ! -r linklint/errorX.html ] || python linklint_addnames.py <linklint/errorX.html >linklint/errorX.html.new',
     '[ ! -r linklint/errorX.html.new ] || mv linklint/errorX.html.new linklint/errorX.html',
     '[ ! -r linklint/errorAX.html ] || python linklint_addnames.py <linklint/errorAX.html >linklint/errorAX.html.new',
diff --git a/Utils/IpChecksum.cci b/Utils/IpChecksum.cci
new file mode 100644
index 000000000..300b09777
--- /dev/null
+++ b/Utils/IpChecksum.cci
@@ -0,0 +1,62 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief IpChecksum inline non-template implementation */
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+prefix_ senf::IpChecksum::IpChecksum()
+    : sum_(0), odd_(false)
+{}
+
+prefix_ void senf::IpChecksum::feed(boost::uint8_t byte)
+{
+    sum_ += odd_ ? byte : (byte<<8);
+    odd_ = ! odd_;
+}
+
+prefix_ boost::uint16_t senf::IpChecksum::sum()
+    const
+{
+    boost::uint32_t v (sum_);
+    while (v >> 16)
+        v = (v & 0xffff) + (v >> 16);
+    return ~ v;
+}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
diff --git a/Utils/IpChecksum.cti b/Utils/IpChecksum.cti
new file mode 100644
index 000000000..5d9ca90fd
--- /dev/null
+++ b/Utils/IpChecksum.cti
@@ -0,0 +1,52 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief IpChecksum inline template implementation */
+
+//#include "IpChecksum.ih"
+
+// Custom includes
+
+#define prefix_ inline
+///////////////////////////////cti.p///////////////////////////////////////
+
+template <class InputIterator>
+prefix_ void senf::IpChecksum::feed(InputIterator b, InputIterator e)
+{
+    for (; b != e; ++b)
+        feed(*b);
+}
+
+///////////////////////////////cti.e///////////////////////////////////////
+#undef prefix_
+
+
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
diff --git a/Utils/IpChecksum.hh b/Utils/IpChecksum.hh
new file mode 100644
index 000000000..7efb55d6f
--- /dev/null
+++ b/Utils/IpChecksum.hh
@@ -0,0 +1,86 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief IpChecksum public header */
+
+#ifndef HH_IpChecksum_
+#define HH_IpChecksum_ 1
+
+// Custom includes
+#include <boost/cstdint.hpp>
+
+//#include "IpChecksum.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+    
+    /** \brief
+      */
+    class IpChecksum
+    {
+    public:
+        ///////////////////////////////////////////////////////////////////////////
+        // Types
+
+        ///////////////////////////////////////////////////////////////////////////
+        ///\name Structors and default members
+        ///@{
+
+        IpChecksum();
+
+        ///@}
+        ///////////////////////////////////////////////////////////////////////////
+
+        void feed(boost::uint8_t byte);
+
+        template <class InputIterator>
+        void feed(InputIterator b, InputIterator e);
+
+        boost::uint16_t sum() const;
+    
+    protected:
+
+    private:
+        boost::uint32_t sum_;
+        bool odd_;
+    };
+
+    
+}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "IpChecksum.cci"
+//#include "IpChecksum.ct"
+#include "IpChecksum.cti"
+#endif
+
+
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
diff --git a/Utils/IpChecksum.test.cc b/Utils/IpChecksum.test.cc
new file mode 100644
index 000000000..24319d04d
--- /dev/null
+++ b/Utils/IpChecksum.test.cc
@@ -0,0 +1,62 @@
+// $Id$
+//
+// Copyright (C) 2007 
+// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
+// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief IpChecksum.test unit tests */
+
+//#include "IpChecksum.test.hh"
+//#include "IpChecksum.test.ih"
+
+// Custom includes
+#include "IpChecksum.hh"
+
+#include <boost/test/auto_unit_test.hpp>
+#include <boost/test/test_tools.hpp>
+
+#define prefix_
+///////////////////////////////cc.p////////////////////////////////////////
+
+BOOST_AUTO_UNIT_TEST(ipChecksum)
+{
+    char data[] = { 0x45, 0x00, 0x00, 0x28, 0x49, 0x44, 0x40, 0x00,
+                    0x40, 0x06, 0x00, 0x00, 0x0a, 0xc1, 0x01, 0x06,
+                    0xc2, 0x9f, 0xa4, 0xc3 };
+
+    senf::IpChecksum summer;
+    summer.feed(data, data+sizeof(data));
+    BOOST_CHECK_EQUAL( summer.sum(), 0x7e62u );
+}
+
+
+///////////////////////////////cc.e////////////////////////////////////////
+#undef prefix_
+
+
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
-- 
GitLab