~ubuntu-branches/ubuntu/maverick/pdns/maverick-updates

« back to all changes in this revision

Viewing changes to pdns/misc.cc

  • Committer: Bazaar Package Importer
  • Author(s): Matthijs Mohlmann, Matthijs Mohlmann, Christoph Haas
  • Date: 2007-04-15 23:23:39 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070415232339-5x3scc8gx04e50um
Tags: 2.9.21-1
[ Matthijs Mohlmann ]
* New upstream release. (Closes: #420294)
* Remove meta pdns package.
* Added new sqlite3 backend package.
* Months and minutes where mixed up. (Closes: #406462)
* Case sensitivity in bind backend caused PowerDNS to not serve a certain
  zone. (Closes: #406461)
* Bind backend forgot about zones on a notify. (Closes: #398213)

[ Christoph Haas ]
* Documented incorporated backend bind. (Closes: #415471)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
    PowerDNS Versatile Database Driven Nameserver
3
 
    Copyright (C) 2002  PowerDNS.COM BV
 
3
    Copyright (C) 2002 - 2006  PowerDNS.COM BV
4
4
 
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
 
8
    
9
9
 
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
14
14
 
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
18
18
*/
 
19
 
 
20
#ifndef WIN32
 
21
#include <sys/param.h>
 
22
#include <netdb.h>
 
23
#include <sys/time.h>
 
24
#include <time.h>
 
25
#include <netinet/in.h>
 
26
#include <unistd.h>
 
27
#endif // WIN32
 
28
 
19
29
#include "misc.hh"
20
30
#include <vector>
21
31
#include <sstream>
22
32
#include <errno.h>
23
33
#include <cstring>
24
34
#include <iostream>
 
35
#include <algorithm>
 
36
#include <boost/optional.hpp>
25
37
 
26
38
#include <iomanip>
27
39
#include <string.h>
29
41
#include <stdio.h>
30
42
#include "ahuexception.hh"
31
43
#include <sys/types.h>
32
 
 
33
 
#ifndef WIN32
34
 
# include <sys/param.h>
35
 
# include <netdb.h>
36
 
# include <sys/time.h>
37
 
# include <time.h>
38
 
# include <netinet/in.h>
39
 
# include <unistd.h>
40
 
#else
41
 
# include <time.h>
42
 
#endif // WIN32
43
 
 
44
44
#include "utility.hh"
45
45
 
46
46
string nowTime()
91
91
  return true;
92
92
}
93
93
 
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) 
96
96
{
97
97
  if(domain.empty())
98
98
    return false;
101
101
 
102
102
  if(fdot==string::npos) 
103
103
    domain="";
104
 
  else 
105
 
    domain=domain.substr(fdot+1);
106
 
  return true;
107
 
}
 
104
  else {
 
105
    string::size_type remain = domain.length() - (fdot + 1);
 
106
    char tmp[remain];
 
107
    memcpy(tmp, domain.c_str()+fdot+1, remain);
 
108
    domain.assign(tmp, remain); // don't dare to do this w/o tmp holder :-)
 
109
  }
 
110
  return true;
 
111
}
 
112
 
 
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)
 
115
{
 
116
  if(domain.empty() || (domain.size()==1 && domain[0]=='.'))
 
117
    return false;
 
118
 
 
119
  string::size_type fdot=domain.find('.');
 
120
  if(fdot == string::npos)
 
121
    return false;
 
122
 
 
123
  if(fdot==domain.size()-1) 
 
124
    domain=".";
 
125
  else  {
 
126
    string::size_type remain = domain.length() - (fdot + 1);
 
127
    char tmp[remain];
 
128
    memcpy(tmp, domain.c_str()+fdot+1, remain);
 
129
    domain.assign(tmp, remain);
 
130
  }
 
131
  return true;
 
132
}
 
133
 
108
134
 
109
135
bool ciEqual(const string& a, const string& b)
110
136
{
123
149
{
124
150
  if( suffix.empty() || ciEqual(domain, suffix) )
125
151
    return true;
126
 
  if(domain.size()<=suffix.size())
127
 
    return false;
128
 
  
129
 
  string::size_type dpos=domain.size()-suffix.size()-1, spos=0;
 
152
 
 
153
  if(domain.size()<=suffix.size())
 
154
    return false;
 
155
  
 
156
  string::size_type dpos=domain.size()-suffix.size()-1, spos=0;
 
157
 
 
158
  if(domain[dpos++]!='.')
 
159
    return false;
 
160
 
 
161
  for(; dpos < domain.size(); ++dpos, ++spos)
 
162
    if(dns_tolower(domain[dpos]) != dns_tolower(suffix[spos]))
 
163
      return false;
 
164
 
 
165
  return true;
 
166
}
 
167
 
 
168
/** does domain end on suffix? Is smart about "wwwds9a.nl" "ds9a.nl" not matching */
 
169
bool dottedEndsOn(const string &domain, const string &suffix) 
 
170
{
 
171
  if( suffix=="." || ciEqual(domain, suffix) )
 
172
    return true;
 
173
 
 
174
  if(domain.size()<=suffix.size())
 
175
    return false;
 
176
  
 
177
  string::size_type dpos=domain.size()-suffix.size()-1, spos=0;
 
178
 
130
179
  if(domain[dpos++]!='.')
131
180
    return false;
132
181
 
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);
149
198
 
150
 
  if(ret<0) {
 
199
  if(ret <= 0)  // "EOF is error" - we can't deal with EAGAIN errors at this stage yet
151
200
    return -1;
152
 
  }
 
201
 
153
202
  if(ret!=replen+2) {
 
203
    // we can safely assume ret > 2, as 2 is < PIPE_BUF
 
204
    
 
205
    buffer += (ret - 2);
 
206
    replen -= (ret - 2);
 
207
 
 
208
    while (replen) {
 
209
      ret = write(outsock, buffer, replen);
 
210
      if(ret < 0) {
 
211
        if(errno==EAGAIN) { // wait, we might've exhausted the window
 
212
          while(waitForRWData(outsock, false, 1, 0)==0)
 
213
            ;
 
214
          continue;
 
215
        }
 
216
        return ret;
 
217
      }
 
218
      if(!ret)
 
219
        return -1; // "EOF == error"
 
220
      replen -= ret;
 
221
      buffer += ret;
 
222
    }
 
223
    if(!replen)
 
224
      return 0;
154
225
    return -1;
155
226
  }
156
227
  return 0;
157
228
}
158
229
 
159
 
void parseService(const string &descr, ServiceTuple &st)
 
230
static void parseService4(const string &descr, ServiceTuple &st)
160
231
{
161
 
 
162
232
  vector<string>parts;
163
233
  stringtok(parts,descr,":");
164
234
  if(parts.empty())
168
238
    st.port=atoi(parts[1].c_str());
169
239
}
170
240
 
171
 
 
 
241
static void parseService6(const string &descr, ServiceTuple &st)
 
242
{
 
243
  string::size_type pos=descr.find(']');
 
244
  if(pos == string::npos)
 
245
    throw AhuException("Unable to parse '"+descr+"' as an IPv6 service");
 
246
 
 
247
  st.host=descr.substr(1, pos-1);
 
248
  if(pos + 2 < descr.length())
 
249
    st.port=atoi(descr.c_str() + pos +2);
 
250
}
 
251
 
 
252
 
 
253
void parseService(const string &descr, ServiceTuple &st)
 
254
{
 
255
  if(descr.empty())
 
256
    throw AhuException("Unable to parse '"+descr+"' as a service");
 
257
 
 
258
  vector<string> parts;
 
259
  stringtok(parts, descr, ":");
 
260
 
 
261
  if(descr[0]=='[') {
 
262
    parseService6(descr, st);
 
263
  }
 
264
  else if(descr[0]==':' || parts.size() > 2 || descr.find("::") != string::npos) {
 
265
    st.host=descr;
 
266
  }
 
267
  else {
 
268
    parseService4(descr, st);
 
269
  }
 
270
}
 
271
 
 
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)
173
274
{
 
275
  return waitForRWData(fd, true, seconds, useconds);
 
276
}
 
