2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
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.
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.
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.
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.
29 #include <type_traits>
30 #include <boost/algorithm/string.hpp>
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>
37 using namespace ::boost::multi_index;
42 #include <sys/types.h>
43 #include <sys/socket.h>
52 #include "namespaces.hh"
55 typedef enum { TSIG_MD5, TSIG_SHA1, TSIG_SHA224, TSIG_SHA256, TSIG_SHA384, TSIG_SHA512, TSIG_GSS } TSIGHashEnum;
58 const string unquotify(const string &item);
59 string humanDuration(time_t passed);
60 bool stripDomainSuffix(string *qname, const string &domain);
61 void stripLine(string &line);
63 string urlEncode(const string &text);
64 int waitForData(int fd, int seconds, int useconds=0);
65 int waitFor2Data(int fd1, int fd2, int seconds, int useconds, int* fd);
66 int waitForRWData(int fd, bool waitForRead, int seconds, int useconds, bool* error=nullptr, bool* disconnected=nullptr);
67 uint16_t getShort(const unsigned char *p);
68 uint16_t getShort(const char *p);
69 uint32_t getLong(const unsigned char *p);
70 uint32_t getLong(const char *p);
71 bool getTSIGHashEnum(const DNSName& algoName, TSIGHashEnum& algoEnum);
72 DNSName getTSIGAlgoName(TSIGHashEnum& algoEnum);
74 int logFacilityToLOG(unsigned int facility);
81 void parseService(const string &descr, ServiceTuple &st);
83 template <typename Container>
85 stringtok (Container &container, string const &in,
86 const char * const delimiters = " \t\n")
88 const string::size_type len = in.length();
89 string::size_type i = 0;
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
97 // find the end of the token
98 string::size_type j = in.find_first_of (delimiters, i);
101 if (j == string::npos) {
102 container.push_back (in.substr(i));
105 container.push_back (in.substr(i, j-i));
107 // set up for next loop
112 template<typename T> bool rfc1982LessThan(T a, T b)
114 return ((signed)(a - b)) < 0;
117 // fills container with ranges, so {posbegin,posend}
118 template <typename Container>
120 vstringtok (Container &container, string const &in,
121 const char * const delimiters = " \t\n")
123 const string::size_type len = in.length();
124 string::size_type i = 0;
127 // eat leading whitespace
128 i = in.find_first_not_of (delimiters, i);
129 if (i == string::npos)
130 return; // nothing left but white space
132 // find the end of the token
133 string::size_type j = in.find_first_of (delimiters, i);
136 if (j == string::npos) {
137 container.push_back (make_pair(i, len));
140 container.push_back (make_pair(i, j));
142 // set up for next loop
147 size_t writen2(int fd, const void *buf, size_t count);
148 inline size_t writen2(int fd, const std::string &s) { return writen2(fd, s.data(), s.size()); }
149 size_t readn2(int fd, void* buffer, size_t len);
150 size_t readn2WithTimeout(int fd, void* buffer, size_t len, int idleTimeout, int totalTimeout=0);
151 size_t writen2WithTimeout(int fd, const void * buffer, size_t len, int timeout);
153 const string toLower(const string &upper);
154 const string toLowerCanonic(const string &upper);
155 bool IpToU32(const string &str, uint32_t *ip);
156 string U32ToIP(uint32_t);
157 string stringerror();
158 string netstringerror();
160 string uitoa(unsigned int i);
161 string bitFlip(const string &str);
163 void dropPrivs(int uid, int gid);
164 int makeGidNumeric(const string &group);
165 int makeUidNumeric(const string &user);
166 void cleanSlashes(string &str);
168 #if defined(_POSIX_THREAD_CPUTIME) && defined(CLOCK_THREAD_CPUTIME_ID)
169 /** CPUTime measurements */
175 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &d_start);
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);
184 struct timespec d_start;
188 /** The DTime class can be used for timing statistics with microsecond resolution.
189 On 32 bits systems this means that 2147 seconds is the longest time that can be measured. */
193 DTime(); //!< Does not set the timer for you! Saves lots of gettimeofday() calls
194 DTime(const DTime &dt);
196 inline void set(); //!< Reset the timer
197 inline int udiff(); //!< Return the number of microseconds since the timer was last set.
198 inline int udiffNoReset(); //!< Return the number of microseconds since the timer was last set.
199 void setTimeval(const struct timeval& tv)
203 struct timeval getTimeval()
208 struct timeval d_set;
211 inline void DTime::set()
213 gettimeofday(&d_set,0);
216 inline int DTime::udiff()
218 int res=udiffNoReset();
219 gettimeofday(&d_set,0);
223 inline int DTime::udiffNoReset()
227 gettimeofday(&now,0);
228 int ret=1000000*(now.tv_sec-d_set.tv_sec)+(now.tv_usec-d_set.tv_usec);
232 inline const string toLower(const string &upper)
235 const size_t length = reply.length();
237 for(unsigned int i = 0; i < length; ++i) {
238 c = dns_tolower(upper[i]);
245 inline const string toLowerCanonic(const string &upper)
249 unsigned int i, limit= ( unsigned int ) reply.length();
251 for(i = 0; i < limit ; i++) {
252 c = dns_tolower(upper[i]);
266 inline string toUpper( const string& s )
269 for( unsigned int i = 0; i < s.length(); i++ ) {
270 r[i] = dns_toupper(r[i]);
275 inline double getTime()
278 gettimeofday(&now,0);
280 return now.tv_sec+now.tv_usec/1000000.0;
283 inline void unixDie(const string &why)
285 throw runtime_error(why+": "+strerror(errno));
288 string makeHexDump(const string& str);
290 struct DNSZoneRecord;
291 void shuffle(vector<DNSRecord>& rrs);
292 void shuffle(vector<DNSZoneRecord>& rrs);
294 void orderAndShuffle(vector<DNSRecord>& rrs);
296 void normalizeTV(struct timeval& tv);
297 const struct timeval operator+(const struct timeval& lhs, const struct timeval& rhs);
298 const struct timeval operator-(const struct timeval& lhs, const struct timeval& rhs);
299 inline float makeFloat(const struct timeval& tv)
301 return tv.tv_sec + tv.tv_usec/1000000.0f;
304 inline bool operator<(const struct timeval& lhs, const struct timeval& rhs)
306 return make_pair(lhs.tv_sec, lhs.tv_usec) < make_pair(rhs.tv_sec, rhs.tv_usec);
309 inline bool operator<(const struct timespec& lhs, const struct timespec& rhs)
311 return tie(lhs.tv_sec, lhs.tv_nsec) < tie(rhs.tv_sec, rhs.tv_nsec);
315 inline bool pdns_ilexicographical_compare(const std::string& a, const std::string& b) __attribute__((pure));
316 inline bool pdns_ilexicographical_compare(const std::string& a, const std::string& b)
318 const unsigned char *aPtr = (const unsigned char*)a.c_str(), *bPtr = (const unsigned char*)b.c_str();
319 const unsigned char *aEptr = aPtr + a.length(), *bEptr = bPtr + b.length();
320 while(aPtr != aEptr && bPtr != bEptr) {
321 if ((*aPtr != *bPtr) && (dns_tolower(*aPtr) - dns_tolower(*bPtr)))
322 return (dns_tolower(*aPtr) - dns_tolower(*bPtr)) < 0;
326 if(aPtr == aEptr && bPtr == bEptr) // strings are equal (in length)
328 return aPtr == aEptr; // true if first string was shorter
331 inline bool pdns_iequals(const std::string& a, const std::string& b) __attribute__((pure));
332 inline bool pdns_iequals(const std::string& a, const std::string& b)
334 if (a.length() != b.length())
337 const char *aPtr = a.c_str(), *bPtr = b.c_str();
338 const char *aEptr = aPtr + a.length();
339 while(aPtr != aEptr) {
340 if((*aPtr != *bPtr) && (dns_tolower(*aPtr) != dns_tolower(*bPtr)))
348 inline bool pdns_iequals_ch(const char a, const char b) __attribute__((pure));
349 inline bool pdns_iequals_ch(const char a, const char b)
351 if ((a != b) && (dns_tolower(a) != dns_tolower(b)))
358 typedef unsigned long AtomicCounterInner;
359 typedef std::atomic<AtomicCounterInner> AtomicCounter ;
361 // FIXME400 this should probably go?
362 struct CIStringCompare: public std::binary_function<string, string, bool>
364 bool operator()(const string& a, const string& b) const
366 return pdns_ilexicographical_compare(a, b);
370 struct CIStringComparePOSIX
372 bool operator() (const std::string& lhs, const std::string& rhs)
374 std::string::const_iterator a,b;
375 const std::locale &loc = std::locale("POSIX");
376 a=lhs.begin();b=rhs.begin();
377 while(a!=lhs.end()) {
378 if (b==rhs.end() || std::tolower(*b,loc)<std::tolower(*a,loc)) return false;
379 else if (std::tolower(*a,loc)<std::tolower(*b,loc)) return true;
382 return (b!=rhs.end());
386 struct CIStringPairCompare: public std::binary_function<pair<string, uint16_t>, pair<string,uint16_t>, bool>
388 bool operator()(const pair<string, uint16_t>& a, const pair<string, uint16_t>& b) const
390 if(pdns_ilexicographical_compare(a.first, b.first))
392 if(pdns_ilexicographical_compare(b.first, a.first))
394 return a.second < b.second;
398 inline size_t pdns_ci_find(const string& haystack, const string& needle)
400 string::const_iterator it = std::search(haystack.begin(), haystack.end(),
401 needle.begin(), needle.end(), pdns_iequals_ch);
402 if (it == haystack.end()) {
406 return it - haystack.begin();
410 pair<string, string> splitField(const string& inp, char sepa);
412 inline bool isCanonical(const string& qname)
416 return qname[qname.size()-1]=='.';
419 inline DNSName toCanonic(const DNSName& zone, const string& qname)
421 if(qname.size()==1 && qname[0]=='@')
423 if(isCanonical(qname))
424 return DNSName(qname);
425 return DNSName(qname) += zone;
428 string stripDot(const string& dom);
430 void seedRandom(const string& source);
431 int makeIPv6sockaddr(const std::string& addr, struct sockaddr_in6* ret);
432 int makeIPv4sockaddr(const std::string& str, struct sockaddr_in* ret);
433 int makeUNsockaddr(const std::string& path, struct sockaddr_un* ret);
434 bool stringfgets(FILE* fp, std::string& line);
436 template<typename Index>
437 std::pair<typename Index::iterator,bool>
438 replacing_insert(Index& i,const typename Index::value_type& x)
440 std::pair<typename Index::iterator,bool> res=i.insert(x);
441 if(!res.second)res.second=i.replace(res.first,x);
445 /** very small regex wrapper */
449 /** constructor that accepts the expression to regex */
450 Regex(const string &expr);
456 /** call this to find out if 'line' matches your expression */
457 bool match(const string &line) const
459 return regexec(&d_preg,line.c_str(),0,0,0)==0;
461 bool match(const DNSName& name) const
463 return match(name.toStringNoDot());
473 SimpleMatch(const string &mask, bool caseFold = false)
476 this->d_fold = caseFold;
479 bool match(string::const_iterator mi, string::const_iterator mend, string::const_iterator vi, string::const_iterator vend)
484 } else if (*mi == '?') {
485 if (vi == vend) return false;
487 } else if (*mi == '*') {
488 while(*mi == '*') mi++;
489 if (mi == d_mask.end()) return true;
491 if (match(mi,mend,vi,vend)) return true;
496 if ((mi == mend && vi != vend)||
497 (mi != mend && vi == vend)) return false;
499 if (dns_tolower(*mi) != dns_tolower(*vi)) return false;
501 if (*mi != *vi) return false;
508 bool match(const string& value) {
509 return match(d_mask.begin(), d_mask.end(), value.begin(), value.end());
512 bool match(const DNSName& name) {
513 return match(name.toStringNoDot());
522 /* itfIndex is an interface index, as returned by if_nametoindex(). 0 means default. */
523 void addCMsgSrcAddr(struct msghdr* msgh, void* cmsgbuf, const ComboAddress* source, int itfIndex);
525 unsigned int getFilenumLimit(bool hardOrSoft=0);
526 void setFilenumLimit(unsigned int lim);
527 bool readFileIfThere(const char* fname, std::string* line);
528 uint32_t burtle(const unsigned char* k, uint32_t length, uint32_t init);
529 bool setSocketTimestamps(int fd);
531 //! Sets the socket into blocking mode.
532 bool setBlocking( int sock );
534 //! Sets the socket into non-blocking mode.
535 bool setNonBlocking( int sock );
536 bool setTCPNoDelay(int sock);
537 bool isNonBlocking(int sock);
538 int closesocket(int fd);
539 bool setCloseOnExec(int sock);
540 uint64_t udpErrorStats(const std::string& str);
542 uint64_t getRealMemoryUsage(const std::string&);
543 uint64_t getOpenFileDescriptors(const std::string&);
544 uint64_t getCPUTimeUser(const std::string&);
545 uint64_t getCPUTimeSystem(const std::string&);
546 std::string getMACAddress(const ComboAddress& ca);
547 template<typename T, typename... Args>
548 std::unique_ptr<T> make_unique(Args&&... args)
550 return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
555 const T& defTer(const T& a, const T& b)
560 template<typename P, typename T>
561 T valueOrEmpty(const P val) {
562 if (!val) return T{};
567 // I'm not very OCD, but I appreciate loglines like "processing 1 delta", "processing 2 deltas" :-)
568 template <typename Integer>
569 const char* addS(Integer siz, typename std::enable_if<std::is_integral<Integer>::value>::type*P=0)
577 const char* addS(const C& c, typename std::enable_if<std::is_class<C>::value>::type*P=0)
579 return addS(c.size());
583 const typename C::value_type::second_type* rplookup(const C& c, const typename C::value_type::first_type& key)
585 auto fnd = c.find(key);
591 double DiffTime(const struct timespec& first, const struct timespec& second);
592 double DiffTime(const struct timeval& first, const struct timeval& second);
593 uid_t strToUID(const string &str);
594 gid_t strToGID(const string &str);
596 unsigned int pdns_stou(const std::string& str, size_t * idx = 0, int base = 10);
598 bool isSettingThreadCPUAffinitySupported();
599 int mapThreadToCPUList(pthread_t tid, const std::set<int>& cpus);