diff options
Diffstat (limited to 'tests/test_dns.cpp')
| -rw-r--r-- | tests/test_dns.cpp | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/tests/test_dns.cpp b/tests/test_dns.cpp new file mode 100644 index 0000000..9a389bb --- /dev/null +++ b/tests/test_dns.cpp @@ -0,0 +1,82 @@ +#include <doctest/doctest.h> + +#include <vector> + +#include "wireframe/l7/dns.hpp" + +using namespace wireframe::net; + +namespace { + +// "example.com" A query, id=0x129d - the same shape as the real query +// captured live over tailscale0 while testing the DNS dissector against +// tshark (id 0x129d / 4765 matched tshark's independent decode exactly). +std::vector<unsigned char> example_com_query() { + return { + 0x12, 0x9d, // id = 4765 + 0x01, 0x00, // flags: RD=1 + 0x00, 0x01, // qdcount = 1 + 0x00, 0x00, // ancount = 0 + 0x00, 0x00, // nscount = 0 + 0x00, 0x00, // arcount = 0 + 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0, + 0x00, 0x01, // qtype = A + 0x00, 0x01, // qclass = IN + }; +} + +} // namespace + +TEST_CASE("parse_dns decodes a query") { + auto msg = parse_dns(example_com_query()); + REQUIRE(msg.has_value()); + CHECK(msg->header.id == 4765); + CHECK_FALSE(msg->header.is_response); + CHECK(msg->header.qdcount == 1); + REQUIRE(msg->question.has_value()); + CHECK(msg->question->name == "example.com"); + CHECK(msg->question->qtype == 1); +} + +TEST_CASE("parse_dns decodes a response") { + std::vector<unsigned char> bytes = { + 0x12, 0x9d, + 0x81, 0x80, // flags: QR=1 (response), RD=1, RA=1 + 0x00, 0x01, // qdcount = 1 + 0x00, 0x02, // ancount = 2 + 0x00, 0x00, + 0x00, 0x00, + 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0, + 0x00, 0x01, 0x00, 0x01, + }; + auto msg = parse_dns(bytes); + REQUIRE(msg.has_value()); + CHECK(msg->header.is_response); + CHECK(msg->header.ancount == 2); +} + +TEST_CASE("parse_dns rejects a truncated header") { + std::vector<unsigned char> bytes(5, 0); + CHECK_FALSE(parse_dns(bytes).has_value()); +} + +TEST_CASE("read_dns_name rejects a compression pointer") { + std::vector<unsigned char> bytes = {0xC0, 0x0C}; // pointer: unsupported by design + CHECK_FALSE(read_dns_name(bytes, 0).has_value()); +} + +TEST_CASE("DnsDissector claims port 53 and its summary matches parse_dns") { + DnsDissector dissector; + CHECK(dissector.port() == kDnsPort); + + auto summary = dissector.summarize(example_com_query()); + REQUIRE(summary.has_value()); + CHECK(summary->substr(0, 9) == "DNS query"); + CHECK(summary->find("example.com") != std::string::npos); +} + +TEST_CASE("DnsDissector::summarize returns nullopt for a truncated payload") { + DnsDissector dissector; + std::vector<unsigned char> bytes(5, 0); + CHECK_FALSE(dissector.summarize(bytes).has_value()); +} |