]>
Commit | Line | Data |
---|---|---|
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 |
2a9094ef | 23 | #include <errno.h> |
61b26744 | 24 | #include <inttypes.h> |
8b3cfcd3 | 25 | #include <cstring> |
f9822705 | 26 | #include <cstdio> |
3ee84c3f | 27 | #include <regex.h> |
58044407 | 28 | #include <limits.h> |
88bf3279 | 29 | #include <type_traits> |
ec6480f3 | 30 | #include <boost/algorithm/string.hpp> |
f0db590d BH |
31 | #include <boost/multi_index_container.hpp> |
32 | #include <boost/multi_index/ordered_index.hpp> | |
33 | #include <boost/tuple/tuple_comparison.hpp> | |
34 | #include <boost/multi_index/key_extractors.hpp> | |
35 | #include <boost/multi_index/sequenced_index.hpp> | |
d190894c | 36 | |
f0db590d | 37 | using namespace ::boost::multi_index; |
12c86877 | 38 | |
e67e250f | 39 | #include "dns.hh" |
ac0995bb | 40 | #include <atomic> |
76473b92 KM |
41 | #include <sys/time.h> |
42 | #include <sys/types.h> | |
43 | #include <sys/socket.h> | |
44 | #include <time.h> | |
45 | #include <syslog.h> | |
3de83124 | 46 | #include <deque> |
a640a9d4 | 47 | #include <stdexcept> |
12c86877 BH |
48 | #include <string> |
49 | #include <ctype.h> | |
e67e250f BH |
50 | #include <vector> |
51 | ||
10f4eea8 | 52 | #include "namespaces.hh" |
d72aaada KM |
53 | #include "dnsname.hh" |
54 | ||
bcb5b94e | 55 | typedef enum { TSIG_MD5, TSIG_SHA1, TSIG_SHA224, TSIG_SHA256, TSIG_SHA384, TSIG_SHA512, TSIG_GSS } TSIGHashEnum; |
da15912b | 56 | |
cc3afe25 | 57 | string nowTime(); |
1d329048 | 58 | const string unquotify(const string &item); |
12c86877 | 59 | string humanDuration(time_t passed); |
f2c11a48 | 60 | bool stripDomainSuffix(string *qname, const string &domain); |
12c86877 BH |
61 | void stripLine(string &line); |
62 | string getHostname(); | |
63 | string urlEncode(const string &text); | |
a7d50153 | 64 | int waitForData(int fd, int seconds, int useconds=0); |
f4ff5929 | 65 | int waitFor2Data(int fd1, int fd2, int seconds, int useconds, int* fd); |
d529011f | 66 | int waitForMultiData(const set<int>& fds, const int seconds, const int useconds, int* fd); |
51959320 | 67 | int waitForRWData(int fd, bool waitForRead, int seconds, int useconds, bool* error=nullptr, bool* disconnected=nullptr); |
092f210a BH |
68 | uint16_t getShort(const unsigned char *p); |
69 | uint16_t getShort(const char *p); | |
70 | uint32_t getLong(const unsigned char *p); | |
71 | uint32_t getLong(const char *p); | |
21a3792f KM |
72 | bool getTSIGHashEnum(const DNSName& algoName, TSIGHashEnum& algoEnum); |
73 | DNSName getTSIGAlgoName(TSIGHashEnum& algoEnum); | |
58044407 | 74 | |
f8499e52 | 75 | int logFacilityToLOG(unsigned int facility); |
bbce5bf0 | 76 | |
12c86877 BH |
77 | struct ServiceTuple |
78 | { | |
79 | string host; | |
092f210a | 80 | uint16_t port; |
12c86877 BH |
81 | }; |
82 | void parseService(const string &descr, ServiceTuple &st); | |
83 | ||
84 | template <typename Container> | |
85 | void | |
86 | stringtok (Container &container, string const &in, | |
87 | const char * const delimiters = " \t\n") | |
88 | { | |
89 | const string::size_type len = in.length(); | |
90 | string::size_type i = 0; | |
3ddb9247 | 91 | |
12c86877 BH |
92 | while (i<len) { |
93 | // eat leading whitespace | |
94 | i = in.find_first_not_of (delimiters, i); | |
95 | if (i == string::npos) | |
96 | return; // nothing left but white space | |
3ddb9247 | 97 | |
12c86877 BH |
98 | // find the end of the token |
99 | string::size_type j = in.find_first_of (delimiters, i); | |
3ddb9247 | 100 | |
12c86877 BH |
101 | // push token |
102 | if (j == string::npos) { | |
103 | container.push_back (in.substr(i)); | |
104 | return; | |
105 | } else | |
106 | container.push_back (in.substr(i, j-i)); | |
3ddb9247 | 107 | |
12c86877 BH |
108 | // set up for next loop |
109 | i = j + 1; | |
110 | } | |
111 | } | |
8c3149f2 | 112 | |
f7a69a4c RA |
113 | template<typename T> bool rfc1982LessThan(T a, T b) |
114 | { | |
115 | return ((signed)(a - b)) < 0; | |
116 | } | |
117 | ||
0ab3fdc6 | 118 | // fills container with ranges, so {posbegin,posend} |
8c3149f2 BH |
119 | template <typename Container> |
120 | void | |
121 | vstringtok (Container &container, string const &in, | |
122 | const char * const delimiters = " \t\n") | |
123 | { | |
124 | const string::size_type len = in.length(); | |
125 | string::size_type i = 0; | |
3ddb9247 | 126 | |
8c3149f2 BH |
127 | while (i<len) { |
128 | // eat leading whitespace | |
129 | i = in.find_first_not_of (delimiters, i); | |
130 | if (i == string::npos) | |
131 | return; // nothing left but white space | |
3ddb9247 | 132 | |
8c3149f2 BH |
133 | // find the end of the token |
134 | string::size_type j = in.find_first_of (delimiters, i); | |
3ddb9247 | 135 | |
8c3149f2 BH |
136 | // push token |
137 | if (j == string::npos) { | |
138 | container.push_back (make_pair(i, len)); | |
139 | return; | |
140 | } else | |
141 | container.push_back (make_pair(i, j)); | |
3ddb9247 | 142 | |
8c3149f2 BH |
143 | // set up for next loop |
144 | i = j + 1; | |
145 | } | |
146 | } | |
147 | ||
a683e8bd RG |
148 | size_t writen2(int fd, const void *buf, size_t count); |
149 | inline size_t writen2(int fd, const std::string &s) { return writen2(fd, s.data(), s.size()); } | |
150 | size_t readn2(int fd, void* buffer, size_t len); | |
9396d955 | 151 | size_t readn2WithTimeout(int fd, void* buffer, size_t len, int idleTimeout, int totalTimeout=0); |
a683e8bd | 152 | size_t writen2WithTimeout(int fd, const void * buffer, size_t len, int timeout); |
040712e0 | 153 | |
c3d9d009 | 154 | const string toLower(const string &upper); |
b0d4fb45 | 155 | const string toLowerCanonic(const string &upper); |
092f210a | 156 | bool IpToU32(const string &str, uint32_t *ip); |
5730f30c | 157 | string U32ToIP(uint32_t); |
12c86877 | 158 | string stringerror(); |
d3b4137e | 159 | string netstringerror(); |
12c86877 | 160 | string itoa(int i); |
22c9c86a | 161 | string uitoa(unsigned int i); |
d88babea | 162 | string bitFlip(const string &str); |
12c86877 BH |
163 | |
164 | void dropPrivs(int uid, int gid); | |
165 | int makeGidNumeric(const string &group); | |
166 | int makeUidNumeric(const string &user); | |
167 | void cleanSlashes(string &str); | |
168 | ||
c6d04bdc | 169 | #if defined(_POSIX_THREAD_CPUTIME) && defined(CLOCK_THREAD_CPUTIME_ID) |
df13e61d | 170 | /** CPUTime measurements */ |
171 | class CPUTime | |
172 | { | |
173 | public: | |
174 | void start() | |
175 | { | |
176 | clock_gettime(CLOCK_THREAD_CPUTIME_ID, &d_start); | |
177 | } | |
178 | uint64_t ndiff() | |
179 | { | |
180 | struct timespec now; | |
181 | clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now); | |
182 | return 1000000000ULL*(now.tv_sec - d_start.tv_sec) + (now.tv_nsec - d_start.tv_nsec); | |
183 | } | |
184 | private: | |
185 | struct timespec d_start; | |
186 | }; | |
3ddb9247 | 187 | #endif |
df13e61d | 188 | |
3ddb9247 | 189 | /** The DTime class can be used for timing statistics with microsecond resolution. |
12c86877 | 190 | On 32 bits systems this means that 2147 seconds is the longest time that can be measured. */ |
3ddb9247 | 191 | class DTime |
12c86877 BH |
192 | { |
193 | public: | |
eefd15f9 | 194 | DTime(); //!< Does not set the timer for you! Saves lots of gettimeofday() calls |
12c86877 BH |
195 | DTime(const DTime &dt); |
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 |
208 | private: |
209 | struct timeval d_set; | |
210 | }; | |
85db02c5 | 211 | |
12c86877 BH |
212 | inline void DTime::set() |
213 | { | |
15ad1a99 | 214 | gettimeofday(&d_set,0); |
12c86877 BH |
215 | } |
216 | ||
217 | inline int DTime::udiff() | |
62c3a7b8 BH |
218 | { |
219 | int res=udiffNoReset(); | |
15ad1a99 | 220 | gettimeofday(&d_set,0); |
62c3a7b8 BH |
221 | return res; |
222 | } | |
223 | ||
224 | inline 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 | 233 | inline 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 |
246 | inline 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: |
267 | inline 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 |
276 | inline 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 |
284 | inline void unixDie(const string &why) |
285 | { | |
286 | throw runtime_error(why+": "+strerror(errno)); | |
287 | } | |
288 | ||
2db9c30e | 289 | string makeHexDump(const string& str); |
4950b140 | 290 | struct DNSRecord; |
c77eccee | 291 | struct DNSZoneRecord; |
4950b140 | 292 | void shuffle(vector<DNSRecord>& rrs); |
d190894c | 293 | void shuffle(vector<DNSZoneRecord>& rrs); |
90ba52e0 | 294 | |
e325f20c | 295 | void orderAndShuffle(vector<DNSRecord>& rrs); |
88358c9b BH |
296 | |
297 | void normalizeTV(struct timeval& tv); | |
298 | const struct timeval operator+(const struct timeval& lhs, const struct timeval& rhs); | |
299 | const struct timeval operator-(const struct timeval& lhs, const struct timeval& rhs); | |
300 | inline float makeFloat(const struct timeval& tv) | |
301 | { | |
705f31ae | 302 | return tv.tv_sec + tv.tv_usec/1000000.0f; |
88358c9b | 303 | } |
5b0ddd18 | 304 | |
3ddb9247 | 305 | inline bool operator<(const struct timeval& lhs, const struct timeval& rhs) |
5b0ddd18 BH |
306 | { |
307 | return make_pair(lhs.tv_sec, lhs.tv_usec) < make_pair(rhs.tv_sec, rhs.tv_usec); | |
308 | } | |
309 | ||
80a216c9 | 310 | inline bool operator<(const struct timespec& lhs, const struct timespec& rhs) |
311 | { | |
312 | return tie(lhs.tv_sec, lhs.tv_nsec) < tie(rhs.tv_sec, rhs.tv_nsec); | |
313 | } | |
314 | ||
315 | ||
ec6480f3 | 316 | inline bool pdns_ilexicographical_compare(const std::string& a, const std::string& b) __attribute__((pure)); |
8fb5b29a | 317 | inline bool pdns_ilexicographical_compare(const std::string& a, const std::string& b) |
7738a23f | 318 | { |
97a24230 | 319 | const unsigned char *aPtr = (const unsigned char*)a.c_str(), *bPtr = (const unsigned char*)b.c_str(); |
7fd7a590 | 320 | const unsigned char *aEptr = aPtr + a.length(), *bEptr = bPtr + b.length(); |
321 | while(aPtr != aEptr && bPtr != bEptr) { | |
8fb5b29a KM |
322 | if ((*aPtr != *bPtr) && (dns_tolower(*aPtr) - dns_tolower(*bPtr))) |
323 | return (dns_tolower(*aPtr) - dns_tolower(*bPtr)) < 0; | |
324 | aPtr++; | |
325 | bPtr++; | |
7738a23f | 326 | } |
7fd7a590 | 327 | if(aPtr == aEptr && bPtr == bEptr) // strings are equal (in length) |
8fb5b29a | 328 | return false; |
7fd7a590 | 329 | return aPtr == aEptr; // true if first string was shorter |
ec6480f3 | 330 | } |
eff65ff8 | 331 | |
ec6480f3 | 332 | inline bool pdns_iequals(const std::string& a, const std::string& b) __attribute__((pure)); |
8fb5b29a | 333 | inline bool pdns_iequals(const std::string& a, const std::string& b) |
ec6480f3 | 334 | { |
8fb5b29a KM |
335 | if (a.length() != b.length()) |
336 | return false; | |
337 | ||
ec6480f3 | 338 | const char *aPtr = a.c_str(), *bPtr = b.c_str(); |
b10795de | 339 | const char *aEptr = aPtr + a.length(); |
340 | while(aPtr != aEptr) { | |
8fb5b29a KM |
341 | if((*aPtr != *bPtr) && (dns_tolower(*aPtr) != dns_tolower(*bPtr))) |
342 | return false; | |
343 | aPtr++; | |
344 | bPtr++; | |
eff65ff8 | 345 | } |
8fb5b29a | 346 | return true; |
ec6480f3 BH |
347 | } |
348 | ||
57cb86d8 CH |
349 | inline bool pdns_iequals_ch(const char a, const char b) __attribute__((pure)); |
350 | inline bool pdns_iequals_ch(const char a, const char b) | |
351 | { | |
352 | if ((a != b) && (dns_tolower(a) != dns_tolower(b))) | |
353 | return false; | |
354 | ||
355 | return true; | |
356 | } | |
357 | ||
1566533a | 358 | |
00c6f2b9 RG |
359 | typedef unsigned long AtomicCounterInner; |
360 | typedef std::atomic<AtomicCounterInner> AtomicCounter ; | |
1bc9e6bd | 361 | |
ac0995bb | 362 | // FIXME400 this should probably go? |
3ddb9247 | 363 | struct CIStringCompare: public std::binary_function<string, string, bool> |
ec6480f3 BH |
364 | { |
365 | bool operator()(const string& a, const string& b) const | |
eff65ff8 | 366 | { |
ec6480f3 | 367 | return pdns_ilexicographical_compare(a, b); |
eff65ff8 | 368 | } |
7738a23f | 369 | }; |
eff65ff8 | 370 | |
2aa1b703 AT |
371 | struct CIStringComparePOSIX |
372 | { | |
373 | bool operator() (const std::string& lhs, const std::string& rhs) | |
374 | { | |
375 | std::string::const_iterator a,b; | |
376 | const std::locale &loc = std::locale("POSIX"); | |
377 | a=lhs.begin();b=rhs.begin(); | |
378 | while(a!=lhs.end()) { | |
379 | if (b==rhs.end() || std::tolower(*b,loc)<std::tolower(*a,loc)) return false; | |
380 | else if (std::tolower(*a,loc)<std::tolower(*b,loc)) return true; | |
4b5da564 | 381 | ++a;++b; |
2aa1b703 AT |
382 | } |
383 | return (b!=rhs.end()); | |
384 | } | |
385 | }; | |
386 | ||
3ddb9247 | 387 | struct CIStringPairCompare: public std::binary_function<pair<string, uint16_t>, pair<string,uint16_t>, bool> |
21f0f88b BH |
388 | { |
389 | bool operator()(const pair<string, uint16_t>& a, const pair<string, uint16_t>& b) const | |
390 | { | |
391 | if(pdns_ilexicographical_compare(a.first, b.first)) | |
392 | return true; | |
393 | if(pdns_ilexicographical_compare(b.first, a.first)) | |
394 | return false; | |
395 | return a.second < b.second; | |
396 | } | |
397 | }; | |
398 | ||
57cb86d8 CH |
399 | inline size_t pdns_ci_find(const string& haystack, const string& needle) |
400 | { | |
401 | string::const_iterator it = std::search(haystack.begin(), haystack.end(), | |
402 | needle.begin(), needle.end(), pdns_iequals_ch); | |
403 | if (it == haystack.end()) { | |
404 | // not found | |
405 | return string::npos; | |
406 | } else { | |
407 | return it - haystack.begin(); | |
408 | } | |
409 | } | |
21f0f88b | 410 | |
50c79a76 | 411 | pair<string, string> splitField(const string& inp, char sepa); |
26cd1b3f | 412 | |
e720f311 | 413 | inline bool isCanonical(const string& qname) |
26cd1b3f | 414 | { |
e720f311 | 415 | if(qname.empty()) |
26cd1b3f | 416 | return false; |
e720f311 | 417 | return qname[qname.size()-1]=='.'; |
26cd1b3f BH |
418 | } |
419 | ||
e720f311 | 420 | inline DNSName toCanonic(const DNSName& zone, const string& qname) |
675fa24c | 421 | { |
e720f311 | 422 | if(qname.size()==1 && qname[0]=='@') |
8171ab83 | 423 | return zone; |
e720f311 | 424 | if(isCanonical(qname)) |
8171ab83 | 425 | return DNSName(qname); |
e720f311 | 426 | return DNSName(qname) += zone; |
26cd1b3f | 427 | } |
da042e6e BH |
428 | |
429 | string stripDot(const string& dom); | |
561434a6 | 430 | |
f71bc087 | 431 | int makeIPv6sockaddr(const std::string& addr, struct sockaddr_in6* ret); |
76cb4593 CH |
432 | int makeIPv4sockaddr(const std::string& str, struct sockaddr_in* ret); |
433 | int makeUNsockaddr(const std::string& path, struct sockaddr_un* ret); | |
834942f1 | 434 | bool stringfgets(FILE* fp, std::string& line); |
f0db590d BH |
435 | |
436 | template<typename Index> | |
437 | std::pair<typename Index::iterator,bool> | |
438 | replacing_insert(Index& i,const typename Index::value_type& x) | |
439 | { | |
440 | std::pair<typename Index::iterator,bool> res=i.insert(x); | |
441 | if(!res.second)res.second=i.replace(res.first,x); | |
442 | return res; | |
443 | } | |
444 | ||
3ee84c3f BH |
445 | /** very small regex wrapper */ |
446 | class Regex | |
447 | { | |
448 | public: | |
449 | /** constructor that accepts the expression to regex */ | |
450 | Regex(const string &expr); | |
3ddb9247 | 451 | |
3ee84c3f BH |
452 | ~Regex() |
453 | { | |
454 | regfree(&d_preg); | |
455 | } | |
456 | /** call this to find out if 'line' matches your expression */ | |
6eecd4c2 | 457 | bool match(const string &line) const |
3ee84c3f BH |
458 | { |
459 | return regexec(&d_preg,line.c_str(),0,0,0)==0; | |
460 | } | |
6eecd4c2 | 461 | bool match(const DNSName& name) const |
60ee1829 AT |
462 | { |
463 | return match(name.toStringNoDot()); | |
464 | } | |
465 | ||
3ee84c3f BH |
466 | private: |
467 | regex_t d_preg; | |
468 | }; | |
469 | ||
ac84f00c AT |
470 | class SimpleMatch |
471 | { | |
472 | public: | |
8a70e507 | 473 | SimpleMatch(const string &mask, bool caseFold = false): d_mask(mask), d_fold(caseFold) |
ac84f00c | 474 | { |
ac84f00c AT |
475 | } |
476 | ||
477 | bool match(string::const_iterator mi, string::const_iterator mend, string::const_iterator vi, string::const_iterator vend) | |
478 | { | |
4b5da564 | 479 | for(;;++mi) { |
ac84f00c AT |
480 | if (mi == mend) { |
481 | return vi == vend; | |
482 | } else if (*mi == '?') { | |
483 | if (vi == vend) return false; | |
4b5da564 | 484 | ++vi; |
ac84f00c | 485 | } else if (*mi == '*') { |
4b5da564 | 486 | while(*mi == '*') ++mi; |
ac84f00c AT |
487 | if (mi == d_mask.end()) return true; |
488 | while(vi != vend) { | |
489 | if (match(mi,mend,vi,vend)) return true; | |
4b5da564 | 490 | ++vi; |
ac84f00c AT |
491 | } |
492 | return false; | |
493 | } else { | |
494 | if ((mi == mend && vi != vend)|| | |
495 | (mi != mend && vi == vend)) return false; | |
496 | if (d_fold) { | |
497 | if (dns_tolower(*mi) != dns_tolower(*vi)) return false; | |
498 | } else { | |
499 | if (*mi != *vi) return false; | |
500 | } | |
4b5da564 | 501 | ++vi; |
ac84f00c AT |
502 | } |
503 | } | |
504 | } | |
505 | ||
506 | bool match(const string& value) { | |
507 | return match(d_mask.begin(), d_mask.end(), value.begin(), value.end()); | |
508 | } | |
509 | ||
510 | bool match(const DNSName& name) { | |
511 | return match(name.toStringNoDot()); | |
512 | } | |
513 | ||
514 | private: | |
515 | string d_mask; | |
516 | bool d_fold; | |
517 | }; | |
518 | ||
65d8e171 | 519 | union ComboAddress; |
fbe2a2e0 RG |
520 | /* itfIndex is an interface index, as returned by if_nametoindex(). 0 means default. */ |
521 | void addCMsgSrcAddr(struct msghdr* msgh, void* cmsgbuf, const ComboAddress* source, int itfIndex); | |
3a8a4d68 | 522 | |
523 | unsigned int getFilenumLimit(bool hardOrSoft=0); | |
524 | void setFilenumLimit(unsigned int lim); | |
4e9a20e6 | 525 | bool readFileIfThere(const char* fname, std::string* line); |
5c57a75a | 526 | uint32_t burtle(const unsigned char* k, uint32_t length, uint32_t init); |
915b0c39 | 527 | bool setSocketTimestamps(int fd); |
15ad1a99 | 528 | |
529 | //! Sets the socket into blocking mode. | |
530 | bool setBlocking( int sock ); | |
531 | ||
532 | //! Sets the socket into non-blocking mode. | |
533 | bool setNonBlocking( int sock ); | |
883a30a7 | 534 | bool setTCPNoDelay(int sock); |
bf676f2f | 535 | bool setReuseAddr(int sock); |
18861f97 | 536 | bool isNonBlocking(int sock); |
29bb743c | 537 | bool setReceiveSocketErrors(int sock, int af); |
3897b9e1 | 538 | int closesocket(int fd); |
539 | bool setCloseOnExec(int sock); | |
74ad42dc | 540 | |
ee271fc4 RG |
541 | size_t getPipeBufferSize(int fd); |
542 | bool setPipeBufferSize(int fd, size_t size); | |
543 | ||
544 | uint64_t udpErrorStats(const std::string& str); | |
a1a787dc | 545 | uint64_t getRealMemoryUsage(const std::string&); |
330dcb5c | 546 | uint64_t getSpecialMemoryUsage(const std::string&); |
a9b6db56 | 547 | uint64_t getOpenFileDescriptors(const std::string&); |
4f99f3d3 RG |
548 | uint64_t getCPUTimeUser(const std::string&); |
549 | uint64_t getCPUTimeSystem(const std::string&); | |
6907f014 | 550 | std::string getMACAddress(const ComboAddress& ca); |
74ad42dc | 551 | template<typename T, typename... Args> |
552 | std::unique_ptr<T> make_unique(Args&&... args) | |
553 | { | |
554 | return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); | |
555 | } | |
1c150f27 | 556 | |
557 | ||
558 | template<typename T> | |
559 | const T& defTer(const T& a, const T& b) | |
560 | { | |
561 | return a ? a : b; | |
562 | } | |
3555371a AT |
563 | |
564 | template<typename P, typename T> | |
565 | T 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 | 572 | template <typename Integer> |
573 | const 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 | |
580 | template<typename C> | |
581 | const 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 | 586 | template<typename C> |
587 | const 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 | 595 | double DiffTime(const struct timespec& first, const struct timespec& second); |
596 | double DiffTime(const struct timeval& first, const struct timeval& second); | |
ffb07158 | 597 | uid_t strToUID(const string &str); |
598 | gid_t strToGID(const string &str); | |
a5c4e4a6 AT |
599 | |
600 | unsigned int pdns_stou(const std::string& str, size_t * idx = 0, int base = 10); | |
60a1c204 | 601 | |
8fd25133 RG |
602 | bool isSettingThreadCPUAffinitySupported(); |
603 | int mapThreadToCPUList(pthread_t tid, const std::set<int>& cpus); | |
5d4e1ef8 RG |
604 | |
605 | std::vector<ComboAddress> getResolvers(const std::string& resolvConfPath); |