📄 packets.hh
字号:
// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-// Copyright (c) 2001-2008 XORP, Inc.//// Permission is hereby granted, free of charge, to any person obtaining a// copy of this software and associated documentation files (the "Software")// to deal in the Software without restriction, subject to the conditions// listed in the XORP LICENSE file. These conditions include: you must// preserve this copyright notice, and you cannot mention the copyright// holders in advertising related to the Software without their permission.// The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This// notice is a summary of the XORP LICENSE file; the license in that file is// legally binding.// $XORP: xorp/rip/packets.hh,v 1.29 2008/07/23 05:11:35 pavlin Exp $#ifndef __RIP_PACKET_ENTRIES_HH__#define __RIP_PACKET_ENTRIES_HH__#include "libxorp/ipv4.hh"#include "libxorp/ipv4net.hh"#include "libxorp/ipv6.hh"#include "libxorp/ipv6net.hh"#include "libxorp/utility.h"#include "libproto/packet.hh"#include "constants.hh"/** * @short Header appearing at the start of each RIP packet. * * The RIP packet header has the following content: * * command (1 byte): // The command: 1 - request, 2 - response * version (1 byte): // 1 - IPv4 RIPv1/IPv6 RIPng, 2 - IPv4 RIP v2 * unused0 (1 byte): // Unused * unused1 (1 byte): // Unused */class RipPacketHeader {public: RipPacketHeader(const uint8_t* data) : _data(data), _command(_data + _command_offset), _version(_data + _version_offset), _unused0(_data + _unused0_offset), _unused1(_data + _unused1_offset) { static_assert(RipPacketHeader::SIZE == _command_sizeof + _version_sizeof + _unused0_sizeof + _unused1_sizeof); static_assert(RipPacketHeader::SIZE == _unused1_offset + _unused1_sizeof); } static const uint8_t REQUEST = 1; static const uint8_t RESPONSE = 2; static const uint8_t IPv4_VERSION = RIP_AF_CONSTANTS<IPv4>::PACKET_VERSION; static const uint8_t IPv6_VERSION = RIP_AF_CONSTANTS<IPv6>::PACKET_VERSION; static const size_t SIZE = 4; // The header size /** * Get the RIP packet header size. * * @return the RIP packet header size. */ static size_t size() { return RipPacketHeader::SIZE; } uint8_t command() const { return extract_8(_command); } uint8_t version() const { return extract_8(_version); } uint8_t unused0() const { return extract_8(_unused0); } uint8_t unused1() const { return extract_8(_unused1); } bool valid_command() const; bool valid_version(uint8_t v) const { return version() == v; } bool valid_padding() const;protected: // Sizes of the fields static const size_t _command_sizeof = 1; static const size_t _version_sizeof = 1; static const size_t _unused0_sizeof = 1; static const size_t _unused1_sizeof = 1; // Offsets for the fields static const size_t _command_offset = 0; static const size_t _version_offset = _command_offset + _command_sizeof; static const size_t _unused0_offset = _version_offset + _version_sizeof; static const size_t _unused1_offset = _unused0_offset + _unused0_sizeof;private: const uint8_t* _data; // The buffer data // Pointers to the fields const uint8_t* _command; // 1 - request, 2 - response const uint8_t* _version; // 1 - IPv4 RIPv1/IPv6 RIPng, 2 - IPv4 RIP v2 const uint8_t* _unused0; const uint8_t* _unused1;};inline boolRipPacketHeader::valid_command() const{ return command() == REQUEST || command() == RESPONSE;}inline boolRipPacketHeader::valid_padding() const{ return (unused0() | unused1()) == 0;}/* * @short Class for writing data to RIP packet header. */class RipPacketHeaderWriter : public RipPacketHeader {public: RipPacketHeaderWriter(uint8_t* data) : RipPacketHeader(data), _data(data), _command(_data + _command_offset), _version(_data + _version_offset), _unused0(_data + _unused0_offset), _unused1(_data + _unused1_offset) {} void initialize(uint8_t cmd, uint8_t vers);private: uint8_t* _data; // The buffer data // Pointers to the fields uint8_t* _command; // 1 - request, 2 - response uint8_t* _version; // 1 - IPv4 RIPv1/IPv6 RIPng, 2 - IPv4 RIP v2 uint8_t* _unused0; uint8_t* _unused1;};inline voidRipPacketHeaderWriter::initialize(uint8_t cmd, uint8_t vers){ embed_8(_command, cmd); embed_8(_version, vers); embed_8(_unused0, 0); embed_8(_unused1, 0);}/** * @short Route Entry as it appears in a RIP Packet. * * This structure is useful only it's specialized forms * @ref PacketRouteEntry<IPv4> and @ref PacketRouteEntry<IPv6>. */template <typename A>class PacketRouteEntry {};/* * @short Class for writing data to RIP route entry. * * This structure is useful only it's specialized forms * @ref PacketRouteEntryWriter<IPv4> and @ref PacketRouteEntryWriter<IPv6>. */template <typename A>class PacketRouteEntryWriter {};/** * Smallest RIPv2 packet size. */static const size_t RIPv2_MIN_PACKET_BYTES = 4;static const size_t RIP_MIN_PACKET_BYTES = 4;/** * Smallest authenticated RIPv2 packet size. */static const size_t RIPv2_MIN_AUTH_PACKET_BYTES = 4 + 20;/** * Largest RIPv2 packet size. */static const size_t RIPv2_MAX_PACKET_BYTES = 4 + 20 * RIPv2_ROUTES_PER_PACKET;/** * @short Route Entry appearing in RIP packets on IPv4. * * This payload is carried in RIP packets on IPv4. The entry contains * all the fields for RIPv2. RIPv1 and RIPv2 use the same size * structure, except RIPv1 treats the route tag, subnet mask and * nexthop fields as Must-Be-Zero (MBZ) items. The interpretation of * the fields is described in RFC2453. * * All items in the route entry are stored in network order. The * accessor methods provide values in host order, and the modifiers * take arguments in host order. * * The route entry has the following content: * * af (2 bytes): // The address family * tag (2 bytes): // Tag * addr (4 bytes): // Address * mask (4 bytes): // Mask * nh (4 bytes): // Next hop * metric (4 bytes): // Metric */template <>class PacketRouteEntry<IPv4> {public: PacketRouteEntry(const uint8_t* data) : _data(data), _af(_data + _af_offset), _tag(_data + _tag_offset), _addr(_data + _addr_offset), _mask(_data + _mask_offset), _nh(_data + _nh_offset), _metric(_data + _metric_offset) { static_assert(PacketRouteEntry<IPv4>::SIZE == _af_sizeof + _tag_sizeof + _addr_sizeof + _mask_sizeof + _nh_sizeof + _metric_sizeof); static_assert(PacketRouteEntry<IPv4>::SIZE == _metric_offset + _metric_sizeof); } static const size_t SIZE = 20; // The entry size /** * Get the RIP IPv4 route entry size. * * @return the RIP IPv4 route entry size. */ static size_t size() { return PacketRouteEntry<IPv4>::SIZE; } uint16_t addr_family() const { return extract_16(_af); } uint16_t tag() const { return extract_16(_tag); } IPv4 addr() const { return IPv4(_addr); } uint32_t prefix_len() const; IPv4Net net() const; IPv4 nexthop() const { return IPv4(_nh); } uint32_t metric() const { return extract_32(_metric); } /** * @return true if route entry has properties of a table request. */ bool is_table_request() const; /** * @return true if route entry has properties of an authentication entry. */ bool is_auth_entry() const; static const uint16_t ADDR_FAMILY = 2; static const uint16_t ADDR_FAMILY_DUMP = 0; static const uint16_t ADDR_FAMILY_AUTH = 0xffff;protected: // Sizes of the fields static const size_t _af_sizeof = 2; static const size_t _tag_sizeof = 2; static const size_t _addr_sizeof = 4; static const size_t _mask_sizeof = 4; static const size_t _nh_sizeof = 4; static const size_t _metric_sizeof = 4; // Offsets for the fields static const size_t _af_offset = 0; static const size_t _tag_offset = _af_offset + _af_sizeof; static const size_t _addr_offset = _tag_offset + _tag_sizeof; static const size_t _mask_offset = _addr_offset + _addr_sizeof; static const size_t _nh_offset = _mask_offset + _mask_sizeof; static const size_t _metric_offset = _nh_offset + _nh_sizeof;private: const uint8_t* _data; // The buffer data // Pointers to the fields const uint8_t* _af; const uint8_t* _tag; const uint8_t* _addr; const uint8_t* _mask; const uint8_t* _nh; const uint8_t* _metric;};inline uint32_tPacketRouteEntry<IPv4>::prefix_len() const{ return IPv4(_mask).mask_len();}inline IPv4NetPacketRouteEntry<IPv4>::net() const{ return IPv4Net(IPv4(_addr), IPv4(_mask).mask_len());}inline boolPacketRouteEntry<IPv4>::is_table_request() const{ return addr_family() == ADDR_FAMILY_DUMP && metric() == RIP_INFINITY;}inline boolPacketRouteEntry<IPv4>::is_auth_entry() const{ return addr_family() == ADDR_FAMILY_AUTH;}/* * @short Class for writing data to RIP IPv4 route entry. */template <>class PacketRouteEntryWriter<IPv4> : public PacketRouteEntry<IPv4> {public: PacketRouteEntryWriter(uint8_t* data) : PacketRouteEntry<IPv4>(data), _data(data), _af(_data + _af_offset), _tag(_data + _tag_offset), _addr(_data + _addr_offset), _mask(_data + _mask_offset), _nh(_data + _nh_offset), _metric(_data + _metric_offset) {} /** * Initialize fields as a regular routing entry. */ void initialize(uint16_t tag, const IPv4Net& net, IPv4 nh, uint32_t cost); /** * Initialize fields as a route table request. */ void initialize_table_request();private: uint8_t* _data; // The buffer data // Pointers to the fields uint8_t* _af; uint8_t* _tag; uint8_t* _addr; uint8_t* _mask; uint8_t* _nh; uint8_t* _metric;};inline voidPacketRouteEntryWriter<IPv4>::initialize(uint16_t tag, const IPv4Net& net, IPv4 nh, uint32_t cost){ embed_16(_af, ADDR_FAMILY); embed_16(_tag, tag); net.masked_addr().copy_out(_addr); net.netmask().copy_out(_mask); nh.copy_out(_nh); embed_32(_metric, cost);}inline voidPacketRouteEntryWriter<IPv4>::initialize_table_request(){ embed_16(_af, ADDR_FAMILY_DUMP); embed_16(_tag, 0); IPv4::ZERO().copy_out(_addr); IPv4::ZERO().copy_out(_mask); IPv4::ZERO().copy_out(_nh); embed_32(_metric, RIP_INFINITY);}/** * @short Route Entry for Plaintext password. * * The PlaintextPacketRouteEntry4 may appear as the first route entry * in a RIPv2 packet. It has the same size as an @ref * PacketRouteEntry<IPv4>. The address family has the special value * 0xffff which implies authentication. The authentication type is * overlaid in the route tag field and takes the special value 2. * * All items in the route entry are stored in network order. The * accessor methods provide values in host order, and the modifiers * take arguments in host order. * * The plaintext authentication entry has the following content: * * af (2 bytes): // The address family * auth (2 bytes): // Authentication type * pw (16 bytes): // Password */class PlaintextPacketRouteEntry4 {public: PlaintextPacketRouteEntry4(const uint8_t* data) : _data(data), _af(_data + _af_offset), _auth(_data + _auth_offset), _pw(_data + _pw_offset) { static_assert(PlaintextPacketRouteEntry4::SIZE == _af_sizeof + _auth_sizeof + _pw_sizeof); static_assert(PlaintextPacketRouteEntry4::SIZE == _pw_offset + _pw_sizeof); } static const size_t SIZE = 20; // The entry size /** * Get the RIP IPv4 plaintext password route entry size. * * @return the RIP IPv4 plaintext password route entry size. */ static size_t size() { return PlaintextPacketRouteEntry4::SIZE; } uint16_t addr_family() const { return extract_16(_af); } uint16_t auth_type() const { return extract_16(_auth); } string password() const; static const uint16_t ADDR_FAMILY = 0xffff; static const uint16_t AUTH_TYPE = 2;protected: // Sizes of the fields static const size_t _af_sizeof = 2; static const size_t _auth_sizeof = 2; static const size_t _pw_sizeof = 16; // Offsets for the fields static const size_t _af_offset = 0; static const size_t _auth_offset = _af_offset + _af_sizeof; static const size_t _pw_offset = _auth_offset + _auth_sizeof;private: const uint8_t* _data; // The buffer data // Pointers to the fields const uint8_t* _af; const uint8_t* _auth; const uint8_t* _pw;};inline stringPlaintextPacketRouteEntry4::password() const{ return string(reinterpret_cast<const char *>(_pw), 0, _pw_sizeof);}/** * @short Class for writing data to Plaintext password authentication entry. */class PlaintextPacketRouteEntry4Writer : public PlaintextPacketRouteEntry4 {public: PlaintextPacketRouteEntry4Writer(uint8_t* data) : PlaintextPacketRouteEntry4(data), _data(data), _af(_data + _af_offset), _auth(_data + _auth_offset), _pw(_data + _pw_offset) {} /** * Initialize the entry. */ void initialize(const string& s);private: uint8_t* _data; // The buffer data // Pointers to the fields uint8_t* _af; uint8_t* _auth; uint8_t* _pw;};inline voidPlaintextPacketRouteEntry4Writer::initialize(const string& s){ embed_16(_af, ADDR_FAMILY); embed_16(_auth, AUTH_TYPE); memset(_pw, 0, _pw_sizeof); s.copy(reinterpret_cast<char *>(_pw), _pw_sizeof);}/** * @short Route Entry for MD5 data. * * The MD5PacketRouteEntry4 may appear as the first route entry * in a RIPv2 packet. It has the same size as an @ref * PacketRouteEntry<IPv4>. The address family has the special value * 0xffff which implies authentication. The authentication type is * overlaid in the route tag field and takes the special value 3. With * MD5 the authentication data appears after the remaining route entries. * Details are disclosed in RFC2082. * * All items in the route entry are stored in network order. The * accessor methods provide values in host order, and the modifiers * take arguments in host order. * * NB We describe the field labelled as "RIP-2 Packet Length" on page 5 of * RFC 2082 as the "auth_off". This matches the textual description in * the RFC. * * The MD5 authentication entry has the following content: * * af (2 bytes): // 0xffff - Authentication header * auth (2 bytes): // Authentication type * auth_off (2 bytes): // Offset of authentication data * key_id (1 byte): // Key number used * auth_bytes (1 byte): // Auth data length at end of packet * seqno (4 bytes): // Monotonically increasing seqno * mbz (8 bytes): // Must-be-zero */class MD5PacketRouteEntry4 {public: MD5PacketRouteEntry4(const uint8_t* data) : _data(data), _af(_data + _af_offset), _auth(_data + _auth_offset), _auth_off(_data + _auth_off_offset), _key_id(_data + _key_id_offset), _auth_bytes(_data + _auth_bytes_offset), _seqno(_data + _seqno_offset), _mbz(_data + _mbz_offset) { static_assert(MD5PacketRouteEntry4::SIZE == _af_sizeof + _auth_sizeof + _auth_off_sizeof + _key_id_sizeof + _auth_bytes_sizeof + _seqno_sizeof + _mbz_sizeof); static_assert(MD5PacketRouteEntry4::SIZE == _mbz_offset + _mbz_sizeof); } static const size_t SIZE = 20; // The entry size /** * Get the RIP IPv4 MD5 authentication route entry size. * * @return the RIP IPv4 MD5 authentication route entry size. */ static size_t size() { return MD5PacketRouteEntry4::SIZE; } uint16_t addr_family() const { return extract_16(_af); } uint16_t auth_type() const { return extract_16(_auth); } uint16_t auth_off() const { return extract_16(_auth_off); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -