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

📄 port.cc

📁 RIP 协议实现
💻 CC
📖 第 1 页 / 共 3 页
字号:
template <typename A>voidPort<A>::record_bad_auth_packet(const string&	why,				const Addr&	host,				uint16_t	port,				Peer<A>*	p){    XLOG_INFO("RIP port %s/%s/%s authentication failed %s:%u - %s\n",	      this->_pio->ifname().c_str(), this->_pio->vifname().c_str(),	      this->_pio->address().str().c_str(), host.str().c_str(), port,	      why.c_str());    counters().incr_bad_auth_packets();    if (p) {	p->counters().incr_bad_auth_packets();    }}template <typename A>voidPort<A>::record_bad_route(const string&	why,			  const Addr&	host,			  uint16_t	port,			  Peer<A>*	p){    XLOG_INFO("RIP port %s/%s/%s received bad route from %s:%u - %s\n",	      this->_pio->ifname().c_str(), this->_pio->vifname().c_str(),	      this->_pio->address().str().c_str(), host.str().c_str(), port,	      why.c_str());    counters().incr_bad_routes();    if (p) {	p->counters().incr_bad_routes();    }}static voidnoop(){}template <typename A>voidPort<A>::block_queries(){    EventLoop& e = _pm.eventloop();    _query_blocked_timer	= e.new_oneoff_after_ms(constants().interquery_delay_ms(),				callback(noop));}template <typename A>boolPort<A>::queries_blocked() const{    return _query_blocked_timer.scheduled();}template <typename A>voidPort<A>::push_packets(){    if (this->io_handler()->pending())	return;    const RipPacket<A>* head = _packet_queue->head();    if (head == 0)	return;    if (this->io_handler()->send(head->address(), head->port(), 				 head->data())) {	return;    }    XLOG_WARNING("Send failed: discarding outbound packets.");    _packet_queue->flush_packets();}template <typename A>pair<A,uint16_t>Port<A>::route_policy(const RouteEntry<A>& r) const{    if (r.net() == RIP_AF_CONSTANTS<A>::DEFAULT_ROUTE() &&	advertise_default_route() == false) {	return make_pair(A::ZERO(), RIP_MAX_COST);    }    uint16_t cost = r.cost();    const Peer<A>* peer = dynamic_cast<const Peer<A>*>(r.origin());    if (peer == 0) {	// Route did not come from a peer: it's a static route or a	// redist route.  No horizon checking necessary.	return make_pair(A::ZERO(), cost);    }    const Port<A>& peer_port = peer->port();    if (&peer_port != this) {	// Route did not originate from this Port instance. No horizon	// checking necessary.	return make_pair(A::ZERO(), cost);    }    switch (horizon()) {    case NONE:	// No processing	break;    case SPLIT:	// Don't advertise route back to source	cost = RIP_MAX_COST;	break;    case SPLIT_POISON_REVERSE:	// Advertise back at cost of infinity	cost = RIP_INFINITY;	break;    }    return make_pair(A::ZERO(), cost);}template <typename A>voidPort<A>::port_io_send_completion(bool success){    if (success == false) {	XLOG_ERROR("Send failed\n");    }    const RipPacket<A>* head = _packet_queue->head();    XLOG_ASSERT(head != 0);    _packet_queue->pop_head();    push_packets();}template <typename A>voidPort<A>::port_io_enabled_change(bool en){    start_stop_output_processing();    if (en == false)	kill_peer_routes();}template <typename A>voidPort<A>::start_stop_output_processing(){    if (output_allowed()) {	start_request_table_timer();	start_output_processing();	request_table();    } else {	stop_request_table_timer();	stop_output_processing();    }}template <typename A>voidPort<A>::kill_peer_routes(){#ifdef INSTANTIATE_IPV4    // Reset the authentication handler    PortAFSpecState<IPv4>& pss = af_state();    if (pss.auth_handler() != NULL)	pss.auth_handler()->reset();#endif    typename PeerList::iterator pli = _peers.begin();    while (pli != _peers.end()) {	vector<const RouteEntry<A>*> routes;	Peer<A>* p = *pli;	p->dump_routes(routes);	typename vector<const RouteEntry<A>*>::const_iterator ri;	for (ri = routes.begin(); ri != routes.end(); ++ri) {	    const RouteEntry<A>* r = *ri;	    p->update_route(r->net(), r->nexthop(), RIP_INFINITY, r->tag(),			    r->policytags());	}	pli++;    }}template <typename A>boolPort<A>::output_allowed() const{    return enabled() && this->port_io_enabled() && (passive() == false);}template <typename A>voidPort<A>::set_enabled(bool en){    bool old_allowed = output_allowed();    _en = en;    bool allowed = output_allowed();    if (allowed != old_allowed) {	start_stop_output_processing();    }    if (en == false)	kill_peer_routes();}template <typename A>voidPort<A>::set_passive(bool p){    bool old_allowed = output_allowed();    _passive = p;    bool allowed = output_allowed();    if (allowed != old_allowed) {	start_stop_output_processing();    }}template <typename A>voidPort<A>::set_advertise_default_route(bool en){    _adv_def_rt = en;}template <typename A>voidPort<A>::set_accept_default_route(bool en){    _acc_def_rt = en;}template <typename A>voidPort<A>::set_accept_non_rip_requests(bool en){    _acc_non_rip_reqs = en;}template <typename A>voidPort<A>::parse_request(const Addr&			src_addr,		       uint16_t				src_port,		       const uint8_t*			entries_ptr,		       uint32_t				n_entries){    if (this->port_io_enabled() == false) {	debug_msg("Discarding RIP request: port io system not enabled.");	return;    }    const PacketRouteEntry<A> pre(entries_ptr);    if (n_entries == 1 && pre.is_table_request()) {	if (src_port == RIP_AF_CONSTANTS<A>::IP_PORT) {	    Peer<A>* p = peer(src_addr);	    if (p == 0) {		p = create_peer(src_addr);		p->counters().incr_packets_recv();		p->counters().incr_table_requests_recv();	    }	    // if already doing unsolicited dump, then ignore	    // set unsolicited timer timeout to zero to trigger port	    // route dump	    unsolicited_response_timeout();	} else {	    if (queries_blocked())		return;	    // if already doing a debug dump, then ignore	    // start debug route dump	    if (_su_out && _su_out->running())		return;	    // Delete existing solicited update output, which is just lying	    // around, and re-instantiate to reply to table dump request	    delete _su_out;	    EventLoop& e = _pm.eventloop();	    RouteDB<A>& rdb = _pm.system().route_db();	    _su_out = new OutputTable<A>(e, *this, *_packet_queue, rdb,					 src_addr, src_port);	    _su_out->start();	    block_queries();	}	return;    }    if (queries_blocked())	return;    //    // This is a query for a set of routes.  Answer it.    //    uint32_t i = 0;    ResponsePacketAssembler<A> rpa(*this);    RouteDB<A>& rdb = _pm.system().route_db();    while (i != n_entries) {	RipPacket<A>* pkt = new RipPacket<A>(src_addr, src_port);	rpa.packet_start(pkt);	while (rpa.packet_full() == false && i != n_entries) {	    const uint8_t* pre_ptr = entries_ptr + i * PacketRouteEntry<A>::size();	    const PacketRouteEntry<A> pre(pre_ptr);	    if (pre.prefix_len() > A::ADDR_BITLEN) {		// Route request has an address with a bad prefix length		// Unfortunately it's non-trivial for us to propagate this		// back to the offending enquirer so we just stop processing		// the request.		delete (pkt);		break;	    }	    const RouteEntry<A>* r = rdb.find_route(pre.net());	    if (r) {		rpa.packet_add_route(r->net(), r->nexthop(),				     r->cost(), r->tag());	    } else {		rpa.packet_add_route(pre.net(), A::ZERO(),				     RIP_INFINITY, 0);	    }	    i++;	}	list<RipPacket<A>*> auth_packets;	if (rpa.packet_finish(auth_packets) == true) {	    typename list<RipPacket<A>*>::iterator iter;	    for (iter = auth_packets.begin(); iter != auth_packets.end(); ++iter) {		RipPacket<A>* auth_pkt = *iter;		_packet_queue->enqueue_packet(auth_pkt);		counters().incr_non_rip_updates_sent();	    }	    delete pkt;	} else {	    delete pkt;	    break;	}    }    push_packets();    block_queries();}template <typename A>voidPort<A>::port_io_receive(const A&	src_address,			 uint16_t 	src_port,			 const uint8_t*	rip_packet,			 size_t		rip_packet_bytes){    string why;    static_assert(RipPacketHeader::SIZE == 4);    static_assert(PacketRouteEntry<A>::SIZE == 20);    if (enabled() == false) {	debug_msg("Discarding RIP packet: Port not enabled.");	return;    }    Peer<A>* p = 0;    if (src_port == RIP_AF_CONSTANTS<A>::IP_PORT) {	p = peer(src_address);    } else {	if (accept_non_rip_requests() == false) {	    return;	}	XLOG_ASSERT(p == 0);    }    record_packet(p);    if (rip_packet_bytes < RIPv2_MIN_PACKET_BYTES) {	why = c_format("Packet size less than minimum (%u < %u)",		       XORP_UINT_CAST(rip_packet_bytes),		       XORP_UINT_CAST(RIPv2_MIN_PACKET_BYTES));	record_bad_packet(why, src_address, src_port, p);	return;    }    const RipPacketHeader rph(rip_packet);    //    // Basic RIP packet header validity checks    //    if (rph.valid_command() == false) {	why = c_format("Invalid command");	record_bad_packet(why, src_address, src_port, p);	return;    } else if (rph.valid_version(RIP_AF_CONSTANTS<A>::PACKET_VERSION) == false) {	why = c_format("Invalid version (%d)", rph.version());	record_bad_packet(why, src_address, src_port, p);	return;    } else if (rph.valid_padding() == false) {	why = c_format("Invalid padding (%u,%u)",		       rph.unused0(), rph.unused1());	record_bad_packet(why,src_address, src_port, p);	return;    }    //    // Check this is not an attempt to inject routes from non-RIP port    //    if (rph.command() == RipPacketHeader::RESPONSE &&	src_port != RIP_AF_CONSTANTS<A>::IP_PORT) {	why = c_format("RIP response originating on wrong port (%d != %d)",		       src_port, RIP_AF_CONSTANTS<A>::IP_PORT);	record_bad_packet(why, src_address, src_port, p);	return;    }#if defined (INSTANTIATE_IPV4)    const uint8_t* entries_ptr = NULL;    uint32_t n_entries = 0;    bool new_peer = (p == NULL);    if ((p != NULL) && (p->route_count() == 0)) {	//	// XXX: If the peer hasn't been active for long enough, then	// consider it a new peer for authentication purpose.	// The reason we need this modification is because the idle	// peer state may be kept for a little bit too long (e.g., 2*180	// seconds), and if the peer is restarted before that we won't	// accept its initial packet with sequence number of zero.	// With this modification we can accept the first authentication	// packet with sequence number of zero immediately after	// all routes have expired (e.g., after 300 seconds).	//	new_peer = true;    }    if (af_state().auth_handler()->authenticate_inbound(rip_packet,

⌨️ 快捷键说明

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