]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/misc.cc
Merge pull request #9070 from rgacogne/boost-173
[thirdparty/pdns.git] / pdns / misc.cc
index 4b8a25d2162dffab809b43941126ecb5f1d11fa1..fb253e5f1c40d7e5563e36b827c2f201818c664b 100644 (file)
@@ -65,8 +65,6 @@
 #  include <sched.h>
 #endif
 
-bool g_singleThreaded;
-
 size_t writen2(int fd, const void *buf, size_t count)
 {
   const char *ptr = (char*)buf;
@@ -585,83 +583,6 @@ string makeHexDump(const string& str)
   return ret;
 }
 
-// shuffle, maintaining some semblance of order
-void shuffle(vector<DNSZoneRecord>& rrs)
-{
-  vector<DNSZoneRecord>::iterator first, second;
-  for(first=rrs.begin();first!=rrs.end();++first)
-    if(first->dr.d_place==DNSResourceRecord::ANSWER && first->dr.d_type != QType::CNAME) // CNAME must come first
-      break;
-  for(second=first;second!=rrs.end();++second)
-    if(second->dr.d_place!=DNSResourceRecord::ANSWER)
-      break;
-
-  if(second-first > 1)
-    random_shuffle(first,second);
-
-  // now shuffle the additional records
-  for(first=second;first!=rrs.end();++first)
-    if(first->dr.d_place==DNSResourceRecord::ADDITIONAL && first->dr.d_type != QType::CNAME) // CNAME must come first
-      break;
-  for(second=first;second!=rrs.end();++second)
-    if(second->dr.d_place!=DNSResourceRecord::ADDITIONAL)
-      break;
-
-  if(second-first>1)
-    random_shuffle(first,second);
-
-  // we don't shuffle the rest
-}
-
-
-// shuffle, maintaining some semblance of order
-void shuffle(vector<DNSRecord>& rrs)
-{
-  vector<DNSRecord>::iterator first, second;
-  for(first=rrs.begin();first!=rrs.end();++first)
-    if(first->d_place==DNSResourceRecord::ANSWER && first->d_type != QType::CNAME) // CNAME must come first
-      break;
-  for(second=first;second!=rrs.end();++second)
-    if(second->d_place!=DNSResourceRecord::ANSWER || second->d_type == QType::RRSIG) // leave RRSIGs at the end
-      break;
-
-  if(second-first>1)
-    random_shuffle(first,second);
-
-  // now shuffle the additional records
-  for(first=second;first!=rrs.end();++first)
-    if(first->d_place==DNSResourceRecord::ADDITIONAL && first->d_type != QType::CNAME) // CNAME must come first
-      break;
-  for(second=first; second!=rrs.end(); ++second)
-    if(second->d_place!=DNSResourceRecord::ADDITIONAL)
-      break;
-
-  if(second-first>1)
-    random_shuffle(first,second);
-
-  // we don't shuffle the rest
-}
-
-static uint16_t mapTypesToOrder(uint16_t type)
-{
-  if(type == QType::CNAME)
-    return 0;
-  if(type == QType::RRSIG)
-    return 65535;
-  else
-    return 1;
-}
-
-// make sure rrs is sorted in d_place order to avoid surprises later
-// then shuffle the parts that desire shuffling
-void orderAndShuffle(vector<DNSRecord>& rrs)
-{
-  std::stable_sort(rrs.begin(), rrs.end(), [](const DNSRecord&a, const DNSRecord& b) { 
-      return std::make_tuple(a.d_place, mapTypesToOrder(a.d_type)) < std::make_tuple(b.d_place, mapTypesToOrder(b.d_type));
-    });
-  shuffle(rrs);
-}
-
 void normalizeTV(struct timeval& tv)
 {
   if(tv.tv_usec > 1000000) {
@@ -777,9 +698,8 @@ int makeIPv6sockaddr(const std::string& addr, struct sockaddr_in6* ret)
     hints.ai_family = AF_INET6;
     hints.ai_flags = AI_NUMERICHOST;
 
-    int error;
     // getaddrinfo has anomalous return codes, anything nonzero is an error, positive or negative
-    if((error=getaddrinfo(ourAddr.c_str(), 0, &hints, &res))) {
+    if (getaddrinfo(ourAddr.c_str(), 0, &hints, &res) != 0) {
       return -1;
     }
 
@@ -890,7 +810,14 @@ void addCMsgSrcAddr(struct msghdr* msgh, cmsgbuf_aligned* cmsgbuf, const ComboAd
     struct in6_pktinfo *pkt;
 
     msgh->msg_control = cmsgbuf;
+#if !defined( __APPLE__ )
+    /* CMSG_SPACE is not a constexpr on macOS */
     static_assert(CMSG_SPACE(sizeof(*pkt)) <= sizeof(*cmsgbuf), "Buffer is too small for in6_pktinfo");
+#else /* __APPLE__ */
+    if (CMSG_SPACE(sizeof(*pkt)) > sizeof(*cmsgbuf)) {
+      throw std::runtime_error("Buffer is too small for in6_pktinfo");
+    }
+#endif /* __APPLE__ */
     msgh->msg_controllen = CMSG_SPACE(sizeof(*pkt));
 
     cmsg = CMSG_FIRSTHDR(msgh);
@@ -909,7 +836,14 @@ void addCMsgSrcAddr(struct msghdr* msgh, cmsgbuf_aligned* cmsgbuf, const ComboAd
     struct in_pktinfo *pkt;
 
     msgh->msg_control = cmsgbuf;
+#if !defined( __APPLE__ )
+    /* CMSG_SPACE is not a constexpr on macOS */
     static_assert(CMSG_SPACE(sizeof(*pkt)) <= sizeof(*cmsgbuf), "Buffer is too small for in_pktinfo");
+#else /* __APPLE__ */
+    if (CMSG_SPACE(sizeof(*pkt)) > sizeof(*cmsgbuf)) {
+      throw std::runtime_error("Buffer is too small for in_pktinfo");
+    }
+#endif /* __APPLE__ */
     msgh->msg_controllen = CMSG_SPACE(sizeof(*pkt));
 
     cmsg = CMSG_FIRSTHDR(msgh);
@@ -926,7 +860,13 @@ void addCMsgSrcAddr(struct msghdr* msgh, cmsgbuf_aligned* cmsgbuf, const ComboAd
     struct in_addr *in;
 
     msgh->msg_control = cmsgbuf;
+#if !defined( __APPLE__ )
     static_assert(CMSG_SPACE(sizeof(*in)) <= sizeof(*cmsgbuf), "Buffer is too small for in_addr");
+#else /* __APPLE__ */
+    if (CMSG_SPACE(sizeof(*in)) > sizeof(*cmsgbuf)) {
+      throw std::runtime_error("Buffer is too small for in_addr");
+    }
+#endif /* __APPLE__ */
     msgh->msg_controllen = CMSG_SPACE(sizeof(*in));
 
     cmsg = CMSG_FIRSTHDR(msgh);
@@ -996,16 +936,26 @@ uint32_t burtle(const unsigned char* k, uint32_t length, uint32_t initval)
   c += length;
   switch(len) {             /* all the case statements fall through */
   case 11: c+=((uint32_t)k[10]<<24);
+    /* fall-through */
   case 10: c+=((uint32_t)k[9]<<16);
+    /* fall-through */
   case 9 : c+=((uint32_t)k[8]<<8);
     /* the first byte of c is reserved for the length */
+    /* fall-through */
   case 8 : b+=((uint32_t)k[7]<<24);
+    /* fall-through */
   case 7 : b+=((uint32_t)k[6]<<16);
+    /* fall-through */
   case 6 : b+=((uint32_t)k[5]<<8);
+    /* fall-through */
   case 5 : b+=k[4];
+    /* fall-through */
   case 4 : a+=((uint32_t)k[3]<<24);
+    /* fall-through */
   case 3 : a+=((uint32_t)k[2]<<16);
+    /* fall-through */
   case 2 : a+=((uint32_t)k[1]<<8);
+    /* fall-through */
   case 1 : a+=k[0];
     /* case 0: nothing left to add */
   }
@@ -1036,16 +986,26 @@ uint32_t burtleCI(const unsigned char* k, uint32_t length, uint32_t initval)
   c += length;
   switch(len) {             /* all the case statements fall through */
   case 11: c+=((uint32_t)dns_tolower(k[10])<<24);
+    /* fall-through */
   case 10: c+=((uint32_t)dns_tolower(k[9])<<16);
+    /* fall-through */
   case 9 : c+=((uint32_t)dns_tolower(k[8])<<8);
     /* the first byte of c is reserved for the length */
+    /* fall-through */
   case 8 : b+=((uint32_t)dns_tolower(k[7])<<24);
+    /* fall-through */
   case 7 : b+=((uint32_t)dns_tolower(k[6])<<16);
+    /* fall-through */
   case 6 : b+=((uint32_t)dns_tolower(k[5])<<8);
+    /* fall-through */
   case 5 : b+=dns_tolower(k[4]);
+    /* fall-through */
   case 4 : a+=((uint32_t)dns_tolower(k[3])<<24);
+    /* fall-through */
   case 3 : a+=((uint32_t)dns_tolower(k[2])<<16);
+    /* fall-through */
   case 2 : a+=((uint32_t)dns_tolower(k[1])<<8);
+    /* fall-through */
   case 1 : a+=dns_tolower(k[0]);
     /* case 0: nothing left to add */
   }
@@ -1196,6 +1156,56 @@ uint64_t udpErrorStats(const std::string& str)
   return 0;
 }
 
+uint64_t getCPUIOWait(const std::string& str)
+{
+#ifdef __linux__
+  ifstream ifs("/proc/stat");
+  if (!ifs) {
+    return 0;
+  }
+
+  string line;
+  vector<string> parts;
+  while (getline(ifs, line)) {
+    if (boost::starts_with(line, "cpu ")) {
+      stringtok(parts, line, " \n\t\r");
+
+      if (parts.size() < 6) {
+        break;
+      }
+
+      return std::stoull(parts[5]);
+    }
+  }
+#endif
+  return 0;
+}
+
+uint64_t getCPUSteal(const std::string& str)
+{
+#ifdef __linux__
+  ifstream ifs("/proc/stat");
+  if (!ifs) {
+    return 0;
+  }
+
+  string line;
+  vector<string> parts;
+  while (getline(ifs, line)) {
+    if (boost::starts_with(line, "cpu ")) {
+      stringtok(parts, line, " \n\t\r");
+
+      if (parts.size() < 9) {
+        break;
+      }
+
+      return std::stoull(parts[8]);
+    }
+  }
+#endif
+  return 0;
+}
+
 bool getTSIGHashEnum(const DNSName& algoName, TSIGHashEnum& algoEnum)
 {
   if (algoName == DNSName("hmac-md5.sig-alg.reg.int") || algoName == DNSName("hmac-md5"))
@@ -1523,3 +1533,30 @@ bool setPipeBufferSize(int fd, size_t size)
   return false;
 #endif /* F_SETPIPE_SZ */
 }
+
+DNSName reverseNameFromIP(const ComboAddress& ip)
+{
+  if (ip.isIPv4()) {
+    std::string result("in-addr.arpa.");
+    auto ptr = reinterpret_cast<const uint8_t*>(&ip.sin4.sin_addr.s_addr);
+    for (size_t idx = 0; idx < sizeof(ip.sin4.sin_addr.s_addr); idx++) {
+      result = std::to_string(ptr[idx]) + "." + result;
+    }
+    return DNSName(result);
+  }
+  else if (ip.isIPv6()) {
+    std::string result("ip6.arpa.");
+    auto ptr = reinterpret_cast<const uint8_t*>(&ip.sin6.sin6_addr.s6_addr[0]);
+    for (size_t idx = 0; idx < sizeof(ip.sin6.sin6_addr.s6_addr); idx++) {
+      std::stringstream stream;
+      stream << std::hex << (ptr[idx] & 0x0F);
+      stream << '.';
+      stream << std::hex << (((ptr[idx]) >> 4) & 0x0F);
+      stream << '.';
+      result = stream.str() + result;
+    }
+    return DNSName(result);
+  }
+
+  throw std::runtime_error("Calling reverseNameFromIP() for an address which is neither an IPv4 nor an IPv6");
+}