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