2 PowerDNS Versatile Database Driven Nameserver
3 Copyright (C) 2002-2015 PowerDNS.COM BV
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2
7 as published by the Free Software Foundation
9 Additionally, the license of this program contains a special
10 exception which allows to distribute the program in binary form when
11 it is linked against OpenSSL.
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 St, 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>
36 using namespace ::boost::multi_index;
41 #include <sys/types.h>
42 #include <sys/socket.h>
51 #include "namespaces.hh"
54 typedef enum { TSIG_MD5, TSIG_SHA1, TSIG_SHA224, TSIG_SHA256, TSIG_SHA384, TSIG_SHA512, TSIG_GSS } TSIGHashEnum;
57 const string unquotify(const string &item);
58 string humanDuration(time_t passed);
59 bool stripDomainSuffix(string *qname, const string &domain);
60 void stripLine(string &line);
62 string urlEncode(const string &text);
63 int waitForData(int fd, int seconds, int useconds=0);
64 int waitFor2Data(int fd1, int fd2, int seconds, int useconds, int* fd);
65 int waitForRWData(int fd, bool waitForRead, int seconds, int useconds);
66 uint16_t getShort(const unsigned char *p);
67 uint16_t getShort(const char *p);
68 uint32_t getLong(const unsigned char *p);
69 uint32_t getLong(const char *p);
70 bool getTSIGHashEnum(const DNSName& algoName, TSIGHashEnum& algoEnum);
71 DNSName getTSIGAlgoName(TSIGHashEnum& algoEnum);
73 int logFacilityToLOG(unsigned int facility);
80 void parseService(const string &descr, ServiceTuple &st);
82 template <typename Container>
84 stringtok (Container &container, string const &in,
85 const char * const delimiters = " \t\n")
87 const string::size_type len = in.length();
88 string::size_type i = 0;
91 // eat leading whitespace
92 i = in.find_first_not_of (delimiters, i);
93 if (i == string::npos)
94 return; // nothing left but white space
96 // find the end of the token
97 string::size_type j = in.find_first_of (delimiters, i);
100 if (j == string::npos) {
101 container.push_back (in.substr(i));
104 container.push_back (in.substr(i, j-i));
106 // set up for next loop
111 template<typename T> bool rfc1982LessThan(T a, T b)
113 return ((signed)(a - b)) < 0;
116 // fills container with ranges, so {posbegin,posend}
117 template <typename Container>
119 vstringtok (Container &container, string const &in,
120 const char * const delimiters = " \t\n")
122 const string::size_type len = in.length();
123 string::size_type i = 0;
126 // eat leading whitespace
127 i = in.find_first_not_of (delimiters, i);
128 if (i == string::npos)
129 return; // nothing left but white space
131 // find the end of the token
132 string::size_type j = in.find_first_of (delimiters, i);
135 if (j == string::npos) {
136 container.push_back (make_pair(i, len));
139 container.push_back (make_pair(i, j));
141 // set up for next loop
146 size_t writen2(int fd, const void *buf, size_t count);
147 inline size_t writen2(int fd, const std::string &s) { return writen2(fd, s.data(), s.size()); }
148 size_t readn2(int fd, void* buffer, size_t len);
149 size_t readn2WithTimeout(int fd, void* buffer, size_t len, int timeout);
150 size_t writen2WithTimeout(int fd, const void * buffer, size_t len, int timeout);
152 const string toLower(const string &upper);
153 const string toLowerCanonic(const string &upper);
154 bool IpToU32(const string &str, uint32_t *ip);
155 string U32ToIP(uint32_t);
156 string stringerror();
157 string netstringerror();
159 string uitoa(unsigned int i);
160 string bitFlip(const string &str);
162 void dropPrivs(int uid, int gid);
163 int makeGidNumeric(const string &group);
164 int makeUidNumeric(const string &user);
165 void cleanSlashes(string &str);
167 #if defined(_POSIX_THREAD_CPUTIME) && defined(CLOCK_THREAD_CPUTIME_ID)
168 /** CPUTime measurements */
174 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &d_start);
179 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now);
180 return 1000000000ULL*(now.tv_sec - d_start.tv_sec) + (now.tv_nsec - d_start.tv_nsec);
183 struct timespec d_start;
187 /** The DTime class can be used for timing statistics with microsecond resolution.
188 On 32 bits systems this means that 2147 seconds is the longest time that can be measured. */
192 DTime(); //!< Does not set the timer for you! Saves lots of gettimeofday() calls
193 DTime(const DTime &dt);
195 inline void set(); //!< Reset the timer
196 inline int udiff(); //!< Return the number of microseconds since the timer was last set.
197 inline int udiffNoReset(); //!< Return the number of microseconds since the timer was last set.
198 void setTimeval(const struct timeval& tv)
202 struct timeval getTimeval()
207 struct timeval d_set;
210 inline void DTime::set()
212 gettimeofday(&d_set,0);
215 inline int DTime::udiff()
217 int res=udiffNoReset();
218 gettimeofday(&d_set,0);
222 inline int DTime::udiffNoReset()
226 gettimeofday(&now,0);
227 int ret=1000000*(now.tv_sec-d_set.tv_sec)+(now.tv_usec-d_set.tv_usec);
232 inline bool dns_isspace(char c)
234 return c==' ' || c=='\t' || c=='\r' || c=='\n';
237 inline char dns_tolower(char c)
244 inline char dns_toupper(char c)
251 inline const string toLower(const string &upper)
255 for(unsigned int i = 0; i < reply.length(); i++) {
256 c = dns_tolower(upper[i]);
263 inline const string toLowerCanonic(const string &upper)
267 unsigned int i, limit= ( unsigned int ) reply.length();
269 for(i = 0; i < limit ; i++) {
270 c = dns_tolower(upper[i]);
284 inline string toUpper( const string& s )
287 for( unsigned int i = 0; i < s.length(); i++ ) {
288 r[i] = dns_toupper(r[i]);
293 inline double getTime()
296 gettimeofday(&now,0);
298 return now.tv_sec+now.tv_usec/1000000.0;
301 inline void unixDie(const string &why)
303 throw runtime_error(why+": "+strerror(errno));
306 string makeHexDump(const string& str);
307 void shuffle(vector<DNSRecord>& rrs);
308 void shuffle(vector<DNSResourceRecord>& rrs);
309 void orderAndShuffle(vector<DNSRecord>& rrs);
311 void normalizeTV(struct timeval& tv);
312 const struct timeval operator+(const struct timeval& lhs, const struct timeval& rhs);
313 const struct timeval operator-(const struct timeval& lhs, const struct timeval& rhs);
314 inline float makeFloat(const struct timeval& tv)
316 return tv.tv_sec + tv.tv_usec/1000000.0f;
319 inline bool operator<(const struct timeval& lhs, const struct timeval& rhs)
321 return make_pair(lhs.tv_sec, lhs.tv_usec) < make_pair(rhs.tv_sec, rhs.tv_usec);
324 inline bool operator<(const struct timespec& lhs, const struct timespec& rhs)
326 return tie(lhs.tv_sec, lhs.tv_nsec) < tie(rhs.tv_sec, rhs.tv_nsec);
330 inline bool pdns_ilexicographical_compare(const std::string& a, const std::string& b) __attribute__((pure));
331 inline bool pdns_ilexicographical_compare(const std::string& a, const std::string& b)
333 const unsigned char *aPtr = (const unsigned char*)a.c_str(), *bPtr = (const unsigned char*)b.c_str();
334 const unsigned char *aEptr = aPtr + a.length(), *bEptr = bPtr + b.length();
335 while(aPtr != aEptr && bPtr != bEptr) {
336 if ((*aPtr != *bPtr) && (dns_tolower(*aPtr) - dns_tolower(*bPtr)))
337 return (dns_tolower(*aPtr) - dns_tolower(*bPtr)) < 0;
341 if(aPtr == aEptr && bPtr == bEptr) // strings are equal (in length)
343 return aPtr == aEptr; // true if first string was shorter
346 inline bool pdns_iequals(const std::string& a, const std::string& b) __attribute__((pure));
347 inline bool pdns_iequals(const std::string& a, const std::string& b)
349 if (a.length() != b.length())
352 const char *aPtr = a.c_str(), *bPtr = b.c_str();
353 const char *aEptr = aPtr + a.length();
354 while(aPtr != aEptr) {
355 if((*aPtr != *bPtr) && (dns_tolower(*aPtr) != dns_tolower(*bPtr)))
363 inline bool pdns_iequals_ch(const char a, const char b) __attribute__((pure));
364 inline bool pdns_iequals_ch(const char a, const char b)
366 if ((a != b) && (dns_tolower(a) != dns_tolower(b)))
373 typedef std::atomic<unsigned long> AtomicCounter ;
375 // FIXME400 this should probably go?
376 struct CIStringCompare: public std::binary_function<string, string, bool>
378 bool operator()(const string& a, const string& b) const
380 return pdns_ilexicographical_compare(a, b);
384 struct CIStringComparePOSIX
386 bool operator() (const std::string& lhs, const std::string& rhs)
388 std::string::const_iterator a,b;
389 const std::locale &loc = std::locale("POSIX");
390 a=lhs.begin();b=rhs.begin();
391 while(a!=lhs.end()) {
392 if (b==rhs.end() || std::tolower(*b,loc)<std::tolower(*a,loc)) return false;
393 else if (std::tolower(*a,loc)<std::tolower(*b,loc)) return true;
396 return (b!=rhs.end());
400 struct CIStringPairCompare: public std::binary_function<pair<string, uint16_t>, pair<string,uint16_t>, bool>
402 bool operator()(const pair<string, uint16_t>& a, const pair<string, uint16_t>& b) const
404 if(pdns_ilexicographical_compare(a.first, b.first))
406 if(pdns_ilexicographical_compare(b.first, a.first))
408 return a.second < b.second;
412 inline size_t pdns_ci_find(const string& haystack, const string& needle)
414 string::const_iterator it = std::search(haystack.begin(), haystack.end(),
415 needle.begin(), needle.end(), pdns_iequals_ch);
416 if (it == haystack.end()) {
420 return it - haystack.begin();
424 pair<string, string> splitField(const string& inp, char sepa);
426 inline bool isCanonical(const string& qname)
430 return qname[qname.size()-1]=='.';
433 inline DNSName toCanonic(const DNSName& zone, const string& qname)
435 if(qname.size()==1 && qname[0]=='@')
437 if(isCanonical(qname))
438 return DNSName(qname);
439 return DNSName(qname) += zone;
442 string stripDot(const string& dom);
444 void seedRandom(const string& source);
445 string makeRelative(const std::string& fqdn, const std::string& zone);
446 string labelReverse(const std::string& qname);
447 std::string dotConcat(const std::string& a, const std::string &b);
448 int makeIPv6sockaddr(const std::string& addr, struct sockaddr_in6* ret);
449 int makeIPv4sockaddr(const std::string& str, struct sockaddr_in* ret);
450 int makeUNsockaddr(const std::string& path, struct sockaddr_un* ret);
451 bool stringfgets(FILE* fp, std::string& line);
453 template<typename Index>
454 std::pair<typename Index::iterator,bool>
455 replacing_insert(Index& i,const typename Index::value_type& x)
457 std::pair<typename Index::iterator,bool> res=i.insert(x);
458 if(!res.second)res.second=i.replace(res.first,x);
462 /** very small regex wrapper */
466 /** constructor that accepts the expression to regex */
467 Regex(const string &expr);
473 /** call this to find out if 'line' matches your expression */
474 bool match(const string &line) const
476 return regexec(&d_preg,line.c_str(),0,0,0)==0;
478 bool match(const DNSName& name) const
480 return match(name.toStringNoDot());
490 SimpleMatch(const string &mask, bool caseFold = false)
493 this->d_fold = caseFold;
496 bool match(string::const_iterator mi, string::const_iterator mend, string::const_iterator vi, string::const_iterator vend)
501 } else if (*mi == '?') {
502 if (vi == vend) return false;
504 } else if (*mi == '*') {
505 while(*mi == '*') mi++;
506 if (mi == d_mask.end()) return true;
508 if (match(mi,mend,vi,vend)) return true;
513 if ((mi == mend && vi != vend)||
514 (mi != mend && vi == vend)) return false;
516 if (dns_tolower(*mi) != dns_tolower(*vi)) return false;
518 if (*mi != *vi) return false;
525 bool match(const string& value) {
526 return match(d_mask.begin(), d_mask.end(), value.begin(), value.end());
529 bool match(const DNSName& name) {
530 return match(name.toStringNoDot());
539 /* itfIndex is an interface index, as returned by if_nametoindex(). 0 means default. */
540 void addCMsgSrcAddr(struct msghdr* msgh, void* cmsgbuf, const ComboAddress* source, int itfIndex);
542 unsigned int getFilenumLimit(bool hardOrSoft=0);
543 void setFilenumLimit(unsigned int lim);
544 bool readFileIfThere(const char* fname, std::string* line);
545 uint32_t burtle(const unsigned char* k, uint32_t lengh, uint32_t init);
546 bool setSocketTimestamps(int fd);
548 //! Sets the socket into blocking mode.
549 bool setBlocking( int sock );
551 //! Sets the socket into non-blocking mode.
552 bool setNonBlocking( int sock );
553 bool setTCPNoDelay(int sock);
554 bool isNonBlocking(int sock);
555 int closesocket(int fd);
556 bool setCloseOnExec(int sock);
557 uint64_t udpErrorStats(const std::string& str);
559 uint64_t getRealMemoryUsage(const std::string&);
560 uint64_t getOpenFileDescriptors(const std::string&);
561 uint64_t getCPUTimeUser(const std::string&);
562 uint64_t getCPUTimeSystem(const std::string&);
563 std::string getMACAddress(const ComboAddress& ca);
564 template<typename T, typename... Args>
565 std::unique_ptr<T> make_unique(Args&&... args)
567 return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
572 const T& defTer(const T& a, const T& b)
577 template<typename P, typename T>
578 T valueOrEmpty(const P val) {
579 if (!val) return T{};
584 // I'm not very OCD, but I appreciate loglines like "processing 1 delta", "processing 2 deltas" :-)
585 template <typename Integer>
586 const char* addS(Integer siz, typename std::enable_if<std::is_integral<Integer>::value>::type*P=0)
594 const char* addS(const C& c, typename std::enable_if<std::is_class<C>::value>::type*P=0)
596 return addS(c.size());
600 const typename C::value_type::second_type* rplookup(const C& c, const typename C::value_type::first_type& key)
602 auto fnd = c.find(key);
608 double DiffTime(const struct timespec& first, const struct timespec& second);
609 double DiffTime(const struct timeval& first, const struct timeval& second);
610 uid_t strToUID(const string &str);
611 gid_t strToGID(const string &str);
613 unsigned int pdns_stou(const std::string& str, size_t * idx = 0, int base = 10);