⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 packet_assembly.hh

📁 RIP 协议实现
💻 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/packet_assembly.hh,v 1.15 2008/07/23 05:11:35 pavlin Exp $#ifndef __RIP_PACKET_ASSEMBLY_HH__#define __RIP_PACKET_ASSEMBLY_HH__#include "rip_module.h"#include "libxorp/xlog.h"#include "auth.hh"#include "packets.hh"#include "port.hh"/** * @short Internal specialized state for PacketAssembler classes. * * Completely specialized implementations exist for IPv4 and IPv6 template * arguments. */template <typename A>class PacketAssemblerSpecState{};/** * @short IPv4 specialized PacketAssembler state. * * This class just holder the authentication handler that IPv4 packet * assembly requires. */template <>class PacketAssemblerSpecState<IPv4>{private:    AuthHandlerBase& _ah;public:    /**     * IPv4 Specific Constructor.     */    PacketAssemblerSpecState(Port<IPv4>& port)	: _ah(*(port.af_state().auth_handler()))    {}    /**     * IPv4 Specific Constructor.     */    PacketAssemblerSpecState(AuthHandlerBase& auth_handler)	: _ah(auth_handler)    {}    /**     * IPv4 Specific authentication handler accessor.     */    AuthHandlerBase&	  ah()			{ return _ah; }    /**     * IPv4 Specific authentication handler accessor.     */    const AuthHandlerBase& ah() const		{ return _ah; }};/** * @short IPv6 specialized PacketAssembler state. * * This provides a means to query the RIP port and query the * configured maximum entries per packet. XXX At present it's a * placeholder and returns a fixed value. * * It also stores the last used nexthop value since nexthops are only * packed when they change. */template <>class PacketAssemblerSpecState<IPv6>{private:    uint32_t _max_entries;    IPv6     _lnh;public:    PacketAssemblerSpecState(Port<IPv6>& )	: _max_entries(25), _lnh(IPv6::ALL_ONES())    {}    PacketAssemblerSpecState()	: _max_entries(25), _lnh(IPv6::ALL_ONES())    {}    uint32_t	max_entries() const;    void	reset_last_nexthop();    void	set_last_nexthop(const IPv6& ip6);    const IPv6&	last_nexthop() const;};inline uint32_tPacketAssemblerSpecState<IPv6>::max_entries() const{    return _max_entries;}inline voidPacketAssemblerSpecState<IPv6>::reset_last_nexthop(){    _lnh = IPv6::ALL_ONES();}inline voidPacketAssemblerSpecState<IPv6>::set_last_nexthop(const IPv6& ip6){    _lnh = ip6;}inline const IPv6&PacketAssemblerSpecState<IPv6>::last_nexthop() const{    return _lnh;}/** * @short Class for RIP Response Packet Assemblers. * * Both RIPv2 and RIPng have some oddities in packing and this interface * provides a consistent interface for that packing. * * This class has specialized IPv4 and IPv6 implementations. */template <typename A>class ResponsePacketAssembler {public:    typedef A				Addr;    typedef IPNet<A>			Net;    typedef PacketAssemblerSpecState<A> SpState;public:    /**     * Constructor.     *     * @param port Port to take configuration information from.     */    ResponsePacketAssembler(Port<A>& port);    /**     * Constructor.     *     * @param sp Specialized state.     */    ResponsePacketAssembler(SpState& sp);    /**     * Destructor.     */    ~ResponsePacketAssembler();    /**     * Start assembling RIP response packet.     */    void packet_start(RipPacket<A>* pkt);    /**     * Add a route to RIP response packet.     *     * @return true if route was added, false if packet is full and would     * have indicated this if only @ref packet_full was called.     */    bool packet_add_route(const Net&	net,			  const Addr&	nexthop,			  uint16_t	cost,			  uint16_t	tag);    /**     * Ready-to-go accessor.     *     * @return true if packet has no more space for route entries.     */    bool packet_full() const;    /**     * Finish packet.  Some packet types require final stage processing     * and this method gives that processing a chance to happen.  Common     * usage is RIPv2 authentication.     *     * @param auth_packets a return-by-reference list with the     * authenticated RIP packets (one copy for each valid authentication key).     * @return true on success, false if a failure is detected.     */    bool packet_finish(list<RipPacket<A>* >& auth_packets);private:    /**     * Copy Constructor (Disabled).     */    ResponsePacketAssembler(const ResponsePacketAssembler&);    /**     * Assignment Operator (Disabled).     */    ResponsePacketAssembler& operator=(const ResponsePacketAssembler&);protected:    RipPacket<A>* _pkt;    uint32_t	  _pos;    SpState	  _sp_state;};/** * @short Class to configure a RIP packet to be a table request. * * This class has specialized IPv4 and IPv6 implementations to cater for * address family differences. */template <typename A>class RequestTablePacketAssembler {public:    typedef A				Addr;    typedef IPNet<A>			Net;    typedef PacketAssemblerSpecState<A> SpState;public:    RequestTablePacketAssembler(Port<A>& port) : _sp_state(port) {}    /**     * Take RipPacket packet and make it into a table request packet.     *     * @param auth_packets a return-by-reference list with the     * authenticated RIP packets (one copy for each valid authentication key).     * @return true on success, false if an error is encountered.  Should     * an error be encountered the reason is written to the xlog facility.     */    bool prepare(RipPacket<A>*		pkt,		 list<RipPacket<A>* >&	auth_packets);protected:    SpState _sp_state;};// ----------------------------------------------------------------------------// ResponsePacketAssembler<IPv4> implementationtemplate <>inlineResponsePacketAssembler<IPv4>::ResponsePacketAssembler(Port<IPv4>& port)    : _pkt(0), _pos(0), _sp_state(port){}template <>inlineResponsePacketAssembler<IPv4>::ResponsePacketAssembler(SpState& sp)    : _pkt(0), _pos(0), _sp_state(sp){}template <>inlineResponsePacketAssembler<IPv4>::~ResponsePacketAssembler(){}template <>inline voidResponsePacketAssembler<IPv4>::packet_start(RipPacket<IPv4>* pkt){    _pkt = pkt;    const AuthHandlerBase& ah = _sp_state.ah();    _pos = ah.head_entries();    _pkt->set_max_entries(ah.head_entries() + ah.max_routing_entries());    RipPacketHeaderWriter rph(_pkt->header_ptr());    rph.initialize(RipPacketHeader::RESPONSE, RipPacketHeader::IPv4_VERSION);}template <>inline boolResponsePacketAssembler<IPv4>::packet_full() const{    const AuthHandlerBase& ah = _sp_state.ah();    return _pos == ah.max_routing_entries();}template <>inline boolResponsePacketAssembler<IPv4>::packet_add_route(const Net&	net,						const Addr&	nexthop,						uint16_t	cost,						uint16_t	tag){    if (packet_full()) {	return false;    }    uint8_t* pre_ptr = _pkt->route_entry_ptr(_pos);    PacketRouteEntryWriter<IPv4> pre(pre_ptr);    pre.initialize(tag, net, nexthop, cost);    _pos++;    return true;}template <>inline boolResponsePacketAssembler<IPv4>::packet_finish(    list<RipPacket<IPv4>* >&	auth_packets){    AuthHandlerBase& ah = _sp_state.ah();    _pkt->set_max_entries(_pos);    size_t n_routes = 0;    if ((ah.authenticate_outbound(*_pkt, auth_packets, n_routes) != true)	|| (n_routes == 0)) {	XLOG_ERROR("Outbound authentication error: %s\n", ah.error().c_str());	return false;    }    return true;}// ----------------------------------------------------------------------------// ResponsePacketAssembler<IPv6> implementationtemplate <>inlineResponsePacketAssembler<IPv6>::ResponsePacketAssembler(Port<IPv6>& port)    : _pkt(0), _pos(0), _sp_state(port){}template <>inlineResponsePacketAssembler<IPv6>::ResponsePacketAssembler(SpState& sp)    : _pkt(0), _pos(0), _sp_state(sp){}template <>inlineResponsePacketAssembler<IPv6>::~ResponsePacketAssembler(){}template <>inline voidResponsePacketAssembler<IPv6>::packet_start(RipPacket<IPv6>* pkt){    _pkt = pkt;    _pos = 0;    _sp_state.reset_last_nexthop();    RipPacketHeaderWriter rph(_pkt->header_ptr());    rph.initialize(RipPacketHeader::RESPONSE, RipPacketHeader::IPv6_VERSION);}template <>inline boolResponsePacketAssembler<IPv6>::packet_full() const{    return (_sp_state.max_entries() - _pos) <= 2;}template <>inline boolResponsePacketAssembler<IPv6>::packet_add_route(const Net&	net,						const Addr&	nexthop,						uint16_t	cost,						uint16_t	tag){    uint8_t* pre_ptr;    if (packet_full()) {	return false;    }    if (nexthop != _sp_state.last_nexthop()) {	pre_ptr = _pkt->route_entry_ptr(_pos);	PacketRouteEntryWriter<IPv6> pre(pre_ptr);	pre.initialize_nexthop(nexthop);	_pos++;	_sp_state.set_last_nexthop(nexthop);    }    pre_ptr = _pkt->route_entry_ptr(_pos);    PacketRouteEntryWriter<IPv6> pre(pre_ptr);    pre.initialize_route(tag, net, cost);    _pos++;    return true;}template <>inline boolResponsePacketAssembler<IPv6>::packet_finish(    list<RipPacket<IPv6>* >&	auth_packets){    _pkt->set_max_entries(_pos);    RipPacket<IPv6>* packet = new RipPacket<IPv6>(*_pkt);    auth_packets.push_back(packet);        return true;}// ----------------------------------------------------------------------------// RequestTablePacketAssembler<IPv4> implementationtemplate<>inline boolRequestTablePacketAssembler<IPv4>::prepare(RipPacket<IPv4>*	    pkt,					   list<RipPacket<IPv4>* >& auth_packets){    RipPacketHeaderWriter rph(pkt->header_ptr());    rph.initialize(RipPacketHeader::REQUEST, RipPacketHeader::IPv4_VERSION);    AuthHandlerBase& ah = _sp_state.ah();    pkt->set_max_entries(1 + ah.head_entries());    uint8_t* pre_ptr = pkt->route_entry_ptr(ah.head_entries());    PacketRouteEntryWriter<IPv4> pre(pre_ptr);    pre.initialize_table_request();    size_t n_routes = 0;    if ((ah.authenticate_outbound(*pkt, auth_packets, n_routes) != true)	|| (n_routes == 0)) {	XLOG_ERROR("Outbound authentication error: %s\n", ah.error().c_str());	return false;    }    return true;}// ----------------------------------------------------------------------------// RequestTablePacketAssembler<IPv6> implementationtemplate<>inline boolRequestTablePacketAssembler<IPv6>::prepare(RipPacket<IPv6>*	    pkt,					   list<RipPacket<IPv6>* >& auth_packets){    RipPacketHeaderWriter rph(pkt->header_ptr());    rph.initialize(RipPacketHeader::REQUEST, RipPacketHeader::IPv6_VERSION);    pkt->set_max_entries(1);    uint8_t* pre_ptr = pkt->route_entry_ptr(0);    PacketRouteEntryWriter<IPv6> pre(pre_ptr);    pre.initialize_table_request();    RipPacket<IPv6>* packet = new RipPacket<IPv6>(*pkt);    auth_packets.push_back(packet);    return true;}#endif // __RIP_PACKET_ASSEMBLY_HH__

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -