From 3fc00dd03fa8c0de826c282a396d09094b217010 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 30 Nov 1999 02:52:56 +0000 Subject: Merge changes from vendor branch onto HEAD. --- contrib/bind/bin/named-xfer/named-xfer.c | 1135 +++++++++++++++++++++++++----- contrib/bind/bin/named/Makefile | 55 +- contrib/bind/bin/nslookup/commands.l | 7 +- contrib/bind/bin/nslookup/debug.c | 21 +- contrib/bind/bin/nslookup/getinfo.c | 84 +-- contrib/bind/bin/nslookup/main.c | 254 ++++--- 6 files changed, 1213 insertions(+), 343 deletions(-) (limited to 'contrib/bind/bin') diff --git a/contrib/bind/bin/named-xfer/named-xfer.c b/contrib/bind/bin/named-xfer/named-xfer.c index 062cc33..d7db886 100644 --- a/contrib/bind/bin/named-xfer/named-xfer.c +++ b/contrib/bind/bin/named-xfer/named-xfer.c @@ -1,5 +1,6 @@ +/* $FreeBSD$ */ /* - * The original version of xfer by Kevin Dunlap. + * 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. @@ -84,7 +85,8 @@ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. */ -/* Portions Copyright (c) 1996, 1997 by Internet Software Consortium. +/* + * 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 @@ -100,27 +102,45 @@ * 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 char sccsid[] = "@(#)named-xfer.c 4.18 (Berkeley) 3/7/91"; -static char rcsid[] = "$Id: named-xfer.c,v 8.38 1998/03/27 00:19:28 halley Exp $"; +static const char sccsid[] = "@(#)named-xfer.c 4.18 (Berkeley) 3/7/91"; +static const char rcsid[] = "$Id: named-xfer.c,v 8.89 1999/11/09 20:36:54 marka Exp $"; #endif /* not lint */ #include "port_before.h" -#include "fd_setsize.h" - #include #include #include #include #include +#include #include #include @@ -141,26 +161,39 @@ static char rcsid[] = "$Id: named-xfer.c,v 8.38 1998/03/27 00:19:28 halley Exp $ #include #include +#include #include +/* This still uses malloc/free, but the tsig routines allocate memory with + * memget, and we free it with memput. + */ +#include + +#include #include "port_after.h" + #define MAIN_PROGRAM #include "../named/named.h" #undef MAIN_PROGRAM #define MAX_XFER_RESTARTS 2 +#define ENABLE_IXFR 0 + # ifdef SHORT_FNAMES extern long pathconf __P((const char *path, int name)); /* XXX */ # endif + static struct zoneinfo zone; /* zone information */ -static char ddtfilename[] = _PATH_TMPXFER, - *ddtfile = ddtfilename, - *tmpname, - *domain; /* domain being xfered */ +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, @@ -168,30 +201,48 @@ static int quiet = 0, domain_len; /* strlen(domain) */ static FILE *fp = NULL, - *dbfp = NULL; + *dbfp = NULL, + *ixfp = NULL; static char *ProgName; -static void usage(const char *); +static void usage(const char *), + 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 *), netread(int, char *, int, int), writemsg(int, const u_char *, int); +static void ixfr_log(const u_char *msg, int len, int *delete, + FILE *file, struct sockaddr_in *sin, + char *domain, 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*); +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; +static u_int32_t old_serial; 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. */ -#ifdef DEBUG void dprintf(int level, const char *format, ...) { va_list ap; @@ -201,10 +252,9 @@ dprintf(int level, const char *format, ...) { (void) vfprintf(ddt, format, ap); va_end(ap); } -#endif /*DEBUG*/ -static -int init_xfer_logging() { +static int +init_xfer_logging() { log_channel chan; if (log_new_context(ns_log_max_category, NULL, &log_ctx) < 0) { @@ -243,7 +293,26 @@ 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; } @@ -252,18 +321,22 @@ main(int argc, char *argv[]) { struct zoneinfo *zp; struct hostent *hp; struct in_addr axfr_src; - char *dbfile = NULL, *tracefile = NULL, *tm = NULL; - int dbfd, ddtd, result, c, fd, closed = 0; + char *dbfile = NULL, *tracefile = NULL, *tm = NULL, *tsigfile = NULL; + char *ixfrfile = NULL; + u_int32_t new_serial_no = 0; + int dbfd, ddtd, result, c, fd, ixfd; u_int32_t serial_no = 0; u_int port = htons(NAMESERVER_PORT); struct stat statbuf; -#ifdef STUBS int stub_only = 0; -#endif int class = C_IN; int n; long num_files; +#ifdef _AUX_SOURCE + set42sig(); +#endif + memset(&axfr_src, 0, sizeof axfr_src); ProgName = strrchr(argv[0], '/'); if (ProgName != NULL) ProgName++; @@ -272,10 +345,9 @@ main(int argc, char *argv[]) { (void) umask(022); - /* this is a hack; closing everything in the parent is hard. */ - num_files = MIN(sysconf(_SC_OPEN_MAX), FD_SETSIZE); - for (fd = num_files - 1; fd > STDERR_FILENO; fd--) - closed += (close(fd) == 0); + ddtfilename = (char *)malloc(strlen(_PATH_TMPXFER) + 1); + strcpy(ddtfilename, _PATH_TMPXFER); + ddtfile = ddtfilename; #ifdef RENICE nice(-40); /* this is the recommended procedure to */ @@ -283,24 +355,21 @@ main(int argc, char *argv[]) { nice(0); /* to "normal" (== 0) - see nice(3) */ #endif + n = LOG_PID; #ifdef LOG_PERROR - n = LOG_PERROR; -#else - n = 0; + n |= LOG_PERROR; #endif -#ifdef SYSLOG_42BSD - openlog(ProgName, LOG_PID); -#else - openlog(ProgName, LOG_PID|LOG_CONS|n, LOG_DAEMON); +#if defined(LOG_CONS) && defined(USE_LOG_CONS) + n |= LOG_CONS; #endif - axfr_src.s_addr = 0; -#ifdef STUBS - while ((c = getopt(argc, argv, "C:d:l:s:t:z:f:p:P:qx:S")) != EOF) +#ifdef SYSLOG_42BSD + openlog(ProgName, n); #else - while ((c = getopt(argc, argv, "C:d:l:s:t:z:f:p:P:qx:")) != EOF) + openlog(ProgName, n, LOG_DAEMON); #endif - switch (c) { - case 'C': + 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': @@ -322,6 +391,7 @@ main(int argc, char *argv[]) { break; case 's': serial_no = strtoul(optarg, (char **)NULL, 10); + check_serial++; break; case 't': tracefile = optarg; @@ -345,17 +415,29 @@ main(int argc, char *argv[]) { (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; -#ifdef STUBS case 'S': stub_only = 1; break; -#endif case 'q': quiet++; break; @@ -363,13 +445,18 @@ main(int argc, char *argv[]) { 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 || optind >= argc) { + } + if (!domain || ((!dbfile) && (!ixfrfile)) || optind >= argc) { if (!domain) usage("no domain"); if (!dbfile) @@ -382,6 +469,14 @@ main(int argc, char *argv[]) { !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"); @@ -389,8 +484,8 @@ main(int argc, char *argv[]) { if ((dbfd = mkstemp(tmpname)) == -1) { perror(tmpname); if (!quiet) - syslog(LOG_ERR, "can't make tmpfile (%s): %m\n", - tmpname); + syslog(LOG_ERR, "can't make tmpfile (%s): %s\n", + tmpname, strerror(errno)); exit(XFER_FAIL); } #ifdef HAVE_FCHMOD /* XXX */ @@ -401,8 +496,8 @@ main(int argc, char *argv[]) { { perror(tmpname); if (!quiet) - syslog(LOG_ERR, "can't [f]chmod tmpfile (%s): %m\n", - tmpname); + syslog(LOG_ERR, "can't [f]chmod tmpfile (%s): %s\n", + tmpname, strerror(errno)); exit(XFER_FAIL); } if ((dbfp = fdopen(dbfd, "r+")) == NULL) { @@ -411,6 +506,36 @@ main(int argc, char *argv[]) { syslog(LOG_ERR, "can't fdopen tmpfile (%s)", 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" */ @@ -433,8 +558,8 @@ main(int argc, char *argv[]) { setvbuf(ddt, NULL, _IOLBF, 0); } #endif - if (!init_xfer_logging()) { + cleanup_for_exit(); perror("init_xfer_logging"); } @@ -464,20 +589,25 @@ main(int argc, char *argv[]) { (void) signal(SIGFPE, SIG_IGN); #endif /* SIGUSR1&&SIGUSR2 */ - dprintf(1, "domain `%s'; file `%s'; serial %u; closed %d\n", - domain, dbfile, serial_no, closed); + if (dbfile) + dprintf(1, "domain `%s'; file `%s'; serial %u\n", + domain, dbfile, serial_no); + + if (ixfrfile) + dprintf(1, "domain `%s'; ixfrfile `%s'; serial %u\n", + domain, ixfrfile, serial_no); buildservicelist(); buildprotolist(); + tsig_init(tsigfile); + /* init zone data */ zp = &zone; -#ifdef STUBS if (stub_only) zp->z_type = Z_STUB; else -#endif zp->z_type = Z_SECONDARY; zp->z_class = class; zp->z_origin = domain; @@ -490,8 +620,34 @@ main(int argc, char *argv[]) { 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, @@ -502,7 +658,7 @@ main(int argc, char *argv[]) { memcpy(&zp->z_addr[zp->z_addrcnt], hp->h_addr, INADDRSZ); - dprintf(1, "Arg: \"%s\"\n", tm); + dprintf(1, "Arg: \"%s\" %s\n", tm,((tmpsupportixfr) ? "IXFR":"AXFR")); } if (++zp->z_addrcnt >= NSMAX) { zp->z_addrcnt = NSMAX; @@ -512,24 +668,71 @@ main(int argc, char *argv[]) { } dprintf(1, "addrcnt = %d\n", zp->z_addrcnt); - res_init(); - _res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE); + res_ninit(&res); + res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE); result = getzone(zp, serial_no, port); - (void) my_fclose(dbfp); + (void) fclose(dbfp); + (void) close(dbfd); + + if (ixfp) + (void) my_fclose(ixfp); + else + close(ixfd); + switch (result) { - case XFER_SUCCESS: /* ok exit */ - if (rename(tmpname, dbfile) == -1) { - perror("rename"); + 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 (movefile(tmpname, ixfrfile) == -1) { + perror("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 (movefile(tmpname, dbfile) == -1) { + perror("movefile"); if (!quiet) - syslog(LOG_ERR, "rename %s to %s: %m", + syslog(LOG_ERR, "movefile %s to %s: %m", tmpname, dbfile); + cleanup_for_exit(); exit(XFER_FAIL); } - exit(XFER_SUCCESS); + exit(XFER_SUCCESSAXFR); + + case XFER_SUCCESSIXFR: + unlink(tmpname); + if (movefile(tmpiname, ixfrfile) == -1) { + perror("movefile"); + if (!quiet) + syslog(LOG_ERR, "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: @@ -537,6 +740,7 @@ main(int argc, char *argv[]) { /* fall through */ case XFER_TIMEOUT: case XFER_FAIL: + (void) unlink(tmpname); cleanup_for_exit(); exit(result); /* error or timeout */ } @@ -547,17 +751,17 @@ main(int argc, char *argv[]) { static char *UsageText[] = { "\t-z zone_to_transfer\n", "\t-f db_file\n", - "\t-s serial_no\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", -#ifdef STUBS - "\t[-S]\n", -#endif + "\t[-S] [-Z]\n", "\t[-C class]\n", "\t[-x axfr-src]\n", - "\tservers...\n", + "\t[-T tsig_info_file]\n", + "\tservers [-ixfr|-axfr]...\n", NULL }; @@ -572,13 +776,66 @@ usage(const char *msg) { exit(XFER_FAIL); } +static void +tsig_init(const char *file) { + char buf[1024]; + int n; + FILE *fp; + char *s; + + if (file == NULL) + return; + fp = fopen(file, "r"); + if (fp == NULL) + return; + dst_init(); + INIT_LIST(tsig_list); + while (1) { + tsig_node *n = malloc(sizeof(tsig_node)); + int alg, secret_len; + char *address, *name; + char *cp; + u_char secret[128]; + + 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); + + 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); + APPEND(tsig_list, n, link); + } + fclose(fp); + unlink(file); +} + #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; -#ifdef STUBS +int soa_cnt = 0, scdsoa = 0, methode = ISNOTIXFR; +int delete_soa = 1; +u_int32_t final_serial = 0; +int ixfr_soa = 0; +int firstsoa = 1; int ns_cnt = 0; -#endif int query_type = 0; int prev_comment = 0; /* was previous record a comment? */ char zone_top[MAXDNAME]; /* the top of the zone */ @@ -592,19 +849,32 @@ getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { u_int len; u_int32_t serial; 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 *buf = NULL, *cpp = NULL; u_int bufsize = 0; char name[MAXDNAME], name2[MAXDNAME]; struct sockaddr_in sin; + struct sockaddr_in local; + int locallen; #ifdef POSIX_SIGNALS struct sigaction sv, osv; #else struct sigvec sv, osv; #endif - int qdcount, ancount, aucount, class, type; + int qdcount, ancount, aucount, arcount, class, type; const char *badsoa_msg = "Nil"; + struct sockaddr_in my_addr; + char my_addr_text[30]; + int alen, ret, tsig_req; + DST_KEY *tsig_key; + ns_tcp_tsig_state tsig_state; + int tsig_signed = 0; + u_char sig[64]; + int siglen; + int ixfr_first = 1; + time_t timesigned; #ifdef DEBUG if (debug) { @@ -648,9 +918,23 @@ getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { 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]; + dprintf(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; if (buf == NULL) { if ((buf = (u_char *)malloc(2 * PACKETSZ)) == NULL) { @@ -661,6 +945,7 @@ getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { } bufsize = 2 * PACKETSZ; } + try_again: if ((s = socket(AF_INET, SOCK_STREAM, PF_UNSPEC)) < 0) { syslog(LOG_INFO, "socket: %m"); error++; @@ -684,20 +969,72 @@ getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { dprintf(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 (zp->z_axfr_src.s_addr != 0) { + dprintf(2, "connect failed, trying w/o -x"); + zp->z_axfr_src.s_addr = 0; + (void) my_close(s); + goto try_again; + } if (!quiet) syslog(LOG_INFO, - "connect(%s) for zone %s failed: %m", - inet_ntoa(sin.sin_addr), zp->z_origin); + "connect(%s) for zone %s failed: %s", + inet_ntoa(sin.sin_addr), zp->z_origin, strerror(errno)); error++; (void) my_close(s); continue; } - n = res_mkquery(QUERY, zp->z_origin, curclass, - T_SOA, NULL, 0, NULL, buf, bufsize); + if (methode == ISIXFR) { + hp = (HEADER *) buf; + cpp = buf; + n = res_nmkquery(&res, QUERY, zp->z_origin, curclass, + T_IXFR, NULL, 0, NULL, buf, bufsize); + dprintf(1, "len = %d\n", n); + if (n < 0) { + if (!quiet) + syslog(LOG_INFO, + "zone %s: dn_comp for ixfr failed", + zp->z_origin); + (void) my_close(s); +#ifdef POSIX_SIGNALS + sigaction(SIGALRM, + &osv, + (struct sigaction*)0); +#else + sigvec(SIGALRM, + &osv, + (struct sigvec *)0); +#endif + return (XFER_FAIL); + } + hp->nscount = htons(1+ntohs(hp->nscount)); + cpp += n; + n = dn_comp(zp->z_origin, cpp, bufsize-(cpp-buf), + NULL, NULL); + if (n > 0) + cpp += n; + PUTSHORT(T_SOA, cpp); /* type */ + PUTSHORT(C_IN, cpp); /* class */ + PUTLONG(0, cpp); /* ttl */ + PUTSHORT(22, cpp); /* dlen */ + *cpp++ = 0; /* mname */ + *cpp++ = 0; /* rname */ + PUTLONG(serial_no, cpp); + PUTLONG(0xDEAD, cpp); /* Refresh */ + PUTLONG(0xBEEF, cpp); /* Retry */ + PUTLONG(0xABCD, cpp); /* Expire */ + PUTLONG(0x1776, cpp); /* Min TTL */ + n = cpp-buf; + dprintf(1, "len = %d\n", cpp-buf); + if (debug) + res_pquery(&res, buf, n, ddt); + } + else { + n = res_nmkquery(&res, QUERY, zp->z_origin, curclass, + T_SOA, NULL, 0, NULL, buf, bufsize); if (n < 0) { if (!quiet) syslog(LOG_INFO, - "zone %s: res_mkquery T_SOA failed", + "zone %s: res_nmkquery T_SOA failed", zp->z_origin); (void) my_close(s); #ifdef POSIX_SIGNALS @@ -707,6 +1044,19 @@ getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { #endif return (XFER_FAIL); } + } + /* + * Append TSIG to SOA query if desired + */ + tsig_key = tsig_key_from_addr(sin.sin_addr); + if (tsig_key != NULL) { + siglen = sizeof(sig); + ret = ns_sign(buf, &n, bufsize, NOERROR, tsig_key, + NULL, 0, sig, &siglen, timesigned); + if (ret == 0) + tsig_signed = 1; + } + /* * Send length & message for SOA query */ @@ -719,6 +1069,7 @@ getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { /* * Get out your butterfly net and catch the SOA */ + if (netread(s, (char *)buf, INT16SZ, XFER_TIMER) < 0) { error++; (void) my_close(s); @@ -745,16 +1096,52 @@ getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { (void) my_close(s); continue; } + /* + * Verify the TSIG if expected + */ + if (tsig_signed != 0) { + ret = ns_verify(buf, (int *)&len, tsig_key, sig, siglen, + NULL, NULL, ×igned, 0); + if (ret != 0) { + syslog(LOG_NOTICE, + "SOA TSIG verification from server [%s], zone %s: %s (%d)\n", + inet_ntoa(sin.sin_addr), zp->z_origin, + tsig_rcode(ret), ret); + error++; + continue; + } + } + #ifdef DEBUG if (debug >= 3) { (void)fprintf(ddt,"len = %d\n", len); - fp_nquery(buf, len, ddt); + res_pquery(&res, buf, len, ddt); } #endif + if ((methode == ISIXFR) && (ixfp == NULL)) { + delete_soa = 1; + firstsoa = 1; + ixfr_soa = 0; + old_serial = serial_no; + if (ixfp != NULL) { + fflush(ixfp); + /* XXX error */ + ftruncate(fileno(ixfp), 0); + } else if ((ixfp = fopen(tmpiname, "w+")) == NULL) { + perror(tmpiname); + if (!quiet) + syslog(LOG_ERR, + "can't fdopen 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: @@ -809,8 +1196,8 @@ getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { } NS_GET16(type, tmp); NS_GET16(class, tmp); - if (class != curclass || type != T_SOA || - strcasecmp(zp->z_origin, name2) != 0) { + if (class != curclass || ((type != T_SOA) && type != T_IXFR) || + 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, @@ -857,7 +1244,7 @@ getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { tmp = cp4 + dlen; } while (1); - if (strcasecmp(zp->z_origin, name2) != 0) { + 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, @@ -869,16 +1256,35 @@ getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { badsoa_msg = soa_zinfo(&zp_start, tmp, eom); if (badsoa_msg) goto badsoa; - if (SEQ_GT(zp_start.z_serial, serial_no) || !serial_no) { - const char *l, *nl; + if (SEQ_GT(zp_start.z_serial, serial_no) || !check_serial) { + const char *l, *nl, *t; + dprintf(1, "need update, serial %u\n", zp_start.z_serial); hp = (HEADER *) buf; - soa_cnt = 0; -#ifdef STUBS + if ((methode == ISIXFR) && (soa_cnt == 0)) { + if (type == T_IXFR) { + if (ixfp) + ixfr_log(buf, len, &delete_soa, ixfp, + &sin, domain, serial_no, + &ixfr_first); + soa_cnt = 2; + } else { + dprintf(1, + "server %s rejected IXFR and responded with AXFR\n", + inet_ntoa(sin.sin_addr)); + methode = ISNOTIXFR; + was_ixfr++; + soa_cnt++; + } + } ns_cnt = 0; -#endif 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) { @@ -894,41 +1300,62 @@ getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { fprintf(dbfp, "; BIND version %.*s\n", (int)len, l); } - fprintf(dbfp, "; zone '%s' last serial %u\n", + fprintf(dbfp, check_serial? + "; zone '%s' last serial %u\n": + "; zone '%s' first transfer\n", domain, serial_no); - fprintf(dbfp, "; from %s at %s", - inet_ntoa(sin.sin_addr), + t = strdup(inet_ntoa(sin.sin_addr)); + fprintf(dbfp, "; from %s:%d (local %s) using %s at %s", + t, ntohs(sin.sin_port), + inet_ntoa(local.sin_addr), + (methode == ISIXFR) ? "IXFR":"AXFR", ctimel(tt.tv_sec)); + free((void *)t); for (;;) { if ((soa_cnt == 0) || (zp->z_type == Z_STUB)) { -#ifdef STUBS if (zp->z_type == Z_STUB) { if (soa_cnt == 1 && ns_cnt == 0) query_type = T_NS; else query_type = T_SOA; - } else -#endif - query_type = T_AXFR; - n = res_mkquery(QUERY, zp->z_origin, - curclass, query_type, - NULL, 0, - NULL, buf, bufsize); + } else if (methode == ISIXFR) + query_type = T_IXFR; + else + query_type = xfr_qtype; + n = res_nmkquery(&res, QUERY, + zp->z_origin, + curclass, query_type, + NULL, 0, + NULL, buf, bufsize); + syslog(LOG_INFO, + "send %s query %d to %s", + (query_type == T_IXFR) ? "IXFR" : + (query_type == T_AXFR) ? "AXFR" : + (query_type == ns_t_zxfr) ? "ZXFR" : + (query_type == T_SOA) ? "SOA" : "NS", + cnt, inet_ntoa(sin.sin_addr)); + dprintf(1, + "send %s query to %s\n", + (query_type == T_IXFR) ? "IXFR" : + (query_type == T_AXFR) ? "AXFR" : + (query_type == ns_t_zxfr) ? "ZXFR" : + (query_type == T_SOA) ? "SOA" : "NS", + inet_ntoa(sin.sin_addr)); + dprintf(1,"bufsize = %d\n", bufsize); if (n < 0) { if (!quiet) { -#ifdef STUBS if (zp->z_type == Z_STUB) syslog(LOG_INFO, (query_type == T_SOA) - ? "zone %s: res_mkquery T_SOA failed" - : "zone %s: res_mkquery T_NS failed", + ? "zone %s: res_nmkquery T_SOA failed" + : "zone %s: res_nmkquery T_NS failed", zp->z_origin); else -#endif syslog(LOG_INFO, - "zone %s: res_mkquery T_AXFR failed", - zp->z_origin); + "zone %s: res_nmkquery %s failed", + zp->z_origin, + p_type(query_type)); } (void) my_close(s); #ifdef POSIX_SIGNALS @@ -940,10 +1367,25 @@ getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { #endif return (XFER_FAIL); } + cpp = buf + n; + /* + * Append TSIG to AXFR query if desired + */ + if (tsig_signed != 0) { + siglen = sizeof(sig); + ns_sign(buf, &n, bufsize, + NOERROR, tsig_key, + NULL, 0, sig, &siglen, + timesigned); + cpp = buf + n; + ns_verify_tcp_init(tsig_key, + sig, siglen, + &tsig_state); + } /* * Send length & msg for zone transfer */ - if (writemsg(s, buf, n) < 0) { + if (writemsg(s, buf, cpp - buf) < 0) { syslog(LOG_INFO, "writemsg: %m"); error++; @@ -951,6 +1393,8 @@ getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { break; } } +/*XXX ZXFR*/ + if (methode == ISNOTIXFR && !was_ixfr) { /* * Receive length & response */ @@ -966,7 +1410,7 @@ getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { buf = (u_char *)realloc(buf, len); if (buf == NULL) { syslog(LOG_INFO, - "malloc(%u) failed for packet from server [%s], zone %s\n", + "malloc(%u) failed for packet from server [%s], zone %s\n", len, inet_ntoa(sin.sin_addr), zp->z_origin); @@ -982,18 +1426,36 @@ getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { error++; break; } + } #ifdef DEBUG if (debug >= 3) { (void)fprintf(ddt,"len = %d\n", len); - fp_nquery(buf, len, ddt); + res_pquery(&res, buf, len, ddt); } if (fp) - fp_nquery(buf, len, fp); + res_pquery(&res, buf, len, fp); #endif + /* + * Verify the TSIG if expected + */ + if (tsig_signed != 0) { + tsig_req = (soa_cnt == 0); + ret = ns_verify_tcp(buf, (int *)&len, + &tsig_state, + tsig_req); + eom = buf + len; + + if (ret != 0) { + syslog(LOG_NOTICE, + "TSIG verification from server [%s], zone %s: %s (%d)\n", + inet_ntoa(sin.sin_addr), + zp->z_origin, + tsig_rcode(ret), ret); + error++; + break; + } + } if (len < HFIXEDSZ) { - struct sockaddr_in my_addr; - char my_addr_text[30]; - int alen; badrec: error++; @@ -1009,25 +1471,54 @@ getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { sin_addr), ntohs(my_addr.sin_port) ); - syslog(LOG_INFO, + 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); + } else { + syslog(LOG_INFO, "[%s] record too short from [%s], zone %s\n", - my_addr_text, - inet_ntoa(sin.sin_addr), - zp->z_origin); + my_addr_text, + inet_ntoa(sin.sin_addr), + zp->z_origin); + } break; } + if (query_type == T_IXFR) + if (hp->rcode != NOERROR) { + dprintf(1, + "server %s did not support IXFR\n", + inet_ntoa(sin.sin_addr)); + methode = ISNOTIXFR; + continue; + }; cp = buf + HFIXEDSZ; - if (hp->qdcount) { - if ((n = dn_skipname(cp, eom)) == -1 - || n + QFIXEDSZ >= eom - cp) + if (ntohs(hp->qdcount) == 1) { + if ((query_type == T_IXFR) && (methode == ISIXFR)) { + dprintf(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; + } else { + if (methode == ISIXFR && ixfp) + ixfr_log(buf, len, &delete_soa, ixfp, + &sin, domain, serial_no, + &ixfr_first); + } nmp = cp; if ((n = dn_skipname(cp, eom)) == -1) goto badrec; tmp = cp + n; -#ifdef STUBS if (zp->z_type == Z_STUB) { ancount = ntohs(hp->ancount); n = 0; @@ -1091,11 +1582,8 @@ getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { break; } } else { -#endif /*STUBS*/ ancount = ntohs(hp->ancount); - for (n = cnt = 0; - cnt < (u_int)ancount; - cnt++) { + for (n = cnt = 0; cnt < (u_int)ancount; cnt++) { n = print_output(zp, serial_no, buf, len, cp); if (n < 0) @@ -1117,13 +1605,12 @@ getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { error++; break; } -#ifdef STUBS } -#endif - if (soa_cnt >= 2) + if ((soa_cnt >= 2) && (methode == ISNOTIXFR)) + break; + if ((soa_cnt == -1) && (methode == ISIXFR)) break; - } (void) my_close(s); if (error == 0) { @@ -1133,21 +1620,43 @@ getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { #else (void) sigvec(SIGALRM, &osv, (struct sigvec *)0); #endif - return (XFER_SUCCESS); + if (methode == ISIXFR) { + fprintf(ixfp, "update:\t{add} "); + if (soa_buf) + fputs(soa_buf, ixfp); + fprintf(ixfp, "[END_DELTA]\n"); + (void) my_close(s); + return (XFER_SUCCESSIXFR); + } else { + if (ixfp) { + (void) fclose(ixfp); + ixfp = NULL; + } + return (XFER_SUCCESSAXFR); + } + } + if (ixfp) { + (void) fclose(ixfp); + ixfp = NULL; } dprintf(2, "error receiving zone transfer\n"); } else if (zp_start.z_serial == serial_no) { - (void) my_close(s); - dprintf(1, "zone up-to-date, serial %u\n", zp_start.z_serial); - return (XFER_UPTODATE); + (void) my_close(s); + dprintf(1, "zone up-to-date, serial %u\n", zp_start.z_serial); + if (ixfp) { + (void) unlink (tmpiname); + (void) fclose(ixfp); + ixfp = NULL; + } + return (XFER_UPTODATE); } else { - (void) my_close(s); - if (!quiet) - syslog(LOG_NOTICE, + (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); + return (XFER_FAIL); } } #ifdef POSIX_SIGNALS @@ -1155,6 +1664,11 @@ getzone(struct zoneinfo *zp, u_int32_t serial_no, int port) { #else (void) sigvec(SIGALRM, &osv, (struct sigvec *)0); #endif + if (ixfp) { + (void) unlink (tmpiname); + (void) my_fclose(ixfp); + ixfp = 0; + } if (!error) return (XFER_TIMEOUT); return (XFER_FAIL); @@ -1382,6 +1896,7 @@ print_output(struct zoneinfo *zp, u_int32_t serial_no, u_char *msg, case T_NSAP: case T_AAAA: case T_KEY: + case ns_t_cert: cp1 = cp; n = dlen; cp += n; @@ -1640,14 +2155,14 @@ print_output(struct zoneinfo *zp, u_int32_t serial_no, u_char *msg, */ if (type == T_SOA) { - if (strcasecmp(dname, zp->z_origin) != 0) { + if (ns_samename(dname, zp->z_origin) != 1) { syslog(LOG_INFO, - "wrong zone name in AXFR (wanted \"%s\", got \"%s\")", + "wrong zone name in XFR (wanted \"%s\", got \"%s\")", zp->z_origin, dname); hp->rcode = FORMERR; return (-1); } - if (!soa_cnt) { + if (soa_cnt == 0) { badsoa_msg = soa_zinfo(&zp_start, rr_type_ptr, eom); if (badsoa_msg) { syslog(LOG_INFO, @@ -1657,13 +2172,33 @@ print_output(struct zoneinfo *zp, u_int32_t serial_no, u_char *msg, return (-1); } if (SEQ_GT(zp_start.z_serial, serial_no) || - !serial_no) + !check_serial) { soa_cnt++; - else { + } 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; + } 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) || (soa_cnt >= 2)) { + return (result); + } } else { badsoa_msg = soa_zinfo(&zp_finish, rr_type_ptr, eom); if (badsoa_msg) { @@ -1673,45 +2208,56 @@ print_output(struct zoneinfo *zp, u_int32_t serial_no, u_char *msg, hp->rcode = FORMERR; return (-1); } - dprintf(2, "SOA, serial %u\n", zp_finish.z_serial); - if (zp_start.z_serial != zp_finish.z_serial) { - dprintf(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; -#ifdef STUBS - ns_cnt = 0; -#endif - 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) + 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 { + dprintf(2, "SOA, serial %u\n", + zp_finish.z_serial); + if (zp_start.z_serial != zp_finish.z_serial) { + dprintf(1, "serial changed, restart\n"); + restarts++; + if (restarts > MAX_XFER_RESTARTS) { syslog(LOG_INFO, - "ftruncate %s: %m\n", - tmpname); - return (-1); + "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); } - fseek(dbfp, 0L, 0); + soa_cnt++; return (result); } - soa_cnt++; - return (result); } } -#ifdef STUBS if (zp->z_type == Z_STUB) { if (query_type == T_NS && type == T_NS) ns_cnt++; @@ -1724,9 +2270,8 @@ print_output(struct zoneinfo *zp, u_int32_t serial_no, u_char *msg, if (query_type == T_SOA && type != T_SOA) return (result); } -#endif - if (!soa_cnt || soa_cnt >= 2) { + if ((!soa_cnt || soa_cnt > 2) && methode == ISNOTIXFR) { char *gripe; if (!soa_cnt) @@ -1756,17 +2301,21 @@ print_output(struct zoneinfo *zp, u_int32_t serial_no, u_char *msg, * where the remote server sends MX records soon after the * NS records for a particular domain. If sent earlier, we lose. XXX */ - if (!samedomain(dname, domain)) { + 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 && - strcasecmp(zone_top, dname) != 0 && - strcasecmp(prev_ns_dname, dname) == 0) + 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 != zp->z_class) { + (void) fprintf(dbfp, "; Ignoring info about %s, not class %s\n", + dname, p_class(zp->z_class)); + ignore = "; "; } /* @@ -1794,13 +2343,13 @@ print_output(struct zoneinfo *zp, u_int32_t serial_no, u_char *msg, /* * If the origin has changed, print the new origin */ - if (strcasecmp(prev_origin, origin)) { + if (ns_samename(prev_origin, origin) != 1) { (void) strcpy(prev_origin, origin); (void) fprintf(dbfp, "%s$ORIGIN %s.\n", ignore, origin); } tab = 0; - if (strcasecmp(prev_dname, dname)) { + 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 '.' @@ -1837,10 +2386,7 @@ print_output(struct zoneinfo *zp, u_int32_t serial_no, u_char *msg, tab = 1; } - if (ttl != minimum_ttl) - (void) fprintf(dbfp, "%d\t", (int) ttl); - else if (tab) - (void) putc('\t', dbfp); + (void) fprintf(dbfp, "%d\t", (int) ttl); (void) fprintf(dbfp, "%s\t%s\t", p_class(class), p_type(type)); cp = cdata; @@ -2085,8 +2631,8 @@ print_output(struct zoneinfo *zp, u_int32_t serial_no, u_char *msg, /* algorithm id */ (void) fprintf(dbfp," %d",*cp++); - /* labels (# of labels in name) - skip in textual record */ - 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)); @@ -2128,6 +2674,33 @@ print_output(struct zoneinfo *zp, u_int32_t serial_no, u_char *msg, 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: cp1 = cp + n; while (cp < cp1) @@ -2175,3 +2748,199 @@ filenamecpy(char *ddtfile, char *optarg) { (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 void +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; + time_t now; + + time(&now); + + /* + * Print answer records. + */ + sflag = (_res.pfcode & pflag); + if (_res.pfcode && !sflag) + return; + + 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)); + else if (rrnum > 0 && sflag != 0 && + (_res.pfcode & RES_PRF_HEAD1)) + putc('\n', file); + return; + } + 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); + if (*delete && serial != old_serial) + /*XXX*/; + old_serial = serial; + 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; + } + n = ns_sprintrr(handle, &rr, NULL, NULL, + soa_buf, 2*PACKETSZ); + if (n < 0) { + fprintf(file, ";; ns_sprintrr: %s\n", + strerror(errno)); + return; + } + } + 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; + } + fputs(buf, file); + fputc('\n', file); + } + } + + } + rrnum++; + } +} + +static void +ixfr_log(const u_char *msg, int len, int *delete, FILE *file, + struct sockaddr_in *sin, char *domain, 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, n; + char time[25]; + ns_rr rr; + char *cp; + HEADER *hp; + + if ((_res.options & RES_INIT) == 0 && res_init() == -1) + return; + + if (ns_initparse(msg, len, &handle) < 0) { + fprintf(file, ";; ns_initparse: %s\n", strerror(errno)); + return; + } + 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"); + return; + } + 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-xfr pid %ld):\n", + id, inet_ntoa(sin->sin_addr), + ntohs(sin->sin_port), time, (long)getpid()); + (*first_rr)++; + } + do_section(&handle, ns_s_an, RES_PRF_ANS, file, delete); +} + +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"); +} diff --git a/contrib/bind/bin/named/Makefile b/contrib/bind/bin/named/Makefile index 28f1ca7..96a3927 100644 --- a/contrib/bind/bin/named/Makefile +++ b/contrib/bind/bin/named/Makefile @@ -1,4 +1,4 @@ -## Copyright (c) 1996, 1997 by Internet Software Consortium +## 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 @@ -13,7 +13,8 @@ ## ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ## SOFTWARE. -# $Id: Makefile,v 8.31 1998/03/20 00:49:46 halley Exp $ +# $Id: Makefile,v 8.47 1999/08/26 18:42:31 vixie Exp $ +# $FreeBSD$ DESTDIR= CC= cc @@ -29,18 +30,21 @@ PORTINCL = ${TOP}/port/${SYSTYPE}/include LIBBIND = ${TOP}/lib/libbind.a A=a O=o -LEX = lex -I +EXE= YACC = yacc -d SYSLIBS = -ll -lutil -PIDDIR = /var/run DESTBIN = /usr/local/bin DESTSBIN = /usr/local/sbin DESTEXEC = /usr/local/libexec DESTMAN = /usr/share/man DESTHELP= /usr/share/misc -AR= ar cruv +DESTETC= /etc +DESTRUN= /var/run +AR= ar cru INSTALL= install STRIP=-s +INSTALL_EXEC= +INSTALL_LIB=-o bin -g bin PS=ps LDFLAGS= @@ -52,23 +56,25 @@ HOSTNAMECMD= hostname || uname -n PROG= named HDRS= db_defs.h db_glob.h ns_defs.h ns_glob.h named.h pathnames.h SRCS= db_dump.c db_load.c db_lookup.c db_save.c db_update.c \ - db_glue.c \ - ns_parser.c ns_lexer.c ns_parseutil.c \ + db_glue.c db_ixfr.c db_sec.c db_tsig.c \ + ns_parser.c ns_lexer.c ns_parseutil.c ns_ctl.c \ ns_forw.c ns_init.c ns_main.c ns_maint.c ns_req.c \ ns_resp.c ns_stats.c ns_ncache.c ns_xfr.c ns_glue.c \ - ns_udp.c ns_config.c ns_update.c + ns_udp.c ns_config.c ns_update.c ns_ixfr.c ns_signal.c \ + ns_sort.c ns_notify.c OBJS= db_dump.${O} db_load.${O} db_lookup.${O} db_save.${O} db_update.${O} \ - db_glue.${O} \ - ns_parser.${O} ns_lexer.${O} ns_parseutil.${O} \ + db_glue.${O} db_ixfr.${O} db_sec.${O} db_tsig.${O} \ + ns_parser.${O} ns_lexer.${O} ns_parseutil.${O} ns_ctl.${O} \ ns_forw.${O} ns_init.${O} ns_main.${O} ns_maint.${O} ns_req.${O} \ ns_resp.${O} ns_stats.${O} ns_ncache.${O} ns_xfr.${O} ns_glue.${O} \ - ns_udp.${O} ns_config.${O} ns_update.${O} + ns_udp.${O} ns_config.${O} ns_update.${O} ns_ixfr.${O} ns_signal.${O} \ + ns_sort.${O} ns_notify.${O} -all: ${PROG} pathnames +all: ${PROG}${EXE} -${PROG}: pathnames.h ${OBJS} ${LIBBIND} Makefile tmp_version.${O} - ${CC} ${CDEBUG} ${LDFLAGS} -o ${PROG} ${OBJS} tmp_version.${O} \ - ${LIBBIND} ${SYSLIBS} +${PROG}${EXE}: pathnames.h ${OBJS} ${LIBBIND} Makefile tmp_version.${O} + ${CC} ${CDEBUG} ${LDFLAGS} ${BOUNDS} -o ${PROG}${EXE} ${OBJS} \ + tmp_version.${O} ${LIBBIND} ${SYSLIBS} ns_parser.c ns_parser.h: ns_parser.y ${YACC} ns_parser.y @@ -83,7 +89,7 @@ tmp_version.c: version.c Makefile ../Makefile ${SRCS} ${HDRS} -e "s|%WHOANDWHERE%|$${u}@$${h}:$${d}|" \ < version.c > tmp_version.c) -pathnames.h: ${TOP}/.settings Makefile +pathnames.h: ${TOP}/.settings Makefile pathtemplate.h rm -f pathnames.h sed -e "s|%DESTSBIN%|${DESTSBIN}|" \ -e "s|%DESTEXEC%|${DESTEXEC}|" \ @@ -91,19 +97,20 @@ pathnames.h: ${TOP}/.settings Makefile -e "s|%DESTRUN%|${DESTRUN}|" \ < pathtemplate.h > pathnames.h -pathnames: pathnames.${O} pathnames.h ${LIBBIND} Makefile - ${CC} ${CDEBUG} ${LDFLAGS} -o $@ pathnames.${O} \ - ${LIBBIND} ${SYSLIBS} +ns_signal.${O}: ns_signal.c + ${CC} ${CPPFLAGS} ${CFLAGS} -c $*.c + +.c.${O}: + ${CC} ${CPPFLAGS} ${CFLAGS} ${BOUNDS} -c $*.c distclean: clean rm -f ns_parser.c ns_parser.h clean: FRC - rm -f ${PROG} ${OBJS} core .depend + rm -f ${PROG}${EXE} ${OBJS} core .depend rm -f *.BAK *.CKP *~ *.orig rm -f tmp_version.c tmp_version.${O} - rm -f pathnames pathnames.${O} tmp_pathnames.h pathnames.h - rm -f y.tab.h y.tab.c + rm -f pathnames.h y.tab.h y.tab.c depend: ${SRCS} pathnames.h mkdep ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${DEFS} ${SRCS} @@ -111,8 +118,8 @@ depend: ${SRCS} pathnames.h ${DESTDIR}${DESTSBIN}: mkdir -p ${DESTDIR}${DESTSBIN} -install: ${DESTDIR}${DESTSBIN} ${PROG} - ${INSTALL} ${STRIP} -c -m 755 ${PROG} ${DESTDIR}${DESTSBIN}/${PROG} +install: ${DESTDIR}${DESTSBIN} ${PROG}${EXE} + ${INSTALL} ${STRIP} -c ${INSTALL_EXEC} -m 755 ${PROG}${EXE} ${DESTDIR}${DESTSBIN}/${PROG}${EXE} links: FRC @ln -s SRC/*.[chy] SRC/test .; rm -f ns_parser.[ch] diff --git a/contrib/bind/bin/nslookup/commands.l b/contrib/bind/bin/nslookup/commands.l index bb626c7..c480d46 100644 --- a/contrib/bind/bin/nslookup/commands.l +++ b/contrib/bind/bin/nslookup/commands.l @@ -1,5 +1,5 @@ %{ - +/* $FreeBSD$ */ /* * Copyright (c) 1985 * The Regents of the University of California. All rights reserved. @@ -101,6 +101,7 @@ static char sccsid[] = "@(#)commands.l 5.13 (Berkeley) 7/24/90"; extern char rootServerName[]; extern void PrintHelp(); +extern void ViewList(char *); #define YY_INPUT(buf, result, max_size) \ { \ @@ -157,7 +158,7 @@ nslookup_yy_input(buf, result, max_size, intr) %} WS [ \t] -FLET [A-Za-z0-9.*\\] +FLET [A-Za-z0-9.*\\_] LET [A-Za-z0-9.*] NAME [A-Za-z0-9.*=_/-] %% @@ -196,7 +197,7 @@ NAME [A-Za-z0-9.*=_/-] return(1); } ^{WS}*view{WS}+{NAME}+{WS}*$ { - ViewList(yytext); + ViewList((char *)yytext); return(1); } ^{WS}*ls{WS}+(("-a"|"-d"|"-h"|"-m"|"-s"){WS}+)?{LET}{NAME}*{WS}+>>?{WS}+{NAME}+{WS}*$ { diff --git a/contrib/bind/bin/nslookup/debug.c b/contrib/bind/bin/nslookup/debug.c index af03daa..7dac192 100644 --- a/contrib/bind/bin/nslookup/debug.c +++ b/contrib/bind/bin/nslookup/debug.c @@ -1,3 +1,4 @@ +/* $FreeBSD$ */ /* * Copyright (c) 1985, 1989 * The Regents of the University of California. All rights reserved. @@ -52,8 +53,8 @@ */ #ifndef lint -static char sccsid[] = "@(#)debug.c 5.26 (Berkeley) 3/21/91"; -static char rcsid[] = "$Id: debug.c,v 8.11 1998/03/19 19:30:54 halley Exp $"; +static const char sccsid[] = "@(#)debug.c 5.26 (Berkeley) 3/21/91"; +static const char rcsid[] = "$Id: debug.c,v 8.15 1999/10/13 16:39:16 vixie Exp $"; #endif /* not lint */ /* @@ -89,7 +90,6 @@ static char rcsid[] = "$Id: debug.c,v 8.11 1998/03/19 19:30:54 halley Exp $"; /* * Imported from res_debug.c */ -extern char *_res_resultcodes[]; extern char *_res_opcodes[]; /* @@ -120,11 +120,11 @@ Fprint_query(const u_char *msg, const u_char *eom, int printHeader, FILE *file) */ hp = (HEADER *)msg; cp = msg + HFIXEDSZ; - if (printHeader || (_res.options & RES_DEBUG2)) { + if (printHeader || (res.options & RES_DEBUG2)) { fprintf(file," HEADER:\n"); fprintf(file,"\topcode = %s", _res_opcodes[hp->opcode]); fprintf(file,", id = %d", ntohs(hp->id)); - fprintf(file,", rcode = %s\n", _res_resultcodes[hp->rcode]); + fprintf(file,", rcode = %s\n", p_rcode(hp->rcode)); fprintf(file,"\theader flags: "); if (hp->qr) { fprintf(file," response"); @@ -281,9 +281,9 @@ Print_rr(const u_char *ocp, const u_char *msg, const u_char *eom, FILE *file) { NS_GET16(dlen, cp); BOUNDS_CHECK(cp, dlen); - debug = _res.options & (RES_DEBUG|RES_DEBUG2); + debug = res.options & (RES_DEBUG|RES_DEBUG2); if (debug) { - if (_res.options & RES_DEBUG2) + if (res.options & RES_DEBUG2) fprintf(file,"\n\ttype = %s, class = %s, dlen = %d", p_type(type), p_class(class), dlen); if (type == T_SOA) @@ -623,8 +623,9 @@ Print_rr(const u_char *ocp, const u_char *msg, const u_char *eom, FILE *file) { default: { char buf[2048]; /* XXX need to malloc/realloc. */ - if (ns_sprintrrf(msg, eom - msg, "?", class, type, rrttl, - cp1, dlen, NULL, NULL, buf, sizeof buf) < 0) { + if (ns_sprintrrf(msg, eom - msg, "?", (ns_class)class, + (ns_type)type, rrttl, cp1, dlen, NULL, NULL, + buf, sizeof buf) < 0) { perror("ns_sprintrrf"); } else { fprintf(file, @@ -634,7 +635,7 @@ Print_rr(const u_char *ocp, const u_char *msg, const u_char *eom, FILE *file) { cp += dlen; } } - if (_res.options & RES_DEBUG && type != T_SOA) { + if (res.options & RES_DEBUG && type != T_SOA) { fprintf(file,"\tttl = %lu (%s)\n", rrttl, p_time(rrttl)); } if (cp != cp1 + dlen) { diff --git a/contrib/bind/bin/nslookup/getinfo.c b/contrib/bind/bin/nslookup/getinfo.c index abd747b..673bad0 100644 --- a/contrib/bind/bin/nslookup/getinfo.c +++ b/contrib/bind/bin/nslookup/getinfo.c @@ -1,3 +1,4 @@ +/* $FreeBSD$ */ /* * Copyright (c) 1985, 1989 * The Regents of the University of California. All rights reserved. @@ -52,8 +53,8 @@ */ #ifndef lint -static char sccsid[] = "@(#)getinfo.c 5.26 (Berkeley) 3/21/91"; -static char rcsid[] = "$Id: getinfo.c,v 8.11 1998/03/19 19:30:55 halley Exp $"; +static const char sccsid[] = "@(#)getinfo.c 5.26 (Berkeley) 3/21/91"; +static const char rcsid[] = "$Id: getinfo.c,v 8.15 1999/10/13 16:39:16 vixie Exp $"; #endif /* not lint */ /* @@ -88,7 +89,6 @@ static char rcsid[] = "$Id: getinfo.c,v 8.11 1998/03/19 19:30:55 halley Exp $"; #include "res.h" -extern char *_res_resultcodes[]; extern char *res_skip(); static char *addr_list[MAXADDRS + 1]; @@ -109,7 +109,7 @@ ServerTable server[MAXSERVERS]; typedef union { HEADER qb1; - u_char qb2[PACKETSZ*2]; + u_char qb2[64*1024]; } querybuf; typedef union { @@ -162,10 +162,10 @@ GetAnswer(nsAddrPtr, queryType, msg, msglen, iquery, hostPtr, isServer) int numAliases = 0; int numAddresses = 0; int n, i, j; - int len; int dlen; int status; int numServers; + size_t s; Boolean haveAnswer; Boolean printedAnswers = FALSE; @@ -179,7 +179,7 @@ GetAnswer(nsAddrPtr, queryType, msg, msglen, iquery, hostPtr, isServer) sizeof(answer), &n); if (status != SUCCESS) { - if (_res.options & RES_DEBUG2) + if (res.options & RES_DEBUG2) printf("SendRequest failed\n"); return (status); } @@ -268,11 +268,11 @@ GetAnswer(nsAddrPtr, queryType, msg, msglen, iquery, hostPtr, isServer) continue; } *aliasPtr++ = (char *)bp; - n = strlen((char *)bp) + 1; - host_aliases_len[numAliases] = n; + s = strlen((char *)bp) + 1; + host_aliases_len[numAliases] = s; numAliases++; - bp += n; - buflen -= n; + bp += s; + buflen -= s; continue; } else if (type == T_PTR) { /* @@ -284,9 +284,9 @@ GetAnswer(nsAddrPtr, queryType, msg, msglen, iquery, hostPtr, isServer) continue; } cp += n; - len = strlen((char *)bp) + 1; - hostPtr->name = Calloc(1, len); - memcpy(hostPtr->name, bp, len); + s = strlen((char *)bp) + 1; + hostPtr->name = Calloc(1, s); + memcpy(hostPtr->name, bp, s); haveAnswer = TRUE; break; } else if (type != T_A) { @@ -316,14 +316,14 @@ GetAnswer(nsAddrPtr, queryType, msg, msglen, iquery, hostPtr, isServer) hostPtr->addrLen = dlen; origClass = class; hostPtr->addrType = (class == C_IN) ? AF_INET : AF_UNSPEC; - len = strlen((char *)bp) + 1; - hostPtr->name = Calloc(1, len); - memcpy(hostPtr->name, bp, len); + s = strlen((char *)bp) + 1; + hostPtr->name = Calloc(1, s); + memcpy(hostPtr->name, bp, s); } bp += (((u_long)bp) % sizeof(align)); if (bp + dlen >= &hostbuf[sizeof(hostbuf)]) { - if (_res.options & RES_DEBUG) { + if (res.options & RES_DEBUG) { printf("Size (%d) too big\n", dlen); } break; @@ -417,9 +417,9 @@ GetAnswer(nsAddrPtr, queryType, msg, msglen, iquery, hostPtr, isServer) return(ERROR); } cp += n; - len = strlen((char *)bp) + 1; - dnamePtr = Calloc(1, len); /* domain name */ - memcpy(dnamePtr, bp, len); + s = strlen((char *)bp) + 1; + dnamePtr = Calloc(1, s); /* domain name */ + memcpy(dnamePtr, bp, s); if (cp + 3 * INT16SZ + INT32SZ > eom) return (ERROR); @@ -440,9 +440,9 @@ GetAnswer(nsAddrPtr, queryType, msg, msglen, iquery, hostPtr, isServer) return(ERROR); } cp += n; - len = strlen((char *)bp) + 1; - namePtr = Calloc(1, len); /* server host name */ - memcpy(namePtr, bp, len); + s = strlen((char *)bp) + 1; + namePtr = Calloc(1, s); /* server host name */ + memcpy(namePtr, bp, s); /* * Store the information keyed by the server host name. @@ -579,10 +579,10 @@ GetAnswer(nsAddrPtr, queryType, msg, msglen, iquery, hostPtr, isServer) * Retrieves host name, address and alias information * for a domain. * -* Algorithm from res_search(). +* Algorithm from res_nsearch(). * * Results: -* ERROR - res_mkquery failed. +* ERROR - res_nmkquery failed. * + return values from GetAnswer() * ******************************************************************************* @@ -604,6 +604,7 @@ GetHostInfoByName(nsAddrPtr, queryClass, queryType, name, hostPtr, isServer) Boolean got_nodata = FALSE; struct in_addr ina; Boolean tried_as_is = FALSE; + char tmp[NS_MAXDNAME]; /* Catch explicit addresses */ if ((queryType == T_A) && IsAddr(name, &ina)) { @@ -624,7 +625,7 @@ GetHostInfoByName(nsAddrPtr, queryClass, queryType, name, hostPtr, isServer) for (cp = name, n = 0; *cp; cp++) if (*cp == '.') n++; - if (n == 0 && (cp = hostalias(name))) { + if (n == 0 && (cp = res_hostalias(&res, name, tmp, sizeof tmp))) { printf("Aliased to \"%s\"\n\n", cp); return (GetHostDomain(nsAddrPtr, queryClass, queryType, cp, (char *)NULL, hostPtr, isServer)); @@ -634,7 +635,7 @@ GetHostInfoByName(nsAddrPtr, queryClass, queryType, name, hostPtr, isServer) * If there are dots in the name already, let's just give it a try * 'as is'. The threshold can be set with the "ndots" option. */ - if (n >= (int)_res.ndots) { + if (n >= (int)res.ndots) { result = GetHostDomain(nsAddrPtr, queryClass, queryType, name, (char *)NULL, hostPtr, isServer); if (result == SUCCESS) @@ -650,9 +651,9 @@ GetHostInfoByName(nsAddrPtr, queryClass, queryType, name, hostPtr, isServer) * - there is at least one dot, there is no trailing dot, * and RES_DNSRCH is set. */ - if ((n == 0 && _res.options & RES_DEFNAMES) || - (n != 0 && *--cp != '.' && _res.options & RES_DNSRCH)) - for (domain = _res.dnsrch; *domain; domain++) { + if ((n == 0 && res.options & RES_DEFNAMES) || + (n != 0 && *--cp != '.' && res.options & RES_DNSRCH)) + for (domain = res.dnsrch; *domain; domain++) { result = GetHostDomain(nsAddrPtr, queryClass, queryType, name, *domain, hostPtr, isServer); /* @@ -672,7 +673,7 @@ GetHostInfoByName(nsAddrPtr, queryClass, queryType, name, hostPtr, isServer) if (result == NO_INFO) got_nodata++; if ((result != NXDOMAIN && result != NO_INFO) || - (_res.options & RES_DNSRCH) == 0) + (res.options & RES_DNSRCH) == 0) break; } /* if we have not already tried the name "as is", do that now. @@ -722,11 +723,11 @@ GetHostDomain(nsAddrPtr, queryClass, queryType, name, domain, hostPtr, isServer) MAXDNAME, name, MAXDNAME, domain); longname = nbuf; } - n = res_mkquery(QUERY, longname, queryClass, queryType, - NULL, 0, 0, buf.qb2, sizeof(buf)); + n = res_nmkquery(&res, QUERY, longname, queryClass, queryType, + NULL, 0, 0, buf.qb2, sizeof(buf)); if (n < 0) { - if (_res.options & RES_DEBUG) { - printf("Res_mkquery failed\n"); + if (res.options & RES_DEBUG) { + printf("Res_nmkquery failed\n"); } return (ERROR); } @@ -738,7 +739,8 @@ GetHostDomain(nsAddrPtr, queryClass, queryType, name, domain, hostPtr, isServer) */ if (n == NONAUTH) { if (hostPtr->name == NULL) { - int len = strlen(longname) + 1; + size_t len = strlen(longname) + 1; + hostPtr->name = Calloc(len, sizeof(char)); memcpy(hostPtr->name, longname, len); } @@ -756,7 +758,7 @@ GetHostDomain(nsAddrPtr, queryClass, queryType, name, domain, hostPtr, isServer) * that corresponds to the given address. * * Results: -* ERROR - res_mkquery failed. +* ERROR - res_nmkquery failed. * + return values from GetAnswer() * ******************************************************************************* @@ -778,11 +780,11 @@ GetHostInfoByAddr(nsAddrPtr, address, hostPtr) ((unsigned)p[2] & 0xff), ((unsigned)p[1] & 0xff), ((unsigned)p[0] & 0xff)); - n = res_mkquery(QUERY, qbuf, C_IN, T_PTR, NULL, 0, NULL, - buf.qb2, sizeof buf); + n = res_nmkquery(&res, QUERY, qbuf, C_IN, T_PTR, NULL, 0, NULL, + buf.qb2, sizeof buf); if (n < 0) { - if (_res.options & RES_DEBUG) { - printf("res_mkquery() failed\n"); + if (res.options & RES_DEBUG) { + printf("res_nmkquery() failed\n"); } return (ERROR); } diff --git a/contrib/bind/bin/nslookup/main.c b/contrib/bind/bin/nslookup/main.c index 67309a4..454fe12 100644 --- a/contrib/bind/bin/nslookup/main.c +++ b/contrib/bind/bin/nslookup/main.c @@ -1,3 +1,4 @@ +/* $FreeBSD$ */ /* * Copyright (c) 1985, 1989 * The Regents of the University of California. All rights reserved. @@ -51,15 +52,33 @@ * SOFTWARE. */ +/* + * 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. + */ + #ifndef lint char copyright[] = "@(#) Copyright (c) 1985,1989 Regents of the University of California.\n\ - All rights reserved.\n"; + All rights reserved.\n\ + @(#) Portions Copyright (c) 1996-1999 Internet Software Consortium.\n"; #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)main.c 5.42 (Berkeley) 3/3/91"; -static char rcsid[] = "$Id: main.c,v 8.7 1997/04/25 00:27:18 vixie Exp $"; +static const char sccsid[] = "@(#)main.c 5.42 (Berkeley) 3/3/91"; +static const char rcsid[] = "$Id: main.c,v 8.13 1999/10/13 16:39:19 vixie Exp $"; #endif /* not lint */ /* @@ -113,10 +132,10 @@ static char rcsid[] = "$Id: main.c,v 8.7 1997/04/25 00:27:18 vixie Exp $"; char rootServerName[NAME_LEN] = ROOT_SERVER; /* - * Import the state information from the resolver library. + * Declare a resolver context. */ -extern struct __res_state _res; +struct __res_state res; /* @@ -160,6 +179,13 @@ char *pager; static void CvtAddrToPtr(); static void ReadRC(); +/* + * Forward declarations. + */ +void LocalServer(HostInfo *defaultPtr); +void res_re_init(void); +void res_dnsrch(char *cp); + /* ****************************************************************************** @@ -187,7 +213,7 @@ main(argc, argv) * Initialize the resolver library routines. */ - if (res_init() == -1) { + if (res_ninit(&res) == -1) { fprintf(stderr,"*** Can't initialize resolver.\n"); exit(1); } @@ -245,8 +271,8 @@ main(argc, argv) */ if (inet_aton(*++argv, &addr)) { - _res.nscount = 1; - _res.nsaddr.sin_addr = addr; + res.nscount = 1; + res.nsaddr.sin_addr = addr; } else { hp = gethostbyname(*argv); if (hp == NULL) { @@ -256,33 +282,33 @@ main(argc, argv) fputc('\n', stderr); } else { for (i = 0; i < MAXNS && hp->h_addr_list[i] != NULL; i++) { - memcpy(&_res.nsaddr_list[i].sin_addr, hp->h_addr_list[i], + memcpy(&res.nsaddr_list[i].sin_addr, hp->h_addr_list[i], hp->h_length); } - _res.nscount = i; + res.nscount = i; } } } - if (_res.nscount == 0 || useLocalServer) { + if (res.nscount == 0 || useLocalServer) { LocalServer(defaultPtr); } else { - for (i = 0; i < _res.nscount; i++) { - if (_res.nsaddr_list[i].sin_addr.s_addr == INADDR_ANY) { + for (i = 0; i < res.nscount; i++) { + if (res.nsaddr_list[i].sin_addr.s_addr == INADDR_ANY) { LocalServer(defaultPtr); break; } else { - result = GetHostInfoByAddr(&(_res.nsaddr_list[i].sin_addr), - &(_res.nsaddr_list[i].sin_addr), + result = GetHostInfoByAddr(&(res.nsaddr_list[i].sin_addr), + &(res.nsaddr_list[i].sin_addr), defaultPtr); if (result != SUCCESS) { fprintf(stderr, "*** Can't find server name for address %s: %s\n", - inet_ntoa(_res.nsaddr_list[i].sin_addr), + inet_ntoa(res.nsaddr_list[i].sin_addr), DecodeError(result)); } else { - defaultAddr = _res.nsaddr_list[i].sin_addr; + defaultAddr = res.nsaddr_list[i].sin_addr; break; } } @@ -293,7 +319,7 @@ main(argc, argv) * command line argument to specify an address. */ - if (i == _res.nscount) { + if (i == res.nscount) { fprintf(stderr, "*** Default servers are not available\n"); exit(1); } @@ -304,10 +330,10 @@ main(argc, argv) #ifdef DEBUG #ifdef DEBUG2 - _res.options |= RES_DEBUG2; + res.options |= RES_DEBUG2; #endif - _res.options |= RES_DEBUG; - _res.retry = 2; + res.options |= RES_DEBUG; + res.retry = 2; #endif /* DEBUG */ /* @@ -350,6 +376,7 @@ main(argc, argv) } +void LocalServer(defaultPtr) HostInfo *defaultPtr; { @@ -459,6 +486,7 @@ SetDefaultServer(string, local) char newServer[NAME_LEN]; int result; int i; + int j; /* * Parse the command line. It maybe of the form "server name", @@ -466,13 +494,32 @@ SetDefaultServer(string, local) */ if (local) { - i = sscanf(string, " lserver %s", newServer); + i = matchString (" lserver ", string); + if (i > 0) { + j = pickString(string + i, newServer, sizeof newServer); + if (j == 0) { /* value was too big for newServer variable */ + fprintf(stderr, + "SetDefaultServer: invalid name: %s\n", + string + i); + return(ERROR); + } + } } else { - i = sscanf(string, " server %s", newServer); + i = matchString(" server ", string); + if (i > 0) { + j = pickString(string + i, newServer, sizeof newServer); + if (j == 0) { /* value was too big for newServer variable */ + fprintf(stderr, + "SetDefaultServer: invalid name: %s\n", + string + i); + return(ERROR); + } + } } - if (i != 1) { - i = sscanf(string, " %s", newServer); - if (i != 1) { + + if (i == 0) { + i = pickString(string, newServer, sizeof newServer); + if (i == 0) { /* value was too big for newServer variable */ fprintf(stderr,"SetDefaultServer: invalid name: %s\n", string); return(ERROR); } @@ -662,6 +709,7 @@ LookupHost(string, putToFile) char host[NAME_LEN]; char file[PATH_MAX]; int result; + int i; /* * Invalidate the current host information to prevent Finger @@ -676,11 +724,16 @@ LookupHost(string, putToFile) * */ - sscanf(string, " %s", host); /* removes white space */ + i = pickString(string, host, sizeof host); + if (i == 0) { /* string was too long for host variable */ + fprintf(stderr, "*** invalid name: %s\n", string); + return(ERROR); + } + if (!putToFile) { filePtr = stdout; } else { - filePtr = OpenFile(string, file); + filePtr = OpenFile(string, file, sizeof file); if (filePtr == NULL) { fprintf(stderr, "*** Can't open %s for writing\n", file); return(ERROR); @@ -734,14 +787,27 @@ LookupHostWithServer(string, putToFile) char server[NAME_LEN]; int result; static HostInfo serverInfo; + int i; + int j; curHostValid = FALSE; - sscanf(string, " %s %s", host, server); + i = pickString(string, host, sizeof host); + if (i == 0) { /* value was too big for host variable */ + fprintf(stderr, "*** invalid name: %s\n", string); + return(ERROR); + } + + j = pickString(string + i, server, sizeof server); + if (j == 0) { /* value was too big for server variable */ + fprintf(stderr, "*** invalid server name: %s\n", string + i); + return(ERROR); + } + if (!putToFile) { filePtr = stdout; } else { - filePtr = OpenFile(string, file); + filePtr = OpenFile(string, file, sizeof file); if (filePtr == NULL) { fprintf(stderr, "*** Can't open %s for writing\n", file); return(ERROR); @@ -818,6 +884,7 @@ SetOption(option) char type[NAME_LEN]; char *ptr; int tmp; + int i; while (isspace(*option)) ++option; @@ -835,28 +902,34 @@ SetOption(option) } else if (strncmp(option, "ALL", 3) == 0) { ShowOptions(); } else if (strncmp(option, "d2", 2) == 0) { /* d2 (more debug) */ - _res.options |= (RES_DEBUG | RES_DEBUG2); + res.options |= (RES_DEBUG | RES_DEBUG2); } else if (strncmp(option, "nod2", 4) == 0) { - _res.options &= ~RES_DEBUG2; + res.options &= ~RES_DEBUG2; printf("d2 mode disabled; still in debug mode\n"); } else if (strncmp(option, "def", 3) == 0) { /* defname */ - _res.options |= RES_DEFNAMES; + res.options |= RES_DEFNAMES; } else if (strncmp(option, "nodef", 5) == 0) { - _res.options &= ~RES_DEFNAMES; + res.options &= ~RES_DEFNAMES; } else if (strncmp(option, "do", 2) == 0) { /* domain */ ptr = strchr(option, '='); if (ptr != NULL) { - sscanf(++ptr, "%s", _res.defdname); + i = pickString(++ptr, res.defdname, sizeof res.defdname); + if (i == 0) { /* name too long or nothing there */ + fprintf(stderr, "** invalid 'domain' value: %s\n", + ptr) ; + return(ERROR); + } + res_re_init(); } } else if (strncmp(option, "deb", 1) == 0) { /* debug */ - _res.options |= RES_DEBUG; + res.options |= RES_DEBUG; } else if (strncmp(option, "nodeb", 5) == 0) { - _res.options &= ~(RES_DEBUG | RES_DEBUG2); + res.options &= ~(RES_DEBUG | RES_DEBUG2); } else if (strncmp(option, "ig", 2) == 0) { /* ignore */ - _res.options |= RES_IGNTC; + res.options |= RES_IGNTC; } else if (strncmp(option, "noig", 4) == 0) { - _res.options &= ~RES_IGNTC; + res.options &= ~RES_IGNTC; } else if (strncmp(option, "po", 2) == 0) { /* port */ ptr = strchr(option, '='); if (ptr != NULL) { @@ -864,44 +937,61 @@ SetOption(option) } #ifdef deprecated } else if (strncmp(option, "pri", 3) == 0) { /* primary */ - _res.options |= RES_PRIMARY; + res.options |= RES_PRIMARY; } else if (strncmp(option, "nopri", 5) == 0) { - _res.options &= ~RES_PRIMARY; + res.options &= ~RES_PRIMARY; #endif } else if (strncmp(option, "q", 1) == 0 || /* querytype */ strncmp(option, "ty", 2) == 0) { /* type */ ptr = strchr(option, '='); if (ptr != NULL) { - sscanf(++ptr, "%s", type); + i = pickString(++ptr, type, sizeof type); + if (i == 0) { /* value too big or nothing there */ + fprintf(stderr, "*** invalid type value: %s\n", + ptr) ; + return(ERROR); + } + queryType = StringToType(type, queryType, stderr); } } else if (strncmp(option, "cl", 2) == 0) { /* query class */ ptr = strchr(option, '='); if (ptr != NULL) { - sscanf(++ptr, "%s", type); + i = pickString(++ptr, type, sizeof type); + if (i == 0) { /* value too big or nothing there */ + fprintf(stderr, "*** invalid class : %s\n", + ptr) ; + return(ERROR); + } + queryClass = StringToClass(type, queryClass, stderr); } } else if (strncmp(option, "rec", 3) == 0) { /* recurse */ - _res.options |= RES_RECURSE; + res.options |= RES_RECURSE; } else if (strncmp(option, "norec", 5) == 0) { - _res.options &= ~RES_RECURSE; + res.options &= ~RES_RECURSE; } else if (strncmp(option, "ret", 3) == 0) { /* retry */ ptr = strchr(option, '='); if (ptr != NULL) { sscanf(++ptr, "%d", &tmp); if (tmp >= 0) { - _res.retry = tmp; + res.retry = tmp; } } } else if (strncmp(option, "ro", 2) == 0) { /* root */ ptr = strchr(option, '='); if (ptr != NULL) { - sscanf(++ptr, "%s", rootServerName); + i = pickString(++ptr, rootServerName, sizeof rootServerName); + if (i == 0) { /* value too big or nothing there */ + fprintf(stderr, "*** invalid root server name : %s\n", + ptr) ; + return(ERROR) ; + } } } else if (strncmp(option, "sea", 3) == 0) { /* search list */ - _res.options |= RES_DNSRCH; + res.options |= RES_DNSRCH; } else if (strncmp(option, "nosea", 5) == 0) { - _res.options &= ~RES_DNSRCH; + res.options &= ~RES_DNSRCH; } else if (strncmp(option, "srchl", 5) == 0) { /* domain search list */ ptr = strchr(option, '='); if (ptr != NULL) { @@ -912,13 +1002,13 @@ SetOption(option) if (ptr != NULL) { sscanf(++ptr, "%d", &tmp); if (tmp >= 0) { - _res.retrans = tmp; + res.retrans = tmp; } } } else if (strncmp(option, "v", 1) == 0) { /* vc */ - _res.options |= RES_USEVC; + res.options |= RES_USEVC; } else if (strncmp(option, "nov", 3) == 0) { - _res.options &= ~RES_USEVC; + res.options &= ~RES_USEVC; } else { fprintf(stderr, "*** Invalid option: %s\n", option); return(ERROR); @@ -930,45 +1020,45 @@ SetOption(option) /* * Fake a reinitialization when the domain is changed. */ -res_re_init() -{ +void +res_re_init(void) { register char *cp, **pp; int n; /* find components of local domain that might be searched */ - pp = _res.dnsrch; - *pp++ = _res.defdname; - for (cp = _res.defdname, n = 0; *cp; cp++) + pp = res.dnsrch; + *pp++ = res.defdname; + for (cp = res.defdname, n = 0; *cp; cp++) if (*cp == '.') n++; - cp = _res.defdname; - for (; n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH; n--) { + cp = res.defdname; + for (; n >= LOCALDOMAINPARTS && pp < res.dnsrch + MAXDFLSRCH; n--) { cp = strchr(cp, '.'); *pp++ = ++cp; } *pp = 0; - _res.options |= RES_INIT; + res.options |= RES_INIT; } #define SRCHLIST_SEP '/' -res_dnsrch(cp) - register char *cp; -{ - register char **pp; +void +res_dnsrch(char *cp) { + char **pp; int n; - (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1); - if ((cp = strchr(_res.defdname, '\n')) != NULL) + (void)strncpy(res.defdname, cp, sizeof(res.defdname) - 1); + res.defdname[sizeof(res.defdname) - 1] = '\0'; + if ((cp = strchr(res.defdname, '\n')) != NULL) *cp = '\0'; /* * Set search list to be blank-separated strings * on rest of line. */ - cp = _res.defdname; - pp = _res.dnsrch; + cp = res.defdname; + pp = res.dnsrch; *pp++ = cp; - for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { + for (n = 0; *cp && pp < res.dnsrch + MAXDNSRCH; cp++) { if (*cp == SRCHLIST_SEP) { *cp = '\0'; n = 1; @@ -1006,24 +1096,24 @@ ShowOptions() } printf("Set options:\n"); - printf(" %sdebug \t", (_res.options & RES_DEBUG) ? "" : "no"); - printf(" %sdefname\t", (_res.options & RES_DEFNAMES) ? "" : "no"); - printf(" %ssearch\t", (_res.options & RES_DNSRCH) ? "" : "no"); - printf(" %srecurse\n", (_res.options & RES_RECURSE) ? "" : "no"); - - printf(" %sd2\t\t", (_res.options & RES_DEBUG2) ? "" : "no"); - printf(" %svc\t\t", (_res.options & RES_USEVC) ? "" : "no"); - printf(" %signoretc\t", (_res.options & RES_IGNTC) ? "" : "no"); + printf(" %sdebug \t", (res.options & RES_DEBUG) ? "" : "no"); + printf(" %sdefname\t", (res.options & RES_DEFNAMES) ? "" : "no"); + printf(" %ssearch\t", (res.options & RES_DNSRCH) ? "" : "no"); + printf(" %srecurse\n", (res.options & RES_RECURSE) ? "" : "no"); + + printf(" %sd2\t\t", (res.options & RES_DEBUG2) ? "" : "no"); + printf(" %svc\t\t", (res.options & RES_USEVC) ? "" : "no"); + printf(" %signoretc\t", (res.options & RES_IGNTC) ? "" : "no"); printf(" port=%u\n", nsport); printf(" querytype=%s\t", p_type(queryType)); printf(" class=%s\t", p_class(queryClass)); - printf(" timeout=%d\t", _res.retrans); - printf(" retry=%d\n", _res.retry); + printf(" timeout=%d\t", res.retrans); + printf(" retry=%d\n", res.retry); printf(" root=%s\n", rootServerName); - printf(" domain=%s\n", _res.defdname); + printf(" domain=%s\n", res.defdname); - cp = _res.dnsrch; + cp = res.dnsrch; if (cp != NULL) { printf(" srchlist=%s", *cp); for (cp++; *cp; cp++) { @@ -1071,7 +1161,7 @@ static void CvtAddrToPtr(name) char *name; { - char *p; + const char *p; int ip[4]; struct in_addr addr; -- cgit v1.1