]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/nsecrecords.cc
dnsdist: Add HTTPStatusAction to return a specific HTTP response
[thirdparty/pdns.git] / pdns / nsecrecords.cc
index ab6a468a201c743fcb54e8379f81a160b5979888..21e6d13da1ce9eacf83f80b6515a895229e39072 100644 (file)
 #endif
 #include "dnsrecords.hh"
 
-void NSECRecordContent::report(void)
-{
-  regist(1, 47, &make, &make, "NSEC");
-}
-
-DNSRecordContent* NSECRecordContent::make(const string& content)
-{
-  return new NSECRecordContent(content);
-}
-
-NSECRecordContent::NSECRecordContent(const string& content, const string& zone) 
+class NSECBitmapGenerator
 {
-  RecordTextReader rtr(content, zone);
-  rtr.xfrName(d_next);
-
-  while(!rtr.eof()) {
-    uint16_t type;
-    rtr.xfrType(type);
-    d_set.insert(type);
+public:
+  NSECBitmapGenerator(DNSPacketWriter& pw_): pw(pw_)
+  {
+    memset(res, 0, sizeof(res));
   }
-}
 
-void NSECRecordContent::toPacket(DNSPacketWriter& pw) 
-{
-  pw.xfrName(d_next);
-
-  uint8_t res[34];
-  set<uint16_t>::const_iterator i;
-  int oldWindow = -1;
-  int window = 0;
-  int len = 0;
-  string tmp;
-
-  for(i=d_set.begin(); i != d_set.end(); ++i){
-    uint16_t bit = (*i)%256;
-    window = static_cast<int>((*i) / 256); 
+  void set(uint16_t type)
+  {
+    uint16_t bit = type % 256;
+    int window = static_cast<int>(type / 256);
 
     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);
+        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);
+      memset(res, 0, sizeof(res));
       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);
+  void finish()
+  {
+    res[0] = static_cast<unsigned char>(oldWindow);
+    res[1] = static_cast<unsigned char>(len);
+    if (len) {
+      tmp.assign(res, res+len+2);
+      pw.xfrBlob(tmp);
+    }
+  }
+
+private:
+  DNSPacketWriter& pw;
+  /* one byte for the window,
+     one for the length,
+     then the maximum of 32 bytes */
+  uint8_t res[34];
+  int oldWindow{-1};
+  int len{0};
+  string tmp;
+};
+
+void NSECBitmap::toPacket(DNSPacketWriter& pw)
+{
+  NSECBitmapGenerator nbg(pw);
+  if (d_bitset) {
+    size_t count = d_bitset->count();
+    size_t found = 0;
+    for(size_t idx = 0; idx < nbTypes && found < count; ++idx){
+      if (!d_bitset->test(idx)) {
+        continue;
+      }
+      found++;
+      nbg.set(idx);
+    }
+  }
+  else {
+    for (const auto& type : d_set) {
+      nbg.set(type);
+    }
+  }
+
+  nbg.finish();
 }
 
