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

📄 db_update.c

📁 早期freebsd实现
💻 C
字号:
#if !defined(lint) && !defined(SABER)static char sccsid[] = "@(#)db_update.c	4.28 (Berkeley) 3/21/91";static char rcsid[] = "$Id: db_update.c,v 4.9.1.6 1993/12/06 00:43:02 vixie Exp $";#endif /* not lint *//* * ++Copyright++ 1986, 1990 * - * Copyright (c) 1986, 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-- */#include <stdio.h>#include <syslog.h>#include <sys/param.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <arpa/nameser.h>#include "named.h"static void			fixttl __P((struct databuf *));static int			db_cmp __P((struct databuf *,					    struct databuf *));#ifdef CRED/* int * isRefByNS(name, htp) *	recurse through all of `htp' looking for NS RR's that refer to `name'. * returns: *	nonzero if at least one such NS RR exists * cautions: *	this is very expensive; probably you only want to use on fcachetab. */static intisRefByNS(name, htp)	char name[];	struct hashbuf *htp;{	register struct namebuf *np;	register struct databuf *dp;	for (np = htp->h_tab[0];  np != NULL;  np = np->n_next) {		for (dp = np->n_data;  dp != NULL;  dp = dp->d_next) {			if ((dp->d_class == C_ANY || dp->d_class == C_IN) &&			    (dp->d_type == T_NS) &&#ifdef NCACHE			    (!dp->d_rcode) &&#endif			    !strcasecmp(name, (char *)dp->d_data)) {				return 1;			}		}		if (np->n_hash && isRefByNS(name, np->n_hash)) {			return 1;		}	}	return 0;}#endif /*CRED*//* int * db_update(name, odp, newdp, flags, htp) *	update data base node at `name'.  `flags' controls the action. * side effects: *	inverse query tables modified, if we're using them. * return value: *	OK - success *	NONAME - name doesn't exist *	AUTH - you can't do that *	DATAEXISTS - there's something there and DB_NODATA was specified *	NODATA - there's no data, and (DB_DELETE or DB_MEXIST) was spec'd */intdb_update(name, odp, newdp, flags, htp)	char name[];	struct databuf *odp, *newdp;	int flags;	struct hashbuf *htp;{	register struct namebuf *np;	register struct databuf *dp, *pdp;	char *fname;        int foundRR = 0;#ifdef CRED	int isHintNS = isRefByNS(name, fcachetab);#endif /*CRED*/	dprintf(3, (ddt, "db_update(%s, 0x%x, 0x%x, 0%o, 0x%x)%s\n",		    name, odp, newdp, flags, htp,		    (odp && (odp->d_flags&DB_F_HINT)) ? " hint":"" ));	np = nlookup(name, &htp, &fname, newdp != NULL);	if (np == NULL || fname != name)		return NONAME;#ifdef CRED	/* some special checks for root NS' A RR's */	if (newdp && isHintNS && newdp->d_type == T_A) {		/* obviously bogus addresses die here */		if (#ifdef NCACHE		(!newdp->d_rcode) &&#endif			(((struct in_addr *)newdp->d_data)->s_addr == 0)) {			syslog(LOG_INFO, "bogus (0.0.0.0) root A RR received");			return AUTH;		}		/* upgrade credibility of additional data */		if (newdp->d_cred == DB_C_ADDITIONAL) {			dprintf(3, (ddt,				    "upgrading credibility for A RR (%s)\n",				    name));			newdp->d_cred = DB_C_ANSWER;			newdp->d_clev = 0;		}	}#endif /*CRED*/        /* Reflect certain updates in hint cache also... */	/* Don't stick data we are authoritative for in hints. */        if (!(flags & DB_NOHINTS) && (odp != NULL) &&	    (htp != fcachetab) &&		/* vix@dec mar92 */	    (odp->d_zone <= 0) && !(odp->d_flags & DB_F_HINT) &&            ((name[0] == '\0' && odp->d_type == T_NS) ||	     (odp->d_type == T_A#ifdef CRED	      && isHintNS#endif /*CRED*/	      )	     )	    )        {		dprintf(3, (ddt, "db_update: hint '%s' %d\n",			    name, odp->d_ttl));		dp = savedata(odp->d_class, odp->d_type, odp->d_ttl,			odp->d_data, odp->d_size);		dp->d_zone = DB_Z_CACHE;		dp->d_flags = DB_F_HINT;#ifdef CRED		dp->d_cred = DB_C_CACHE;		dp->d_clev = 0;#endif /*CRED*/		if (db_update(name,			      dp, dp,			      (flags|DB_NOHINTS),			      fcachetab)		    != OK) {			dprintf(3, (ddt, "db_update: hint %x freed\n", dp));			(void) free((char *)dp);		}        }	if (odp != NULL) {		pdp = NULL;		for (dp = np->n_data; dp != NULL; ) {			if (!match(dp, odp->d_class, odp->d_type)) {				if ((dp->d_type == T_CNAME ||				    odp->d_type == T_CNAME) &&				    odp->d_mark == dp->d_mark &&#ifdef NCACHE				    /* neither the odp nor the new dp are				     * negatively cached records...				     */				    (!dp->d_rcode) &&				    (!odp->d_rcode) &&#endif /*NCACHE*/				    zones[odp->d_zone].z_type != Z_CACHE) {					syslog(LOG_ERR,				     "%s has CNAME and other data (illegal)\n",					    name);					dprintf(1, (ddt,				    "db_update: %s: CNAME and more (%d, %d)\n",						    name, odp->d_type,						    dp->d_type));				}				goto skip;			}			dprintf(5, (ddt,			       "db_update: flags = %#x, sizes = %d, %d (%d)\n",				    flags, odp->d_size, dp->d_size,				    db_cmp(dp, odp)));			if (flags & DB_NOTAUTH && dp->d_zone) {				dprintf(1, (ddt,			     "[%s].%d attempted update to auth zone %d '%s'\n",					    inet_ntoa(from_addr.sin_addr),					    ntohs(from_addr.sin_port),					    dp->d_zone,					    zones[dp->d_zone].z_origin));				return AUTH;			}#ifdef CRED			if (newdp) {				dprintf(4, (ddt,		     "credibility for %s is %d(%d) from [%s].%d, is %d(%d) in cache\n",					    *name? ".": name,					    newdp->d_cred,					    newdp->d_clev,					    inet_ntoa(from_addr.sin_addr),					    ntohs(from_addr.sin_port),					    dp->d_cred,					    dp->d_clev));				if ((newdp->d_cred > dp->d_cred) || 					((newdp->d_cred == DB_C_AUTH) && 					(newdp->d_clev > dp->d_clev))) {					/* better credibility and the old datum					 * was not from a zone file.  remove					 * the old datum.					 */					dp = rm_datum(dp, np, pdp);					continue;				}				if (newdp->d_cred < dp->d_cred) {					/* credibility is worse.  ignore it. */					return AUTH;				}				/* credibility is the same.				 * let it aggregate in the normal way.				 */			}#endif /*CRED*/			if ((flags & DB_NODATA) && !db_cmp(dp, odp)) {				/* refresh ttl if cache entry */				if (dp->d_zone == 0) {					if (odp->d_zone != 0) {	/* XXX */						/* changing cache->auth */						dp->d_zone = odp->d_zone;						dp->d_ttl = odp->d_ttl;						dprintf(4, (ddt,				    "db_update: cache entry now in auth zone\n"							    ));						return DATAEXISTS;					}					fixttl(odp);					if (odp->d_ttl > dp->d_ttl)						dp->d_ttl = odp->d_ttl;					dprintf(3, (ddt,						"db_update: new ttl %d, +%d\n",						    dp->d_ttl,						    dp->d_ttl - tt.tv_sec));				}				return DATAEXISTS;			}			/*			 * If the old databuf has some data, check that the			 * data matches that in the new databuf (so UPDATED			 * will delete only the matching RR)			 */			if (odp->d_size > 0) {				if (db_cmp(dp, odp))					goto skip;			}			foundRR = 1;			if (flags & DB_DELETE)				dp = rm_datum(dp, np, pdp);			else {skip:				pdp = dp;				dp = dp->d_next;			}		}                if (!foundRR) {			if (flags & DB_DELETE)				return NODATA;			if (flags & DB_MEXIST)				return NODATA;		}	}	if (newdp == NULL)		return OK;	fixttl(newdp);	dprintf(3, (ddt, "db_update: adding%s %x\n",		    (newdp->d_flags&DB_F_HINT) ? " hint":"", newdp));#if INVQ	if (!(newdp->d_flags & DB_F_HINT))		addinv(np, newdp);	/* modify inverse query tables */#endif	/* Add to end of list, generally preserving order */	newdp->d_next = NULL;	if ((dp = np->n_data) == NULL)  {#ifdef	DATUMREFCNT		newdp->d_rcnt = 1;#endif		np->n_data = newdp;		return OK;	}	/* XXX: need to check for duplicate WKS records and flag error */	while (dp->d_next != NULL) {		if ((flags & DB_NODATA) && !db_cmp(dp, newdp))			return DATAEXISTS;		dp = dp->d_next;	}	if ((flags & DB_NODATA) && !db_cmp(dp, newdp))		return DATAEXISTS;#ifdef	DATUMREFCNT	newdp->d_rcnt = 1;#endif	dp->d_next = newdp;	return OK;}static voidfixttl(dp)	register struct databuf *dp;{	if (dp->d_zone == 0 && !(dp->d_flags & DB_F_HINT)) {		if (dp->d_ttl <= tt.tv_sec)			return;		else if (dp->d_ttl < tt.tv_sec+min_cache_ttl)			dp->d_ttl = tt.tv_sec+min_cache_ttl;		else if (dp->d_ttl > tt.tv_sec+max_cache_ttl)			dp->d_ttl = tt.tv_sec+max_cache_ttl;	}	return;}/* * Compare type, class and data from databufs for equivalence. * Must be case insensitive for some domain names. * Return 0 if equivalent, nonzero otherwise. */static intdb_cmp(dp1, dp2)	register struct databuf *dp1, *dp2;{	register u_char *cp1, *cp2;	int len;	if (dp1->d_type != dp2->d_type || dp1->d_class != dp2->d_class)		return(1);	if (dp1->d_size != dp2->d_size)		return(1);	if (dp1->d_mark != dp2->d_mark)		return(1);		/* old and new RR's are distinct */#ifdef NCACHE	if (dp1->d_rcode && dp2->d_rcode)		return((dp1->d_rcode == dp1->d_rcode)?0:1);	if (dp1->d_rcode || dp2->d_rcode)		return(1);#endif	switch (dp1->d_type) {	case T_A:	case T_UID:	case T_GID:	case T_WKS:	case T_NULL:#ifdef ALLOW_T_UNSPEC        case T_UNSPEC:#endif		return bcmp(dp1->d_data, dp2->d_data, dp1->d_size);	case T_NS:	case T_CNAME:	case T_PTR:	case T_MB:	case T_MG:	case T_MR:	case T_UINFO:		return strcasecmp((char *)dp1->d_data, (char *)dp2->d_data);	case T_HINFO:		cp1 = dp1->d_data;		cp2 = dp2->d_data;		len = *cp1;		if (strncasecmp((char *)++cp1, (char *)++cp2, len))			return 1;		cp1 += len;		cp2 += len;		len = *cp1;		return strncasecmp((char *)++cp1, (char *)++cp2, len);	case T_SOA:	case T_MINFO:	case T_RP:		if (strcasecmp((char *)dp1->d_data, (char *)dp2->d_data))			return(1);		cp1 = dp1->d_data + strlen((char *)dp1->d_data) + 1;		cp2 = dp2->d_data + strlen((char *)dp2->d_data) + 1;		if (dp1->d_type != T_SOA)			return strcasecmp((char *)cp1, (char *)cp2);		if (strcasecmp((char *)cp1, (char *)cp2))			return 1;		cp1 += strlen((char *)cp1) + 1;		cp2 += strlen((char *)cp2) + 1;		return bcmp(cp1, cp2, sizeof(u_int32_t) * 5);		case T_MX:	case T_AFSDB:		cp1 = dp1->d_data;		cp2 = dp2->d_data;		if (*cp1++ != *cp2++ || *cp1++ != *cp2++)	/* cmp prio */			return 1;		return strcasecmp((char *)cp1, (char *)cp2);	case T_TXT:		if (dp1->d_size != dp2->d_size)			return 1;		return bcmp(dp1->d_data, dp2->d_data, dp1->d_size);	default:		return (1);	}}

⌨️ 快捷键说明

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