📄 peer.cc
字号:
/* ** A corrupt message is being sent so catch the decode exception. */ XLOG_WARNING("BAD Message: %s", c.why().c_str()); } } _busy++; send_message(buf, len, callback(this, &Peer::xrl_callback, "send packet"));}struct mrt_header { uint32_t time; uint16_t type; uint16_t subtype; uint32_t length;};struct mrt_update { uint16_t source_as; uint16_t dest_as; uint16_t ifindex; uint16_t af; uint32_t source_ip; uint32_t dest_ip;};inlineconstuint8_t *mrtd_traffic_file_read(FILE *fp, size_t& len){ mrt_header header; if(fread(&header, sizeof(header), 1, fp) != 1) { if(feof(fp)) return 0; XLOG_WARNING("fread failed:%s", strerror(errno)); return 0; } len = ntohl(header.length) - sizeof(mrt_update); mrt_update update; if(fread(&update, sizeof(update), 1, fp) != 1) { if(feof(fp)) return 0; XLOG_WARNING("fread failed:%s", strerror(errno)); return 0; } uint8_t *buf = new uint8_t[len]; if(fread(buf, len, 1, fp) != 1) { if(feof(fp)) return 0; XLOG_WARNING("fread failed:%s", strerror(errno)); return 0; } return buf;}#if 0// Code to read from a MRTD table dump.// In order to hook this code up:// 1) Modify send_dump to support "routeview" as well as "update".// 2) Compare with mrtd_routeview_dump and rename to mrtd_routview_read.// 3) Update the manual.// Contributed by Ratul Mahajanstruct mrt_table { uint16_t view; uint16_t seqno; uint32_t prefix; uint8_t prefix_len; uint8_t status; uint32_t time; uint32_t peerip; uint16_t peeras; uint16_t att_len;};inlineconstuint8_t *mrtd_table_file_read(FILE *fp, size_t& len){ mrt_header header; if(fread(&header, sizeof(header), 1, fp) != 1) { if(feof(fp)) return 0; XLOG_WARNING("fread failed:%s", strerror(errno)); return 0; } uint16_t type = ntohs(header.type); if (type == 12) { // TABLE_DUMP mrt_table table; //sizeof(mrt_table) gives 24 which is incorrect size_t sizeof_table = 22; /* ** this did not work for me: the struct was not being populated ** correctly. no clue why! */ // if(fread(&table, sizeof_table, 1, fp) != 1) { // if(feof(fp)) // return 0; // XLOG_WARNING("fread failed:%s",strerror(errno)); // return 0; // } //uglier version of the above if (! (fread(&table.view, 2, 1, fp) == 1 && fread(&table.seqno, 2, 1, fp) == 1 && fread(&table.prefix, 4, 1, fp) == 1 && fread(&table.prefix_len, 1, 1, fp) == 1 && fread(&table.status, 1, 1, fp) == 1 && fread(&table.time, 4, 1, fp) == 1 && fread(&table.peerip, 4, 1, fp) == 1 && fread(&table.peeras, 2, 1, fp) == 1 && fread(&table.att_len, 2, 1, fp) == 1 ) ) { if (feof(fp)) return 0; XLOG_WARNING("fread failed:%s", strerror(errno)); return 0; } UpdatePacket update; size_t pa_len = ntohl(header.length) - sizeof_table; uint8_t * attributes = new uint8_t[pa_len]; if(fread(attributes, pa_len, 1, fp) != 1) { if(feof(fp)) return 0; XLOG_WARNING("fread failed:%s", strerror(errno)); return 0; } // this didn't work for me. i thought it should have, but didn't // look closely when it didn't. //update.add_nlri(BGPUpdateAttrib(IPv4(ntohl(table.prefix)), // ntohs(table.prefix_len))); //stupid way to do the above uint8_t *pfx = new uint8_t[5]; memcpy(pfx, &(table.prefix_len), 1); memcpy(pfx+1, &(table.prefix), 4); BGPUpdateAttrib nlri(pfx); update.add_nlri(nlri); delete [] pfx; uint8_t * d = attributes; while (pa_len > 0) { size_t used = 0; PathAttribute *pa = PathAttribute::create(d, pa_len, used); if (used == 0) xorp_throw(CorruptMessage, c_format("failed to read path attribute"), UPDATEMSGERR, ATTRLEN); update.add_pathatt(pa); d += used; pa_len -= used; } delete [] attributes; debug_msg("update packet = %s\n", update.str().c_str()); const uint8_t *buf = update.encode(len); return buf; } else { XLOG_WARNING("incorrect record type: %d", type); return 0; }}#endif/*** peer send dump mrtd update fname <count>** 0 1 2 3 4 5 6*/voidPeer::send_dump(const string& line, const vector<string>& words) throw(InvalidString){ if(6 != words.size() && 7 != words.size()) xorp_throw(InvalidString, c_format("Incorrect number of arguments:\n[%s]", line.c_str())); const char MRTD[] = "mrtd"; if(MRTD != words[3]) xorp_throw(InvalidString, c_format("Third argument should be %s not <%s>\n[%s]", MRTD, words[3].c_str(), line.c_str())); const char UPDATE[] = "update"; if(UPDATE != words[4]) xorp_throw(InvalidString, c_format("Fourth argument should be %s not <%s>\n[%s]", UPDATE, words[4].c_str(), line.c_str())); string fname = words[5]; FILE *fp = fopen(fname.c_str(), "r"); if(0 == fp) xorp_throw(InvalidString, c_format("fopen of %s failed: %s\n[%s]", fname.c_str(), strerror(errno), line.c_str())); size_t packets_to_send = 0; if(7 == words.size()) packets_to_send = atoi(words[6].c_str()); // XXX - We don't check for this to be an integer, we assume // failure returns zero. In which case the whole file is sent. /* ** It could take quite a while to send a large file so we need to ** set up the transfer and then return. */ send_dump_callback(XrlError::OKAY(), fp, 0, packets_to_send, "mrtd_traffic_send");}voidPeer::send_dump_callback(const XrlError& error, FILE *fp, const size_t packet_number, const size_t packets_to_send, const char *comment){ debug_msg("callback %s %s\n", comment, error.str().c_str()); if(XrlError::OKAY() != error) { XLOG_WARNING("callback: %s %s", comment, error.str().c_str()); fclose(fp); return; } if(packets_to_send != 0 && packet_number == packets_to_send) { fclose(fp); return; } size_t len; const uint8_t *buf; while(0 != (buf = mrtd_traffic_file_read(fp, len))) { uint8_t type = extract_8(buf + BGPPacket::TYPE_OFFSET); if(MESSAGETYPEUPDATE == type) { /* ** Save the update message in the sent trie. */ TimeVal tv; _eventloop->current_time(tv); _trie_sent.process_update_packet(tv, buf, len); _smcb = callback(this, &Peer::send_dump_callback, fp, packet_number + 1, packets_to_send, "mrtd_traffic_send"); send_message(buf, len, _smcb); return; } else { delete [] buf; } } fclose(fp);}voidPeer::trie(const string& line, const vector<string>& words) throw(InvalidString){ if(words.size() < 4) xorp_throw(InvalidString, c_format("Insufficient arguments:\n[%s]", line.c_str())); /* ** Each peer holds two tries. One holds updates sent the other ** holds updates received. Determine which trie we are about to ** operate on. */ Trie *op; if("sent" == words[2]) { op = &_trie_sent; } else if("recv" == words[2]) { op = &_trie_recv; } else xorp_throw(InvalidString, c_format("\"sent\" or \"recv\" accepted not <%s>\n[%s]", words[2].c_str(), line.c_str())); /* ** The only operation currently supported is lookup */ if("lookup" != words[3]) xorp_throw(InvalidString, c_format("\"lookup\" expected not <%s>\n[%s]", words[3].c_str(), line.c_str())); if(words.size() < 5) xorp_throw(InvalidString, c_format("No arguments for \"lookup\"\n[%s]", line.c_str())); const UpdatePacket *bgpupdate = op->lookup(words[4]); if(0 == bgpupdate) { if((words.size() == 6) && ("not" == words[5])) return; xorp_throw(InvalidString, c_format("Lookup failed [%s]", line.c_str())); } if((words.size() == 6) && ("not" == words[5])) xorp_throw(InvalidString, c_format("Lookup failed entry exists [%s]", line.c_str())); debug_msg("Found: %s\n", bgpupdate->str().c_str()); size_t size = words.size(); if(0 == (size % 2)) xorp_throw(InvalidString, c_format("Incorrect number of arguments:\n[%s]", line.c_str())); for(size_t i = 5; i < size; i += 2) { debug_msg("attribute: %s value: %s\n", words[i].c_str(), words[i + 1].c_str()); if("aspath" == words[i]) { /* ** Search for the AS Path in the update packet. */ const list<PathAttribute*>& palist = bgpupdate->pa_list(); list<PathAttribute*>::const_iterator pai; const AsPath *aspath = 0; for(pai = palist.begin(); pai != palist.end(); pai++) { if(AS_PATH == (*pai)->type()) aspath = &((static_cast<ASPathAttribute *>(*pai))-> as_path()); } if(0 == aspath) xorp_throw(InvalidString, c_format("NO AS Path associated with route\n[%s]", line.c_str())); string aspath_search; if("empty" != words[i + 1]) aspath_search = words[i + 1]; if(*aspath != AsPath(aspath_search.c_str())) xorp_throw(InvalidString, c_format("Looking for Path: <%s> Found: <%s>\n[%s]", words[i + 1].c_str(), aspath->str().c_str(), line.c_str())); } else xorp_throw(InvalidString, c_format("Illegal attribute: <%s>\n[%s]", words[i].c_str(), line.c_str())); }}/*** peer expect packet ...** 0 1 2*/voidPeer::expect(const string& line, const vector<string>& words) throw(InvalidString){ if(words.size() < 3) xorp_throw(InvalidString, c_format("Insufficient arguments:\n[%s]", line.c_str())); if("packet" == words[2]) { _expect._list.push_back(packet(line, words, 3)); } else xorp_throw(InvalidString, c_format( "\"packet\" accepted not <%s>\n[%s]", words[2].c_str(), line.c_str()));}/*** peer assert queue** 0 1 2**** peer assert queue <len>** 0 1 2 3**** peer assert connected** 0 1 2**** peer assert established** 0 1 2**** peer assert idle** 0 1 2*/voidPeer::assertX(const string& line, const vector<string>& words) throw(InvalidString){ if(words.size() < 3) xorp_throw(InvalidString, c_format("Insufficient arguments:\n[%s]", line.c_str())); if("queue" == words[2]) { if(!_expect._ok) xorp_throw(InvalidString, c_format("Expect queue violated\nExpect: %sReceived: %s", _expect._list.front()->str().c_str(), _expect._bad->str().c_str())); switch(words.size()) { case 3: break; case 4: if(static_cast<unsigned int>(atoi(words[3].c_str())) != _expect._list.size()) xorp_throw(InvalidString, c_format("Expected list size to be %d actual %u", atoi(words[3].c_str()), XORP_UINT_CAST(_expect._list.size()))); break; default: xorp_throw(InvalidString, c_format("Illegal number of arguments to \"queue\"\n[%s]", line.c_str())); break; } } else if("connected" == words[2]) { if(!_connected) xorp_throw(InvalidString, c_format("No TCP session established")); } else if("established" == words[2]) { if(!_established) xorp_throw(InvalidString, c_format("No BGP session established")); } else if("idle" == words[2]) { if(_connected) xorp_throw(InvalidString, c_format("Session established")); } else xorp_throw(InvalidString, c_format( "\"queue\" \"established\" \"idle\"accepted not <%s>\n[%s]", words[2].c_str(), line.c_str()));}voidmrtd_traffic_dump(const uint8_t *buf, const size_t len , const TimeVal tv, const string fname){ FILE *fp = fopen(fname.c_str(), "a"); if(0 == fp) XLOG_FATAL("fopen of %s failed: %s", fname.c_str(), strerror(errno)); mrt_header header; header.time = htonl(tv.sec()); header.type = htons(16); header.subtype = htons(1); header.length = htonl(len + sizeof(mrt_update)); if(fwrite(&header, sizeof(header), 1, fp) != 1) XLOG_FATAL("fwrite of %s failed: %s", fname.c_str(), strerror(errno));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -