10 Maxdest= 24, /* maximum destinations for a request message */
11 Maxtrans= 3, /* maximum transmissions to a server */
14 static int netquery(DN*, int, RR*, Request*, int);
15 static RR* dnresolve1(char*, int, int, Request*, int, int);
20 * lookup 'type' info for domain name 'name'. If it doesn't exist, try
21 * looking it up as a canonical name.
24 dnresolve(char *name, int class, int type, Request *req, RR **cn, int depth, int recurse, int rooted, int *status)
35 * hack for systems that don't have resolve search
36 * lists. Just look up the simple name in the database.
38 if(!rooted && strchr(name, '.') == 0){
40 drp = domainlist(class);
41 for(nrp = drp; nrp != nil; nrp = nrp->next){
42 snprint(nname, sizeof(nname), "%s.%s", name, nrp->ptr->name);
43 rp = dnresolve(nname, class, type, req,cn, depth, recurse, rooted, status);
44 rrfreelist(rrremneg(&rp));
54 * try the name directly
56 rp = dnresolve1(name, class, type, req, depth, recurse);
60 /* try it as a canonical name if we weren't told the name didn't exist */
61 dp = dnlookup(name, class, 0);
62 if(type != Tptr && dp->nonexistent != Rname){
63 for(loops=0; rp == nil && loops < 32; loops++){
64 rp = dnresolve1(name, class, Tcname, req, depth, recurse);
74 name = rp->host->name;
80 rp = dnresolve1(name, class, type, req, depth, recurse);
84 /* distinction between not found and not good */
85 if(rp == 0 && status != 0 && dp->nonexistent != 0)
86 *status = dp->nonexistent;
92 dnresolve1(char *name, int class, int type, Request *req, int depth, int recurse)
95 RR *rp, *nsrp, *dbnsrp;
99 syslog(0, LOG, "dnresolve1 %s %d %d", name, type, class);
101 /* only class Cin implemented so far */
105 dp = dnlookup(name, class, 1);
108 * Try the cache first
110 rp = rrlookup(dp, type, OKneg);
113 /* unauthenticated db entries are hints */
117 /* cached entry must still be valid */
119 /* but Tall entries are special */
120 if(type != Tall || rp->query == Tall)
128 * try the cache for a canonical name. if found punt
129 * since we'll find it during the canonical name search
133 rp = rrlookup(dp, Tcname, NOneg);
140 * if we're running as just a resolver, go to our
141 * designated name servers
144 nsrp = randomize(getdnsservers(class));
146 if(netquery(dp, type, nsrp, req, depth+1)){
148 return rrlookup(dp, type, OKneg);
155 * walk up the domain name looking for
156 * a name server for the domain.
158 for(cp = name; cp; cp = walkup(cp)){
160 * if this is a local (served by us) domain,
163 dbnsrp = randomize(dblookup(cp, class, Tns, 0, 0));
164 if(dbnsrp && dbnsrp->local){
165 rp = dblookup(name, class, type, 1, dbnsrp->ttl);
171 * if recursion isn't set, just accept local
174 if(recurse == Dontrecurse){
180 /* look for ns in cache */
181 nsdp = dnlookup(cp, class, 0);
184 nsrp = randomize(rrlookup(nsdp, Tns, NOneg));
186 /* if the entry timed out, ignore it */
187 if(nsrp && nsrp->ttl < now){
195 /* try the name servers found in cache */
196 if(netquery(dp, type, nsrp, req, depth+1)){
198 return rrlookup(dp, type, OKneg);
206 /* try the name servers found in db */
207 if(netquery(dp, type, dbnsrp, req, depth+1)){
208 /* we got an answer */
210 return rrlookup(dp, type, NOneg);
216 /* settle for a non-authoritative answer */
217 rp = rrlookup(dp, type, OKneg);
221 /* noone answered. try the database, we might have a chance. */
222 return dblookup(name, class, type, 0, 0);
226 * walk a domain name one element to the right. return a pointer to that element.
227 * in other words, return a pointer to the parent domain name.
234 cp = strchr(name, '.');
244 * Get a udpport for requests and replies.
251 if((fd = dial("udp!0!53", nil, nil, nil)) < 0)
252 warning("can't get udp port");
257 mkreq(DN *dp, int type, uchar *buf, int flags, ushort reqno)
261 Udphdr *uh = (Udphdr*)buf;
263 /* stuff port number into output buffer */
264 memset(uh, 0, sizeof(*uh));
265 hnputs(uh->rport, 53);
267 /* make request and convert it to output format */
268 memset(&m, 0, sizeof(m));
271 m.qd = rralloc(type);
274 len = convDNS2M(&m, &buf[Udphdrsize], Maxudp);
276 abort(); /* "can't convert" */;
282 freeanswers(DNSmsg *mp)
291 * read replies to a request. ignore any of the wrong type. wait at most 5 seconds.
293 static int udpreadtimeout(int, Udphdr*, void*, int, int);
295 readreply(int fd, DN *dp, int type, ushort req,
296 uchar *ibuf, DNSmsg *mp, ulong endtime, Request *reqp)
303 for(; ; freeanswers(mp)){
306 return -1; /* timed out */
309 len = udpreadtimeout(fd, (Udphdr*)ibuf, ibuf+Udphdrsize, Maxudpin, (endtime-now)*1000);
311 return -1; /* timed out */
313 /* convert into internal format */
314 memset(mp, 0, sizeof(*mp));
315 err = convM2DNS(&ibuf[Udphdrsize], len, mp);
317 syslog(0, LOG, "input err %s: %I", err, ibuf);
321 logreply(reqp->id, ibuf, mp);
323 /* answering the right question? */
325 syslog(0, LOG, "%d: id %d instead of %d: %I", reqp->id,
330 syslog(0, LOG, "%d: no question RR: %I", reqp->id, ibuf);
333 if(mp->qd->owner != dp){
334 syslog(0, LOG, "%d: owner %s instead of %s: %I", reqp->id,
335 mp->qd->owner->name, dp->name, ibuf);
338 if(mp->qd->type != type){
339 syslog(0, LOG, "%d: type %d instead of %d: %I", reqp->id,
340 mp->qd->type, type, ibuf);
344 /* remember what request this is in answer to */
345 for(rp = mp->an; rp; rp = rp->next)
351 return 0; /* never reached */
355 udpreadtimeout(int fd, Udphdr *h, void *data, int n, int ms)
364 tv.tv_usec = (ms%1000)*1000;
366 if(select(fd+1, &rd, 0, 0, &tv) != 1)
368 return udpread(fd, h, data, n);
372 * return non-0 if first list includes second list
375 contains(RR *rp1, RR *rp2)
379 for(trp2 = rp2; trp2; trp2 = trp2->next){
380 for(trp1 = rp1; trp1; trp1 = trp1->next){
381 if(trp1->type == trp2->type)
382 if(trp1->host == trp2->host)
383 if(trp1->owner == trp2->owner)
394 typedef struct Dest Dest;
397 uchar a[IPaddrlen]; /* ip address */
398 DN *s; /* name server */
399 int nx; /* number of transmissions */
405 * return multicast version if any
411 if(ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0)
413 if(ipcmp(ip, IPv4bcast) == 0)
423 * Get next server address
426 serveraddrs(RR *nsrp, Dest *dest, int nd, int depth, Request *reqp)
435 * look for a server whose address we already know.
436 * if we find one, mark it so we ignore this on
440 for(rp = nsrp; rp; rp = rp->next){
441 assert(rp->magic == RRmagic);
444 arp = rrlookup(rp->host, Ta, NOneg);
449 arp = dblookup(rp->host->name, Cin, Ta, 0, 0);
457 * if the cache and database lookup didn't find any new
458 * server addresses, try resolving one via the network.
459 * Mark any we try to resolve so we don't try a second time.
462 for(rp = nsrp; rp; rp = rp->next){
468 * avoid loops looking up a server under itself
470 if(subsume(rp->owner->name, rp->host->name))
473 arp = dnresolve(rp->host->name, Cin, Ta, reqp, 0, depth+1, Recurse, 1, 0);
474 rrfreelist(rrremneg(&arp));
480 /* use any addresses that we found */
481 for(trp = arp; trp; trp = trp->next){
485 parseip(cur->a, trp->ip->name);
490 cur->code = Rtimeout;
498 * cache negative responses
501 cacheneg(DN *dp, int type, int rcode, RR *soarr)
507 /* no cache time specified, don' make anything up */
509 if(soarr->next != nil){
510 rrfreelist(soarr->next);
513 soaowner = soarr->owner;
517 /* the attach can cause soarr to be freed so mine it now */
518 if(soarr != nil && soarr->soa != nil)
519 ttl = soarr->soa->minttl+now;
523 /* add soa and negative RR to the database */
529 rp->negsoaowner = soaowner;
530 rp->negrcode = rcode;
536 * query name servers. If the name server returns a pointer to another
537 * name server, recurse.
540 netquery1(int fd, DN *dp, int type, RR *nsrp, Request *reqp, int depth, uchar *ibuf, uchar *obuf)
542 int ndest, j, len, replywaits, rv;
552 /* pack request into a message */
554 len = mkreq(dp, type, obuf, Frecurse|Oquery, req);
556 /* no server addresses yet */
560 * transmit requests and wait for answers.
561 * at most Maxtrans attempts to each address.
562 * each cycle send one more message than the previous.
564 for(ndest = 1; ndest < Maxdest; ndest++){
568 if(endtime >= reqp->aborttime)
571 /* get a server address if we need one */
573 j = serveraddrs(nsrp, dest, l - p, depth, reqp);
577 /* no servers, punt */
581 /* send to first 'ndest' destinations */
583 for(; p < &dest[ndest] && p < l; p++){
584 /* skip destinations we've finished with */
585 if(p->nx >= Maxtrans)
590 /* exponential backoff of requests */
591 if((1<<p->nx) > ndest)
594 memmove(obuf, p->a, sizeof(p->a));
596 logsend(reqp->id, depth, obuf, p->s->name,
599 fprint(2, "send %I %I %d %d\n", uh->raddr, uh->laddr, nhgets(uh->rport), nhgets(uh->lport));
600 if(udpwrite(fd, uh, obuf+Udphdrsize, len) < 0)
601 warning("sending udp msg %r");
605 break; /* no destinations left */
607 /* wait up to 5 seconds for replies */
608 endtime = time(0) + 5;
609 if(endtime > reqp->aborttime)
610 endtime = reqp->aborttime;
612 for(replywaits = 0; replywaits < ndest; replywaits++){
613 if(readreply(fd, dp, type, req, ibuf, &m, endtime, reqp) < 0)
614 break; /* timed out */
617 for(p = dest; p < l; p++)
618 if(memcmp(p->a, ibuf, sizeof(p->a)) == 0)
621 /* remove all addrs of responding server from list */
622 for(np = dest; np < l; np++)
626 /* ignore any error replies */
627 if((m.flags & Rmask) == Rserver){
637 /* ignore any bad delegations */
638 if(m.ns && baddelegation(m.ns, nsrp, ibuf)){
651 /* remove any soa's from the authority section */
652 soarr = rrremtype(&m.ns, Tsoa);
654 /* incorporate answers */
656 rrattach(m.an, (m.flags & Fauth) ? 1 : 0);
665 /* free the question */
670 * Any reply from an authoritative server,
671 * or a positive reply terminates the search
673 if(m.an != nil || (m.flags & Fauth)){
674 if(m.an == nil && (m.flags & Rmask) == Rname)
675 dp->nonexistent = Rname;
680 * cache any negative responses, free soarr
682 if((m.flags & Fauth) && m.an == nil)
683 cacheneg(dp, type, (m.flags & Rmask), soarr);
691 * if we've been given better name servers
695 tp = rrlookup(ndp, Tns, NOneg);
696 if(!contains(nsrp, tp)){
697 rv = netquery(dp, type, tp, reqp, depth+1);
706 /* if all servers returned failure, propogate it */
707 dp->nonexistent = Rserver;
708 for(p = dest; p < l; p++)
709 if(p->code != Rserver)
715 typedef struct Qarg Qarg;
727 netquery(DN *dp, int type, RR *nsrp, Request *reqp, int depth)
737 /* use alloced buffers rather than ones from the stack */
738 ibuf = emalloc(Maxudpin+Udphdrsize);
739 obuf = emalloc(Maxudp+Udphdrsize);
741 /* prepare server RR's for incremental lookup */
742 for(rp = nsrp; rp; rp = rp->next)
748 rv = netquery1(fd, dp, type, nsrp, reqp, depth, ibuf, obuf);