db_update.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 454 行

C
454
字号
#ifndef lintstatic	char	*sccsid = "@(#)db_update.c	4.1	(ULTRIX)	7/2/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1984-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.	* *									* ************************************************************************//* * Copyright (c) 1986 Regents of the University of California *	All Rights Reserved * static char sccsid[] = "@(#)db_update.c	4.16 (Berkeley) 2/28/88"; *//* * Modification History: * * 18-Jan-88	logcher *	Added BIND 4.7.2 with ifdef-ed MIT Hesiod support. * * 26-Jan-88	logcher *	Added BIND 4.7.3. * * 08-Mar-88	logcher *	Added bug fix to db_update to check type and class after XXX *	per bind-test mailing list dated 19-Feb-88 * * 08-Jun-88	logcher *	Added the correct MIT Hesiod support. * * 11-Nov-88	logcher *	Updated with V3.0 changes. * * 17-May-89	logcher *	Added BIND 4.8. * * 10-Jan-90	sue *	Incorporated Hesiod changes from MIT to implement multiple *	"character strings" in a TXT record according to RFC1035. */#include <sys/types.h>#include <sys/socket.h>#include <sys/time.h>#ifdef ULTRIXFUNC#include <sys/stat.h>#endif ULTRIXFUNC#include <netinet/in.h>#include <stdio.h>#include <syslog.h>#include <arpa/nameser.h>#include "ns.h"#include "db.h"extern struct timeval	tt;extern FILE *ddt;extern struct zoneinfo zones[];extern struct sockaddr_in from_addr;	/* Source addr of last packet */extern int needs_prime_cache;int	max_cache_ttl = (7*24*60*60);	/* ONE_WEEK maximum ttl */int	min_cache_ttl = (2*60);		/* 5 minute minimum ttl *//* * Update data base. Flags control the action. * Inverse query tables modified. */db_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 DEBUG	if (debug >= 3)		fprintf(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":"" );#endif	np = nlookup(name, &htp, &fname, newdp != NULL);	if (np == NULL || fname != name)		return (NONAME);        /* Reflect certain updates in hint cache also... */	/* Don't stick data we are authoritative for in hints. */        if (!(flags & DB_NOHINTS) && (odp != NULL) &&	    (odp->d_zone <= 0) && !(odp->d_flags & DB_F_HINT) &&            ((name[0] == '\0' && odp->d_type == T_NS) ||	     (odp->d_type == T_A)))        {		register struct databuf *dp;#ifdef DEBUG		if (debug >= 3)			fprintf(ddt,"db_update: hint '%s' %d\n",				name, odp->d_ttl);#endif#ifdef AUTHEN		dp = savedata(odp->d_class, odp->d_type, odp->d_ttl,			      odp->d_authen_type, odp->d_authen_ver,			      odp->d_data, odp->d_size);#else AUTHEN		dp = savedata(odp->d_class, odp->d_type, odp->d_ttl,			odp->d_data, odp->d_size);#endif AUTHEN		dp->d_zone = DB_Z_CACHE;		dp->d_flags = DB_F_HINT;		if (db_update(name, dp,dp, (flags|DB_NOHINTS), fcachetab) != OK) {#ifdef DEBUG					if (debug > 2)				fprintf(ddt, "db_update: hint %x freed\n", dp);#endif			(void) free((char *)dp);		}        }	if (odp != NULL) {		pdp = NULL;#ifdef ULTRIXFUNC		for (dp = ((flags & DB_LOADDB) ? np->n_loaddb : np->n_data);				dp != NULL; ) {#else ULTRIXFUNC		for (dp = np->n_data; dp != NULL; ) {#endif ULTRIXFUNC			if (!match(dp, odp->d_class, odp->d_type)) {				if ((dp->d_type == T_CNAME ||				    odp->d_type == T_CNAME) &&				    zones[odp->d_zone].z_type != Z_CACHE) {					syslog(LOG_ERR,				"%s has CNAME and other data (illegal)\n",					    name);#ifdef DEBUG					if (debug)					    fprintf(ddt,				"db_update: %s: CNAME and more (%d, %d)\n",						name, odp->d_type, dp->d_type);#endif				}				goto skip;			}#ifdef DEBUG			if (debug >= 5)				fprintf(ddt,"db_update: flags = %#x, sizes = %d, %d (%d)\n",				    flags, odp->d_size, dp->d_size,				    db_cmp(dp, odp));#endif			if (flags & DB_NOTAUTH && dp->d_zone) {#ifdef DEBUG				if (debug)					fprintf(ddt,					"%s attempted update to auth zone %d '%s'\n",				    inet_ntoa(from_addr.sin_addr),				    dp->d_zone, zones[dp->d_zone].z_origin);#endif				return (AUTH);			}			if ((flags & DB_NODATA) && !db_cmp(dp, odp)) {				/* refresh ttl if cache entry */				if (dp->d_zone == 0) {					fixttl(odp);					if (odp->d_ttl > dp->d_ttl)						dp->d_ttl = odp->d_ttl;#ifdef DEBUG				        if (debug >= 3)				        fprintf(ddt,"db_update: new ttl %d, +%d\n",				                dp->d_ttl, dp->d_ttl - tt.tv_sec);#endif				}				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)#ifdef ULTRIXFUNC				dp = rm_datum(((flags & DB_LOADDB) ? 1 : 0),						dp, np, pdp);#else ULTRIXFUNC				dp = rm_datum(dp, np, pdp);#endif ULTRIXFUNC			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);#ifdef DEBUG        if (debug >= 3)	        fprintf(ddt,"db_update: adding%s %x\n",			(newdp->d_flags&DB_F_HINT) ? " hint":"", newdp);#endif	if (!(newdp->d_flags & DB_F_HINT))		addinv(np, newdp);	/* modify inverse query tables */	/* Add to end of list, generally preserving order */	newdp->d_next = NULL;#ifdef ULTRIXFUNC	if ((dp = ((flags & DB_LOADDB) ? np->n_loaddb : np->n_data)) == NULL) {		if(flags & DB_LOADDB)			np->n_loaddb = newdp;		else			np->n_data = newdp;#else ULTRIXFUNC	if ((dp = np->n_data) == NULL)  {		np->n_data = newdp;#endif ULTRIXFUNC		return (OK);	}	/* XXX: need to check for duplicate WKS records and flag error */	while (dp->d_next != NULL) {		if ((flags & DB_NODATA) && (dp->d_type == newdp->d_type) && (dp->d_class == newdp->d_class) && !db_cmp(dp, newdp))			return (DATAEXISTS);		dp = dp->d_next;	}	if ((flags & DB_NODATA) && (dp->d_type == newdp->d_type) && (dp->d_class == newdp->d_class) && !db_cmp(dp, newdp))		return (DATAEXISTS);	dp->d_next = newdp;	return (OK);}fixttl(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;}struct invbuf *invtab[INVHASHSZ];	/* Inverse query hash table *//* * Add data 'dp' to inverse query tables for name 'np'. */addinv(np, dp)	struct namebuf *np;	struct databuf *dp;{	register struct invbuf *ip;	register int hval, i;	switch (dp->d_type) {	case T_A:	case T_UID:	case T_GID:		break;	default:		return;	}	hval = dhash(dp->d_data, dp->d_size);	for (ip = invtab[hval]; ip != NULL; ip = ip->i_next)		for (i = 0; i < INVBLKSZ; i++)			if (ip->i_dname[i] == NULL) {				ip->i_dname[i] = np;				return;			}	ip = saveinv();	ip->i_next = invtab[hval];	invtab[hval] = ip;	ip->i_dname[0] = np;}/* * Remove data 'odp' from inverse query table. */rminv(flag, odp)	int flag;	struct databuf *odp;{	register struct invbuf *ip;	register struct databuf *dp;	struct namebuf *np;	register int i;	for (ip = invtab[dhash(odp->d_data, odp->d_size)]; ip != NULL;	    ip = ip->i_next) {		for (i = 0; i < INVBLKSZ; i++) {			if ((np = ip->i_dname[i]) == NULL)				break;#ifdef ULTRIXFUNC			for (dp = (flag ? np->n_loaddb : np->n_data);					dp != NULL; dp = dp->d_next) {#else ULTRIXFUNC			for (dp = np->n_data; dp != NULL; dp = dp->d_next) {#endif ULTRIXFUNC				if (!match(dp, odp->d_class, odp->d_type))					continue;				if (db_cmp(dp, odp))					continue;				while (i < INVBLKSZ-1) {					ip->i_dname[i] = ip->i_dname[i+1];					i++;				}				ip->i_dname[i] = NULL;				return;			}		}	}}/* * Compute hash value from data. */dhash(dp, dlen)	char *dp;	int dlen;{	register char *cp;	register unsigned hval;	register int n;	n = dlen;	if (n > 8)		n = 8;	hval = 0;	for (cp = dp; --n >= 0; ) {		hval <<= 1;		hval += *cp++;	}	return (hval % INVHASHSZ);}/* * Compare data sections from databufs for equivalence.  Must be case * insensitive for some domain names.  We assume that they are the * same type when they are passed.  Return 0 if equivalent, nonzero * otherwise. */db_cmp(dp1, dp2)	register struct databuf *dp1, *dp2;{	register char *cp1, *cp2;	int len;	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 */	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 ALLOW_T_UNSPEC		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(dp1->d_data, dp2->d_data));	case T_HINFO:		cp1 = dp1->d_data;		cp2 = dp2->d_data;		len = *cp1;		if (strncasecmp(++cp1, ++cp2, len))			return(1);		cp1 += len;		cp2 += len;		len = *cp1;		return(strncasecmp(++cp1, ++cp2, len));	case T_SOA:	case T_MINFO:		if (strcasecmp(dp1->d_data, dp2->d_data))			return(1);		cp1 = dp1->d_data + strlen(dp1->d_data) + 1;		cp2 = dp2->d_data + strlen(dp2->d_data) + 1;		if (dp1->d_type != T_SOA)			return(strcasecmp(cp1, cp2));		if (strcasecmp(cp1, cp2))			return(1);		cp1 += strlen(cp1) + 1;		cp2 += strlen(cp2) + 1;		return(bcmp(cp1, cp2, sizeof(u_long) * 5));		case T_MX:		cp1 = dp1->d_data;		cp2 = dp2->d_data;		if (*cp1++ != *cp2++ || *cp1++ != *cp2++)	/* cmp prio */			return(1);		return(strcasecmp(cp1, 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 + =
减小字号Ctrl + -
显示快捷键?