11 Maxdest= 24, /* maximum destinations for a request message */
12 Maxtrans= 3 /* maximum transmissions to a server */
15 static int netquery(DN*, int, RR*, Request*, int);
16 static RR* dnresolve1(char*, int, int, Request*, int, int);
21 * lookup 'type' info for domain name 'name'. If it doesn't exist, try
22 * looking it up as a canonical name.
25 dnresolve(char *name, int class, int type, Request *req, RR **cn, int depth, int recurse, int rooted, int *status)
36 * hack for systems that don't have resolve search
37 * lists. Just look up the simple name in the database.
39 if(!rooted && strchr(name, '.') == 0){
41 drp = domainlist(class);
42 for(nrp = drp; nrp != nil; nrp = nrp->next){
43 snprint(nname, sizeof(nname), "%s.%s", name, nrp->ptr->name);
44 rp = dnresolve(nname, class, type, req,cn, depth, recurse, rooted, status);
45 rrfreelist(rrremneg(&rp));
55 * try the name directly
57 rp = dnresolve1(name, class, type, req, depth, recurse);
61 /* try it as a canonical name if we weren't told the name didn't exist */
62 dp = dnlookup(name, class, 0);
63 if(type != Tptr && dp->nonexistent != Rname){
64 for(loops=0; rp == nil && loops < 32; loops++){
65 rp = dnresolve1(name, class, Tcname, req, depth, recurse);
75 name = rp->host->name;
81 rp = dnresolve1(name, class, type, req, depth, recurse);
85 /* distinction between not found and not good */
86 if(rp == 0 && status != 0 && dp->nonexistent != 0)
87 *status = dp->nonexistent;
93 dnresolve1(char *name, int class, int type, Request *req, int depth, int recurse)
96 RR *rp, *nsrp, *dbnsrp;
100 syslog(0, LOG, "dnresolve1 %s %d %d", name, type, class);
102 /* only class Cin implemented so far */
106 dp = dnlookup(name, class, 1);
109 * Try the cache first
111 rp = rrlookup(dp, type, OKneg);
114 /* unauthenticated db entries are hints */
118 /* cached entry must still be valid */
120 /* but Tall entries are special */
121 if(type != Tall || rp->query == Tall)
129 * try the cache for a canonical name. if found punt
130 * since we'll find it during the canonical name search
134 rp = rrlookup(dp, Tcname, NOneg);
141 * if we're running as just a resolver, go to our
142 * designated name servers
145 nsrp = randomize(getdnsservers(class));
147 if(netquery(dp, type, nsrp, req, depth+1)){
149 return rrlookup(dp, type, OKneg);
156 * walk up the domain name looking for
157 * a name server for the domain.
159 for(cp = name; cp; cp = walkup(cp)){
161 * if this is a local (served by us) domain,
164 dbnsrp = randomize(dblookup(cp, class, Tns, 0, 0));
165 if(dbnsrp && dbnsrp->local){
166 rp = dblookup(name, class, type, 1, dbnsrp->ttl);
172 * if recursion isn't set, just accept local
175 if(recurse == Dontrecurse){
181 /* look for ns in cache */
182 nsdp = dnlookup(cp, class, 0);
185 nsrp = randomize(rrlookup(nsdp, Tns, NOneg));
187 /* if the entry timed out, ignore it */
188 if(nsrp && nsrp->ttl < now){
196 /* try the name servers found in cache */
197 if(netquery(dp, type, nsrp, req, depth+1)){
199 return rrlookup(dp, type, OKneg);
207 /* try the name servers found in db */
208 if(netquery(dp, type, dbnsrp, req, depth+1)){
209 /* we got an answer */
211 return rrlookup(dp, type, NOneg);
217 /* settle for a non-authoritative answer */
218 rp = rrlookup(dp, type, OKneg);
222 /* noone answered. try the database, we might have a chance. */
223 return dblookup(name, class, type, 0, 0);
227 * walk a domain name one element to the right. return a pointer to that element.
228 * in other words, return a pointer to the parent domain name.
235 cp = strchr(name, '.');
245 * Get a udpport for requests and replies.
252 if((fd = dial("udp!0!53", nil, nil, nil)) < 0)
253 warning("can't get udp port");
258 mkreq(DN *dp, int type, uchar *buf, int flags, ushort reqno)
262 Udphdr *uh = (Udphdr*)buf;
264 /* stuff port number into output buffer */
265 memset(uh, 0, sizeof(*uh));
266 hnputs(uh->rport, 53);
268 /* make request and convert it to output format */
269 memset(&m, 0, sizeof(m));
272 m.qd = rralloc(type);
275 len = convDNS2M(&m, &buf[Udphdrsize], Maxudp);
277 abort(); /* "can't convert" */;
283 freeanswers(DNSmsg *mp)
292 * read replies to a request. ignore any of the wrong type. wait at most 5 seconds.
294 static int udpreadtimeout(int, Udphdr*, void*, int, int);
296 readreply(int fd, DN *dp, int type, ushort req,
297 uchar *ibuf, DNSmsg *mp, ulong endtime, Request *reqp)
304 for(; ; freeanswers(mp)){
307 return -1; /* timed out */
310 len = udpreadtimeout(fd, (Udphdr*)ibuf, ibuf+Udphdrsize, Maxudpin, (endtime-now)*1000);
312 return -1; /* timed out */
314 /* convert into internal format */
315 memset(mp, 0, sizeof(*mp));
316 err = convM2DNS(&ibuf[Udphdrsize], len, mp);
318 syslog(0, LOG, "input err %s: %I", err, ibuf);
322 logreply(reqp->id, ibuf, mp);
324 /* answering the right question? */
326 syslog(0, LOG, "%d: id %d instead of %d: %I", reqp->id,
331 syslog(0, LOG, "%d: no question RR: %I", reqp->id, ibuf);
334 if(mp->qd->owner != dp){
335 syslog(0, LOG, "%d: owner %s instead of %s: %I", reqp->id,
336 mp->qd->owner->name, dp->name, ibuf);
339 if(mp->qd->type != type){
340 syslog(0, LOG, "%d: type %d instead of %d: %I", reqp->id,
341 mp->qd->type, type, ibuf);
345 /* remember what request this is in answer to */
346 for(rp = mp->an; rp; rp = rp->next)
352 return 0; /* never reached */
356 udpreadtimeout(int fd, Udphdr *h, void *data, int n, int ms)
365 tv.tv_usec = (ms%1000)*1000;
367 if(select(fd+1, &rd, 0, 0, &tv) != 1)
369 return udpread(fd, h, data, n);
373 * return non-0 if first list includes second list
376 contains(RR *rp1, RR *rp2)
380 for(trp2 = rp2; trp2; trp2 = trp2->next){
381 for(trp1 = rp1; trp1; trp1 = trp1->next){
382 if(trp1->type == trp2->type)
383 if(trp1->host == trp2->host)
384 if(trp1->owner == trp2->owner)
395 typedef struct Dest Dest;
398 uchar a[IPaddrlen]; /* ip address */
399 DN *s; /* name server */
400 int nx; /* number of transmissions */
406 * return multicast version if any
412 if(ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0)
414 if(ipcmp(ip, IPv4bcast) == 0)
424 * Get next server address
427 serveraddrs(RR *nsrp, Dest *dest, int nd, int depth, Request *reqp)
436 * look for a server whose address we already know.
437 * if we find one, mark it so we ignore this on
441 for(rp = nsrp; rp; rp = rp->next){
442 assert(rp->magic == RRmagic);
445 arp = rrlookup(rp->host, Ta, NOneg);
450 arp = dblookup(rp->host->name, Cin, Ta, 0, 0);
458 * if the cache and database lookup didn't find any new
459 * server addresses, try resolving one via the network.
460 * Mark any we try to resolve so we don't try a second time.
463 for(rp = nsrp; rp; rp = rp->next){
469 * avoid loops looking up a server under itself
471 if(subsume(rp->owner->name, rp->host->name))
474 arp = dnresolve(rp->host->name, Cin, Ta, reqp, 0, depth+1, Recurse, 1, 0);
475 rrfreelist(rrremneg(&arp));
481 /* use any addresses that we found */
482 for(trp = arp; trp; trp = trp->next){
486 parseip(cur->a, trp->ip->name);
491 cur->code = Rtimeout;
499 * cache negative responses
502 cacheneg(DN *dp, int type, int rcode, RR *soarr)
508 /* no cache time specified, don' make anything up */
510 if(soarr->next != nil){
511 rrfreelist(soarr->next);
514 soaowner = soarr->owner;
518 /* the attach can cause soarr to be freed so mine it now */
519 if(soarr != nil && soarr->soa != nil)
520 ttl = soarr->soa->minttl+now;
524 /* add soa and negative RR to the database */
530 rp->negsoaowner = soaowner;
531 rp->negrcode = rcode;
537 * query name servers. If the name server returns a pointer to another
538 * name server, recurse.
541 netquery1(int fd, DN *dp, int type, RR *nsrp, Request *reqp, int depth, uchar *ibuf, uchar *obuf)
543 int ndest, j, len, replywaits, rv;
553 /* pack request into a message */
555 len = mkreq(dp, type, obuf, Frecurse|Oquery, req);
557 /* no server addresses yet */
561 * transmit requests and wait for answers.
562 * at most Maxtrans attempts to each address.
563 * each cycle send one more message than the previous.
565 for(ndest = 1; ndest < Maxdest; ndest++){
569 if(endtime >= reqp->aborttime)
572 /* get a server address if we need one */
574 j = serveraddrs(nsrp, dest, l - p, depth, reqp);
578 /* no servers, punt */
582 /* send to first 'ndest' destinations */
584 for(; p < &dest[ndest] && p < l; p++){
585 /* skip destinations we've finished with */
586 if(p->nx >= Maxtrans)
591 /* exponential backoff of requests */
592 if((1<<p->nx) > ndest)
595 memmove(obuf, p->a, sizeof(p->a));
597 logsend(reqp->id, depth, obuf, p->s->name,
600 fprint(2, "send %I %I %d %d\n", uh->raddr, uh->laddr, nhgets(uh->rport), nhgets(uh->lport));
601 if(udpwrite(fd, uh, obuf+Udphdrsize, len) < 0)
602 warning("sending udp msg %r");
606 break; /* no destinations left */
608 /* wait up to 5 seconds for replies */
609 endtime = time(0) + 5;
610 if(endtime > reqp->aborttime)
611 endtime = reqp->aborttime;
613 for(replywaits = 0; replywaits < ndest; replywaits++){
614 if(readreply(fd, dp, type, req, ibuf, &m, endtime, reqp) < 0)
615 break; /* timed out */
618 for(p = dest; p < l; p++)
619 if(memcmp(p->a, ibuf, sizeof(p->a)) == 0)
622 /* remove all addrs of responding server from list */
623 for(np = dest; np < l; np++)
627 /* ignore any error replies */
628 if((m.flags & Rmask) == Rserver){
638 /* ignore any bad delegations */
639 if(m.ns && baddelegation(m.ns, nsrp, ibuf)){
652 /* remove any soa's from the authority section */
653 soarr = rrremtype(&m.ns, Tsoa);
655 /* incorporate answers */
657 rrattach(m.an, (m.flags & Fauth) ? 1 : 0);
666 /* free the question */
671 * Any reply from an authoritative server,
672 * or a positive reply terminates the search
674 if(m.an != nil || (m.flags & Fauth)){
675 if(m.an == nil && (m.flags & Rmask) == Rname)
676 dp->nonexistent = Rname;
681 * cache any negative responses, free soarr
683 if((m.flags & Fauth) && m.an == nil)
684 cacheneg(dp, type, (m.flags & Rmask), soarr);
692 * if we've been given better name servers
696 tp = rrlookup(ndp, Tns, NOneg);
697 if(!contains(nsrp, tp)){
698 rv = netquery(dp, type, tp, reqp, depth+1);
707 /* if all servers returned failure, propogate it */
708 dp->nonexistent = Rserver;
709 for(p = dest; p < l; p++)
710 if(p->code != Rserver)
716 typedef struct Qarg Qarg;
728 netquery(DN *dp, int type, RR *nsrp, Request *reqp, int depth)
738 /* use alloced buffers rather than ones from the stack */
739 ibuf = emalloc(Maxudpin+Udphdrsize);
740 obuf = emalloc(Maxudp+Udphdrsize);
742 /* prepare server RR's for incremental lookup */
743 for(rp = nsrp; rp; rp = rp->next)
749 rv = netquery1(fd, dp, type, nsrp, reqp, depth, ibuf, obuf);