]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/misc.hh
Limit the number of queries sent out to get NS addresses per query.
[thirdparty/pdns.git] / pdns / misc.hh
CommitLineData
12c86877 1/*
12471842
PL
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
ea76bac0 22#pragma once
61b26744 23#include <inttypes.h>
8b3cfcd3 24#include <cstring>
f9822705 25#include <cstdio>
3ee84c3f 26#include <regex.h>
58044407 27#include <limits.h>
88bf3279 28#include <type_traits>
ec6480f3 29#include <boost/algorithm/string.hpp>
f0db590d
BH
30#include <boost/multi_index_container.hpp>
31#include <boost/multi_index/ordered_index.hpp>
32#include <boost/tuple/tuple_comparison.hpp>
33#include <boost/multi_index/key_extractors.hpp>
34#include <boost/multi_index/sequenced_index.hpp>
d190894c 35
f0db590d 36using namespace ::boost::multi_index;
12c86877 37
e67e250f 38#include "dns.hh"
ac0995bb 39#include <atomic>
76473b92
KM
40#include <sys/time.h>
41#include <sys/types.h>
42#include <sys/socket.h>
43#include <time.h>
44#include <syslog.h>
3de83124 45#include <deque>
a640a9d4 46#include <stdexcept>
12c86877
BH
47#include <string>
48#include <ctype.h>
e67e250f
BH
49#include <vector>
50
10f4eea8 51#include "namespaces.hh"
d72aaada
KM
52#include "dnsname.hh"
53
bcb5b94e 54typedef enum { TSIG_MD5, TSIG_SHA1, TSIG_SHA224, TSIG_SHA256, TSIG_SHA384, TSIG_SHA512, TSIG_GSS } TSIGHashEnum;
da15912b 55
cc3afe25 56string nowTime();
1d329048 57const string unquotify(const string &item);
12c86877 58string humanDuration(time_t passed);
f2c11a48 59bool stripDomainSuffix(string *qname, const string &domain);
12c86877
BH
60void stripLine(string &line);
61string getHostname();
62string urlEncode(const string &text);
a7d50153 63int waitForData(int fd, int seconds, int useconds=0);
f4ff5929 64int waitFor2Data(int fd1, int fd2, int seconds, int useconds, int* fd);
d529011f 65int waitForMultiData(const set<int>& fds, const int seconds, const int useconds, int* fd);
51959320 66int waitForRWData(int fd, bool waitForRead, int seconds, int useconds, bool* error=nullptr, bool* disconnected=nullptr);
092f210a
BH
67uint16_t getShort(const unsigned char *p);
68uint16_t getShort(const char *p);
69uint32_t getLong(const unsigned char *p);
70uint32_t getLong(const char *p);
21a3792f
KM
71bool getTSIGHashEnum(const DNSName& algoName, TSIGHashEnum& algoEnum);
72DNSName getTSIGAlgoName(TSIGHashEnum& algoEnum);
58044407 73
f8499e52 74int logFacilityToLOG(unsigned int facility);
bbce5bf0 75
12c86877
BH
76struct ServiceTuple
77{
78 string host;
092f210a 79 uint16_t port;
12c86877
BH
80};
81void parseService(const string &descr, ServiceTuple &st);
82
83template <typename Container>
84void
85stringtok (Container &container, string const &in,
86 const char * const delimiters = " \t\n")
87{
88 const string::size_type len = in.length();
89 string::size_type i = 0;
3ddb9247 90
12c86877
BH
91 while (i<len) {
92 // eat leading whitespace
93 i = in.find_first_not_of (delimiters, i);
94 if (i == string::npos)
95 return; // nothing left but white space
3ddb9247 96
12c86877
BH
97 // find the end of the token
98 string::size_type j = in.find_first_of (delimiters, i);
3ddb9247 99
12c86877
BH
100 // push token
101 if (j == string::npos) {
102 container.push_back (in.substr(i));
103 return;
104 } else
105 container.push_back (in.substr(i, j-i));
3ddb9247 106
12c86877
BH
107 // set up for next loop
108 i = j + 1;
109 }
110}
8c3149f2 111
f7a69a4c
RA
112template<typename T> bool rfc1982LessThan(T a, T b)
113{
d24c4eec 114 static_assert(std::is_unsigned<T>::value, "rfc1982LessThan only works for unsigned types");
9a363102
OM
115 typedef typename std::make_signed<T>::type signed_t;
116 return static_cast<signed_t>(a - b) < 0;
f7a69a4c
RA
117}
118
0ab3fdc6 119// fills container with ranges, so {posbegin,posend}
8c3149f2
BH
120template <typename Container>
121void
122vstringtok (Container &container, string const &in,
123 const char * const delimiters = " \t\n")
124{
125 const string::size_type len = in.length();
126 string::size_type i = 0;
3ddb9247 127
8c3149f2
BH
128 while (i<len) {
129 // eat leading whitespace
130 i = in.find_first_not_of (delimiters, i);
131 if (i == string::npos)
132 return; // nothing left but white space
3ddb9247 133
8c3149f2
BH
134 // find the end of the token
135 string::size_type j = in.find_first_of (delimiters, i);
3ddb9247 136
8c3149f2
BH
137 // push token
138 if (j == string::npos) {
139 container.push_back (make_pair(i, len));
140 return;
141 } else
142 container.push_back (make_pair(i, j));
3ddb9247 143
8c3149f2
BH
144 // set up for next loop
145 i = j + 1;
146 }
147}
148
a683e8bd
RG
149size_t writen2(int fd, const void *buf, size_t count);
150inline size_t writen2(int fd, const std::string &s) { return writen2(fd, s.data(), s.size()); }
151size_t readn2(int fd, void* buffer, size_t len);
9396d955 152size_t readn2WithTimeout(int fd, void* buffer, size_t len, int idleTimeout, int totalTimeout=0);
a683e8bd 153size_t writen2WithTimeout(int fd, const void * buffer, size_t len, int timeout);
040712e0 154
c3d9d009 155const string toLower(const string &upper);
b0d4fb45 156const string toLowerCanonic(const string &upper);
092f210a 157bool IpToU32(const string &str, uint32_t *ip);
5730f30c 158string U32ToIP(uint32_t);
a2a81d42 159string stringerror(int);
12c86877
BH
160string stringerror();
161string itoa(int i);
22c9c86a 162string uitoa(unsigned int i);
d88babea 163string bitFlip(const string &str);
12c86877
BH
164
165void dropPrivs(int uid, int gid);
12c86877
BH
166void cleanSlashes(string &str);
167
c6d04bdc 168#if defined(_POSIX_THREAD_CPUTIME) && defined(CLOCK_THREAD_CPUTIME_ID)
df13e61d 169/** CPUTime measurements */
170class CPUTime
171{
172public:
173 void start()
174 {
175 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &d_start);
176 }
177 uint64_t ndiff()
178 {
179 struct timespec now;
180 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now);
181 return 1000000000ULL*(now.tv_sec - d_start.tv_sec) + (now.tv_nsec - d_start.tv_nsec);
182 }
183private:
184 struct timespec d_start;
185};
3ddb9247 186#endif
df13e61d 187
3ddb9247 188/** The DTime class can be used for timing statistics with microsecond resolution.
12c86877 189On 32 bits systems this means that 2147 seconds is the longest time that can be measured. */
3ddb9247 190class DTime
12c86877
BH
191{
192public:
eefd15f9 193 DTime(); //!< Does not set the timer for you! Saves lots of gettimeofday() calls
f238ce64
OM
194 DTime(const DTime &dt) = default;
195 DTime & operator=(const DTime &dt) = default;
12c86877
BH
196 time_t time();
197 inline void set(); //!< Reset the timer
198 inline int udiff(); //!< Return the number of microseconds since the timer was last set.
62c3a7b8 199 inline int udiffNoReset(); //!< Return the number of microseconds since the timer was last set.
88358c9b
BH
200 void setTimeval(const struct timeval& tv)
201 {
202 d_set=tv;
203 }
204 struct timeval getTimeval()
205 {
206 return d_set;
207 }
12c86877
BH
208private:
209 struct timeval d_set;
210};
85db02c5 211
12c86877
BH
212inline void DTime::set()
213{
15ad1a99 214 gettimeofday(&d_set,0);
12c86877
BH
215}
216
217inline int DTime::udiff()
62c3a7b8
BH
218{
219 int res=udiffNoReset();
15ad1a99 220 gettimeofday(&d_set,0);
62c3a7b8
BH
221 return res;
222}
223
224inline int DTime::udiffNoReset()
12c86877
BH
225{
226 struct timeval now;
12c86877 227
15ad1a99 228 gettimeofday(&now,0);
fe213470 229 int ret=1000000*(now.tv_sec-d_set.tv_sec)+(now.tv_usec-d_set.tv_usec);
fe213470 230 return ret;
12c86877
BH
231}
232
c3d9d009 233inline const string toLower(const string &upper)
12c86877
BH
234{
235 string reply(upper);
2b3eefc3 236 const size_t length = reply.length();
c536ca8d 237 char c;
2b3eefc3 238 for(unsigned int i = 0; i < length; ++i) {
e3cacd48
BH
239 c = dns_tolower(upper[i]);
240 if( c != upper[i])
c536ca8d
BH
241 reply[i] = c;
242 }
12c86877
BH
243 return reply;
244}
245
b0d4fb45
BH
246inline const string toLowerCanonic(const string &upper)
247{
248 string reply(upper);
249 if(!upper.empty()) {
705f31ae 250 unsigned int i, limit= ( unsigned int ) reply.length();
1352c9b6 251 unsigned char c;
c536ca8d 252 for(i = 0; i < limit ; i++) {
e3cacd48
BH
253 c = dns_tolower(upper[i]);
254 if(c != upper[i])
4957a608 255 reply[i] = c;
3ddb9247 256 }
e3cacd48 257 if(upper[i-1]=='.')
b0d4fb45
BH
258 reply.resize(i-1);
259 }
3ddb9247 260
b0d4fb45
BH
261 return reply;
262}
263
264
12c86877 265
52936200
BH
266// Make s uppercase:
267inline string toUpper( const string& s )
268{
4957a608
BH
269 string r(s);
270 for( unsigned int i = 0; i < s.length(); i++ ) {
315f45a0 271 r[i] = dns_toupper(r[i]);
4957a608
BH
272 }
273 return r;
52936200
BH
274}
275
a6d7640a
BH
276inline double getTime()
277{
278 struct timeval now;
15ad1a99 279 gettimeofday(&now,0);
3ddb9247 280
a6d7640a
BH
281 return now.tv_sec+now.tv_usec/1000000.0;
282}
283
a640a9d4
BH
284inline void unixDie(const string &why)
285{
a2a81d42 286 throw runtime_error(why+": "+stringerror());
a640a9d4
BH
287}
288
2db9c30e 289string makeHexDump(const string& str);
88358c9b
BH
290
291void normalizeTV(struct timeval& tv);
292const struct timeval operator+(const struct timeval& lhs, const struct timeval& rhs);
293const struct timeval operator-(const struct timeval& lhs, const struct timeval& rhs);
294inline float makeFloat(const struct timeval& tv)
295{
705f31ae 296 return tv.tv_sec + tv.tv_usec/1000000.0f;
88358c9b 297}
5b0ddd18 298
3ddb9247 299inline bool operator<(const struct timeval& lhs, const struct timeval& rhs)
5b0ddd18
BH
300{
301 return make_pair(lhs.tv_sec, lhs.tv_usec) < make_pair(rhs.tv_sec, rhs.tv_usec);
302}
303
80a216c9 304inline bool operator<(const struct timespec& lhs, const struct timespec& rhs)
305{
306 return tie(lhs.tv_sec, lhs.tv_nsec) < tie(rhs.tv_sec, rhs.tv_nsec);
307}
308
309
ec6480f3 310inline bool pdns_ilexicographical_compare(const std::string& a, const std::string& b) __attribute__((pure));
8fb5b29a 311inline bool pdns_ilexicographical_compare(const std::string& a, const std::string& b)
7738a23f 312{
97a24230 313 const unsigned char *aPtr = (const unsigned char*)a.c_str(), *bPtr = (const unsigned char*)b.c_str();
7fd7a590 314 const unsigned char *aEptr = aPtr + a.length(), *bEptr = bPtr + b.length();
315 while(aPtr != aEptr && bPtr != bEptr) {
8fb5b29a
KM
316 if ((*aPtr != *bPtr) && (dns_tolower(*aPtr) - dns_tolower(*bPtr)))
317 return (dns_tolower(*aPtr) - dns_tolower(*bPtr)) < 0;
318 aPtr++;
319 bPtr++;
7738a23f 320 }
7fd7a590 321 if(aPtr == aEptr && bPtr == bEptr) // strings are equal (in length)
8fb5b29a 322 return false;
7fd7a590 323 return aPtr == aEptr; // true if first string was shorter
ec6480f3 324}
eff65ff8 325
ec6480f3 326inline bool pdns_iequals(const std::string& a, const std::string& b) __attribute__((pure));
8fb5b29a 327inline bool pdns_iequals(const std::string& a, const std::string& b)
ec6480f3 328{
8fb5b29a
KM
329 if (a.length() != b.length())
330 return false;
331
ec6480f3 332 const char *aPtr = a.c_str(), *bPtr = b.c_str();
b10795de 333 const char *aEptr = aPtr + a.length();
334 while(aPtr != aEptr) {
8fb5b29a
KM
335 if((*aPtr != *bPtr) && (dns_tolower(*aPtr) != dns_tolower(*bPtr)))
336 return false;
337 aPtr++;
338 bPtr++;
eff65ff8 339 }
8fb5b29a 340 return true;
ec6480f3
BH
341}
342
57cb86d8
CH
343inline bool pdns_iequals_ch(const char a, const char b) __attribute__((pure));
344inline bool pdns_iequals_ch(const char a, const char b)
345{
346 if ((a != b) && (dns_tolower(a) != dns_tolower(b)))
347 return false;
348
349 return true;
350}
351
1566533a 352
00c6f2b9
RG
353typedef unsigned long AtomicCounterInner;
354typedef std::atomic<AtomicCounterInner> AtomicCounter ;
1bc9e6bd 355
ac0995bb 356// FIXME400 this should probably go?
3ddb9247 357struct CIStringCompare: public std::binary_function<string, string, bool>
ec6480f3
BH
358{
359 bool operator()(const string& a, const string& b) const
eff65ff8 360 {
ec6480f3 361 return pdns_ilexicographical_compare(a, b);
eff65ff8 362 }
7738a23f 363};
eff65ff8 364
2aa1b703
AT
365struct CIStringComparePOSIX
366{
367 bool operator() (const std::string& lhs, const std::string& rhs)
368 {
369 std::string::const_iterator a,b;
370 const std::locale &loc = std::locale("POSIX");
371 a=lhs.begin();b=rhs.begin();
372 while(a!=lhs.end()) {
373 if (b==rhs.end() || std::tolower(*b,loc)<std::tolower(*a,loc)) return false;
374 else if (std::tolower(*a,loc)<std::tolower(*b,loc)) return true;
4b5da564 375 ++a;++b;
2aa1b703
AT
376 }
377 return (b!=rhs.end());
378 }
379};
380
3ddb9247 381struct CIStringPairCompare: public std::binary_function<pair<string, uint16_t>, pair<string,uint16_t>, bool>
21f0f88b
BH
382{
383 bool operator()(const pair<string, uint16_t>& a, const pair<string, uint16_t>& b) const
384 {
385 if(pdns_ilexicographical_compare(a.first, b.first))
386 return true;
387 if(pdns_ilexicographical_compare(b.first, a.first))
388 return false;
389 return a.second < b.second;
390 }
391};
392
57cb86d8
CH
393inline size_t pdns_ci_find(const string& haystack, const string& needle)
394{
395 string::const_iterator it = std::search(haystack.begin(), haystack.end(),
396 needle.begin(), needle.end(), pdns_iequals_ch);
397 if (it == haystack.end()) {
398 // not found
399 return string::npos;
400 } else {
401 return it - haystack.begin();
402 }
403}
21f0f88b 404
50c79a76 405pair<string, string> splitField(const string& inp, char sepa);
26cd1b3f 406
e720f311 407inline bool isCanonical(const string& qname)
26cd1b3f 408{
e720f311 409 if(qname.empty())
26cd1b3f 410 return false;
e720f311 411 return qname[qname.size()-1]=='.';
26cd1b3f
BH
412}
413
e720f311 414inline DNSName toCanonic(const DNSName& zone, const string& qname)
675fa24c 415{
e720f311 416 if(qname.size()==1 && qname[0]=='@')
8171ab83 417 return zone;
e720f311 418 if(isCanonical(qname))
8171ab83 419 return DNSName(qname);
e720f311 420 return DNSName(qname) += zone;
26cd1b3f 421}
da042e6e
BH
422
423string stripDot(const string& dom);
561434a6 424
f71bc087 425int makeIPv6sockaddr(const std::string& addr, struct sockaddr_in6* ret);
76cb4593
CH
426int makeIPv4sockaddr(const std::string& str, struct sockaddr_in* ret);
427int makeUNsockaddr(const std::string& path, struct sockaddr_un* ret);
834942f1 428bool stringfgets(FILE* fp, std::string& line);
f0db590d
BH
429
430template<typename Index>
431std::pair<typename Index::iterator,bool>
432replacing_insert(Index& i,const typename Index::value_type& x)
433{
434 std::pair<typename Index::iterator,bool> res=i.insert(x);
435 if(!res.second)res.second=i.replace(res.first,x);
436 return res;
437}
438
3ee84c3f
BH
439/** very small regex wrapper */
440class Regex
441{
442public:
443 /** constructor that accepts the expression to regex */
444 Regex(const string &expr);
3ddb9247 445
3ee84c3f
BH
446 ~Regex()
447 {
448 regfree(&d_preg);
449 }
450 /** call this to find out if 'line' matches your expression */
6eecd4c2 451 bool match(const string &line) const
3ee84c3f
BH
452 {
453 return regexec(&d_preg,line.c_str(),0,0,0)==0;
454 }
6eecd4c2 455 bool match(const DNSName& name) const
60ee1829
AT
456 {
457 return match(name.toStringNoDot());
458 }
459
3ee84c3f
BH
460private:
461 regex_t d_preg;
462};
463
ac84f00c
AT
464class SimpleMatch
465{
466public:
8a70e507 467 SimpleMatch(const string &mask, bool caseFold = false): d_mask(mask), d_fold(caseFold)
ac84f00c 468 {
ac84f00c
AT
469 }
470
471 bool match(string::const_iterator mi, string::const_iterator mend, string::const_iterator vi, string::const_iterator vend)
472 {
4b5da564 473 for(;;++mi) {
ac84f00c
AT
474 if (mi == mend) {
475 return vi == vend;
476 } else if (*mi == '?') {
477 if (vi == vend) return false;
4b5da564 478 ++vi;
ac84f00c 479 } else if (*mi == '*') {
4b5da564 480 while(*mi == '*') ++mi;
ac84f00c
AT
481 if (mi == d_mask.end()) return true;
482 while(vi != vend) {
483 if (match(mi,mend,vi,vend)) return true;
4b5da564 484 ++vi;
ac84f00c
AT
485 }
486 return false;
487 } else {
488 if ((mi == mend && vi != vend)||
489 (mi != mend && vi == vend)) return false;
490 if (d_fold) {
491 if (dns_tolower(*mi) != dns_tolower(*vi)) return false;
492 } else {
493 if (*mi != *vi) return false;
494 }
4b5da564 495 ++vi;
ac84f00c
AT
496 }
497 }
498 }
499
500 bool match(const string& value) {
501 return match(d_mask.begin(), d_mask.end(), value.begin(), value.end());
502 }
503
504 bool match(const DNSName& name) {
505 return match(name.toStringNoDot());
506 }
507
508private:
509 string d_mask;
510 bool d_fold;
511};
512
65d8e171 513union ComboAddress;
7bec330a 514
00692909 515// An aligned type to hold cmsgbufs. See https://man.openbsd.org/CMSG_DATA
7bec330a
OM
516typedef union { struct cmsghdr hdr; char buf[256]; } cmsgbuf_aligned;
517
fbe2a2e0 518/* itfIndex is an interface index, as returned by if_nametoindex(). 0 means default. */
7bec330a 519void addCMsgSrcAddr(struct msghdr* msgh, cmsgbuf_aligned* cbuf, const ComboAddress* source, int itfIndex);
3a8a4d68 520
521unsigned int getFilenumLimit(bool hardOrSoft=0);
522void setFilenumLimit(unsigned int lim);
4e9a20e6 523bool readFileIfThere(const char* fname, std::string* line);
5c57a75a 524uint32_t burtle(const unsigned char* k, uint32_t length, uint32_t init);
915b0c39 525bool setSocketTimestamps(int fd);
15ad1a99 526
527//! Sets the socket into blocking mode.
528bool setBlocking( int sock );
529
530//! Sets the socket into non-blocking mode.
531bool setNonBlocking( int sock );
883a30a7 532bool setTCPNoDelay(int sock);
bf676f2f 533bool setReuseAddr(int sock);
18861f97 534bool isNonBlocking(int sock);
29bb743c 535bool setReceiveSocketErrors(int sock, int af);
3897b9e1 536int closesocket(int fd);
537bool setCloseOnExec(int sock);
74ad42dc 538
ee271fc4
RG
539size_t getPipeBufferSize(int fd);
540bool setPipeBufferSize(int fd, size_t size);
541
542uint64_t udpErrorStats(const std::string& str);
a1a787dc 543uint64_t getRealMemoryUsage(const std::string&);
330dcb5c 544uint64_t getSpecialMemoryUsage(const std::string&);
a9b6db56 545uint64_t getOpenFileDescriptors(const std::string&);
4f99f3d3
RG
546uint64_t getCPUTimeUser(const std::string&);
547uint64_t getCPUTimeSystem(const std::string&);
591d1bd3
RG
548uint64_t getCPUIOWait(const std::string&);
549uint64_t getCPUSteal(const std::string&);
6907f014 550std::string getMACAddress(const ComboAddress& ca);
74ad42dc 551template<typename T, typename... Args>
552std::unique_ptr<T> make_unique(Args&&... args)
553{
554 return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
555}
1c150f27 556
557
558template<typename T>
559const T& defTer(const T& a, const T& b)
560{
561 return a ? a : b;
562}
3555371a
AT
563
564template<typename P, typename T>
565T valueOrEmpty(const P val) {
566 if (!val) return T{};
567 return T(val);
568}
f5f96ff1 569
88bf3279 570
f5f96ff1 571// I'm not very OCD, but I appreciate loglines like "processing 1 delta", "processing 2 deltas" :-)
88bf3279 572template <typename Integer>
573const char* addS(Integer siz, typename std::enable_if<std::is_integral<Integer>::value>::type*P=0)
f5f96ff1 574{
f5f96ff1 575 if(!siz || siz > 1)
576 return "s";
577 else return "";
578}
88bf3279 579
580template<typename C>
581const char* addS(const C& c, typename std::enable_if<std::is_class<C>::value>::type*P=0)
582{
583 return addS(c.size());
584}
585
2ac8ae89 586template<typename C>
587const typename C::value_type::second_type* rplookup(const C& c, const typename C::value_type::first_type& key)
588{
589 auto fnd = c.find(key);
590 if(fnd == c.end())
591 return 0;
592 return &fnd->second;
593}
594
3fcaeeac 595double DiffTime(const struct timespec& first, const struct timespec& second);
596double DiffTime(const struct timeval& first, const struct timeval& second);
ffb07158 597uid_t strToUID(const string &str);
598gid_t strToGID(const string &str);
a5c4e4a6
AT
599
600unsigned int pdns_stou(const std::string& str, size_t * idx = 0, int base = 10);
60a1c204 601
8fd25133
RG
602bool isSettingThreadCPUAffinitySupported();
603int mapThreadToCPUList(pthread_t tid, const std::set<int>& cpus);
5d4e1ef8
RG
604
605std::vector<ComboAddress> getResolvers(const std::string& resolvConfPath);
ef3ee606
RG
606
607DNSName reverseNameFromIP(const ComboAddress& ip);