home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / n / bind / bind-4.001 / bind-4~ / bind-4.9.3-BETA9 / named / named-xfer.c < prev    next >
C/C++ Source or Header  |  1994-07-22  |  35KB  |  1,482 lines

  1. /*
  2.  * The original version of xfer by Kevin Dunlap.
  3.  * Completed and integrated with named by David Waitzman
  4.  *    (dwaitzman@bbn.com) 3/14/88.
  5.  * Modified by M. Karels and O. Kure 10-88.
  6.  * Modified extensively since then by just about everybody.
  7.  */
  8.  
  9. /*
  10.  * ++Copyright++ 1988, 1990
  11.  * -
  12.  * Copyright (c) 1988, 1990
  13.  *    The Regents of the University of California.  All rights reserved.
  14.  * 
  15.  * Redistribution and use in source and binary forms, with or without
  16.  * modification, are permitted provided that the following conditions
  17.  * are met:
  18.  * 1. Redistributions of source code must retain the above copyright
  19.  *    notice, this list of conditions and the following disclaimer.
  20.  * 2. Redistributions in binary form must reproduce the above copyright
  21.  *    notice, this list of conditions and the following disclaimer in the
  22.  *    documentation and/or other materials provided with the distribution.
  23.  * 3. All advertising materials mentioning features or use of this software
  24.  *    must display the following acknowledgement:
  25.  *     This product includes software developed by the University of
  26.  *     California, Berkeley and its contributors.
  27.  * 4. Neither the name of the University nor the names of its contributors
  28.  *    may be used to endorse or promote products derived from this software
  29.  *    without specific prior written permission.
  30.  * 
  31.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  32.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  33.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  34.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  35.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  39.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  40.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  41.  * SUCH DAMAGE.
  42.  * -
  43.  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  44.  * 
  45.  * Permission to use, copy, modify, and distribute this software for any
  46.  * purpose with or without fee is hereby granted, provided that the above
  47.  * copyright notice and this permission notice appear in all copies, and that
  48.  * the name of Digital Equipment Corporation not be used in advertising or
  49.  * publicity pertaining to distribution of the document or software without
  50.  * specific, written prior permission.
  51.  * 
  52.  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  53.  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
  54.  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
  55.  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  56.  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  57.  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  58.  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  59.  * SOFTWARE.
  60.  * -
  61.  * --Copyright--
  62.  */
  63.  
  64. #if !defined(lint) && !defined(SABER)
  65. char copyright[] =
  66. "@(#) Copyright (c) 1988, 1990 The Regents of the University of California.\n\
  67.  portions Copyright (c) 1993 Digital Equipment Corporation\n\
  68.  All rights reserved.\n";
  69. #endif /* not lint */
  70.  
  71. #if !defined(lint) && !defined(SABER)
  72. static char sccsid[] = "@(#)named-xfer.c    4.18 (Berkeley) 3/7/91";
  73. static char rcsid[] = "$Id: named-xfer.c,v 4.9.1.23 1994/07/22 08:42:39 vixie Exp $";
  74. #endif /* not lint */
  75.  
  76. #include <sys/param.h>
  77. #include <sys/file.h>
  78. #include <sys/stat.h>
  79. #include <sys/socket.h>
  80. #include <sys/time.h>
  81.  
  82. #include <netinet/in.h>
  83. #include <net/if.h>
  84. #include <netdb.h>
  85. #include <arpa/inet.h>
  86. #include <arpa/nameser.h>
  87.  
  88. #include <errno.h>
  89. #include <resolv.h>
  90. #include <stdio.h>
  91. #include <syslog.h>
  92. #include <math.h>
  93. #include <signal.h>
  94.  
  95. #define MAIN_PROGRAM
  96. #include "named.h"
  97. #undef MAIN_PROGRAM
  98.  
  99. #ifndef LOG_PERROR
  100. # define LOG_PERROR 0
  101. #endif
  102.  
  103. static    struct zoneinfo    zone;        /* zone information */
  104.  
  105. static    char        ddtfilename[] = _PATH_TMPXFER,
  106.             *ddtfile = ddtfilename,
  107.             *tmpname,
  108.             *domain;        /* domain being xfered */
  109.  
  110. static    int        quiet = 0,
  111.             read_interrupted = 0,
  112.             domain_len;        /* strlen(domain) */
  113.  
  114. static    FILE        *fp = NULL,
  115.             *dbfp = NULL;
  116.  
  117. static    void        usage __P((const char *));
  118. static    int        getzone __P((struct zoneinfo *, u_int32_t, int)),
  119.             soa_zinfo __P((struct zoneinfo *, u_char *, u_char *)),
  120.             print_output __P((u_char *, int, u_char *)),
  121.             netread __P((int, char *, int, int));
  122. static    SIG_FN        read_alarm __P((void));
  123. static    char        *ProgName;
  124.  
  125. extern char *optarg;
  126. extern int optind, getopt();
  127.  
  128. void
  129. main(argc, argv)
  130.     int argc;
  131.     char *argv[];
  132. {
  133.     register struct zoneinfo *zp;
  134.     register struct hostent *hp;
  135.      char *dbfile = NULL, *tracefile = NULL, *tm = NULL;
  136.     int dbfd, ddtd, result, c, fd, closed = 0;
  137.     u_int32_t serial_no = 0;
  138.     u_int16_t port = htons(NAMESERVER_PORT);
  139.     struct stat statbuf;
  140. #ifdef STUBS
  141.     int stub_only = 0;
  142. #endif
  143. #ifdef GEN_AXFR
  144.     int class = C_IN;
  145. #endif
  146.  
  147.     if (ProgName = strrchr(argv[0], '/'))
  148.         ProgName++;
  149.     else
  150.         ProgName = argv[0];
  151.  
  152.     (void) umask(022);
  153.  
  154.     /* this is a hack; closing everything in the parent is hard. */
  155.     for (fd = getdtablesize()-1;  fd > STDERR_FILENO;  fd--)
  156.         closed += (close(fd) == 0);
  157.  
  158. #ifdef RENICE
  159.     nice (-40);    /* this is the recommended procedure to        */
  160.     nice (20);    /*   reset the priority of the current process */
  161.     nice (0);    /*   to "normal" (== 0) - see nice(3)          */
  162. #endif
  163.  
  164. #ifdef LOG_DAEMON
  165.     openlog(ProgName, LOG_PID|LOG_CONS|LOG_PERROR, LOGFAC);
  166. #else
  167.     openlog(ProgName, LOG_PID);
  168. #endif
  169. #ifdef STUBS
  170.     while ((c = getopt(argc, argv, "C:d:l:s:t:z:f:p:P:qS")) != EOF)
  171. #else
  172.     while ((c = getopt(argc, argv, "C:d:l:s:t:z:f:p:P:q")) != EOF)
  173. #endif
  174.         switch (c) {
  175. #ifdef GEN_AXFR
  176.             case 'C':
  177.             class = get_class(optarg);
  178.             break;
  179. #endif
  180.         case 'd':
  181. #ifdef DEBUG
  182.             debug = atoi(optarg);
  183. #endif
  184.             break;
  185.         case 'l':
  186.             ddtfile = (char *)malloc(strlen(optarg) +
  187.                 sizeof(".XXXXXX") + 1);
  188. #ifdef SHORT_FNAMES
  189.             filenamecpy(ddtfile, optarg);
  190. #else
  191.             (void) strcpy(ddtfile, optarg);
  192. #endif /* SHORT_FNAMES */
  193.             (void) strcat(ddtfile, ".XXXXXX");
  194.             break;
  195.         case 's':
  196.             serial_no = strtoul(optarg, (char **)NULL, 10);
  197.             break;
  198.         case 't':
  199.             tracefile = optarg;
  200.             break;
  201.         case 'z':        /* zone == domain */
  202.             domain = optarg;
  203.             domain_len = strlen(domain);
  204.             while ((domain_len > 0) && 
  205.                     (domain[domain_len-1] == '.'))
  206.                 domain[--domain_len] = '\0';
  207.             break;
  208.         case 'f':
  209.             dbfile = optarg;
  210.             tmpname = (char *)malloc((unsigned)strlen(optarg) +
  211.                          sizeof(".XXXXXX") + 1);
  212. #ifdef SHORT_FNAMES
  213.             filenamecpy(tmpname, optarg);
  214. #else
  215.             (void) strcpy(tmpname, optarg);
  216. #endif /* SHORT_FNAMES */
  217.             break;
  218.         case 'p':
  219.             port = htons((u_int16_t)atoi(optarg));
  220.             break;
  221.         case 'P':
  222.             port = (u_int16_t)atoi(optarg);
  223.             break;
  224. #ifdef STUBS
  225.         case 'S':
  226.             stub_only = 1;
  227.             break;
  228. #endif
  229.         case 'q':
  230.             quiet++;
  231.             break;
  232.         case '?':
  233.         default:
  234.             usage("unrecognized argument");
  235.             /* NOTREACHED */
  236.         }
  237.  
  238.     if (!domain || !dbfile || optind >= argc) {
  239.         if (!domain)
  240.             usage("no domain");
  241.         if (!dbfile)
  242.             usage("no dbfile");
  243.         if (optind >= argc)
  244.             usage("not enough arguments");
  245.         /* NOTREACHED */
  246.     }
  247.     if (stat(dbfile, &statbuf) != -1 &&
  248.         !S_ISREG(statbuf.st_mode) &&
  249.         !S_ISFIFO(statbuf.st_mode))
  250.         usage("dbfile must be a regular file or FIFO");
  251.     if (tracefile && (fp = fopen(tracefile, "w")) == NULL)
  252.         perror(tracefile);
  253.     (void) strcat(tmpname, ".XXXXXX");
  254.     /* tmpname is now something like "/etc/named/named.bu.db.XXXXXX" */
  255.     if ((dbfd = mkstemp(tmpname)) == -1) {
  256.         perror(tmpname);
  257.         if (!quiet)
  258.             syslog(LOG_ERR, "can't make tmpfile (%s): %m\n",
  259.                 tmpname);
  260.         exit(XFER_FAIL);
  261.     }
  262. #if HAVE_FCHMOD
  263.     if (fchmod(dbfd, 0644) == -1)
  264. #else
  265.     if (chmod(tmpname, 0644) == -1)
  266. #endif
  267.     {
  268.         perror(tmpname);
  269.         if (!quiet)
  270.             syslog(LOG_ERR, "can't [f]chmod tmpfile (%s): %m\n",
  271.                 tmpname);
  272.         exit(XFER_FAIL);
  273.     }
  274.     if ((dbfp = fdopen(dbfd, "r+")) == NULL) {
  275.         perror(tmpname);
  276.         if (!quiet)
  277.             syslog(LOG_ERR, "can't fdopen tmpfile (%s)", tmpname);
  278.         exit(XFER_FAIL);
  279.     }
  280. #ifdef DEBUG
  281.     if (debug) {
  282.         /* ddtfile is now something like "/usr/tmp/xfer.ddt.XXXXXX" */
  283.         if ((ddtd = mkstemp(ddtfile)) == -1) {
  284.             perror(ddtfile);
  285.             debug = 0;
  286.         }
  287. #if HAVE_FCHMOD
  288.         else if (fchmod(ddtd, 0644) == -1)
  289. #else
  290.         else if (chmod(ddtfile, 0644) == -1)
  291. #endif
  292.         {
  293.             perror(ddtfile);
  294.             debug = 0;
  295.         } else if ((ddt = fdopen(ddtd, "w")) == NULL) {
  296.             perror(ddtfile);
  297.             debug = 0;
  298.         } else {
  299. #if defined(SYSV)
  300.             setvbuf(ddt, NULL, _IOLBF, BUFSIZ);
  301. #else
  302.             setlinebuf(ddt);
  303. #endif
  304.         }
  305.     }
  306. #endif
  307.     /*
  308.      * Ignore many types of signals that named (assumed to be our parent)
  309.      * considers important- if not, the user controlling named with
  310.      * signals usually kills us.
  311.      */
  312.     (void) signal(SIGHUP, SIG_IGN);
  313. #ifdef SIGSYS
  314.     (void) signal(SIGSYS, SIG_IGN);
  315. #endif
  316. #ifdef DEBUG
  317.     if (debug == 0)
  318. #endif
  319.     {
  320.         (void) signal(SIGINT, SIG_IGN);
  321.         (void) signal(SIGQUIT, SIG_IGN);
  322.     }
  323.     (void) signal(SIGIOT, SIG_IGN);
  324.  
  325. #if defined(SIGUSR1) && defined(SIGUSR2)
  326.     (void) signal(SIGUSR1, SIG_IGN);
  327.     (void) signal(SIGUSR2, SIG_IGN);
  328. #else    /* SIGUSR1&&SIGUSR2 */
  329.     (void) signal(SIGEMT, SIG_IGN);
  330.     (void) signal(SIGFPE, SIG_IGN);
  331. #endif /* SIGUSR1&&SIGUSR2 */
  332.  
  333.     dprintf(1, (ddt,
  334.             "domain `%s'; file `%s'; serial %lu; closed %d\n",
  335.             domain, dbfile, serial_no, closed));
  336.  
  337.     buildservicelist();
  338.     buildprotolist();
  339.  
  340.     /* init zone data */
  341.  
  342.     zp = &zone;
  343. #ifdef STUBS
  344.     if (stub_only)
  345.         zp->z_type = Z_STUB;
  346.     else
  347. #endif
  348.         zp->z_type = Z_SECONDARY;
  349. #ifdef GEN_AXFR
  350.     zp->z_class = class;
  351. #endif
  352.     zp->z_origin = domain;
  353.     zp->z_source = dbfile;
  354.     zp->z_addrcnt = 0;
  355.     dprintf(1, (ddt, "zone found (%d): \"%s\", source = %s\n",
  356.             zp->z_type,
  357.             (zp->z_origin[0] == '\0')
  358.             ? "."
  359.                 : zp->z_origin,
  360.             zp->z_source));
  361.  
  362.     for (;  optind != argc;  optind++, zp->z_addrcnt++) {
  363.         tm = argv[optind];
  364.         if (!inet_aton(tm, &zp->z_addr[zp->z_addrcnt])) {
  365.             hp = gethostbyname(tm);
  366.             if (hp == NULL) {
  367.                 syslog(LOG_NOTICE,
  368.                        "uninterpretable server (%s) for %s\n",
  369.                        tm, zp->z_origin);
  370.                 zp->z_addrcnt--;    /* hack */
  371.                 continue;
  372.             }
  373.             bcopy(hp->h_addr,
  374.                   (char *)&zp->z_addr[zp->z_addrcnt],
  375.                   INADDRSZ);
  376.             dprintf(1, (ddt, "Arg: \"%s\"\n", tm));
  377.         }
  378.         if (zp->z_addr[zp->z_addrcnt].s_addr == 0) {
  379.             syslog(LOG_NOTICE,
  380.                    "SOA query to localhost (%s) for %s",
  381.                    tm, zp->z_origin);
  382.             zp->z_addrcnt--;    /* hack */
  383.             continue;
  384.         }
  385.         if (zp->z_addrcnt >= NSMAX) {
  386.             zp->z_addrcnt = NSMAX;
  387.             dprintf(1, (ddt, "NSMAX reached\n"));
  388.             break;
  389.         }
  390.     }
  391.     dprintf(1, (ddt, "addrcnt = %d\n", zp->z_addrcnt));
  392.  
  393.     _res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE);
  394.     result = getzone(zp, serial_no, port);
  395.     (void) my_fclose(dbfp);
  396.     switch (result) {
  397.  
  398.     case XFER_SUCCESS:            /* ok exit */
  399.         if (rename(tmpname, dbfile) == -1) {
  400.             perror("rename");
  401.             if (!quiet)
  402.                 syslog(LOG_ERR, "rename %s to %s: %m",
  403.                 tmpname, dbfile);
  404.             exit(XFER_FAIL);
  405.         }
  406.         exit(XFER_SUCCESS);
  407.  
  408.     case XFER_UPTODATE:        /* the zone was already uptodate */
  409.         (void) unlink(tmpname);
  410.         exit(XFER_UPTODATE);
  411.  
  412.     case XFER_TIMEOUT:
  413. #ifdef DEBUG
  414.         if (!debug)
  415. #endif
  416.             (void) unlink(tmpname);
  417.         exit(XFER_TIMEOUT);    /* servers not reachable exit */
  418.  
  419.     case XFER_FAIL:
  420.     default:
  421. #ifdef DEBUG
  422.         if (!debug)
  423. #endif
  424.             (void) unlink(tmpname);
  425.         exit(XFER_FAIL);    /* yuck exit */
  426.     }
  427.     /*NOTREACHED*/
  428. }
  429.  
  430. static char *UsageText[] = {
  431.     "\t-z zone_to_transfer\n",
  432.     "\t-f db_file\n",
  433.     "\t-s serial_no\n",
  434.     "\t[-d debug_level]\n",
  435.     "\t[-l debug_log_file]\n",
  436.     "\t[-t trace_file]\n",
  437.     "\t[-p port]\n",
  438. #ifdef STUBS
  439.     "\t[-S]\n",
  440. #endif
  441. #ifdef GEN_AXFR
  442.     "\t[-C class]\n",
  443. #endif
  444.     "\tservers...\n",
  445.     NULL
  446. };
  447.  
  448. static void
  449. usage(msg)
  450.     const char *msg;
  451. {
  452.     char * const *line;
  453.  
  454.     fprintf(stderr, "Usage error: %s\n", msg);
  455.     fprintf(stderr, "Usage: %s\n", ProgName);
  456.     for (line = UsageText;  *line;  line++)
  457.         fputs(*line, stderr);
  458.     exit(XFER_FAIL);
  459. }
  460.  
  461. #define DEF_DNAME    '\001'        /* '\0' means the root domain */
  462. /* XXX: The following variables should probably all be "static" */
  463. int    minimum_ttl = 0, got_soa = 0;
  464. int    prev_comment = 0;        /* was previous record a comment? */
  465. char    zone_top[MAXDNAME];        /* the top of the zone */
  466. char    prev_origin[MAXDNAME];        /* from most recent $ORIGIN line */
  467. char    prev_dname[MAXDNAME] = { DEF_DNAME };    /* from previous record */
  468. char    prev_ns_dname[MAXDNAME] = { DEF_DNAME }; /* from most recent NS record */
  469.  
  470. static int
  471. getzone(zp, serial_no, port)
  472.     struct zoneinfo *zp;
  473.     u_int32_t serial_no;
  474.     int port;
  475. {
  476.     HEADER *hp;
  477.     u_int16_t len;
  478.     u_int32_t serial;
  479.     int s, n, l, cnt, nscnt, soacnt, error = 0;
  480.      u_char *cp, *nmp, *eom, *tmp ;
  481.     u_char *buf = NULL;
  482.     int bufsize;
  483.     char name[MAXDNAME], name2[MAXDNAME];
  484.     struct sockaddr_in sin;
  485.     struct zoneinfo zp_start, zp_finish;
  486. #ifdef POSIX_SIGNALS
  487.     struct sigaction sv, osv;
  488. #else
  489.     struct sigvec sv, osv;
  490. #endif
  491.     int ancount, aucount;
  492.     int Class;
  493. #ifdef DEBUG
  494.     if (debug) {
  495.         (void)fprintf(ddt,"getzone() %s ", zp->z_origin);
  496.         switch (zp->z_type) {
  497.         case Z_STUB:
  498.             fprintf(ddt,"stub\n");
  499.             break;
  500.         case Z_SECONDARY:
  501.             fprintf(ddt,"secondary\n");
  502.             break;
  503.         default:
  504.             fprintf(ddt,"unknown type\n");
  505.         }
  506.     }
  507. #endif
  508. #ifdef POSIX_SIGNALS
  509.     sv.sa_handler = read_alarm;
  510.     /* SA_ONSTACK isn't recommended for strict POSIX code */
  511.     /* is it absolutely necessary? */
  512.     /* sv.sa_flags = SA_ONSTACK; */
  513.     sigfillset(&sv.sa_mask);
  514.     (void) sigaction(SIGALRM, &sv, &osv);
  515. #else
  516.     sv.sv_handler = read_alarm;
  517.     sv.sv_onstack = 0;
  518.     sv.sv_mask = ~0;
  519.     (void) sigvec(SIGALRM, &sv, &osv);
  520. #endif
  521.  
  522.     strcpy(zone_top, zp->z_origin);
  523.     if ((l = strlen(zone_top)) != 0 && zone_top[l - 1] == '.')
  524.         zone_top[l - 1] = '\0';
  525.     strcpy(prev_origin, zone_top);
  526.  
  527.     for (cnt = 0; cnt < zp->z_addrcnt; cnt++) {
  528. #ifdef GEN_AXFR
  529.         Class = zp->z_class;
  530. #else
  531.         Class = C_IN;
  532. #endif
  533.         error = 0;
  534.         if (buf == NULL) {
  535.             if ((buf = (u_char *)malloc(2 * PACKETSZ)) == NULL) {
  536.                 syslog(LOG_ERR, "malloc(%u) failed",
  537.                        2 * PACKETSZ);
  538.                 error++;
  539.                 break;
  540.             }
  541.             bufsize = 2 * PACKETSZ;
  542.         }
  543.         bzero((char *)&sin, sizeof(sin));
  544.         sin.sin_family = AF_INET;
  545.         sin.sin_port = (u_int16_t)port;
  546.         sin.sin_addr = zp->z_addr[cnt];
  547.         if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  548.             syslog(LOG_ERR, "socket: %m");
  549.             error++;
  550.             break;
  551.         }    
  552.         dprintf(2, (ddt, "connecting to server #%d [%s].%d\n",
  553.                 cnt+1, inet_ntoa(sin.sin_addr),
  554.                 ntohs(sin.sin_port)));
  555.         if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
  556.             syslog(LOG_ERR, "connect(%s) failed: %m",
  557.                    inet_ntoa(sin.sin_addr));
  558.             error++;
  559.             (void) my_close(s);
  560.             continue;
  561.         }    
  562. tryagain:
  563.         n = res_mkquery(QUERY, zp->z_origin, Class,
  564.                 T_SOA, NULL, 0, NULL, buf, bufsize);
  565.         if (n < 0) {
  566.             if (!quiet)
  567.                 syslog(LOG_NOTICE,
  568.                        "zone %s: res_mkquery T_SOA failed",
  569.                        zp->z_origin);
  570.             (void) my_close(s);
  571. #ifdef POSIX_SIGNALS
  572.             (void) sigaction(SIGALRM, &osv, (struct sigaction *)0);
  573. #else
  574.             (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
  575. #endif
  576.             return (XFER_FAIL);
  577.         }
  578.         /*
  579.          * Send length & message for SOA query
  580.          */
  581.         if (writemsg(s, buf, n) < 0) {
  582.             syslog(LOG_ERR, "writemsg: %m");
  583.             error++;
  584.             (void) my_close(s);
  585.             continue;    
  586.         }
  587.         /*
  588.          * Get out your butterfly net and catch the SOA
  589.          */
  590.         if (netread(s, (char *)buf, INT16SZ, XFER_TIMER) < 0) {
  591.             error++;
  592.             (void) my_close(s);
  593.             continue;
  594.         }
  595.         if ((len = _getshort(buf)) == 0) {
  596.             (void) my_close(s);
  597.             continue;
  598.         }
  599.         if (len > bufsize) {
  600.             if ((buf = (u_char *)realloc(buf, len)) == NULL) {
  601.                 syslog(LOG_ERR,
  602.                "malloc(%u) failed for SOA from server [%s], zone %s\n",
  603.                        len,
  604.                        inet_ntoa(sin.sin_addr),
  605.                        zp->z_origin);
  606.                 (void) my_close(s);
  607.                 continue;
  608.             }
  609.             bufsize = len;
  610.         }
  611.         if (netread(s, (char *)buf, len, XFER_TIMER) < 0) {
  612.             error++;
  613.             (void) my_close(s);
  614.             continue;
  615.         }
  616. #ifdef DEBUG
  617.         if (debug >= 3) {
  618.             (void)fprintf(ddt,"len = %d\n", len);
  619.             fp_query(buf, ddt);
  620.         }
  621. #endif
  622.         hp = (HEADER *) buf;
  623.         ancount = ntohs(hp->ancount);
  624.         aucount = ntohs(hp->nscount);
  625.  
  626.         /*
  627.          * close socket if:
  628.          *  1) rcode != NOERROR
  629.          *  2) not an authority response
  630.          *  3) both the number of answers and authority count < 1)
  631.          */
  632.         if (hp->rcode != NOERROR || !(hp->aa) || 
  633.             (ancount < 1 && aucount < 1)) {
  634. #ifndef GEN_AXFR
  635.             if (Class == C_IN) {
  636.                 dprintf(1, (ddt, "SOA failed, trying C_HS\n"));
  637.                 Class = C_HS;
  638.                 goto tryagain;
  639.             }
  640. #endif
  641.             syslog(LOG_NOTICE,
  642.         "%s from [%s], zone %s: rcode %d, aa %d, ancount %d, aucount %d\n",
  643.                    "bad response to SOA query",
  644.                    inet_ntoa(sin.sin_addr), zp->z_origin,
  645.                    hp->rcode, hp->aa, ancount, aucount);
  646.             error++;
  647.             (void) my_close(s);
  648.             continue;
  649.         }
  650.         zp_start = *zp;
  651.         if (len < HFIXEDSZ + QFIXEDSZ) {
  652.     badsoa:
  653.             syslog(LOG_NOTICE,
  654.                    "malformed SOA from [%s], zone %s: too short\n",
  655.                    inet_ntoa(sin.sin_addr), zp->z_origin);
  656.             error++;
  657.             (void) my_close(s);
  658.             continue;
  659.         }
  660.         tmp = buf + HFIXEDSZ;
  661.         eom = buf + len;
  662.         if ((n = dn_skipname(tmp, eom)) == -1)
  663.             goto badsoa;
  664.         tmp += n + QFIXEDSZ;
  665.         if ((n = dn_skipname(tmp, eom)) == -1)
  666.             goto badsoa;
  667.         tmp += n;
  668.         if (soa_zinfo(&zp_start, tmp, eom) == -1)
  669.             goto badsoa;
  670.         if (SEQ_GT(zp_start.z_serial, serial_no) || !serial_no) {
  671.             dprintf(1, (ddt, "need update, serial %d\n",
  672.                     zp_start.z_serial));
  673.             hp = (HEADER *) buf;
  674.             soacnt = 0;
  675.             nscnt = 0;
  676.             gettime (&tt);
  677.             (void) fprintf (dbfp, "; zone '%s'   last serial %lu\n",
  678.                     domain, serial_no);
  679.             (void) fprintf (dbfp, "; from %s   at %s",
  680.                     inet_ntoa (sin.sin_addr),
  681.                     ctime (&tt.tv_sec));
  682.             for (;;) {
  683.                 if ((soacnt == 0) || (zp->z_type == Z_STUB)) {
  684.                     int type;
  685. #ifdef STUBS
  686.                     if (zp->z_type == Z_STUB) {
  687.                         if (!soacnt)
  688.                             type = T_SOA;
  689.                         else if (!nscnt)
  690.                             type = T_NS;
  691.                         else 
  692.                             type = T_SOA;
  693.                     } else
  694. #endif
  695.                         type = T_AXFR;
  696.                     n = res_mkquery(QUERY, zp->z_origin,
  697.                             Class, type, NULL, 0,
  698.                             NULL, buf, bufsize);
  699.                     if (n < 0) {
  700.                         if (!quiet) {
  701. #ifdef STUBS
  702.                             if (zp->z_type == Z_STUB)
  703.                             syslog(LOG_NOTICE,
  704.                                    (type == T_SOA)
  705.                     ? "zone %s: res_mkquery T_SOA failed"
  706.                     : "zone %s: res_mkquery T_NS failed",
  707.                                    zp->z_origin);
  708.                             else
  709. #endif
  710.                             syslog(LOG_NOTICE,
  711.                       "zone %s: res_mkquery T_AXFR failed",
  712.                                    zp->z_origin);
  713.                         }
  714.                         (void) my_close(s);
  715. #ifdef POSIX_SIGNALS
  716.                         sigaction(SIGALRM, &osv,
  717.                             (struct sigaction *)0);
  718. #else
  719.                         sigvec(SIGALRM, &osv,
  720.                                (struct sigvec *)0);
  721. #endif
  722.                         return (XFER_FAIL);
  723.                     }
  724.                     /*
  725.                      * Send length & msg for zone transfer
  726.                      */
  727.                     if (writemsg(s, buf, n) < 0) {
  728.                         syslog(LOG_ERR,"writemsg: %m");
  729.                         error++;
  730.                         (void) my_close(s);
  731.                         break;    
  732.                     }
  733.                 }
  734.                 /*
  735.                  * Receive length & response
  736.                  */
  737.                 if (netread(s, (char *)buf, INT16SZ,
  738.                         (soacnt == 0) ?300 :XFER_TIMER)
  739.                     < 0) {
  740.                     error++;
  741.                     break;
  742.                 }
  743.                 if ((len = _getshort(buf)) == 0)
  744.                     break;
  745.                 eom = buf + len;
  746.                 if (netread(s, (char *)buf, len, XFER_TIMER)
  747.                     < 0) {
  748.                     error++;
  749.                     break;
  750.                 }
  751. #ifdef DEBUG
  752.                 if (debug >= 3) {
  753.                     (void)fprintf(ddt,"len = %d\n", len);
  754.                     fp_query(buf, ddt);
  755.                 }
  756.                 if (fp)
  757.                     fp_query(buf, fp);
  758. #endif
  759.                 if (len < HFIXEDSZ) {
  760.         badrec:
  761.                     error++;
  762.                     syslog(LOG_NOTICE,
  763.                        "record too short from [%s], zone %s\n",
  764.                            inet_ntoa(sin.sin_addr),
  765.                            zp->z_origin);
  766.                     break;
  767.                 }
  768.                 cp = buf + HFIXEDSZ;
  769.                 if (hp->qdcount) {
  770.                     if ((n = dn_skipname(cp, eom)) == -1
  771.                         || n + QFIXEDSZ >= eom - cp)
  772.                         goto badrec;
  773.                     cp += n + QFIXEDSZ;
  774.                 }
  775.                 nmp = cp;
  776.                 if ((n = dn_skipname(cp, eom)) == -1)
  777.                     goto badrec;
  778.                 tmp = cp + n;
  779. #ifdef STUBS
  780.             if (zp->z_type == Z_STUB) {
  781.                 ancount = ntohs(hp->ancount);
  782.                 for (cnt = 0 ; cnt < ancount ; cnt++) {
  783.  
  784.                     n = print_output(buf, bufsize, cp);
  785.                     cp += n;
  786.                 }
  787.                 if (hp->nscount) {
  788.                     /* we should not get here */
  789.                     ancount = ntohs(hp->nscount);
  790.                     for (cnt = 0 ; cnt < ancount ; cnt++) {
  791.                         n = print_output(buf, bufsize, cp);
  792.                         cp += n;
  793.                     }
  794.                 }
  795.                 ancount = ntohs(hp->arcount);
  796.                 for (cnt = 0 ; cnt < ancount ; cnt ++) {
  797.                     n = print_output(buf, bufsize, cp);
  798.                     cp += n;
  799.                 }
  800.                 if (cp != eom) {
  801.                     syslog(LOG_ERR,
  802.                      "print_output: short answer (%d, %d), zone %s",
  803.                            cp - buf, n, zp->z_origin);
  804.                     error++;
  805.                     break;
  806.                 }
  807.         
  808.             } else {
  809. #endif /*STUBS*/
  810.                 n = print_output(buf, bufsize, cp);
  811.                 if (cp + n != eom) {
  812.                     syslog(LOG_ERR,
  813.                      "print_output: short answer (%d, %d), zone %s",
  814.                            cp - buf, n, zp->z_origin);
  815.                     error++;
  816.                     break;
  817.                 }
  818. #ifdef STUBS
  819.             }
  820. #endif
  821.             GETSHORT(n, tmp);
  822.             if (n == T_SOA) {
  823.                 if (soacnt == 0) {
  824.                     soacnt++;
  825.                     if (dn_expand(buf, buf + 512, nmp,
  826.                               name, sizeof name) == -1)
  827.                         goto badsoa;
  828.                     if (eom - tmp
  829.                         <= 2 * INT16SZ
  830.                            + INT32SZ) {
  831.                         goto badsoa;
  832.                     }
  833.                     tmp += 2 * INT16SZ
  834.                            + INT32SZ;
  835.                     if ((n = dn_skipname(tmp, eom)) == -1)
  836.                         goto badsoa;
  837.                     tmp += n;
  838.                     if ((n = dn_skipname(tmp, eom)) == -1)
  839.                         goto badsoa;
  840.                     tmp += n;
  841.                     if (eom - tmp <= INT32SZ)
  842.                         goto badsoa;
  843.                     GETLONG(serial, tmp);
  844.                     dprintf(3, (ddt,
  845.                            "first SOA for %s, serial %d\n",
  846.                             name, serial));
  847.                     continue;
  848.                 }
  849.                 if (dn_expand(buf, buf + 512, nmp,
  850.                           name2, sizeof name2) == -1)
  851.                     goto badsoa;
  852.                 if (strcasecmp((char *)name,
  853.                            (char *)name2) != 0) {
  854.                     dprintf(2, (ddt,
  855.                             "extraneous SOA for %s\n",
  856.                             name2));
  857.                     continue;
  858.                 }
  859.                 tmp -= INT16SZ;
  860.                 if (soa_zinfo(&zp_finish, tmp, eom) == -1)
  861.                     goto badsoa;
  862.                 dprintf(2, (ddt,
  863.                         "SOA, serial %d\n",
  864.                         zp_finish.z_serial));
  865.                 if (serial != zp_finish.z_serial) {
  866.                     soacnt = 0;
  867.                     got_soa = 0;
  868.                     minimum_ttl = 0;
  869.                     strcpy(prev_origin, zp->z_origin);
  870.                     prev_dname[0] = DEF_DNAME;
  871.                     dprintf(1, (ddt,
  872.                             "serial changed, restart\n"
  873.                             ));
  874.                     /*
  875.                      * Flush buffer, truncate file
  876.                      * and seek to beginning to restart.
  877.                      */
  878.                     fflush(dbfp);
  879.                     if (ftruncate(fileno(dbfp), 0) != 0) {
  880.                         if (!quiet)
  881.                             syslog(LOG_ERR,
  882.                             "ftruncate %s: %m\n",
  883.                             tmpname);
  884.                         return (XFER_FAIL);
  885.                     }
  886.                     fseek(dbfp, 0L, 0);
  887.                 } else
  888.                     break;
  889. #ifdef STUBS
  890.             } else if (zp->z_type == Z_STUB && n == T_NS) {
  891.                 nscnt++;
  892.             } else if (zp->z_type == Z_STUB) {
  893.                 break;
  894. #endif
  895.             }
  896.         }
  897.         (void) my_close(s);
  898.         if (error == 0) {
  899. #ifdef POSIX_SIGNALS
  900.             (void) sigaction(SIGALRM, &osv,
  901.                      (struct sigaction *)0);
  902. #else
  903.             (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
  904. #endif
  905.             return (XFER_SUCCESS);
  906.         }
  907.         dprintf(2, (ddt, "error receiving zone transfer\n"));
  908.         } else if (zp_start.z_serial == serial_no) {
  909.         (void) my_close(s);
  910.         dprintf(1, (ddt,
  911.                 "zone up-to-date, serial %u\n",
  912.                 zp_start.z_serial));
  913.         return (XFER_UPTODATE);
  914.         } else {
  915.         (void) my_close(s);
  916.         if (!quiet)
  917.             syslog(LOG_NOTICE,
  918.               "serial from [%s], zone %s: %u lower than current: %u\n",
  919.                inet_ntoa(sin.sin_addr), zp->z_origin,
  920.                zp_start.z_serial, serial_no);
  921.         return (XFER_FAIL);
  922.         }
  923.     }
  924. #ifdef POSIX_SIGNALS
  925.     (void) sigaction(SIGALRM, &osv, (struct sigaction *)0);
  926. #else
  927.     (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
  928. #endif
  929.     if (error)
  930.         return (XFER_TIMEOUT);
  931.     return (XFER_FAIL);
  932. }
  933.  
  934. /*
  935.  * Set flag saying to read was interrupted
  936.  * used for a read timer
  937.  */
  938. static SIG_FN
  939. read_alarm()
  940. {
  941.     read_interrupted = 1;
  942. }
  943.  
  944. static int
  945. netread(fd, buf, len, timeout)
  946.     int fd;
  947.     register char *buf;
  948.     register int len;
  949.     int timeout;
  950. {
  951.     static const char setitimerStr[] = "setitimer: %m";
  952.     struct itimerval ival, zeroival;
  953.     register int n;
  954. #if defined(sun)
  955.     int retries = 0;
  956. #endif
  957.  
  958.     memset(&zeroival, 0, sizeof zeroival);
  959.     ival = zeroival;
  960.     ival.it_value.tv_sec = timeout;
  961.     while (len > 0) {
  962.         if (setitimer(ITIMER_REAL, &ival, NULL) < 0) {
  963.             syslog(LOG_ERR, setitimerStr);
  964.             return (-1);
  965.         }
  966.         errno = 0;
  967.         n = recv(fd, buf, len, 0);
  968.         if (n <= 0) {
  969.             if (errno == 0) {
  970. #if defined(sun)
  971.                 if (++retries < 42)    /* doug adams */
  972.                     continue;
  973. #endif
  974.                 syslog(LOG_ERR,
  975.                        "recv(len=%d): n=%d && !errno",
  976.                        len, n);
  977.                 return (-1);
  978.             }
  979.             if (errno == EINTR && !read_interrupted) {
  980.                 /* Some other signal returned; ignore it. */
  981.                 continue;
  982.             }
  983.             syslog(LOG_ERR, "recv(len=%d): %m", len);
  984.             return (-1);
  985.         }
  986.         buf += n;
  987.         len -= n;
  988.     }
  989.     if (setitimer(ITIMER_REAL, &zeroival, NULL) < 0) {
  990.         syslog(LOG_ERR, setitimerStr);
  991.         return (-1);
  992.     }
  993.     return (0);
  994. }
  995.  
  996. static int
  997. soa_zinfo(zp, cp, eom)
  998.     register struct zoneinfo *zp;
  999.     register u_char *cp;
  1000.     u_char *eom;
  1001. {
  1002.     register int n;
  1003.  
  1004.     if (eom - cp < 3 * INT16SZ + INT32SZ)
  1005.         return (-1);
  1006.     cp += 3 * INT16SZ + INT32SZ;
  1007.     if ((n = dn_skipname(cp, eom)) == -1)
  1008.         return (-1);
  1009.     cp += n;
  1010.     if ((n = dn_skipname(cp, eom)) == -1)
  1011.         return (-1);
  1012.     cp += n;
  1013.     if (eom - cp < 5 * INT32SZ)
  1014.         return (-1);
  1015.     GETLONG(zp->z_serial, cp);
  1016.     GETLONG(zp->z_refresh, cp);
  1017.     GETLONG(zp->z_retry, cp);
  1018.     GETLONG(zp->z_expire, cp);
  1019.     GETLONG(zp->z_minimum, cp);
  1020.     return (0);
  1021. }
  1022.  
  1023. /*
  1024.  * Parse the message, determine if it should be printed, and if so, print it
  1025.  * in .db file form.
  1026.  * Does minimal error checking on the message content.
  1027.  */
  1028. static int
  1029. print_output(msg, msglen, rrp)
  1030.     u_char *msg;
  1031.     int msglen;
  1032.     u_char *rrp;
  1033. {
  1034.     register u_char *cp;
  1035.     register HEADER *hp = (HEADER *) msg;
  1036.     u_int32_t addr, ttl;
  1037.     int i, j, tab, result, class, type, dlen, n1, n;
  1038.     char data[BUFSIZ];
  1039.     u_char *cp1, *cp2, *temp_ptr;
  1040.     char *cdata, *origin, *proto, dname[MAXDNAME];
  1041.     char *ignore = "";
  1042. #ifdef NO_GLUE
  1043.     int lend, lenn;
  1044. #endif /*NO_GLUE*/
  1045.  
  1046.     cp = rrp;
  1047.     n = dn_expand(msg, msg + msglen, cp, dname, sizeof dname);
  1048.     if (n < 0) {
  1049.         hp->rcode = FORMERR;
  1050.         return (-1);
  1051.     }
  1052.     cp += n;
  1053.     GETSHORT(type, cp);
  1054.     GETSHORT(class, cp);
  1055.     GETLONG(ttl, cp);
  1056.     GETSHORT(dlen, cp);
  1057.  
  1058.     origin = strchr(dname, '.');
  1059.     if (origin == NULL)
  1060.         origin = "";
  1061.     else
  1062.         origin++;    /* move past the '.' */
  1063.     dprintf(3, (ddt,
  1064.             "print_output: dname %s type %d class %d ttl %d\n",
  1065.             dname, type, class, ttl));
  1066.     /*
  1067.      * Convert the resource record data into the internal database format.
  1068.      */
  1069.     switch (type) {
  1070.     case T_A:
  1071.     case T_WKS:
  1072.     case T_HINFO:
  1073.     case T_UINFO:
  1074.     case T_TXT:
  1075.     case T_X25:
  1076.     case T_ISDN:
  1077.     case T_UID:
  1078.     case T_GID:
  1079.         cp1 = cp;
  1080.         n = dlen;
  1081.         cp += n;
  1082.         break;
  1083.  
  1084.     case T_CNAME:
  1085.     case T_MB:
  1086.     case T_MG:
  1087.     case T_MR:
  1088.     case T_NS:
  1089.     case T_PTR:
  1090.         n = dn_expand(msg, msg + msglen, cp, data, sizeof data);
  1091.         if (n < 0) {
  1092.             hp->rcode = FORMERR;
  1093.             return (-1);
  1094.         }
  1095.         cp += n;
  1096.         cp1 = (u_char *)data;
  1097.         n = strlen(data) + 1;
  1098.         break;
  1099.  
  1100.     case T_MINFO:
  1101.     case T_SOA:
  1102.     case T_RP:
  1103.         n = dn_expand(msg, msg + msglen, cp, data, sizeof data);
  1104.         if (n < 0) {
  1105.             hp->rcode = FORMERR;
  1106.             return (-1);
  1107.         }
  1108.         cp += n;
  1109.         n = strlen(data) + 1;
  1110.         cp1 = (u_char *)data + n;
  1111.         n1 = sizeof data - n;
  1112.         if (type == T_SOA)
  1113.             n1 -= 5 * INT32SZ;
  1114.         n = dn_expand(msg, msg + msglen, cp, (char *)cp1, n1);
  1115.         if (n < 0) {
  1116.             hp->rcode = FORMERR;
  1117.             return (-1);
  1118.         }
  1119.         cp += n;
  1120.         cp1 += strlen((char *) cp1) + 1;
  1121.         if (type == T_SOA) {
  1122.             temp_ptr = cp + 4 * INT32SZ;
  1123.             GETLONG(minimum_ttl, temp_ptr);
  1124.             n = 5 * INT32SZ;
  1125.             bcopy((char *) cp, (char *) cp1, n);
  1126.             cp += n;
  1127.             cp1 += n;
  1128.         }
  1129.         n = cp1 - (u_char *)data;
  1130.         cp1 = (u_char *)data;
  1131.         break;
  1132.  
  1133.     case T_MX:
  1134.     case T_AFSDB:
  1135.     case T_RT:
  1136.         /* grab preference */
  1137.         bcopy((char *)cp, data, INT16SZ);
  1138.         cp1 = (u_char *)data + INT16SZ;
  1139.         cp += INT16SZ;
  1140.  
  1141.         /* get name */
  1142.         n = dn_expand(msg, msg + msglen, cp,
  1143.                   (char *)cp1, sizeof data - INT16SZ);
  1144.         if (n < 0)
  1145.             return (-1);
  1146.         cp += n;
  1147.  
  1148.         /* compute end of data */
  1149.         cp1 += strlen((char *) cp1) + 1;
  1150.         /* compute size of data */
  1151.         n = cp1 - (u_char *)data;
  1152.         cp1 = (u_char *)data;
  1153.         break;
  1154.  
  1155.     default:
  1156.         dprintf(3, (ddt, "unknown type %d\n", type));
  1157.         return ((cp - rrp) + dlen);
  1158.     }
  1159.     if (n > MAXDATA) {
  1160.         dprintf(1, (ddt,
  1161.                 "update type %d: %d bytes is too much data\n",
  1162.                 type, n));
  1163.         hp->rcode = NOCHANGE;    /* XXX - FORMERR ??? */
  1164.         return (-1);
  1165.     }
  1166.     cdata = (char *) cp1;
  1167.     result = cp - rrp;
  1168.  
  1169.     /*
  1170.      * Only print one SOA per db file
  1171.      */
  1172.     if (type == T_SOA) {
  1173.         if (got_soa)
  1174.             return (result);
  1175.         else
  1176.             got_soa++;
  1177.     }
  1178.  
  1179. #ifdef NO_GLUE
  1180.     /*
  1181.      * If they are trying to tell us info about something that is
  1182.      * not in the zone that we are transfering, then ignore it!
  1183.      * They don't have the authority to tell us this info.
  1184.      *
  1185.      * We have to do a bit of checking here - the name that we are
  1186.      * checking vs is fully qualified & may be in a subdomain of the
  1187.      * zone in question.  We also need to ignore any final dots.
  1188.      *
  1189.      * If a domain has both NS records and non-NS records, (for
  1190.      * example, NS and MX records), then we should ignore the non-NS
  1191.      * records (except that we should not ignore glue A records).
  1192.      * XXX: It is difficult to do this properly, so we just compare
  1193.      * the current dname with that in the most recent NS record.
  1194.      * This defends against the most common error case,
  1195.      * where the remote server sends MX records soon after the
  1196.      * NS records for a particular domain.  If sent earlier, we lose. XXX
  1197.      */
  1198.      if (!samedomain(dname, domain)) {
  1199.         (void) fprintf(dbfp, "; Ignoring info about %s, not in zone %s.\n",
  1200.             dname, domain);
  1201.         ignore = "; ";
  1202.     } else if (type != T_NS && type != T_A &&
  1203.            strcasecmp(zone_top, dname) != 0 &&
  1204.            strcasecmp(prev_ns_dname, dname) == 0)
  1205.     {
  1206.         (void) fprintf(dbfp, "; Ignoring extra info about %s, invalid after NS delegation.\n",
  1207.             dname);
  1208.         ignore = "; ";
  1209.     }
  1210. #endif /*NO_GLUE*/
  1211.  
  1212.     /*
  1213.      * If the current record is not being ignored, but the
  1214.      * previous record was ignored, then we invalidate information
  1215.      * that might have been altered by ignored records.
  1216.      * (This means that we sometimes output unnecessary $ORIGIN
  1217.      * lines, but that is harmless.)
  1218.      * 
  1219.      * Also update prev_comment now.
  1220.      */
  1221.     if (prev_comment && ignore[0] == '\0') {
  1222.         prev_dname[0] = DEF_DNAME;
  1223.         prev_origin[0] = DEF_DNAME;
  1224.     }
  1225.     prev_comment = (ignore[0] != '\0');
  1226.  
  1227.     /*
  1228.      * set prev_ns_dname if necessary
  1229.      */
  1230.     if (type == T_NS) {
  1231.         (void) strcpy(prev_ns_dname, dname);
  1232.     }
  1233.  
  1234.     /*
  1235.      * If the origin has changed, print the new origin
  1236.      */
  1237.     if (strcasecmp(prev_origin, origin)) {
  1238.         (void) strcpy(prev_origin, origin);
  1239.         (void) fprintf(dbfp, "%s$ORIGIN %s.\n", ignore, origin);
  1240.     }
  1241.     tab = 0;
  1242.  
  1243.     if (strcasecmp(prev_dname, dname)) {
  1244.         /*
  1245.          * set the prev_dname to be the current dname, then cut off all
  1246.          * characters of dname after (and including) the first '.'
  1247.          */
  1248.         char *cutp = strchr(dname, '.');
  1249.  
  1250.         (void) strcpy(prev_dname, dname);
  1251.         if (cutp)
  1252.             *cutp = '\0';
  1253.  
  1254.         if (dname[0] == 0) {
  1255.             if (origin[0] == 0)
  1256.                 (void) fprintf(dbfp, "%s.\t", ignore);
  1257.             else
  1258.                 (void) fprintf(dbfp, "%s.%s.\t",
  1259.                     ignore, origin);    /* ??? */
  1260.         } else
  1261.             (void) fprintf(dbfp, "%s%s\t", ignore, dname);
  1262.         if (strlen(dname) < 8)
  1263.             tab = 1;
  1264.     } else {
  1265.         (void) fprintf(dbfp, "%s\t", ignore);
  1266.         tab = 1;
  1267.     }
  1268.  
  1269.     if (ttl != 0 && ttl != minimum_ttl)
  1270.         (void) fprintf(dbfp, "%d\t", (int) ttl);
  1271.     else if (tab)
  1272.         (void) putc('\t', dbfp);
  1273.  
  1274.     (void) fprintf(dbfp, "%s\t%s\t", p_class(class), p_type(type));
  1275.     cp = (u_char *) cdata;
  1276.  
  1277.     /*
  1278.      * Print type specific data
  1279.      */
  1280.     switch (type) {
  1281.  
  1282.     case T_A:
  1283.         switch (class) {
  1284.         case C_IN:
  1285.         case C_HS:
  1286.             GETLONG(n, cp);
  1287.             n = htonl(n);
  1288.             (void) fprintf(dbfp, "%s",
  1289.                        inet_ntoa(*(struct in_addr *) & n));
  1290.             break;
  1291.         }
  1292.         (void) fprintf(dbfp, "\n");
  1293.         break;
  1294.  
  1295.     case T_CNAME:
  1296.     case T_MB:
  1297.     case T_MG:
  1298.     case T_MR:
  1299.     case T_PTR:
  1300.         if (cp[0] == '\0')
  1301.             (void) fprintf(dbfp, ".\n");
  1302.         else
  1303.             (void) fprintf(dbfp, "%s.\n", cp);
  1304.         break;
  1305.  
  1306.     case T_NS:
  1307.         cp = (u_char *) cdata;
  1308.         if (cp[0] == '\0')
  1309.             (void) fprintf(dbfp, ".\t");
  1310.         else
  1311.             (void) fprintf(dbfp, "%s.", cp);
  1312.         (void) fprintf(dbfp, "\n");
  1313.         break;
  1314.  
  1315.     case T_HINFO:
  1316.     case T_ISDN:
  1317.         cp2 = cp + n;
  1318.         n = *cp++;
  1319.         cp1 = cp + n;
  1320.         if (cp1 > cp2)
  1321.             cp1 = cp2;
  1322.         (void) putc('"', dbfp);
  1323.         while (cp < cp1) {
  1324.             if (*cp == '\0') {
  1325.                 cp = cp1;
  1326.                 break;
  1327.             }
  1328.             if ((*cp == '\n') || (*cp == '"')) {
  1329.                 (void) putc('\\', dbfp);
  1330.             }
  1331.             (void) putc(*cp++, dbfp);
  1332.         }
  1333.         (void) fputs("\" \"", dbfp);
  1334.         n = *cp++;
  1335.         cp1 = cp + n;
  1336.         if (cp1 > cp2)
  1337.             cp1 = cp2;
  1338.         while (cp < cp1) {
  1339.             if (*cp == '\0') {
  1340.                 cp = cp1;
  1341.                 break;
  1342.             }
  1343.             if ((*cp == '\n') || (*cp == '"')) {
  1344.                 (void) putc('\\', dbfp);
  1345.             }
  1346.             (void) putc(*cp++, dbfp);
  1347.         }
  1348.         (void) fputs("\"\n", dbfp);
  1349.         break;
  1350.  
  1351.     case T_SOA:
  1352.         (void) fprintf(dbfp, "%s.", cp);
  1353.         cp += strlen((char *) cp) + 1;
  1354.         (void) fprintf(dbfp, " %s. (\n", cp);
  1355.         cp += strlen((char *) cp) + 1;
  1356.         GETLONG(n, cp);
  1357.         (void) fprintf(dbfp, "%s\t\t%lu", ignore, n);
  1358.         GETLONG(n, cp);
  1359.         (void) fprintf(dbfp, " %lu", n);
  1360.         GETLONG(n, cp);
  1361.         (void) fprintf(dbfp, " %lu", n);
  1362.         GETLONG(n, cp);
  1363.         (void) fprintf(dbfp, " %lu", n);
  1364.         GETLONG(n, cp);
  1365.         (void) fprintf(dbfp, " %lu )\n", n);
  1366.         break;
  1367.  
  1368.     case T_MX:
  1369.     case T_AFSDB:
  1370.     case T_RT:
  1371.         GETSHORT(n, cp);
  1372.         (void) fprintf(dbfp, "%lu", n);
  1373.         (void) fprintf(dbfp, " %s.\n", cp);
  1374.         break;
  1375.  
  1376.     case T_TXT:
  1377.     case T_X25:
  1378.         cp1 = cp + n;
  1379.         (void) putc('"', dbfp);
  1380.         while (cp < cp1) {
  1381.             if (i = *cp++) {
  1382.                 for (j = i ; j > 0 && cp < cp1 ; j--) {
  1383.                     if ((*cp == '\n') || (*cp == '"')) {
  1384.                         (void) putc('\\', dbfp);
  1385.                     }
  1386.                     (void) putc(*cp++, dbfp);
  1387.                 }
  1388.             }
  1389.         }
  1390.         (void) fputs("\"\n", dbfp);
  1391.         break;
  1392.  
  1393.     case T_NSAP:
  1394.         fprintf(dbfp, "%s\n", inet_nsap_ntoa(n, cp, NULL));
  1395.         break;
  1396.  
  1397.     case T_UINFO:
  1398.         (void) fprintf(dbfp, "\"%s\"\n", cp);
  1399.         break;
  1400.  
  1401.     case T_UID:
  1402.     case T_GID:
  1403.         if (n == INT32SZ) {
  1404.             GETLONG(n, cp);
  1405.             (void) fprintf(dbfp, "%lu\n", n);
  1406.         }
  1407.         break;
  1408.  
  1409.     case T_WKS:
  1410.         GETLONG(addr, cp);
  1411.         addr = htonl(addr);
  1412.         (void) fprintf(dbfp, "%s ",
  1413.                    inet_ntoa(*(struct in_addr *) & addr));
  1414.         proto = protocolname(*cp);
  1415.         cp += sizeof(char);
  1416.         (void) fprintf(dbfp, "%s ", proto);
  1417.         i = 0;
  1418.         while (cp < (u_char *) cdata + n) {
  1419.             j = *cp++;
  1420.             do {
  1421.                 if (j & 0200)
  1422.                     (void) fprintf(dbfp, " %s",
  1423.                         servicename(i, proto));
  1424.                 j <<= 1;
  1425.             } while (++i & 07);
  1426.         }
  1427.         (void) fprintf(dbfp, "\n");
  1428.         break;
  1429.  
  1430.     case T_MINFO:
  1431.     case T_RP:
  1432.         (void) fprintf(dbfp, "%s.", cp);
  1433.         cp += strlen((char *) cp) + 1;
  1434.         (void) fprintf(dbfp, " %s.\n", cp);
  1435.         break;
  1436.  
  1437.     default:
  1438.         (void) fprintf(dbfp, "???\n");
  1439.     }
  1440.     if (ferror(dbfp)) {
  1441.         syslog(LOG_ERR, "%s: %m", tmpname);
  1442.         exit(XFER_FAIL);
  1443.     }
  1444.     return (result);
  1445. }
  1446.  
  1447. #ifdef SHORT_FNAMES
  1448. /*
  1449. ** This routine handles creating temporary files with mkstemp
  1450. ** in the presence of a 14 char filename system.  Pathconf()
  1451. ** does not work over NFS.
  1452. */
  1453. filenamecpy(ddtfile, optarg)
  1454. char *ddtfile, *optarg;
  1455. {
  1456.     int namelen, extra, len;
  1457.     char *dirname, *filename;
  1458.  
  1459.     /* determine the length of filename allowed */
  1460.     if((dirname = strrchr(optarg, '/')) == NULL){
  1461.         filename = optarg;
  1462.     } else {
  1463.         *dirname++ = '\0';
  1464.         filename = dirname;
  1465.     }
  1466.     namelen = pathconf(dirname == NULL? "." : optarg, _PC_NAME_MAX);
  1467.     if(namelen <= 0)
  1468.         namelen = 255;  /* length could not be determined */
  1469.     if(dirname != NULL)
  1470.         *--dirname = '/';
  1471.  
  1472.     /* copy a shorter name if it will be longer than allowed */
  1473.     extra = (strlen(filename)+strlen(".XXXXXX")) - namelen;
  1474.     if(extra > 0){
  1475.         len = strlen(optarg) - extra;
  1476.         (void) strncpy(ddtfile, optarg, len);
  1477.         ddtfile[len] = '\0';
  1478.     } else
  1479.         (void) strcpy(ddtfile, optarg);
  1480. }
  1481. #endif /* SHORT_FNAMES */
  1482.