⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ns_req.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
				dprintf(1, (ddt,					    "doaddinfo: stale entry '%s'%s\n",					    np->n_dname,					    (dp->d_flags&DB_F_HINT)					        ? " hint"					        : ""					    ));				continue;			}#ifdef	NCACHE			if (dp->d_rcode)				continue;#endif			/*			 *  Should be smart and eliminate duplicate			 *  data here.	XXX			 */			if ((n = make_rr(ap->a_dname, dp, cp, msglen, 0)) < 0){				/* truncation in the additional-data section				 * is not all that serious.  we do not set TC,				 * since the answer and authority sections are				 * OK; however, since we're not setting TC we				 * have to make sure that none of the RR's for				 * this name go out (!TC implies that all				 * {name,type} appearances are complete -- and				 * since we only do A RR's here, the name is				 * the key).	vixie, 23apr93				 */				cp = save_cp;				msglen = save_msglen;				count = save_count;				break;			}			dprintf(5, (ddt,				    "addinfo: adding address data n = %d\n",				    n));			cp += n;			msglen -= n;			count++;		}next_rr:	if (foundstale) {			/* Cache invalidate the address RR's */			delete_all(np, (int)ap->a_class, T_A);		}		if (foundstale || !foundany) {			/* ask a real server for this info */			(void) sysquery(ap->a_dname, (int)ap->a_class, T_A,					NULL, 0);		}		free(ap->a_dname);	}	hp->arcount = htons((u_int16_t)count);	return (cp - msg);}intdoaddauth(hp, cp, buflen, np, dp)	register HEADER *hp;	u_char *cp;	int buflen;	struct namebuf *np;	struct databuf *dp;{	char dnbuf[MAXDNAME];	int n;	getname(np, dnbuf, sizeof(dnbuf));	if (stale(dp)) {		dprintf(1, (ddt,			    "doaddauth: can't add stale '%s' (%d) (n=%d)\n",			    dnbuf, buflen, n));		return 0;	}	n = make_rr(dnbuf, dp, cp, buflen, 1);	if (n <= 0) {		dprintf(1, (ddt,			    "doaddauth: can't add oversize '%s' (%d) (n=%d)\n",			    dnbuf, buflen, n));		if (n < 0) {			hp->tc = 1;		}		return 0;	}	hp->nscount = htons((u_int16_t)1);	return (n);}/* * Do a zone transfer (or a recursive part of a zone transfer). * SOA record already sent. * * top always refers to the domain at the top of the zone being transferred. * np refers to a domain inside the zone being transferred, *	which will be equal to top if this is the first call, *	or will be a subdomain below top if this is a recursive call, * rfp is a stdio file to which output is sent. */static voiddoaxfr(np, rfp, top, class)	register struct namebuf *np;	FILE *rfp;	struct namebuf *top;	int class;		/* Class to transfer */{	register struct databuf *dp;	register int n;	struct hashbuf *htp;	struct databuf *gdp;	/* glue databuf */	struct namebuf *gnp;	/* glue namebuf */	struct namebuf *tnp;	/* top namebuf */	struct databuf *tdp;	/* top databuf */	struct namebuf **npp, **nppend;	char msg[PACKETSZ];	u_char *cp;	char *fname;	char dname[MAXDNAME];	HEADER *hp = (HEADER *) msg;	int fndns;	if (np == top)		dprintf(1, (ddt, "doaxfr()\n"));	fndns = 0;	hp->id = 0;	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;	hp->arcount = 0;	cp = (u_char *) (msg + sizeof(HEADER));	getname(np, dname, sizeof(dname));	/* first do the NS records (del@harris) */	for (dp = np->n_data; dp != NULL; dp = dp->d_next) {#ifdef GEN_AXFR	    if (dp->d_class != class && class != C_ANY)		continue;#endif#ifdef	    NCACHE	    if (dp->d_rcode)		continue;#endif	    if (dp->d_type == T_NS) {		fndns = 1;		if ((n = make_rr(dname, dp, cp,				 sizeof(msg)-sizeof(HEADER), 0)) < 0)			continue;		fwritemsg(rfp, msg, n + sizeof(HEADER));		if (np != top) {		    /*  Glue the sub domains together by sending 		     *  the address records for the sub domain		     *  name servers along if necessary.		     *  Glue is necessary if the server is in any zone		     *  delegated from the current (top) zone.  Such		     *  a delegated zone might or might not be that		     *  referred to by the NS record now being handled.		     */ 		    htp = hashtab;		    cp = (u_char *) (msg + sizeof(HEADER)); 		    gnp = nlookup((caddr_t)dp->d_data, &htp, &fname, 0); 		    if (gnp == NULL || fname != (caddr_t)dp->d_data) 			continue;		    for (tnp = gnp; tnp != NULL; tnp = tnp->n_parent)			if ( tnp == top )			    break;		    if ( tnp == NULL )			continue;  /* name server is not below top domain */		    for (tnp = gnp; tnp != top; tnp = tnp->n_parent) {			for (tdp = tnp->n_data; tdp != NULL; tdp = tdp->d_next)			{#ifdef GEN_AXFR			    if (tdp->d_class != class && class != C_ANY)				continue;#endif			    if (tdp->d_type == T_NS)				break;			}			if (tdp != NULL)			    break; /* found a zone cut */		    }		    if (tnp == top)			continue;  /* name server is not in a delegated zone */		    /* now we know glue records are needed.  send them. */ 		    for(gdp=gnp->n_data; gdp != NULL; gdp=gdp->d_next) {#ifdef GEN_AXFR			if (gdp->d_class != class && class != C_ANY)			    continue;#endif 			if (gdp->d_type != T_A || stale(gdp)) 			    continue;#ifdef NCACHE			if (gdp->d_rcode)			   continue;#endif 			if ((n = make_rr(fname, gdp, cp, 		    	    sizeof(msg)-sizeof(HEADER), 0)) < 0)	 		    continue; 			fwritemsg(rfp, msg, n + sizeof(HEADER)); 		    }		}	    }	}	/* no need to send anything else because of delegation */	if ((np != top) && fndns)		return;	/* do the rest of the data records */	for (dp = np->n_data; dp != NULL; dp = dp->d_next) {#ifdef GEN_AXFR		if (dp->d_class != class && class != C_ANY)			continue;#endif		/*		 * Skip the top SOA record (marks end of data);		 * don't send SOA for subdomains, as we're not sending them;		 * skip the NS records because we did them first.		 */		if (dp->d_type == T_SOA || dp->d_type == T_NS)			continue;		if (dp->d_zone == 0 || stale(dp))			continue;#ifdef NCACHE		if (dp->d_rcode)			continue;#endif		if ((n = make_rr(dname, dp, cp, sizeof(msg)-sizeof(HEADER), 0)) < 0)			continue;		fwritemsg(rfp, msg, n + sizeof(HEADER));	}	/* Finally do non-delegated subdomains.  Delegated subdomains	 * have already been handled.	 */	/*	 * We find the subdomains by looking in the hash table for this	 * domain, but the root domain needs special treatment, because	 * of the following wart in the database design:	 *	 * The top level hash table (pointed to by the global `hashtab'	 * variable) contains pointers to the namebuf's for the root as	 * well as for the top-level domains below the root, in contrast	 * to the usual situation where a hash table contains entries	 * for domains at the same level.  The n_hash member of the	 * namebuf for the root domain is NULL instead of pointing to a	 * hashbuf for the top-level domains.  The n_parent members of	 * the namebufs for the top-level domains are NULL instead of	 * pointing to the namebuf for the root.	 *	 * We work around the wart as follows:	 *	 * If we are not dealing with the root zone then we just set	 * htp = np->n_hash, pointing to the hash table for the current	 * domain, and we walk through the hash table as usual,	 * processing the namebufs for all the subdomains.	 *	 * If we are dealing with the root zone, then we set	 * htp = hashtab, pointing to the global hash table (because	 * there is no hash table associated with the root domain's	 * namebuf.  While we walk this hash table, we take care not to	 * recursively process the entry for the root namebuf.	 *	 * (apb@und nov1990)	 */	htp = ((dname[0] == '\0') ? hashtab : np->n_hash);	if (htp == NULL) {		return; /* no subdomains */	}	npp = htp->h_tab;	nppend = npp + htp->h_size;	while (npp < nppend) {		for (np = *npp++; np != NULL; np = np->n_next) {		    if (np->n_dname[0] != '\0') { /* don't redo root domain */			doaxfr(np, rfp, top, class);		    }		}	}	if (np == top)		dprintf(1, (ddt, "exit doaxfr()\n"));}#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. */static intInitDynUpdate(hp, msg, msglen, startcp, from, qsp, dfd)	register HEADER *hp;	char *msg;	int msglen;	u_char *startcp;	struct sockaddr_in *from;	struct qstream *qsp;	int dfd;{	struct databuf *nsp[NSMAX];	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;	register u_char *cp = startcp;	u_int16_t class, type;	int n, size, zonenum;	char ZoneName[MAXDNAME], *znp;#ifdef 	DATUMREFCNT	nsp[0] = NULL;#endif	if ((n = dn_expand(msg, msg + msglen, cp, dnbuf, sizeof(dnbuf))) < 0) {		dprintf(1, (ddt,"FORMERR InitDynUpdate expand name failed\n"));		hp->rcode = FORMERR;		return(FORMERR);	}	cp += n;	GETSHORT(type, cp);	if (type == T_SOA) {	/* T_SOA updates not allowed */		hp->rcode = REFUSED;		dprintf(1, (ddt, "InitDynUpdate: REFUSED - SOA update\n"));		return(REFUSED);	}	GETSHORT(class, cp);	cp += sizeof(u_int32_t);	GETSHORT(size, 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;		dprintf(1, (ddt,		 "InitDynUpdate: REFUSED - non-{primary,secondary} update\n"));		return(REFUSED);	}	if (!(zp->z_state & Z_DYNAMIC)) {		hp->rcode = REFUSED;		dprintf(1, (ddt,		 "InitDynUpdate: REFUSED - dynamic flag not set for zone\n"));		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)) {		dprintf(1, (ddt, "InitDynUpdate: lookup failed on zone (%s)\n",			    ZoneName));	        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;#ifdef	DATUMREFCNT					dp->d_rcnt++;#endif				} else					break;			}			dp = dp->d_next;		}		*nspp = NULL; /* Delimiter */		if (ns_forw(nsp, msg, msglen, from, qsp, dfd, NULL, dnbuf)		    <		    0) {			hp->rcode = SERVFAIL;#ifdef	DATUMREFCNT			free_nsp(nsp);#endif			return(SERVFAIL);		}#ifdef	DATUMREFCNT		free_nsp(nsp);#endif		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) {			dprintf(1, (ddt,			 "InitDynUpdate: Couldn't find SOA record for '%s'\n",				    ZoneName));			syslog(LOG_ERR,			   "InitDynUpdate: Couldn't find SOA record for '%s'\n",			   ZoneName);			hp->rcode = NXDOMAIN;#ifdef	DATUMREFCNT			free_nsp(nsp);#endif			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;#ifdef CRED		newdp->d_cred = DB_C_AUTH;		newdp->d_clev = db_getclev(zp->z_origin);#endif		cp = (u_char *)newdp->d_data;		cp += strlen(cp) + 1; /* skip origin string */		cp += strlen(cp) + 1; /* skip in-charge string */		putlong((u_int32_t)(zp->z_serial), cp);		dprintf(4, (ddt, "after stuffing data into newdp:\n"));#ifdef DEBUG		if (debug >= 4)			printSOAdata(newdp);#endif		if ((n = db_update(ZoneName, olddp, newdp, DB_DELETE,				   hashtab)) != NOERROR) {			dprintf(1, (ddt,				    "InitDynUpdate: SOA update failed\n"));			hp->rcode = NOCHANGE;			free((char*) dp);		/* vix@dec mar92 */#ifdef	DATUMREFCNT			free_nsp(nsp);#endif			return(NOCHANGE);		}		/* Now update the RR itself */		if (doupdate(msg, msglen, msg + sizeof(HEADER),			     zonenum, (struct databuf *)0, DB_NODATA#ifdef CRED			     , DB_C_AUTH#endif			     ) < 0) {			dprintf(1, (ddt, "InitDynUpdate: doupdate failed\n"));			/* doupdate fills in rcode */#ifdef	DATUMREFCNT			free_nsp(nsp);#endif			return(hp->rcode);		}		zp->z_state |= Z_CHANGED;#ifdef	DATUMREFCNT			free_nsp(nsp);#endif		return(NOERROR);	}}#ifdef DEBUG/* * Print the contents of the data in databuf pointed to by dp for an SOA record */static voidprintSOAdata(dp)	struct databuf *dp;{	register u_char *cp;	if (!debug)		return;  /* Otherwise fprintf to ddt will bomb */	cp = (u_char *)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#endifstatic voidstartxfr(qsp, np, msg, msglen, class)	struct qstream	*qsp;	struct namebuf	*np;	char		*msg;	int		msglen;	int		class;{	register FILE	*rfp;	int		fdstat;	dprintf(5, (ddt, "startxfr()\n"));	/*	 * child does the work while	 * the parent continues	 *	 * XXX this should be a vfork/exec since on non-copy-on-write	 * systems with huge nameserver images, this is very expensive.	 */	if (fork() == 0) {		dprintf(5, (ddt, "startxfr: child pid %d\n", getpid()));		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 & ~PORT_NONBLOCK);		fwritemsg(rfp, msg, msglen);		doaxfr(np, rfp, np, class);		fwritemsg(rfp, msg, msglen);		(void) fflush(rfp);		exit(0);	}}free_addinfo(){	register struct addinfo *ap;	for (ap = addinfo; --addcount >= 0; ap++) {		free(ap->a_dname);	}	addcount = 0;}#ifdef DATUMREFCNTfree_nsp(nsp)struct databuf **nsp;{	while (*nsp) {		if (--((*nsp)->d_rcnt)) {			dprintf(3, (ddt, "free_nsp: %s rcnt %d\n",			(*nsp)->d_data, (*nsp)->d_rcnt));		} else {			dprintf(3, (ddt, "free_nsp: %s rcnt %d delayed\n",				(*nsp)->d_data, (*nsp)->d_rcnt));			free(*nsp);	/* delayed free */		}		nsp++;	}}#endif

⌨️ 快捷键说明

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