]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/dnsname.cc
rec: ensure correct service user on debian
[thirdparty/pdns.git] / pdns / dnsname.cc
index 07214efb1fcf53166a6c2d58d1d0b0aa5f4a5f02..ecfda97bec5015ae82db6fdcf247afa740f16d1b 100644 (file)
@@ -113,7 +113,7 @@ void DNSName::packetParser(const char* qpos, int len, int offset, bool uncompres
   const unsigned char* end = pos + len;
   pos += offset;
   while((labellen=*pos++) && pos < end) { // "scan and copy"
-    if(labellen & 0xc0) {
+    if(labellen >= 0xc0) {
       if(!uncompress)
         throw std::range_error("Found compressed label, instructed not to follow");
 
@@ -130,6 +130,8 @@ void DNSName::packetParser(const char* qpos, int len, int offset, bool uncompres
         throw std::range_error("Found a forward reference during label decompression");
       pos++;
       break;
+    } else if(labellen & 0xc0) {
+      throw std::range_error("Found an invalid label length in qname (only one of the first two bits is set)");
     }
     if (pos + labellen < end) {
       appendRawLabel((const char*)pos, labellen);
@@ -223,7 +225,7 @@ bool DNSName::isPartOf(const DNSName& parent) const
     if (static_cast<size_t>(distance) == parent.d_storage.size()) {
       auto p = parent.d_storage.cbegin();
       for(; us != d_storage.cend(); ++us, ++p) {
-        if(dns2_tolower(*p) != dns2_tolower(*us))
+        if(dns_tolower(*p) != dns_tolower(*us))
           return false;
       }
       return true;
@@ -251,6 +253,27 @@ void DNSName::makeUsRelative(const DNSName& zone)
     clear();
 }
 
+DNSName DNSName::getCommonLabels(const DNSName& other) const
+{
+  DNSName result;
+
+  const std::vector<std::string> ours = getRawLabels();
+  const std::vector<std::string> others = other.getRawLabels();
+
+  for (size_t pos = 0; ours.size() > pos && others.size() > pos; pos++) {
+    const std::string& ourLabel = ours.at(ours.size() - pos - 1);
+    const std::string& otherLabel = others.at(others.size() - pos - 1);
+
+    if (!pdns_iequals(ourLabel, otherLabel)) {
+      break;
+    }
+
+    result.prependRawLabel(ourLabel);
+  }
+
+  return result;
+}
+
 DNSName DNSName::labelReverse() const
 {
   DNSName ret;
@@ -326,6 +349,24 @@ vector<string> DNSName::getRawLabels() const
   return ret;
 }
 
+std::string DNSName::getRawLabel(unsigned int pos) const
+{
+  unsigned int currentPos = 0;
+  for(const unsigned char* p = (const unsigned char*) d_storage.c_str(); p < ((const unsigned char*) d_storage.c_str()) + d_storage.size() && *p; p+=*p+1, currentPos++) {
+    if (currentPos == pos) {
+      return std::string((const char*)p+1, (size_t)*p);
+    }
+  }
+
+  throw std::out_of_range("trying to get label at position "+std::to_string(pos)+" of a DNSName that only has "+std::to_string(currentPos)+" labels");
+}
+
+DNSName DNSName::getLastLabel() const
+{
+  DNSName ret(*this);
+  ret.trimToLabels(1);
+  return ret;
+}
 
 bool DNSName::chopOff()
 {
@@ -343,6 +384,16 @@ bool DNSName::isWildcard() const
   return (*p == 0x01 && *++p == '*');
 }
 
+/*
+ * Returns true if the DNSName is a valid RFC 1123 hostname, this function uses
+ * a regex on the string, so it is probably best not used when speed is essential.
+ */
+bool DNSName::isHostname() const
+{
+  static Regex hostNameRegex = Regex("^(([A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?)\\.)+$");
+  return hostNameRegex.match(this->toString());
+}
+
 unsigned int DNSName::countLabels() const
 {
   unsigned int count=0;
@@ -372,7 +423,7 @@ string DNSName::escapeLabel(const std::string& label)
       ret+="\\.";
     else if(p=='\\')
       ret+="\\\\";
-    else if(p > 0x21 && p < 0x7e)
+    else if(p > 0x20 && p < 0x7f)
       ret.append(1, (char)p);
     else {
       ret+="\\" + (boost::format("%03d") % (unsigned int)p).str();