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

##### Functions

    InitDynUpdate     X
    addname           X
    doaddauth         X
    doaddinfo         X
    doaxfr            X
    fwritemsg         X
    getname           X
    make_rr           X
    ns_req            X
    printSOAdata      X
    rm_datum          X
    stale             X
    startxfr          X
    writemsg          X

##### Variables

    addcount          X
    addinfo           X
    dnptrs            X
    needs_prime_cache X
    xfr_disabled      X

##### Macros

    FORWARDED         X
    NADDRECS          X

##### struct's

    addinfo           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_req.c	4.32 (Berkeley) 3/31/88";
      15: #endif /* not lint */
      16:
      17: #include <stdio.h>
      18: #include <sys/param.h>
      19: #include <sys/uio.h>
      20: #include <sys/time.h>
      21: #include <sys/socket.h>
      22: #include <netinet/in.h>
      23: #include <syslog.h>
      24: #include <sys/file.h>
      25: #include <arpa/nameser.h>
      26: #include "ns.h"
      27: #include "db.h"
      28:
      29: #define NADDRECS    20
      30:
      31: extern  int debug;
      32: extern  FILE    *ddt;
      33:
      34: struct addinfo {
      35:     char    *a_dname;       /* domain name */
      36:     u_short a_class;        /* class for address */
      37: };
      38:
      39: struct  addinfo addinfo[NADDRECS];  /* additional info records */
      40: int addcount;           /* number of names in addinfo */
      41: int xfr_disabled = 0;       /* set to disable zone xfrs */
      42: int needs_prime_cache = 0;      /* set if we need a priming */
      43:
      44: u_char  *dnptrs[20];        /* ptrs to dnames in message for dn_comp */
      45:
      46: extern time_t retrytime();
      47: extern struct qinfo *sysquery();
      48: extern char *localdomain;   /* XXX */
      49: extern int errno;
      50: /*
      51:  * Process request using database; assemble and send response.
      52:  */
      53: ns_req(msg, msglen, buflen, qsp, from, dfd)
      54:     u_char *msg;
      55:     int msglen, buflen;
      56:     struct qstream *qsp;
      57:     struct sockaddr_in *from;
      58:     int dfd;
      59: {
      60:     register HEADER *hp;
      61:     register u_char *cp;
      62:     struct namebuf *np;
      63:     register struct databuf *dp;
      64:     struct hashbuf *htp;
      65:     struct netinfo *lp;
      66:     char *fname, *answers;
      67:     u_char *eom, *omsg;
      68:     char dnbuf[MAXDNAME], *dname;
      69:     u_char **dpp;
      70:     int n, class, type, count, foundname, founddata, omsglen, cname = 0;
      71:     u_short id;
      72:     struct databuf *nsp[NSMAX];
      73:     struct qinfo *qp;
      74:     extern struct qinfo *qhead;
      75:     extern struct netinfo *local();
      76:     extern int nsid;
      77:
      78: #ifdef DEBUG
      79:     if (debug > 3) {
      80:         fprintf(ddt,"ns_req()\n");
      81:         fp_query(msg, ddt);
      82:     }
      83: #endif
      84:
      85:     hp = (HEADER *) msg;
      86:     if (hp->qr) {
      87:         ns_resp(msg, msglen);
      88:
      89:         /* Now is a safe time for housekeeping */
      90:         if (needs_prime_cache)
      91:             prime_cache();
      92:         return;
      93:     }
      94:
      95:     hp->rcode = NOERROR;
      96:     cp = msg + sizeof(HEADER);
      97:     eom = msg + msglen;
      98:     dpp = dnptrs;
      99:     *dpp++ = msg;
     100:     addcount = 0;
     101:
     102:     switch (hp->opcode) {
     103:     case QUERY:
     104: #ifdef STATS
     105:         stats[S_QUERIES].cnt++;
     106: #endif
     107:         if (ntohs(hp->qdcount) != 1 ||
     108:             hp->ancount || hp->nscount || hp->arcount) {
     109: #ifdef DEBUG
     110:             if (debug)
     111:                 fprintf(ddt,"FORMERR Query header counts wrong\n");
     112: #endif
     113:             hp->qdcount = 0;
     114:             hp->ancount = 0;
     115:             hp->nscount = 0;
     116:             hp->arcount = 0;
     117:             hp->rcode = FORMERR;
     118:             goto finish;
     119:         }
     120:         /*
     121: 		 * Get domain name, class, and type.
     122: 		 */
     123:         if ((*cp & INDIR_MASK) == 0)
     124:             *dpp++ = cp;    /* remember name for compression */
     125:         *dpp = NULL;
     126:         if ((n = dn_expand(msg, eom, cp, dnbuf,
     127:             sizeof(dnbuf))) < 0) {
     128: #ifdef DEBUG
     129:             if (debug)
     130:                 fprintf(ddt,"FORMERR Query expand name failed\n");
     131: #endif
     132:             hp->rcode = FORMERR;
     133:             goto finish;
     134:         }
     135:         cp += n;
     136:         GETSHORT(type, cp);
     137:         GETSHORT(class, cp);
     138:         if (cp > eom) {
     139: #ifdef DEBUG
     140:             if (debug)
     141:                 fprintf(ddt,"FORMERR Query message length short\n");
     142: #endif
     143:             hp->rcode = FORMERR;
     144:             goto finish;
     145:         }
     146: #ifdef DEBUG
     147:         if (cp < eom)
     148:             if (debug > 5)
     149:                 fprintf(ddt,"message length > received message\n");
     150: #endif
     151:
     152: #ifdef STATS
     153:         if ((type > T_ANY) || (type < 0))
     154:             typestats[0]++; /* Bad type */
     155:         else
     156:             typestats[type]++;
     157: #endif
     158:         /*
     159: 		 * Process query.
     160: 		 */
     161:         if (type == T_AXFR) {
     162:             /* refuse request if not a TCP connection */
     163:             if (qsp == QSTREAM_NULL || xfr_disabled) {
     164: #ifdef DEBUG
     165:                 if (debug)
     166:                     fprintf(ddt,"T_AXFR via UDP refused\n");
     167: #endif
     168:                 hp->rcode = REFUSED;
     169:                 goto finish;
     170:             }
     171:             dnptrs[0] = NULL;   /* don't compress names */
     172:             hp->rd = 0;     /* recursion not possible */
     173:         }
     174:         buflen -= msglen;
     175:         count = 0;
     176:         foundname = 0;
     177:         founddata = 0;
     178:         dname = dnbuf;
     179: try_again:
     180: #ifdef DEBUG
     181:         if (debug)
     182:             fprintf(ddt,"req: nlookup(%s) id %d type=%d\n",
     183:                 dname, hp->id, type);
     184: #endif
     185:         htp = hashtab;      /* lookup relative to root */
     186:         if ((np = nlookup(dname, &htp, &fname, 0)) == NULL)
     187:             fname = "";
     188: #ifdef DEBUG
     189:         if (debug)
     190:             fprintf(ddt,"req: %s '%s' as '%s' (cname=%d)\n",
     191:                 np == NULL ? "missed" : "found",
     192:                 dname, fname, cname);
     193: #endif
     194:         /* START XXX */
     195:         /*
     196: 		 * if nlookup failed to find address then
     197: 		 *  see if there are any '.''s in the name
     198: 		 * if not then add local domain name to the
     199: 		 * name and try again.
     200: 		 */
     201:         if (np == NULL && localdomain && index(dname, '.') == NULL) {
     202:             (void) strcat(dname,".");
     203:             (void) strcat(dname, localdomain);
     204: #ifdef DEBUG
     205:             if (debug)
     206:                 fprintf(ddt,"req: nlookup(%s) type=%d\n",
     207:                     dname, type);
     208: #endif
     209:             htp = hashtab;
     210:             np = nlookup(dname, &htp, &fname, 0);
     211:             }
     212:         /* END XXX */
     213:         if (np == NULL || fname != dname)
     214:             goto fetchns;
     215:
     216:         foundname++;
     217:         answers = (char *)cp;
     218:         count = cp - msg;
     219:         n = finddata(np, class, type, hp, &dname, &buflen, &count);
     220:         if (n == 0)
     221:             goto fetchns;       /* NO data available */
     222:         cp += n;
     223:         buflen -= n;
     224:         msglen += n;
     225:         hp->ancount += count;
     226:         if (fname != dname && type != T_CNAME && type != T_ANY) {
     227:             cname++;
     228:             goto try_again;
     229:         }
     230:         founddata = 1;
     231: #ifdef DEBUG
     232:         if (debug >= 3) {
     233:             fprintf(ddt,"req: foundname = %d count = %d ", foundname, count);
     234:             fprintf(ddt,"founddata = %d cname = %d\n",founddata, cname);
     235:         }
     236: #endif
     237:         if ((lp = local(from)) != NULL)
     238:             sort_response(answers, count, lp, cp);
     239:         if (type == T_AXFR) {
     240:             if (founddata) {
     241:                 hp->ancount = htons(hp->ancount);
     242:                 startxfr(qsp, np, msg, cp - msg);
     243:                 return;
     244:             }
     245:             hp->rcode = REFUSED;    /* No go if unauthoritative */
     246:             goto finish;
     247:         }
     248: #ifdef notdef
     249:         /*
     250: 		 * If we found an authoritative answer,
     251: 		 * we're done.
     252: 		 */
     253:         if (hp->aa)
     254:             goto finish;
     255: #endif
     256:
     257: fetchns:
     258:         /*
     259: 	 	 * Look for name servers to refer to and fill in the authority
     260: 	 	 * section or record the address for forwarding the query
     261: 	 	 * (recursion desired).
     262: 	 	 */
     263:         switch (findns(&np, class, nsp, &count)) {
     264:         case NXDOMAIN:
     265:             if (!foundname)
     266:                 hp->rcode = NXDOMAIN;
     267: #ifdef DEBUG
     268:             if (debug >= 3)
     269:                 fprintf(ddt,"req: leaving (%s, rcode %d)\n",
     270:                     dname, hp->rcode);
     271: #endif
     272:             if (class != C_ANY) {
     273:                 hp->aa = 1;
     274:                 /*
     275: 				 * should return SOA if founddata == 0,
     276: 				 * but old named's are confused by an SOA
     277: 				 * in the auth. section if there's no error.
     278: 				 */
     279:                 if (foundname == 0 && np) {
     280:                     n = doaddauth(hp, cp, buflen, np, nsp[0]);
     281:                     cp += n;
     282:                     buflen -= n;
     283:                 }
     284:             }
     285:             goto finish;
     286:
     287:         case SERVFAIL:
     288:             hp->rcode = SERVFAIL;
     289:             goto finish;
     290:         }
     291:
     292:         /*
     293: 		 *  If we successfully found the answer in the cache
     294: 		 *  or this is not a recursive query, then add the
     295: 		 *  nameserver references here and return.
     296: 		 */
     297:         if (founddata || (!hp->rd)) {
     298:             n = add_data(np, nsp, cp, buflen);
     299:             if (n < 0) {
     300:                 hp->tc = 1;
     301:                 n = (-n);
     302:             }
     303:             cp += n;
     304:             buflen -= n;
     305:             hp->nscount = htons((u_short)count);
     306:             goto finish;
     307:         }
     308:
     309:         /*
     310: 		 *  At this point, we don't have the answer, but we do
     311: 		 *  have some NS's to try.  If the user would like us
     312: 		 *  to recurse, create the initial query.  If a cname
     313: 		 *  is involved, we need to build a new query and save
     314: 		 *  the old one in cmsg/cmsglen.
     315: 		 */
     316:         if (cname) {
     317:             omsg = (u_char *)malloc((unsigned)msglen);
     318:             if (omsg == (u_char *)NULL) {
     319: #ifdef DEBUG
     320:                 if (debug)
     321:                         fprintf(ddt,"ns_req: malloc fail\n");
     322: #endif
     323:                 syslog(LOG_ERR, "ns_req: Out Of Memory");
     324:                 hp->rcode = SERVFAIL;
     325:                 break;
     326:             }
     327:             id = hp->id;
     328:             hp->ancount = htons(hp->ancount);
     329:             bcopy(msg, omsg, omsglen = msglen);
     330:             msglen = res_mkquery(QUERY, dname, class, type,
     331:                 (char *)NULL, 0, NULL, msg, msglen+buflen);
     332:         }
     333:         n = ns_forw(nsp, msg, msglen, from, qsp, dfd, &qp);
     334:         if (n != FW_OK && cname)
     335:             free(omsg);
     336:         switch (n) {
     337:         case FW_OK:
     338:             if (cname) {
     339:                 qp->q_cname++;
     340:                 qp->q_cmsg = (char *)omsg;
     341:                 qp->q_cmsglen = omsglen;
     342:                 qp->q_id = id;
     343:             }
     344:             break;
     345:         case FW_DUP:
     346:             break;      /* Duplicate request dropped */
     347:         case FW_NOSERVER:
     348:             if(np)
     349:                 np = np->n_parent;
     350:             goto fetchns;   /* Try again. */
     351:         case FW_SERVFAIL:
     352:             hp->rcode = SERVFAIL;
     353:             goto finish;
     354:         }
     355:         /* Now is a safe time for housekeeping */
     356:         if (needs_prime_cache)
     357:             prime_cache();
     358:         return;
     359:
     360:     case IQUERY: {
     361:         register struct invbuf *ip;
     362:         register int i;
     363:         int dlen, alen;
     364:         char anbuf[PACKETSZ], *data;
     365:
     366: #ifdef STATS
     367:         stats[S_IQUERIES].cnt++;
     368: #endif
     369:         hp->ancount = htons(hp->ancount);
     370:         if (hp->ancount != 1 ||
     371:             hp->qdcount || hp->nscount || hp->arcount) {
     372: #ifdef DEBUG
     373:             if (debug)
     374:                 fprintf(ddt,"FORMERR IQuery header counts wrong\n");
     375: #endif
     376:             hp->qdcount = 0;
     377:             hp->ancount = 0;
     378:             hp->nscount = 0;
     379:             hp->arcount = 0;
     380:             hp->rcode = FORMERR;
     381:             goto finish;
     382:         }
     383:         /*
     384: 		 * Skip domain name, get class, and type.
     385: 		 */
     386:         if ((n = dn_skipname(cp, eom)) < 0) {
     387: #ifdef DEBUG
     388:             if (debug)
     389:                 fprintf(ddt,"FORMERR IQuery packet name problem\n");
     390: #endif
     391:             hp->rcode = FORMERR;
     392:             goto finish;
     393:         }
     394:         cp += n;
     395:         GETSHORT(type, cp);
     396:         GETSHORT(class, cp);
     397:         cp += sizeof(u_long);
     398:         GETSHORT(dlen, cp);
     399:         cp += dlen;
     400:         if (cp != eom) {
     401: #ifdef DEBUG
     402:             if (debug)
     403:                 fprintf(ddt,"FORMERR IQuery message length off\n");
     404: #endif
     405:             hp->rcode = FORMERR;
     406:             goto finish;
     407:         }
     408:         /* not all inverse queries are handled. */
     409:         switch (type) {
     410:         case T_A:
     411:         case T_UID:
     412:         case T_GID:
     413:             break;
     414:
     415:         default:
     416:             hp->rcode = REFUSED;
     417:             goto finish;
     418:         }
     419: #ifdef DEBUG
     420:         if (debug)
     421:             fprintf(ddt,"req: IQuery class %d type %d\n",
     422:                 class, type);
     423: #endif
     424:         fname = (char *)msg + sizeof(HEADER);
     425:         bcopy(fname, anbuf, alen = (char *)cp - fname);
     426:         data = anbuf + alen - dlen;
     427:         cp = (u_char *)fname;
     428:         buflen -= sizeof(HEADER);
     429:         count = 0;
     430:         for (ip = invtab[dhash(data, dlen)]; ip != NULL;
     431:             ip = ip->i_next) {
     432:             for (i = 0; i < INVBLKSZ; i++) {
     433:             if ((np = ip->i_dname[i]) == NULL)
     434:                 break;
     435: #ifdef DEBUG
     436:             if (debug >= 5)
     437:                 fprintf(ddt,"dname = %d\n", np->n_dname);
     438: #endif
     439:             for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
     440:                 if (!match(dp, class, type))
     441:                     continue;
     442:                 if (dp->d_size != dlen ||
     443:                     bcmp(dp->d_data, data, dlen))
     444:                     continue;
     445:                 getname(np, dnbuf, sizeof(dnbuf));
     446: #ifdef DEBUG
     447:                 if (debug > 2)
     448:                     fprintf(ddt,"req: IQuery found %s\n",
     449:                         dnbuf);
     450: #endif
     451:                 buflen -= QFIXEDSZ;
     452:                 if ((n =
     453:                    dn_comp(dnbuf, cp, buflen, (char **)NULL,
     454:                       (char **)NULL)) < 0)
     455:                 {
     456:                     hp->tc = 1;
     457:                     goto finish;
     458:                 }
     459:                 cp += n;
     460:                 PUTSHORT((u_short)dp->d_type, cp);
     461:                 PUTSHORT((u_short)dp->d_class, cp);
     462:                 buflen -= n;
     463:                 count++;
     464:             }
     465:             }
     466:         }
     467: #ifdef DEBUG
     468:         if (debug)
     469:             fprintf(ddt,"req: IQuery %d records\n", count);
     470: #endif
     471:         hp->qdcount = htons((u_short)count);
     472:         if (alen > buflen) {
     473:             hp->tc = 1;
     474:             break;
     475:         }
     476:         bcopy(anbuf, cp, alen);
     477:         cp += alen;
     478:         break;
     479:         }
     480:
     481: #ifdef ALLOW_UPDATES
     482: /*
     483:  * In a sense the following constant should be defined in <arpa/nameser.h>,
     484:  * since it is returned here in place of a response code if the update was
     485:  * forwarded, and the response codes are defined in nameser.h.  On the other
     486:  * hand, though, this constant is only seen in this file.  The assumption
     487:  * here is that none of the other return codes equals this one (a good
     488:  * assumption, since they only occupy 4 bits over-the-wire)
     489:  */
     490: #define FORWARDED 1000
     491:         /* Call InitDynUpdate for all dynamic update requests */
     492:         case UPDATEM:
     493:         case UPDATEMA:
     494:         case UPDATED:
     495:         case UPDATEDA:
     496:         case UPDATEA:
     497:                 n = InitDynUpdate(hp, nsp, msg, msglen, cp, from, qsp, dfd);
     498:                 if (n == FORWARDED)
     499:                         return; /* Return directly because InitDynUpdate
     500:                                  * forwarded the query to the primary, so we
     501:                                  * will send response later
     502:                                  */
     503:                 else
     504:                         break;  /* Either sucessful primary update or failure;
     505:                                  * return response code to client
     506:                                  */
     507: #endif ALLOW_UPDATES
     508:
     509:     case ZONEREF:
     510: #ifdef DEBUG
     511:         if (debug)
     512:             fprintf(ddt,"Refresh Zone\n");
     513: #endif
     514:
     515:     default:
     516: #ifdef DEBUG
     517:         if (debug >= 2)
     518:             fprintf(ddt,"Opcode %d not implemented\n", hp->opcode);
     519: #endif
     520:         hp->qdcount = 0;
     521:         hp->ancount = 0;
     522:         hp->nscount = 0;
     523:         hp->arcount = 0;
     524:         hp->rcode = NOTIMP;
     525:     }
     526: finish:
     527: #ifdef STATS
     528:     switch(hp->rcode) {
     529:     case NOERROR:
     530:         stats[S_RESPOK].cnt++;
     531:         break;
     532:     case FORMERR:
     533:         stats[S_RESPFORMERR].cnt++;
     534:         break;
     535:     default:
     536:         stats[S_RESPFAIL].cnt++;
     537:         break;
     538:     }
     539: #endif
     540:     hp->qr = 1;     /* set Response flag */
     541:     hp->ra = 1;     /* Recursion is Available */
     542:     hp->ancount = htons(hp->ancount);
     543:     if (addcount) {
     544:         n = doaddinfo(hp, cp, buflen);
     545:         cp += n;
     546:         buflen -= n;
     547:     }
     548:
     549: #ifdef DEBUG
     550:     if (debug) {
     551:         fprintf(ddt,"req: answer -> %s %d (%d) id=%d %s\n",
     552:             inet_ntoa(from->sin_addr), dfd, ntohs(from->sin_port),
     553:         ntohs(hp->id), local(from) == NULL ? "Remote" : "Local");
     554:     }
     555:     if (debug >= 10)
     556:         fp_query(msg, ddt);
     557: #endif DEBUG
     558:     if (qsp == QSTREAM_NULL) {
     559:         if (sendto(dfd, msg, cp-msg, 0, (struct sockaddr *)from,
     560:             sizeof(*from))< 0){
     561: #ifdef DEBUG
     562:             if (debug)
     563:                 fprintf(ddt,"error returning msg errno=%d\n",errno);
     564: #endif DEBUG
     565:         }
     566: #ifdef STATS
     567:         stats[S_OUTPKTS].cnt++;
     568: #endif
     569:     } else {
     570:         (void) writemsg(qsp->s_rfd, msg, cp - msg);
     571:         qsp->s_time = tt.tv_sec;
     572:         qsp->s_refcnt--;
     573:     }
     574:     if (needs_prime_cache)
     575:         prime_cache();  /* Now is a safe time */
     576: }
     577:
     578: fwritemsg(rfp, msg, msglen)
     579:     FILE *rfp;
     580:     char *msg;
     581:     int msglen;
     582: {
     583:     u_short len = htons((u_short)msglen);
     584:
     585:     if (fwrite((char *)&len, sizeof(len), 1, rfp) != 1 ||
     586:         fwrite(msg, msglen, 1, rfp) != 1) {
     587: #ifdef DEBUG
     588:         if (debug)
     589:             fprintf(ddt,"fwrite failed %d\n", errno);
     590: #endif
     591:     }
     592:     return;
     593: }
     594:
     595: writemsg(rfd, msg, msglen)
     596:     int rfd;
     597:     char *msg;
     598:     int msglen;
     599: {
     600:     struct iovec iov[2];
     601:     u_short len = htons((u_short)msglen);
     602:
     603:     iov[0].iov_base = (caddr_t)&len;
     604:     iov[0].iov_len = sizeof(len);
     605:     iov[1].iov_base = msg;
     606:     iov[1].iov_len = msglen;
     607:     if (writev(rfd, iov, 2) != sizeof(len) + msglen) {
     608: #ifdef DEBUG
     609:         if (debug)
     610:             fprintf(ddt,"write failed %d\n", errno);
     611: #endif
     612:         return (-1);
     613:     }
     614:     return (0);
     615: }
     616:
     617: /*
     618:  *  Test a datum for validity and return non-zero if it is out of date.
     619:  */
     620: stale(dp)
     621: register struct databuf *dp;
     622: {
     623:     register struct zoneinfo *zp = &zones[dp->d_zone];
     624:
     625:     switch (zp->z_type) {
     626:
     627:     case Z_PRIMARY:
     628:         return (0);
     629:
     630:     case Z_SECONDARY:
     631:         return ((u_long)(tt.tv_sec - zp->z_lastupdate) > zp->z_expire);
     632:
     633:     case Z_CACHE:
     634: #ifdef DEBUG
     635:         if (debug >= 3)
     636:             fprintf(ddt,"stale: ttl %ld %ld (x%x)\n",
     637:                 dp->d_ttl, dp->d_ttl - tt.tv_sec, dp->d_flags);
     638: #endif
     639:         if (dp->d_flags & DB_F_HINT)
     640:             return(0);
     641:         return(dp->d_ttl <= tt.tv_sec);
     642:
     643:     }
     644:     /* NOTREACHED */
     645: }
     646:
     647: /*
     648:  * Copy databuf into a resource record for replies.
     649:  * Return size of RR if OK, -1 if buffer is full.
     650:  */
     651: make_rr(name, dp, buf, buflen, doadd)
     652:     char *name;
     653:     register struct databuf *dp;
     654:     char *buf;
     655:     int buflen, doadd;
     656: {
     657:     register char *cp;
     658:     char *cp1, *sp;
     659:     struct zoneinfo *zp;
     660:     register long n;
     661:     register long ttl;
     662:     u_char **edp = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);
     663:
     664: #ifdef DEBUG
     665:     if (debug >= 5)
     666:         fprintf(ddt,"make_rr(%s, %x, %x, %d, %d) %d zone %d ttl %ld\n",
     667:             name, dp, buf,
     668:             buflen, doadd, dp->d_size, dp->d_zone, dp->d_ttl);
     669: #endif
     670:
     671:     zp = &zones[dp->d_zone];
     672:     /* check for outdated RR before updating dnptrs by dn_comp() */
     673:     if (zp->z_type == Z_CACHE) {
     674:         ttl = dp->d_ttl - (u_long) tt.tv_sec;
     675:         if ((dp->d_flags & DB_F_HINT) || (ttl <= 0)) {
     676: #ifdef DEBUG
     677: /*XXX*/if (debug >= 3) fprintf(ddt,"make_rr: %ld=>1, x%x\n", ttl, dp->d_flags);
     678: #endif
     679:             ttl = 1;
     680:         }
     681:     } else {
     682:         ttl = zp->z_minimum;        /* really default */
     683:         if (dp->d_ttl > 0)
     684:             ttl = dp->d_ttl;
     685:         if (zp->z_type == Z_SECONDARY) {
     686:             /*
     687: 			 * Set ttl to value received from primary,
     688: 			 * less time since we verified it (but never
     689: 			 * less than a small positive value).
     690: 			 */
     691:             ttl -= tt.tv_sec - zp->z_lastupdate;
     692:             if (ttl <= 0)
     693:                 ttl = 120;
     694:         }
     695:     }
     696:
     697:     buflen -= RRFIXEDSZ;
     698:     if ((n = dn_comp(name, buf, buflen, (char **)dnptrs, (char **)edp)) < 0)
     699:         return (-1);
     700:     cp = buf + n;
     701:     buflen -= n;
     702:     PUTSHORT((u_short)dp->d_type, cp);
     703:     PUTSHORT((u_short)dp->d_class, cp);
     704:     PUTLONG(ttl, cp);
     705:     sp = cp;
     706:     cp += sizeof(u_short);
     707:     switch (dp->d_type) {
     708:     case T_CNAME:
     709:     case T_MG:
     710:     case T_MR:
     711:     case T_PTR:
     712:         if ((n = dn_comp(dp->d_data, cp, buflen, (char **)dnptrs,
     713:            (char **)edp)) < 0)
     714:             return (-1);
     715:         PUTSHORT((u_short)n, sp);
     716:         cp += n;
     717:         break;
     718:
     719:     case T_MB:
     720:     case T_NS:
     721:         /* Store domain name in answer */
     722:         if ((n = dn_comp(dp->d_data, cp, buflen, (char **)dnptrs,
     723:            (char **)edp)) < 0)
     724:             return (-1);
     725:         PUTSHORT((u_short)n, sp);
     726:         cp += n;
     727:         if (doadd)
     728:             addname(dp->d_data, dp->d_class);
     729:         break;
     730:
     731:     case T_SOA:
     732:     case T_MINFO:
     733:         cp1 = dp->d_data;
     734:         if ((n = dn_comp(cp1, cp, buflen, (char **)dnptrs,
     735:             (char **)edp)) < 0)
     736:             return (-1);
     737:         cp += n;
     738:         buflen -= dp->d_type == T_MINFO ? n : n + 5 * sizeof(u_long);
     739:         cp1 += strlen(cp1) + 1;
     740:         if ((n = dn_comp(cp1, cp, buflen, (char **)dnptrs,
     741:             (char **)edp)) < 0)
     742:             return (-1);
     743:         cp += n;
     744:         if (dp->d_type == T_SOA) {
     745:             cp1 += strlen(cp1) + 1;
     746:             bcopy(cp1, cp,
     747:                (int)(n = dp->d_size - (cp1 - dp->d_data)));
     748:             cp += n;
     749:         }
     750:         n = (u_short)(cp - sp) - sizeof(u_short);
     751:         PUTSHORT((u_short)n, sp);
     752:         break;
     753:
     754:     case T_MX:
     755:         /* cp1 == our data/ cp == data of RR */
     756:         cp1 = dp->d_data;
     757:
     758:         /* copy preference */
     759:         bcopy(cp1,cp,sizeof(u_short));
     760:         cp += sizeof(u_short);
     761:         cp1 += sizeof(u_short);
     762:         buflen -= sizeof(u_short);
     763:
     764:         if ((n = dn_comp(cp1, cp, buflen, (char **)dnptrs,
     765:             (char **)edp)) < 0)
     766:             return(-1);
     767:         cp += n;
     768:
     769:         /* save data length */
     770:         n = (u_short)(cp - sp) - sizeof(u_short);
     771:         PUTSHORT((u_short)n, sp);
     772:         if (doadd)
     773:             addname(cp1, dp->d_class);
     774:         break;
     775:
     776:     default:
     777:         if (dp->d_size > buflen)
     778:             return (-1);
     779:         bcopy(dp->d_data, cp, dp->d_size);
     780:         PUTSHORT((u_short)dp->d_size, sp);
     781:         cp += dp->d_size;
     782:     }
     783:     return (cp - buf);
     784: }
     785:
     786: addname(name, class)
     787: register char   *name;
     788: short   class;
     789: {
     790:     register struct addinfo *ap;
     791:     register int n;
     792:
     793:     for (ap = addinfo, n = addcount; --n >= 0; ap++)
     794:         if (strcasecmp(ap->a_dname, name) == 0)
     795:             return;
     796:     /* add domain name to additional section */
     797:     if (addcount < NADDRECS) {
     798:         addcount++;
     799:         ap->a_dname = name;
     800:         ap->a_class = class;
     801:     }
     802: }
     803:
     804: /*
     805:  * Lookup addresses for names in addinfo and put into the message's
     806:  * additional section.
     807:  */
     808: doaddinfo(hp, msg, msglen)
     809:     HEADER *hp;
     810:     char *msg;
     811:     int msglen;
     812: {
     813:     register struct namebuf *np;
     814:     register struct databuf *dp;
     815:     register struct addinfo *ap;
     816:     register char *cp;
     817:     struct hashbuf *htp;
     818:     char *fname;
     819:     int n, count, foundstale;
     820:
     821: #ifdef DEBUG
     822:     if (debug >= 3)
     823:         fprintf(ddt,"doaddinfo() addcount = %d\n", addcount);
     824: #endif
     825:
     826:     count = 0;
     827:     cp = msg;
     828:     for (ap = addinfo; --addcount >= 0; ap++) {
     829: #ifdef DEBUG
     830:         if (debug >= 3)
     831:             fprintf(ddt,"do additional '%s'\n", ap->a_dname);
     832: #endif
     833:         htp = hashtab;  /* because "nlookup" stomps on arg. */
     834:         np = nlookup(ap->a_dname, &htp, &fname, 0);
     835:         if (np == NULL || fname != ap->a_dname)
     836:             continue;
     837: #ifdef DEBUG
     838:         if (debug >= 3)
     839:             fprintf(ddt,"found it\n");
     840: #endif
     841:         foundstale = 0;
     842:         /* look for the data */
     843:         for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
     844:             if (!match(dp, (int)ap->a_class, T_A))
     845:                 continue;
     846:             if (stale(dp)) {
     847:                 foundstale++;
     848: #ifdef DEBUG
     849:                 if (debug)
     850:                     fprintf(ddt,"doaddinfo: stale entry '%s'%s\n",
     851:                         np->n_dname,
     852:                         (dp->d_flags&DB_F_HINT) ? " hint":"" );
     853: #endif
     854:                 continue;
     855:             }
     856:             /*
     857: 			 *  Should be smart and eliminate duplicate
     858: 			 *  data here.	XXX
     859: 			 */
     860:             if ((n = make_rr(ap->a_dname, dp, cp, msglen, 0)) < 0)
     861:                 break;
     862: #ifdef DEBUG
     863:             if (debug >= 5)
     864:                 fprintf(ddt,"addinfo: adding address data n = %d\n",
     865:                    n);
     866: #endif
     867:             cp += n;
     868:             msglen -= n;
     869:             count++;
     870:         }
     871:         if (foundstale) {
     872:             /* Cache invalidate the address RR's */
     873:             delete_all(np, (int)ap->a_class, T_A);
     874:             (void) sysquery(ap->a_dname, (int)ap->a_class, T_A);
     875:         }
     876:     }
     877:     hp->arcount = htons((u_short)count);
     878:     return (cp - msg);
     879: }
     880:
     881: doaddauth(hp, cp, buflen, np, dp)
     882:     register HEADER *hp;
     883:     char *cp;
     884:     int buflen;
     885:     struct namebuf *np;
     886:     struct databuf *dp;
     887: {
     888:     char dnbuf[MAXDNAME];
     889:     int n;
     890:
     891:     getname(np, dnbuf, sizeof(dnbuf));
     892:     if (stale(dp) || (n = make_rr(dnbuf, dp, cp, buflen, 1)) <= 0) {
     893: #ifdef DEBUG
     894:         if (debug)
     895:             fprintf(ddt,"doaddauth: can't add '%s' (%d)\n",
     896:                 dnbuf, buflen);
     897: #endif
     898:         return(0);
     899:     } else {
     900:         hp->nscount = htons(1);
     901:         return(n);
     902:     }
     903: }
     904:
     905:
     906: /*
     907:  * Get the domain name of 'np' and put in 'buf'.  Bounds checking is done.
     908:  */
     909: getname(np, buf, buflen)
     910:     struct namebuf *np;
     911:     char *buf;
     912:     int buflen;
     913: {
     914:     register char *cp;
     915:     register int i;
     916:
     917:     cp = buf;
     918:     while (np != NULL) {
     919:         if ((i = strlen(np->n_dname))+1 >= buflen) {
     920:             *cp = '\0';
     921:             syslog(LOG_ERR, "domain name too long: %s...\n", buf);
     922:             strcpy(buf, "Name_Too_Long");
     923:             return;
     924:         }
     925:         if (cp != buf)
     926:             *cp++ = '.';
     927:         (void) strcpy(cp, np->n_dname);
     928:         cp += i;
     929:         buflen -= (i+1);
     930:         np = np->n_parent;
     931:     }
     932:     *cp = '\0';
     933: }
     934:
     935: /*
     936:  * Do a zone transfer. SOA record already sent.
     937:  */
     938: doaxfr(np, rfp, isroot)
     939:     register struct namebuf *np;
     940:     FILE *rfp;
     941:     int isroot;
     942: {
     943:     register struct databuf *dp;
     944:     register int n;
     945:     struct hashbuf *htp;
     946:     struct databuf *gdp;    /* glue databuf */
     947:     struct namebuf *gnp;    /* glue namebuf */
     948:     struct namebuf **npp, **nppend;
     949:     char msg[PACKETSZ];
     950:     char *cp;
     951:     char *fname;
     952:     char dname[MAXDNAME];
     953:     HEADER *hp = (HEADER *) msg;
     954:     int fndns;
     955:
     956: #ifdef DEBUG
     957:     if (debug && isroot)
     958:         fprintf(ddt,"doaxfr()\n");
     959: #endif
     960:     fndns = 0;
     961:     hp->id = 0;
     962:     hp->opcode = QUERY;
     963:     hp->aa = hp->tc = hp->ra = hp->pr = hp->rd = 0;
     964:     hp->qr = 1;
     965:     hp->rcode = NOERROR;
     966:     hp->qdcount = 0;
     967:     hp->ancount = htons(1);
     968:     hp->nscount = 0;
     969:     hp->arcount = 0;
     970:     cp = msg + sizeof(HEADER);
     971:     getname(np, dname, sizeof(dname));
     972:
     973:     /* first do data records */
     974:     for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
     975:         /*
     976: 		 * Skip the root SOA record (marks end of data);
     977: 		 * don't send SOA for subdomains, as we're not sending them.
     978: 		 */
     979:         if (dp->d_type == T_SOA)
     980:             continue;
     981:         if (dp->d_type == T_NS)
     982:             fndns = 1;
     983:         if (dp->d_zone == 0 || stale(dp))
     984:             continue;
     985:         if ((n = make_rr(dname, dp, cp, sizeof(msg)-sizeof(HEADER), 0)) < 0)
     986:             continue;
     987:         fwritemsg(rfp, msg, n + sizeof(HEADER));
     988:
     989:         if (dp->d_type == T_NS) {
     990:             /*  Glue the sub domains together by sending
     991: 			 *  the address records for the sub domain
     992: 			 *  name servers along.
     993: 			 */
     994:             htp = hashtab;
     995:             cp = msg + sizeof(HEADER);
     996:             gnp = nlookup(dp->d_data, &htp, &fname, 0);
     997:             if (gnp == NULL || fname != dp->d_data)
     998:                 continue;
     999:             for(gdp=gnp->n_data; gdp != NULL; gdp=gdp->d_next) {
    1000:                 if (gdp->d_type != T_A || stale(gdp))
    1001:                 continue;
    1002:                 if ((n = make_rr(fname, gdp, cp,
    1003:                     sizeof(msg)-sizeof(HEADER), 0)) < 0)
    1004:                 continue;
    1005:                 fwritemsg(rfp, msg, n + sizeof(HEADER));
    1006:             }
    1007:         }
    1008:     }
    1009:
    1010:     /* next do subdomains, unless delegated */
    1011:     if ((isroot == 0 && fndns) || np->n_hash == NULL)
    1012:         return;
    1013:     npp = np->n_hash->h_tab;
    1014:     nppend = npp + np->n_hash->h_size;
    1015:     while (npp < nppend) {
    1016:         for (np = *npp++; np != NULL; np = np->n_next) {
    1017:             doaxfr(np, rfp, 0);
    1018:         }
    1019:     }
    1020: #ifdef DEBUG
    1021:     if (debug && isroot)
    1022:         fprintf(ddt,"exit doaxfr()\n");
    1023: #endif
    1024: }
    1025:
    1026: #ifdef ALLOW_UPDATES
    1027: /*
    1028:  * Called by UPDATE{A,D,DA,M,MA} to initiate a dynamic update.  If this is the
    1029:  * primary server for the zone being updated, we update the zone's serial
    1030:  * number and then call doupdate directly. If this is a secondary, we just
    1031:  * forward the update; this way, if the primary update fails (e.g., if the
    1032:  * primary is unavailable), we don't update the secondary; if the primary
    1033:  * update suceeds, ns_resp will get called with the response (when it comes
    1034:  * in), and then update the secondary's copy.
    1035:  */
    1036: InitDynUpdate(hp, nsp, msg, msglen, startcp, from, qsp, dfd)
    1037:     register HEADER *hp;
    1038:     struct databuf *nsp[];
    1039:     char *msg;
    1040:     int msglen;
    1041:     char *startcp;
    1042:     struct sockaddr_in *from;
    1043:     struct qstream *qsp;
    1044:     int dfd;
    1045: {
    1046:     struct zoneinfo *zp;
    1047:     char dnbuf[MAXDNAME];
    1048:     struct hashbuf *htp = hashtab;  /* lookup relative to root */
    1049:     struct namebuf *np;
    1050:     struct databuf *olddp, *newdp, *dp;
    1051:     struct databuf **nspp;
    1052:     char *fname;
    1053:     char *data;
    1054:     register u_char *cp = startcp;
    1055:     short class, type;
    1056:     int n, size, zonenum;
    1057:     char ZoneName[MAXDNAME], *znp;
    1058:
    1059:     if ((n = dn_expand(msg, msg + msglen, cp, dnbuf, sizeof(dnbuf))) < 0) {
    1060: #ifdef DEBUG
    1061:         if (debug)
    1062:             fprintf(ddt,"FORMERR InitDynUpdate expand name failed\n");
    1063: #endif
    1064:         hp->rcode = FORMERR;
    1065:         return(FORMERR);
    1066:     }
    1067:     cp += n;
    1068:     GETSHORT(type, cp);
    1069:     if (type == T_SOA) {    /* T_SOA updates not allowed */
    1070:         hp->rcode = REFUSED;
    1071: #ifdef DEBUG
    1072:         if (debug)
    1073:             fprintf(ddt, "InitDynUpdate: REFUSED - SOA update\n");
    1074: #endif
    1075:         return(REFUSED);
    1076:     }
    1077:     GETSHORT(class, cp);
    1078:     cp += sizeof(u_long);
    1079:     GETSHORT(size, cp);
    1080:     data = cp;
    1081: /****XXX - need bounds checking here ****/
    1082:     cp += size;
    1083:
    1084:     if ((zonenum = findzone(dnbuf, class)) == 0) {  /* zone not found */
    1085:         hp->rcode = NXDOMAIN;
    1086:         return(NXDOMAIN);
    1087:     }
    1088:     zp = &zones[zonenum];
    1089:
    1090:     /* Disallow updates for which we aren't authoratative.  Note: the
    1091: 	   following test doesn't work right:  If it's for a non-local zone,
    1092: 	   we will think it's a primary but be unable to lookup the namebuf,
    1093: 	   thus returning 'NXDOMAIN' */
    1094:     if (zp->z_type != Z_PRIMARY && zp->z_type != Z_SECONDARY) {
    1095:         hp->rcode = REFUSED;
    1096: #ifdef DEBUG
    1097:         if (debug)
    1098:             fprintf(ddt, "InitDynUpdate: REFUSED - non-primary, non-sedondary update\n");
    1099: #endif
    1100:         return(REFUSED);
    1101:     }
    1102:
    1103:     /*
    1104: 	 * Lookup the zone namebuf.  Lookup "xyz" not "xyz.", since
    1105: 	 * otherwise the lookup fails, because '.' may have a nil n_hash
    1106: 	 * associated with it.
    1107: 	 */
    1108:     strcpy(ZoneName, zp->z_origin);
    1109:     znp = &ZoneName[strlen(ZoneName) - 1];
    1110:     if (*znp == '.')
    1111:         *znp = NULL;
    1112:     np = nlookup(ZoneName, &htp, &fname, 0);
    1113:     if ((np == NULL) || (fname != ZoneName)) {
    1114: #ifdef DEBUG
    1115:         if (debug)
    1116:             fprintf(ddt, "InitDynUpdate: lookup failed on zone (%s)\n",
    1117:                 ZoneName);
    1118: #endif DEBUG
    1119:             syslog(LOG_ERR, "InitDynUpdate: lookup failed on zone (%s)\n",
    1120:                ZoneName);
    1121:         hp->rcode = NXDOMAIN;
    1122:         return(NXDOMAIN);
    1123:     }
    1124:
    1125:     /*
    1126: 	 * If this is the primary copy increment the serial number.  Don't
    1127: 	 * increment the serial number if this is a secondary; this way, if 2
    1128: 	 * different secondaries both update the primary, they will both have
    1129: 	 * lower serial numbers than the primary has, and hence eventually
    1130: 	 * refresh and get all updates and become consistent.
    1131: 	 *
    1132: 	 * Note that the serial number must be incremented in both the zone
    1133: 	 * data structure and the zone's namebuf.
    1134: 	 */
    1135:     switch (zp->z_type) {
    1136:     case Z_SECONDARY:       /* forward update to primary */
    1137:         nspp = nsp;
    1138:         dp = np->n_data;
    1139:         while (dp != NULL) {
    1140:             if (match(dp, class, T_NS)) {
    1141:                 if (nspp < &nsp[NSMAX-1])
    1142:                     *nspp++ = dp;
    1143:                 else
    1144:                     break;
    1145:             }
    1146:             dp = dp->d_next;
    1147:         }
    1148:         *nspp = NULL; /* Delimiter */
    1149:         if (ns_forw(nsp, msg, msglen, from, qsp, dfd, NULL) < 0) {
    1150:             hp->rcode = SERVFAIL;
    1151:             return(SERVFAIL);
    1152:         }
    1153:         return(FORWARDED);
    1154:
    1155:     case Z_PRIMARY:
    1156:         zp->z_serial++;
    1157:         olddp = np->n_data; /* old databuf */
    1158:         /* Find the SOA record */
    1159:         for (olddp = np->n_data; olddp != NULL; olddp = olddp->d_next)
    1160:             if (match(olddp, class, T_SOA))
    1161:                 break;
    1162:         if (olddp == NULL) {
    1163: #ifdef DEBUG
    1164:             if (debug)
    1165:                 fprintf(ddt,"InitDynUpdate: Couldn't find SOA record for '%s'\n",
    1166:                         ZoneName);
    1167: #endif DEBUG
    1168:             syslog(LOG_ERR,
    1169:                "InitDynUpdate: Couldn't find SOA record for '%s'\n"
    1170: ,
    1171:                ZoneName);
    1172:             hp->rcode = NXDOMAIN;
    1173:             return(NXDOMAIN);
    1174:         }
    1175:         newdp = savedata(olddp->d_class, olddp->d_type, olddp->d_ttl,
    1176:                  olddp->d_data, olddp->d_size);
    1177:         newdp->d_zone = olddp->d_zone;
    1178:         cp = newdp->d_data;
    1179:         cp += strlen(cp) + 1; /* skip origin string */
    1180:         cp += strlen(cp) + 1; /* skip in-charge string */
    1181:         putlong((u_long)(zp->z_serial), cp);
    1182: #ifdef DEBUG
    1183:         if (debug >= 4) {
    1184:             fprintf(ddt, "after stuffing data into newdp:\n");
    1185:             printSOAdata(newdp);
    1186:         }
    1187: #endif DEBUG
    1188:
    1189:         if ((n = db_update(ZoneName, olddp, newdp, DB_DELETE,
    1190:                    hashtab)) != NOERROR) {
    1191: #ifdef DEBUG
    1192:             if (debug)
    1193:                 fprintf(ddt,"InitDynUpdate: SOA update failed\n");
    1194: #endif DEBUG
    1195:             hp->rcode = NOCHANGE;
    1196:             return(NOCHANGE);
    1197:         }
    1198:
    1199:         /* Now update the RR itself */
    1200:         if (doupdate(msg, msglen, msg + sizeof(HEADER),
    1201:                  zonenum, (struct databuf *)0, DB_NODATA) < 0) {
    1202: #ifdef DEBUG
    1203:             if (debug)
    1204:                 fprintf(ddt,"InitDynUpdate: doupdate failed\n");
    1205: #endif DEBUG
    1206:             /* doupdate fills in rcode */
    1207:             return(hp->rcode);
    1208:         }
    1209:         zp->hasChanged++;
    1210:         return(NOERROR);
    1211:     }
    1212: }
    1213:
    1214: #ifdef DEBUG
    1215: /*
    1216:  * Print the contents of the data in databuf pointed to by dp for an SOA record
    1217:  */
    1218: printSOAdata(dp)
    1219:     struct databuf *dp;
    1220: {
    1221:     register u_char *cp;
    1222:
    1223:     if (!debug)
    1224:         return;  /* Otherwise fprintf to ddt will bomb */
    1225:     cp = dp->d_data;
    1226:     fprintf(ddt, "printSOAdata(%x): origin(%x)='%s'\n", dp, cp, cp);
    1227:     cp += strlen(cp) + 1; /* skip origin string */
    1228:     fprintf(ddt, "printSOAdata: in-charge(%x)='%s'\n", cp, cp);
    1229:     cp += strlen(cp) + 1; /* skip in-charge string */
    1230:     fprintf(ddt, "printSOAdata: serial(%x)=%ld\n", cp, _getlong(cp));
    1231: }
    1232: #endif DEBUG
    1233: #endif ALLOW_UPDATES
    1234:
    1235: struct databuf *
    1236: rm_datum(dp, np, pdp)
    1237: register struct databuf *pdp, *dp;
    1238: register struct namebuf *np;
    1239: {
    1240:     register struct databuf *ndp = dp->d_next;
    1241:
    1242: #ifdef DEBUG
    1243:     if (debug > 2)
    1244:         fprintf(ddt, "rm_datum(%x, %x, %x) -> %x\n",
    1245:             dp, np->n_data, pdp, ndp);
    1246: #endif DEBUG
    1247:     if (pdp == NULL)
    1248:         np->n_data = ndp;
    1249:     else
    1250:         pdp->d_next = ndp;
    1251:     rminv(dp);
    1252:     (void) free((char *)dp);
    1253:     return(ndp);
    1254: }
    1255:
    1256: startxfr(qsp, np, msg, msglen)
    1257:     struct qstream *qsp;
    1258:     struct namebuf *np;
    1259:     char    *msg;
    1260:     int msglen;
    1261: {
    1262:     register FILE *rfp;
    1263:     int fdstat;
    1264:
    1265: #ifdef DEBUG
    1266:     if (debug >= 5)
    1267:         fprintf(ddt,"startxfr()\n");
    1268: #endif
    1269:     /*
    1270: 	 * child does the work while
    1271: 	 * the parent continues
    1272: 	 */
    1273:     if (fork() == 0) {
    1274: #ifdef DEBUG
    1275:         if (debug >= 5)
    1276:             fprintf(ddt,"startxfr: child pid %d\n", getpid());
    1277: #endif
    1278:         rfp = fdopen(qsp->s_rfd, "w");
    1279:         setproctitle("zone XFR to", qsp->s_rfd);
    1280:         fdstat = fcntl(qsp->s_rfd, F_GETFL, 0);
    1281:         if (fdstat != -1)
    1282:             (void) fcntl(qsp->s_rfd, F_SETFL, fdstat & ~FNDELAY);
    1283:         fwritemsg(rfp, msg, msglen);
    1284:         doaxfr(np, rfp, 1);
    1285:         fwritemsg(rfp, msg, msglen);
    1286:         (void) fflush(rfp);
    1287:         exit(0);
    1288:     }
    1289:     qsp->s_time = tt.tv_sec;
    1290:     qsp->s_refcnt--;
    1291: }

