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 / db_dump.c < prev    next >
C/C++ Source or Header  |  1994-07-22  |  23KB  |  893 lines

  1. #if !defined(lint) && !defined(SABER)
  2. static char sccsid[] = "@(#)db_dump.c    4.33 (Berkeley) 3/3/91";
  3. static char rcsid[] = "$Id: db_dump.c,v 4.9.1.12 1994/07/22 08:42:39 vixie Exp $";
  4. #endif /* not lint */
  5.  
  6. /*
  7.  * ++Copyright++ 1986, 1988, 1990
  8.  * -
  9.  * Copyright (c) 1986, 1988, 1990
  10.  *    The Regents of the University of California.  All rights reserved.
  11.  * 
  12.  * Redistribution and use in source and binary forms, with or without
  13.  * modification, are permitted provided that the following conditions
  14.  * are met:
  15.  * 1. Redistributions of source code must retain the above copyright
  16.  *    notice, this list of conditions and the following disclaimer.
  17.  * 2. Redistributions in binary form must reproduce the above copyright
  18.  *    notice, this list of conditions and the following disclaimer in the
  19.  *    documentation and/or other materials provided with the distribution.
  20.  * 3. All advertising materials mentioning features or use of this software
  21.  *    must display the following acknowledgement:
  22.  *     This product includes software developed by the University of
  23.  *     California, Berkeley and its contributors.
  24.  * 4. Neither the name of the University nor the names of its contributors
  25.  *    may be used to endorse or promote products derived from this software
  26.  *    without specific prior written permission.
  27.  * 
  28.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  29.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  30.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  31.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  32.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  33.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  34.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  37.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  38.  * SUCH DAMAGE.
  39.  * -
  40.  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  41.  * 
  42.  * Permission to use, copy, modify, and distribute this software for any
  43.  * purpose with or without fee is hereby granted, provided that the above
  44.  * copyright notice and this permission notice appear in all copies, and that
  45.  * the name of Digital Equipment Corporation not be used in advertising or
  46.  * publicity pertaining to distribution of the document or software without
  47.  * specific, written prior permission.
  48.  * 
  49.  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  50.  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
  51.  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
  52.  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  53.  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  54.  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  55.  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  56.  * SOFTWARE.
  57.  * -
  58.  * --Copyright--
  59.  */
  60.  
  61. #include <sys/param.h>
  62. #include <sys/stat.h>
  63. #include <netinet/in.h>
  64. #include <arpa/nameser.h>
  65. #include <arpa/inet.h>
  66. #include <netdb.h>
  67. #include <stdio.h>
  68. #include <syslog.h>
  69. #include <resolv.h>
  70. #include <errno.h>
  71.  
  72. #include "named.h"
  73.  
  74. static int        scan_root __P((struct hashbuf *));
  75. static const char    *MkCredStr __P((int));
  76.  
  77. #ifdef ALLOW_T_UNSPEC
  78. static void        putbyte __P((int, char **));
  79. #endif
  80.  
  81. /*
  82.  * Dump current cache in a format similar to RFC 883.
  83.  *
  84.  * We try to be careful and determine whether the operation succeeded
  85.  * so that the new cache file can be installed.
  86.  */
  87.  
  88. void
  89. doachkpt()
  90. {
  91.     FILE *fp;
  92.     char tmpcheckfile[256];
  93.  
  94.     /* nowhere to checkpoint cache... */
  95.     if (cache_file == NULL) {
  96.     dprintf(3, (ddt, "skipping doachkpt (cache_file == NULL)\n"));
  97.         return;
  98.     }
  99.  
  100.     dprintf(3, (ddt, "doachkpt()\n"));
  101.  
  102.     (void) sprintf(tmpcheckfile, "%s.chk", cache_file);
  103.     if ((fp = fopen(tmpcheckfile, "w")) == NULL) {
  104.     dprintf(3, (ddt,
  105.             "doachkpt(can't open %s for write)\n", tmpcheckfile));
  106.         return;
  107.     }
  108.  
  109.     (void) gettime(&tt);
  110.     fprintf(fp, "; Dumped at %s", ctime(&tt.tv_sec));
  111.     fflush(fp);
  112.     if (ferror(fp)) {
  113.     dprintf(3, (ddt, "doachkpt(write to checkpoint file failed)\n"));
  114.         return;
  115.     }
  116.  
  117.     if (fcachetab != NULL) {
  118.     int n = scan_root(hashtab);
  119.  
  120.     if (n < MINROOTS) {
  121.         syslog(LOG_ERR, "%d root hints... (too low)", n);
  122.         fprintf(fp, "; ---- Root hint cache dump ----\n");
  123.         (void) db_dump(fcachetab, fp, DB_Z_CACHE, "");
  124.     }
  125.     }
  126.  
  127.     if (hashtab != NULL) {
  128.         fprintf(fp, "; ---- Cache dump ----\n");
  129.         if (db_dump(hashtab, fp, DB_Z_CACHE, "") == NODBFILE) {
  130.         dprintf(3, (ddt, "doachkpt(checkpoint failed)\n"));
  131.             (void) my_fclose(fp);
  132.             return;
  133.         }
  134.     }
  135.  
  136.     (void) fsync(fileno(fp));
  137.     if (my_fclose(fp) == EOF) {
  138.         return;
  139.     }
  140.  
  141.     if (rename(tmpcheckfile, cache_file)) {
  142.     dprintf(3, (ddt, "doachkpt(install %s to %s failed, %d)\n",
  143.             tmpcheckfile, cache_file, errno));
  144.     }
  145. }
  146.  
  147. /*
  148.  * What we do is scan the root hint cache to make sure there are at least
  149.  * MINROOTS root pointers with non-0 TTL's so that the checkpoint will not
  150.  * lose the root.  Failing this, all pointers are written out w/ TTL ~0
  151.  * (root pointers timed out and prime_cache() not done or failed).
  152.  */
  153.  
  154. static int
  155. scan_root(htp)
  156.     struct hashbuf *htp;
  157. {
  158.     register struct databuf *dp;
  159.     register struct namebuf *np;
  160.     struct timeval soon;
  161.     int roots = 0;
  162.  
  163.     dprintf(1, (ddt, "scan_root(0x%x)\n", htp));
  164.  
  165.     /* metric by which we determine whether a root NS pointer is still */
  166.     /* valid (will be written out if we do a dump).  we also add some */
  167.     /* time buffer for safety... */
  168.     (void) gettime(&soon);
  169.     soon.tv_sec += TIMBUF;
  170.  
  171.     for (np = htp->h_tab[0]; np != NULL; np = np->n_next) {
  172.         if (np->n_dname[0] == '\0') {
  173.             dp = np->n_data;
  174.             while (dp != NULL) {
  175.                 if (dp->d_type == T_NS &&
  176.                     dp->d_ttl > soon.tv_sec) {
  177.                     roots++;
  178.                     if (roots >= MINROOTS)
  179.                         return (roots);
  180.                 }
  181.                 dp = dp->d_next;
  182.             }
  183.         }
  184.     }
  185.     return (roots);
  186. }
  187.  
  188. #ifdef notdef
  189. mark_cache(htp, ttl)
  190.     struct hashbuf *htp;
  191.     int ttl;
  192. {
  193.     register struct databuf *dp;
  194.     register struct namebuf *np;
  195.     struct namebuf **npp, **nppend;
  196.     struct timeval soon;
  197.  
  198.     dprintf(1, (ddt, "mark_cache()\n"));
  199.  
  200.     (void) gettime(&soon);
  201.     soon.tv_sec += TIMBUF;
  202.  
  203.     npp = htp->h_tab;
  204.     nppend = npp + htp->h_size;
  205.     while (npp < nppend) {
  206.         for (np = *npp++; np != NULL; np = np->n_next) {
  207.             if (np->n_data == NULL)
  208.                 continue;
  209.             for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
  210.                 if (dp->d_ttl < soon.tv_sec)
  211.                     dp->d_ttl = ttl;
  212.             }
  213.         }
  214.     }
  215.  
  216.     npp = htp->h_tab;
  217.     nppend = npp + htp->h_size;
  218.     while (npp < nppend) {
  219.         for (np = *npp++; np != NULL; np = np->n_next) {
  220.             if (np->n_hash == NULL)
  221.                 continue;
  222.             mark_cache(np->n_hash, ttl);
  223.         }
  224.     }
  225. }
  226. #endif /* notdef */
  227.  
  228. /*
  229.  * Dump current data base in a format similar to RFC 883.
  230.  */
  231.  
  232. void
  233. doadump()
  234. {
  235.     FILE    *fp;
  236.  
  237.     dprintf(3, (ddt, "doadump()\n"));
  238.  
  239.     if ((fp = fopen(dumpfile, "w")) == NULL)
  240.         return;
  241.     gettime(&tt);
  242.     fprintf(fp, "; Dumped at %s", ctime(&tt.tv_sec));
  243.     if (zones && nzones)
  244.         zt_dump(fp);
  245.     fputs(
  246. "; Note: Cr=(auth,answer,addtnl,cache) tag only shown for non-auth RR's\n",
  247.           fp);
  248.     fputs(
  249. "; Note: NT=milliseconds for any A RR which we've used as a nameserver\n",
  250.           fp);
  251.     fprintf(fp, "; --- Cache & Data ---\n");
  252.     if (hashtab != NULL)
  253.         (void) db_dump(hashtab, fp, DB_Z_ALL, "");
  254.     fprintf(fp, "; --- Hints ---\n");
  255.     if (fcachetab != NULL)
  256.         (void) db_dump(fcachetab, fp, DB_Z_ALL, "");
  257.     (void) my_fclose(fp);
  258. }
  259.  
  260. #ifdef ALLOW_UPDATES
  261. /* Create a disk database to back up zones 
  262.  */
  263. void
  264. zonedump(zp)
  265.     register struct zoneinfo *zp;
  266. {
  267.     FILE        *fp;
  268.     char        *fname;
  269.     struct hashbuf    *htp;
  270.     char        *op;
  271.     struct stat    st;
  272.  
  273.     /* Only dump zone if there is a cache specified */
  274.     if (zp->z_source && *(zp->z_source)) {
  275.         dprintf(1, (ddt, "zonedump(%s)\n", zp->z_source));
  276.  
  277.         if ((fp = fopen(zp->z_source, "w")) == NULL)
  278.             return;
  279.         if (op = strchr(zp->z_origin, '.'))
  280.         op++;
  281.         gettime(&tt);
  282.         htp = hashtab;
  283.         if (nlookup(zp->z_origin, &htp, &fname, 0) != NULL) {
  284.             db_dump(htp, fp, zp-zones, (op == NULL ? "" : op));
  285.             zp->z_flags &= ~Z_CHANGED;        /* Checkpointed */
  286.         }
  287.         (void) my_fclose(fp);
  288.         if (stat(zp->z_source, &st) == 0)
  289.             zp->z_ftime = st.st_mtime;
  290.     } else {
  291.         dprintf(1, (ddt, "zonedump: no zone to dump\n"));
  292.     }
  293. }
  294. #endif
  295.  
  296. int
  297. zt_dump(fp)
  298.     FILE *fp;
  299. {
  300.     register struct zoneinfo *zp;
  301.  
  302.     fprintf(fp, ";; ++zone table++\n");
  303.         for (zp = &zones[1]; zp < &zones[nzones]; zp++) {
  304.         char *pre, buf[64];
  305.         u_int cnt;
  306.  
  307.         fprintf(fp, "; %s (type %d, class %d, source %s)\n",
  308.             zp->z_origin, zp->z_type, zp->z_class,
  309.             zp->z_source ? zp->z_source : "Nil");
  310.         fprintf(fp, ";\ttime=%ld, lastupdate=%ld, serial=%u,\n",
  311.             zp->z_time, zp->z_lastupdate, zp->z_serial);
  312.         fprintf(fp, ";\trefresh=%u, retry=%u, expire=%u, minimum=%u\n",
  313.             zp->z_refresh, zp->z_retry,
  314.             zp->z_expire, zp->z_minimum);
  315.         fprintf(fp, ";\tftime=%ld, xaddr=[%s], state=%04x, pid=%d\n",
  316.             zp->z_ftime, inet_ntoa(zp->z_xaddr),
  317.             zp->z_flags, zp->z_xferpid);
  318.         sprintf(buf, ";\tz_addr[%d]: ", zp->z_addrcnt);
  319.         pre = buf;
  320.         for (cnt = 0;  cnt < zp->z_addrcnt;  cnt++) {
  321.             fprintf(fp, "%s[%s]", pre, inet_ntoa(zp->z_addr[cnt]));
  322.             pre = ", ";
  323.         }
  324.         if (zp->z_addrcnt)
  325.             fputc('\n', fp);
  326.     }
  327.     fprintf(fp, ";; --zone table--\n");
  328. }
  329.  
  330. int
  331. db_dump(htp, fp, zone, origin)
  332.     struct hashbuf *htp;
  333.     FILE *fp;
  334.     int zone;
  335.     char *origin;
  336. {
  337.     register struct databuf *dp = NULL;
  338.     register struct namebuf *np;
  339.     struct namebuf **npp, **nppend;
  340.     char dname[MAXDNAME];
  341.     u_int32_t n;
  342.     u_int32_t addr;
  343.     int j, i;
  344.     register u_char *cp;
  345.     u_char *end;
  346.     char *proto, *sep;
  347.     int found_data = 0, tab, printed_origin = 0;
  348.  
  349.     npp = htp->h_tab;
  350.     nppend = npp + htp->h_size;
  351.     while (npp < nppend) {
  352.         for (np = *npp++; np != NULL; np = np->n_next) {
  353.         if (np->n_data == NULL)
  354.             continue;
  355.         /* Blecch - can't tell if there is data here for the
  356.          * right zone, so can't print name yet
  357.          */
  358.         found_data = 0;
  359.         /* we want a snapshot in time... */
  360.         for (dp = np->n_data; dp != NULL; dp = dp->d_next) {
  361.             /* Is the data for this zone? */
  362.             if (zone != DB_Z_ALL && dp->d_zone != zone)
  363.                 continue;
  364.             if (dp->d_zone == DB_Z_CACHE &&
  365.                 dp->d_ttl <= tt.tv_sec &&
  366.                 (dp->d_flags & DB_F_HINT) == 0)
  367.                 continue;
  368.             if (!printed_origin) {
  369.                 fprintf(fp, "$ORIGIN %s.\n", origin);
  370.                 printed_origin++;
  371.             }
  372.             tab = 0;
  373. #ifdef NCACHE
  374.             if (dp->d_rcode == NXDOMAIN ||
  375.                 dp->d_rcode == NOERROR_NODATA) {
  376.                 fputc(';', fp);
  377.             } else if (found_data == 0 || found_data == 1) {
  378.                 found_data = 2;
  379.             }
  380. #endif /*NCACHE*/
  381.             if (found_data == 0 || found_data == 2) {
  382.                 if (np->n_dname[0] == 0) {
  383.                 if (origin[0] == 0)
  384.                     fprintf(fp, ".\t");
  385.                 else
  386.                     fprintf(fp, ".%s.\t", origin); /* ??? */
  387.                 } else
  388.                 fprintf(fp, "%s\t", np->n_dname);
  389.                 if (strlen(np->n_dname) < 8)
  390.                 tab = 1;
  391.                 found_data++;
  392.             } else {
  393.                 (void) putc('\t', fp);
  394.                 tab = 1;
  395.             }
  396.             if (dp->d_zone == DB_Z_CACHE) {
  397.                 if (dp->d_flags & DB_F_HINT
  398.                 && (int32_t)(dp->d_ttl - tt.tv_sec)
  399.                     < DB_ROOT_TIMBUF)
  400.                     fprintf(fp, "%d\t", DB_ROOT_TIMBUF);
  401.                 else
  402.                     fprintf(fp, "%d\t",
  403.                         (int)(dp->d_ttl - tt.tv_sec));
  404.             } else if (dp->d_ttl != 0 &&
  405.                 dp->d_ttl != zones[dp->d_zone].z_minimum)
  406.                 fprintf(fp, "%d\t", (int)dp->d_ttl);
  407.             else if (tab)
  408.                 (void) putc('\t', fp);
  409.             fprintf(fp, "%s\t%s\t",
  410.                 p_class(dp->d_class),
  411.                 p_type(dp->d_type));
  412.             cp = (u_char *)dp->d_data;
  413.             sep = "\t;";
  414. #ifdef NCACHE
  415. #ifdef RETURNSOA
  416.             if (dp->d_rcode == NOERROR_NODATA) {
  417.                fprintf(fp, "NODATA%s-$", sep);
  418.                 goto eoln;
  419.             }
  420. #else
  421.             if (dp->d_rcode == NXDOMAIN ||
  422.                 dp->d_rcode == NOERROR_NODATA) {
  423.                 fprintf(fp, "%s%s-$",
  424.                     (dp->d_rcode == NXDOMAIN)
  425.                         ?"NXDOMAIN" :"NODATA",
  426.                     sep);
  427.                 goto eoln;
  428.             }
  429. #endif
  430. #endif
  431.             /*
  432.              * Print type specific data
  433.              */
  434.             switch (dp->d_type) {
  435.             case T_A:
  436.                 switch (dp->d_class) {
  437.                 case C_IN:
  438.                 case C_HS:
  439.                     GETLONG(n, cp);
  440.                     n = htonl(n);
  441.                     fprintf(fp, "%s",
  442.                        inet_ntoa(*(struct in_addr *)&n));
  443.                     break;
  444.                 }
  445.                 if (dp->d_nstime) {
  446.                     fprintf(fp, "%sNT=%d",
  447.                         sep, dp->d_nstime);
  448.                     sep = " ";
  449.                 }
  450.                 break;
  451.             case T_CNAME:
  452.             case T_MB:
  453.             case T_MG:
  454.             case T_MR:
  455.             case T_PTR:
  456.                 fprintf(fp, "%s.", cp);
  457.                 break;
  458.  
  459.             case T_NS:
  460.                 cp = (u_char *)dp->d_data;
  461.                 if (cp[0] == '\0')
  462.                     fprintf(fp, ".\t");
  463.                 else
  464.                     fprintf(fp, "%s.", cp);
  465.                 break;
  466.  
  467.             case T_HINFO:
  468.             case T_ISDN:
  469.                 if (n = *cp++) {
  470.                     fprintf(fp, "\"%.*s\"", (int)n, cp);
  471.                     cp += n;
  472.                 } else
  473.                     fprintf(fp, "\"\"");
  474.                 if (n = *cp++)
  475.                     fprintf(fp, " \"%.*s\"", (int)n, cp);
  476.                 else
  477.                     fprintf(fp, " \"\"");
  478.                 break;
  479.  
  480.             case T_SOA:
  481.                 fprintf(fp, "%s.", cp);
  482.                 cp += strlen((char *)cp) + 1;
  483.                 fprintf(fp, " %s. (\n", cp);
  484. #if defined(RETURNSOA) && defined(NCACHE)
  485.                 if (dp->d_rcode == NXDOMAIN)
  486.                     fputs(";", fp);
  487. #endif
  488.                 cp += strlen((char *)cp) + 1;
  489.                 GETLONG(n, cp);
  490.                 fprintf(fp, "\t\t%lu", n);
  491.                 GETLONG(n, cp);
  492.                 fprintf(fp, " %lu", n);
  493.                 GETLONG(n, cp);
  494.                 fprintf(fp, " %lu", n);
  495.                 GETLONG(n, cp);
  496.                 fprintf(fp, " %lu", n);
  497.                 GETLONG(n, cp);
  498.                 fprintf(fp, " %lu )", n);
  499. #if defined(RETURNSOA) && defined(NCACHE)
  500.                 if (dp->d_rcode == NXDOMAIN) {
  501.                     fprintf(fp,";%s.;NXDOMAIN%s-$",cp,sep);
  502.                 }
  503. #endif
  504.                 break;
  505.  
  506.             case T_MX:
  507.             case T_AFSDB:
  508.             case T_RT:
  509.                 GETSHORT(n, cp);
  510.                 fprintf(fp,"%lu", n);
  511.                 fprintf(fp," %s.", cp);
  512.                 break;
  513.  
  514.             case T_TXT:
  515.             case T_X25:
  516.                 end = (u_char *)dp->d_data + dp->d_size;
  517.                 (void) putc('"', fp);
  518.                 while (cp < end) {
  519.                     if (n = *cp++) {
  520.                     for (j = n ; j > 0 && cp < end ; j--)
  521.                         if (*cp == '\n') {
  522.                         (void) putc('\\', fp);
  523.                         (void) putc(*cp++, fp);
  524.                         } else
  525.                         (void) putc(*cp++, fp);
  526.                     }
  527.                 }
  528.                 (void) fputs("\"", fp);
  529.                 break;
  530.  
  531.             case T_NSAP:
  532.                 (void) fputs(inet_nsap_ntoa(dp->d_size,
  533.                                 dp->d_data, NULL),
  534.                          fp);
  535.                 break;
  536.  
  537.             case T_UINFO:
  538.                 fprintf(fp, "\"%s\"", cp);
  539.                 break;
  540.  
  541.             case T_UID:
  542.             case T_GID:
  543.                 if (dp->d_size == INT32SZ) {
  544.                     GETLONG(n, cp);
  545.                 } else {
  546.                     n = -2;        /* XXX - hack */
  547.                 }
  548.                 fprintf(fp, "%u", n);
  549.                 break;
  550.  
  551.             case T_WKS:
  552.                 GETLONG(addr, cp);    
  553.                 addr = htonl(addr);    
  554.                 fprintf(fp, "%s ",
  555.                     inet_ntoa(*(struct in_addr *)&addr));
  556.                 proto = protocolname(*cp);
  557.                 cp += sizeof(char); 
  558.                 fprintf(fp, "%s ", proto);
  559.                 i = 0;
  560.                 while(cp < (u_char *)dp->d_data + dp->d_size) {
  561.                     j = *cp++;
  562.                     do {
  563.                         if (j & 0200)
  564.                         fprintf(fp, " %s",
  565.                             servicename(i, proto));
  566.                         j <<= 1;
  567.                     } while (++i & 07);
  568.                 } 
  569.                 break;
  570.  
  571.             case T_MINFO:
  572.             case T_RP:
  573.                 fprintf(fp, "%s.", cp);
  574.                 cp += strlen((char *)cp) + 1;
  575.                 fprintf(fp, " %s.", cp);
  576.                 break;
  577. #ifdef ALLOW_T_UNSPEC
  578.             case T_UNSPEC:
  579.                 /* Dump binary data out in an ASCII-encoded
  580.                    format */
  581.                 {
  582.                   /* Allocate more than enough space:
  583.                    *  actually need 5/4 size + 20 or so
  584.                    */
  585.                   int TmpSize = 2 * dp->d_size + 30;
  586.                   char *TmpBuf = (char *) malloc(TmpSize);
  587.                   if (TmpBuf == NULL) {
  588.                     dprintf(1,
  589.                         (ddt,
  590.                          "Dump T_UNSPEC: bad malloc\n"
  591.                          )
  592.                         );
  593.                     syslog(LOG_ERR,
  594.                            "Dump T_UNSPEC: malloc: %m");
  595.                     TmpBuf = "BAD_MALLOC";
  596.                   }
  597.                   if (btoa(cp, dp->d_size, TmpBuf, TmpSize)
  598.                       == CONV_OVERFLOW) {
  599.                     dprintf(1, (ddt,
  600.                       "Dump T_UNSPEC: Output buffer overflow\n"
  601.                             )
  602.                         );
  603.                         syslog(LOG_ERR,
  604.                     "Dump T_UNSPEC: Output buffer overflow\n");
  605.                         TmpBuf = "OVERFLOW";
  606.                     }
  607.                     fprintf(fp, "%s", TmpBuf);
  608.                 }
  609.                 break;
  610. #endif /* ALLOW_T_UNSPEC */
  611.             default:
  612.                 fprintf(fp, "%s?d_type=%d?",
  613.                     sep, dp->d_type);
  614.                 sep = " ";
  615.             }
  616.             if (dp->d_cred < DB_C_ZONE) {
  617.                 fprintf(fp, "%sCr=%s",
  618.                     sep, MkCredStr(dp->d_cred));
  619.                 sep = " ";
  620.             } else {
  621.                 fprintf(fp, "%sCl=%d",
  622.                     sep, dp->d_clev);
  623.                 sep = " ";
  624.             }
  625. eoln:
  626. #ifdef STATS
  627.             if (dp->d_ns) {
  628.                 fprintf(fp, "%s[%s]",
  629.                     sep, inet_ntoa(dp->d_ns->addr));
  630.                 sep = " ";
  631.             }
  632. #endif
  633.             putc('\n', fp);
  634.         }
  635.         }
  636.     }
  637.         if (ferror(fp))
  638.         return(NODBFILE);
  639.  
  640.     npp = htp->h_tab;
  641.     nppend = npp + htp->h_size;
  642.     while (npp < nppend) {
  643.         for (np = *npp++; np != NULL; np = np->n_next) {
  644.         if (np->n_hash == NULL)
  645.             continue;
  646.         getname(np, dname, sizeof(dname));
  647.         if (db_dump(np->n_hash, fp, zone, dname) == NODBFILE)
  648.             return(NODBFILE);
  649.         }
  650.     }
  651.     return(OK);
  652. }
  653.  
  654. static const char *
  655. MkCredStr(cred)
  656.     int cred;
  657. {
  658.     static char badness[20];
  659.  
  660.     switch (cred) {
  661.     case DB_C_ZONE:        return "zone";
  662.     case DB_C_AUTH:        return "auth";
  663.     case DB_C_ANSWER:    return "answer";
  664.     case DB_C_ADDITIONAL:    return "addtnl";
  665.     case DB_C_CACHE:    return "cache";
  666.     default:        break;
  667.     }
  668.     sprintf(badness, "?%d?", cred);
  669.     return (badness);
  670. }
  671.  
  672. #ifdef ALLOW_T_UNSPEC
  673. /*
  674.  * Subroutines to convert between 8 bit binary bytes and printable ASCII.
  675.  * Computes the number of bytes, and three kinds of simple checksums.
  676.  * Incoming bytes are collected into 32-bit words, then printed in base 85:
  677.  *    exp(85,5) > exp(2,32)
  678.  * The ASCII characters used are between '!' and 'u';
  679.  * 'z' encodes 32-bit zero; 'x' is used to mark the end of encoded data.
  680.  *
  681.  * Originally by Paul Rutter (philabs!per) and Joe Orost (petsd!joe) for
  682.  * the atob/btoa programs, released with the compress program, in mod.sources.
  683.  * Modified by Mike Schwartz 8/19/86 for use in BIND.
  684.  */
  685.  
  686. /* Make sure global variable names are unique */
  687. #define Ceor T_UNSPEC_Ceor
  688. #define Csum T_UNSPEC_Csum
  689. #define Crot T_UNSPEC_Crot
  690. #define word T_UNSPEC_word
  691. #define bcount T_UNSPEC_bcount
  692.  
  693. static int32_t Ceor, Csum, Crot, word, bcount;
  694.  
  695. #define EN(c)    ((int) ((c) + '!'))
  696. #define DE(c) ((c) - '!')
  697. #define AddToBuf(bufp, c) **bufp = c; (*bufp)++;
  698. #define times85(x)    ((((((x<<2)+x)<<2)+x)<<2)+x)
  699.  
  700. /* Decode ASCII-encoded byte c into binary representation and 
  701.  * place into *bufp, advancing bufp 
  702.  */
  703. static int
  704. byte_atob(c, bufp)
  705.     register c;
  706.     char **bufp;
  707. {
  708.     if (c == 'z') {
  709.         if (bcount != 0)
  710.             return(CONV_BADFMT);
  711.         else {
  712.             putbyte(0, bufp);
  713.             putbyte(0, bufp);
  714.             putbyte(0, bufp);
  715.             putbyte(0, bufp);
  716.         }
  717.     } else if ((c >= '!') && (c < ('!' + 85))) {
  718.         if (bcount == 0) {
  719.             word = DE(c);
  720.             ++bcount;
  721.         } else if (bcount < 4) {
  722.             word = times85(word);
  723.             word += DE(c);
  724.             ++bcount;
  725.         } else {
  726.             word = times85(word) + DE(c);
  727.             putbyte((int)((word >> 24) & 255), bufp);
  728.             putbyte((int)((word >> 16) & 255), bufp);
  729.             putbyte((int)((word >> 8) & 255), bufp);
  730.             putbyte((int)(word & 255), bufp);
  731.             word = 0;
  732.             bcount = 0;
  733.         }
  734.     } else
  735.         return(CONV_BADFMT);
  736.     return(CONV_SUCCESS);
  737. }
  738.  
  739. /* Compute checksum info and place c into *bufp, advancing bufp */
  740. static void
  741. putbyte(c, bufp)
  742.     register c;
  743.     char **bufp;
  744. {
  745.     Ceor ^= c;
  746.     Csum += c;
  747.     Csum += 1;
  748.     if ((Crot & 0x80000000)) {
  749.         Crot <<= 1;
  750.         Crot += 1;
  751.     } else {
  752.         Crot <<= 1;
  753.     }
  754.     Crot += c;
  755.     AddToBuf(bufp, c);
  756. }
  757.  
  758. /* Read the ASCII-encoded data from inbuf, of length inbuflen, and convert
  759.    it into T_UNSPEC (binary data) in outbuf, not to exceed outbuflen bytes;
  760.    outbuflen must be divisible by 4.  (Note: this is because outbuf is filled
  761.    in 4 bytes at a time.  If the actual data doesn't end on an even 4-byte
  762.    boundary, there will be no problem...it will be padded with 0 bytes, and
  763.    numbytes will indicate the correct number of bytes.  The main point is
  764.    that since the buffer is filled in 4 bytes at a time, even if there is
  765.    not a full 4 bytes of data at the end, there has to be room to 0-pad the
  766.    data, so the buffer must be of size divisible by 4).  Place the number of
  767.    output bytes in numbytes, and return a failure/success status  */
  768. int
  769. atob(inbuf, inbuflen, outbuf, outbuflen, numbytes)
  770.     char *inbuf;
  771.     int inbuflen;
  772.     char *outbuf;
  773.     int outbuflen;
  774.     int *numbytes;
  775. {
  776.     int inc, nb;
  777.     int32_t oeor, osum, orot;
  778.     char *inp, *outp = outbuf, *endoutp = &outbuf[outbuflen];
  779.  
  780.     if ( (outbuflen % 4) != 0)
  781.         return(CONV_BADBUFLEN);
  782.     Ceor = Csum = Crot = word = bcount = 0;
  783.     for (inp = inbuf, inc = 0; inc < inbuflen; inp++, inc++) {
  784.         if (outp > endoutp)
  785.             return(CONV_OVERFLOW);
  786.         if (*inp == 'x') {
  787.             inp +=2;
  788.             break;
  789.         } else {
  790.             if (byte_atob(*inp, &outp) == CONV_BADFMT)
  791.                 return(CONV_BADFMT);
  792.         }
  793.     }
  794.  
  795.     /* Get byte count and checksum information from end of buffer */
  796.     if(sscanf(inp, "%ld %lx %lx %lx", numbytes, &oeor, &osum, &orot) != 4)
  797.         return(CONV_BADFMT);
  798.     if ((oeor != Ceor) || (osum != Csum) || (orot != Crot))
  799.         return(CONV_BADCKSUM);
  800.     return(CONV_SUCCESS);
  801. }
  802.  
  803. /* Encode binary byte c into ASCII representation and place into *bufp,
  804.    advancing bufp */
  805. static void
  806. byte_btoa(c, bufp)
  807.     register c;
  808.     char **bufp;
  809. {
  810.     Ceor ^= c;
  811.     Csum += c;
  812.     Csum += 1;
  813.     if ((Crot & 0x80000000)) {
  814.         Crot <<= 1;
  815.         Crot += 1;
  816.     } else {
  817.         Crot <<= 1;
  818.     }
  819.     Crot += c;
  820.  
  821.     word <<= 8;
  822.     word |= c;
  823.     if (bcount == 3) {
  824.         if (word == 0) {
  825.             AddToBuf(bufp, 'z');
  826.         } else {
  827.             register int tmp = 0;
  828.             register int32_t tmpword = word;
  829.             
  830.             if (tmpword < 0) {    
  831.                /* Because some don't support unsigned long */
  832.                 tmp = 32;
  833.                 tmpword -= (int32_t)(85 * 85 * 85 * 85 * 32);
  834.             }
  835.             if (tmpword < 0) {
  836.                 tmp = 64;
  837.                 tmpword -= (int32_t)(85 * 85 * 85 * 85 * 32);
  838.             }
  839.             AddToBuf(bufp,
  840.                  EN((tmpword / (int32_t)(85 * 85 * 85 * 85)) + tmp));
  841.             tmpword %= (int32_t)(85 * 85 * 85 * 85);
  842.             AddToBuf(bufp, EN(tmpword / (85 * 85 * 85)));
  843.             tmpword %= (85 * 85 * 85);
  844.             AddToBuf(bufp, EN(tmpword / (85 * 85)));
  845.             tmpword %= (85 * 85);
  846.             AddToBuf(bufp, EN(tmpword / 85));
  847.             tmpword %= 85;
  848.             AddToBuf(bufp, EN(tmpword));
  849.         }
  850.         bcount = 0;
  851.     } else {
  852.         bcount += 1;
  853.     }
  854. }
  855.  
  856.  
  857. /*
  858.  * Encode the binary data from inbuf, of length inbuflen, into a
  859.  * null-terminated ASCII representation in outbuf, not to exceed outbuflen
  860.  * bytes. Return success/failure status
  861.  */
  862. static int
  863. btoa(inbuf, inbuflen, outbuf, outbuflen)
  864.     char *inbuf;
  865.     int inbuflen;
  866.     char *outbuf;
  867.     int outbuflen;
  868. {
  869.     int32_t inc, nb;
  870.     int32_t oeor, osum, orot;
  871.     char *inp, *outp = outbuf, *endoutp = &outbuf[outbuflen -1];
  872.  
  873.     Ceor = Csum = Crot = word = bcount = 0;
  874.     for (inp = inbuf, inc = 0; inc < inbuflen; inp++, inc++) {
  875.         byte_btoa((unsigned char) (*inp), &outp);
  876.         if (outp >= endoutp)
  877.             return(CONV_OVERFLOW);
  878.     }
  879.     while (bcount != 0) {
  880.         byte_btoa(0, &outp);
  881.         if (outp >= endoutp)
  882.             return(CONV_OVERFLOW);
  883.     }
  884.     /* Put byte count and checksum information at end of buffer, delimited
  885.        by 'x' */
  886.     (void) sprintf(outp, "x %ld %lx %lx %lx", inbuflen, Ceor, Csum, Crot);
  887.     if (&outp[strlen(outp) - 1] >= endoutp)
  888.         return(CONV_OVERFLOW);
  889.     else
  890.         return(CONV_SUCCESS);
  891. }
  892. #endif /* ALLOW_T_UNSPEC */
  893.