📄 peer.cc
字号:
"\"traffic\" or \"routeview\" or \"replay\" or \"debug\" accepted not <%s>\n[%s]", words[4].c_str(), line.c_str()));}boolcompare_packets(const BGPPacket *base_one, const BGPPacket *base_two){ if(base_one->type() != base_two->type()) return false; switch(base_one->type()) { case MESSAGETYPEOPEN: { const OpenPacket *one = dynamic_cast<const OpenPacket *>(base_one); const OpenPacket *two = dynamic_cast<const OpenPacket *>(base_two); return *one == *two; } break; case MESSAGETYPEUPDATE: { const UpdatePacket *one = dynamic_cast<const UpdatePacket *>(base_one); const UpdatePacket *two = dynamic_cast<const UpdatePacket *>(base_two); return *one == *two; } break; case MESSAGETYPENOTIFICATION: { const NotificationPacket *one = dynamic_cast<const NotificationPacket *>(base_one); const NotificationPacket *two = dynamic_cast<const NotificationPacket *>(base_two); return *one == *two; } break; case MESSAGETYPEKEEPALIVE: { const KeepAlivePacket *one = dynamic_cast<const KeepAlivePacket *>(base_one); const KeepAlivePacket *two = dynamic_cast<const KeepAlivePacket *>(base_two); return *one == *two; } break; default: XLOG_FATAL("Unexpected BGP message type %d", base_one->type()); } return false;}/*** We just received a BGP message. Check our expected queue for a match.*/voidPeer::check_expect(BGPPacket *rec){ /* ** If its already gone bad just return. */ if(!_expect._ok) return; /* ** If there is nothing on the queue return. */ if(_expect._list.empty()) return; const BGPPacket *exp = _expect._list.front(); debug_msg("Expecting: %s\n", exp->str().c_str()); if(compare_packets(rec, exp)) { _expect._list.pop_front(); delete exp; } else { debug_msg("Received packet %s did not match Expected\n", rec->str().c_str()); _expect._ok = false; /* ** Need to go through this performance in order to copy a ** packet. */ size_t rec_len; const uint8_t *rec_buf = rec->encode(rec_len); switch(rec->type()) { case MESSAGETYPEOPEN: { OpenPacket *pac = new OpenPacket(rec_buf, rec_len); _expect._bad = pac; } break; case MESSAGETYPEUPDATE: { UpdatePacket *pac = new UpdatePacket(rec_buf, rec_len); _expect._bad = pac; } break; case MESSAGETYPENOTIFICATION: { NotificationPacket *pac = new NotificationPacket(rec_buf, rec_len); _expect._bad = pac; } break; case MESSAGETYPEKEEPALIVE: _expect._bad = new KeepAlivePacket(rec_buf, rec_len); break; default: XLOG_FATAL("Unexpected BGP message type %d", rec->type()); } delete [] rec_buf; }}voidPeer::xrl_callback(const XrlError& error, const char *comment){ debug_msg("callback %s %s\n", comment, error.str().c_str()); XLOG_ASSERT(0 != _busy); _busy--; if(XrlError::OKAY() != error) { XLOG_WARNING("callback: %s %s", comment, error.str().c_str()); _session = false; _established = false; }}/*** This method receives data from the BGP process under test via the** 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(), (uint32_t)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()); 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]; const fixed_header *header = reinterpret_cast<const struct fixed_header *>(buf); if (!_traffic_recv.is_empty()) _traffic_recv->dispatch(buf, length, tv); try { switch(header->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", (uint32_t)length); KeepAlivePacket pac(buf, length); debug_msg(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", header->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()); _session = false; _established = false;}voidPeer::send_message(const uint8_t *buf, const size_t len, SMCB cb){ debug_msg("len: %u\n", (uint32_t)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"); }; 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);}/*** 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); 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]) { bgpupdate->add_pathatt(OriginAttribute(static_cast<OriginType> (atoi(words[i + 1].c_str())))); } else if("aspath" == words[i]) { string aspath = words[i+1]; bgpupdate->add_pathatt(ASPathAttribute(AsPath( aspath.c_str()))); debug_msg("aspath: %s\n", AsPath(aspath.c_str()).str().c_str()); } else if("nexthop" == words[i]) { bgpupdate->add_pathatt(IPv4NextHopAttribute(IPv4( words[i+1].c_str()))); } else if("nexthop6" == words[i]) { mpipv6_nlri.set_nexthop(IPv6(words[i+1].c_str())); } else if("localpref" == words[i]) { bgpupdate->add_pathatt(LocalPrefAttribute(atoi( words[i+1].c_str()))); } else if("nlri" == words[i]) { bgpupdate->add_nlri(BGPUpdateAttrib(IPv4Net( words[i+1].c_str()))); } else if("nlri6" == words[i]) { mpipv6_nlri.add_nlri(words[i+1].c_str()); } else if("withdraw" == words[i]) { bgpupdate->add_withdrawn(BGPUpdateAttrib(IPv4Net( words[i+1].c_str()))); } else if("withdraw6" == words[i]) { mpipv6_withdraw.add_withdrawn(IPv6Net(words[i+1].c_str())); } else if("med" == words[i]) { bgpupdate->add_pathatt(MEDAttribute(atoi( words[i+1].c_str()))); } else if("pathattr" == words[i]) { bgpupdate->add_pathatt(AnyAttribute(words[i+1].c_str())); } 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); } 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 update:\n[%s]", line.c_str())); string asnum; string bgpid; string holdtime; 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 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())); } OpenPacket *open = new OpenPacket(AsNum( static_cast<uint16_t>(atoi(asnum.c_str()))), IPv4(bgpid.c_str()), atoi(holdtime.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 + -