277
 
 
278
int waitForRWData(int fd, bool waitForRead, int seconds, int useconds)
 
279
{
174
280
  struct timeval tv;
175
281
  int ret;
176
282
 
177
283
  tv.tv_sec   = seconds;
178
284
  tv.tv_usec  = useconds;
179
285
 
180
 
  fd_set readfds;
 
286
  fd_set readfds, writefds;
181
287
  FD_ZERO( &readfds );
182
 
  FD_SET( fd, &readfds );
 
288
  FD_ZERO( &writefds );
 
289
  if(waitForRead)
 
290
    FD_SET( fd, &readfds );
 
291
  else
 
292
    FD_SET( fd, &writefds );
183
293
 
184
 
  ret = select( fd + 1, &readfds, NULL, NULL, &tv );
 
294
  ret = select( fd + 1, &readfds, &writefds, NULL, &tv );
185
295
  if ( ret == -1 )
186
296
    errno = ETIMEDOUT;
187
297
 
287
397
  return strerror(errno);
288
398
}
289
399
 
 
400
#ifdef WIN32
 
401
string netstringerror()
 
402
{
 
403
  char buf[512];
 
404
  int err=WSAGetLastError();
 
405
  if(FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
 
406
                     0, buf, sizeof(buf)-1, NULL)) {
 
407
    return string(buf);
 
408
  }
 
