This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / usr.sbin / named / ns_resp.c
CommitLineData
15637ed4
RG
1/*
2 * Copyright (c) 1986, 1988, 1990 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static char sccsid[] = "@(#)ns_resp.c 4.65 (Berkeley) 3/3/91";
36#endif /* not lint */
37
38#include <sys/param.h>
39#include <sys/time.h>
40#include <sys/socket.h>
41#include <sys/file.h>
42#include <netinet/in.h>
43#include <syslog.h>
44#include <arpa/nameser.h>
45#include <resolv.h>
46#include <stdio.h>
47#include "ns.h"
48#include "db.h"
49
50extern int debug;
51extern FILE *ddt;
52extern int errno;
53extern u_char *dnptrs[];
54extern time_t retrytime();
55extern struct fwdinfo *fwdtab;
56extern struct sockaddr_in from_addr; /* Source addr of last packet */
57extern int needs_prime_cache;
58extern int priming;
59
60struct qinfo *sysquery();
61
62ns_resp(msg, msglen)
63 u_char *msg;
64 int msglen;
65{
66 register struct qinfo *qp;
67 register HEADER *hp;
68 register struct qserv *qs;
69 register struct databuf *ns, *ns2;
70 register u_char *cp;
71 struct databuf *nsp[NSMAX], **nspp;
72 int i, c, n, ancount, aucount, nscount, arcount;
73 int type, class, dbflags;
74 int cname = 0; /* flag for processing cname response */
75 int count, founddata, foundname;
76 int buflen;
77 int newmsglen;
78 char name[MAXDNAME], *dname;
79 char *fname;
80 u_char newmsg[BUFSIZ];
81 u_char **dpp, *tp;
82 time_t rtrip;
83
84 struct hashbuf *htp;
85 struct namebuf *np;
86 struct netinfo *lp;
87 extern struct netinfo *local();
88 extern int nsid;
89 extern int addcount;
90 struct fwdinfo *fwd;
91
92#ifdef STATS
93 stats[S_RESPONSES].cnt++;
94#endif
95 hp = (HEADER *) msg;
96 if ((qp = qfindid(hp->id)) == NULL ) {
97#ifdef DEBUG
98 if (debug > 1)
99 fprintf(ddt,"DUP? dropped (id %d)\n", ntohs(hp->id));
100#endif
101#ifdef STATS
102 stats[S_DUPRESP].cnt++;
103#endif
104 return;
105 }
106
107#ifdef DEBUG
108 if (debug >= 2)
109 fprintf(ddt,"%s response nsid=%d id=%d\n",
110 qp->q_system ? "SYSTEM" : "USER",
111 ntohs(qp->q_nsid), ntohs(qp->q_id));
112#endif
113
114 /*
115 * Here we handle bad responses from servers.
116 * Several possibilities come to mind:
117 * The server is sick and returns SERVFAIL
118 * The server returns some garbage opcode (its sick)
119 * The server can't understand our query and return FORMERR
120 * In all these cases, we simply drop the packet and force
121 * a retry. This will make him look bad due to unresponsiveness.
122 * Be sure not to include authoritative NXDOMAIN
123 */
124 if ((hp->rcode != NOERROR && hp->rcode != NXDOMAIN)
125 || (hp->rcode == NXDOMAIN && !hp->aa)
126 || hp->opcode != QUERY) {
127#ifdef DEBUG
128 if (debug >= 2)
129 fprintf(ddt,"resp: error (ret %d, op %d), dropped\n",
130 hp->rcode, hp->opcode);
131#endif
132#ifdef STATS
133 stats[S_BADRESPONSES].cnt++;
134#endif
135 return;
136 }
137
138#ifdef ALLOW_UPDATES
139 if ( (hp->rcode == NOERROR) &&
140 (hp->opcode == UPDATEA || hp->opcode == UPDATED ||
141 hp->opcode == UPDATEDA || hp->opcode == UPDATEM ||
142 hp->opcode == UPDATEMA) ) {
143 /*
144 * Update the secondary's copy, now that the primary
145 * successfully completed the update. Zone doesn't matter
146 * for dyn. update -- doupdate calls findzone to find it
147 */
148 doupdate(qp->q_msg, qp->q_msglen, qp->q_msg + sizeof(HEADER),
149 0, (struct databuf *)0, 0);
150#ifdef DEBUG
151 if (debug >= 3)
152 fprintf(ddt,"resp: leaving, UPDATE*\n");
153#endif
154 /* return code filled in by doupdate */
155 goto return_msg;
156 }
157#endif ALLOW_UPDATES
158
159 /*
160 * Determine if the response came from a forwarder. Packets from
161 * anyplace not listed as a forwarder or as a server to whom we
162 * might have forwarded the query will be dropped.
163 */
164 for (fwd = fwdtab; fwd != (struct fwdinfo *)NULL; fwd = fwd->next)
165 if (bcmp((char *)&fwd->fwdaddr.sin_addr, &from_addr.sin_addr,
166 sizeof(struct in_addr)) == 0)
167 break;
168 /*
169 * If we were using nameservers, find the qinfo pointer and update
170 * the rtt and fact that we have called on this server before.
171 */
172 if (fwd == (struct fwdinfo *)NULL) {
173 struct timeval *stp;
174
175 for (n = 0, qs = qp->q_addr; n < qp->q_naddr; n++, qs++)
176 if (bcmp((char *)&qs->ns_addr.sin_addr,
177 &from_addr.sin_addr, sizeof(struct in_addr)) == 0)
178 break;
179 if (n >= qp->q_naddr) {
180#ifdef DEBUG
181 if (debug)
182 fprintf(ddt, "Response from unexpected source %s\n",
183 inet_ntoa(from_addr.sin_addr));
184#endif DEBUG
185#ifdef STATS
186 stats[S_MARTIANS].cnt++;
187#endif
188 /*
189 * We don't know who this response came from so it
190 * gets dropped on the floor.
191 */
192 return;
193 }
194 stp = &qs->stime;
195
196 /* Handle response from different (untried) interface */
197 if (stp->tv_sec == 0) {
198 ns = qs->ns;
199 while (qs > qp->q_addr &&
200 (qs->stime.tv_sec == 0 || qs->ns != ns))
201 qs--;
202 *stp = qs->stime;
203#ifdef DEBUG
204 if (debug)
205 fprintf(ddt,
206 "Response from unused address %s, assuming %s\n",
207 inet_ntoa(from_addr.sin_addr),
208 inet_ntoa(qs->ns_addr.sin_addr));
209#endif DEBUG
210 }
211
212 /* compute query round trip time */
213 rtrip = ((tt.tv_sec - stp->tv_sec) * 1000 +
214 (tt.tv_usec - stp->tv_usec) / 1000);
215
216#ifdef DEBUG
217 if (debug > 2)
218 fprintf(ddt,"stime %d/%d now %d/%d rtt %d\n",
219 stp->tv_sec, stp->tv_usec,
220 tt.tv_sec, tt.tv_usec, rtrip);
221#endif
222 /* prevent floating point overflow, limit to 1000 sec */
223 if (rtrip > 1000000)
224 rtrip = 1000000;
225 ns = qs->nsdata;
226 /*
227 * Don't update nstime if this doesn't look
228 * like an address databuf now. XXX
229 */
230 if (ns->d_type == T_A && ns->d_class == qs->ns->d_class) {
231 if (ns->d_nstime == 0)
232 ns->d_nstime = (u_long)rtrip;
233 else
234 ns->d_nstime = ns->d_nstime * ALPHA +
235 (1-ALPHA) * (u_long)rtrip;
236 /* prevent floating point overflow, limit to 1000 sec */
237 if (ns->d_nstime > 1000000)
238 ns->d_nstime = 1000000;
239 }
240
241 /*
242 * Record the source so that we do not use this NS again.
243 */
244 if(qp->q_nusedns < NSMAX) {
245 qp->q_usedns[qp->q_nusedns++] = qs->ns;
246#ifdef DEBUG
247 if(debug > 1)
248 fprintf(ddt, "NS #%d addr %s used, rtt %d\n",
249 n, inet_ntoa(qs->ns_addr.sin_addr),
250 ns->d_nstime);
251#endif DEBUG
252 }
253
254 /*
255 * Penalize those who had earlier chances but failed
256 * by multiplying round-trip times by BETA (>1).
257 * Improve nstime for unused addresses by applying GAMMA.
258 * The GAMMA factor makes unused entries slowly
259 * improve, so they eventually get tried again.
260 * GAMMA should be slightly less than 1.
261 * Watch out for records that may have timed out
262 * and are no longer the correct type. XXX
263 */
264
265 for (n = 0, qs = qp->q_addr; n < qp->q_naddr; n++, qs++) {
266 ns2 = qs->nsdata;
267 if (ns2 == ns)
268 continue;
269 if (ns2->d_type != T_A ||
270 ns2->d_class != qs->ns->d_class) /* XXX */
271 continue;
272 if (qs->stime.tv_sec) {
273 if (ns2->d_nstime == 0)
274 ns2->d_nstime = rtrip * BETA;
275 else
276 ns2->d_nstime =
277 ns2->d_nstime * BETA + (1-ALPHA) * rtrip;
278 if (ns2->d_nstime > 1000000)
279 ns2->d_nstime = 1000000;
280 } else
281 ns2->d_nstime = ns2->d_nstime * GAMMA;
282#ifdef DEBUG
283 if(debug > 1)
284 fprintf(ddt, "NS #%d %s rtt now %d\n", n,
285 inet_ntoa(qs->ns_addr.sin_addr),
286 ns2->d_nstime);
287#endif DEBUG
288 }
289 }
290
291 /*
292 * Skip query section
293 */
294 addcount = 0;
295 cp = msg + sizeof(HEADER);
296 dpp = dnptrs;
297 *dpp++ = msg;
298 if ((*cp & INDIR_MASK) == 0)
299 *dpp++ = cp;
300 *dpp = NULL;
301 if (hp->qdcount) {
302 n = dn_skipname(cp, msg + msglen);
303 if (n <= 0)
304 goto formerr;
305 cp += n;
306 GETSHORT(type, cp);
307 GETSHORT(class, cp);
308 if (cp - msg > msglen)
309 goto formerr;
310 }
311
312 /*
313 * Save answers, authority, and additional records for future use.
314 */
315 ancount = ntohs(hp->ancount);
316 aucount = ntohs(hp->nscount);
317 arcount = ntohs(hp->arcount);
318 nscount = 0;
319 tp = cp;
320#ifdef DEBUG
321 if (debug >= 3)
322 fprintf(ddt,"resp: ancount %d, aucount %d, arcount %d\n",
323 ancount, aucount, arcount);
324#endif
325
326 /*
327 * If there's an answer, check if it's a CNAME response;
328 * if no answer but aucount > 0, see if there is an NS
329 * or just an SOA. (NOTE: ancount might be 1 with a CNAME,
330 * and NS records may still be in the authority section;
331 * we don't bother counting them, as we only use nscount
332 * if ancount == 0.)
333 */
334 if (ancount == 1 || (ancount == 0 && aucount > 0)) {
335 c = aucount;
336 do {
337 if (tp - msg >= msglen)
338 goto formerr;
339 n = dn_skipname(tp, msg + msglen);
340 if (n <= 0)
341 goto formerr;
342 tp += n; /* name */
343 GETSHORT(i, tp); /* type */
344 tp += sizeof(u_short); /* class */
345 tp += sizeof(u_long); /* ttl */
346 GETSHORT(count, tp); /* dlen */
347 if (tp - msg > msglen - count)
348 goto formerr;
349 tp += count;
350 if (ancount && i == T_CNAME) {
351 cname++;
352#ifdef DEBUG
353 if (debug)
354 fprintf(ddt,"CNAME - needs more processing\n");
355#endif
356 if (!qp->q_cmsglen) {
357 qp->q_cmsg = qp->q_msg;
358 qp->q_cmsglen = qp->q_msglen;
359 qp->q_msg = NULL;
360 qp->q_msglen = 0;
361 }
362 }
363 /*
364 * See if authority record is a nameserver.
365 */
366 if (ancount == 0 && i == T_NS)
367 nscount++;
368 } while (--c > 0);
369 tp = cp;
370 }
371
372 /*
373 * Add the info received in the response to the Data Base
374 */
375 c = ancount + aucount + arcount;
376#ifdef notdef
377 /*
378 * If the request was for a CNAME that doesn't exist,
379 * but the name is valid, fetch any other data for the name.
380 * DON'T do this now, as it will requery if data are already
381 * in the cache (maybe later with negative caching).
382 */
383 if (hp->qdcount && type == T_CNAME && c == 0 && hp->rcode == NOERROR &&
384 !qp->q_system) {
385#ifdef DEBUG
386 if (debug >= 3)
387 fprintf(ddt,"resp: leaving, no CNAME\n");
388#endif
389 /* Cause us to put it in the cache later */
390 prime(class, T_ANY, qp);
391
392 /* Nothing to store, just give user the answer */
393 goto return_msg;
394 }
395#endif /* notdef */
396
397 nspp = nsp;
398 if (qp->q_system)
399 dbflags = DB_NOTAUTH | DB_NODATA;
400 else
401 dbflags = DB_NOTAUTH | DB_NODATA | DB_NOHINTS;
402 for (i = 0; i < c; i++) {
403 struct databuf *ns3;
404
405 if (cp >= msg + msglen)
406 goto formerr;
407 ns3 = 0;
408 if ((n = doupdate(msg, msglen, cp, 0, &ns3, dbflags)) < 0) {
409#ifdef DEBUG
410 if (debug)
411 fprintf(ddt,"resp: leaving, doupdate failed\n");
412#endif
413 /* return code filled in by doupdate */
414 goto return_msg;
415 }
416 /*
417 * Remember nameservers from the authority section
418 * for referrals.
419 * (This is usually overwritten by findns below(?). XXX
420 */
421 if (ns3 && i >= ancount && i < ancount + aucount &&
422 nspp < &nsp[NSMAX-1])
423 *nspp++ = ns3;
424 cp += n;
425 }
426
427 if (qp->q_system && ancount) {
428 if (qp->q_system == PRIMING_CACHE)
429 check_root();
430#ifdef DEBUG
431 if (debug > 2)
432 fprintf(ddt,"resp: leaving, SYSQUERY ancount %d\n", ancount);
433#endif
434 qremove(qp);
435 return;
436 }
437
438 if (cp > msg + msglen)
439 goto formerr;
440
441 /*
442 * If there are addresses and this is a local query,
443 * sort them appropriately for the local context.
444 */
445 if (ancount > 1 && (lp = local(&qp->q_from)) != NULL)
446 sort_response(tp, ancount, lp, msg + msglen);
447
448 /*
449 * An answer to a T_ANY query or a successful answer to a
450 * regular query with no indirection, then just return answer.
451 */
452 if ((hp->qdcount && type == T_ANY && ancount) ||
453 (!cname && !qp->q_cmsglen && ancount)) {
454#ifdef DEBUG
455 if (debug >= 3)
456 fprintf(ddt,"resp: got as much answer as there is\n");
457#endif
458 goto return_msg;
459 }
460
461 /*
462 * Eventually we will want to cache this negative answer.
463 */
464 if (ancount == 0 && nscount == 0 &&
465 (hp->aa || fwd || class == C_ANY)) {
466 /* We have an authoritative NO */
467#ifdef DEBUG
468 if (debug >= 3)
469 fprintf(ddt,"resp: leaving auth NO\n");
470#endif
471 if (qp->q_cmsglen) {
472 msg = (u_char *)qp->q_cmsg;
473 msglen = qp->q_cmsglen;
474 hp = (HEADER *)msg;
475 }
476 goto return_msg;
477 }
478
479 /*
480 * All messages in here need further processing. i.e. they
481 * are either CNAMEs or we got referred again.
482 */
483 count = 0;
484 founddata = 0;
485 foundname = 0;
486 dname = name;
487 if (!cname && qp->q_cmsglen && ancount) {
488#ifdef DEBUG
489 if (debug)
490 fprintf(ddt,"Cname second pass\n");
491#endif
492 newmsglen = qp->q_cmsglen;
493 bcopy(qp->q_cmsg, newmsg, newmsglen);
494 } else {
495 newmsglen = msglen;
496 bcopy(msg, newmsg, newmsglen);
497 }
498 hp = (HEADER *) newmsg;
499 hp->ancount = 0;
500 hp->nscount = 0;
501 hp->arcount = 0;
502 dnptrs[0] = newmsg;
503 dnptrs[1] = NULL;
504 cp = newmsg + sizeof(HEADER);
505 if (cname)
506 cp += dn_skipname(cp, newmsg + newmsglen) + QFIXEDSZ;
507 if ((n = dn_expand(newmsg, newmsg + newmsglen,
508 cp, (u_char *)dname, sizeof(name))) < 0) {
509#ifdef DEBUG
510 if (debug)
511 fprintf(ddt,"dn_expand failed\n" );
512#endif
513 goto servfail;
514 }
515 if (!cname)
516 cp += n + QFIXEDSZ;
517 buflen = sizeof(newmsg) - (cp - newmsg);
518
519try_again:
520#ifdef DEBUG
521 if (debug)
522 fprintf(ddt,"resp: nlookup(%s) type=%d\n",dname, type);
523#endif
524 fname = "";
525 htp = hashtab; /* lookup relative to root */
526 np = nlookup(dname, &htp, &fname, 0);
527#ifdef DEBUG
528 if (debug)
529 fprintf(ddt,"resp: %s '%s' as '%s' (cname=%d)\n",
530 np == NULL ? "missed" : "found", dname, fname, cname);
531#endif
532 if (np == NULL || fname != dname)
533 goto fetch_ns;
534
535 foundname++;
536 count = cp - newmsg;
537 n = finddata(np, class, type, hp, &dname, &buflen, &count);
538 if (n == 0)
539 goto fetch_ns; /* NO data available */
540 cp += n;
541 buflen -= n;
542 hp->ancount += count;
543 if (fname != dname && type != T_CNAME && type != T_ANY) {
544 cname++;
545 goto try_again;
546 }
547 founddata = 1;
548
549#ifdef DEBUG
550 if (debug >= 3) {
551 fprintf(ddt,"resp: foundname = %d count = %d ", foundname, count);
552 fprintf(ddt,"founddata = %d cname = %d\n", founddata, cname);
553 }
554#endif
555
556fetch_ns:
557 hp->ancount = htons(hp->ancount);
558 /*
559 * Look for name servers to refer to and fill in the authority
560 * section or record the address for forwarding the query
561 * (recursion desired).
562 */
563 switch (findns(&np, class, nsp, &count)) {
564 case NXDOMAIN: /* shouldn't happen */
565#ifdef DEBUG
566 if (debug >= 3)
567 fprintf(ddt,"req: leaving (%s, rcode %d)\n",
568 dname, hp->rcode);
569#endif
570 if (!foundname)
571 hp->rcode = NXDOMAIN;
572 if (class != C_ANY) {
573 hp->aa = 1;
574 /*
575 * should return SOA if founddata == 0,
576 * but old named's are confused by an SOA
577 * in the auth. section if there's no error.
578 */
579 if (foundname == 0 && np) {
580 n = doaddauth(hp, cp, buflen, np, nsp[0]);
581 cp += n;
582 buflen -= n;
583 }
584 }
585 goto return_newmsg;
586
587 case SERVFAIL:
588 goto servfail;
589 }
590
591 if (founddata) {
592 hp = (HEADER *)newmsg;
593 n = add_data(np, nsp, cp, buflen);
594 if (n < 0) {
595 hp->tc = 1;
596 n = (-n);
597 }
598 cp += n;
599 buflen -= n;
600 hp->nscount = htons((u_short)count);
601 goto return_newmsg;
602 }
603
604 /*
605 * If we get here, we don't have the answer yet and are about
606 * to iterate to try and get it. First, infinite loop avoidance.
607 */
608 if (qp->q_nqueries++ > MAXQUERIES) {
609#ifdef DEBUG
610 if (debug)
611 fprintf(ddt,"resp: MAXQUERIES exceeded (%s, class %d, type %d)\n",
612 dname, class, type);
613#endif
614 syslog(LOG_NOTICE,
615 "MAXQUERIES exceeded, possible data loop in resolving (%s)",
616 dname);
617 goto servfail;
618 }
619
620 /* Reset the query control structure */
621 qp->q_naddr = 0;
622 qp->q_curaddr = 0;
623 qp->q_fwd = fwdtab;
624 if (nslookup(nsp, qp) == 0) {
625#ifdef DEBUG
626 if (debug >= 3)
627 fprintf(ddt,"resp: no addrs found for NS's\n");
628#endif
629 goto servfail;
630 }
631 for (n = 0; n < qp->q_naddr; n++)
632 qp->q_addr[n].stime.tv_sec = 0;
633 if (!qp->q_fwd)
634 qp->q_addr[0].stime = tt;
635 if (cname) {
636 if (qp->q_cname++ == MAXCNAMES) {
637#ifdef DEBUG
638 if (debug >= 3)
639 fprintf(ddt,"resp: leaving, MAXCNAMES exceeded\n");
640#endif
641 goto servfail;
642 }
643#ifdef DEBUG
644 if (debug)
645 fprintf(ddt,"q_cname = %d\n",qp->q_cname);
646 if (debug >= 3)
647 fprintf(ddt,"resp: building recursive query; nslookup\n");
648#endif
649 if (qp->q_msg)
650 (void) free(qp->q_msg);
651 if ((qp->q_msg = malloc(BUFSIZ)) == NULL) {
652#ifdef DEBUG
653 if (debug)
654 fprintf(ddt,"resp: malloc error\n");
655#endif
656 goto servfail;
657 }
658 qp->q_msglen = res_mkquery(QUERY, dname, class,
659 type, (char *)NULL, 0, NULL, qp->q_msg, BUFSIZ);
660 hp = (HEADER *) qp->q_msg;
661 hp->rd = 0;
662 } else
663 hp = (HEADER *)qp->q_msg;
664 hp->id = qp->q_nsid = htons((u_short)++nsid);
665 if (qp->q_fwd)
666 hp->rd = 1;
667 unsched(qp);
668 schedretry(qp, retrytime(qp));
669#ifdef DEBUG
670 if (debug)
671 fprintf(ddt,"resp: forw -> %s %d (%d) nsid=%d id=%d %dms\n",
672 inet_ntoa(Q_NEXTADDR(qp,0)->sin_addr),
673 ds, ntohs(Q_NEXTADDR(qp,0)->sin_port),
674 ntohs(qp->q_nsid), ntohs(qp->q_id),
675 qp->q_addr[0].nsdata->d_nstime);
676 if ( debug >= 10)
677 fp_query((char *)msg, ddt);
678#endif
679 if (sendto(ds, qp->q_msg, qp->q_msglen, 0,
680 (struct sockaddr *)Q_NEXTADDR(qp,0),
681 sizeof(struct sockaddr_in)) < 0) {
682#ifdef DEBUG
683 if (debug >= 5)
684 fprintf(ddt, "sendto error = %d\n", errno);
685#endif
686 }
687 hp->rd = 0; /* leave set to 0 for dup detection */
688#ifdef STATS
689 stats[S_OUTPKTS].cnt++;
690#endif
691#ifdef DEBUG
692 if (debug >= 3)
693 fprintf(ddt,"resp: Query sent.\n");
694#endif
695 return;
696
697formerr:
698#ifdef DEBUG
699 if (debug)
700 fprintf(ddt,"FORMERR resp() from %s size err %d, msglen %d\n",
701 inet_ntoa(from_addr.sin_addr),
702 cp-msg, msglen);
703#endif
704 syslog(LOG_INFO, "Malformed response from %s\n",
705 inet_ntoa(from_addr.sin_addr));
706#ifdef STATS
707 stats[S_RESPFORMERR].cnt++;
708#endif
709 return;
710
711return_msg:
712#ifdef STATS
713 stats[S_RESPOK].cnt++;
714#endif
715 /* The "standard" return code */
716 hp->qr = 1;
717 hp->id = qp->q_id;
718 hp->rd = 1;
719 hp->ra = 1;
720 (void) send_msg(msg, msglen, qp);
721 qremove(qp);
722 return;
723
724return_newmsg:
725#ifdef STATS
726 stats[S_RESPOK].cnt++;
727#endif
728 if (addcount) {
729 n = doaddinfo(hp, cp, buflen);
730 cp += n;
731 buflen -= n;
732 }
733
734 hp->id = qp->q_id;
735 hp->rd = 1;
736 hp->ra = 1;
737 hp->qr = 1;
738 (void) send_msg(newmsg, cp - newmsg, qp);
739 qremove(qp);
740 return;
741
742servfail:
743#ifdef STATS
744 stats[S_RESPFAIL].cnt++;
745#endif
746 hp = (HEADER *)(cname ? qp->q_cmsg : qp->q_msg);
747 hp->rcode = SERVFAIL;
748 hp->id = qp->q_id;
749 hp->rd = 1;
750 hp->ra = 1;
751 hp->qr = 1;
752 (void) send_msg((char *)hp, (cname ? qp->q_cmsglen : qp->q_msglen), qp);
753 qremove(qp);
754 return;
755}
756
757/*
758 * Decode the resource record 'rrp' and update the database.
759 * If savens is true, record pointer for forwarding queries a second time.
760 */
761doupdate(msg, msglen, rrp, zone, savens, flags)
762 char *msg;
763 u_char *rrp;
764 struct databuf **savens;
765 int msglen, zone, flags;
766{
767 register u_char *cp;
768 register int n;
769 int class, type, dlen, n1;
770 u_long ttl;
771 struct databuf *dp;
772 char dname[MAXDNAME];
773 u_char *cp1;
774 u_char data[BUFSIZ];
775 register HEADER *hp = (HEADER *) msg;
776#ifdef ALLOW_UPDATES
777 int zonenum;
778#endif
779
780#ifdef DEBUG
781 if (debug > 2)
782 fprintf(ddt,"doupdate(zone %d, savens %x, flags %x)\n",
783 zone, savens, flags);
784#endif
785
786 cp = rrp;
787 if ((n = dn_expand((u_char *)msg, (u_char *)msg + msglen, cp,
788 (u_char *)dname, sizeof(dname))) < 0) {
789 hp->rcode = FORMERR;
790 return (-1);
791 }
792 cp += n;
793 GETSHORT(type, cp);
794 GETSHORT(class, cp);
795 GETLONG(ttl, cp);
796 GETSHORT(dlen, cp);
797#ifdef DEBUG
798 if (debug > 2)
799 fprintf(ddt,"doupdate: dname %s type %d class %d ttl %d\n",
800 dname, type, class, ttl);
801#endif
802 /*
803 * Convert the resource record data into the internal
804 * database format.
805 */
806 switch (type) {
807 case T_A:
808 case T_WKS:
809 case T_HINFO:
810 case T_UINFO:
811 case T_UID:
812 case T_GID:
813 case T_TXT:
814#ifdef ALLOW_T_UNSPEC
815 case T_UNSPEC:
816#endif ALLOW_T_UNSPEC
817 cp1 = cp;
818 n = dlen;
819 cp += n;
820 break;
821
822 case T_CNAME:
823 case T_MB:
824 case T_MG:
825 case T_MR:
826 case T_NS:
827 case T_PTR:
828 if ((n = dn_expand((u_char *)msg, (u_char *)msg + msglen,
829 cp, data, sizeof(data))) < 0) {
830 hp->rcode = FORMERR;
831 return (-1);
832 }
833 cp += n;
834 cp1 = data;
835 n = strlen((char *)data) + 1;
836 break;
837
838 case T_MINFO:
839 case T_SOA:
840 if ((n = dn_expand((u_char *)msg, (u_char *)msg + msglen,
841 cp, data, sizeof(data))) < 0) {
842 hp->rcode = FORMERR;
843 return (-1);
844 }
845 cp += n;
846 cp1 = data + (n = strlen((char *)data) + 1);
847 n1 = sizeof(data) - n;
848 if (type == T_SOA)
849 n1 -= 5 * sizeof(u_long);
850 if ((n = dn_expand((u_char *)msg, (u_char *)msg + msglen,
851 cp, cp1, n1)) < 0) {
852 hp->rcode = FORMERR;
853 return (-1);
854 }
855 cp += n;
856 cp1 += strlen((char *)cp1) + 1;
857 if (type == T_SOA) {
858 bcopy(cp, cp1, n = 5 * sizeof(u_long));
859 cp += n;
860 cp1 += n;
861 }
862 n = cp1 - data;
863 cp1 = data;
864 break;
865
866 case T_MX:
867 /* grab preference */
868 bcopy(cp,data,sizeof(u_short));
869 cp1 = data + sizeof(u_short);
870 cp += sizeof(u_short);
871
872 /* get name */
873 if ((n = dn_expand((u_char *)msg, (u_char *)msg + msglen,
874 cp, cp1, sizeof(data) - sizeof(u_short))) < 0)
875 return(-1);
876 cp += n;
877
878 /* compute end of data */
879 cp1 += strlen((char *)cp1) + 1;
880 /* compute size of data */
881 n = cp1 - data;
882 cp1 = data;
883 break;
884
885 default:
886#ifdef DEBUG
887 if (debug >= 3)
888 fprintf(ddt,"unknown type %d\n", type);
889#endif
890 return ((cp - rrp) + dlen);
891 }
892 if (n > MAXDATA) {
893#ifdef DEBUG
894 if (debug)
895 fprintf(ddt,
896 "update type %d: %d bytes is too much data\n",
897 type, n);
898#endif
899 hp->rcode = NOCHANGE; /* XXX - FORMERR ??? */
900 return(-1);
901 }
902
903#ifdef ALLOW_UPDATES
904 /*
905 * If this is a dynamic update request, process it specially; else,
906 * execute normal update code.
907 */
908 switch(hp->opcode) {
909
910 /* For UPDATEM and UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA */
911 case UPDATEM:
912 case UPDATEMA:
913
914 /*
915 * The named code for UPDATED and UPDATEDA is the same except that for
916 * UPDATEDA we we ignore any data that was passed: we just delete all
917 * RRs whose name, type, and class matches
918 */
919 case UPDATED:
920 case UPDATEDA:
921 if (type == T_SOA) { /* Not allowed */
922#ifdef DEBUG
923 if (debug)
924 fprintf(ddt, "UDPATE: REFUSED - SOA delete\n");
925#endif
926 hp->rcode = REFUSED;
927 return(-1);
928 }
929 /*
930 * Don't check message length if doing UPDATEM/UPDATEMA,
931 * since the whole message wont have been demarshalled until
932 * we reach the code for UPDATEA
933 */
934 if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEDA) ) {
935 if (cp != (u_char *)(msg + msglen)) {
936#ifdef DEBUG
937 if (debug)
938 fprintf(ddt,"FORMERR UPDATE message length off\n");
939#endif
940 hp->rcode = FORMERR;
941 return(-1);
942 }
943 }
944 if ((zonenum = findzone(dname, class)) == 0) {
945 hp->rcode = NXDOMAIN;
946 return(-1);
947 }
948 if (zones[zonenum].z_state & Z_DYNADDONLY) {
949 hp->rcode = NXDOMAIN;
950 return(-1);
951 }
952 if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEM) ) {
953 /* Make a dp for use in db_update, as old dp */
954 dp = savedata(class, type, 0, cp1, n);
955 dp->d_zone = zonenum;
956 n = db_update(dname, dp, NULL, DB_MEXIST | DB_DELETE,
957 hashtab);
958 if (n != OK) {
959#ifdef DEBUG
960 if (debug)
961 fprintf(ddt,"UPDATE: db_update failed\n");
962#endif DEBUG
963 free( (struct databuf *) dp);
964 hp->rcode = NOCHANGE;
965 return(-1);
966 }
967 } else { /* UPDATEDA or UPDATEMA */
968 int DeletedOne = 0;
969 /* Make a dp for use in db_update, as old dp */
970 dp = savedata(class, type, 0, NULL, 0);
971 dp->d_zone = zonenum;
972 do { /* Loop and delete all matching RR(s) */
973 n = db_update(dname, dp, NULL, DB_DELETE,
974 hashtab);
975 if (n != OK)
976 break;
977 DeletedOne++;
978 } while (1);
979 free( (struct databuf *) dp);
980 /* Ok for UPDATEMA not to have deleted any RRs */
981 if (!DeletedOne && hp->opcode == UPDATEDA) {
982#ifdef DEBUG
983 if (debug)
984 fprintf(ddt,"UPDATE: db_update failed\n");
985#endif DEBUG
986 hp->rcode = NOCHANGE;
987 return(-1);
988 }
989 }
990 if ( (hp->opcode == UPDATED) || (hp->opcode == UPDATEDA) )
991 return (cp - rrp);;
992 /*
993 * Else unmarshal the RR to be added and continue on to
994 * UPDATEA code for UPDATEM/UPDATEMA
995 */
996 if ((n =
997 dn_expand(msg, msg+msglen, cp, dname, sizeof(dname))) < 0) {
998#ifdef DEBUG
999 if (debug)
1000 fprintf(ddt,"FORMERR UPDATE expand name failed\n");
1001#endif
1002 hp->rcode = FORMERR;
1003 return(-1);
1004 }
1005 cp += n;
1006 GETSHORT(type, cp);
1007 GETSHORT(class, cp);
1008 GETLONG(ttl, cp);
1009 GETSHORT(n, cp);
1010 cp1 = cp;
1011/**** XXX - need bounds checking here ****/
1012 cp += n;
1013
1014 case UPDATEA:
1015 if (n > MAXDATA) {
1016#ifdef DEBUG
1017 if (debug)
1018 fprintf(ddt,"UPDATE: too much data\n");
1019#endif
1020 hp->rcode = NOCHANGE;
1021 return(-1);
1022 }
1023 if (cp != (u_char *)(msg + msglen)) {
1024#ifdef DEBUG
1025 if (debug)
1026 fprintf(ddt,"FORMERR UPDATE message length off\n");
1027#endif
1028 hp->rcode = FORMERR;
1029 return(-1);
1030 }
1031 if ((zonenum = findzone(dname, class)) == 0) {
1032 hp->rcode = NXDOMAIN;
1033 return(-1);
1034 }
1035 if (zones[zonenum].z_state & Z_DYNADDONLY) {
1036 struct hashbuf *htp = hashtab;
1037 char *fname;
1038 if (nlookup(dname, &htp, &fname, 0) &&
1039 !strcmp(dname, fname)) {
1040#ifdef DEBUG
1041 if (debug)
1042 fprintf(ddt,"refusing add of existing name\n");
1043#endif
1044 hp->rcode = REFUSED;
1045 return(-1);
1046 }
1047 }
1048 dp = savedata(class, type, ttl, cp1, n);
1049 dp->d_zone = zonenum;
1050 if ((n = db_update(dname, NULL, dp, DB_NODATA,
1051 hashtab)) != OK) {
1052#ifdef DEBUG
1053 if (debug)
1054 fprintf(ddt,"UPDATE: db_update failed\n");
1055#endif
1056 hp->rcode = NOCHANGE;
1057 return (-1);
1058 }
1059 else
1060 return (cp - rrp);
1061 }
1062#endif ALLOW_UPDATES
1063
1064 if (zone == 0)
1065 ttl += tt.tv_sec;
1066 dp = savedata(class, type, ttl, cp1, n);
1067 dp->d_zone = zone;
1068 if ((n = db_update(dname, dp, dp, flags, hashtab)) < 0) {
1069#ifdef DEBUG
1070 if (debug && (n != DATAEXISTS))
1071 fprintf(ddt,"update failed (%d)\n", n);
1072 else if (debug >= 3)
1073 fprintf(ddt,"update failed (DATAEXISTS)\n");
1074#endif
1075 (void) free((char *)dp);
1076 } else if (type == T_NS && savens != NULL)
1077 *savens = dp;
1078 return (cp - rrp);
1079}
1080
1081send_msg(msg, msglen, qp)
1082 char *msg;
1083 int msglen;
1084 struct qinfo *qp;
1085{
1086 extern struct qinfo *qhead;
1087#ifdef DEBUG
1088 struct qinfo *tqp;
1089#endif DEBUG
1090
1091 if (qp->q_system)
1092 return(1);
1093#ifdef DEBUG
1094 if (debug) {
1095 fprintf(ddt,"send_msg -> %s (%s %d %d) id=%d\n",
1096 inet_ntoa(qp->q_from.sin_addr),
1097 qp->q_stream == QSTREAM_NULL ? "UDP" : "TCP",
1098 qp->q_stream == QSTREAM_NULL ? qp->q_dfd
1099 : qp->q_stream->s_rfd,
1100 ntohs(qp->q_from.sin_port),
1101 ntohs(qp->q_id));
1102 }
1103 if (debug>4)
1104 for (tqp = qhead; tqp!=QINFO_NULL; tqp = tqp->q_link) {
1105 fprintf(ddt, "qp %x q_id: %d q_nsid: %d q_msglen: %d ",
1106 tqp, tqp->q_id,tqp->q_nsid,tqp->q_msglen);
1107 fprintf(ddt,"q_naddr: %d q_curaddr: %d\n", tqp->q_naddr,
1108 tqp->q_curaddr);
1109 fprintf(ddt,"q_next: %x q_link: %x\n", qp->q_next,
1110 qp->q_link);
1111 }
1112 if (debug >= 10)
1113 fp_query(msg, ddt);
1114#endif DEBUG
1115 if (qp->q_stream == QSTREAM_NULL) {
1116 if (sendto(qp->q_dfd, msg, msglen, 0,
1117 (struct sockaddr *)&qp->q_from, sizeof(qp->q_from)) < 0) {
1118#ifdef DEBUG
1119 if (debug)
1120 fprintf(ddt, "sendto error errno= %d\n",errno);
1121#endif
1122 return(1);
1123 }
1124#ifdef STATS
1125 stats[S_OUTPKTS].cnt++;
1126#endif
1127 } else {
1128 (void) writemsg(qp->q_stream->s_rfd, msg, msglen);
1129 sq_done(qp->q_stream);
1130 }
1131 return(0);
1132}
1133
1134prime(class, type, oqp)
1135 int class, type;
1136 register struct qinfo *oqp;
1137{
1138 char dname[BUFSIZ];
1139
1140 if (oqp->q_msg == NULL)
1141 return;
1142 if (dn_expand((u_char *)oqp->q_msg,
1143 (u_char *)oqp->q_msg + oqp->q_msglen,
1144 (u_char *)oqp->q_msg + sizeof(HEADER), (u_char *)dname,
1145 sizeof(dname)) < 0)
1146 return;
1147#ifdef DEBUG
1148 if (debug >= 2)
1149 fprintf(ddt,"prime: %s\n", dname);
1150#endif
1151 (void) sysquery(dname, class, type);
1152}
1153
1154
1155prime_cache()
1156{
1157 register struct qinfo *qp;
1158
1159#ifdef DEBUG
1160 if (debug)
1161 fprintf(ddt,"prime_cache: priming = %d\n", priming);
1162#endif
1163#ifdef STATS
1164 stats[S_PRIMECACHE].cnt++;
1165#endif
1166 if (!priming && fcachetab->h_tab[0] != NULL && !forward_only) {
1167 priming++;
1168 if ((qp = sysquery("", C_IN, T_NS)) == NULL)
1169 priming = 0;
1170 else
1171 qp->q_system = PRIMING_CACHE;
1172 }
1173 needs_prime_cache = 0;
1174 return;
1175}
1176
1177struct qinfo *
1178sysquery(dname, class, type)
1179 char *dname;
1180 int class, type;
1181{
1182 extern struct qinfo *qhead;
1183 extern int nsid;
1184 register struct qinfo *qp, *oqp;
1185 register HEADER *hp;
1186 struct namebuf *np;
1187 struct databuf *nsp[NSMAX];
1188 struct hashbuf *htp;
1189 char *fname;
1190 int count;
1191
1192#ifdef DEBUG
1193 if (debug > 2)
1194 fprintf(ddt,"sysquery(%s, %d, %d)\n", dname, class, type);
1195#endif
1196#ifdef STATS
1197 stats[S_SYSQUERIES].cnt++;
1198#endif
1199 htp = hashtab;
1200 if (priming && dname[0] == '\0')
1201 np = NULL;
1202 else if ((np = nlookup(dname, &htp, &fname, 1)) == NULL) {
1203#ifdef DEBUG
1204 if (debug)
1205 fprintf(ddt,"sysquery: nlookup error on %s?\n", dname);
1206#endif
1207 return(0);
1208 }
1209
1210 switch (findns(&np, class, nsp, &count)) {
1211 case NXDOMAIN:
1212 case SERVFAIL:
1213#ifdef DEBUG
1214 if (debug)
1215 fprintf(ddt,"sysquery: findns error on %s?\n", dname);
1216#endif
1217 return(0);
1218 }
1219
1220 /* build new qinfo struct */
1221 qp = qnew();
1222 qp->q_cmsg = qp->q_msg = NULL;
1223 qp->q_dfd = ds;
1224 qp->q_fwd = fwdtab;
1225 qp->q_system++;
1226
1227 if ((qp->q_msg = malloc(BUFSIZ)) == NULL) {
1228 qfree(qp);
1229 return(0);
1230 }
1231 qp->q_msglen = res_mkquery(QUERY, dname, class,
1232 type, (char *)NULL, 0, NULL, qp->q_msg, BUFSIZ);
1233 hp = (HEADER *) qp->q_msg;
1234 hp->id = qp->q_nsid = htons((u_short)++nsid);
1235 hp->rd = (qp->q_fwd ? 1 : 0);
1236
1237 /* First check for an already pending query for this data */
1238 for (oqp = qhead; oqp!=QINFO_NULL; oqp = oqp->q_link) {
1239 if (oqp != qp && oqp->q_msglen == qp->q_msglen &&
1240 bcmp((char *)oqp->q_msg+2, qp->q_msg+2, qp->q_msglen-2) == 0) {
1241#ifdef DEBUG
1242 if (debug >= 3)
1243 fprintf(ddt, "sysquery: duplicate\n");
1244#endif
1245 qfree(qp);
1246 return(0);
1247 }
1248 }
1249
1250 if (nslookup(nsp, qp) == 0) {
1251#ifdef DEBUG
1252 if (debug)
1253 fprintf(ddt,"resp: no addrs found for NS's\n");
1254#endif
1255 qfree(qp);
1256 return(0);
1257 }
1258
1259 schedretry(qp, retrytime(qp));
1260 if (qp->q_fwd == 0)
1261 qp->q_addr[0].stime = tt;
1262
1263#ifdef DEBUG
1264 if (debug)
1265 fprintf(ddt,"sysquery: send -> %s %d (%d), nsid=%d id=%d %dms\n",
1266 inet_ntoa(Q_NEXTADDR(qp,0)->sin_addr),
1267 qp->q_dfd, ntohs(Q_NEXTADDR(qp,0)->sin_port),
1268 ntohs(qp->q_nsid), ntohs(qp->q_id),
1269 qp->q_addr[0].nsdata->d_nstime);
1270 if ( debug >= 10)
1271 fp_query(qp->q_msg, ddt);
1272#endif
1273 if (sendto(qp->q_dfd, qp->q_msg, qp->q_msglen, 0,
1274 (struct sockaddr *)Q_NEXTADDR(qp,0),
1275 sizeof(struct sockaddr_in)) < 0){
1276#ifdef DEBUG
1277 if (debug)
1278 fprintf(ddt, "sendto error errno= %d\n",errno);
1279#endif
1280 }
1281#ifdef STATS
1282 stats[S_OUTPKTS].cnt++;
1283#endif
1284 return(qp);
1285}
1286
1287/*
1288 * Check the list of root servers after receiving a response
1289 * to a query for the root servers.
1290 */
1291check_root()
1292{
1293 register struct databuf *dp, *pdp;
1294 register struct namebuf *np;
1295 int count = 0;
1296
1297 priming = 0;
1298 for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next)
1299 if (np->n_dname[0] == '\0')
1300 break;
1301 if (np == NULL) {
1302 syslog(LOG_ERR, "check_root: Can't find root!\n");
1303 return;
1304 }
1305 for (dp = np->n_data; dp != NULL; dp = dp->d_next)
1306 if (dp->d_type == T_NS)
1307 count++;
1308#ifdef DEBUG
1309 if (debug)
1310 fprintf(ddt,"%d root servers\n", count);
1311#endif
1312 if (count < MINROOTS) {
1313 syslog(LOG_WARNING,
1314 "check_root: %d root servers after query to root server < min",
1315 count);
1316 return;
1317 }
1318 pdp = NULL;
1319 dp = np->n_data;
1320 while (dp != NULL) {
1321 if (dp->d_type == T_NS && dp->d_zone == 0 &&
1322 dp->d_ttl < tt.tv_sec) {
1323#ifdef DEBUG
1324 if (debug)
1325 fprintf(ddt,"deleting old root server '%s'\n",
1326 dp->d_data);
1327#endif
1328 dp = rm_datum(dp, np, pdp);
1329 /* SHOULD DELETE FROM HINTS ALSO */
1330 continue;
1331 }
1332 pdp = dp;
1333 dp = dp->d_next;
1334 }
1335 check_ns();
1336}
1337
1338/*
1339 * Check the root to make sure that for each NS record we have a A RR
1340 */
1341check_ns()
1342{
1343 register struct databuf *dp, *tdp;
1344 register struct namebuf *np, *tnp;
1345 struct hashbuf *htp;
1346 char *dname;
1347 int found_arr;
1348 char *fname;
1349 time_t curtime;
1350
1351#ifdef DEBUG
1352 if (debug >= 2)
1353 fprintf(ddt,"check_ns()\n");
1354#endif
1355#ifdef STATS
1356 stats[S_CHECKNS].cnt++;
1357#endif
1358
1359 curtime = (u_long) tt.tv_sec;
1360 for (np = hashtab->h_tab[0]; np != NULL; np = np->n_next) {
1361 if (np->n_dname[0] != 0)
1362 continue;
1363 for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
1364 if (dp->d_type != T_NS)
1365 continue;
1366
1367 /* look for A records */
1368 dname = dp->d_data;
1369 htp = hashtab;
1370 tnp = nlookup(dname, &htp, &fname, 0);
1371 if (tnp == NULL || fname != dname) {
1372#ifdef DEBUG
1373 if (debug >= 3)
1374 fprintf(ddt,"check_ns: %s: not found %s %x\n",
1375 dname, fname, tnp);
1376#endif
1377 (void) sysquery(dname, dp->d_class, T_A);
1378 continue;
1379 }
1380 /* look for name server addresses */
1381 found_arr = 0;
1382 for (tdp=tnp->n_data; tdp!=NULL; tdp=tdp->d_next) {
1383 if (tdp->d_type != T_A ||
1384 tdp->d_class != dp->d_class)
1385 continue;
1386 if ((tdp->d_zone == 0) &&
1387 (tdp->d_ttl < curtime)) {
1388#ifdef DEBUG
1389 if (debug >= 3)
1390 fprintf(ddt,"check_ns: stale entry '%s'\n",
1391 tnp->n_dname);
1392#endif
1393 /* Cache invalidate the address RR's */
1394 delete_all(tnp, dp->d_class, T_A);
1395 found_arr = 0;
1396 break;
1397 }
1398 found_arr++;
1399 }
1400 if (!found_arr)
1401 (void) sysquery(dname, dp->d_class, T_A);
1402 }
1403 }
1404}
1405
1406#define MAXCLASS 255 /* belongs elsewhere */
1407int norootlogged[MAXCLASS];
1408
1409/*
1410 * Find NS's or an SOA for the given dname (np) and fill in the
1411 * nsp array. Returns OK on success, and SERVFAIL on error.
1412 * We return NXDOMAIN to indicate we are authoritative.
1413 */
1414findns(npp, class, nsp, countp)
1415 register struct namebuf **npp;
1416 struct databuf **nsp;
1417 int *countp;
1418{
1419 register struct namebuf *np = *npp;
1420 register struct databuf *dp;
1421 register struct databuf **nspp;
1422 struct hashbuf *htp = hashtab;
1423
1424 if (priming && (np == NULL || np->n_dname[0] == '\0'))
1425 htp = fcachetab;
1426try_again:
1427 if (htp == fcachetab)
1428 needs_prime_cache = 1;
1429 while (np == NULL && htp != NULL) {
1430#ifdef DEBUG
1431 if (debug > 2)
1432 fprintf(ddt, "findns: using %s\n", htp == hashtab ?
1433 "cache" : "hints");
1434#endif
1435 for (np = htp->h_tab[0]; np != NULL; np = np->n_next)
1436 if (np->n_dname[0] == '\0')
1437 break;
1438 htp = (htp == hashtab ? fcachetab : NULL); /* Fallback */
1439 }
1440 while(np != NULL) {
1441#ifdef DEBUG
1442 if (debug >= 5)
1443 fprintf(ddt, "findns: np 0x%x\n", np);
1444#endif
1445 /* Look first for SOA records. */
1446 for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
1447 if (dp->d_zone != 0 && match(dp, class, T_SOA)) {
1448#ifdef DEBUG
1449 if (debug >= 3)
1450 fprintf(ddt,"findns: SOA found\n");
1451#endif
1452 if (zones[dp->d_zone].z_auth) {
1453 *npp = np;
1454 nsp[0] = dp;
1455 return(NXDOMAIN);
1456 } else
1457 return (SERVFAIL);
1458 }
1459 }
1460
1461 /* If no SOA records, look for NS records. */
1462 nspp = &nsp[0];
1463 *nspp = NULL;
1464 for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
1465 if (dp->d_type != T_NS ||
1466 (dp->d_class != class && class != C_ANY))
1467 continue;
1468 /*
1469 * Don't use records that may become invalid to
1470 * reference later when we do the rtt computation.
1471 * Never delete our safety-belt information!
1472 */
1473 if ((dp->d_zone == 0) &&
1474 (dp->d_ttl < (tt.tv_sec+900)) &&
1475 !(dp->d_flags & DB_F_HINT)) {
1476#ifdef DEBUG
1477 if (debug)
1478 fprintf(ddt,"findns: stale entry '%s'\n",
1479 np->n_dname);
1480#endif
1481 /* Cache invalidate the NS RR's */
1482 if (dp->d_ttl < tt.tv_sec)
1483 delete_all(np, class, T_NS);
1484 goto try_parent;
1485 }
1486 if (nspp < &nsp[NSMAX-1])
1487 *nspp++ = dp;
1488 }
1489
1490 *countp = nspp - nsp;
1491 if (*countp > 0) {
1492#ifdef DEBUG
1493 if (debug >= 3)
1494 fprintf(ddt,"findns: %d NS's added for '%s'\n",
1495 *countp, np->n_dname);
1496#endif
1497 *nspp = NULL;
1498 *npp = np;
1499 return(OK); /* Success, got some NS's */
1500 }
1501try_parent:
1502 np = np->n_parent;
1503 }
1504 if (htp)
1505 goto try_again;
1506#ifdef DEBUG
1507 if (debug)
1508 fprintf(ddt, "findns: No root nameservers for class %d?\n",
1509 class);
1510#endif
1511 if ((unsigned)class < MAXCLASS && norootlogged[class] == 0) {
1512 norootlogged[class] = 1;
1513 syslog(LOG_ERR, "No root nameservers for class %d\n", class);
1514 }
1515 return(SERVFAIL);
1516}
1517
1518/*
1519 * Extract RR's from the given node that match class and type.
1520 * Return number of bytes added to response.
1521 * If no matching data is found, then 0 is returned.
1522 */
1523finddata(np, class, type, hp, dnamep, lenp, countp)
1524 struct namebuf *np;
1525 int class, type;
1526 register HEADER *hp;
1527 char **dnamep;
1528 int *lenp, *countp;
1529{
1530 register struct databuf *dp;
1531 register char *cp;
1532 int buflen, n, count = 0, foundstale = 0;
1533
1534 buflen = *lenp;
1535 cp = ((char *)hp) + *countp;
1536 for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
1537 if (!wanted(dp, class, type)) {
1538 if (type == T_CNAME && class == dp->d_class) {
1539 /* any data means no CNAME exists */
1540 *countp = 0;
1541 return(0);
1542 }
1543 continue;
1544 }
1545 if (stale(dp)) {
1546 /*
1547 * Don't use stale data.
1548 * Would like to call delete_all here
1549 * and continue, but the data chain would get
1550 * munged; can't restart, as make_rr has side
1551 * effects (leaving pointers in dnptr).
1552 * Just skip this entry for now
1553 * and call delete_all at the end.
1554 */
1555#ifdef DEBUG
1556 if (debug >=3)
1557 fprintf(ddt,"finddata: stale entry '%s'\n",np->n_dname);
1558#endif
1559 if (dp->d_zone == 0)
1560 foundstale++;
1561 continue;
1562 }
1563 if ((n = make_rr(*dnamep, dp, cp, buflen, 1)) < 0) {
1564 hp->tc = 1;
1565 *countp = count;
1566 return(*lenp - buflen);
1567 }
1568
1569 cp += n;
1570 buflen -= n;
1571 count++;
1572#ifdef notdef
1573 /* this isn't right for glue records, aa is set in ns_req */
1574 if (dp->d_zone && zones[dp->d_zone].z_auth && class != C_ANY)
1575 hp->aa = 1; /* XXX */
1576#endif
1577 if (dp->d_type == T_CNAME) {
1578 if (type != T_ANY) { /* or T_NS? */
1579 *dnamep = dp->d_data;
1580 if (dp->d_zone && zones[dp->d_zone].z_auth &&
1581 class != C_ANY) /* XXX */
1582 hp->aa = 1; /* XXX */
1583 }
1584 break;
1585 }
1586 }
1587 /*
1588 * Cache invalidate the other RR's of same type
1589 * if some have timed out
1590 */
1591 if (foundstale)
1592 delete_all(np, class, type);
1593#ifdef DEBUG
1594 if (debug >=3)
1595 fprintf(ddt,"finddata: added %d class %d type %d RRs\n",
1596 count, class, type);
1597#endif
1598 *countp = count;
1599 return(*lenp - buflen);
1600}
1601
1602/*
1603 * Do we want this data record based on the class and type?
1604 */
1605wanted(dp, class, type)
1606 struct databuf *dp;
1607 int class, type;
1608{
1609
1610#ifdef DEBUG
1611 if (debug > 3)
1612 fprintf(ddt,"wanted(%x, %d, %d) %d, %d\n", dp, class, type,
1613 dp->d_class, dp->d_type);
1614#endif
1615
1616 if (dp->d_class != class && class != C_ANY)
1617 return (0);
1618 if (type == dp->d_type)
1619 return (1);
1620 switch (dp->d_type) {
1621 case T_ANY:
1622 case T_CNAME:
1623 return (1);
1624 }
1625 switch (type) {
1626 case T_ANY:
1627 return (1);
1628
1629 case T_MAILB:
1630 switch (dp->d_type) {
1631 case T_MR:
1632 case T_MB:
1633 case T_MG:
1634 case T_MINFO:
1635 return (1);
1636 }
1637 break;
1638
1639 case T_AXFR:
1640 if (dp->d_type == T_SOA)
1641 return (1);
1642 }
1643 return (0);
1644}
1645
1646/*
1647 * Add RR entries from dpp array to a query/response.
1648 * Return the number of bytes added or negative the amount
1649 * added if truncation was required. Typically you are
1650 * adding NS records to a response.
1651 */
1652add_data(np, dpp, cp, buflen)
1653 struct namebuf *np;
1654 struct databuf **dpp;
1655 register char *cp;
1656 int buflen;
1657{
1658 register struct databuf *dp;
1659 char dname[MAXDNAME];
1660 register int n, count = 0;
1661
1662 getname(np, dname, sizeof(dname));
1663 for(dp = *dpp++; dp != NULL; dp = *dpp++) {
1664 if (stale(dp))
1665 continue; /* ignore old cache entry */
1666 if ((n = make_rr(dname, dp, cp, buflen, 1)) < 0)
1667 return(-count); /* Truncation */
1668 cp += n;
1669 buflen -= n;
1670 count += n;
1671 }
1672 return(count);
1673}
1674
1675/*
1676 * This is best thought of as a "cache invalidate" function.
1677 * It is called whenever a piece of data is determined to have
1678 * timed out. It is better to have no information, than to
1679 * have partial information you pass off as complete.
1680 */
1681delete_all(np, class, type)
1682register struct namebuf *np;
1683int class, type;
1684{
1685 register struct databuf *dp, *pdp;
1686
1687#ifdef DEBUG
1688 if (debug > 2)
1689 fprintf(ddt,"delete_all: '%s' 0x%x class %d type %d\n",
1690 np->n_dname, np, class, type);
1691#endif
1692 pdp = NULL;
1693 dp = np->n_data;
1694 while (dp != NULL) {
1695 if ((dp->d_zone == 0) && !(dp->d_flags & DB_F_HINT)
1696 && match(dp, class, type)) {
1697 dp = rm_datum(dp, np, pdp);
1698 continue;
1699 }
1700 pdp = dp;
1701 dp = dp->d_next;
1702 }
1703}