Blame


1 3e0d8fb3 2005-12-27 devnull #include <u.h>
2 4936c293 2006-05-06 devnull #include <sys/time.h>
3 3e0d8fb3 2005-12-27 devnull #include <libc.h>
4 3e0d8fb3 2005-12-27 devnull #include <ip.h>
5 3e0d8fb3 2005-12-27 devnull #include <bio.h>
6 3e0d8fb3 2005-12-27 devnull #include <ndb.h>
7 3e0d8fb3 2005-12-27 devnull #include "dns.h"
8 3e0d8fb3 2005-12-27 devnull
9 3e0d8fb3 2005-12-27 devnull enum
10 3e0d8fb3 2005-12-27 devnull {
11 3e0d8fb3 2005-12-27 devnull Maxdest= 24, /* maximum destinations for a request message */
12 226d80b8 2006-04-01 devnull Maxtrans= 3 /* maximum transmissions to a server */
13 3e0d8fb3 2005-12-27 devnull };
14 3e0d8fb3 2005-12-27 devnull
15 3e0d8fb3 2005-12-27 devnull static int netquery(DN*, int, RR*, Request*, int);
16 3e0d8fb3 2005-12-27 devnull static RR* dnresolve1(char*, int, int, Request*, int, int);
17 3e0d8fb3 2005-12-27 devnull
18 3e0d8fb3 2005-12-27 devnull char *LOG = "dns";
19 3e0d8fb3 2005-12-27 devnull
20 3e0d8fb3 2005-12-27 devnull /*
21 3e0d8fb3 2005-12-27 devnull * lookup 'type' info for domain name 'name'. If it doesn't exist, try
22 3e0d8fb3 2005-12-27 devnull * looking it up as a canonical name.
23 3e0d8fb3 2005-12-27 devnull */
24 3e0d8fb3 2005-12-27 devnull RR*
25 3e0d8fb3 2005-12-27 devnull dnresolve(char *name, int class, int type, Request *req, RR **cn, int depth, int recurse, int rooted, int *status)
26 3e0d8fb3 2005-12-27 devnull {
27 3e0d8fb3 2005-12-27 devnull RR *rp, *nrp, *drp;
28 3e0d8fb3 2005-12-27 devnull DN *dp;
29 3e0d8fb3 2005-12-27 devnull int loops;
30 3e0d8fb3 2005-12-27 devnull char nname[Domlen];
31 3e0d8fb3 2005-12-27 devnull
32 3e0d8fb3 2005-12-27 devnull if(status)
33 3e0d8fb3 2005-12-27 devnull *status = 0;
34 3e0d8fb3 2005-12-27 devnull
35 3e0d8fb3 2005-12-27 devnull /*
36 3e0d8fb3 2005-12-27 devnull * hack for systems that don't have resolve search
37 3e0d8fb3 2005-12-27 devnull * lists. Just look up the simple name in the database.
38 3e0d8fb3 2005-12-27 devnull */
39 3e0d8fb3 2005-12-27 devnull if(!rooted && strchr(name, '.') == 0){
40 3e0d8fb3 2005-12-27 devnull rp = nil;
41 3e0d8fb3 2005-12-27 devnull drp = domainlist(class);
42 3e0d8fb3 2005-12-27 devnull for(nrp = drp; nrp != nil; nrp = nrp->next){
43 3e0d8fb3 2005-12-27 devnull snprint(nname, sizeof(nname), "%s.%s", name, nrp->ptr->name);
44 3e0d8fb3 2005-12-27 devnull rp = dnresolve(nname, class, type, req,cn, depth, recurse, rooted, status);
45 3e0d8fb3 2005-12-27 devnull rrfreelist(rrremneg(&rp));
46 3e0d8fb3 2005-12-27 devnull if(rp != nil)
47 3e0d8fb3 2005-12-27 devnull break;
48 3e0d8fb3 2005-12-27 devnull }
49 3e0d8fb3 2005-12-27 devnull if(drp != nil)
50 3e0d8fb3 2005-12-27 devnull rrfree(drp);
51 3e0d8fb3 2005-12-27 devnull return rp;
52 3e0d8fb3 2005-12-27 devnull }
53 3e0d8fb3 2005-12-27 devnull
54 3e0d8fb3 2005-12-27 devnull /*
55 3e0d8fb3 2005-12-27 devnull * try the name directly
56 3e0d8fb3 2005-12-27 devnull */
57 3e0d8fb3 2005-12-27 devnull rp = dnresolve1(name, class, type, req, depth, recurse);
58 3e0d8fb3 2005-12-27 devnull if(rp)
59 3e0d8fb3 2005-12-27 devnull return randomize(rp);
60 3e0d8fb3 2005-12-27 devnull
61 3e0d8fb3 2005-12-27 devnull /* try it as a canonical name if we weren't told the name didn't exist */
62 3e0d8fb3 2005-12-27 devnull dp = dnlookup(name, class, 0);
63 3e0d8fb3 2005-12-27 devnull if(type != Tptr && dp->nonexistent != Rname){
64 3e0d8fb3 2005-12-27 devnull for(loops=0; rp == nil && loops < 32; loops++){
65 3e0d8fb3 2005-12-27 devnull rp = dnresolve1(name, class, Tcname, req, depth, recurse);
66 3e0d8fb3 2005-12-27 devnull if(rp == nil)
67 3e0d8fb3 2005-12-27 devnull break;
68 3e0d8fb3 2005-12-27 devnull
69 3e0d8fb3 2005-12-27 devnull if(rp->negative){
70 3e0d8fb3 2005-12-27 devnull rrfreelist(rp);
71 3e0d8fb3 2005-12-27 devnull rp = nil;
72 3e0d8fb3 2005-12-27 devnull break;
73 3e0d8fb3 2005-12-27 devnull }
74 3e0d8fb3 2005-12-27 devnull
75 3e0d8fb3 2005-12-27 devnull name = rp->host->name;
76 3e0d8fb3 2005-12-27 devnull if(cn)
77 3e0d8fb3 2005-12-27 devnull rrcat(cn, rp);
78 3e0d8fb3 2005-12-27 devnull else
79 3e0d8fb3 2005-12-27 devnull rrfreelist(rp);
80 3e0d8fb3 2005-12-27 devnull
81 3e0d8fb3 2005-12-27 devnull rp = dnresolve1(name, class, type, req, depth, recurse);
82 3e0d8fb3 2005-12-27 devnull }
83 3e0d8fb3 2005-12-27 devnull }
84 3e0d8fb3 2005-12-27 devnull
85 3e0d8fb3 2005-12-27 devnull /* distinction between not found and not good */
86 3e0d8fb3 2005-12-27 devnull if(rp == 0 && status != 0 && dp->nonexistent != 0)
87 3e0d8fb3 2005-12-27 devnull *status = dp->nonexistent;
88 3e0d8fb3 2005-12-27 devnull
89 3e0d8fb3 2005-12-27 devnull return randomize(rp);
90 3e0d8fb3 2005-12-27 devnull }
91 3e0d8fb3 2005-12-27 devnull
92 3e0d8fb3 2005-12-27 devnull static RR*
93 3e0d8fb3 2005-12-27 devnull dnresolve1(char *name, int class, int type, Request *req, int depth, int recurse)
94 3e0d8fb3 2005-12-27 devnull {
95 3e0d8fb3 2005-12-27 devnull DN *dp, *nsdp;
96 3e0d8fb3 2005-12-27 devnull RR *rp, *nsrp, *dbnsrp;
97 3e0d8fb3 2005-12-27 devnull char *cp;
98 3e0d8fb3 2005-12-27 devnull
99 3e0d8fb3 2005-12-27 devnull if(debug)
100 3e0d8fb3 2005-12-27 devnull syslog(0, LOG, "dnresolve1 %s %d %d", name, type, class);
101 3e0d8fb3 2005-12-27 devnull
102 3e0d8fb3 2005-12-27 devnull /* only class Cin implemented so far */
103 3e0d8fb3 2005-12-27 devnull if(class != Cin)
104 3e0d8fb3 2005-12-27 devnull return 0;
105 3e0d8fb3 2005-12-27 devnull
106 3e0d8fb3 2005-12-27 devnull dp = dnlookup(name, class, 1);
107 3e0d8fb3 2005-12-27 devnull
108 3e0d8fb3 2005-12-27 devnull /*
109 3e0d8fb3 2005-12-27 devnull * Try the cache first
110 3e0d8fb3 2005-12-27 devnull */
111 3e0d8fb3 2005-12-27 devnull rp = rrlookup(dp, type, OKneg);
112 3e0d8fb3 2005-12-27 devnull if(rp){
113 3e0d8fb3 2005-12-27 devnull if(rp->db){
114 3e0d8fb3 2005-12-27 devnull /* unauthenticated db entries are hints */
115 3e0d8fb3 2005-12-27 devnull if(rp->auth)
116 3e0d8fb3 2005-12-27 devnull return rp;
117 3e0d8fb3 2005-12-27 devnull } else {
118 3e0d8fb3 2005-12-27 devnull /* cached entry must still be valid */
119 3e0d8fb3 2005-12-27 devnull if(rp->ttl > now){
120 3e0d8fb3 2005-12-27 devnull /* but Tall entries are special */
121 3e0d8fb3 2005-12-27 devnull if(type != Tall || rp->query == Tall)
122 3e0d8fb3 2005-12-27 devnull return rp;
123 3e0d8fb3 2005-12-27 devnull }
124 3e0d8fb3 2005-12-27 devnull }
125 3e0d8fb3 2005-12-27 devnull }
126 3e0d8fb3 2005-12-27 devnull rrfreelist(rp);
127 3e0d8fb3 2005-12-27 devnull
128 3e0d8fb3 2005-12-27 devnull /*
129 3e0d8fb3 2005-12-27 devnull * try the cache for a canonical name. if found punt
130 3e0d8fb3 2005-12-27 devnull * since we'll find it during the canonical name search
131 3e0d8fb3 2005-12-27 devnull * in dnresolve().
132 3e0d8fb3 2005-12-27 devnull */
133 3e0d8fb3 2005-12-27 devnull if(type != Tcname){
134 3e0d8fb3 2005-12-27 devnull rp = rrlookup(dp, Tcname, NOneg);
135 3e0d8fb3 2005-12-27 devnull rrfreelist(rp);
136 3e0d8fb3 2005-12-27 devnull if(rp)
137 3e0d8fb3 2005-12-27 devnull return 0;
138 3e0d8fb3 2005-12-27 devnull }
139 3e0d8fb3 2005-12-27 devnull
140 3e0d8fb3 2005-12-27 devnull /*
141 3e0d8fb3 2005-12-27 devnull * if we're running as just a resolver, go to our
142 3e0d8fb3 2005-12-27 devnull * designated name servers
143 3e0d8fb3 2005-12-27 devnull */
144 3e0d8fb3 2005-12-27 devnull if(resolver){
145 3e0d8fb3 2005-12-27 devnull nsrp = randomize(getdnsservers(class));
146 3e0d8fb3 2005-12-27 devnull if(nsrp != nil) {
147 3e0d8fb3 2005-12-27 devnull if(netquery(dp, type, nsrp, req, depth+1)){
148 3e0d8fb3 2005-12-27 devnull rrfreelist(nsrp);
149 3e0d8fb3 2005-12-27 devnull return rrlookup(dp, type, OKneg);
150 3e0d8fb3 2005-12-27 devnull }
151 3e0d8fb3 2005-12-27 devnull rrfreelist(nsrp);
152 3e0d8fb3 2005-12-27 devnull }
153 3e0d8fb3 2005-12-27 devnull }
154 3e0d8fb3 2005-12-27 devnull
155 3e0d8fb3 2005-12-27 devnull /*
156 3e0d8fb3 2005-12-27 devnull * walk up the domain name looking for
157 3e0d8fb3 2005-12-27 devnull * a name server for the domain.
158 3e0d8fb3 2005-12-27 devnull */
159 3e0d8fb3 2005-12-27 devnull for(cp = name; cp; cp = walkup(cp)){
160 3e0d8fb3 2005-12-27 devnull /*
161 3e0d8fb3 2005-12-27 devnull * if this is a local (served by us) domain,
162 3e0d8fb3 2005-12-27 devnull * return answer
163 3e0d8fb3 2005-12-27 devnull */
164 3e0d8fb3 2005-12-27 devnull dbnsrp = randomize(dblookup(cp, class, Tns, 0, 0));
165 3e0d8fb3 2005-12-27 devnull if(dbnsrp && dbnsrp->local){
166 3e0d8fb3 2005-12-27 devnull rp = dblookup(name, class, type, 1, dbnsrp->ttl);
167 3e0d8fb3 2005-12-27 devnull rrfreelist(dbnsrp);
168 3e0d8fb3 2005-12-27 devnull return rp;
169 3e0d8fb3 2005-12-27 devnull }
170 3e0d8fb3 2005-12-27 devnull
171 3e0d8fb3 2005-12-27 devnull /*
172 3e0d8fb3 2005-12-27 devnull * if recursion isn't set, just accept local
173 3e0d8fb3 2005-12-27 devnull * entries
174 3e0d8fb3 2005-12-27 devnull */
175 3e0d8fb3 2005-12-27 devnull if(recurse == Dontrecurse){
176 3e0d8fb3 2005-12-27 devnull if(dbnsrp)
177 3e0d8fb3 2005-12-27 devnull rrfreelist(dbnsrp);
178 3e0d8fb3 2005-12-27 devnull continue;
179 3e0d8fb3 2005-12-27 devnull }
180 3e0d8fb3 2005-12-27 devnull
181 3e0d8fb3 2005-12-27 devnull /* look for ns in cache */
182 3e0d8fb3 2005-12-27 devnull nsdp = dnlookup(cp, class, 0);
183 3e0d8fb3 2005-12-27 devnull nsrp = nil;
184 3e0d8fb3 2005-12-27 devnull if(nsdp)
185 3e0d8fb3 2005-12-27 devnull nsrp = randomize(rrlookup(nsdp, Tns, NOneg));
186 3e0d8fb3 2005-12-27 devnull
187 3e0d8fb3 2005-12-27 devnull /* if the entry timed out, ignore it */
188 3e0d8fb3 2005-12-27 devnull if(nsrp && nsrp->ttl < now){
189 3e0d8fb3 2005-12-27 devnull rrfreelist(nsrp);
190 3e0d8fb3 2005-12-27 devnull nsrp = nil;
191 3e0d8fb3 2005-12-27 devnull }
192 3e0d8fb3 2005-12-27 devnull
193 3e0d8fb3 2005-12-27 devnull if(nsrp){
194 3e0d8fb3 2005-12-27 devnull rrfreelist(dbnsrp);
195 3e0d8fb3 2005-12-27 devnull
196 3e0d8fb3 2005-12-27 devnull /* try the name servers found in cache */
197 3e0d8fb3 2005-12-27 devnull if(netquery(dp, type, nsrp, req, depth+1)){
198 3e0d8fb3 2005-12-27 devnull rrfreelist(nsrp);
199 3e0d8fb3 2005-12-27 devnull return rrlookup(dp, type, OKneg);
200 3e0d8fb3 2005-12-27 devnull }
201 3e0d8fb3 2005-12-27 devnull rrfreelist(nsrp);
202 3e0d8fb3 2005-12-27 devnull continue;
203 3e0d8fb3 2005-12-27 devnull }
204 3e0d8fb3 2005-12-27 devnull
205 3e0d8fb3 2005-12-27 devnull /* use ns from db */
206 3e0d8fb3 2005-12-27 devnull if(dbnsrp){
207 3e0d8fb3 2005-12-27 devnull /* try the name servers found in db */
208 3e0d8fb3 2005-12-27 devnull if(netquery(dp, type, dbnsrp, req, depth+1)){
209 3e0d8fb3 2005-12-27 devnull /* we got an answer */
210 3e0d8fb3 2005-12-27 devnull rrfreelist(dbnsrp);
211 3e0d8fb3 2005-12-27 devnull return rrlookup(dp, type, NOneg);
212 3e0d8fb3 2005-12-27 devnull }
213 3e0d8fb3 2005-12-27 devnull rrfreelist(dbnsrp);
214 3e0d8fb3 2005-12-27 devnull }
215 3e0d8fb3 2005-12-27 devnull }
216 3e0d8fb3 2005-12-27 devnull
217 3e0d8fb3 2005-12-27 devnull /* settle for a non-authoritative answer */
218 3e0d8fb3 2005-12-27 devnull rp = rrlookup(dp, type, OKneg);
219 3e0d8fb3 2005-12-27 devnull if(rp)
220 3e0d8fb3 2005-12-27 devnull return rp;
221 3e0d8fb3 2005-12-27 devnull
222 3e0d8fb3 2005-12-27 devnull /* noone answered. try the database, we might have a chance. */
223 3e0d8fb3 2005-12-27 devnull return dblookup(name, class, type, 0, 0);
224 3e0d8fb3 2005-12-27 devnull }
225 3e0d8fb3 2005-12-27 devnull
226 3e0d8fb3 2005-12-27 devnull /*
227 3e0d8fb3 2005-12-27 devnull * walk a domain name one element to the right. return a pointer to that element.
228 3e0d8fb3 2005-12-27 devnull * in other words, return a pointer to the parent domain name.
229 3e0d8fb3 2005-12-27 devnull */
230 3e0d8fb3 2005-12-27 devnull char*
231 3e0d8fb3 2005-12-27 devnull walkup(char *name)
232 3e0d8fb3 2005-12-27 devnull {
233 3e0d8fb3 2005-12-27 devnull char *cp;
234 3e0d8fb3 2005-12-27 devnull
235 3e0d8fb3 2005-12-27 devnull cp = strchr(name, '.');
236 3e0d8fb3 2005-12-27 devnull if(cp)
237 3e0d8fb3 2005-12-27 devnull return cp+1;
238 3e0d8fb3 2005-12-27 devnull else if(*name)
239 3e0d8fb3 2005-12-27 devnull return "";
240 3e0d8fb3 2005-12-27 devnull else
241 3e0d8fb3 2005-12-27 devnull return 0;
242 3e0d8fb3 2005-12-27 devnull }
243 3e0d8fb3 2005-12-27 devnull
244 3e0d8fb3 2005-12-27 devnull /*
245 3e0d8fb3 2005-12-27 devnull * Get a udpport for requests and replies.
246 3e0d8fb3 2005-12-27 devnull */
247 3e0d8fb3 2005-12-27 devnull int
248 3e0d8fb3 2005-12-27 devnull udpport(void)
249 3e0d8fb3 2005-12-27 devnull {
250 3e0d8fb3 2005-12-27 devnull int fd;
251 3e0d8fb3 2005-12-27 devnull
252 3e0d8fb3 2005-12-27 devnull if((fd = dial("udp!0!53", nil, nil, nil)) < 0)
253 3e0d8fb3 2005-12-27 devnull warning("can't get udp port");
254 3e0d8fb3 2005-12-27 devnull return fd;
255 3e0d8fb3 2005-12-27 devnull }
256 3e0d8fb3 2005-12-27 devnull
257 3e0d8fb3 2005-12-27 devnull int
258 3e0d8fb3 2005-12-27 devnull mkreq(DN *dp, int type, uchar *buf, int flags, ushort reqno)
259 3e0d8fb3 2005-12-27 devnull {
260 3e0d8fb3 2005-12-27 devnull DNSmsg m;
261 3e0d8fb3 2005-12-27 devnull int len;
262 5c9f76b5 2006-02-14 devnull Udphdr *uh = (Udphdr*)buf;
263 3e0d8fb3 2005-12-27 devnull
264 3e0d8fb3 2005-12-27 devnull /* stuff port number into output buffer */
265 3e0d8fb3 2005-12-27 devnull memset(uh, 0, sizeof(*uh));
266 3e0d8fb3 2005-12-27 devnull hnputs(uh->rport, 53);
267 3e0d8fb3 2005-12-27 devnull
268 3e0d8fb3 2005-12-27 devnull /* make request and convert it to output format */
269 3e0d8fb3 2005-12-27 devnull memset(&m, 0, sizeof(m));
270 3e0d8fb3 2005-12-27 devnull m.flags = flags;
271 3e0d8fb3 2005-12-27 devnull m.id = reqno;
272 3e0d8fb3 2005-12-27 devnull m.qd = rralloc(type);
273 3e0d8fb3 2005-12-27 devnull m.qd->owner = dp;
274 3e0d8fb3 2005-12-27 devnull m.qd->type = type;
275 5c9f76b5 2006-02-14 devnull len = convDNS2M(&m, &buf[Udphdrsize], Maxudp);
276 3e0d8fb3 2005-12-27 devnull if(len < 0)
277 3e0d8fb3 2005-12-27 devnull abort(); /* "can't convert" */;
278 3e0d8fb3 2005-12-27 devnull rrfree(m.qd);
279 3e0d8fb3 2005-12-27 devnull return len;
280 3e0d8fb3 2005-12-27 devnull }
281 3e0d8fb3 2005-12-27 devnull
282 3e0d8fb3 2005-12-27 devnull static void
283 3e0d8fb3 2005-12-27 devnull freeanswers(DNSmsg *mp)
284 3e0d8fb3 2005-12-27 devnull {
285 3e0d8fb3 2005-12-27 devnull rrfreelist(mp->qd);
286 3e0d8fb3 2005-12-27 devnull rrfreelist(mp->an);
287 3e0d8fb3 2005-12-27 devnull rrfreelist(mp->ns);
288 3e0d8fb3 2005-12-27 devnull rrfreelist(mp->ar);
289 3e0d8fb3 2005-12-27 devnull }
290 3e0d8fb3 2005-12-27 devnull
291 3e0d8fb3 2005-12-27 devnull /*
292 3e0d8fb3 2005-12-27 devnull * read replies to a request. ignore any of the wrong type. wait at most 5 seconds.
293 3e0d8fb3 2005-12-27 devnull */
294 49a1496c 2006-02-20 devnull static int udpreadtimeout(int, Udphdr*, void*, int, int);
295 3e0d8fb3 2005-12-27 devnull static int
296 3e0d8fb3 2005-12-27 devnull readreply(int fd, DN *dp, int type, ushort req,
297 3e0d8fb3 2005-12-27 devnull uchar *ibuf, DNSmsg *mp, ulong endtime, Request *reqp)
298 3e0d8fb3 2005-12-27 devnull {
299 3e0d8fb3 2005-12-27 devnull char *err;
300 3e0d8fb3 2005-12-27 devnull int len;
301 3e0d8fb3 2005-12-27 devnull ulong now;
302 3e0d8fb3 2005-12-27 devnull RR *rp;
303 3e0d8fb3 2005-12-27 devnull
304 3e0d8fb3 2005-12-27 devnull for(; ; freeanswers(mp)){
305 3e0d8fb3 2005-12-27 devnull now = time(0);
306 3e0d8fb3 2005-12-27 devnull if(now >= endtime)
307 3e0d8fb3 2005-12-27 devnull return -1; /* timed out */
308 3e0d8fb3 2005-12-27 devnull
309 3e0d8fb3 2005-12-27 devnull /* timed read */
310 49a1496c 2006-02-20 devnull len = udpreadtimeout(fd, (Udphdr*)ibuf, ibuf+Udphdrsize, Maxudpin, (endtime-now)*1000);
311 3e0d8fb3 2005-12-27 devnull if(len < 0)
312 3e0d8fb3 2005-12-27 devnull return -1; /* timed out */
313 3e0d8fb3 2005-12-27 devnull
314 3e0d8fb3 2005-12-27 devnull /* convert into internal format */
315 3e0d8fb3 2005-12-27 devnull memset(mp, 0, sizeof(*mp));
316 5c9f76b5 2006-02-14 devnull err = convM2DNS(&ibuf[Udphdrsize], len, mp);
317 3e0d8fb3 2005-12-27 devnull if(err){
318 3e0d8fb3 2005-12-27 devnull syslog(0, LOG, "input err %s: %I", err, ibuf);
319 3e0d8fb3 2005-12-27 devnull continue;
320 3e0d8fb3 2005-12-27 devnull }
321 3e0d8fb3 2005-12-27 devnull if(debug)
322 3e0d8fb3 2005-12-27 devnull logreply(reqp->id, ibuf, mp);
323 3e0d8fb3 2005-12-27 devnull
324 3e0d8fb3 2005-12-27 devnull /* answering the right question? */
325 3e0d8fb3 2005-12-27 devnull if(mp->id != req){
326 3e0d8fb3 2005-12-27 devnull syslog(0, LOG, "%d: id %d instead of %d: %I", reqp->id,
327 3e0d8fb3 2005-12-27 devnull mp->id, req, ibuf);
328 3e0d8fb3 2005-12-27 devnull continue;
329 3e0d8fb3 2005-12-27 devnull }
330 3e0d8fb3 2005-12-27 devnull if(mp->qd == 0){
331 3e0d8fb3 2005-12-27 devnull syslog(0, LOG, "%d: no question RR: %I", reqp->id, ibuf);
332 3e0d8fb3 2005-12-27 devnull continue;
333 3e0d8fb3 2005-12-27 devnull }
334 3e0d8fb3 2005-12-27 devnull if(mp->qd->owner != dp){
335 3e0d8fb3 2005-12-27 devnull syslog(0, LOG, "%d: owner %s instead of %s: %I", reqp->id,
336 3e0d8fb3 2005-12-27 devnull mp->qd->owner->name, dp->name, ibuf);
337 3e0d8fb3 2005-12-27 devnull continue;
338 3e0d8fb3 2005-12-27 devnull }
339 3e0d8fb3 2005-12-27 devnull if(mp->qd->type != type){
340 3e0d8fb3 2005-12-27 devnull syslog(0, LOG, "%d: type %d instead of %d: %I", reqp->id,
341 3e0d8fb3 2005-12-27 devnull mp->qd->type, type, ibuf);
342 3e0d8fb3 2005-12-27 devnull continue;
343 3e0d8fb3 2005-12-27 devnull }
344 3e0d8fb3 2005-12-27 devnull
345 3e0d8fb3 2005-12-27 devnull /* remember what request this is in answer to */
346 3e0d8fb3 2005-12-27 devnull for(rp = mp->an; rp; rp = rp->next)
347 3e0d8fb3 2005-12-27 devnull rp->query = type;
348 3e0d8fb3 2005-12-27 devnull
349 3e0d8fb3 2005-12-27 devnull return 0;
350 3e0d8fb3 2005-12-27 devnull }
351 3e0d8fb3 2005-12-27 devnull
352 3e0d8fb3 2005-12-27 devnull return 0; /* never reached */
353 3e0d8fb3 2005-12-27 devnull }
354 3e0d8fb3 2005-12-27 devnull
355 49a1496c 2006-02-20 devnull static int
356 49a1496c 2006-02-20 devnull udpreadtimeout(int fd, Udphdr *h, void *data, int n, int ms)
357 49a1496c 2006-02-20 devnull {
358 49a1496c 2006-02-20 devnull fd_set rd;
359 49a1496c 2006-02-20 devnull struct timeval tv;
360 49a1496c 2006-02-20 devnull
361 49a1496c 2006-02-20 devnull FD_ZERO(&rd);
362 49a1496c 2006-02-20 devnull FD_SET(fd, &rd);
363 49a1496c 2006-02-20 devnull
364 49a1496c 2006-02-20 devnull tv.tv_sec = ms/1000;
365 49a1496c 2006-02-20 devnull tv.tv_usec = (ms%1000)*1000;
366 49a1496c 2006-02-20 devnull
367 49a1496c 2006-02-20 devnull if(select(fd+1, &rd, 0, 0, &tv) != 1)
368 49a1496c 2006-02-20 devnull return -1;
369 49a1496c 2006-02-20 devnull return udpread(fd, h, data, n);
370 49a1496c 2006-02-20 devnull }
371 49a1496c 2006-02-20 devnull
372 3e0d8fb3 2005-12-27 devnull /*
373 3e0d8fb3 2005-12-27 devnull * return non-0 if first list includes second list
374 3e0d8fb3 2005-12-27 devnull */
375 3e0d8fb3 2005-12-27 devnull int
376 3e0d8fb3 2005-12-27 devnull contains(RR *rp1, RR *rp2)
377 3e0d8fb3 2005-12-27 devnull {
378 3e0d8fb3 2005-12-27 devnull RR *trp1, *trp2;
379 3e0d8fb3 2005-12-27 devnull
380 3e0d8fb3 2005-12-27 devnull for(trp2 = rp2; trp2; trp2 = trp2->next){
381 3e0d8fb3 2005-12-27 devnull for(trp1 = rp1; trp1; trp1 = trp1->next){
382 3e0d8fb3 2005-12-27 devnull if(trp1->type == trp2->type)
383 3e0d8fb3 2005-12-27 devnull if(trp1->host == trp2->host)
384 3e0d8fb3 2005-12-27 devnull if(trp1->owner == trp2->owner)
385 3e0d8fb3 2005-12-27 devnull break;
386 3e0d8fb3 2005-12-27 devnull }
387 3e0d8fb3 2005-12-27 devnull if(trp1 == 0)
388 3e0d8fb3 2005-12-27 devnull return 0;
389 3e0d8fb3 2005-12-27 devnull }
390 3e0d8fb3 2005-12-27 devnull
391 3e0d8fb3 2005-12-27 devnull return 1;
392 3e0d8fb3 2005-12-27 devnull }
393 3e0d8fb3 2005-12-27 devnull
394 3e0d8fb3 2005-12-27 devnull
395 3e0d8fb3 2005-12-27 devnull typedef struct Dest Dest;
396 3e0d8fb3 2005-12-27 devnull struct Dest
397 3e0d8fb3 2005-12-27 devnull {
398 3e0d8fb3 2005-12-27 devnull uchar a[IPaddrlen]; /* ip address */
399 3e0d8fb3 2005-12-27 devnull DN *s; /* name server */
400 3e0d8fb3 2005-12-27 devnull int nx; /* number of transmissions */
401 3e0d8fb3 2005-12-27 devnull int code;
402 3e0d8fb3 2005-12-27 devnull };
403 3e0d8fb3 2005-12-27 devnull
404 3e0d8fb3 2005-12-27 devnull
405 3e0d8fb3 2005-12-27 devnull /*
406 3e0d8fb3 2005-12-27 devnull * return multicast version if any
407 3e0d8fb3 2005-12-27 devnull */
408 3e0d8fb3 2005-12-27 devnull int
409 3e0d8fb3 2005-12-27 devnull ipisbm(uchar *ip)
410 3e0d8fb3 2005-12-27 devnull {
411 3e0d8fb3 2005-12-27 devnull if(isv4(ip)){
412 3e0d8fb3 2005-12-27 devnull if(ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0)
413 3e0d8fb3 2005-12-27 devnull return 4;
414 3e0d8fb3 2005-12-27 devnull if(ipcmp(ip, IPv4bcast) == 0)
415 3e0d8fb3 2005-12-27 devnull return 4;
416 3e0d8fb3 2005-12-27 devnull } else {
417 3e0d8fb3 2005-12-27 devnull if(ip[0] == 0xff)
418 3e0d8fb3 2005-12-27 devnull return 6;
419 3e0d8fb3 2005-12-27 devnull }
420 3e0d8fb3 2005-12-27 devnull return 0;
421 3e0d8fb3 2005-12-27 devnull }
422 3e0d8fb3 2005-12-27 devnull
423 3e0d8fb3 2005-12-27 devnull /*
424 3e0d8fb3 2005-12-27 devnull * Get next server address
425 3e0d8fb3 2005-12-27 devnull */
426 3e0d8fb3 2005-12-27 devnull static int
427 3e0d8fb3 2005-12-27 devnull serveraddrs(RR *nsrp, Dest *dest, int nd, int depth, Request *reqp)
428 3e0d8fb3 2005-12-27 devnull {
429 3e0d8fb3 2005-12-27 devnull RR *rp, *arp, *trp;
430 3e0d8fb3 2005-12-27 devnull Dest *cur;
431 3e0d8fb3 2005-12-27 devnull
432 3e0d8fb3 2005-12-27 devnull if(nd >= Maxdest)
433 3e0d8fb3 2005-12-27 devnull return 0;
434 3e0d8fb3 2005-12-27 devnull
435 3e0d8fb3 2005-12-27 devnull /*
436 3e0d8fb3 2005-12-27 devnull * look for a server whose address we already know.
437 3e0d8fb3 2005-12-27 devnull * if we find one, mark it so we ignore this on
438 3e0d8fb3 2005-12-27 devnull * subsequent passes.
439 3e0d8fb3 2005-12-27 devnull */
440 3e0d8fb3 2005-12-27 devnull arp = 0;
441 3e0d8fb3 2005-12-27 devnull for(rp = nsrp; rp; rp = rp->next){
442 3e0d8fb3 2005-12-27 devnull assert(rp->magic == RRmagic);
443 3e0d8fb3 2005-12-27 devnull if(rp->marker)
444 3e0d8fb3 2005-12-27 devnull continue;
445 3e0d8fb3 2005-12-27 devnull arp = rrlookup(rp->host, Ta, NOneg);
446 3e0d8fb3 2005-12-27 devnull if(arp){
447 3e0d8fb3 2005-12-27 devnull rp->marker = 1;
448 3e0d8fb3 2005-12-27 devnull break;
449 3e0d8fb3 2005-12-27 devnull }
450 3e0d8fb3 2005-12-27 devnull arp = dblookup(rp->host->name, Cin, Ta, 0, 0);
451 3e0d8fb3 2005-12-27 devnull if(arp){
452 3e0d8fb3 2005-12-27 devnull rp->marker = 1;
453 3e0d8fb3 2005-12-27 devnull break;
454 3e0d8fb3 2005-12-27 devnull }
455 3e0d8fb3 2005-12-27 devnull }
456 3e0d8fb3 2005-12-27 devnull
457 3e0d8fb3 2005-12-27 devnull /*
458 3e0d8fb3 2005-12-27 devnull * if the cache and database lookup didn't find any new
459 3e0d8fb3 2005-12-27 devnull * server addresses, try resolving one via the network.
460 3e0d8fb3 2005-12-27 devnull * Mark any we try to resolve so we don't try a second time.
461 3e0d8fb3 2005-12-27 devnull */
462 3e0d8fb3 2005-12-27 devnull if(arp == 0){
463 3e0d8fb3 2005-12-27 devnull for(rp = nsrp; rp; rp = rp->next){
464 3e0d8fb3 2005-12-27 devnull if(rp->marker)
465 3e0d8fb3 2005-12-27 devnull continue;
466 3e0d8fb3 2005-12-27 devnull rp->marker = 1;
467 3e0d8fb3 2005-12-27 devnull
468 3e0d8fb3 2005-12-27 devnull /*
469 3e0d8fb3 2005-12-27 devnull * avoid loops looking up a server under itself
470 3e0d8fb3 2005-12-27 devnull */
471 3e0d8fb3 2005-12-27 devnull if(subsume(rp->owner->name, rp->host->name))
472 3e0d8fb3 2005-12-27 devnull continue;
473 3e0d8fb3 2005-12-27 devnull
474 3e0d8fb3 2005-12-27 devnull arp = dnresolve(rp->host->name, Cin, Ta, reqp, 0, depth+1, Recurse, 1, 0);
475 3e0d8fb3 2005-12-27 devnull rrfreelist(rrremneg(&arp));
476 3e0d8fb3 2005-12-27 devnull if(arp)
477 3e0d8fb3 2005-12-27 devnull break;
478 3e0d8fb3 2005-12-27 devnull }
479 3e0d8fb3 2005-12-27 devnull }
480 3e0d8fb3 2005-12-27 devnull
481 3e0d8fb3 2005-12-27 devnull /* use any addresses that we found */
482 3e0d8fb3 2005-12-27 devnull for(trp = arp; trp; trp = trp->next){
483 3e0d8fb3 2005-12-27 devnull if(nd >= Maxdest)
484 3e0d8fb3 2005-12-27 devnull break;
485 3e0d8fb3 2005-12-27 devnull cur = &dest[nd];
486 3e0d8fb3 2005-12-27 devnull parseip(cur->a, trp->ip->name);
487 3e0d8fb3 2005-12-27 devnull if(ipisbm(cur->a))
488 3e0d8fb3 2005-12-27 devnull continue;
489 3e0d8fb3 2005-12-27 devnull cur->nx = 0;
490 3e0d8fb3 2005-12-27 devnull cur->s = trp->owner;
491 3e0d8fb3 2005-12-27 devnull cur->code = Rtimeout;
492 3e0d8fb3 2005-12-27 devnull nd++;
493 3e0d8fb3 2005-12-27 devnull }
494 3e0d8fb3 2005-12-27 devnull rrfreelist(arp);
495 3e0d8fb3 2005-12-27 devnull return nd;
496 3e0d8fb3 2005-12-27 devnull }
497 3e0d8fb3 2005-12-27 devnull
498 3e0d8fb3 2005-12-27 devnull /*
499 3e0d8fb3 2005-12-27 devnull * cache negative responses
500 3e0d8fb3 2005-12-27 devnull */
501 3e0d8fb3 2005-12-27 devnull static void
502 3e0d8fb3 2005-12-27 devnull cacheneg(DN *dp, int type, int rcode, RR *soarr)
503 3e0d8fb3 2005-12-27 devnull {
504 3e0d8fb3 2005-12-27 devnull RR *rp;
505 3e0d8fb3 2005-12-27 devnull DN *soaowner;
506 3e0d8fb3 2005-12-27 devnull ulong ttl;
507 3e0d8fb3 2005-12-27 devnull
508 3e0d8fb3 2005-12-27 devnull /* no cache time specified, don' make anything up */
509 3e0d8fb3 2005-12-27 devnull if(soarr != nil){
510 3e0d8fb3 2005-12-27 devnull if(soarr->next != nil){
511 3e0d8fb3 2005-12-27 devnull rrfreelist(soarr->next);
512 3e0d8fb3 2005-12-27 devnull soarr->next = nil;
513 3e0d8fb3 2005-12-27 devnull }
514 3e0d8fb3 2005-12-27 devnull soaowner = soarr->owner;
515 3e0d8fb3 2005-12-27 devnull } else
516 3e0d8fb3 2005-12-27 devnull soaowner = nil;
517 3e0d8fb3 2005-12-27 devnull
518 3e0d8fb3 2005-12-27 devnull /* the attach can cause soarr to be freed so mine it now */
519 3e0d8fb3 2005-12-27 devnull if(soarr != nil && soarr->soa != nil)
520 3e0d8fb3 2005-12-27 devnull ttl = soarr->soa->minttl+now;
521 3e0d8fb3 2005-12-27 devnull else
522 3e0d8fb3 2005-12-27 devnull ttl = 5*Min;
523 3e0d8fb3 2005-12-27 devnull
524 3e0d8fb3 2005-12-27 devnull /* add soa and negative RR to the database */
525 3e0d8fb3 2005-12-27 devnull rrattach(soarr, 1);
526 3e0d8fb3 2005-12-27 devnull
527 3e0d8fb3 2005-12-27 devnull rp = rralloc(type);
528 3e0d8fb3 2005-12-27 devnull rp->owner = dp;
529 3e0d8fb3 2005-12-27 devnull rp->negative = 1;
530 3e0d8fb3 2005-12-27 devnull rp->negsoaowner = soaowner;
531 3e0d8fb3 2005-12-27 devnull rp->negrcode = rcode;
532 3e0d8fb3 2005-12-27 devnull rp->ttl = ttl;
533 3e0d8fb3 2005-12-27 devnull rrattach(rp, 1);
534 3e0d8fb3 2005-12-27 devnull }
535 3e0d8fb3 2005-12-27 devnull
536 3e0d8fb3 2005-12-27 devnull /*
537 3e0d8fb3 2005-12-27 devnull * query name servers. If the name server returns a pointer to another
538 3e0d8fb3 2005-12-27 devnull * name server, recurse.
539 3e0d8fb3 2005-12-27 devnull */
540 3e0d8fb3 2005-12-27 devnull static int
541 3e0d8fb3 2005-12-27 devnull netquery1(int fd, DN *dp, int type, RR *nsrp, Request *reqp, int depth, uchar *ibuf, uchar *obuf)
542 3e0d8fb3 2005-12-27 devnull {
543 3e0d8fb3 2005-12-27 devnull int ndest, j, len, replywaits, rv;
544 3e0d8fb3 2005-12-27 devnull ushort req;
545 3e0d8fb3 2005-12-27 devnull RR *tp, *soarr;
546 3e0d8fb3 2005-12-27 devnull Dest *p, *l, *np;
547 3e0d8fb3 2005-12-27 devnull DN *ndp;
548 3e0d8fb3 2005-12-27 devnull Dest dest[Maxdest];
549 3e0d8fb3 2005-12-27 devnull DNSmsg m;
550 3e0d8fb3 2005-12-27 devnull ulong endtime;
551 5c9f76b5 2006-02-14 devnull Udphdr *uh;
552 3e0d8fb3 2005-12-27 devnull
553 3e0d8fb3 2005-12-27 devnull /* pack request into a message */
554 3e0d8fb3 2005-12-27 devnull req = rand();
555 3e0d8fb3 2005-12-27 devnull len = mkreq(dp, type, obuf, Frecurse|Oquery, req);
556 3e0d8fb3 2005-12-27 devnull
557 3e0d8fb3 2005-12-27 devnull /* no server addresses yet */
558 3e0d8fb3 2005-12-27 devnull l = dest;
559 3e0d8fb3 2005-12-27 devnull
560 3e0d8fb3 2005-12-27 devnull /*
561 3e0d8fb3 2005-12-27 devnull * transmit requests and wait for answers.
562 3e0d8fb3 2005-12-27 devnull * at most Maxtrans attempts to each address.
563 3e0d8fb3 2005-12-27 devnull * each cycle send one more message than the previous.
564 3e0d8fb3 2005-12-27 devnull */
565 3e0d8fb3 2005-12-27 devnull for(ndest = 1; ndest < Maxdest; ndest++){
566 3e0d8fb3 2005-12-27 devnull p = dest;
567 3e0d8fb3 2005-12-27 devnull
568 3e0d8fb3 2005-12-27 devnull endtime = time(0);
569 3e0d8fb3 2005-12-27 devnull if(endtime >= reqp->aborttime)
570 3e0d8fb3 2005-12-27 devnull break;
571 3e0d8fb3 2005-12-27 devnull
572 3e0d8fb3 2005-12-27 devnull /* get a server address if we need one */
573 3e0d8fb3 2005-12-27 devnull if(ndest > l - p){
574 3e0d8fb3 2005-12-27 devnull j = serveraddrs(nsrp, dest, l - p, depth, reqp);
575 3e0d8fb3 2005-12-27 devnull l = &dest[j];
576 3e0d8fb3 2005-12-27 devnull }
577 3e0d8fb3 2005-12-27 devnull
578 3e0d8fb3 2005-12-27 devnull /* no servers, punt */
579 3e0d8fb3 2005-12-27 devnull if(l == dest)
580 3e0d8fb3 2005-12-27 devnull break;
581 3e0d8fb3 2005-12-27 devnull
582 3e0d8fb3 2005-12-27 devnull /* send to first 'ndest' destinations */
583 3e0d8fb3 2005-12-27 devnull j = 0;
584 3e0d8fb3 2005-12-27 devnull for(; p < &dest[ndest] && p < l; p++){
585 3e0d8fb3 2005-12-27 devnull /* skip destinations we've finished with */
586 3e0d8fb3 2005-12-27 devnull if(p->nx >= Maxtrans)
587 3e0d8fb3 2005-12-27 devnull continue;
588 3e0d8fb3 2005-12-27 devnull
589 3e0d8fb3 2005-12-27 devnull j++;
590 3e0d8fb3 2005-12-27 devnull
591 3e0d8fb3 2005-12-27 devnull /* exponential backoff of requests */
592 3e0d8fb3 2005-12-27 devnull if((1<<p->nx) > ndest)
593 3e0d8fb3 2005-12-27 devnull continue;
594 3e0d8fb3 2005-12-27 devnull
595 3e0d8fb3 2005-12-27 devnull memmove(obuf, p->a, sizeof(p->a));
596 3e0d8fb3 2005-12-27 devnull if(debug)
597 3e0d8fb3 2005-12-27 devnull logsend(reqp->id, depth, obuf, p->s->name,
598 3e0d8fb3 2005-12-27 devnull dp->name, type);
599 5c9f76b5 2006-02-14 devnull uh = (Udphdr*)obuf;
600 5c9f76b5 2006-02-14 devnull fprint(2, "send %I %I %d %d\n", uh->raddr, uh->laddr, nhgets(uh->rport), nhgets(uh->lport));
601 5c9f76b5 2006-02-14 devnull if(udpwrite(fd, uh, obuf+Udphdrsize, len) < 0)
602 3e0d8fb3 2005-12-27 devnull warning("sending udp msg %r");
603 3e0d8fb3 2005-12-27 devnull p->nx++;
604 3e0d8fb3 2005-12-27 devnull }
605 3e0d8fb3 2005-12-27 devnull if(j == 0)
606 3e0d8fb3 2005-12-27 devnull break; /* no destinations left */
607 3e0d8fb3 2005-12-27 devnull
608 3e0d8fb3 2005-12-27 devnull /* wait up to 5 seconds for replies */
609 3e0d8fb3 2005-12-27 devnull endtime = time(0) + 5;
610 3e0d8fb3 2005-12-27 devnull if(endtime > reqp->aborttime)
611 3e0d8fb3 2005-12-27 devnull endtime = reqp->aborttime;
612 3e0d8fb3 2005-12-27 devnull
613 3e0d8fb3 2005-12-27 devnull for(replywaits = 0; replywaits < ndest; replywaits++){
614 3e0d8fb3 2005-12-27 devnull if(readreply(fd, dp, type, req, ibuf, &m, endtime, reqp) < 0)
615 3e0d8fb3 2005-12-27 devnull break; /* timed out */
616 3e0d8fb3 2005-12-27 devnull
617 3e0d8fb3 2005-12-27 devnull /* find responder */
618 3e0d8fb3 2005-12-27 devnull for(p = dest; p < l; p++)
619 3e0d8fb3 2005-12-27 devnull if(memcmp(p->a, ibuf, sizeof(p->a)) == 0)
620 3e0d8fb3 2005-12-27 devnull break;
621 3e0d8fb3 2005-12-27 devnull
622 3e0d8fb3 2005-12-27 devnull /* remove all addrs of responding server from list */
623 3e0d8fb3 2005-12-27 devnull for(np = dest; np < l; np++)
624 3e0d8fb3 2005-12-27 devnull if(np->s == p->s)
625 3e0d8fb3 2005-12-27 devnull p->nx = Maxtrans;
626 3e0d8fb3 2005-12-27 devnull
627 3e0d8fb3 2005-12-27 devnull /* ignore any error replies */
628 3e0d8fb3 2005-12-27 devnull if((m.flags & Rmask) == Rserver){
629 3e0d8fb3 2005-12-27 devnull rrfreelist(m.qd);
630 3e0d8fb3 2005-12-27 devnull rrfreelist(m.an);
631 3e0d8fb3 2005-12-27 devnull rrfreelist(m.ar);
632 3e0d8fb3 2005-12-27 devnull rrfreelist(m.ns);
633 3e0d8fb3 2005-12-27 devnull if(p != l)
634 3e0d8fb3 2005-12-27 devnull p->code = Rserver;
635 3e0d8fb3 2005-12-27 devnull continue;
636 3e0d8fb3 2005-12-27 devnull }
637 3e0d8fb3 2005-12-27 devnull
638 3e0d8fb3 2005-12-27 devnull /* ignore any bad delegations */
639 3e0d8fb3 2005-12-27 devnull if(m.ns && baddelegation(m.ns, nsrp, ibuf)){
640 3e0d8fb3 2005-12-27 devnull rrfreelist(m.ns);
641 3e0d8fb3 2005-12-27 devnull m.ns = nil;
642 3e0d8fb3 2005-12-27 devnull if(m.an == nil){
643 3e0d8fb3 2005-12-27 devnull rrfreelist(m.qd);
644 3e0d8fb3 2005-12-27 devnull rrfreelist(m.ar);
645 3e0d8fb3 2005-12-27 devnull if(p != l)
646 3e0d8fb3 2005-12-27 devnull p->code = Rserver;
647 3e0d8fb3 2005-12-27 devnull continue;
648 3e0d8fb3 2005-12-27 devnull }
649 3e0d8fb3 2005-12-27 devnull }
650 3e0d8fb3 2005-12-27 devnull
651 3e0d8fb3 2005-12-27 devnull
652 3e0d8fb3 2005-12-27 devnull /* remove any soa's from the authority section */
653 3e0d8fb3 2005-12-27 devnull soarr = rrremtype(&m.ns, Tsoa);
654 3e0d8fb3 2005-12-27 devnull
655 3e0d8fb3 2005-12-27 devnull /* incorporate answers */
656 3e0d8fb3 2005-12-27 devnull if(m.an)
657 3e0d8fb3 2005-12-27 devnull rrattach(m.an, (m.flags & Fauth) ? 1 : 0);
658 3e0d8fb3 2005-12-27 devnull if(m.ar)
659 3e0d8fb3 2005-12-27 devnull rrattach(m.ar, 0);
660 3e0d8fb3 2005-12-27 devnull if(m.ns){
661 3e0d8fb3 2005-12-27 devnull ndp = m.ns->owner;
662 3e0d8fb3 2005-12-27 devnull rrattach(m.ns, 0);
663 3e0d8fb3 2005-12-27 devnull } else
664 3e0d8fb3 2005-12-27 devnull ndp = 0;
665 3e0d8fb3 2005-12-27 devnull
666 3e0d8fb3 2005-12-27 devnull /* free the question */
667 3e0d8fb3 2005-12-27 devnull if(m.qd)
668 3e0d8fb3 2005-12-27 devnull rrfreelist(m.qd);
669 3e0d8fb3 2005-12-27 devnull
670 3e0d8fb3 2005-12-27 devnull /*
671 3e0d8fb3 2005-12-27 devnull * Any reply from an authoritative server,
672 3e0d8fb3 2005-12-27 devnull * or a positive reply terminates the search
673 3e0d8fb3 2005-12-27 devnull */
674 3e0d8fb3 2005-12-27 devnull if(m.an != nil || (m.flags & Fauth)){
675 3e0d8fb3 2005-12-27 devnull if(m.an == nil && (m.flags & Rmask) == Rname)
676 3e0d8fb3 2005-12-27 devnull dp->nonexistent = Rname;
677 3e0d8fb3 2005-12-27 devnull else
678 3e0d8fb3 2005-12-27 devnull dp->nonexistent = 0;
679 3e0d8fb3 2005-12-27 devnull
680 3e0d8fb3 2005-12-27 devnull /*
681 3e0d8fb3 2005-12-27 devnull * cache any negative responses, free soarr
682 3e0d8fb3 2005-12-27 devnull */
683 3e0d8fb3 2005-12-27 devnull if((m.flags & Fauth) && m.an == nil)
684 3e0d8fb3 2005-12-27 devnull cacheneg(dp, type, (m.flags & Rmask), soarr);
685 3e0d8fb3 2005-12-27 devnull else
686 3e0d8fb3 2005-12-27 devnull rrfreelist(soarr);
687 3e0d8fb3 2005-12-27 devnull return 1;
688 3e0d8fb3 2005-12-27 devnull }
689 3e0d8fb3 2005-12-27 devnull rrfreelist(soarr);
690 3e0d8fb3 2005-12-27 devnull
691 3e0d8fb3 2005-12-27 devnull /*
692 3e0d8fb3 2005-12-27 devnull * if we've been given better name servers
693 3e0d8fb3 2005-12-27 devnull * recurse
694 3e0d8fb3 2005-12-27 devnull */
695 3e0d8fb3 2005-12-27 devnull if(m.ns){
696 3e0d8fb3 2005-12-27 devnull tp = rrlookup(ndp, Tns, NOneg);
697 3e0d8fb3 2005-12-27 devnull if(!contains(nsrp, tp)){
698 3e0d8fb3 2005-12-27 devnull rv = netquery(dp, type, tp, reqp, depth+1);
699 3e0d8fb3 2005-12-27 devnull rrfreelist(tp);
700 3e0d8fb3 2005-12-27 devnull return rv;
701 3e0d8fb3 2005-12-27 devnull } else
702 3e0d8fb3 2005-12-27 devnull rrfreelist(tp);
703 3e0d8fb3 2005-12-27 devnull }
704 3e0d8fb3 2005-12-27 devnull }
705 3e0d8fb3 2005-12-27 devnull }
706 3e0d8fb3 2005-12-27 devnull
707 3e0d8fb3 2005-12-27 devnull /* if all servers returned failure, propogate it */
708 3e0d8fb3 2005-12-27 devnull dp->nonexistent = Rserver;
709 3e0d8fb3 2005-12-27 devnull for(p = dest; p < l; p++)
710 3e0d8fb3 2005-12-27 devnull if(p->code != Rserver)
711 3e0d8fb3 2005-12-27 devnull dp->nonexistent = 0;
712 3e0d8fb3 2005-12-27 devnull
713 3e0d8fb3 2005-12-27 devnull return 0;
714 3e0d8fb3 2005-12-27 devnull }
715 3e0d8fb3 2005-12-27 devnull
716 3e0d8fb3 2005-12-27 devnull typedef struct Qarg Qarg;
717 3e0d8fb3 2005-12-27 devnull struct Qarg
718 3e0d8fb3 2005-12-27 devnull {
719 3e0d8fb3 2005-12-27 devnull DN *dp;
720 3e0d8fb3 2005-12-27 devnull int type;
721 3e0d8fb3 2005-12-27 devnull RR *nsrp;
722 3e0d8fb3 2005-12-27 devnull Request *reqp;
723 3e0d8fb3 2005-12-27 devnull int depth;
724 3e0d8fb3 2005-12-27 devnull };
725 3e0d8fb3 2005-12-27 devnull
726 3e0d8fb3 2005-12-27 devnull
727 3e0d8fb3 2005-12-27 devnull static int
728 3e0d8fb3 2005-12-27 devnull netquery(DN *dp, int type, RR *nsrp, Request *reqp, int depth)
729 3e0d8fb3 2005-12-27 devnull {
730 3e0d8fb3 2005-12-27 devnull uchar *obuf;
731 3e0d8fb3 2005-12-27 devnull uchar *ibuf;
732 3e0d8fb3 2005-12-27 devnull RR *rp;
733 3e0d8fb3 2005-12-27 devnull int fd, rv;
734 3e0d8fb3 2005-12-27 devnull
735 3e0d8fb3 2005-12-27 devnull if(depth > 12)
736 3e0d8fb3 2005-12-27 devnull return 0;
737 3e0d8fb3 2005-12-27 devnull
738 3e0d8fb3 2005-12-27 devnull /* use alloced buffers rather than ones from the stack */
739 5c9f76b5 2006-02-14 devnull ibuf = emalloc(Maxudpin+Udphdrsize);
740 5c9f76b5 2006-02-14 devnull obuf = emalloc(Maxudp+Udphdrsize);
741 3e0d8fb3 2005-12-27 devnull
742 3e0d8fb3 2005-12-27 devnull /* prepare server RR's for incremental lookup */
743 3e0d8fb3 2005-12-27 devnull for(rp = nsrp; rp; rp = rp->next)
744 3e0d8fb3 2005-12-27 devnull rp->marker = 0;
745 3e0d8fb3 2005-12-27 devnull
746 3e0d8fb3 2005-12-27 devnull fd = udpport();
747 3e0d8fb3 2005-12-27 devnull if(fd < 0)
748 3e0d8fb3 2005-12-27 devnull return 0;
749 3e0d8fb3 2005-12-27 devnull rv = netquery1(fd, dp, type, nsrp, reqp, depth, ibuf, obuf);
750 3e0d8fb3 2005-12-27 devnull close(fd);
751 3e0d8fb3 2005-12-27 devnull free(ibuf);
752 3e0d8fb3 2005-12-27 devnull free(obuf);
753 3e0d8fb3 2005-12-27 devnull
754 3e0d8fb3 2005-12-27 devnull return rv;
755 3e0d8fb3 2005-12-27 devnull }