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

📄 cache.c

📁 此dns服务器是在mydns基础上改写
💻 C
📖 第 1 页 / 共 2 页
字号:
		for (n = ThisCache->nodes[ct]; n; n = tmp)		{			tmp = n->next_node;			if (n->zone == zone)				cache_free_node(ThisCache, ct, n);		}}/*--- cache_purge_zone() ------------------------------------------------------------------------*//**************************************************************************************************	CACHE_HASH	Returns hash value.**************************************************************************************************/static inline uint32_tcache_hash(CACHE *ThisCache, uint32_t initval, void *buf, register size_t buflen)#if (HASH_TYPE == ORIGINAL_HASH){	register uint32_t	hash;	register unsigned char *p;	/* Generate hash value */	for (hash = initval, p = (unsigned char *)buf; p < (unsigned char *)(buf + buflen); p++)	{		register int tmp;		hash = (hash << 4) + (*p);		if ((tmp = (hash & 0xf0000000)))		{			hash = hash ^ (tmp >> 24);			hash = hash ^ tmp;		}	}	return (hash % ThisCache->slots);}#elif (HASH_TYPE == ADDITIVE_HASH){	register uint32_t	hash;	register unsigned char *p;	for (hash = initval, p = (unsigned char *)buf; p < (unsigned char *)(buf + buflen); p++)		hash += *p;	return (hash % ThisCache->slots);}#elif (HASH_TYPE == ROTATING_HASH){	register uint32_t	hash;	register unsigned char *p;	for (hash = initval, p = (unsigned char *)buf; p < (unsigned char *)(buf + buflen); p++)		hash = (hash << 4) ^ (hash >> 28) ^ (*p);	return ((hash ^ (hash>>10) ^ (hash>>20)) & ThisCache->mask);}#elif (HASH_TYPE == FNV_HASH){	register uint32_t	hash = FNV_32_INIT;	unsigned char *bp = (unsigned char *)buf;	unsigned char *be = bp + buflen;	while (bp < be)	{		hash *= FNV_32_PRIME;		hash ^= (uint32_t)*bp++;	}	hash *= FNV_32_PRIME;	hash ^= (uint32_t)initval;	if (ThisCache->bits == 16)		return ((hash >> 16) ^ (hash & (((uint32_t)1 << 16) - 1)));	else		return (hash % ThisCache->slots);}#else#	error Hash method unknown or unspecified#endif/*--- cache_hash() ------------------------------------------------------------------------------*//**************************************************************************************************	ZONE_CACHE_FIND	Returns the SOA/RR from cache (or via the database) or NULL if `name' doesn't match.**************************************************************************************************/void *zone_cache_find(TASK *t, uint32_t zone, char *origin, dns_qtype_t type,					 char *name, size_t namelen, int *errflag, MYDNS_SOA *parent){	register uint32_t	hash = 0;	register CNODE		*n;	MYDNS_SOA			*soa = NULL;	MYDNS_RR				*rr = NULL;	CACHE					*C;										/* Which cache to use when inserting */	SQL_RES				*res;	SQL_ROW				row;#if DEBUG_ENABLED && DEBUG_CACHE	Debug("%s: zone_cache_find(zone=%u, origin='%s', name='%s', qtype=%s)",			desctask(t), zone, origin, name, mydns_qtype_str(type));#endif	*errflag = 0;	if (!name)		return (NULL);	/*add by zyl 20080331 --begin*/   char*  myip = (char*)malloc(16);   memset(myip,0,sizeof(myip));   iplong_to_ipchs(myip, 16, t->addr4.sin_addr.s_addr);   /*add by zyl 20080331 --end*/   /*add by zyl 20080408 --begin*/   int telecom_operator = 0;	int ipint = 0;	ipchs_to_ipuint32(&ipint,myip);	if(ipint)   	get_telecom_operator(&telecom_operator,ipint);   /*add by zyl 20080408 --end*/	free(myip);	if (ZoneCache)	{		hash = cache_hash(ZoneCache, zone + type, name, namelen);#if USE_NEGATIVE_CACHE		/* Check negative reply cache */		if (NegativeCache)		{			NegativeCache->questions++;			/* Look at the appropriate node.  Descend list and find match. */			for (n = NegativeCache->nodes[hash]; n; n = n->next_node)				if ((n->namelen == namelen) && (n->zone == zone) && (n->type == type))				{					if (!n->name)						Errx(_("negative cache node %p at hash %u has NULL name"), n, hash);					if (!memcmp(n->name, name, namelen))					{						/* Is the node expired? */						if (n->expire && (current_time > n->expire))						{							cache_free_node(NegativeCache, hash, n);							break;						}						NegativeCache->hits++;						/* Found in cache; move to head of usefulness list */						mrulist_del(NegativeCache, n);						mrulist_add(NegativeCache, n);						return NULL;					}				}			NegativeCache->misses++;		}#endif		/* Not in negative cache, so look in zone cache */		ZoneCache->questions++;		/* Look at the appropriate node.  Descend list and find match. */		for (n = ZoneCache->nodes[hash]; n; n = n->next_node)		{			if ((n->namelen == namelen) && (n->zone == zone) && (n->type == type))			{				if (!n->name)					Errx(_("zone cache node %p at hash %u has NULL name"), n, hash);				if (!memcmp(n->name, name, namelen))				{					/* Is the node expired? */					if (n->expire && (current_time > n->expire))					{						cache_free_node(ZoneCache, hash, n);						break;					}					ZoneCache->hits++;					/* Found in cache; move to head of usefulness list */					mrulist_del(ZoneCache, n);					mrulist_add(ZoneCache, n);					if (type == DNS_QTYPE_SOA)						return (n->data ? mydns_soa_dup(n->data, 1) : NULL);					else						return (n->data ? mydns_rr_dup(n->data, 1) : NULL);				}			}		}	}	/* Result not found in cache; Get answer from database */	if (type == DNS_QTYPE_SOA)	{		/* Try to load from database */#if DEBUG_ENABLED && DEBUG_SQL_QUERIES		Debug("%s: SQL query: table \"%s\", origin=\"%s\"", desctask(t), mydns_soa_table_name, name);#endif		if (mydns_soa_load(sql, &soa, name,telecom_operator) != 0)				//modi by zyl 080408		{			sql_reopen();			if (mydns_soa_load(sql, &soa, name,telecom_operator) != 0)			//modi by zyl 080408			{				WarnSQL(sql, "%s: %s", name, _("error loading SOA"));				*errflag = 1;				return (NULL);			}		}			/*add by zyl 20080403 __begin*/		/*select the most matched soa*/		//select_matched_zone(sql,&soa,name,origin,myip);				/*add by zyl 20080403 __end*/#ifdef DN_COLUMN_NAMES		if (soa && dn_default_ns)			strncpy(soa->ns, dn_default_ns, sizeof(soa->ns)-1);#endif#if USE_NEGATIVE_CACHE		if (!(C = soa ? ZoneCache : NegativeCache))#else		if (!(soa && (C = ZoneCache)))#endif			return ((void *)soa);		/* Don't cache if TTL is 0 */		if (soa && !soa->ttl)			return ((void *)soa);	}	else	{#if DEBUG_ENABLED && DEBUG_SQL_QUERIES		Debug("%s: SQL query: table \"%s\", zone=%u,type=\"%s\",name=\"%s\", requestor_ip_section=\"%s\"",				desctask(t), mydns_rr_table_name, zone, mydns_qtype_str(type), name,myip);#endif		if (mydns_rr_load(sql, &rr, zone, type, name, origin, myip) != 0)		{			sql_reopen();			if (mydns_rr_load(sql, &rr, zone, type, name, origin, myip) != 0)			{				WarnSQL(sql, _("error finding %s type resource records for name `%s' in zone %u"),						  mydns_qtype_str(type), name, zone);				sql_reopen();				*errflag = 1;				return (NULL);			}		}#ifdef DN_COLUMN_NAMES		/* DN database has no TTL - use parent's */		if (rr && parent && parent->ttl)			rr->ttl = parent->ttl;#endif#if USE_NEGATIVE_CACHE		if (!(C = rr ? ZoneCache : NegativeCache))#else		if (!(rr && (C = ZoneCache)))#endif			return ((void *)rr);		/* Don't cache if TTL of this RR (or the parent SOA) is 0 */		if ((rr && !rr->ttl) || (parent && !parent->ttl))			return ((void *)rr);	}	C->misses++;	/* If the cache is full, delete the least recently used node and add new node */	if (C->count >= C->limit)	{		if (C->mruTail)		{			C->removed++;			C->removed_secs += current_time - C->mruTail->insert_time;			cache_free_node(C, C->mruTail->hash, C->mruTail);		}		else			return (type == DNS_QTYPE_SOA ? (void *)soa : (void *)rr);	}	/* Add to cache */	C->in++;	if (!(n = calloc(1, sizeof(CNODE))))		Err(_("out of memory"));	n->hash = hash;	n->zone = zone;	n->type = type;	strncpy(n->name, name, sizeof(n->name)-1);	n->namelen = namelen;	n->insert_time = current_time;	if (type == DNS_QTYPE_SOA)	{		if (C == ZoneCache)			n->data = mydns_soa_dup(soa, 1);		if (soa && (soa->ttl < C->expire))			n->expire = current_time + soa->ttl;		else if (C->expire)			n->expire = current_time + C->expire;	}	else	{		if (C == ZoneCache)			n->data = mydns_rr_dup(rr, 1);		if (rr && (rr->ttl < C->expire))			n->expire = current_time + rr->ttl;		else if (C->expire)			n->expire = current_time + C->expire;	}	n->next_node = C->nodes[hash];#if DEBUG_ENABLED && DEBUG_CACHE	Debug("%s: Added to cache: zone=%u, type=%s, name='%s'", desctask(t), zone, mydns_qtype_str(type), name);#endif	/* Add node to cache */	C->nodes[hash] = n;	C->count++;	/* Add node to head of MRU list */	mrulist_add(C, n);	return (type == DNS_QTYPE_SOA ? (void *)soa : (void *)rr);}/*--- zone_cache_find() --------------------------------------------------------------------------*//**************************************************************************************************	REPLY_CACHE_FIND	Attempt to find the reply data whole in the cache.	Returns nonzero if found, 0 if not found.	If found, fills in t->reply and t->replylen.**************************************************************************************************/intreply_cache_find(TASK *t){	register uint32_t	hash;	register CNODE		*n;	register void		*p;#if DEBUG_ENABLED && DEBUG_CACHE	Debug("%s: reply_cache_find(qdlen=%d proto=%d)", desctask(t), t->qdlen, t->protocol);#endif	if (!ReplyCache || t->qdlen > DNS_MAXPACKETLEN_UDP)		return (0);#if STATUS_ENABLED	/* Status requests aren't cached */	if (t->qclass == DNS_CLASS_CHAOS)		return (0);#endif	hash = cache_hash(ReplyCache, t->qtype, t->qd, t->qdlen);	ReplyCache->questions++;	/* Look at the appropriate node.  Descend list and find match. */	for (n = ReplyCache->nodes[hash]; n; n = n->next_node)	{		if ((n->namelen == t->qdlen) && (n->type == t->qtype) && (n->protocol == t->protocol))		{			if (!n->name)				Errx(_("reply cache node %p at hash %u has NULL name"), n, hash);			if (!memcmp(n->name, t->qd, t->qdlen))			{				/* Is the node expired? */				if (n->expire && (current_time > n->expire))				{					cache_free_node(ReplyCache, hash, n);					break;				}				/* Found in cache; move to head of usefulness list */				mrulist_del(ReplyCache, n);				mrulist_add(ReplyCache, n);				/* Allocate space for reply data */				t->replylen = n->datalen - sizeof(DNS_HEADER) - sizeof(task_error_t);				if (!(t->reply = malloc(t->replylen)))					Err(_("out of memory"));				p = n->data;				/* Copy DNS header */				memcpy(&t->hdr, p, sizeof(DNS_HEADER));				p += sizeof(DNS_HEADER);				/* Copy reason */				memcpy(&t->reason, p, sizeof(task_error_t));				p += sizeof(task_error_t);				/* Copy reply data */				memcpy(t->reply, p, t->replylen);				/* Set count of records in each section */				p = t->reply + SIZE16 + SIZE16 + SIZE16;				DNS_GET16(t->an.size, p);				DNS_GET16(t->ns.size, p);				DNS_GET16(t->ar.size, p);				t->zone = n->zone;				t->reply_from_cache = 1;				ReplyCache->hits++;#if DEBUG_ENABLED && DEBUG_CACHE				Debug(_("%s: %d octet reply found in cache"), desctask(t), t->replylen);#endif				return (1);			}		}	}	ReplyCache->misses++;	return (0);}/*--- reply_cache_find() ------------------------------------------------------------------------*//**************************************************************************************************	ADD_REPLY_TO_CACHE	Adds the current reply to the reply cache.**************************************************************************************************/voidadd_reply_to_cache(TASK *t){	register uint32_t	hash;	register CNODE		*n;	register void		*p;#if DEBUG_ENABLED && DEBUG_CACHE	Debug("%s: add_reply_to_cache(qdlen=%d rcode=%s rd=%d proto=%d)", desctask(t),			t->qdlen, mydns_rcode_str(t->hdr.rcode), t->hdr.rd, t->protocol);#endif	if (!ReplyCache || t->qdlen > DNS_MAXPACKETLEN_UDP || t->hdr.rcode == DNS_RCODE_SERVFAIL)	{#if DEBUG_ENABLED && DEBUG_CACHE		Debug("reply should not be cached");#endif		return;	}	/* Don't cache replies from recursive forwarder */	if (t->forwarded)		return;#if STATUS_ENABLED	/* Don't cache status requests */	if (t->qclass == DNS_CLASS_CHAOS)		return;#endif	/* Don't cache negative replies if recursive forwarding is enabled */	if (forward_recursive && t->hdr.rcode != DNS_RCODE_NOERROR)		return;	hash = cache_hash(ReplyCache, t->qtype, t->qd, t->qdlen);	/* Look at the appropriate node.  Descend list and find match. */	for (n = ReplyCache->nodes[hash]; n; n = n->next_node)	{		if ((n->namelen == t->qdlen) && (n->type == t->qtype) && (n->protocol == t->protocol))		{			if (!n->name)				Errx(_("reply cache node %p at hash %u has NULL name"), n, hash);			if (!memcmp(n->name, t->qd, t->qdlen))			{				/* Is the node expired? */				if (n->expire && (current_time > n->expire))				{					cache_free_node(ReplyCache, hash, n);					break;				}				/* Found in cache; move to head of usefulness list */				mrulist_del(ReplyCache, n);				mrulist_add(ReplyCache, n);				return;			}		}	}	/* If the cache is full, delete the least recently used node and add new node */	if (ReplyCache->count >= ReplyCache->limit)	{		if (ReplyCache->mruTail)		{			ReplyCache->removed++;			ReplyCache->removed_secs += current_time - ReplyCache->mruTail->insert_time;			cache_free_node(ReplyCache, ReplyCache->mruTail->hash, ReplyCache->mruTail);		}		else			return;	}	/* Add to cache */	ReplyCache->in++;	if (!(n = calloc(1, sizeof(CNODE))))		Err(_("out of memory"));	n->hash = hash;	n->zone = t->zone;	n->type = t->qtype;	n->protocol = t->protocol;	memcpy(n->name, t->qd, t->qdlen);	n->namelen = t->qdlen;	/* The data is the DNS_HEADER, the reason, then the reply */	n->datalen = sizeof(DNS_HEADER) + sizeof(task_error_t) + t->replylen;	if (!(n->data = malloc(n->datalen)))		Err(_("out of memory"));	p = n->data;	/* Save DNS header */	memcpy(p, &t->hdr, sizeof(DNS_HEADER));	p += sizeof(DNS_HEADER);	/* Save reason for error, if any */	memcpy(p, &t->reason, sizeof(task_error_t));	p += sizeof(task_error_t);	/* Save reply data */	memcpy(p, t->reply, t->replylen);	n->insert_time = current_time;	if (ReplyCache->expire)		n->expire = current_time + ReplyCache->expire;	n->next_node = ReplyCache->nodes[hash];	/* Add node to cache */	ReplyCache->nodes[hash] = n;	ReplyCache->count++;	/* Add node to head of MRU list */	mrulist_add(ReplyCache, n);#if DEBUG_ENABLED && DEBUG_CACHE	Debug("%s: %s (qtype=%s qdlen=%d rd=%d proto=%d)", desctask(t), _("reply cached"),			mydns_qtype_str(t->qtype), t->qdlen, t->hdr.rd, t->protocol);#endif}/*--- add_reply_to_cache() ----------------------------------------------------------------------*//* vi:set ts=3: *//* NEED_PO */

⌨️ 快捷键说明

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