]> granicus.if.org Git - pdns/commitdiff
teach DNSName to get names from DNS packets, including decompression
authorbert hubert <bert.hubert@netherlabs.nl>
Fri, 20 Feb 2015 13:26:37 +0000 (14:26 +0100)
committerbert hubert <bert.hubert@netherlabs.nl>
Fri, 20 Feb 2015 13:26:37 +0000 (14:26 +0100)
pdns/dnsdist.cc
pdns/dnsname.cc
pdns/dnsname.hh
pdns/test-dnsname_cc.cc

index 57d3256f2e1cee9729c1c619fb75abed60dc4902..99426da2f9878a919df1b99b06694a333afc3693 100644 (file)
@@ -235,7 +235,7 @@ try
       continue;
 
 
-    DNSName qname(packet+12, len-12, &qtype);
+    DNSName qname(packet, len, 12, false, &qtype);
     if(blockFilter(remote, qname, qtype))
       continue;
     if(re && re->match(qname.toString())) {
index 36faa8a3f29fbba42549b3b7251b86e4b6c0a98e..043363e5bd08474ec03031b4729bec3b8e625620 100644 (file)
@@ -12,11 +12,25 @@ DNSName::DNSName(const char* p)
       throw std::range_error("label too long");
 }
 
-DNSName::DNSName(const char* pos, int len, uint16_t* qtype, uint16_t* qclass)
+// this should be the __only__ dns name parser in PowerDNS. 
+DNSName::DNSName(const char* pos, int len, int offset, bool uncompress, uint16_t* qtype, uint16_t* qclass)
 {
   unsigned char labellen;
+  const char *opos = pos;
+  pos += offset;
   const char* end = pos + len;
   while((labellen=*pos++) && pos < end) { // "scan and copy"
+    if(labellen & 0xc0) {
+      if(!uncompress)
+       throw std::range_error("Found compressed label, instructed not to follow");
+
+      labellen &= (~0xc0);
+      int newpos = (labellen << 8) + *(const unsigned char*)pos;
+
+      (*this) += DNSName(opos, len, newpos, false);
+      pos++;
+      break;
+    }
     d_labels.push_back(string(pos, labellen));
     pos+=labellen;
   }
index 4b6d5a26a1898617426f2322f0ed9e43588d4d08..6e7eb1540693c3bddee20dc67efc362bf808b5e4 100644 (file)
@@ -24,7 +24,7 @@ public:
   DNSName() {}                 //!< Constructs the root name
   DNSName(const char* p);      //!< Constructs from a human formatted, escaped presentation
   DNSName(const std::string& str) : DNSName(str.c_str()) {}   //!< Constructs from a human formatted, escaped presentation
-  DNSName(const char* p, int len, uint16_t* qtype=0, uint16_t* qclass=0); //!< Construct from a DNS Packet, taking the first question
+  DNSName(const char* p, int len, int offset, bool uncompress, uint16_t* qtype=0, uint16_t* qclass=0); //!< Construct from a DNS Packet, taking the first question
   
   bool isPartOf(const DNSName& rhs) const;   //!< Are we part of the rhs name?
   bool operator==(const DNSName& rhs) const; //!< DNS-native comparison (case insensitive)
index 6dc35e8c4c6350be2a7555f8eef3c61742282cd3..b1e251de32e4664ef4ed3d24c6beca8c460405de 100644 (file)
@@ -137,13 +137,44 @@ BOOST_AUTO_TEST_CASE(test_Append) {
 
 BOOST_AUTO_TEST_CASE(test_packetParse) {
   vector<unsigned char> packet;
+  reportBasicTypes();
   DNSPacketWriter dpw(packet, "www.ds9a.nl.", QType::AAAA);
-
+  
   uint16_t qtype, qclass;
-  DNSName dn((char*)&packet[12], packet.size() - 12, &qtype, &qclass);
+  DNSName dn((char*)&packet[0], packet.size(), 12, false, &qtype, &qclass);
   BOOST_CHECK_EQUAL(dn.toString(), "www.ds9a.nl.");
   BOOST_CHECK_EQUAL(qtype, QType::AAAA);
   BOOST_CHECK_EQUAL(qclass, 1);
+
+  dpw.startRecord("ds9a.nl.", DNSRecordContent::TypeToNumber("NS"));
+  NSRecordContent nrc("ns1.powerdns.com");
+  nrc.toPacket(dpw);
+
+  dpw.commit();
+
+  /* packet now looks like this:
+     012345678901 12 bytes of header
+     3www4ds9a2nl0 13 bytes of name
+     0001 0001      4 bytes of qtype and qclass
+     answername     2 bytes
+     0001 0001      4 bytes of qtype and class
+     0000 0000      4 bytes of TTL
+     0000           2 bytes of content length
+     content name */
+
+  DNSName dn2((char*)&packet[0], packet.size(), 12+13+4, true, &qtype, &qclass);
+  BOOST_CHECK_EQUAL(dn2.toString(), "ds9a.nl."); 
+  BOOST_CHECK_EQUAL(qtype, QType::NS);
+  BOOST_CHECK_EQUAL(qclass, 1);
+
+  DNSName dn3((char*)&packet[0], packet.size(), 12+13+4+2 + 4 + 4 + 2, true);
+  BOOST_CHECK_EQUAL(dn3.toString(), "ns1.powerdns.com."); 
+
+  try {
+    DNSName dn4((char*)&packet[0], packet.size(), 12+13+4, false); // compressed, should fail
+    BOOST_CHECK(0); 
+  }
+  catch(...){}
 }
 
 BOOST_AUTO_TEST_CASE(test_suffixmatch) {