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