📄 peer.cc
字号:
** test_peer. The test_peer attempts to packetise the data into BGP** messages.*/voidPeer::datain(const bool& status, const TimeVal& tv, const vector<uint8_t>& data){ debug_msg("status: %d secs: %lu micro: %lu data length: %u\n", status, (unsigned long)tv.sec(), (unsigned long)tv.usec(), XORP_UINT_CAST(data.size())); /* ** A bgp error has occured. */ if(false == status) { /* ** BGP has closed the connection to the test_peer. */ if(0 == data.size()) { XLOG_WARNING("TCP connection from test_peer: %s to: %s closed", _peername.c_str(), _target_hostname.c_str()); _connected = false; _session = false; _established = false; return; } XLOG_FATAL("Bad BGP message received by test_peer: %s from: %s", _peername.c_str(), _target_hostname.c_str()); } size_t length = data.size(); uint8_t *buf = new uint8_t[length]; for(size_t i = 0; i < length; i++) buf[i] = data[i]; uint8_t type = extract_8(buf + BGPPacket::TYPE_OFFSET); if (!_traffic_recv.is_empty()) _traffic_recv->dispatch(buf, length, tv); try { switch(type) { case MESSAGETYPEOPEN: { debug_msg("OPEN Packet RECEIVED\n"); OpenPacket pac(buf, length); debug_msg(pac.str().c_str()); if(_session && !_established && _passive) send_open(); check_expect(&pac); } break; case MESSAGETYPEKEEPALIVE: { debug_msg("KEEPALIVE Packet RECEIVED %u\n", XORP_UINT_CAST(length)); KeepAlivePacket pac(buf, length); debug_msg("%s", pac.str().c_str()); /* XXX ** Send any received keepalive right back. ** At the moment we are not bothering to maintain a timer ** to send keepalives. An incoming keepalive prompts a ** keepalive response. At the beginning of a conversation ** this keepalive response will cause the peer to go to ** established. As opens must have been exchanged for the ** peer to send a keepalive. ** */ if(_keepalive || (_session && !_established)) { XrlTestPeerV0p1Client test_peer(_xrlrouter); debug_msg("KEEPALIVE Packet SENT\n"); _busy++; if(!test_peer.send_send(_peername.c_str(), data, callback(this, &Peer::xrl_callback, "keepalive"))) XLOG_FATAL("send_send failed"); } _established = true; check_expect(&pac); } break; case MESSAGETYPEUPDATE: { debug_msg("UPDATE Packet RECEIVED\n"); UpdatePacket pac(buf, length); debug_msg(pac.str().c_str()); /* ** Save the update message in the receive trie. */ _trie_recv.process_update_packet(tv, buf, length); check_expect(&pac); } break; case MESSAGETYPENOTIFICATION: { debug_msg("NOTIFICATION Packet RECEIVED\n"); NotificationPacket pac(buf, length); debug_msg(pac.str().c_str()); check_expect(&pac); } break; default: /* ** Send a notification to the peer. This is a bad message type. */ XLOG_ERROR("Unknown packet type %d", type); } } catch(CorruptMessage c) { /* ** This peer had sent us a bad message. */ XLOG_WARNING("From peer %s: %s", _peername.c_str(), c.why().c_str()); } delete [] buf;}void Peer::datain_error(const string& reason){ XLOG_WARNING("Error on TCP connection from test_peer: %s to %s reason: %s", _peername.c_str(), _target_hostname.c_str(), reason.c_str());}voidPeer::datain_closed(){ XLOG_WARNING("TCP connection from test_peer: %s to %s closed", _peername.c_str(), _target_hostname.c_str()); _connected = false; _session = false; _established = false;}voidPeer::send_message(const uint8_t *buf, const size_t len, SMCB cb){ debug_msg("len: %u\n", XORP_UINT_CAST(len)); if(!_traffic_sent.is_empty()) { TimeVal tv; _eventloop->current_time(tv); _traffic_sent->dispatch(buf, len, tv); } vector<uint8_t> v(len); for(size_t i = 0; i < len; i++) v[i] = buf[i]; delete [] buf; XrlTestPeerV0p1Client test_peer(_xrlrouter); if(!test_peer.send_send(_peername.c_str(), v, cb)) XLOG_FATAL("send_send failed");}voidPeer::send_open(){ /* ** Create an open packet and send it in. */ OpenPacket bgpopen(_as, _id, _holdtime); if(_ipv6) bgpopen.add_parameter( new BGPMultiProtocolCapability(AFI_IPV6, SAFI_UNICAST)); size_t len; const uint8_t *buf = bgpopen.encode(len); debug_msg("OPEN Packet SENT\n%s", bgpopen.str().c_str()); _busy++; send_message(buf, len, callback(this, &Peer::xrl_callback, "open"));}/*** The standard BGP code that deals with path attributes contains** fairly stringent checking. For testing we want to be able to create** arbitary path attributes.*/class AnyAttribute : public PathAttribute {public: /* ** The attr string should be a comma separated list of numbers. */ AnyAttribute(const char *attr) throw(InvalidString) // In order to protect against accidents in the BGP code, // PathAttribute does not have a default constructor. However, // we need to manipulate a PathAttribute so pass in a valid // constructor argument. : PathAttribute(&_valid[0]) { _init_string = attr; string line = attr; vector<string> v; tokenize(line, v, ","); _data = new uint8_t [v.size()]; for(size_t i = 0; i < v.size(); i++) { _data[i] = strtol(v[i].c_str(), 0, 0);// fprintf(stderr, "%#x ", _data[i]); }// fprintf(stderr, "\n"); _size = length(_data); }; PathAttribute *clone() const { return new AnyAttribute(_init_string.c_str()); }private: static const uint8_t _valid[]; string _init_string;};const uint8_t AnyAttribute::_valid[] = {0x80|0x40, 255, 1, 1};/*** The input is a comma separated list of numbers that are turned into** an array.*/PathAttribute *Peer::path_attribute(const char *) const throw(InvalidString){ const uint8_t path[] = {0x80|0x40, 255, 1, 1}; uint16_t max_len = sizeof(path); size_t actual_length; return PathAttribute::create(&path[0], max_len, actual_length);}/** * Helper function to decipher a community string */uint32_tcommunity_interpret(const string& community){ char *endptr; uint32_t val = strtoul(community.c_str(), &endptr, 0); if (0 == *endptr) return val; if ("NO_EXPORT" == community) return CommunityAttribute::NO_EXPORT; else if ("NO_ADVERTISE" == community) return CommunityAttribute::NO_ADVERTISE; else if ("NO_EXPORT_SUBCONFED" == community) return CommunityAttribute::NO_EXPORT_SUBCONFED; else xorp_throw(InvalidString, c_format("Invalid community name %s", community.c_str())); return val;}/*** Generate a BGP message from the textual description.** Note: It is up to the caller of this method to delete the packet** that has been created.*/const BGPPacket *Peer::packet(const string& line, const vector<string>& words, int index) const throw(InvalidString){ BGPPacket *pac = 0; try { if("notify" == words[index]) { switch(words.size() - (index + 1)) { case 1: pac = new NotificationPacket(atoi(words[index + 1].c_str())); break; case 2: pac = new NotificationPacket(atoi(words[index + 1].c_str()), atoi(words[index + 2].c_str())); break; default: { int errlen = words.size() - (index + 3); if (errlen < 1) xorp_throw(InvalidString, c_format( "Incorrect number of arguments to notify:\n[%s]", line.c_str())); uint8_t buf[errlen]; for (int i=0; i< errlen; i++) { int value = atoi(words[index + 3 + i].c_str()); if (value < 0 || value > 255) xorp_throw(InvalidString, c_format( "Incorrect byte value to notify:\n[%s]", line.c_str())); buf[i] = (uint8_t)value; pac = new NotificationPacket(atoi(words[index+1].c_str()), atoi(words[index+2].c_str()), buf, errlen); } } } } else if("update" == words[index]) { size_t size = words.size(); if(0 != ((size - (index + 1)) % 2)) xorp_throw(InvalidString, c_format("Incorrect number of arguments to update:\n[%s]", line.c_str())); UpdatePacket *bgpupdate = new UpdatePacket(); MPReachNLRIAttribute<IPv6> mpipv6_nlri(SAFI_UNICAST); MPUNReachNLRIAttribute<IPv6> mpipv6_withdraw(SAFI_UNICAST); CLUSTER_LISTAttribute cl; CommunityAttribute community; for(size_t i = index + 1; i < size; i += 2) { debug_msg("name: %s value: <%s>\n", words[i].c_str(), words[i + 1].c_str()); if("origin" == words[i]) { OriginAttribute oa(static_cast<OriginType> (atoi(words[i + 1].c_str()))); bgpupdate->add_pathatt(oa); } else if("aspath" == words[i]) { string aspath = words[i+1]; if ("empty" == aspath) aspath = ""; ASPathAttribute aspa(AsPath(aspath.c_str())); bgpupdate->add_pathatt(aspa); debug_msg("aspath: %s\n", AsPath(aspath.c_str()).str().c_str()); } else if("nexthop" == words[i]) { IPv4NextHopAttribute nha(IPv4((const char*) (words[i+1].c_str()))); bgpupdate->add_pathatt(nha); } else if("nexthop6" == words[i]) { mpipv6_nlri.set_nexthop(IPv6((const char*) (words[i+1].c_str()))); } else if("localpref" == words[i]) { LocalPrefAttribute lpa(atoi(words[i+1].c_str())); bgpupdate->add_pathatt(lpa); } else if("nlri" == words[i]) { BGPUpdateAttrib upa(IPv4Net((const char*) (words[i+1].c_str()))); bgpupdate->add_nlri(upa); } else if("nlri6" == words[i]) { mpipv6_nlri.add_nlri(words[i+1].c_str()); } else if("withdraw" == words[i]) { BGPUpdateAttrib upa(IPv4Net((const char*) (words[i+1].c_str()))); bgpupdate->add_withdrawn(upa); } else if("withdraw6" == words[i]) { mpipv6_withdraw.add_withdrawn(IPv6Net(words[i+1].c_str())); } else if("med" == words[i]) { MEDAttribute ma(atoi(words[i+1].c_str())); bgpupdate->add_pathatt(ma); } else if("originatorid" == words[i]) { ORIGINATOR_IDAttribute oid(IPv4((const char *) (words[i+1].c_str()))); bgpupdate->add_pathatt(oid); } else if("clusterlist" == words[i]) { cl.prepend_cluster_id(IPv4((const char *) (words[i+1].c_str()))); } else if("community" == words[i]) { community.add_community(community_interpret(words[i+1])); } else if("pathattr" == words[i]) { AnyAttribute aa(words[i+1].c_str()); bgpupdate->add_pathatt(aa); } else xorp_throw(InvalidString, c_format("Illegal argument to update: <%s>\n[%s]", words[i].c_str(), line.c_str())); } if(!mpipv6_nlri.nlri_list().empty()) { mpipv6_nlri.encode(); bgpupdate->add_pathatt(mpipv6_nlri); } if(!mpipv6_withdraw.wr_list().empty()) { mpipv6_withdraw.encode(); bgpupdate->add_pathatt(mpipv6_withdraw); } if(!cl.cluster_list().empty()) { bgpupdate->add_pathatt(cl); } if(!community.community_set().empty()) { bgpupdate->add_pathatt(community); } pac = bgpupdate; } else if("open" == words[index]) { size_t size = words.size(); if(0 != ((size - (index + 1)) % 2)) xorp_throw(InvalidString, c_format("Incorrect number of arguments to open:\n[%s]", line.c_str())); string asnum; string bgpid; string holdtime; string afi; string safi; for(size_t i = index + 1; i < size; i += 2) { debug_msg("name: %s value: %s\n", words[i].c_str(), words[i + 1].c_str()); if("asnum" == words[i]) { asnum = words[i + 1]; } else if("bgpid" == words[i]) { bgpid = words[i + 1]; } else if("holdtime" == words[i]) { holdtime = words[i + 1]; } else if("afi" == words[i]) { afi = words[i + 1]; } else if("safi" == words[i]) { safi = words[i + 1]; } else xorp_throw(InvalidString, c_format("Illegal argument to open: <%s>\n[%s]", words[i].c_str(), line.c_str())); } if("" == asnum) { xorp_throw(InvalidString, c_format("AS number not supplied to open:\n[%s]", line.c_str())); } if("" == bgpid) { xorp_throw(InvalidString, c_format("BGP ID not supplied to open:\n[%s]", line.c_str())); } if("" == holdtime) { xorp_throw(InvalidString, c_format("Holdtime not supplied to open:\n[%s]", line.c_str())); } if(("" != afi && "" == safi) || ("" == afi && "" != safi)) { xorp_throw(InvalidString, c_format("Both AFI and SAFI must be set/not set to open:\n[%s]", line.c_str())); } OpenPacket *open = new OpenPacket(AsNum( static_cast<uint16_t>(atoi(asnum.c_str()))), IPv4(bgpid.c_str()), atoi(holdtime.c_str())); if("" != afi && "" != safi) { open->add_parameter( new BGPMultiProtocolCapability( (Afi)atoi(afi.c_str()), (Safi)atoi(safi.c_str()))); } pac = open; } else if("keepalive" == words[index]) { pac = new KeepAlivePacket(); } else xorp_throw(InvalidString, c_format("\"notify\" or" " \"update\" or" " \"open\" or" " \"keepalive\" accepted" " not <%s>\n[%s]", words[index].c_str(), line.c_str())); } catch(CorruptMessage c) { xorp_throw(InvalidString, c_format("Unable to construct packet " "%s\n[%s])", c.why().c_str(), line.c_str())); } debug_msg("%s\n", pac->str().c_str()); return pac;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -