You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

610 lines
17 KiB

  1. /*
  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. */
  22. #pragma once
  23. #include <inttypes.h>
  24. #include <cstring>
  25. #include <cstdio>
  26. #include <regex.h>
  27. #include <limits.h>
  28. #include <type_traits>
  29. #include <boost/algorithm/string.hpp>
  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>
  35. using namespace ::boost::multi_index;
  36. #include "dns.hh"
  37. #include <atomic>
  38. #include <sys/time.h>
  39. #include <sys/types.h>
  40. #include <sys/socket.h>
  41. #include <time.h>
  42. #include <syslog.h>
  43. #include <deque>
  44. #include <stdexcept>
  45. #include <string>
  46. #include <ctype.h>
  47. #include <vector>
  48. #include "namespaces.hh"
  49. #include "dnsname.hh"
  50. typedef enum { TSIG_MD5, TSIG_SHA1, TSIG_SHA224, TSIG_SHA256, TSIG_SHA384, TSIG_SHA512, TSIG_GSS } TSIGHashEnum;
  51. string nowTime();
  52. const string unquotify(const string &item);
  53. string humanDuration(time_t passed);
  54. bool stripDomainSuffix(string *qname, const string &domain);
  55. void stripLine(string &line);
  56. string getHostname();
  57. string urlEncode(const string &text);
  58. int waitForData(int fd, int seconds, int useconds=0);
  59. int waitFor2Data(int fd1, int fd2, int seconds, int useconds, int* fd);
  60. int waitForMultiData(const set<int>& fds, const int seconds, const int useconds, int* fd);
  61. int waitForRWData(int fd, bool waitForRead, int seconds, int useconds, bool* error=nullptr, bool* disconnected=nullptr);
  62. uint16_t getShort(const unsigned char *p);
  63. uint16_t getShort(const char *p);
  64. uint32_t getLong(const unsigned char *p);
  65. uint32_t getLong(const char *p);
  66. bool getTSIGHashEnum(const DNSName& algoName, TSIGHashEnum& algoEnum);
  67. DNSName getTSIGAlgoName(TSIGHashEnum& algoEnum);
  68. int logFacilityToLOG(unsigned int facility);
  69. struct ServiceTuple
  70. {
  71. string host;
  72. uint16_t port;
  73. };
  74. void parseService(const string &descr, ServiceTuple &st);
  75. template <typename Container>
  76. void
  77. stringtok (Container &container, string const &in,
  78. const char * const delimiters = " \t\n")
  79. {
  80. const string::size_type len = in.length();
  81. string::size_type i = 0;
  82. while (i<len) {
  83. // eat leading whitespace
  84. i = in.find_first_not_of (delimiters, i);
  85. if (i == string::npos)
  86. return; // nothing left but white space
  87. // find the end of the token
  88. string::size_type j = in.find_first_of (delimiters, i);
  89. // push token
  90. if (j == string::npos) {
  91. container.push_back (in.substr(i));
  92. return;
  93. } else
  94. container.push_back (in.substr(i, j-i));
  95. // set up for next loop
  96. i = j + 1;
  97. }
  98. }
  99. template<typename T> bool rfc1982LessThan(T a, T b)
  100. {
  101. static_assert(std::is_unsigned<T>::value, "rfc1982LessThan only works for unsigned types");
  102. typedef typename std::make_signed<T>::type signed_t;
  103. return static_cast<signed_t>(a - b) < 0;
  104. }
  105. // fills container with ranges, so {posbegin,posend}
  106. template <typename Container>
  107. void
  108. vstringtok (Container &container, string const &in,
  109. const char * const delimiters = " \t\n")
  110. {
  111. const string::size_type len = in.length();
  112. string::size_type i = 0;
  113. while (i<len) {
  114. // eat leading whitespace
  115. i = in.find_first_not_of (delimiters, i);
  116. if (i == string::npos)
  117. return; // nothing left but white space
  118. // find the end of the token
  119. string::size_type j = in.find_first_of (delimiters, i);
  120. // push token
  121. if (j == string::npos) {
  122. container.push_back (make_pair(i, len));
  123. return;
  124. } else
  125. container.push_back (make_pair(i, j));
  126. // set up for next loop
  127. i = j + 1;
  128. }
  129. }
  130. size_t writen2(int fd, const void *buf, size_t count);
  131. inline size_t writen2(int fd, const std::string &s) { return writen2(fd, s.data(), s.size()); }
  132. size_t readn2(int fd, void* buffer, size_t len);
  133. size_t readn2WithTimeout(int fd, void* buffer, size_t len, int idleTimeout, int totalTimeout=0);
  134. size_t writen2WithTimeout(int fd, const void * buffer, size_t len, int timeout);
  135. const string toLower(const string &upper);
  136. const string toLowerCanonic(const string &upper);
  137. bool IpToU32(const string &str, uint32_t *ip);
  138. string U32ToIP(uint32_t);
  139. string stringerror(int);
  140. string stringerror();
  141. string itoa(int i);
  142. string uitoa(unsigned int i);
  143. string bitFlip(const string &str);
  144. void dropPrivs(int uid, int gid);
  145. void cleanSlashes(string &str);
  146. #if defined(_POSIX_THREAD_CPUTIME) && defined(CLOCK_THREAD_CPUTIME_ID)
  147. /** CPUTime measurements */
  148. class CPUTime
  149. {
  150. public:
  151. void start()
  152. {
  153. clock_gettime(CLOCK_THREAD_CPUTIME_ID, &d_start);
  154. }
  155. uint64_t ndiff()
  156. {
  157. struct timespec now;
  158. clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now);
  159. return 1000000000ULL*(now.tv_sec - d_start.tv_sec) + (now.tv_nsec - d_start.tv_nsec);
  160. }
  161. private:
  162. struct timespec d_start;
  163. };
  164. #endif
  165. /** The DTime class can be used for timing statistics with microsecond resolution.
  166. On 32 bits systems this means that 2147 seconds is the longest time that can be measured. */
  167. class DTime
  168. {
  169. public:
  170. DTime(); //!< Does not set the timer for you! Saves lots of gettimeofday() calls
  171. DTime(const DTime &dt) = default;
  172. DTime & operator=(const DTime &dt) = default;
  173. time_t time();
  174. inline void set(); //!< Reset the timer
  175. inline int udiff(); //!< Return the number of microseconds since the timer was last set.
  176. inline int udiffNoReset(); //!< Return the number of microseconds since the timer was last set.
  177. void setTimeval(const struct timeval& tv)
  178. {
  179. d_set=tv;
  180. }
  181. struct timeval getTimeval()
  182. {
  183. return d_set;
  184. }
  185. private:
  186. struct timeval d_set;
  187. };
  188. inline void DTime::set()
  189. {
  190. gettimeofday(&d_set,0);
  191. }
  192. inline int DTime::udiff()
  193. {
  194. int res=udiffNoReset();
  195. gettimeofday(&d_set,0);
  196. return res;
  197. }
  198. inline int DTime::udiffNoReset()
  199. {
  200. struct timeval now;
  201. gettimeofday(&now,0);
  202. int ret=1000000*(now.tv_sec-d_set.tv_sec)+(now.tv_usec-d_set.tv_usec);
  203. return ret;
  204. }
  205. inline const string toLower(const string &upper)
  206. {
  207. string reply(upper);
  208. const size_t length = reply.length();
  209. char c;
  210. for(unsigned int i = 0; i < length; ++i) {
  211. c = dns_tolower(upper[i]);
  212. if( c != upper[i])
  213. reply[i] = c;
  214. }
  215. return reply;
  216. }
  217. inline const string toLowerCanonic(const string &upper)
  218. {
  219. string reply(upper);
  220. if(!upper.empty()) {
  221. unsigned int i, limit= ( unsigned int ) reply.length();
  222. unsigned char c;
  223. for(i = 0; i < limit ; i++) {
  224. c = dns_tolower(upper[i]);
  225. if(c != upper[i])
  226. reply[i] = c;
  227. }
  228. if(upper[i-1]=='.')
  229. reply.resize(i-1);
  230. }
  231. return reply;
  232. }
  233. // Make s uppercase:
  234. inline string toUpper( const string& s )
  235. {
  236. string r(s);
  237. for( unsigned int i = 0; i < s.length(); i++ ) {
  238. r[i] = dns_toupper(r[i]);
  239. }
  240. return r;
  241. }
  242. inline double getTime()
  243. {
  244. struct timeval now;
  245. gettimeofday(&now,0);
  246. return now.tv_sec+now.tv_usec/1000000.0;
  247. }
  248. inline void unixDie(const string &why)
  249. {
  250. throw runtime_error(why+": "+stringerror());
  251. }
  252. string makeHexDump(const string& str);
  253. void normalizeTV(struct timeval& tv);
  254. const struct timeval operator+(const struct timeval& lhs, const struct timeval& rhs);
  255. const struct timeval operator-(const struct timeval& lhs, const struct timeval& rhs);
  256. inline float makeFloat(const struct timeval& tv)
  257. {
  258. return tv.tv_sec + tv.tv_usec/1000000.0f;
  259. }
  260. inline bool operator<(const struct timeval& lhs, const struct timeval& rhs)
  261. {
  262. return make_pair(lhs.tv_sec, lhs.tv_usec) < make_pair(rhs.tv_sec, rhs.tv_usec);
  263. }
  264. inline bool operator<(const struct timespec& lhs, const struct timespec& rhs)
  265. {
  266. return tie(lhs.tv_sec, lhs.tv_nsec) < tie(rhs.tv_sec, rhs.tv_nsec);
  267. }
  268. inline bool pdns_ilexicographical_compare(const std::string& a, const std::string& b) __attribute__((pure));
  269. inline bool pdns_ilexicographical_compare(const std::string& a, const std::string& b)
  270. {
  271. const unsigned char *aPtr = (const unsigned char*)a.c_str(), *bPtr = (const unsigned char*)b.c_str();
  272. const unsigned char *aEptr = aPtr + a.length(), *bEptr = bPtr + b.length();
  273. while(aPtr != aEptr && bPtr != bEptr) {
  274. if ((*aPtr != *bPtr) && (dns_tolower(*aPtr) - dns_tolower(*bPtr)))
  275. return (dns_tolower(*aPtr) - dns_tolower(*bPtr)) < 0;
  276. aPtr++;
  277. bPtr++;
  278. }
  279. if(aPtr == aEptr && bPtr == bEptr) // strings are equal (in length)
  280. return false;
  281. return aPtr == aEptr; // true if first string was shorter
  282. }
  283. inline bool pdns_iequals(const std::string& a, const std::string& b) __attribute__((pure));
  284. inline bool pdns_iequals(const std::string& a, const std::string& b)
  285. {
  286. if (a.length() != b.length())
  287. return false;
  288. const char *aPtr = a.c_str(), *bPtr = b.c_str();
  289. const char *aEptr = aPtr + a.length();
  290. while(aPtr != aEptr) {
  291. if((*aPtr != *bPtr) && (dns_tolower(*aPtr) != dns_tolower(*bPtr)))
  292. return false;
  293. aPtr++;
  294. bPtr++;
  295. }
  296. return true;
  297. }
  298. inline bool pdns_iequals_ch(const char a, const char b) __attribute__((pure));
  299. inline bool pdns_iequals_ch(const char a, const char b)
  300. {
  301. if ((a != b) && (dns_tolower(a) != dns_tolower(b)))
  302. return false;
  303. return true;
  304. }
  305. typedef unsigned long AtomicCounterInner;
  306. typedef std::atomic<AtomicCounterInner> AtomicCounter ;
  307. // FIXME400 this should probably go?
  308. struct CIStringCompare: public std::binary_function<string, string, bool>
  309. {
  310. bool operator()(const string& a, const string& b) const
  311. {
  312. return pdns_ilexicographical_compare(a, b);
  313. }
  314. };
  315. struct CIStringComparePOSIX
  316. {
  317. bool operator() (const std::string& lhs, const std::string& rhs)
  318. {
  319. std::string::const_iterator a,b;
  320. const std::locale &loc = std::locale("POSIX");
  321. a=lhs.begin();b=rhs.begin();
  322. while(a!=lhs.end()) {
  323. if (b==rhs.end() || std::tolower(*b,loc)<std::tolower(*a,loc)) return false;
  324. else if (std::tolower(*a,loc)<std::tolower(*b,loc)) return true;
  325. ++a;++b;
  326. }
  327. return (b!=rhs.end());
  328. }
  329. };
  330. struct CIStringPairCompare: public std::binary_function<pair<string, uint16_t>, pair<string,uint16_t>, bool>
  331. {
  332. bool operator()(const pair<string, uint16_t>& a, const pair<string, uint16_t>& b) const
  333. {
  334. if(pdns_ilexicographical_compare(a.first, b.first))
  335. return true;
  336. if(pdns_ilexicographical_compare(b.first, a.first))
  337. return false;
  338. return a.second < b.second;
  339. }
  340. };
  341. inline size_t pdns_ci_find(const string& haystack, const string& needle)
  342. {
  343. string::const_iterator it = std::search(haystack.begin(), haystack.end(),
  344. needle.begin(), needle.end(), pdns_iequals_ch);
  345. if (it == haystack.end()) {
  346. // not found
  347. return string::npos;
  348. } else {
  349. return it - haystack.begin();
  350. }
  351. }
  352. pair<string, string> splitField(const string& inp, char sepa);
  353. inline bool isCanonical(const string& qname)
  354. {
  355. if(qname.empty())
  356. return false;
  357. return qname[qname.size()-1]=='.';
  358. }
  359. inline DNSName toCanonic(const DNSName& zone, const string& qname)
  360. {
  361. if(qname.size()==1 && qname[0]=='@')
  362. return zone;
  363. if(isCanonical(qname))
  364. return DNSName(qname);
  365. return DNSName(qname) += zone;
  366. }
  367. string stripDot(const string& dom);
  368. int makeIPv6sockaddr(const std::string& addr, struct sockaddr_in6* ret);
  369. int makeIPv4sockaddr(const std::string& str, struct sockaddr_in* ret);
  370. int makeUNsockaddr(const std::string& path, struct sockaddr_un* ret);
  371. bool stringfgets(FILE* fp, std::string& line);
  372. template<typename Index>
  373. std::pair<typename Index::iterator,bool>
  374. replacing_insert(Index& i,const typename Index::value_type& x)
  375. {
  376. std::pair<typename Index::iterator,bool> res=i.insert(x);
  377. if(!res.second)res.second=i.replace(res.first,x);
  378. return res;
  379. }
  380. /** very small regex wrapper */
  381. class Regex
  382. {
  383. public:
  384. /** constructor that accepts the expression to regex */
  385. Regex(const string &expr);
  386. ~Regex()
  387. {
  388. regfree(&d_preg);
  389. }
  390. /** call this to find out if 'line' matches your expression */
  391. bool match(const string &line) const
  392. {
  393. return regexec(&d_preg,line.c_str(),0,0,0)==0;
  394. }
  395. bool match(const DNSName& name) const
  396. {
  397. return match(name.toStringNoDot());
  398. }
  399. private:
  400. regex_t d_preg;
  401. };
  402. class SimpleMatch
  403. {
  404. public:
  405. SimpleMatch(const string &mask, bool caseFold = false): d_mask(mask), d_fold(caseFold)
  406. {
  407. }
  408. bool match(string::const_iterator mi, string::const_iterator mend, string::const_iterator vi, string::const_iterator vend)
  409. {
  410. for(;;++mi) {
  411. if (mi == mend) {
  412. return vi == vend;
  413. } else if (*mi == '?') {
  414. if (vi == vend) return false;
  415. ++vi;
  416. } else if (*mi == '*') {
  417. while(*mi == '*') ++mi;
  418. if (mi == d_mask.end()) return true;
  419. while(vi != vend) {
  420. if (match(mi,mend,vi,vend)) return true;
  421. ++vi;
  422. }
  423. return false;
  424. } else {
  425. if ((mi == mend && vi != vend)||
  426. (mi != mend && vi == vend)) return false;
  427. if (d_fold) {
  428. if (dns_tolower(*mi) != dns_tolower(*vi)) return false;
  429. } else {
  430. if (*mi != *vi) return false;
  431. }
  432. ++vi;
  433. }
  434. }
  435. }
  436. bool match(const string& value) {
  437. return match(d_mask.begin(), d_mask.end(), value.begin(), value.end());
  438. }
  439. bool match(const DNSName& name) {
  440. return match(name.toStringNoDot());
  441. }
  442. private:
  443. string d_mask;
  444. bool d_fold;
  445. };
  446. union ComboAddress;
  447. // An aligned type to hold cmsgbufs. See https://man.openbsd.org/CMSG_DATA
  448. typedef union { struct cmsghdr hdr; char buf[256]; } cmsgbuf_aligned;
  449. /* itfIndex is an interface index, as returned by if_nametoindex(). 0 means default. */
  450. void addCMsgSrcAddr(struct msghdr* msgh, cmsgbuf_aligned* cbuf, const ComboAddress* source, int itfIndex);
  451. unsigned int getFilenumLimit(bool hardOrSoft=0);
  452. void setFilenumLimit(unsigned int lim);
  453. bool readFileIfThere(const char* fname, std::string* line);
  454. uint32_t burtle(const unsigned char* k, uint32_t length, uint32_t init);
  455. bool setSocketTimestamps(int fd);
  456. //! Sets the socket into blocking mode.
  457. bool setBlocking( int sock );
  458. //! Sets the socket into non-blocking mode.
  459. bool setNonBlocking( int sock );
  460. bool setTCPNoDelay(int sock);
  461. bool setReuseAddr(int sock);
  462. bool isNonBlocking(int sock);
  463. bool setReceiveSocketErrors(int sock, int af);
  464. int closesocket(int fd);
  465. bool setCloseOnExec(int sock);
  466. size_t getPipeBufferSize(int fd);
  467. bool setPipeBufferSize(int fd, size_t size);
  468. uint64_t udpErrorStats(const std::string& str);
  469. uint64_t getRealMemoryUsage(const std::string&);
  470. uint64_t getSpecialMemoryUsage(const std::string&);
  471. uint64_t getOpenFileDescriptors(const std::string&);
  472. uint64_t getCPUTimeUser(const std::string&);
  473. uint64_t getCPUTimeSystem(const std::string&);
  474. uint64_t getCPUIOWait(const std::string&);
  475. uint64_t getCPUSteal(const std::string&);
  476. std::string getMACAddress(const ComboAddress& ca);
  477. template<typename T, typename... Args>
  478. std::unique_ptr<T> make_unique(Args&&... args)
  479. {
  480. return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
  481. }
  482. template<typename T>
  483. const T& defTer(const T& a, const T& b)
  484. {
  485. return a ? a : b;
  486. }
  487. template<typename P, typename T>
  488. T valueOrEmpty(const P val) {
  489. if (!val) return T{};
  490. return T(val);
  491. }
  492. // I'm not very OCD, but I appreciate loglines like "processing 1 delta", "processing 2 deltas" :-)
  493. template <typename Integer>
  494. const char* addS(Integer siz, typename std::enable_if<std::is_integral<Integer>::value>::type*P=0)
  495. {
  496. if(!siz || siz > 1)
  497. return "s";
  498. else return "";
  499. }
  500. template<typename C>
  501. const char* addS(const C& c, typename std::enable_if<std::is_class<C>::value>::type*P=0)
  502. {
  503. return addS(c.size());
  504. }
  505. template<typename C>
  506. const typename C::value_type::second_type* rplookup(const C& c, const typename C::value_type::first_type& key)
  507. {
  508. auto fnd = c.find(key);
  509. if(fnd == c.end())
  510. return 0;
  511. return &fnd->second;
  512. }
  513. double DiffTime(const struct timespec& first, const struct timespec& second);
  514. double DiffTime(const struct timeval& first, const struct timeval& second);
  515. uid_t strToUID(const string &str);
  516. gid_t strToGID(const string &str);
  517. unsigned int pdns_stou(const std::string& str, size_t * idx = 0, int base = 10);
  518. bool isSettingThreadCPUAffinitySupported();
  519. int mapThreadToCPUList(pthread_t tid, const std::set<int>& cpus);
  520. std::vector<ComboAddress> getResolvers(const std::string& resolvConfPath);
  521. DNSName reverseNameFromIP(const ComboAddress& ip);
  522. std::string getCarbonHostName();