2
2
PowerDNS Versatile Database Driven Nameserver
3
Copyright (C) 2002 PowerDNS.COM BV
3
Copyright (C) 2002 - 2006 PowerDNS.COM BV
5
5
This program is free software; you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation; either version 2 of the License, or
8
(at your option) any later version.
6
it under the terms of the GNU General Public License version 2
7
as published by the Free Software Foundation
10
10
This program is distributed in the hope that it will be useful,
11
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
15
You should have received a copy of the GNU General Public License
16
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
#include <sys/param.h>
25
#include <netinet/in.h>
24
34
#include <iostream>
36
#include <boost/optional.hpp>
27
39
#include <string.h>
94
/** Chops off the start of a domain, so goes from 'www.ds9a.nl' to 'ds9a.nl' to ''. Return zero on the empty string */
95
bool chopOff(string &domain)
94
/** Chops off the start of a domain, so goes from 'www.ds9a.nl' to 'ds9a.nl' to 'nl' to ''. Return zero on the empty string */
95
bool chopOff(string &domain)
102
102
if(fdot==string::npos)
105
domain=domain.substr(fdot+1);
105
string::size_type remain = domain.length() - (fdot + 1);
107
memcpy(tmp, domain.c_str()+fdot+1, remain);
108
domain.assign(tmp, remain); // don't dare to do this w/o tmp holder :-)
113
/** Chops off the start of a domain, so goes from 'www.ds9a.nl.' to 'ds9a.nl.' to 'nl.' to '.' Return zero on the empty string */
114
bool chopOffDotted(string &domain)
116
if(domain.empty() || (domain.size()==1 && domain[0]=='.'))
119
string::size_type fdot=domain.find('.');
120
if(fdot == string::npos)
123
if(fdot==domain.size()-1)
126
string::size_type remain = domain.length() - (fdot + 1);
128
memcpy(tmp, domain.c_str()+fdot+1, remain);
129
domain.assign(tmp, remain);
109
135
bool ciEqual(const string& a, const string& b)
124
150
if( suffix.empty() || ciEqual(domain, suffix) )
126
if(domain.size()<=suffix.size())
129
string::size_type dpos=domain.size()-suffix.size()-1, spos=0;
153
if(domain.size()<=suffix.size())
156
string::size_type dpos=domain.size()-suffix.size()-1, spos=0;
158
if(domain[dpos++]!='.')
161
for(; dpos < domain.size(); ++dpos, ++spos)
162
if(dns_tolower(domain[dpos]) != dns_tolower(suffix[spos]))
168
/** does domain end on suffix? Is smart about "wwwds9a.nl" "ds9a.nl" not matching */
169
bool dottedEndsOn(const string &domain, const string &suffix)
171
if( suffix=="." || ciEqual(domain, suffix) )
174
if(domain.size()<=suffix.size())
177
string::size_type dpos=domain.size()-suffix.size()-1, spos=0;
130
179
if(domain[dpos++]!='.')
145
194
iov[0].iov_len=2;
146
195
iov[1].iov_base=(char*)buffer;
147
196
iov[1].iov_len=replen;
148
int ret=writev(outsock,iov,2);
197
int ret=Utility::writev(outsock,iov,2);
199
if(ret <= 0) // "EOF is error" - we can't deal with EAGAIN errors at this stage yet
153
202
if(ret!=replen+2) {
203
// we can safely assume ret > 2, as 2 is < PIPE_BUF
209
ret = write(outsock, buffer, replen);
211
if(errno==EAGAIN) { // wait, we might've exhausted the window
212
while(waitForRWData(outsock, false, 1, 0)==0)
219
return -1; // "EOF == error"
159
void parseService(const string &descr, ServiceTuple &st)
230
static void parseService4(const string &descr, ServiceTuple &st)
162
232
vector<string>parts;
163
233
stringtok(parts,descr,":");
164
234
if(parts.empty())
168
238
st.port=atoi(parts[1].c_str());
241
static void parseService6(const string &descr, ServiceTuple &st)
243
string::size_type pos=descr.find(']');
244
if(pos == string::npos)
245
throw AhuException("Unable to parse '"+descr+"' as an IPv6 service");
247
st.host=descr.substr(1, pos-1);
248
if(pos + 2 < descr.length())
249
st.port=atoi(descr.c_str() + pos +2);
253
void parseService(const string &descr, ServiceTuple &st)
256
throw AhuException("Unable to parse '"+descr+"' as a service");
258
vector<string> parts;
259
stringtok(parts, descr, ":");
262
parseService6(descr, st);
264
else if(descr[0]==':' || parts.size() > 2 || descr.find("::") != string::npos) {
268
parseService4(descr, st);
272
// returns -1 in case if error, 0 if no data is available, 1 if there is. In the first two cases, errno is set
172
273
int waitForData(int fd, int seconds, int useconds)
275
return waitForRWData(fd, true, seconds, useconds);
278
int waitForRWData(int fd, bool waitForRead, int seconds, int useconds)
174
280
struct timeval tv;
177
283
tv.tv_sec = seconds;
178
284
tv.tv_usec = useconds;
286
fd_set readfds, writefds;
181
287
FD_ZERO( &readfds );
182
FD_SET( fd, &readfds );
288
FD_ZERO( &writefds );
290
FD_SET( fd, &readfds );
292
FD_SET( fd, &writefds );
184
ret = select( fd + 1, &readfds, NULL, NULL, &tv );
294
ret = select( fd + 1, &readfds, &writefds, NULL, &tv );
186
296
errno = ETIMEDOUT;
287
397
return strerror(errno);
401
string netstringerror()
404
int err=WSAGetLastError();
405
if(FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
406
0, buf, sizeof(buf)-1, NULL)) {
410
return strerror(err);
414
string netstringerror()
416
return stringerror();
290
420
void cleanSlashes(string &str)
292
422
string::const_iterator i;
310
440
struct in_addr inp;
311
if(inet_aton(str.c_str(), &inp)) {
441
if(Utility::inet_aton(str.c_str(), &inp)) {
318
const string sockAddrToString(struct sockaddr_in *remote, Utility::socklen_t socklen)
448
string U32ToIP(uint32_t val)
451
snprintf(tmp, sizeof(tmp)-1, "%u.%u.%u.%u",
460
const string sockAddrToString(struct sockaddr_in *remote)
320
if(socklen==sizeof(struct sockaddr_in)) {
462
if(remote->sin_family == AF_INET) {
321
463
struct sockaddr_in sip;
322
464
memcpy(&sip,(struct sockaddr_in*)remote,sizeof(sip));
323
465
return inet_ntoa(sip.sin_addr);
329
if(!inet_ntop(AF_INET6, ( const char * ) &((struct sockaddr_in6 *)remote)->sin6_addr, tmp, sizeof(tmp)))
470
if(!Utility::inet_ntop(AF_INET6, ( const char * ) &((struct sockaddr_in6 *)remote)->sin6_addr, tmp, sizeof(tmp)))
330
471
return "IPv6 untranslateable";
336
return "untranslateable";
339
477
string makeHexDump(const string& str)
379
517
// we don't shuffle the rest
521
void normalizeTV(struct timeval& tv)
523
if(tv.tv_usec > 1000000) {
527
else if(tv.tv_usec < 0) {
533
const struct timeval operator+(const struct timeval& lhs, const struct timeval& rhs)
536
ret.tv_sec=lhs.tv_sec + rhs.tv_sec;
537
ret.tv_usec=lhs.tv_usec + rhs.tv_usec;
542
const struct timeval operator-(const struct timeval& lhs, const struct timeval& rhs)
545
ret.tv_sec=lhs.tv_sec - rhs.tv_sec;
546
ret.tv_usec=lhs.tv_usec - rhs.tv_usec;
551
pair<string, string> splitField(const string& inp, char sepa)
553
pair<string, string> ret;
554
string::size_type cpos=inp.find(sepa);
555
if(cpos==string::npos)
558
ret.first=inp.substr(0, cpos);
559
ret.second=inp.substr(cpos+1);
564
boost::optional<int> logFacilityToLOG(unsigned int facility)
566
boost::optional<int> ret;
590
string stripDot(const string& dom)
595
if(dom[dom.size()-1]!='.')
598
return dom.substr(0,dom.size()-1);