|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)ns_req.c 4.3 (Berkeley) 5/30/86";
3: #endif
4:
5: /*
6: * Copyright (c) 1986 Regents of the University of California
7: * All Rights Reserved
8: */
9:
10: #include <stdio.h>
11: #include <sys/types.h>
12: #include <sys/uio.h>
13: #include <sys/time.h>
14: #include <netinet/in.h>
15: #include <syslog.h>
16: #include <sys/file.h>
17: #include <arpa/nameser.h>
18: #include "ns.h"
19: #include "db.h"
20:
21: #define NADDRECS 20
22:
23: struct addinfo {
24: char *a_dname; /* domain name */
25: u_short a_class; /* class for address */
26: };
27:
28: struct addinfo addinfo[NADDRECS]; /* additional info records */
29: int addcount; /* number of names in addinfo */
30:
31: char *dnptrs[20]; /* ptrs to dnames in message for dn_comp */
32:
33: extern char *malloc();
34: extern int errno;
35: /*
36: * Process request using database; assemble and send response.
37: */
38: ns_req(msg, msglen, buflen, qsp, from)
39: char *msg;
40: int msglen, buflen;
41: struct qstream *qsp;
42: struct sockaddr_in *from;
43: {
44: register HEADER *hp;
45: register char *cp;
46: register struct namebuf *np;
47: register struct databuf *dp;
48: struct databuf *tmp;
49: struct databuf *pdp;
50: struct hashbuf *htp;
51: struct zoneinfo *zp;
52: char *fname;
53: char dnbuf[MAXDNAME], *dname;
54: char **dpp;
55: char *dnp;
56: char *newmsg;
57: int n, class, type, count, foundname, founddata, cname = 0;
58: int newmsglen;
59: u_short id;
60: struct databuf *nsp[MAXNS], **nspp;
61: struct qinfo *qp;
62: time_t curtime;
63: extern struct qinfo *qhead;
64: extern int nsid;
65:
66: #ifdef DEBUG
67: if (debug > 3) {
68: fprintf(ddt,"ns_req()\n");
69: fp_query(msg, ddt);
70: }
71: #endif
72:
73: hp = (HEADER *) msg;
74: if (hp->qr) {
75: ns_resp(msg, msglen);
76: return;
77: }
78:
79: cp = msg + sizeof(HEADER);
80: hp->rcode = NOERROR;
81: dpp = dnptrs;
82: *dpp++ = msg;
83: addcount = 0;
84:
85:
86: switch (hp->opcode) {
87: case QUERY:
88: if (ntohs(hp->qdcount) != 1 ||
89: hp->ancount || hp->nscount || hp->arcount) {
90: #ifdef DEBUG
91: if (debug)
92: fprintf(ddt,"FORMERR Query header counts wrong\n");
93: #endif
94: hp->qdcount = 0;
95: hp->ancount = 0;
96: hp->nscount = 0;
97: hp->arcount = 0;
98: hp->rcode = FORMERR;
99: break;
100: }
101: /*
102: * Get domain name, class, and type.
103: */
104: if ((*cp & INDIR_MASK) == 0)
105: *dpp++ = cp; /* remember name for compression */
106: *dpp = NULL;
107: if ((n = dn_expand(msg, msg + msglen, cp, dnbuf,
108: sizeof(dnbuf))) < 0) {
109: #ifdef DEBUG
110: if (debug)
111: fprintf(ddt,"FORMERR Query expand name failed\n");
112: #endif
113: hp->rcode = FORMERR;
114: break;
115: }
116: cp += n;
117: type = getshort(cp);
118: cp += sizeof(u_short);
119: class = getshort(cp);
120: cp += sizeof(u_short);
121: if (cp < msg + msglen) {
122: #ifdef DEBUG
123: if (debug)
124: fprintf(ddt,"FORMERR Query message length off\n");
125: #endif
126: hp->rcode = FORMERR;
127: break;
128: }
129: #ifdef DEBUG
130: if (cp > msg + msglen)
131: if (debug > 5)
132: fprintf(ddt,"message length > recived message\n");
133: #endif
134: #ifdef notdef
135: if (!check_class(quest.qtype->class)) {
136: if (debug)
137: fprintf(ddt,"FORMERR Query class is wrong\n");
138: hp->rcode = FORMERR;
139: break;
140: }
141: if (!check_type(quest.qtype->type)) {
142: if (debug)
143: fprintf(ddt,"proc_query FORMERR Query type wrong\n");
144: hp->rcode = FORMERR;
145: break;
146: }
147: #endif
148: /*
149: * Process query.
150: */
151: if (type == T_AXFR) {
152: /* refuse request if not a TCP connection */
153: if (qsp == QSTREAM_NULL) {
154: hp->rcode = REFUSED;
155: break;
156: }
157: /* don't compress names */
158: dnptrs[0] = NULL;
159: }
160: buflen -= msglen;
161: count = 0;
162: foundname = 0;
163: founddata = 0;
164: dname = dnbuf;
165: again:
166: #ifdef DEBUG
167: if (debug)
168: fprintf(ddt,"nlookup(%s)\n", dname);
169: #endif
170: htp = hashtab; /* lookup relative to root */
171: np = nlookup(dname, &htp, &fname, 0);
172: /*
173: * if nlookup failed to find address then
174: * see if there are any '.''s in the name
175: * if not then add local domain name to the
176: * name and try again.
177: */
178: if (np == NULL) {
179: fname = "";
180: dnp = &dname[strlen(dname)];
181: if ( index(dname, '.') == NULL)
182: for (zp = zones; zp < &zones[nzones]; zp++) {
183: if ( zp->z_type == Z_DOMAIN){
184: #ifdef DEBUG
185: if (debug >= 5)
186: fprintf(ddt,"domain = %s\n",
187: zp->z_origin);
188: #endif
189: (void) strcat(dname,".");
190: (void) strcat(dname,zp->z_origin);
191: #ifdef DEBUG
192: if (debug)
193: fprintf(ddt,"nlookup(%s)\n", dname);
194: #endif
195: np = nlookup(dname, &htp, &fname, 0);
196: if (np != NULL)
197: break;
198: fname = "";
199: *dnp = '\0';
200: }
201: }
202: }
203: if (fname != dname) {
204: #ifdef DEBUG
205: if (debug && cname) {
206: if (founddata)
207: fprintf(ddt,"CNAME with data\n");
208: else
209: fprintf(ddt,"CNAME without data %s\n", dname);
210: }
211: #endif
212: goto findns;
213: }
214: #ifdef DEBUG
215: if (debug)
216: fprintf(ddt,"found '%s'\n", dname);
217: #endif
218: foundname++;
219: pdp = NULL;
220: dp = np->n_data;
221: /* look for the data */
222: while (dp != NULL) {
223: if (!wanted(dp, class, type)) {
224: pdp = dp;
225: dp = dp->d_next;
226: continue;
227: }
228: if ((n = make_rr(dname, dp, cp, buflen, 1)) < 0) {
229: if (n == -1) {
230: hp->tc = 1;
231: break;
232: }
233:
234: /* delete old cache entry */
235: #ifdef DEBUG
236: if (debug)
237: fprintf(ddt,"deleting cache entry\n");
238: #endif
239: rminv(dp);
240: tmp = dp->d_next;
241: (void) free((char *)dp);
242: dp = tmp;
243: if (pdp == NULL)
244: np->n_data = dp;
245: else
246: pdp->d_next = dp;
247: continue;
248:
249: }
250: cp += n;
251: buflen -= n;
252: count++;
253: if (dp->d_zone)
254: hp->aa = 1;
255: if (dp->d_type == T_CNAME) {
256: if (type == T_ANY)
257: break;
258: cname++;
259: dname = dp->d_data;
260: goto again;
261: }
262: founddata++;
263: pdp = dp;
264: dp = dp->d_next;
265: }
266: #ifdef DEBUG
267: if (debug >= 5) {
268: fprintf(ddt,"foundname = %d count = %d ", foundname, count);
269: fprintf(ddt,"founddata = %d cname = %d\n",founddata, cname);
270: }
271: #endif
272: if (count) {
273: hp->ancount = htons((u_short)count);
274: if (type == T_AXFR && founddata) {
275: #ifdef DEBUG
276: if (debug >= 5)
277: fprintf(ddt,"doing axfr()\n");
278: #endif
279: /*
280: * child does the work while
281: * the parent continues
282: */
283: if (fork() == 0) {
284: register FILE *rfp;
285: int fdstat;
286:
287: rfp = fdopen(qsp->s_rfd, "w");
288: setproctitle("zone XFR to", qsp->s_rfd);
289: fdstat = fcntl(qsp->s_rfd, F_GETFL, 0);
290: if (fdstat != -1)
291: (void) fcntl(qsp->s_rfd, F_SETFL,
292: fdstat & ~FNDELAY);
293: fwritemsg(rfp, msg, cp - msg);
294: doaxfr(np, rfp, 1);
295: fwritemsg(rfp, msg, cp - msg);
296: (void) fflush(rfp);
297: exit(0);
298: }
299: qsp->s_time = tt.tv_sec;
300: qsp->s_refcnt--;
301: return;
302: }
303: if (hp->aa)
304: break;
305: }
306: findns:
307: /*
308: * Look for name servers to refer to and
309: * fill in the authority section or record the address
310: * for forwarding the query (recursion desired).
311: */
312: for (count = 0; ; np = np->n_parent) {
313: #ifdef DEBUG
314: if (debug >= 5)
315: fprintf(ddt,"fname = '%s'\n", fname);
316: #endif
317: if (*fname == '\0') {
318: for (np = hashtab->h_tab[0]; np != NULL;
319: np = np->n_next)
320: if ( np->n_dname[0] == '\0')
321: goto foundns;
322: #ifdef DEBUG
323: if (debug)
324: fprintf(ddt,"No root nameserver?\n");
325: #endif
326: syslog(LOG_ERR,"No root Nameserver\n");
327: hp->rcode = SERVFAIL;
328: break;
329: }
330: foundns:
331: nspp = nsp; /* record ns records if forwarding */
332: pdp = NULL;
333: dp = np->n_data;
334: curtime =(u_long) tt.tv_sec;
335: while (dp != NULL) {
336: if (dp->d_zone && match(dp, class, T_SOA)) {
337: if (!foundname)
338: hp->rcode = NXDOMAIN;
339: hp->aa = 1;
340: goto finish;
341: }
342: if (!match(dp, class, T_NS)) {
343: pdp = dp;
344: dp = dp->d_next;
345: continue;
346: }
347: if ((dp->d_zone == 0) &&
348: (dp->d_ttl < curtime)) {
349: /* delete old cache entry */
350: #ifdef DEBUG
351: if (debug)
352: fprintf(ddt,"deleting cache entry\n");
353: #endif
354: rminv(dp);
355: tmp = dp->d_next;
356: (void) free((char *)dp);
357: dp = tmp;
358: if (pdp == NULL)
359: np->n_data = dp;
360: else
361: pdp->d_next = dp;
362: continue;
363: }
364: if (hp->rd && !founddata) {
365: if (nspp < &nsp[MAXNS-1])
366: *nspp++ = dp;
367: pdp = dp;
368: dp = dp->d_next;
369: continue;
370: }
371: if ((n = make_rr(fname, dp, cp, buflen, 1)) < 0) {
372: if (n == -1) {
373: hp->tc = 1;
374: break;
375: }
376: /* delete old cache entry */
377: #ifdef DEBUG
378: if (debug)
379: fprintf(ddt,"deleting cache entry\n");
380: #endif
381: rminv(dp);
382: tmp = dp->d_next;
383: (void) free((char *)dp);
384: dp = tmp;
385: if (pdp == NULL)
386: np->n_data = dp;
387: else
388: pdp->d_next = dp;
389: continue;
390: }
391: cp += n;
392: buflen -= n;
393: count++;
394: pdp = dp;
395: dp = dp->d_next;
396: }
397: if (count && founddata) {
398: hp->nscount = htons((u_short)count);
399: break;
400: }
401: if (nspp != nsp) {
402: *nspp = NULL;
403: if (cname) {
404: id = hp->id;
405: for (qp = qhead; qp!=QINFO_NULL;
406: qp = qp->q_link) {
407: if (qp->q_id == id &&
408: qp->q_cmsglen == msglen &&
409: bcmp((char *)qp->q_cmsg+2,
410: msg+2, msglen-2) == 0)
411: return;
412: }
413: /* build new qinfo struct */
414: qp = qnew();
415: qp->q_naddr = 0;
416: if (nslookup(nsp, qp) == 0) {
417: #ifdef DEBUG
418: if (debug >= 5)
419: fprintf(ddt,"none found in nsp\n");
420: #endif
421: qfree(qp);
422: hp->rcode = SERVFAIL;
423: break;
424: }
425: qp->q_cname++;
426: qp->q_stream = qsp;
427: qp->q_curaddr = 0;
428: qp->q_id = id;
429: qp->q_from = *from;
430: if ((qp->q_cmsg = malloc((unsigned)msglen))
431: == NULL) {
432: #if DEBUG
433: if (debug)
434: fprintf(ddt,"ns_req: malloc fail\n");
435: #endif
436: syslog(LOG_ERR, "ns_req: Out Of Memory");
437: hp->rcode = SERVFAIL;
438: break;
439: }
440: bcopy(msg, qp->q_cmsg, qp->q_cmsglen = msglen);
441: if ((newmsg = malloc(BUFSIZ)) == NULL) {
442: #if DEBUG
443: if (debug)
444: fprintf(ddt,"ns_req: malloc error\n");
445: #endif
446: syslog(LOG_ERR, "ns_req: Out Of Memory");
447: hp->rcode = SERVFAIL;
448: goto finish;
449: }
450: buflen = BUFSIZ;
451: dnptrs[0] = newmsg;
452: dnptrs[1] = NULL;
453: newmsglen = res_mkquery(QUERY, dname, class,
454: type, (char *)NULL, 0, NULL,
455: newmsg, buflen);
456: qp->q_msg = newmsg;
457: qp->q_msglen = newmsglen;
458: hp = (HEADER *) newmsg;
459: hp->id = qp->q_nsid = htons((u_short)++nsid);
460: hp->ancount = 0;
461: hp->nscount = 0;
462: hp->arcount = 0;
463: schedretry(qp, (time_t)RETRYTIME);
464:
465: #ifdef DEBUG
466: if (debug)
467: fprintf(ddt,"forw -> %s (%d)\n",
468: inet_ntoa(qp->q_addr[0].sin_addr),
469: ntohs(qp->q_addr[0].sin_port));
470: if ( debug >= 10)
471: fp_query(newmsg, ddt);
472: #endif
473: if (sendto(ds, newmsg, newmsglen, 0,
474: &qp->q_addr[0], sizeof(qp->q_addr[0])) < 0){
475: #ifdef DEBUG
476: if (debug)
477: fprintf(ddt,"sendto error \n");
478: #endif
479: }
480: return;
481: }
482: if ((n = ns_forw(nsp, msg, msglen, from, qsp)) == 0)
483: return;
484: if (n == -2) {
485: hp->rcode = SERVFAIL;
486: break;
487: }
488: }
489: if (*fname == '\0')
490: break;
491: if ((fname = index(fname, '.')) == NULL)
492: fname = "";
493: else
494: fname++;
495: }
496: break;
497:
498: case IQUERY: {
499: register struct invbuf *ip;
500: register int i;
501: int dlen, alen;
502: char anbuf[PACKETSZ], *data;
503:
504: if (ntohs(hp->ancount) != 1 ||
505: hp->qdcount || hp->nscount || hp->arcount) {
506: #ifdef DEBUG
507: if (debug)
508: fprintf(ddt,"FORMERR IQuery header counts wrong\n");
509: #endif
510: hp->qdcount = 0;
511: hp->ancount = 0;
512: hp->nscount = 0;
513: hp->arcount = 0;
514: hp->rcode = FORMERR;
515: break;
516: }
517: /*
518: * Skip domain name, get class, and type.
519: */
520: if ((n = dn_skip(cp)) < 0) {
521: #ifdef DEBUG
522: if (debug)
523: fprintf(ddt,"FORMERR IQuery packet name problem\n");
524: #endif
525: hp->rcode = FORMERR;
526: break;
527: }
528: cp += n;
529: type = getshort(cp);
530: cp += sizeof(u_short);
531: class = getshort(cp);
532: cp += sizeof(u_short) + sizeof(u_long);
533: dlen = getshort(cp);
534: cp += sizeof(u_short) + dlen;
535: if (cp != msg + msglen) {
536: #ifdef DEBUG
537: if (debug)
538: fprintf(ddt,"FORMERR IQuery message length off\n");
539: #endif
540: hp->rcode = FORMERR;
541: break;
542: }
543: /* not all inverse queries are handled. */
544: switch (type) {
545: case T_A:
546: case T_UID:
547: case T_GID:
548: break;
549:
550: default:
551: hp->rcode = REFUSED;
552: goto finish;
553: }
554: fname = msg + sizeof(HEADER);
555: bcopy(fname, anbuf, alen = cp - fname);
556: data = anbuf + alen - dlen;
557: cp = fname;
558: buflen -= sizeof(HEADER);
559: count = 0;
560: for (ip = invtab[dhash(data, dlen)]; ip != NULL;
561: ip = ip->i_next) {
562: for (i = 0; i < INVBLKSZ; i++) {
563: if ((np = ip->i_dname[i]) == NULL)
564: break;
565: #ifdef DEBUG
566: if (debug >= 5)
567: fprintf(ddt,"dname = %d\n", np->n_dname);
568: #endif
569: for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
570: if (!match(dp, class, type))
571: continue;
572: if (dp->d_size != dlen ||
573: bcmp(dp->d_data, data, dlen))
574: continue;
575: getname(np, dnbuf, sizeof(dnbuf));
576: buflen -= QFIXEDSZ;
577: if ((n =
578: dn_comp(dnbuf, cp, buflen, (char **)NULL,
579: (char **)NULL)) < 0)
580: {
581: hp->tc = 1;
582: goto finish;
583: }
584: cp += n;
585: putshort((u_short)dp->d_type, cp);
586: cp += sizeof(u_short);
587: putshort((u_short)dp->d_class, cp);
588: cp += sizeof(u_short);
589: buflen -= n;
590: count++;
591: }
592: }
593: }
594: hp->qdcount = htons((u_short)count);
595: if (alen > buflen) {
596: hp->tc = 1;
597: break;
598: }
599: bcopy(anbuf, cp, alen);
600: cp += alen;
601: break;
602: }
603:
604: #ifdef notdef
605: case UPDATEA:
606: if ((n =
607: dn_expand(msg, msg + msglen, cp, dnbuf, sizeof(dnbuf))) < 0)
608: {
609: #ifdef DEBUG
610: if (debug)
611: fprintf(ddt,"FORMERR UpdateA expand name failed\n");
612: #endif
613: hp->rcode = FORMERR;
614: break;
615: }
616: cp += n;
617: type = getshort(cp);
618: cp += sizeof(u_short);
619: class = getshort(cp);
620: cp += sizeof(u_short);
621: ttl = getlong(cp);
622: cp += sizeof(u_long);
623: n = getshort(cp);
624: cp += sizeof(u_short);
625: if (cp + n != msg + msglen) {
626: #ifdef DEBUG
627: if (debug)
628: fprintf(ddt,"FORMERR UpdateA expand name failed\n");
629: #endif
630: hp->rcode = FORMERR;
631: break;
632: }
633: dp = savedata(class, type, ttl, cp, n);
634: dp->d_zone = findzone(dnbuf, class);
635: if ((n = updatedb(dnbuf, NULL, dp, DB_NODATA)) != NOERROR) {
636: #ifdef DEBUG
637: if (debug)
638: fprintf(ddt,"update failed\n");
639: #endif
640: hp->rcode = n;
641: }
642: hp->rcode = NOERROR;
643: break;
644:
645: case UPDATED:
646: if ((n =
647: dn_expand(msg, msg + msglen, cp, dnbuf, sizeof(dnbuf))) < 0)
648: {
649: #ifdef DEBUG
650: if (debug)
651: fprintf(ddt,"FORMERR UpdateD expand name failed\n");
652: #endif
653: hp->rcode = FORMERR;
654: break;
655: }
656: cp += n;
657: rrec.r_type = getshort(cp);
658: cp += sizeof(u_short);
659: rrec.r_class = getshort(cp);
660: cp += sizeof(u_short) + sizeof(u_long);
661: rrec.r_size = getshort(cp);
662: rrec.r_data = cp += sizeof(u_short);
663: if (cp + rrec.r_size != msg + msglen) {
664: #ifdef DEBUG
665: if (debug)
666: fprintf(ddt,"FORMERR UpdateD message length off\n");
667: #endif
668: hp->rcode = FORMERR;
669: break;
670: }
671: if (updatedb(dnbuf, &rrec, NULL, DB_DELETE) < 0) {
672: #ifdef DEBUG
673: if (debug)
674: fprintf(ddt,"update failed\n");
675: #endif
676: }
677: hp->rcode = NOERROR;
678: break;
679:
680: case UPDATEM:
681: if ((n = dn_expand(msg, msg + msglen, cp, addbuf,
682: sizeof(addbuf))) < 0) {
683: #ifdef DEBUG
684: if (debug)
685: fprintf(ddt,"FORMERR UpdateM expand name 1 failed\n");
686: #endif
687: hp->rcode = FORMERR;
688: break;
689: }
690: cp += n;
691: rrec.r_type = getshort(cp);
692: cp += sizeof(u_short);
693: rrec.r_class = getshort(cp);
694: cp += sizeof(u_short) + sizeof(u_long);
695: rrec.r_size = getshort(cp);
696: rrec.r_data = cp += sizeof(u_short);
697: cp += rrec.r_size;
698: if ((n =
699: dn_expand(msg, msg + msglen, cp, dnbuf, sizeof(dnbuf))) < 0)
700: {
701: #ifdef DEBUG
702: if (debug)
703: fprintf(ddt,"FORMERR UpdateM expand name 2 failed\n");
704: #endif
705: hp->rcode = FORMERR;
706: break;
707: }
708: if (cistrcmp(dnbuf, addbuf) != 0) {
709: #ifdef DEBUG
710: if (debug)
711: fprintf(ddt,"FORMERR UpdateM string compair failed\n");
712: #endif
713: hp->rcode = FORMERR;
714: break;
715: }
716: cp += n;
717: type = getshort(cp);
718: cp += sizeof(u_short);
719: class = getshort(cp);
720: cp += sizeof(u_short);
721: ttl = getlong(cp);
722: cp += sizeof(u_long);
723: n = getshort(cp);
724: cp += sizeof(u_short);
725: if (cp + n != msg + msglen) {
726: #ifdef DEBUG
727: if (debug)
728: fprintf(ddt,"FORMERR UpdateM message length off\n");
729: #endif
730: hp->rcode = FORMERR;
731: break;
732: }
733: dp = savedata(class, type, ttl, cp, n);
734: dp->d_zone = findzone(dnbuf, class);
735: if ((n =
736: updatedb(dnbuf, &rrec, dp, DB_MEXIST|DB_DELETE)) != NOERROR)
737: {
738: #ifdef DEBUG
739: if (debug)
740: fprintf(ddt,"update failed\n");
741: #endif
742: hp->rcode = n;
743: }
744: hp->rcode = NOERROR;
745: break;
746: #endif
747:
748: case ZONEREF:
749: #ifdef DEBUG
750: if (debug)
751: fprintf(ddt,"Refresh Zone\n");
752: #endif
753:
754: default:
755: hp->rcode = NOTIMP;
756: hp->qdcount = 0;
757: hp->ancount = 0;
758: hp->nscount = 0;
759: hp->arcount = 0;
760: }
761: finish:
762: hp->qr = 1; /* set Response flag */
763: hp->ra = 1; /* Recursion is Available */
764: if (addcount)
765: cp += doaddinfo(hp, cp, buflen - (cp - msg));
766: #ifdef DEBUG
767: if (debug >= 10)
768: fp_query(msg, ddt);
769: #endif
770: if (qsp == QSTREAM_NULL) {
771: if (sendto(ds, msg, cp-msg, 0, from, sizeof(*from)) < 0) {
772: #ifdef DEBUG
773: if (debug)
774: fprintf(ddt,"error returning msg\n");
775: #endif
776: }
777: } else {
778: (void) writemsg(qsp->s_rfd, msg, cp - msg);
779: qsp->s_time = tt.tv_sec;
780: qsp->s_refcnt--;
781: }
782: }
783:
784: fwritemsg(rfp, msg, msglen)
785: FILE *rfp;
786: char *msg;
787: int msglen;
788: {
789: u_short len = htons((u_short)msglen);
790:
791: if (fwrite((char *)&len, sizeof(len), 1, rfp) != 1 ||
792: fwrite(msg, msglen, 1, rfp) != 1) {
793: #ifdef DEBUG
794: if (debug)
795: fprintf(ddt,"fwrite failed %d\n", errno);
796: #endif
797: /*
798: syslog(LOG_ERR, "fwritemsg: write failed: %m");
799: */
800: }
801: return;
802: }
803:
804: writemsg(rfd, msg, msglen)
805: int rfd;
806: char *msg;
807: int msglen;
808: {
809: struct iovec iov[2];
810: u_short len = htons((u_short)msglen);
811:
812: iov[0].iov_base = (caddr_t)&len;
813: iov[0].iov_len = sizeof(len);
814: iov[1].iov_base = msg;
815: iov[1].iov_len = msglen;
816: if (writev(rfd, iov, 2) != sizeof(len) + msglen) {
817: #ifdef DEBUG
818: if (debug)
819: fprintf(ddt,"write failed %d\n", errno);
820: #endif
821: /*
822: syslog(LOG_ERR, "writemsg: write failed: %m");
823: */
824: return (-1);
825: }
826: return (0);
827: }
828:
829: /*
830: * Copy databuf into a resource record for replies.
831: * Return size of RR if OK, -1 if buffer is full and
832: * -2 if its an outdated cache entry.
833: */
834: make_rr(name, dp, buf, buflen, doadd)
835: char *name;
836: register struct databuf *dp;
837: char *buf;
838: int buflen, doadd;
839: {
840: register char *cp;
841: register struct addinfo *ap;
842: char *cp1, *sp;
843: register long n;
844: u_long ttl;
845: char **edp = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);
846:
847: #ifdef DEBUG
848: if (debug >= 5)
849: fprintf(ddt,"make_rr(%s, %x, %x, %d, %d) %d\n", name, dp, buf,
850: buflen, doadd, dp->d_size);
851: #endif
852:
853: /* check for outdated RR before updating dnptrs by dn_comp() */
854: if (dp->d_zone == 0) {
855: ttl = dp->d_ttl - (u_long) tt.tv_sec;
856: if (dp->d_ttl < (u_long)tt.tv_sec)
857: return (-2);
858: } else {
859: ttl = zones[dp->d_zone].z_minimum;
860: if (dp->d_ttl > ttl)
861: ttl = dp->d_ttl;
862: }
863:
864: buflen -= RRFIXEDSZ;
865: if ((n = dn_comp(name, buf, buflen, (char **)dnptrs, (char **)edp)) < 0)
866: return (-1);
867: cp = buf + n;
868: buflen -= n;
869: putshort((u_short)dp->d_type, cp);
870: cp += sizeof(u_short);
871: putshort((u_short)dp->d_class, cp);
872: cp += sizeof(u_short);
873: putlong(ttl, cp);
874: cp += sizeof(u_long);
875: sp = cp;
876: cp += sizeof(u_short);
877: switch (dp->d_type) {
878: case T_CNAME:
879: case T_MG:
880: case T_MR:
881: case T_PTR:
882: if ((n = dn_comp(dp->d_data, cp, buflen, (char **)dnptrs,
883: (char **)edp)) < 0)
884: return (-1);
885: putshort((u_short)n, sp);
886: cp += n;
887: break;
888:
889: case T_MB:
890: case T_NS:
891: /* Store domain name in answer */
892: if ((n = dn_comp(dp->d_data, cp, buflen, (char **)dnptrs,
893: (char **)edp)) < 0)
894: return (-1);
895: putshort((u_short)n, sp);
896: cp += n;
897: if (!doadd)
898: break;
899: for (ap = addinfo, n = addcount; --n >= 0; ap++)
900: if (cistrcmp(ap->a_dname, dp->d_data) == 0)
901: goto found;
902: /* add domain name to additional section */
903: if (addcount >= NADDRECS)
904: break;
905: addcount++;
906: ap->a_dname = dp->d_data;
907: ap->a_class = dp->d_class;
908: found:
909: break;
910:
911: case T_SOA:
912: case T_MINFO:
913: cp1 = dp->d_data;
914: if ((n = dn_comp(cp1, cp, buflen, (char **)dnptrs,
915: (char **)edp)) < 0)
916: return (-1);
917: cp += n;
918: buflen -= dp->d_type == T_MINFO ? n : n + 5 * sizeof(u_long);
919: cp1 += strlen(cp1) + 1;
920: if ((n = dn_comp(cp1, cp, buflen, (char **)dnptrs,
921: (char **)edp)) < 0)
922: return (-1);
923: cp += n;
924: if (dp->d_type == T_SOA) {
925: cp1 += strlen(cp1) + 1;
926: bcopy(cp1, cp,
927: (int)(n = dp->d_size - (cp1 - dp->d_data)));
928: cp += n;
929: }
930: putshort((u_short)(cp - sp) - sizeof(u_short), sp);
931: break;
932:
933: case T_MX:
934: /* cp1 == our data/ cp == data of RR */
935: cp1 = dp->d_data;
936:
937: /* copy preference */
938: bcopy(cp1,cp,sizeof(u_short));
939: cp += sizeof(u_short);
940: cp1 += sizeof(u_short);
941: buflen -= sizeof(u_short);
942:
943: if ((n = dn_comp(cp1, cp, buflen, (char **)dnptrs,
944: (char **)edp)) < 0)
945: return(-1);
946: cp += n;
947:
948: /* save data length */
949: putshort((u_short)(cp-sp)-sizeof(u_short),sp);
950: break;
951:
952: default:
953: if (dp->d_size > buflen)
954: return (-1);
955: bcopy(dp->d_data, cp, dp->d_size);
956: putshort((u_short)dp->d_size, sp);
957: cp += dp->d_size;
958: }
959: return (cp - buf);
960: }
961:
962: /*
963: * Lookup addresses for names in addinfo and put into the message's
964: * additional section.
965: */
966: doaddinfo(hp, msg, msglen)
967: HEADER *hp;
968: char *msg;
969: int msglen;
970: {
971: register char *cp;
972: register struct namebuf *np;
973: register struct databuf *dp;
974: register struct databuf *tmp;
975: struct hashbuf *htp;
976: struct databuf *pdp;
977: struct addinfo *ap;
978: char *fname;
979: int n, count;
980:
981: #ifdef DEBUG
982: if (debug >= 3)
983: fprintf(ddt,"doaddinfo() addcount = %d\n", addcount);
984: #endif
985:
986: count = 0;
987: cp = msg;
988: for (ap = addinfo; --addcount >= 0; ap++) {
989: #ifdef DEBUG
990: if (debug >= 5)
991: fprintf(ddt,"do additional '%s'\n", ap->a_dname);
992: #endif
993: htp = hashtab; /* lookup relative to root */
994: np = nlookup(ap->a_dname, &htp, &fname, 0);
995: if (np == NULL || fname != ap->a_dname)
996: continue;
997: #ifdef DEBUG
998: if (debug >= 5)
999: fprintf(ddt,"found it\n");
1000: #endif
1001: pdp = NULL;
1002: dp = np->n_data;
1003: /* look for the data */
1004: while (dp != NULL) {
1005: if (!match(dp, (int)ap->a_class, T_A)) {
1006: pdp = dp;
1007: dp = dp->d_next;
1008: continue;
1009: }
1010: if ((n = make_rr(ap->a_dname, dp, cp, msglen, 0)) < 0)
1011: {
1012: if (n == -1)
1013: break;
1014: /* delete old cache entry */
1015: #ifdef DEBUG
1016: if (debug)
1017: fprintf(ddt,"deleting cache entry\n");
1018: #endif
1019: rminv(dp);
1020: tmp = dp->d_next;
1021: (void) free((char *)dp);
1022: dp = tmp;
1023: if (pdp == NULL)
1024: np->n_data = dp;
1025: else
1026: pdp->d_next = dp;
1027: continue;
1028: }
1029: #ifdef DEBUG
1030: if (debug >= 5)
1031: fprintf(ddt,"n = %d\n", n);
1032: #endif
1033: cp += n;
1034: msglen -= n;
1035: count++;
1036: pdp = dp;
1037: dp = dp->d_next;
1038: }
1039: }
1040: hp->arcount = htons((u_short)count);
1041: return (cp - msg);
1042: }
1043:
1044: /*
1045: * Do we want this data record based on the class and type?
1046: */
1047: wanted(dp, class, type)
1048: struct databuf *dp;
1049: int class, type;
1050: {
1051:
1052: #ifdef DEBUG
1053: if (debug > 3)
1054: fprintf(ddt,"wanted(%x, %d, %d) %d, %d\n", dp, class, type,
1055: dp->d_class, dp->d_type);
1056: #endif
1057:
1058: if (dp->d_class != class && class != C_ANY)
1059: return (0);
1060: if (type == dp->d_type)
1061: return (1);
1062: switch (dp->d_type) {
1063: case T_ANY:
1064: case T_CNAME:
1065: return (1);
1066: }
1067: switch (type) {
1068: case T_ANY:
1069: return (1);
1070:
1071: case T_MAILB:
1072: switch (dp->d_type) {
1073: case T_MR:
1074: case T_MB:
1075: case T_MG:
1076: case T_MINFO:
1077: return (1);
1078: }
1079: break;
1080:
1081: case T_AXFR:
1082: if (dp->d_type == T_SOA)
1083: return (1);
1084: }
1085: return (0);
1086: }
1087:
1088: /*
1089: * Get the domain name of 'np' and put in 'buf'.
1090: */
1091: getname(np, buf, buflen)
1092: struct namebuf *np;
1093: char *buf;
1094: int buflen;
1095: {
1096: register char *cp;
1097:
1098: cp = buf;
1099: while (np != NULL) {
1100: if (cp != buf)
1101: *cp++ = '.';
1102: (void) strcpy(cp, np->n_dname);
1103: cp += strlen(cp);
1104: np = np->n_parent;
1105: }
1106: *cp = '\0';
1107: }
1108:
1109: /*
1110: * Do a zone transfer. SOA record already sent.
1111: */
1112: doaxfr(np, rfp, isroot)
1113: register struct namebuf *np;
1114: FILE *rfp;
1115: int isroot;
1116: {
1117: register struct databuf *dp;
1118: register int n;
1119: struct namebuf **npp, **nppend;
1120: char msg[PACKETSZ];
1121: HEADER *hp = (HEADER *) msg;
1122: char *cp;
1123: char dname[MAXDNAME];
1124: int fndns;
1125:
1126: #ifdef DEBUG
1127: if (debug && isroot)
1128: fprintf(ddt,"doaxfr()\n");
1129: #endif
1130: fndns = 0;
1131: hp->id = 0;
1132: hp->opcode = QUERY;
1133: hp->qr = hp->aa = hp->tc = hp->ra = hp->pr = hp->rd = 0;
1134: hp->rcode = NOERROR;
1135: hp->qdcount = 0;
1136: hp->ancount = htons(1);
1137: hp->nscount = 0;
1138: hp->arcount = 0;
1139: cp = msg + sizeof(HEADER);
1140: getname(np, dname, sizeof(dname));
1141:
1142: /* first do data records */
1143: for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
1144: /* skip the root SOA record (marks end of data) */
1145: if (isroot) {
1146: if (dp->d_type == T_SOA)
1147: continue;
1148: } else if (dp->d_type == T_NS)
1149: fndns = 1;
1150: if (dp->d_zone == 0)
1151: continue;
1152: if ((n = make_rr(dname, dp, cp,
1153: sizeof(msg)-sizeof(HEADER), 0)) < 0)
1154: continue;
1155: fwritemsg(rfp, msg, n + sizeof(HEADER));
1156: }
1157:
1158: /* next do subdomains */
1159: if (fndns || np->n_hash == NULL)
1160: return;
1161: npp = np->n_hash->h_tab;
1162: nppend = npp + np->n_hash->h_size;
1163: while (npp < nppend) {
1164: for (np = *npp++; np != NULL; np = np->n_next) {
1165: doaxfr(np, rfp, 0);
1166: }
1167: }
1168: #ifdef DEBUG
1169: if (debug && isroot)
1170: fprintf(ddt,"exit doaxfr()\n");
1171: #endif
1172: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.