summaryrefslogtreecommitdiffstats
path: root/contrib/bind9/lib/isc
diff options
context:
space:
mode:
authorerwin <erwin@FreeBSD.org>2013-08-22 08:15:03 +0000
committererwin <erwin@FreeBSD.org>2013-08-22 08:15:03 +0000
commit6a288ef517fece2ca5a21d081efd7b4a81da0053 (patch)
tree37271fd86c9be9a6bab12a7aebd85ccfbb8a7b62 /contrib/bind9/lib/isc
parent0b46e38a09fbccfdfd7bca0f387c66b2c64fa5b6 (diff)
parentf32b4abce98c97ee6e51b7aa8f8fde6e4cab7f28 (diff)
downloadFreeBSD-src-6a288ef517fece2ca5a21d081efd7b4a81da0053.zip
FreeBSD-src-6a288ef517fece2ca5a21d081efd7b4a81da0053.tar.gz
Update Bind to 9.9.3-P2
Notable new features: * Elliptic Curve Digital Signature Algorithm keys and signatures in DNSSEC are now supported per RFC 6605. [RT #21918] * Introduces a new tool "dnssec-verify" that validates a signed zone, checking for the correctness of signatures and NSEC/NSEC3 chains. [RT #23673] * BIND now recognizes the TLSA resource record type, created to support IETF DANE (DNS-based Authentication of Named Entities) [RT #28989] * The new "inline-signing" option, in combination with the "auto-dnssec" option that was introduced in BIND 9.7, allows named to sign zones completely transparently. Approved by: delphij (mentor) MFC after: 3 days Sponsored by: DK Hostmaster A/S
Diffstat (limited to 'contrib/bind9/lib/isc')
-rw-r--r--contrib/bind9/lib/isc/Makefile.in4
-rw-r--r--contrib/bind9/lib/isc/api4
-rw-r--r--contrib/bind9/lib/isc/include/isc/heap.h4
-rw-r--r--contrib/bind9/lib/isc/include/isc/list.h15
-rw-r--r--contrib/bind9/lib/isc/include/isc/mem.h4
-rw-r--r--contrib/bind9/lib/isc/include/isc/namespace.h9
-rw-r--r--contrib/bind9/lib/isc/include/isc/pool.h149
-rw-r--r--contrib/bind9/lib/isc/include/isc/queue.h165
-rw-r--r--contrib/bind9/lib/isc/include/isc/radix.h38
-rw-r--r--contrib/bind9/lib/isc/include/isc/socket.h24
-rw-r--r--contrib/bind9/lib/isc/include/isc/task.h62
-rw-r--r--contrib/bind9/lib/isc/include/isc/taskpool.h13
-rw-r--r--contrib/bind9/lib/isc/log.c9
-rw-r--r--contrib/bind9/lib/isc/pool.c177
-rw-r--r--contrib/bind9/lib/isc/radix.c37
-rw-r--r--contrib/bind9/lib/isc/socket_api.c40
-rw-r--r--contrib/bind9/lib/isc/task.c273
-rw-r--r--contrib/bind9/lib/isc/task_api.c30
-rw-r--r--contrib/bind9/lib/isc/task_p.h10
-rw-r--r--contrib/bind9/lib/isc/taskpool.c13
-rw-r--r--contrib/bind9/lib/isc/unix/socket.c129
21 files changed, 1101 insertions, 108 deletions
diff --git a/contrib/bind9/lib/isc/Makefile.in b/contrib/bind9/lib/isc/Makefile.in
index 2fa5633..e68290c 100644
--- a/contrib/bind9/lib/isc/Makefile.in
+++ b/contrib/bind9/lib/isc/Makefile.in
@@ -58,7 +58,7 @@ OBJS = @ISC_EXTRA_OBJS@ \
httpd.@O@ inet_aton.@O@ iterated_hash.@O@ \
lex.@O@ lfsr.@O@ lib.@O@ log.@O@ \
md5.@O@ mem.@O@ mutexblock.@O@ \
- netaddr.@O@ netscope.@O@ ondestroy.@O@ \
+ netaddr.@O@ netscope.@O@ pool.@O@ ondestroy.@O@ \
parseint.@O@ portset.@O@ quota.@O@ radix.@O@ random.@O@ \
ratelimiter.@O@ refcount.@O@ region.@O@ regex.@O@ result.@O@ \
rwlock.@O@ \
@@ -75,7 +75,7 @@ SRCS = @ISC_EXTRA_SRCS@ \
httpd.c inet_aton.c iterated_hash.c \
lex.c lfsr.c lib.c log.c \
md5.c mem.c mutexblock.c \
- netaddr.c netscope.c ondestroy.c \
+ netaddr.c netscope.c pool.c ondestroy.c \
parseint.c portset.c quota.c radix.c random.c \
ratelimiter.c refcount.c region.c regex.c result.c rwlock.c \
serial.c sha1.c sha2.c sockaddr.c stats.c string.c strtoul.c \
diff --git a/contrib/bind9/lib/isc/api b/contrib/bind9/lib/isc/api
index c7d2813..48bc766 100644
--- a/contrib/bind9/lib/isc/api
+++ b/contrib/bind9/lib/isc/api
@@ -4,6 +4,6 @@
# 9.8: 80-89, 120-129
# 9.9: 90-109
# 9.9-sub: 130-139
-LIBINTERFACE = 87
+LIBINTERFACE = 95
LIBREVISION = 1
-LIBAGE = 3
+LIBAGE = 0
diff --git a/contrib/bind9/lib/isc/include/isc/heap.h b/contrib/bind9/lib/isc/include/isc/heap.h
index 77bf07c..0b3a53b 100644
--- a/contrib/bind9/lib/isc/include/isc/heap.h
+++ b/contrib/bind9/lib/isc/include/isc/heap.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009, 2012 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1997-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -60,6 +60,8 @@ isc_heap_create(isc_mem_t *mctx, isc_heapcompare_t compare,
* storage method. When the heap elements are deleted space is not freed
* but will be reused when new elements are inserted.
*
+ * Heap elements are indexed from 1.
+ *
* Requires:
*\li "mctx" is valid.
*\li "compare" is a function which takes two void * arguments and
diff --git a/contrib/bind9/lib/isc/include/isc/list.h b/contrib/bind9/lib/isc/include/isc/list.h
index 2b174ec..401bbdad 100644
--- a/contrib/bind9/lib/isc/include/isc/list.h
+++ b/contrib/bind9/lib/isc/include/isc/list.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2006, 2007, 2012, 2013 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2006, 2007, 2011-2013 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1997-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -171,6 +171,19 @@
(list2).tail = NULL; \
} while (0)
+#define ISC_LIST_PREPENDLIST(list1, list2, link) \
+ do { \
+ if (ISC_LIST_EMPTY(list1)) \
+ (list1) = (list2); \
+ else if (!ISC_LIST_EMPTY(list2)) { \
+ (list2).tail->link.next = (list1).head; \
+ (list1).head->link.prev = (list2).tail; \
+ (list1).head = (list2).head; \
+ } \
+ (list2).head = NULL; \
+ (list2).tail = NULL; \
+ } while (0)
+
#define ISC_LIST_ENQUEUE(list, elt, link) ISC_LIST_APPEND(list, elt, link)
#define __ISC_LIST_ENQUEUEUNSAFE(list, elt, link) \
__ISC_LIST_APPENDUNSAFE(list, elt, link)
diff --git a/contrib/bind9/lib/isc/include/isc/mem.h b/contrib/bind9/lib/isc/include/isc/mem.h
index 317417f..320d0d8 100644
--- a/contrib/bind9/lib/isc/include/isc/mem.h
+++ b/contrib/bind9/lib/isc/include/isc/mem.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2010, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1997-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -317,7 +317,7 @@ isc_mem_createx2(size_t max_size, size_t target_size,
* ISC_MEMFLAG_INTERNAL is not set, 'target_size' is ignored.
*
* 'max_size' is also used to size the statistics arrays and the array
- * used to record active memory when ISC_MEM_DEBUGRECORD is set. Settin
+ * used to record active memory when ISC_MEM_DEBUGRECORD is set. Setting
* 'max_size' too low can have detrimental effects on performance.
*
* A memory context created using isc_mem_createx() will obtain
diff --git a/contrib/bind9/lib/isc/include/isc/namespace.h b/contrib/bind9/lib/isc/include/isc/namespace.h
index 45b769c..f8744d8 100644
--- a/contrib/bind9/lib/isc/include/isc/namespace.h
+++ b/contrib/bind9/lib/isc/include/isc/namespace.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2010, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2009-2012 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -31,6 +31,7 @@
#define isc_app_run isc__app_run
#define isc_app_ctxrun isc__app_ctxrun
#define isc_app_shutdown isc__app_shutdown
+#define isc_app_ctxfinish isc__app_ctxfinish
#define isc_app_ctxshutdown isc__app_ctxshutdown
#define isc_app_ctxsuspend isc__app_ctxsuspend
#define isc_app_reload isc__app_reload
@@ -89,6 +90,7 @@
#define isc_mempool_getfillcount isc__mempool_getfillcount
#define isc_socket_create isc__socket_create
+#define isc_socket_dup isc__socket_dup
#define isc_socket_attach isc__socket_attach
#define isc_socket_detach isc__socket_detach
#define isc_socketmgr_create isc__socketmgr_create
@@ -111,6 +113,7 @@
#define isc_socket_listen isc__socket_listen
#define isc_socket_accept isc__socket_accept
#define isc_socket_connect isc__socket_connect
+#define isc_socket_getfd isc__socket_getfd
#define isc_socket_getname isc__socket_getname
#define isc_socket_gettag isc__socket_gettag
#define isc_socket_getpeername isc__socket_getpeername
@@ -146,11 +149,15 @@
#define isc_task_gettag isc__task_gettag
#define isc_task_getcurrenttime isc__task_getcurrenttime
#define isc_taskmgr_create isc__taskmgr_create
+#define isc_taskmgr_setmode isc__taskmgr_setmode
+#define isc_taskmgr_mode isc__taskmgr_mode
#define isc_taskmgr_destroy isc__taskmgr_destroy
#define isc_taskmgr_setexcltask isc__taskmgr_setexcltask
#define isc_taskmgr_excltask isc__taskmgr_excltask
#define isc_task_beginexclusive isc__task_beginexclusive
#define isc_task_endexclusive isc__task_endexclusive
+#define isc_task_setprivilege isc__task_setprivilege
+#define isc_task_privilege isc__task_privilege
#define isc_timer_create isc__timer_create
#define isc_timer_reset isc__timer_reset
diff --git a/contrib/bind9/lib/isc/include/isc/pool.h b/contrib/bind9/lib/isc/include/isc/pool.h
new file mode 100644
index 0000000..7b33c37
--- /dev/null
+++ b/contrib/bind9/lib/isc/include/isc/pool.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or 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.
+ */
+
+#ifndef ISC_OBJPOOL_H
+#define ISC_OBJPOOL_H 1
+
+/*****
+ ***** Module Info
+ *****/
+
+/*! \file isc/pool.h
+ * \brief An object pool is a mechanism for sharing a small pool of
+ * fungible objects among a large number of objects that depend on them.
+ *
+ * This is useful, for example, when it causes performance problems for
+ * large number of zones to share a single memory context or task object,
+ * but it would create a different set of problems for them each to have an
+ * independent task or memory context.
+ */
+
+
+/***
+ *** Imports.
+ ***/
+
+#include <isc/lang.h>
+#include <isc/mem.h>
+#include <isc/types.h>
+
+ISC_LANG_BEGINDECLS
+
+/*****
+ ***** Types.
+ *****/
+
+typedef void
+(*isc_pooldeallocator_t)(void **object);
+
+typedef isc_result_t
+(*isc_poolinitializer_t)(void **target, void *arg);
+
+typedef struct isc_pool isc_pool_t;
+
+/*****
+ ***** Functions.
+ *****/
+
+isc_result_t
+isc_pool_create(isc_mem_t *mctx, unsigned int count,
+ isc_pooldeallocator_t free,
+ isc_poolinitializer_t init, void *initarg,
+ isc_pool_t **poolp);
+/*%<
+ * Create a pool of "count" object pointers. If 'free' is not NULL,
+ * it points to a function that will detach the objects. 'init'
+ * points to a function that will initialize the arguments, and
+ * 'arg' to an argument to be passed into that function (for example,
+ * a relevant manager or context object).
+ *
+ * Requires:
+ *
+ *\li 'mctx' is a valid memory context.
+ *
+ *\li init != NULL
+ *
+ *\li poolp != NULL && *poolp == NULL
+ *
+ * Ensures:
+ *
+ *\li On success, '*poolp' points to the new object pool.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ *\li #ISC_R_UNEXPECTED
+ */
+
+void *
+isc_pool_get(isc_pool_t *pool);
+/*%<
+ * Returns a pointer to an object from the pool. Currently the object
+ * is chosen from the pool at random. (This may be changed in the future
+ * to something that guaratees balance.)
+ */
+
+int
+isc_pool_count(isc_pool_t *pool);
+/*%<
+ * Returns the number of objcts in the pool 'pool'.
+ */
+
+isc_result_t
+isc_pool_expand(isc_pool_t **sourcep, unsigned int count, isc_pool_t **targetp);
+
+/*%<
+ * If 'size' is larger than the number of objects in the pool pointed to by
+ * 'sourcep', then a new pool of size 'count' is allocated, the existing
+ * objects are copied into it, additional ones created to bring the
+ * total number up to 'count', and the resulting pool is attached to
+ * 'targetp'.
+ *
+ * If 'count' is less than or equal to the number of objects in 'source', then
+ * 'sourcep' is attached to 'targetp' without any other action being taken.
+ *
+ * In either case, 'sourcep' is detached.
+ *
+ * Requires:
+ *
+ * \li 'sourcep' is not NULL and '*source' is not NULL
+ * \li 'targetp' is not NULL and '*source' is NULL
+ *
+ * Ensures:
+ *
+ * \li On success, '*targetp' points to a valid task pool.
+ * \li On success, '*sourcep' points to NULL.
+ *
+ * Returns:
+ *
+ * \li #ISC_R_SUCCESS
+ * \li #ISC_R_NOMEMORY
+ */
+
+void
+isc_pool_destroy(isc_pool_t **poolp);
+/*%<
+ * Destroy a task pool. The tasks in the pool are detached but not
+ * shut down.
+ *
+ * Requires:
+ * \li '*poolp' is a valid task pool.
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_OBJPOOL_H */
diff --git a/contrib/bind9/lib/isc/include/isc/queue.h b/contrib/bind9/lib/isc/include/isc/queue.h
new file mode 100644
index 0000000..1cc6c12
--- /dev/null
+++ b/contrib/bind9/lib/isc/include/isc/queue.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or 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$ */
+
+/*
+ * This is a generic implementation of a two-lock concurrent queue.
+ * There are built-in mutex locks for the head and tail of the queue,
+ * allowing elements to be safely added and removed at the same time.
+ *
+ * NULL is "end of list"
+ * -1 is "not linked"
+ */
+
+#ifndef ISC_QUEUE_H
+#define ISC_QUEUE_H 1
+#include <isc/assertions.h>
+#include <isc/boolean.h>
+#include <isc/mutex.h>
+
+#ifdef ISC_QUEUE_CHECKINIT
+#define ISC_QLINK_INSIST(x) ISC_INSIST(x)
+#else
+#define ISC_QLINK_INSIST(x) (void)0
+#endif
+
+#define ISC_QLINK(type) struct { type *prev, *next; }
+
+#define ISC_QLINK_INIT(elt, link) \
+ do { \
+ (elt)->link.next = (elt)->link.prev = (void *)(-1); \
+ } while(0)
+
+#define ISC_QLINK_LINKED(elt, link) ((void*)(elt)->link.next != (void*)(-1))
+
+#define ISC_QUEUE(type) struct { \
+ type *head, *tail; \
+ isc_mutex_t headlock, taillock; \
+}
+
+#define ISC_QUEUE_INIT(queue, link) \
+ do { \
+ (void) isc_mutex_init(&(queue).taillock); \
+ (void) isc_mutex_init(&(queue).headlock); \
+ (queue).tail = (queue).head = NULL; \
+ } while (0)
+
+#define ISC_QUEUE_EMPTY(queue) ISC_TF((queue).head == NULL)
+
+#define ISC_QUEUE_DESTROY(queue) \
+ do { \
+ ISC_QLINK_INSIST(ISC_QUEUE_EMPTY(queue)); \
+ (void) isc_mutex_destroy(&(queue).taillock); \
+ (void) isc_mutex_destroy(&(queue).headlock); \
+ } while (0)
+
+/*
+ * queues are meant to separate the locks at either end. For best effect, that
+ * means keeping the ends separate - i.e. non-empty queues work best.
+ *
+ * a push to an empty queue has to take the pop lock to update
+ * the pop side of the queue.
+ * Popping the last entry has to take the push lock to update
+ * the push side of the queue.
+ *
+ * The order is (pop, push), because a pop is presumably in the
+ * latency path and a push is when we're done.
+ *
+ * We do an MT hot test in push to see if we need both locks, so we can
+ * acquire them in order. Hopefully that makes the case where we get
+ * the push lock and find we need the pop lock (and have to release it) rare.
+ *
+ * > 1 entry - no collision, push works on one end, pop on the other
+ * 0 entry - headlock race
+ * pop wins - return(NULL), push adds new as both head/tail
+ * push wins - updates head/tail, becomes 1 entry case.
+ * 1 entry - taillock race
+ * pop wins - return(pop) sets head/tail NULL, becomes 0 entry case
+ * push wins - updates {head,tail}->link.next, pop updates head
+ * with new ->link.next and doesn't update tail
+ *
+ */
+#define ISC_QUEUE_PUSH(queue, elt, link) \
+ do { \
+ isc_boolean_t headlocked = ISC_FALSE; \
+ ISC_QLINK_INSIST(!ISC_QLINK_LINKED(elt, link)); \
+ if ((queue).head == NULL) { \
+ LOCK(&(queue).headlock); \
+ headlocked = ISC_TRUE; \
+ } \
+ LOCK(&(queue).taillock); \
+ if ((queue).tail == NULL && !headlocked) { \
+ UNLOCK(&(queue).taillock); \
+ LOCK(&(queue).headlock); \
+ LOCK(&(queue).taillock); \
+ headlocked = ISC_TRUE; \
+ } \
+ (elt)->link.prev = (queue).tail; \
+ (elt)->link.next = NULL; \
+ if ((queue).tail != NULL) \
+ (queue).tail->link.next = (elt); \
+ (queue).tail = (elt); \
+ UNLOCK(&(queue).taillock); \
+ if (headlocked) { \
+ if ((queue).head == NULL) \
+ (queue).head = (elt); \
+ UNLOCK(&(queue).headlock); \
+ } \
+ } while (0)
+
+#define ISC_QUEUE_POP(queue, link, ret) \
+ do { \
+ LOCK(&(queue).headlock); \
+ ret = (queue).head; \
+ while (ret != NULL) { \
+ if (ret->link.next == NULL) { \
+ LOCK(&(queue).taillock); \
+ if (ret->link.next == NULL) { \
+ (queue).head = (queue).tail = NULL; \
+ UNLOCK(&(queue).taillock); \
+ break; \
+ }\
+ UNLOCK(&(queue).taillock); \
+ } \
+ (queue).head = ret->link.next; \
+ (queue).head->link.prev = NULL; \
+ break; \
+ } \
+ UNLOCK(&(queue).headlock); \
+ if (ret != NULL) \
+ (ret)->link.next = (ret)->link.prev = (void *)(-1); \
+ } while(0)
+
+#define ISC_QUEUE_UNLINK(queue, elt, link) \
+ do { \
+ ISC_QLINK_INSIST(ISC_QLINK_LINKED(elt, link)); \
+ LOCK(&(queue).headlock); \
+ LOCK(&(queue).taillock); \
+ if ((elt)->link.prev == NULL) \
+ (queue).head = (elt)->link.next; \
+ else \
+ (elt)->link.prev->link.next = (elt)->link.next; \
+ if ((elt)->link.next == NULL) \
+ (queue).tail = (elt)->link.prev; \
+ else \
+ (elt)->link.next->link.prev = (elt)->link.prev; \
+ UNLOCK(&(queue).taillock); \
+ UNLOCK(&(queue).headlock); \
+ (elt)->link.next = (elt)->link.prev = (void *)(-1); \
+ } while(0)
+
+#endif /* ISC_QUEUE_H */
diff --git a/contrib/bind9/lib/isc/include/isc/radix.h b/contrib/bind9/lib/isc/include/isc/radix.h
index 6b413a2..47512c7 100644
--- a/contrib/bind9/lib/isc/include/isc/radix.h
+++ b/contrib/bind9/lib/isc/include/isc/radix.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2007, 2008, 2013 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -54,13 +54,14 @@
} while(0)
typedef struct isc_prefix {
- unsigned int family; /* AF_INET | AF_INET6, or AF_UNSPEC for "any" */
- unsigned int bitlen; /* 0 for "any" */
- isc_refcount_t refcount;
- union {
+ isc_mem_t *mctx;
+ unsigned int family; /* AF_INET | AF_INET6, or AF_UNSPEC for "any" */
+ unsigned int bitlen; /* 0 for "any" */
+ isc_refcount_t refcount;
+ union {
struct in_addr sin;
struct in6_addr sin6;
- } add;
+ } add;
} isc_prefix_t;
typedef void (*isc_radix_destroyfunc_t)(void *);
@@ -90,12 +91,13 @@ typedef void (*isc_radix_processfunc_t)(isc_prefix_t *, void **);
#define ISC_IS6(family) ((family) == AF_INET6 ? 1 : 0)
typedef struct isc_radix_node {
- isc_uint32_t bit; /* bit length of the prefix */
- isc_prefix_t *prefix; /* who we are in radix tree */
- struct isc_radix_node *l, *r; /* left and right children */
- struct isc_radix_node *parent; /* may be used */
- void *data[2]; /* pointers to IPv4 and IPV6 data */
- int node_num[2]; /* which node this was in the tree,
+ isc_mem_t *mctx;
+ isc_uint32_t bit; /* bit length of the prefix */
+ isc_prefix_t *prefix; /* who we are in radix tree */
+ struct isc_radix_node *l, *r; /* left and right children */
+ struct isc_radix_node *parent; /* may be used */
+ void *data[2]; /* pointers to IPv4 and IPV6 data */
+ int node_num[2]; /* which node this was in the tree,
or -1 for glue nodes */
} isc_radix_node_t;
@@ -103,12 +105,12 @@ typedef struct isc_radix_node {
#define RADIX_TREE_VALID(a) ISC_MAGIC_VALID(a, RADIX_TREE_MAGIC);
typedef struct isc_radix_tree {
- unsigned int magic;
- isc_mem_t *mctx;
- isc_radix_node_t *head;
- isc_uint32_t maxbits; /* for IP, 32 bit addresses */
- int num_active_node; /* for debugging purposes */
- int num_added_node; /* total number of nodes */
+ unsigned int magic;
+ isc_mem_t *mctx;
+ isc_radix_node_t *head;
+ isc_uint32_t maxbits; /* for IP, 32 bit addresses */
+ int num_active_node; /* for debugging purposes */
+ int num_added_node; /* total number of nodes */
} isc_radix_tree_t;
isc_result_t
diff --git a/contrib/bind9/lib/isc/include/isc/socket.h b/contrib/bind9/lib/isc/include/isc/socket.h
index 4111ec2..9d086b4 100644
--- a/contrib/bind9/lib/isc/include/isc/socket.h
+++ b/contrib/bind9/lib/isc/include/isc/socket.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2009, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -283,12 +283,20 @@ typedef struct isc_socketmethods {
isc_task_t *task, isc_taskaction_t action,
const void *arg, isc_sockaddr_t *address,
struct in6_pktinfo *pktinfo);
+ isc_result_t (*sendto2)(isc_socket_t *sock, isc_region_t *region,
+ isc_task_t *task, isc_sockaddr_t *address,
+ struct in6_pktinfo *pktinfo,
+ isc_socketevent_t *event,
+ unsigned int flags);
isc_result_t (*connect)(isc_socket_t *sock, isc_sockaddr_t *addr,
isc_task_t *task, isc_taskaction_t action,
const void *arg);
isc_result_t (*recv)(isc_socket_t *sock, isc_region_t *region,
unsigned int minimum, isc_task_t *task,
isc_taskaction_t action, const void *arg);
+ isc_result_t (*recv2)(isc_socket_t *sock, isc_region_t *region,
+ unsigned int minimum, isc_task_t *task,
+ isc_socketevent_t *event, unsigned int flags);
void (*cancel)(isc_socket_t *sock, isc_task_t *task,
unsigned int how);
isc_result_t (*getsockname)(isc_socket_t *sock,
@@ -296,6 +304,9 @@ typedef struct isc_socketmethods {
isc_sockettype_t (*gettype)(isc_socket_t *sock);
void (*ipv6only)(isc_socket_t *sock, isc_boolean_t yes);
isc_result_t (*fdwatchpoke)(isc_socket_t *sock, int flags);
+ isc_result_t (*dup)(isc_socket_t *socket,
+ isc_socket_t **socketp);
+ int (*getfd)(isc_socket_t *socket);
} isc_socketmethods_t;
/*%
@@ -449,6 +460,12 @@ isc_socket_create(isc_socketmgr_t *manager,
*\li #ISC_R_UNEXPECTED
*/
+isc_result_t
+isc_socket_dup(isc_socket_t *sock0, isc_socket_t **socketp);
+/*%<
+ * Duplicate an existing socket, reusing its file descriptor.
+ */
+
void
isc_socket_cancel(isc_socket_t *sock, isc_task_t *task,
unsigned int how);
@@ -1102,6 +1119,11 @@ void *isc_socket_gettag(isc_socket_t *socket);
* Get the tag associated with a socket, if any.
*/
+int isc_socket_getfd(isc_socket_t *socket);
+/*%<
+ * Get the file descriptor associated with a socket
+ */
+
void
isc__socketmgr_setreserved(isc_socketmgr_t *mgr, isc_uint32_t);
/*%<
diff --git a/contrib/bind9/lib/isc/include/isc/task.h b/contrib/bind9/lib/isc/include/isc/task.h
index ced7059..7abf2ef 100644
--- a/contrib/bind9/lib/isc/include/isc/task.h
+++ b/contrib/bind9/lib/isc/include/isc/task.h
@@ -88,6 +88,7 @@
#define ISC_TASKEVENT_FIRSTEVENT (ISC_EVENTCLASS_TASK + 0)
#define ISC_TASKEVENT_SHUTDOWN (ISC_EVENTCLASS_TASK + 1)
+#define ISC_TASKEVENT_TEST (ISC_EVENTCLASS_TASK + 1)
#define ISC_TASKEVENT_LASTEVENT (ISC_EVENTCLASS_TASK + 65535)
/*****
@@ -100,9 +101,17 @@ ISC_LANG_BEGINDECLS
*** Types
***/
+typedef enum {
+ isc_taskmgrmode_normal = 0,
+ isc_taskmgrmode_privileged
+} isc_taskmgrmode_t;
+
/*% Task and task manager methods */
typedef struct isc_taskmgrmethods {
void (*destroy)(isc_taskmgr_t **managerp);
+ void (*setmode)(isc_taskmgr_t *manager,
+ isc_taskmgrmode_t mode);
+ isc_taskmgrmode_t (*mode)(isc_taskmgr_t *manager);
isc_result_t (*taskcreate)(isc_taskmgr_t *manager,
unsigned int quantum,
isc_task_t **taskp);
@@ -129,6 +138,8 @@ typedef struct isc_taskmethods {
void *tag);
isc_result_t (*beginexclusive)(isc_task_t *task);
void (*endexclusive)(isc_task_t *task);
+ void (*setprivilege)(isc_task_t *task, isc_boolean_t priv);
+ isc_boolean_t (*privilege)(isc_task_t *task);
} isc_taskmethods_t;
/*%
@@ -613,6 +624,32 @@ isc_task_exiting(isc_task_t *t);
*\li 'task' is a valid task.
*/
+void
+isc_task_setprivilege(isc_task_t *task, isc_boolean_t priv);
+/*%<
+ * Set or unset the task's "privileged" flag depending on the value of
+ * 'priv'.
+ *
+ * Under normal circumstances this flag has no effect on the task behavior,
+ * but when the task manager has been set to privileged exeuction mode via
+ * isc_taskmgr_setmode(), only tasks with the flag set will be executed,
+ * and all other tasks will wait until they're done. Once all privileged
+ * tasks have finished executing, the task manager will automatically
+ * return to normal execution mode and nonprivileged task can resume.
+ *
+ * Requires:
+ *\li 'task' is a valid task.
+ */
+
+isc_boolean_t
+isc_task_privilege(isc_task_t *task);
+/*%<
+ * Returns the current value of the task's privilege flag.
+ *
+ * Requires:
+ *\li 'task' is a valid task.
+ */
+
/*****
***** Task Manager.
*****/
@@ -666,6 +703,31 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
*/
void
+isc_taskmgr_setmode(isc_taskmgr_t *manager, isc_taskmgrmode_t mode);
+
+isc_taskmgrmode_t
+isc_taskmgr_mode(isc_taskmgr_t *manager);
+/*%<
+ * Set/get the current operating mode of the task manager. Valid modes are:
+ *
+ *\li isc_taskmgrmode_normal
+ *\li isc_taskmgrmode_privileged
+ *
+ * In privileged execution mode, only tasks that have had the "privilege"
+ * flag set via isc_task_setprivilege() can be executed. When all such
+ * tasks are complete, the manager automatically returns to normal mode
+ * and proceeds with running non-privileged ready tasks. This means it is
+ * necessary to have at least one privileged task waiting on the ready
+ * queue *before* setting the manager into privileged execution mode,
+ * which in turn means the task which calls this function should be in
+ * task-exclusive mode when it does so.
+ *
+ * Requires:
+ *
+ *\li 'manager' is a valid task manager.
+ */
+
+void
isc_taskmgr_destroy(isc_taskmgr_t **managerp);
/*%<
* Destroy '*managerp'.
diff --git a/contrib/bind9/lib/isc/include/isc/taskpool.h b/contrib/bind9/lib/isc/include/isc/taskpool.h
index 64c739a..46f395e 100644
--- a/contrib/bind9/lib/isc/include/isc/taskpool.h
+++ b/contrib/bind9/lib/isc/include/isc/taskpool.h
@@ -139,6 +139,19 @@ isc_taskpool_destroy(isc_taskpool_t **poolp);
* \li '*poolp' is a valid task pool.
*/
+void
+isc_taskpool_setprivilege(isc_taskpool_t *pool, isc_boolean_t priv);
+/*%<
+ * Set the privilege flag on all tasks in 'pool' to 'priv'. If 'priv' is
+ * true, then when the task manager is set into privileged mode, only
+ * tasks wihin this pool will be able to execute. (Note: It is important
+ * to turn the pool tasks' privilege back off before the last task finishes
+ * executing.)
+ *
+ * Requires:
+ * \li 'pool' is a valid task pool.
+ */
+
ISC_LANG_ENDDECLS
#endif /* ISC_TASKPOOL_H */
diff --git a/contrib/bind9/lib/isc/log.c b/contrib/bind9/lib/isc/log.c
index f1c925c..024d97c 100644
--- a/contrib/bind9/lib/isc/log.c
+++ b/contrib/bind9/lib/isc/log.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2007, 2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -275,7 +275,8 @@ isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp, isc_logconfig_t **lcfgp) {
lctx = isc_mem_get(mctx, sizeof(*lctx));
if (lctx != NULL) {
- lctx->mctx = mctx;
+ lctx->mctx = NULL;
+ isc_mem_attach(mctx, &lctx->mctx);
lctx->categories = NULL;
lctx->category_count = 0;
lctx->modules = NULL;
@@ -286,7 +287,7 @@ isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp, isc_logconfig_t **lcfgp) {
result = isc_mutex_init(&lctx->lock);
if (result != ISC_R_SUCCESS) {
- isc_mem_put(mctx, lctx, sizeof(*lctx));
+ isc_mem_putanddetach(&mctx, lctx, sizeof(*lctx));
return (result);
}
@@ -493,7 +494,7 @@ isc_log_destroy(isc_log_t **lctxp) {
lctx->mctx = NULL;
lctx->magic = 0;
- isc_mem_put(mctx, lctx, sizeof(*lctx));
+ isc_mem_putanddetach(&mctx, lctx, sizeof(*lctx));
*lctxp = NULL;
}
diff --git a/contrib/bind9/lib/isc/pool.c b/contrib/bind9/lib/isc/pool.c
new file mode 100644
index 0000000..509abcb
--- /dev/null
+++ b/contrib/bind9/lib/isc/pool.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or 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$ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <isc/mem.h>
+#include <isc/random.h>
+#include <isc/pool.h>
+#include <isc/util.h>
+
+/***
+ *** Types.
+ ***/
+
+struct isc_pool {
+ isc_mem_t * mctx;
+ unsigned int count;
+ isc_pooldeallocator_t free;
+ isc_poolinitializer_t init;
+ void * initarg;
+ void ** pool;
+};
+
+/***
+ *** Functions.
+ ***/
+
+static isc_result_t
+alloc_pool(isc_mem_t *mctx, unsigned int count, isc_pool_t **poolp) {
+ isc_pool_t *pool;
+
+ pool = isc_mem_get(mctx, sizeof(*pool));
+ if (pool == NULL)
+ return (ISC_R_NOMEMORY);
+ pool->count = count;
+ pool->free = NULL;
+ pool->init = NULL;
+ pool->initarg = NULL;
+ pool->mctx = NULL;
+ isc_mem_attach(mctx, &pool->mctx);
+ pool->pool = isc_mem_get(mctx, count * sizeof(void *));
+ if (pool->pool == NULL) {
+ isc_mem_put(mctx, pool, sizeof(*pool));
+ return (ISC_R_NOMEMORY);
+ }
+ memset(pool->pool, 0, count * sizeof(void *));
+
+ *poolp = pool;
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+isc_pool_create(isc_mem_t *mctx, unsigned int count,
+ isc_pooldeallocator_t free,
+ isc_poolinitializer_t init, void *initarg,
+ isc_pool_t **poolp)
+{
+ isc_pool_t *pool = NULL;
+ isc_result_t result;
+ unsigned int i;
+
+ INSIST(count > 0);
+
+ /* Allocate the pool structure */
+ result = alloc_pool(mctx, count, &pool);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ pool->free = free;
+ pool->init = init;
+ pool->initarg = initarg;
+
+ /* Populate the pool */
+ for (i = 0; i < count; i++) {
+ result = init(&pool->pool[i], initarg);
+ if (result != ISC_R_SUCCESS) {
+ isc_pool_destroy(&pool);
+ return (result);
+ }
+ }
+
+ *poolp = pool;
+ return (ISC_R_SUCCESS);
+}
+
+void *
+isc_pool_get(isc_pool_t *pool) {
+ isc_uint32_t i;
+ isc_random_get(&i);
+ return (pool->pool[i % pool->count]);
+}
+
+int
+isc_pool_count(isc_pool_t *pool) {
+ REQUIRE(pool != NULL);
+ return (pool->count);
+}
+
+isc_result_t
+isc_pool_expand(isc_pool_t **sourcep, unsigned int count,
+ isc_pool_t **targetp)
+{
+ isc_result_t result;
+ isc_pool_t *pool;
+
+ REQUIRE(sourcep != NULL && *sourcep != NULL);
+ REQUIRE(targetp != NULL && *targetp == NULL);
+
+ pool = *sourcep;
+ if (count > pool->count) {
+ isc_pool_t *newpool = NULL;
+ unsigned int i;
+
+ /* Allocate a new pool structure */
+ result = alloc_pool(pool->mctx, count, &newpool);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ newpool->free = pool->free;
+ newpool->init = pool->init;
+ newpool->initarg = pool->initarg;
+
+ /* Copy over the objects from the old pool */
+ for (i = 0; i < pool->count; i++) {
+ newpool->pool[i] = pool->pool[i];
+ pool->pool[i] = NULL;
+ }
+
+ /* Populate the new entries */
+ for (i = pool->count; i < count; i++) {
+ result = pool->init(&newpool->pool[i], pool->initarg);
+ if (result != ISC_R_SUCCESS) {
+ isc_pool_destroy(&pool);
+ return (result);
+ }
+ }
+
+ isc_pool_destroy(&pool);
+ pool = newpool;
+ }
+
+ *sourcep = NULL;
+ *targetp = pool;
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_pool_destroy(isc_pool_t **poolp) {
+ unsigned int i;
+ isc_pool_t *pool = *poolp;
+ for (i = 0; i < pool->count; i++) {
+ if (pool->free != NULL && pool->pool[i] != NULL)
+ pool->free(&pool->pool[i]);
+ }
+ isc_mem_put(pool->mctx, pool->pool, pool->count * sizeof(void *));
+ isc_mem_putanddetach(&pool->mctx, pool, sizeof(*pool));
+ *poolp = NULL;
+}
diff --git a/contrib/bind9/lib/isc/radix.c b/contrib/bind9/lib/isc/radix.c
index ac211ef..3508878 100644
--- a/contrib/bind9/lib/isc/radix.c
+++ b/contrib/bind9/lib/isc/radix.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2007-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -34,7 +34,7 @@ _new_prefix(isc_mem_t *mctx, isc_prefix_t **target, int family,
void *dest, int bitlen);
static void
-_deref_prefix(isc_mem_t *mctx, isc_prefix_t *prefix);
+_deref_prefix(isc_prefix_t *prefix);
static isc_result_t
_ref_prefix(isc_mem_t *mctx, isc_prefix_t **target, isc_prefix_t *prefix);
@@ -70,6 +70,8 @@ _new_prefix(isc_mem_t *mctx, isc_prefix_t **target, int family, void *dest,
}
prefix->family = family;
+ prefix->mctx = NULL;
+ isc_mem_attach(mctx, &prefix->mctx);
isc_refcount_init(&prefix->refcount, 1);
@@ -78,7 +80,7 @@ _new_prefix(isc_mem_t *mctx, isc_prefix_t **target, int family, void *dest,
}
static void
-_deref_prefix(isc_mem_t *mctx, isc_prefix_t *prefix) {
+_deref_prefix(isc_prefix_t *prefix) {
int refs;
if (prefix == NULL)
@@ -88,7 +90,8 @@ _deref_prefix(isc_mem_t *mctx, isc_prefix_t *prefix) {
if (refs <= 0) {
isc_refcount_destroy(&prefix->refcount);
- isc_mem_put(mctx, prefix, sizeof(isc_prefix_t));
+ isc_mem_putanddetach(&prefix->mctx, prefix,
+ sizeof(isc_prefix_t));
}
}
@@ -109,7 +112,7 @@ _ref_prefix(isc_mem_t *mctx, isc_prefix_t **target, isc_prefix_t *prefix) {
isc_result_t ret;
ret = _new_prefix(mctx, target, prefix->family,
&prefix->add, prefix->bitlen);
- return ret;
+ return (ret);
}
isc_refcount_increment(&prefix->refcount, NULL);
@@ -146,7 +149,8 @@ isc_radix_create(isc_mem_t *mctx, isc_radix_tree_t **target, int maxbits) {
if (radix == NULL)
return (ISC_R_NOMEMORY);
- radix->mctx = mctx;
+ radix->mctx = NULL;
+ isc_mem_attach(mctx, &radix->mctx);
radix->maxbits = maxbits;
radix->head = NULL;
radix->num_active_node = 0;
@@ -168,7 +172,6 @@ _clear_radix(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func) {
REQUIRE(radix != NULL);
if (radix->head != NULL) {
-
isc_radix_node_t *Xstack[RADIX_MAXBITS+1];
isc_radix_node_t **Xsp = Xstack;
isc_radix_node_t *Xrn = radix->head;
@@ -178,7 +181,7 @@ _clear_radix(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func) {
isc_radix_node_t *r = Xrn->r;
if (Xrn->prefix != NULL) {
- _deref_prefix(radix->mctx, Xrn->prefix);
+ _deref_prefix(Xrn->prefix);
if (func != NULL && (Xrn->data[0] != NULL ||
Xrn->data[1] != NULL))
func(Xrn->data);
@@ -209,11 +212,10 @@ _clear_radix(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func) {
void
-isc_radix_destroy(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func)
-{
+isc_radix_destroy(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func) {
REQUIRE(radix != NULL);
_clear_radix(radix, func);
- isc_mem_put(radix->mctx, radix, sizeof(*radix));
+ isc_mem_putanddetach(&radix->mctx, radix, sizeof(*radix));
}
@@ -221,8 +223,7 @@ isc_radix_destroy(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func)
* func will be called as func(node->prefix, node->data)
*/
void
-isc_radix_process(isc_radix_tree_t *radix, isc_radix_processfunc_t func)
-{
+isc_radix_process(isc_radix_tree_t *radix, isc_radix_processfunc_t func) {
isc_radix_node_t *node;
REQUIRE(func != NULL);
@@ -461,8 +462,8 @@ isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
*target = node;
return (ISC_R_SUCCESS);
} else {
- result =
- _ref_prefix(radix->mctx, &node->prefix, prefix);
+ result = _ref_prefix(radix->mctx,
+ &node->prefix, prefix);
if (result != ISC_R_SUCCESS)
return (result);
}
@@ -623,7 +624,7 @@ isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node) {
* make sure there is a prefix associated with it!
*/
if (node->prefix != NULL)
- _deref_prefix(radix->mctx, node->prefix);
+ _deref_prefix(node->prefix);
node->prefix = NULL;
node->data[0] = node->data[1] = NULL;
@@ -632,7 +633,7 @@ isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node) {
if (node->r == NULL && node->l == NULL) {
parent = node->parent;
- _deref_prefix(radix->mctx, node->prefix);
+ _deref_prefix(node->prefix);
isc_mem_put(radix->mctx, node, sizeof(*node));
radix->num_active_node--;
@@ -680,7 +681,7 @@ isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node) {
parent = node->parent;
child->parent = parent;
- _deref_prefix(radix->mctx, node->prefix);
+ _deref_prefix(node->prefix);
isc_mem_put(radix->mctx, node, sizeof(*node));
radix->num_active_node--;
diff --git a/contrib/bind9/lib/isc/socket_api.c b/contrib/bind9/lib/isc/socket_api.c
index e97a931..1fba3e0 100644
--- a/contrib/bind9/lib/isc/socket_api.c
+++ b/contrib/bind9/lib/isc/socket_api.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -141,6 +141,18 @@ isc_socket_sendto(isc_socket_t *sock, isc_region_t *region, isc_task_t *task,
}
isc_result_t
+isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
+ isc_task_t *task, isc_sockaddr_t *address,
+ struct in6_pktinfo *pktinfo, isc_socketevent_t *event,
+ unsigned int flags)
+{
+ REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+ return (sock->methods->sendto2(sock, region, task, address,
+ pktinfo, event, flags));
+}
+
+isc_result_t
isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr, isc_task_t *task,
isc_taskaction_t action, const void *arg)
{
@@ -158,6 +170,17 @@ isc_socket_recv(isc_socket_t *sock, isc_region_t *region, unsigned int minimum,
return (sock->methods->recv(sock, region, minimum, task, action, arg));
}
+isc_result_t
+isc_socket_recv2(isc_socket_t *sock, isc_region_t *region,
+ unsigned int minimum, isc_task_t *task,
+ isc_socketevent_t *event, unsigned int flags)
+{
+ REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+ return (sock->methods->recv2(sock, region, minimum, task,
+ event, flags));
+}
+
void
isc_socket_cancel(isc_socket_t *sock, isc_task_t *task, unsigned int how) {
REQUIRE(ISCAPI_SOCKET_VALID(sock));
@@ -214,3 +237,18 @@ isc_socket_fdwatchpoke(isc_socket_t *sock, int flags)
return(sock->methods->fdwatchpoke(sock, flags));
}
+
+isc_result_t
+isc_socket_dup(isc_socket_t *sock, isc_socket_t **socketp) {
+ REQUIRE(ISCAPI_SOCKET_VALID(sock));
+ REQUIRE(socketp != NULL && *socketp == NULL);
+
+ return(sock->methods->dup(sock, socketp));
+}
+
+int
+isc_socket_getfd(isc_socket_t *sock) {
+ REQUIRE(ISCAPI_SOCKET_VALID(sock));
+
+ return(sock->methods->getfd(sock));
+}
diff --git a/contrib/bind9/lib/isc/task.c b/contrib/bind9/lib/isc/task.c
index 94f1c6d..b743271 100644
--- a/contrib/bind9/lib/isc/task.c
+++ b/contrib/bind9/lib/isc/task.c
@@ -64,9 +64,7 @@
#endif /* ISC_PLATFORM_USETHREADS */
#endif /* BIND9 */
-#ifndef USE_WORKER_THREADS
#include "task_p.h"
-#endif /* USE_WORKER_THREADS */
#ifdef ISC_TASK_TRACE
#define XTRACE(m) fprintf(stderr, "task %p thread %lu: %s\n", \
@@ -120,9 +118,11 @@ struct isc__task {
/* Locked by task manager lock. */
LINK(isc__task_t) link;
LINK(isc__task_t) ready_link;
+ LINK(isc__task_t) ready_priority_link;
};
#define TASK_F_SHUTTINGDOWN 0x01
+#define TASK_F_PRIVILEGED 0x02
#define TASK_SHUTTINGDOWN(t) (((t)->flags & TASK_F_SHUTTINGDOWN) \
!= 0)
@@ -145,11 +145,15 @@ struct isc__taskmgr {
unsigned int default_quantum;
LIST(isc__task_t) tasks;
isc__tasklist_t ready_tasks;
+ isc__tasklist_t ready_priority_tasks;
+ isc_taskmgrmode_t mode;
#ifdef ISC_PLATFORM_USETHREADS
isc_condition_t work_available;
isc_condition_t exclusive_granted;
+ isc_condition_t paused;
#endif /* ISC_PLATFORM_USETHREADS */
unsigned int tasks_running;
+ isc_boolean_t pause_requested;
isc_boolean_t exclusive_requested;
isc_boolean_t exiting;
isc__task_t *excl;
@@ -230,6 +234,23 @@ ISC_TASKFUNC_SCOPE isc_result_t
isc__task_beginexclusive(isc_task_t *task);
ISC_TASKFUNC_SCOPE void
isc__task_endexclusive(isc_task_t *task0);
+ISC_TASKFUNC_SCOPE void
+isc__task_setprivilege(isc_task_t *task0, isc_boolean_t priv);
+ISC_TASKFUNC_SCOPE isc_boolean_t
+isc__task_privilege(isc_task_t *task0);
+ISC_TASKFUNC_SCOPE void
+isc__taskmgr_setmode(isc_taskmgr_t *manager0, isc_taskmgrmode_t mode);
+ISC_TASKFUNC_SCOPE isc_taskmgrmode_t
+isc__taskmgr_mode(isc_taskmgr_t *manager0);
+
+static inline isc_boolean_t
+empty_readyq(isc__taskmgr_t *manager);
+
+static inline isc__task_t *
+pop_readyq(isc__taskmgr_t *manager);
+
+static inline void
+push_readyq(isc__taskmgr_t *manager, isc__task_t *task);
static struct isc__taskmethods {
isc_taskmethods_t methods;
@@ -254,7 +275,9 @@ static struct isc__taskmethods {
isc__task_purge,
isc__task_purgerange,
isc__task_beginexclusive,
- isc__task_endexclusive
+ isc__task_endexclusive,
+ isc__task_setprivilege,
+ isc__task_privilege
}
#ifndef BIND9
,
@@ -266,6 +289,8 @@ static struct isc__taskmethods {
static isc_taskmgrmethods_t taskmgrmethods = {
isc__taskmgr_destroy,
+ isc__taskmgr_setmode,
+ isc__taskmgr_mode,
isc__task_create,
isc__taskmgr_setexcltask,
isc__taskmgr_excltask
@@ -340,6 +365,7 @@ isc__task_create(isc_taskmgr_t *manager0, unsigned int quantum,
task->tag = NULL;
INIT_LINK(task, link);
INIT_LINK(task, ready_link);
+ INIT_LINK(task, ready_priority_link);
exiting = ISC_FALSE;
LOCK(&manager->lock);
@@ -407,6 +433,7 @@ task_shutdown(isc__task_t *task) {
}
INSIST(task->state == task_state_ready ||
task->state == task_state_running);
+
/*
* Note that we post shutdown events LIFO.
*/
@@ -422,9 +449,17 @@ task_shutdown(isc__task_t *task) {
return (was_idle);
}
+/*
+ * Moves a task onto the appropriate run queue.
+ *
+ * Caller must NOT hold manager lock.
+ */
static inline void
task_ready(isc__task_t *task) {
isc__taskmgr_t *manager = task->manager;
+#ifdef USE_WORKER_THREADS
+ isc_boolean_t has_privilege = isc__task_privilege((isc_task_t *) task);
+#endif /* USE_WORKER_THREADS */
REQUIRE(VALID_MANAGER(manager));
REQUIRE(task->state == task_state_ready);
@@ -432,12 +467,11 @@ task_ready(isc__task_t *task) {
XTRACE("task_ready");
LOCK(&manager->lock);
-
- ENQUEUE(manager->ready_tasks, task, ready_link);
+ push_readyq(manager, task);
#ifdef USE_WORKER_THREADS
- SIGNAL(&manager->work_available);
+ if (manager->mode == isc_taskmgrmode_normal || has_privilege)
+ SIGNAL(&manager->work_available);
#endif /* USE_WORKER_THREADS */
-
UNLOCK(&manager->lock);
}
@@ -875,21 +909,81 @@ isc__task_getcurrenttime(isc_task_t *task0, isc_stdtime_t *t) {
REQUIRE(t != NULL);
LOCK(&task->lock);
-
*t = task->now;
-
UNLOCK(&task->lock);
}
/***
*** Task Manager.
***/
+
+/*
+ * Return ISC_TRUE if the current ready list for the manager, which is
+ * either ready_tasks or the ready_priority_tasks, depending on whether
+ * the manager is currently in normal or privileged execution mode.
+ *
+ * Caller must hold the task manager lock.
+ */
+static inline isc_boolean_t
+empty_readyq(isc__taskmgr_t *manager) {
+ isc__tasklist_t queue;
+
+ if (manager->mode == isc_taskmgrmode_normal)
+ queue = manager->ready_tasks;
+ else
+ queue = manager->ready_priority_tasks;
+
+ return (ISC_TF(EMPTY(queue)));
+}
+
+/*
+ * Dequeue and return a pointer to the first task on the current ready
+ * list for the manager.
+ * If the task is privileged, dequeue it from the other ready list
+ * as well.
+ *
+ * Caller must hold the task manager lock.
+ */
+static inline isc__task_t *
+pop_readyq(isc__taskmgr_t *manager) {
+ isc__task_t *task;
+
+ if (manager->mode == isc_taskmgrmode_normal)
+ task = HEAD(manager->ready_tasks);
+ else
+ task = HEAD(manager->ready_priority_tasks);
+
+ if (task != NULL) {
+ DEQUEUE(manager->ready_tasks, task, ready_link);
+ if (ISC_LINK_LINKED(task, ready_priority_link))
+ DEQUEUE(manager->ready_priority_tasks, task,
+ ready_priority_link);
+ }
+
+ return (task);
+}
+
+/*
+ * Push 'task' onto the ready_tasks queue. If 'task' has the privilege
+ * flag set, then also push it onto the ready_priority_tasks queue.
+ *
+ * Caller must hold the task manager lock.
+ */
+static inline void
+push_readyq(isc__taskmgr_t *manager, isc__task_t *task) {
+ ENQUEUE(manager->ready_tasks, task, ready_link);
+ if ((task->flags & TASK_F_PRIVILEGED) != 0)
+ ENQUEUE(manager->ready_priority_tasks, task,
+ ready_priority_link);
+}
+
static void
dispatch(isc__taskmgr_t *manager) {
isc__task_t *task;
#ifndef USE_WORKER_THREADS
unsigned int total_dispatch_count = 0;
- isc__tasklist_t ready_tasks;
+ isc__tasklist_t new_ready_tasks;
+ isc__tasklist_t new_priority_tasks;
#endif /* USE_WORKER_THREADS */
REQUIRE(VALID_MANAGER(manager));
@@ -945,9 +1039,11 @@ dispatch(isc__taskmgr_t *manager) {
*/
#ifndef USE_WORKER_THREADS
- ISC_LIST_INIT(ready_tasks);
+ ISC_LIST_INIT(new_ready_tasks);
+ ISC_LIST_INIT(new_priority_tasks);
#endif
LOCK(&manager->lock);
+
while (!FINISHED(manager)) {
#ifdef USE_WORKER_THREADS
/*
@@ -956,10 +1052,12 @@ dispatch(isc__taskmgr_t *manager) {
* the task while only holding the manager lock, and then
* change the task to running state while only holding the
* task lock.
+ *
+ * If a pause has been requested, don't do any work
+ * until it's been released.
*/
- while ((EMPTY(manager->ready_tasks) ||
- manager->exclusive_requested) &&
- !FINISHED(manager))
+ while ((empty_readyq(manager) || manager->pause_requested ||
+ manager->exclusive_requested) && !FINISHED(manager))
{
XTHREADTRACE(isc_msgcat_get(isc_msgcat,
ISC_MSGSET_GENERAL,
@@ -971,13 +1069,13 @@ dispatch(isc__taskmgr_t *manager) {
}
#else /* USE_WORKER_THREADS */
if (total_dispatch_count >= DEFAULT_TASKMGR_QUANTUM ||
- EMPTY(manager->ready_tasks))
+ empty_readyq(manager))
break;
#endif /* USE_WORKER_THREADS */
XTHREADTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TASK,
ISC_MSG_WORKING, "working"));
- task = HEAD(manager->ready_tasks);
+ task = pop_readyq(manager);
if (task != NULL) {
unsigned int dispatch_count = 0;
isc_boolean_t done = ISC_FALSE;
@@ -992,7 +1090,6 @@ dispatch(isc__taskmgr_t *manager) {
* have a task to do. We must reacquire the manager
* lock before exiting the 'if (task != NULL)' block.
*/
- DEQUEUE(manager->ready_tasks, task, ready_link);
manager->tasks_running++;
UNLOCK(&manager->lock);
@@ -1113,6 +1210,9 @@ dispatch(isc__taskmgr_t *manager) {
if (manager->exclusive_requested &&
manager->tasks_running == 1) {
SIGNAL(&manager->exclusive_granted);
+ } else if (manager->pause_requested &&
+ manager->tasks_running == 0) {
+ SIGNAL(&manager->paused);
}
#endif /* USE_WORKER_THREADS */
if (requeue) {
@@ -1136,17 +1236,39 @@ dispatch(isc__taskmgr_t *manager) {
* might even hurt rather than help.
*/
#ifdef USE_WORKER_THREADS
- ENQUEUE(manager->ready_tasks, task,
- ready_link);
+ push_readyq(manager, task);
#else
- ENQUEUE(ready_tasks, task, ready_link);
+ ENQUEUE(new_ready_tasks, task, ready_link);
+ if ((task->flags & TASK_F_PRIVILEGED) != 0)
+ ENQUEUE(new_priority_tasks, task,
+ ready_priority_link);
#endif
}
}
+
+#ifdef USE_WORKER_THREADS
+ /*
+ * If we are in privileged execution mode and there are no
+ * tasks remaining on the current ready queue, then
+ * we're stuck. Automatically drop privileges at that
+ * point and continue with the regular ready queue.
+ */
+ if (manager->tasks_running == 0 && empty_readyq(manager)) {
+ manager->mode = isc_taskmgrmode_normal;
+ if (!empty_readyq(manager))
+ BROADCAST(&manager->work_available);
+ }
+#endif
}
+
#ifndef USE_WORKER_THREADS
- ISC_LIST_APPENDLIST(manager->ready_tasks, ready_tasks, ready_link);
+ ISC_LIST_APPENDLIST(manager->ready_tasks, new_ready_tasks, ready_link);
+ ISC_LIST_APPENDLIST(manager->ready_priority_tasks, new_priority_tasks,
+ ready_priority_link);
+ if (empty_readyq(manager))
+ manager->mode = isc_taskmgrmode_normal;
#endif
+
UNLOCK(&manager->lock);
}
@@ -1181,6 +1303,7 @@ manager_free(isc__taskmgr_t *manager) {
#ifdef USE_WORKER_THREADS
(void)isc_condition_destroy(&manager->exclusive_granted);
(void)isc_condition_destroy(&manager->work_available);
+ (void)isc_condition_destroy(&manager->paused);
isc_mem_free(manager->mctx, manager->threads);
#endif /* USE_WORKER_THREADS */
DESTROYLOCK(&manager->lock);
@@ -1231,6 +1354,7 @@ isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers,
manager->common.methods = &taskmgrmethods;
manager->common.impmagic = TASK_MANAGER_MAGIC;
manager->common.magic = ISCAPI_TASKMGR_MAGIC;
+ manager->mode = isc_taskmgrmode_normal;
manager->mctx = NULL;
result = isc_mutex_init(&manager->lock);
if (result != ISC_R_SUCCESS)
@@ -1260,14 +1384,24 @@ isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers,
result = ISC_R_UNEXPECTED;
goto cleanup_workavailable;
}
+ if (isc_condition_init(&manager->paused) != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "isc_condition_init() %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
+ result = ISC_R_UNEXPECTED;
+ goto cleanup_exclusivegranted;
+ }
#endif /* USE_WORKER_THREADS */
if (default_quantum == 0)
default_quantum = DEFAULT_DEFAULT_QUANTUM;
manager->default_quantum = default_quantum;
INIT_LIST(manager->tasks);
INIT_LIST(manager->ready_tasks);
+ INIT_LIST(manager->ready_priority_tasks);
manager->tasks_running = 0;
manager->exclusive_requested = ISC_FALSE;
+ manager->pause_requested = ISC_FALSE;
manager->exiting = ISC_FALSE;
manager->excl = NULL;
@@ -1304,6 +1438,8 @@ isc__taskmgr_create(isc_mem_t *mctx, unsigned int workers,
return (ISC_R_SUCCESS);
#ifdef USE_WORKER_THREADS
+ cleanup_exclusivegranted:
+ (void)isc_condition_destroy(&manager->exclusive_granted);
cleanup_workavailable:
(void)isc_condition_destroy(&manager->work_available);
cleanup_threads:
@@ -1375,6 +1511,11 @@ isc__taskmgr_destroy(isc_taskmgr_t **managerp) {
manager->exiting = ISC_TRUE;
/*
+ * If privileged mode was on, turn it off.
+ */
+ manager->mode = isc_taskmgrmode_normal;
+
+ /*
* Post shutdown event(s) to every task (if they haven't already been
* posted).
*/
@@ -1383,7 +1524,7 @@ isc__taskmgr_destroy(isc_taskmgr_t **managerp) {
task = NEXT(task, link)) {
LOCK(&task->lock);
if (task_shutdown(task))
- ENQUEUE(manager->ready_tasks, task, ready_link);
+ push_readyq(manager, task);
UNLOCK(&task->lock);
}
#ifdef USE_WORKER_THREADS
@@ -1422,10 +1563,30 @@ isc__taskmgr_destroy(isc_taskmgr_t **managerp) {
*managerp = NULL;
}
+ISC_TASKFUNC_SCOPE void
+isc__taskmgr_setmode(isc_taskmgr_t *manager0, isc_taskmgrmode_t mode) {
+ isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
+
+ LOCK(&manager->lock);
+ manager->mode = mode;
+ UNLOCK(&manager->lock);
+}
+
+ISC_TASKFUNC_SCOPE isc_taskmgrmode_t
+isc__taskmgr_mode(isc_taskmgr_t *manager0) {
+ isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
+ isc_taskmgrmode_t mode;
+ LOCK(&manager->lock);
+ mode = manager->mode;
+ UNLOCK(&manager->lock);
+ return (mode);
+}
+
#ifndef USE_WORKER_THREADS
isc_boolean_t
isc__taskmgr_ready(isc_taskmgr_t *manager0) {
isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
+ isc_boolean_t is_ready;
#ifdef USE_SHARED_MANAGER
if (manager == NULL)
@@ -1433,7 +1594,12 @@ isc__taskmgr_ready(isc_taskmgr_t *manager0) {
#endif
if (manager == NULL)
return (ISC_FALSE);
- return (ISC_TF(!ISC_LIST_EMPTY(manager->ready_tasks)));
+
+ LOCK(&manager->lock);
+ is_ready = !empty_readyq(manager);
+ UNLOCK(&manager->lock);
+
+ return (is_ready);
}
isc_result_t
@@ -1452,6 +1618,29 @@ isc__taskmgr_dispatch(isc_taskmgr_t *manager0) {
return (ISC_R_SUCCESS);
}
+#else
+ISC_TASKFUNC_SCOPE void
+isc__taskmgr_pause(isc_taskmgr_t *manager0) {
+ isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
+ LOCK(&manager->lock);
+ while (manager->tasks_running > 0) {
+ WAIT(&manager->paused, &manager->lock);
+ }
+ manager->pause_requested = ISC_TRUE;
+ UNLOCK(&manager->lock);
+}
+
+ISC_TASKFUNC_SCOPE void
+isc__taskmgr_resume(isc_taskmgr_t *manager0) {
+ isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0;
+
+ LOCK(&manager->lock);
+ if (manager->pause_requested) {
+ manager->pause_requested = ISC_FALSE;
+ BROADCAST(&manager->work_available);
+ }
+ UNLOCK(&manager->lock);
+}
#endif /* USE_WORKER_THREADS */
ISC_TASKFUNC_SCOPE void
@@ -1522,6 +1711,44 @@ isc__task_endexclusive(isc_task_t *task0) {
#endif
}
+ISC_TASKFUNC_SCOPE void
+isc__task_setprivilege(isc_task_t *task0, isc_boolean_t priv) {
+ isc__task_t *task = (isc__task_t *)task0;
+ isc__taskmgr_t *manager = task->manager;
+ isc_boolean_t oldpriv;
+
+ LOCK(&task->lock);
+ oldpriv = ISC_TF((task->flags & TASK_F_PRIVILEGED) != 0);
+ if (priv)
+ task->flags |= TASK_F_PRIVILEGED;
+ else
+ task->flags &= ~TASK_F_PRIVILEGED;
+ UNLOCK(&task->lock);
+
+ if (priv == oldpriv)
+ return;
+
+ LOCK(&manager->lock);
+ if (priv && ISC_LINK_LINKED(task, ready_link))
+ ENQUEUE(manager->ready_priority_tasks, task,
+ ready_priority_link);
+ else if (!priv && ISC_LINK_LINKED(task, ready_priority_link))
+ DEQUEUE(manager->ready_priority_tasks, task,
+ ready_priority_link);
+ UNLOCK(&manager->lock);
+}
+
+ISC_TASKFUNC_SCOPE isc_boolean_t
+isc__task_privilege(isc_task_t *task0) {
+ isc__task_t *task = (isc__task_t *)task0;
+ isc_boolean_t priv;
+
+ LOCK(&task->lock);
+ priv = ISC_TF((task->flags & TASK_F_PRIVILEGED) != 0);
+ UNLOCK(&task->lock);
+ return (priv);
+}
+
#ifdef USE_SOCKETIMPREGISTER
isc_result_t
isc__task_register() {
diff --git a/contrib/bind9/lib/isc/task_api.c b/contrib/bind9/lib/isc/task_api.c
index 06a8d24..f49ab32 100644
--- a/contrib/bind9/lib/isc/task_api.c
+++ b/contrib/bind9/lib/isc/task_api.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2010, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2009-2012 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -99,6 +99,20 @@ isc_taskmgr_destroy(isc_taskmgr_t **managerp) {
ENSURE(*managerp == NULL);
}
+void
+isc_taskmgr_setmode(isc_taskmgr_t *manager, isc_taskmgrmode_t mode) {
+ REQUIRE(ISCAPI_TASKMGR_VALID(manager));
+
+ manager->methods->setmode(manager, mode);
+}
+
+isc_taskmgrmode_t
+isc_taskmgr_mode(isc_taskmgr_t *manager) {
+ REQUIRE(ISCAPI_TASKMGR_VALID(manager));
+
+ return (manager->methods->mode(manager));
+}
+
isc_result_t
isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
isc_task_t **taskp)
@@ -212,6 +226,20 @@ isc_task_endexclusive(isc_task_t *task) {
task->methods->endexclusive(task);
}
+void
+isc_task_setprivilege(isc_task_t *task, isc_boolean_t priv) {
+ REQUIRE(ISCAPI_TASK_VALID(task));
+
+ task->methods->setprivilege(task, priv);
+}
+
+isc_boolean_t
+isc_task_privilege(isc_task_t *task) {
+ REQUIRE(ISCAPI_TASK_VALID(task));
+
+ return (task->methods->privilege(task));
+}
+
/*%
* This is necessary for libisc's internal timer implementation. Other
diff --git a/contrib/bind9/lib/isc/task_p.h b/contrib/bind9/lib/isc/task_p.h
index 85deeae..8c1e4c5 100644
--- a/contrib/bind9/lib/isc/task_p.h
+++ b/contrib/bind9/lib/isc/task_p.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007, 2009, 2012 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -22,10 +22,18 @@
/*! \file */
+#if defined(BIND9) && defined(ISC_PLATFORM_USETHREADS)
+void
+isc__taskmgr_pause(isc_taskmgr_t *taskmgr);
+
+void
+isc__taskmgr_resume(isc_taskmgr_t *taskmgr);
+#else
isc_boolean_t
isc__taskmgr_ready(isc_taskmgr_t *taskmgr);
isc_result_t
isc__taskmgr_dispatch(isc_taskmgr_t *taskmgr);
+#endif /* !BIND9 || !ISC_PLATFORM_USETHREADS */
#endif /* ISC_TASK_P_H */
diff --git a/contrib/bind9/lib/isc/taskpool.c b/contrib/bind9/lib/isc/taskpool.c
index 7324cfa..a5ce0e8 100644
--- a/contrib/bind9/lib/isc/taskpool.c
+++ b/contrib/bind9/lib/isc/taskpool.c
@@ -165,9 +165,8 @@ isc_taskpool_destroy(isc_taskpool_t **poolp) {
unsigned int i;
isc_taskpool_t *pool = *poolp;
for (i = 0; i < pool->ntasks; i++) {
- if (pool->tasks[i] != NULL) {
+ if (pool->tasks[i] != NULL)
isc_task_detach(&pool->tasks[i]);
- }
}
isc_mem_put(pool->mctx, pool->tasks,
pool->ntasks * sizeof(isc_task_t *));
@@ -175,4 +174,14 @@ isc_taskpool_destroy(isc_taskpool_t **poolp) {
*poolp = NULL;
}
+void
+isc_taskpool_setprivilege(isc_taskpool_t *pool, isc_boolean_t priv) {
+ unsigned int i;
+
+ REQUIRE(pool != NULL);
+ for (i = 0; i < pool->ntasks; i++) {
+ if (pool->tasks[i] != NULL)
+ isc_task_setprivilege(pool->tasks[i], priv);
+ }
+}
diff --git a/contrib/bind9/lib/isc/unix/socket.c b/contrib/bind9/lib/isc/unix/socket.c
index d007598..7bd12aa 100644
--- a/contrib/bind9/lib/isc/unix/socket.c
+++ b/contrib/bind9/lib/isc/unix/socket.c
@@ -334,7 +334,8 @@ struct isc__socket {
listener : 1, /* listener socket */
connected : 1,
connecting : 1, /* connect pending */
- bound : 1; /* bound to local addr */
+ bound : 1, /* bound to local addr */
+ dupped : 1;
#ifdef ISC_NET_RECVOVERFLOW
unsigned char overflow; /* used for MSG_TRUNC fake */
@@ -428,6 +429,10 @@ static isc__socketmgr_t *socketmgr = NULL;
# define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER)
#endif
+static isc_result_t socket_create(isc_socketmgr_t *manager0, int pf,
+ isc_sockettype_t type,
+ isc_socket_t **socketp,
+ isc_socket_t *dup_socket);
static void send_recvdone_event(isc__socket_t *, isc_socketevent_t **);
static void send_senddone_event(isc__socket_t *, isc_socketevent_t **);
static void free_socket(isc__socket_t **);
@@ -546,6 +551,10 @@ isc__socket_fdwatchcreate(isc_socketmgr_t *manager, int fd, int flags,
isc_task_t *task, isc_socket_t **socketp);
ISC_SOCKETFUNC_SCOPE isc_result_t
isc__socket_fdwatchpoke(isc_socket_t *sock, int flags);
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_dup(isc_socket_t *sock, isc_socket_t **socketp);
+ISC_SOCKETFUNC_SCOPE int
+isc__socket_getfd(isc_socket_t *sock);
static struct {
isc_socketmethods_t methods;
@@ -563,13 +572,17 @@ static struct {
isc__socket_detach,
isc__socket_bind,
isc__socket_sendto,
+ isc__socket_sendto2,
isc__socket_connect,
isc__socket_recv,
+ isc__socket_recv2,
isc__socket_cancel,
isc__socket_getsockname,
isc__socket_gettype,
isc__socket_ipv6only,
- isc__socket_fdwatchpoke
+ isc__socket_fdwatchpoke,
+ isc__socket_dup,
+ isc__socket_getfd
}
#ifndef BIND9
,
@@ -2046,6 +2059,7 @@ allocate_socket(isc__socketmgr_t *manager, isc_sockettype_t type,
sock->manager = manager;
sock->type = type;
sock->fd = -1;
+ sock->dupped = 0;
sock->statsindex = NULL;
ISC_LINK_INIT(sock, link);
@@ -2251,7 +2265,9 @@ use_min_mtu(isc__socket_t *sock) {
}
static isc_result_t
-opensocket(isc__socketmgr_t *manager, isc__socket_t *sock) {
+opensocket(isc__socketmgr_t *manager, isc__socket_t *sock,
+ isc__socket_t *dup_socket)
+{
isc_result_t result;
char strbuf[ISC_STRERRORSIZE];
const char *err = "socket";
@@ -2265,22 +2281,29 @@ opensocket(isc__socketmgr_t *manager, isc__socket_t *sock) {
#endif
again:
- switch (sock->type) {
- case isc_sockettype_udp:
- sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_UDP);
- break;
- case isc_sockettype_tcp:
- sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP);
- break;
- case isc_sockettype_unix:
- sock->fd = socket(sock->pf, SOCK_STREAM, 0);
- break;
- case isc_sockettype_fdwatch:
- /*
- * We should not be called for isc_sockettype_fdwatch sockets.
- */
- INSIST(0);
- break;
+ if (dup_socket == NULL) {
+ switch (sock->type) {
+ case isc_sockettype_udp:
+ sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_UDP);
+ break;
+ case isc_sockettype_tcp:
+ sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP);
+ break;
+ case isc_sockettype_unix:
+ sock->fd = socket(sock->pf, SOCK_STREAM, 0);
+ break;
+ case isc_sockettype_fdwatch:
+ /*
+ * We should not be called for isc_sockettype_fdwatch
+ * sockets.
+ */
+ INSIST(0);
+ break;
+ }
+ } else {
+ sock->fd = dup(dup_socket->fd);
+ sock->dupped = 1;
+ sock->bound = dup_socket->bound;
}
if (sock->fd == -1 && errno == EINTR && tries++ < 42)
goto again;
@@ -2357,6 +2380,9 @@ opensocket(isc__socketmgr_t *manager, isc__socket_t *sock) {
}
}
+ if (dup_socket != NULL)
+ goto setup_done;
+
result = make_nonblock(sock->fd);
if (result != ISC_R_SUCCESS) {
(void)close(sock->fd);
@@ -2521,20 +2547,21 @@ opensocket(isc__socketmgr_t *manager, isc__socket_t *sock) {
}
#endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */
+setup_done:
inc_stats(manager->stats, sock->statsindex[STATID_OPEN]);
return (ISC_R_SUCCESS);
}
-/*%
- * Create a new 'type' socket managed by 'manager'. Events
- * will be posted to 'task' and when dispatched 'action' will be
- * called with 'arg' as the arg value. The new socket is returned
- * in 'socketp'.
+/*
+ * Create a 'type' socket or duplicate an existing socket, managed
+ * by 'manager'. Events will be posted to 'task' and when dispatched
+ * 'action' will be called with 'arg' as the arg value. The new
+ * socket is returned in 'socketp'.
*/
-ISC_SOCKETFUNC_SCOPE isc_result_t
-isc__socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type,
- isc_socket_t **socketp)
+static isc_result_t
+socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type,
+ isc_socket_t **socketp, isc_socket_t *dup_socket)
{
isc__socket_t *sock = NULL;
isc__socketmgr_t *manager = (isc__socketmgr_t *)manager0;
@@ -2566,7 +2593,8 @@ isc__socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type,
}
sock->pf = pf;
- result = opensocket(manager, sock);
+
+ result = opensocket(manager, sock, (isc__socket_t *)dup_socket);
if (result != ISC_R_SUCCESS) {
inc_stats(manager->stats, sock->statsindex[STATID_OPENFAIL]);
free_socket(&sock);
@@ -2601,11 +2629,40 @@ isc__socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type,
UNLOCK(&manager->lock);
socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
- ISC_MSG_CREATED, "created");
+ ISC_MSG_CREATED, dup_socket != NULL ? "dupped" : "created");
return (ISC_R_SUCCESS);
}
+/*%
+ * Create a new 'type' socket managed by 'manager'. Events
+ * will be posted to 'task' and when dispatched 'action' will be
+ * called with 'arg' as the arg value. The new socket is returned
+ * in 'socketp'.
+ */
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_create(isc_socketmgr_t *manager0, int pf, isc_sockettype_t type,
+ isc_socket_t **socketp)
+{
+ return (socket_create(manager0, pf, type, socketp, NULL));
+}
+
+/*%
+ * Duplicate an existing socket. The new socket is returned
+ * in 'socketp'.
+ */
+ISC_SOCKETFUNC_SCOPE isc_result_t
+isc__socket_dup(isc_socket_t *sock0, isc_socket_t **socketp) {
+ isc__socket_t *sock = (isc__socket_t *)sock0;
+
+ REQUIRE(VALID_SOCKET(sock));
+ REQUIRE(socketp != NULL && *socketp == NULL);
+
+ return (socket_create((isc_socketmgr_t *) sock->manager,
+ sock->pf, sock->type, socketp,
+ sock0));
+}
+
#ifdef BIND9
ISC_SOCKETFUNC_SCOPE isc_result_t
isc__socket_open(isc_socket_t *sock0) {
@@ -2624,7 +2681,7 @@ isc__socket_open(isc_socket_t *sock0) {
*/
REQUIRE(sock->fd == -1);
- result = opensocket(sock->manager, sock);
+ result = opensocket(sock->manager, sock, NULL);
if (result != ISC_R_SUCCESS)
sock->fd = -1;
@@ -2804,6 +2861,7 @@ isc__socket_close(isc_socket_t *sock0) {
int fd;
isc__socketmgr_t *manager;
+ fflush(stdout);
REQUIRE(VALID_SOCKET(sock));
LOCK(&sock->lock);
@@ -2824,6 +2882,7 @@ isc__socket_close(isc_socket_t *sock0) {
manager = sock->manager;
fd = sock->fd;
sock->fd = -1;
+ sock->dupped = 0;
memset(sock->name, 0, sizeof(sock->name));
sock->tag = NULL;
sock->listener = 0;
@@ -4991,11 +5050,13 @@ isc__socket_bind(isc_socket_t *sock0, isc_sockaddr_t *sockaddr,
LOCK(&sock->lock);
INSIST(!sock->bound);
+ INSIST(!sock->dupped);
if (sock->pf != sockaddr->type.sa.sa_family) {
UNLOCK(&sock->lock);
return (ISC_R_FAMILYMISMATCH);
}
+
/*
* Only set SO_REUSEADDR when we want a specific port.
*/
@@ -5680,6 +5741,7 @@ isc__socket_ipv6only(isc_socket_t *sock0, isc_boolean_t yes) {
#endif
REQUIRE(VALID_SOCKET(sock));
+ INSIST(!sock->dupped);
#ifdef IPV6_V6ONLY
if (sock->pf == AF_INET6) {
@@ -5846,6 +5908,13 @@ isc__socket_register() {
}
#endif
+ISC_SOCKETFUNC_SCOPE int
+isc__socket_getfd(isc_socket_t *socket0) {
+ isc__socket_t *socket = (isc__socket_t *)socket0;
+
+ return ((short) socket->fd);
+}
+
#if defined(HAVE_LIBXML2) && defined(BIND9)
static const char *
OpenPOWER on IntegriCloud