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

📄 dispatch.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003  Internet Software Consortium. * * 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. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS.  IN NO EVENT SHALL ISC 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. *//* $Id: dispatch.c,v 1.101.2.6.2.10 2004/09/01 04:27:41 marka Exp $ */#include <config.h>#include <stdlib.h>#include <isc/entropy.h>#include <isc/lfsr.h>#include <isc/mem.h>#include <isc/mutex.h>#include <isc/print.h>#include <isc/string.h>#include <isc/task.h>#include <isc/util.h>#include <dns/acl.h>#include <dns/dispatch.h>#include <dns/events.h>#include <dns/log.h>#include <dns/message.h>#include <dns/portlist.h>#include <dns/tcpmsg.h>#include <dns/types.h>typedef ISC_LIST(dns_dispentry_t)	dns_displist_t;typedef struct dns_qid {	unsigned int	magic;	unsigned int	qid_nbuckets;	/* hash table size */	unsigned int	qid_increment;	/* id increment on collision */	isc_mutex_t	lock;	isc_lfsr_t	qid_lfsr1;	/* state generator info */	isc_lfsr_t	qid_lfsr2;	/* state generator info */	dns_displist_t	*qid_table;	/* the table itself */} dns_qid_t;struct dns_dispatchmgr {	/* Unlocked. */	unsigned int			magic;	isc_mem_t		       *mctx;	dns_acl_t		       *blackhole;	dns_portlist_t		       *portlist;	/* Locked by "lock". */	isc_mutex_t			lock;	unsigned int			state;	ISC_LIST(dns_dispatch_t)	list;	/* locked by buffer lock */	dns_qid_t			*qid;	isc_mutex_t			buffer_lock;	unsigned int			buffers;    /* allocated buffers */	unsigned int			buffersize; /* size of each buffer */	unsigned int			maxbuffers; /* max buffers */	/* Locked internally. */	isc_mutex_t			pool_lock;	isc_mempool_t		       *epool;	/* memory pool for events */	isc_mempool_t		       *rpool;	/* memory pool for replies */	isc_mempool_t		       *dpool;  /* dispatch allocations */	isc_mempool_t		       *bpool;	/* memory pool for buffers */	isc_entropy_t		       *entropy; /* entropy source */};#define MGR_SHUTTINGDOWN		0x00000001U#define MGR_IS_SHUTTINGDOWN(l)	(((l)->state & MGR_SHUTTINGDOWN) != 0)#define IS_PRIVATE(d)	(((d)->attributes & DNS_DISPATCHATTR_PRIVATE) != 0)struct dns_dispentry {	unsigned int			magic;	dns_dispatch_t		       *disp;	dns_messageid_t			id;	unsigned int			bucket;	isc_sockaddr_t			host;	isc_task_t		       *task;	isc_taskaction_t		action;	void			       *arg;	isc_boolean_t			item_out;	ISC_LIST(dns_dispatchevent_t)	items;	ISC_LINK(dns_dispentry_t)	link;};#define INVALID_BUCKET		(0xffffdead)struct dns_dispatch {	/* Unlocked. */	unsigned int		magic;		/* magic */	dns_dispatchmgr_t      *mgr;		/* dispatch manager */	isc_task_t	       *task;		/* internal task */	isc_socket_t	       *socket;		/* isc socket attached to */	isc_sockaddr_t		local;		/* local address */	unsigned int		maxrequests;	/* max requests */	isc_event_t	       *ctlevent;	/* Locked by mgr->lock. */	ISC_LINK(dns_dispatch_t) link;	/* Locked by "lock". */	isc_mutex_t		lock;		/* locks all below */	isc_sockettype_t	socktype;	unsigned int		attributes;	unsigned int		refcount;	/* number of users */	dns_dispatchevent_t    *failsafe_ev;	/* failsafe cancel event */	unsigned int		shutting_down : 1,				shutdown_out : 1,				connected : 1,				tcpmsg_valid : 1,				recv_pending : 1; /* is a recv() pending? */	isc_result_t		shutdown_why;	unsigned int		requests;	/* how many requests we have */	unsigned int		tcpbuffers;	/* allocated buffers */	dns_tcpmsg_t		tcpmsg;		/* for tcp streams */	dns_qid_t		*qid;};#define QID_MAGIC		ISC_MAGIC('Q', 'i', 'd', ' ')#define VALID_QID(e)		ISC_MAGIC_VALID((e), QID_MAGIC)#define RESPONSE_MAGIC		ISC_MAGIC('D', 'r', 's', 'p')#define VALID_RESPONSE(e)	ISC_MAGIC_VALID((e), RESPONSE_MAGIC)#define DISPATCH_MAGIC		ISC_MAGIC('D', 'i', 's', 'p')#define VALID_DISPATCH(e)	ISC_MAGIC_VALID((e), DISPATCH_MAGIC)#define DNS_DISPATCHMGR_MAGIC	ISC_MAGIC('D', 'M', 'g', 'r')#define VALID_DISPATCHMGR(e)	ISC_MAGIC_VALID((e), DNS_DISPATCHMGR_MAGIC)#define DNS_QID(disp) ((disp)->socktype == isc_sockettype_tcp) ? \		       (disp)->qid : (disp)->mgr->qid/* * Statics. */static dns_dispentry_t *bucket_search(dns_qid_t *, isc_sockaddr_t *,				      dns_messageid_t, unsigned int);static isc_boolean_t destroy_disp_ok(dns_dispatch_t *);static void destroy_disp(isc_task_t *task, isc_event_t *event);static void udp_recv(isc_task_t *, isc_event_t *);static void tcp_recv(isc_task_t *, isc_event_t *);static void startrecv(dns_dispatch_t *);static dns_messageid_t dns_randomid(dns_qid_t *);static isc_uint32_t dns_hash(dns_qid_t *, isc_sockaddr_t *, dns_messageid_t);static void free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len);static void *allocate_udp_buffer(dns_dispatch_t *disp);static inline void free_event(dns_dispatch_t *disp, dns_dispatchevent_t *ev);static inline dns_dispatchevent_t *allocate_event(dns_dispatch_t *disp);static void do_cancel(dns_dispatch_t *disp);static dns_dispentry_t *linear_first(dns_qid_t *disp);static dns_dispentry_t *linear_next(dns_qid_t *disp,				    dns_dispentry_t *resp);static void dispatch_free(dns_dispatch_t **dispp);static isc_result_t dispatch_createudp(dns_dispatchmgr_t *mgr,				       isc_socketmgr_t *sockmgr,				       isc_taskmgr_t *taskmgr,				       isc_sockaddr_t *localaddr,				       unsigned int maxrequests,				       unsigned int attributes,				       dns_dispatch_t **dispp);static isc_boolean_t destroy_mgr_ok(dns_dispatchmgr_t *mgr);static void destroy_mgr(dns_dispatchmgr_t **mgrp);static isc_result_t qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets,				 unsigned int increment, dns_qid_t **qidp);static void qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp);#define LVL(x) ISC_LOG_DEBUG(x)static voidmgr_log(dns_dispatchmgr_t *mgr, int level, const char *fmt, ...)     ISC_FORMAT_PRINTF(3, 4);static voidmgr_log(dns_dispatchmgr_t *mgr, int level, const char *fmt, ...) {	char msgbuf[2048];	va_list ap;	if (! isc_log_wouldlog(dns_lctx, level))		return;	va_start(ap, fmt);	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);	va_end(ap);	isc_log_write(dns_lctx,		      DNS_LOGCATEGORY_DISPATCH, DNS_LOGMODULE_DISPATCH,		      level, "dispatchmgr %p: %s", mgr, msgbuf);}static voiddispatch_log(dns_dispatch_t *disp, int level, const char *fmt, ...)     ISC_FORMAT_PRINTF(3, 4);static voiddispatch_log(dns_dispatch_t *disp, int level, const char *fmt, ...) {	char msgbuf[2048];	va_list ap;	if (! isc_log_wouldlog(dns_lctx, level))		return;	va_start(ap, fmt);	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);	va_end(ap);	isc_log_write(dns_lctx,		      DNS_LOGCATEGORY_DISPATCH, DNS_LOGMODULE_DISPATCH,		      level, "dispatch %p: %s", disp, msgbuf);}static voidrequest_log(dns_dispatch_t *disp, dns_dispentry_t *resp,	    int level, const char *fmt, ...)     ISC_FORMAT_PRINTF(4, 5);static voidrequest_log(dns_dispatch_t *disp, dns_dispentry_t *resp,	    int level, const char *fmt, ...){	char msgbuf[2048];	char peerbuf[256];	va_list ap;	if (! isc_log_wouldlog(dns_lctx, level))		return;	va_start(ap, fmt);	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);	va_end(ap);	if (VALID_RESPONSE(resp)) {		isc_sockaddr_format(&resp->host, peerbuf, sizeof(peerbuf));		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DISPATCH,			      DNS_LOGMODULE_DISPATCH, level,			      "dispatch %p response %p %s: %s", disp, resp,			      peerbuf, msgbuf);	} else {		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DISPATCH,			      DNS_LOGMODULE_DISPATCH, level,			      "dispatch %p req/resp %p: %s", disp, resp,			      msgbuf);	}}static voidreseed_lfsr(isc_lfsr_t *lfsr, void *arg){	dns_dispatchmgr_t *mgr = arg;	isc_result_t result;	isc_uint32_t val;	REQUIRE(VALID_DISPATCHMGR(mgr));	if (mgr->entropy != NULL) {		result = isc_entropy_getdata(mgr->entropy, &val, sizeof(val),					     NULL, 0);		INSIST(result == ISC_R_SUCCESS);		lfsr->count = (val & 0x1f) + 32;		lfsr->state = val;		return;	}	lfsr->count = (random() & 0x1f) + 32;	/* From 32 to 63 states */	lfsr->state = random();}/* * Return an unpredictable message ID. */static dns_messageid_tdns_randomid(dns_qid_t *qid) {	isc_uint32_t id;	id = isc_lfsr_generate32(&qid->qid_lfsr1, &qid->qid_lfsr2);	return (dns_messageid_t)(id & 0xFFFF);}/* * Return a hash of the destination and message id. */static isc_uint32_tdns_hash(dns_qid_t *qid, isc_sockaddr_t *dest, dns_messageid_t id) {	unsigned int ret;	ret = isc_sockaddr_hash(dest, ISC_TRUE);	ret ^= id;	ret %= qid->qid_nbuckets;	INSIST(ret < qid->qid_nbuckets);	return (ret);}/* * Find the first entry in 'qid'.  Returns NULL if there are no entries. */static dns_dispentry_t *linear_first(dns_qid_t *qid) {	dns_dispentry_t *ret;	unsigned int bucket;	bucket = 0;	while (bucket < qid->qid_nbuckets) {		ret = ISC_LIST_HEAD(qid->qid_table[bucket]);		if (ret != NULL)			return (ret);		bucket++;	}	return (NULL);}/* * Find the next entry after 'resp' in 'qid'.  Return NULL if there are * no more entries. */static dns_dispentry_t *linear_next(dns_qid_t *qid, dns_dispentry_t *resp) {	dns_dispentry_t *ret;	unsigned int bucket;	ret = ISC_LIST_NEXT(resp, link);	if (ret != NULL)		return (ret);	bucket = resp->bucket;	bucket++;	while (bucket < qid->qid_nbuckets) {		ret = ISC_LIST_HEAD(qid->qid_table[bucket]);		if (ret != NULL)			return (ret);		bucket++;	}	return (NULL);}/* * The dispatch must be locked. */static isc_boolean_tdestroy_disp_ok(dns_dispatch_t *disp){	if (disp->refcount != 0)		return (ISC_FALSE);	if (disp->recv_pending != 0)		return (ISC_FALSE);	if (disp->shutting_down == 0)		return (ISC_FALSE);	return (ISC_TRUE);}/* * Called when refcount reaches 0 (and safe to destroy). * * The dispatcher must not be locked. * The manager must be locked. */static voiddestroy_disp(isc_task_t *task, isc_event_t *event) {	dns_dispatch_t *disp;	dns_dispatchmgr_t *mgr;	isc_boolean_t killmgr;	INSIST(event->ev_type == DNS_EVENT_DISPATCHCONTROL);	UNUSED(task);	disp = event->ev_arg;	mgr = disp->mgr;	LOCK(&mgr->lock);	ISC_LIST_UNLINK(mgr->list, disp, link);	dispatch_log(disp, LVL(90),		     "shutting down; detaching from sock %p, task %p",		     disp->socket, disp->task);	isc_socket_detach(&disp->socket);	isc_task_detach(&disp->task);	isc_event_free(&event);	dispatch_free(&disp);	killmgr = destroy_mgr_ok(mgr);	UNLOCK(&mgr->lock);	if (killmgr)		destroy_mgr(&mgr);}/* * Find an entry for query ID 'id' and socket address 'dest' in 'qid'. * Return NULL if no such entry exists. */static dns_dispentry_t *bucket_search(dns_qid_t *qid, isc_sockaddr_t *dest, dns_messageid_t id,	      unsigned int bucket){	dns_dispentry_t *res;	REQUIRE(bucket < qid->qid_nbuckets);	res = ISC_LIST_HEAD(qid->qid_table[bucket]);	while (res != NULL) {		if ((res->id == id) && isc_sockaddr_equal(dest, &res->host))			return (res);		res = ISC_LIST_NEXT(res, link);	}	return (NULL);}static voidfree_buffer(dns_dispatch_t *disp, void *buf, unsigned int len) {	INSIST(buf != NULL && len != 0);	switch (disp->socktype) {	case isc_sockettype_tcp:		INSIST(disp->tcpbuffers > 0);		disp->tcpbuffers--;		isc_mem_put(disp->mgr->mctx, buf, len);		break;	case isc_sockettype_udp:		LOCK(&disp->mgr->buffer_lock);		INSIST(disp->mgr->buffers > 0);		INSIST(len == disp->mgr->buffersize);		disp->mgr->buffers--;		isc_mempool_put(disp->mgr->bpool, buf);		UNLOCK(&disp->mgr->buffer_lock);		break;	default:		INSIST(0);		break;	}}static void *allocate_udp_buffer(dns_dispatch_t *disp) {	void *temp;	LOCK(&disp->mgr->buffer_lock);	temp = isc_mempool_get(disp->mgr->bpool);	if (temp != NULL)		disp->mgr->buffers++;	UNLOCK(&disp->mgr->buffer_lock);	return (temp);}static inline voidfree_event(dns_dispatch_t *disp, dns_dispatchevent_t *ev) {	if (disp->failsafe_ev == ev) {		INSIST(disp->shutdown_out == 1);		disp->shutdown_out = 0;		return;	}	isc_mempool_put(disp->mgr->epool, ev);}static inline dns_dispatchevent_t *allocate_event(dns_dispatch_t *disp) {	dns_dispatchevent_t *ev;	ev = isc_mempool_get(disp->mgr->epool);	if (ev == NULL)		return (NULL);	ISC_EVENT_INIT(ev, sizeof(*ev), 0, NULL, 0,		       NULL, NULL, NULL, NULL, NULL);	return (ev);}/* * General flow: * * If I/O result == CANCELED or error, free the buffer. * * If query, free the buffer, restart. * * If response: *	Allocate event, fill in details. *		If cannot allocate, free buffer, restart. *	find target.  If not found, free buffer, restart. *	if event queue is not empty, queue.  else, send. *	restart. */static voidudp_recv(isc_task_t *task, isc_event_t *ev_in) {	isc_socketevent_t *ev = (isc_socketevent_t *)ev_in;	dns_dispatch_t *disp = ev_in->ev_arg;	dns_messageid_t id;	isc_result_t dres;	isc_buffer_t source;	unsigned int flags;	dns_dispentry_t *resp;	dns_dispatchevent_t *rev;	unsigned int bucket;	isc_boolean_t killit;	isc_boolean_t queue_response;	dns_dispatchmgr_t *mgr;	dns_qid_t *qid;	isc_netaddr_t netaddr;	int match;	UNUSED(task);	LOCK(&disp->lock);	mgr = disp->mgr;	qid = mgr->qid;	dispatch_log(disp, LVL(90),		     "got packet: requests %d, buffers %d, recvs %d",		     disp->requests, disp->mgr->buffers, disp->recv_pending);	if (ev->ev_type == ISC_SOCKEVENT_RECVDONE) {		/*		 * Unless the receive event was imported from a listening		 * interface, in which case the event type is		 * DNS_EVENT_IMPORTRECVDONE, receive operation must be pending.		 */		INSIST(disp->recv_pending != 0);

⌨️ 快捷键说明

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