-NSECRecordContent::DNSRecordContent* NSECRecordContent::make(const DNSRecord &dr, PacketReader& pr) 
+void NSECBitmap::fromPacket(PacketReader& pr)
 {
-  NSECRecordContent* ret=new NSECRecordContent();
-  pr.xfrName(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.empty()) {
+    return;
+  }
 
-  if(bitmap.size() < 2)
+  if(bitmap.size() < 2) {
     throw MOADNSException("NSEC record with impossibly small bitmap");
+  }
   
   for(unsigned int n = 0; n+1 < bitmap.size();) {
     unsigned int window=static_cast<unsigned char>(bitmap[n++]);
     unsigned int blen=static_cast<unsigned char>(bitmap[n++]);
 
     // end if zero padding and ensure packet length
-    if(window == 0 && blen == 0) break;
-    if(n + blen > bitmap.size())
+    if(window == 0 && blen == 0) {
+      break;
+    }
+
+    if(n + blen > bitmap.size()) {
       throw MOADNSException("NSEC record with bitmap length > packet length");
+    }
 
     for(unsigned int k=0; k < blen; k++) {
       uint8_t val=bitmap[n++];
-      for(int bit = 0; bit < 8 ; ++bit , val>>=1)
+      for(int bit = 0; bit < 8 ; ++bit , val>>=1) {
         if(val & 1) {
-          ret->d_set.insert((7-bit) + 8*(k) + 256*window);
+          set((7-bit) + 8*(k) + 256*window);
         }
       }
+    }
+  }
+}
+
+string NSECBitmap::getZoneRepresentation() const
+{
+  string ret;
+
+  if (d_bitset) {
+    size_t count = d_bitset->count();
+    size_t found = 0;
+    for(size_t idx = 0; idx < nbTypes && found < count; ++idx) {
+      if (!d_bitset->test(idx)) {
+        continue;
+      }
+      found++;
+
+      ret+=" ";
+      ret+=DNSRecordContent::NumberToType(idx);
+    }
+  }
+  else {
+    for(const auto& type : d_set) {
+      ret+=" ";
+      ret+=DNSRecordContent::NumberToType(type);
+    }
+  }
+
+  return ret;
+}
+
+void NSECRecordContent::report(void)
+{
+  regist(1, 47, &make, &make, "NSEC");
+}
+
+std::shared_ptr<DNSRecordContent> NSECRecordContent::make(const string& content)
+{
+  return std::make_shared<NSECRecordContent>(content);
+}
+
+NSECRecordContent::NSECRecordContent(const string& content, const string& zone)
+{
+  RecordTextReader rtr(content, DNSName(zone));
+  rtr.xfrName(d_next);
+
+  while(!rtr.eof()) {
+    uint16_t type;
+    rtr.xfrType(type);
+    set(type);
   }
+}
+
+void NSECRecordContent::toPacket(DNSPacketWriter& pw)
+{
+  pw.xfrName(d_next);
+  d_bitmap.toPacket(pw);
+}
+
+std::shared_ptr<NSECRecordContent::DNSRecordContent> NSECRecordContent::make(const DNSRecord &dr, PacketReader& pr)
+{
+  auto ret=std::make_shared<NSECRecordContent>();
+  pr.xfrName(ret->d_next);
+
+  ret->d_bitmap.fromPacket(pr);
+
   return ret;
 }
 
@@ -120,13 +203,8 @@ string NSECRecordContent::getZoneRepresentation(bool noDot) const
   string ret;
   RecordTextWriter rtw(ret);
   rtw.xfrName(d_next);
-  
-  for(set<uint16_t>::const_iterator i=d_set.begin(); i!=d_set.end(); ++i) {
-    ret+=" ";
-    ret+=NumberToType(*i);
-  }
-  
-  return ret;
+
+  return ret + d_bitmap.getZoneRepresentation();
 }
 
 ////// begin of NSEC3
@@ -136,14 +214,14 @@ void NSEC3RecordContent::report(void)
   regist(1, 50, &make, &make, "NSEC3");
 }
 
-DNSRecordContent* NSEC3RecordContent::make(const string& content)
+std::shared_ptr<DNSRecordContent> NSEC3RecordContent::make(const string& content)
 {
-  return new NSEC3RecordContent(content);
+  return std::make_shared<NSEC3RecordContent>(content);
 }
 
 NSEC3RecordContent::NSEC3RecordContent(const string& content, const string& zone)
 {
-  RecordTextReader rtr(content, zone);
+  RecordTextReader rtr(content, DNSName(zone));
   rtr.xfr8BitInt(d_algorithm);
   rtr.xfr8BitInt(d_flags);
   rtr.xfr16BitInt(d_iterations);
@@ -154,7 +232,7 @@ NSEC3RecordContent::NSEC3RecordContent(const string& content, const string& zone
   while(!rtr.eof()) {
     uint16_t type;
     rtr.xfrType(type);
-    d_set.insert(type);
+    set(type);
   }
 }
 
@@ -168,44 +246,13 @@ void NSEC3RecordContent::toPacket(DNSPacketWriter& pw)
 
   pw.xfr8BitInt(d_nexthash.length());
   pw.xfrBlob(d_nexthash);
-  
-  uint8_t res[34];
-  set<uint16_t>::const_iterator i;
-  int oldWindow = -1;
-  int window = 0;
-  int len = 0;
-  string tmp;
 
-  for(i=d_set.begin(); i != d_set.end(); ++i){
-    uint16_t bit = (*i)%256;
-    window = static_cast<int>((*i) / 256);
-
-    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);
-
-  if (len) {
-    tmp.assign(res, res+len+2);
-    pw.xfrBlob(tmp);
-  }
+  d_bitmap.toPacket(pw);
 }
 
