dispatch.c revision bbf667382840b943a639f2bd09fc3abd52fe9b7a
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * Copyright (C) 1999, 2000 Internet Software Consortium.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * Permission to use, copy, modify, and distribute this software for any
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * purpose with or without fee is hereby granted, provided that the above
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * copyright notice and this permission notice appear in all copies.
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley /* Unlocked. */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley unsigned int magic;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley /* Locked by "lock". */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley unsigned int state;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#define MGR_IS_SHUTTINGDOWN(l) (((l)->state & MGR_SHUTTINGDOWN) != 0)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#define IS_PRIVATE(d) (((d)->attributes & DNS_DISPATCHATTR_PRIVATE) != 0)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley unsigned int magic;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley unsigned int bucket;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley /* Unlocked. */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley isc_socket_t *socket; /* isc socket attached to */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley unsigned int buffersize; /* size of each buffer */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley /* Locked by mgr->lock. */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley unsigned int attributes;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley /* Locked by "lock". */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley unsigned int flags;
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley isc_mempool_t *epool; /* memory pool for events */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley isc_mempool_t *bpool; /* memory pool for buffers */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley isc_mempool_t *rpool; /* memory pool request/reply */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley dns_dispatchevent_t *failsafe_ev; /* failsafe cancel event */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley unsigned int recvs; /* recv() calls outstanding */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley unsigned int recvs_wanted; /* recv() calls wanted */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley unsigned int requests; /* how many requests we have */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley ISC_LIST(dns_dispentry_t) rq_handlers; /* request handler list */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley ISC_LIST(dns_dispatchevent_t) rq_events; /* holder for rq events */
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley dns_dispatchmethods_t methods; /* methods to use */
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley unsigned int qid_increment; /* id increment on collision */
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley dns_displist_t *qid_table; /* the table itself */
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#define REQUEST_MAGIC ISC_MAGIC('D', 'r', 'q', 's')
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#define VALID_REQUEST(e) ISC_MAGIC_VALID((e), REQUEST_MAGIC)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#define RESPONSE_MAGIC ISC_MAGIC('D', 'r', 's', 'p')
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#define VALID_RESPONSE(e) ISC_MAGIC_VALID((e), RESPONSE_MAGIC)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#define DISPATCH_MAGIC ISC_MAGIC('D', 'i', 's', 'p')
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#define VALID_DISPATCH(e) ISC_MAGIC_VALID((e), DISPATCH_MAGIC)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#define DNS_DISPATCHMGR_MAGIC ISC_MAGIC('D', 'M', 'g', 'r')
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley#define VALID_DISPATCHMGR(e) ISC_MAGIC_VALID((e), DNS_DISPATCHMGR_MAGIC)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic dns_dispentry_t *bucket_search(dns_dispatch_t *, isc_sockaddr_t *,
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley dns_messageid_t, unsigned int);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic void udp_recv(isc_task_t *, isc_event_t *);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic void tcp_recv(isc_task_t *, isc_event_t *);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic isc_uint32_t dns_randomid(dns_dispatch_t *);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic isc_uint32_t dns_hash(dns_dispatch_t *, isc_sockaddr_t *, isc_uint32_t);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic void free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic void *allocate_buffer(dns_dispatch_t *disp, unsigned int len);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic inline void free_event(dns_dispatch_t *disp, dns_dispatchevent_t *ev);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic inline dns_dispatchevent_t *allocate_event(dns_dispatch_t *disp);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic void do_next_request(dns_dispatch_t *disp, dns_dispentry_t *resp);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic void do_next_response(dns_dispatch_t *disp, dns_dispentry_t *resp);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic void do_cancel(dns_dispatch_t *disp, dns_dispentry_t *resp);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic dns_dispentry_t *linear_first(dns_dispatch_t *disp);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleystatic dns_dispentry_t *linear_next(dns_dispatch_t *disp,
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley DNS_LOGCATEGORY_DISPATCH, DNS_LOGMODULE_DISPATCH, \
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley isc_logcategory_t *category, isc_logmodule_t *module, int level,
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley const char *fmt, ...)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halleyrequest_log(dns_dispatch_t *disp, dns_dispentry_t *resp,
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley isc_logcategory_t *category, isc_logmodule_t *module, int level,
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley const char *fmt, ...)
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley isc_sockaddr_format(&resp->host, peerbuf, sizeof peerbuf);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley REQUIRE(VALID_REQUEST(resp) || VALID_RESPONSE(resp));
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley lfsr->count = (random() & 0x1f) + 32; /* From 32 to 63 states */
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * Return an unpredictable message ID.
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley id = isc_lfsr_generate32(&disp->qid_lfsr1, &disp->qid_lfsr2);
4e142a5bccd2944174ad9ae58d86cf03e170054dBob Halley * Return a hash of the destination and message id.
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halleydns_hash(dns_dispatch_t *disp, isc_sockaddr_t *dest, isc_uint32_t id) {
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley unsigned int ret;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley ret ^= (id & 0x0000ffff); /* important to mask off garbage bits */
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley unsigned int bucket;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halleylinear_next(dns_dispatch_t *disp, dns_dispentry_t *resp) {
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley unsigned int bucket;
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * Called when refcount reaches 0 (and safe to destroy).
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * The dispatch lock must NOT be locked, and the manager lock MUST be
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley "shutting down; detaching from sock %p, task %p",
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley * Final cleanup of packets on the request list.
948eabe2a254a8a278ef6325f3790e75329ee656Bob Halley free_buffer(disp, ev->buffer.base, ev->buffer.length);
static dns_dispentry_t *
unsigned int bucket)
return (res);
return (NULL);
switch (socktype) {
case isc_sockettype_tcp:
case isc_sockettype_udp:
INSIST(0);
void *temp;
return (temp);
static inline dns_dispatchevent_t *
return (ev);
unsigned int flags;
unsigned int bucket;
if (killit)
goto restart;
goto restart;
goto restart;
goto restart;
goto restart;
if (queue_request) {
} else if (queue_response) {
unsigned int flags;
unsigned int bucket;
case ISC_R_SUCCESS:
case ISC_R_EOF:
case ISC_R_CANCELED:
if (killit)
goto restart;
goto restart;
goto restart;
goto restart;
goto restart;
if (queue_request) {
} else if (queue_response) {
unsigned int wanted;
if (wanted == 0)
switch (socktype) {
case isc_sockettype_udp:
case isc_sockettype_tcp:
disp);
static isc_boolean_t
return (ISC_FALSE);
return (ISC_FALSE);
return (ISC_TRUE);
return (ISC_R_NOMEMORY);
return (result);
return (ISC_R_SUCCESS);
if (killit)
static isc_boolean_t
return (ISC_TRUE);
if (port == 0)
static isc_boolean_t
return (ISC_TRUE);
return (ISC_TRUE);
goto out;
out:
return (result);
return (res);
return (ISC_R_NOMEMORY);
goto out1;
for (i = 0 ; i < buckets ; i++)
goto out2;
goto out3;
goto out4;
goto out5;
goto out6;
return (ISC_R_SUCCESS);
out6:
out5:
out4:
out3:
out2:
out1:
return (res);
if (killit)
if (killit)
unsigned int bucket;
return (ISC_R_SHUTTINGDOWN);
return (ISC_R_QUOTA);
if (!ok) {
return (ISC_R_NOMORE);
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
unsigned int bucket;
if (killit)
return (ISC_R_SHUTTINGDOWN);
return (ISC_R_QUOTA);
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
if (killit)
if (response)