{
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////////////////////////////////////////
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////////////////////////////////////////
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);
SENF_PARSER_SKIP ( optionLength(), 0 );
SENF_PARSER_FINALIZE ( GenericOptTypeTLVPacketParser );
+
senf::PacketInterpreterBase::range value() const;
template<class ForwardReadableRange>
void value(ForwardReadableRange const &range);
+
};
} //namespace senf
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)
}
//==============================================================================================
- /*
- 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_
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>
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);
}
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
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()
bytes(data_iterator i, state_type s)
const
{
- return (realAux_ + 2);
+ return (realAux_ );
}
//size()
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);
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()
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);