#if !defined(lint) && !defined(SABER) static const char sccsid[] = "@(#)db_dump.c 4.33 (Berkeley) 3/3/91"; static const char rcsid[] = "$Id: db_dump.c,v 8.51 2001/06/18 14:42:49 marka Exp $"; #endif /* not lint */ /* * Copyright (c) 1986, 1988, 1990 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Portions Copyright (c) 1993 by Digital Equipment Corporation. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies, and that * the name of Digital Equipment Corporation not be used in advertising or * publicity pertaining to distribution of the document or software without * specific, written prior permission. * * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ /* * Portions Copyright (c) 1995 by International Business Machines, Inc. * * International Business Machines, Inc. (hereinafter called IBM) grants * permission under its copyrights to use, copy, modify, and distribute this * Software with or without fee, provided that the above copyright notice and * all paragraphs of this notice appear in all copies, and that the name of IBM * not be used in connection with the marketing of any product incorporating * the Software or modifications thereof, without specific, written prior * permission. * * To the extent it has a right to do so, IBM grants an immunity from suit * under its patents, if any, for the use, sale or manufacture of products to * the extent that such products are used for performing Domain Name System * dynamic updates in TCP/IP networks by means of the Software. No immunity is * granted for any product per se or for any other function of any product. * * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. */ /* * Portions Copyright (c) 1996-2000 by Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ #include "port_before.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "port_after.h" #include "named.h" #ifdef HITCOUNTS u_int32_t db_total_hits; #endif /* HITCOUNTS */ static const char *MkCredStr(int); static int fwd_dump(FILE *fp); /* * Dump current data base in a format similar to RFC 883. */ void doadump(void) { FILE *fp; ns_notice(ns_log_db, "dumping nameserver data"); if ((fp = write_open(server_options->dump_filename)) == NULL) return; gettime(&tt); #ifdef HITCOUNTS if (NS_OPTION_P(OPTION_HITCOUNT)) fprintf(fp, "; Total hits: %d\n",db_total_hits); #endif /* HITCOUNTS */ fprintf(fp, "; Dumped at %s", ctimel(tt.tv_sec)); if (zones != NULL && nzones != 0) zt_dump(fp); if (fwddata != NULL && fwddata_count != 0) fwd_dump(fp); fputs( "; Note: Cr=(auth,answer,addtnl,cache) tag only shown for non-auth RR's\n", fp); fputs( "; Note: NT=milliseconds for any A RR which we've used as a nameserver\n", fp); fprintf(fp, "; --- Cache & Data ---\n"); if (hashtab != NULL) (void) db_dump(hashtab, fp, DB_Z_ALL, ""); fprintf(fp, "; --- Hints ---\n"); if (fcachetab != NULL) (void) db_dump(fcachetab, fp, DB_Z_ALL, ""); (void) my_fclose(fp); ns_notice(ns_log_db, "finished dumping nameserver data"); } int zt_dump(FILE *fp) { struct zoneinfo *zp; fprintf(fp, ";; ++zone table++\n"); for (zp = &zones[0]; zp < &zones[nzones]; zp++) { const char *pre; char buf[64]; u_int cnt; if (!zp->z_origin) continue; fprintf(fp, "; %s (type %d, class %d, source %s)\n", zp->z_origin ? (*zp->z_origin ? zp->z_origin : ".") : "Nil", zp->z_type, zp->z_class, zp->z_source ? zp->z_source : "Nil"); fprintf(fp, ";\ttime=%lu, lastupdate=%lu, serial=%u,\n", (u_long)zp->z_time, (u_long)zp->z_lastupdate, zp->z_serial); fprintf(fp, ";\trefresh=%u, retry=%u, expire=%u, minimum=%u\n", zp->z_refresh, zp->z_retry, zp->z_expire, zp->z_minimum); fprintf(fp, ";\tftime=%lu, xaddrcnt=%d, state=%04x, pid=%d\n", (u_long)zp->z_ftime, zp->z_xaddrcnt, zp->z_flags, (int)zp->z_xferpid); sprintf(buf, ";\tz_addr[%d]: ", zp->z_addrcnt); pre = buf; for (cnt = 0; cnt < zp->z_addrcnt; cnt++) { fprintf(fp, "%s[%s]", pre, inet_ntoa(zp->z_addr[cnt])); pre = ", "; } if (zp->z_addrcnt) fputc('\n', fp); if (zp->z_axfr_src.s_addr != 0) fprintf(fp, ";\tupdate source [%s]\n", inet_ntoa(zp->z_axfr_src)); } fprintf(fp, ";; --zone table--\n"); return (0); } static int fwd_dump(FILE *fp) { int i; fprintf(fp, ";; ++forwarders table++\n"); for (i = 0; i < fwddata_count; i++) { if (fwddata[i] != NULL) fprintf(fp,"; %s rtt=%d\n", inet_ntoa(fwddata[i]->fwdaddr.sin_addr), fwddata[i]->nsdata->d_nstime); } fprintf(fp, ";; --forwarders table--\n"); return (0); } int db_dump(struct hashbuf *htp, FILE *fp, int zone, const char *origin) { struct databuf *dp = NULL; struct namebuf *np; struct namebuf **npp, **nppend; char dname[MAXDNAME]; u_int32_t n; int j, i, found_data, tab, printed_origin; u_char *cp, *end; const char *proto, *sep; int16_t type; u_int16_t keyflags; u_char *sigdata, *certdata; u_char *savecp; char temp_base64[NS_MD5RSA_MAX_BASE64]; found_data = 0; printed_origin = 0; npp = htp->h_tab; nppend = npp + htp->h_size; while (npp < nppend) { for (np = *npp++; np != NULL; np = np->n_next) { if (np->n_data == NULL) continue; /* Blecch - can't tell if there is data here for the * right zone, so can't print name yet */ found_data = 0; /* we want a snapshot in time... */ for (dp = np->n_data; dp != NULL; dp = dp->d_next) { /* Is the data for this zone? */ if (zone != DB_Z_ALL && dp->d_zone != zone) continue; /* XXX why are we not calling stale() here? */ if (dp->d_zone == DB_Z_CACHE && dp->d_ttl <= (u_int32_t)tt.tv_sec && (dp->d_flags & DB_F_HINT) == 0) continue; if (!printed_origin) { fprintf(fp, "$ORIGIN %s.\n", origin); printed_origin++; } tab = 0; if (dp->d_rcode == NXDOMAIN || dp->d_rcode == NOERROR_NODATA) { fputc(';', fp); } else if (found_data == 0 || found_data == 1) { found_data = 2; } if (found_data == 0 || found_data == 2) { if (NAME(*np)[0] == '\0') { if (origin[0] == '\0') fprintf(fp, ".\t"); else fprintf(fp, ".%s.\t", origin); /* ??? */ } else fprintf(fp, "%s\t", NAME(*np)); if (NAMELEN(*np) < (unsigned)8) tab = 1; found_data++; } else { (void) putc('\t', fp); tab = 1; } if (dp->d_zone == DB_Z_CACHE) { if (dp->d_flags & DB_F_HINT && (int32_t)(dp->d_ttl - tt.tv_sec) < DB_ROOT_TIMBUF) fprintf(fp, "%d\t", DB_ROOT_TIMBUF); else fprintf(fp, "%d\t", (int)(dp->d_ttl - tt.tv_sec)); } else if (dp->d_ttl != USE_MINIMUM) fprintf(fp, "%u\t", dp->d_ttl); else fprintf(fp, "%u\t", zones[dp->d_zone].z_minimum); fprintf(fp, "%s\t%s\t", p_class(dp->d_class), p_type(dp->d_type)); cp = (u_char *)dp->d_data; sep = "\t;"; type = dp->d_type; if (dp->d_rcode == NXDOMAIN || dp->d_rcode == NOERROR_NODATA) { #ifdef RETURNSOA if (dp->d_size == 0) { #endif fprintf(fp, "%s%s-$", (dp->d_rcode == NXDOMAIN) ?"NXDOMAIN" :"NODATA", sep); goto eoln; #ifdef RETURNSOA } else { type = T_SOA; } #endif } /* * Print type specific data */ /* XXX why are we not using ns_sprintrr() here? */ switch (type) { case T_A: switch (dp->d_class) { case C_IN: case C_HS: fputs(inet_ntoa(ina_get(cp)), fp); break; } if (dp->d_nstime) { fprintf(fp, "%sNT=%d", sep, dp->d_nstime); sep = " "; } break; case T_CNAME: case T_MB: case T_MG: case T_MR: case T_PTR: fprintf(fp, "%s.", cp); break; case T_NS: cp = (u_char *)dp->d_data; if (cp[0] == '\0') fprintf(fp, ".\t"); else fprintf(fp, "%s.", cp); break; case T_HINFO: case T_ISDN: { char buf[256]; if ((n = *cp++) != '\0') { memcpy(buf, cp, n); buf[n] = '\0'; fprintf(fp, "\"%.*s\"", (int)n, buf); cp += n; } else fprintf(fp, "\"\""); if ((n = *cp++) != '\0') { memcpy(buf, cp, n); buf[n] = '\0'; fprintf(fp, " \"%.*s\"", (int)n, buf); } else fprintf(fp, " \"\""); break; } case T_SOA: fprintf(fp, "%s.", cp); cp += strlen((char *)cp) + 1; fprintf(fp, " %s. (\n", cp); #if defined(RETURNSOA) if (dp->d_rcode) fputs(";", fp); #endif cp += strlen((char *)cp) + 1; NS_GET32(n, cp); fprintf(fp, "\t\t%u", n); NS_GET32(n, cp); fprintf(fp, " %u", n); NS_GET32(n, cp); fprintf(fp, " %u", n); NS_GET32(n, cp); fprintf(fp, " %u", n); NS_GET32(n, cp); fprintf(fp, " %u )", n); #if defined(RETURNSOA) if (dp->d_rcode) { fprintf(fp,";%s.;%s%s-$",cp, (dp->d_rcode == NXDOMAIN) ? "NXDOMAIN" : "NODATA", sep); } #endif break; case T_MX: case T_AFSDB: case T_RT: NS_GET16(n, cp); fprintf(fp, "%u", n); fprintf(fp, " %s.", cp); break; case T_PX: NS_GET16(n, cp); fprintf(fp, "%u", n); fprintf(fp, " %s.", cp); cp += strlen((char *)cp) + 1; fprintf(fp, " %s.", cp); break; case T_X25: if ((n = *cp++) != '\0') fprintf(fp, " \"%.*s\"", (int)n, cp); else fprintf(fp, " \"\""); break; case T_TXT: end = (u_char *)dp->d_data + dp->d_size; while (cp < end) { (void) putc('"', fp); if ((n = *cp++) != '\0') { for (j = n ; j > 0 && cp < end ; j--) { if (*cp == '\n' || *cp == '"' || *cp == '\\') (void) putc('\\', fp); (void) putc(*cp++, fp); } } (void) putc('"', fp); if (cp < end) (void) putc(' ', fp); } break; case T_NSAP: (void) fputs(inet_nsap_ntoa(dp->d_size, dp->d_data, NULL), fp); break; case T_AAAA: { char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255" ]; (void) fputs(inet_ntop(AF_INET6, dp->d_data, t, sizeof t), fp); break; } case T_LOC: { char t[256]; (void) fputs(loc_ntoa(dp->d_data, t), fp); break; } case T_NAPTR: { u_int32_t order, preference; NS_GET16(order, cp); fprintf(fp, "%u", order); NS_GET16(preference, cp); fprintf(fp, "%u", preference); n = *cp++; fprintf(fp, "\"%.*s\"", (int)n, cp); cp += n; n = *cp++; fprintf(fp, "\"%.*s\"", (int)n, cp); cp += n; n = *cp++; fprintf(fp, " \"%.*s\"", (int)n, cp); cp += n; fprintf(fp, " %s.", cp); break; } case T_SRV: { u_int priority, weight, port; NS_GET16(priority, cp); NS_GET16(weight, cp); NS_GET16(port, cp); fprintf(fp, "\t%u %u %u %s.", priority, weight, port, cp); break; } case T_WKS: fputs(inet_ntoa(ina_get(cp)), fp); cp += INADDRSZ; proto = protocolname(*cp); cp += sizeof(char); fprintf(fp, " %s ", proto); i = 0; while(cp < (u_char *)dp->d_data + dp->d_size) { j = *cp++; do { if (j & 0200) fprintf(fp, " %s", servicename(i, proto)); j <<= 1; } while (++i & 07); } break; case T_MINFO: case T_RP: fprintf(fp, "%s.", cp); cp += strlen((char *)cp) + 1; fprintf(fp, " %s.", cp); break; case T_KEY: savecp = cp; /* save the beginning */ /*>>> Flags (unsigned_16) */ NS_GET16(keyflags,cp); fprintf(fp, "0x%04x ", keyflags); /*>>> Protocol (8-bit decimal) */ fprintf(fp, "%3u ", *cp++); /*>>> Algorithm id (8-bit decimal) */ fprintf(fp, "%3u ", *cp++); /*>>> Public-Key Data (multidigit BASE64) */ /* containing ExponentLen, Exponent, and Modulus */ i = b64_ntop(cp, dp->d_size - (cp - savecp), temp_base64, sizeof temp_base64); if (i < 0) fprintf(fp, "; BAD BASE64"); else fprintf(fp, "%s", temp_base64); break; case T_SIG: sigdata = cp; /* RRtype (char *) */ NS_GET16(n,cp); fprintf(fp, "%s ", p_type(n)); /* Algorithm id (8-bit decimal) */ fprintf(fp, "%d ", *cp++); /* Labels (8-bit decimal) */ fprintf(fp, "%d ", *cp++); /* OTTL (u_long) */ NS_GET32(n, cp); fprintf(fp, "%u ", n); /* Texp (u_long) */ NS_GET32(n, cp); fprintf(fp, "%s ", p_secstodate (n)); /* Tsig (u_long) */ NS_GET32(n, cp); fprintf(fp, "%s ", p_secstodate (n)); /* Kfootprint (unsigned_16) */ NS_GET16(n, cp); fprintf(fp, "%u ", n); /* Signer's Name (char *) */ fprintf(fp, "%s ", cp); cp += strlen((char *)cp) + 1; /* Signature (base64 of any length) */ i = b64_ntop(cp, dp->d_size - (cp - sigdata), temp_base64, sizeof temp_base64); if (i < 0) fprintf(fp, "; BAD BASE64"); else fprintf(fp, "%s", temp_base64); break; case T_NXT: fprintf(fp, "%s.", cp); n = strlen ((char *)cp) + 1; cp += n; i = 8 * (dp->d_size - n); /* How many bits? */ for (n = 0; n < (u_int32_t)i; n++) { if (NS_NXT_BIT_ISSET(n, cp)) fprintf(fp," %s", p_type(n)); } break; case ns_t_cert: certdata = cp; NS_GET16(n,cp); fprintf(fp, "%d ", n); /* cert type */ NS_GET16(n,cp); fprintf(fp, "%d %d ", n, *cp++); /* tag & alg */ /* Certificate (base64 of any length) */ i = b64_ntop(cp, dp->d_size - (cp - certdata), temp_base64, sizeof(temp_base64)); if (i < 0) fprintf(fp, "; BAD BASE64"); else fprintf(fp, "%s", temp_base64); break; default: fprintf(fp, "\\# %u", dp->d_size); if (dp->d_size != 0) { fputs(" ( ", fp); isc_puthexstring(fp, dp->d_data, dp->d_size, 40, 48, "\n\t\t\t\t"); fputs(" ) ", fp); } } if (dp->d_cred < DB_C_ZONE) { fprintf(fp, "%sCr=%s", sep, MkCredStr(dp->d_cred)); sep = " "; } else { fprintf(fp, "%sCl=%d", sep, dp->d_clev); sep = " "; } if ((dp->d_flags & DB_F_LAME) != 0) { time_t when; getname(np, dname, sizeof(dname)); when = db_lame_find(dname, dp); if (when != 0 && when > tt.tv_sec) { fprintf(fp, "%sLAME=%ld", sep, when - tt.tv_sec); sep = " "; } } eoln: if (dp->d_addr.s_addr != htonl(0)) { fprintf(fp, "%s[%s]", sep, inet_ntoa(dp->d_addr)); sep = " "; } #ifdef HITCOUNTS if (NS_OPTION_P(OPTION_HITCOUNT)) { fprintf(fp, "%shits=%d", sep, dp->d_hitcnt); sep=" "; } #endif /* HITCOUNTS */ putc('\n', fp); } } } if (ferror(fp)) return (NODBFILE); npp = htp->h_tab; nppend = npp + htp->h_size; while (npp < nppend) { for (np = *npp++; np != NULL; np = np->n_next) { if (np->n_hash == NULL) continue; getname(np, dname, sizeof(dname)); if (db_dump(np->n_hash, fp, zone, dname) == NODBFILE) return (NODBFILE); } } return (OK); } static const char * MkCredStr(int cred) { static char badness[20]; switch (cred) { case DB_C_ZONE: return "zone"; case DB_C_AUTH: return "auth"; case DB_C_ANSWER: return "answer"; case DB_C_ADDITIONAL: return "addtnl"; case DB_C_CACHE: return "cache"; default: break; } sprintf(badness, "?%d?", cred); return (badness); }