📄 named-xfer.c
字号:
/* * The original version of 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. *//* * ++Copyright++ 1988, 1990 * - * 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. * - * --Copyright-- */#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\ 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 4.9.1.8 1993/11/03 12:26:04 vixie Exp $";#endif /* not lint */#include <sys/param.h>#include <sys/file.h>#include <sys/stat.h>#include <sys/socket.h>#include <netinet/in.h>#include <net/if.h>#include <netdb.h>#include <arpa/inet.h>#include <arpa/nameser.h>#include <errno.h>#include <resolv.h>#include <stdio.h>#include <syslog.h>#include <math.h>#define MAIN_PROGRAM#include "named.h"#undef MAIN_PROGRAM#ifdef POSIX_SIGNALS#include <signal.h>#else#include <sys/signal.h>#endifstatic struct zoneinfo zone; /* zone information */static char ddtfilename[] = _PATH_TMPXFER, *ddtfile = ddtfilename, *tmpname, *domain; /* domain being xfered */static int quiet = 0, read_interrupted = 0, domain_len; /* strlen(domain) */static FILE *fp = NULL, *dbfp = NULL;static void usage();static int getzone(), soa_zinfo(), print_output(), samedomain();static SIG_FN read_alarm();static char *ProgName;extern char *optarg;extern int optind, getopt();voidmain(argc, argv) int argc; char *argv[];{ register struct zoneinfo *zp; register struct hostent *hp; char *dbfile = NULL, *tracefile = NULL, *tm = NULL; int dbfd, ddtd, result, c, fd, closed = 0; u_int32_t serial_no = 0; u_int16_t port = htons(NAMESERVER_PORT);#ifdef STUBS int stub_only = 0;#endif#ifdef GEN_AXFR int class = C_IN;#endif if (ProgName = strrchr(argv[0], '/')) ProgName++; else ProgName = argv[0]; (void) umask(022); /* this is a hack; closing everything in the parent is hard. */ for (fd = getdtablesize()-1; fd > 2; fd--) /* "2" is stderr... */ closed += (close(fd) == 0);#ifdef LOG_DAEMON openlog(ProgName, LOG_PID|LOG_CONS, LOGFAC);#else openlog(ProgName, LOG_PID);#endif#ifdef STUBS while ((c = getopt(argc, argv, "C:d:l:s:t:z:f:p:P:qS")) != EOF)#else while ((c = getopt(argc, argv, "C:d:l:s:t:z:f:p:P:q")) != EOF)#endif switch (c) {#ifdef GEN_AXFR case 'C': class = get_class(optarg); break;#endif case 'd': debug = atoi(optarg); break; case 'l': ddtfile = (char *)malloc(strlen(optarg) + sizeof(".XXXXXX") + 1);#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); break; case 't': tracefile = optarg; break; case 'z': /* zone == domain */ domain = optarg; domain_len = strlen(domain); break; case 'f': dbfile = optarg; tmpname = (char *)malloc((unsigned)strlen(optarg) + sizeof(".XXXXXX") + 1);#ifdef SHORT_FNAMES filenamecpy(tmpname, optarg);#else (void) strcpy(tmpname, optarg);#endif /* SHORT_FNAMES */ 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; case '?': default: usage("unrecognized argument"); /* NOTREACHED */ } if (!domain || !dbfile || optind >= argc) { if (!domain) usage("no domain"); if (!dbfile) usage("no dbfile"); if (optind >= argc) usage("not enough arguments"); /* NOTREACHED */ } 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): %m\n", tmpname); exit(XFER_FAIL); } if (fchmod(dbfd, 0644) == -1) { perror(tmpname); if (!quiet) syslog(LOG_ERR, "can't fchmod tmpfile (%s): %m\n", tmpname); exit(XFER_FAIL); } if ((dbfp = fdopen(dbfd, "r+")) == NULL) { perror(tmpname); if (!quiet) syslog(LOG_ERR, "can't fdopen tmpfile (%s)", tmpname); exit(XFER_FAIL); }#ifdef DEBUG if (debug) { /* ddtfile is now something like "/usr/tmp/xfer.ddt.XXXXXX" */ if ((ddtd = mkstemp(ddtfile)) == -1) { perror(ddtfile); debug = 0; } else if (fchmod(ddtd, 0644) == -1) { perror(ddtfile); debug = 0; } else if ((ddt = fdopen(ddtd, "w")) == NULL) { perror(ddtfile); debug = 0; } else {#if defined(SYSV) setvbuf(ddt, NULL, _IOLBF, BUFSIZ);#else setlinebuf(ddt);#endif } }#endif /* * 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); (void) signal(SIGSYS, SIG_IGN); if (debug == 0) { (void) signal(SIGINT, SIG_IGN); (void) signal(SIGQUIT, SIG_IGN); } (void) signal(SIGIOT, 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 */ dprintf(1, (ddt, "domain `%s'; file `%s'; serial %lu; closed %d\n", domain, dbfile, serial_no, closed)); buildservicelist(); buildprotolist(); /* init zone data */ zp = &zone;#ifdef STUBS if (stub_only) zp->z_type = Z_STUB; else#endif zp->z_type = Z_SECONDARY;#ifdef GEN_AXFR zp->z_class = class;#endif zp->z_origin = domain; zp->z_source = dbfile; zp->z_addrcnt = 0; dprintf(1, (ddt, "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++, zp->z_addrcnt++) { tm = argv[optind]; if (!inet_aton(tm, &zp->z_addr[zp->z_addrcnt])) { hp = gethostbyname(tm); if (hp == NULL) { syslog(LOG_ERR, "uninterpretable server (%s) for %s\n", tm, zp->z_origin); zp->z_addrcnt--; /* hack */ continue; } bcopy(hp->h_addr, (char *)&zp->z_addr[zp->z_addrcnt].s_addr, sizeof(zp->z_addr[zp->z_addrcnt].s_addr)); dprintf(1, (ddt, "Arg: \"%s\"\n", tm)); } if (zp->z_addr[zp->z_addrcnt].s_addr == 0) { syslog(LOG_ERR, "SOA query to localhost (%s) for %s", tm, zp->z_origin); zp->z_addrcnt--; /* hack */ continue; } if (zp->z_addrcnt >= NSMAX) { zp->z_addrcnt = NSMAX; dprintf(1, (ddt, "NSMAX reached\n")); break; } } dprintf(1, (ddt, "addrcnt = %d\n", zp->z_addrcnt)); _res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE); result = getzone(zp, serial_no, port); (void) my_fclose(dbfp); switch (result) { case XFER_SUCCESS: /* ok exit */ if (rename(tmpname, dbfile) == -1) { perror("rename"); if (!quiet) syslog(LOG_ERR, "rename %s to %s: %m", tmpname, dbfile); exit(XFER_FAIL); } exit(XFER_SUCCESS); case XFER_UPTODATE: /* the zone was already uptodate */ (void) unlink(tmpname); exit(XFER_UPTODATE); case XFER_TIMEOUT:#ifdef DEBUG if (!debug)#endif (void) unlink(tmpname); exit(XFER_TIMEOUT); /* servers not reachable exit */ case XFER_FAIL: default:#ifdef DEBUG if (!debug)#endif (void) unlink(tmpname); exit(XFER_FAIL); /* yuck exit */ } /*NOTREACHED*/} static char *UsageText[] = { "\t-z zone_to_transfer\n", "\t-f db_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#ifdef GEN_AXFR "\t[-C class]\n",#endif "\tservers...\n", NULL};static voidusage(msg) char *msg;{ 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);}#define DEF_DNAME '\001' /* '\0' means the root domain */int minimum_ttl = 0, got_soa = 0;char prev_origin[MAXDNAME];char prev_dname[MAXDNAME] = { DEF_DNAME };static intgetzone(zp, serial_no, port) struct zoneinfo *zp; u_int32_t serial_no; u_int16_t port;{ HEADER *hp; u_int16_t len; u_int32_t serial; int s, n, l, cnt, nscnt, soacnt, error = 0; u_char *cp, *nmp, *eom, *tmp ; u_char *buf = NULL; int bufsize; u_char name[MAXDNAME], name2[MAXDNAME]; struct sockaddr_in sin; struct zoneinfo zp_start, zp_finish; struct itimerval ival, zeroival;#ifdef POSIX_SIGNALS struct sigaction sv, osv;#else struct sigvec sv, osv;#endif int ancount, aucount; int Class;#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,"secondary\n"); break; default: fprintf(ddt,"unknown type\n"); } }#endif bzero((char *)&zeroival, sizeof(zeroival)); ival = zeroival; ival.it_value.tv_sec = XFER_TIMER;#ifdef POSIX_SIGNALS sv.sa_handler = 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);#else sv.sv_handler = read_alarm; sv.sv_onstack = 0; sv.sv_mask = ~0; (void) sigvec(SIGALRM, &sv, &osv);#endif strcpy(prev_origin, zp->z_origin); for (cnt = 0; cnt < zp->z_addrcnt; cnt++) {#ifdef GEN_AXFR Class = zp->z_class;#else Class = C_IN;#endif error = 0; if (buf == NULL) { if ((buf = (u_char *)malloc(2 * PACKETSZ)) == NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -