#include #include #include #include "binbuf.h" // Insert a string using a length byte followed by it's characters. // For DNS requests, the limit is 63 characters, for the basic format // 255 character limit. This method performs no check on all that, // so don't abuse it. void BinaryBuffer::puts(std::string s) { put8(s.length()); for(auto x: s) put(x); } // Get a string by reading a length byte then that many characters. std::string BinaryBuffer::gets() { int len = get(); std::string ret; while(len--) ret.push_back(get()); return ret; } /* * Put a host name as a series of lenth/data strings ending with a zero * byte, per RFC 1035 */ void BinaryBuffer::puthost(string host) { int start = 0; while(start < host.length()) { int next = host.find(".", start); if(next == string::npos) next = host.length(); puts(host.substr(start,next-start)); start = next + 1; } puts(""); } /* * Get a segment starting with a length. If accum is not empty, add a . * then add characters until either a forward or terminator. Returns * the location that stopped it. */ unsigned int BinaryBuffer::segment(unsigned int start, string &accum) { unsigned ct = m_data[start++]; if(accum != "") accum.push_back('.'); while(ct--) { accum.push_back(m_data[start++]); } return start; } /* * Get a host name as a series of lenth/data strings, obeying the offset * compression semantics, per RFC 1035. */ string BinaryBuffer::gethost() { string ret = ""; // Reads segments which are in place until end or reference. while(m_data[m_rwloc] != 0 && !is_jump(m_data[m_rwloc])) { m_rwloc = segment(m_rwloc,ret); } // If we're done, we stop. unsigned int loc = m_rwloc++; if(m_data[loc] == 0) { // Terminator. We're done, and m_wrloc is past terminator. return ret; } else { // Jump. We continue, and m_wrloc is only half way past, // so we need to advance it again. ++m_rwloc; } // Process any back references. do { if(is_jump(m_data[loc])) loc = (((static_cast(m_data[loc])) << 8) | (static_cast(m_data[loc+1]))) & 0x03fff; loc = segment(loc,ret); } while(m_data[loc]); return ret; } // Dump the contents up to the location, or the indicated size. void BinaryBuffer::dump(int limit, std::ostream &strm) const { static const int bytes_per_group = 4; static const int groups_per_line = 5; static const int bytes_per_line = bytes_per_group * groups_per_line; if(limit < 0) limit = m_rwloc; unsigned int line = 0; while(limit > 0) { int linelimit = limit > bytes_per_line ? bytes_per_line : limit; strm << " " << std::setw(3) << std::setfill('0') << std::right << std::dec << line << " "; int grct = bytes_per_group; for(int i = 0; i < bytes_per_line; ++i) { if(i < linelimit) { strm << std::setw(2) << std::setfill('0') << std::right << std::hex << static_cast (m_data[line+i]); } else { strm << " "; } if(--grct <= 0) { strm << " "; grct = bytes_per_group; } } strm << " "; for(int i = 0; i < linelimit; ++i) { char ch = static_cast(m_data[line+i]); if(isprint(ch)) strm << ch; else strm << "."; } strm << std::endl; limit -= linelimit; line += linelimit; } }