xfer.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,802 行 · 第 1/3 页
C
1,802 行
#ifndef lintstatic char *sccsid = "@(#)xfer.c 4.1 (ULTRIX) 7/2/90";#endif lint/************************************************************************ * * * Copyright (c) 1990 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//* * Modification History: * * 30-Mar-90 sue * Added the Hesiod class to case A record per Mark Rosenstein's * MIT bug report. * * 28-Feb-90 sue * Added two missing if (debug) lines to DEBUG spots in getzone(). * * 07-Feb-90 sue * Added proper TXT handling according to rfc1035. * * 07-Feb-90 bbrown * Added 4.8.2 and Kerberos *//* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * * The original version of xfer is 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. * static char sccsid[] = "@(#)xfer.c 4.8 (Berkeley) 10/4/89"; */#include <sys/param.h>#include <sys/file.h>#include <sys/time.h>#include <sys/stat.h>#include <sys/wait.h>#include <sys/resource.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <sys/uio.h>#include <netinet/in.h>#include <net/if.h>#include <stdio.h>#include <syslog.h>#include <errno.h>#include <signal.h>#include <netdb.h>#include <arpa/inet.h>#include <arpa/nameser.h>#include <resolv.h>#ifdef AUTHEN#include <krb.h>#endif AUTHEN#define XFER /* modifies the ns.h include file */#include "ns.h"char *savestr();/* max length of data in RR data field */#define MAXDATA 1024 /* from db.h */ int debug = 0; int quiet = 0;int read_interrupted = 0;struct zoneinfo zones; /* zone information */struct timeval tt;static char *ddtfile = _PATH_TMPXFER;static char *tmpname;FILE *fp = 0, *ddt, *dbfp;char *domain; /* domain being xfered */int domain_len; /* strlen(domain) */extern char *malloc();extern int errno;#ifdef AUTHENint defauthentype = AUTH_KRB;int defauthenver = ONE;int netsafe = 0;extern map_t m_credval[];extern map_t m_credtype[];extern struct hostent *gethostbyaddr_local();extern struct hostent *gethostbyname_local();extern char *res_dotname_head();char *mktemp();#endif AUTHENmain(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; u_long serial_no = 0; extern char *optarg; extern int optind, getopt(); u_short port = htons(NAMESERVER_PORT);#ifdef AUTHEN char *p_char; char *optarg2; char localhost[MAXDNAME]; struct hostent *temp_ent; char tkt_filename[50];#endif AUTHEN (void) umask(022);#ifdef LOG_DAEMON openlog("named-xfer", LOG_PID|LOG_CONS, LOG_DAEMON);#else openlog("named-xfer", LOG_PID);#endif#ifdef AUTHEN while ((c = getopt(argc, argv, "a:d:l:s:t:z:f:p:P:qn")) != EOF)#else AUTHEN while ((c = getopt(argc, argv, "d:l:s:t:z:f:p:P:q")) != EOF)#endif AUTHEN switch (c) {#ifdef AUTHEN case 'a': for( p_char = optarg; *p_char != '.' && *p_char != '\0'; p_char++); if(*p_char != '.') usage(); else { optarg2 = p_char + 1; *p_char = '\0'; } if((defauthentype = m_str_val(m_credtype, NUMMAPCREDTYPE, optarg))== RET_BAD) usage(); _res.defauthtype = defauthentype; if((defauthenver=m_str_val(m_credval, NUMMAPCREDVAL, optarg2)) == RET_BAD) usage(); _res.defauthversion= defauthenver; break; case 'n': netsafe = 1; break;#endif AUTHEN case 'd': debug = atoi(optarg); break; case 'l': ddtfile = malloc(strlen(optarg) + sizeof(".XXXXXX") + 1); (void) strcpy(ddtfile, optarg); (void) strcat(ddtfile, ".XXXXXX"); break; case 's': serial_no = (u_long) atol(optarg); break; case 't': tracefile = optarg; break; case 'z': /* zone == domain */ domain = optarg; domain_len = strlen(domain); break; case 'f': dbfile = optarg; tmpname = malloc((unsigned)strlen(optarg) + sizeof(".XXXXXX") + 1); (void) strcpy(tmpname, optarg); break; case 'p': port = htons((u_short)atoi(optarg)); break; case 'P': port = (u_short)atoi(optarg); break; case 'q': quiet++; break; case '?': default: usage(); /* NOTREACHED */ } if (!domain || !dbfile || optind >= argc) { usage(); /* NOTREACHED */ } #ifdef AUTHEN if(netsafe) { if(gethostname(localhost, MAXDNAME)) { if (!quiet) syslog(LOG_ERR, "bad gethostname call\n"); exit(XFER_FAIL); } if((temp_ent = gethostbyname_local(localhost)) < 0) { if (!quiet) syslog(LOG_ERR, "bad gethostbyname call %s\n", localhost); exit(XFER_FAIL); } if((p_char = index(localhost, '.')) != (char *)0) *p_char = '\0'; strcpy(tkt_filename, "/var/dss/kerberos/tkt/tkt.xfer.XXXXXX"); if (mktemp(tkt_filename) == (char *)NULL) { perror(tkt_filename); if (!quiet) syslog(LOG_ERR,"can't make tkt tmpfile\n"); exit(XFER_FAIL); } if((result = krb_svc_init("named", localhost, NULL, 0, NULL, tkt_filename)) != RET_OK) { if (!quiet) syslog(LOG_ERR, "bad krb_svc_int call %d\n", result); exit(XFER_FAIL); } }#endif AUTHEN 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 { setlinebuf(ddt); } }#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#ifdef ULTRIXFUNC (void) signal(SIGTRAP, SIG_IGN); (void) signal(SIGXFSZ, SIG_IGN);#endif ULTRIXFUNC#ifdef DEBUG if (debug) (void)fprintf(ddt, "domain `%s' file `%s' ser no %lu \n", domain, dbfile,serial_no);#endif buildservicelist(); buildprotolist(); /* init zone data */ zp = &zones; zp->z_type = Z_SECONDARY; zp->z_origin = domain; zp->z_source = dbfile; zp->z_addrcnt = 0; zp->z_class = C_ANY;#ifdef DEBUG if (debug) { (void)fprintf(ddt,"zone found (%d): ", zp->z_type); if (zp->z_origin[0] == '\0') (void)fprintf(ddt,"'.'"); else (void)fprintf(ddt,"'%s'", zp->z_origin); (void)fprintf(ddt,", source = %s\n", zp->z_source); }#endif for (; optind != argc; optind++,zp->z_addrcnt++) { tm = argv[optind]; zp->z_addr[zp->z_addrcnt].s_addr = inet_addr(tm); if (zp->z_addr[zp->z_addrcnt].s_addr == (unsigned)-1) { hp = gethostbyname_local(tm); if (hp == NULL) { syslog(LOG_ERR,"uninterpretable server name %s\n", tm); continue; } bcopy(hp->h_addr, (char *)&zp->z_addr[zp->z_addrcnt].s_addr, sizeof(zp->z_addr[zp->z_addrcnt].s_addr));#ifdef DEBUG if (debug) (void)fprintf(ddt,", %s",tm);#endif }#ifdef AUTHEN else { if((hp = gethostbyaddr_local( &(zp->z_addr[zp->z_addrcnt].s_addr), sizeof(struct in_addr), AF_INET)) == (struct hostent *)NULL) { syslog(LOG_ERR,"uninterpretable server addr %s\n", tm); continue; } } strcpy(zp->z_dname[zp->z_addrcnt], hp->h_name);#endif AUTHEN if (zp->z_addrcnt >= NSMAX) { zp->z_addrcnt = NSMAX;#ifdef DEBUG if (debug) (void)fprintf(ddt, "\nns.h NSMAX reached\n");#endif break; } }#ifdef DEBUG if (debug) (void)fprintf(ddt," (addrcnt) = %d\n", zp->z_addrcnt);#endif _res.options &= ~(RES_DEFNAMES | RES_DNSRCH | RES_RECURSE); result = getzone(zp, serial_no, port); (void) fclose(dbfp); if(netsafe) unlink(tkt_filename); 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 */ }} usage(){ (void)fprintf(stderr,"Usage: xfer\n\\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 (default %s)]\n\\t[-t trace_file]\n\\t[-p port]\n\\t[-n]\n\\t[-a auth_type.auth_ver]\n\\tservers...\n", ddtfile); exit(XFER_FAIL);}int minimum_ttl = 0, got_soa = 0;char prev_origin[MAXDNAME];char prev_dname[MAXDNAME];getzone(zp, serial_no, port) struct zoneinfo *zp; u_long serial_no; u_short port;{ HEADER *hp; u_short len; u_long serial; int s, n, l, cnt, 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; extern void read_alarm(); struct sigvec sv, osv; int ancount, aucount;#ifdef AUTHEN u_char *authen_tmp; int authen_len; int authen; CREDENTIALS cred; u_char *namptr; int authen_answtype; int authen_answclass; char *krbnameptr;#endif AUTHEN#ifdef DEBUG if (debug) (void)fprintf(ddt,"getzone() %s\n", zp->z_origin);#endif bzero((char *)&zeroival, sizeof(zeroival)); ival = zeroival; ival.it_value.tv_sec = 120; sv.sv_handler = read_alarm; sv.sv_onstack = 0; sv.sv_mask = ~0; (void) sigvec(SIGALRM, &sv, &osv); strcpy(prev_origin, zp->z_origin); for (cnt = 0; cnt < zp->z_addrcnt; cnt++) { error = 0; if (buf == NULL) { if ((buf = (u_char *)malloc(2 * PACKETSZ)) == NULL) { syslog(LOG_ERR, "malloc(%u) failed", 2 * PACKETSZ); error++; break; } bufsize = 2 * PACKETSZ; } bzero((char *)&sin, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = port; sin.sin_addr = zp->z_addr[cnt]; if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { syslog(LOG_ERR, "socket: %m"); error++; break; } #ifdef DEBUG if (debug >= 2) { (void)fprintf(ddt,"connecting to server #%d %s, %d\n", cnt+1, inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); }#endif#ifdef ULTRIXFUNC if (icmp_ping(&sin.sin_addr)) { (void) close(s); error++; #ifdef DEBUG if (debug) (void)fprintf(ddt,"icmp_ping failed\n");#endif continue; }#endif ULTRIXFUNC if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { (void) close(s); error++;#ifdef DEBUG if (debug) (void)fprintf(ddt, "connect failed, errno %d\n", errno);#endif continue; } #ifdef AUTHEN if(netsafe && defauthentype == AUTH_KRB && defauthenver==ONE) { if ((n = res_mkquery(AQUERY, zp->z_origin, zp->z_class, T_SOA, (char *)NULL, 0, NULL, buf, bufsize)) < 0) { if (!quiet) syslog(LOG_ERR, "zone %s: res_mkquery T_SOA failed", zp->z_origin); (void) close(s); (void) sigvec(SIGALRM, &osv, (struct sigvec *)0); return XFER_FAIL; } krbnameptr = res_dotname_head(zp->z_dname[cnt]); if((authen_len = res_mkl_krbcred(ONE, "named", krbnameptr, &cred, buf, buf + n, bufsize - n, zp->z_origin, T_SOA, zp->z_class)) < RET_OK) { if (!quiet) syslog(LOG_ERR, "zoneref: res_mkl_krbcred T_SOA failed"); free(krbnameptr); (void) close(s); (void) sigvec(SIGALRM, &osv, (struct sigvec *)0); return XFER_FAIL; } free(krbnameptr); n += authen_len; } else if (netsafe){ if (!quiet) syslog(LOG_ERR, "%s:", "bad default auth type in zoneref T_SOA"); (void) close(s); (void) sigvec(SIGALRM, &osv, (struct sigvec *)0); return XFER_FAIL; } else { if ((n = res_mkquery(QUERY, zp->z_origin, zp->z_class, T_SOA, (char *)NULL, 0, NULL, buf, bufsize)) < 0) { if (!quiet) syslog(LOG_ERR, "zone %s: res_mkquery T_SOA failed", zp->z_origin); (void) close(s); (void) sigvec(SIGALRM, &osv, (struct sigvec *)0);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?