]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
implement support for NSEC bitmaps covering types above 255. Reported by Michael...
authorPeter van Dijk <peter.van.dijk@netherlabs.nl>
Sun, 29 Apr 2012 14:38:06 +0000 (14:38 +0000)
committerPeter van Dijk <peter.van.dijk@netherlabs.nl>
Sun, 29 Apr 2012 14:38:06 +0000 (14:38 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@2590 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/nsecrecords.cc
regression-tests/example.com
regression-tests/nsec-bitmap/command [new file with mode: 0755]
regression-tests/nsec-bitmap/expected_result [new file with mode: 0644]
regression-tests/nsec-bitmap/expected_result.nsec3 [new file with mode: 0644]
regression-tests/nsec-bitmap/skip.nodnssec [new file with mode: 0644]

index 670c755b0e9b76e38e6937a048f5a3689664d7e5..aa16b2b4e9f905fb386cdbebbadc563dcf246a3a 100644 (file)
@@ -27,19 +27,32 @@ void NSECRecordContent::toPacket(DNSPacketWriter& pw)
   pw.xfrLabel(d_next);
 
   uint8_t res[34];
-  memset(res, 0, sizeof(res));
-
   set<uint16_t>::const_iterator i;
-  for(i=d_set.begin(); i != d_set.end() && *i<255; ++i){
-    res[2+*i/8] |= 1 << (7-(*i%8));
-  }
-  int len=0;
-  if(!d_set.empty()) 
-    len=1+*--i/8;
+  int oldWindow = -1;
+  int window = 0;
+  int len = 0;
+  string tmp;
 
-  res[1]=len;
+  for(i=d_set.begin(); i != d_set.end(); ++i){
+    uint16_t bit = (*i)%256;
+    window = static_cast<int>((*i) / 256); 
 
-  string tmp;
+    if (window != oldWindow) {
+      if (oldWindow > -1) {
+          res[0] = static_cast<unsigned char>(oldWindow);
+          res[1] = static_cast<unsigned char>(len);
+          tmp.assign(res, res+len+2);
+          pw.xfrBlob(tmp);
+      }
+      memset(res, 0, 34);
+      oldWindow = window;
+    }
+    res[2+bit/8] |= 1 << (7-(bit%8));
+    len=1+bit/8;
+  }
+
+  res[0] = static_cast<unsigned char>(window);
+  res[1] = static_cast<unsigned char>(len);
   tmp.assign(res, res+len+2);
   pw.xfrBlob(tmp);
 }
