]>
Commit | Line | Data |
---|---|---|
12c86877 BH |
1 | /* |
2 | PowerDNS Versatile Database Driven Nameserver | |
ec6480f3 | 3 | Copyright (C) 2002-2009 PowerDNS.COM BV |
12c86877 BH |
4 | |
5 | This program is free software; you can redistribute it and/or modify | |
22dc646a BH |
6 | it under the terms of the GNU General Public License version 2 |
7 | as published by the Free Software Foundation | |
8 | ||
12c86877 BH |
9 | |
10 | This program is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License | |
16 | along with this program; if not, write to the Free Software | |
06bd9ccf | 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
12c86877 BH |
18 | */ |
19 | #ifndef MISC_HH | |
20 | #define MISC_HH | |
61b26744 | 21 | #include <inttypes.h> |
8b3cfcd3 | 22 | #include <cstring> |
f9822705 | 23 | #include <cstdio> |
ec6480f3 | 24 | #include <boost/algorithm/string.hpp> |
4b8b58e1 | 25 | #if 0 |
eff65ff8 BH |
26 | #include <iostream> |
27 | using std::cout; | |
28 | using std::endl; | |
29 | ||
30 | struct TSCTimer | |
31 | { | |
32 | TSCTimer() | |
33 | { | |
34 | RDTSC(d_tsc1); | |
35 | } | |
36 | ~TSCTimer() | |
37 | { | |
38 | uint64_t tsc2; | |
39 | RDTSC(tsc2); | |
40 | cout<<"Timer: "<< (tsc2 - d_tsc1)/3000.0 << endl; | |
41 | } | |
42 | uint64_t d_tsc1; | |
43 | }; | |
44 | #endif | |
12c86877 BH |
45 | |
46 | #include "utility.hh" | |
e67e250f | 47 | #include "dns.hh" |
12c86877 BH |
48 | #ifndef WIN32 |
49 | # include <sys/time.h> | |
50 | # include <sys/types.h> | |
51 | # include <sys/socket.h> | |
cc3afe25 | 52 | # include <time.h> |
6e2514e4 | 53 | # include <syslog.h> |
cc3afe25 | 54 | #else |
cc3afe25 BH |
55 | # define WINDOWS_LEAN_AND_MEAN |
56 | # include <windows.h> | |
57 | # include "utility.hh" | |
cc3afe25 | 58 | #endif // WIN32 |
3de83124 | 59 | #include <deque> |
a640a9d4 | 60 | #include <stdexcept> |
12c86877 BH |
61 | #include <string> |
62 | #include <ctype.h> | |
e67e250f | 63 | #include <vector> |
6e2514e4 | 64 | #include <boost/optional.hpp> |
e67e250f | 65 | |
12c86877 | 66 | using namespace std; |
728485ca | 67 | bool chopOff(string &domain); |
7738a23f BH |
68 | bool chopOffDotted(string &domain); |
69 | ||
728485ca | 70 | bool endsOn(const string &domain, const string &suffix); |
7738a23f | 71 | bool dottedEndsOn(const string &domain, const string &suffix); |
cc3afe25 | 72 | string nowTime(); |
1d329048 | 73 | const string unquotify(const string &item); |
12c86877 BH |
74 | string humanDuration(time_t passed); |
75 | void chomp(string &line, const string &delim); | |
f2c11a48 | 76 | bool stripDomainSuffix(string *qname, const string &domain); |
12c86877 BH |
77 | void stripLine(string &line); |
78 | string getHostname(); | |
79 | string urlEncode(const string &text); | |
a7d50153 | 80 | int waitForData(int fd, int seconds, int useconds=0); |
6a3e5d1a | 81 | int waitForRWData(int fd, bool waitForRead, int seconds, int useconds); |
092f210a BH |
82 | uint16_t getShort(const unsigned char *p); |
83 | uint16_t getShort(const char *p); | |
84 | uint32_t getLong(const unsigned char *p); | |
85 | uint32_t getLong(const char *p); | |
6e2514e4 | 86 | boost::optional<int> logFacilityToLOG(unsigned int facility); |
bbce5bf0 | 87 | |
092f210a | 88 | inline void putLong(unsigned char* p, uint32_t val) |
7bf26383 BH |
89 | { |
90 | *p++=(val>>24)&0xff; | |
91 | *p++=(val>>16)&0xff; | |
92 | *p++=(val>>8)&0xff; | |
93 | *p++=(val )&0xff; | |
94 | ||
95 | } | |
092f210a | 96 | inline void putLong(char* p, uint32_t val) |
7bf26383 BH |
97 | { |
98 | putLong((unsigned char *)p,val); | |
99 | } | |
12c86877 | 100 | |
7b35aa49 | 101 | |
092f210a | 102 | inline uint32_t getLong(unsigned char *p) |
7b35aa49 BH |
103 | { |
104 | return (p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]; | |
105 | } | |
106 | ||
12c86877 BH |
107 | |
108 | struct ServiceTuple | |
109 | { | |
110 | string host; | |
092f210a | 111 | uint16_t port; |
12c86877 BH |
112 | }; |
113 | void parseService(const string &descr, ServiceTuple &st); | |
114 | ||
115 | template <typename Container> | |
116 | void | |
117 | stringtok (Container &container, string const &in, | |
118 | const char * const delimiters = " \t\n") | |
119 | { | |
120 | const string::size_type len = in.length(); | |
121 | string::size_type i = 0; | |
122 | ||
123 | while (i<len) { | |
124 | // eat leading whitespace | |
125 | i = in.find_first_not_of (delimiters, i); | |
126 | if (i == string::npos) | |
127 | return; // nothing left but white space | |
128 | ||
129 | // find the end of the token | |
130 | string::size_type j = in.find_first_of (delimiters, i); | |
131 | ||
132 | // push token | |
133 | if (j == string::npos) { | |
134 | container.push_back (in.substr(i)); | |
135 | return; | |
136 | } else | |
137 | container.push_back (in.substr(i, j-i)); | |
138 | ||
139 | // set up for next loop | |
140 | i = j + 1; | |
141 | } | |
142 | } | |
8c3149f2 BH |
143 | |
144 | template <typename Container> | |
145 | void | |
146 | vstringtok (Container &container, string const &in, | |
147 | const char * const delimiters = " \t\n") | |
148 | { | |
149 | const string::size_type len = in.length(); | |
150 | string::size_type i = 0; | |
151 | ||
152 | while (i<len) { | |
153 | // eat leading whitespace | |
154 | i = in.find_first_not_of (delimiters, i); | |
155 | if (i == string::npos) | |
156 | return; // nothing left but white space | |
157 | ||
158 | // find the end of the token | |
159 | string::size_type j = in.find_first_of (delimiters, i); | |
160 | ||
161 | // push token | |
162 | if (j == string::npos) { | |
163 | container.push_back (make_pair(i, len)); | |
164 | return; | |
165 | } else | |
166 | container.push_back (make_pair(i, j)); | |
167 | ||
168 | // set up for next loop | |
169 | i = j + 1; | |
170 | } | |
171 | } | |
172 | ||
040712e0 BH |
173 | int writen2(int fd, const void *buf, size_t count); |
174 | inline int writen2(int fd, const std::string &s) { return writen2(fd, s.data(), s.size()); } | |
175 | ||
176 | ||
c3d9d009 | 177 | const string toLower(const string &upper); |
b0d4fb45 | 178 | const string toLowerCanonic(const string &upper); |
092f210a | 179 | bool IpToU32(const string &str, uint32_t *ip); |
5730f30c | 180 | string U32ToIP(uint32_t); |
12c86877 | 181 | string stringerror(); |
d3b4137e | 182 | string netstringerror(); |
12c86877 | 183 | string itoa(int i); |
22c9c86a | 184 | string uitoa(unsigned int i); |
12c86877 BH |
185 | |
186 | void dropPrivs(int uid, int gid); | |
187 | int makeGidNumeric(const string &group); | |
188 | int makeUidNumeric(const string &user); | |
189 | void cleanSlashes(string &str); | |
190 | ||
191 | /** The DTime class can be used for timing statistics with microsecond resolution. | |
192 | On 32 bits systems this means that 2147 seconds is the longest time that can be measured. */ | |
193 | class DTime | |
194 | { | |
195 | public: | |
eefd15f9 | 196 | DTime(); //!< Does not set the timer for you! Saves lots of gettimeofday() calls |
12c86877 BH |
197 | DTime(const DTime &dt); |
198 | time_t time(); | |
199 | inline void set(); //!< Reset the timer | |
200 | inline int udiff(); //!< Return the number of microseconds since the timer was last set. | |
88358c9b BH |
201 | void setTimeval(const struct timeval& tv) |
202 | { | |
203 | d_set=tv; | |
204 | } | |
205 | struct timeval getTimeval() | |
206 | { | |
207 | return d_set; | |
208 | } | |
12c86877 BH |
209 | private: |
210 | struct timeval d_set; | |
211 | }; | |
37d3f960 | 212 | const string sockAddrToString(struct sockaddr_in *remote); |
12c86877 BH |
213 | int sendData(const char *buffer, int replen, int outsock); |
214 | ||
12c86877 BH |
215 | inline void DTime::set() |
216 | { | |
d3b729e8 | 217 | Utility::gettimeofday(&d_set,0); |
12c86877 BH |
218 | } |
219 | ||
220 | inline int DTime::udiff() | |
221 | { | |
222 | struct timeval now; | |
12c86877 | 223 | |
d3b729e8 | 224 | Utility::gettimeofday(&now,0); |
fe213470 BH |
225 | int ret=1000000*(now.tv_sec-d_set.tv_sec)+(now.tv_usec-d_set.tv_usec); |
226 | d_set=now; | |
227 | return ret; | |
12c86877 BH |
228 | } |
229 | ||
f5be3a1e BH |
230 | inline bool dns_isspace(char c) |
231 | { | |
232 | return c==' ' || c=='\t' || c=='\r' || c=='\n'; | |
233 | } | |
234 | ||
8b3cfcd3 | 235 | inline char dns_tolower(char c) |
f5be3a1e BH |
236 | { |
237 | if(c>='A' && c<='Z') | |
238 | c+='a'-'A'; | |
239 | return c; | |
240 | } | |
241 | ||
c3d9d009 | 242 | inline const string toLower(const string &upper) |
12c86877 BH |
243 | { |
244 | string reply(upper); | |
c536ca8d BH |
245 | char c; |
246 | for(unsigned int i = 0; i < reply.length(); i++) { | |
e3cacd48 BH |
247 | c = dns_tolower(upper[i]); |
248 | if( c != upper[i]) | |
c536ca8d BH |
249 | reply[i] = c; |
250 | } | |
12c86877 BH |
251 | return reply; |
252 | } | |
253 | ||
b0d4fb45 BH |
254 | inline const string toLowerCanonic(const string &upper) |
255 | { | |
256 | string reply(upper); | |
257 | if(!upper.empty()) { | |
705f31ae | 258 | unsigned int i, limit= ( unsigned int ) reply.length(); |
c536ca8d BH |
259 | char c; |
260 | for(i = 0; i < limit ; i++) { | |
e3cacd48 BH |
261 | c = dns_tolower(upper[i]); |
262 | if(c != upper[i]) | |
c536ca8d BH |
263 | reply[i] = c; |
264 | } | |
e3cacd48 | 265 | if(upper[i-1]=='.') |
b0d4fb45 BH |
266 | reply.resize(i-1); |
267 | } | |
268 | ||
269 | return reply; | |
270 | } | |
271 | ||
272 | ||
12c86877 | 273 | |
52936200 BH |
274 | // Make s uppercase: |
275 | inline string toUpper( const string& s ) | |
276 | { | |
277 | string r(s); | |
278 | for( unsigned int i = 0; i < s.length(); i++ ) { | |
279 | r[i] = toupper( r[i] ); | |
280 | } | |
281 | return r; | |
282 | } | |
283 | ||
a6d7640a BH |
284 | inline double getTime() |
285 | { | |
286 | struct timeval now; | |
287 | Utility::gettimeofday(&now,0); | |
288 | ||
289 | return now.tv_sec+now.tv_usec/1000000.0; | |
290 | } | |
291 | ||
a640a9d4 BH |
292 | inline void unixDie(const string &why) |
293 | { | |
294 | throw runtime_error(why+": "+strerror(errno)); | |
295 | } | |
296 | ||
2db9c30e | 297 | string makeHexDump(const string& str); |
e67e250f | 298 | void shuffle(vector<DNSResourceRecord>& rrs); |
88358c9b BH |
299 | |
300 | void normalizeTV(struct timeval& tv); | |
301 | const struct timeval operator+(const struct timeval& lhs, const struct timeval& rhs); | |
302 | const struct timeval operator-(const struct timeval& lhs, const struct timeval& rhs); | |
303 | inline float makeFloat(const struct timeval& tv) | |
304 | { | |
705f31ae | 305 | return tv.tv_sec + tv.tv_usec/1000000.0f; |
88358c9b | 306 | } |
5b0ddd18 BH |
307 | |
308 | inline bool operator<(const struct timeval& lhs, const struct timeval& rhs) | |
309 | { | |
310 | return make_pair(lhs.tv_sec, lhs.tv_usec) < make_pair(rhs.tv_sec, rhs.tv_usec); | |
311 | } | |
312 | ||
ec6480f3 BH |
313 | inline bool pdns_ilexicographical_compare(const std::string& a, const std::string& b) __attribute__((pure)); |
314 | inline bool pdns_ilexicographical_compare(const std::string& a, const std::string& b) | |
7738a23f | 315 | { |
ec6480f3 BH |
316 | string::size_type aLen = a.length(), bLen = b.length(), n; |
317 | const char *aPtr = a.c_str(), *bPtr = b.c_str(); | |
318 | int result; | |
319 | ||
320 | for(n = 0 ; n < aLen && n < bLen ; ++n) { | |
321 | if((result = dns_tolower(*aPtr++) - dns_tolower(*bPtr++))) { | |
322 | return result < 0; | |
323 | } | |
7738a23f | 324 | } |
ec6480f3 BH |
325 | if(n == aLen && n == bLen) // strings are equal (in length) |
326 | return 0; | |
327 | if(n == aLen) // first string was shorter | |
328 | return true; | |
329 | return false; | |
330 | } | |
eff65ff8 | 331 | |
ec6480f3 BH |
332 | inline bool pdns_iequals(const std::string& a, const std::string& b) __attribute__((pure)); |
333 | ||
334 | inline bool pdns_iequals(const std::string& a, const std::string& b) | |
335 | { | |
336 | string::size_type aLen = a.length(), bLen = b.length(), n; | |
337 | const char *aPtr = a.c_str(), *bPtr = b.c_str(); | |
338 | ||
339 | for(n = 0 ; n < aLen && n < bLen ; ++n) { | |
340 | if(dns_tolower(*aPtr++) != dns_tolower(*bPtr++)) | |
341 | return false; | |
eff65ff8 | 342 | } |
ec6480f3 BH |
343 | return aLen == bLen; // strings are equal (in length) |
344 | } | |
345 | ||
eff65ff8 | 346 | |
ec6480f3 BH |
347 | struct CIStringCompare: public binary_function<string, string, bool> |
348 | { | |
349 | bool operator()(const string& a, const string& b) const | |
eff65ff8 | 350 | { |
ec6480f3 | 351 | return pdns_ilexicographical_compare(a, b); |
eff65ff8 | 352 | } |
7738a23f | 353 | }; |
eff65ff8 | 354 | |
50c79a76 | 355 | pair<string, string> splitField(const string& inp, char sepa); |
26cd1b3f BH |
356 | |
357 | inline bool isCanonical(const string& dom) | |
358 | { | |
359 | if(dom.empty()) | |
360 | return false; | |
361 | return dom[dom.size()-1]=='.'; | |
362 | } | |
363 | ||
364 | inline string toCanonic(const string& zone, const string& domain) | |
365 | { | |
366 | if(isCanonical(domain)) | |
367 | return domain; | |
368 | string ret=domain; | |
369 | ret.append(1,'.'); | |
4d2c97aa BH |
370 | if(!zone.empty() && zone[0]!='.') |
371 | ret.append(zone); | |
26cd1b3f BH |
372 | return ret; |
373 | } | |
da042e6e | 374 | |
f8c44754 BH |
375 | inline void setSocketReusable(int fd) |
376 | { | |
377 | int tmp=1; | |
378 | setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&tmp, static_cast<unsigned>(sizeof tmp)); | |
379 | } | |
380 | ||
da042e6e | 381 | string stripDot(const string& dom); |
a28a204a | 382 | void seedRandom(const string& source); |
12c86877 | 383 | #endif |