# include <sched.h>
#endif
-bool g_singleThreaded;
-
size_t writen2(int fd, const void *buf, size_t count)
{
const char *ptr = (char*)buf;
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) {
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;
}
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);
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);
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);
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 */
}
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 */
}
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"))
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");
+}