@@ -50,27 +63,31 @@ NSECRecordContent::DNSRecordContent* NSECRecordContent::make(const DNSRecord &dr
   pr.xfrLabel(ret->d_next);
   string bitmap;
   pr.xfrBlob(bitmap);
-  
   // 00 06 20 00 00 00 00 03  -> NS RRSIG NSEC  ( 2, 46, 47 ) counts from left
-  
+  if(bitmap.empty())
+    return ret;
+
   if(bitmap.size() < 2)
     throw MOADNSException("NSEC record with impossibly small bitmap");
   
-  if(bitmap[0])
-    throw MOADNSException("Can't deal with NSEC mappings > 255 yet");
-  
-  unsigned int len=bitmap[1];
-  if(bitmap.size()!=2+len)
-    throw MOADNSException("Can't deal with multi-part NSEC mappings yet");
-  
-  for(unsigned int n=0 ; n < len ; ++n) {
-    uint8_t val=bitmap[2+n];
-    for(int bit = 0; bit < 8 ; ++bit , val>>=1) 
-      if(val & 1) {
-        ret->d_set.insert((7-bit) + 8*(n));
+  for(unsigned int n = 0; n+1 < bitmap.size();) {
+    unsigned int window=static_cast<unsigned char>(bitmap[n++]);
+    unsigned int len=static_cast<unsigned char>(bitmap[n++]);
+
+    // end if zero padding and ensure packet length
+    if(window == 0&&len == 0) break;
+    if(n+len>bitmap.size()) 
+      throw MOADNSException("NSEC record with bitmap length > packet length");
+
+    for(unsigned int k=0; k < len; k++) {
+      uint8_t val=bitmap[n++];
+      for(int bit = 0; bit < 8 ; ++bit , val>>=1) 
+        if(val & 1) { 
+          ret->d_set.insert((7-bit) + 8*(k) + 256*window);
+        }
       }
   }
-  
   return ret;
 }
 
@@ -129,19 +146,32 @@ void NSEC3RecordContent::toPacket(DNSPacketWriter& pw)
   pw.xfrBlob(d_nexthash);
   
   uint8_t res[34];
-  memset(res, 0, sizeof(res));
-
   set<uint16_t>::const_iterator i;
-  for(i=d_set.begin(); i != d_set.end() && *i<255; ++i){
-    res[2+*i/8] |= 1 << (7-(*i%8));
-  }
-  int len=0;
-  if(!d_set.empty()) 
-    len=1+*--i/8;
+  int oldWindow = -1;
+  int window = 0;
+  int len = 0;
+  string tmp;
 
-  res[1]=len;
+  for(i=d_set.begin(); i != d_set.end(); ++i){
+    uint16_t bit = (*i)%256;
+    window = static_cast<int>((*i) / 256);
 
-  string tmp;
+    if (window != oldWindow) {
+      if (oldWindow > -1) {
+          res[0] = static_cast<unsigned char>(oldWindow);
+          res[1] = static_cast<unsigned char>(len);
+          tmp.assign(res, res+len+2);
+          pw.xfrBlob(tmp);
+      }
+      memset(res, 0, 34);
+      oldWindow = window;
+    }
+    res[2+bit/8] |= 1 << (7-(bit%8));
+    len=1+bit/8;
+  }
+
+  res[0] = static_cast<unsigned char>(window);
+  res[1] = static_cast<unsigned char>(len);
   tmp.assign(res, res+len+2);
   pw.xfrBlob(tmp);
 }
@@ -170,22 +200,24 @@ NSEC3RecordContent::DNSRecordContent* NSEC3RecordContent::make(const DNSRecord &
 
   if(bitmap.size() < 2)
     throw MOADNSException("NSEC3 record with impossibly small bitmap");
-  
-  if(bitmap[0])
-    throw MOADNSException("Can't deal with NSEC3 mappings > 255 yet");
-  
-  unsigned int bitmaplen=bitmap[1];
-  if(bitmap.size()!=2+bitmaplen)
-    throw MOADNSException("Can't deal with multi-part NSEC3 mappings yet");
-  
-  for(unsigned int n=0 ; n < bitmaplen ; ++n) {
-    uint8_t val=bitmap[2+n];
-    for(int bit = 0; bit < 8 ; ++bit , val>>=1)
-      if(val & 1) {
-        ret->d_set.insert((7-bit) + 8*(n));
+
+  for(unsigned int n = 0; n+1 < bitmap.size();) {
+    unsigned int window=static_cast<unsigned char>(bitmap[n++]);
+    unsigned int len=static_cast<unsigned char>(bitmap[n++]);
+    
+    // end if zero padding and ensure packet length
+    if(window == 0&&len == 0) break;
+    if(n+len>bitmap.size())
+      throw MOADNSException("NSEC record with bitmap length > packet length");
+
+    for(unsigned int k=0; k < len; k++) {
+      uint8_t val=bitmap[n++];
+      for(int bit = 0; bit < 8 ; ++bit , val>>=1)
+        if(val & 1) {
+          ret->d_set.insert((7-bit) + 8*(k) + 256*window);
+        }
       }
   }
-  
   return ret;
 }
 
index 1d2dc8cf762bf3ae77bac88d81a9da5cc5cb8460..62f804371c0f1b51ba679f8fe43940a160918dc3 100644 (file)
@@ -17,6 +17,9 @@ $ORIGIN example.com.
 ns1                    IN      A       192.168.1.1
 ns2                    IN      A       192.168.1.2
 ;
+hightype               IN      A       192.168.1.5
+hightype               IN      TYPE65534 \# 5 07ED260001
+;
 localhost              IN      A       127.0.0.1
 www                    IN      CNAME   outpost.example.com.
 ;
diff --git a/regression-tests/nsec-bitmap/command b/regression-tests/nsec-bitmap/command
new file mode 100755 (executable)
index 0000000..312d4fc
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+cleandig hightype.example.com NSEC dnssec | egrep 'IN[[:space:]]+NSEC'
diff --git a/regression-tests/nsec-bitmap/expected_result b/regression-tests/nsec-bitmap/expected_result
new file mode 100644 (file)
index 0000000..992d779
--- /dev/null
@@ -0,0 +1 @@
+0      hightype.example.com.   IN      NSEC    120     host-0.example.com. A RRSIG NSEC TYPE65534
diff --git a/regression-tests/nsec-bitmap/expected_result.nsec3 b/regression-tests/nsec-bitmap/expected_result.nsec3
new file mode 100644 (file)
index 0000000..2882793
--- /dev/null
@@ -0,0 +1,3 @@
+1      3v4it454kfh142bi7afagnuvigrpfptt.example.com.   IN      NSEC3   120     1 1 1 abcd 3V4S43RV1GT28N0F2PPJ8I8482ESMUOB A RRSIG TYPE65534
+1      9f8hti7cc7oqnqjv84klnp89glqrss3r.example.com.   IN      NSEC3   120     1 1 1 abcd 9FDAOFPLLN0FQFU9DP274GOU59QFHSLD A RRSIG
+1      vtnq6ocn2vkuiv3nju14oqtaen2mt5sk.example.com.   IN      NSEC3   120     1 1 1 abcd VTP9NUQBEH436S7J0K8TI2A32MMKCUUL NS SOA MX RRSIG DNSKEY NSEC3PARAM
diff --git a/regression-tests/nsec-bitmap/skip.nodnssec b/regression-tests/nsec-bitmap/skip.nodnssec
new file mode 100644 (file)
index 0000000..e69de29