409
  else {
 
410
    return strerror(err);
 
411
  }
 
412
}
 
413
#else
 
414
string netstringerror()
 
415
{
 
416
  return stringerror();
 
417
}
 
418
#endif
 
419
 
290
420
void cleanSlashes(string &str)
291
421
{
292
422
  string::const_iterator i;
308
438
  }
309
439
  
310
440
  struct in_addr inp;
311
 
  if(inet_aton(str.c_str(), &inp)) {
 
441
  if(Utility::inet_aton(str.c_str(), &inp)) {
312
442
    *ip=inp.s_addr;
313
443
    return true;
314
444
  }
315
445
  return false;
316
446
}
317
447
 
318
 
const string sockAddrToString(struct sockaddr_in *remote, Utility::socklen_t socklen) 
 
448
string U32ToIP(uint32_t val)
 
449
{
 
450
  char tmp[17];
 
451
  snprintf(tmp, sizeof(tmp)-1, "%u.%u.%u.%u", 
 
452
           (val >> 24)&0xff,
 
453
           (val >> 16)&0xff,
 
454
           (val >>  8)&0xff,
 
455
           (val      )&0xff);
 
456
  return tmp;
 
457
}
 
458
 
 
459
 
 
460
const string sockAddrToString(struct sockaddr_in *remote) 
319
461
{    
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);
324
466
  }
325
 
#ifdef HAVE_IPV6
326
467
  else {
327
468
    char tmp[128];
328
469
    
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";
331
472
 
332
473
    return tmp;
333
474
  }
334
 
#endif
335
 
 
336
 
  return "untranslateable";
337
475
}
338
476
 
339
477
string makeHexDump(const string& str)
378
516
 
379
517
  // we don't shuffle the rest
380
518
}
 
519
 
 
520
 
 
521
void normalizeTV(struct timeval& tv)
 
522
{
 
523
  if(tv.tv_usec > 1000000) {
 
524
    ++tv.tv_sec;
 
525
    tv.tv_usec-=1000000;
 
526
  }
 
527
  else if(tv.tv_usec < 0) {
 
528
    --tv.tv_sec;
 
529
    tv.tv_usec+=1000000;
 
530
  }
 
531
}
 
532
 
 
533
const struct timeval operator+(const struct timeval& lhs, const struct timeval& rhs)
 
534
{
 
535
  struct timeval ret;
 
536
  ret.tv_sec=lhs.tv_sec + rhs.tv_sec;
 
537
  ret.tv_usec=lhs.tv_usec + rhs.tv_usec;
 
538
  normalizeTV(ret);
 
539
  return ret;
 
540
}
 
541
 
 
542
const struct timeval operator-(const struct timeval& lhs, const struct timeval& rhs)
 
543
{
 
544
  struct timeval ret;
 
545
  ret.tv_sec=lhs.tv_sec - rhs.tv_sec;
 
546
  ret.tv_usec=lhs.tv_usec - rhs.tv_usec;
 
547
  normalizeTV(ret);
 
548
  return ret;
 
549
}
 
550
 
 
551
pair<string, string> splitField(const string& inp, char sepa)
 
552
{
 
553
  pair<string, string> ret;
 
554
  string::size_type cpos=inp.find(sepa);
 
555
  if(cpos==string::npos)
 
556
    ret.first=inp;
 
557
  else {
 
558
    ret.first=inp.substr(0, cpos);
 
559
    ret.second=inp.substr(cpos+1);
 
560
  }
 
561
  return ret;
 
562
}
 
563
 
 
564
boost::optional<int> logFacilityToLOG(unsigned int facility)
 
565
{
 
566
  boost::optional<int> ret;
 
567
 
 
568
  switch(facility) {
 
569
  case 0:
 
570
    return LOG_LOCAL0;
 
571
  case 1:
 
572
    return(LOG_LOCAL1);
 
573
  case 2:
 
574
    return(LOG_LOCAL2);
 
575
  case 3:
 
576
    return(LOG_LOCAL3);
 
577
  case 4:
 
578
    return(LOG_LOCAL4);
 
579
  case 5:
 
580
    return(LOG_LOCAL5);
 
581
  case 6:
 
582
    return(LOG_LOCAL6);
 
583
  case 7:
 
584
    return(LOG_LOCAL7);
 
585
  default:
 
586
    return ret;
 
587
  }
 
588
}
 
589
 
 
590
string stripDot(const string& dom)
 
591
{
 
592
  if(dom.empty())
 
593
    return dom;
 
594
 
 
595
  if(dom[dom.size()-1]!='.')
 
596
    return dom;
 
597
 
 
598
  return dom.substr(0,dom.size()-1);
 
599
}