-NSEC3RecordContent::DNSRecordContent* NSEC3RecordContent::make(const DNSRecord &dr, PacketReader& pr) 
+std::shared_ptr<NSEC3RecordContent::DNSRecordContent> NSEC3RecordContent::make(const DNSRecord &dr, PacketReader& pr)
 {
-  NSEC3RecordContent* ret=new NSEC3RecordContent();
+  auto ret=std::make_shared<NSEC3RecordContent>();
   pr.xfr8BitInt(ret->d_algorithm);
   pr.xfr8BitInt(ret->d_flags);
   pr.xfr16BitInt(ret->d_iterations);
@@ -215,35 +262,8 @@ NSEC3RecordContent::DNSRecordContent* NSEC3RecordContent::make(const DNSRecord &
 
   pr.xfr8BitInt(len);
   pr.xfrBlob(ret->d_nexthash, len);
-  
-  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("NSEC3 record with impossibly small bitmap");
-
-  for(unsigned int n = 0; n+1 < bitmap.size();) {
-    unsigned int window=static_cast<unsigned char>(bitmap[n++]);
-    unsigned int innerlen=static_cast<unsigned char>(bitmap[n++]);
-    
-    // end if zero padding and ensure packet length
-    if(window == 0&&innerlen == 0) break;
-    if(n+innerlen>bitmap.size())
-      throw MOADNSException("NSEC record with bitmap length > packet length");
-
-    for(unsigned int k=0; k < innerlen; 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);
-        }
-      }
-  }
+  ret->d_bitmap.fromPacket(pr);
   return ret;
 }
 
@@ -257,12 +277,8 @@ string NSEC3RecordContent::getZoneRepresentation(bool noDot) const
 
   rtw.xfrHexBlob(d_salt);
   rtw.xfrBase32HexBlob(d_nexthash);
-  for(set<uint16_t>::const_iterator i=d_set.begin(); i!=d_set.end(); ++i) {
-    ret+=" ";
-    ret+=NumberToType(*i);
-  }
-  
-  return ret;
+
+  return ret + d_bitmap.getZoneRepresentation();
 }
 
 
@@ -272,14 +288,14 @@ void NSEC3PARAMRecordContent::report(void)
   regist(254, 51, &make, &make, "NSEC3PARAM");
 }
 
-DNSRecordContent* NSEC3PARAMRecordContent::make(const string& content)
+std::shared_ptr<DNSRecordContent> NSEC3PARAMRecordContent::make(const string& content)
 {
-  return new NSEC3PARAMRecordContent(content);
+  return std::make_shared<NSEC3PARAMRecordContent>(content);
 }
 
 NSEC3PARAMRecordContent::NSEC3PARAMRecordContent(const string& content, const string& zone) 
 {
-  RecordTextReader rtr(content, zone);
+  RecordTextReader rtr(content, DNSName(zone));
   rtr.xfr8BitInt(d_algorithm); 
   rtr.xfr8BitInt(d_flags); 
   rtr.xfr16BitInt(d_iterations); 
@@ -296,9 +312,9 @@ void NSEC3PARAMRecordContent::toPacket(DNSPacketWriter& pw)
   pw.xfrBlob(d_salt);
 }
 
-NSEC3PARAMRecordContent::DNSRecordContent* NSEC3PARAMRecordContent::make(const DNSRecord &dr, PacketReader& pr) 
+std::shared_ptr<NSEC3PARAMRecordContent::DNSRecordContent> NSEC3PARAMRecordContent::make(const DNSRecord &dr, PacketReader& pr)
 {
-  NSEC3PARAMRecordContent* ret=new NSEC3PARAMRecordContent();
+  auto ret=std::make_shared<NSEC3PARAMRecordContent>();
   pr.xfr8BitInt(ret->d_algorithm); 
         pr.xfr8BitInt(ret->d_flags); 
         pr.xfr16BitInt(ret->d_iterations);