Blame


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