updated ListOptionTypeParser and unittests, fixed error in ICMP packet
pug [Fri, 4 Sep 2009 13:32:16 +0000 (13:32 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1383 270642c3-0616-0410-b53a-bc976706d245

senf/Packets/DefaultBundle/ICMPv6Packet.cc
senf/Packets/DefaultBundle/IPv6ExtOptionType.ct
senf/Packets/DefaultBundle/IPv6ExtOptionType.hh
senf/Packets/DefaultBundle/IPv6Extensions.cc
senf/Packets/DefaultBundle/IPv6Extensions.test.cc
senf/Packets/ListOptionTypeParser.cti
senf/Packets/ListOptionTypeParser.ih

index 42a48bd..8692539 100644 (file)
@@ -74,9 +74,9 @@ prefix_ void senf::ICMPv6PacketType::dump(packet p, std::ostream &os)
 {
     boost::io::ios_all_saver ias(os);
     os << "ICMPv6 protocol:\n"
-       <<     "  type                    : " << p->type() <<"\n"
-       <<     "  code                    : " << p->code() <<"\n"
-       <<     "  checksum                : " << p->checksum() << "\n";
+       <<     "  type                    : " << (unsigned) p->type() <<"\n"
+       <<     "  code                    : " << (unsigned) p->code() <<"\n"
+       <<     "  checksum                : " << (unsigned) p->checksum() << "\n";
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////
index 3aa4f2a..cc5f9f2 100644 (file)
 template <class ForwardReadableRange>
 prefix_ void senf::GenericOptTypeTLVPacketParser::value(ForwardReadableRange const &range)
 {
-    safe_data_iterator si = resizeValueField( boost::size(range) );
-    std::copy( boost::begin(range), boost::end(range), si);
+    safe_data_iterator si( data(), boost::next(data().begin()+2) );
+    unsigned int rangeSize = boost::size(range);
+//    std::cout << "tmpl. method - optLength =" << (unsigned) optionLength()
+//      << ", rangeSize: " << rangeSize
+//      << ", optionType: " << (unsigned) optionType() << std::endl;
+    if ( rangeSize > optionLength() ){
+//        std::cout << "rangeSize > optionLength()" << std::endl;
+        data().insert(si, rangeSize - optionLength(),0 );
+    }
+    if (rangeSize < optionLength() ){
+//        std::cout << "rangeSize < optionLength()" << std::endl;
+        data().erase(si, si + (optionLength() - rangeSize));
+    }
+    std::copy(( boost::begin(range)), boost::end(range), si);
+    optionLength() = 2u;
+//    std::cout << "optLength AFTER =" << (unsigned) optionLength() << ", rangeSize: " << rangeSize << std::endl;
 }
 
 ///////////////////////////////ct.e////////////////////////////////////////
index ab8adf6..5feed04 100644 (file)
@@ -33,9 +33,10 @@ namespace senf {
 class OptTypeTLVPacketParser: public PacketParserBase {
 public:
 #       include SENF_PARSER()
-    SENF_PARSER_BITFIELD (altAction, 2, unsigned);
-    SENF_PARSER_BITFIELD (changeFlag, 1, unsigned);
-    SENF_PARSER_BITFIELD (optionType, 5, unsigned);
+//    SENF_PARSER_BITFIELD (altAction, 2, unsigned);
+//    SENF_PARSER_BITFIELD (changeFlag, 1, unsigned);
+//    SENF_PARSER_BITFIELD (optionType, 5, unsigned);
+    SENF_PARSER_FIELD (optionType, UInt8Parser);
     SENF_PARSER_FIELD (optionLength, UInt8Parser);
     SENF_PARSER_FINALIZE (OptTypeTLVPacketParser);
 
@@ -47,10 +48,12 @@ struct GenericOptTypeTLVPacketParser: public OptTypeTLVPacketParser {
     SENF_PARSER_SKIP ( optionLength(), 0 );
     SENF_PARSER_FINALIZE ( GenericOptTypeTLVPacketParser );
 
+
     senf::PacketInterpreterBase::range value() const;
 
     template<class ForwardReadableRange>
     void value(ForwardReadableRange const &range);
+
 };
 
 } //namespace senf
index 0e39c65..ca4b9d7 100644 (file)
@@ -72,6 +72,12 @@ prefix_ void senf::IPv6ExtensionType_HopByHop::dump(packet p, std::ostream & os)
     os << "Internet protocol Version 6 Hop-By-Hop extension:\n"
        <<     "  next header             : " << unsigned (p->nextHeader()) << "\n"
        <<     "  header length           : " << unsigned (p->headerLength()) << "\n";
+       os << "OptionTypes:\n";
+       IPv6Extension_HopByHop::Parser::options_t::container options (p->options());
+       IPv6Extension_HopByHop::Parser::options_t::container::iterator optIter(options.begin());
+       for(;optIter != options.end(); ++ optIter)
+           os << "Option Type:\t" << (unsigned) optIter->optionType()
+             << "\nOptionLength:\t" << (unsigned)  optIter->optionLength() <<"\n";
 }
 
 prefix_ void senf::IPv6ExtensionType_Destination::dump(packet p, std::ostream & os)
index 4fcd159..55563a4 100644 (file)
@@ -149,9 +149,66 @@ BOOST_AUTO_UNIT_TEST(ipv6Extensions)
 }
     //==============================================================================================
     
-    /*
-    no unittests for Hop by Hop - and Destination - Options extension Header yet. No real implementation there, only IPv6 extension skeleton implemented.
-    */
+BOOST_AUTO_UNIT_TEST(ipv6Extensions_hopByHop)
+{
+    unsigned char HopByHop_packetData[] = {
+        0x60, 0x00, 0x00, 0x00, //IP version, class, flow label
+        0x00, 0x24,           //payload length
+        0x00,                 //next header: IPv6 hop-by-hop option (0)
+        0x01,                 //hop limit (1)
+        0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,     //IPv6 Source address (fe80::219:b9ff:feeb:b226)
+        0x02, 0x19, 0xb9, 0xff, 0xfe, 0xeb, 0xb2, 0x26,
+
+        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,     //IPv6 Destination address ff02::16
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16,
+        //HopByHop option
+        0x3a,   //next Header (ICMPv6)
+        0x00,   //Length (0 = 8Bytes)
+
+        //option Header
+        0x05, //option type
+        0x02, //option Length (= 2 byte)
+        0x00, 0x00, //data (zero data here ...)
+
+        0x02, //option type (2, set for testing purposes only)
+        0x00,  //option Type length (=0, no data field needed here)
+
+        //ICMPv6
+        0x8f, //type 143
+        0x00, //code 0, should always be 0
+        0x50, 0xcc, //checksum
+    };
+
+    std::ostringstream oss (std::ostringstream::out);
+
+    senf::IPv6Packet pHop_packet (senf::IPv6Packet::create(HopByHop_packetData));
+    BOOST_CHECK_EQUAL( pHop_packet->version(), 6u );
+    BOOST_CHECK_EQUAL( pHop_packet->length(), 36u );
+    BOOST_CHECK_EQUAL( pHop_packet->nextHeader(), 0u );
+    BOOST_CHECK_EQUAL( pHop_packet->source().value(), senf::INet6Address::from_string("fe80::219:b9ff:feeb:b226") );
+    BOOST_CHECK_EQUAL( pHop_packet->destination().value(), senf::INet6Address::from_string("ff02::16") );
+
+    SENF_CHECK_NO_THROW( pHop_packet.dump( oss ));
+    BOOST_REQUIRE( pHop_packet.next().is<senf::IPv6Extension_HopByHop>() );
+
+    //hopByHop extension header
+    senf::IPv6Extension_HopByHop pHop_extension (pHop_packet.next().as<senf::IPv6Extension_HopByHop>());
+    BOOST_CHECK_EQUAL( pHop_extension->nextHeader(), 58u );
+    BOOST_CHECK_EQUAL( pHop_extension->headerLength(), 0x00 );
+
+    SENF_CHECK_NO_THROW( pHop_extension.dump( oss ));
+    pHop_extension.dump(std::cout);
+    senf::IPv6Extension_HopByHop::Parser::options_t::container optC(pHop_extension->options() );
+    senf::IPv6Extension_HopByHop::Parser::options_t::container::iterator listIter (optC.begin());
+    BOOST_CHECK_EQUAL( listIter->optionType(), 5u);
+    BOOST_CHECK_EQUAL( listIter->optionLength(), 2u);
+    std::cout << listIter->value() << std::endl;
+    ++listIter;
+    BOOST_CHECK_EQUAL( listIter->optionType(), 2u);
+    BOOST_CHECK_EQUAL( listIter->optionLength(), 0);
+//    pHop_extension.dump(std::cout);  //( no optiontype output ... sth wrong here! )
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 
index 317c2cd..adf88ca 100644 (file)
@@ -53,7 +53,7 @@ senf::detail::ListOptionTypeParser_Policy<ElementParser,AuxPolicy>::bytes(data_i
                                                                           state_type s)
     const
 {
-    return AuxPolicy::aux(i, s) + AuxPolicy::aux_bytes;
+    return ((AuxPolicy::aux(i, s) * 8 + 6)  + AuxPolicy::aux_bytes);
 }
 
 template <class ElementParser, class AuxPolicy>
@@ -73,6 +73,10 @@ senf::detail::ListOptionTypeParser_Policy<ElementParser,AuxPolicy>::init(data_it
                                                                          state_type s)
     const
 {
+    i[0] = 1u;
+    i[1] = 4u;
+    for (unsigned int n = 2;n < 6; ++n)
+        i[n] = 0u;
     AuxPolicy::aux(0, i, s);
 }
 
@@ -100,17 +104,20 @@ prefix_ void
 senf::detail::ListOptionTypeParser_Policy<ElementParser,AuxPolicy>::container_policy::
 construct(container_type & c)
 {
-    data_iterator i = c.i();
+    safe_data_iterator i (c.data(), c.i()) ;
     realAux_ = (AuxPolicy::aux(i, c.state()) * 8) + 6;
-    data_iterator e = i + realAux_;
-    for (n_ = 0; i != e; ++n_) {
+    safe_data_iterator e = i + realAux_;
+    for (n_ = 0; i != e;) {
         unsigned int elByte = senf::bytes(ElementParser(i, c.state()));
         if (((i + elByte) == e) && (i[0] == 0u || i[0] == 1u)) { //check wether last element is padding or not
             realAux_ -= std::distance(i, e);
+            container_size_ -= std::distance(i, e);
             c.data().erase(i, e); //delete padding
             e = i; //set end iterator
-        } else
+        } else{
+            ++n_;
             std::advance(i, elByte);
+        }
     }
     //    container_size_ = std::distance(i,e);
     container_size_ = c.data().size(); //set actual size without padding
@@ -123,20 +130,25 @@ senf::detail::ListOptionTypeParser_Policy<ElementParser,AuxPolicy>::container_po
 destruct(container_type & c)
 {
     // data_iterator i (AuxPolicy::adjust(parser_type::get(p).i(), parser_type::get(p).state()));
-    data_iterator i = c.i();
-    data_iterator const e = i + realAux_;
-    unsigned int padBytes = (realAux_ % 8);
-    c.data().insert(e, padBytes, 0u);
+    safe_data_iterator i (c.data(), c.i()) ;
+    safe_data_iterator const e = i + realAux_;
+    unsigned int padBytes = 0;
+    if (realAux_ == 0)      //if list is empty, 6 padding bytes required!
+      padBytes = 6;
+    else
+      padBytes = ( (realAux_+2) % 8);
     if (padBytes > 0) {
+        c.data().insert(e, padBytes, 0u);
         if (padBytes > 1) {
-            e[0] = 1;
+            e[0] = 1u;
             e[1] = padBytes - 2;
         } else
             e[0] = 0;
         container_size_ += padBytes;
+        realAux_ += padBytes;
         ++n_;
     }
-    AuxPolicy::aux((realAux_ / 8 - 1), i, c.state());
+    AuxPolicy::aux(( (realAux_ + 2)/ 8 - 1), i, c.state());
 }
 
 //bytes()
@@ -147,7 +159,7 @@ senf::detail::ListOptionTypeParser_Policy<ElementParser,AuxPolicy>::container_po
 bytes(data_iterator i, state_type s)
     const
 {
-    return (realAux_ + 2);
+    return (realAux_ );
 }
 
 //size()
@@ -167,6 +179,9 @@ prefix_ void
 senf::detail::ListOptionTypeParser_Policy<ElementParser,AuxPolicy>::container_policy::
 init(data_iterator i, state_type s)
 {
+//    i[0] = 1u;
+    //    for (unsigned int n = 1;n < 6; ++n)
+//        i[n] = 0u;
     n_ = 0;
     container_size_ = s->size();
     AuxPolicy::aux(0, i, s);
@@ -186,7 +201,7 @@ erase(container_type & c, data_iterator p)
     realAux_ -= b;
     --n_;
     // The container will be reduced by b bytes directly after this call
-    container_size_ = c.data().size() - b;
+    container_size_ -= b;
 }
 
 //insert()
index 207bc76..d85995a 100644 (file)
@@ -52,7 +52,7 @@ namespace senf {
             typedef ListParser< ListOptionTypeParser_Policy > parser_type;
             typedef ListParser_Container< container_policy > container_type;
 
-            static const size_type init_bytes = AuxPolicy::aux_bytes;
+            static const size_type init_bytes = 6 + AuxPolicy::aux_bytes;
 
             ListOptionTypeParser_Policy();
             template <class Arg> ListOptionTypeParser_Policy(Arg const & arg);