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

Defined functions

add_data defined in line 1585; used 2 times
check_ns defined in line 1271; used 1 times
check_root defined in line 1221; used 1 times
finddata defined in line 1454; used 2 times
findns defined in line 1344; used 3 times
ns_resp defined in line 40; used 1 times
prime defined in line 1065; used 1 times
send_msg defined in line 1013; used 4 times
wanted defined in line 1538; used 1 times

Defined variables

norootlogged defined in line 1337; used 2 times
sccsid defined in line 14; never used

Defined macros

MAXCLASS defined in line 1336; used 2 times
Last modified: 1988-10-22
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 9531
Valid CSS Valid XHTML 1.0 Strict