#### Defined functions

InitDynUpdate defined in line 1036; used 1 times

- in line 497

addname defined in line 786; used 2 times

- in line 728, 773

doaddauth defined in line 881; used 2 times

- in line 280
- in /usr/src/usr.sbin/named/named/ns_resp.c line 541

doaddinfo defined in line 808; used 2 times

- in line 544
- in /usr/src/usr.sbin/named/named/ns_resp.c line 684

doaxfr defined in line 938; used 2 times

- in line 1017, 1284

fwritemsg defined in line 578; used 4 times

- in line 987, 1005, 1283-1285(2)

getname defined in line 909; used 5 times

- in line 445, 891, 971
- in /usr/src/usr.sbin/named/named/db_dump.c line 512
- in /usr/src/usr.sbin/named/named/ns_resp.c line 1595

make_rr defined in line 651; used 6 times

- in line 860, 892, 985, 1002
- in /usr/src/usr.sbin/named/named/ns_resp.c line 1496, 1599

ns_req defined in line 53; used 2 times

- in /usr/src/usr.sbin/named/named/ns_main.c line 687, 852

printSOAdata defined in line 1218; used 1 times

- in line 1185

rm_datum defined in line 1235; used 6 times

- in /usr/src/usr.sbin/named/named/db.h line 105
- in /usr/src/usr.sbin/named/named/db_update.c line 147
- in /usr/src/usr.sbin/named/named/ns_maint.c line 505, 615
- in /usr/src/usr.sbin/named/named/ns_resp.c line 1258, 1630

