diff options
author | Dag-Erling Smørgrav <des@FreeBSD.org> | 2004-09-24 19:48:50 +0000 |
---|---|---|
committer | Dag-Erling Smørgrav <des@FreeBSD.org> | 2004-09-24 19:48:50 +0000 |
commit | 29d75632bd276029d874c42e613218086eebd6dd (patch) | |
tree | bb3edb8dcc07615d426eb359f46c1741e4c22575 /contrib/bind/bin/named-xfer/named-xfer.c | |
parent | 8540155e95215c1e3287e1c7de8ec20d820b7692 (diff) |
Retire the BIND 8 sources.
Notes
Notes:
svn path=/head/; revision=135758
Diffstat (limited to 'contrib/bind/bin/named-xfer/named-xfer.c')
-rw-r--r-- | contrib/bind/bin/named-xfer/named-xfer.c | 3256 |
1 files changed, 0 insertions, 3256 deletions
diff --git a/contrib/bind/bin/named-xfer/named-xfer.c b/contrib/bind/bin/named-xfer/named-xfer.c deleted file mode 100644 index bbc1898ce416..000000000000 --- a/contrib/bind/bin/named-xfer/named-xfer.c +++ /dev/null @@ -1,3256 +0,0 @@ -/* $FreeBSD$ */ -/* - * The original version of named-xfer by Kevin Dunlap. - * Completed and integrated with named by David Waitzman - * (dwaitzman@bbn.com) 3/14/88. - * Modified by M. Karels and O. Kure 10-88. - * Modified extensively since then by just about everybody. - */ - -/* - * Copyright (c) 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-1999 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. - */ - -/* - * Portions Copyright (c) 1998 by MetaInfo, Incorporated. - * - * 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 MetaInfo Incorporated 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 METAINFO INCORPORATED DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL METAINFO INCORPRATED - * 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. - */ -#if !defined(lint) && !defined(SABER) -char copyright[] = -"@(#) Copyright (c) 1988, 1990 The Regents of the University of California.\n\ - portions Copyright (c) 1993 Digital Equipment Corporation\n\ - portions Copyright (c) 1998 MetaInfo, Inc.\n\ - portions Copyright (c) 1995, 1996 Internet Software Consorium\n\ - All rights reserved.\n"; -#endif /* not lint */ - -#if !defined(lint) && !defined(SABER) -static const char sccsid[] = "@(#)named-xfer.c 4.18 (Berkeley) 3/7/91"; -static const char rcsid[] = "$Id: named-xfer.c,v 8.122.8.2 2003/06/02 05:59:56 marka Exp $"; -#endif /* not lint */ - -#include "port_before.h" -#include <sys/types.h> -#include <sys/param.h> -#include <sys/file.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <sys/un.h> - -#include <netinet/in.h> -#include <netdb.h> -#include <arpa/inet.h> -#include <arpa/nameser.h> - -#include <limits.h> -#include <ctype.h> -#include <errno.h> -#include <math.h> -#include <resolv.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <syslog.h> -#include <unistd.h> -#include <stdarg.h> - -#include <isc/eventlib.h> -#include <isc/list.h> -#include <isc/logging.h> -#include <isc/memcluster.h> -#include <isc/dst.h> -#include <isc/misc.h> - -#include "port_after.h" - - -#ifndef PATH_SEP -#define PATH_SEP '/' -#endif - -#define MAIN_PROGRAM -#include "../named/named.h" -#undef MAIN_PROGRAM - -#define MAX_XFER_RESTARTS 2 - -#define ENABLE_IXFR 1 - -# ifdef SHORT_FNAMES -extern long pathconf __P((const char *path, int name)); /* XXX */ -# endif - - -static struct zoneinfo zone; /* zone information */ - -static char *ddtfilename = NULL, - *ddtfile = NULL; - -static char *tmpname = NULL, - *tmpiname = NULL, /* temporary file name for ixfr transaction file */ - *domain; /* domain being xfered */ - -static int quiet = 0, - read_interrupted = 0, - curclass, - domain_len; /* strlen(domain) */ - -static FILE *fp = NULL, - *dbfp = NULL, - *ixfp = NULL; - -static char *ProgName; - -static void usage(const char *); -static int tsig_init(const char *); -static int getzone(struct zoneinfo *, u_int32_t, int), - print_output(struct zoneinfo *, u_int32_t, - u_char *, int, u_char *, int), - netread(int, char *, int, int), - writemsg(int, const u_char *, int); -static int ixfr_log(const u_char *msg, int len, int *delete, - FILE *file, struct sockaddr_in *sin, - u_int32_t *serial_no, int *); -static SIG_FN read_alarm(void); -static SIG_FN term_handler(void); -static const char *soa_zinfo(struct zoneinfo *, u_char *, u_char*), - *tsig_rcode(int); - -struct zoneinfo zp_start, zp_finish; - -static int restarts = 0; -static int check_serial = 0; -static int xfr_qtype = T_AXFR; - -FILE *ddt = NULL; -int servermethode[NSMAX]; -char *soa_buf; - -typedef struct _tsig_node { - struct in_addr addr; - DST_KEY *dst_key; - LINK(struct _tsig_node) link; -} tsig_node; - -LIST(tsig_node) tsig_list; - -/* - * Debugging printf. - */ -static void lprintf(int level, const char *format, ...) ISC_FORMAT_PRINTF(2, 3); -static void -lprintf(int level, const char *format, ...) { - va_list ap; - - va_start(ap, format); - if (ddt != NULL && debug >= level) - (void) vfprintf(ddt, format, ap); - va_end(ap); -} - -static int -init_xfer_logging() { - log_channel chan; - - if (log_new_context(ns_log_max_category, NULL, &log_ctx) < 0) { - perror("log_new_context"); - return (0); - } - log_option(log_ctx, LOG_OPTION_DEBUG, debug); - log_option(log_ctx, LOG_OPTION_LEVEL, debug); - - log_ctx_valid = 1; - - chan = log_new_syslog_channel(0, 0, ISC_FACILITY); - if (chan == NULL) - return (0); - if (log_add_channel(log_ctx, ns_log_default, chan) < 0) { - perror("log_add_channel syslog"); - return (0); - } - - if (debug) { - unsigned int flags = LOG_USE_CONTEXT_LEVEL|LOG_REQUIRE_DEBUG; - - chan = log_new_file_channel(flags, 0, NULL, ddt, 0, ULONG_MAX); - if (chan == NULL) - return (0); - if (log_add_channel(log_ctx, ns_log_default, chan) < 0) { - perror("log_add_channel debug"); - return (0); - } - } - - return (1); -} - -static void -cleanup_for_exit(void) { -#ifdef DEBUG - if (!debug) -#endif - { - (void) unlink(tmpname); - if (tmpiname != NULL) - (void) unlink(tmpiname); - } - if(tmpiname) - free(tmpiname); - tmpiname = NULL; - if (ddtfilename != NULL) { - free(ddtfilename); - if (ddtfilename == ddtfile) - ddtfile = NULL; - ddtfilename = NULL; - } - if(tmpname) - free(tmpname); - tmpname = NULL; - if(ddtfile) - free(ddtfile); - ddtfile = NULL; -} - - -int -main(int argc, char *argv[]) { - struct zoneinfo *zp; - struct hostent *hp; - struct in_addr axfr_src; - char *dbfile = NULL, *tracefile = NULL, *tm = NULL, *tsigfile = NULL; - char *ixfrfile = NULL; - int dbfd, ddtd, result, c, ixfd = -1; - u_int32_t serial_no = 0; - u_int port = htons(NAMESERVER_PORT); - struct stat statbuf; - int stub_only = 0; - int class = C_IN; - int n; - -#ifdef _AUX_SOURCE - set42sig(); -#endif - memset(&axfr_src, 0, sizeof axfr_src); - ProgName = strrchr(argv[0], PATH_SEP); - if (ProgName != NULL) - ProgName++; - else - ProgName = argv[0]; - - (void) umask(022); - - ddtfilename = (char *)malloc(strlen(_PATH_TMPXFER) + 1); - strcpy(ddtfilename, _PATH_TMPXFER); - ddtfile = ddtfilename; - -#ifdef RENICE - nice(-40); /* this is the recommended procedure to */ - nice(20); /* reset the priority of the current process */ - nice(0); /* to "normal" (== 0) - see nice(3) */ -#endif - - n = LOG_PID; -#ifdef LOG_PERROR - n |= LOG_PERROR; -#endif -#if defined(LOG_CONS) && defined(USE_LOG_CONS) - n |= LOG_CONS; -#endif -#ifdef SYSLOG_42BSD - openlog(ProgName, n); -#else - openlog(ProgName, n, ISC_FACILITY); -#endif - while ((c = getopt(argc, argv, "C:d:l:s:t:z:f:i:p:P:qx:ST:Z")) != -1) - switch (c) { - case 'C': - class = get_class(optarg); - break; - case 'd': -#ifdef DEBUG - debug = atoi(optarg); -#endif - break; - case 'l': - ddtfile = (char *)malloc(strlen(optarg) + - sizeof(".XXXXXX") + 1); - if (!ddtfile) - panic("malloc(ddtfile)", NULL); -#ifdef SHORT_FNAMES - filenamecpy(ddtfile, optarg); -#else - (void) strcpy(ddtfile, optarg); -#endif /* SHORT_FNAMES */ - (void) strcat(ddtfile, ".XXXXXX"); - break; - case 's': - serial_no = strtoul(optarg, (char **)NULL, 10); - check_serial++; - break; - case 't': - tracefile = optarg; - break; - case 'z': /* zone == domain */ - domain = optarg; - domain_len = strlen(domain); - while ((domain_len > 0) && - (domain[domain_len-1] == '.')) - domain[--domain_len] = '\0'; - break; - case 'f': - dbfile = optarg; - tmpname = (char *)malloc((unsigned)strlen(optarg) + - sizeof(".XXXXXX") + 1); - if (!tmpname) - panic("malloc(tmpname)", NULL); -#ifdef SHORT_FNAMES - filenamecpy(tmpname, optarg); -#else - (void) strcpy(tmpname, optarg); -#endif /* SHORT_FNAMES */ - break; - case 'i': -#if ENABLE_IXFR - ixfrfile = optarg; - tmpiname = (char *) malloc(strlen(optarg) + - sizeof(".XXXXXX") + 1); - if (!tmpiname) - panic("malloc(tmpiname)", NULL); -#ifdef SHORT_FNAMES - filenamecpy(tmpiname, optarg); -#else - (void) strcpy(tmpiname, optarg); -#endif /* SHORT_FNAMES */ -#endif /* ENABLE_IXFR */ - break; - case 'p': - port = htons((u_int16_t)atoi(optarg)); - break; - case 'P': - port = (u_int16_t)atoi(optarg); - break; - case 'S': - stub_only = 1; - break; - case 'q': - quiet++; - break; - case 'x': - if (!inet_aton(optarg, &axfr_src)) - panic("bad -x addr: %s", optarg); - break; - case 'T': - tsigfile = optarg; - break; - case 'Z': - xfr_qtype = ns_t_zxfr; - break; - case '?': - default: - usage("unrecognized argument"); - /* NOTREACHED */ - } - if (!domain || ((!dbfile) && (!ixfrfile)) || optind >= argc) { - if (!domain) - usage("no domain"); - if (!dbfile) - usage("no dbfile"); - if (optind >= argc) - usage("not enough arguments"); - /* NOTREACHED */ - } - if (stat(dbfile, &statbuf) != -1 && - !S_ISREG(statbuf.st_mode) && - !S_ISFIFO(statbuf.st_mode)) - usage("dbfile must be a regular file or FIFO"); - if (ixfrfile && (stat(ixfrfile, &statbuf) != -1 && - !S_ISREG(statbuf.st_mode) && - !S_ISFIFO(statbuf.st_mode))) - usage("ixfrfile must be a regular file or FIFO"); - if (tsigfile && stat(tsigfile, &statbuf) != -1 && - !S_ISREG(statbuf.st_mode) && - !S_ISFIFO(statbuf.st_mode)) - usage("tsigfile must be a regular file or FIFO"); - if (tracefile && (fp = fopen(tracefile, "w")) == NULL) - perror(tracefile); - (void) strcat(tmpname, ".XXXXXX"); - /* tmpname is now something like "/etc/named/named.bu.db.XXXXXX" */ - if ((dbfd = mkstemp(tmpname)) == -1) { - perror(tmpname); - if (!quiet) - syslog(LOG_ERR, "can't make tmpfile (%s): %s\n", - tmpname, strerror(errno)); - exit(XFER_FAIL); - } -#ifdef HAVE_FCHMOD /* XXX */ - if (fchmod(dbfd, 0644) == -1) -#else - if (chmod(tmpname, 0644) == -1) -#endif - { - perror(tmpname); - if (!quiet) - syslog(LOG_ERR, "can't [f]chmod tmpfile (%s): %s\n", - tmpname, strerror(errno)); - close(dbfd); - unlink(tmpname); - exit(XFER_FAIL); - } - if ((dbfp = fdopen(dbfd, "r+")) == NULL) { - perror(tmpname); - if (!quiet) - syslog(LOG_ERR, "can't fdopen tmpfile (%s)", tmpname); - close(dbfd); - unlink(tmpname); - exit(XFER_FAIL); - } - if (ixfrfile) { - (void) strcat(tmpiname, ".XXXXXX"); - if ((ixfd = mkstemp(tmpiname)) == -1) { - perror(tmpiname); - if (!quiet) - syslog(LOG_ERR, - "can't make tmpifile (%s): %s\n", - tmpiname, strerror(errno)); - (void) fclose(dbfp); - (void) close(dbfd); - exit(XFER_FAIL); - } -#ifdef HAVE_FCHMOD /* XXX */ - if (fchmod(ixfd, 0644) == -1) -#else - if (chmod(tmpiname, 0644) == -1) -#endif - { - perror(tmpiname); - if (!quiet) - syslog(LOG_ERR, - "can't [f]chmod tmpifile (%s): %s\n", - tmpiname, strerror(errno)); - (void) fclose(dbfp); - (void) close(dbfd); - (void) close(ixfd); - exit(XFER_FAIL); - } - close(ixfd); - } -#ifdef DEBUG - if (debug) { - /* ddtfile is now something like "/usr/tmp/xfer.ddt.XXXXXX" */ - if ((ddtd = mkstemp(ddtfile)) == -1) { - perror(ddtfile); - debug = 0; - } -#ifdef HAVE_FCHMOD - else if (fchmod(ddtd, 0644) == -1) -#else - else if (chmod(ddtfile, 0644) == -1) -#endif - { - perror(ddtfile); - close(ddtd); - unlink(ddtfile); - debug = 0; - } else if ((ddt = fdopen(ddtd, "w")) == NULL) { - perror(ddtfile); - close(ddtd); - unlink(ddtfile); - debug = 0; - } else - setvbuf(ddt, NULL, _IOLBF, 0); - } -#endif - if (!init_xfer_logging()) { - cleanup_for_exit(); - perror("init_xfer_logging"); - } - - /* - * Ignore many types of signals that named (assumed to be our parent) - * considers important- if not, the user controlling named with - * signals usually kills us. - */ - (void) signal(SIGHUP, SIG_IGN); -#ifdef SIGSYS - (void) signal(SIGSYS, SIG_IGN); -#endif -#ifdef DEBUG - if (debug == 0) -#endif - { - (void) signal(SIGINT, SIG_IGN); - (void) signal(SIGQUIT, SIG_IGN); - } - (void) signal(SIGILL, SIG_IGN); - -#if defined(SIGUSR1) && defined(SIGUSR2) - (void) signal(SIGUSR1, SIG_IGN); - (void) signal(SIGUSR2, SIG_IGN); -#else /* SIGUSR1&&SIGUSR2 */ - (void) signal(SIGEMT, SIG_IGN); - (void) signal(SIGFPE, SIG_IGN); -#endif /* SIGUSR1&&SIGUSR2 */ - - if (dbfile) - lprintf(1, "domain `%s'; file `%s'; serial %u\n", - domain, dbfile, serial_no); - - if (ixfrfile) - lprintf(1, "domain `%s'; ixfrfile `%s'; serial %u\n", - domain, ixfrfile, serial_no); - - if (tsigfile) - lprintf(1, "tsigfile `%s'\n", tsigfile); - - buildservicelist(); - buildprotolist(); - - if (tsig_init(tsigfile) == -1) { - cleanup_for_exit(); - return (XFER_FAIL); - } - - /* init zone data */ - - zp = &zone; - if (stub_only) - zp->z_type = Z_STUB; - else - zp->z_type = Z_SECONDARY; - zp->z_class = class; - zp->z_origin = domain; - zp->z_source = dbfile; - zp->z_axfr_src = axfr_src; - zp->z_addrcnt = 0; - lprintf(1, "zone found (%d): \"%s\", source = %s\n", - zp->z_type, - (zp->z_origin[0] == '\0') ? "." : zp->z_origin, - zp->z_source); - - for (; optind != argc; optind++) { - int tmpsupportixfr; - - tm = argv[optind]; - tmpsupportixfr = ISNOTIXFR; - if ((optind+1) != argc) { - if (strcasecmp("ixfr", argv[optind+1]) == 0) { -#if ENABLE_IXFR - tmpsupportixfr = ISIXFR; - servermethode[zp->z_addrcnt] = tmpsupportixfr; -#endif - optind++; - } else if (strcasecmp("axfr", argv[optind+1]) == 0) { - tmpsupportixfr = ISNOTIXFR; - optind++; - } - } - if (!inet_aton(tm, &zp->z_addr[zp->z_addrcnt])) { - if (strcmp("-ixfr",tm)==0) { -#if ENABLE_IXFR - tmpsupportixfr = ISIXFR; - servermethode[zp->z_addrcnt-1] = tmpsupportixfr; -#endif - continue; - } else - if (strcmp("-axfr",tm)==0) { - tmpsupportixfr = ISNOTIXFR; - continue; - } - hp = gethostbyname(tm); - if (hp == NULL) { - syslog(LOG_NOTICE, - "uninterpretable server (%s) for %s\n", - tm, zp->z_origin); - continue; - } - memcpy(&zp->z_addr[zp->z_addrcnt], - hp->h_addr, - INADDRSZ); - lprintf(1, "Arg: \"%s\" %s\n", tm,((tmpsupportixfr) ? "IXFR":"AXFR")); - } - if (++zp->z_addrcnt >= NSMAX) { - zp->z_addrcnt = NSMAX; - lprintf(1, "NSMAX reached\n"); - break; - } - } - lprintf(1, "addrcnt = %d\n", zp->z_addrcnt); - - res_ninit(&res); - res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE); - result = getzone(zp, serial_no, port); - (void) fclose(dbfp); - (void) close(dbfd); - - if (ixfp) - (void) my_fclose(ixfp); - else - close(ixfd); - - switch (result) { - - case XFER_SUCCESSAXFR: /* ok exit */ - if (tmpiname != NULL) - unlink(tmpiname); - if (ixfrfile) { - /* - * An IXFR was requested but we performed an - * AXFR. Rename the temporary file to the IXFR - * name, named will rename it again to the dbname. - */ - if (isc_movefile(tmpname, ixfrfile) == -1) { - perror("isc_movefile"); -#ifdef DEBUG - if (debug) - (void) unlink(ddtfile); -#endif - if (!quiet) - syslog(LOG_ERR, - "rename %s to %s: %s", - tmpname, ixfrfile, strerror(errno)); - cleanup_for_exit(); - exit(XFER_FAIL); - }; - exit(XFER_SUCCESSAXFRIXFRFILE); - } - if (isc_movefile(tmpname, dbfile) == -1) { - perror("isc_movefile"); - if (!quiet) - syslog(LOG_ERR, "isc_movefile %s to %s: %m", - tmpname, dbfile); - cleanup_for_exit(); - exit(XFER_FAIL); - } - exit(XFER_SUCCESSAXFR); - - case XFER_SUCCESSIXFR: - unlink(tmpname); - if (isc_movefile(tmpiname, ixfrfile) == -1) { - perror("isc_movefile"); - if (!quiet) - syslog(LOG_ERR, "isc_movefile %s to %s: %m", - tmpiname, ixfrfile); - cleanup_for_exit(); - exit(XFER_FAIL); - } - cleanup_for_exit(); - exit(XFER_SUCCESSIXFR); - - case XFER_UPTODATE: /* the zone was already uptodate */ - (void) unlink(tmpname); - if (tmpiname != NULL) - (void) unlink(tmpiname); - cleanup_for_exit(); - exit(XFER_UPTODATE); - - default: - result = XFER_FAIL; - /* fall through */ - case XFER_REFUSED: - case XFER_TIMEOUT: - case XFER_FAIL: - (void) unlink(tmpname); - cleanup_for_exit(); - exit(result); /* error or timeout */ - } - /*NOTREACHED*/ - return (0); /* Make gcc happy. */ -} - -static const char *UsageText[] = { - "\t-z zone_to_transfer\n", - "\t-f db_file\n", - "\t[-i ixfr_file]\n", - "\t[-s serial_no]\n", - "\t[-d debug_level]\n", - "\t[-l debug_log_file]\n", - "\t[-t trace_file]\n", - "\t[-p port]\n", - "\t[-S] [-Z]\n", - "\t[-C class]\n", - "\t[-x axfr-src]\n", - "\t[-T tsig_info_file]\n", - "\tservers [-ixfr|-axfr]...\n", - NULL -}; - -static void -usage(const char *msg) { - const char **line; - - fprintf(stderr, "Usage error: %s\n", msg); - fprintf(stderr, "Usage: %s\n", ProgName); - for (line = UsageText; *line; line++) - fputs(*line, stderr); - exit(XFER_FAIL); -} - -static int -tsig_init(const char *file) { - char buf[1024]; - FILE *fp; - char *s; - - if (file == NULL) - return (0); - fp = fopen(file, "r"); - if (fp == NULL) - return (-1); - dst_init(); - INIT_LIST(tsig_list); - while (1) { - tsig_node *n = malloc(sizeof(tsig_node)); - int alg, secret_len; - char *cp; - u_char secret[128]; - char *name; - - if (n == NULL) - return (-1); - - s = fgets(buf, sizeof(buf), fp); - if (s == NULL) - break; - buf[strlen(buf)-1] = 0; - inet_aton(buf, &n->addr); - - fgets(buf, sizeof(buf), fp); - buf[strlen(buf)-1] = 0; - name = strdup(buf); - - if (name == NULL) - return (-1); - - fscanf(fp, "%d", &alg); - fgets(buf, sizeof(buf), fp); - - fgets(buf, sizeof(buf), fp); - buf[strlen(buf)-1] = 0; - cp = buf; - while (isspace(*cp)) - cp++; - - secret_len = b64_pton(cp, secret, sizeof(secret)); - n->dst_key = dst_buffer_to_key(name, alg, 0, 0, - secret, secret_len); - - free(name); - INIT_LINK(n, link); - APPEND(tsig_list, n, link); - } - fclose(fp); - unlink(file); - return (0); -} - -#define DEF_DNAME '\001' /* '\0' means the root domain */ -/* XXX: The following variables should probably all be "static" */ -u_int32_t minimum_ttl = 0; -int soa_cnt = 0, scdsoa = 0, methode = ISNOTIXFR; -int delete_soa = 1; -int ixfr_single_answer_mode = 0; -u_int32_t final_serial = 0; -int ixfr_soa = 0; -int ns_cnt = 0; -int query_type = 0; -int prev_comment = 0; /* was previous record a comment? */ -char zone_top[MAXDNAME]; /* the top of the zone */ -char prev_origin[MAXDNAME]; /* from most recent $ORIGIN line */ -char prev_dname[MAXDNAME] = { DEF_DNAME }; /* from previous record */ -char prev_ns_dname[MAXDNAME] = { DEF_DNAME }; /* from most recent NS record */ - -/* - * TSIG state - */ -static int tsig_signed; -static ns_tcp_tsig_state tsig_state; - -static int -make_query(int fd, struct zoneinfo *zp, int type, u_int32_t serial_no, - DST_KEY *tsig_key, u_char *buf, u_int bufsize) -{ - HEADER *hp; - u_char *cp; - int n, ret; - time_t timesigned = 0; - - n = res_nmkquery(&res, QUERY, zp->z_origin, curclass, - type, NULL, 0, NULL, buf, bufsize); - if (n < 0) { - if (!quiet) - syslog(LOG_INFO, "zone %s: res_nmkquery %s failed", - p_type(query_type), zp->z_origin); - return (n); - } - - if (type == T_IXFR) { - hp = (HEADER *) buf; - cp = buf; - lprintf(1, "len = %d\n", n); - hp->nscount = htons(1+ntohs(hp->nscount)); - cp += n; - n = dn_comp(zp->z_origin, cp, bufsize - (cp - buf), NULL, NULL); - if (n < 0) - return (n); - cp += n; - if (cp + 3 * INT16SZ + 6 * INT32SZ + 2 > buf + bufsize) - return (-1); - PUTSHORT(T_SOA, cp); /* type */ - PUTSHORT(C_IN, cp); /* class */ - PUTLONG(0, cp); /* ttl */ - PUTSHORT(22, cp); /* dlen */ - *cp++ = 0; /* mname */ - *cp++ = 0; /* rname */ - PUTLONG(serial_no, cp); - PUTLONG(0xDEAD, cp); /* Refresh */ - PUTLONG(0xBEEF, cp); /* Retry */ - PUTLONG(0xABCD, cp); /* Expire */ - PUTLONG(0x1776, cp); /* Min TTL */ - n = cp - buf; - lprintf(1, "len = %d\n", cp-buf); - } - - tsig_signed = 0; - if (tsig_key != NULL) { - int siglen; - u_char sig[64]; - - siglen = sizeof(sig); - ret = ns_sign(buf, &n, bufsize, NOERROR, tsig_key, - NULL, 0, sig, &siglen, timesigned); - if (ret == 0) { - tsig_signed = 1; - ns_verify_tcp_init(tsig_key, sig, siglen, &tsig_state); - } - } - - if (debug) - res_pquery(&res, buf, n, ddt); - - if (writemsg(fd, buf, n) < 0) { - syslog(LOG_INFO, "writemsg: %m"); - return (-1); - } - - return (n); -} - -static u_int -readandverify(int fd, u_char **bufp, u_int *bufsizep, - struct sockaddr_in *sin, char *z_origin, int sig_req) -{ - u_char *buf = *bufp; - u_char *newbuf; - u_int bufsize = *bufsizep; - u_int len; - - if (netread(fd, (char *)buf, INT16SZ, XFER_TIMER) < 0) - return (0); - - if ((len = ns_get16(buf)) == 0) - return (0); - - if (len > bufsize) { - newbuf = realloc(buf, len); - if (newbuf == NULL) { - syslog(LOG_INFO, "realloc(%u) failed\n", len); - return (0); - } - *bufp = buf = newbuf; - *bufsizep = bufsize = len; - } - - if (netread(fd, (char *)buf, len, XFER_TIMER) < 0) - return (0); - -#ifdef DEBUG - if (debug >= 3) { - (void)fprintf(ddt,"len = %d\n", len); - res_pquery(&res, buf, len, ddt); - } - if (fp) - res_pquery(&res, buf, len, fp); -#endif - - if (tsig_signed) { - int ret; - - ret = ns_verify_tcp(buf, (int *)&len, &tsig_state, sig_req); - if (ret != 0) { - syslog(LOG_NOTICE, "%s [%s] %s %s: %s (%d)\n", - "TSIG verification from server", - inet_ntoa(sin->sin_addr), "zone", z_origin, - tsig_rcode(ret), ret); - return (0); - } - } - - return (len); -} - -static void -print_comment(int s, struct sockaddr_in *sin, int check_serial, - u_int32_t serial_no, DST_KEY *tsig_key) -{ - struct sockaddr_in local; - ISC_SOCKLEN_T locallen; - const char *l, *nl; - - gettime(&tt); - locallen = sizeof local; - if (getsockname(s, (struct sockaddr *)&local, &locallen) < 0) - memset(&local, 0, sizeof local); - - for (l = Version; l; l = nl) { - size_t len; - if ((nl = strchr(l, '\n')) != NULL) { - len = nl - l; - nl = nl + 1; - } else { - len = strlen(l); - nl = NULL; - } - while (isspace((unsigned char) *l)) - l++; - if (*l) - fprintf(dbfp, "; BIND version %.*s\n", (int)len, l); - } - - fprintf(dbfp, check_serial ? - "; zone '%s' last serial %u\n" : - "; zone '%s' first transfer\n", - domain, serial_no); - fprintf(dbfp, "; from %s:%d", - inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); - fprintf(dbfp, " (local %s) using %s at %s", - inet_ntoa(local.sin_addr), (methode == ISIXFR) ? "IXFR":"AXFR", - ctimel(tt.tv_sec)); - if (tsig_signed != 0) - fprintf(dbfp, "; TSIG verified: key %s.\n", - tsig_key->dk_key_name); - else - fprintf(dbfp, "; NOT TSIG verified\n"); -} - -static int -getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { - HEADER *hp; - u_int len; - int s, n, l, error = 0; - int was_ixfr = 0; - u_int cnt; - u_char *cp, *nmp, *eom, *tmp ; - u_char *buf = NULL; - u_char *bp; - u_int bufsize = 0; - u_char *buf2 = NULL; - u_int buf2size = 0; - char name2[MAXDNAME]; - struct sockaddr_in sin; -#ifdef POSIX_SIGNALS - struct sigaction sv, osv; -#else - struct sigvec sv, osv; -#endif - int qdcount, ancount, aucount, arcount, class = 0, type = 0; - const char *badsoa_msg = "Nil"; - struct sockaddr_in my_addr; - char my_addr_text[30]; - ISC_SOCKLEN_T alen; - int tsig_req; - DST_KEY *tsig_key; - int ixfr_first = 1; - int loop_cnt = 0; - u_int32_t query_serial = serial_no; - int first_soa_printed; - struct in_addr z_axfr_src; - int refused = 0; - -#ifdef DEBUG - if (debug) { - (void)fprintf(ddt,"getzone() %s ", zp->z_origin); - switch (zp->z_type) { - case Z_STUB: - fprintf(ddt, "stub\n"); - break; - case Z_SECONDARY: - fprintf(ddt, "slave\n"); - break; - default: - fprintf(ddt, "unknown type\n"); - } - } -#endif -#ifdef POSIX_SIGNALS - memset(&sv, 0, sizeof sv); - sv.sa_handler = (SIG_FN (*)()) read_alarm; - /* SA_ONSTACK isn't recommended for strict POSIX code */ - /* is it absolutely necessary? */ - /* sv.sa_flags = SA_ONSTACK; */ - sigfillset(&sv.sa_mask); - (void) sigaction(SIGALRM, &sv, &osv); - memset(&sv, 0, sizeof sv); - sv.sa_handler = (SIG_FN (*)()) term_handler; - sigfillset(&sv.sa_mask); - (void) sigaction(SIGTERM, &sv, &osv); -#else - memset(&sv, 0, sizeof sv); - sv.sv_handler = read_alarm; - sv.sv_mask = ~0; - (void) sigvec(SIGALRM, &sv, &osv); - memset(&sv, 0, sizeof sv); - sv.sv_handler = term_handler; - sv.sv_mask = ~0; - (void) sigvec(SIGTERM, &sv, &osv); -#endif - - strcpy(zone_top, zp->z_origin); - if ((l = strlen(zone_top)) != 0 && zone_top[l - 1] == '.') - zone_top[l - 1] = '\0'; - strcpy(prev_origin, zone_top); - - for (cnt = 0; cnt < zp->z_addrcnt; cnt++) { - methode = servermethode[cnt]; - sin.sin_addr = zp->z_addr[cnt]; - lprintf(3, "address [%s] %s\n", - inet_ntoa(sin.sin_addr), - (methode == ISIXFR) ? "IXFR":"AXFR"); - } - - for (cnt = 0; cnt < zp->z_addrcnt; cnt++) { - methode = ISNOTIXFR; - curclass = zp->z_class; - /* - * If we have been given a serial number and a ixfr log - * file name then set methode. - */ - if (check_serial && tmpiname != NULL) - methode = servermethode[cnt]; - error = 0; - tsig_signed = 0; - z_axfr_src = zp->z_axfr_src; - if (buf == NULL) { - if ((buf = (u_char *)malloc(2 * PACKETSZ)) == NULL) { - syslog(LOG_INFO, "malloc(%u) failed", - 2 * PACKETSZ); - error++; - break; - } - bufsize = 2 * PACKETSZ; - } - tsig_key = tsig_key_from_addr(sin.sin_addr); - - try_again: - first_soa_printed = 0; - if ((s = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) { - syslog(LOG_INFO, "socket: %m"); - error++; - break; - } - if (z_axfr_src.s_addr != 0) { - memset(&sin, 0, sizeof sin); - sin.sin_family = AF_INET; - sin.sin_port = 0; /* "ANY" */ - sin.sin_addr = z_axfr_src; - lprintf(2, "binding to address [%s]\n", - inet_ntoa(sin.sin_addr)); - if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) - syslog(LOG_INFO, "warning: bind(%s) failed", - inet_ntoa(zp->z_axfr_src)); - } - memset(&sin, 0, sizeof sin); - sin.sin_family = AF_INET; - sin.sin_port = port; - sin.sin_addr = zp->z_addr[cnt]; - lprintf(2, "connecting to server #%d [%s].%d\n", - cnt + 1, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); - if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { - if (z_axfr_src.s_addr != 0) { - lprintf(2, "connect failed, trying w/o -x"); - z_axfr_src.s_addr = 0; - (void) my_close(s); - goto try_again; - } - if (!quiet) - syslog(LOG_INFO, - "connect(%s) for zone %s failed: %s", - inet_ntoa(sin.sin_addr), zp->z_origin, - strerror(errno)); - error++; - (void) my_close(s); - continue; - } - - query_type = (methode == ISIXFR && was_ixfr == 0) ? - T_IXFR : T_SOA; - - n = make_query(s, zp, query_type, serial_no, tsig_key, - buf, bufsize); - - if (n < 0) { - (void) my_close(s); -#ifdef POSIX_SIGNALS - (void) sigaction(SIGALRM, &osv, - (struct sigaction *)0); -#else - (void) sigvec(SIGALRM, &osv, - (struct sigvec *)0); -#endif - return (XFER_FAIL); - } - - /* - * Get out your butterfly net and catch the answer. - */ - len = readandverify(s, &buf, &bufsize, &sin, zp->z_origin, 1); - if (len == 0) { - my_close(s); - error++; - continue; - } - - if (query_type == T_IXFR && ixfp == NULL) { - delete_soa = 1; - ixfr_soa = 0; - if ((ixfp = fopen(tmpiname, "w+")) == NULL) { - perror(tmpiname); - if (!quiet) - syslog(LOG_ERR, - "can't fopen ixfr log (%s)", - tmpname); - exit(XFER_FAIL); - } - } - - hp = (HEADER *) buf; - qdcount = ntohs(hp->qdcount); - ancount = ntohs(hp->ancount); - aucount = ntohs(hp->nscount); - arcount = ntohs(hp->arcount); - /* - * close socket if any of these apply: - * 1) rcode != NOERROR - * 2) not an authority response - * 3) not an answer to our question - * 4) both the number of answers and authority count < 1) - */ - if (hp->rcode != NOERROR || - (query_type == T_SOA && (!hp->aa || qdcount != 1)) || - (ancount < 1 && aucount < 1)) { -#ifndef SYSLOG_42BSD - syslog(LOG_NOTICE, - "[%s] %s for %s, %s query got rcode %d, aa %d, ancount %d, aucount %d", - inet_ntoa(sin.sin_addr), - (hp->aa - ? (qdcount==1 ?"no SOA found" :"bad response") - : "not authoritative"), - zp->z_origin[0] != '\0' ? zp->z_origin : ".", - p_type(query_type), - hp->rcode, hp->aa, ancount, aucount); -#endif - error++; - (void) my_close(s); - continue; - } - zp_start = *zp; - if ((int)len < HFIXEDSZ + QFIXEDSZ) { - badsoa_msg = "too short"; - badsoa: - syslog(LOG_INFO, - "malformed %s from [%s], zone %s: %s", - p_type(query_type), inet_ntoa(sin.sin_addr), - zp->z_origin, badsoa_msg); - error++; - (void) my_close(s); - continue; - } - /* - * Step through response. - */ - tmp = buf + HFIXEDSZ; - eom = buf + len; - /* Query Section. */ - if (qdcount > 1) { - badsoa_msg = "question error"; - goto badsoa; - } - if (qdcount < 1) - goto no_question; - n = dn_expand(buf, eom, tmp, name2, sizeof name2); - if (n < 0) { - badsoa_msg = "qname error"; - goto badsoa; - } - tmp += n; - if (tmp + 2 * INT16SZ > eom) { - badsoa_msg = "query error"; - goto badsoa; - } - NS_GET16(type, tmp); - NS_GET16(class, tmp); - if (class != curclass || - ((type != T_SOA) && (type != T_IXFR) && (type != T_AXFR)) || - ns_samename(zp->z_origin, name2) != 1) - { - syslog(LOG_INFO, - "wrong query in resp from [%s], zone %s: [%s %s %s]\n", - inet_ntoa(sin.sin_addr), zp->z_origin, - name2, p_class(class), p_type(type)); - error++; - (void) my_close(s); - continue; - } - no_question: - /* ... Answer Section. - * We may have to loop a little, to bypass SIG SOA's in - * the response. - */ - loop_cnt = 0; - bp = NULL; - do { - u_char *cp4, *ocp = tmp; - u_short type, class, dlen, olen = len; - u_int32_t ttl; - - n = dn_expand(buf, eom, tmp, name2, sizeof name2); - if (n < 0) { - badsoa_msg = "aname error"; - goto badsoa; - } - tmp += n; - - if (loop_cnt == 0) - bp = tmp; - - /* Are type, class, and ttl OK? */ - cp4 = tmp; /* Leave tmp pointing to type field */ - if (eom - cp4 < 3 * INT16SZ + INT32SZ) { - badsoa_msg = "zinfo too short"; - goto badsoa; - } - NS_GET16(type, cp4); - NS_GET16(class, cp4); - NS_GET32(ttl, cp4); - NS_GET16(dlen, cp4); - if (cp4 + dlen > eom) { - badsoa_msg = "zinfo dlen too big"; - goto badsoa; - } - if (type == T_SOA) { - if (was_ixfr) { - methode = ISNOTIXFR; - break; - } - if ((methode == ISIXFR) && (loop_cnt == 0)) { - soa_cnt++; - badsoa_msg = soa_zinfo(&zp_finish, tmp, - eom); - if (badsoa_msg) - goto badsoa; - if (ixfp && ixfr_log(buf, len, - &delete_soa, - ixfp, &sin, - &serial_no, - &ixfr_first) < 0) { - error++; - break; - } - } else { - if (methode == ISIXFR) { - check_serial = 0; - soa_cnt++; - break; - } - break; - } - } - if ((loop_cnt >= 1) && (soa_cnt < 2)) { - lprintf(1, - "server %s %d rejected IXFR and responded with AXFR\n", - inet_ntoa(sin.sin_addr), soa_cnt); - methode = ISNOTIXFR; - check_serial = 0; - was_ixfr++; - tmp = bp; - break; - } - /* Skip to next record, if any. */ - lprintf(1, "skipping %s %s RR in response\n", - name2, p_type(type)); - tmp = cp4 + dlen; - loop_cnt++; - if (loop_cnt == 1) { - - badsoa_msg = soa_zinfo(&zp_start, bp, eom); - if (badsoa_msg) - goto badsoa; - if (check_serial && - !SEQ_GT(zp_start.z_serial, query_serial)) { - (void) my_close(s); - lprintf(1, - "zone up-to-date, serial %u\n", - zp_start.z_serial); - if (ixfp) { - (void) fclose(ixfp); - (void) unlink (tmpiname); - ixfp = NULL; - } - return (XFER_UPTODATE); - } - } - if (ancount == 1 && loop_cnt == 1) { - if (buf2 == NULL) { - if ((buf2 = (u_char *)malloc(2 * PACKETSZ)) == NULL) { - syslog(LOG_INFO, - "malloc(%u) failed", - 2 * PACKETSZ); - error++; - break; - } - buf2size = 2 * PACKETSZ; - } - len = readandverify(s, &buf2, &buf2size, &sin, - zp->z_origin, 0); - if (len == 0) { - error++; - tmp = bp; - check_serial = 0; - break; - } - - hp = (HEADER *) buf2; - qdcount = ntohs(hp->qdcount); - ancount = ntohs(hp->ancount); - aucount = ntohs(hp->nscount); - arcount = ntohs(hp->arcount); - - tmp = buf2 + HFIXEDSZ; - eom = buf2 + len; - /* Query Section. */ - if (qdcount > 1) { - badsoa_msg = "question error"; - goto badsoa; - } else if (qdcount == 1) { - n = dn_skipname(tmp, eom); - if (n < 0) { - badsoa_msg = "qname error"; - goto badsoa; - } - tmp += n; - if (tmp + 2 * INT16SZ > eom) { - badsoa_msg = "query error"; - goto badsoa; - } - tmp += 2 * INT16SZ; - } - /* answer section */ - if (ancount < 1) { - badsoa_msg = "empty answer"; - goto badsoa; - } - n = dn_expand(buf2, eom, tmp, name2, - sizeof name2); - if (n < 0) { - badsoa_msg = "qname error"; - goto badsoa; - } - tmp += n; - bp = tmp; - if (tmp + 2 * INT16SZ > eom) { - badsoa_msg = "query error"; - goto badsoa; - } - NS_GET16(type, tmp); - NS_GET16(class, tmp); - if (class != curclass || - ns_samename(zp->z_origin, name2) != 1) - { - syslog(LOG_INFO, - "wrong query in resp from [%s], zone %s: [%s %s %s]\n", - inet_ntoa(sin.sin_addr), zp->z_origin, - name2, p_class(class), p_type(type)); - error++; - tmp = bp; - check_serial = 0; - break; - } - if (type == T_SOA) { - ixfr_single_answer_mode = 1; - if (ixfp && - ixfr_log(buf2, len, &delete_soa, ixfp, - &sin, &serial_no, - &ixfr_first) < 0) { - error++; - break; - } - free(buf); - buf = buf2; - bufsize = buf2size; - buf2 = NULL; - break; - } else { - methode = ISNOTIXFR; - was_ixfr++; - check_serial = 0; - cp = buf + HFIXEDSZ; - n = print_output(zp, serial_no, buf, olen, ocp, 3); - first_soa_printed = 1; - free(buf); - buf = buf2; - buf2 = NULL; - bufsize = buf2size; - break; - } - } - if (loop_cnt > 1) { - tmp = bp; - check_serial = 0; - break; - } - } while (1); - - if (error != 0) { - (void) my_close(s); - continue; - } - - if (ns_samename(zp->z_origin, name2) != 1) { - syslog(LOG_INFO, - "wrong answer in resp from [%s], zone %s: [%s %s %s]\n", - inet_ntoa(sin.sin_addr), zp->z_origin, - name2, p_class(class), p_type(type)); - error++; - (void) my_close(s); - continue; - } - if (loop_cnt < 1) { - badsoa_msg = soa_zinfo(&zp_start, tmp, eom); - if (badsoa_msg) - goto badsoa; - } - if (methode == ISNOTIXFR) { - if (SEQ_GT(zp_start.z_serial, serial_no) || - !check_serial) { - if (soa_cnt) { - if (!first_soa_printed) - soa_cnt = 0; - goto axfr_response; - } - lprintf(1, "need update, serial %u\n", - zp_start.z_serial); - soa_cnt = 0; - hp = (HEADER *) buf; - ns_cnt = 0; - print_comment(s, &sin, check_serial, - serial_no, tsig_key); - - for (;;) { - if ((soa_cnt == 0) || (zp->z_type == Z_STUB)) { - if (zp->z_type == Z_STUB) { - if (soa_cnt == 1 && - ns_cnt == 0) - query_type = T_NS; - else - query_type = T_SOA; - } else if (methode == ISIXFR) - query_type = T_IXFR; - else - query_type = xfr_qtype; - n = make_query(s, zp, query_type, - serial_no, tsig_key, - buf, bufsize); - syslog(LOG_INFO, - "send %s query %d to %s for %s", - p_type(query_type), - cnt, inet_ntoa(sin.sin_addr), - (*zp->z_origin != '\0') ? - zp->z_origin : "."); - lprintf(1, - "send %s query to %s\n", - p_type(query_type), - inet_ntoa(sin.sin_addr)); - lprintf(1,"bufsize = %d\n", bufsize); - if (n < 0) { - if (!quiet) { - if (zp->z_type == Z_STUB) - syslog(LOG_INFO, - "zone %s: res_nmkquery %s failed", - p_type(query_type), - zp->z_origin); - else - syslog(LOG_INFO, - "zone %s: res_nmkquery %s failed", - zp->z_origin, - p_type(query_type)); - } - (void) my_close(s); -#ifdef POSIX_SIGNALS - sigaction(SIGALRM, &osv, - (struct sigaction *)0); -#else - sigvec(SIGALRM, &osv, - (struct sigvec *)0); -#endif - return (XFER_FAIL); - } - } -/*XXX ZXFR*/ -receive: - /* - * Receive length & response - */ - tsig_req = (soa_cnt == 0); - len = readandverify(s, &buf, &bufsize, &sin, - zp->z_origin, tsig_req); - if (len == 0) { - error++; - break; - } - hp = (HEADER *)buf; - eom = buf + len; - if (len < HFIXEDSZ) { - badrec: - error++; - alen = sizeof my_addr; - if (getsockname(s, (struct sockaddr *) - &my_addr, &alen) < 0) - sprintf(my_addr_text, - "[errno %d]", errno); - else - sprintf(my_addr_text, - "[%s].%u", - inet_ntoa(my_addr. - sin_addr), - ntohs(my_addr.sin_port) - ); - if ((len >= HFIXEDSZ) && - (hp->rcode == REFUSED)) { - syslog(LOG_INFO, - "[%s] transfer refused from [%s], zone %s\n", - my_addr_text, - inet_ntoa(sin.sin_addr), - zp->z_origin); - refused = 1; - } else { - syslog(LOG_INFO, - "[%s] record too short from [%s], zone %s\n", - my_addr_text, - inet_ntoa(sin.sin_addr), - zp->z_origin); - } - break; - } -axfr_response: - if (query_type == T_IXFR) - if (hp->rcode != NOERROR) { - lprintf(1, - "server %s did not support IXFR\n", - inet_ntoa(sin.sin_addr)); - methode = ISNOTIXFR; - continue; - }; - cp = buf + HFIXEDSZ; - if (ntohs(hp->qdcount) == 1) { - if ((query_type == T_IXFR) && - (methode == ISIXFR)) { - lprintf(1, - "server %s rejected IXFR and responded with AXFR\n", - inet_ntoa(sin.sin_addr)); - methode = ISNOTIXFR; - } - n = dn_skipname(cp, eom); - if ((n == -1) || - ((n + QFIXEDSZ) >= (eom - cp))) - goto badrec; - cp += n + QFIXEDSZ; - } - nmp = cp; - if ((n = dn_skipname(cp, eom)) == -1) - goto badrec; - tmp = cp + n; - if (zp->z_type == Z_STUB) { - ancount = ntohs(hp->ancount); - n = 0; - for (cnt = 0; - cnt < (u_int)ancount; - cnt++) { - n = print_output(zp, - serial_no, - buf, len, cp, - 0); - if (n < 0) - break; - cp += n; - } - /* - * If we've processed the answer - * section and didn't get any useful - * answers, bail out. - */ - if (query_type == T_SOA && - soa_cnt == 0) { - syslog(LOG_ERR, - "stubs: no SOA in answer"); - error++; - break; - } - if (query_type == T_NS && - ns_cnt == 0) { - syslog(LOG_ERR, - "stubs: no NS in answer"); - error++; - break; - } - if (n >= 0 && hp->nscount) { - ancount = ntohs(hp->nscount); - for (cnt = 0; - cnt < (u_int)ancount; - cnt++) { - n = print_output(zp, - serial_no, - buf, - len, - cp, - 0); - if (n < 0) - break; - cp += n; - } - } - ancount = ntohs(hp->arcount); - for (cnt = 0; - n > 0 && cnt < (u_int)ancount; - cnt++) { - n = print_output(zp, serial_no, - buf, len, cp, - 0); - cp += n; - } - if (n < 0) { - syslog(LOG_INFO, - "print_output: unparseable answer (%d), zone %s", - hp->rcode, - zp->z_origin); - error++; - break; - } - if (cp != eom) { - syslog(LOG_INFO, - "print_output: short answer (%d, %d), zone %s", - cp - buf, eom - buf, - zp->z_origin); - error++; - break; - } - } else { - ancount = ntohs(hp->ancount); - if (query_type == T_IXFR && - methode == ISIXFR && - ixfr_log(buf, len, &delete_soa, - ixfp, &sin, &serial_no, - &ixfr_first) < 0 ){ - error++; - break; - } - for (n = cnt = 0; - cnt < (u_int)ancount; - cnt++) { - n = print_output(zp, serial_no, - buf, len, cp, - 0); - if (n < 0) - break; - cp += n; - } - if (n < 0) { - syslog(LOG_INFO, - "print_output: unparseable answer (%d), zone %s", - hp->rcode, - zp->z_origin); - error++; - break; - } - if (cp != eom) { - syslog(LOG_INFO, - "print_output: short answer (%d, %d), zone %s", - cp - buf, eom - buf, - zp->z_origin); - error++; - break; - } - } - if ((soa_cnt >= 2) && (methode == ISNOTIXFR)) - break; - if ((soa_cnt == -1) && (methode == ISIXFR)) - break; - } - (void) my_close(s); - if (error == 0) { -#ifdef POSIX_SIGNALS - (void) sigaction(SIGALRM, &osv, - (struct sigaction *)0); -#else - (void) sigvec(SIGALRM, &osv, - (struct sigvec *)0); -#endif - if (ixfp) { - (void) fclose(ixfp); - ixfp = NULL; - } - return (XFER_SUCCESSAXFR); - } - if (ixfp) { - (void) fclose(ixfp); - ixfp = NULL; - } - lprintf(2, "error receiving zone transfer\n"); - } else if (zp_start.z_serial == serial_no) { - (void) my_close(s); - lprintf(1, "zone up-to-date, serial %u\n", - zp_start.z_serial); - if (ixfp) { - (void) fclose(ixfp); - (void) unlink (tmpiname); - ixfp = NULL; - } - return (XFER_UPTODATE); - } else { - (void) my_close(s); - if (!quiet) - syslog(LOG_NOTICE, - "serial from [%s], zone %s: %u lower than current: %u\n", - inet_ntoa(sin.sin_addr), zp->z_origin, - zp_start.z_serial, serial_no); - return (XFER_FAIL); - } - } else { - if (zp_finish.z_serial == query_serial) { - (void) my_close(s); - lprintf(1, "zone up-to-date, serial %u\n", - zp_start.z_serial); - if (ixfp) { - (void) fclose(ixfp); - (void) unlink (tmpiname); - ixfp = NULL; - } - return (XFER_UPTODATE); - } - if (SEQ_GT(query_serial, zp_finish.z_serial)) { - if (!quiet) - syslog(LOG_NOTICE, - "serial from [%s], zone %s: %u lower than current: %u\n", - inet_ntoa(sin.sin_addr), zp->z_origin, - zp_finish.z_serial, query_serial); - lprintf(1, - "serial from [%s], zone %s: %u lower than current: %u\n", - inet_ntoa(sin.sin_addr), zp->z_origin, - zp_finish.z_serial, query_serial); - if (ixfp) { - (void) fclose(ixfp); - (void) unlink (tmpiname); - ixfp = NULL; - } - if (was_ixfr == 0) { - was_ixfr++; - n = make_query(s, zp, T_AXFR, - serial_no, tsig_key, - buf, bufsize); - if (n < 0) { - (void) my_close(s); -#ifdef POSIX_SIGNALS - (void) sigaction(SIGALRM, &osv, - (struct sigaction *)0); -#else - (void) sigvec(SIGALRM, &osv, - (struct sigvec *)0); -#endif - return (XFER_FAIL); - } - methode = ISNOTIXFR; - check_serial = 0; - soa_cnt = 0; - was_ixfr = 0; - goto receive; - } - (void) my_close(s); - return (XFER_FAIL); - } - if (soa_cnt > 2) { - methode = ISNOTIXFR; - check_serial = 0; - soa_cnt = 0; - goto axfr_response; - } - lprintf(1, "We have an IXFR\n"); - loop_cnt = 0; - while (SEQ_GT(zp_finish.z_serial, serial_no)) { - /* - * Receive length & response - */ - tsig_req = (soa_cnt == 0); - len = readandverify(s, &buf, &bufsize, &sin, - zp->z_origin, 1); - if (len == 0) { - error++; - break; - } - hp = (HEADER *)buf; - eom = buf + len; - if (len < HFIXEDSZ) { - error++; - alen = sizeof my_addr; - if (getsockname(s, (struct sockaddr *) - &my_addr, &alen) < 0) - sprintf(my_addr_text, "[errno %d]", errno); - else - sprintf(my_addr_text, "[%s].%u", - inet_ntoa(my_addr. sin_addr), - ntohs(my_addr.sin_port)); - if ((hp->rcode == REFUSED) && - (len >= HFIXEDSZ)) { - syslog(LOG_INFO, - "[%s] transfer refused from [%s], zone %s\n", - my_addr_text, - inet_ntoa(sin.sin_addr), - zp->z_origin); - refused = 1; - } else { - syslog(LOG_INFO, - "[%s] record too short from [%s], zone %s\n", - my_addr_text, - inet_ntoa(sin.sin_addr), - zp->z_origin); - } - break; - } - if (ixfp && - ixfr_log(buf, len, &delete_soa, ixfp, - &sin, &serial_no, &ixfr_first) < 0) - { - error++; - break; - } - } - (void) my_close(s); - if (!error) { - fprintf(ixfp, "update:\t{add} "); - if (soa_buf) - fputs(soa_buf, ixfp); - fprintf(ixfp, "[END_DELTA]\n"); - return (XFER_SUCCESSIXFR); - } - } - } -#ifdef POSIX_SIGNALS - (void) sigaction(SIGALRM, &osv, (struct sigaction *)0); -#else - (void) sigvec(SIGALRM, &osv, (struct sigvec *)0); -#endif - if (ixfp) { - (void) my_fclose(ixfp); - (void) unlink (tmpiname); - ixfp = NULL; - } - if (!error) - return (XFER_TIMEOUT); - if (refused) - return (XFER_REFUSED); - return (XFER_FAIL); -} - -static SIG_FN -term_handler() { - cleanup_for_exit(); - _exit(XFER_FAIL); /* not safe to call exit() from a signal handler */ -} - -/* - * Set flag saying to read was interrupted - * used for a read timer - */ -static SIG_FN -read_alarm() { - read_interrupted = 1; -} - -static int -netread(int fd, char *buf, int len, int timeout) { - static const char setitimerStr[] = "setitimer: %m"; - struct itimerval ival, zeroival; - struct sockaddr_in sa; - int n; - ISC_SOCKLEN_T salen; -#if defined(NETREAD_BROKEN) - int retries = 0; -#endif - - memset(&zeroival, 0, sizeof zeroival); - ival = zeroival; - ival.it_value.tv_sec = timeout; - while (len > 0) { -#ifndef _WIN32 - if (setitimer(ITIMER_REAL, &ival, NULL) < 0) { - syslog(LOG_INFO, setitimerStr); - return (-1); - } -#endif - errno = 0; - salen = sizeof sa; - n = recvfrom(fd, buf, len, 0, (struct sockaddr *)&sa, &salen); - if (n == 0 && errno == 0) { -#if defined(NETREAD_BROKEN) - if (++retries < 42) /* doug adams */ - continue; -#endif - syslog(LOG_INFO, "premature EOF, fetching \"%s\"", - domain); - return (-1); - } - if (n < 0) { - if (errno == 0) { -#if defined(NETREAD_BROKEN) - if (++retries < 42) /* doug adams */ - continue; -#endif - syslog(LOG_INFO, - "recv(len=%d): n=%d && !errno", - len, n); - return (-1); - } - if (errno == EINTR) { - if (!read_interrupted) { - /* It wasn't a timeout; ignore it. */ - continue; - } - errno = ETIMEDOUT; - } - syslog(LOG_INFO, "recv(len=%d): %m", len); - return (-1); - } - buf += n; - len -= n; -#if defined(NETREAD_BROKEN) - /* Reset the retry counter if we are successfully reading. */ - if(n > 0) - retries = 0; -#endif - } -#ifndef _WIN32 - if (setitimer(ITIMER_REAL, &zeroival, NULL) < 0) { - syslog(LOG_INFO, setitimerStr); - return (-1); - } -#endif - return (0); -} - -/* - * Write a counted buffer to a file descriptor preceded by a length word. - */ -static int -writemsg(int rfd, const u_char *msg, int msglen) { - struct iovec iov[2]; - u_char len[INT16SZ]; - int ret; - - ns_put16(msglen, len); - iov[0].iov_base = (char *)len; - iov[0].iov_len = INT16SZ; - DE_CONST(msg, iov[1].iov_base); - iov[1].iov_len = msglen; - ret = writev(rfd, iov, 2); - if (ret != INT16SZ + msglen) { - syslog(LOG_DEBUG, "writemsg(%d,%p,%d) failed: %s", - rfd, msg, msglen, strerror(errno)); - return (-1); - } - return (ret); -} - -static const char * -soa_zinfo(struct zoneinfo *zp, u_char *cp, u_char *eom) { - int n, type, class; - u_int32_t ttl; - u_int16_t dlen; - u_char *rdatap; - - /* Are type, class, and ttl OK? */ - if (eom - cp < 3 * INT16SZ + INT32SZ) - return ("zinfo too short"); - NS_GET16(type, cp); - NS_GET16(class, cp); - NS_GET32(ttl, cp); - NS_GET16(dlen, cp); - rdatap = cp; - if (type != T_SOA || class != curclass) - return ("zinfo wrong typ/cla/ttl"); - /* Skip master name and contact name, we can't validate them. */ - if ((n = dn_skipname(cp, eom)) == -1) - return ("zinfo mname"); - cp += n; - if ((n = dn_skipname(cp, eom)) == -1) - return ("zinfo hname"); - cp += n; - /* Grab the data fields. */ - if (eom - cp < 5 * INT32SZ) - return ("zinfo dlen"); - NS_GET32(zp->z_serial, cp); - NS_GET32(zp->z_refresh, cp); - NS_GET32(zp->z_retry, cp); - NS_GET32(zp->z_expire, cp); - NS_GET32(zp->z_minimum, cp); - if (cp != rdatap + dlen) - return ("bad soa dlen"); - return (NULL); -} - -#define BOUNDS_CHECK(ptr, count) \ - do { \ - if ((ptr) + (count) > eom) { \ - hp->rcode = FORMERR; \ - return (-1); \ - } \ - } while (0) - -/* - * Parse the message, determine if it should be printed, and if so, print it - * in .db file form. Does minimal error checking on the message content. - * - * XXX why aren't we using ns_sprintrr() ? - */ -static int -print_output(struct zoneinfo *zp, u_int32_t serial_no, u_char *msg, - int msglen, u_char *rrp, int xfr_detect) { - u_char *cp; - HEADER *hp = (HEADER *) msg; - u_int32_t ttl, tmpnum; - int i, j, longname, result, n1, n; - u_int class, type, dlen; - char data[MAXDATA]; - u_char *cp1, *cp2, *temp_ptr, *eom, *rr_type_ptr; - u_char *cdata, *rdatap; - char *origin, dname[MAXDNAME]; - const char *proto; - const char *ignore = ""; - const char *badsoa_msg; - int escaped = 0; - - eom = msg + msglen; - cp = rrp; - n = dn_expand(msg, msg + msglen, cp, dname, sizeof dname); - if (n < 0) { - hp->rcode = FORMERR; - return (-1); - } - cp += n; - BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); - rr_type_ptr = cp; - NS_GET16(type, cp); - NS_GET16(class, cp); - NS_GET32(ttl, cp); - /* - * Following the Clarification draft's direction, we treat TTLs with - * the MSB set as if they were 0. - */ - if (ttl > MAXIMUM_TTL) { - syslog(LOG_INFO, "%s: TTL > %u, converted to 0", dname, - MAXIMUM_TTL); - ttl = 0; - } - NS_GET16(dlen, cp); - BOUNDS_CHECK(cp, dlen); - rdatap = cp; - - origin = dname; - while (*origin) { - if (!escaped && *origin == '.') { - origin++; /* skip over '.' */ - break; - } - escaped = (*origin++ == '\\') && !escaped; - } - lprintf(3, "print_output: dname %s type %d class %d ttl %u\n", - dname, type, class, ttl); - /* - * Convert the resource record data into the internal database format. - * CP points to the raw resource record. - * After this switch: - * CP has been updated to point past the RR. - * CP1 points to the internal database version. - * N is the length of the internal database version. - */ - switch (type) { - case T_A: - case T_WKS: - case T_HINFO: - case T_TXT: - case T_X25: - case T_ISDN: - case T_LOC: - case T_NSAP: - case T_AAAA: - case T_KEY: - case ns_t_cert: - cp1 = cp; - n = dlen; - cp += n; - break; - - case T_CNAME: - case T_MB: - case T_MG: - case T_MR: - case T_NS: - case T_PTR: - n = dn_expand(msg, msg + msglen, cp, data, sizeof data); - if (n < 0) { - hp->rcode = FORMERR; - return (-1); - } - cp += n; - cp1 = (u_char *)data; - n = strlen(data) + 1; - break; - - case T_MINFO: - case T_SOA: - case T_RP: - n = dn_expand(msg, msg + msglen, cp, data, sizeof data); - if (n < 0) { - hp->rcode = FORMERR; - return (-1); - } - cp += n; - n = strlen(data) + 1; - cp1 = (u_char *)data + n; - n1 = sizeof data - n; - if (type == T_SOA) - n1 -= 5 * INT32SZ; - n = dn_expand(msg, msg + msglen, cp, (char *)cp1, n1); - if (n < 0) { - hp->rcode = FORMERR; - return (-1); - } - cp += n; - cp1 += strlen((char *) cp1) + 1; - if (type == T_SOA) { - BOUNDS_CHECK(cp, 5 * INT32SZ); - temp_ptr = cp + 4 * INT32SZ; - NS_GET32(minimum_ttl, temp_ptr); - /* - * Following the Clarification draft's direction, - * we treat TTLs with the MSB set as if they were 0. - */ - if (minimum_ttl > MAXIMUM_TTL) { - syslog(LOG_INFO, - "%s: SOA minimum TTL > %u, converted to 0", - dname, MAXIMUM_TTL); - minimum_ttl = 0; - } - n = 5 * INT32SZ; - memcpy(cp1, cp, n); - cp += n; - cp1 += n; - } - n = cp1 - (u_char *)data; - cp1 = (u_char *)data; - break; - - case T_NAPTR: - /* Grab weight and port. */ - BOUNDS_CHECK(cp, INT16SZ*2); - memcpy(data, cp, INT16SZ*2); - cp1 = (u_char *)data + INT16SZ*2; - cp += INT16SZ*2; - - /* Flags */ - BOUNDS_CHECK(cp, 1); - n = *cp++; - BOUNDS_CHECK(cp, n); - *cp1++ = n; - memcpy(cp1, cp, n); - cp += n; cp1 += n; - - /* Service */ - BOUNDS_CHECK(cp, 1); - n = *cp++; - BOUNDS_CHECK(cp, n); - *cp1++ = n; - memcpy(cp1, cp, n); - cp += n; cp1 += n; - - /* Regexp */ - BOUNDS_CHECK(cp, 1); - n = *cp++; - BOUNDS_CHECK(cp, n); - *cp1++ = n; - memcpy(cp1, cp, n); - cp += n; cp1 += n; - - /* Replacement */ - n = dn_expand(msg, msg + msglen, cp, (char *)cp1, - sizeof data - ((char *)cp1 - data)); - if (n < 0) - return (-1); - cp += n; - - /* compute end of data */ - cp1 += strlen((char *)cp1) + 1; - /* compute size of data */ - n = cp1 - (u_char *)data; - cp1 = (u_char *)data; - break; - - case T_MX: - case T_AFSDB: - case T_RT: - case T_SRV: - /* grab preference */ - BOUNDS_CHECK(cp, INT16SZ); - memcpy(data, cp, INT16SZ); - cp1 = (u_char *)data + INT16SZ; - cp += INT16SZ; - - if (type == T_SRV) { - BOUNDS_CHECK(cp, INT16SZ*2); - memcpy(cp1, cp, INT16SZ*2); - cp1 += INT16SZ*2; - cp += INT16SZ*2; - } - - /* get name */ - n = dn_expand(msg, msg + msglen, cp, - (char *)cp1, - sizeof data - (cp1 - (u_char *)data)); - if (n < 0) - return (-1); - cp += n; - - /* compute end of data */ - cp1 += strlen((char *) cp1) + 1; - /* compute size of data */ - n = cp1 - (u_char *)data; - cp1 = (u_char *)data; - break; - - case T_PX: - /* grab preference */ - BOUNDS_CHECK(cp, INT16SZ); - memcpy(data, cp, INT16SZ); - cp1 = (u_char *)data + INT16SZ; - cp += INT16SZ; - - /* get MAP822 name */ - n = dn_expand(msg, msg + msglen, cp, - (char *)cp1, sizeof data - INT16SZ); - if (n < 0) - return (-1); - cp += n; - cp1 += (n = (strlen((char *) cp1) + 1)); - n1 = sizeof data - n; - - /* get MAPX400 name */ - n = dn_expand(msg, msg + msglen, cp, (char *)cp1, n1); - if (n < 0) - return (-1); - cp += n; - cp1 += strlen((char *) cp1) + 1; - n = cp1 - (u_char *)data; - cp1 = (u_char *)data; - break; - - case T_SIG: - /* CP is the raw resource record as it arrived. - * CP1, after this switch, points to the internal database version. */ - cp1 = (u_char *)data; - - /* first just copy over the type_covered, algorithm, */ - /* labels, orig ttl, two timestamps, and the footprint */ - BOUNDS_CHECK(cp, NS_SIG_SIGNER); - memcpy(cp1, cp, NS_SIG_SIGNER); - cp += NS_SIG_SIGNER; - cp1 += NS_SIG_SIGNER; - - /* then the signer's name */ - n = dn_expand(msg, msg + msglen, cp, - (char *)cp1, (sizeof data) - 18); - if (n < 0) - return (-1); - cp += n; - cp1 += strlen((char*)cp1)+1; - - /* finally, we copy over the variable-length signature. - Its size is the total data length, minus what we copied. */ - n = dlen - (NS_SIG_SIGNER + n); - if (n > ((int)(sizeof data) - (int)(cp1 - (u_char *)data))) { - hp->rcode = FORMERR; - return (-1); /* out of room! */ - } - memcpy(cp1, cp, n); - cp += n; - cp1 += n; - - /* compute size of data */ - n = cp1 - (u_char *)data; - cp1 = (u_char *)data; - break; - - case T_NXT: - n = dn_expand(msg, msg + msglen, cp, - (char *)data, sizeof data); - if (n < 0) { - hp->rcode = FORMERR; - return (-1); - } - cp += n; - cp1 = (u_char *)data + strlen(data) + 1; - n = dlen - n; - if (n > ((int)(sizeof data) - (int)(cp1 - (u_char *)data))) { - hp->rcode = FORMERR; - return (-1); /* out of room! */ - } - if (n > 0) { /* Actually, n should never be less than 4 */ - memcpy(cp1, cp, n); - cp += n; - } else { - hp->rcode = FORMERR; - return (-1); - } - n += cp1 - (u_char *)data; - cp1 = (u_char *)data; - break; - - default: - cp1 = cp; - n = dlen; - cp += n; - break; - } - - if (n > MAXDATA) { - lprintf(1, "update type %d: %d bytes is too much data\n", - type, n); - hp->rcode = FORMERR; - return (-1); - } - if (cp != rdatap + dlen) { - lprintf(1, - "encoded rdata length is %u, but actual length was %u\n", - dlen, (u_int)(cp - rdatap)); - hp->rcode = FORMERR; - return (-1); - } - - cdata = cp1; - result = cp - rrp; - - /* - * Special handling for SOA records. - */ - - if (type == T_SOA) { - if (ns_samename(dname, zp->z_origin) != 1) { - syslog(LOG_INFO, - "wrong zone name in XFR (wanted \"%s\", got \"%s\")", - zp->z_origin, dname); - hp->rcode = FORMERR; - return (-1); - } - if (soa_cnt == 0) { - badsoa_msg = soa_zinfo(&zp_start, rr_type_ptr, eom); - if (badsoa_msg) { - syslog(LOG_INFO, - "malformed SOA for zone %s: %s", - zp->z_origin, badsoa_msg); - hp->rcode = FORMERR; - return (-1); - } - if (SEQ_GT(zp_start.z_serial, serial_no) || - !check_serial) { - soa_cnt++; - } else { - syslog(LOG_INFO, - "serial went backwards after transfer started"); - return (-1); - } - } else if (soa_cnt == 1) { - badsoa_msg = soa_zinfo(&zp_finish, rr_type_ptr, eom); - if (badsoa_msg) { - syslog(LOG_INFO, - "malformed SOA for zone %s: %s", - zp->z_origin, badsoa_msg); - hp->rcode = FORMERR; - return (-1); - } - if (zp_start.z_serial == zp_finish.z_serial) { - methode = ISNOTIXFR; - if (xfr_detect == 3) - soa_cnt = 0; - } else if (zp_finish.z_serial != serial_no) { - syslog(LOG_INFO, - "Unexpected serial number for zone %s: %u", - zp->z_origin, zp_finish.z_serial); - } - soa_cnt++; - if (methode == ISIXFR) - return (result); - } else { - badsoa_msg = soa_zinfo(&zp_finish, rr_type_ptr, eom); - if (badsoa_msg) { - syslog(LOG_INFO, - "malformed SOA for zone %s: %s", - zp->z_origin, badsoa_msg); - hp->rcode = FORMERR; - return (-1); - } - if (methode == ISIXFR) { - if (zp_start.z_serial == zp_finish.z_serial) { - if (scdsoa) { - soa_cnt = -1; - return (result); - } else { - scdsoa = 1; - soa_cnt++; - }; - } else - soa_cnt++; - } else { - lprintf(2, "SOA, serial %u\n", - zp_finish.z_serial); - if (zp_start.z_serial != zp_finish.z_serial) { - lprintf(1, "serial changed, restart\n"); - restarts++; - if (restarts > MAX_XFER_RESTARTS) { - syslog(LOG_INFO, - "too many transfer restarts for zone %s", - zp->z_origin); - hp->rcode = FORMERR; - return (-1); - } - soa_cnt = 0; - ns_cnt = 0; - minimum_ttl = 0; - strcpy(prev_origin, zp->z_origin); - prev_dname[0] = DEF_DNAME; - /* - * Flush buffer, truncate file - * and seek to beginning to restart. - */ - fflush(dbfp); - if (ftruncate(fileno(dbfp), 0) != 0) { - if (!quiet) - syslog(LOG_INFO, - "ftruncate %s: %m\n", - tmpname); - return (-1); - } - fseek(dbfp, 0L, 0); - return (result); - } - soa_cnt++; - return (result); - } - } - if (soa_cnt == 2) - return (result); - - } - - if (zp->z_type == Z_STUB) { - if (query_type == T_NS && type == T_NS) - ns_cnt++; - /* - * If we're processing a response to an SOA query, we don't - * want to print anything from the response except for the SOA. - * We do want to check everything in the packet, which is - * why we do this check now instead of earlier. - */ - if (query_type == T_SOA && type != T_SOA) - return (result); - } - - if ((!soa_cnt || soa_cnt > 2) && methode == ISNOTIXFR) { - const char *gripe; - - if (!soa_cnt) - gripe = "got RR before first SOA"; - else - gripe = "got RR after second SOA"; - syslog(LOG_INFO, "%s in zone %s", gripe, zp->z_origin); - hp->rcode = FORMERR; - return (-1); - } - - /* - * If they are trying to tell us info about something that is - * not in the zone that we are transfering, then ignore it! - * They don't have the authority to tell us this info. - * - * We have to do a bit of checking here - the name that we are - * checking is is fully qualified & may be in a subdomain of the - * zone in question. We also need to ignore any final dots. - * - * If a domain has both NS records and non-NS records, (for - * example, NS and MX records), then we should ignore the non-NS - * records (except that we should not ignore glue A records). - * XXX: It is difficult to do this properly, so we just compare - * the current dname with that in the most recent NS record. - * This defends against the most common error case, - * where the remote server sends MX records soon after the - * NS records for a particular domain. If sent earlier, we lose. XXX - */ - if (!ns_samedomain(dname, domain)) { - (void) fprintf(dbfp, "; Ignoring info about %s, not in zone %s.\n", - dname, domain); - ignore = "; "; - } else if (type != T_NS && type != T_A && - ns_samename(zone_top, dname) != 1 && - ns_samename(prev_ns_dname, dname) == 1) - { - (void) fprintf(dbfp, "; Ignoring extra info about %s, invalid after NS delegation.\n", - dname); - ignore = "; "; - } else if (class != (unsigned)zp->z_class) { - (void) fprintf(dbfp, "; Ignoring info about %s, not class %s\n", - dname, p_class(zp->z_class)); - ignore = "; "; - } - - /* - * If the current record is not being ignored, but the - * previous record was ignored, then we invalidate information - * that might have been altered by ignored records. - * (This means that we sometimes output unnecessary $ORIGIN - * lines, but that is harmless.) - * - * Also update prev_comment now. - */ - if (prev_comment && ignore[0] == '\0') { - prev_dname[0] = DEF_DNAME; - prev_origin[0] = DEF_DNAME; - } - prev_comment = (ignore[0] != '\0'); - - /* - * set prev_ns_dname if necessary - */ - if (type == T_NS) { - (void) strcpy(prev_ns_dname, dname); - } - - /* - * If the origin has changed, print the new origin - */ - if (ns_samename(prev_origin, origin) != 1) { - (void) strcpy(prev_origin, origin); - (void) fprintf(dbfp, "%s$ORIGIN %s.\n", ignore, origin); - } - - longname = 0; - - if (ns_samename(prev_dname, dname) != 1) { - /* - * set the prev_dname to be the current dname, then cut off all - * characters of dname after (and including) the first '.' - */ - char *cutp; - - (void) strcpy(prev_dname, dname); - escaped = 0; - cutp = dname; - while (*cutp) { - if (!escaped && *cutp == '.') - break; - escaped = (*cutp++ == '\\') && !escaped; - } - *cutp = '\0'; - - if (dname[0] == 0) { - if (origin[0] == 0) - (void) fprintf(dbfp, "%s.\t", ignore); - else - (void) fprintf(dbfp, "%s.%s.\t", - ignore, origin); /* ??? */ - } else { - const char *backslash; - backslash = (*dname == '@' || *dname == '$') ? - "\\" : ""; - (void) fprintf(dbfp, "%s%s%s\t", ignore, - backslash, dname); - } - if (strlen(dname) > (size_t)8) - longname = 1; - } else { - (void) fprintf(dbfp, "%s\t", ignore); - } - - (void) fprintf(dbfp, "%d\t", (int) ttl); - - (void) fprintf(dbfp, "%s\t%s\t", p_class(class), p_type(type)); - cp = cdata; - - /* - * Print type specific data - */ - switch (type) { - - case T_A: - switch (class) { - case C_IN: - case C_HS: - fputs(inet_ntoa(ina_get(cp)), dbfp); - break; - } - (void) fprintf(dbfp, "\n"); - break; - - case T_CNAME: - case T_MB: - case T_MG: - case T_MR: - case T_PTR: - if (cp[0] == '\0') - (void) fprintf(dbfp, ".\n"); - else - (void) fprintf(dbfp, "%s.\n", cp); - break; - - case T_NS: - cp = cdata; - if (cp[0] == '\0') - (void) fprintf(dbfp, ".\t"); - else - (void) fprintf(dbfp, "%s.", cp); - (void) fprintf(dbfp, "\n"); - break; - - case T_HINFO: - case T_ISDN: - cp2 = cp + n; - for (i = 0; i < 2; i++) { - if (i != 0) - (void) putc(' ', dbfp); - n = *cp++; - cp1 = cp + n; - if (cp1 > cp2) - cp1 = cp2; - (void) putc('"', dbfp); - j = 0; - while (cp < cp1) { - if (*cp == '\0') { - cp = cp1; - break; - } - if (strchr("\n\"\\", *cp)) - (void) putc('\\', dbfp); - (void) putc(*cp++, dbfp); - j++; - } - if (j == 0 && (type != T_ISDN || i == 0)) - (void) putc('?', dbfp); - (void) putc('"', dbfp); - } - (void) putc('\n', dbfp); - break; - - case T_SOA: - (void) fprintf(dbfp, "%s.", cp); - cp += strlen((char *) cp) + 1; - (void) fprintf(dbfp, " %s. (\n", cp); - cp += strlen((char *) cp) + 1; - NS_GET32(tmpnum, cp); - (void) fprintf(dbfp, "%s\t\t%u", ignore, tmpnum); - NS_GET32(tmpnum, cp); - (void) fprintf(dbfp, " %u", tmpnum); - NS_GET32(tmpnum, cp); - (void) fprintf(dbfp, " %u", tmpnum); - NS_GET32(tmpnum, cp); - (void) fprintf(dbfp, " %u", tmpnum); - NS_GET32(tmpnum, cp); - (void) fprintf(dbfp, " %u )\n", tmpnum); - break; - - case T_MX: - case T_AFSDB: - case T_RT: - NS_GET16(tmpnum, cp); - (void) fprintf(dbfp, "%u", tmpnum); - (void) fprintf(dbfp, " %s.\n", cp); - break; - - case T_PX: - NS_GET16(tmpnum, cp); - (void) fprintf(dbfp, "%u", tmpnum); - (void) fprintf(dbfp, " %s.", cp); - cp += strlen((char *) cp) + 1; - (void) fprintf(dbfp, " %s.\n", cp); - break; - - case T_TXT: - case T_X25: - cp1 = cp + n; - while (cp < cp1) { - (void) putc('"', dbfp); - if ((i = *cp++) != 0) { - for (j = i; j > 0 && cp < cp1; j--) { - if (strchr("\n\"\\", *cp)) - (void) putc('\\', dbfp); - (void) putc(*cp++, dbfp); - } - } - (void) putc('"', dbfp); - if (cp < cp1) - (void) putc(' ', dbfp); - } - (void) putc('\n', dbfp); - break; - - case T_NSAP: - fprintf(dbfp, "%s\n", inet_nsap_ntoa(n, cp, NULL)); - break; - - case T_AAAA: { - char t[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"]; - - fprintf(dbfp, "%s\n", inet_ntop(AF_INET6, cp, t, sizeof t)); - break; - } - - case T_LOC: { - char t[255]; - - (void) fprintf(dbfp, "%s\n", loc_ntoa(cp, t)); - break; - } - - case T_NAPTR: { - u_int32_t order, preference; - - /* Order */ - NS_GET16(order, cp); - fprintf(dbfp, "%u", order); - - /* Preference */ - NS_GET16(preference, cp); - fprintf(dbfp, " %u", preference); - - /* Flags */ - n = *cp++; - fprintf(dbfp, " \"%.*s\"", (int)n, cp); - cp += n; - - /* Service */ - n = *cp++; - fprintf(dbfp, " \"%.*s\"", (int)n, cp); - cp += n; - - /* Regexp */ - n = *cp++; - fprintf(dbfp, " \"%.*s\"", (int)n, cp); - cp += n; - - /* Replacement */ - fprintf(dbfp, " %s.\n", cp); - - break; - } - case T_SRV: { - u_int priority, weight, port; - - NS_GET16(priority, cp); - NS_GET16(weight, cp); - NS_GET16(port, cp); - fprintf(dbfp, "\t%u %u %u %s.\n", - priority, weight, port, cp); - break; - } - - case T_WKS: - fputs(inet_ntoa(ina_get(cp)), dbfp); - cp += INADDRSZ; - fputc(' ', dbfp); - proto = protocolname(*cp); - cp += sizeof(char); - (void) fprintf(dbfp, "%s ", proto); - i = 0; - while (cp < cdata + n) { - j = *cp++; - do { - if (j & 0200) - (void) fprintf(dbfp, " %s", - servicename(i, proto)); - j <<= 1; - } while (++i & 07); - } - (void) fprintf(dbfp, "\n"); - break; - - case T_MINFO: - case T_RP: - (void) fprintf(dbfp, "%s.", cp); - cp += strlen((char *) cp) + 1; - (void) fprintf(dbfp, " %s.\n", cp); - break; - - case T_KEY: { - char databuf[16+NS_MD5RSA_MAX_BASE64]; /* 16 for slop */ - u_int keyflags; - - /* get & format key flags */ - keyflags = ns_get16(cp); - (void) fprintf(dbfp, "0x%04x ", keyflags); - cp += INT16SZ; - - /* protocol id */ - (void) fprintf(dbfp, " %u", *cp++); - - /* algorithm id */ - (void) fprintf(dbfp, " %u ", *cp++); - - /* key itself (which may have zero length) */ - n = b64_ntop(cp, (cp1 + n) - cp, databuf, sizeof databuf); - if (n < 0) - fprintf(dbfp, "; BAD BASE64\n"); - else - fprintf(dbfp, "%s\n", databuf); - break; - } - - case T_SIG: { - char databuf[16+NS_MD5RSA_MAX_BASE64]; /* 16 for slop */ - - /* get & format rr type which signature covers */ - (void) fprintf(dbfp,"%s", p_type(ns_get16((u_char*)cp))); - cp += INT16SZ; - - /* algorithm id */ - (void) fprintf(dbfp," %d",*cp++); - - /* labels (# of labels in name) */ - (void) fprintf(dbfp," %d",*cp++); - - /* orig time to live (TTL)) */ - (void) fprintf(dbfp," %u", (u_int32_t)ns_get32((u_char*)cp)); - cp += INT32SZ; - - /* expiration time */ - (void) fprintf(dbfp," %s", p_secstodate(ns_get32((u_char*)cp))); - cp += INT32SZ; - - /* time signed */ - (void) fprintf(dbfp," %s", p_secstodate(ns_get32((u_char*)cp))); - cp += INT32SZ; - - /* Key footprint */ - (void) fprintf(dbfp," %d", ns_get16((u_char*)cp)); - cp += INT16SZ; - - /* signer's name */ - (void) fprintf(dbfp, " %s. ", cp); - cp += strlen((char *) cp) + 1; - - /* signature itself */ - n = b64_ntop(cp, (cdata + n) - cp, databuf, sizeof databuf); - if (n < 0) - fprintf (dbfp, "; BAD BASE64\n"); - else - fprintf (dbfp, "%s\n", databuf); - break; - } - - case T_NXT: - fprintf(dbfp, "%s.", (char *)cp); - i = strlen((char *)cp)+1; - cp += i; - n -= i; - for (i=0; i < n*NS_NXT_BITS; i++) - if (NS_NXT_BIT_ISSET (i, cp)) - fprintf(dbfp, " %s", p_type(i)); - fprintf(dbfp,"\n"); - break; - - case ns_t_cert: { - int databufsize = n * 4 / 3 + 4; - char *databuf = malloc(databufsize); - - if (databuf == NULL) - panic("cert malloc failed", NULL); - - /* Object id */ - (void) fprintf(dbfp,"%d ", ns_get16((u_char*)cp)); - cp += INT16SZ; - - /* Key tag */ - (void) fprintf(dbfp,"%d ", ns_get16((u_char*)cp)); - cp += INT16SZ; - - /* Algorithm id */ - (void) fprintf(dbfp,"%d ", (u_char)*cp); - cp += 1; - - n = b64_ntop(cp, n - 2 * INT16SZ - 1, databuf, databufsize); - if (n < 0) - panic ("cert b64_ntop failed", NULL); - fprintf (dbfp, "%s\n", databuf); - free(databuf); - break; - } - - default: - fprintf (dbfp, "\\# %u", n); - if (n > 0) { - fputs(" ( ", dbfp); - isc_puthexstring(dbfp, cp1, n, - (longname ? 28 : 40), 48, - "\n\t\t\t\t"); - fputs(" )\n", dbfp); - } - - } - if (ferror(dbfp)) { - syslog(LOG_ERR, "%s: %m", tmpname); - cleanup_for_exit(); - exit(XFER_FAIL); - } - return (result); -} - -#ifdef SHORT_FNAMES -/* -** This routine handles creating temporary files with mkstemp -** in the presence of a 14 char filename system. Pathconf() -** does not work over NFS. -*/ -filenamecpy(char *ddtfile, char *optarg) { - int namelen, extra, len; - char *dirname, *filename; - - /* determine the length of filename allowed */ - if((dirname = strrchr(optarg, '/')) == NULL){ - filename = optarg; - } else { - *dirname++ = '\0'; - filename = dirname; - } - namelen = pathconf(dirname == NULL? "." : optarg, _PC_NAME_MAX); - if(namelen <= 0) - namelen = 255; /* length could not be determined */ - if(dirname != NULL) - *--dirname = '/'; - - /* copy a shorter name if it will be longer than allowed */ - extra = (strlen(filename)+strlen(".XXXXXX")) - namelen; - if(extra > 0){ - len = strlen(optarg) - extra; - (void) strncpy(ddtfile, optarg, len); - ddtfile[len] = '\0'; - } else - (void) strcpy(ddtfile, optarg); -} -#endif /* SHORT_FNAMES */ - -DST_KEY * -tsig_key_from_addr(struct in_addr addr) { - tsig_node *n; - for (n = HEAD(tsig_list); n != NULL; n = NEXT(n, link)) - if (memcpy(&addr, &n->addr, sizeof(struct in_addr))) - return n->dst_key; - return NULL; -} - -static u_int32_t -do_section(ns_msg *handle, ns_sect section, int pflag, FILE *file, int *delete) { - int n, sflag, rrnum; - char buf[2048]; /* XXX need to malloc */ - ns_opcode opcode; - ns_rr rr; - const unsigned char *cp; - const unsigned char *eom; - u_int32_t serial = 0; - time_t now; - - time(&now); - - /* - * Print answer records. - */ - sflag = (_res.pfcode & pflag); - if (_res.pfcode && !sflag) - return (-1); - - opcode = (ns_opcode)ns_msg_getflag(*handle, ns_f_opcode); - rrnum = 0; - for (;;) { - if (ns_parserr(handle, section, rrnum, &rr)) { - if (errno != ENODEV) { - fprintf(file, ";; ns_parserr: %s\n", - strerror(errno)); - return (-1); - } else if (rrnum > 0 && sflag != 0 && - (_res.pfcode & RES_PRF_HEAD1)) - putc('\n', file); - break; - } - if (rrnum == 0 && sflag != 0 && (_res.pfcode & RES_PRF_HEAD1)) - fprintf(file, ";; %s SECTION:\n", - p_section(section, opcode)); - if (section == ns_s_qd) - fprintf(file, ";;\t%s, type = %s, class = %s\n", - ns_rr_name(rr), - p_type(ns_rr_type(rr)), - p_class(ns_rr_class(rr))); - else { - int print_record = 1; - if (rr.type == ns_t_soa) { - print_record = 0; - *delete = !*delete; - cp = ns_rr_rdata(rr); - eom = cp + ns_rr_rdlen(rr); - if ((n = dn_skipname(cp, eom)) < 0) { - rrnum++; - continue; - } - cp += n; - if ((n = dn_skipname(cp, eom)) < 0) { - rrnum++; - continue; - } - cp += n; - NS_GET32(serial, cp); - switch (++ixfr_soa) { - case 1: - final_serial = serial; - if (soa_buf == NULL) { - if ((soa_buf = (char *)malloc(2 * PACKETSZ)) == NULL) { - syslog(LOG_INFO, "malloc(%u) failed", 2 * PACKETSZ); - return(-1); - } - n = ns_sprintrr(handle, &rr, NULL, NULL, - soa_buf, 2*PACKETSZ); - if (n < 0) { - fprintf(file, ";; ns_sprintrr: %s\n", - strerror(errno)); - return (-1); - } - } - print_record = 0; - break; - case 2: - fprintf(file, - "zone:\torigin %s class %s serial %u\n", - ns_rr_name(rr), - p_class(ns_rr_class(rr)), - serial); - print_record = 0; - break; - default: - print_record = 0; - break; - } - - } - - if (print_record) { - if (rr.type != ns_t_soa) { - fprintf(file, "update:\t{%s} ", - *delete ? "delete" : "add"); - - n = ns_sprintrr(handle, &rr, NULL, NULL, - buf, sizeof buf); - if (n < 0) { - fprintf(file, ";; ns_sprintrr: %s\n", - strerror(errno)); - return(-1); - } - fputs(buf, file); - fputc('\n', file); - } - } - - } - rrnum++; - } - return (serial); -} - -static int -ixfr_log(const u_char *msg, int len, int *delete, FILE *file, - struct sockaddr_in *sin, u_int32_t *serial_no, int *first_rr) -{ - ns_msg handle; - ns_type type; - ns_class class; - ns_opcode opcode; - ns_rcode rcode; - u_int id; - u_int32_t new_serial = 0; - char time[25]; - ns_rr rr; - - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { - lprintf(1, "ixfr_log() failed\n"); - return (-1); - } - - if (ns_initparse(msg, len, &handle) < 0) { - fprintf(file, ";; ns_initparse: %s\n", strerror(errno)); - lprintf(1, "ixfr_log() failed\n"); - return (-1); - } - opcode = (ns_opcode) ns_msg_getflag(handle, ns_f_opcode); - rcode = (ns_rcode) ns_msg_getflag(handle, ns_f_rcode); - id = ns_msg_id(handle); - - if (ns_parserr(&handle, ns_s_an, 0, &rr)) - { - - (void) fprintf(file,"ns_parserr() failed"); - lprintf(1, "ixfr_log() failed\n"); - return (-1); - } - type = (ns_type)rr.type; - class = (ns_class)rr.rr_class; - - if (*first_rr == 1) { - gettime(&tt); - (void) fprintf(file,"%s", LogSignature); - sprintf(time, "at %lu", (u_long)tt.tv_sec); - fprintf(file, - "[IXFR_UPDATE] id %u from [%s].%d %s (named-xfer pid %ld):\n", - id, inet_ntoa(sin->sin_addr), - ntohs(sin->sin_port), time, (long)getpid()); - (*first_rr)++; - } - new_serial = do_section(&handle, ns_s_an, RES_PRF_ANS, file, delete); - if (type == T_SOA && SEQ_GT(new_serial, *serial_no) && (*delete)) - *serial_no = new_serial; - return (1); -} - -static const char * -tsig_rcode(int rcode) { - static char buffer[64]; - - switch (rcode) { - case ns_r_badkey: - case ns_r_badsig: - case ns_r_badtime: - sprintf(buffer, "message had %s set", p_rcode(rcode)); - return (buffer); - case -ns_r_badkey: - case -ns_r_badsig: - case -ns_r_badtime: - return (p_rcode(-rcode)); - case NS_TSIG_ERROR_NO_TSIG: - return ("no TSIG present"); - default: - break; - } - return ("FORMERR"); -} |