Skip to content
Snippets Groups Projects
Commit 4d584f4f authored by g0dil's avatar g0dil
Browse files

Packets: Allow packet parsers to access the packet chain

Packets/DefaultBundle: Implement IpV6Packet, IpV6Extensions and UDPPacket's finalize()
parent 1ee23334
No related branches found
No related tags found
No related merge requests found
......@@ -52,6 +52,7 @@ namespace {
prefix_ boost::uint16_t senf::Parse_IpV4::calcChecksum()
const
{
validate(bytes(*this));
IpChecksum summer;
summer.feed( i(), i()+checksum_offset );
// Not needed since the number of 0-bytes is even
......
......@@ -101,6 +101,9 @@ namespace senf {
{ return p->nextHeader(); }
static void dump(packet p, std::ostream & os);
static void finalize(packet p)
{ p->nextHeader() << key(p.next()); }
};
/** \brief IpV6 fragment extension packet typedef */
......
......@@ -25,6 +25,7 @@
//#include "IpV6Packet.ih"
// Custom includes
#include <iomanip>
#include <boost/io/ios_state.hpp>
#include "EthernetPacket.hh"
#include "../../Socket/Protocols/INet/INetAddressing.hh"
......@@ -48,14 +49,22 @@ prefix_ void senf::IpV6PacketType::dump(packet p, std::ostream & os)
{
boost::io::ios_all_saver ias(os);
os << "Internet protocol Version 6:\n"
<< " version : " << unsigned(p->version()) << "\n"
<< " traffic class : " << std::hex << unsigned(p->trafficClass()) << "\n"
<< " flow label : " << std::hex << unsigned(p->flowLabel()) << "\n"
<< " length : " << std::dec << unsigned(p->length()) << "\n"
<< " next header : " << unsigned(p->nextHeader()) << "\n"
<< " hop limit : " << unsigned(p->hopLimit()) << "\n"
<< " source : " << p->source() << "\n"
<< " destination : " << p->destination() << "\n";
<< " version : " << unsigned(p->version()) << "\n"
<< " traffic class : 0x"
<< std::hex << std::setw(2) << std::setfill('0') << unsigned(p->trafficClass()) << "\n"
<< " flow label : 0x"
<< std::hex << std::setw(5) << std::setfill('0') << unsigned(p->flowLabel()) << "\n"
<< " payload length : " << std::dec << unsigned(p->length()) << "\n"
<< " next header : " << unsigned(p->nextHeader()) << "\n"
<< " hop limit : " << unsigned(p->hopLimit()) << "\n"
<< " source : " << p->source() << "\n"
<< " destination : " << p->destination() << "\n";
}
prefix_ void senf::IpV6PacketType::finalize(packet p)
{
p->length() << (p.size() - Parse_IpV6::fixed_bytes);
p->nextHeader() << key(p.next());
}
///////////////////////////////cc.e////////////////////////////////////////
......
......@@ -131,6 +131,8 @@ namespace senf {
{ return p->nextHeader(); }
static void dump(packet p, std::ostream & os);
static void finalize(packet p);
};
/** \brief IpV6 packet typedef */
......
......@@ -28,7 +28,12 @@
#include "IpV4Packet.hh"
// Custom includes
#include <iomanip>
#include <boost/io/ios_state.hpp>
#include "../../Packets/Packets.hh"
#include "../../Utils/IpChecksum.hh"
#include "IpV4Packet.hh"
#include "IpV6Packet.hh"
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
......@@ -38,13 +43,73 @@ namespace {
registerUDPPacket (17);
}
///////////////////////////////////////////////////////////////////////////
// senf::Parse_UDP
prefix_ boost::uint16_t senf::Parse_UDP::calcChecksum()
const
{
IpChecksum summer;
summer.feed( i(), i()+checksum_offset );
summer.feed( i()+checksum_offset+2, data().end() );
// Now on to the awkward part: the IP pseudo header
IpV4Packet ipv4 (packet().prev<IpV4Packet>(nothrow));
if (ipv4) {
// Pseudo header defined in RFC768
summer.feed( ipv4->source().i(),
ipv4->source().i() + Parse_IpV4::source_t::fixed_bytes );
///\fixme What about a hop-by-hop routing option? Which destination is used in IpV4 ?
summer.feed( ipv4->destination().i(),
ipv4->destination().i() + Parse_IpV4::destination_t::fixed_bytes );
summer.feed( 0u );
///\fixme May there be another header between the IpV4 header and UDP? if so, we
/// need to hack the correct protocol number here ...
summer.feed( 17u );
summer.feed( i() + length_offset, i() + length_offset + 2 );
}
else {
// Pseudo header defined in RFC2460
IpV6Packet ipv6 (packet().prev<IpV6Packet>(nothrow));
if (ipv6) {
summer.feed( ipv6->source().i(),
ipv6->source().i() + Parse_IpV6::source_t::fixed_bytes );
///\todo Implement routing header support
// The destination used here must be the *final* destination ...
summer.feed( ipv6->destination().i(),
ipv6->destination().i() + Parse_IpV6::destination_t::fixed_bytes );
/// This is a simplification. The value is really 32bit to support UDP Jumbograms
/// (RFC2147). However, skipping an even number of 0 bytes does not change the checksum
summer.feed( i() + length_offset, i() + length_offset + 2 );
// RFC2460 specifies, that this must always be 17, not the value used in the ipv6
// header
summer.feed( 0u );
summer.feed( 17u );
}
}
boost::uint16_t rv (summer.sum());
return rv ? rv : 0xffffu;
}
///////////////////////////////////////////////////////////////////////////
// senf::UDPPacketType
prefix_ void senf::UDPPacketType::dump(packet p, std::ostream & os)
{
boost::io::ios_all_saver ias(os);
os << "UDP:\n"
<< " source port : " << p->source() << "\n"
<< " dest port : " << p->destination() << "\n"
<< " length : " << p->length() << "\n"
<< " crc : " << std::hex << p->crc() << std::dec << "\n";
<< " checksum : "
<< std::hex << std::setw(4) << std::setfill('0') << p->checksum() << "\n";
}
prefix_ void senf::UDPPacketType::finalize(packet p)
{
p->length() << p.size();
p->checksum() << p->calcChecksum();
}
///////////////////////////////cc.e////////////////////////////////////////
......
......@@ -53,16 +53,21 @@ namespace senf {
((Field)( source, Parse_16bit ))
((Field)( destination, Parse_16bit ))
((Field)( length, Parse_16bit ))
((Field)( crc, Parse_16bit )) );
((Field)( checksum, Parse_16bit )) );
# else
Parse_16bit source();
Parse_16bit destination();
Parse_16bit length();
Parse_16bit crc();
Parse_16bit checksum();
# endif
boost::uint16_t calcChecksum() const;
bool validateChecksum() const {
return checksum() == 0u || checksum() == calcChecksum();
}
};
/** \brief UDP packet
......@@ -88,6 +93,8 @@ namespace senf {
using mixin::init;
static void dump(packet p, std::ostream & os);
static void finalize(packet p);
};
/** \brief UDP packet typedef */
......
......@@ -27,6 +27,7 @@
// Custom includes
#include "UDPPacket.hh"
#include "IpV4Packet.hh"
#include <boost/test/auto_unit_test.hpp>
#include <boost/test/test_tools.hpp>
......@@ -46,10 +47,37 @@ BOOST_AUTO_UNIT_TEST(udpPacket_packet)
BOOST_CHECK_EQUAL( p->source(), 0x0102 );
BOOST_CHECK_EQUAL( p->destination(), 0x0304 );
BOOST_CHECK_EQUAL( p->length(), 0x0506 );
BOOST_CHECK_EQUAL( p->crc(), 0x0708 );
BOOST_CHECK_EQUAL( p->checksum(), 0x0708 );
}
BOOST_AUTO_UNIT_TEST(udpPacket_create)
{
unsigned char data[] = { 0x45, 0x00, 0x00, 0x26, 0x00, 0x00, 0x40, 0x00,
0x40, 0x11, 0x3c, 0xc5, 0x7f, 0x00, 0x00, 0x01,
0x7f, 0x00, 0x00, 0x01, 0x5b, 0xa0, 0x30, 0x39,
0x00, 0x12, 0xfa, 0x6e, 0x54, 0x45, 0x53, 0x54,
0x2d, 0x57, 0x52, 0x49, 0x54, 0x45 };
senf::IpV4Packet ip (senf::IpV4Packet::create());
ip->source() = senf::INet4Address::Loopback;
ip->destination() = senf::INet4Address::Loopback;
ip->df() = true;
ip->ttl() = 64;
senf::UDPPacket udp (senf::UDPPacket::createAfter(ip));
udp->source() = 23456;
udp->destination() = 12345;
senf::DataPacket::createAfter(udp,std::string("TEST-WRITE"));
// validates, since the checksum is 0 and thus ignored !
BOOST_CHECK( udp->validateChecksum() );
ip.finalize();
BOOST_CHECK_EQUAL_COLLECTIONS( data, data+sizeof(data),
ip.data().begin(), ip.data().end() );
BOOST_CHECK( udp->validateChecksum() );
}
///////////////////////////////cc.e////////////////////////////////////////
......
......@@ -384,6 +384,7 @@ namespace senf {
template <class PacketType>
friend class ConcretePacket;
friend class PacketParserBase;
};
/** \brief Protocol specific packet handle
......
......@@ -212,6 +212,7 @@ namespace senf {
friend class intrusive_refcount_t<PacketInterpreterBase>;
template <class PacketType> friend class PacketInterpreter;
friend class detail::packet::test::TestDriver;
friend class PacketParserBase;
};
/** \brief Internal: Concrete packet interpreter
......
......@@ -53,6 +53,19 @@ prefix_ void senf::PacketParserBase::init()
const
{}
prefix_ void senf::PacketParserBase::defaultInit()
const
{}
prefix_ senf::Packet senf::PacketParserBase::packet()
const
{
// OUCH ... I hate this but for some awkward packet types, access to the packet
// from the parser is really needed (e.g. UDP when building the pseudo-header
// for calculating the checksum).
return Packet(PacketInterpreterBase::ptr(static_cast<PacketInterpreterBase*>(&data())));
}
////////////////////////////////////////
// protected members
......@@ -68,11 +81,13 @@ prefix_ senf::PacketParserBase::PacketParserBase(data_iterator i, state_type s,
}
prefix_ bool senf::PacketParserBase::check(size_type size)
const
{
return size <= size_type(std::distance(i(),end()));
}
prefix_ void senf::PacketParserBase::validate(size_type size)
const
{
if (! check(size))
throw TruncatedPacketException();
......@@ -82,6 +97,7 @@ prefix_ void senf::PacketParserBase::validate(size_type size)
// private members
prefix_ senf::PacketParserBase::data_iterator senf::PacketParserBase::end()
const
{
return data_->end();
}
......
......@@ -46,10 +46,6 @@ prefix_ Parser senf::PacketParserBase::parse(size_type n)
return Parser(boost::next(i(),n),state());
}
prefix_ void senf::PacketParserBase::defaultInit()
const
{}
///////////////////////////////////////////////////////////////////////////
// namespace members
......
......@@ -159,6 +159,8 @@
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
class Packet;
/** \brief Parser Base class
......@@ -292,10 +294,10 @@ namespace senf {
container does not hold at least \a size bytes
beginning at \a i. */
bool check(size_type size); ///< Check size of data container
bool check(size_type size) const; ///< Check size of data container
/**< \returns \c true, if the data container holds at least
\a size beginning at i(), \c false otherwise. */
void validate(size_type size); ///< Validate size of data container
void validate(size_type size) const; ///< Validate size of data container
/**< \throws TruncatedPacketException if the raw data
container does not hold at least \a size bytes
beginning at i(). */
......@@ -314,8 +316,13 @@ namespace senf {
implementation. Re-implement this member in your own
parsers if needed. */
Packet packet() const; ///< Get packet this parser is parsing from
/**< \important This member should only be used from packet
parsers when access to previous or following packets is
needed e.g. for calculating checksums etc. */
private:
data_iterator end();
data_iterator end() const;
data_iterator i_;
PacketData * data_;
......
......@@ -334,8 +334,8 @@ namespace senf {
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);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment