ns_req.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,919 行 · 第 1/3 页

C
1,919
字号
			strcpy(buf, "Name_Too_Long");			return;		}		if (cp != buf)			*cp++ = '.';		(void) strcpy(cp, np->n_dname);		cp += i;		buflen -= (i+1);		np = np->n_parent;	}	*cp = '\0';}/* * Do a zone transfer. SOA record already sent. */#ifdef AUTHENdoaxfr(np, rfp, ns_ad, isaquery, auth_type, auth_version, isroot, rootdname)	register struct namebuf *np;	FILE *rfp;	AUTH_DAT *ns_ad;	int isaquery;	int auth_type;	int auth_version;	int isroot;	char *rootdname;#elsedoaxfr(np, rfp, isroot)	register struct namebuf *np;	FILE *rfp;	int isroot;#endif AUTHEN{	register struct databuf *dp;	register int n;	struct hashbuf *htp;	struct databuf *gdp;	/* glue databuf */	struct namebuf *gnp;	/* glue namebuf */	struct namebuf **npp, **nppend;	/* MAXDATA below was changed from PAXCKETSZ to accomodate data items	   larger than 512 bytes. Will this create conflicts with 883? */	char msg[MAXDATA];	char *cp;	char *fname;	char dname[MAXDNAME];	HEADER *hp = (HEADER *) msg;	int fndns;#ifdef AUTHEN	char *dnptr;	int cred_len;#endif AUTHEN#ifdef DEBUG	if (debug && isroot)		fprintf(ddt,"doaxfr()\n");#endif	fndns = 0;	hp->id = 0;#ifdef AUTHEN	if(isaquery)		hp->opcode = AQUERY;	else#endif AUTHEN		hp->opcode = QUERY;	hp->aa = hp->tc = hp->ra = hp->pr = hp->rd = 0;	hp->qr = 1;	hp->rcode = NOERROR;	hp->qdcount = 0;	hp->ancount = htons(1);	hp->nscount = 0;#ifdef AUTHEN	if(isaquery)		hp->arcount = htons(1);	else#endif AUTHEN		hp->arcount = 0;	cp = msg + sizeof(HEADER);	getname(np, dname, sizeof(dname));#ifdef AUTHEN	if(isroot)		 getname(np, rootdname, MAXDNAME);#endif AUTHEN	/* first do data records */	for (dp = np->n_data; dp != NULL; dp = dp->d_next) {		/*		 * Skip the root SOA record (marks end of data);		 * don't send SOA for subdomains, as we're not sending them.		 */#ifdef AUTHEN		if (dp->d_type == T_SOA)			continue;#else AUTHEN		if (dp->d_type == T_SOA)			continue;#endif AUTHEN		if (dp->d_type == T_NS)			fndns = 1;		if (dp->d_zone == 0 || stale(dp))			continue;		if ((n = make_rr(dname, dp, cp, sizeof(msg)-sizeof(HEADER), 0)) < 0)			continue;#ifdef AUTHEN		if(isaquery) {			if(auth_type == AUTH_KRB && auth_version == ONE) {				cp += n;				dnptr = dname;				if(dp->d_type != T_SOA && dp->d_type != T_AXFR)					res_dotname_rmhead(&dnptr);				hp->arcount = htons(1);				if((cred_len = res_mks_krbcred(auth_version,						   "", "", ns_ad,						   hp, cp,						   MAXDATA - (cp -(char *)hp),						   dnptr, dp->d_type,						   dp->d_class)) < RET_OK) {					syslog(LOG_ERR, "%s, %d:", "bad res_mks_krbcred call in doaxfr", cred_len);					exit(1);				}				n += cred_len;				cp = msg + sizeof(HEADER);			} else				hp->arcount = 0;		}#endif AUTHEN		fwritemsg(rfp, msg, n + sizeof(HEADER));		if (dp->d_type == T_NS) {			/*  Glue the sub domains together by sending 			 *  the address records for the sub domain			 *  name servers along.			 */ 			htp = hashtab;			cp = msg + sizeof(HEADER); 			gnp = nlookup(dp->d_data, &htp, &fname, 0); 			if (gnp == NULL || fname != dp->d_data) 				continue; 			for(gdp=gnp->n_data; gdp != NULL; gdp=gdp->d_next) { 			    if (gdp->d_type != T_A || stale(gdp)) 				continue; 			    if ((n = make_rr(fname, gdp, cp, 		    		sizeof(msg)-sizeof(HEADER), 0)) < 0) 				continue;#ifdef AUTHEN			    if(isaquery) {				    if(auth_type == AUTH_KRB) {					    cp += n;					    dnptr = fname;					    if(gdp->d_type != T_SOA &&						    gdp->d_type != T_AXFR)						res_dotname_rmhead(&dnptr);					    hp->arcount = htons(1);					    if((cred_len = res_mks_krbcred(						auth_version, "", "", ns_ad,						hp, cp,						MAXDATA - (cp - (char *)hp),						dnptr, gdp->d_type,						gdp->d_class)) < RET_OK) {						    syslog(LOG_ERR, "%s:", "bad res_mks_krbcred call in doaxfr");						    exit(1);					    }					    n += cred_len;					    cp = msg + sizeof(HEADER);				    } else					    hp->arcount = 0;			    }#endif AUTHEN 			    fwritemsg(rfp, msg, n + sizeof(HEADER)); 			} 		}	}	/* next do subdomains, unless delegated */	if ((isroot == 0 && fndns) || np->n_hash == NULL)		return;	npp = np->n_hash->h_tab;	nppend = npp + np->n_hash->h_size;	while (npp < nppend) {		for (np = *npp++; np != NULL; np = np->n_next) {#ifdef AUTHEN			doaxfr(np, rfp, ns_ad, isaquery, auth_type, auth_version, 0, rootdname);#else AUTHEN			doaxfr(np, rfp, 0);#endif AUTHEN		}	}#ifdef DEBUG	if (debug && isroot)		fprintf(ddt,"exit doaxfr()\n");#endif}#ifdef ALLOW_UPDATES/* * Called by UPDATE{A,D,DA,M,MA} to initiate a dynamic update.  If this is the * primary server for the zone being updated, we update the zone's serial * number and then call doupdate directly. If this is a secondary, we just * forward the update; this way, if the primary update fails (e.g., if the * primary is unavailable), we don't update the secondary; if the primary * update suceeds, ns_resp will get called with the response (when it comes * in), and then update the secondary's copy. */InitDynUpdate(hp, nsp, msg, msglen, startcp, from, qsp, dfd)	register HEADER *hp;	struct databuf *nsp[];	char *msg;	int msglen;	char *startcp;	struct sockaddr_in *from;	struct qstream *qsp;	int dfd;{	struct zoneinfo *zp;	char dnbuf[MAXDNAME];	struct hashbuf *htp = hashtab;	/* lookup relative to root */	struct namebuf *np;	struct databuf *olddp, *newdp, *dp;	struct databuf **nspp;	char *fname;	char *data;	register u_char *cp = startcp;	short class, type;	int n, size, zonenum;	char ZoneName[MAXDNAME], *znp;	if ((n = dn_expand(msg, msg + msglen, cp, dnbuf, sizeof(dnbuf))) < 0) {#ifdef DEBUG		if (debug)		    fprintf(ddt,"FORMERR InitDynUpdate expand name failed\n");#endif		hp->rcode = FORMERR;		return(FORMERR);	}	cp += n;	GETSHORT(type, cp);	if (type == T_SOA) {	/* T_SOA updates not allowed */		hp->rcode = REFUSED;#ifdef DEBUG		if (debug)		    fprintf(ddt, "InitDynUpdate: REFUSED - SOA update\n");#endif		return(REFUSED);	}	GETSHORT(class, cp);	cp += sizeof(u_long);	GETSHORT(size, cp);	data = cp;/****XXX - need bounds checking here ****/	cp += size;	if ((zonenum = findzone(dnbuf, class)) == 0) {  /* zone not found */		hp->rcode = NXDOMAIN;		return(NXDOMAIN);	}	zp = &zones[zonenum];	/* Disallow updates for which we aren't authoratative.  Note: the	   following test doesn't work right:  If it's for a non-local zone,	   we will think it's a primary but be unable to lookup the namebuf,	   thus returning 'NXDOMAIN' */	if (zp->z_type != Z_PRIMARY && zp->z_type != Z_SECONDARY) {		hp->rcode = REFUSED;#ifdef DEBUG		if (debug)		    fprintf(ddt, "InitDynUpdate: REFUSED - non-primary, non-sedondary update\n");#endif		return(REFUSED);	}	/*	 * Lookup the zone namebuf.  Lookup "xyz" not "xyz.", since	 * otherwise the lookup fails, because '.' may have a nil n_hash	 * associated with it.	 */	strcpy(ZoneName, zp->z_origin);	znp = &ZoneName[strlen(ZoneName) - 1];	if (*znp == '.')		*znp = NULL;	np = nlookup(ZoneName, &htp, &fname, 0);	if ((np == NULL) || (fname != ZoneName)) {#ifdef DEBUG		if (debug)		    fprintf(ddt, "InitDynUpdate: lookup failed on zone (%s)\n",			    ZoneName);#endif DEBUG	        syslog(LOG_ERR, "InitDynUpdate: lookup failed on zone (%s)\n",		       ZoneName);		hp->rcode = NXDOMAIN;		return(NXDOMAIN);	}	/*	 * If this is the primary copy increment the serial number.  Don't	 * increment the serial number if this is a secondary; this way, if 2	 * different secondaries both update the primary, they will both have	 * lower serial numbers than the primary has, and hence eventually	 * refresh and get all updates and become consistent.	 *	 * Note that the serial number must be incremented in both the zone	 * data structure and the zone's namebuf.	 */	switch (zp->z_type) {	case Z_SECONDARY:		/* forward update to primary */		nspp = nsp;		dp = np->n_data;		while (dp != NULL) {			if (match(dp, class, T_NS)) {				if (nspp < &nsp[NSMAX-1])					*nspp++ = dp;				else					break;			}			dp = dp->d_next;		}		*nspp = NULL; /* Delimiter */		if (ns_forw(nsp, msg, msglen, from, qsp, dfd, NULL) < 0) {			hp->rcode = SERVFAIL;			return(SERVFAIL);		}		return(FORWARDED);	case Z_PRIMARY:		zp->z_serial++;		olddp = np->n_data; /* old databuf */		/* Find the SOA record */		for (olddp = np->n_data; olddp != NULL; olddp = olddp->d_next)			if (match(olddp, class, T_SOA))				break;		if (olddp == NULL) {#ifdef DEBUG			if (debug)				fprintf(ddt,"InitDynUpdate: Couldn't find SOA record for '%s'\n",				        ZoneName);#endif DEBUG			syslog(LOG_ERR,			   "InitDynUpdate: Couldn't find SOA record for '%s'\n",			   ZoneName);			hp->rcode = NXDOMAIN;			return(NXDOMAIN);		}		newdp = savedata(olddp->d_class, olddp->d_type, olddp->d_ttl,				 olddp->d_data, olddp->d_size);		newdp->d_zone = olddp->d_zone;		cp = newdp->d_data;		cp += strlen(cp) + 1; /* skip origin string */		cp += strlen(cp) + 1; /* skip in-charge string */		putlong((u_long)(zp->z_serial), cp);#ifdef DEBUG		if (debug >= 4) {			fprintf(ddt, "after stuffing data into newdp:\n");			printSOAdata(newdp);		}#endif DEBUG		if ((n = db_update(ZoneName, olddp, newdp, DB_DELETE,				   hashtab)) != NOERROR) {#ifdef DEBUG			if (debug)			    fprintf(ddt,"InitDynUpdate: SOA update failed\n");#endif DEBUG			hp->rcode = NOCHANGE;			return(NOCHANGE);		}		/* Now update the RR itself */		if (doupdate(msg, msglen, msg + sizeof(HEADER),			     zonenum, (struct databuf *)0, DB_NODATA) < 0) {#ifdef DEBUG			if (debug)				fprintf(ddt,"InitDynUpdate: doupdate failed\n");#endif DEBUG			/* doupdate fills in rcode */			return(hp->rcode);		}		zp->hasChanged++;		return(NOERROR);	}}#ifdef DEBUG/* * Print the contents of the data in databuf pointed to by dp for an SOA record */printSOAdata(dp)	struct databuf *dp;{	register u_char *cp;	if (!debug)		return;  /* Otherwise fprintf to ddt will bomb */	cp = dp->d_data;	fprintf(ddt, "printSOAdata(%x): origin(%x)='%s'\n", dp, cp, cp);	cp += strlen(cp) + 1; /* skip origin string */	fprintf(ddt, "printSOAdata: in-charge(%x)='%s'\n", cp, cp);	cp += strlen(cp) + 1; /* skip in-charge string */	fprintf(ddt, "printSOAdata: serial(%x)=%d\n", cp, _getlong(cp));}#endif DEBUG#endif ALLOW_UPDATES#ifdef ULTRIXFUNCstruct databuf *rm_datum(flag, dp, np, pdp)register struct databuf *pdp, *dp;register struct namebuf *np;int flag;{	register struct databuf *ndp = dp->d_next;#ifdef DEBUG	if (debug > 2)		fprintf(ddt, "rm_datum(%x, %x, %x) -> %x\n",			dp, np->n_data, pdp, ndp);#endif DEBUG	rminv(flag, dp);	if (pdp == NULL) {		if(flag)			np->n_loaddb = ndp;		else			np->n_data = ndp;	} else		pdp->d_next = ndp;	(void) free((char *)dp);	return(ndp);}#else ULTRIXFUNCstruct databuf *rm_datum(dp, np, pdp)register struct databuf *pdp, *dp;register struct namebuf *np;{	register struct databuf *ndp = dp->d_next;#ifdef DEBUG	if (debug > 2)		fprintf(ddt, "rm_datum(%x, %x, %x) -> %x\n",			dp, np->n_data, pdp, ndp);#endif DEBUG	if (pdp == NULL)		np->n_data = ndp;	else		pdp->d_next = ndp;	rminv(dp);	(void) free((char *)dp);	return(ndp);}#endif ULTRIXFUNC#ifdef AUTHENstartxfr(qsp, np, isaquery, ns_ad, auth_type, auth_version, msg, msglen, rr,	 dname, type, class)	struct qstream *qsp;	struct namebuf *np;	int isaquery;	AUTH_DAT *ns_ad;	int auth_type;	int auth_version;	char	*msg;	int	msglen;	char	*rr;		char	*dname;	int	type;	int	class;#elsestartxfr(qsp, np, msg, msglen)	struct qstream *qsp;	struct namebuf *np;	char	*msg;	int	msglen;#endif AUTHEN{	register FILE *rfp;	int fdstat;char buff[MAXDNAME];#ifdef AUTHEN	int cred_len;#endif#ifdef DEBUG	if (debug >= 5)		fprintf(ddt,"startxfr()\n");#endif	/*	 * child does the work while	 * the parent continues	 */	if (fork() == 0) {#ifdef DEBUG		if (debug >= 5)			fprintf(ddt,"startxfr: child pid %d\n", getpid());#endif		rfp = fdopen(qsp->s_rfd, "w");		setproctitle("zone XFR to", qsp->s_rfd);		fdstat = fcntl(qsp->s_rfd, F_GETFL, 0);		if (fdstat != -1)			(void) fcntl(qsp->s_rfd, F_SETFL, fdstat & ~FNDELAY);		fwritemsg(rfp, msg, msglen);#ifdef AUTHEN		doaxfr(np, rfp, ns_ad, isaquery, auth_type, auth_version, 1,buff);#else		doaxfr(np, rfp, 1);#endif AUTHEN/* fix the old cred */#ifdef AUTHEN		if(isaquery) {			/* switch on auth type */			if((cred_len = res_mks_krbcred(auth_version, "", "", ns_ad, msg, rr, BUFSIZ - msglen, dname, T_SOA, class)) < RET_OK) {				syslog(LOG_ERR, " Couldn't send last SOA of AXFR to %s\n", ns_ad->pinst);				(void)fflush(rfp);				exit(0);			}			msglen = (rr - msg) + cred_len;		}#endif AUTHEN		fwritemsg(rfp, msg, msglen);		(void) fflush(rfp);		exit(0);	}	qsp->s_time = tt.tv_sec;	qsp->s_refcnt--;}#ifdef AUTHEN/* * Copy databuf into a resource record for replies. * Return size of RR if OK, -1 if buffer is full. */fixup_rrs(buf, buflen, cutoff, shift)	u_char *buf;	register int buflen;	int cutoff;	int shift;{	register u_char *cp = buf;	register u_char *sp;	register int n;	int type;	for(; buflen > 0;){		if((n = fixup_rr(cp, cutoff, shift)) < 0)			return(-1);		cp += n;		buflen -= n;		GETSHORT(type, cp);		cp += sizeof(u_short) + sizeof(u_long);		GETSHORT(n, cp);		sp = cp;		cp += n;		buflen -= 3 * sizeof(u_short) + sizeof(u_long) + n;		switch (type) {		case T_CNAME:		case T_MG:		case T_MR:		case T_PTR:		case T_MB:		case T_NS:			if ((n = fixup_rr(sp, cutoff, shift)) < 0)				return(-1);			break;		case T_SOA:		case T_MINFO:			if ((n = fixup_rr(sp, cutoff, shift)) < 0)				return(-1);			sp += n;				if ((n = fixup_rr(sp, cutoff, shift)) < 0)				return(-1);			break;		case T_MX:			sp += sizeof(u_short);			if ((n = fixup_rr(sp, cutoff, shift)) < 0)				return(-1);			break;		}	}	return ((int)(cp - buf));}fixup_rr(comp_dn, cutoff, shift)	u_char *comp_dn;	int cutoff;	register int shift;{	register u_char *cp;	register int val, n;	cp = comp_dn;	/*	 * fetch next label in domain name	 */	while (n = *cp++) {		/*		 * Check for indirection		 */		switch (n & INDIR_MASK) {		case 0:			cp += n;			break;		case INDIR_MASK:			val = (((n & 0x3f) << 8) | (*cp & 0xff));			if (val >= cutoff) {				val = val + shift;				--cp;				*cp++ = (val >> 8) | INDIR_MASK;				*cp++ = val % 256;			}			else				cp++;			return ((int)(cp - comp_dn));		default:			return (-1);			/* flag error */		}	}	return ((int)(cp - comp_dn));}#endif AUTHEN

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?