# 2.11BSD#431 - /usr/src/usr.sbin/named/named/ns_resp.c

##### Functions

    add_data          X
    check_ns          X
    check_root        X
    delete_all        X
    doupdate          X
    finddata          X
    findns            X
    ns_resp           X
    prime             X
    prime_cache       X
    send_msg          X
    sysquery          X
    wanted            X

##### Variables

    norootlogged      X

##### Macros

    MAXCLASS          X

       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

- in line 554
- in /usr/src/usr.sbin/named/named/ns_req.c line 298

check_ns defined in line 1271; used 1 times

- in line 1265

check_root defined in line 1221; used 1 times

- in line 391

delete_all defined in line 1614; used 5 times

- in line 1324, 1413, 1525
- in /usr/src/usr.sbin/named/named/ns_forw.c line 222
- in /usr/src/usr.sbin/named/named/ns_req.c line 873

doupdate defined in line 716; used 4 times

- in line 125, 370
- in /usr/src/usr.sbin/named/named/ns_maint.c line 376
- in /usr/src/usr.sbin/named/named/ns_req.c line 1200

finddata defined in line 1454; used 2 times

- in line 498
- in /usr/src/usr.sbin/named/named/ns_req.c line 219

findns defined in line 1344; used 3 times

- in line 524, 1139
- in /usr/src/usr.sbin/named/named/ns_req.c line 263

ns_resp defined in line 40; used 1 times

- in /usr/src/usr.sbin/named/named/ns_req.c line 87

prime defined in line 1065; used 1 times

- in line 352

prime_cache defined in line 1084; used 4 times

- in /usr/src/usr.sbin/named/named/ns_main.c line 573
- in /usr/src/usr.sbin/named/named/ns_req.c line 91, 357, 575

send_msg defined in line 1013; used 4 times

- in line 675, 693, 707
- in /usr/src/usr.sbin/named/named/ns_forw.c line 395

sysquery defined in line 1106; used 8 times

- in line 38, 1080, 1097, 1307, 1331
- in /usr/src/usr.sbin/named/named/ns_forw.c line 251
- in /usr/src/usr.sbin/named/named/ns_req.c line 47, 874

wanted defined in line 1538; used 1 times

- in line 1468

#### Defined variables

norootlogged defined in line 1337; used 2 times

- in line 1441-1442(2)

sccsid defined in line 14; never used

#### Defined macros

MAXCLASS defined in line 1336; used 2 times

- in line 1337, 1441

Last modified: 1988-10-22 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 6384 |