From 167ae30fbd5375fc4906febc0bdd42630c6f4a3f Mon Sep 17 00:00:00 2001 From: Dario Lombardo Date: Thu, 11 Sep 2014 16:03:05 +0200 Subject: [PATCH] Major restyle to support response packets --- src/dns_header.cpp | 9 +-- src/dns_header.hpp | 2 +- src/dns_packet.cpp | 142 ++++++++++++++++++++++++++++++++----------- src/dns_packet.hpp | 15 +++-- src/dns_question.cpp | 30 +++------ src/dns_question.hpp | 2 +- src/main.cpp | 101 +++++++++++++++--------------- src/rr.cpp | 44 ++++++++++---- src/rr.hpp | 3 + src/server.cpp | 36 +++++++---- src/server.hpp | 1 + src/utils.cpp | 46 +++++++++++++- src/utils.hpp | 13 ++-- tests/test.cpp | 78 ++++++++++++++++++++++-- 14 files changed, 366 insertions(+), 156 deletions(-) diff --git a/src/dns_header.cpp b/src/dns_header.cpp index 8d56b2f..26e2b2f 100644 --- a/src/dns_header.cpp +++ b/src/dns_header.cpp @@ -215,11 +215,12 @@ bool operator!=(const DnsHeaderFlags& f1, const DnsHeaderFlags& f2) return !(f1 == f2); } -void DnsHeader::parse(char* buf) +size_t DnsHeader::parse(char* buf, unsigned offset) { - memcpy(&_txid, buf, 2); - memcpy(&_flags, buf + 2, 2); - memcpy(&_nRecord, buf + 4, 8); + memcpy(&_txid, buf + offset, 2); + memcpy(&_flags, buf + offset + 2, 2); + memcpy(&_nRecord, buf + offset + 4, 8); + return 12; } bool DnsHeader::rd() const diff --git a/src/dns_header.hpp b/src/dns_header.hpp index aeed692..5a4a99e 100644 --- a/src/dns_header.hpp +++ b/src/dns_header.hpp @@ -87,7 +87,7 @@ class DnsHeader { void fuzzTxid(); void fuzzNRecord(unsigned section); - void parse(char* buf); + size_t parse(char* buf, unsigned offset); }; #endif diff --git a/src/dns_packet.cpp b/src/dns_packet.cpp index 18f1393..39253ac 100644 --- a/src/dns_packet.cpp +++ b/src/dns_packet.cpp @@ -48,6 +48,8 @@ DnsPacket::DnsPacket() _log = NULL; + _spoofing = false; + this->packets(0); } @@ -237,12 +239,34 @@ void DnsPacket::sendNet(bool doCksum) _log(this->to_string()); if (send(_socket, output.data(), output.length(), 0) < 0) { - if (errno == 22) { - cout << "Invalid parameter (probably fuzzer is shaking it).\n"; + if (_log && errno == 22) { + _log("Invalid parameter (probably fuzzer is shaking it)"); } else { throw runtime_error("send() error: " + string(strerror(errno))); } } + + if (!_spoofing) { + char buf[65535]; + struct sockaddr_in addr; + socklen_t fromlen = sizeof(addr); + ssize_t bytes = recvfrom(_socket, buf, 65535, 0, (struct sockaddr*)&addr, &fromlen); + if (bytes == -1) { + throw runtime_error("Error in recvfrom(): " + string(strerror(errno))); + } + DnsPacket p; + p.parse(buf + sizeof(_ipHdr) + sizeof(_udpHdr)); + struct iphdr* iph; + iph = (struct iphdr*)buf; + + p.ipFrom(iph->saddr); + p.ipTo(iph->daddr); + + if (_log) + _log(string("Received ") + p.to_string()); + + } + _datagrams--; } @@ -273,17 +297,19 @@ string DnsPacket::to_string(bool dnsonly) const s += " "; } - s += "txid: " + std::to_string(_dnsHdr.txid()); + s += "txid: 0x" + Dines::toHex(_dnsHdr.txid()); s += isQuestion() ? " Q " : " R "; - s += "[Question:" + _question.to_string() + "]"; + if (!_question.empty()) + s += "[Question:" + _question.to_string() + "]"; if (_answers.size() > 0) { s += "[Answers:"; for (vector::const_iterator itr = _answers.begin(); itr != _answers.end(); ++itr) { - s += itr->to_string(); + s += itr->to_string() + ","; } + s.pop_back(); s += "]"; } @@ -291,8 +317,9 @@ string DnsPacket::to_string(bool dnsonly) const s += "[Authorities:"; for (vector::const_iterator itr = _authorities.begin(); itr != _authorities.end(); ++itr) { - s += itr->to_string(); + s += itr->to_string() + ","; } + s.pop_back(); s += "]"; } @@ -300,8 +327,9 @@ string DnsPacket::to_string(bool dnsonly) const s += "[Additionals:"; for (vector::const_iterator itr = _additionals.begin(); itr != _additionals.end(); ++itr) { - s += itr->to_string(); + s += itr->to_string() + ","; } + s.pop_back(); s += "]"; } @@ -331,8 +359,35 @@ DnsQuestion& DnsPacket::addQuestion(const DnsQuestion& q) return _question; } +ResourceRecord& DnsPacket::addRR(Dines::RecordSection section, const ResourceRecord& rr, bool counter_increment) +{ + std::vector *rrPtr; + + switch (section) { + case Dines::R_ANSWER: + rrPtr = &_answers; + break; + case Dines::R_AUTHORITIES: + rrPtr = &_authorities; + break; + case Dines::R_ADDITIONAL: + rrPtr = &_additionals; + break; + default: + throw runtime_error("Unexpected section " + std::to_string(section)); + } + + if (counter_increment) + _dnsHdr.nRecordAdd(section, 1); + + rrPtr->push_back(rr); + isQuestion(false); + return rrPtr->front(); +} + ResourceRecord& DnsPacket::addRR(Dines::RecordSection section, const std::string& rrDomain, - unsigned rrType, unsigned rrClass, unsigned ttl, const char* rdata, unsigned rdatalen) + unsigned rrType, unsigned rrClass, unsigned ttl, const char* rdata, unsigned rdatalen, + bool counter_increment) { string rd(rdata, rdatalen); return addRR(section, rrDomain, rrType, rrClass, ttl, rd); @@ -340,7 +395,7 @@ ResourceRecord& DnsPacket::addRR(Dines::RecordSection section, const std::string ResourceRecord& DnsPacket::addRR(Dines::RecordSection section, const std::string rrDomain, const std::string& rrType, const std::string& rrClass, const std::string& ttl, - const std::string& rdata) + const std::string& rdata, bool counter_increment) { unsigned type = Dines::stringToQtype(rrType); unsigned klass = Dines::stringToQclass(rrClass); @@ -350,7 +405,7 @@ ResourceRecord& DnsPacket::addRR(Dines::RecordSection section, const std::string } ResourceRecord& DnsPacket::addRR(Dines::RecordSection section, const std::string& rrDomain, - unsigned rrType, unsigned rrClass, unsigned ttl, const std::string& rdata) + unsigned rrType, unsigned rrClass, unsigned ttl, const std::string& rdata, bool counter_increment) { ResourceRecord rr(rrDomain, rrType, rrClass, ttl, rdata); return addRR(section, rr); @@ -378,6 +433,7 @@ uint16_t DnsPacket::nRecord(Dines::RecordSection section) const void DnsPacket::question(const DnsQuestion& q) { + _dnsHdr.nRecord(Dines::R_QUESTION, 1); _question = q; } @@ -401,8 +457,15 @@ const ResourceRecord& DnsPacket::authorities(unsigned n) const return _authorities.at(n); } +void DnsPacket::ipFrom(uint32_t ip) +{ + _spoofing = true; + _ipHdr.saddr = ip; +} + void DnsPacket::ipFrom(string ip_from) { + _spoofing = true; _ipHdr.saddr = inet_addr(ip_from.data()); } @@ -411,6 +474,12 @@ void DnsPacket::ipTo(string ip_to) _ipHdr.daddr = inet_addr(ip_to.data()); } +void DnsPacket::ipTo(uint32_t ip) +{ + _spoofing = true; + _ipHdr.daddr = ip; +} + uint16_t DnsPacket::sport() const { return ntohs(_udpHdr.source); @@ -500,30 +569,6 @@ DnsHeader& DnsPacket::dnsHdr() return _dnsHdr; } -ResourceRecord& DnsPacket::addRR(Dines::RecordSection section, const ResourceRecord& rr) -{ - std::vector *rrPtr; - - switch (section) { - case Dines::R_ANSWER: - rrPtr = &_answers; - break; - case Dines::R_AUTHORITIES: - rrPtr = &_authorities; - break; - case Dines::R_ADDITIONAL: - rrPtr = &_additionals; - break; - default: - throw runtime_error("Unexpected section " + std::to_string(section)); - } - - _dnsHdr.nRecordAdd(section, 1); - rrPtr->push_back(rr); - isQuestion(false); - return rrPtr->front(); -} - void DnsPacket::fuzzSrcIp() { _fuzzSrcIp = true; @@ -569,13 +614,36 @@ bool DnsPacket::invalid() const string DnsPacket::invalidMsg() const { if (_ipHdr.daddr == 0) - return "You must specify destination ip (--dst-ip)"; + return "You must specify destination ip"; return ""; } void DnsPacket::parse(char* buf) { - _dnsHdr.parse(buf); - _question.parse(buf + 12); + unsigned i; + unsigned offset = 0; + offset += _dnsHdr.parse(buf, offset); + offset += _question.parse(buf, offset); + + // Parse answers + for (i = 0; i < _dnsHdr.nRecord(Dines::R_ANSWER); i++) { + ResourceRecord rr; + offset += rr.parse(buf, offset); + this->addRR(Dines::R_ANSWER, rr, false); + } + + // Parse auth + for (i = 0; i < _dnsHdr.nRecord(Dines::R_AUTHORITIES); i++) { + ResourceRecord rr; + offset += rr.parse(buf, offset); + this->addRR(Dines::R_AUTHORITIES, rr, false); + } + + // Parse add + for (i = 0; i < _dnsHdr.nRecord(Dines::R_ADDITIONAL); i++) { + ResourceRecord rr; + offset += rr.parse(buf, offset); + this->addRR(Dines::R_ADDITIONAL, rr, false); + } } diff --git a/src/dns_packet.hpp b/src/dns_packet.hpp index df5cc2e..a8adf55 100644 --- a/src/dns_packet.hpp +++ b/src/dns_packet.hpp @@ -16,6 +16,7 @@ class DnsPacket { int _socket; int _recvSocket; + bool _spoofing; //! Creates the socket void _socketCreate(); @@ -77,8 +78,10 @@ class DnsPacket { std::string to_string(bool dnsonly = false) const; void ipFrom(std::string ip_from); + void ipFrom(uint32_t ip); void ipTo(std::string ip_to); + void ipTo(uint32_t ip); //! IP source as string std::string ipFrom() const; @@ -128,19 +131,21 @@ class DnsPacket { //! Adds a RR ResourceRecord& addRR(Dines::RecordSection section, const std::string rrDomain, const std::string& rrType, const std::string& rrClass, const std::string& ttl, - const std::string& rdata); + const std::string& rdata, bool counter_increment = true); //! Adds a RR ResourceRecord& addRR(Dines::RecordSection section, const std::string& rrDomain, - unsigned rrType, unsigned rrClass, unsigned ttl, const std::string& rdata); + unsigned rrType, unsigned rrClass, unsigned ttl, const std::string& rdata, + bool counter_increment = true); //! Adds a RR ResourceRecord& addRR(Dines::RecordSection section, const std::string& rrDomain, unsigned rrType, unsigned rrClass, unsigned ttl, const char* rdata, - unsigned rdatalen); + unsigned rdatalen, bool counter_increment= true); //! Adds a RR - ResourceRecord& addRR(Dines::RecordSection section, const ResourceRecord& rr); + ResourceRecord& addRR(Dines::RecordSection section, const ResourceRecord& rr, + bool counter_increment = true); //! Run the fuzzer void fuzz(); @@ -169,7 +174,7 @@ class DnsPacket { //! Return a message that describe why a packet is invalid, empty string otherwise std::string invalidMsg() const; - //! Parse a message from a buffer + //! Parse a message from a buffer. The buffer must point to the start of the dns packet void parse(char* buf); }; diff --git a/src/dns_question.cpp b/src/dns_question.cpp index 54551b1..9cd52cd 100644 --- a/src/dns_question.cpp +++ b/src/dns_question.cpp @@ -170,29 +170,15 @@ string DnsQuestion::to_string() const return _qdomain_str + "/" + qtypeStr() + "/" + qclassStr(); } -void DnsQuestion::parse(char* buf) -{ - unsigned i = 0; - while (buf[i] != 0) - i++; - i++; - _qdomain_enc = string(buf, i); - - // Now parse the domain into printable form - _qdomain_str = ""; - int cur = 1; - int len = buf[0]; - while (len != 0) { - _qdomain_str += string(buf + cur, len); - _qdomain_str += "."; - cur += len; - len = buf[cur]; - cur++; - } - _qdomain_str.erase(_qdomain_str.size() - 1, _qdomain_str.size()); +size_t DnsQuestion::parse(char* buf, unsigned offset) +{ + unsigned i; + + i = Dines::domainDecode(buf, offset, _qdomain_enc, _qdomain_str); - memcpy(&_qtype, buf + i, 2); - memcpy(&_qclass, buf + i + 2, 2); + memcpy(&_qtype, buf + offset + i, 2); + memcpy(&_qclass, buf + offset + i + 2, 2); + return (_qdomain_enc.size() + 4); } bool DnsQuestion::empty() const diff --git a/src/dns_question.hpp b/src/dns_question.hpp index ec64344..1b09fa8 100644 --- a/src/dns_question.hpp +++ b/src/dns_question.hpp @@ -50,7 +50,7 @@ class DnsQuestion { std::string to_string() const; - void parse(char* buf); + size_t parse(char* buf, unsigned offset = 0); bool empty() const; diff --git a/src/main.cpp b/src/main.cpp index 9b37f94..c78cc67 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -269,68 +269,73 @@ int main(int argc, char* argv[]) return 2; } - // We are forging the number of records. We need to explicitly set them after options processing - for (unsigned i = 0; i < 4; i++) { - if (forged_nrecords.at(i) != 0) { - p.nRecord(Dines::RecordSection(i), forged_nrecords.at(i)); +// try { + // We are forging the number of records. We need to explicitly set them after options processing + for (unsigned i = 0; i < 4; i++) { + if (forged_nrecords.at(i) != 0) { + p.nRecord(Dines::RecordSection(i), forged_nrecords.at(i)); + } } - } - if (server_port > 0) { - // Server mode - if (argc != optind) { - cerr << "When running in server mode you can't specify server destination address" << endl; - return 1; - } + if (server_port > 0) { + // Server mode + if (argc != optind) { + cerr << "When running in server mode you can't specify server destination address" << endl; + return 1; + } - p.ipTo("255.255.255.255"); + p.ipTo("255.255.255.255"); - if (p.invalid()) { - cerr << "Invalid parameters:\n\n"; - cerr << p.invalidMsg() << endl; - return 1; - } + if (p.invalid()) { + cerr << "Invalid parameters:\n\n"; + cerr << p.invalidMsg() << endl; + return 1; + } - Server server(&p, server_port); - if (verbose == true) - server.logger(logger); - server.launch(); - } else { - // Client mode + Server server(&p, server_port); + if (verbose == true) + server.logger(logger); + server.launch(); + } else { + // Client mode - if (argc == optind) { - cerr << "You must specify the server destination address" << endl; - return 1; - } + if (argc == optind) { + cerr << "You must specify the server destination address" << endl; + return 1; + } - // The rest of the cmdline contains the addresses to scan - p.ipTo(argv[optind]); + // The rest of the cmdline contains the addresses to scan + p.ipTo(argv[optind]); - p.packets(num); + p.packets(num); - if (p.invalid()) { - cerr << "Invalid parameters:\n\n"; - cerr << p.invalidMsg() << endl; - return 1; - } + if (p.invalid()) { + cerr << "Invalid parameters:\n\n"; + cerr << p.invalidMsg() << endl; + return 1; + } + + logger(string("Sending ") + p.packetsStr() + " datagrams"); - cout << "Sending " << p.packetsStr() << " datagrams\n"; + // Create a fake server to receive answers + Server s(NULL); + s.packets(1); - while (p.packets() > 0) { - p.fuzz(); - try { + while (p.packets() > 0) { + p.fuzz(); p.sendNet(); - } catch(exception& e) { - cout << "\n\nError: " << e.what() << "\n"; - return 1; - } - PRINT_DOT(); + if (!verbose) + PRINT_DOT(); - if (p.packets() > 0) - nanosleep(&delay, NULL); + if (p.packets() > 0) + nanosleep(&delay, NULL); + } + cout << endl; } - cout << endl; - } +// } catch(exception& e) { +// logger(string("Runtime error: ") + e.what()); +// return 1; +// } return 0; } diff --git a/src/rr.cpp b/src/rr.cpp index 844138c..9ed64bc 100644 --- a/src/rr.cpp +++ b/src/rr.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -154,7 +155,14 @@ uint32_t ResourceRecord::ttl() const string ResourceRecord::rData() const { - return _rData; + string out; + if (Dines::qtypeToString(ntohs(_rrType)) == "A") { + char addr[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, _rData.data(), addr, INET_ADDRSTRLEN); + out += string(addr); + } + + return out; } unsigned ResourceRecord::rDataLen() const @@ -235,19 +243,13 @@ void ResourceRecord::rrDomain(string domain) string ResourceRecord::to_string() const { - string out = _rrDomain_str + "/" + this->rrTypeStr() + "/" + this->rrClassStr() + "/" + - std::to_string(this->ttl()); - - if (Dines::qtypeToString(ntohs(_rrType)) == "A") { - char addr[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, _rData.data(), addr, INET_ADDRSTRLEN); - out += "/" + string(addr); - } - - if (Dines::qtypeToString(ntohs(_rrType)) == "NS") { - out += "/" + this->rData(); - } + string out = ""; + out = _rrDomain_str + "/" + this->rrTypeStr() + "/" + this->rrClassStr() + "/" + + std::to_string(this->ttl()); + string rd = this->rData(); + if (rd != "") + out += "/" + rd; return out; } @@ -260,3 +262,19 @@ void ResourceRecord::logger(Dines::LogFunc l) { _log = l; } + +size_t ResourceRecord::parse(char* buf, unsigned offset) +{ + unsigned len; + unsigned i; + + i = Dines::domainDecode(buf, offset, _rrDomain_enc, _rrDomain_str); + + memcpy(&_rrType, buf + offset + i, 2); + memcpy(&_rrClass, buf + offset + i + 2, 2); + memcpy(&_ttl, buf + offset + i + 4, 4); + memcpy(&len, buf + offset + i + 8, 2); + len = ntohs(len); + _rData = string(buf + offset + i + 10, len); + return (i + 10 + len); +} diff --git a/src/rr.hpp b/src/rr.hpp index e72687d..e10f75a 100644 --- a/src/rr.hpp +++ b/src/rr.hpp @@ -67,6 +67,9 @@ class ResourceRecord { //! Set the logger void logger(Dines::LogFunc l); + + //! Parse from a buffer + size_t parse(char* buf, unsigned offset); }; #endif diff --git a/src/server.cpp b/src/server.cpp index ab38b0f..075adea 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -56,7 +56,7 @@ void Server::launch() servaddr.sin_port = htons(_port); if (bind(servSock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 ) - throw runtime_error("Can't bind() listening socket"); + throw runtime_error(string("Can't bind() listening socket: ") + strerror(errno)); const unsigned buflen = 65535; char buf[buflen]; @@ -76,19 +76,31 @@ void Server::launch() if (_log) _log("Incoming packet: " + _incoming.to_string(true)); - if (_incoming.dnsHdr().rd() == true) { - _outgoing.dnsHdr().ra(true); - } - _outgoing.dnsHdr().txid(_incoming.dnsHdr().txid()); -// _outgoing.question(_incoming.question()); - _outgoing.isQuestion(false); + if (_autoanswer) { + if (_incoming.dnsHdr().rd() == true) { + _outgoing.dnsHdr().ra(true); + } + _outgoing.dnsHdr().txid(_incoming.dnsHdr().txid()); + _outgoing.question(_incoming.question()); + _outgoing.isQuestion(false); - if (sendto(servSock, _outgoing.data().data(), _outgoing.data().size(), 0, (struct sockaddr*)&peer, - sockaddr_len) == -1) { - throw runtime_error(string(__func__) + "::sendto() error: " + string(strerror(errno))); - } + if (sendto(servSock, _outgoing.data().data(), _outgoing.data().size(), 0, (struct sockaddr*)&peer, + sockaddr_len) == -1) { + throw runtime_error(string(__func__) + "::sendto() error: " + string(strerror(errno))); + } - _outgoing.fuzz(); + _outgoing.fuzz(); + } _packets--; } } + +void Server::packets(uint64_t p) +{ + _packets = p; +} + +void Server::port(uint16_t p) +{ + _port = p; +} diff --git a/src/server.hpp b/src/server.hpp index 55d86c4..b9b2a6d 100644 --- a/src/server.hpp +++ b/src/server.hpp @@ -18,6 +18,7 @@ class Server { void autoanswer(bool a); void logger(Dines::LogFunc l); void launch(); + void packets(uint64_t p); }; #endif diff --git a/src/utils.cpp b/src/utils.cpp index b4f4e69..fc19d42 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -12,6 +13,8 @@ #include #include #include +#include +#include using namespace std; @@ -52,7 +55,7 @@ std::string random_string(size_t length) return random_string_int(length, randchar); } -std::string domainEncode(const std::string& s) +std::string domainEncode(const std::string s) { std::string out = ""; std::vector frags = tokenize(s, "."); @@ -68,10 +71,39 @@ std::string domainEncode(const std::string& s) return out; } +unsigned domainDecode(char* base, unsigned offset, std::string& encoded, std::string & decoded) +{ + uint16_t jump; + unsigned len; + + if (base[offset] == '\0') { + decoded.erase(decoded.size() - 1, decoded.size()); + return 1; + } + + if (((u_char*)base)[offset] >> 6 == 3) { + // Compressed + memcpy(&jump, base + offset, 2); + jump = ntohs(jump); + jump = (jump & 0x3FFF); + len = base[jump]; + encoded += string(base + jump, len + 1); + decoded += string(base + jump + 1, len) + "."; + domainDecode(base, jump + 1 + len, encoded, decoded); + return 2; + } else { + // Not compressed + len = base[offset]; + encoded += string(base + offset, len + 1); + decoded += string(base + 1 + offset, len) + "."; + return (len + 1 + domainDecode(base, offset + 1 + len, encoded, decoded)); + } +} + // A reference for qtypes and qclasses // http://edgedirector.com/app/type.htm -uint16_t stringToQtype(const std::string& s) +uint16_t stringToQtype(const std::string s) { if (s == "A" || s == "a") return 1; if (s == "NS" || s == "ns") return 2; @@ -128,7 +160,7 @@ string qtypeToString(uint16_t qtype) } } -uint16_t stringToQclass(const std::string& s) +uint16_t stringToQclass(const std::string s) { if (s == "IN" || s == "in" || s == "1") return 0x0001; if (s == "CSNET" || s == "csnet" || s == "2") return 0x0002; @@ -196,4 +228,12 @@ string rDataConvert(const char* opt, uint16_t qtype) throw runtime_error("Conversion of " + string(opt) + " not supported"); } +std::string toHex(uint32_t value) +{ + std::ostringstream oss; + if (!(oss< std::string convertInt(C i); +std::string toHex(uint32_t value); + +std::string ipToString(uint32_t ip); }; diff --git a/tests/test.cpp b/tests/test.cpp index 646fa47..3dd60c4 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -209,7 +209,7 @@ int test_rr_tostring() rr1.rrType("NS"); rr1.rData("ns.test.com"); - CHECK(rr1.to_string() == "www.test.com/NS/IN/64/ns.test.com"); + CHECK(rr1.to_string() == "www.test.com/NS/IN/64"); return 0; } @@ -249,7 +249,7 @@ int test_answer() CHECK(p.nRecord(Dines::R_ANSWER) == 1); CHECK(p.answers(0).rrDomain() == "www.test.com"); - CHECK(*(unsigned*)p.answers(0).rData().data() == 0x0101A8C0); + CHECK(p.answers(0).rData() == "192.168.1.1"); CHECK(p.answers(0).ttl() == 64); CHECK(p.answers(0).rDataLen() == 4); @@ -572,7 +572,7 @@ int test_invalid() { DnsPacket p; CHECK(p.invalid() == true); - CHECK(p.invalidMsg() == "You must specify destination ip (--dst-ip)"); + CHECK(p.invalidMsg() == "You must specify destination ip"); p.ipTo("1.2.3.4"); CHECK(p.invalid() == false); CHECK(p.invalidMsg() == ""); @@ -590,12 +590,77 @@ int test_dns_packet() p.dport("53"); p.txid("100"); p.addQuestion(q); - CHECK(p.to_string() == "1.2.3.4:100 -> 2.3.4.5:53 txid: 100 Q [Question:www.polito.it/A/IN]"); + CHECK(p.to_string() == "1.2.3.4:100 -> 2.3.4.5:53 txid: 0x64 Q [Question:www.polito.it/A/IN]"); p.addRR(Dines::R_ANSWER, rr); p.addRR(Dines::R_ADDITIONAL, rr); p.addRR(Dines::R_AUTHORITIES, rr); - CHECK(p.to_string() == "1.2.3.4:100 -> 2.3.4.5:53 txid: 100 R [Question:www.polito.it/A/IN][Answers:www.polito.it/A/IN/64/1.2.3.4][Authorities:www.polito.it/A/IN/64/1.2.3.4][Additionals:www.polito.it/A/IN/64/1.2.3.4]"); - CHECK(p.to_string(true) == "txid: 100 R [Question:www.polito.it/A/IN][Answers:www.polito.it/A/IN/64/1.2.3.4][Authorities:www.polito.it/A/IN/64/1.2.3.4][Additionals:www.polito.it/A/IN/64/1.2.3.4]"); + CHECK(p.to_string() == "1.2.3.4:100 -> 2.3.4.5:53 txid: 0x64 R [Question:www.polito.it/A/IN][Answers:www.polito.it/A/IN/64/1.2.3.4][Authorities:www.polito.it/A/IN/64/1.2.3.4][Additionals:www.polito.it/A/IN/64/1.2.3.4]"); + CHECK(p.to_string(true) == "txid: 0x64 R [Question:www.polito.it/A/IN][Answers:www.polito.it/A/IN/64/1.2.3.4][Authorities:www.polito.it/A/IN/64/1.2.3.4][Additionals:www.polito.it/A/IN/64/1.2.3.4]"); + return 0; +} + +int test_domain_decode() +{ + int b; + string encoded; + string decoded; + + char* buf1 = (char*)"\x03\x77\x77\x77\x06\x70\x6f\x6c\x69\x74\x6f\x02\x69\x74\x00"; + b = Dines::domainDecode(buf1, 0, encoded, decoded); + CHECK(decoded == "www.polito.it"); + CHECK(b == 15); + + char* buf2 = (char*) + "\x4c\xa8\x81\x80\x00\x01\x00\x02\x00\x04" + "\x00\x05\x03\x77\x77\x77\x06\x70\x6f\x6c" + "\x69\x74\x6f\x02\x69\x74\x00\x00\x01\x00" + "\x01\xc0\x0c\x00\x05\x00\x01\x00\x01\x4a" + "\xdb\x00\x0a\x07\x77\x65\x62\x66\x61\x72" + "\x6d\xc0\x10\xc0\x2b\x00\x01\x00\x01\x00" + "\x01\x4a\xdb\x00\x04\x82\xc0\xb6\x21\xc0" + "\x10\x00\x02\x00\x01\x00\x01\x4a\xdb\x00" + "\x0b\x08\x6c\x65\x6f\x6e\x61\x72\x64\x6f" + "\xc0\x10\xc0\x10\x00\x02\x00\x01\x00\x01" + "\x4a\xdb\x00\x0e\x03\x6e\x73\x31\x04\x67" + "\x61\x72\x72\x03\x6e\x65\x74\x00\xc0\x10" + "\x00\x02\x00\x01\x00\x01\x4a\xdb\x00\x06" + "\x03\x6e\x73\x33\xc0\x10\xc0\x10\x00\x02" + "\x00\x01\x00\x01\x4a\xdb\x00\x08\x05\x67" + "\x69\x6f\x76\x65\xc0\x10\xc0\x68\x00\x01" + "\x00\x01\x00\x00\x5c\x9c\x00\x04\xc1\xce" + "\x8d\x26\xc0\x68\x00\x1c\x00\x01\x00\x00" + "\x5c\x9c\x00\x10\x20\x01\x07\x60\xff\xff" + "\xff\xff\x00\x00\x00\x00\x00\x00\x00\xaa" + "\xc0\x82\x00\x01\x00\x01\x00\x01\x4a\xdb" + "\x00\x04\x82\xc0\x04\x1e\xc0\x94\x00\x01" + "\x00\x01\x00\x01\x46\x95\x00\x04\x82\xc0" + "\x03\x18\xc0\x51\x00\x01\x00\x01\x00\x01" + "\x46\x95\x00\x04\x82\xc0\x03\x15"; + + encoded = ""; + decoded = ""; + b = Dines::domainDecode(buf2, 12, encoded, decoded); + CHECK(decoded == "www.polito.it"); + CHECK(b == 15); + + encoded = ""; + decoded = ""; + b = Dines::domainDecode(buf2, 31, encoded, decoded); + CHECK(decoded == "www.polito.it"); + CHECK(b == 2); + + encoded = ""; + decoded = ""; + b = Dines::domainDecode(buf2, 53, encoded, decoded); + CHECK(decoded == "webfarm.polito.it"); + CHECK(b == 2); + + encoded = ""; + decoded = ""; + b = Dines::domainDecode(buf2, 92, encoded, decoded); + CHECK(decoded == "polito.it"); + CHECK(b == 2); + return 0; } @@ -625,6 +690,7 @@ int main(int argc, char* argv[]) TEST(test_packets()); TEST(test_invalid()); TEST(test_dns_packet()); + TEST(test_domain_decode()); cout << "done" << "\n"; }