|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)ns_forw.c 4.3 (Berkeley) 6/4/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/socket.h>
13: #include <sys/time.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: struct qinfo *qhead = QINFO_NULL; /* head of allocated queries */
21: struct qinfo *retryqp = QINFO_NULL; /* list of queries to retry */
22:
23: int nsid; /* next forwarded query id */
24: extern int errno;
25:
26: /*
27: * Forward the query to get the answer since its not in the database.
28: */
29: ns_forw(nsp, msg, msglen, fp, qsp)
30: struct databuf *nsp[];
31: char *msg;
32: int msglen;
33: struct sockaddr_in *fp;
34: struct qstream *qsp;
35: {
36: register struct qinfo *qp;
37: HEADER *hp;
38: u_short id;
39: extern char *calloc();
40: extern char *malloc();
41:
42: #ifdef DEBUG
43: if (debug > 3)
44: fprintf(ddt,"ns_forw()\n");
45: #endif
46:
47: /* Don't forward if we're already working on it. */
48: hp = (HEADER *) msg;
49: id = hp->id;
50: hp->rd = 0;
51: /* Look at them all */
52: for (qp = qhead; qp!=QINFO_NULL; qp = qp->q_link) {
53: if (qp->q_id == id && qp->q_msglen == msglen &&
54: bcmp((char *)qp->q_msg+2, msg+2, msglen-2) == 0)
55: return (0);
56: }
57:
58: qp = qnew();
59: qp->q_naddr = 0;
60: if (nslookup(nsp, qp) == 0) {
61: #ifdef DEBUG
62: if (debug >= 5)
63: fprintf(ddt,"none found in nsp\n");
64: #endif
65: qfree(qp);
66: return (-1);
67: }
68: qp->q_stream = qsp;
69: qp->q_curaddr = 0;
70: qp->q_id = id;
71: hp->id = qp->q_nsid = htons((u_short)++nsid);
72: hp->ancount = 0;
73: hp->nscount = 0;
74: hp->arcount = 0;
75: qp->q_from = *fp;
76: if ((qp->q_msg = malloc((unsigned)msglen)) == NULL) {
77: syslog(LOG_ERR, "forw: %m");
78: exit(1);
79: }
80: bcopy(msg, qp->q_msg, qp->q_msglen = msglen);
81:
82: schedretry(qp, (time_t)RETRYTIME);
83: #ifdef DEBUG
84: if (debug)
85: fprintf(ddt,"forw -> %s (%d)\n",
86: inet_ntoa(qp->q_addr[0].sin_addr),
87: ntohs(qp->q_addr[0].sin_port));
88: if ( debug >= 10)
89: fp_query(msg, ddt);
90: #endif
91: if (sendto(ds, msg, msglen, 0, &qp->q_addr[0],
92: sizeof(qp->q_addr[0])) < 0) {
93: #ifdef DEBUG
94: if (debug >= 5)
95: fprintf(ddt,"error forwarding msg\n");
96: #endif
97: }
98: return (0);
99: }
100:
101: /*
102: * Lookup the address for each nameserver in `nsp' and add it to
103: * the list saved in the qinfo structure.
104: */
105: nslookup(nsp, qp)
106: struct databuf *nsp[];
107: struct qinfo *qp;
108: {
109: register struct namebuf *np;
110: register struct databuf *dp, *pdp;
111: register int n, i;
112: struct databuf *tmp;
113: struct hashbuf *htp;
114: char *dname, *fname;
115: int naddr, class;
116: time_t curtime;
117:
118: extern short ns_port;
119:
120: #ifdef DEBUG
121: if (debug >= 3)
122: fprintf(ddt,"nslookup(nsp=x%x,qp=x%x)\n",nsp,qp);
123: #endif
124:
125: naddr = n = qp->q_naddr;
126: curtime = (u_long) tt.tv_sec;
127: while ((dp = *nsp++) != NULL) {
128: dname = dp->d_data;
129: class = dp->d_class;
130: htp = hashtab; /* lookup relative to root */
131: np = nlookup(dname, &htp, &fname, 0);
132: if (np == NULL || fname != dname) {
133: #ifdef DEBUG
134: if (debug >= 5)
135: fprintf(ddt,"%s: not found\n", dname);
136: #endif
137: continue;
138: }
139: /* look for name server addresses */
140: pdp = NULL;
141: dp = np->n_data;
142: while (dp != NULL) {
143: if (!match(dp, class, T_A))
144: goto skip;
145: if ((dp->d_zone == 0) && (dp->d_ttl < curtime)) {
146: /* delete old cache entry */
147: #ifdef DEBUG
148: if (debug >= 5)
149: fprintf(ddt,"deleting cache entry\n");
150: #endif
151: rminv(dp);
152: tmp = dp->d_next;
153: (void) free((char *)dp);
154: dp = tmp;
155: if (pdp == NULL)
156: np->n_data = dp;
157: else
158: pdp->d_next = dp;
159: continue;
160: }
161: /* don't put in duplicates */
162: for (i = 0; i < n; i++)
163: if (bcmp((char *)&qp->q_addr[i].sin_addr,
164: dp->d_data, sizeof(struct in_addr)) == 0)
165: goto skip;
166: if (n >= MAXNS)
167: break;
168: qp->q_addr[n].sin_family = AF_INET;
169: qp->q_addr[n].sin_addr = *(struct in_addr *)dp->d_data;
170: qp->q_addr[n].sin_port = (u_short)ns_port;
171: qp->q_nretry[n] = 0;
172: n++;
173: skip: pdp = dp;
174: dp = dp->d_next;
175: }
176: if (n >= MAXNS) {
177: #ifdef DEBUG
178: if (debug >= 5)
179: fprintf(ddt,"q_addr table full\n");
180: #endif
181: break;
182: }
183: }
184: qp->q_naddr = n;
185: return (n - naddr);
186: }
187:
188: /*
189: * Arrange that forwarded query (qp) is retried after t seconds.
190: */
191: schedretry(qp, t)
192: struct qinfo *qp;
193: time_t t;
194: {
195: register struct qinfo *qp1, *qp2;
196:
197: #ifdef DEBUG
198: if (debug > 3) {
199: fprintf(ddt,"schedretry(%#x, %d)\n", qp, t);
200: if (qp->q_time)
201: fprintf(ddt,"WARNING: schedretry(%x,%d) q_time already %d\n", qp->q_time);
202: }
203: #endif
204: t += (u_long) tt.tv_sec;
205: qp->q_time = t;
206:
207: if ((qp1 = retryqp) == NULL) {
208: retryqp = qp;
209: qp->q_next = NULL;
210: return;
211: }
212: while ((qp2 = qp1->q_next) != NULL && qp2->q_time < t)
213: qp1 = qp2;
214: qp1->q_next = qp;
215: qp->q_next = qp2;
216: }
217:
218: /*
219: * Unsched is called to remove a forwarded query entry.
220: */
221: unsched(qp)
222: struct qinfo *qp;
223: {
224: register struct qinfo *np;
225:
226: #ifdef DEBUG
227: if (debug > 3) {
228: fprintf(ddt,"unsched(%#x, %d )\n", qp, qp->q_id);
229: }
230: #endif
231: if( retryqp == qp ) {
232: retryqp = qp->q_next;
233: } else {
234: for( np=retryqp; np->q_next != QINFO_NULL; np = np->q_next ) {
235: if( np->q_next != qp)
236: continue;
237: np->q_next = qp->q_next; /* dequeue */
238: break;
239: }
240: }
241: qp->q_next = QINFO_NULL; /* sanity check */
242: qp->q_time = 0;
243: }
244:
245: /*
246: * Retry is called to retransmit query 'qp'.
247: */
248: retry(qp)
249: register struct qinfo *qp;
250: {
251: register int n;
252: register HEADER *hp;
253:
254: #ifdef DEBUG
255: if (debug > 3)
256: fprintf(ddt,"retry(x%x) id=%d\n", qp, ntohs(qp->q_id));
257: #endif
258:
259: /* try next address */
260: n = qp->q_curaddr;
261: ++qp->q_nretry[n];
262: do {
263: if (++n >= qp->q_naddr)
264: n = 0;
265: if (qp->q_nretry[n] < MAXRETRY)
266: goto found;
267: } while (n != qp->q_curaddr);
268: /*
269: * Give up. Can't reach destination.
270: */
271: #ifdef DEBUG
272: if (debug >= 5)
273: fprintf(ddt,"give up\n");
274: #endif
275: hp = (HEADER *)qp->q_msg;
276: hp->qr = 1;
277: hp->rcode = SERVFAIL;
278: hp->ra = 1;
279: #ifdef DEBUG
280: if (debug >= 10)
281: fp_query(qp->q_msg, ddt);
282: #endif
283: if (sendto(ds, qp->q_msg, qp->q_msglen, 0, &qp->q_from,
284: sizeof(qp->q_from))) {
285: #ifdef DEBUG
286: if (debug)
287: fprintf(ddt,"gave up retry(x%x) id=%d\n",
288: qp, ntohs(qp->q_id));
289: #endif
290: }
291: qremove(qp);
292: return;
293: found:
294: qp->q_curaddr = n;
295: #ifdef DEBUG
296: if (debug)
297: fprintf(ddt,"resend(id=%d n=%d) -> %s (%d)\n",ntohs(qp->q_id),
298: n, inet_ntoa(qp->q_addr[n].sin_addr),
299: ntohs(qp->q_addr[n].sin_port));
300: if ( debug >= 10)
301: fp_query(qp->q_msg, ddt);
302: #endif
303: if (sendto(ds, qp->q_msg, qp->q_msglen, 0, &qp->q_addr[n],
304: sizeof(qp->q_addr[0])) < 0) {
305: #ifdef DEBUG
306: if (debug > 3)
307: fprintf(ddt,"error returning msg\n");
308: #endif
309: }
310: unsched(qp);
311: schedretry(qp, (time_t)RETRYTIME);
312: }
313:
314: qremove(qp)
315: register struct qinfo *qp;
316: {
317: #ifdef DEBUG
318: if(debug > 3)
319: fprintf(ddt,"qremove(x%x)\n", qp);
320: #endif
321: unsched(qp); /* get off queue first */
322: free(qp->q_msg);
323: if (qp->q_cmsg);
324: free(qp->q_cmsg);
325: qfree(qp);
326: }
327:
328: struct qinfo *
329: qfindid(id)
330: register u_short id;
331: {
332: register struct qinfo *qp;
333:
334: #ifdef DEBUG
335: if(debug > 3)
336: fprintf(ddt,"qfindid(%d)\n", ntohs(id));
337: #endif
338: for (qp = qhead; qp!=QINFO_NULL; qp = qp->q_link) {
339: if (qp->q_nsid == id)
340: return(qp);
341: }
342: #ifdef DEBUG
343: if (debug >= 5)
344: fprintf(ddt,"qp not found\n");
345: #endif
346: return(NULL);
347: }
348:
349: struct qinfo *
350: qnew()
351: {
352: register struct qinfo *qp;
353:
354: if ((qp = (struct qinfo *)calloc(1, sizeof(struct qinfo))) == NULL) {
355: #ifdef DEBUG
356: if (debug >= 5)
357: fprintf(ddt,"qnew: calloc error\n");
358: #endif
359: syslog(LOG_ERR, "forw: %m");
360: exit(12);
361: }
362: #ifdef DEBUG
363: if (debug >= 5)
364: fprintf(ddt,"qnew(x%x)\n", qp);
365: #endif
366: qp->q_link = qhead;
367: qhead = qp;
368: return( qp );
369: }
370:
371: qfree(qp)
372: struct qinfo *qp;
373: {
374: register struct qinfo *np;
375:
376: #ifdef DEBUG
377: if(debug > 3)
378: fprintf(ddt,"qfree( x%x )\n", qp);
379: if(debug && qp->q_next)
380: fprintf(ddt,"WARNING: qfree of linked ptr x%x\n", qp);
381: #endif
382: if( qhead == qp ) {
383: qhead = qp->q_link;
384: } else {
385: for( np=qhead; np->q_link != QINFO_NULL; np = np->q_link ) {
386: if( np->q_link != qp ) continue;
387: np->q_link = qp->q_link; /* dequeue */
388: break;
389: }
390: }
391: (void)free((char *)qp);
392: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.