]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/misc.cc
Merge pull request #7704 from ahupowerdns/boost-stringref-cutoff
[thirdparty/pdns.git] / pdns / misc.cc
index b4c6d5cf8bd489544cef083a60b28d5e4c0026cb..9b6eea36d56b2668367ed46974fb98a7b58805e5 100644 (file)
@@ -202,7 +202,7 @@ string nowTime()
   // YYYY-mm-dd HH:MM:SS TZOFF
   strftime(buffer, sizeof(buffer), "%F %T %z", tm);
   buffer[sizeof(buffer)-1] = '\0';
-  return buffer;
+  return string(buffer);
 }
 
 uint16_t getShort(const unsigned char *p)
@@ -338,10 +338,7 @@ int waitForRWData(int fd, bool waitForRead, int seconds, int useconds, bool* err
     pfd.events=POLLOUT;
 
   ret = poll(&pfd, 1, seconds * 1000 + useconds/1000);
-  if ( ret == -1 ) {
-    errno = ETIMEDOUT; // ???
-  }
-  else if (ret > 0) {
+  if (ret > 0) {
     if (error && (pfd.revents & POLLERR)) {
       *error = true;
     }
@@ -354,7 +351,7 @@ int waitForRWData(int fd, bool waitForRead, int seconds, int useconds, bool* err
 }
 
 // returns -1 in case of error, 0 if no data is available, 1 if there is. In the first two cases, errno is set
-int waitForMultiData(const set<int>& fds, const int seconds, const int useconds, int* fd) {
+int waitForMultiData(const set<int>& fds, const int seconds, const int useconds, int* fdOut) {
   set<int> realFDs;
   for (const auto& fd : fds) {
     if (fd >= 0 && realFDs.count(fd) == 0) {
@@ -362,8 +359,8 @@ int waitForMultiData(const set<int>& fds, const int seconds, const int useconds,
     }
   }
 
-  struct pollfd pfds[realFDs.size()];
-  memset(&pfds[0], 0, realFDs.size()*sizeof(struct pollfd));
+  std::vector<struct pollfd> pfds(realFDs.size());
+  memset(pfds.data(), 0, realFDs.size()*sizeof(struct pollfd));
   int ctr = 0;
   for (const auto& fd : realFDs) {
     pfds[ctr].fd = fd;
@@ -373,9 +370,9 @@ int waitForMultiData(const set<int>& fds, const int seconds, const int useconds,
 
   int ret;
   if(seconds >= 0)
-    ret = poll(pfds, realFDs.size(), seconds * 1000 + useconds/1000);
+    ret = poll(pfds.data(), realFDs.size(), seconds * 1000 + useconds/1000);
   else
-    ret = poll(pfds, realFDs.size(), -1);
+    ret = poll(pfds.data(), realFDs.size(), -1);
   if(ret <= 0)
     return ret;
 
@@ -387,7 +384,7 @@ int waitForMultiData(const set<int>& fds, const int seconds, const int useconds,
   }
   set<int>::const_iterator it(pollinFDs.begin());
   advance(it, random() % pollinFDs.size());
-  *fd = *it;
+  *fdOut = *it;
   return 1;
 }
 
@@ -449,9 +446,8 @@ DTime::DTime()
   d_set.tv_sec=d_set.tv_usec=0;
 }
 
-DTime::DTime(const DTime &dt)
+DTime::DTime(const DTime &dt) : d_set(dt.d_set)
 {
-  d_set=dt.d_set;
 }
 
 time_t DTime::time()
@@ -502,7 +498,7 @@ string getHostname()
   if(gethostname(tmp, MAXHOSTNAMELEN))
     return "UNKNOWN";
 
-  return tmp;
+  return string(tmp);
 }
 
 string itoa(int i)
@@ -570,12 +566,12 @@ bool IpToU32(const string &str, uint32_t *ip)
 string U32ToIP(uint32_t val)
 {
   char tmp[17];
-  snprintf(tmp, sizeof(tmp)-1, "%u.%u.%u.%u",
+  snprintf(tmp, sizeof(tmp), "%u.%u.%u.%u",
            (val >> 24)&0xff,
            (val >> 16)&0xff,
            (val >>  8)&0xff,
            (val      )&0xff);
-  return tmp;
+  return string(tmp);
 }
 
 
@@ -586,7 +582,7 @@ string makeHexDump(const string& str)
   ret.reserve((int)(str.size()*2.2));
 
   for(string::size_type n=0;n<str.size();++n) {
-    sprintf(tmp,"%02x ", (unsigned char)str[n]);
+    snprintf(tmp, sizeof(tmp), "%02x ", (unsigned char)str[n]);
     ret+=tmp;
   }
   return ret;
@@ -768,7 +764,7 @@ int makeIPv6sockaddr(const std::string& addr, struct sockaddr_in6* ret)
         port = pdns_stou(addr.substr(pos+2));
         portSet = true;
       }
-      catch(std::out_of_range) {
+      catch(const std::out_of_range&) {
         return -1;
       }
     }
@@ -870,11 +866,12 @@ bool stringfgets(FILE* fp, std::string& line)
 bool readFileIfThere(const char* fname, std::string* line)
 {
   line->clear();
-  FILE* fp = fopen(fname, "r");
+  auto fp = std::unique_ptr<FILE, int(*)(FILE*)>(fopen(fname, "r"), fclose);
   if(!fp)
     return false;
-  stringfgets(fp, *line);
-  fclose(fp);
+  stringfgets(fp.get(), *line);
+  fp.reset();
+
   return true;
 }
 
@@ -1104,6 +1101,22 @@ bool isNonBlocking(int sock)
   return flags & O_NONBLOCK;
 }
 
+bool setReceiveSocketErrors(int sock, int af)
+{
+#ifdef __linux__
+  int tmp = 1, ret;
+  if (af == AF_INET) {
+    ret = setsockopt(sock, IPPROTO_IP, IP_RECVERR, &tmp, sizeof(tmp));
+  } else {
+    ret = setsockopt(sock, IPPROTO_IPV6, IPV6_RECVERR, &tmp, sizeof(tmp));
+  }
+  if (ret < 0) {
+    throw PDNSException(string("Setsockopt failed: ") + strerror(errno));
+  }
+#endif
+  return true;
+}
+
 // Closes a socket.
 int closesocket( int socket )
 {
@@ -1244,7 +1257,27 @@ uint64_t getOpenFileDescriptors(const std::string&)
 uint64_t getRealMemoryUsage(const std::string&)
 {
 #ifdef __linux__
-  ifstream ifs("/proc/"+std::to_string(getpid())+"/smaps");
+  ifstream ifs("/proc/self/statm");
+  if(!ifs)
+    return 0;
+
+  uint64_t size, resident, shared, text, lib, data;
+  ifs >> size >> resident >> shared >> text >> lib >> data;
+
+  return data * getpagesize();
+#else
+  struct rusage ru;
+  if (getrusage(RUSAGE_SELF, &ru) != 0)
+    return 0;
+  return ru.ru_maxrss * 1024;
+#endif
+}
+
+
+uint64_t getSpecialMemoryUsage(const std::string&)
+{
+#ifdef __linux__
+  ifstream ifs("/proc/self/smaps");
   if(!ifs)
     return 0;
   string line;
@@ -1360,9 +1393,18 @@ gid_t strToGID(const string &str)
 unsigned int pdns_stou(const std::string& str, size_t * idx, int base)
 {
   if (str.empty()) return 0; // compatibility
-  unsigned long result = std::stoul(str, idx, base);
+  unsigned long result;
+  try {
+    result = std::stoul(str, idx, base);
+  }
+  catch(std::invalid_argument& e) {
+    throw std::invalid_argument(string(e.what()) + "; (invalid argument during std::stoul); data was \""+str+"\"");
+  }
+  catch(std::out_of_range& e) {
+    throw std::out_of_range(string(e.what()) + "; (out of range during std::stoul); data was \""+str+"\"");
+  }
   if (result > std::numeric_limits<unsigned int>::max()) {
-    throw std::out_of_range("stou");
+    throw std::out_of_range("stoul returned result out of unsigned int range; data was \""+str+"\"");
   }
   return static_cast<unsigned int>(result);
 }
@@ -1407,3 +1449,39 @@ int mapThreadToCPUList(pthread_t tid, const std::set<int>& cpus)
   return ENOSYS;
 #endif /* HAVE_PTHREAD_SETAFFINITY_NP */
 }
+
+std::vector<ComboAddress> getResolvers(const std::string& resolvConfPath)
+{
+  std::vector<ComboAddress> results;
+
+  ifstream ifs(resolvConfPath);
+  if (!ifs) {
+    return results;
+  }
+
+  string line;
+  while(std::getline(ifs, line)) {
+    boost::trim_right_if(line, is_any_of(" \r\n\x1a"));
+    boost::trim_left(line); // leading spaces, let's be nice
+
+    string::size_type tpos = line.find_first_of(";#");
+    if (tpos != string::npos) {
+      line.resize(tpos);
+    }
+
+    if (boost::starts_with(line, "nameserver ") || boost::starts_with(line, "nameserver\t")) {
+      vector<string> parts;
+      stringtok(parts, line, " \t,"); // be REALLY nice
+      for(vector<string>::const_iterator iter = parts.begin() + 1; iter != parts.end(); ++iter) {
+        try {
+          results.emplace_back(*iter, 53);
+        }
+        catch(...)
+        {
+        }
+      }
+    }
+  }
+
+  return results;
+}