home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.sbin / named / xfer / named-xfer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-25  |  27.6 KB  |  1,232 lines

  1. /*-
  2.  * Copyright (c) 1988, 1990 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  * The original version of xfer by Kevin Dunlap.
  34.  * Completed and integrated with named by David Waitzman
  35.  *    (dwaitzman@bbn.com) 3/14/88.
  36.  * Modified by M. Karels and O. Kure 10-88.
  37.  */
  38.  
  39. #ifndef lint
  40. char copyright[] =
  41. "@(#) Copyright (c) 1988, 1990 The Regents of the University of California.\n\
  42.  All rights reserved.\n";
  43. #endif /* not lint */
  44.  
  45. #ifndef lint
  46. static char sccsid[] = "@(#)named-xfer.c    4.18 (Berkeley) 3/7/91";
  47. #endif /* not lint */
  48.  
  49. #include <sys/param.h>
  50. #include <sys/file.h>
  51. #include <sys/time.h>
  52. #include <sys/stat.h>
  53. #include <sys/socket.h>
  54. #include <sys/uio.h>
  55. #include <sys/signal.h>
  56.  
  57. #include <netinet/in.h>
  58. #include <net/if.h>
  59. #include <netdb.h>
  60. #include <arpa/inet.h>
  61. #include <arpa/nameser.h>
  62.  
  63. #include <errno.h>
  64. #include <resolv.h>
  65. #include <string.h>
  66. #include <stdio.h>
  67. #include <syslog.h>
  68.  
  69. #define XFER            /* modifies the ns.h include file */
  70. #include "ns.h"
  71. #include "pathnames.h"
  72.  
  73. char    *savestr();
  74.  
  75. /* max length of data in RR data field */
  76. #define MAXDATA        2048    /* from db.h */
  77.  
  78. int    debug = 0; 
  79. int    quiet = 0;
  80. int    read_interrupted = 0;
  81. struct    zoneinfo zones;        /* zone information */
  82. struct    timeval    tt;
  83.  
  84. static    char ddtfilename[] = _PATH_TMPXFER;
  85. static    char *ddtfile = ddtfilename;
  86. static    char *tmpname;
  87. FILE    *fp = 0, *ddt, *dbfp;
  88. char    *domain;            /* domain being xfered */
  89. int    domain_len;            /* strlen(domain) */
  90.  
  91. extern    int errno;
  92.  
  93. main(argc, argv)
  94.     int argc;
  95.     char *argv[];
  96. {
  97.     register struct zoneinfo *zp;
  98.     register struct hostent *hp;
  99.      char *dbfile = NULL, *tracefile = NULL, *tm = NULL;
  100.     int dbfd, ddtd, result, c;
  101.     u_long serial_no = 0;
  102.     extern char *optarg;
  103.     extern int optind, getopt();
  104.     u_short port = htons(NAMESERVER_PORT);
  105.  
  106.     (void) umask(022);
  107. #ifdef LOG_DAEMON
  108.     openlog("named-xfer", LOG_PID|LOG_CONS, LOG_DAEMON);
  109. #else
  110.     openlog("named-xfer", LOG_PID);
  111. #endif
  112.     while ((c = getopt(argc, argv, "d:l:s:t:z:f:p:P:q")) != EOF)
  113.         switch (c) {
  114.         case 'd':
  115.             debug = atoi(optarg);
  116.             break;
  117.         case 'l':
  118.             ddtfile = (char *)malloc(strlen(optarg) +
  119.                 sizeof(".XXXXXX") + 1);
  120.             (void) strcpy(ddtfile, optarg);
  121.             (void) strcat(ddtfile, ".XXXXXX");
  122.             break;
  123.         case 's':
  124.             serial_no = (u_long) atol(optarg);
  125.             break;
  126.         case 't':
  127.             tracefile = optarg;
  128.             break;
  129.         case 'z':        /* zone == domain */
  130.             domain = optarg;
  131.             domain_len = strlen(domain);
  132.             break;
  133.         case 'f':
  134.             dbfile = optarg;
  135.             tmpname = (char *)malloc((unsigned)strlen(optarg) +
  136.                 sizeof(".XXXXXX") + 1);
  137.             (void) strcpy(tmpname, optarg);
  138.             break;
  139.         case 'p':
  140.             port = htons((u_short)atoi(optarg));
  141.             break;
  142.         case 'P':
  143.             port = (u_short)atoi(optarg);
  144.             break;
  145.         case 'q':
  146.             quiet++;
  147.             break;
  148.         case '?':
  149.         default:
  150.             usage();
  151.             /* NOTREACHED */
  152.         }
  153.  
  154.     if (!domain || !dbfile || optind >= argc) {
  155.         usage();
  156.         /* NOTREACHED */
  157.     }        
  158.     if (tracefile && (fp = fopen(tracefile, "w")) == NULL)
  159.         perror(tracefile);
  160.     (void) strcat(tmpname, ".XXXXXX");
  161.     /* tmpname is now something like "/etc/named/named.bu.db.XXXXXX" */
  162.     if ((dbfd = mkstemp(tmpname)) == -1) {
  163.         perror(tmpname);
  164.         if (!quiet)
  165.             syslog(LOG_ERR, "can't make tmpfile (%s): %m\n",
  166.                 tmpname);
  167.         exit(XFER_FAIL);
  168.     }
  169.     if (fchmod(dbfd, 0644) == -1) {
  170.         perror(tmpname);
  171.         if (!quiet)
  172.             syslog(LOG_ERR, "can't fchmod tmpfile (%s): %m\n",
  173.                 tmpname);
  174.         exit(XFER_FAIL);
  175.     }
  176.     if ((dbfp = fdopen(dbfd, "r+")) == NULL) {
  177.         perror(tmpname);
  178.         if (!quiet)
  179.             syslog(LOG_ERR, "can't fdopen tmpfile (%s)", tmpname);
  180.         exit(XFER_FAIL);
  181.     }
  182. #ifdef DEBUG
  183.     if (debug) {
  184.         /* ddtfile is now something like "/usr/tmp/xfer.ddt.XXXXXX" */
  185.         if ((ddtd = mkstemp(ddtfile)) == -1) {
  186.             perror(ddtfile);
  187.             debug = 0;
  188.         } else if (fchmod(ddtd, 0644) == -1) {
  189.             perror(ddtfile);
  190.             debug = 0;
  191.         } else if ((ddt = fdopen(ddtd, "w")) == NULL) {
  192.             perror(ddtfile);
  193.             debug = 0;
  194.         } else {
  195. #if defined(SYSV)
  196.             setvbuf(ddt, NULL, _IOLBF, BUFSIZ);
  197. #else
  198.             setlinebuf(ddt);
  199. #endif
  200.         }
  201.     }
  202. #endif
  203.     /*
  204.      * Ignore many types of signals that named (assumed to be our parent)
  205.      * considers important- if not, the user controlling named with
  206.      * signals usually kills us.
  207.      */
  208.     (void) signal(SIGHUP, SIG_IGN);
  209.     (void) signal(SIGSYS, SIG_IGN);
  210.     if (debug == 0) {
  211.         (void) signal(SIGINT, SIG_IGN);
  212.         (void) signal(SIGQUIT, SIG_IGN);
  213.     }
  214.     (void) signal(SIGIOT, SIG_IGN);
  215.  
  216. #if defined(SIGUSR1) && defined(SIGUSR2)
  217.     (void) signal(SIGUSR1, SIG_IGN);
  218.     (void) signal(SIGUSR2, SIG_IGN);
  219. #else    SIGUSR1&&SIGUSR2
  220.     (void) signal(SIGEMT, SIG_IGN);
  221.     (void) signal(SIGFPE, SIG_IGN);
  222. #endif SIGUSR1&&SIGUSR2
  223.  
  224. #ifdef DEBUG
  225.     if (debug) (void)fprintf(ddt, "domain `%s' file `%s' ser no %lu \n", 
  226.           domain, dbfile,serial_no);
  227. #endif
  228.     buildservicelist();
  229.     buildprotolist();
  230.  
  231.     /* init zone data */
  232.  
  233.     zp = &zones;
  234.     zp->z_type = Z_SECONDARY;
  235.     zp->z_origin = domain;
  236.     zp->z_source = dbfile;
  237.     zp->z_addrcnt = 0;
  238. #ifdef DEBUG
  239.     if (debug) {
  240.         (void)fprintf(ddt,"zone found (%d): ", zp->z_type);
  241.         if (zp->z_origin[0] == '\0')
  242.             (void)fprintf(ddt,"'.'");
  243.         else
  244.             (void)fprintf(ddt,"'%s'", zp->z_origin);
  245.         (void)fprintf(ddt,", source = %s\n", zp->z_source);
  246.     }
  247. #endif
  248.     for (; optind != argc; optind++,zp->z_addrcnt++) {
  249.         tm = argv[optind];
  250.         zp->z_addr[zp->z_addrcnt].s_addr = inet_addr(tm);
  251.  
  252.         if (zp->z_addr[zp->z_addrcnt].s_addr == (unsigned)-1) {
  253.             hp = gethostbyname(tm);
  254.             if (hp == NULL) {
  255.                 syslog(LOG_ERR, "uninterpretable server %s\n",
  256.                     tm);
  257.                 continue;
  258.             }
  259.             bcopy(hp->h_addr,
  260.                 (char *)&zp->z_addr[zp->z_addrcnt].s_addr,
  261.                 sizeof(zp->z_addr[zp->z_addrcnt].s_addr));
  262. #ifdef DEBUG
  263.             if (debug)
  264.                 (void)fprintf(ddt,", %s",tm);
  265. #endif
  266.         }
  267.         if (zp->z_addrcnt >= NSMAX) {
  268.             zp->z_addrcnt = NSMAX;
  269. #ifdef DEBUG
  270.             if (debug)
  271.                 (void)fprintf(ddt, "\nns.h NSMAX reached\n");
  272. #endif
  273.             break;
  274.         }
  275.     }
  276. #ifdef DEBUG
  277.     if (debug) (void)fprintf(ddt," (addrcnt) = %d\n", zp->z_addrcnt);
  278. #endif
  279.  
  280.     _res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE);
  281.     result = getzone(zp, serial_no, port);
  282.     (void) fclose(dbfp);
  283.     switch (result) {
  284.  
  285.     case XFER_SUCCESS:            /* ok exit */
  286.         if (rename(tmpname, dbfile) == -1) {
  287.             perror("rename");
  288.             if (!quiet)
  289.                 syslog(LOG_ERR, "rename %s to %s: %m",
  290.                 tmpname, dbfile);
  291.             exit(XFER_FAIL);
  292.         }
  293.         exit(XFER_SUCCESS);
  294.  
  295.     case XFER_UPTODATE:        /* the zone was already uptodate */
  296.         (void) unlink(tmpname);
  297.         exit(XFER_UPTODATE);
  298.  
  299.     case XFER_TIMEOUT:
  300. #ifdef DEBUG
  301.         if (!debug)
  302. #endif
  303.             (void) unlink(tmpname);
  304.         exit(XFER_TIMEOUT);        /* servers not reachable exit */
  305.  
  306.     case XFER_FAIL:
  307.     default:
  308. #ifdef DEBUG
  309.         if (!debug)
  310. #endif
  311.             (void) unlink(tmpname);
  312.         exit(XFER_FAIL);        /* yuck exit */
  313.     }
  314. }
  315.  
  316. usage()
  317. {
  318.     (void)fprintf(stderr,
  319. "Usage: xfer\n\
  320. \t-z zone_to_transfer\n\
  321. \t-f db_file\n\
  322. \t-s serial_no\n\
  323. \t[-d debug_level]\n\
  324. \t[-l debug_log_file (default %s)]\n\
  325. \t[-t trace_file]\n\
  326. \t[-p port]\n\
  327. \tservers...\n", ddtfile);
  328.     exit(XFER_FAIL);
  329. }
  330.  
  331. int    minimum_ttl = 0, got_soa = 0;
  332. char    prev_origin[MAXDNAME];
  333. char    prev_dname[MAXDNAME];
  334.  
  335. getzone(zp, serial_no, port)
  336.     struct zoneinfo *zp;
  337.     u_long serial_no;
  338.     u_short port;
  339. {
  340.     HEADER *hp;
  341.     u_short len;
  342.     u_long serial;
  343.     int s, n, l, cnt, soacnt, error = 0;
  344.      u_char *cp, *nmp, *eom, *tmp ;
  345.     u_char *buf = NULL;
  346.     int bufsize;
  347.     u_char name[MAXDNAME], name2[MAXDNAME];
  348.     struct sockaddr_in sin;
  349.     struct zoneinfo zp_start, zp_finish;
  350.     struct itimerval ival, zeroival;
  351.     extern SIG_FN read_alarm();
  352.     struct sigvec sv, osv;
  353.     int ancount, aucount;
  354. #ifdef DEBUG
  355.     if (debug)
  356.         (void)fprintf(ddt,"getzone() %s\n", zp->z_origin);
  357. #endif
  358.     bzero((char *)&zeroival, sizeof(zeroival));
  359.     ival = zeroival;
  360.     ival.it_value.tv_sec = 120;
  361.     sv.sv_handler = read_alarm;
  362.     sv.sv_onstack = 0;
  363.     sv.sv_mask = ~0;
  364.     (void) sigvec(SIGALRM, &sv, &osv);
  365.  
  366.     strcpy(prev_origin, zp->z_origin);
  367.  
  368.     for (cnt = 0; cnt < zp->z_addrcnt; cnt++) {
  369.         error = 0;
  370.         if (buf == NULL) {
  371.             if ((buf = (u_char *)malloc(2 * PACKETSZ)) == NULL) {
  372.                 syslog(LOG_ERR, "malloc(%u) failed",
  373.                     2 * PACKETSZ);
  374.                 error++;
  375.                 break;
  376.             }
  377.             bufsize = 2 * PACKETSZ;
  378.         }
  379.         bzero((char *)&sin, sizeof(sin));
  380.         sin.sin_family = AF_INET;
  381.         sin.sin_port = port;
  382.         sin.sin_addr = zp->z_addr[cnt];
  383.         if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  384.             syslog(LOG_ERR, "socket: %m");
  385.             error++;
  386.             break;
  387.         }    
  388. #ifdef DEBUG
  389.         if (debug >= 2) {
  390.             (void)fprintf(ddt,"connecting to server #%d %s, %d\n",
  391.                cnt+1, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
  392.         }
  393. #endif
  394.         if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
  395.             (void) close(s);
  396.             error++;
  397. #ifdef DEBUG
  398.             if (debug >= 2)
  399.                 (void)fprintf(ddt, "connect failed, %s\n",
  400.                     strerror(errno));
  401. #endif
  402.             continue;
  403.         }    
  404.         if ((n = res_mkquery(QUERY, zp->z_origin, C_IN,
  405.             T_SOA, (char *)NULL, 0, NULL, (char *)buf, bufsize)) < 0) {
  406.             if (!quiet)
  407.                 syslog(LOG_ERR, "zone %s: res_mkquery T_SOA failed",
  408.                 zp->z_origin);
  409.             (void) close(s);
  410.             (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
  411.             return XFER_FAIL;
  412.         }
  413.         /*
  414.          * Send length & message for zone transfer
  415.          */
  416.         if (writemsg(s, buf, n) < 0) {
  417.             (void) close(s);
  418.             error++;
  419. #ifdef DEBUG
  420.             if (debug >= 2)
  421.                 (void)fprintf(ddt,"writemsg failed\n");
  422. #endif
  423.             continue;    
  424.         }
  425.         /*
  426.          * Get out your butterfly net and catch the SOA
  427.          */
  428.         cp = buf;
  429.         l = sizeof(u_short);
  430.         read_interrupted = 0;
  431.         while (l > 0) {
  432. #ifdef DEBUG
  433.             if (debug > 10) (void)fprintf(ddt,"Before setitimer\n");
  434. #endif
  435.             (void) setitimer(ITIMER_REAL, &ival,
  436.                 (struct itimerval *)NULL);
  437. #ifdef DEBUG
  438.             if (debug > 10) (void)fprintf(ddt,"Before recv(l = %d)\n",n);
  439. #endif
  440.             errno = 0;
  441.             if ((n = recv(s, (char *)cp, l, 0)) > 0) {
  442.                 cp += n;
  443.                 l -= n;
  444.             } else {
  445. #ifdef DEBUG
  446.                 if (debug > 10)
  447.                 (void)fprintf(ddt,
  448. "bad recv->%d, errno= %d, read_interrupt=%d\n", n, errno, read_interrupted);
  449. #endif
  450.                 if (n == -1 && errno == EINTR 
  451.                     && !read_interrupted)
  452.                     continue;
  453.                 error++;
  454.                 break;
  455.             }
  456.         }
  457.  
  458.         (void) setitimer(ITIMER_REAL, &zeroival,
  459.             (struct itimerval *)NULL);
  460.         if (error) {
  461.             (void) close(s);
  462.             continue;
  463.         }
  464.         if ((len = htons(*(u_short *)buf)) == 0) {
  465.             (void) close(s);
  466.             continue;
  467.         }
  468.         if (len > bufsize) {
  469.             if ((buf = (u_char *)realloc(buf, len)) == NULL) {
  470.                 syslog(LOG_ERR,
  471.               "malloc(%u) failed for SOA from server %s, zone %s\n",
  472.                     len, inet_ntoa(sin.sin_addr), zp->z_origin);
  473.                 (void) close(s);
  474.                 continue;
  475.             }
  476.             bufsize = len;
  477.         }
  478.         l = len;
  479.         cp = buf;
  480.         while (l > 0) {
  481.             (void) setitimer(ITIMER_REAL, &ival,
  482.                 (struct itimerval *)NULL);
  483.             errno = 0;
  484.             if ((n = recv(s, (char *)cp, l, 0)) > 0) {
  485.                 cp += n;
  486.                 l -= n;
  487.             } else {
  488.                 if (errno == EINTR && !read_interrupted)
  489.                     continue;
  490.                 error++;
  491. #ifdef DEBUG
  492.                 if (debug > 10)
  493.                     (void)fprintf(ddt,
  494.                         "recv failed: n= %d, errno = %d\n",
  495.                         n, errno);
  496. #endif
  497.                 break;
  498.             }
  499.         }
  500.         (void) setitimer(ITIMER_REAL, &zeroival,
  501.             (struct itimerval *)NULL);
  502.         if (error) {
  503.             (void) close(s);
  504.             continue;
  505.         }
  506. #ifdef DEBUG
  507.         if (debug >= 3) {
  508.             (void)fprintf(ddt,"len = %d\n", len);
  509.             fp_query(buf, ddt);
  510.         }
  511. #endif DEBUG
  512.         hp = (HEADER *) buf;
  513.         ancount = ntohs(hp->ancount);
  514.         aucount = ntohs(hp->nscount);
  515.  
  516.         /*
  517.          * close socket if:
  518.          *  1) rcode != NOERROR
  519.          *  2) not an authority response
  520.          *  3) both the number of answers and authority count < 1)
  521.          */
  522.         if (hp->rcode != NOERROR || !(hp->aa) || 
  523.             (ancount < 1 && aucount < 1)) {
  524.             if (!quiet)
  525.                 syslog(LOG_ERR,
  526.         "%s from %s, zone %s: rcode %d, aa %d, ancount %d, aucount %d\n",
  527.                     "bad response to SOA query",
  528.                     inet_ntoa(sin.sin_addr), zp->z_origin,
  529.                     hp->rcode, hp->aa, ancount, aucount);
  530. #ifdef DEBUG
  531.             if (debug)
  532.                 fprintf(ddt,
  533.         "%s from %s, zone %s: rcode %d, aa %d, ancount %d, aucount %d\n",
  534.                     "bad response to SOA query",
  535.                     inet_ntoa(sin.sin_addr), zp->z_origin,
  536.                     hp->rcode, hp->aa, ancount, aucount);
  537. #endif DEBUG
  538.             (void) close(s);
  539.             error++;
  540.             continue;
  541.         }
  542.         zp_start = *zp;
  543.         if (len < sizeof(HEADER) + QFIXEDSZ) {
  544.     badsoa:
  545.             if (!quiet)
  546.                 syslog(LOG_ERR,
  547.                   "malformed SOA from %s, zone %s: too short\n",
  548.                     inet_ntoa(sin.sin_addr), zp->z_origin);
  549. #ifdef DEBUG
  550.             if (debug)
  551.                 fprintf(ddt,
  552.                     "malformed SOA from %s: too short\n",
  553.                     inet_ntoa(sin.sin_addr));
  554. #endif DEBUG
  555.             (void) close(s);
  556.             error++;
  557.             continue;
  558.         }
  559.         tmp = buf + sizeof(HEADER);
  560.         eom = buf + len;
  561.         if ((n = dn_skipname(tmp, eom)) == -1)
  562.             goto badsoa;
  563.         tmp += n + QFIXEDSZ;
  564.         if ((n = dn_skipname(tmp, eom)) == -1)
  565.             goto badsoa;
  566.         tmp += n;
  567.         if (soa_zinfo(&zp_start, tmp, eom) == -1)
  568.             goto badsoa;
  569.         if (zp_start.z_serial > serial_no || serial_no == 0) {
  570. #ifdef DEBUG
  571.             if (debug)
  572.             (void)fprintf(ddt, "need update, serial %d\n",
  573.                 zp_start.z_serial);
  574. #endif DEBUG
  575.             hp = (HEADER *) buf;
  576.             soacnt = 0;
  577.             for (;;) {
  578.             if (soacnt == 0) {
  579.                 if ((n = res_mkquery(QUERY, zp->z_origin, C_IN,
  580.                   T_AXFR, (char *)NULL, 0, NULL,
  581.                   (char *)buf, bufsize)) < 0) {
  582.                 if (!quiet)
  583.                     syslog(LOG_ERR,
  584.                     "zone %s: res_mkquery T_AXFR failed",
  585.                     zp->z_origin);
  586.                 (void) close(s);
  587.                 (void) sigvec(SIGALRM, &osv,
  588.                     (struct sigvec *)0);
  589.                 return XFER_FAIL;
  590.                 }
  591.                 /*
  592.                  * Send length & message for zone transfer
  593.                  */
  594.                 if (writemsg(s, buf, n) < 0) {
  595.                     (void) close(s);
  596.                     error++;
  597. #ifdef DEBUG
  598.                     if (debug >= 2)
  599.                         (void)fprintf(ddt,"writemsg failed\n");
  600. #endif
  601.                     break;    
  602.                 }
  603.             }
  604.             /*
  605.              * Receive length & response
  606.              */
  607.             cp = buf;
  608.             l = sizeof(u_short);
  609.             /* allow extra time for the fork on first read */
  610.             if (soacnt == 0)
  611.                 ival.it_value.tv_sec = 300;
  612.             while (l > 0) {
  613.                 (void) setitimer(ITIMER_REAL, &ival,
  614.                     (struct itimerval *)NULL);
  615.                 errno = 0;
  616.                 if ((n = recv(s, (char *)cp, l, 0)) > 0) {
  617.                     cp += n;
  618.                     l -= n;
  619.                 } else {
  620.                     if (errno == EINTR && !read_interrupted)
  621.                         continue;
  622.                     error++;
  623. #ifdef DEBUG
  624.                     if (debug >= 2)
  625.                       (void)fprintf(ddt,
  626.                         "recv failed: n= %d, errno = %d\n",
  627.                         n, errno);
  628. #endif
  629.                     break;
  630.                 }
  631.             }
  632.             if (soacnt == 0)
  633.                 ival.it_value.tv_sec = 120;
  634.             (void) setitimer(ITIMER_REAL, &zeroival,
  635.                 (struct itimerval *)NULL);
  636.             if (error)
  637.                 break;
  638.             if ((len = htons(*(u_short *)buf)) == 0)
  639.                 break;
  640.             l = len;
  641.             cp = buf;
  642.             eom = buf + len;
  643.             while (l > 0) {
  644.                 (void) setitimer(ITIMER_REAL, &ival,
  645.                     (struct itimerval *)NULL);
  646.                 errno = 0;
  647.                 if ((n = recv(s, (char *)cp, l, 0)) > 0) {
  648.                     cp += n;
  649.                     l -= n;
  650.                 } else {
  651.                     if (errno == EINTR && !read_interrupted)
  652.                         continue;
  653.                     error++;
  654. #ifdef DEBUG
  655.                     if (debug >= 2)
  656.                         (void)fprintf(ddt,"recv failed\n");
  657. #endif
  658.                     break;
  659.                 }
  660.             }
  661.             (void) setitimer(ITIMER_REAL, &zeroival,
  662.                 (struct itimerval *)NULL);
  663.             if (error)
  664.                 break;
  665. #ifdef DEBUG
  666.             if (debug >= 3) {
  667.                 (void)fprintf(ddt,"len = %d\n", len);
  668.                 fp_query(buf, ddt);
  669.             }
  670.             if (fp) fp_query(buf,fp);
  671. #endif
  672.             if (len < sizeof(HEADER)) {
  673.         badrec:
  674.                 error++;
  675.                 if (!quiet)
  676.                     syslog(LOG_ERR,
  677.                       "record too short from %s, zone %s\n",
  678.                       inet_ntoa(sin.sin_addr),
  679.                       zp->z_source);
  680. #ifdef DEBUG
  681.                 if (debug)
  682.                     fprintf(ddt,
  683.                         "record too short from %s\n",
  684.                     inet_ntoa(sin.sin_addr));
  685. #endif DEBUG
  686.                 break;
  687.             }
  688.             cp = buf + sizeof(HEADER);
  689.             if (hp->qdcount) {
  690.                 if ((n = dn_skipname(cp, eom)) == -1 ||
  691.                     n + QFIXEDSZ >= eom - cp)
  692.                     goto badrec;
  693.                 cp += n + QFIXEDSZ;
  694.             }
  695.             nmp = cp;
  696.             if ((n = dn_skipname(cp, eom)) == -1)
  697.                 goto badrec;
  698.             tmp = cp + n;
  699.  
  700.             n = print_output(buf, bufsize, cp);
  701.             if (cp + n != eom) {
  702. #ifdef DEBUG
  703.                if (debug)
  704.                (void)fprintf(ddt,
  705.                      "getzone: print_update failed (%d, %d)\n",
  706.                     cp - buf, n);
  707. #endif
  708.                 error++;
  709.                 break;
  710.             }
  711.             GETSHORT(n, tmp);
  712.             if (n == T_SOA) {
  713.                 if (soacnt == 0) {
  714.                     soacnt++;
  715.                     if (dn_expand(buf, buf + 512, nmp,
  716.                         name, sizeof(name)) == -1)
  717.                         goto badsoa;
  718.                     if (eom - tmp <= 2 * sizeof(u_short) +
  719.                         sizeof(u_long))
  720.                         goto badsoa;
  721.                     tmp += 2 * sizeof(u_short)
  722.                         + sizeof(u_long);
  723.                     if ((n = dn_skipname(tmp, eom)) == -1)
  724.                         goto badsoa;
  725.                     tmp += n;
  726.                     if ((n = dn_skipname(tmp, eom)) == -1)
  727.                         goto badsoa;
  728.                     tmp += n;
  729.                     if (eom - tmp <= sizeof(u_long))
  730.                         goto badsoa;
  731.                     GETLONG(serial, tmp);
  732. #ifdef DEBUG
  733.                     if (debug > 2)
  734.                         (void)fprintf(ddt,
  735.                             "first SOA for %s, serial %d\n",
  736.                             name, serial);
  737. #endif DEBUG
  738.                     continue;
  739.                 }
  740.                 if (dn_expand(buf, buf + 512, nmp, name2, 
  741.                     sizeof(name2)) == -1)
  742.                     goto badsoa;
  743.                 if (strcasecmp((char *)name, (char *)name2) != 0) {
  744. #ifdef DEBUG
  745.                     if (debug > 1)
  746.                         (void)fprintf(ddt,
  747.                           "extraneous SOA for %s\n",
  748.                           name2);
  749. #endif DEBUG
  750.                     continue;
  751.                 }
  752.                 tmp -= sizeof(u_short);
  753.                 if (soa_zinfo(&zp_finish, tmp, eom) == -1)
  754.                     goto badsoa;
  755. #ifdef DEBUG
  756.                 if (debug > 1)
  757.                     (void)fprintf(ddt,
  758.                       "SOA, serial %d\n", zp_finish.z_serial);
  759. #endif DEBUG
  760.                 if (serial != zp_finish.z_serial) {
  761.                     soacnt = 0;
  762.                     got_soa = 0;
  763.                     minimum_ttl = 0;
  764.                     strcpy(prev_origin, zp->z_origin);
  765.                     prev_dname[0] = 0;
  766. #ifdef DEBUG
  767.                     if (debug)
  768.                         (void)fprintf(ddt,
  769.                         "serial changed, restart\n");
  770. #endif DEBUG
  771.                     /*
  772.                      * Flush buffer, truncate file
  773.                      * and seek to beginning to restart.
  774.                      */
  775.                     fflush(dbfp);
  776.                     if (ftruncate(fileno(dbfp), 0) != 0) {
  777.                         if (!quiet)
  778.                             syslog(LOG_ERR,
  779.                             "ftruncate %s: %m\n",
  780.                             tmpname);
  781.                         return(XFER_FAIL);
  782.                     }
  783.                     fseek(dbfp, 0L, 0);
  784.                 } else
  785.                     break;
  786.             }
  787.         }
  788.         (void) close(s);
  789.         if (error == 0) {
  790.             (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
  791.             return XFER_SUCCESS;
  792.         }
  793. #ifdef DEBUG
  794.         if (debug >= 2)
  795.           (void)fprintf(ddt,"error receiving zone transfer\n");
  796. #endif
  797.         } else {
  798.         (void) close(s);
  799. #ifdef DEBUG
  800.         if (debug)
  801.             (void)fprintf(ddt,
  802.               "zone up-to-date, serial %d\n", zp_start.z_serial);
  803. #endif DEBUG
  804.         return XFER_UPTODATE;
  805.         }
  806.     }
  807.     (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
  808.     if (error)
  809.         return XFER_TIMEOUT;
  810.     return XFER_FAIL;
  811. }
  812.  
  813. /*
  814.  * Set flag saying to read was interrupted
  815.  * used for a read timer
  816.  */
  817. SIG_FN
  818. read_alarm()
  819. {
  820.     extern int read_interrupted;
  821.     read_interrupted = 1;
  822. }
  823.  
  824. writemsg(rfd, msg, msglen)
  825.     int rfd;
  826.     u_char *msg;
  827.     int msglen;
  828. {
  829.     struct iovec iov[2];
  830.     u_short len = htons((u_short)msglen);
  831.  
  832.     iov[0].iov_base = (caddr_t)&len;
  833.     iov[0].iov_len = sizeof(len);
  834.     iov[1].iov_base = (caddr_t)msg;
  835.     iov[1].iov_len = msglen;
  836.     if (writev(rfd, iov, 2) != sizeof(len) + msglen) {
  837. #ifdef DEBUG
  838.         if (debug)
  839.           (void)fprintf(ddt,"write failed %d\n", errno);
  840. #endif
  841.         return (-1);
  842.     }
  843.     return (0);
  844. }
  845.  
  846.  
  847. soa_zinfo(zp, cp, eom)
  848.     register struct zoneinfo *zp;
  849.     register u_char *cp;
  850.     u_char *eom;
  851. {
  852.     register int n;
  853.  
  854.     if (eom - cp < 3 * sizeof(u_short) + sizeof(u_long))
  855.         return (-1);
  856.     cp += 3 * sizeof(u_short) + sizeof(u_long);
  857.     if ((n = dn_skipname(cp, eom)) == -1)
  858.         return (-1);
  859.     cp += n;
  860.     if ((n = dn_skipname(cp, eom)) == -1)
  861.         return (-1);
  862.     cp += n;
  863.     if (eom - cp < 5 * sizeof(u_long))
  864.         return (-1);
  865.     GETLONG(zp->z_serial, cp);
  866.     GETLONG(zp->z_refresh, cp);
  867.     gettime(&tt);
  868.     zp->z_time = tt.tv_sec + zp->z_refresh;
  869.     GETLONG(zp->z_retry, cp);
  870.     GETLONG(zp->z_expire, cp);
  871.     GETLONG(zp->z_minimum, cp);
  872.     return (0);
  873. }
  874.  
  875. gettime(ttp)
  876. struct timeval *ttp;
  877. {
  878.     if (gettimeofday(ttp, (struct timezone *)0) < 0)
  879.         syslog(LOG_ERR, "gettimeofday failed: %m");
  880. }
  881.  
  882. /*
  883.  * Parse the message, determine if it should be printed, and if so, print it
  884.  * in .db file form.
  885.  * Does minimal error checking on the message content.
  886.  */
  887. print_output(msg, msglen, rrp)
  888.     u_char *msg;
  889.     int msglen;
  890.     u_char *rrp;
  891. {
  892.     register u_char *cp;
  893.     register HEADER *hp = (HEADER *) msg;
  894.     u_long addr, ttl;
  895.     int i, j, tab, result, class, type, dlen, n1;
  896.     long n;
  897.     u_char *cp1, data[BUFSIZ];
  898.     u_char *temp_ptr;    /* used to get ttl for RR */
  899.     char *cdata, *origin, *proto, dname[MAXDNAME];
  900.     extern char *inet_ntoa(), *protocolname(), *servicename();
  901.  
  902.     cp = rrp;
  903.     if ((n = dn_expand(msg, msg + msglen, cp, (u_char *) dname,
  904.             sizeof(dname))) < 0) {
  905.         hp->rcode = FORMERR;
  906.         return (-1);
  907.     }
  908.     cp += n;
  909.     GETSHORT(type, cp);
  910.     GETSHORT(class, cp);
  911.     GETLONG(ttl, cp);
  912.     GETSHORT(dlen, cp);
  913.  
  914.     origin = index(dname, '.');
  915.     if (origin == NULL)
  916.         origin = "";
  917.     else
  918.         origin++;    /* move past the '.' */
  919. #ifdef DEBUG
  920.     if (debug > 2)
  921.         (void) fprintf(ddt, "print_output: dname %s type %d class %d ttl %d\n",
  922.             dname, type, class, ttl);
  923. #endif
  924.     /*
  925.      * Convert the resource record data into the internal database format.
  926.      */
  927.     switch (type) {
  928.     case T_A:
  929.     case T_WKS:
  930.     case T_HINFO:
  931.     case T_UINFO:
  932.     case T_TXT:
  933.     case T_UID:
  934.     case T_GID:
  935.         cp1 = cp;
  936.         n = dlen;
  937.         cp += n;
  938.         break;
  939.  
  940.     case T_CNAME:
  941.     case T_MB:
  942.     case T_MG:
  943.     case T_MR:
  944.     case T_NS:
  945.     case T_PTR:
  946.         if ((n = dn_expand(msg, msg + msglen, cp, data,
  947.                 sizeof(data))) < 0) {
  948.             hp->rcode = FORMERR;
  949.             return (-1);
  950.         }
  951.         cp += n;
  952.         cp1 = data;
  953.         n = strlen((char *) data) + 1;
  954.         break;
  955.  
  956.     case T_MINFO:
  957.     case T_SOA:
  958.         if ((n = dn_expand(msg, msg + msglen, cp, data,
  959.                 sizeof(data))) < 0) {
  960.             hp->rcode = FORMERR;
  961.             return (-1);
  962.         }
  963.         cp += n;
  964.         cp1 = data + (n = strlen((char *) data) + 1);
  965.         n1 = sizeof(data) - n;
  966.         if (type == T_SOA)
  967.             n1 -= 5 * sizeof(u_long);
  968.         if ((n = dn_expand(msg, msg + msglen, cp, cp1, n1)) < 0) {
  969.             hp->rcode = FORMERR;
  970.             return (-1);
  971.         }
  972.         cp += n;
  973.         cp1 += strlen((char *) cp1) + 1;
  974.         if (type == T_SOA) {
  975.             temp_ptr = cp + 4 * sizeof(u_long);
  976.             GETLONG(minimum_ttl, temp_ptr);
  977.             bcopy((char *) cp, (char *) cp1,
  978.                 n = 5 * sizeof(u_long));
  979.             cp += n;
  980.             cp1 += n;
  981.         }
  982.         n = cp1 - data;
  983.         cp1 = data;
  984.         break;
  985.  
  986.     case T_MX:
  987.         /* grab preference */
  988.         bcopy((char *) cp, (char *) data, sizeof(u_short));
  989.         cp1 = data + sizeof(u_short);
  990.         cp += sizeof(u_short);
  991.  
  992.         /* get name */
  993.         if ((n = dn_expand(msg, msg + msglen, cp, cp1,
  994.                 sizeof(data) - sizeof(u_short))) < 0)
  995.             return (-1);
  996.         cp += n;
  997.  
  998.         /* compute end of data */
  999.         cp1 += strlen((char *) cp1) + 1;
  1000.         /* compute size of data */
  1001.         n = cp1 - data;
  1002.         cp1 = data;
  1003.         break;
  1004.  
  1005.     default:
  1006. #ifdef DEBUG
  1007.         if (debug >= 3)
  1008.             (void) fprintf(ddt, "unknown type %d\n", type);
  1009. #endif
  1010.         return ((cp - rrp) + dlen);
  1011.     }
  1012.     if (n > MAXDATA) {
  1013. #ifdef DEBUG
  1014.         if (debug)
  1015.             (void) fprintf(ddt,
  1016.                 "update type %d: %d bytes is too much data\n",
  1017.                 type, n);
  1018. #endif
  1019.         hp->rcode = NOCHANGE;    /* XXX - FORMERR ??? */
  1020.         return (-1);
  1021.     }
  1022.     cdata = (char *) cp1;
  1023.     result = cp - rrp;
  1024.  
  1025.     /*
  1026.      * Only print one SOA per db file
  1027.      */
  1028.     if (type == T_SOA) {
  1029.         if (got_soa)
  1030.             return result;
  1031.         else
  1032.             got_soa++;
  1033.     }
  1034.     /*
  1035.      * If the origin has changed, print the new origin
  1036.      */
  1037.     if (strcasecmp(prev_origin, origin)) {
  1038.         (void) strcpy(prev_origin, origin);
  1039.         (void) fprintf(dbfp, "$ORIGIN %s.\n", origin);
  1040.     }
  1041.     tab = 0;
  1042.  
  1043.     if (strcasecmp(prev_dname, dname)) {
  1044.         /*
  1045.          * set the prev_dname to be the current dname, then cut off all
  1046.          * characters of dname after (and including) the first '.'
  1047.          */
  1048.         char *cutp = index(dname, '.');
  1049.  
  1050.         (void) strcpy(prev_dname, dname);
  1051.         if (cutp)
  1052.             *cutp = NULL;
  1053.  
  1054.         if (dname[0] == 0) {
  1055.             if (origin[0] == 0)
  1056.                 (void) fprintf(dbfp, ".\t");
  1057.             else
  1058.                 (void) fprintf(dbfp, ".%s.\t", origin);    /* ??? */
  1059.         } else
  1060.             (void) fprintf(dbfp, "%s\t", dname);
  1061.         if (strlen(dname) < 8)
  1062.             tab = 1;
  1063.     } else {
  1064.         (void) putc('\t', dbfp);
  1065.         tab = 1;
  1066.     }
  1067.  
  1068.     if (ttl != 0 && ttl != minimum_ttl)
  1069.         (void) fprintf(dbfp, "%d\t", (int) ttl);
  1070.     else if (tab)
  1071.         (void) putc('\t', dbfp);
  1072.  
  1073.     (void) fprintf(dbfp, "%s\t%s\t", p_class(class), p_type(type));
  1074.     cp = (u_char *) cdata;
  1075.  
  1076.     /*
  1077.      * Print type specific data
  1078.      */
  1079.     switch (type) {
  1080.  
  1081.     case T_A:
  1082.         switch (class) {
  1083.         case C_IN:
  1084.         case C_HS:
  1085.             GETLONG(n, cp);
  1086.             n = htonl(n);
  1087.             (void) fprintf(dbfp, "%s",
  1088.                 inet_ntoa(*(struct in_addr *) & n));
  1089.             break;
  1090.         }
  1091.         (void) fprintf(dbfp, "\n");
  1092.         break;
  1093.  
  1094.     case T_CNAME:
  1095.     case T_MB:
  1096.     case T_MG:
  1097.     case T_MR:
  1098.     case T_PTR:
  1099.         if (cp[0] == '\0')
  1100.             (void) fprintf(dbfp, ".\n");
  1101.         else
  1102.             (void) fprintf(dbfp, "%s.\n", cp);
  1103.         break;
  1104.  
  1105.     case T_NS:
  1106.         cp = (u_char *) cdata;
  1107.         if (cp[0] == '\0')
  1108.             (void) fprintf(dbfp, ".\t");
  1109.         else
  1110.             (void) fprintf(dbfp, "%s.", cp);
  1111.         (void) fprintf(dbfp, "\n");
  1112.         break;
  1113.  
  1114.     case T_HINFO:
  1115.         if (n = *cp++) {
  1116.             (void) fprintf(dbfp, "\"%.*s\"", (int) n, cp);
  1117.             cp += n;
  1118.         } else
  1119.             (void) fprintf(dbfp, "\"\"");
  1120.         if (n = *cp++)
  1121.             (void) fprintf(dbfp, " \"%.*s\"", (int) n, cp);
  1122.         else
  1123.             (void) fprintf(dbfp, "\"\"");
  1124.         (void) putc('\n', dbfp);
  1125.         break;
  1126.  
  1127.     case T_SOA:
  1128.         (void) fprintf(dbfp, "%s.", cp);
  1129.         cp += strlen((char *) cp) + 1;
  1130.         (void) fprintf(dbfp, " %s. (\n", cp);
  1131.         cp += strlen((char *) cp) + 1;
  1132.         GETLONG(n, cp);
  1133.         (void) fprintf(dbfp, "\t\t%lu", n);
  1134.         GETLONG(n, cp);
  1135.         (void) fprintf(dbfp, " %lu", n);
  1136.         GETLONG(n, cp);
  1137.         (void) fprintf(dbfp, " %lu", n);
  1138.         GETLONG(n, cp);
  1139.         (void) fprintf(dbfp, " %lu", n);
  1140.         GETLONG(n, cp);
  1141.         (void) fprintf(dbfp, " %lu )\n", n);
  1142.         break;
  1143.  
  1144.     case T_MX:
  1145.         GETSHORT(n, cp);
  1146.         (void) fprintf(dbfp, "%lu", n);
  1147.         (void) fprintf(dbfp, " %s.\n", cp);
  1148.         break;
  1149.  
  1150.     case T_TXT:
  1151.         cp1 = cp + n;
  1152.         (void) putc('"', dbfp);
  1153.         while (cp < cp1) {
  1154.             if (i = *cp++) {
  1155.                 for (j = i ; j > 0 && cp < cp1 ; j--)
  1156.                     if (*cp == '\n') {
  1157.                         (void) putc('\\', dbfp);
  1158.                         (void) putc(*cp++, dbfp);
  1159.                     } else
  1160.                         (void) putc(*cp++, dbfp);
  1161.             }
  1162.         }
  1163.         (void) fputs("\"\n", dbfp);
  1164.         break;
  1165.  
  1166.     case T_UINFO:
  1167.         (void) fprintf(dbfp, "\"%s\"\n", cp);
  1168.         break;
  1169.  
  1170.     case T_UID:
  1171.     case T_GID:
  1172.         if (n == sizeof(u_long)) {
  1173.             GETLONG(n, cp);
  1174.             (void) fprintf(dbfp, "%lu\n", n);
  1175.         }
  1176.         break;
  1177.  
  1178.     case T_WKS:
  1179.         GETLONG(addr, cp);
  1180.         addr = htonl(addr);
  1181.         (void) fprintf(dbfp, "%s ",
  1182.             inet_ntoa(*(struct in_addr *) & addr));
  1183.         proto = protocolname(*cp);
  1184.         cp += sizeof(char);
  1185.         (void) fprintf(dbfp, "%s ", proto);
  1186.         i = 0;
  1187.         while (cp < (u_char *) cdata + n) {
  1188.             j = *cp++;
  1189.             do {
  1190.                 if (j & 0200)
  1191.                     (void) fprintf(dbfp, " %s",
  1192.                         servicename(i, proto));
  1193.                 j <<= 1;
  1194.             } while (++i & 07);
  1195.         }
  1196.         (void) fprintf(dbfp, "\n");
  1197.         break;
  1198.  
  1199.     case T_MINFO:
  1200.         (void) fprintf(dbfp, "%s.", cp);
  1201.         cp += strlen((char *) cp) + 1;
  1202.         (void) fprintf(dbfp, " %s.\n", cp);
  1203.         break;
  1204.  
  1205.     default:
  1206.         (void) fprintf(dbfp, "???\n");
  1207.     }
  1208.     if (ferror(dbfp)) {
  1209.         syslog(LOG_ERR, "%s: %m", tmpname);
  1210.         exit(XFER_FAIL);
  1211.     }
  1212.     return result;
  1213. }
  1214.  
  1215. /*
  1216.  * Make a copy of a string and return a pointer to it.
  1217.  */
  1218. char *
  1219. savestr(str)
  1220.     char *str;
  1221. {
  1222.     char *cp;
  1223.  
  1224.     cp = (char *)malloc((unsigned)strlen(str) + 1);
  1225.     if (cp == NULL) {
  1226.         syslog(LOG_ERR, "savestr: %m");
  1227.         exit(XFER_FAIL);
  1228.     }
  1229.     (void) strcpy(cp, str);
  1230.     return (cp);
  1231. }
  1232.