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: }

Defined functions

ns_forw defined in line 29; used 1 times
nslookup defined in line 105; used 3 times
qfindid defined in line 328; used 2 times
qfree defined in line 371; used 3 times
qnew defined in line 349; used 3 times
qremove defined in line 314; used 3 times
retry defined in line 248; used 2 times
schedretry defined in line 191; used 4 times
unsched defined in line 221; used 3 times

Defined variables

nsid defined in line 23; used 1 times
  • in line 71
qhead defined in line 20; used 7 times
retryqp defined in line 21; used 14 times
sccsid defined in line 2; never used
Last modified: 1986-06-04
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1154
Valid CSS Valid XHTML 1.0 Strict