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