home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / NETWORK / ISP / bind.4.8.3.lzh / BIND483 / NAMED / ns_req.c < prev    next >
Text File  |  1993-08-24  |  32KB  |  1,337 lines

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