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

📄 test_request.cc

📁 RIP 协议实现
💻 CC
字号:
// -*- 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.#ident "$XORP: xorp/rip/test_request.cc,v 1.30 2008/07/23 05:11:37 pavlin Exp $"#include <set>#include "rip_module.h"#include "libxorp/xlog.h"#include "libxorp/c_format.hh"#include "libxorp/eventloop.hh"#include "libxorp/ipv4.hh"#include "libxorp/ipv4net.hh"#include "auth.hh"#include "port.hh"#include "peer.hh"#include "route_db.hh"#include "system.hh"#include "test_utils.hh"#ifdef HAVE_GETOPT_H#include <getopt.h>#endif/////////////////////////////////////////////////////////////////////////////////// Constants//static const char *program_name         = "test_request";static const char *program_description  = "Test RIP handling route requests";static const char *program_version_id   = "0.1";static const char *program_date         = "July, 2003";static const char *program_copyright    = "See file LICENSE";static const char *program_return_value = "0 on success, 1 if test error, 2 if internal error";// ----------------------------------------------------------------------------// Spoof Port that supports just a single Peer//template <typename A>class SpoofPort : public Port<A> {public:    SpoofPort(PortManagerBase<A>& pm, A addr) : Port<A>(pm)    {	this->_peers.push_back(new Peer<A>(*this, addr));	verbose_log("Constructing SpoofPort instance\n");	this->set_enabled(true);    }    ~SpoofPort()    {	verbose_log("Destructing SpoofPort instance\n");	while (this->_peers.empty() == false) {	    delete this->_peers.front();	    this->_peers.pop_front();	}    }};// ----------------------------------------------------------------------------// Type specific helperstemplate <typename A>struct DefaultPeer {    static A get();};template <>IPv4 DefaultPeer<IPv4>::get() { return IPv4("10.0.0.1"); }template <>IPv6 DefaultPeer<IPv6>::get() { return IPv6("10::1"); }// ----------------------------------------------------------------------------// Spoof Port Manager instance support a single Spoof Port which in turn// contains a single Peer.//template <typename A>class SpoofPortManager : public PortManagerBase<A> {public:    SpoofPortManager(System<A>& s, const IfMgrIfTree& iftree)	: PortManagerBase<A>(s, iftree)    {	this->_ports.push_back(new SpoofPort<A>(*this, DefaultPeer<A>::get()));    }    ~SpoofPortManager()    {	while (!this->_ports.empty()) {	    delete this->_ports.front();	    this->_ports.pop_front();	}    }    Port<A>* the_port()    {	XLOG_ASSERT(this->_ports.size() == 1);	return this->_ports.front();    }    Peer<A>* the_peer()    {	XLOG_ASSERT(this->_ports.size() == 1);	XLOG_ASSERT(this->_ports.front()->peers().size() == 1);	return this->_ports.front()->peers().front();    }};// ----------------------------------------------------------------------------// Test PortIO classtemplate <typename A>class SpoofPortIO : public PortIOBase<A>{public:    typedef A			Addr;    typedef PortIOUserBase<A>	PortIOUser;public:    SpoofPortIO(PortIOUserBase<A>& user)	: PortIOBase<A>(user, "if0", "vif0", IPv4("10.0.0.1"))    {	last_rip_send_flush();    }    /**     * Called by RIP Port instance.     */    bool send(const Addr&    addr,	      uint16_t	     port,	      const vector<uint8_t>& rip_packet)    {	_lo_addr = addr;	_lo_port = port;	_lo_data = rip_packet;	_pending = true;	return true;    }    bool pending() const    {	return _lo_port != 0;    }    const Addr&	last_rip_send_addr() const		{ return _lo_addr; }    uint16_t	last_rip_send_port() const		{ return _lo_port; }    const vector<uint8_t>& last_rip_send_data() const	{ return _lo_data; }    void last_rip_send_flush()    {	_lo_addr = A::ZERO();	_lo_port = 0;	_lo_data.resize(0);	_pending = false;    }private:    vector<uint8_t>	_lo_data;    Addr		_lo_addr;    uint16_t		_lo_port;    bool		_pending;};static const IPv4	REQUESTING_HOST = IPv4("10.0.100.1");static const uint16_t	REQUESTING_PORT = 1092;static const uint8_t	ROUTE_COST	= 5;static const IfMgrIfTree ift_dummy = IfMgrIfTree();class RequestPacketTester {public:    static const uint32_t INJECTED_ROUTES  = 10;    static const uint32_t REQUESTED_ROUTES = 25;public:    RequestPacketTester() : _e(), _rip_system(_e), _pm(_rip_system, ift_dummy)    {	_portio	= new SpoofPortIO<IPv4>(*_pm.the_port());	_pm.the_port()->set_io_handler(_portio, false);	_portio->set_enabled(true);    }    ~RequestPacketTester()    {	_portio->set_enabled(false);	delete _portio;	RouteDB<IPv4>& rdb = _rip_system.route_db();	rdb.flush_routes();    }    bool init_nets()    {	string ifname, vifname;		// XXX: not set, because not needed	RouteDB<IPv4>& rdb = _rip_system.route_db();	make_nets(_testnets, REQUESTED_ROUTES);	set<IPv4Net>::const_iterator n = _testnets.begin();	for (uint32_t i = 0; i < INJECTED_ROUTES; i++) {	    if (rdb.update_route(*n, IPv4::ZERO(), ifname, vifname, ROUTE_COST,				 0, _pm.the_peer(), PolicyTags(),				 false) == false) {		verbose_log("Failed to add route for %s\n",			    n->str().c_str());		return false;	    }	    n++;	}	return true;    }    bool    send_rip_route_queries()    {	vector<uint8_t> buf;	buf.resize(RipPacketHeader::SIZE +		   REQUESTED_ROUTES * PacketRouteEntry<IPv4>::size());	RipPacketHeaderWriter rph(&buf[0]);	rph.initialize(RipPacketHeader::REQUEST, 2);	set<IPv4Net>::const_iterator n = _testnets.begin();	for (uint32_t i = 0; i < REQUESTED_ROUTES; i++) {	    XLOG_ASSERT(n != _testnets.end());	    uint32_t offset = RipPacketHeader::SIZE +		i * PacketRouteEntry<IPv4>::size();	    PacketRouteEntryWriter<IPv4> pre(&(buf[offset]));	    pre.initialize(0, *n, IPv4::ZERO(), 0);	    n++;	}	XLOG_ASSERT(_pm.the_port() != 0);	_pm.the_port()->port_io_receive(REQUESTING_HOST, REQUESTING_PORT,					&(buf[0]), buf.size());	return true;    }    bool    check_response()    {	if (_portio->pending() == false) {	    verbose_log("No response packet sent by rip\n");	    return false;	}	if (_portio->last_rip_send_addr() != REQUESTING_HOST) {	    verbose_log("Response was not sent to originator\n");	    return false;	}	if (_portio->last_rip_send_port() != REQUESTING_PORT) {	    verbose_log("Response was not sent to originators port\n");	    return false;	}	const vector<uint8_t> buf = _portio->last_rip_send_data();	// Validate RIP packet header	const RipPacketHeader rph(&buf[0]);	if (rph.valid_command() == false) {	    verbose_log("Invalid command\n");	    return false;	}	if (rph.valid_version(RipPacketHeader::IPv4_VERSION) == false) {	    verbose_log("Invalid version\n");	    return false;	}	if (rph.valid_padding() == false) {	    verbose_log("Invalid padding\n");	    return false;	}	if (rph.command() != RipPacketHeader::RESPONSE) {	    verbose_log("Not a response packet\n");	    return false;	}	// Validate entries	const uint8_t* pre_ptr = &buf[0] + RipPacketHeader::size();	uint32_t n_entries = buf.size() / PacketRouteEntry<IPv4>::size() - 1;	if (n_entries > _testnets.size()) {	    verbose_log("Got more routes than requested (%u > %u).\n",			XORP_UINT_CAST(n_entries),			XORP_UINT_CAST(_testnets.size()));	    return false;	}	set<IPv4Net>::const_iterator ni = _testnets.begin();	for (uint32_t i = 0; i < n_entries;	     i++, pre_ptr += PacketRouteEntry<IPv4>::size()) {	    const PacketRouteEntry<IPv4> pre(pre_ptr);	    verbose_log("%s %s %u %u\n",			pre.net().str().c_str(),			pre.nexthop().str().c_str(),			XORP_UINT_CAST(pre.metric()),			pre.tag());	    if (pre.addr_family() != PacketRouteEntry<IPv4>::ADDR_FAMILY) {		verbose_log("Invalid address family in route entry %u\n",			    XORP_UINT_CAST(i));		return false;	    }	    if (*ni != pre.net()) {		verbose_log("Mismatched net in route entry %u\n",			    XORP_UINT_CAST(i));		return false;	    }	    if (i < INJECTED_ROUTES) {		if (pre.metric() != ROUTE_COST) {		    verbose_log("Metric changed.\n");		    return false;		}	    } else {		if (pre.metric() != RIP_INFINITY) {		    verbose_log("Non-existant route with finite metric??\n");		}	    }	    ni++;	}	return true;    }    int run_test()    {	if (init_nets() == false) {	    return -1;	}	bool start_test = false;	XorpTimer d = _e.set_flag_after_ms(1 * 1000, &start_test);	while (start_test == false) {	    _e.run();	}	if (send_rip_route_queries() == false) {	    return -1;	}	if (check_response() == false) {	    return -1;	}	return 0;    }protected:    EventLoop			_e;    System<IPv4>		_rip_system;    SpoofPortManager<IPv4>	_pm;    SpoofPortIO<IPv4>*		_portio;    set<IPv4Net>		_testnets;};/** * Print program info to output stream. * * @param stream the output stream the print the program info to. */static voidprint_program_info(FILE *stream){    fprintf(stream, "Name:          %s\n", program_name);    fprintf(stream, "Description:   %s\n", program_description);    fprintf(stream, "Version:       %s\n", program_version_id);    fprintf(stream, "Date:          %s\n", program_date);    fprintf(stream, "Copyright:     %s\n", program_copyright);    fprintf(stream, "Return:        %s\n", program_return_value);}/* * Print program usage information to the stderr. * * @param progname the name of the program. */static voidusage(const char* progname){    print_program_info(stderr);    fprintf(stderr, "usage: %s [-v] [-h]\n", progname);    fprintf(stderr, "       -h          : usage (this message)\n");    fprintf(stderr, "       -v          : verbose output\n");}intmain(int argc, char* const argv[]){    //    // Initialize and start xlog    //    xlog_init(argv[0], NULL);    xlog_set_verbose(XLOG_VERBOSE_LOW);         // Least verbose messages    // XXX: verbosity of the error messages temporary increased    xlog_level_set_verbose(XLOG_LEVEL_ERROR, XLOG_VERBOSE_HIGH);    xlog_add_default_output();    xlog_start();    int ch;    while ((ch = getopt(argc, argv, "hv")) != -1) {        switch (ch) {        case 'v':            set_verbose(true);            break;        case 'h':        case '?':        default:            usage(argv[0]);            xlog_stop();            xlog_exit();            if (ch == 'h')                return (0);            else                return (1);        }    }    argc -= optind;    argv += optind;    int rval = 0;    XorpUnexpectedHandler x(xorp_unexpected_handler);    try {	RequestPacketTester rpt;	rval = rpt.run_test();    } catch (...) {        // Internal error        xorp_print_standard_exceptions();        rval = 2;    }    //    // Gracefully stop and exit xlog    //    xlog_stop();    xlog_exit();    return rval;}

⌨️ 快捷键说明

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