stale defined in line 620; used 6 times

- in line 846, 892, 983, 1000
- in /usr/src/usr.sbin/named/named/ns_resp.c line 1478, 1597

startxfr defined in line 1256; used 1 times

- in line 242

writemsg defined in line 595; used 5 times

- in line 570
- in /usr/src/usr.sbin/named/named/ns_main.c line 836
- in /usr/src/usr.sbin/named/named/ns_maint.c line 183, 311
- in /usr/src/usr.sbin/named/named/ns_resp.c line 1058

#### Defined variables

addcount defined in line 40; used 7 times

- in line 100, 543, 793-798(3), 823-828(2)

addinfo defined in line 39; used 2 times

- in line 793, 828

dnptrs defined in line 44; used 14 times

- in line 98, 171, 662(3), 698, 712, 722, 734, 740, 764
- in /usr/src/usr.sbin/named/named/ns_resp.c line 258, 463-464(2)

needs_prime_cache defined in line 42; used 5 times

- in line 90, 356, 574
- in /usr/src/usr.sbin/named/named/ns_resp.c line 1102, 1358

sccsid defined in line 14; never used
xfr_disabled defined in line 41; used 1 times

- in line 163

#### Defined struct's

addinfo defined in line 34; used 6 times

- in line 39(2), 790(2), 815(2)

#### Defined macros

FORWARDED defined in line 490; used 2 times

- in line 498, 1153

NADDRECS defined in line 29; used 2 times

- in line 39, 797

Last modified: 1988-09-05 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 4456 |