From: pug Date: Wed, 6 Aug 2008 15:36:41 +0000 (+0000) Subject: Added ICMPv6 Packet Parser and Unittests for different ICMP Packages. X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=ccc827edda90ace7d2f8564660ee26b09a5a23b5;hp=1ff250cd4570aadd9016dad01660d37d1c120590;p=senf.git Added ICMPv6 Packet Parser and Unittests for different ICMP Packages. git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@896 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Packets/DefaultBundle/ICMPv6Packet.cc b/Packets/DefaultBundle/ICMPv6Packet.cc new file mode 100644 index 0000000..719b8d9 --- /dev/null +++ b/Packets/DefaultBundle/ICMPv6Packet.cc @@ -0,0 +1,70 @@ +// Copyright (C) 2008 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Philipp Batroff +// +// 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. + +// Custom includes +#include "../../Packets/Packets.hh" +#include "ICMPv6Packet.hh" +#include +#include "../../Packets/DefaultBundle/IPv6Packet.hh" +#include "../../Utils/IpChecksum.hh" + +#define prefix_ + +namespace { + senf::PacketRegistry::RegistrationProxy + registerICMPv6Packet (58); +} + +prefix_ void senf::ICMPV6PacketParser::calcChecksum() const { + + senf::IpChecksum summer; + senf::IPv6Packet ipv6 (packet().rfind(senf::nothrow)); + + summer.feed( ipv6->source().i(), + ipv6->source().i() + senf::IPv6Packet::Parser::source_t::fixed_bytes ); + // The destination used here must be the *final* destination ... + summer.feed( ipv6->destination().i(), ipv6->destination().i() + senf::IPv6PacketParser::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() + ipv6->length(), i() + ipv6->length() + 2 ); + // --> http://www.iana.org/assignments/protocol-numbers + // need to insert the correct protocol number here, NOT static 17!! + summer.feed( 0u ); + summer.feed( 58u ); + // since header are 16 / even 32bit aligned we don't have to care for padding. since IpChecksum + // cares for padding at the final summing we don't have to care is the payload is 16nbit-aligned, too. + summer.feed( i(), i()+checksum_offset ); + summer.feed( i()+checksum_offset+2, data().end() ); + + boost::uint16_t rv (summer.sum()); + this->checksum() << (rv ? rv : 0xffffu); +} + +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->checksumOutput() << "\n"; +} + +#undef prefix_ diff --git a/Packets/DefaultBundle/ICMPv6Packet.hh b/Packets/DefaultBundle/ICMPv6Packet.hh new file mode 100644 index 0000000..ad8bb00 --- /dev/null +++ b/Packets/DefaultBundle/ICMPv6Packet.hh @@ -0,0 +1,73 @@ +// Copyright (C) 2008 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Philipp Batroff +// +// 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. + +#ifndef HH_ICMPV6Packet +#define HH_ICMPV6Packet + +// Custom includes +#include "../../Packets/Packets.hh" +#include "../../Packets/DefaultBundle/IPv6Packet.hh" + +namespace senf{ + struct ICMPV6PacketParser : public senf::PacketParserBase + { + # include SENF_FIXED_PARSER() + SENF_PARSER_FIELD ( type, senf::UInt8Parser ); + SENF_PARSER_FIELD ( code, senf::UInt8Parser ); + SENF_PARSER_PRIVATE_FIELD ( checksum, senf::UInt16Parser); + + SENF_PARSER_FINALIZE ( ICMPV6PacketParser ); + + void calcChecksum() const; + boost::uint16_t checksumOutput() const + { return this->checksum();} + }; + + struct ICMPTypes { + // ICMP type registry + typedef boost::uint16_t key_t; + }; + + struct ICMPV6PacketType + : public senf::PacketTypeBase, + public senf::PacketTypeMixin + { + typedef senf::PacketTypeMixin mixin; + typedef senf::ConcretePacket packet; + typedef ICMPV6PacketParser parser; + + using mixin::nextPacketRange; + using mixin::nextPacketType; + using mixin::init; + using mixin::initSize; + + static void dump(packet p, std::ostream & os); + static senf::IpTypes::key_t nextPacketKey(packet p) { + return p->type(); + } + static void finalize(packet p) { + p->calcChecksum(); + p->type() << key(p.next(senf::nothrow)); + } + }; + + typedef ICMPV6PacketType::packet ICMPv6Packet; +} +#endif diff --git a/Packets/DefaultBundle/ICMPv6Packet.test.cc b/Packets/DefaultBundle/ICMPv6Packet.test.cc new file mode 100644 index 0000000..3b1bd02 --- /dev/null +++ b/Packets/DefaultBundle/ICMPv6Packet.test.cc @@ -0,0 +1,46 @@ +// $Id: main.test.cc 206 2007-02-20 14:20:52Z g0dil $ +// +// Copyright (C) 2006 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Philipp Batroff +// +// 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. + +// Definition of non-inline non-template functions + +// Custom includes + +#include "ICMPv6Packet.hh" +#include "../../Packets/Packets.hh" +#include "../../Utils/auto_unit_test.hh" +#include +#include "ICMPv6TypePacket.hh" + +BOOST_AUTO_UNIT_TEST(ICMPv6Packet_packet) +{ + unsigned char data[] = { 0x8f, 0x00 ,0x8d ,0x54 ,0x00 ,0x00 ,0x00 ,0x01 ,0x04 ,0x00 ,0x00 ,0x00 ,0xff ,0x15 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x00 ,0x16}; + + senf::ICMPv6Packet p ( senf::ICMPv6Packet::create(data) ); + + BOOST_CHECK_EQUAL( p->type(), 0x8f); + BOOST_CHECK_EQUAL( p->code(), 0x00); + BOOST_CHECK_EQUAL( p->checksumOutput(), 0x8d54); + BOOST_CHECK( p.next() ); + BOOST_CHECK( p.next().is() ); + BOOST_CHECK_EQUAL( p.next().size(), 24u ); + +} diff --git a/Packets/DefaultBundle/ICMPv6TypePacket.cc b/Packets/DefaultBundle/ICMPv6TypePacket.cc new file mode 100644 index 0000000..f0c434b --- /dev/null +++ b/Packets/DefaultBundle/ICMPv6TypePacket.cc @@ -0,0 +1,48 @@ +// $Id: main.test.cc 206 2008-06-08 14:20:52Z pug $ +// +// Copyright (C) 2006 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Philipp Batroff +// +// 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. + +// Definition of non-inline non-template functions + +// Custom includes +#include "../../Packets/Packets.hh" +#include "ICMPv6Packet.hh" +#include "ICMPv6TypePacket.hh" + +namespace { +//Implementing the ICMPv6 Type registry + senf::PacketRegistry::RegistrationProxy + registerICMPV6ErrDestUnreachable (1); + senf::PacketRegistry::RegistrationProxy + registerICMPV6ErrTooBig (2); + senf::PacketRegistry::RegistrationProxy + registerICMPV6ErrTimeExceeded (3); + senf::PacketRegistry::RegistrationProxy + registerICMPV6ErrParamProblem (4); + senf::PacketRegistry::RegistrationProxy + registerICMPv6EchoReq (128); + senf::PacketRegistry::RegistrationProxy + registerICMPv6EchoReply (129); + senf::PacketRegistry::RegistrationProxy + registerMLDv2ListenerQuery (130); + senf::PacketRegistry::RegistrationProxy + registerMLDv2ListenerReport (143); +} diff --git a/Packets/DefaultBundle/ICMPv6TypePacket.hh b/Packets/DefaultBundle/ICMPv6TypePacket.hh new file mode 100644 index 0000000..0b28c35 --- /dev/null +++ b/Packets/DefaultBundle/ICMPv6TypePacket.hh @@ -0,0 +1,314 @@ +// $Id: main.test.cc 206 2008-06-08 14:20:52Z pug $ +// +// Copyright (C) 2006 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Philipp Batroff +// +// 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. + +// Definition of non-inline non-template functions + +#ifndef HH_ICMPV6TYPEPacket +#define HH_ICMPV6TYPEPacket +// Custom includes +#include "../../Packets/Packets.hh" +#include "ICMPv6Packet.hh" + +namespace senf{ + //############################################################# + //ICMPv6 Echo Request + //############################################################# + struct ICMPV6EchoRequestParser : public senf::PacketParserBase + { + # include SENF_FIXED_PARSER() + SENF_PARSER_FIELD ( identifier, senf::UInt16Parser ); + SENF_PARSER_FIELD ( seqNr, senf::UInt16Parser ); + + SENF_PARSER_FINALIZE ( ICMPV6EchoRequestParser ); + }; + + struct ICMPV6EchoRequestType + : public senf::PacketTypeBase, + public senf::PacketTypeMixin + { + typedef senf::PacketTypeMixin mixin; + typedef senf::ConcretePacket packet; + typedef ICMPV6EchoRequestParser parser; + + using mixin::nextPacketRange; + using mixin::init; + using mixin::initSize; + }; + + typedef ICMPV6EchoRequestType::packet ICMPv6EchoReq; + + //############################################################# + //ICMPv6 Echo Reply + //############################################################# + struct ICMPV6EchoReplyParser : public senf::PacketParserBase + { + # include SENF_FIXED_PARSER() + SENF_PARSER_FIELD ( identifier, senf::UInt16Parser ); + SENF_PARSER_FIELD ( seqNr, senf::UInt16Parser ); + + SENF_PARSER_FINALIZE ( ICMPV6EchoReplyParser ); + }; + + struct ICMPV6EchoReplyType + : public senf::PacketTypeBase, + public senf::PacketTypeMixin + { + typedef senf::PacketTypeMixin mixin; + typedef senf::ConcretePacket packet; + typedef ICMPV6EchoReplyParser parser; + + using mixin::nextPacketRange; + using mixin::init; + using mixin::initSize; + }; + typedef ICMPV6EchoReplyType::packet ICMPv6EchoReply; + + //############################################################# + //ICMPv6 Error Destination Unreachable Message + //############################################################# + struct ICMPV6ErrDestUnreachableParser : public senf::PacketParserBase + { + # include SENF_FIXED_PARSER() + //should be set static 0 by sender and ignored by receiver + SENF_PARSER_PRIVATE_FIELD ( unused, senf::UInt32Parser ); + + SENF_PARSER_INIT() { unused() = 0; } + /* Code 0 - No route to destination + 1 - Communication with destination + administratively prohibited + 2 - Beyond scope of source address + 3 - Address unreachable + 4 - Port unreachable + 5 - Source address failed ingress/egress policy + 6 - Reject route to destination */ + void setErrCode(int code){ + ICMPv6Packet icmpv6 (senf::Packet().rfind(senf::nothrow)); + icmpv6->code() = code; + } + + SENF_PARSER_FINALIZE ( ICMPV6ErrDestUnreachableParser ); + }; + + struct ICMPV6ErrDestUnreachableType + : public senf::PacketTypeBase, + public senf::PacketTypeMixin + { + typedef senf::PacketTypeMixin mixin; + typedef senf::ConcretePacket packet; + typedef ICMPV6ErrDestUnreachableParser parser; + + using mixin::nextPacketRange; + using mixin::init; + using mixin::initSize; + }; + typedef ICMPV6ErrDestUnreachableType::packet ICMPV6ErrDestUnreachable; + + //############################################################# + //ICMPv6 Error Packet Too Big Message + //############################################################# + struct ICMPV6ErrTooBigParser : public senf::PacketParserBase + { + # include SENF_FIXED_PARSER() + SENF_PARSER_FIELD ( MTU, senf::UInt32Parser ); + + /* Code static set to 0 */ + // SENF_PARSER_INIT() { + // ICMPv6Packet icmpv6 (senf::Packet().rfind(senf::nothrow)); + // icmpv6->code() = 0; + // } + + SENF_PARSER_FINALIZE ( ICMPV6ErrTooBigParser ); + }; + + struct ICMPV6ErrTooBigType + : public senf::PacketTypeBase, + public senf::PacketTypeMixin + { + typedef senf::PacketTypeMixin mixin; + typedef senf::ConcretePacket packet; + typedef ICMPV6ErrTooBigParser parser; + + using mixin::nextPacketRange; + using mixin::init; + using mixin::initSize; + }; + typedef ICMPV6ErrTooBigType::packet ICMPV6ErrTooBig; + + //############################################################# + //ICMPv6 Error Time Exceeded Message + //############################################################# + struct ICMPV6ErrTimeExceededParser : public senf::PacketParserBase + { + # include SENF_FIXED_PARSER() + //should be set static 0 by sender and ignored by receiver + SENF_PARSER_FIELD ( unused, senf::UInt32Parser ); + /* Code 0 - Hop limit exceeded in transit + 1 - Fragment reassembly time exceeded */ + void setErrCode(int code){ + ICMPv6Packet icmpv6 (senf::Packet().rfind(senf::nothrow)); + icmpv6->code() = code; + } + + SENF_PARSER_FINALIZE ( ICMPV6ErrTimeExceededParser ); + }; + + struct ICMPV6ErrTimeExceededType + : public senf::PacketTypeBase, + public senf::PacketTypeMixin + { + typedef senf::PacketTypeMixin mixin; + typedef senf::ConcretePacket packet; + typedef ICMPV6ErrTimeExceededParser parser; + + using mixin::nextPacketRange; + using mixin::init; + using mixin::initSize; + }; + typedef ICMPV6ErrTimeExceededType::packet ICMPV6ErrTimeExceeded; + + //############################################################# + //ICMPv6 Error Parameter Problem Message + //############################################################# + struct ICMPV6ErrParamProblemParser : public senf::PacketParserBase + { + # include SENF_FIXED_PARSER() + //should be set static 0 by sender and ignored by receiver + SENF_PARSER_FIELD ( pointer, senf::UInt32Parser ); + /* Code 0 - Erroneous header field encountered + 1 - Unrecognized Next Header type encountered + 2 - Unrecognized IPv6 option encountered */ + + void setErrCode(int code){ + ICMPv6Packet icmpv6 (senf::Packet().rfind(senf::nothrow)); + icmpv6->code() = code; + } + SENF_PARSER_FINALIZE ( ICMPV6ErrParamProblemParser ); + }; + + struct ICMPV6ErrParamProblemType + : public senf::PacketTypeBase, + public senf::PacketTypeMixin + { + typedef senf::PacketTypeMixin mixin; + typedef senf::ConcretePacket packet; + typedef ICMPV6ErrParamProblemParser parser; + + using mixin::nextPacketRange; + using mixin::init; + using mixin::initSize; + }; + typedef ICMPV6ErrParamProblemType::packet ICMPV6ErrParamProblem; + + //############################################################# + //ICMPv6 MLDv2 (RFC 3810) Multicast Listener Query + //############################################################# + struct MLDv2ListenerQueryParser : public senf::PacketParserBase + { + # include SENF_PARSER() + //need a variant here + // a.) maxResponseCode < 32768 =>Interger + // b.) maxResponseCode >=32768 => float (is there a float parser???) + /* + float value as followed: + 0 1 2 3 4 5 6 7 8 9 A B C D E F + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |1| exp | mant | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ + + SENF_PARSER_FIELD ( maxResponseCode, senf::UInt16Parser ); + SENF_PARSER_FIELD ( reserved, senf::UInt16Parser ); //set to zero by default + SENF_PARSER_FIELD ( mcAddress, senf::INet6AddressParser); + SENF_PARSER_BITFIELD ( resv, 4, unsigned); //set to zero by default + SENF_PARSER_BITFIELD ( sFlag, 1, unsigned); + SENF_PARSER_BITFIELD ( qrv, 3, unsigned); + SENF_PARSER_FIELD ( qqic, senf::UInt8Parser ); + SENF_PARSER_PRIVATE_FIELD ( nrSources, senf::UInt16Parser ); + SENF_PARSER_VECTOR (srcAddresses, nrSources, senf::INet6AddressParser ); + + SENF_PARSER_INIT() + { + reserved() = 0; + resv() = 0; + } + SENF_PARSER_FINALIZE ( MLDv2ListenerQueryParser ); + + }; + + struct MLDv2ListenerQueryType + : public senf::PacketTypeBase, + public senf::PacketTypeMixin + { + typedef senf::PacketTypeMixin mixin; + typedef senf::ConcretePacket packet; + typedef MLDv2ListenerQueryParser parser; + + using mixin::nextPacketRange; + using mixin::init; + using mixin::initSize; + }; + typedef MLDv2ListenerQueryType::packet MLDv2ListenerQuery; + + //############################################################# + //ICMPv6 MLDv2 (RFC 3810) Multicast Listener Report Message + //############################################################# + //First: the Multicast Address Record Parser + struct MLDv2AddressRecordParser : public senf::PacketParserBase + { + # include SENF_PARSER() + SENF_PARSER_FIELD ( recordType, senf::UInt8Parser ); + SENF_PARSER_PRIVATE_FIELD ( auxDataLen, senf::UInt8Parser ); + SENF_PARSER_PRIVATE_FIELD ( nrOfSrcs, senf::UInt16Parser ); + SENF_PARSER_FIELD ( mcAddress, senf::INet6AddressParser); + SENF_PARSER_VECTOR ( srcAddresses, nrOfSrcs, senf::INet6AddressParser ); + SENF_PARSER_VECTOR ( auxData, auxDataLen, senf::UInt32Parser ); + + + SENF_PARSER_FINALIZE ( MLDv2AddressRecordParser ); + }; + + struct MLDv2ListenerReportParser : public senf::PacketParserBase + { + # include SENF_PARSER() + SENF_PARSER_FIELD ( reserved, senf::UInt16Parser ); //set to zero by default + SENF_PARSER_PRIVATE_FIELD ( nrMcastAddrRecords_, senf::UInt16Parser ); + SENF_PARSER_LIST ( mcastAddrRecords, nrMcastAddrRecords_, MLDv2AddressRecordParser ); + + SENF_PARSER_INIT() { reserved() = 0; } + + SENF_PARSER_FINALIZE ( MLDv2ListenerReportParser ); + }; + + struct MLDv2ListenerReportType + : public senf::PacketTypeBase, + public senf::PacketTypeMixin + { + typedef senf::PacketTypeMixin mixin; + typedef senf::ConcretePacket packet; + typedef MLDv2ListenerReportParser parser; + + using mixin::nextPacketRange; + using mixin::init; + using mixin::initSize; + }; + typedef MLDv2ListenerReportType::packet MLDv2ListenerReport; +} +#endif