]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/lwres.cc
move timeval arithmetic away from dnsreplay-mindex, make DTime able to save a few...
[thirdparty/pdns.git] / pdns / lwres.cc
CommitLineData
e14f094b
BH
1/*
2 PowerDNS Versatile Database Driven Nameserver
d0166f4a 3 Copyright (C) 2002 - 2005 PowerDNS.COM BV
e14f094b
BH
4
5 This program is free software; you can redistribute it and/or modify
d0166f4a
BH
6 it under the terms of the GNU General Public License version 2 as
7 published by the Free Software Foundation
e14f094b
BH
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17*/
36c5ee42 18#include "utility.hh"
e14f094b
BH
19#include "lwres.hh"
20#include <pthread.h>
21#include <semaphore.h>
22#include <iostream>
23#include <errno.h>
24#include "misc.hh"
25#include <algorithm>
26#include <sstream>
27#include <cstring>
28#include <string>
29#include <vector>
30#include "dnspacket.hh"
31#include "dns.hh"
32#include "qtype.hh"
33#include "tcpreceiver.hh"
34#include "ahuexception.hh"
35#include "statbag.hh"
36#include "arguments.hh"
5c633640
BH
37#include "sstuff.hh"
38#include "syncres.hh"
ea634573
BH
39#include "dnswriter.hh"
40#include "dnsparser.hh"
e14f094b
BH
41
42LWRes::LWRes()
43{
44 d_sock=-1;
45 d_timeout=500000;
b636533b
BH
46 d_bufsize=1500;
47 d_buf=new unsigned char[d_bufsize];
e14f094b
BH
48}
49
50LWRes::~LWRes()
51{
52 if(d_sock>=0)
53 Utility::closesocket(d_sock);
54 delete[] d_buf;
55}
56
57
58//! returns -1 for permanent error, 0 for timeout, 1 for success
59/** Never throws! */
5c633640 60int LWRes::asyncresolve(const string &ip, const char *domain, int type, bool doTCP)
e14f094b 61{
ea634573
BH
62 vector<uint8_t> vpacket;
63 DNSPacketWriter pw(vpacket, domain, type);
64
65 pw.getHeader()->rd=0;
8a63d3ce 66 pw.getHeader()->id=random();
e14f094b
BH
67 d_domain=domain;
68 d_type=type;
69 d_inaxfr=false;
36f5e3db 70 d_rcode=0;
e14f094b
BH
71
72 struct sockaddr_in toaddr;
73 struct in_addr inp;
5c633640 74 Utility::socklen_t addrlen=sizeof(toaddr);
e14f094b
BH
75 Utility::inet_aton(ip.c_str(),&inp);
76 toaddr.sin_addr.s_addr=inp.s_addr;
77
78 toaddr.sin_port=htons(53);
79 toaddr.sin_family=AF_INET;
80
eefd15f9
BH
81 int ret;
82
83 DTime dt;
84 dt.set();
5c633640
BH
85
86 if(!doTCP) {
ea634573 87 if(asendto((const char*)&*vpacket.begin(), vpacket.size(), 0, (struct sockaddr*)(&toaddr), sizeof(toaddr), pw.getHeader()->id)<0) {
5c633640
BH
88 return -1;
89 }
90
91 // sleep until we see an answer to this, interface to mtasker
92
ea634573 93 ret=arecvfrom(reinterpret_cast<char *>(d_buf), d_bufsize-1,0,(struct sockaddr*)(&toaddr), &addrlen, &d_len, pw.getHeader()->id);
e14f094b 94 }
5c633640
BH
95 else {
96 Socket s(InterNetwork, Stream);
97 IPEndpoint ie(ip, 53);
98 s.setNonBlocking();
99 s.connect(ie);
100
ea634573 101 unsigned int len=htons(vpacket.size());
5c633640 102 char *lenP=(char*)&len;
ea634573
BH
103 const char *msgP=(const char*)&*vpacket.begin();
104 string packet=string(lenP, lenP+2)+string(msgP, msgP+vpacket.size());
5c633640
BH
105
106 if(asendtcp(packet, &s) == 0) {
d0166f4a
BH
107 // cerr<<"asendtcp: timeout"<<endl;
108 return 0;
5c633640 109 }
eefd15f9 110
5c633640
BH
111 packet.clear();
112 if(arecvtcp(packet,2, &s)==0) {
d0166f4a
BH
113 // cerr<<"arecvtcp: timeout"<<endl;
114 return 0;
5c633640
BH
115 }
116
117 memcpy(&len, packet.c_str(), 2);
118 len=ntohs(len);
119
120 // cerr<<"Now reading "<<len<<" bytes"<<endl;
121
122 if(arecvtcp(packet, len, &s)==0) {
d0166f4a
BH
123 // cerr<<"arecvtcp: timeout"<<endl;
124 return 0;
5c633640 125 }
ea634573 126 if(len > (unsigned int)d_bufsize) {
66ab6a63
BH
127 d_bufsize=len;
128 delete[] d_buf;
129 d_buf = new unsigned char[d_bufsize];
130 }
5c633640
BH
131 memcpy(d_buf, packet.c_str(), len);
132 d_len=len;
133 ret=1;
134 }
135 d_usec=dt.udiff();
36c5ee42 136
eefd15f9 137 return ret;
e14f094b
BH
138}
139
140
eefd15f9 141LWRes::res_t LWRes::result()
e14f094b 142{
c836dc19 143 try {
ea634573
BH
144 MOADNSParser mdp((const char*)d_buf, d_len);
145 // if(p.parse((char *)d_buf, d_len)<0)
146 // throw LWResException("resolver: unable to parse packet of "+itoa(d_len)+" bytes");
147 d_aabit=mdp.d_header.aa;
148 d_tcbit=mdp.d_header.tc;
149 d_rcode=mdp.d_header.rcode;
150
ea634573
BH
151 LWRes::res_t ret;
152 for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {
153 // cout<<i->first.d_place<<"\t"<<i->first.d_label<<"\tIN\t"<<DNSRecordContent::NumberToType(i->first.d_type);
154 // cout<<"\t"<<i->first.d_ttl<<"\t"<< i->first.d_content->getZoneRepresentation()<<endl;
155 DNSResourceRecord rr;
156 rr.qtype=i->first.d_type;
157 rr.qname=i->first.d_label;
158 rr.ttl=i->first.d_ttl;
159 rr.content=i->first.d_content->getZoneRepresentation(); // this should be the serialised form
160
161 rr.d_place=(DNSResourceRecord::Place) i->first.d_place;
162 ret.push_back(rr);
163 }
164
165 return ret;
166 // return p.getAnswers();
c836dc19
BH
167 }
168 catch(...) {
169 d_rcode=RCode::ServFail;
170 LWRes::res_t empty;
171 return empty;
172 }
e14f094b
BH
173}
174