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 3e0d8fb3 2005-12-27 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 3e0d8fb3 2005-12-27 devnull OUdphdr *uh = (OUdphdr*)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 3e0d8fb3 2005-12-27 devnull len = convDNS2M(&m, &buf[OUdphdrsize], 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 /* for alarms in readreply */
282 3e0d8fb3 2005-12-27 devnull static void
283 3e0d8fb3 2005-12-27 devnull ding(void *x, char *msg)
284 3e0d8fb3 2005-12-27 devnull {
285 3e0d8fb3 2005-12-27 devnull USED(x);
286 3e0d8fb3 2005-12-27 devnull if(strcmp(msg, "alarm") == 0)
287 3e0d8fb3 2005-12-27 devnull noted(NCONT);
288 3e0d8fb3 2005-12-27 devnull else
289 3e0d8fb3 2005-12-27 devnull noted(NDFLT);
290 3e0d8fb3 2005-12-27 devnull }
291 3e0d8fb3 2005-12-27 devnull
292 3e0d8fb3 2005-12-27 devnull static void
293 3e0d8fb3 2005-12-27 devnull freeanswers(DNSmsg *mp)
294 3e0d8fb3 2005-12-27 devnull {
295 3e0d8fb3 2005-12-27 devnull rrfreelist(mp->qd);
296 3e0d8fb3 2005-12-27 devnull rrfreelist(mp->an);
297 3e0d8fb3 2005-12-27 devnull rrfreelist(mp->ns);
298 3e0d8fb3 2005-12-27 devnull rrfreelist(mp->ar);
299 3e0d8fb3 2005-12-27 devnull }
300 3e0d8fb3 2005-12-27 devnull
301 3e0d8fb3 2005-12-27 devnull /*
302 3e0d8fb3 2005-12-27 devnull * read replies to a request. ignore any of the wrong type. wait at most 5 seconds.
303 3e0d8fb3 2005-12-27 devnull */
304 3e0d8fb3 2005-12-27 devnull static int
305 3e0d8fb3 2005-12-27 devnull readreply(int fd, DN *dp, int type, ushort req,
306 3e0d8fb3 2005-12-27 devnull uchar *ibuf, DNSmsg *mp, ulong endtime, Request *reqp)
307 3e0d8fb3 2005-12-27 devnull {
308 3e0d8fb3 2005-12-27 devnull char *err;
309 3e0d8fb3 2005-12-27 devnull int len;
310 3e0d8fb3 2005-12-27 devnull ulong now;
311 3e0d8fb3 2005-12-27 devnull RR *rp;
312 3e0d8fb3 2005-12-27 devnull
313 3e0d8fb3 2005-12-27 devnull notify(ding);
314 3e0d8fb3 2005-12-27 devnull
315 3e0d8fb3 2005-12-27 devnull for(; ; freeanswers(mp)){
316 3e0d8fb3 2005-12-27 devnull now = time(0);
317 3e0d8fb3 2005-12-27 devnull if(now >= endtime)
318 3e0d8fb3 2005-12-27 devnull return -1; /* timed out */
319 3e0d8fb3 2005-12-27 devnull
320 3e0d8fb3 2005-12-27 devnull /* timed read */
321 3e0d8fb3 2005-12-27 devnull alarm((endtime - now) * 1000);
322 3e0d8fb3 2005-12-27 devnull len = udpread(fd, (OUdphdr*)ibuf, ibuf+OUdphdrsize, Maxudpin);
323 3e0d8fb3 2005-12-27 devnull alarm(0);
324 3e0d8fb3 2005-12-27 devnull if(len < 0)
325 3e0d8fb3 2005-12-27 devnull return -1; /* timed out */
326 3e0d8fb3 2005-12-27 devnull
327 3e0d8fb3 2005-12-27 devnull /* convert into internal format */
328 3e0d8fb3 2005-12-27 devnull memset(mp, 0, sizeof(*mp));
329 3e0d8fb3 2005-12-27 devnull err = convM2DNS(&ibuf[OUdphdrsize], len, mp);
330 3e0d8fb3 2005-12-27 devnull if(err){
331 3e0d8fb3 2005-12-27 devnull syslog(0, LOG, "input err %s: %I", err, ibuf);
332 3e0d8fb3 2005-12-27 devnull continue;
333 3e0d8fb3 2005-12-27 devnull }
334 3e0d8fb3 2005-12-27 devnull if(debug)
335 3e0d8fb3 2005-12-27 devnull logreply(reqp->id, ibuf, mp);
336 3e0d8fb3 2005-12-27 devnull
337 3e0d8fb3 2005-12-27 devnull /* answering the right question? */
338 3e0d8fb3 2005-12-27 devnull if(mp->id != req){
339 3e0d8fb3 2005-12-27 devnull syslog(0, LOG, "%d: id %d instead of %d: %I", reqp->id,
340 3e0d8fb3 2005-12-27 devnull mp->id, req, ibuf);
341 3e0d8fb3 2005-12-27 devnull continue;
342 3e0d8fb3 2005-12-27 devnull }
343 3e0d8fb3 2005-12-27 devnull if(mp->qd == 0){
344 3e0d8fb3 2005-12-27 devnull syslog(0, LOG, "%d: no question RR: %I", reqp->id, ibuf);
345 3e0d8fb3 2005-12-27 devnull continue;
346 3e0d8fb3 2005-12-27 devnull }
347 3e0d8fb3 2005-12-27 devnull if(mp->qd->owner != dp){
348 3e0d8fb3 2005-12-27 devnull syslog(0, LOG, "%d: owner %s instead of %s: %I", reqp->id,
349 3e0d8fb3 2005-12-27 devnull mp->qd->owner->name, dp->name, ibuf);
350 3e0d8fb3 2005-12-27 devnull continue;
351 3e0d8fb3 2005-12-27 devnull }
352 3e0d8fb3 2005-12-27 devnull if(mp->qd->type != type){
353 3e0d8fb3 2005-12-27 devnull syslog(0, LOG, "%d: type %d instead of %d: %I", reqp->id,
354 3e0d8fb3 2005-12-27 devnull mp->qd->type, type, ibuf);
355 3e0d8fb3 2005-12-27 devnull continue;
356 3e0d8fb3 2005-12-27 devnull }
357 3e0d8fb3 2005-12-27 devnull
358 3e0d8fb3 2005-12-27 devnull /* remember what request this is in answer to */
359 3e0d8fb3 2005-12-27 devnull for(rp = mp->an; rp; rp = rp->next)
360 3e0d8fb3 2005-12-27 devnull rp->query = type;
361 3e0d8fb3 2005-12-27 devnull
362 3e0d8fb3 2005-12-27 devnull return 0;
363 3e0d8fb3 2005-12-27 devnull }
364 3e0d8fb3 2005-12-27 devnull
365 3e0d8fb3 2005-12-27 devnull return 0; /* never reached */
366 3e0d8fb3 2005-12-27 devnull }
367 3e0d8fb3 2005-12-27 devnull
368 3e0d8fb3 2005-12-27 devnull /*
369 3e0d8fb3 2005-12-27 devnull * return non-0 if first list includes second list
370 3e0d8fb3 2005-12-27 devnull */
371 3e0d8fb3 2005-12-27 devnull int
372 3e0d8fb3 2005-12-27 devnull contains(RR *rp1, RR *rp2)
373 3e0d8fb3 2005-12-27 devnull {
374 3e0d8fb3 2005-12-27 devnull RR *trp1, *trp2;
375 3e0d8fb3 2005-12-27 devnull
376 3e0d8fb3 2005-12-27 devnull for(trp2 = rp2; trp2; trp2 = trp2->next){
377 3e0d8fb3 2005-12-27 devnull for(trp1 = rp1; trp1; trp1 = trp1->next){
378 3e0d8fb3 2005-12-27 devnull if(trp1->type == trp2->type)
379 3e0d8fb3 2005-12-27 devnull if(trp1->host == trp2->host)
380 3e0d8fb3 2005-12-27 devnull if(trp1->owner == trp2->owner)
381 3e0d8fb3 2005-12-27 devnull break;
382 3e0d8fb3 2005-12-27 devnull }
383 3e0d8fb3 2005-12-27 devnull if(trp1 == 0)
384 3e0d8fb3 2005-12-27 devnull return 0;
385 3e0d8fb3 2005-12-27 devnull }
386 3e0d8fb3 2005-12-27 devnull
387 3e0d8fb3 2005-12-27 devnull return 1;
388 3e0d8fb3 2005-12-27 devnull }
389 3e0d8fb3 2005-12-27 devnull
390 3e0d8fb3 2005-12-27 devnull
391 3e0d8fb3 2005-12-27 devnull typedef struct Dest Dest;
392 3e0d8fb3 2005-12-27 devnull struct Dest
393 3e0d8fb3 2005-12-27 devnull {
394 3e0d8fb3 2005-12-27 devnull uchar a[IPaddrlen]; /* ip address */
395 3e0d8fb3 2005-12-27 devnull DN *s; /* name server */
396 3e0d8fb3 2005-12-27 devnull int nx; /* number of transmissions */
397 3e0d8fb3 2005-12-27 devnull int code;
398 3e0d8fb3 2005-12-27 devnull };
399 3e0d8fb3 2005-12-27 devnull
400 3e0d8fb3 2005-12-27 devnull
401 3e0d8fb3 2005-12-27 devnull /*
402 3e0d8fb3 2005-12-27 devnull * return multicast version if any
403 3e0d8fb3 2005-12-27 devnull */
404 3e0d8fb3 2005-12-27 devnull int
405 3e0d8fb3 2005-12-27 devnull ipisbm(uchar *ip)
406 3e0d8fb3 2005-12-27 devnull {
407 3e0d8fb3 2005-12-27 devnull if(isv4(ip)){
408 3e0d8fb3 2005-12-27 devnull if(ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0)
409 3e0d8fb3 2005-12-27 devnull return 4;
410 3e0d8fb3 2005-12-27 devnull if(ipcmp(ip, IPv4bcast) == 0)
411 3e0d8fb3 2005-12-27 devnull return 4;
412 3e0d8fb3 2005-12-27 devnull } else {
413 3e0d8fb3 2005-12-27 devnull if(ip[0] == 0xff)
414 3e0d8fb3 2005-12-27 devnull return 6;
415 3e0d8fb3 2005-12-27 devnull }
416 3e0d8fb3 2005-12-27 devnull return 0;
417 3e0d8fb3 2005-12-27 devnull }
418 3e0d8fb3 2005-12-27 devnull
419 3e0d8fb3 2005-12-27 devnull /*
420 3e0d8fb3 2005-12-27 devnull * Get next server address
421 3e0d8fb3 2005-12-27 devnull */
422 3e0d8fb3 2005-12-27 devnull static int
423 3e0d8fb3 2005-12-27 devnull serveraddrs(RR *nsrp, Dest *dest, int nd, int depth, Request *reqp)
424 3e0d8fb3 2005-12-27 devnull {
425 3e0d8fb3 2005-12-27 devnull RR *rp, *arp, *trp;
426 3e0d8fb3 2005-12-27 devnull Dest *cur;
427 3e0d8fb3 2005-12-27 devnull
428 3e0d8fb3 2005-12-27 devnull if(nd >= Maxdest)
429 3e0d8fb3 2005-12-27 devnull return 0;
430 3e0d8fb3 2005-12-27 devnull
431 3e0d8fb3 2005-12-27 devnull /*
432 3e0d8fb3 2005-12-27 devnull * look for a server whose address we already know.
433 3e0d8fb3 2005-12-27 devnull * if we find one, mark it so we ignore this on
434 3e0d8fb3 2005-12-27 devnull * subsequent passes.
435 3e0d8fb3 2005-12-27 devnull */
436 3e0d8fb3 2005-12-27 devnull arp = 0;
437 3e0d8fb3 2005-12-27 devnull for(rp = nsrp; rp; rp = rp->next){
438 3e0d8fb3 2005-12-27 devnull assert(rp->magic == RRmagic);
439 3e0d8fb3 2005-12-27 devnull if(rp->marker)
440 3e0d8fb3 2005-12-27 devnull continue;
441 3e0d8fb3 2005-12-27 devnull arp = rrlookup(rp->host, Ta, NOneg);
442 3e0d8fb3 2005-12-27 devnull if(arp){
443 3e0d8fb3 2005-12-27 devnull rp->marker = 1;
444 3e0d8fb3 2005-12-27 devnull break;
445 3e0d8fb3 2005-12-27 devnull }
446 3e0d8fb3 2005-12-27 devnull arp = dblookup(rp->host->name, Cin, Ta, 0, 0);
447 3e0d8fb3 2005-12-27 devnull if(arp){
448 3e0d8fb3 2005-12-27 devnull rp->marker = 1;
449 3e0d8fb3 2005-12-27 devnull break;
450 3e0d8fb3 2005-12-27 devnull }
451 3e0d8fb3 2005-12-27 devnull }
452 3e0d8fb3 2005-12-27 devnull
453 3e0d8fb3 2005-12-27 devnull /*
454 3e0d8fb3 2005-12-27 devnull * if the cache and database lookup didn't find any new
455 3e0d8fb3 2005-12-27 devnull * server addresses, try resolving one via the network.
456 3e0d8fb3 2005-12-27 devnull * Mark any we try to resolve so we don't try a second time.
457 3e0d8fb3 2005-12-27 devnull */
458 3e0d8fb3 2005-12-27 devnull if(arp == 0){
459 3e0d8fb3 2005-12-27 devnull for(rp = nsrp; rp; rp = rp->next){
460 3e0d8fb3 2005-12-27 devnull if(rp->marker)
461 3e0d8fb3 2005-12-27 devnull continue;
462 3e0d8fb3 2005-12-27 devnull rp->marker = 1;
463 3e0d8fb3 2005-12-27 devnull
464 3e0d8fb3 2005-12-27 devnull /*
465 3e0d8fb3 2005-12-27 devnull * avoid loops looking up a server under itself
466 3e0d8fb3 2005-12-27 devnull */
467 3e0d8fb3 2005-12-27 devnull if(subsume(rp->owner->name, rp->host->name))
468 3e0d8fb3 2005-12-27 devnull continue;
469 3e0d8fb3 2005-12-27 devnull
470 3e0d8fb3 2005-12-27 devnull arp = dnresolve(rp->host->name, Cin, Ta, reqp, 0, depth+1, Recurse, 1, 0);
471 3e0d8fb3 2005-12-27 devnull rrfreelist(rrremneg(&arp));
472 3e0d8fb3 2005-12-27 devnull if(arp)
473 3e0d8fb3 2005-12-27 devnull break;
474 3e0d8fb3 2005-12-27 devnull }
475 3e0d8fb3 2005-12-27 devnull }
476 3e0d8fb3 2005-12-27 devnull
477 3e0d8fb3 2005-12-27 devnull /* use any addresses that we found */
478 3e0d8fb3 2005-12-27 devnull for(trp = arp; trp; trp = trp->next){
479 3e0d8fb3 2005-12-27 devnull if(nd >= Maxdest)
480 3e0d8fb3 2005-12-27 devnull break;
481 3e0d8fb3 2005-12-27 devnull cur = &dest[nd];
482 3e0d8fb3 2005-12-27 devnull parseip(cur->a, trp->ip->name);
483 3e0d8fb3 2005-12-27 devnull if(ipisbm(cur->a))
484 3e0d8fb3 2005-12-27 devnull continue;
485 3e0d8fb3 2005-12-27 devnull cur->nx = 0;
486 3e0d8fb3 2005-12-27 devnull cur->s = trp->owner;
487 3e0d8fb3 2005-12-27 devnull cur->code = Rtimeout;
488 3e0d8fb3 2005-12-27 devnull nd++;
489 3e0d8fb3 2005-12-27 devnull }
490 3e0d8fb3 2005-12-27 devnull rrfreelist(arp);
491 3e0d8fb3 2005-12-27 devnull return nd;
492 3e0d8fb3 2005-12-27 devnull }
493 3e0d8fb3 2005-12-27 devnull
494 3e0d8fb3 2005-12-27 devnull /*
495 3e0d8fb3 2005-12-27 devnull * cache negative responses
496 3e0d8fb3 2005-12-27 devnull */
497 3e0d8fb3 2005-12-27 devnull static void
498 3e0d8fb3 2005-12-27 devnull cacheneg(DN *dp, int type, int rcode, RR *soarr)
499 3e0d8fb3 2005-12-27 devnull {
500 3e0d8fb3 2005-12-27 devnull RR *rp;
501 3e0d8fb3 2005-12-27 devnull DN *soaowner;
502 3e0d8fb3 2005-12-27 devnull ulong ttl;
503 3e0d8fb3 2005-12-27 devnull
504 3e0d8fb3 2005-12-27 devnull /* no cache time specified, don' make anything up */
505 3e0d8fb3 2005-12-27 devnull if(soarr != nil){
506 3e0d8fb3 2005-12-27 devnull if(soarr->next != nil){
507 3e0d8fb3 2005-12-27 devnull rrfreelist(soarr->next);
508 3e0d8fb3 2005-12-27 devnull soarr->next = nil;
509 3e0d8fb3 2005-12-27 devnull }
510 3e0d8fb3 2005-12-27 devnull soaowner = soarr->owner;
511 3e0d8fb3 2005-12-27 devnull } else
512 3e0d8fb3 2005-12-27 devnull soaowner = nil;
513 3e0d8fb3 2005-12-27 devnull
514 3e0d8fb3 2005-12-27 devnull /* the attach can cause soarr to be freed so mine it now */
515 3e0d8fb3 2005-12-27 devnull if(soarr != nil && soarr->soa != nil)
516 3e0d8fb3 2005-12-27 devnull ttl = soarr->soa->minttl+now;
517 3e0d8fb3 2005-12-27 devnull else
518 3e0d8fb3 2005-12-27 devnull ttl = 5*Min;
519 3e0d8fb3 2005-12-27 devnull
520 3e0d8fb3 2005-12-27 devnull /* add soa and negative RR to the database */
521 3e0d8fb3 2005-12-27 devnull rrattach(soarr, 1);
522 3e0d8fb3 2005-12-27 devnull
523 3e0d8fb3 2005-12-27 devnull rp = rralloc(type);
524 3e0d8fb3 2005-12-27 devnull rp->owner = dp;
525 3e0d8fb3 2005-12-27 devnull rp->negative = 1;
526 3e0d8fb3 2005-12-27 devnull rp->negsoaowner = soaowner;
527 3e0d8fb3 2005-12-27 devnull rp->negrcode = rcode;
528 3e0d8fb3 2005-12-27 devnull rp->ttl = ttl;
529 3e0d8fb3 2005-12-27 devnull rrattach(rp, 1);
530 3e0d8fb3 2005-12-27 devnull }
531 3e0d8fb3 2005-12-27 devnull
532 3e0d8fb3 2005-12-27 devnull /*
533 3e0d8fb3 2005-12-27 devnull * query name servers. If the name server returns a pointer to another
534 3e0d8fb3 2005-12-27 devnull * name server, recurse.
535 3e0d8fb3 2005-12-27 devnull */
536 3e0d8fb3 2005-12-27 devnull static int
537 3e0d8fb3 2005-12-27 devnull netquery1(int fd, DN *dp, int type, RR *nsrp, Request *reqp, int depth, uchar *ibuf, uchar *obuf)
538 3e0d8fb3 2005-12-27 devnull {
539 3e0d8fb3 2005-12-27 devnull int ndest, j, len, replywaits, rv;
540 3e0d8fb3 2005-12-27 devnull ushort req;
541 3e0d8fb3 2005-12-27 devnull RR *tp, *soarr;
542 3e0d8fb3 2005-12-27 devnull Dest *p, *l, *np;
543 3e0d8fb3 2005-12-27 devnull DN *ndp;
544 3e0d8fb3 2005-12-27 devnull Dest dest[Maxdest];
545 3e0d8fb3 2005-12-27 devnull DNSmsg m;
546 3e0d8fb3 2005-12-27 devnull ulong endtime;
547 3e0d8fb3 2005-12-27 devnull
548 3e0d8fb3 2005-12-27 devnull /* pack request into a message */
549 3e0d8fb3 2005-12-27 devnull req = rand();
550 3e0d8fb3 2005-12-27 devnull len = mkreq(dp, type, obuf, Frecurse|Oquery, req);
551 3e0d8fb3 2005-12-27 devnull
552 3e0d8fb3 2005-12-27 devnull /* no server addresses yet */
553 3e0d8fb3 2005-12-27 devnull l = dest;
554 3e0d8fb3 2005-12-27 devnull
555 3e0d8fb3 2005-12-27 devnull /*
556 3e0d8fb3 2005-12-27 devnull * transmit requests and wait for answers.
557 3e0d8fb3 2005-12-27 devnull * at most Maxtrans attempts to each address.
558 3e0d8fb3 2005-12-27 devnull * each cycle send one more message than the previous.
559 3e0d8fb3 2005-12-27 devnull */
560 3e0d8fb3 2005-12-27 devnull for(ndest = 1; ndest < Maxdest; ndest++){
561 3e0d8fb3 2005-12-27 devnull p = dest;
562 3e0d8fb3 2005-12-27 devnull
563 3e0d8fb3 2005-12-27 devnull endtime = time(0);
564 3e0d8fb3 2005-12-27 devnull if(endtime >= reqp->aborttime)
565 3e0d8fb3 2005-12-27 devnull break;
566 3e0d8fb3 2005-12-27 devnull
567 3e0d8fb3 2005-12-27 devnull /* get a server address if we need one */
568 3e0d8fb3 2005-12-27 devnull if(ndest > l - p){
569 3e0d8fb3 2005-12-27 devnull j = serveraddrs(nsrp, dest, l - p, depth, reqp);
570 3e0d8fb3 2005-12-27 devnull l = &dest[j];
571 3e0d8fb3 2005-12-27 devnull }
572 3e0d8fb3 2005-12-27 devnull
573 3e0d8fb3 2005-12-27 devnull /* no servers, punt */
574 3e0d8fb3 2005-12-27 devnull if(l == dest)
575 3e0d8fb3 2005-12-27 devnull break;
576 3e0d8fb3 2005-12-27 devnull
577 3e0d8fb3 2005-12-27 devnull /* send to first 'ndest' destinations */
578 3e0d8fb3 2005-12-27 devnull j = 0;
579 3e0d8fb3 2005-12-27 devnull for(; p < &dest[ndest] && p < l; p++){
580 3e0d8fb3 2005-12-27 devnull /* skip destinations we've finished with */
581 3e0d8fb3 2005-12-27 devnull if(p->nx >= Maxtrans)
582 3e0d8fb3 2005-12-27 devnull continue;
583 3e0d8fb3 2005-12-27 devnull
584 3e0d8fb3 2005-12-27 devnull j++;
585 3e0d8fb3 2005-12-27 devnull
586 3e0d8fb3 2005-12-27 devnull /* exponential backoff of requests */
587 3e0d8fb3 2005-12-27 devnull if((1<<p->nx) > ndest)
588 3e0d8fb3 2005-12-27 devnull continue;
589 3e0d8fb3 2005-12-27 devnull
590 3e0d8fb3 2005-12-27 devnull memmove(obuf, p->a, sizeof(p->a));
591 3e0d8fb3 2005-12-27 devnull if(debug)
592 3e0d8fb3 2005-12-27 devnull logsend(reqp->id, depth, obuf, p->s->name,
593 3e0d8fb3 2005-12-27 devnull dp->name, type);
594 3e0d8fb3 2005-12-27 devnull {Udphdr *uh = (Udphdr*)obuf;
595 3e0d8fb3 2005-12-27 devnull print("send %I %I %d %d\n", uh->raddr, uh->laddr, nhgets(uh->rport), nhgets(uh->lport));
596 3e0d8fb3 2005-12-27 devnull }
597 3e0d8fb3 2005-12-27 devnull if(udpwrite(fd, (OUdphdr*)obuf, obuf+OUdphdrsize, len) < 0)
598 3e0d8fb3 2005-12-27 devnull warning("sending udp msg %r");
599 3e0d8fb3 2005-12-27 devnull p->nx++;
600 3e0d8fb3 2005-12-27 devnull }
601 3e0d8fb3 2005-12-27 devnull if(j == 0)
602 3e0d8fb3 2005-12-27 devnull break; /* no destinations left */
603 3e0d8fb3 2005-12-27 devnull
604 3e0d8fb3 2005-12-27 devnull /* wait up to 5 seconds for replies */
605 3e0d8fb3 2005-12-27 devnull endtime = time(0) + 5;
606 3e0d8fb3 2005-12-27 devnull if(endtime > reqp->aborttime)
607 3e0d8fb3 2005-12-27 devnull endtime = reqp->aborttime;
608 3e0d8fb3 2005-12-27 devnull
609 3e0d8fb3 2005-12-27 devnull for(replywaits = 0; replywaits < ndest; replywaits++){
610 3e0d8fb3 2005-12-27 devnull if(readreply(fd, dp, type, req, ibuf, &m, endtime, reqp) < 0)
611 3e0d8fb3 2005-12-27 devnull break; /* timed out */
612 3e0d8fb3 2005-12-27 devnull
613 3e0d8fb3 2005-12-27 devnull /* find responder */
614 3e0d8fb3 2005-12-27 devnull for(p = dest; p < l; p++)
615 3e0d8fb3 2005-12-27 devnull if(memcmp(p->a, ibuf, sizeof(p->a)) == 0)
616 3e0d8fb3 2005-12-27 devnull break;
617 3e0d8fb3 2005-12-27 devnull
618 3e0d8fb3 2005-12-27 devnull /* remove all addrs of responding server from list */
619 3e0d8fb3 2005-12-27 devnull for(np = dest; np < l; np++)
620 3e0d8fb3 2005-12-27 devnull if(np->s == p->s)
621 3e0d8fb3 2005-12-27 devnull p->nx = Maxtrans;
622 3e0d8fb3 2005-12-27 devnull
623 3e0d8fb3 2005-12-27 devnull /* ignore any error replies */
624 3e0d8fb3 2005-12-27 devnull if((m.flags & Rmask) == Rserver){
625 3e0d8fb3 2005-12-27 devnull rrfreelist(m.qd);
626 3e0d8fb3 2005-12-27 devnull rrfreelist(m.an);
627 3e0d8fb3 2005-12-27 devnull rrfreelist(m.ar);
628 3e0d8fb3 2005-12-27 devnull rrfreelist(m.ns);
629 3e0d8fb3 2005-12-27 devnull if(p != l)
630 3e0d8fb3 2005-12-27 devnull p->code = Rserver;
631 3e0d8fb3 2005-12-27 devnull continue;
632 3e0d8fb3 2005-12-27 devnull }
633 3e0d8fb3 2005-12-27 devnull
634 3e0d8fb3 2005-12-27 devnull /* ignore any bad delegations */
635 3e0d8fb3 2005-12-27 devnull if(m.ns && baddelegation(m.ns, nsrp, ibuf)){
636 3e0d8fb3 2005-12-27 devnull rrfreelist(m.ns);
637 3e0d8fb3 2005-12-27 devnull m.ns = nil;
638 3e0d8fb3 2005-12-27 devnull if(m.an == nil){
639 3e0d8fb3 2005-12-27 devnull rrfreelist(m.qd);
640 3e0d8fb3 2005-12-27 devnull rrfreelist(m.ar);
641 3e0d8fb3 2005-12-27 devnull if(p != l)
642 3e0d8fb3 2005-12-27 devnull p->code = Rserver;
643 3e0d8fb3 2005-12-27 devnull continue;
644 3e0d8fb3 2005-12-27 devnull }
645 3e0d8fb3 2005-12-27 devnull }
646 3e0d8fb3 2005-12-27 devnull
647 3e0d8fb3 2005-12-27 devnull
648 3e0d8fb3 2005-12-27 devnull /* remove any soa's from the authority section */
649 3e0d8fb3 2005-12-27 devnull soarr = rrremtype(&m.ns, Tsoa);
650 3e0d8fb3 2005-12-27 devnull
651 3e0d8fb3 2005-12-27 devnull /* incorporate answers */
652 3e0d8fb3 2005-12-27 devnull if(m.an)
653 3e0d8fb3 2005-12-27 devnull rrattach(m.an, (m.flags & Fauth) ? 1 : 0);
654 3e0d8fb3 2005-12-27 devnull if(m.ar)
655 3e0d8fb3 2005-12-27 devnull rrattach(m.ar, 0);
656 3e0d8fb3 2005-12-27 devnull if(m.ns){
657 3e0d8fb3 2005-12-27 devnull ndp = m.ns->owner;
658 3e0d8fb3 2005-12-27 devnull rrattach(m.ns, 0);
659 3e0d8fb3 2005-12-27 devnull } else
660 3e0d8fb3 2005-12-27 devnull ndp = 0;
661 3e0d8fb3 2005-12-27 devnull
662 3e0d8fb3 2005-12-27 devnull /* free the question */
663 3e0d8fb3 2005-12-27 devnull if(m.qd)
664 3e0d8fb3 2005-12-27 devnull rrfreelist(m.qd);
665 3e0d8fb3 2005-12-27 devnull
666 3e0d8fb3 2005-12-27 devnull /*
667 3e0d8fb3 2005-12-27 devnull * Any reply from an authoritative server,
668 3e0d8fb3 2005-12-27 devnull * or a positive reply terminates the search
669 3e0d8fb3 2005-12-27 devnull */
670 3e0d8fb3 2005-12-27 devnull if(m.an != nil || (m.flags & Fauth)){
671 3e0d8fb3 2005-12-27 devnull if(m.an == nil && (m.flags & Rmask) == Rname)
672 3e0d8fb3 2005-12-27 devnull dp->nonexistent = Rname;
673 3e0d8fb3 2005-12-27 devnull else
674 3e0d8fb3 2005-12-27 devnull dp->nonexistent = 0;
675 3e0d8fb3 2005-12-27 devnull
676 3e0d8fb3 2005-12-27 devnull /*
677 3e0d8fb3 2005-12-27 devnull * cache any negative responses, free soarr
678 3e0d8fb3 2005-12-27 devnull */
679 3e0d8fb3 2005-12-27 devnull if((m.flags & Fauth) && m.an == nil)
680 3e0d8fb3 2005-12-27 devnull cacheneg(dp, type, (m.flags & Rmask), soarr);
681 3e0d8fb3 2005-12-27 devnull else
682 3e0d8fb3 2005-12-27 devnull rrfreelist(soarr);
683 3e0d8fb3 2005-12-27 devnull return 1;
684 3e0d8fb3 2005-12-27 devnull }
685 3e0d8fb3 2005-12-27 devnull rrfreelist(soarr);
686 3e0d8fb3 2005-12-27 devnull
687 3e0d8fb3 2005-12-27 devnull /*
688 3e0d8fb3 2005-12-27 devnull * if we've been given better name servers
689 3e0d8fb3 2005-12-27 devnull * recurse
690 3e0d8fb3 2005-12-27 devnull */
691 3e0d8fb3 2005-12-27 devnull if(m.ns){
692 3e0d8fb3 2005-12-27 devnull tp = rrlookup(ndp, Tns, NOneg);
693 3e0d8fb3 2005-12-27 devnull if(!contains(nsrp, tp)){
694 3e0d8fb3 2005-12-27 devnull rv = netquery(dp, type, tp, reqp, depth+1);
695 3e0d8fb3 2005-12-27 devnull rrfreelist(tp);
696 3e0d8fb3 2005-12-27 devnull return rv;
697 3e0d8fb3 2005-12-27 devnull } else
698 3e0d8fb3 2005-12-27 devnull rrfreelist(tp);
699 3e0d8fb3 2005-12-27 devnull }
700 3e0d8fb3 2005-12-27 devnull }
701 3e0d8fb3 2005-12-27 devnull }
702 3e0d8fb3 2005-12-27 devnull
703 3e0d8fb3 2005-12-27 devnull /* if all servers returned failure, propogate it */
704 3e0d8fb3 2005-12-27 devnull dp->nonexistent = Rserver;
705 3e0d8fb3 2005-12-27 devnull for(p = dest; p < l; p++)
706 3e0d8fb3 2005-12-27 devnull if(p->code != Rserver)
707 3e0d8fb3 2005-12-27 devnull dp->nonexistent = 0;
708 3e0d8fb3 2005-12-27 devnull
709 3e0d8fb3 2005-12-27 devnull return 0;
710 3e0d8fb3 2005-12-27 devnull }
711 3e0d8fb3 2005-12-27 devnull
712 3e0d8fb3 2005-12-27 devnull typedef struct Qarg Qarg;
713 3e0d8fb3 2005-12-27 devnull struct Qarg
714 3e0d8fb3 2005-12-27 devnull {
715 3e0d8fb3 2005-12-27 devnull DN *dp;
716 3e0d8fb3 2005-12-27 devnull int type;
717 3e0d8fb3 2005-12-27 devnull RR *nsrp;
718 3e0d8fb3 2005-12-27 devnull Request *reqp;
719 3e0d8fb3 2005-12-27 devnull int depth;
720 3e0d8fb3 2005-12-27 devnull };
721 3e0d8fb3 2005-12-27 devnull
722 3e0d8fb3 2005-12-27 devnull
723 3e0d8fb3 2005-12-27 devnull static int
724 3e0d8fb3 2005-12-27 devnull netquery(DN *dp, int type, RR *nsrp, Request *reqp, int depth)
725 3e0d8fb3 2005-12-27 devnull {
726 3e0d8fb3 2005-12-27 devnull uchar *obuf;
727 3e0d8fb3 2005-12-27 devnull uchar *ibuf;
728 3e0d8fb3 2005-12-27 devnull RR *rp;
729 3e0d8fb3 2005-12-27 devnull int fd, rv;
730 3e0d8fb3 2005-12-27 devnull
731 3e0d8fb3 2005-12-27 devnull if(depth > 12)
732 3e0d8fb3 2005-12-27 devnull return 0;
733 3e0d8fb3 2005-12-27 devnull
734 3e0d8fb3 2005-12-27 devnull /* use alloced buffers rather than ones from the stack */
735 3e0d8fb3 2005-12-27 devnull ibuf = emalloc(Maxudpin+OUdphdrsize);
736 3e0d8fb3 2005-12-27 devnull obuf = emalloc(Maxudp+OUdphdrsize);
737 3e0d8fb3 2005-12-27 devnull
738 3e0d8fb3 2005-12-27 devnull slave(reqp);
739 3e0d8fb3 2005-12-27 devnull
740 3e0d8fb3 2005-12-27 devnull /* prepare server RR's for incremental lookup */
741 3e0d8fb3 2005-12-27 devnull for(rp = nsrp; rp; rp = rp->next)
742 3e0d8fb3 2005-12-27 devnull rp->marker = 0;
743 3e0d8fb3 2005-12-27 devnull
744 3e0d8fb3 2005-12-27 devnull fd = udpport();
745 3e0d8fb3 2005-12-27 devnull if(fd < 0)
746 3e0d8fb3 2005-12-27 devnull return 0;
747 3e0d8fb3 2005-12-27 devnull rv = netquery1(fd, dp, type, nsrp, reqp, depth, ibuf, obuf);
748 3e0d8fb3 2005-12-27 devnull close(fd);
749 3e0d8fb3 2005-12-27 devnull free(ibuf);
750 3e0d8fb3 2005-12-27 devnull free(obuf);
751 3e0d8fb3 2005-12-27 devnull
752 3e0d8fb3 2005-12-27 devnull return rv;
753 3e0d8fb3 2005-12-27 devnull }