|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)ns_resp.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/time.h>
13: #include <sys/socket.h>
14: #include <netinet/in.h>
15: #include <syslog.h>
16: #include <arpa/nameser.h>
17: #include "ns.h"
18: #include "db.h"
19:
20: extern int errno;
21: extern char *dnptrs[];
22: extern char *malloc();
23: struct databuf *nsp[MAXNS], **nspp;
24:
25: /*
26: * Handle a response from a forwarded query.
27: */
28: ns_resp(msg, msglen)
29: char *msg;
30: int msglen;
31: {
32: register struct qinfo *qp;
33: register HEADER *hp;
34: register char *cp, *tp;
35: int i, c, n, ancount, nscount, arcount;
36: int type;
37: int qtype, qclass;
38: int cname = 0; /* flag for processing cname response */
39: int count, founddata;
40: int buflen;
41: int newmsglen;
42: char name[MAXDNAME], *dname;
43: char *fname;
44: char *newmsg;
45:
46: struct hashbuf *htp;
47: struct databuf *dp, *tmp, *pdp;
48: struct namebuf *np;
49:
50: #ifdef DEBUG
51: if (debug >= 3)
52: fprintf(ddt,"ns_resp(%x, %d)\n", msg, msglen);
53: #endif
54: hp = (HEADER *) msg;
55: if( (qp = qfindid(hp->id)) == NULL )
56: return;
57:
58: if (hp->rcode != NOERROR || hp->opcode != QUERY)
59: goto retmsg;
60: /*
61: * Skip query section
62: */
63: cp = msg + sizeof(HEADER);
64: if (hp->qdcount) {
65: if ((n = dn_skip(cp)) < 0) {
66: #ifdef DEBUG
67: if (debug)
68: fprintf(ddt,"FORMERR ns_resp() dn_skip failed\n");
69: #endif
70: hp->rcode = FORMERR;
71: goto retmsg;
72: }
73: cp += n;
74: qtype = getshort(cp);
75: cp += sizeof(u_short);
76: qclass = getshort(cp);
77: cp += sizeof(u_short);
78: }
79: /*
80: * Save answers, name server, and additional records for future use.
81: */
82: ancount = ntohs(hp->ancount);
83: nscount = ntohs(hp->nscount);
84: arcount = ntohs(hp->arcount);
85: if (ancount == 1 || nscount) {
86: /*
87: * Check if it's a CNAME responce
88: */
89: tp = cp;
90: tp += dn_skip(tp); /* name */
91: type = getshort(tp);
92: tp += sizeof(u_short); /* type */
93: if (type == T_CNAME) {
94: tp += sizeof(u_short); /* class */
95: tp += sizeof(u_long); /* ttl */
96: tp += sizeof(u_short); /* dlen */
97: cname++;
98: #ifdef DEBUG
99: if (debug) {
100: fprintf(ddt,"CNAME - needs more processing\n");
101: }
102: #endif
103: if (!qp->q_cmsglen) {
104: qp->q_cmsg = qp->q_msg;
105: qp->q_cmsglen = qp->q_msglen;
106: }
107: }
108: }
109: /*
110: * Add the info recived in the responce to the Data Base
111: */
112: c = ancount + nscount + arcount;
113: nspp = nsp;
114: for (i = 0; i < c; i++) {
115: if (cp >= msg + msglen) {
116: #ifdef DEBUG
117: if (debug)
118: fprintf(ddt, "FORMERR ns_resp() message bad count?\n");
119: #endif
120: hp->rcode = FORMERR;
121: goto retmsg;
122: }
123: if ((n = doupdate(msg, msglen, cp, 0,
124: !ancount && i < nscount)) < 0) {
125: #ifdef DEBUG
126: if (debug)
127: fprintf(ddt,"FORMERR ns_resp() doupdate failed\n");
128: #endif
129: hp->rcode = FORMERR;
130: goto retmsg;
131: }
132: cp += n;
133: }
134: if (cp > msg + msglen) {
135: #ifdef DEBUG
136: if (debug)
137: fprintf(ddt,"FORMERR ns_resp() packet size err %d, %d\n",
138: cp-msg, msglen);
139: #endif
140: hp->rcode = FORMERR;
141: goto retmsg;
142: }
143: if ((qtype == C_ANY) && ancount)
144: goto retmsg;
145: if ((!cname && !qp->q_cmsglen) && (ancount || nscount == 0))
146: goto retmsg;
147:
148: /*
149: * All messages in here need further processing. i.e. they
150: * are either CNAMEs or we got referred again.
151: */
152: count = 0;
153: founddata = 0;
154: dname = name;
155: if ((newmsg = malloc(BUFSIZ)) == NULL) {
156: #if DEBUG
157: if (debug)
158: fprintf(ddt,"ns_resp: malloc error\n");
159: #endif
160: syslog(LOG_ERR, "ns_resp: Out Of Memory");
161: hp->rcode = SERVFAIL;
162: goto retmsg;
163: }
164: buflen = BUFSIZ;
165: if ((!cname && qp->q_cmsglen) && ancount) {
166: #if DEBUG
167: if (debug) {
168: fprintf(ddt,"Cname second pass\n");
169: }
170: #endif
171: newmsglen = qp->q_cmsglen;
172: bcopy(qp->q_cmsg, newmsg, newmsglen);
173: } else {
174: newmsglen = msglen;
175: bcopy(msg, newmsg, newmsglen);
176: }
177: buflen = buflen - newmsglen;
178: hp = (HEADER *) newmsg;
179: dnptrs[0] = newmsg;
180: dnptrs[1] = NULL;
181: cp = newmsg + sizeof(HEADER);
182: if (cname)
183: cp += dn_skip(cp) + QFIXEDSZ;
184: if ((n = dn_expand(newmsg, newmsg + newmsglen,
185: cp, dname, sizeof(name))) < 0) {
186: #ifdef DEBUG
187: if (debug)
188: fprintf(ddt,"dn_expand failed\n" );
189: #endif
190: hp->rcode = SERVFAIL;
191: free(newmsg);
192: goto retmsg;
193: }
194: cp = newmsg + sizeof(HEADER);
195: if (cname)
196: cp += dn_skip(cp);
197: else
198: cp += n;
199: cp += QFIXEDSZ;
200:
201: again:
202: htp = hashtab; /* lookup relative to root */
203: #ifdef DEBUG
204: if (debug)
205: fprintf(ddt,"ns_resp() nlookup(%s)\n",dname);
206: #endif
207: np = nlookup(dname, &htp, &fname, 0);
208: if (np == (struct namebuf *)NULL)
209: fname = "";
210: if (fname != dname)
211: goto findns;
212: #ifdef DEBUG
213: if (debug)
214: fprintf(ddt,"found '%s'\n", dname);
215: #endif
216: pdp = NULL;
217: dp = np->n_data;
218: /* look for the data */
219: while (dp != NULL) {
220: if (!wanted(dp, qclass, qtype)) {
221: pdp = dp;
222: dp = dp->d_next;
223: continue;
224: }
225: if ((n = make_rr(dname, dp, cp, buflen, 1)) < 0) {
226: if (n == -1) {
227: hp->tc = 1;
228: break;
229: }
230: /* delete old cache entry */
231: #ifdef DEBUG
232: if (debug >= 5)
233: fprintf(ddt,"deleting cache entry\n");
234: #endif
235: rminv(dp);
236: tmp = dp->d_next;
237: free((char *)dp);
238: dp = tmp;
239: if (pdp == NULL)
240: np->n_data = dp;
241: else
242: pdp->d_next = dp;
243: continue;
244: }
245: cp += n;
246: buflen -= n;
247: count++;
248: if (dp->d_zone)
249: hp->aa = 1;
250: if (dp->d_type == T_CNAME) {
251: if (type == T_ANY)
252: break;
253: dname = dp->d_data;
254: goto again;
255: }
256: founddata++;
257: pdp = dp;
258: dp = dp->d_next;
259: }
260: #ifdef DEBUG
261: if (debug >= 5)
262: fprintf(ddt,"count = %d, founddata = %d\n", count, founddata);
263: #endif
264: if (count)
265: hp->ancount = htons((u_short)count);
266:
267: findns:
268:
269: /*
270: * Look for name servers to refer to and fill in the authority
271: * section or record the address for forwarding the query
272: * (recursion desired).
273: */
274: for (count = 0;; np = np->n_parent) {
275: #ifdef DEBUG
276: if (debug >= 5)
277: fprintf(ddt, "fname = '%s'\n", fname);
278: #endif
279: if (*fname == '\0') {
280: for (np = hashtab->h_tab[0]; np != NULL;
281: np = np->n_next)
282: if (np->n_dname[0] == '\0')
283: goto foundns;
284: #ifdef DEBUG
285: if (debug)
286: fprintf(ddt, "No root nameserver?\n");
287: #endif
288: syslog(LOG_ERR, "No root Nameserver\n");
289: hp->rcode = SERVFAIL;
290: break;
291: }
292: foundns:
293: nspp = nsp;
294: pdp = NULL;
295: dp = np->n_data;
296: while (dp != NULL) {
297: if (!match(dp, qclass, T_NS)) {
298: pdp = dp;
299: dp = dp->d_next;
300: continue;
301: }
302: if (!founddata) {
303: if (nspp < &nsp[MAXNS-1])
304: *nspp++ = dp;
305: pdp = dp;
306: dp = dp->d_next;
307: continue;
308: }
309: if ((n = make_rr(fname, dp, cp, buflen, 1)) < 0) {
310: if (n == -1) {
311: hp->tc = 1;
312: break;
313: }
314: /* delete old cache entry */
315: #ifdef DEBUG
316: if (debug)
317: fprintf(ddt,"deleting cache entry\n");
318: #endif
319: rminv(dp);
320: tmp = dp->d_next;
321: free((char *)dp);
322: dp = tmp;
323: if (pdp == NULL)
324: np->n_data = dp;
325: else
326: pdp->d_next = dp;
327: continue;
328: }
329: cp += n;
330: buflen -= n;
331: count++;
332: pdp = dp;
333: dp = dp->d_next;
334: }
335: if ((*fname == '\0') || (count > 0))
336: break;
337: if (nspp != nsp)
338: break;
339: if ((fname = index(fname, '.')) == NULL)
340: fname = "";
341: else
342: fname++;
343: }
344:
345: if (count && founddata) {
346: hp->nscount = htons((u_short)count);
347: cp += doaddinfo(hp, cp, buflen);
348: buflen = cp - newmsg;
349: msg = newmsg;
350: msglen = buflen;
351: hp = (HEADER *) msg;
352: goto retmsg;
353: }
354:
355: *nspp = NULL;
356: if (cname) {
357: newmsglen = res_mkquery(QUERY, dname, C_ANY, T_A, (char *)NULL,
358: 0, NULL, newmsg, BUFSIZ);
359: qp->q_msglen = newmsglen;
360: hp->id = qp->q_nsid;
361: } else {
362: hp->ancount = 0;
363: hp->nscount = 0;
364: hp->arcount = 0;
365: hp->qr = 0;
366: }
367: qp->q_naddr = 0;
368: qp->q_curaddr = 0;
369: n = nslookup(nsp, qp);
370:
371: #ifdef DEBUG
372: if (debug > 7) {
373: int kjd;
374:
375: fprintf(ddt,"n = %d\n",n);
376: for (kjd = 0; kjd < qp->q_naddr; kjd++ )
377: fprintf(ddt,"list %d-> %s (%d)\n", kjd,
378: inet_ntoa(qp->q_addr[kjd].sin_addr),
379: ntohs(qp->q_addr[kjd].sin_port));
380: }
381: #endif DEBUG
382: qp->q_msg = newmsg;
383: if (qp->q_cname++ == MAXCNAMES) {
384: hp->id = qp->q_id;
385: hp->rd = 1;
386: hp->ra = 1;
387: if (qp->q_stream != QSTREAM_NULL) {
388: (void) writemsg(qp->q_stream->s_rfd, newmsg, newmsglen);
389: qp->q_stream->s_time = tt.tv_sec;
390: qp->q_stream->s_refcnt--;
391: } else {
392: if (sendto(ds, newmsg, newmsglen, 0, &qp->q_from,
393: sizeof(qp->q_from)) < 0) {
394: #ifdef DEBUG
395: if (debug)
396: fprintf(ddt,"sendto failed\n");
397: #endif
398: }
399: }
400: qremove(qp);
401: return;
402: }
403: #ifdef DEBUG
404: if (debug)
405: fprintf(ddt,"q_cname = %d\n",qp->q_cname);
406: #endif
407: unsched(qp);
408: schedretry(qp, (time_t)RETRYTIME);
409:
410: #ifdef DEBUG
411: if (debug >= 3)
412: fp_query(qp->q_msg, ddt);
413: if (debug)
414: fprintf(ddt,"try -> %s (%d)\n",
415: inet_ntoa(qp->q_addr[0].sin_addr),
416: ntohs(qp->q_addr[0].sin_port));
417: #endif
418: if (sendto(ds, qp->q_msg, qp->q_msglen, 0,
419: &qp->q_addr[0], sizeof(qp->q_addr[0])) < 0) {
420: #ifdef DEBUG
421: if (debug)
422: fprintf(ddt, "error returning msg errno=%d\n",errno);
423: #endif
424: }
425: return;
426:
427: retmsg:
428: /*
429: * Pass answer back to original requestor.
430: */
431: hp->id = qp->q_id;
432: hp->rd = 1; /* restore Recursion Desired bit */
433: hp->ra = 1; /* Recursion is Available */
434: #ifdef DEBUG
435: if (debug)
436: fprintf(ddt,"respond -> %s (%d)\n",
437: inet_ntoa(qp->q_from.sin_addr),
438: ntohs(qp->q_from.sin_port));
439: if (debug >= 10)
440: fp_query(msg, ddt);
441: #endif
442: if (qp->q_stream == QSTREAM_NULL) {
443: if (sendto(ds, msg, msglen, 0,
444: &qp->q_from, sizeof(qp->q_from)) < 0) {
445: #ifdef DEBUG
446: if (debug)
447: fprintf(ddt,"sendto failed\n");
448: #endif
449: }
450:
451: } else {
452: (void) writemsg(qp->q_stream->s_rfd, msg, msglen);
453: qp->q_stream->s_time = tt.tv_sec;
454: qp->q_stream->s_refcnt--;
455: }
456: if (msg == newmsg)
457: (void) free(newmsg);
458: /*
459: * Remove from table
460: */
461: qremove(qp);
462: }
463:
464: /*
465: * Decode the resource record 'rrp' and update the database.
466: * If savens is true, record pointer for forwarding queries a second time.
467: */
468: doupdate(msg, msglen, rrp, zone, savens)
469: char *msg ;
470: char *rrp;
471: int msglen, zone, savens;
472: {
473: register char *cp;
474: register int n;
475: int class, type, dlen, n1;
476: u_long ttl;
477: struct databuf *dp;
478: char dname[MAXDNAME];
479: char data[BUFSIZ], *cp1;
480:
481: #ifdef DEBUG
482: if (debug >= 3)
483: fprintf(ddt,"doupdate(%d, %d)\n", zone, savens);
484: #endif
485:
486: cp = rrp;
487: if ((n = dn_expand(msg, msg + msglen, cp, dname, sizeof(dname))) < 0)
488: return (-1);
489: cp += n;
490: type = getshort(cp);
491: cp += sizeof(u_short);
492: class = getshort(cp);
493: cp += sizeof(u_short);
494: ttl = getlong(cp);
495: cp += sizeof(u_long);
496: dlen = getshort(cp);
497: cp += sizeof(u_short);
498: if (zone == 0) {
499: if (ttl == 0)
500: ttl = 5 * 60;
501: ttl += (u_long) tt.tv_sec;
502: }
503: /*
504: * Convert the resource record data into the internal
505: * database format.
506: */
507: switch (type) {
508: case T_A:
509: case T_HINFO:
510: case T_UINFO:
511: case T_UID:
512: case T_GID:
513: cp1 = cp;
514: n = dlen;
515: cp += n;
516: break;
517:
518: case T_CNAME:
519: case T_MB:
520: case T_MG:
521: case T_MR:
522: case T_NS:
523: case T_PTR:
524: if ((n = dn_expand(msg, msg + msglen, cp, data,
525: sizeof(data))) < 0)
526: return (-1);
527: cp += n;
528: cp1 = data;
529: n = strlen(data) + 1;
530: break;
531:
532: case T_MINFO:
533: case T_SOA:
534: if ((n = dn_expand(msg, msg + msglen, cp, data,
535: sizeof(data))) < 0)
536: return (-1);
537: cp += n;
538: cp1 = data + (n = strlen(data) + 1);
539: n1 = sizeof(data) - n;
540: if (type == T_SOA)
541: n1 -= 5 * sizeof(u_long);
542: if ((n = dn_expand(msg, msg + msglen, cp, cp1, n1)) < 0)
543: return (-1);
544: cp += n;
545: cp1 += strlen(cp1) + 1;
546: if (type == T_SOA) {
547: bcopy(cp, cp1, n = 5 * sizeof(u_long));
548: cp += n;
549: cp1 += n;
550: }
551: n = cp1 - data;
552: cp1 = data;
553: break;
554:
555: case T_MX:
556: /* grab preference */
557: bcopy(cp,data,sizeof(u_short));
558: cp1 = data + sizeof(u_short);
559: cp += sizeof(u_short);
560:
561: /* get name */
562: if ((n = dn_expand(msg, msg + msglen, cp, cp1,
563: sizeof(data)-sizeof(u_short))) < 0)
564: return(-1);
565: cp += n;
566:
567: /* compute end of data */
568: cp1 += strlen(cp1) + 1;
569: /* compute size of data */
570: n = cp1 - data;
571: cp1 = data;
572: break;
573:
574: default:
575: #ifdef DEBUG
576: if (debug >= 3)
577: fprintf(ddt,"unknown type %d\n", type);
578: #endif
579: return ((cp - rrp) + dlen);
580: }
581: dp = savedata(class, type, ttl, cp1, n);
582: dp->d_zone = zone;
583: if ((n = db_update(dname, dp, dp, DB_NODATA)) < 0) {
584: #ifdef DEBUG
585: if (debug && (n != DATAEXISTS))
586: fprintf(ddt,"update failed (%d)\n", n);
587: else if (debug >= 3)
588: fprintf(ddt,"update failed (DATAEXISTS)\n");
589: #endif
590: (void) free((char *)dp);
591: } else if (savens && type == T_NS && nspp < &nsp[MAXNS-1])
592: *nspp++ = dp;
593: return (cp - rrp);
594: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.