summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authordougb <dougb@FreeBSD.org>2008-12-23 18:35:21 +0000
committerdougb <dougb@FreeBSD.org>2008-12-23 18:35:21 +0000
commit6c8226d7d6bb16d3d0bc2ab68a30b0700011c64f (patch)
treed25d756be8550df073eb3ed4e5b39831380291b5 /lib
parente2c9b86ef6b41282513a874faaf6d208422cfc7b (diff)
downloadFreeBSD-src-6c8226d7d6bb16d3d0bc2ab68a30b0700011c64f.zip
FreeBSD-src-6c8226d7d6bb16d3d0bc2ab68a30b0700011c64f.tar.gz
Vendor import of BIND 9.4.3
Diffstat (limited to 'lib')
-rw-r--r--lib/bind/api6
-rw-r--r--lib/bind/bsd/Makefile.in8
-rw-r--r--lib/bind/bsd/strerror.c6
-rw-r--r--lib/bind/bsd/strtoul.c10
-rw-r--r--lib/bind/configure.in217
-rw-r--r--lib/bind/dst/Makefile.in8
-rw-r--r--lib/bind/dst/dst_api.c2
-rw-r--r--lib/bind/dst/hmac_link.c2
-rw-r--r--lib/bind/dst/support.c2
-rw-r--r--lib/bind/include/Makefile.in8
-rw-r--r--lib/bind/include/arpa/nameser.h5
-rw-r--r--lib/bind/include/isc/assertions.h7
-rw-r--r--lib/bind/include/isc/eventlib.h4
-rw-r--r--lib/bind/include/isc/misc.h3
-rw-r--r--lib/bind/include/isc/platform.h.in36
-rw-r--r--lib/bind/include/netdb.h4
-rw-r--r--lib/bind/include/resolv.h6
-rw-r--r--lib/bind/inet/Makefile.in8
-rw-r--r--lib/bind/inet/inet_net_pton.c6
-rw-r--r--lib/bind/inet/inet_network.c4
-rw-r--r--lib/bind/irs/Makefile.in8
-rw-r--r--lib/bind/irs/dns_ho.c11
-rw-r--r--lib/bind/irs/getnetgrent.c6
-rw-r--r--lib/bind/irs/getnetgrent_r.c81
-rw-r--r--lib/bind/irs/irp.c5
-rw-r--r--lib/bind/isc/Makefile.in8
-rw-r--r--lib/bind/isc/assertions.c3
-rw-r--r--lib/bind/isc/bitncmp.c4
-rw-r--r--lib/bind/isc/ctl_clnt.c5
-rw-r--r--lib/bind/isc/ctl_srvr.c5
-rw-r--r--lib/bind/isc/logging.c12
-rw-r--r--lib/bind/nameser/Makefile.in8
-rw-r--r--lib/bind/port_after.h.in114
-rw-r--r--lib/bind/port_before.h.in13
-rw-r--r--lib/bind/resolv/Makefile.in8
-rw-r--r--lib/bind/resolv/res_debug.c55
-rw-r--r--lib/bind/resolv/res_mkquery.c66
-rw-r--r--lib/bind/resolv/res_query.c14
-rw-r--r--lib/bind/resolv/res_send.c28
-rw-r--r--lib/bind9/api2
-rw-r--r--lib/bind9/check.c124
-rw-r--r--lib/dns/acache.c50
-rw-r--r--lib/dns/adb.c64
-rw-r--r--lib/dns/api2
-rw-r--r--lib/dns/cache.c37
-rw-r--r--lib/dns/dispatch.c1330
-rw-r--r--lib/dns/dst_parse.c8
-rw-r--r--lib/dns/dst_parse.h8
-rw-r--r--lib/dns/include/dns/dispatch.h64
-rw-r--r--lib/dns/journal.c30
-rw-r--r--lib/dns/master.c34
-rw-r--r--lib/dns/masterdump.c23
-rw-r--r--lib/dns/message.c13
-rw-r--r--lib/dns/rbt.c40
-rw-r--r--lib/dns/rbtdb.c78
-rw-r--r--lib/dns/rdata/generic/nsec_47.c10
-rw-r--r--lib/dns/rdata/generic/nsec_47.h8
-rw-r--r--lib/dns/rdata/generic/txt_16.c8
-rw-r--r--lib/dns/rdata/in_1/apl_42.c67
-rw-r--r--lib/dns/rdata/in_1/naptr_35.c14
-rw-r--r--lib/dns/request.c94
-rw-r--r--lib/dns/resolver.c335
-rw-r--r--lib/dns/rootns.c48
-rw-r--r--lib/dns/sdb.c16
-rw-r--r--lib/dns/tkey.c14
-rw-r--r--lib/dns/tsig.c76
-rw-r--r--lib/dns/validator.c110
-rw-r--r--lib/dns/view.c21
-rw-r--r--lib/dns/xfrin.c26
-rw-r--r--lib/dns/zone.c62
-rw-r--r--lib/isc/Makefile.in8
-rw-r--r--lib/isc/api4
-rw-r--r--lib/isc/assertions.c7
-rw-r--r--lib/isc/include/isc/assertions.h11
-rw-r--r--lib/isc/include/isc/lex.h8
-rw-r--r--lib/isc/include/isc/mem.h86
-rw-r--r--lib/isc/include/isc/msgs.h13
-rw-r--r--lib/isc/include/isc/platform.h.in25
-rw-r--r--lib/isc/include/isc/portset.h141
-rw-r--r--lib/isc/include/isc/resource.h15
-rw-r--r--lib/isc/include/isc/socket.h77
-rw-r--r--lib/isc/include/isc/timer.h2
-rw-r--r--lib/isc/include/isc/types.h7
-rw-r--r--lib/isc/mem.c46
-rw-r--r--lib/isc/portset.c143
-rw-r--r--lib/isc/print.c95
-rw-r--r--lib/isc/pthreads/mutex.c78
-rw-r--r--lib/isc/timer.c4
-rw-r--r--lib/isc/unix/app.c37
-rw-r--r--lib/isc/unix/include/isc/net.h27
-rw-r--r--lib/isc/unix/net.c161
-rw-r--r--lib/isc/unix/resource.c61
-rw-r--r--lib/isc/unix/socket.c1674
-rw-r--r--lib/isc/unix/socket_p.h15
-rw-r--r--lib/isc/unix/time.c10
-rw-r--r--lib/isccfg/api2
-rw-r--r--lib/isccfg/namedconf.c170
-rw-r--r--lib/lwres/api2
98 files changed, 4925 insertions, 1626 deletions
diff --git a/lib/bind/api b/lib/bind/api
index a87852a..7ffeba8 100644
--- a/lib/bind/api
+++ b/lib/bind/api
@@ -1,3 +1,3 @@
-LIBINTERFACE = 4
-LIBREVISION = 10
-LIBAGE = 0
+LIBINTERFACE = 5
+LIBREVISION = 2
+LIBAGE = 1
diff --git a/lib/bind/bsd/Makefile.in b/lib/bind/bsd/Makefile.in
index cf70c10..72a52f6 100644
--- a/lib/bind/bsd/Makefile.in
+++ b/lib/bind/bsd/Makefile.in
@@ -1,7 +1,7 @@
-# Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004, 2008 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 2001 Internet Software Consortium.
#
-# Permission to use, copy, modify, and distribute this software for any
+# 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.
#
@@ -13,7 +13,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.7 2004/03/05 05:05:07 marka Exp $
+# $Id: Makefile.in,v 1.7.18.2 2008/03/20 23:46:01 tbox Exp $
srcdir= @srcdir@
VPATH = @srcdir@
@@ -34,6 +34,6 @@ SRCS= daemon.c ftruncate.c gettimeofday.c mktemp.c putenv.c \
TARGETS= ${OBJS}
-CINCLUDES= -I.. -I${srcdir}/../include
+CINCLUDES= -I.. -I../include -I${srcdir}/../include
@BIND9_MAKE_RULES@
diff --git a/lib/bind/bsd/strerror.c b/lib/bind/bsd/strerror.c
index 5743398..325cd52 100644
--- a/lib/bind/bsd/strerror.c
+++ b/lib/bind/bsd/strerror.c
@@ -1,6 +1,6 @@
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "@(#)strerror.c 8.1 (Berkeley) 6/4/93";
-static const char rcsid[] = "$Id: strerror.c,v 1.4.332.1 2005/04/27 05:00:46 sra Exp $";
+static const char rcsid[] = "$Id: strerror.c,v 1.4.332.2 2008/02/18 04:04:06 marka Exp $";
#endif /* LIBC_SCCS and not lint */
/*
@@ -60,12 +60,14 @@ isc_strerror(int num) {
static char ebuf[40] = UPREFIX; /*%< 64-bit number + slop */
u_int errnum;
char *p, *t;
+#ifndef USE_SYSERROR_LIST
const char *ret;
+#endif
char tmp[40];
errnum = num; /*%< convert to unsigned */
#ifdef USE_SYSERROR_LIST
- if (errnum < sys_nerr)
+ if (errnum < (u_int)sys_nerr)
return (sys_errlist[errnum]);
#else
#undef strerror
diff --git a/lib/bind/bsd/strtoul.c b/lib/bind/bsd/strtoul.c
index f419227..c2efeda 100644
--- a/lib/bind/bsd/strtoul.c
+++ b/lib/bind/bsd/strtoul.c
@@ -1,6 +1,6 @@
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93";
-static const char rcsid[] = "$Id: strtoul.c,v 1.2.164.1 2005/04/27 05:00:47 sra Exp $";
+static const char rcsid[] = "$Id: strtoul.c,v 1.2.164.2 2008/02/18 04:04:06 marka Exp $";
#endif /* LIBC_SCCS and not lint */
/*
@@ -70,7 +70,7 @@ strtoul(const char *nptr, char **endptr, int base) {
* See strtol for comments as to the logic used.
*/
do {
- c = *(unsigned char *)s++;
+ c = *(const unsigned char *)s++;
} while (isspace(c));
if (c == '-') {
neg = 1;
@@ -87,7 +87,7 @@ strtoul(const char *nptr, char **endptr, int base) {
base = c == '0' ? 8 : 10;
cutoff = (u_long)ULONG_MAX / (u_long)base;
cutlim = (u_long)ULONG_MAX % (u_long)base;
- for (acc = 0, any = 0;; c = *(unsigned char*)s++) {
+ for (acc = 0, any = 0;; c = *(const unsigned char*)s++) {
if (isdigit(c))
c -= '0';
else if (isalpha(c))
@@ -96,7 +96,7 @@ strtoul(const char *nptr, char **endptr, int base) {
break;
if (c >= base)
break;
- if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else {
any = 1;
@@ -110,7 +110,7 @@ strtoul(const char *nptr, char **endptr, int base) {
} else if (neg)
acc = -acc;
if (endptr != 0)
- *endptr = (char *)(any ? s - 1 : nptr);
+ DE_CONST((any ? s - 1 : nptr), *endptr);
return (acc);
}
diff --git a/lib/bind/configure.in b/lib/bind/configure.in
index 6e98c5c..9b9b53b 100644
--- a/lib/bind/configure.in
+++ b/lib/bind/configure.in
@@ -13,7 +13,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-AC_REVISION($Revision: 1.90.18.34.10.2 $)
+AC_REVISION($Revision: 1.90.18.43 $)
AC_INIT(resolv/herror.c)
AC_PREREQ(2.13)
@@ -169,7 +169,7 @@ AC_PROG_CC
AC_HEADER_STDC
-AC_CHECK_HEADERS(fcntl.h db.h paths.h sys/time.h unistd.h sys/sockio.h sys/select.h sys/timers.h stropts.h)
+AC_CHECK_HEADERS(fcntl.h db.h paths.h sys/time.h unistd.h sys/sockio.h sys/select.h sys/timers.h stropts.h memory.h)
AC_C_CONST
AC_C_INLINE
@@ -461,6 +461,7 @@ AC_SUBST(WANT_THREADS_OBJS)
AC_CHECK_FUNC(strlcat, AC_DEFINE(HAVE_STRLCAT))
AC_CHECK_FUNC(memmove, AC_DEFINE(HAVE_MEMMOVE))
AC_CHECK_FUNC(memchr, AC_DEFINE(HAVE_MEMCHR))
+AC_CHECK_FUNC(strtoul, , AC_DEFINE(NEED_STRTOUL))
AC_CHECK_FUNC(if_nametoindex,
[USE_IFNAMELINKID="#define USE_IFNAMELINKID 1"],
@@ -490,6 +491,16 @@ AC_CHECK_FUNC(strerror, [NEED_STRERROR="#undef NEED_STRERROR"],
[NEED_STRERROR="#define NEED_STRERROR 1"])
AC_SUBST(NEED_STRERROR)
+if test -n "$NEED_STRERROR"
+then
+ AC_MSG_CHECKING([for extern char * sys_errlist[]])
+ AC_TRY_LINK([ extern int sys_nerr; extern char *sys_errlist[]; ],
+ [ const char *p = sys_errlist[0]; ],
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(USE_SYSERROR_LIST),
+ AC_MSG_RESULT(no))
+fi
+
#
# flockfile is usually provided by pthreads, but we may want to use it
# even if compiled with --disable-threads.
@@ -666,6 +677,14 @@ AC_SUBST(PURIFY)
#
# GNU libtool support
#
+case $host in
+sunos*)
+ # Just set the maximum command line length for sunos as it otherwise
+ # takes a exceptionally long time to work it out. Required for libtool.
+ lt_cv_sys_max_cmd_len=4096;
+ ;;
+esac
+
AC_ARG_WITH(libtool,
[ --with-libtool use GNU libtool (following indented options supported)],
use_libtool="$withval", use_libtool="no")
@@ -976,6 +995,8 @@ AC_SUBST(ISC_PLATFORM_NEEDATON)
#
case "$host" in
*-dec-osf*)
+ # Tru64 broke send() by defining it to send_OBSOLETE
+ AC_DEFINE(REENABLE_SEND)
# Turn on 4.4BSD style sa_len support.
AC_DEFINE(_SOCKADDR_LEN)
;;
@@ -1050,6 +1071,7 @@ case "$host" in
*-qnx*) PORT_DIR="port/qnx";;
*-rhapsody*) PORT_DIR="port/rhapsody";;
*-sunos4*)
+ AC_DEFINE(NEED_SUN4PROTOS)
PORT_NONBLOCK="#define PORT_NONBLOCK O_NDELAY"
PORT_DIR="port/sunos";;
*-solaris2.[[01234]])
@@ -1246,6 +1268,38 @@ found_rt_iflist
AC_CHECK_FUNC(strsep,
[ISC_PLATFORM_NEEDSTRSEP="#undef ISC_PLATFORM_NEEDSTRSEP"],
[ISC_PLATFORM_NEEDSTRSEP="#define ISC_PLATFORM_NEEDSTRSEP 1"])
+
+
+AC_MSG_CHECKING(for char *sprintf)
+AC_TRY_COMPILE([
+#include <stdio.h>
+],
+[ char buf[2]; return(*sprintf(buf,"x"));],
+AC_DEFINE(SPRINTF_CHAR)
+AC_MSG_RESULT(yes)
+,
+AC_MSG_RESULT(no)
+)
+
+AC_MSG_CHECKING(for char *vsprintf)
+case $host in
+*sunos4*) # not decared in any header file.
+AC_DEFINE(VSPRINTF_CHAR)
+AC_MSG_RESULT(yes)
+;;
+*)
+AC_TRY_COMPILE([
+#include <stdio.h>
+],
+[ char buf[2]; return(*vsprintf(buf,"x"));],
+AC_DEFINE(VSPRINTF_CHAR)
+AC_MSG_RESULT(yes)
+,
+AC_MSG_RESULT(no)
+)
+;;
+esac
+
AC_CHECK_FUNC(vsnprintf,
[ISC_PLATFORM_NEEDVSNPRINTF="#undef ISC_PLATFORM_NEEDVSNPRINTF"],
[ISC_EXTRA_OBJS="$ISC_EXTRA_OBJS print.$O"
@@ -1256,12 +1310,7 @@ AC_SUBST(ISC_PLATFORM_NEEDVSNPRINTF)
AC_SUBST(ISC_EXTRA_OBJS)
AC_SUBST(ISC_EXTRA_SRCS)
-AC_CHECK_FUNC(strerror,
- [USE_SYSERROR_LIST="#undef USE_SYSERROR_LIST"],
- [USE_SYSERROR_LIST="#define USE_SYSERROR_LIST 1"])
-AC_SUBST(USE_SYSERROR_LIST)
-#
# Determine the printf format characters to use when printing
# values of type isc_int64_t. We make the assumption that platforms
# where a "long long" is the same size as a "long" (e.g., Alpha/OSF1)
@@ -1865,19 +1914,37 @@ AC_SUBST(SETGRENT_VOID)
case $host in
ia64-hp-hpux11.*)
+NGR_R_CONST="#define NGR_R_CONST"
;;
+*-hp-hpux11.*)
+#
+# HPUX doesn't have a prototype for getnetgrent_r().
+#
+NGR_R_CONST="#define NGR_R_CONST"
+NGR_R_ARGS="#define NGR_R_ARGS char *buf, int buflen"
+NGR_R_BAD="#define NGR_R_BAD (0)"
+NGR_R_COPY="#define NGR_R_COPY buf, buflen"
+NGR_R_COPY_ARGS="#define NGR_R_COPY_ARGS NGR_R_ARGS"
+NGR_R_OK="#define NGR_R_OK 1"
+NGR_R_RETURN="#define NGR_R_RETURN int"
+;;
+
*)
AC_CHECK_FUNC(getnetgrent_r,
AC_TRY_COMPILE(
[
#undef __USE_MISC
#define __USE_MISC
+#undef _REEENTRANT
+#define _REEENTRANT
#include <netdb.h>
+#include <unistd.h>
int getnetgrent_r(char **m, char **u, char **d, char *b, int l) {}
]
,
[return (0);],
[
+NGR_R_CONST="#define NGR_R_CONST"
NGR_R_ARGS="#define NGR_R_ARGS char *buf, int buflen"
NGR_R_BAD="#define NGR_R_BAD (0)"
NGR_R_COPY="#define NGR_R_COPY buf, buflen"
@@ -1890,12 +1957,16 @@ AC_TRY_COMPILE(
[
#undef __USE_MISC
#define __USE_MISC
+#undef _REEENTRANT
+#define _REEENTRANT
#include <netdb.h>
+#include <unistd.h>
int getnetgrent_r(char **m, char **u, char **d, char *b, size_t l) {}
]
,
[return (0);],
[
+NGR_R_CONST="#define NGR_R_CONST"
NGR_R_ARGS="#define NGR_R_ARGS char *buf, size_t buflen"
NGR_R_BAD="#define NGR_R_BAD (0)"
NGR_R_COPY="#define NGR_R_COPY buf, buflen"
@@ -1908,12 +1979,16 @@ AC_TRY_COMPILE(
[
#undef __USE_MISC
#define __USE_MISC
+#undef _REEENTRANT
+#define _REEENTRANT
#include <netdb.h>
-extern int getnetgrent_r( char **, char **, char **, void **);
+#include <unistd.h>
+extern int getnetgrent_r(char **, char **, char **, void **);
]
,
[return (0);],
[
+NGR_R_CONST="#define NGR_R_CONST"
NGR_R_ARGS="#define NGR_R_ARGS void **buf"
NGR_R_BAD="#define NGR_R_BAD (0)"
NGR_R_COPY="#define NGR_R_COPY buf"
@@ -1923,10 +1998,35 @@ NGR_R_RETURN="#define NGR_R_RETURN int"
NGR_R_PRIVATE="#define NGR_R_PRIVATE 1"
]
,
+AC_TRY_COMPILE(
+[
+#undef __USE_MISC
+#define __USE_MISC
+#undef _REEENTRANT
+#define _REEENTRANT
+#include <netdb.h>
+#include <unistd.h>
+extern int getnetgrent_r(const char **, const char **, const char **, void *);
+]
+,
+[return (0);],
+[
+NGR_R_CONST="#define NGR_R_CONST const"
+NGR_R_ARGS="#define NGR_R_ARGS void *buf"
+NGR_R_BAD="#define NGR_R_BAD (0)"
+NGR_R_COPY="#define NGR_R_COPY buf"
+NGR_R_COPY_ARGS="#define NGR_R_COPY_ARGS NGR_R_ARGS"
+NGR_R_OK="#define NGR_R_OK 1"
+NGR_R_RETURN="#define NGR_R_RETURN int"
+NGR_R_PRIVATE="#define NGR_R_PRIVATE 2"
+]
+,
+)
)
)
)
,
+NGR_R_CONST="#define NGR_R_CONST"
NGR_R_ARGS="#define NGR_R_ARGS char *buf, int buflen"
NGR_R_BAD="#define NGR_R_BAD (0)"
NGR_R_COPY="#define NGR_R_COPY buf, buflen"
@@ -1935,6 +2035,7 @@ NGR_R_OK="#define NGR_R_OK 1"
NGR_R_RETURN="#define NGR_R_RETURN int"
)
esac
+AC_SUBST(NGR_R_CONST)
AC_SUBST(NGR_R_ARGS)
AC_SUBST(NGR_R_BAD)
AC_SUBST(NGR_R_COPY)
@@ -1948,7 +2049,10 @@ AC_TRY_COMPILE(
[
#undef __USE_MISC
#define __USE_MISC
+#undef _REEENTRANT
+#define _REEENTRANT
#include <netdb.h>
+#include <unistd.h>
void endnetgrent_r(void **ptr);
]
,
@@ -1957,44 +2061,128 @@ void endnetgrent_r(void **ptr);
[
NGR_R_END_RESULT="#define NGR_R_END_RESULT(x) /* empty */"
NGR_R_END_RETURN="#define NGR_R_END_RETURN void"
-NGR_R_ENT_ARGS="#define NGR_R_ENT_ARGS NGR_R_ARGS"
+NGR_R_END_ARGS="#define NGR_R_END_ARGS NGR_R_ARGS"
+]
+,
+AC_TRY_COMPILE(
+[
+#undef __USE_MISC
+#define __USE_MISC
+#undef _REEENTRANT
+#define _REEENTRANT
+#include <netdb.h>
+#include <unistd.h>
+void endnetgrent_r(void *ptr);
+]
+,
+[return (0);]
+,
+[
+NGR_R_END_RESULT="#define NGR_R_END_RESULT(x) /* empty */"
+NGR_R_END_RETURN="#define NGR_R_END_RETURN void"
+NGR_R_END_ARGS="#define NGR_R_END_ARGS void *buf"
]
,
[
NGR_R_END_RESULT="#define NGR_R_END_RESULT(x) return (x)"
NGR_R_END_RETURN="#define NGR_R_END_RETURN int"
-NGR_R_ENT_ARGS="#define NGR_R_ENT_ARGS NGR_R_ARGS"
+NGR_R_END_ARGS="#define NGR_R_END_ARGS NGR_R_ARGS"
]
)
+)
,
NGR_R_END_RESULT="#define NGR_R_END_RESULT(x) /*empty*/"
NGR_R_END_RETURN="#define NGR_R_END_RETURN void"
-NGR_R_ENT_ARGS="#undef NGR_R_ENT_ARGS /*empty*/"
+NGR_R_END_ARGS="#undef NGR_R_END_ARGS /*empty*/"
AC_DEFINE(NEED_ENDNETGRENT_R)
)
AC_SUBST(NGR_R_END_RESULT)
AC_SUBST(NGR_R_END_RETURN)
-AC_SUBST(NGR_R_ENT_ARGS)
+AC_SUBST(NGR_R_END_ARGS)
AC_CHECK_FUNC(setnetgrent_r,
[
case "$host" in
*bsdi*)
+ #
+ # No prototype
+ #
NGR_R_SET_RESULT="#undef NGR_R_SET_RESULT /*empty*/"
NGR_R_SET_RETURN="#define NGR_R_SET_RETURN void"
+ NGR_R_SET_ARGS="#define NGR_R_SET_ARGS NGR_R_ARGS"
+ NGR_R_SET_CONST="#define NGR_R_SET_CONST"
;;
-*)
+*hpux*)
+ #
+ # No prototype
+ #
NGR_R_SET_RESULT="#define NGR_R_SET_RESULT NGR_R_OK"
NGR_R_SET_RETURN="#define NGR_R_SET_RETURN int"
+ NGR_R_SET_ARGS="#undef NGR_R_SET_ARGS /* empty */"
+ NGR_R_SET_CONST="#define NGR_R_SET_CONST"
;;
+*)
+AC_TRY_COMPILE(
+[
+#undef __USE_MISC
+#define __USE_MISC
+#undef _REEENTRANT
+#define _REEENTRANT
+#include <netdb.h>
+#include <unistd.h>
+void setnetgrent_r(void **ptr);
+]
+,
+[return (0);]
+,
+[
+NGR_R_SET_RESULT="#undef NGR_R_SET_RESULT /* empty */"
+NGR_R_SET_RETURN="#define NGR_R_SET_RETURN void"
+NGR_R_SET_ARGS="#define NGR_R_SET_ARGS void **buf"
+NGR_R_SET_CONST="#define NGR_R_SET_CONST"
+]
+,
+AC_TRY_COMPILE(
+[
+#undef __USE_MISC
+#define __USE_MISC
+#undef _REEENTRANT
+#define _REEENTRANT
+#include <netdb.h>
+#include <unistd.h>
+extern int setnetgrent_r(char *, void **);
+]
+,
+[return (0);]
+,
+[
+NGR_R_SET_RESULT="#define NGR_R_SET_RESULT NGR_R_OK"
+NGR_R_SET_RETURN="#define NGR_R_SET_RETURN int"
+NGR_R_SET_ARGS="#define NGR_R_SET_ARGS void **buf"
+NGR_R_SET_CONST="#define NGR_R_SET_CONST"
+]
+,
+[
+NGR_R_SET_RESULT="#define NGR_R_SET_RESULT NGR_R_OK"
+NGR_R_SET_RETURN="#define NGR_R_SET_RETURN int"
+NGR_R_SET_ARGS="#undef NGR_R_SET_ARGS"
+NGR_R_SET_CONST="#define NGR_R_SET_CONST const"
+]
+))
+;;
esac
]
,
NGR_R_SET_RESULT="#undef NGR_R_SET_RESULT /*empty*/"
NGR_R_SET_RETURN="#define NGR_R_SET_RETURN void"
+NGR_R_SET_ARGS="#undef NGR_R_SET_ARGS"
+NGR_R_SET_CONST="#define NGR_R_SET_CONST const"
)
+
AC_SUBST(NGR_R_SET_RESULT)
AC_SUBST(NGR_R_SET_RETURN)
+AC_SUBST(NGR_R_SET_ARGS)
+AC_SUBST(NGR_R_SET_CONST)
AC_CHECK_FUNC(innetgr_r,,AC_DEFINE(NEED_INNETGR_R))
@@ -2590,7 +2778,7 @@ case "$host" in
*-solaris2.9)
hack_shutup_in6addr_init_macros=yes
;;
- *-solaris2.1[0-9])
+ *-solaris2.1[[0-9]])
hack_shutup_in6addr_init_macros=yes
;;
esac
@@ -2675,6 +2863,7 @@ AC_OUTPUT(
port/Makefile
${PORT_DIR}/Makefile
${PORT_INCLUDE}/Makefile
+ include/isc/platform.h
)
# Tell Emacs to edit this file in shell mode.
diff --git a/lib/bind/dst/Makefile.in b/lib/bind/dst/Makefile.in
index c802840..a841d49 100644
--- a/lib/bind/dst/Makefile.in
+++ b/lib/bind/dst/Makefile.in
@@ -1,7 +1,7 @@
-# Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004, 2008 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 2001 Internet Software Consortium.
#
-# Permission to use, copy, modify, and distribute this software for any
+# 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.
#
@@ -13,7 +13,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.6 2004/03/05 05:05:09 marka Exp $
+# $Id: Makefile.in,v 1.6.18.2 2008/03/20 23:46:01 tbox Exp $
srcdir= @srcdir@
VPATH = @srcdir@
@@ -26,7 +26,7 @@ TARGETS= ${OBJS}
CRYPTFLAGS= -DCYLINK_DSS -DHMAC_MD5 -DUSE_MD5 -DDNSSAFE
-CINCLUDES= -I.. -I${srcdir}/../include ${CRYPTINCL}
+CINCLUDES= -I.. -I../include -I${srcdir}/../include ${CRYPTINCL}
CDEFINES= ${CRYPTFLAGS}
@BIND9_MAKE_RULES@
diff --git a/lib/bind/dst/dst_api.c b/lib/bind/dst/dst_api.c
index a622ae3..5bcd80a 100644
--- a/lib/bind/dst/dst_api.c
+++ b/lib/bind/dst/dst_api.c
@@ -1,5 +1,5 @@
#ifndef LINT
-static const char rcsid[] = "$Header: /proj/cvs/prod/bind9/lib/bind/dst/dst_api.c,v 1.10.332.7 2007/09/26 04:41:47 each Exp $";
+static const char rcsid[] = "$Header: /proj/cvs/prod/bind9/lib/bind/dst/Attic/dst_api.c,v 1.10.332.7 2007/09/26 04:41:47 each Exp $";
#endif
/*
diff --git a/lib/bind/dst/hmac_link.c b/lib/bind/dst/hmac_link.c
index b97a996..cbd68f4 100644
--- a/lib/bind/dst/hmac_link.c
+++ b/lib/bind/dst/hmac_link.c
@@ -1,6 +1,6 @@
#ifdef HMAC_MD5
#ifndef LINT
-static const char rcsid[] = "$Header: /proj/cvs/prod/bind9/lib/bind/dst/hmac_link.c,v 1.3.164.5 2007/09/26 04:41:47 each Exp $";
+static const char rcsid[] = "$Header: /proj/cvs/prod/bind9/lib/bind/dst/Attic/hmac_link.c,v 1.3.164.5 2007/09/26 04:41:47 each Exp $";
#endif
/*
* Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
diff --git a/lib/bind/dst/support.c b/lib/bind/dst/support.c
index ec228d0..263f957 100644
--- a/lib/bind/dst/support.c
+++ b/lib/bind/dst/support.c
@@ -1,4 +1,4 @@
-static const char rcsid[] = "$Header: /proj/cvs/prod/bind9/lib/bind/dst/support.c,v 1.3.332.3 2005/10/11 00:25:09 marka Exp $";
+static const char rcsid[] = "$Header: /proj/cvs/prod/bind9/lib/bind/dst/Attic/support.c,v 1.3.332.3 2005/10/11 00:25:09 marka Exp $";
/*
diff --git a/lib/bind/include/Makefile.in b/lib/bind/include/Makefile.in
index d07ea7a..17a69bf 100644
--- a/lib/bind/include/Makefile.in
+++ b/lib/bind/include/Makefile.in
@@ -1,7 +1,7 @@
-# Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004, 2008 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 2001 Internet Software Consortium.
#
-# Permission to use, copy, modify, and distribute this software for any
+# 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.
#
@@ -13,7 +13,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.4 2004/03/05 05:05:11 marka Exp $
+# $Id: Makefile.in,v 1.4.18.2 2008/01/23 02:15:02 tbox Exp $
srcdir = @srcdir@
VPATH = @srcdir@
@@ -24,7 +24,7 @@ HEADERS=fd_setsize.h hesiod.h irp.h irs.h netdb.h netgroup.h res_update.h \
AHEADERS= arpa/inet.h arpa/nameser.h arpa/nameser_compat.h
IHEADERS= isc/assertions.h isc/ctl.h isc/dst.h isc/eventlib.h isc/heap.h \
isc/irpmarshall.h isc/list.h isc/logging.h isc/memcluster.h \
- isc/misc.h isc/tree.h
+ isc/misc.h isc/tree.h isc/platform.h.in
all:
diff --git a/lib/bind/include/arpa/nameser.h b/lib/bind/include/arpa/nameser.h
index b3a7849..8f8d8a7 100644
--- a/lib/bind/include/arpa/nameser.h
+++ b/lib/bind/include/arpa/nameser.h
@@ -49,7 +49,7 @@
*/
/*
- * $Id: nameser.h,v 1.7.18.1 2005/04/27 05:00:50 sra Exp $
+ * $Id: nameser.h,v 1.7.18.2 2008/04/03 23:15:15 marka Exp $
*/
#ifndef _ARPA_NAMESER_H_
@@ -427,9 +427,10 @@ typedef enum __ns_cert_types {
#define NS_NXT_MAX 127
/*%
- * EDNS0 extended flags, host order.
+ * EDNS0 extended flags and option codes, host order.
*/
#define NS_OPT_DNSSEC_OK 0x8000U
+#define NS_OPT_NSID 3
/*%
* Inline versions of get/put short/long. Pointer is advanced.
diff --git a/lib/bind/include/isc/assertions.h b/lib/bind/include/isc/assertions.h
index 2ed768d..100e586 100644
--- a/lib/bind/include/isc/assertions.h
+++ b/lib/bind/include/isc/assertions.h
@@ -16,7 +16,7 @@
*/
/*
- * $Id: assertions.h,v 1.2.18.1 2005/04/27 05:00:50 sra Exp $
+ * $Id: assertions.h,v 1.2.18.2 2008/10/15 03:57:21 marka Exp $
*/
#ifndef ASSERTIONS_H
@@ -29,18 +29,19 @@ typedef enum {
typedef void (*assertion_failure_callback)(const char *, int, assertion_type,
const char *, int);
+/* coverity[+kill] */
extern assertion_failure_callback __assertion_failed;
void set_assertion_failure_callback(assertion_failure_callback f);
const char *assertion_type_to_text(assertion_type type);
-#ifdef CHECK_ALL
+#if defined(CHECK_ALL) || defined(__COVERITY__)
#define CHECK_REQUIRE 1
#define CHECK_ENSURE 1
#define CHECK_INSIST 1
#define CHECK_INVARIANT 1
#endif
-#ifdef CHECK_NONE
+#if defined(CHECK_NONE) && !defined(__COVERITY__)
#define CHECK_REQUIRE 0
#define CHECK_ENSURE 0
#define CHECK_INSIST 0
diff --git a/lib/bind/include/isc/eventlib.h b/lib/bind/include/isc/eventlib.h
index 598c71c..5003823 100644
--- a/lib/bind/include/isc/eventlib.h
+++ b/lib/bind/include/isc/eventlib.h
@@ -18,7 +18,7 @@
/* eventlib.h - exported interfaces for eventlib
* vix 09sep95 [initial]
*
- * $Id: eventlib.h,v 1.3.18.2 2005/07/28 07:38:07 marka Exp $
+ * $Id: eventlib.h,v 1.3.18.3 2008/01/23 02:12:01 marka Exp $
*/
#ifndef _EVENTLIB_H
@@ -29,6 +29,8 @@
#include <sys/time.h>
#include <stdio.h>
+#include <isc/platform.h>
+
#ifndef __P
# define __EVENTLIB_P_DEFINED
# ifdef __STDC__
diff --git a/lib/bind/include/isc/misc.h b/lib/bind/include/isc/misc.h
index d2e98ac..0cd1487 100644
--- a/lib/bind/include/isc/misc.h
+++ b/lib/bind/include/isc/misc.h
@@ -16,7 +16,7 @@
*/
/*
- * $Id: misc.h,v 1.4.18.1 2005/04/27 05:00:52 sra Exp $
+ * $Id: misc.h,v 1.4.18.2 2008/02/18 04:04:06 marka Exp $
*/
#ifndef _ISC_MISC_H
@@ -25,6 +25,7 @@
/*! \file */
#include <stdio.h>
+#include <sys/types.h>
#define bitncmp __bitncmp
/*#define isc_movefile __isc_movefile */
diff --git a/lib/bind/include/isc/platform.h.in b/lib/bind/include/isc/platform.h.in
new file mode 100644
index 0000000..40ab5d7
--- /dev/null
+++ b/lib/bind/include/isc/platform.h.in
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2008 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: platform.h.in,v 1.2.6.2 2008/01/23 02:15:02 tbox Exp $ */
+
+/*! \file */
+
+#ifndef ISC_PLATFORM_H
+#define ISC_PLATFORM_H
+
+/*
+ * Define if the OS does not define struct timespec.
+ */
+@ISC_PLATFORM_NEEDTIMESPEC@
+#ifdef ISC_PLATFORM_NEEDTIMESPEC
+#include <time.h> /* For time_t */
+struct timespec {
+ time_t tv_sec; /* seconds */
+ long tv_nsec; /* nanoseconds */
+};
+#endif
+
+#endif
diff --git a/lib/bind/include/netdb.h b/lib/bind/include/netdb.h
index 66dd13d..b74c646 100644
--- a/lib/bind/include/netdb.h
+++ b/lib/bind/include/netdb.h
@@ -86,7 +86,7 @@
/*
* @(#)netdb.h 8.1 (Berkeley) 6/2/93
- * $Id: netdb.h,v 1.15.18.6 2006/10/02 01:23:09 marka Exp $
+ * $Id: netdb.h,v 1.15.18.7 2008/02/28 05:49:37 marka Exp $
*/
#ifndef _NETDB_H_
@@ -481,7 +481,7 @@ int endservent_r __P((struct servent_data *));
void endservent_r __P((struct servent_data *));
#endif
#ifdef _AIX
-int setnetgrent_r __P((const char *, void **));
+int setnetgrent_r __P((char *, void **));
void endnetgrent_r __P((void **));
/*
* Note: AIX's netdb.h declares innetgr_r() as:
diff --git a/lib/bind/include/resolv.h b/lib/bind/include/resolv.h
index 66d84fc..eebc62e 100644
--- a/lib/bind/include/resolv.h
+++ b/lib/bind/include/resolv.h
@@ -50,7 +50,7 @@
/*%
* @(#)resolv.h 8.1 (Berkeley) 6/2/93
- * $Id: resolv.h,v 1.19.18.3 2005/08/25 04:43:51 marka Exp $
+ * $Id: resolv.h,v 1.19.18.4 2008/04/03 23:15:15 marka Exp $
*/
#ifndef _RESOLV_H_
@@ -250,6 +250,7 @@ union res_sockaddr_union {
#define RES_NOCHECKNAME 0x00008000 /*%< do not check names for sanity. */
#define RES_KEEPTSIG 0x00010000 /*%< do not strip TSIG records */
#define RES_BLAST 0x00020000 /*%< blast all recursive servers */
+#define RES_NSID 0x00040000 /*%< request name server ID */
#define RES_NOTLDQUERY 0x00100000 /*%< don't unqualified name as a tld */
#define RES_USE_DNSSEC 0x00200000 /*%< use DNSSEC using OK bit in OPT */
/* #define RES_DEBUG2 0x00400000 */ /* nslookup internal */
@@ -396,6 +397,7 @@ extern const struct res_sym __p_rcode_syms[];
#define sym_ntos __sym_ntos
#define sym_ston __sym_ston
#define res_nopt __res_nopt
+#define res_nopt_rdata __res_nopt_rdata
#define res_ndestroy __res_ndestroy
#define res_nametoclass __res_nametoclass
#define res_nametotype __res_nametotype
@@ -482,6 +484,8 @@ int res_findzonecut2 __P((res_state, const char *, ns_class, int,
union res_sockaddr_union *, int));
void res_nclose __P((res_state));
int res_nopt __P((res_state, int, u_char *, int, int));
+int res_nopt_rdata __P((res_state, int, u_char *, int, u_char *,
+ u_short, u_short, u_char *));
void res_send_setqhook __P((res_send_qhook));
void res_send_setrhook __P((res_send_rhook));
int __res_vinit __P((res_state, int));
diff --git a/lib/bind/inet/Makefile.in b/lib/bind/inet/Makefile.in
index 7eb297c..7b84896 100644
--- a/lib/bind/inet/Makefile.in
+++ b/lib/bind/inet/Makefile.in
@@ -1,7 +1,7 @@
-# Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004, 2008 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 2001 Internet Software Consortium.
#
-# Permission to use, copy, modify, and distribute this software for any
+# 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.
#
@@ -13,7 +13,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.5 2004/03/05 05:05:13 marka Exp $
+# $Id: Makefile.in,v 1.5.18.2 2008/03/20 23:46:01 tbox Exp $
srcdir= @srcdir@
VPATH = @srcdir@
@@ -30,6 +30,6 @@ SRCS= inet_addr.c inet_cidr_ntop.c inet_cidr_pton.c inet_data.c \
TARGETS= ${OBJS}
-CINCLUDES= -I.. -I${srcdir}/../include
+CINCLUDES= -I.. -I../include -I${srcdir}/../include
@BIND9_MAKE_RULES@
diff --git a/lib/bind/inet/inet_net_pton.c b/lib/bind/inet/inet_net_pton.c
index d3de33b..71a8715 100644
--- a/lib/bind/inet/inet_net_pton.c
+++ b/lib/bind/inet/inet_net_pton.c
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: inet_net_pton.c,v 1.7.18.1 2005/04/27 05:00:53 sra Exp $";
+static const char rcsid[] = "$Id: inet_net_pton.c,v 1.7.18.2 2008/08/26 04:42:43 marka Exp $";
#endif
#include "port_before.h"
@@ -133,11 +133,11 @@ inet_net_pton_ipv4(const char *src, u_char *dst, size_t size) {
INSIST(n >= 0 && n <= 9);
bits *= 10;
bits += n;
+ if (bits > 32)
+ goto enoent;
} while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
if (ch != '\0')
goto enoent;
- if (bits > 32)
- goto emsgsize;
}
/* Firey death and destruction unless we prefetched EOS. */
diff --git a/lib/bind/inet/inet_network.c b/lib/bind/inet/inet_network.c
index 4758a00..47976cf 100644
--- a/lib/bind/inet/inet_network.c
+++ b/lib/bind/inet/inet_network.c
@@ -84,9 +84,9 @@ again:
}
if (!digit)
return (INADDR_NONE);
+ if (pp >= parts + 4 || val > 0xffU)
+ return (INADDR_NONE);
if (*cp == '.') {
- if (pp >= parts + 4 || val > 0xffU)
- return (INADDR_NONE);
*pp++ = val, cp++;
goto again;
}
diff --git a/lib/bind/irs/Makefile.in b/lib/bind/irs/Makefile.in
index ce6f5f2..e4f38f7 100644
--- a/lib/bind/irs/Makefile.in
+++ b/lib/bind/irs/Makefile.in
@@ -1,7 +1,7 @@
-# Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004, 2008 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 2001 Internet Software Consortium.
#
-# Permission to use, copy, modify, and distribute this software for any
+# 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.
#
@@ -13,7 +13,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.8.18.2 2004/12/07 00:53:48 marka Exp $
+# $Id: Makefile.in,v 1.8.18.4 2008/03/20 23:46:01 tbox Exp $
srcdir= @srcdir@
VPATH = @srcdir@
@@ -65,6 +65,6 @@ WANT_IRS_THREADSGR_OBJS=getgrent_r.@O@
TARGETS= ${OBJS}
-CINCLUDES= -I.. -I${srcdir}/../include
+CINCLUDES= -I.. -I../include -I${srcdir}/../include
@BIND9_MAKE_RULES@
diff --git a/lib/bind/irs/dns_ho.c b/lib/bind/irs/dns_ho.c
index d1d6f5a..db7ff02 100644
--- a/lib/bind/irs/dns_ho.c
+++ b/lib/bind/irs/dns_ho.c
@@ -52,7 +52,7 @@
/* BIND Id: gethnamaddr.c,v 8.15 1996/05/22 04:56:30 vixie Exp $ */
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: dns_ho.c,v 1.14.18.7 2006/12/07 03:54:24 marka Exp $";
+static const char rcsid[] = "$Id: dns_ho.c,v 1.14.18.8 2008/09/24 05:59:50 marka Exp $";
#endif /* LIBC_SCCS and not lint */
/* Imports. */
@@ -958,7 +958,7 @@ gethostans(struct irs_ho *this,
}
if (m == 0)
continue;
- if (hap < &pvt->h_addr_ptrs[MAXADDRS-1])
+ if (hap < &pvt->h_addr_ptrs[MAXADDRS])
hap++;
*hap = NULL;
bp += m;
@@ -980,9 +980,10 @@ gethostans(struct irs_ho *this,
*ap = NULL;
*hap = NULL;
- if (pvt->res->nsort && haveanswer > 1 && qtype == T_A)
+ if (pvt->res->nsort && hap != pvt->h_addr_ptrs &&
+ qtype == T_A)
addrsort(pvt->res, pvt->h_addr_ptrs,
- haveanswer);
+ hap - pvt->h_addr_ptrs);
if (pvt->host.h_name == NULL) {
n = strlen(qname) + 1; /*%< for the \\0 */
if (n > (ep - bp) || n >= MAXHOSTNAMELEN)
@@ -1049,7 +1050,7 @@ add_hostent(struct pvt *pvt, char *bp, char **hap, struct addrinfo *ai)
/* Avoid overflows. */
if (bp + addrlen > &pvt->hostbuf[sizeof(pvt->hostbuf) - 1])
return(-1);
- if (hap >= &pvt->h_addr_ptrs[MAXADDRS-1])
+ if (hap >= &pvt->h_addr_ptrs[MAXADDRS])
return(0); /*%< fail, but not treat it as an error. */
/* Suppress duplicates. */
for (tap = (const char **)pvt->h_addr_ptrs;
diff --git a/lib/bind/irs/getnetgrent.c b/lib/bind/irs/getnetgrent.c
index a11fa08..1e6ff9b 100644
--- a/lib/bind/irs/getnetgrent.c
+++ b/lib/bind/irs/getnetgrent.c
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: getnetgrent.c,v 1.3.18.1 2005/04/27 05:00:58 sra Exp $";
+static const char rcsid[] = "$Id: getnetgrent.c,v 1.3.18.2 2008/02/27 00:08:30 marka Exp $";
#endif /* LIBC_SCCS and not lint */
/* Imports */
@@ -76,7 +76,9 @@ innetgr(INNETGR_ARGS) {
}
int
-getnetgrent(char **host, char **user, char **domain) {
+getnetgrent(NGR_R_CONST char **host, NGR_R_CONST char **user,
+ NGR_R_CONST char **domain)
+{
struct net_data *net_data = init();
const char *ch, *cu, *cd;
int ret;
diff --git a/lib/bind/irs/getnetgrent_r.c b/lib/bind/irs/getnetgrent_r.c
index 261d9b7..3ff5542 100644
--- a/lib/bind/irs/getnetgrent_r.c
+++ b/lib/bind/irs/getnetgrent_r.c
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: getnetgrent_r.c,v 1.7.18.4 2005/09/03 12:45:15 marka Exp $";
+static const char rcsid[] = "$Id: getnetgrent_r.c,v 1.7.18.6 2008/02/28 05:49:37 marka Exp $";
#endif /* LIBC_SCCS and not lint */
#include <port_before.h>
@@ -33,10 +33,13 @@ static const char rcsid[] = "$Id: getnetgrent_r.c,v 1.7.18.4 2005/09/03 12:45:15
#include <port_after.h>
#ifdef NGR_R_RETURN
+#ifndef NGR_R_PRIVATE
+#define NGR_R_PRIVATE 0
+#endif
static NGR_R_RETURN
-copy_protoent(char **, char **, char **, const char *, const char *,
- const char *, NGR_R_COPY_ARGS);
+copy_protoent(NGR_R_CONST char **, NGR_R_CONST char **, NGR_R_CONST char **,
+ const char *, const char *, const char *, NGR_R_COPY_ARGS);
NGR_R_RETURN
innetgr_r(const char *netgroup, const char *host, const char *user,
@@ -58,8 +61,10 @@ innetgr_r(const char *netgroup, const char *host, const char *user,
*/
NGR_R_RETURN
-getnetgrent_r(char **machinep, char **userp, char **domainp, NGR_R_ARGS) {
- char *mp, *up, *dp;
+getnetgrent_r(NGR_R_CONST char **machinep, NGR_R_CONST char **userp,
+ NGR_R_CONST char **domainp, NGR_R_ARGS)
+{
+ NGR_R_CONST char *mp, *up, *dp;
int res = getnetgrent(&mp, &up, &dp);
if (res != 1)
@@ -69,15 +74,24 @@ getnetgrent_r(char **machinep, char **userp, char **domainp, NGR_R_ARGS) {
mp, up, dp, NGR_R_COPY));
}
+#if NGR_R_PRIVATE == 2
+struct private {
+ char *buf;
+};
+
+#endif
NGR_R_SET_RETURN
-#ifdef NGR_R_ENT_ARGS
-setnetgrent_r(const char *netgroup, NGR_R_ENT_ARGS)
+#ifdef NGR_R_SET_ARGS
+setnetgrent_r(NGR_R_SET_CONST char *netgroup, NGR_R_SET_ARGS)
#else
-setnetgrent_r(const char *netgroup)
+setnetgrent_r(NGR_R_SET_CONST char *netgroup)
#endif
{
+#if NGR_R_PRIVATE == 2
+ struct private *p;
+#endif
char *tmp;
-#if defined(NGR_R_ENT_ARGS) && !defined(NGR_R_PRIVATE)
+#if defined(NGR_R_SET_ARGS) && NGR_R_PRIVATE == 0
UNUSED(buf);
UNUSED(buflen);
#endif
@@ -85,8 +99,17 @@ setnetgrent_r(const char *netgroup)
DE_CONST(netgroup, tmp);
setnetgrent(tmp);
-#ifdef NGR_R_PRIVATE
+#if NGR_R_PRIVATE == 1
*buf = NULL;
+#elif NGR_R_PRIVATE == 2
+ *buf = p = malloc(sizeof(struct private));
+ if (p == NULL)
+#ifdef NGR_R_SET_RESULT
+ return (NGR_R_BAD);
+#else
+ return;
+#endif
+ p->buf = NULL;
#endif
#ifdef NGR_R_SET_RESULT
return (NGR_R_SET_RESULT);
@@ -94,22 +117,29 @@ setnetgrent_r(const char *netgroup)
}
NGR_R_END_RETURN
-#ifdef NGR_R_ENT_ARGS
-endnetgrent_r(NGR_R_ENT_ARGS)
+#ifdef NGR_R_END_ARGS
+endnetgrent_r(NGR_R_END_ARGS)
#else
endnetgrent_r(void)
#endif
{
-#if defined(NGR_R_ENT_ARGS) && !defined(NGR_R_PRIVATE)
+#if NGR_R_PRIVATE == 2
+ struct private *p = buf;
+#endif
+#if defined(NGR_R_SET_ARGS) && NGR_R_PRIVATE == 0
UNUSED(buf);
UNUSED(buflen);
#endif
endnetgrent();
-#ifdef NGR_R_PRIVATE
+#if NGR_R_PRIVATE == 1
if (*buf != NULL)
free(*buf);
*buf = NULL;
+#elif NGR_R_PRIVATE == 2
+ if (p->buf != NULL)
+ free(p->buf);
+ free(p);
#endif
NGR_R_END_RESULT(NGR_R_OK);
}
@@ -117,9 +147,13 @@ endnetgrent_r(void)
/* Private */
static int
-copy_protoent(char **machinep, char **userp, char **domainp,
- const char *mp, const char *up, const char *dp,
- NGR_R_COPY_ARGS) {
+copy_protoent(NGR_R_CONST char **machinep, NGR_R_CONST char **userp,
+ NGR_R_CONST char **domainp, const char *mp, const char *up,
+ const char *dp, NGR_R_COPY_ARGS)
+{
+#if NGR_R_PRIVATE == 2
+ struct private *p = buf;
+#endif
char *cp;
int n;
int len;
@@ -130,12 +164,20 @@ copy_protoent(char **machinep, char **userp, char **domainp,
if (up != NULL) len += strlen(up) + 1;
if (dp != NULL) len += strlen(dp) + 1;
-#ifdef NGR_R_PRIVATE
- free(*buf);
+#if NGR_R_PRIVATE == 1
+ if (*buf != NULL)
+ free(*buf);
*buf = malloc(len);
if (*buf == NULL)
return(NGR_R_BAD);
cp = *buf;
+#elif NGR_R_PRIVATE == 2
+ if (p->buf)
+ free(p->buf);
+ p->buf = malloc(len);
+ if (p->buf == NULL)
+ return(NGR_R_BAD);
+ cp = p->buf;
#else
if (len > (int)buflen) {
errno = ERANGE;
@@ -144,7 +186,6 @@ copy_protoent(char **machinep, char **userp, char **domainp,
cp = buf;
#endif
-
if (mp != NULL) {
n = strlen(mp) + 1;
strcpy(cp, mp);
diff --git a/lib/bind/irs/irp.c b/lib/bind/irs/irp.c
index 85a053d..aae4e7b 100644
--- a/lib/bind/irs/irp.c
+++ b/lib/bind/irs/irp.c
@@ -16,7 +16,7 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static const char rcsid[] = "$Id: irp.c,v 1.6.18.3 2006/03/10 00:20:08 marka Exp $";
+static const char rcsid[] = "$Id: irp.c,v 1.6.18.5 2008/02/28 05:49:37 marka Exp $";
#endif
/* Imports */
@@ -528,7 +528,8 @@ irs_irp_send_command(struct irp_p *pvt, const char *fmt, ...) {
}
va_start(ap, fmt);
- todo = vsprintf(buffer, fmt, ap);
+ (void) vsprintf(buffer, fmt, ap);
+ todo = strlen(buffer);
va_end(ap);
if (todo > (int)sizeof(buffer) - 3) {
syslog(LOG_CRIT, "memory overrun in irs_irp_send_command()");
diff --git a/lib/bind/isc/Makefile.in b/lib/bind/isc/Makefile.in
index 3cbb640..70b0548 100644
--- a/lib/bind/isc/Makefile.in
+++ b/lib/bind/isc/Makefile.in
@@ -1,7 +1,7 @@
-# Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004, 2008 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 2001 Internet Software Consortium.
#
-# Permission to use, copy, modify, and distribute this software for any
+# 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.
#
@@ -13,7 +13,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.7 2004/03/05 05:05:38 marka Exp $
+# $Id: Makefile.in,v 1.7.18.2 2008/03/20 23:46:01 tbox Exp $
srcdir= @srcdir@
VPATH = @srcdir@
@@ -30,6 +30,6 @@ SRCS= assertions.c base64.c bitncmp.c ctl_clnt.c ctl_p.c \
TARGETS= ${OBJS}
-CINCLUDES= -I.. -I${srcdir}/../include
+CINCLUDES= -I.. -I../include -I${srcdir}/../include
@BIND9_MAKE_RULES@
diff --git a/lib/bind/isc/assertions.c b/lib/bind/isc/assertions.c
index c03464d..e4bd42a 100644
--- a/lib/bind/isc/assertions.c
+++ b/lib/bind/isc/assertions.c
@@ -16,7 +16,7 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static const char rcsid[] = "$Id: assertions.c,v 1.2.18.1 2005/04/27 05:01:05 sra Exp $";
+static const char rcsid[] = "$Id: assertions.c,v 1.2.18.2 2008/10/15 03:57:21 marka Exp $";
#endif
#include "port_before.h"
@@ -78,6 +78,7 @@ assertion_type_to_text(assertion_type type) {
* Private.
*/
+/* coverity[+kill] */
static void
default_assertion_failed(const char *file, int line, assertion_type type,
const char *cond, int print_errno)
diff --git a/lib/bind/isc/bitncmp.c b/lib/bind/isc/bitncmp.c
index 8764db1..9bbbd24 100644
--- a/lib/bind/isc/bitncmp.c
+++ b/lib/bind/isc/bitncmp.c
@@ -16,7 +16,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$Id: bitncmp.c,v 1.2.18.1 2005/04/27 05:01:05 sra Exp $";
+static const char rcsid[] = "$Id: bitncmp.c,v 1.2.18.2 2008/05/12 00:21:22 marka Exp $";
#endif
#include "port_before.h"
@@ -48,7 +48,7 @@ bitncmp(const void *l, const void *r, int n) {
b = n / 8;
x = memcmp(l, r, b);
- if (x)
+ if (x || (n % 8) == 0)
return (x);
lb = ((const u_char *)l)[b];
diff --git a/lib/bind/isc/ctl_clnt.c b/lib/bind/isc/ctl_clnt.c
index eca8e7f..7627200 100644
--- a/lib/bind/isc/ctl_clnt.c
+++ b/lib/bind/isc/ctl_clnt.c
@@ -1,5 +1,5 @@
#if !defined(lint) && !defined(SABER)
-static const char rcsid[] = "$Id: ctl_clnt.c,v 1.7.18.2 2007/05/18 06:24:39 marka Exp $";
+static const char rcsid[] = "$Id: ctl_clnt.c,v 1.7.18.3 2008/02/18 04:04:06 marka Exp $";
#endif /* not lint */
/*
@@ -38,6 +38,9 @@ static const char rcsid[] = "$Id: ctl_clnt.c,v 1.7.18.2 2007/05/18 06:24:39 mark
#include <string.h>
#include <time.h>
#include <unistd.h>
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
#include <isc/assertions.h>
#include <isc/ctl.h>
diff --git a/lib/bind/isc/ctl_srvr.c b/lib/bind/isc/ctl_srvr.c
index 52137c0..1ab3f8a 100644
--- a/lib/bind/isc/ctl_srvr.c
+++ b/lib/bind/isc/ctl_srvr.c
@@ -1,5 +1,5 @@
#if !defined(lint) && !defined(SABER)
-static const char rcsid[] = "$Id: ctl_srvr.c,v 1.6.18.2 2006/12/07 04:53:02 marka Exp $";
+static const char rcsid[] = "$Id: ctl_srvr.c,v 1.6.18.3 2008/02/18 04:04:06 marka Exp $";
#endif /* not lint */
/*
@@ -40,6 +40,9 @@ static const char rcsid[] = "$Id: ctl_srvr.c,v 1.6.18.2 2006/12/07 04:53:02 mark
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
+#ifdef HAVE_MEMORY_H
+#include <memory.h>
+#endif
#include <isc/assertions.h>
#include <isc/ctl.h>
diff --git a/lib/bind/isc/logging.c b/lib/bind/isc/logging.c
index ca7049c..0cabc4d 100644
--- a/lib/bind/isc/logging.c
+++ b/lib/bind/isc/logging.c
@@ -16,7 +16,7 @@
*/
#if !defined(LINT) && !defined(CODECENTER)
-static const char rcsid[] = "$Id: logging.c,v 1.6.18.1 2005/04/27 05:01:07 sra Exp $";
+static const char rcsid[] = "$Id: logging.c,v 1.6.18.2 2008/02/28 05:49:37 marka Exp $";
#endif /* not lint */
#include "port_before.h"
@@ -43,12 +43,6 @@ static const char rcsid[] = "$Id: logging.c,v 1.6.18.1 2005/04/27 05:01:07 sra E
#include "port_after.h"
-#ifdef VSPRINTF_CHAR
-# define VSPRINTF(x) strlen(vsprintf/**/x)
-#else
-# define VSPRINTF(x) ((size_t)vsprintf x)
-#endif
-
#include "logging_p.h"
static const int syslog_priority[] = { LOG_DEBUG, LOG_INFO, LOG_NOTICE,
@@ -363,8 +357,8 @@ log_vwrite(log_context lc, int category, int level, const char *format,
continue;
if (!did_vsprintf) {
- if (VSPRINTF((lc->buffer, format, args)) >
- (size_t)LOG_BUFFER_SIZE) {
+ (void)vsprintf(lc->buffer, format, args);
+ if (strlen(lc->buffer) > (size_t)LOG_BUFFER_SIZE) {
syslog(LOG_CRIT,
"memory overrun in log_vwrite()");
exit(1);
diff --git a/lib/bind/nameser/Makefile.in b/lib/bind/nameser/Makefile.in
index d033eee..fcb7ed7 100644
--- a/lib/bind/nameser/Makefile.in
+++ b/lib/bind/nameser/Makefile.in
@@ -1,7 +1,7 @@
-# Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004, 2008 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 2001 Internet Software Consortium.
#
-# Permission to use, copy, modify, and distribute this software for any
+# 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.
#
@@ -13,7 +13,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.5 2004/03/16 05:22:19 marka Exp $
+# $Id: Makefile.in,v 1.5.18.2 2008/03/20 23:46:01 tbox Exp $
srcdir= @srcdir@
VPATH = @srcdir@
@@ -26,6 +26,6 @@ SRCS= ns_date.c ns_name.c ns_netint.c ns_parse.c ns_print.c \
TARGETS= ${OBJS}
-CINCLUDES= -I.. -I${srcdir}/../include
+CINCLUDES= -I.. -I../include -I${srcdir}/../include
@BIND9_MAKE_RULES@
diff --git a/lib/bind/port_after.h.in b/lib/bind/port_after.h.in
index f248d23..daddae6 100644
--- a/lib/bind/port_after.h.in
+++ b/lib/bind/port_after.h.in
@@ -16,12 +16,20 @@
#include <sys/select.h>
#endif /* HAVE_SYS_SELECT_H */
+#ifdef REENABLE_SEND
+#undef send
+#endif
+
@NEED_PSELECT@
@HAVE_SA_LEN@
@HAVE_MINIMUM_IFREQ@
@NEED_DAEMON@
@NEED_STRSEP@
@NEED_STRERROR@
+#ifdef NEED_STRERROR
+const char *isc_strerror(int);
+#define strerror isc_strerror
+#endif
@HAS_INET6_STRUCTS@
@HAVE_SIN6_SCOPE_ID@
@NEED_IN6ADDR_ANY@
@@ -30,12 +38,18 @@
@NEED_GETTIMEOFDAY@
@HAVE_STRNDUP@
@USE_FIONBIO_IOCTL@
-@USE_SYSERROR_LIST@
@INNETGR_ARGS@
@SETNETGRENT_ARGS@
@USE_IFNAMELINKID@
@PORT_NONBLOCK@
+#ifndef _POSIX_PATH_MAX
+#define _POSIX_PATH_MAX 255
+#endif
+#ifndef PATH_MAX
+#define PATH_MAX _POSIX_PATH_MAX
+#endif
+
/*
* We need to know the IPv6 address family number even on IPv4-only systems.
* Note that this is NOT a protocol constant, and that if the system has its
@@ -309,16 +323,16 @@ innetgr_r(const char *, const char *, const char *, const char *);
#endif
#ifdef NEED_SETNETGRENT_R
-#ifdef NGR_R_ENT_ARGS
-NGR_R_SET_RETURN setnetgrent_r(const char *netgroup, NGR_R_ENT_ARGS);
+#ifdef NGR_R_SET_ARGS
+NGR_R_SET_RETURN setnetgrent_r(NGR_R_SET_CONST char *netgroup, NGR_R_SET_ARGS);
#else
-NGR_R_SET_RETURN setnetgrent_r(const char *netgroup);
+NGR_R_SET_RETURN setnetgrent_r(NGR_R_SET_CONST char *netgroup);
#endif
#endif
#ifdef NEED_ENDNETGRENT_R
-#ifdef NGR_R_ENT_ARGS
-NGR_R_END_RETURN endnetgrent_r(NGR_R_ENT_ARGS);
+#ifdef NGR_R_END_ARGS
+NGR_R_END_RETURN endnetgrent_r(NGR_R_END_ARGS);
#else
NGR_R_END_RETURN endnetgrent_r(void);
#endif
@@ -384,10 +398,12 @@ int isc__gettimeofday(struct timeval *tvp, struct _TIMEZONE *tzp);
int isc__gettimeofday(struct timeval *tp, struct timezone *tzp);
#endif
-int getnetgrent(char **machinep, char **userp, char **domainp);
+int getnetgrent(NGR_R_CONST char **machinep, NGR_R_CONST char **userp,
+ NGR_R_CONST char **domainp);
#ifdef NGR_R_ARGS
-int getnetgrent_r(char **machinep, char **userp, char **domainp, NGR_R_ARGS);
+int getnetgrent_r(NGR_R_CONST char **machinep, NGR_R_CONST char **userp,
+ NGR_R_CONST char **domainp, NGR_R_ARGS);
#endif
#ifdef SETNETGRENT_ARGS
@@ -405,11 +421,87 @@ int innetgr(const char *netgroup, const char *machine,
const char *user, const char *domain);
#endif
-#ifdef NGR_R_ENT_ARGS
+#ifdef NGR_R_SET_ARGS
NGR_R_SET_RETURN
-setnetgrent_r(const char *netgroup, NGR_R_ENT_ARGS);
+setnetgrent_r(NGR_R_SET_CONST char *netgroup, NGR_R_SET_ARGS);
#else
NGR_R_SET_RETURN
-setnetgrent_r(const char *netgroup);
+setnetgrent_r(NGR_R_SET_CONST char *netgroup);
+#endif
+
+#ifdef NEED_STRTOUL
+unsigned long strtoul(const char *, char **, int);
+#endif
+
+#ifdef NEED_SUN4PROTOS
+#include <stdarg.h>
+#ifndef __SIZE_TYPE__
+#define __SIZE_TYPE__ int
+#endif
+struct sockaddr;
+struct iovec;
+struct timeval;
+struct timezone;
+int fprintf(FILE *, const char *, ...);
+int getsockname(int, struct sockaddr *, int *);
+int getpeername(int, struct sockaddr *, int *);
+int socket(int, int, int);
+int connect(int, const struct sockaddr *, int);
+int writev(int, struct iovec *, int);
+int readv(int, struct iovec *, int);
+int send(int, const char *, int, int);
+void bzero(char *, int);
+int recvfrom(int, char *, int, int, struct sockaddr *, int *);
+int syslog(int, const char *, ... );
+int printf(const char *, ...);
+__SIZE_TYPE__ fread(void *, __SIZE_TYPE__, __SIZE_TYPE__, FILE *);
+__SIZE_TYPE__ fwrite(const void *, __SIZE_TYPE__, __SIZE_TYPE__, FILE *);
+int fclose(FILE *);
+int ungetc(int, FILE *);
+int scanf(const char *, ...);
+int sscanf(const char *, const char *, ... );
+int tolower(int);
+int toupper(int);
+int strcasecmp(const char *, const char *);
+int strncasecmp(const char *, const char *, int);
+int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+#ifdef gettimeofday
+#undef gettimeofday
+int gettimeofday(struct timeval *, struct timezone *);
+#define gettimeofday isc__gettimeofday
+#else
+int gettimeofday(struct timeval *, struct timezone *);
+#endif
+long strtol(const char*, char **, int);
+int fseek(FILE *, long, int);
+int setsockopt(int, int, int, const char *, int);
+int bind(int, const struct sockaddr *, int);
+void bcopy(char *, char *, int);
+int fputc(char, FILE *);
+int listen(int, int);
+int accept(int, struct sockaddr *, int *);
+int getsockopt(int, int, int, char *, int *);
+int vfprintf(FILE *, const char *, va_list);
+int fflush(FILE *);
+int fgetc(FILE *);
+int fputs(const char *, FILE *);
+int fchown(int, int, int);
+void setbuf(FILE *, char *);
+int gethostname(char *, int);
+int rename(const char *, const char *);
+time_t time(time_t *);
+int fscanf(FILE *, const char *, ...);
+int sscanf(const char *, const char *, ...);
+int ioctl(int, int, caddr_t);
+void perror(const char *);
+
+#if !defined(__USE_FIXED_PROTOTYPES__) && !defined(__cplusplus) && !defined(__STRICT_ANSI__)
+/*
+ * 'gcc -ansi' changes the prototype for vsprintf().
+ * Use this prototype when 'gcc -ansi' is not in effect.
+ */
+char *vsprintf(char *, const char *, va_list);
#endif
+#endif
+
#endif
diff --git a/lib/bind/port_before.h.in b/lib/bind/port_before.h.in
index 1f6ff1a..eb0c3fc 100644
--- a/lib/bind/port_before.h.in
+++ b/lib/bind/port_before.h.in
@@ -2,6 +2,10 @@
#define port_before_h
#include <config.h>
+#ifdef NEED_SUN4PROTOS
+#define _PARAMS(x) x
+#endif
+
struct group; /* silence warning */
struct passwd; /* silence warning */
struct timeval; /* silence warning */
@@ -81,15 +85,22 @@ struct timespec {
@NGR_R_BAD@
@NGR_R_COPY@
@NGR_R_COPY_ARGS@
+@NGR_R_CONST@
@NGR_R_END_RESULT@
@NGR_R_END_RETURN@
-@NGR_R_ENT_ARGS@
+@NGR_R_END_ARGS@
@NGR_R_OK@
@NGR_R_RETURN@
+@NGR_R_SET_CONST@
@NGR_R_SET_RESULT@
@NGR_R_SET_RETURN@
+@NGR_R_SET_ARGS@
@NGR_R_PRIVATE@
+#if !defined(NGR_R_SET_ARGS) && defined(NGR_R_END_ARGS)
+#define NGR_R_SET_ARGS NGR_R_END_ARGS
+#endif
+
@PROTO_R_ARGS@
@PROTO_R_BAD@
@PROTO_R_COPY@
diff --git a/lib/bind/resolv/Makefile.in b/lib/bind/resolv/Makefile.in
index cc661b6..557f020 100644
--- a/lib/bind/resolv/Makefile.in
+++ b/lib/bind/resolv/Makefile.in
@@ -1,7 +1,7 @@
-# Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 2001 Internet Software Consortium.
#
-# Permission to use, copy, modify, and distribute this software for any
+# 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.
#
@@ -13,7 +13,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.4.18.2 2005/07/29 00:12:55 marka Exp $
+# $Id: Makefile.in,v 1.4.18.4 2008/03/20 23:46:01 tbox Exp $
srcdir= @srcdir@
VPATH = @srcdir@
@@ -28,7 +28,7 @@ SRCS= herror.c mtctxres.c res_comp.c res_data.c res_debug.c \
TARGETS= ${OBJS}
-CINCLUDES= -I.. -I${srcdir}/../include
+CINCLUDES= -I.. -I../include -I${srcdir}/../include
CWARNINGS=
@BIND9_MAKE_RULES@
diff --git a/lib/bind/resolv/res_debug.c b/lib/bind/resolv/res_debug.c
index 2ed234e..71dc676 100644
--- a/lib/bind/resolv/res_debug.c
+++ b/lib/bind/resolv/res_debug.c
@@ -95,7 +95,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
-static const char rcsid[] = "$Id: res_debug.c,v 1.10.18.5 2005/07/28 07:38:11 marka Exp $";
+static const char rcsid[] = "$Id: res_debug.c,v 1.10.18.6 2008/04/03 23:15:15 marka Exp $";
#endif /* LIBC_SCCS and not lint */
#include "port_before.h"
@@ -189,10 +189,56 @@ do_section(const res_state statp,
p_type(ns_rr_type(rr)),
p_class(ns_rr_class(rr)));
else if (section == ns_s_ar && ns_rr_type(rr) == ns_t_opt) {
+ u_int16_t optcode, optlen, rdatalen = ns_rr_rdlen(rr);
u_int32_t ttl = ns_rr_ttl(rr);
+
fprintf(file,
"; EDNS: version: %u, udp=%u, flags=%04x\n",
(ttl>>16)&0xff, ns_rr_class(rr), ttl&0xffff);
+
+ while (rdatalen >= 4) {
+ const u_char *cp = ns_rr_rdata(rr);
+ int i;
+
+ GETSHORT(optcode, cp);
+ GETSHORT(optlen, cp);
+
+ if (optcode == NS_OPT_NSID) {
+ fputs("; NSID: ", file);
+ if (optlen == 0) {
+ fputs("; NSID\n", file);
+ } else {
+ fputs("; NSID: ", file);
+ for (i = 0; i < optlen; i++)
+ fprintf(file, "%02x ",
+ cp[i]);
+ fputs(" (",file);
+ for (i = 0; i < optlen; i++)
+ fprintf(file, "%c",
+ isprint(cp[i])?
+ cp[i] : '.');
+ fputs(")\n", file);
+ }
+ } else {
+ if (optlen == 0) {
+ fprintf(file, "; OPT=%u\n",
+ optcode);
+ } else {
+ fprintf(file, "; OPT=%u: ",
+ optcode);
+ for (i = 0; i < optlen; i++)
+ fprintf(file, "%02x ",
+ cp[i]);
+ fputs(" (",file);
+ for (i = 0; i < optlen; i++)
+ fprintf(file, "%c",
+ isprint(cp[i]) ?
+ cp[i] : '.');
+ fputs(")\n", file);
+ }
+ }
+ rdatalen -= 4 + optlen;
+ }
} else {
n = ns_sprintrr(handle, &rr, NULL, NULL,
buf, buflen);
@@ -204,7 +250,7 @@ do_section(const res_state statp,
buf = malloc(buflen += 1024);
if (buf == NULL) {
fprintf(file,
- ";; memory allocation failure\n");
+ ";; memory allocation failure\n");
return;
}
continue;
@@ -381,7 +427,7 @@ const struct res_sym __p_default_section_syms[] = {
{ns_s_an, "ANSWER", (char *)0},
{ns_s_ns, "AUTHORITY", (char *)0},
{ns_s_ar, "ADDITIONAL", (char *)0},
- {0, (char *)0, (char *)0}
+ {0, (char *)0, (char *)0}
};
const struct res_sym __p_update_section_syms[] = {
@@ -389,7 +435,7 @@ const struct res_sym __p_update_section_syms[] = {
{S_PREREQ, "PREREQUISITE", (char *)0},
{S_UPDATE, "UPDATE", (char *)0},
{S_ADDT, "ADDITIONAL", (char *)0},
- {0, (char *)0, (char *)0}
+ {0, (char *)0, (char *)0}
};
const struct res_sym __p_key_syms[] = {
@@ -617,6 +663,7 @@ p_option(u_long option) {
case RES_USE_INET6: return "inet6";
#ifdef RES_USE_EDNS0 /*%< KAME extension */
case RES_USE_EDNS0: return "edns0";
+ case RES_NSID: return "nsid";
#endif
#ifdef RES_USE_DNAME
case RES_USE_DNAME: return "dname";
diff --git a/lib/bind/resolv/res_mkquery.c b/lib/bind/resolv/res_mkquery.c
index 50e4a9e..049f6c5 100644
--- a/lib/bind/resolv/res_mkquery.c
+++ b/lib/bind/resolv/res_mkquery.c
@@ -70,7 +70,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
-static const char rcsid[] = "$Id: res_mkquery.c,v 1.5.18.1 2005/04/27 05:01:11 sra Exp $";
+static const char rcsid[] = "$Id: res_mkquery.c,v 1.5.18.2 2008/04/03 23:15:15 marka Exp $";
#endif /* LIBC_SCCS and not lint */
#include "port_before.h"
@@ -203,9 +203,6 @@ res_nmkquery(res_state statp,
#ifdef RES_USE_EDNS0
/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */
-#ifndef T_OPT
-#define T_OPT 41
-#endif
int
res_nopt(res_state statp,
@@ -230,13 +227,14 @@ res_nopt(res_state statp,
if ((ep - cp) < 1 + RRFIXEDSZ)
return (-1);
- *cp++ = 0; /*%< "." */
- ns_put16(T_OPT, cp); /*%< TYPE */
+ *cp++ = 0; /*%< "." */
+ ns_put16(ns_t_opt, cp); /*%< TYPE */
cp += INT16SZ;
- ns_put16(anslen & 0xffff, cp); /*%< CLASS = UDP payload size */
+ ns_put16(anslen & 0xffff, cp); /*%< CLASS = UDP payload size */
cp += INT16SZ;
- *cp++ = NOERROR; /*%< extended RCODE */
- *cp++ = 0; /*%< EDNS version */
+ *cp++ = NOERROR; /*%< extended RCODE */
+ *cp++ = 0; /*%< EDNS version */
+
if (statp->options & RES_USE_DNSSEC) {
#ifdef DEBUG
if (statp->options & RES_DEBUG)
@@ -246,12 +244,60 @@ res_nopt(res_state statp,
}
ns_put16(flags, cp);
cp += INT16SZ;
- ns_put16(0, cp); /*%< RDLEN */
+
+ ns_put16(0U, cp); /*%< RDLEN */
cp += INT16SZ;
+
hp->arcount = htons(ntohs(hp->arcount) + 1);
return (cp - buf);
}
+
+/*
+ * Construct variable data (RDATA) block for OPT psuedo-RR, append it
+ * to the buffer, then update the RDLEN field (previously set to zero by
+ * res_nopt()) with the new RDATA length.
+ */
+int
+res_nopt_rdata(res_state statp,
+ int n0, /*%< current offset in buffer */
+ u_char *buf, /*%< buffer to put query */
+ int buflen, /*%< size of buffer */
+ u_char *rdata, /*%< ptr to start of opt rdata */
+ u_short code, /*%< OPTION-CODE */
+ u_short len, /*%< OPTION-LENGTH */
+ u_char *data) /*%< OPTION_DATA */
+{
+ register u_char *cp, *ep;
+
+#ifdef DEBUG
+ if ((statp->options & RES_DEBUG) != 0U)
+ printf(";; res_nopt_rdata()\n");
+#endif
+
+ cp = buf + n0;
+ ep = buf + buflen;
+
+ if ((ep - cp) < (4 + len))
+ return (-1);
+
+ if (rdata < (buf + 2) || rdata >= ep)
+ return (-1);
+
+ ns_put16(code, cp);
+ cp += INT16SZ;
+
+ ns_put16(len, cp);
+ cp += INT16SZ;
+
+ memcpy(cp, data, len);
+ cp += len;
+
+ len = cp - rdata;
+ ns_put16(len, rdata - 2); /* Update RDLEN field */
+
+ return (cp - buf);
+}
#endif
/*! \file */
diff --git a/lib/bind/resolv/res_query.c b/lib/bind/resolv/res_query.c
index c160e93..8c01cb0 100644
--- a/lib/bind/resolv/res_query.c
+++ b/lib/bind/resolv/res_query.c
@@ -70,7 +70,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
-static const char rcsid[] = "$Id: res_query.c,v 1.7.18.1 2005/04/27 05:01:11 sra Exp $";
+static const char rcsid[] = "$Id: res_query.c,v 1.7.18.2 2008/04/03 23:15:15 marka Exp $";
#endif /* LIBC_SCCS and not lint */
#include "port_before.h"
@@ -116,8 +116,9 @@ res_nquery(res_state statp,
{
u_char buf[MAXPACKET];
HEADER *hp = (HEADER *) answer;
- int n;
u_int oflags;
+ u_char *rdata;
+ int n;
oflags = statp->_flags;
@@ -132,8 +133,14 @@ again:
buf, sizeof(buf));
#ifdef RES_USE_EDNS0
if (n > 0 && (statp->_flags & RES_F_EDNS0ERR) == 0 &&
- (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0U)
+ (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC|RES_NSID))) {
n = res_nopt(statp, n, buf, sizeof(buf), anslen);
+ rdata = &buf[n];
+ if (n > 0 && (statp->options & RES_NSID) != 0U) {
+ n = res_nopt_rdata(statp, n, buf, sizeof(buf), rdata,
+ NS_OPT_NSID, 0, NULL);
+ }
+ }
#endif
if (n <= 0) {
#ifdef DEBUG
@@ -143,6 +150,7 @@ again:
RES_SET_H_ERRNO(statp, NO_RECOVERY);
return (n);
}
+
n = res_nsend(statp, buf, n, answer, anslen);
if (n < 0) {
#ifdef RES_USE_EDNS0
diff --git a/lib/bind/resolv/res_send.c b/lib/bind/resolv/res_send.c
index 39dc998..5154fe2 100644
--- a/lib/bind/resolv/res_send.c
+++ b/lib/bind/resolv/res_send.c
@@ -70,7 +70,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
-static const char rcsid[] = "$Id: res_send.c,v 1.9.18.8 2006/10/16 23:00:58 marka Exp $";
+static const char rcsid[] = "$Id: res_send.c,v 1.9.18.10 2008/01/27 02:06:26 marka Exp $";
#endif /* LIBC_SCCS and not lint */
/*! \file
@@ -293,7 +293,7 @@ int
res_nsend(res_state statp,
const u_char *buf, int buflen, u_char *ans, int anssiz)
{
- int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
+ int gotsomewhere, terrno, tries, v_circuit, resplen, ns, n;
char abuf[NI_MAXHOST];
#ifdef USE_POLL
@@ -405,7 +405,7 @@ res_nsend(res_state statp,
/*
* Send request, RETRY times, or until successful.
*/
- for (try = 0; try < statp->retry; try++) {
+ for (tries = 0; tries < statp->retry; tries++) {
for (ns = 0; ns < statp->nscount; ns++) {
struct sockaddr *nsap;
int nsaplen;
@@ -453,7 +453,7 @@ res_nsend(res_state statp,
if (v_circuit) {
/* Use VC; at most one attempt per server. */
- try = statp->retry;
+ tries = statp->retry;
n = send_vc(statp, buf, buflen, ans, anssiz, &terrno,
ns);
if (n < 0)
@@ -464,7 +464,7 @@ res_nsend(res_state statp,
} else {
/* Use datagrams. */
n = send_dg(statp, buf, buflen, ans, anssiz, &terrno,
- ns, try, &v_circuit, &gotsomewhere);
+ ns, tries, &v_circuit, &gotsomewhere);
if (n < 0)
goto fail;
if (n == 0)
@@ -601,6 +601,9 @@ send_vc(res_state statp,
u_short len;
u_char *cp;
void *tmp;
+#ifdef SO_NOSIGPIPE
+ int on = 1;
+#endif
nsap = get_nsaddr(statp, ns);
nsaplen = get_salen(nsap);
@@ -646,6 +649,17 @@ send_vc(res_state statp,
return (-1);
}
}
+#ifdef SO_NOSIGPIPE
+ /*
+ * Disable generation of SIGPIPE when writing to a closed
+ * socket. Write should return -1 and set errno to EPIPE
+ * instead.
+ *
+ * Push on even if setsockopt(SO_NOSIGPIPE) fails.
+ */
+ (void)setsockopt(statp->_vcsock, SOL_SOCKET, SO_NOSIGPIPE, &on,
+ sizeof(on));
+#endif
errno = 0;
if (connect(statp->_vcsock, nsap, nsaplen) < 0) {
*terrno = errno;
@@ -773,7 +787,7 @@ send_vc(res_state statp,
static int
send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans,
- int anssiz, int *terrno, int ns, int try, int *v_circuit,
+ int anssiz, int *terrno, int ns, int tries, int *v_circuit,
int *gotsomewhere)
{
const HEADER *hp = (const HEADER *) buf;
@@ -855,7 +869,7 @@ send_dg(res_state statp, const u_char *buf, int buflen, u_char *ans,
/*
* Wait for reply.
*/
- seconds = (statp->retrans << try);
+ seconds = (statp->retrans << tries);
if (ns > 0)
seconds /= statp->nscount;
if (seconds <= 0)
diff --git a/lib/bind9/api b/lib/bind9/api
index 93632d1..3a74aee 100644
--- a/lib/bind9/api
+++ b/lib/bind9/api
@@ -1,3 +1,3 @@
LIBINTERFACE = 31
-LIBREVISION = 0
+LIBREVISION = 1
LIBAGE = 1
diff --git a/lib/bind9/check.c b/lib/bind9/check.c
index 6cfdc93..2967650 100644
--- a/lib/bind9/check.c
+++ b/lib/bind9/check.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2001-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: check.c,v 1.44.18.35 2007/09/13 05:04:01 each Exp $ */
+/* $Id: check.c,v 1.44.18.41 2008/03/29 23:46:10 tbox Exp $ */
/*! \file */
@@ -222,13 +222,24 @@ check_dual_stack(const cfg_obj_t *options, isc_log_t *logctx) {
}
static isc_result_t
-check_forward(const cfg_obj_t *options, isc_log_t *logctx) {
+check_forward(const cfg_obj_t *options, const cfg_obj_t *global,
+ isc_log_t *logctx)
+{
const cfg_obj_t *forward = NULL;
const cfg_obj_t *forwarders = NULL;
(void)cfg_map_get(options, "forward", &forward);
(void)cfg_map_get(options, "forwarders", &forwarders);
+ if (forwarders != NULL && global != NULL) {
+ const char *file = cfg_obj_file(global);
+ unsigned int line = cfg_obj_line(global);
+ cfg_obj_log(forwarders, logctx, ISC_LOG_ERROR,
+ "forwarders declared in root zone and "
+ "in general configuration: %s:%u",
+ file, line);
+ return (ISC_R_FAILURE);
+ }
if (forward != NULL && forwarders == NULL) {
cfg_obj_log(forward, logctx, ISC_LOG_ERROR,
"no matching 'forwarders' statement");
@@ -391,7 +402,7 @@ check_viewacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
{
isc_result_t result = ISC_R_SUCCESS, tresult;
int i = 0;
-
+
static const char *acls[] = { "allow-query", "allow-query-cache",
"allow-recursion", "blackhole", "match-clients",
"match-destinations", "sortlist", NULL };
@@ -400,7 +411,7 @@ check_viewacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
tresult = checkacl(acls[i++], actx, NULL, voptions, config,
logctx, mctx);
if (tresult != ISC_R_SUCCESS)
- result = tresult;
+ result = tresult;
}
return (result);
}
@@ -464,8 +475,8 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
(void)cfg_map_get(options, "preferred-glue", &obj);
if (obj != NULL) {
const char *str;
- str = cfg_obj_asstring(obj);
- if (strcasecmp(str, "a") != 0 &&
+ str = cfg_obj_asstring(obj);
+ if (strcasecmp(str, "a") != 0 &&
strcasecmp(str, "aaaa") != 0 &&
strcasecmp(str, "none") != 0)
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
@@ -494,7 +505,7 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
isc_buffer_add(&b, strlen(str));
tresult = dns_name_fromtext(name, &b,
dns_rootname,
- ISC_FALSE, NULL);
+ ISC_FALSE, NULL);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"bad domain name '%s'",
@@ -504,7 +515,7 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
}
}
}
-
+
/*
* Set supported DNSSEC algorithms.
*/
@@ -552,6 +563,7 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"bad domain name '%s'", dlv);
result = tresult;
+ continue;
}
if (symtab != NULL) {
tresult = nameexist(obj, dlv, 1, symtab,
@@ -699,7 +711,7 @@ get_masters_def(const cfg_obj_t *cctx, const char *name, const cfg_obj_t **ret)
static isc_result_t
validate_masters(const cfg_obj_t *obj, const cfg_obj_t *config,
- isc_uint32_t *countp, isc_log_t *logctx, isc_mem_t *mctx)
+ isc_uint32_t *countp, isc_log_t *logctx, isc_mem_t *mctx)
{
isc_result_t result = ISC_R_SUCCESS;
isc_result_t tresult;
@@ -721,7 +733,7 @@ validate_masters(const cfg_obj_t *obj, const cfg_obj_t *config,
newlist:
list = cfg_tuple_get(obj, "addresses");
element = cfg_list_first(list);
- resume:
+ resume:
for ( ;
element != NULL;
element = cfg_list_next(element))
@@ -818,7 +830,7 @@ check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) {
isc_buffer_init(&b, str, strlen(str));
isc_buffer_add(&b, strlen(str));
tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
- dns_rootname, ISC_FALSE, NULL);
+ dns_rootname, ISC_FALSE, NULL);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(identity, logctx, ISC_LOG_ERROR,
"'%s' is not a valid name", str);
@@ -851,7 +863,7 @@ check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) {
const cfg_obj_t *typeobj;
isc_textregion_t r;
dns_rdatatype_t type;
-
+
typeobj = cfg_listelt_value(element2);
DE_CONST(cfg_obj_asstring(typeobj), r.base);
r.length = strlen(r.base);
@@ -859,7 +871,7 @@ check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) {
tresult = dns_rdatatype_fromtext(&type, &r);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(typeobj, logctx, ISC_LOG_ERROR,
- "'%s' is not a valid type", r.base);
+ "'%s' is not a valid type", r.base);
result = tresult;
}
}
@@ -897,6 +909,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
dns_rdataclass_t zclass;
dns_fixedname_t fixedname;
isc_buffer_t b;
+ isc_boolean_t root = ISC_FALSE;
static optionstable options[] = {
{ "allow-query", MASTERZONE | SLAVEZONE | STUBZONE | CHECKACL },
@@ -1014,21 +1027,24 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
isc_buffer_init(&b, zname, strlen(zname));
isc_buffer_add(&b, strlen(zname));
tresult = dns_name_fromtext(dns_fixedname_name(&fixedname), &b,
- dns_rootname, ISC_TRUE, NULL);
- if (result != ISC_R_SUCCESS) {
+ dns_rootname, ISC_TRUE, NULL);
+ if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
"zone '%s': is not a valid name", zname);
- tresult = ISC_R_FAILURE;
+ result = ISC_R_FAILURE;
} else {
char namebuf[DNS_NAME_FORMATSIZE];
dns_name_format(dns_fixedname_name(&fixedname),
namebuf, sizeof(namebuf));
tresult = nameexist(zconfig, namebuf, ztype == HINTZONE ? 1 : 2,
- symtab, "zone '%s': already exists "
- "previous definition: %s:%u", logctx, mctx);
+ symtab, "zone '%s': already exists "
+ "previous definition: %s:%u", logctx, mctx);
if (tresult != ISC_R_SUCCESS)
result = tresult;
+ if (dns_name_equal(dns_fixedname_name(&fixedname),
+ dns_rootname))
+ root = ISC_TRUE;
}
/*
@@ -1059,7 +1075,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
(options[i].allowed & CHECKACL) != 0) {
tresult = checkacl(options[i].name, actx, zconfig,
- voptions, config, logctx, mctx);
+ voptions, config, logctx, mctx);
if (tresult != ISC_R_SUCCESS)
result = tresult;
}
@@ -1148,7 +1164,18 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
/*
* Check that forwarding is reasonable.
*/
- if (check_forward(zoptions, logctx) != ISC_R_SUCCESS)
+ obj = NULL;
+ if (root) {
+ if (voptions != NULL)
+ (void)cfg_map_get(voptions, "forwarders", &obj);
+ if (obj == NULL) {
+ const cfg_obj_t *options = NULL;
+ (void)cfg_map_get(config, "options", &options);
+ if (options != NULL)
+ (void)cfg_map_get(options, "forwarders", &obj);
+ }
+ }
+ if (check_forward(zoptions, obj, logctx) != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
/*
@@ -1178,7 +1205,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
result = tresult;
}
}
-
+
return (result);
}
@@ -1207,7 +1234,7 @@ bind9_check_key(const cfg_obj_t *key, isc_log_t *logctx) {
{ "hmac-sha512", 512 },
{ NULL, 0 }
};
-
+
(void)cfg_map_get(key, "algorithm", &algobj);
(void)cfg_map_get(key, "secret", &secretobj);
if (secretobj == NULL || algobj == NULL) {
@@ -1258,7 +1285,7 @@ bind9_check_key(const cfg_obj_t *key, isc_log_t *logctx) {
(digestbits < 80U)))
cfg_obj_log(algobj, logctx, ISC_LOG_WARNING,
"key '%s' digest-bits too small "
- "[<%u]", keyname,
+ "[<%u]", keyname,
algorithms[i].size/2);
} else {
cfg_obj_log(algobj, logctx, ISC_LOG_ERROR,
@@ -1389,7 +1416,7 @@ check_servers(const cfg_obj_t *servers, isc_log_t *logctx) {
}
return (result);
}
-
+
static isc_result_t
check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
dns_rdataclass_t vclass, isc_log_t *logctx, isc_mem_t *mctx)
@@ -1452,7 +1479,7 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
isc_symtab_destroy(&symtab);
return (tresult);
}
-
+
if (voptions != NULL) {
keys = NULL;
(void)cfg_map_get(voptions, "key", &keys);
@@ -1474,10 +1501,11 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
const cfg_obj_t *options = NULL;
(void)cfg_map_get(config, "options", &options);
if (options != NULL)
- if (check_forward(options, logctx) != ISC_R_SUCCESS)
+ if (check_forward(options, NULL,
+ logctx) != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
} else {
- if (check_forward(voptions, logctx) != ISC_R_SUCCESS)
+ if (check_forward(voptions, NULL, logctx) != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
}
/*
@@ -1574,10 +1602,10 @@ bind9_check_logging(const cfg_obj_t *config, isc_log_t *logctx,
const char *channelname;
const char *catname;
const cfg_obj_t *fileobj = NULL;
- const cfg_obj_t *syslogobj = NULL;
- const cfg_obj_t *nullobj = NULL;
- const cfg_obj_t *stderrobj = NULL;
- const cfg_obj_t *logobj = NULL;
+ const cfg_obj_t *syslogobj = NULL;
+ const cfg_obj_t *nullobj = NULL;
+ const cfg_obj_t *stderrobj = NULL;
+ const cfg_obj_t *logobj = NULL;
isc_result_t result = ISC_R_SUCCESS;
isc_result_t tresult;
isc_symtab_t *symtab = NULL;
@@ -1638,9 +1666,9 @@ bind9_check_logging(const cfg_obj_t *config, isc_log_t *logctx,
cfg_map_get(logobj, "category", &categories);
for (element = cfg_list_first(categories);
- element != NULL;
- element = cfg_list_next(element))
- {
+ element != NULL;
+ element = cfg_list_next(element))
+ {
category = cfg_listelt_value(element);
catname = cfg_obj_asstring(cfg_tuple_get(category, "name"));
if (isc_log_categorybyname(logctx, catname) == NULL) {
@@ -1656,7 +1684,7 @@ bind9_check_logging(const cfg_obj_t *config, isc_log_t *logctx,
channel = cfg_listelt_value(delement);
channelname = cfg_obj_asstring(channel);
tresult = isc_symtab_lookup(symtab, channelname, 1,
- &symvalue);
+ &symvalue);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(channel, logctx, ISC_LOG_ERROR,
"undefined channel: '%s'",
@@ -1674,12 +1702,12 @@ key_exists(const cfg_obj_t *keylist, const char *keyname) {
const cfg_listelt_t *element;
const char *str;
const cfg_obj_t *obj;
-
+
if (keylist == NULL)
return (ISC_R_NOTFOUND);
for (element = cfg_list_first(keylist);
- element != NULL;
- element = cfg_list_next(element))
+ element != NULL;
+ element = cfg_list_next(element))
{
obj = cfg_listelt_value(element);
str = cfg_obj_asstring(cfg_map_getname(obj));
@@ -1697,7 +1725,7 @@ bind9_check_controlskeys(const cfg_obj_t *control, const cfg_obj_t *keylist,
const cfg_obj_t *control_keylist;
const cfg_listelt_t *element;
const cfg_obj_t *key;
-
+
control_keylist = cfg_tuple_get(control, "keys");
if (cfg_obj_isvoid(control_keylist))
return (ISC_R_SUCCESS);
@@ -1849,7 +1877,7 @@ bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
if (bind9_check_controls(config, logctx, mctx) != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
- if (options != NULL &&
+ if (options != NULL &&
check_order(options, logctx) != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
@@ -1911,7 +1939,7 @@ bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
const char *file;
unsigned int line;
RUNTIME_CHECK(isc_symtab_lookup(symtab, key,
- vclass, &symvalue) == ISC_R_SUCCESS);
+ vclass, &symvalue) == ISC_R_SUCCESS);
file = cfg_obj_file(symvalue.as_cpointer);
line = cfg_obj_line(symvalue.as_cpointer);
cfg_obj_log(view, logctx, ISC_LOG_ERROR,
@@ -1919,7 +1947,7 @@ bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
"previous definition: %s:%u",
key, file, line);
result = tresult;
- } else if (result != ISC_R_SUCCESS) {
+ } else if (tresult != ISC_R_SUCCESS) {
result = tresult;
} else if ((strcasecmp(key, "_bind") == 0 &&
vclass == dns_rdataclass_ch) ||
@@ -1951,8 +1979,8 @@ bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
}
}
- tresult = cfg_map_get(config, "acl", &acls);
- if (tresult == ISC_R_SUCCESS) {
+ tresult = cfg_map_get(config, "acl", &acls);
+ if (tresult == ISC_R_SUCCESS) {
const cfg_listelt_t *elt;
const cfg_listelt_t *elt2;
const char *aclname;
@@ -1971,7 +1999,7 @@ bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
cfg_obj_log(acl, logctx, ISC_LOG_ERROR,
"attempt to redefine "
"builtin acl '%s'",
- aclname);
+ aclname);
result = ISC_R_FAILURE;
break;
}
@@ -2001,8 +2029,8 @@ bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx,
}
}
- tresult = cfg_map_get(config, "kal", &kals);
- if (tresult == ISC_R_SUCCESS) {
+ tresult = cfg_map_get(config, "kal", &kals);
+ if (tresult == ISC_R_SUCCESS) {
const cfg_listelt_t *elt;
const cfg_listelt_t *elt2;
const char *aclname;
diff --git a/lib/dns/acache.c b/lib/dns/acache.c
index 5787a5a..cd56c3c 100644
--- a/lib/dns/acache.c
+++ b/lib/dns/acache.c
@@ -1,7 +1,7 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2006, 2008 Internet Systems Consortium, Inc. ("ISC")
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -14,7 +14,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: acache.c,v 1.3.2.16 2006/07/19 00:34:56 marka Exp $ */
+/* $Id: acache.c,v 1.3.2.18 2008/02/07 23:45:56 tbox Exp $ */
#include <config.h>
@@ -137,7 +137,7 @@ struct acache_cleaner {
in seconds. */
isc_stdtime_t last_cleanup_time; /* The time when the last
- cleanup task completed */
+ cleanup task completed */
isc_timer_t *cleaning_timer;
isc_event_t *resched_event; /* Sent by cleaner task to
@@ -347,11 +347,11 @@ shutdown_buckets(dns_acache_t *acache) {
INSIST(ISC_LIST_EMPTY(dbent->originlist) &&
ISC_LIST_EMPTY(dbent->referlist));
ISC_LIST_UNLINK(acache->dbbucket[i], dbent, link);
-
+
dns_db_detach(&dbent->db);
isc_mem_put(acache->mctx, dbent, sizeof(*dbent));
-
+
acache->dbentries--;
}
}
@@ -513,7 +513,7 @@ clear_entry(dns_acache_t *acache, dns_acacheentry_t *entry) {
if (dns_name_dynamic(entry->foundname))
dns_name_free(entry->foundname, acache->mctx);
isc_mem_put(acache->mctx, entry->foundname,
- sizeof(*entry->foundname));
+ sizeof(*entry->foundname));
entry->foundname = NULL;
}
@@ -558,7 +558,7 @@ acache_cleaner_init(dns_acache_t *acache, isc_timermgr_t *timermgr,
if (timermgr != NULL) {
cleaner->acache->live_cleaners++;
-
+
result = isc_task_onshutdown(acache->task,
acache_cleaner_shutdown_action,
acache);
@@ -677,7 +677,7 @@ end_cleaning(acache_cleaner_t *cleaner, isc_event_t *event) {
*/
if (isc_refcount_current(&cleaner->current_entry->references) == 1) {
INSIST(cleaner->current_entry->callback == NULL);
-
+
if (ISC_LINK_LINKED(cleaner->current_entry, link)) {
ISC_LIST_UNLINK(acache->entries,
cleaner->current_entry, link);
@@ -701,7 +701,7 @@ end_cleaning(acache_cleaner_t *cleaner, isc_event_t *event) {
acache->stats.queries,
acache->stats.adds, acache->stats.deleted,
acache->stats.cleaned, acache->stats.cleaner_runs,
- acache->stats.overmem, acache->stats.overmem_nocreates,
+ acache->stats.overmem, acache->stats.overmem_nocreates,
acache->stats.nomem);
reset_stats(acache);
@@ -913,7 +913,7 @@ static void
acache_overmem_cleaning_action(isc_task_t *task, isc_event_t *event) {
acache_cleaner_t *cleaner = event->ev_arg;
isc_boolean_t want_cleaning = ISC_FALSE;
-
+
UNUSED(task);
INSIST(event->ev_type == DNS_EVENT_ACACHEOVERMEM);
@@ -965,10 +965,14 @@ water(void *arg, int mark) {
LOCK(&acache->cleaner.lock);
- acache->cleaner.overmem = overmem;
+ if (acache->cleaner.overmem != overmem) {
+ acache->cleaner.overmem = overmem;
- if (acache->cleaner.overmem_event != NULL)
- isc_task_send(acache->task, &acache->cleaner.overmem_event);
+ if (acache->cleaner.overmem_event != NULL)
+ isc_task_send(acache->task,
+ &acache->cleaner.overmem_event);
+ isc_mem_waterack(acache->mctx, mark);
+ }
UNLOCK(&acache->cleaner.lock);
}
@@ -1102,7 +1106,7 @@ dns_acache_create(dns_acache_t **acachep, isc_mem_t *mctx,
}
acache->live_cleaners = 0;
- result = acache_cleaner_init(acache, timermgr, &acache->cleaner);
+ result = acache_cleaner_init(acache, timermgr, &acache->cleaner);
if (result != ISC_R_SUCCESS)
goto cleanup;
@@ -1177,7 +1181,7 @@ dns_acache_detach(dns_acache_t **acachep) {
isc_task_shutdown(acache->task);
should_free = ISC_FALSE;
}
-
+
if (should_free)
destroy(acache);
}
@@ -1366,14 +1370,14 @@ dns_acache_createentry(dns_acache_t *acache, dns_db_t *origdb,
REQUIRE(entryp != NULL && *entryp == NULL);
REQUIRE(origdb != NULL);
- /*
- * Should we exceed our memory limit for some reason (for
- * example, if the cleaner does not run aggressively enough),
+ /*
+ * Should we exceed our memory limit for some reason (for
+ * example, if the cleaner does not run aggressively enough),
* then we will not create additional entries.
*
* XXXSK: It might be better to lock the acache->cleaner->lock,
- * but locking may be an expensive bottleneck. If we misread
- * the value, we will occasionally refuse to create a few
+ * but locking may be an expensive bottleneck. If we misread
+ * the value, we will occasionally refuse to create a few
* cache entries, or create a few that we should not. I do not
* expect this to happen often, and it will not have very bad
* effects when it does. So no lock for now.
@@ -1391,7 +1395,7 @@ dns_acache_createentry(dns_acache_t *acache, dns_db_t *origdb,
isc_random_get(&r);
newentry->locknum = r % DEFAULT_ACACHE_ENTRY_LOCK_COUNT;
-
+
result = isc_refcount_init(&newentry->references, 1);
if (result != ISC_R_SUCCESS) {
isc_mem_put(acache->mctx, newentry, sizeof(*newentry));
@@ -1738,7 +1742,7 @@ dns_acache_setcleaninginterval(dns_acache_t *acache, unsigned int t) {
isc_timertype_ticker,
NULL, &interval, ISC_FALSE);
}
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS)
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_ACACHE, ISC_LOG_WARNING,
"could not set acache cleaning interval: %s",
diff --git a/lib/dns/adb.c b/lib/dns/adb.c
index c65c474..ae5dec8 100644
--- a/lib/dns/adb.c
+++ b/lib/dns/adb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,9 +15,9 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: adb.c,v 1.215.18.17 2007/09/11 02:23:26 marka Exp $ */
+/* $Id: adb.c,v 1.215.18.24 2008/10/17 03:35:14 marka Exp $ */
-/*! \file
+/*! \file
*
* \note
* In finds, if task == NULL, no events will be generated, and no events
@@ -71,7 +71,7 @@
#define DNS_ADBFETCH6_MAGIC ISC_MAGIC('a', 'd', 'F', '6')
#define DNS_ADBFETCH6_VALID(x) ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC)
-/*!
+/*!
* The number of buckets needs to be a prime (for good hashing).
*
* XXXRTH How many buckets do we need?
@@ -119,6 +119,7 @@ struct dns_adb {
isc_mutex_t lock;
isc_mutex_t reflock; /*%< Covers irefcnt, erefcnt */
+ isc_mutex_t overmemlock; /*%< Covers overmem */
isc_mem_t *mctx;
dns_view_t *view;
isc_timermgr_t *timermgr;
@@ -494,6 +495,7 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
isc_boolean_t new_addresses_added;
dns_rdatatype_t rdtype;
unsigned int findoptions;
+ dns_adbnamehooklist_t *hookhead;
INSIST(DNS_ADBNAME_VALID(adbname));
adb = adbname->adb;
@@ -518,10 +520,12 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
INSIST(rdata.length == 4);
memcpy(&ina.s_addr, rdata.data, 4);
isc_sockaddr_fromin(&sockaddr, &ina, 0);
+ hookhead = &adbname->v4;
} else {
INSIST(rdata.length == 16);
memcpy(in6a.s6_addr, rdata.data, 16);
isc_sockaddr_fromin6(&sockaddr, &in6a, 0);
+ hookhead = &adbname->v6;
}
INSIST(nh == NULL);
@@ -550,7 +554,7 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
link_entry(adb, addr_bucket, entry);
} else {
- for (anh = ISC_LIST_HEAD(adbname->v4);
+ for (anh = ISC_LIST_HEAD(*hookhead);
anh != NULL;
anh = ISC_LIST_NEXT(anh, plink))
if (anh->entry == foundentry)
@@ -563,12 +567,8 @@ import_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,
}
new_addresses_added = ISC_TRUE;
- if (nh != NULL) {
- if (rdtype == dns_rdatatype_a)
- ISC_LIST_APPEND(adbname->v4, nh, plink);
- else
- ISC_LIST_APPEND(adbname->v6, nh, plink);
- }
+ if (nh != NULL)
+ ISC_LIST_APPEND(*hookhead, nh, plink);
nh = NULL;
result = dns_rdataset_next(rdataset);
}
@@ -1738,8 +1738,11 @@ copy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_name_t *qname,
bucket = entry->lock_bucket;
LOCK(&adb->entrylocks[bucket]);
- if (entry_is_lame(adb, entry, qname, qtype, now))
+ if (!FIND_RETURNLAME(find)
+ && entry_is_lame(adb, entry, qname, qtype, now)) {
+ find->options |= DNS_ADBFIND_LAMEPRUNED;
goto nextv6;
+ }
addrinfo = new_adbaddrinfo(adb, entry, find->port);
if (addrinfo == NULL) {
find->partial_result |= DNS_ADBFIND_INET6;
@@ -1773,12 +1776,15 @@ shutdown_task(isc_task_t *task, isc_event_t *ev) {
INSIST(DNS_ADB_VALID(adb));
/*
+ * Wait for lock around check_exit() call to be released.
+ */
+ LOCK(&adb->lock);
+ /*
* Kill the timer, and then the ADB itself. Note that this implies
* that this task was the one scheduled to get timer events. If
* this is not true (and it is unfortunate there is no way to INSIST()
* this) badness will occur.
*/
- LOCK(&adb->lock);
isc_timer_detach(&adb->timer);
UNLOCK(&adb->lock);
isc_event_free(&ev);
@@ -1990,6 +1996,7 @@ destroy(dns_adb_t *adb) {
DESTROYLOCK(&adb->reflock);
DESTROYLOCK(&adb->lock);
DESTROYLOCK(&adb->mplock);
+ DESTROYLOCK(&adb->overmemlock);
isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t));
}
@@ -2060,6 +2067,10 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
if (result != ISC_R_SUCCESS)
goto fail0d;
+ result = isc_mutex_init(&adb->overmemlock);
+ if (result != ISC_R_SUCCESS)
+ goto fail0e;
+
/*
* Initialize the bucket locks for names and elements.
* May as well initialize the list heads, too.
@@ -2162,6 +2173,8 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,
if (adb->afmp != NULL)
isc_mempool_destroy(&adb->afmp);
+ DESTROYLOCK(&adb->overmemlock);
+ fail0e:
DESTROYLOCK(&adb->reflock);
fail0d:
DESTROYLOCK(&adb->mplock);
@@ -3133,8 +3146,10 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) {
address_type = DNS_ADBFIND_INET6;
fetch = name->fetch_aaaa;
name->fetch_aaaa = NULL;
- }
- INSIST(address_type != 0);
+ } else
+ fetch = NULL;
+
+ INSIST(address_type != 0 && fetch != NULL);
dns_resolver_destroyfetch(&fetch->fetch);
dev->fetch = NULL;
@@ -3582,12 +3597,21 @@ water(void *arg, int mark) {
DP(ISC_LOG_DEBUG(1),
"adb reached %s water mark", overmem ? "high" : "low");
- adb->overmem = overmem;
- if (overmem) {
- isc_interval_set(&interval, 0, 1);
- (void)isc_timer_reset(adb->timer, isc_timertype_once, NULL,
- &interval, ISC_TRUE);
+ /*
+ * We can't use adb->lock as there is potential for water
+ * to be called when adb->lock is held.
+ */
+ LOCK(&adb->overmemlock);
+ if (adb->overmem != overmem) {
+ adb->overmem = overmem;
+ if (overmem) {
+ isc_interval_set(&interval, 0, 1);
+ (void)isc_timer_reset(adb->timer, isc_timertype_once,
+ NULL, &interval, ISC_TRUE);
+ }
+ isc_mem_waterack(adb->mctx, mark);
}
+ UNLOCK(&adb->overmemlock);
}
void
diff --git a/lib/dns/api b/lib/dns/api
index 7ad5506..7949ab0 100644
--- a/lib/dns/api
+++ b/lib/dns/api
@@ -1,3 +1,3 @@
-LIBINTERFACE = 35
+LIBINTERFACE = 36
LIBREVISION = 1
LIBAGE = 0
diff --git a/lib/dns/cache.c b/lib/dns/cache.c
index 011dbf7..c9b4a95 100644
--- a/lib/dns/cache.c
+++ b/lib/dns/cache.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2006, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: cache.c,v 1.57.18.16 2006/08/01 01:06:48 marka Exp $ */
+/* $Id: cache.c,v 1.57.18.18 2008/02/07 23:45:56 tbox Exp $ */
/*! \file */
@@ -42,16 +42,16 @@
#define CACHE_MAGIC ISC_MAGIC('$', '$', '$', '$')
#define VALID_CACHE(cache) ISC_MAGIC_VALID(cache, CACHE_MAGIC)
-/*!
+/*!
* Control incremental cleaning.
* DNS_CACHE_MINSIZE is how many bytes is the floor for dns_cache_setcachesize().
* See also DNS_CACHE_CLEANERINCREMENT
*/
#define DNS_CACHE_MINSIZE 2097152 /*%< Bytes. 2097152 = 2 MB */
-/*!
+/*!
* Control incremental cleaning.
* CLEANERINCREMENT is how many nodes are examined in one pass.
- * See also DNS_CACHE_MINSIZE
+ * See also DNS_CACHE_MINSIZE
*/
#define DNS_CACHE_CLEANERINCREMENT 1000U /*%< Number of nodes. */
@@ -173,7 +173,7 @@ adjust_increment(cache_cleaner_t *cleaner, unsigned int remaining,
unsigned int pps = dns_pps;
unsigned int interval;
unsigned int names;
-
+
/*
* Tune for minumum of 100 packets per second (pps).
*/
@@ -194,7 +194,7 @@ adjust_increment(cache_cleaner_t *cleaner, unsigned int remaining,
ISC_LOG_DEBUG(1), "adjust_increment interval=%u "
"names=%u usec=%" ISC_PLATFORM_QUADFORMAT "u",
interval, names, usecs);
-
+
if (usecs == 0) {
/*
* If we cleaned all the nodes in unmeasurable time
@@ -537,7 +537,7 @@ dns_cache_setcleaninginterval(dns_cache_t *cache, unsigned int t) {
isc_timertype_ticker,
NULL, &interval, ISC_FALSE);
}
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS)
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_CACHE, ISC_LOG_WARNING,
"could not set cache cleaning interval: %s",
@@ -624,7 +624,7 @@ cache_cleaner_init(dns_cache_t *cache, isc_taskmgr_t *taskmgr,
result = ISC_R_NOMEMORY;
goto cleanup;
}
-
+
cleaner->overmem_event =
isc_event_allocate(cache->mctx, cleaner,
DNS_EVENT_CACHEOVERMEM,
@@ -662,7 +662,7 @@ begin_cleaning(cache_cleaner_t *cleaner) {
/*
* Create an iterator, if it does not already exist, and
- * position it at the beginning of the cache.
+ * position it at the beginning of the cache.
*/
if (cleaner->iterator == NULL)
result = dns_db_createiterator(cleaner->cache->db, ISC_FALSE,
@@ -701,7 +701,7 @@ begin_cleaning(cache_cleaner_t *cleaner) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1),
"begin cache cleaning, mem inuse %lu",
- (unsigned long)isc_mem_inuse(cleaner->cache->mctx));
+ (unsigned long)isc_mem_inuse(cleaner->cache->mctx));
cleaner->state = cleaner_s_busy;
isc_task_send(cleaner->task, &cleaner->resched_event);
}
@@ -761,7 +761,7 @@ static void
overmem_cleaning_action(isc_task_t *task, isc_event_t *event) {
cache_cleaner_t *cleaner = event->ev_arg;
isc_boolean_t want_cleaning = ISC_FALSE;
-
+
UNUSED(task);
INSIST(task == cleaner->task);
@@ -980,9 +980,12 @@ water(void *arg, int mark) {
REQUIRE(VALID_CACHE(cache));
LOCK(&cache->cleaner.lock);
-
- dns_db_overmem(cache->db, overmem);
- cache->cleaner.overmem = overmem;
+
+ if (overmem != cache->cleaner.overmem) {
+ dns_db_overmem(cache->db, overmem);
+ cache->cleaner.overmem = overmem;
+ isc_mem_waterack(cache->mctx, mark);
+ }
if (cache->cleaner.overmem_event != NULL)
isc_task_send(cache->cleaner.task,
@@ -1106,7 +1109,7 @@ dns_cache_flushname(dns_cache_t *cache, dns_name_t *name) {
dns_rdatasetiter_t *iter = NULL;
dns_dbnode_t *node = NULL;
dns_db_t *db = NULL;
-
+
LOCK(&cache->lock);
if (cache->db != NULL)
dns_db_attach(cache->db, &db);
diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c
index 617fde8..794cdb5 100644
--- a/lib/dns/dispatch.c
+++ b/lib/dns/dispatch.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dispatch.c,v 1.116.18.19.12.5 2008/07/23 23:16:43 marka Exp $ */
+/* $Id: dispatch.c,v 1.116.18.37 2008/09/04 00:24:41 jinmei Exp $ */
/*! \file */
@@ -24,10 +24,12 @@
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
+#include <stdlib.h>
#include <isc/entropy.h>
#include <isc/mem.h>
#include <isc/mutex.h>
+#include <isc/portset.h>
#include <isc/print.h>
#include <isc/random.h>
#include <isc/string.h>
@@ -46,13 +48,8 @@
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;
- dns_displist_t *qid_table; /*%< the table itself */
-} dns_qid_t;
+typedef struct dispsocket dispsocket_t;
+typedef ISC_LIST(dispsocket_t) dispsocketlist_t;
/* ARC4 Random generator state */
typedef struct arc4ctx {
@@ -60,14 +57,26 @@ typedef struct arc4ctx {
isc_uint8_t j;
isc_uint8_t s[256];
int count;
+ isc_entropy_t *entropy; /*%< entropy source for ARC4 */
+ isc_mutex_t *lock;
} arc4ctx_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;
+ dns_displist_t *qid_table; /*%< the table itself */
+ dispsocketlist_t *sock_table; /*%< socket table */
+} dns_qid_t;
+
struct dns_dispatchmgr {
/* Unlocked. */
unsigned int magic;
isc_mem_t *mctx;
dns_acl_t *blackhole;
dns_portlist_t *portlist;
+ isc_entropy_t *entropy; /*%< entropy source */
/* Locked by "lock". */
isc_mutex_t lock;
@@ -91,8 +100,27 @@ struct dns_dispatchmgr {
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 */
+ isc_mempool_t *spool; /*%< memory pool for dispsocs */
+
+ /*%
+ * Locked by qid->lock if qid exists; otherwise, can be used without
+ * being locked.
+ * Memory footprint considerations: this is a simple implementation of
+ * available ports, i.e., an ordered array of the actual port numbers.
+ * This will require about 256KB of memory in the worst case (128KB for
+ * each of IPv4 and IPv6). We could reduce it by representing it as a
+ * more sophisticated way such as a list (or array) of ranges that are
+ * searched to identify a specific port. Our decision here is the saved
+ * memory isn't worth the implementation complexity, considering the
+ * fact that the whole BIND9 process (which is mainly named) already
+ * requires a pretty large memory footprint. We may, however, have to
+ * revisit the decision when we want to use it as a separate module for
+ * an environment where memory requirement is severer.
+ */
+ in_port_t *v4ports; /*%< available ports for IPv4 */
+ unsigned int nv4ports; /*%< # of available ports for IPv4 */
+ in_port_t *v6ports; /*%< available ports for IPv4 */
+ unsigned int nv6ports; /*%< # of available ports for IPv4 */
};
#define MGR_SHUTTINGDOWN 0x00000001U
@@ -111,17 +139,65 @@ struct dns_dispentry {
isc_taskaction_t action;
void *arg;
isc_boolean_t item_out;
+ dispsocket_t *dispsocket;
ISC_LIST(dns_dispatchevent_t) items;
ISC_LINK(dns_dispentry_t) link;
};
+/*%
+ * Maximum number of dispatch sockets that can be pooled for reuse. The
+ * appropriate value may vary, but experiments have shown a busy caching server
+ * may need more than 1000 sockets concurrently opened. The maximum allowable
+ * number of dispatch sockets (per manager) will be set to the double of this
+ * value.
+ */
+#ifndef DNS_DISPATCH_POOLSOCKS
+#define DNS_DISPATCH_POOLSOCKS 2048
+#endif
+
+/*%
+ * Quota to control the number of dispatch sockets. If a dispatch has more
+ * than the quota of sockets, new queries will purge oldest ones, so that
+ * a massive number of outstanding queries won't prevent subsequent queries
+ * (especially if the older ones take longer time and result in timeout).
+ */
+#ifndef DNS_DISPATCH_SOCKSQUOTA
+#define DNS_DISPATCH_SOCKSQUOTA 3072
+#endif
+
+struct dispsocket {
+ unsigned int magic;
+ isc_socket_t *socket;
+ dns_dispatch_t *disp;
+ isc_sockaddr_t host;
+ in_port_t localport;
+ dns_dispentry_t *resp;
+ isc_task_t *task;
+ ISC_LINK(dispsocket_t) link;
+ unsigned int bucket;
+ ISC_LINK(dispsocket_t) blink;
+};
+
#define INVALID_BUCKET (0xffffdead)
+/*%
+ * Number of tasks for each dispatch that use separate sockets for different
+ * transactions. This must be a power of 2 as it will divide 32 bit numbers
+ * to get an uniformly random tasks selection. See get_dispsocket().
+ */
+#define MAX_INTERNAL_TASKS 64
+
struct dns_dispatch {
/* Unlocked. */
unsigned int magic; /*%< magic */
dns_dispatchmgr_t *mgr; /*%< dispatch manager */
- isc_task_t *task; /*%< internal task */
+ int ntasks;
+ /*%
+ * internal task buckets. We use multiple tasks to distribute various
+ * socket events well when using separate dispatch sockets. We use the
+ * 1st task (task[0]) for internal control events.
+ */
+ isc_task_t *task[MAX_INTERNAL_TASKS];
isc_socket_t *socket; /*%< isc socket attached to */
isc_sockaddr_t local; /*%< local address */
in_port_t localport; /*%< local UDP port */
@@ -143,10 +219,14 @@ struct dns_dispatch {
tcpmsg_valid : 1,
recv_pending : 1; /*%< is a recv() pending? */
isc_result_t shutdown_why;
+ ISC_LIST(dispsocket_t) activesockets;
+ ISC_LIST(dispsocket_t) inactivesockets;
+ unsigned int nsockets;
unsigned int requests; /*%< how many requests we have */
unsigned int tcpbuffers; /*%< allocated buffers */
dns_tcpmsg_t tcpmsg; /*%< for tcp streams */
dns_qid_t *qid;
+ arc4ctx_t arc4ctx; /*%< for QID/UDP port num */
};
#define QID_MAGIC ISC_MAGIC('Q', 'i', 'd', ' ')
@@ -155,6 +235,9 @@ struct dns_dispatch {
#define RESPONSE_MAGIC ISC_MAGIC('D', 'r', 's', 'p')
#define VALID_RESPONSE(e) ISC_MAGIC_VALID((e), RESPONSE_MAGIC)
+#define DISPSOCK_MAGIC ISC_MAGIC('D', 's', 'o', 'c')
+#define VALID_DISPSOCK(e) ISC_MAGIC_VALID((e), DISPSOCK_MAGIC)
+
#define DISPATCH_MAGIC ISC_MAGIC('D', 'i', 's', 'p')
#define VALID_DISPATCH(e) ISC_MAGIC_VALID((e), DISPATCH_MAGIC)
@@ -163,16 +246,33 @@ struct dns_dispatch {
#define DNS_QID(disp) ((disp)->socktype == isc_sockettype_tcp) ? \
(disp)->qid : (disp)->mgr->qid
+#define DISP_ARC4CTX(disp) ((disp)->socktype == isc_sockettype_udp) ? \
+ (&(disp)->arc4ctx) : (&(disp)->mgr->arc4ctx)
+
+/*%
+ * Locking a query port buffer is a bit tricky. We access the buffer without
+ * locking until qid is created. Technically, there is a possibility of race
+ * between the creation of qid and access to the port buffer; in practice,
+ * however, this should be safe because qid isn't created until the first
+ * dispatch is created and there should be no contending situation until then.
+ */
+#define PORTBUFLOCK(mgr) if ((mgr)->qid != NULL) LOCK(&((mgr)->qid->lock))
+#define PORTBUFUNLOCK(mgr) if ((mgr)->qid != NULL) UNLOCK((&(mgr)->qid->lock))
+
/*
* Statics.
*/
-static dns_dispentry_t *bucket_search(dns_qid_t *, isc_sockaddr_t *,
- dns_messageid_t, in_port_t, unsigned int);
+static dns_dispentry_t *entry_search(dns_qid_t *, isc_sockaddr_t *,
+ dns_messageid_t, in_port_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 destroy_dispsocket(dns_dispatch_t *, dispsocket_t **);
+static void deactivate_dispsocket(dns_dispatch_t *, dispsocket_t *);
+static void udp_exrecv(isc_task_t *, isc_event_t *);
+static void udp_shrecv(isc_task_t *, isc_event_t *);
+static void udp_recv(isc_event_t *, dns_dispatch_t *, dispsocket_t *);
static void tcp_recv(isc_task_t *, isc_event_t *);
-static void startrecv(dns_dispatch_t *);
+static isc_result_t startrecv(dns_dispatch_t *, dispsocket_t *);
static isc_uint32_t dns_hash(dns_qid_t *, isc_sockaddr_t *, dns_messageid_t,
in_port_t);
static void free_buffer(dns_dispatch_t *disp, void *buf, unsigned int len);
@@ -184,6 +284,11 @@ 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 get_udpsocket(dns_dispatchmgr_t *mgr,
+ dns_dispatch_t *disp,
+ isc_socketmgr_t *sockmgr,
+ isc_sockaddr_t *localaddr,
+ isc_socket_t **sockp);
static isc_result_t dispatch_createudp(dns_dispatchmgr_t *mgr,
isc_socketmgr_t *sockmgr,
isc_taskmgr_t *taskmgr,
@@ -194,8 +299,13 @@ static isc_result_t dispatch_createudp(dns_dispatchmgr_t *mgr,
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);
+ unsigned int increment, dns_qid_t **qidp,
+ isc_boolean_t needaddrtable);
static void qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp);
+static isc_result_t open_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local,
+ unsigned int options, isc_socket_t **sockp);
+static isc_boolean_t portavailable(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
+ isc_sockaddr_t *sockaddrp);
#define LVL(x) ISC_LOG_DEBUG(x)
@@ -275,7 +385,7 @@ request_log(dns_dispatch_t *disp, dns_dispentry_t *resp,
}
}
-/*
+/*%
* ARC4 random number generator derived from OpenBSD.
* Only dispatch_arc4random() and dispatch_arc4uniformrandom() are expected
* to be called from general dispatch routines; the rest of them are subroutines
@@ -298,13 +408,15 @@ request_log(dns_dispatch_t *disp, dns_dispentry_t *resp,
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
static void
-dispatch_arc4init(arc4ctx_t *actx) {
+dispatch_arc4init(arc4ctx_t *actx, isc_entropy_t *entropy, isc_mutex_t *lock) {
int n;
for (n = 0; n < 256; n++)
actx->s[n] = n;
actx->i = 0;
actx->j = 0;
actx->count = 0;
+ actx->entropy = entropy; /* don't have to attach */
+ actx->lock = lock;
}
static void
@@ -348,7 +460,7 @@ dispatch_arc4get16(arc4ctx_t *actx) {
}
static void
-dispatch_arc4stir(dns_dispatchmgr_t *mgr) {
+dispatch_arc4stir(arc4ctx_t *actx) {
int i;
union {
unsigned char rnd[128];
@@ -356,51 +468,55 @@ dispatch_arc4stir(dns_dispatchmgr_t *mgr) {
} rnd;
isc_result_t result;
- if (mgr->entropy != NULL) {
+ if (actx->entropy != NULL) {
/*
* We accept any quality of random data to avoid blocking.
*/
- result = isc_entropy_getdata(mgr->entropy, rnd.rnd,
+ result = isc_entropy_getdata(actx->entropy, rnd.rnd,
sizeof(rnd), NULL, 0);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
} else {
for (i = 0; i < 32; i++)
isc_random_get(&rnd.rnd32[i]);
}
- dispatch_arc4addrandom(&mgr->arc4ctx, rnd.rnd, sizeof(rnd.rnd));
+ dispatch_arc4addrandom(actx, rnd.rnd, sizeof(rnd.rnd));
/*
* Discard early keystream, as per recommendations in:
* http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps
*/
for (i = 0; i < 256; i++)
- (void)dispatch_arc4get8(&mgr->arc4ctx);
+ (void)dispatch_arc4get8(actx);
/*
* Derived from OpenBSD's implementation. The rationale is not clear,
* but should be conservative enough in safety, and reasonably large
* for efficiency.
*/
- mgr->arc4ctx.count = 1600000;
+ actx->count = 1600000;
}
static isc_uint16_t
-dispatch_arc4random(dns_dispatchmgr_t *mgr) {
+dispatch_arc4random(arc4ctx_t *actx) {
isc_uint16_t result;
- LOCK(&mgr->arc4_lock);
- mgr->arc4ctx.count -= sizeof(isc_uint16_t);
- if (mgr->arc4ctx.count <= 0)
- dispatch_arc4stir(mgr);
- result = dispatch_arc4get16(&mgr->arc4ctx);
- UNLOCK(&mgr->arc4_lock);
+ if (actx->lock != NULL)
+ LOCK(actx->lock);
+
+ actx->count -= sizeof(isc_uint16_t);
+ if (actx->count <= 0)
+ dispatch_arc4stir(actx);
+ result = dispatch_arc4get16(actx);
+
+ if (actx->lock != NULL)
+ UNLOCK(actx->lock);
+
return (result);
}
static isc_uint16_t
-dispatch_arc4uniformrandom(dns_dispatchmgr_t *mgr, isc_uint16_t upper_bound) {
+dispatch_arc4uniformrandom(arc4ctx_t *actx, isc_uint16_t upper_bound) {
isc_uint16_t min, r;
- /* The caller must hold the manager lock. */
if (upper_bound < 2)
return (0);
@@ -422,7 +538,7 @@ dispatch_arc4uniformrandom(dns_dispatchmgr_t *mgr, isc_uint16_t upper_bound) {
* to re-roll.
*/
for (;;) {
- r = dispatch_arc4random(mgr);
+ r = dispatch_arc4random(actx);
if (r >= min)
break;
}
@@ -505,13 +621,15 @@ destroy_disp_ok(dns_dispatch_t *disp)
if (disp->recv_pending != 0)
return (ISC_FALSE);
+ if (!ISC_LIST_EMPTY(disp->activesockets))
+ return (ISC_FALSE);
+
if (disp->shutting_down == 0)
return (ISC_FALSE);
return (ISC_TRUE);
}
-
/*
* Called when refcount reaches 0 (and safe to destroy).
*
@@ -523,6 +641,8 @@ destroy_disp(isc_task_t *task, isc_event_t *event) {
dns_dispatch_t *disp;
dns_dispatchmgr_t *mgr;
isc_boolean_t killmgr;
+ dispsocket_t *dispsocket;
+ int i;
INSIST(event->ev_type == DNS_EVENT_DISPATCHCONTROL);
@@ -536,10 +656,16 @@ destroy_disp(isc_task_t *task, isc_event_t *event) {
dispatch_log(disp, LVL(90),
"shutting down; detaching from sock %p, task %p",
- disp->socket, disp->task);
+ disp->socket, disp->task[0]); /* XXXX */
- isc_socket_detach(&disp->socket);
- isc_task_detach(&disp->task);
+ if (disp->socket != NULL)
+ isc_socket_detach(&disp->socket);
+ while ((dispsocket = ISC_LIST_HEAD(disp->inactivesockets)) != NULL) {
+ ISC_LIST_UNLINK(disp->inactivesockets, dispsocket, link);
+ destroy_dispsocket(disp, &dispsocket);
+ }
+ for (i = 0; i < disp->ntasks; i++)
+ isc_task_detach(&disp->task[i]);
isc_event_free(&event);
dispatch_free(&disp);
@@ -550,14 +676,210 @@ destroy_disp(isc_task_t *task, isc_event_t *event) {
destroy_mgr(&mgr);
}
+/*%
+ * Find a dispsocket for socket address 'dest', and port number 'port'.
+ * Return NULL if no such entry exists.
+ */
+static dispsocket_t *
+socket_search(dns_qid_t *qid, isc_sockaddr_t *dest, in_port_t port,
+ unsigned int bucket)
+{
+ dispsocket_t *dispsock;
+
+ REQUIRE(bucket < qid->qid_nbuckets);
+
+ dispsock = ISC_LIST_HEAD(qid->sock_table[bucket]);
+
+ while (dispsock != NULL) {
+ if (isc_sockaddr_equal(dest, &dispsock->host) &&
+ dispsock->localport == port)
+ return (dispsock);
+ dispsock = ISC_LIST_NEXT(dispsock, blink);
+ }
+
+ return (NULL);
+}
+
+/*%
+ * Make a new socket for a single dispatch with a random port number.
+ * The caller must hold the disp->lock and qid->lock.
+ */
+static isc_result_t
+get_dispsocket(dns_dispatch_t *disp, isc_sockaddr_t *dest,
+ isc_socketmgr_t *sockmgr, dns_qid_t *qid,
+ dispsocket_t **dispsockp, in_port_t *portp)
+{
+ int i;
+ isc_uint32_t r;
+ dns_dispatchmgr_t *mgr = disp->mgr;
+ isc_socket_t *sock = NULL;
+ isc_result_t result = ISC_R_FAILURE;
+ in_port_t port;
+ isc_sockaddr_t localaddr;
+ unsigned int bucket = 0;
+ dispsocket_t *dispsock;
+ unsigned int nports;
+ in_port_t *ports;
+
+ if (isc_sockaddr_pf(&disp->local) == AF_INET) {
+ nports = disp->mgr->nv4ports;
+ ports = disp->mgr->v4ports;
+ } else {
+ nports = disp->mgr->nv6ports;
+ ports = disp->mgr->v6ports;
+ }
+ if (nports == 0)
+ return (ISC_R_ADDRNOTAVAIL);
+
+ dispsock = ISC_LIST_HEAD(disp->inactivesockets);
+ if (dispsock != NULL) {
+ ISC_LIST_UNLINK(disp->inactivesockets, dispsock, link);
+ sock = dispsock->socket;
+ dispsock->socket = NULL;
+ } else {
+ dispsock = isc_mempool_get(mgr->spool);
+ if (dispsock == NULL)
+ return (ISC_R_NOMEMORY);
+
+ disp->nsockets++;
+ dispsock->socket = NULL;
+ dispsock->disp = disp;
+ dispsock->resp = NULL;
+ isc_random_get(&r);
+ dispsock->task = NULL;
+ isc_task_attach(disp->task[r % disp->ntasks], &dispsock->task);
+ ISC_LINK_INIT(dispsock, link);
+ ISC_LINK_INIT(dispsock, blink);
+ dispsock->magic = DISPSOCK_MAGIC;
+ }
+
+ /*
+ * Pick up a random UDP port and open a new socket with it. Avoid
+ * choosing ports that share the same destination because it will be
+ * very likely to fail in bind(2) or connect(2).
+ */
+ localaddr = disp->local;
+ for (i = 0; i < 64; i++) {
+ port = ports[dispatch_arc4uniformrandom(DISP_ARC4CTX(disp),
+ nports)];
+ isc_sockaddr_setport(&localaddr, port);
+
+ bucket = dns_hash(qid, dest, 0, port);
+ if (socket_search(qid, dest, port, bucket) != NULL)
+ continue;
+
+ result = open_socket(sockmgr, &localaddr, 0, &sock);
+ if (result == ISC_R_SUCCESS || result != ISC_R_ADDRINUSE)
+ break;
+ }
+
+ if (result == ISC_R_SUCCESS) {
+ dispsock->socket = sock;
+ dispsock->host = *dest;
+ dispsock->localport = port;
+ dispsock->bucket = bucket;
+ ISC_LIST_APPEND(qid->sock_table[bucket], dispsock, blink);
+ *dispsockp = dispsock;
+ *portp = port;
+ } else {
+ /*
+ * We could keep it in the inactive list, but since this should
+ * be an exceptional case and might be resource shortage, we'd
+ * rather destroy it.
+ */
+ if (sock != NULL)
+ isc_socket_detach(&sock);
+ destroy_dispsocket(disp, &dispsock);
+ }
+
+ return (result);
+}
+
+/*%
+ * Destroy a dedicated dispatch socket.
+ */
+static void
+destroy_dispsocket(dns_dispatch_t *disp, dispsocket_t **dispsockp) {
+ dispsocket_t *dispsock;
+ dns_qid_t *qid;
+
+ /*
+ * The dispatch must be locked.
+ */
+
+ REQUIRE(dispsockp != NULL && *dispsockp != NULL);
+ dispsock = *dispsockp;
+ REQUIRE(!ISC_LINK_LINKED(dispsock, link));
+
+ disp->nsockets--;
+ dispsock->magic = 0;
+ if (dispsock->socket != NULL)
+ isc_socket_detach(&dispsock->socket);
+ if (ISC_LINK_LINKED(dispsock, blink)) {
+ qid = DNS_QID(disp);
+ LOCK(&qid->lock);
+ ISC_LIST_UNLINK(qid->sock_table[dispsock->bucket], dispsock,
+ blink);
+ UNLOCK(&qid->lock);
+ }
+ if (dispsock->task != NULL)
+ isc_task_detach(&dispsock->task);
+ isc_mempool_put(disp->mgr->spool, dispsock);
+
+ *dispsockp = NULL;
+}
+
+/*%
+ * Deactivate a dedicated dispatch socket. Move it to the inactive list for
+ * future reuse unless the total number of sockets are exceeding the maximum.
+ */
+static void
+deactivate_dispsocket(dns_dispatch_t *disp, dispsocket_t *dispsock) {
+ isc_result_t result;
+ dns_qid_t *qid;
+
+ /*
+ * The dispatch must be locked.
+ */
+ ISC_LIST_UNLINK(disp->activesockets, dispsock, link);
+ if (dispsock->resp != NULL) {
+ INSIST(dispsock->resp->dispsocket == dispsock);
+ dispsock->resp->dispsocket = NULL;
+ }
+
+ if (disp->nsockets > DNS_DISPATCH_POOLSOCKS)
+ destroy_dispsocket(disp, &dispsock);
+ else {
+ result = isc_socket_close(dispsock->socket);
+
+ qid = DNS_QID(disp);
+ LOCK(&qid->lock);
+ ISC_LIST_UNLINK(qid->sock_table[dispsock->bucket], dispsock,
+ blink);
+ UNLOCK(&qid->lock);
+
+ if (result == ISC_R_SUCCESS)
+ ISC_LIST_APPEND(disp->inactivesockets, dispsock, link);
+ else {
+ /*
+ * If the underlying system does not allow this
+ * optimization, destroy this temporary structure (and
+ * create a new one for a new transaction).
+ */
+ INSIST(result == ISC_R_NOTIMPLEMENTED);
+ destroy_dispsocket(disp, &dispsock);
+ }
+ }
+}
/*
- * Find an entry for query ID 'id' and socket address 'dest' in 'qid'.
+ * Find an entry for query ID 'id', socket address 'dest', and port number
+ * 'port'.
* 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,
- in_port_t port, unsigned int bucket)
+entry_search(dns_qid_t *qid, isc_sockaddr_t *dest, dns_messageid_t id,
+ in_port_t port, unsigned int bucket)
{
dns_dispentry_t *res;
@@ -566,7 +888,7 @@ bucket_search(dns_qid_t *qid, isc_sockaddr_t *dest, dns_messageid_t id,
res = ISC_LIST_HEAD(qid->qid_table[bucket]);
while (res != NULL) {
- if ((res->id == id) && isc_sockaddr_equal(dest, &res->host) &&
+ if (res->id == id && isc_sockaddr_equal(dest, &res->host) &&
res->port == port) {
return (res);
}
@@ -640,6 +962,26 @@ allocate_event(dns_dispatch_t *disp) {
return (ev);
}
+static void
+udp_exrecv(isc_task_t *task, isc_event_t *ev) {
+ dispsocket_t *dispsock = ev->ev_arg;
+
+ UNUSED(task);
+
+ REQUIRE(VALID_DISPSOCK(dispsock));
+ udp_recv(ev, dispsock->disp, dispsock);
+}
+
+static void
+udp_shrecv(isc_task_t *task, isc_event_t *ev) {
+ dns_dispatch_t *disp = ev->ev_arg;
+
+ UNUSED(task);
+
+ REQUIRE(VALID_DISPATCH(disp));
+ udp_recv(ev, disp, NULL);
+}
+
/*
* General flow:
*
@@ -655,14 +997,13 @@ allocate_event(dns_dispatch_t *disp) {
* restart.
*/
static void
-udp_recv(isc_task_t *task, isc_event_t *ev_in) {
+udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) {
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_dispentry_t *resp = NULL;
dns_dispatchevent_t *rev;
unsigned int bucket;
isc_boolean_t killit;
@@ -671,8 +1012,8 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
dns_qid_t *qid;
isc_netaddr_t netaddr;
int match;
-
- UNUSED(task);
+ int result;
+ isc_boolean_t qidlocked = ISC_FALSE;
LOCK(&disp->lock);
@@ -683,7 +1024,7 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
"got packet: requests %d, buffers %d, recvs %d",
disp->requests, disp->mgr->buffers, disp->recv_pending);
- if (ev->ev_type == ISC_SOCKEVENT_RECVDONE) {
+ if (dispsock == NULL && ev->ev_type == ISC_SOCKEVENT_RECVDONE) {
/*
* Unless the receive event was imported from a listening
* interface, in which case the event type is
@@ -693,6 +1034,19 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
disp->recv_pending = 0;
}
+ if (dispsock != NULL &&
+ (ev->result == ISC_R_CANCELED || dispsock->resp == NULL)) {
+ /*
+ * dispsock->resp can be NULL if this transaction was canceled
+ * just after receiving a response. Since this socket is
+ * exclusively used and there should be at most one receive
+ * event the canceled event should have been no effect. So
+ * we can (and should) deactivate the socket right now.
+ */
+ deactivate_dispsocket(disp, dispsock);
+ dispsock = NULL;
+ }
+
if (disp->shutting_down) {
/*
* This dispatcher is shutting down.
@@ -705,12 +1059,32 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
killit = destroy_disp_ok(disp);
UNLOCK(&disp->lock);
if (killit)
- isc_task_send(disp->task, &disp->ctlevent);
+ isc_task_send(disp->task[0], &disp->ctlevent);
return;
}
- if (ev->result != ISC_R_SUCCESS) {
+ if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
+ if (dispsock != NULL) {
+ resp = dispsock->resp;
+ id = resp->id;
+ if (ev->result != ISC_R_SUCCESS) {
+ /*
+ * This is most likely a network error on a
+ * connected socket. It makes no sense to
+ * check the address or parse the packet, but it
+ * will help to return the error to the caller.
+ */
+ goto sendresponse;
+ }
+ } else {
+ free_buffer(disp, ev->region.base, ev->region.length);
+
+ UNLOCK(&disp->lock);
+ isc_event_free(&ev_in);
+ return;
+ }
+ } else if (ev->result != ISC_R_SUCCESS) {
free_buffer(disp, ev->region.base, ev->region.length);
if (ev->result != ISC_R_CANCELED)
@@ -729,7 +1103,7 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
isc_netaddr_fromsockaddr(&netaddr, &ev->address);
if (disp->mgr->blackhole != NULL &&
dns_acl_match(&netaddr, NULL, disp->mgr->blackhole,
- NULL, &match, NULL) == ISC_R_SUCCESS &&
+ NULL, &match, NULL) == ISC_R_SUCCESS &&
match > 0)
{
if (isc_log_wouldlog(dns_lctx, LVL(10))) {
@@ -771,18 +1145,32 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
goto restart;
}
- /* response */
- bucket = dns_hash(qid, &ev->address, id, disp->localport);
- LOCK(&qid->lock);
- resp = bucket_search(qid, &ev->address, id, disp->localport, bucket);
- dispatch_log(disp, LVL(90),
- "search for response in bucket %d: %s",
- bucket, (resp == NULL ? "not found" : "found"));
-
+ /*
+ * Search for the corresponding response. If we are using an exclusive
+ * socket, we've already identified it and we can skip the search; but
+ * the ID and the address must match the expected ones.
+ */
if (resp == NULL) {
+ bucket = dns_hash(qid, &ev->address, id, disp->localport);
+ LOCK(&qid->lock);
+ qidlocked = ISC_TRUE;
+ resp = entry_search(qid, &ev->address, id, disp->localport,
+ bucket);
+ dispatch_log(disp, LVL(90),
+ "search for response in bucket %d: %s",
+ bucket, (resp == NULL ? "not found" : "found"));
+
+ if (resp == NULL) {
+ free_buffer(disp, ev->region.base, ev->region.length);
+ goto unlock;
+ }
+ } else if (resp->id != id || !isc_sockaddr_equal(&ev->address,
+ &resp->host)) {
+ dispatch_log(disp, LVL(90),
+ "response to an exclusive socket doesn't match");
free_buffer(disp, ev->region.base, ev->region.length);
goto unlock;
- }
+ }
/*
* Now that we have the original dispatch the query was sent
@@ -792,7 +1180,7 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
if (disp != resp->disp) {
isc_sockaddr_t a1;
isc_sockaddr_t a2;
-
+
/*
* Check that the socket types and ports match.
*/
@@ -805,11 +1193,11 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
/*
* If both dispatches are bound to an address then fail as
- * the addresses can't be equal (enforced by the IP stack).
+ * the addresses can't be equal (enforced by the IP stack).
*
* Note under Linux a packet can be sent out via IPv4 socket
* and the response be received via a IPv6 socket.
- *
+ *
* Requests sent out via IPv6 should always come back in
* via IPv6.
*/
@@ -827,6 +1215,7 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
}
}
+ sendresponse:
queue_response = resp->item_out;
rev = allocate_event(resp->disp);
if (rev == NULL) {
@@ -841,7 +1230,7 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
*/
isc_buffer_init(&rev->buffer, ev->region.base, ev->region.length);
isc_buffer_add(&rev->buffer, ev->n);
- rev->result = ISC_R_SUCCESS;
+ rev->result = ev->result;
rev->id = id;
rev->addr = ev->address;
rev->pktinfo = ev->pktinfo;
@@ -860,14 +1249,23 @@ udp_recv(isc_task_t *task, isc_event_t *ev_in) {
isc_task_send(resp->task, ISC_EVENT_PTR(&rev));
}
unlock:
- UNLOCK(&qid->lock);
+ if (qidlocked)
+ UNLOCK(&qid->lock);
/*
* Restart recv() to get the next packet.
*/
restart:
- startrecv(disp);
-
+ result = startrecv(disp, dispsock);
+ if (result != ISC_R_SUCCESS && dispsock != NULL) {
+ /*
+ * XXX: wired. There seems to be no recovery process other than
+ * deactivate this socket anyway (since we cannot start
+ * receiving, we won't be able to receive a cancel event
+ * from the user).
+ */
+ deactivate_dispsocket(disp, dispsock);
+ }
UNLOCK(&disp->lock);
isc_event_free(&ev_in);
@@ -930,7 +1328,7 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) {
switch (tcpmsg->result) {
case ISC_R_CANCELED:
break;
-
+
case ISC_R_EOF:
dispatch_log(disp, LVL(90), "shutting down on EOF");
do_cancel(disp);
@@ -967,7 +1365,7 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) {
killit = destroy_disp_ok(disp);
UNLOCK(&disp->lock);
if (killit)
- isc_task_send(disp->task, &disp->ctlevent);
+ isc_task_send(disp->task[0], &disp->ctlevent);
return;
}
@@ -1010,8 +1408,7 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) {
*/
bucket = dns_hash(qid, &tcpmsg->address, id, disp->localport);
LOCK(&qid->lock);
- resp = bucket_search(qid, &tcpmsg->address, id, disp->localport,
- bucket);
+ resp = entry_search(qid, &tcpmsg->address, id, disp->localport, bucket);
dispatch_log(disp, LVL(90),
"search for response in bucket %d: %s",
bucket, (resp == NULL ? "not found" : "found"));
@@ -1052,7 +1449,7 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) {
* Restart recv() to get the next packet.
*/
restart:
- startrecv(disp);
+ (void)startrecv(disp, NULL);
UNLOCK(&disp->lock);
@@ -1062,22 +1459,33 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) {
/*
* disp must be locked.
*/
-static void
-startrecv(dns_dispatch_t *disp) {
+static isc_result_t
+startrecv(dns_dispatch_t *disp, dispsocket_t *dispsock) {
isc_result_t res;
isc_region_t region;
+ isc_socket_t *socket;
if (disp->shutting_down == 1)
- return;
+ return (ISC_R_SUCCESS);
if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) != 0)
- return;
+ return (ISC_R_SUCCESS);
- if (disp->recv_pending != 0)
- return;
+ if (disp->recv_pending != 0 && dispsock == NULL)
+ return (ISC_R_SUCCESS);
if (disp->mgr->buffers >= disp->mgr->maxbuffers)
- return;
+ return (ISC_R_NOMEMORY);
+
+ if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0 &&
+ dispsock == NULL)
+ return (ISC_R_SUCCESS);
+
+ if (dispsock != NULL)
+ socket = dispsock->socket;
+ else
+ socket = disp->socket;
+ INSIST(socket != NULL);
switch (disp->socktype) {
/*
@@ -1087,28 +1495,38 @@ startrecv(dns_dispatch_t *disp) {
region.length = disp->mgr->buffersize;
region.base = allocate_udp_buffer(disp);
if (region.base == NULL)
- return;
- res = isc_socket_recv(disp->socket, &region, 1,
- disp->task, udp_recv, disp);
- if (res != ISC_R_SUCCESS) {
- free_buffer(disp, region.base, region.length);
- disp->shutdown_why = res;
- disp->shutting_down = 1;
- do_cancel(disp);
- return;
+ return (ISC_R_NOMEMORY);
+ if (dispsock != NULL) {
+ res = isc_socket_recv(socket, &region, 1,
+ dispsock->task, udp_exrecv,
+ dispsock);
+ if (res != ISC_R_SUCCESS) {
+ free_buffer(disp, region.base, region.length);
+ return (res);
+ }
+ } else {
+ res = isc_socket_recv(socket, &region, 1,
+ disp->task[0], udp_shrecv, disp);
+ if (res != ISC_R_SUCCESS) {
+ free_buffer(disp, region.base, region.length);
+ disp->shutdown_why = res;
+ disp->shutting_down = 1;
+ do_cancel(disp);
+ return (ISC_R_SUCCESS); /* recover by cancel */
+ }
+ INSIST(disp->recv_pending == 0);
+ disp->recv_pending = 1;
}
- INSIST(disp->recv_pending == 0);
- disp->recv_pending = 1;
break;
case isc_sockettype_tcp:
- res = dns_tcpmsg_readmessage(&disp->tcpmsg, disp->task,
+ res = dns_tcpmsg_readmessage(&disp->tcpmsg, disp->task[0],
tcp_recv, disp);
if (res != ISC_R_SUCCESS) {
disp->shutdown_why = res;
disp->shutting_down = 1;
do_cancel(disp);
- return;
+ return (ISC_R_SUCCESS); /* recover by cancel */
}
INSIST(disp->recv_pending == 0);
disp->recv_pending = 1;
@@ -1117,6 +1535,8 @@ startrecv(dns_dispatch_t *disp) {
INSIST(0);
break;
}
+
+ return (ISC_R_SUCCESS);
}
/*
@@ -1169,6 +1589,7 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) {
isc_mempool_destroy(&mgr->rpool);
isc_mempool_destroy(&mgr->dpool);
isc_mempool_destroy(&mgr->bpool);
+ isc_mempool_destroy(&mgr->spool);
DESTROYLOCK(&mgr->pool_lock);
@@ -1182,32 +1603,46 @@ destroy_mgr(dns_dispatchmgr_t **mgrp) {
if (mgr->blackhole != NULL)
dns_acl_detach(&mgr->blackhole);
- if (mgr->portlist != NULL)
- dns_portlist_detach(&mgr->portlist);
-
+ if (mgr->v4ports != NULL) {
+ isc_mem_put(mctx, mgr->v4ports,
+ mgr->nv4ports * sizeof(in_port_t));
+ }
+ if (mgr->v6ports != NULL) {
+ isc_mem_put(mctx, mgr->v6ports,
+ mgr->nv6ports * sizeof(in_port_t));
+ }
isc_mem_put(mctx, mgr, sizeof(dns_dispatchmgr_t));
isc_mem_detach(&mctx);
}
static isc_result_t
-create_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local,
- unsigned int options, isc_socket_t **sockp)
+open_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local,
+ unsigned int options, isc_socket_t **sockp)
{
isc_socket_t *sock;
isc_result_t result;
- sock = NULL;
- result = isc_socket_create(mgr, isc_sockaddr_pf(local),
- isc_sockettype_udp, &sock);
- if (result != ISC_R_SUCCESS)
- return (result);
+ sock = *sockp;
+ if (sock == NULL) {
+ result = isc_socket_create(mgr, isc_sockaddr_pf(local),
+ isc_sockettype_udp, &sock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ } else {
+ result = isc_socket_open(sock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
#ifndef ISC_ALLOW_MAPPED
isc_socket_ipv6only(sock, ISC_TRUE);
#endif
result = isc_socket_bind(sock, local, options);
if (result != ISC_R_SUCCESS) {
- isc_socket_detach(&sock);
+ if (*sockp == NULL)
+ isc_socket_detach(&sock);
+ else
+ isc_socket_close(sock);
return (result);
}
@@ -1215,6 +1650,24 @@ create_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local,
return (ISC_R_SUCCESS);
}
+/*%
+ * Create a temporary port list to set the initial default set of dispatch
+ * ports: [1024, 65535]. This is almost meaningless as the application will
+ * normally set the ports explicitly, but is provided to fill some minor corner
+ * cases.
+ */
+static isc_result_t
+create_default_portset(isc_mem_t *mctx, isc_portset_t **portsetp) {
+ isc_result_t result;
+
+ result = isc_portset_create(mctx, portsetp);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_portset_addrange(*portsetp, 1024, 65535);
+
+ return (ISC_R_SUCCESS);
+}
+
/*
* Publics.
*/
@@ -1225,6 +1678,8 @@ dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy,
{
dns_dispatchmgr_t *mgr;
isc_result_t result;
+ isc_portset_t *v4portset = NULL;
+ isc_portset_t *v6portset = NULL;
REQUIRE(mctx != NULL);
REQUIRE(mgrp != NULL && *mgrp == NULL);
@@ -1237,7 +1692,6 @@ dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy,
isc_mem_attach(mctx, &mgr->mctx);
mgr->blackhole = NULL;
- mgr->portlist = NULL;
result = isc_mutex_init(&mgr->lock);
if (result != ISC_R_SUCCESS)
@@ -1292,20 +1746,43 @@ dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy,
mgr->buffersize = 0;
mgr->maxbuffers = 0;
mgr->bpool = NULL;
+ mgr->spool = NULL;
mgr->entropy = NULL;
mgr->qid = NULL;
mgr->state = 0;
ISC_LIST_INIT(mgr->list);
+ mgr->v4ports = NULL;
+ mgr->v6ports = NULL;
+ mgr->nv4ports = 0;
+ mgr->nv6ports = 0;
mgr->magic = DNS_DISPATCHMGR_MAGIC;
+ result = create_default_portset(mctx, &v4portset);
+ if (result == ISC_R_SUCCESS) {
+ result = create_default_portset(mctx, &v6portset);
+ if (result == ISC_R_SUCCESS) {
+ result = dns_dispatchmgr_setavailports(mgr,
+ v4portset,
+ v6portset);
+ }
+ }
+ if (v4portset != NULL)
+ isc_portset_destroy(mctx, &v4portset);
+ if (v6portset != NULL)
+ isc_portset_destroy(mctx, &v6portset);
+ if (result != ISC_R_SUCCESS)
+ goto kill_dpool;
+
if (entropy != NULL)
isc_entropy_attach(entropy, &mgr->entropy);
- dispatch_arc4init(&mgr->arc4ctx);
+ dispatch_arc4init(&mgr->arc4ctx, mgr->entropy, &mgr->arc4_lock);
*mgrp = mgr;
return (ISC_R_SUCCESS);
+ kill_dpool:
+ isc_mempool_destroy(&mgr->dpool);
kill_rpool:
isc_mempool_destroy(&mgr->rpool);
kill_epool:
@@ -1344,22 +1821,88 @@ dns_dispatchmgr_setblackportlist(dns_dispatchmgr_t *mgr,
dns_portlist_t *portlist)
{
REQUIRE(VALID_DISPATCHMGR(mgr));
- if (mgr->portlist != NULL)
- dns_portlist_detach(&mgr->portlist);
- if (portlist != NULL)
- dns_portlist_attach(portlist, &mgr->portlist);
+ UNUSED(portlist);
+
+ /* This function is deprecated: use dns_dispatchmgr_setavailports(). */
+ return;
}
dns_portlist_t *
dns_dispatchmgr_getblackportlist(dns_dispatchmgr_t *mgr) {
REQUIRE(VALID_DISPATCHMGR(mgr));
- return (mgr->portlist);
+ return (NULL); /* this function is deprecated */
+}
+
+isc_result_t
+dns_dispatchmgr_setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset,
+ isc_portset_t *v6portset)
+{
+ in_port_t *v4ports, *v6ports, p;
+ unsigned int nv4ports, nv6ports, i4, i6;
+
+ REQUIRE(VALID_DISPATCHMGR(mgr));
+
+ nv4ports = isc_portset_nports(v4portset);
+ nv6ports = isc_portset_nports(v6portset);
+
+ v4ports = NULL;
+ if (nv4ports != 0) {
+ v4ports = isc_mem_get(mgr->mctx, sizeof(in_port_t) * nv4ports);
+ if (v4ports == NULL)
+ return (ISC_R_NOMEMORY);
+ }
+ v6ports = NULL;
+ if (nv6ports != 0) {
+ v6ports = isc_mem_get(mgr->mctx, sizeof(in_port_t) * nv6ports);
+ if (v6ports == NULL) {
+ if (v4ports != NULL) {
+ isc_mem_put(mgr->mctx, v4ports,
+ sizeof(in_port_t) *
+ isc_portset_nports(v4portset));
+ }
+ return (ISC_R_NOMEMORY);
+ }
+ }
+
+ p = 0;
+ i4 = 0;
+ i6 = 0;
+ do {
+ if (isc_portset_isset(v4portset, p)) {
+ INSIST(i4 < nv4ports);
+ v4ports[i4++] = p;
+ }
+ if (isc_portset_isset(v6portset, p)) {
+ INSIST(i6 < nv6ports);
+ v6ports[i6++] = p;
+ }
+ } while (p++ < 65535);
+ INSIST(i4 == nv4ports && i6 == nv6ports);
+
+ PORTBUFLOCK(mgr);
+ if (mgr->v4ports != NULL) {
+ isc_mem_put(mgr->mctx, mgr->v4ports,
+ mgr->nv4ports * sizeof(in_port_t));
+ }
+ mgr->v4ports = v4ports;
+ mgr->nv4ports = nv4ports;
+
+ if (mgr->v6ports != NULL) {
+ isc_mem_put(mgr->mctx, mgr->v6ports,
+ mgr->nv6ports * sizeof(in_port_t));
+ }
+ mgr->v6ports = v6ports;
+ mgr->nv6ports = nv6ports;
+ PORTBUFUNLOCK(mgr);
+
+ return (ISC_R_SUCCESS);
}
static isc_result_t
dns_dispatchmgr_setudp(dns_dispatchmgr_t *mgr,
- unsigned int buffersize, unsigned int maxbuffers,
- unsigned int buckets, unsigned int increment)
+ unsigned int buffersize, unsigned int maxbuffers,
+ unsigned int maxrequests, unsigned int buckets,
+ unsigned int increment)
{
isc_result_t result;
@@ -1386,24 +1929,39 @@ dns_dispatchmgr_setudp(dns_dispatchmgr_t *mgr,
maxbuffers = 8;
LOCK(&mgr->buffer_lock);
+
+ /* Create or adjust buffer pool */
if (mgr->bpool != NULL) {
isc_mempool_setmaxalloc(mgr->bpool, maxbuffers);
mgr->maxbuffers = maxbuffers;
+ } else {
+ result = isc_mempool_create(mgr->mctx, buffersize, &mgr->bpool);
+ if (result != ISC_R_SUCCESS) {
+ UNLOCK(&mgr->buffer_lock);
+ return (result);
+ }
+ isc_mempool_setname(mgr->bpool, "dispmgr_bpool");
+ isc_mempool_setmaxalloc(mgr->bpool, maxbuffers);
+ isc_mempool_associatelock(mgr->bpool, &mgr->pool_lock);
+ }
+
+ /* Create or adjust socket pool */
+ if (mgr->spool != NULL) {
+ isc_mempool_setmaxalloc(mgr->spool, DNS_DISPATCH_POOLSOCKS * 2);
UNLOCK(&mgr->buffer_lock);
return (ISC_R_SUCCESS);
}
-
- if (isc_mempool_create(mgr->mctx, buffersize,
- &mgr->bpool) != ISC_R_SUCCESS) {
+ result = isc_mempool_create(mgr->mctx, sizeof(dispsocket_t),
+ &mgr->spool);
+ if (result != ISC_R_SUCCESS) {
UNLOCK(&mgr->buffer_lock);
- return (ISC_R_NOMEMORY);
+ goto cleanup;
}
+ isc_mempool_setname(mgr->spool, "dispmgr_spool");
+ isc_mempool_setmaxalloc(mgr->spool, maxrequests);
+ isc_mempool_associatelock(mgr->spool, &mgr->pool_lock);
- isc_mempool_setname(mgr->bpool, "dispmgr_bpool");
- isc_mempool_setmaxalloc(mgr->bpool, maxbuffers);
- isc_mempool_associatelock(mgr->bpool, &mgr->pool_lock);
-
- result = qid_allocate(mgr, buckets, increment, &mgr->qid);
+ result = qid_allocate(mgr, buckets, increment, &mgr->qid, ISC_TRUE);
if (result != ISC_R_SUCCESS)
goto cleanup;
@@ -1414,8 +1972,10 @@ dns_dispatchmgr_setudp(dns_dispatchmgr_t *mgr,
cleanup:
isc_mempool_destroy(&mgr->bpool);
+ if (mgr->spool != NULL)
+ isc_mempool_destroy(&mgr->spool);
UNLOCK(&mgr->buffer_lock);
- return (ISC_R_NOMEMORY);
+ return (result);
}
void
@@ -1441,30 +2001,56 @@ dns_dispatchmgr_destroy(dns_dispatchmgr_t **mgrp) {
destroy_mgr(&mgr);
}
+static int
+port_cmp(const void *key, const void *ent) {
+ in_port_t p1 = *(const in_port_t *)key;
+ in_port_t p2 = *(const in_port_t *)ent;
+
+ if (p1 < p2)
+ return (-1);
+ else if (p1 == p2)
+ return (0);
+ else
+ return (1);
+}
+
static isc_boolean_t
-blacklisted(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
- isc_sockaddr_t *sockaddrp)
+portavailable(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
+ isc_sockaddr_t *sockaddrp)
{
isc_sockaddr_t sockaddr;
isc_result_t result;
+ in_port_t *ports, port;
+ unsigned int nports;
+ isc_boolean_t available = ISC_FALSE;
REQUIRE(sock != NULL || sockaddrp != NULL);
- if (mgr->portlist == NULL)
- return (ISC_FALSE);
-
+ PORTBUFLOCK(mgr);
if (sock != NULL) {
sockaddrp = &sockaddr;
result = isc_socket_getsockname(sock, sockaddrp);
if (result != ISC_R_SUCCESS)
- return (ISC_FALSE);
+ goto unlock;
}
- if (mgr->portlist != NULL &&
- dns_portlist_match(mgr->portlist, isc_sockaddr_pf(sockaddrp),
- isc_sockaddr_getport(sockaddrp)))
- return (ISC_TRUE);
- return (ISC_FALSE);
+ if (isc_sockaddr_pf(sockaddrp) == AF_INET) {
+ ports = mgr->v4ports;
+ nports = mgr->nv4ports;
+ } else {
+ ports = mgr->v6ports;
+ nports = mgr->nv6ports;
+ }
+ if (ports == NULL)
+ goto unlock;
+
+ port = isc_sockaddr_getport(sockaddrp);
+ if (bsearch(&port, ports, nports, sizeof(in_port_t), port_cmp) != NULL)
+ available = ISC_TRUE;
+
+unlock:
+ PORTBUFUNLOCK(mgr);
+ return (available);
}
#define ATTRMATCH(_a1, _a2, _mask) (((_a1) & (_mask)) == ((_a2) & (_mask)))
@@ -1474,17 +2060,20 @@ local_addr_match(dns_dispatch_t *disp, isc_sockaddr_t *addr) {
isc_sockaddr_t sockaddr;
isc_result_t result;
+ REQUIRE(disp->socket != NULL);
+
if (addr == NULL)
return (ISC_TRUE);
/*
- * Don't match wildcard ports against newly blacklisted ports.
+ * Don't match wildcard ports unless the port is available in the
+ * current configuration.
*/
- if (disp->mgr->portlist != NULL &&
- isc_sockaddr_getport(addr) == 0 &&
+ if (isc_sockaddr_getport(addr) == 0 &&
isc_sockaddr_getport(&disp->local) == 0 &&
- blacklisted(disp->mgr, disp->socket, NULL))
+ !portavailable(disp->mgr, disp->socket, NULL)) {
return (ISC_FALSE);
+ }
/*
* Check if we match the binding <address,port>.
@@ -1526,10 +2115,10 @@ dispatch_find(dns_dispatchmgr_t *mgr, isc_sockaddr_t *local,
isc_result_t result;
/*
- * Make certain that we will not match a private dispatch.
+ * Make certain that we will not match a private or exclusive dispatch.
*/
- attributes &= ~DNS_DISPATCHATTR_PRIVATE;
- mask |= DNS_DISPATCHATTR_PRIVATE;
+ attributes &= ~(DNS_DISPATCHATTR_PRIVATE|DNS_DISPATCHATTR_EXCLUSIVE);
+ mask |= (DNS_DISPATCHATTR_PRIVATE|DNS_DISPATCHATTR_EXCLUSIVE);
disp = ISC_LIST_HEAD(mgr->list);
while (disp != NULL) {
@@ -1556,7 +2145,8 @@ dispatch_find(dns_dispatchmgr_t *mgr, isc_sockaddr_t *local,
static isc_result_t
qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets,
- unsigned int increment, dns_qid_t **qidp)
+ unsigned int increment, dns_qid_t **qidp,
+ isc_boolean_t needsocktable)
{
dns_qid_t *qid;
unsigned int i;
@@ -1578,16 +2168,35 @@ qid_allocate(dns_dispatchmgr_t *mgr, unsigned int buckets,
return (ISC_R_NOMEMORY);
}
+ qid->sock_table = NULL;
+ if (needsocktable) {
+ qid->sock_table = isc_mem_get(mgr->mctx, buckets *
+ sizeof(dispsocketlist_t));
+ if (qid->sock_table == NULL) {
+ isc_mem_put(mgr->mctx, qid, sizeof(*qid));
+ isc_mem_put(mgr->mctx, qid->qid_table,
+ buckets * sizeof(dns_displist_t));
+ return (ISC_R_NOMEMORY);
+ }
+ }
+
result = isc_mutex_init(&qid->lock);
if (result != ISC_R_SUCCESS) {
+ if (qid->sock_table != NULL) {
+ isc_mem_put(mgr->mctx, qid->sock_table,
+ buckets * sizeof(dispsocketlist_t));
+ }
isc_mem_put(mgr->mctx, qid->qid_table,
buckets * sizeof(dns_displist_t));
isc_mem_put(mgr->mctx, qid, sizeof(*qid));
return (result);
}
- for (i = 0; i < buckets; i++)
+ for (i = 0; i < buckets; i++) {
ISC_LIST_INIT(qid->qid_table[i]);
+ if (qid->sock_table != NULL)
+ ISC_LIST_INIT(qid->sock_table[i]);
+ }
qid->qid_nbuckets = buckets;
qid->qid_increment = increment;
@@ -1609,6 +2218,10 @@ qid_destroy(isc_mem_t *mctx, dns_qid_t **qidp) {
qid->magic = 0;
isc_mem_put(mctx, qid->qid_table,
qid->qid_nbuckets * sizeof(dns_displist_t));
+ if (qid->sock_table != NULL) {
+ isc_mem_put(mctx, qid->sock_table,
+ qid->qid_nbuckets * sizeof(dispsocketlist_t));
+ }
DESTROYLOCK(&qid->lock);
isc_mem_put(mctx, qid, sizeof(*qid));
}
@@ -1652,6 +2265,10 @@ dispatch_allocate(dns_dispatchmgr_t *mgr, unsigned int maxrequests,
disp->requests = 0;
disp->tcpbuffers = 0;
disp->qid = NULL;
+ ISC_LIST_INIT(disp->activesockets);
+ ISC_LIST_INIT(disp->inactivesockets);
+ disp->nsockets = 0;
+ dispatch_arc4init(&disp->arc4ctx, mgr->entropy, NULL);
result = isc_mutex_init(&disp->lock);
if (result != ISC_R_SUCCESS)
@@ -1704,6 +2321,8 @@ dispatch_free(dns_dispatch_t **dispp)
INSIST(disp->tcpbuffers == 0);
INSIST(disp->requests == 0);
INSIST(disp->recv_pending == 0);
+ INSIST(ISC_LIST_EMPTY(disp->activesockets));
+ INSIST(ISC_LIST_EMPTY(disp->inactivesockets));
isc_mempool_put(mgr->epool, disp->failsafe_ev);
disp->failsafe_ev = NULL;
@@ -1749,7 +2368,7 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
return (result);
}
- result = qid_allocate(mgr, buckets, increment, &disp->qid);
+ result = qid_allocate(mgr, buckets, increment, &disp->qid, ISC_FALSE);
if (result != ISC_R_SUCCESS)
goto deallocate_dispatch;
@@ -1757,8 +2376,9 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
disp->socket = NULL;
isc_socket_attach(sock, &disp->socket);
- disp->task = NULL;
- result = isc_task_create(taskmgr, 0, &disp->task);
+ disp->ntasks = 1;
+ disp->task[0] = NULL;
+ result = isc_task_create(taskmgr, 0, &disp->task[0]);
if (result != ISC_R_SUCCESS)
goto kill_socket;
@@ -1771,7 +2391,7 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
goto kill_task;
}
- isc_task_setname(disp->task, "tcpdispatch", disp);
+ isc_task_setname(disp->task[0], "tcpdispatch", disp);
dns_tcpmsg_init(mgr->mctx, disp->socket, &disp->tcpmsg);
disp->tcpmsg_valid = 1;
@@ -1785,7 +2405,7 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
UNLOCK(&mgr->lock);
mgr_log(mgr, LVL(90), "created TCP dispatcher %p", disp);
- dispatch_log(disp, LVL(90), "created task %p", disp->task);
+ dispatch_log(disp, LVL(90), "created task %p", disp->task[0]);
*dispp = disp;
@@ -1795,7 +2415,7 @@ dns_dispatch_createtcp(dns_dispatchmgr_t *mgr, isc_socket_t *sock,
* Error returns.
*/
kill_task:
- isc_task_detach(&disp->task);
+ isc_task_detach(&disp->task[0]);
kill_socket:
isc_socket_detach(&disp->socket);
deallocate_dispatch:
@@ -1830,13 +2450,13 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
REQUIRE((attributes & DNS_DISPATCHATTR_TCP) == 0);
result = dns_dispatchmgr_setudp(mgr, buffersize, maxbuffers,
- buckets, increment);
+ maxrequests, buckets, increment);
if (result != ISC_R_SUCCESS)
return (result);
LOCK(&mgr->lock);
- if ((attributes & DNS_DISPATCHATTR_RANDOMPORT) != 0) {
+ if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
REQUIRE(isc_sockaddr_getport(localaddr) == 0);
goto createudp;
}
@@ -1857,7 +2477,7 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
{
disp->attributes |= DNS_DISPATCHATTR_NOLISTEN;
if (disp->recv_pending != 0)
- isc_socket_cancel(disp->socket, disp->task,
+ isc_socket_cancel(disp->socket, disp->task[0],
ISC_SOCKCANCEL_RECV);
}
@@ -1894,6 +2514,101 @@ dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
#endif
static isc_result_t
+get_udpsocket(dns_dispatchmgr_t *mgr, dns_dispatch_t *disp,
+ isc_socketmgr_t *sockmgr, isc_sockaddr_t *localaddr,
+ isc_socket_t **sockp)
+{
+ unsigned int i, j;
+ isc_socket_t *held[DNS_DISPATCH_HELD];
+ isc_sockaddr_t localaddr_bound;
+ isc_socket_t *sock = NULL;
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_boolean_t anyport;
+
+ INSIST(sockp != NULL && *sockp == NULL);
+
+ localaddr_bound = *localaddr;
+ anyport = ISC_TF(isc_sockaddr_getport(localaddr) == 0);
+
+ if (anyport) {
+ unsigned int nports;
+ in_port_t *ports;
+
+ /*
+ * If no port is specified, we first try to pick up a random
+ * port by ourselves.
+ */
+ if (isc_sockaddr_pf(&disp->local) == AF_INET) {
+ nports = disp->mgr->nv4ports;
+ ports = disp->mgr->v4ports;
+ } else {
+ nports = disp->mgr->nv6ports;
+ ports = disp->mgr->v6ports;
+ }
+ if (nports == 0)
+ return (ISC_R_ADDRNOTAVAIL);
+
+ for (i = 0; i < 1024; i++) {
+ in_port_t prt;
+
+ prt = ports[dispatch_arc4uniformrandom(
+ DISP_ARC4CTX(disp),
+ nports)];
+ isc_sockaddr_setport(&localaddr_bound, prt);
+ result = open_socket(sockmgr, &localaddr_bound,
+ 0, &sock);
+ if (result == ISC_R_SUCCESS ||
+ result != ISC_R_ADDRINUSE) {
+ disp->localport = prt;
+ *sockp = sock;
+ return (result);
+ }
+ }
+
+ /*
+ * If this fails 1024 times, we then ask the kernel for
+ * choosing one.
+ */
+ }
+
+ memset(held, 0, sizeof(held));
+ i = 0;
+
+ for (j = 0; j < 0xffffU; j++) {
+ result = open_socket(sockmgr, localaddr, 0, &sock);
+ if (result != ISC_R_SUCCESS)
+ goto end;
+ else if (!anyport)
+ break;
+ else if (portavailable(mgr, sock, NULL))
+ break;
+ if (held[i] != NULL)
+ isc_socket_detach(&held[i]);
+ held[i++] = sock;
+ sock = NULL;
+ if (i == DNS_DISPATCH_HELD)
+ i = 0;
+ }
+ if (j == 0xffffU) {
+ mgr_log(mgr, ISC_LOG_ERROR,
+ "avoid-v%s-udp-ports: unable to allocate "
+ "an available port",
+ isc_sockaddr_pf(localaddr) == AF_INET ? "4" : "6");
+ result = ISC_R_FAILURE;
+ goto end;
+ }
+ *sockp = sock;
+
+end:
+ for (i = 0; i < DNS_DISPATCH_HELD; i++) {
+ if (held[i] != NULL)
+ isc_socket_detach(&held[i]);
+ }
+
+ return (result);
+}
+
+static isc_result_t
dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
isc_taskmgr_t *taskmgr,
isc_sockaddr_t *localaddr,
@@ -1904,10 +2619,7 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
isc_result_t result;
dns_dispatch_t *disp;
isc_socket_t *sock = NULL;
- isc_socket_t *held[DNS_DISPATCH_HELD];
- unsigned int i = 0, j = 0, k = 0;
- isc_sockaddr_t localaddr_bound;
- in_port_t localport = 0;
+ int i = 0;
/*
* dispatch_allocate() checks mgr for us.
@@ -1917,67 +2629,46 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
if (result != ISC_R_SUCCESS)
return (result);
- /*
- * Try to allocate a socket that is not on the blacklist.
- * Hold up to DNS_DISPATCH_HELD sockets to prevent the OS
- * from returning the same port to us too quickly.
- */
- memset(held, 0, sizeof(held));
- localaddr_bound = *localaddr;
- getsocket:
- if ((attributes & DNS_DISPATCHATTR_RANDOMPORT) != 0) {
- in_port_t prt;
-
- /* XXX: should the range be configurable? */
- prt = 1024 + dispatch_arc4uniformrandom(mgr, 65535 - 1023);
- isc_sockaddr_setport(&localaddr_bound, prt);
- if (blacklisted(mgr, NULL, &localaddr_bound)) {
- if (++k == 1024)
- attributes &= ~DNS_DISPATCHATTR_RANDOMPORT;
- goto getsocket;
- }
- result = create_socket(sockmgr, &localaddr_bound, 0, &sock);
- if (result == ISC_R_ADDRINUSE) {
- if (++k == 1024)
- attributes &= ~DNS_DISPATCHATTR_RANDOMPORT;
- goto getsocket;
- }
- localport = prt;
- } else
- result = create_socket(sockmgr, localaddr,
- ISC_SOCKET_REUSEADDRESS, &sock);
- if (result != ISC_R_SUCCESS)
- goto deallocate_dispatch;
- if ((attributes & DNS_DISPATCHATTR_RANDOMPORT) == 0 &&
- isc_sockaddr_getport(localaddr) == 0 &&
- blacklisted(mgr, sock, NULL))
- {
- if (held[i] != NULL)
- isc_socket_detach(&held[i]);
- held[i++] = sock;
- sock = NULL;
- if (i == DNS_DISPATCH_HELD)
- i = 0;
- if (j++ == 0xffffU) {
- mgr_log(mgr, ISC_LOG_ERROR, "avoid-v%s-udp-ports: "
- "unable to allocate a non-blacklisted port",
- isc_sockaddr_pf(localaddr) == AF_INET ?
- "4" : "6");
- result = ISC_R_FAILURE;
+ if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0) {
+ result = get_udpsocket(mgr, disp, sockmgr, localaddr, &sock);
+ if (result != ISC_R_SUCCESS)
goto deallocate_dispatch;
+ } else {
+ isc_sockaddr_t sa_any;
+
+ /*
+ * For dispatches using exclusive sockets with a specific
+ * source address, we only check if the specified address is
+ * available on the system. Query sockets will be created later
+ * on demand.
+ */
+ isc_sockaddr_anyofpf(&sa_any, isc_sockaddr_pf(localaddr));
+ if (!isc_sockaddr_eqaddr(&sa_any, localaddr)) {
+ result = open_socket(sockmgr, localaddr, 0, &sock);
+ if (sock != NULL)
+ isc_socket_detach(&sock);
+ if (result != ISC_R_SUCCESS)
+ goto deallocate_dispatch;
}
- goto getsocket;
}
-
disp->socktype = isc_sockettype_udp;
disp->socket = sock;
disp->local = *localaddr;
- disp->localport = localport;
- disp->task = NULL;
- result = isc_task_create(taskmgr, 0, &disp->task);
- if (result != ISC_R_SUCCESS)
- goto kill_socket;
+ if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0)
+ disp->ntasks = MAX_INTERNAL_TASKS;
+ else
+ disp->ntasks = 1;
+ for (i = 0; i < disp->ntasks; i++) {
+ disp->task[i] = NULL;
+ result = isc_task_create(taskmgr, 0, &disp->task[i]);
+ if (result != ISC_R_SUCCESS) {
+ while (--i >= 0)
+ isc_task_destroy(&disp->task[i]);
+ goto kill_socket;
+ }
+ isc_task_setname(disp->task[i], "udpdispatch", disp);
+ }
disp->ctlevent = isc_event_allocate(mgr->mctx, disp,
DNS_EVENT_DISPATCHCONTROL,
@@ -1988,8 +2679,6 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
goto kill_task;
}
- isc_task_setname(disp->task, "udpdispatch", disp);
-
attributes &= ~DNS_DISPATCHATTR_TCP;
attributes |= DNS_DISPATCHATTR_UDP;
disp->attributes = attributes;
@@ -2000,26 +2689,25 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
ISC_LIST_APPEND(mgr->list, disp, link);
mgr_log(mgr, LVL(90), "created UDP dispatcher %p", disp);
- dispatch_log(disp, LVL(90), "created task %p", disp->task);
- dispatch_log(disp, LVL(90), "created socket %p", disp->socket);
+ dispatch_log(disp, LVL(90), "created task %p", disp->task[0]); /* XXX */
+ if (disp->socket != NULL)
+ dispatch_log(disp, LVL(90), "created socket %p", disp->socket);
*dispp = disp;
-
- goto cleanheld;
+ return (result);
/*
* Error returns.
*/
kill_task:
- isc_task_detach(&disp->task);
+ for (i = 0; i < disp->ntasks; i++)
+ isc_task_detach(&disp->task[i]);
kill_socket:
- isc_socket_detach(&disp->socket);
+ if (disp->socket != NULL)
+ isc_socket_detach(&disp->socket);
deallocate_dispatch:
dispatch_free(&disp);
- cleanheld:
- for (i = 0; i < DNS_DISPATCH_HELD; i++)
- if (held[i] != NULL)
- isc_socket_detach(&held[i]);
+
return (result);
}
@@ -2045,6 +2733,7 @@ dns_dispatch_attach(dns_dispatch_t *disp, dns_dispatch_t **dispp) {
void
dns_dispatch_detach(dns_dispatch_t **dispp) {
dns_dispatch_t *disp;
+ dispsocket_t *dispsock;
isc_boolean_t killit;
REQUIRE(dispp != NULL && VALID_DISPATCH(*dispp));
@@ -2059,8 +2748,14 @@ dns_dispatch_detach(dns_dispatch_t **dispp) {
killit = ISC_FALSE;
if (disp->refcount == 0) {
if (disp->recv_pending > 0)
- isc_socket_cancel(disp->socket, disp->task,
+ isc_socket_cancel(disp->socket, disp->task[0],
+ ISC_SOCKCANCEL_RECV);
+ for (dispsock = ISC_LIST_HEAD(disp->activesockets);
+ dispsock != NULL;
+ dispsock = ISC_LIST_NEXT(dispsock, link)) {
+ isc_socket_cancel(dispsock->socket, dispsock->task,
ISC_SOCKCANCEL_RECV);
+ }
disp->shutting_down = 1;
}
@@ -2069,26 +2764,32 @@ dns_dispatch_detach(dns_dispatch_t **dispp) {
killit = destroy_disp_ok(disp);
UNLOCK(&disp->lock);
if (killit)
- isc_task_send(disp->task, &disp->ctlevent);
+ isc_task_send(disp->task[0], &disp->ctlevent);
}
isc_result_t
-dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
- isc_task_t *task, isc_taskaction_t action, void *arg,
- dns_messageid_t *idp, dns_dispentry_t **resp)
+dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ dns_messageid_t *idp, dns_dispentry_t **resp,
+ isc_socketmgr_t *sockmgr)
{
dns_dispentry_t *res;
unsigned int bucket;
+ in_port_t localport = 0;
dns_messageid_t id;
int i;
isc_boolean_t ok;
dns_qid_t *qid;
+ dispsocket_t *dispsocket = NULL;
+ isc_result_t result;
REQUIRE(VALID_DISPATCH(disp));
REQUIRE(task != NULL);
REQUIRE(dest != NULL);
REQUIRE(resp != NULL && *resp == NULL);
REQUIRE(idp != NULL);
+ if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0)
+ REQUIRE(sockmgr != NULL);
LOCK(&disp->lock);
@@ -2102,23 +2803,75 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
return (ISC_R_QUOTA);
}
+ if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0 &&
+ disp->nsockets > DNS_DISPATCH_SOCKSQUOTA) {
+ dispsocket_t *oldestsocket;
+ dns_dispentry_t *oldestresp;
+ dns_dispatchevent_t *rev;
+
+ /*
+ * Kill oldest outstanding query if the number of sockets
+ * exceeds the quota to keep the room for new queries.
+ */
+ oldestsocket = ISC_LIST_HEAD(disp->activesockets);
+ oldestresp = oldestsocket->resp;
+ if (oldestresp != NULL && !oldestresp->item_out) {
+ rev = allocate_event(oldestresp->disp);
+ if (rev != NULL) {
+ rev->buffer.base = NULL;
+ rev->result = ISC_R_CANCELED;
+ rev->id = oldestresp->id;
+ ISC_EVENT_INIT(rev, sizeof(*rev), 0,
+ NULL, DNS_EVENT_DISPATCH,
+ oldestresp->action,
+ oldestresp->arg, oldestresp,
+ NULL, NULL);
+ oldestresp->item_out = ISC_TRUE;
+ isc_task_send(oldestresp->task,
+ ISC_EVENT_PTR(&rev));
+ }
+ }
+
+ /*
+ * Move this entry to the tail so that it won't (easily) be
+ * examined before actually being canceled.
+ */
+ ISC_LIST_UNLINK(disp->activesockets, oldestsocket, link);
+ ISC_LIST_APPEND(disp->activesockets, oldestsocket, link);
+ }
+
+ qid = DNS_QID(disp);
+ LOCK(&qid->lock);
+
+ if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
+ /*
+ * Get a separate UDP socket with a random port number.
+ */
+ result = get_dispsocket(disp, dest, sockmgr, qid, &dispsocket,
+ &localport);
+ if (result != ISC_R_SUCCESS) {
+ UNLOCK(&qid->lock);
+ UNLOCK(&disp->lock);
+ return (result);
+ }
+ } else {
+ localport = disp->localport;
+ }
+
/*
* Try somewhat hard to find an unique ID.
*/
- id = (dns_messageid_t)dispatch_arc4random(disp->mgr);
- qid = DNS_QID(disp);
- LOCK(&qid->lock);
- bucket = dns_hash(qid, dest, id, disp->localport);
+ id = (dns_messageid_t)dispatch_arc4random(DISP_ARC4CTX(disp));
+ bucket = dns_hash(qid, dest, id, localport);
ok = ISC_FALSE;
for (i = 0; i < 64; i++) {
- if (bucket_search(qid, dest, id, disp->localport, bucket) ==
- NULL) {
+ if (entry_search(qid, dest, id, localport, bucket) == NULL) {
ok = ISC_TRUE;
break;
}
id += qid->qid_increment;
id &= 0x0000ffff;
- bucket = dns_hash(qid, dest, id, disp->localport);
+ bucket = dns_hash(qid, dest, id, localport);
}
if (!ok) {
@@ -2131,6 +2884,8 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
if (res == NULL) {
UNLOCK(&qid->lock);
UNLOCK(&disp->lock);
+ if (dispsocket != NULL)
+ destroy_dispsocket(disp, &dispsocket);
return (ISC_R_NOMEMORY);
}
@@ -2140,11 +2895,14 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
isc_task_attach(task, &res->task);
res->disp = disp;
res->id = id;
- res->port = disp->localport;
+ res->port = localport;
res->bucket = bucket;
res->host = *dest;
res->action = action;
res->arg = arg;
+ res->dispsocket = dispsocket;
+ if (dispsocket != NULL)
+ dispsocket->resp = res;
res->item_out = ISC_FALSE;
ISC_LIST_INIT(res->items);
ISC_LINK_INIT(res, link);
@@ -2156,27 +2914,62 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
"attached to task %p", res->task);
if (((disp->attributes & DNS_DISPATCHATTR_UDP) != 0) ||
- ((disp->attributes & DNS_DISPATCHATTR_CONNECTED) != 0))
- startrecv(disp);
+ ((disp->attributes & DNS_DISPATCHATTR_CONNECTED) != 0)) {
+ result = startrecv(disp, dispsocket);
+ if (result != ISC_R_SUCCESS) {
+ LOCK(&qid->lock);
+ ISC_LIST_UNLINK(qid->qid_table[bucket], res, link);
+ UNLOCK(&qid->lock);
+
+ if (dispsocket != NULL)
+ destroy_dispsocket(disp, &dispsocket);
+
+ disp->refcount--;
+ disp->requests--;
+
+ UNLOCK(&disp->lock);
+ isc_task_detach(&res->task);
+ isc_mempool_put(disp->mgr->rpool, res);
+ return (result);
+ }
+ }
+
+ if (dispsocket != NULL)
+ ISC_LIST_APPEND(disp->activesockets, dispsocket, link);
UNLOCK(&disp->lock);
*idp = id;
*resp = res;
+ if ((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) != 0)
+ INSIST(res->dispsocket != NULL);
+
return (ISC_R_SUCCESS);
}
+isc_result_t
+dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ dns_messageid_t *idp, dns_dispentry_t **resp)
+{
+ REQUIRE(VALID_DISPATCH(disp));
+ REQUIRE((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0);
+
+ return (dns_dispatch_addresponse2(disp, dest, task, action, arg,
+ idp, resp, NULL));
+}
+
void
dns_dispatch_starttcp(dns_dispatch_t *disp) {
REQUIRE(VALID_DISPATCH(disp));
- dispatch_log(disp, LVL(90), "starttcp %p", disp->task);
+ dispatch_log(disp, LVL(90), "starttcp %p", disp->task[0]);
LOCK(&disp->lock);
disp->attributes |= DNS_DISPATCHATTR_CONNECTED;
- startrecv(disp);
+ (void)startrecv(disp, NULL);
UNLOCK(&disp->lock);
}
@@ -2187,6 +2980,7 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp,
dns_dispatchmgr_t *mgr;
dns_dispatch_t *disp;
dns_dispentry_t *res;
+ dispsocket_t *dispsock;
dns_dispatchevent_t *ev;
unsigned int bucket;
isc_boolean_t killit;
@@ -2224,8 +3018,14 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp,
killit = ISC_FALSE;
if (disp->refcount == 0) {
if (disp->recv_pending > 0)
- isc_socket_cancel(disp->socket, disp->task,
+ isc_socket_cancel(disp->socket, disp->task[0],
ISC_SOCKCANCEL_RECV);
+ for (dispsock = ISC_LIST_HEAD(disp->activesockets);
+ dispsock != NULL;
+ dispsock = ISC_LIST_NEXT(dispsock, link)) {
+ isc_socket_cancel(dispsock->socket, dispsock->task,
+ ISC_SOCKCANCEL_RECV);
+ }
disp->shutting_down = 1;
}
@@ -2261,6 +3061,12 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp,
request_log(disp, res, LVL(90), "detaching from task %p", res->task);
isc_task_detach(&res->task);
+ if (res->dispsocket != NULL) {
+ isc_socket_cancel(res->dispsocket->socket,
+ res->dispsocket->task, ISC_SOCKCANCEL_RECV);
+ res->dispsocket->resp = NULL;
+ }
+
/*
* Free any buffered requests as well
*/
@@ -2277,12 +3083,12 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp,
if (disp->shutting_down == 1)
do_cancel(disp);
else
- startrecv(disp);
+ (void)startrecv(disp, NULL);
killit = destroy_disp_ok(disp);
UNLOCK(&disp->lock);
if (killit)
- isc_task_send(disp->task, &disp->ctlevent);
+ isc_task_send(disp->task[0], &disp->ctlevent);
}
static void
@@ -2297,13 +3103,15 @@ do_cancel(dns_dispatch_t *disp) {
qid = DNS_QID(disp);
/*
- * Search for the first response handler without packets outstanding.
+ * Search for the first response handler without packets outstanding
+ * unless a specific hander is given.
*/
LOCK(&qid->lock);
for (resp = linear_first(qid);
- resp != NULL && resp->item_out != ISC_FALSE;
+ resp != NULL && resp->item_out;
/* Empty. */)
resp = linear_next(qid, resp);
+
/*
* No one to send the cancel event to, so nothing to do.
*/
@@ -2336,6 +3144,16 @@ dns_dispatch_getsocket(dns_dispatch_t *disp) {
return (disp->socket);
}
+isc_socket_t *
+dns_dispatch_getentrysocket(dns_dispentry_t *resp) {
+ REQUIRE(VALID_RESPONSE(resp));
+
+ if (resp->dispsocket != NULL)
+ return (resp->dispsocket->socket);
+ else
+ return (NULL);
+}
+
isc_result_t
dns_dispatch_getlocaladdress(dns_dispatch_t *disp, isc_sockaddr_t *addrp) {
@@ -2369,11 +3187,27 @@ dns_dispatch_cancel(dns_dispatch_t *disp) {
return;
}
+unsigned int
+dns_dispatch_getattributes(dns_dispatch_t *disp) {
+ REQUIRE(VALID_DISPATCH(disp));
+
+ /*
+ * We don't bother locking disp here; it's the caller's responsibility
+ * to use only non volatile flags.
+ */
+ return (disp->attributes);
+}
+
void
dns_dispatch_changeattributes(dns_dispatch_t *disp,
unsigned int attributes, unsigned int mask)
{
REQUIRE(VALID_DISPATCH(disp));
+ /* Exclusive attribute can only be set on creation */
+ REQUIRE((attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0);
+ /* Also, a dispatch with randomport specified cannot start listening */
+ REQUIRE((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0 ||
+ (attributes & DNS_DISPATCHATTR_NOLISTEN) == 0);
/* XXXMLG
* Should check for valid attributes here!
@@ -2385,13 +3219,13 @@ dns_dispatch_changeattributes(dns_dispatch_t *disp,
if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN) != 0 &&
(attributes & DNS_DISPATCHATTR_NOLISTEN) == 0) {
disp->attributes &= ~DNS_DISPATCHATTR_NOLISTEN;
- startrecv(disp);
+ (void)startrecv(disp, NULL);
} else if ((disp->attributes & DNS_DISPATCHATTR_NOLISTEN)
== 0 &&
(attributes & DNS_DISPATCHATTR_NOLISTEN) != 0) {
disp->attributes |= DNS_DISPATCHATTR_NOLISTEN;
if (disp->recv_pending != 0)
- isc_socket_cancel(disp->socket, disp->task,
+ isc_socket_cancel(disp->socket, disp->task[0],
ISC_SOCKCANCEL_RECV);
}
}
@@ -2415,7 +3249,7 @@ dns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t *event) {
INSIST(sevent->n <= disp->mgr->buffersize);
newsevent = (isc_socketevent_t *)
isc_event_allocate(disp->mgr->mctx, NULL,
- DNS_EVENT_IMPORTRECVDONE, udp_recv,
+ DNS_EVENT_IMPORTRECVDONE, udp_shrecv,
disp, sizeof(isc_socketevent_t));
if (newsevent == NULL)
return;
@@ -2434,8 +3268,8 @@ dns_dispatch_importrecv(dns_dispatch_t *disp, isc_event_t *event) {
newsevent->timestamp = sevent->timestamp;
newsevent->pktinfo = sevent->pktinfo;
newsevent->attributes = sevent->attributes;
-
- isc_task_send(disp->task, ISC_EVENT_PTR(&newsevent));
+
+ isc_task_send(disp->task[0], ISC_EVENT_PTR(&newsevent));
}
#if 0
diff --git a/lib/dns/dst_parse.c b/lib/dns/dst_parse.c
index aad7998..ce361ef 100644
--- a/lib/dns/dst_parse.c
+++ b/lib/dns/dst_parse.c
@@ -1,9 +1,9 @@
/*
- * Portions Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2006, 2008 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 1999-2002 Internet Software Consortium.
* Portions Copyright (C) 1995-2000 by Network Associates, Inc.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,7 +18,7 @@
/*%
* Principal Author: Brian Wellington
- * $Id: dst_parse.c,v 1.1.6.7 2006/05/16 03:59:26 marka Exp $
+ * $Id: dst_parse.c,v 1.1.6.9 2008/01/22 23:27:05 tbox Exp $
*/
#include <config.h>
@@ -260,6 +260,7 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
REQUIRE(priv != NULL);
priv->nelements = 0;
+ memset(priv->elements, 0, sizeof(priv->elements));
#define NEXTTOKEN(lex, opt, token) \
do { \
@@ -351,7 +352,6 @@ dst__privstruct_parse(dst_key_t *key, unsigned int alg, isc_lex_t *lex,
goto fail;
}
- memset(&priv->elements[n], 0, sizeof(dst_private_element_t));
tag = find_value(DST_AS_STR(token), alg);
if (tag < 0 || TAG_ALG(tag) != alg) {
ret = DST_R_INVALIDPRIVATEKEY;
diff --git a/lib/dns/dst_parse.h b/lib/dns/dst_parse.h
index 8656f59..665fcfc 100644
--- a/lib/dns/dst_parse.h
+++ b/lib/dns/dst_parse.h
@@ -1,9 +1,9 @@
/*
- * Portions Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (C) 2004-2006, 2008 Internet Systems Consortium, Inc. ("ISC")
* Portions Copyright (C) 2000-2002 Internet Software Consortium.
* Portions Copyright (C) 1995-2000 by Network Associates, Inc.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -16,7 +16,7 @@
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dst_parse.h,v 1.1.6.5 2006/01/27 23:57:44 marka Exp $ */
+/* $Id: dst_parse.h,v 1.1.6.7 2008/05/15 23:46:06 tbox Exp $ */
/*! \file */
#ifndef DST_DST_PARSE_H
@@ -75,7 +75,7 @@
#define HMACSHA256_NTAGS 2
#define TAG_HMACSHA256_KEY ((DST_ALG_HMACSHA256 << TAG_SHIFT) + 0)
-#define TAG_HMACSHA256_BITS ((DST_ALG_HMACSHA224 << TAG_SHIFT) + 1)
+#define TAG_HMACSHA256_BITS ((DST_ALG_HMACSHA256 << TAG_SHIFT) + 1)
#define HMACSHA384_NTAGS 2
#define TAG_HMACSHA384_KEY ((DST_ALG_HMACSHA384 << TAG_SHIFT) + 0)
diff --git a/lib/dns/include/dns/dispatch.h b/lib/dns/include/dns/dispatch.h
index 914993b..8c14320 100644
--- a/lib/dns/include/dns/dispatch.h
+++ b/lib/dns/include/dns/dispatch.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: dispatch.h,v 1.48.18.5.12.2 2008/07/23 07:28:56 tbox Exp $ */
+/* $Id: dispatch.h,v 1.48.18.9 2008/06/24 23:45:55 tbox Exp $ */
#ifndef DNS_DISPATCH_H
#define DNS_DISPATCH_H 1
@@ -105,7 +105,7 @@ struct dns_dispatchevent {
* The dispatcher is a TCP or UDP socket.
*
* _IPV4, _IPV6
- * The dispatcher uses an ipv4 or ipv6 socket.
+ * The dispatcher uses an IPv4 or IPv6 socket.
*
* _NOLISTEN
* The dispatcher should not listen on the socket.
@@ -115,7 +115,12 @@ struct dns_dispatchevent {
* accept replies from them.
*
* _RANDOMPORT
- * Allocate UDP port randomly.
+ * Previously used to indicate that the port of a dispatch UDP must be
+ * chosen randomly. This behavior now always applies and the attribute
+ * is obsoleted.
+ *
+ * _EXCLUSIVE
+ * A separate socket will be used on-demand for each transaction.
*/
#define DNS_DISPATCHATTR_PRIVATE 0x00000001U
#define DNS_DISPATCHATTR_TCP 0x00000002U
@@ -125,7 +130,8 @@ struct dns_dispatchevent {
#define DNS_DISPATCHATTR_NOLISTEN 0x00000020U
#define DNS_DISPATCHATTR_MAKEQUERY 0x00000040U
#define DNS_DISPATCHATTR_CONNECTED 0x00000080U
-#define DNS_DISPATCHATTR_RANDOMPORT 0x00000100U
+/*#define DNS_DISPATCHATTR_RANDOMPORT 0x00000100U*/
+#define DNS_DISPATCHATTR_EXCLUSIVE 0x00000200U
/*@}*/
isc_result_t
@@ -187,26 +193,34 @@ dns_dispatchmgr_getblackhole(dns_dispatchmgr_t *mgr);
void
dns_dispatchmgr_setblackportlist(dns_dispatchmgr_t *mgr,
- dns_portlist_t *portlist);
+ dns_portlist_t *portlist);
/*%<
- * Sets a list of UDP ports that won't be used when creating a udp
- * dispatch with a wildcard port.
+ * This function is deprecated. Use dns_dispatchmgr_setavailports() instead.
*
* Requires:
*\li mgr is a valid dispatchmgr
- *\li portlist to be NULL or a valid port list.
*/
dns_portlist_t *
dns_dispatchmgr_getblackportlist(dns_dispatchmgr_t *mgr);
/*%<
- * Return the current port list.
+ * This function is deprecated and always returns NULL.
*
* Requires:
*\li mgr is a valid dispatchmgr
*/
-
+isc_result_t
+dns_dispatchmgr_setavailports(dns_dispatchmgr_t *mgr, isc_portset_t *v4portset,
+ isc_portset_t *v6portset);
+/*%<
+ * Sets a list of UDP ports that can be used for outgoing UDP messages.
+ *
+ * Requires:
+ *\li mgr is a valid dispatchmgr
+ *\li v4portset is NULL or a valid port set
+ *\li v6portset is NULL or a valid port set
+ */
isc_result_t
dns_dispatch_getudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr,
@@ -319,6 +333,12 @@ dns_dispatch_starttcp(dns_dispatch_t *disp);
*/
isc_result_t
+dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest,
+ isc_task_t *task, isc_taskaction_t action, void *arg,
+ isc_uint16_t *idp, dns_dispentry_t **resp,
+ isc_socketmgr_t *sockmgr);
+
+isc_result_t
dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
isc_task_t *task, isc_taskaction_t action, void *arg,
isc_uint16_t *idp, dns_dispentry_t **resp);
@@ -341,6 +361,10 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest,
*
*\li "resp" be non-NULL and *resp be NULL
*
+ *\li "sockmgr" be NULL or a valid socket manager. If 'disp' has
+ * the DNS_DISPATCHATTR_EXCLUSIVE attribute, this must not be NULL,
+ * which also means dns_dispatch_addresponse() cannot be used.
+ *
* Ensures:
*
*\li &lt;id, dest> is a unique tuple. That means incoming messages
@@ -367,10 +391,12 @@ dns_dispatch_removeresponse(dns_dispentry_t **resp,
*\li "resp" != NULL and "*resp" contain a value previously allocated
* by dns_dispatch_addresponse();
*
- *\li May only be called from within the task given as the 'task'
+ *\li May only be called from within the task given as the 'task'
* argument to dns_dispatch_addresponse() when allocating '*resp'.
*/
+isc_socket_t *
+dns_dispatch_getentrysocket(dns_dispentry_t *resp);
isc_socket_t *
dns_dispatch_getsocket(dns_dispatch_t *disp);
@@ -384,7 +410,7 @@ dns_dispatch_getsocket(dns_dispatch_t *disp);
*\li The socket the dispatcher is using.
*/
-isc_result_t
+isc_result_t
dns_dispatch_getlocaladdress(dns_dispatch_t *disp, isc_sockaddr_t *addrp);
/*%<
* Return the local address for this dispatch.
@@ -395,7 +421,7 @@ dns_dispatch_getlocaladdress(dns_dispatch_t *disp, isc_sockaddr_t *addrp);
*\li addrp to be non null.
*
* Returns:
- *\li ISC_R_SUCCESS
+ *\li ISC_R_SUCCESS
*\li ISC_R_NOTIMPLEMENTED
*/
@@ -408,6 +434,16 @@ dns_dispatch_cancel(dns_dispatch_t *disp);
*\li disp is valid.
*/
+unsigned int
+dns_dispatch_getattributes(dns_dispatch_t *disp);
+/*%<
+ * Return the attributes (DNS_DISPATCHATTR_xxx) of this dispatch. Only the
+ * non-changeable attributes are expected to be referenced by the caller.
+ *
+ * Requires:
+ *\li disp is valid.
+ */
+
void
dns_dispatch_changeattributes(dns_dispatch_t *disp,
unsigned int attributes, unsigned int mask);
@@ -421,7 +457,7 @@ dns_dispatch_changeattributes(dns_dispatch_t *disp,
* new = (old & ~mask) | (attributes & mask)
* \endcode
*
- * This function has a side effect when #DNS_DISPATCHATTR_NOLISTEN changes.
+ * This function has a side effect when #DNS_DISPATCHATTR_NOLISTEN changes.
* When the flag becomes off, the dispatch will start receiving on the
* corresponding socket. When the flag becomes on, receive events on the
* corresponding socket will be canceled.
diff --git a/lib/dns/journal.c b/lib/dns/journal.c
index 6cfb5af..4e4010f 100644
--- a/lib/dns/journal.c
+++ b/lib/dns/journal.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: journal.c,v 1.86.18.12 2007/09/07 05:21:41 marka Exp $ */
+/* $Id: journal.c,v 1.86.18.14 2008/09/25 04:01:36 tbox Exp $ */
#include <config.h>
@@ -41,7 +41,7 @@
#include <dns/result.h>
#include <dns/soa.h>
-/*! \file
+/*! \file
* \brief Journalling.
*
* A journal file consists of
@@ -107,7 +107,7 @@ static isc_boolean_t bind8_compat = ISC_TRUE; /* XXX config */
} while (0)
#define CHECK(op) \
- do { result = (op); \
+ do { result = (op); \
if (result != ISC_R_SUCCESS) goto failure; \
} while (0)
@@ -149,11 +149,11 @@ dns_db_createsoatuple(dns_db_t *db, dns_dbversion_t *ver, isc_mem_t *mctx,
dns_rdataset_init(&rdataset);
result = dns_db_findrdataset(db, node, ver, dns_rdatatype_soa, 0,
(isc_stdtime_t)0, &rdataset, NULL);
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS)
goto freenode;
result = dns_rdataset_first(&rdataset);
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS)
goto freenode;
dns_rdataset_current(&rdataset, &rdata);
@@ -674,7 +674,7 @@ dns_journal_open(isc_mem_t *mctx, const char *filename, isc_boolean_t write,
isc_result_t result;
int namelen;
char backup[1024];
-
+
result = journal_open(mctx, filename, write, write, journalp);
if (result == ISC_R_NOTFOUND) {
namelen = strlen(filename);
@@ -1367,7 +1367,7 @@ dns_journal_print(isc_mem_t *mctx, const char *filename, FILE *file) {
if (result != ISC_R_SUCCESS) {
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
"journal open failure: %s: %s",
- isc_result_totext(result), j->filename);
+ isc_result_totext(result), filename);
return (result);
}
@@ -1405,9 +1405,9 @@ dns_journal_print(isc_mem_t *mctx, const char *filename, FILE *file) {
if (n_soa == 3)
n_soa = 1;
if (n_soa == 0) {
- isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
- "%s: journal file corrupt: missing "
- "initial SOA", j->filename);
+ isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
+ "%s: journal file corrupt: missing "
+ "initial SOA", j->filename);
FAIL(ISC_R_UNEXPECTED);
}
CHECK(dns_difftuple_create(diff.mctx, n_soa == 1 ?
@@ -1984,7 +1984,7 @@ dns_journal_compact(isc_mem_t *mctx, char *filename, isc_uint32_t serial,
dns_journal_destroy(&j);
return (ISC_R_SUCCESS);
}
-
+
if (DNS_SERIAL_GT(j->header.begin.serial, serial) ||
DNS_SERIAL_GT(serial, j->header.end.serial)) {
dns_journal_destroy(&j);
@@ -2008,7 +2008,7 @@ dns_journal_compact(isc_mem_t *mctx, char *filename, isc_uint32_t serial,
}
CHECK(journal_open(mctx, newname, ISC_TRUE, ISC_TRUE, &new));
-
+
/*
* Remove overhead so space test below can succeed.
*/
@@ -2066,7 +2066,7 @@ dns_journal_compact(isc_mem_t *mctx, char *filename, isc_uint32_t serial,
result = ISC_R_NOMEMORY;
goto failure;
}
-
+
CHECK(journal_seek(j, best_guess.offset));
CHECK(journal_seek(new, indexend));
for (i = 0; i < copy_length; i += size) {
@@ -2139,7 +2139,7 @@ dns_journal_compact(isc_mem_t *mctx, char *filename, isc_uint32_t serial,
goto failure;
}
}
-
+
dns_journal_destroy(&j);
result = ISC_R_SUCCESS;
diff --git a/lib/dns/master.c b/lib/dns/master.c
index aa04be0..b04f2eb 100644
--- a/lib/dns/master.c
+++ b/lib/dns/master.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: master.c,v 1.148.18.18 2007/08/28 07:20:04 tbox Exp $ */
+/* $Id: master.c,v 1.148.18.21 2008/01/17 23:45:58 tbox Exp $ */
/*! \file */
@@ -536,7 +536,7 @@ loadctx_create(dns_masterformat_t format, isc_mem_t *mctx,
lctx->inc = NULL;
result = incctx_create(mctx, origin, &lctx->inc);
- if (result != ISC_R_SUCCESS)
+ if (result != ISC_R_SUCCESS)
goto cleanup_ctx;
lctx->format = format;
@@ -708,7 +708,7 @@ openfile_raw(dns_loadctx_t *lctx, const char *master_file) {
if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_stdio_open() failed: %s",
- isc_result_totext(result));
+ isc_result_totext(result));
}
return (result);
@@ -912,7 +912,7 @@ check_ns(dns_loadctx_t *lctx, isc_token_t *token, const char *source,
callback = lctx->callbacks->error;
else
callback = lctx->callbacks->warn;
-
+
if (token->type == isc_tokentype_string) {
struct in_addr addr;
struct in6_addr addr6;
@@ -1237,7 +1237,7 @@ load_text(dns_loadctx_t *lctx) {
/* CLASS? */
GETTOKEN(lctx->lex, 0, &token, ISC_FALSE);
if (dns_rdataclass_fromtext(&rdclass,
- &token.value.as_textregion)
+ &token.value.as_textregion)
== ISC_R_SUCCESS) {
GETTOKEN(lctx->lex, 0, &token,
ISC_FALSE);
@@ -1421,7 +1421,7 @@ load_text(dns_loadctx_t *lctx) {
target_save = target;
ictx->glue = new_name;
ictx->glue_in_use = new_in_use;
- ictx->in_use[ictx->glue_in_use] =
+ ictx->in_use[ictx->glue_in_use] =
ISC_TRUE;
} else {
result = commit(callbacks, lctx,
@@ -1689,7 +1689,7 @@ load_text(dns_loadctx_t *lctx) {
dns_name_format(name, namebuf, sizeof(namebuf));
result = DNS_R_BADOWNERNAME;
desc = dns_result_totext(result);
- if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0) {
+ if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0) {
(*callbacks->error)(callbacks,
"%s:%lu: %s: %s",
source, line,
@@ -1739,9 +1739,9 @@ load_text(dns_loadctx_t *lctx) {
dns_name_format(ictx->current, namebuf,
sizeof(namebuf));
(*callbacks->error)(callbacks,
- "%s:%lu: SOA "
- "record not at top of zone (%s)",
- source, line, namebuf);
+ "%s:%lu: SOA "
+ "record not at top of zone (%s)",
+ source, line, namebuf);
result = DNS_R_NOTZONETOP;
if (MANYERRS(lctx, result)) {
SETRESULT(lctx, result);
@@ -1801,7 +1801,9 @@ load_text(dns_loadctx_t *lctx) {
if (type == dns_rdatatype_rrsig && lctx->warn_sigexpired) {
dns_rdata_rrsig_t sig;
- (void)dns_rdata_tostruct(&rdata[rdcount], &sig, NULL);
+ result = dns_rdata_tostruct(&rdata[rdcount], &sig,
+ NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
if (isc_serial_lt(sig.timeexpire, now)) {
(*callbacks->warn)(callbacks,
"%s:%lu: "
@@ -1813,7 +1815,7 @@ load_text(dns_loadctx_t *lctx) {
if ((type == dns_rdatatype_sig || type == dns_rdatatype_nxt) &&
lctx->warn_tcr && (lctx->options & DNS_MASTER_ZONE) != 0 &&
- (lctx->options & DNS_MASTER_SLAVE) == 0) {
+ (lctx->options & DNS_MASTER_SLAVE) == 0) {
(*callbacks->warn)(callbacks, "%s:%lu: old style DNSSEC "
" zone detected", source, line);
lctx->warn_tcr = ISC_FALSE;
@@ -1871,7 +1873,7 @@ load_text(dns_loadctx_t *lctx) {
ISC_LIST_INITANDPREPEND(glue_list, this, link);
else
ISC_LIST_INITANDPREPEND(current_list, this,
- link);
+ link);
} else if (this->ttl != lctx->ttl) {
(*callbacks->warn)(callbacks,
"%s:%lu: "
@@ -1881,7 +1883,7 @@ load_text(dns_loadctx_t *lctx) {
}
ISC_LIST_APPEND(this->rdata, &rdata[rdcount], link);
- if (ictx->glue != NULL)
+ if (ictx->glue != NULL)
ictx->glue_line = line;
else
ictx->current_line = line;
@@ -2222,7 +2224,7 @@ load_raw(dns_loadctx_t *lctx) {
isc_uint16_t rdlen;
dns_rdata_init(&rdata[i]);
-
+
if (sequential_read &&
isc_buffer_availablelength(&target) < MINTSIZ) {
unsigned int j;
diff --git a/lib/dns/masterdump.c b/lib/dns/masterdump.c
index 03716e2..1ffdfcb 100644
--- a/lib/dns/masterdump.c
+++ b/lib/dns/masterdump.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2006, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: masterdump.c,v 1.73.18.14 2006/08/08 06:39:36 marka Exp $ */
+/* $Id: masterdump.c,v 1.73.18.16 2008/08/13 23:46:04 tbox Exp $ */
/*! \file */
@@ -183,7 +183,7 @@ struct dns_dumpctx {
isc_buffer_t *buffer, FILE *f);
};
-#define NXDOMAIN(x) (((x)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
+#define NXDOMAIN(x) (((x)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
/*%
* Output tabs and spaces to go from column '*current' to
@@ -1071,13 +1071,13 @@ dns_dumpctx_detach(dns_dumpctx_t **dctxp) {
dns_dbversion_t *
dns_dumpctx_version(dns_dumpctx_t *dctx) {
- REQUIRE(DNS_DCTX_VALID(dctx));
+ REQUIRE(DNS_DCTX_VALID(dctx));
return (dctx->version);
}
dns_db_t *
dns_dumpctx_db(dns_dumpctx_t *dctx) {
- REQUIRE(DNS_DCTX_VALID(dctx));
+ REQUIRE(DNS_DCTX_VALID(dctx));
return (dctx->db);
}
@@ -1412,12 +1412,11 @@ dumptostreaminc(dns_dumpctx_t *dctx) {
"dumptostreaminc(%p) new nodes -> %d\n",
dctx, dctx->nodes);
}
- result = dns_dbiterator_pause(dctx->dbiter);
- RUNTIME_CHECK(result == ISC_R_SUCCESS);
result = DNS_R_CONTINUE;
} else if (result == ISC_R_NOMORE)
result = ISC_R_SUCCESS;
fail:
+ RUNTIME_CHECK(dns_dbiterator_pause(dctx->dbiter) == ISC_R_SUCCESS);
isc_mem_put(dctx->mctx, buffer.base, buffer.length);
return (result);
}
@@ -1703,10 +1702,10 @@ dns_master_dumpnode(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
isc_result_t
dns_master_stylecreate(dns_master_style_t **stylep, unsigned int flags,
- unsigned int ttl_column, unsigned int class_column,
- unsigned int type_column, unsigned int rdata_column,
- unsigned int line_length, unsigned int tab_width,
- isc_mem_t *mctx)
+ unsigned int ttl_column, unsigned int class_column,
+ unsigned int type_column, unsigned int rdata_column,
+ unsigned int line_length, unsigned int tab_width,
+ isc_mem_t *mctx)
{
dns_master_style_t *style;
diff --git a/lib/dns/message.c b/lib/dns/message.c
index e8e4948..8c56377 100644
--- a/lib/dns/message.c
+++ b/lib/dns/message.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: message.c,v 1.222.18.14 2007/08/28 07:20:04 tbox Exp $ */
+/* $Id: message.c,v 1.222.18.16 2008/07/28 23:46:20 tbox Exp $ */
/*! \file */
@@ -592,6 +592,9 @@ msgreset(dns_message_t *msg, isc_boolean_t everything) {
msg->tsigkey = NULL;
}
+ if (msg->tsigctx != NULL)
+ dst_context_destroy(&msg->tsigctx);
+
if (msg->query.base != NULL) {
if (msg->free_query != 0)
isc_mem_put(msg->mctx, msg->query.base,
@@ -987,7 +990,7 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
if (name == NULL)
return (ISC_R_NOMEMORY);
free_name = ISC_TRUE;
-
+
offsets = newoffsets(msg);
if (offsets == NULL) {
result = ISC_R_NOMEMORY;
@@ -1297,7 +1300,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
}
/*
* When the rdata is empty, the data pointer is
- * never dereferenced, but it must still be non-NULL.
+ * never dereferenced, but it must still be non-NULL.
* Casting 1 rather than "" avoids warnings about
* discarding the const attribute of a string,
* for compilers that would warn about such things.
@@ -1436,7 +1439,7 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
rdataset)
== ISC_R_SUCCESS);
- if (rdtype != dns_rdatatype_opt &&
+ if (rdtype != dns_rdatatype_opt &&
rdtype != dns_rdatatype_tsig &&
!issigzero)
{
diff --git a/lib/dns/rbt.c b/lib/dns/rbt.c
index b8db99a..4d3ca3a 100644
--- a/lib/dns/rbt.c
+++ b/lib/dns/rbt.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rbt.c,v 1.128.18.7 2005/10/13 01:26:06 marka Exp $ */
+/* $Id: rbt.c,v 1.128.18.10 2008/03/31 13:32:59 fdupont Exp $ */
/*! \file */
@@ -203,7 +203,7 @@ static inline void
rotate_right(dns_rbtnode_t *node, dns_rbtnode_t **rootp);
static void
-dns_rbt_addonlevel(dns_rbtnode_t *node, dns_rbtnode_t *current, int order,
+dns_rbt_addonlevel(dns_rbtnode_t *node, dns_rbtnode_t *current, int order,
dns_rbtnode_t **rootp);
static void
@@ -227,7 +227,7 @@ dns_rbt_create(isc_mem_t *mctx, void (*deleter)(void *, void *),
isc_result_t result;
#endif
dns_rbt_t *rbt;
-
+
REQUIRE(mctx != NULL);
REQUIRE(rbtp != NULL && *rbtp == NULL);
@@ -576,7 +576,7 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) {
rbt->nodecount++;
dns_name_getlabelsequence(name,
nlabels - hlabels,
- hlabels, new_name);
+ hlabels, new_name);
hash_node(rbt, new_current, new_name);
if (common_labels ==
@@ -772,7 +772,7 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
dns_name_init(&hash_name, NULL);
hashagain:
- /*
+ /*
* Hash includes tail.
*/
dns_name_getlabelsequence(name,
@@ -832,7 +832,7 @@ dns_rbt_findnode(dns_rbt_t *rbt, dns_name_t *name, dns_name_t *foundname,
*/
current = NULL;
continue;
-
+
nohash:
#endif /* DNS_RBT_USEHASH */
/*
@@ -1375,7 +1375,7 @@ dns_rbt_fullnamefromnode(dns_rbtnode_t *node, dns_name_t *name) {
result = dns_name_concatenate(name, &current, name, NULL);
if (result != ISC_R_SUCCESS)
break;
-
+
node = find_up(node);
} while (! dns_name_isabsolute(name));
@@ -1642,7 +1642,7 @@ rotate_right(dns_rbtnode_t *node, dns_rbtnode_t **rootp) {
* true red/black tree on a single level.
*/
static void
-dns_rbt_addonlevel(dns_rbtnode_t *node, dns_rbtnode_t *current, int order,
+dns_rbt_addonlevel(dns_rbtnode_t *node, dns_rbtnode_t *current, int order,
dns_rbtnode_t **rootp)
{
dns_rbtnode_t *child, *root, *parent, *grandparent;
@@ -2051,10 +2051,6 @@ dns_rbt_deletetreeflat(dns_rbt_t *rbt, unsigned int quantum,
node = LEFT(node);
goto traverse;
}
- if (RIGHT(node) != NULL) {
- node = RIGHT(node);
- goto traverse;
- }
if (DOWN(node) != NULL) {
node = DOWN(node);
goto traverse;
@@ -2065,20 +2061,21 @@ dns_rbt_deletetreeflat(dns_rbt_t *rbt, unsigned int quantum,
/*
* Note: we don't call unhash_node() here as we are destroying
- * the complete rbt tree.
- */
+ * the complete rbt tree.
+ */
#if DNS_RBT_USEMAGIC
node->magic = 0;
#endif
parent = PARENT(node);
+ if (RIGHT(node) != NULL)
+ PARENT(RIGHT(node)) = parent;
if (parent != NULL) {
if (LEFT(parent) == node)
- LEFT(parent) = NULL;
+ LEFT(parent) = RIGHT(node);
else if (DOWN(parent) == node)
- DOWN(parent) = NULL;
- else if (RIGHT(parent) == node)
- RIGHT(parent) = NULL;
- }
+ DOWN(parent) = RIGHT(node);
+ } else
+ parent = RIGHT(node);
isc_mem_put(rbt->mctx, node, NODE_SIZE(node));
rbt->nodecount--;
node = parent;
@@ -2191,6 +2188,7 @@ dns_rbtnodechain_init(dns_rbtnodechain_t *chain, isc_mem_t *mctx) {
chain->end = NULL;
chain->level_count = 0;
chain->level_matches = 0;
+ memset(chain->levels, 0, sizeof(chain->levels));
chain->magic = CHAIN_MAGIC;
}
diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c
index 1d729d0..462a718 100644
--- a/lib/dns/rbtdb.c
+++ b/lib/dns/rbtdb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rbtdb.c,v 1.196.18.48 2007/08/28 07:20:04 tbox Exp $ */
+/* $Id: rbtdb.c,v 1.196.18.53 2008/01/31 23:46:05 tbox Exp $ */
/*! \file */
@@ -195,7 +195,7 @@ struct noqname {
void * nsecsig;
};
-typedef struct acachectl acachectl_t;
+typedef struct acachectl acachectl_t;
typedef struct rdatasetheader {
/*%
@@ -219,7 +219,7 @@ typedef struct rdatasetheader {
* Otherwise, it points up to the header whose down pointer points
* at this header.
*/
-
+
struct rdatasetheader *down;
/*%<
* Points to the header for the next older version of
@@ -387,7 +387,7 @@ static void rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata);
static void rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target);
static unsigned int rdataset_count(dns_rdataset_t *rdataset);
static isc_result_t rdataset_getnoqname(dns_rdataset_t *rdataset,
- dns_name_t *name,
+ dns_name_t *name,
dns_rdataset_t *nsec,
dns_rdataset_t *nsecsig);
static isc_result_t rdataset_getadditional(dns_rdataset_t *rdataset,
@@ -604,13 +604,13 @@ adjust_quantum(unsigned int old, isc_time_t *start) {
/* Smooth */
new = (new + old * 3) / 4;
-
+
isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_CACHE,
ISC_LOG_DEBUG(1), "adjust_quantum -> %d", new);
return (new);
}
-
+
static void
free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) {
unsigned int i;
@@ -647,7 +647,7 @@ free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) {
if (event == NULL)
event = isc_event_allocate(rbtdb->common.mctx,
NULL,
- DNS_EVENT_FREESTORAGE,
+ DNS_EVENT_FREESTORAGE,
free_rbtdb_callback,
rbtdb,
sizeof(isc_event_t));
@@ -890,7 +890,7 @@ free_acachearray(isc_mem_t *mctx, rdatasetheader_t *header,
/*
* Sanity check: since an additional cache entry has a reference to
* the original DB node (in the callback arg), there should be no
- * acache entries when the node can be freed.
+ * acache entries when the node can be freed.
*/
for (i = 0; i < count; i++)
INSIST(array[i].entry == NULL && array[i].cbarg == NULL);
@@ -1241,7 +1241,7 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
isc_rwlocktype_write);
RUNTIME_CHECK(result == ISC_R_SUCCESS ||
result == ISC_R_LOCKBUSY);
-
+
write_locked = ISC_TF(result == ISC_R_SUCCESS);
} else
write_locked = ISC_TRUE;
@@ -1388,6 +1388,7 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
rbtdb_serial_t serial, least_serial;
dns_rbtnode_t *rbtnode;
unsigned int refs;
+ isc_boolean_t writer;
REQUIRE(VALID_RBTDB(rbtdb));
version = (rbtdb_version_t *)*versionp;
@@ -1407,6 +1408,7 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write);
serial = version->serial;
+ writer = version->writer;
if (version->writer) {
if (commit) {
unsigned cur_ref;
@@ -1539,7 +1541,7 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
/*
* Update the zone's secure status.
*/
- if (version->writer && commit && !IS_CACHE(rbtdb))
+ if (writer && commit && !IS_CACHE(rbtdb))
rbtdb->secure = iszonesecure(db, rbtdb->origin_node);
if (cleanup_version != NULL) {
@@ -1751,7 +1753,7 @@ zone_zonecut_callback(dns_rbtnode_t *node, dns_name_t *name, void *arg) {
if (header != NULL) {
if (header->type == dns_rdatatype_dname)
dname_header = header;
- else if (header->type ==
+ else if (header->type ==
RBTDB_RDATATYPE_SIGDNAME)
sigdname_header = header;
else if (node != onode ||
@@ -1983,7 +1985,7 @@ valid_glue(rbtdb_search_t *search, dns_name_t *name, rbtdb_rdatatype_t type,
count = raw[0] * 256 + raw[1];
#if DNS_RDATASET_FIXED
raw += 2 + (4 * count);
-#else
+#else
raw += 2;
#endif
@@ -2997,7 +2999,7 @@ cache_zonecut_callback(dns_rbtnode_t *node, dns_name_t *name, void *arg) {
UNUSED(name);
lock = &(search->rbtdb->node_locks[node->locknum].lock);
- locktype = isc_rwlocktype_read;
+ locktype = isc_rwlocktype_read;
NODE_LOCK(lock, locktype);
/*
@@ -3026,7 +3028,7 @@ cache_zonecut_callback(dns_rbtnode_t *node, dns_name_t *name, void *arg) {
* will eventually take the job as the last
* resort.
* We won't downgrade the lock, since other
- * rdatasets are probably stale, too.
+ * rdatasets are probably stale, too.
*/
locktype = isc_rwlocktype_write;
@@ -3262,7 +3264,7 @@ find_coveringnsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
matchtype = RBTDB_RDATATYPE_VALUE(dns_rdatatype_nsec, 0);
sigmatchtype = RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig,
dns_rdatatype_nsec);
-
+
do {
node = NULL;
dns_fixedname_init(&fname);
@@ -3289,7 +3291,7 @@ find_coveringnsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
* This rdataset is stale. If no one else is
* using the node, we can clean it up right
* now, otherwise we mark it as stale, and the
- * node as dirty, so it will get cleaned up
+ * node as dirty, so it will get cleaned up
* later.
*/
if ((header->ttl <= now - RBTDB_VIRTUAL) &&
@@ -4211,7 +4213,7 @@ cache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
* can get write access.
*/
locktype = isc_rwlocktype_write;
-
+
/*
* We don't check if refcurrent(rbtnode) == 0
* and try to free like we do in cache_find(),
@@ -4482,7 +4484,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
for (topheader = rbtnode->data;
topheader != NULL;
topheader = topheader->next) {
- if (topheader->type ==
+ if (topheader->type ==
RBTDB_RDATATYPE_NCACHEANY)
break;
}
@@ -4496,7 +4498,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
* The NXDOMAIN/NODATA(QTYPE=ANY)
* is more trusted.
*/
-
+
free_rdataset(rbtdb->common.mctx,
newheader);
if (addedrdataset != NULL)
@@ -4576,7 +4578,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
INSIST(rbtversion->serial >= header->serial);
merged = NULL;
result = ISC_R_SUCCESS;
-
+
if ((options & DNS_DBADD_EXACT) != 0)
flags |= DNS_RDATASLAB_EXACT;
if ((options & DNS_DBADD_EXACTTTL) != 0 &&
@@ -4622,9 +4624,9 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
header->trust >= newheader->trust &&
dns_rdataslab_equalx((unsigned char *)header,
(unsigned char *)newheader,
- (unsigned int)(sizeof(*newheader)),
+ (unsigned int)(sizeof(*newheader)),
rbtdb->common.rdclass,
- (dns_rdatatype_t)header->type)) {
+ (dns_rdatatype_t)header->type)) {
/*
* Honour the new ttl if it is less than the
* older one.
@@ -4649,7 +4651,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
header->trust >= newheader->trust &&
dns_rdataslab_equal((unsigned char *)header,
(unsigned char *)newheader,
- (unsigned int)(sizeof(*newheader)))) {
+ (unsigned int)(sizeof(*newheader)))) {
/*
* Honour the new ttl if it is less than the
* older one.
@@ -5050,7 +5052,7 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
if ((options & DNS_DBSUB_EXACT) != 0)
result = DNS_R_NOTEXACT;
else
- result = DNS_R_UNCHANGED;
+ result = DNS_R_UNCHANGED;
}
if (result == ISC_R_SUCCESS && newrdataset != NULL)
@@ -5514,7 +5516,7 @@ dns_rbtdb_create
}
rbtdb->node_locks[i].exiting = ISC_FALSE;
}
-
+
/*
* Attach to the mctx. The database will persist so long as there
* are references to it, and attaching to the mctx ensures that our
@@ -5661,7 +5663,7 @@ rdataset_first(dns_rdataset_t *rdataset) {
rdataset->private5 = NULL;
return (ISC_R_NOMORE);
}
-
+
#if DNS_RDATASET_FIXED
if ((rdataset->attributes & DNS_RDATASETATTR_LOADORDER) == 0)
raw += 2 + (4 * count);
@@ -5928,7 +5930,7 @@ rdatasetiter_next(dns_rdatasetiter_t *iterator) {
if (rdtype == 0) {
covers = RBTDB_RDATATYPE_EXT(header->type);
negtype = RBTDB_RDATATYPE_VALUE(covers, 0);
- } else
+ } else
negtype = RBTDB_RDATATYPE_VALUE(0, rdtype);
for (header = header->next; header != NULL; header = top_next) {
top_next = header->next;
@@ -6517,12 +6519,13 @@ acache_callback(dns_acacheentry_t *entry, void **arg) {
}
count = cbarg->count;
- if (acarray[count].entry == entry)
+ if (acarray != NULL && acarray[count].entry == entry) {
acarray[count].entry = NULL;
- INSIST(acarray[count].cbarg != NULL);
- isc_mem_put(rbtdb->common.mctx, acarray[count].cbarg,
- sizeof(acache_cbarg_t));
- acarray[count].cbarg = NULL;
+ INSIST(acarray[count].cbarg == cbarg);
+ isc_mem_put(rbtdb->common.mctx, cbarg, sizeof(acache_cbarg_t));
+ acarray[count].cbarg = NULL;
+ } else
+ isc_mem_put(rbtdb->common.mctx, cbarg, sizeof(acache_cbarg_t));
dns_acache_detachentry(&entry);
@@ -6664,9 +6667,7 @@ rdataset_setadditional(dns_rdataset_t *rdataset, dns_rdatasetadditional_t type,
NODE_UNLOCK(nodelock, isc_rwlocktype_write);
if (oldentry != NULL) {
- if (oldcbarg != NULL)
- acache_cancelentry(rbtdb->common.mctx, oldentry,
- &oldcbarg);
+ acache_cancelentry(rbtdb->common.mctx, oldentry, &oldcbarg);
dns_acache_detachentry(&oldentry);
}
@@ -6692,7 +6693,7 @@ rdataset_setadditional(dns_rdataset_t *rdataset, dns_rdatasetadditional_t type,
static isc_result_t
rdataset_putadditional(dns_acache_t *acache, dns_rdataset_t *rdataset,
dns_rdatasetadditional_t type, dns_rdatatype_t qtype)
-{
+{
dns_rbtdb_t *rbtdb = rdataset->private1;
dns_rbtnode_t *rbtnode = rdataset->private2;
unsigned char *raw = rdataset->private3; /* RDATASLAB */
@@ -6751,8 +6752,7 @@ rdataset_putadditional(dns_acache_t *acache, dns_rdataset_t *rdataset,
NODE_UNLOCK(nodelock, isc_rwlocktype_write);
if (entry != NULL) {
- if (cbarg != NULL)
- acache_cancelentry(rbtdb->common.mctx, entry, &cbarg);
+ acache_cancelentry(rbtdb->common.mctx, entry, &cbarg);
dns_acache_detachentry(&entry);
}
diff --git a/lib/dns/rdata/generic/nsec_47.c b/lib/dns/rdata/generic/nsec_47.c
index f3e56ca..dd39105 100644
--- a/lib/dns/rdata/generic/nsec_47.c
+++ b/lib/dns/rdata/generic/nsec_47.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,11 +15,11 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: nsec_47.c,v 1.7 2004/03/05 05:10:15 marka Exp $ */
+/* $Id: nsec_47.c,v 1.7.20.2 2008/07/15 23:46:14 tbox Exp $ */
/* reviewed: Wed Mar 15 18:21:15 PST 2000 by brister */
-/* draft-ietf-dnsext-nsec-rdata-01.txt */
+/* RFC 3845 */
#ifndef RDATA_GENERIC_NSEC_47_C
#define RDATA_GENERIC_NSEC_47_C
@@ -255,7 +255,7 @@ fromstruct_nsec(ARGS_FROMSTRUCT) {
window = nsec->typebits[i];
len = nsec->typebits[i+1];
i += 2;
- INSIST(first || window > lastwindow);
+ INSIST(first || window > lastwindow);
INSIST(len > 0 && len <= 32);
INSIST(i + len <= nsec->len);
INSIST(nsec->typebits[i + len - 1] != 0);
diff --git a/lib/dns/rdata/generic/nsec_47.h b/lib/dns/rdata/generic/nsec_47.h
index ff03483..5c52447 100644
--- a/lib/dns/rdata/generic/nsec_47.h
+++ b/lib/dns/rdata/generic/nsec_47.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -18,10 +18,10 @@
#ifndef GENERIC_NSEC_47_H
#define GENERIC_NSEC_47_H 1
-/* $Id: nsec_47.h,v 1.4.20.2 2005/04/29 00:16:37 marka Exp $ */
+/* $Id: nsec_47.h,v 1.4.20.4 2008/07/15 23:46:14 tbox Exp $ */
/*!
- * \brief Per draft-ietf-dnsext-nsec-rdata-01.txt */
+ * \brief Per RFC 3845 */
typedef struct dns_rdata_nsec {
dns_rdatacommon_t common;
diff --git a/lib/dns/rdata/generic/txt_16.c b/lib/dns/rdata/generic/txt_16.c
index fa3ffef..01ca87a 100644
--- a/lib/dns/rdata/generic/txt_16.c
+++ b/lib/dns/rdata/generic/txt_16.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: txt_16.c,v 1.41 2004/03/05 05:10:18 marka Exp $ */
+/* $Id: txt_16.c,v 1.41.18.2 2008/02/15 23:45:53 tbox Exp $ */
/* Reviewed: Thu Mar 16 15:40:00 PST 2000 by bwelling */
@@ -142,7 +142,7 @@ fromstruct_txt(ARGS_FROMSTRUCT) {
while (region.length > 0) {
length = uint8_fromregion(&region);
isc_region_consume(&region, 1);
- if (region.length <= length)
+ if (region.length < length)
return (ISC_R_UNEXPECTEDEND);
isc_region_consume(&region, length);
}
diff --git a/lib/dns/rdata/in_1/apl_42.c b/lib/dns/rdata/in_1/apl_42.c
index 42b2e7f..2fce328 100644
--- a/lib/dns/rdata/in_1/apl_42.c
+++ b/lib/dns/rdata/in_1/apl_42.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: apl_42.c,v 1.8.18.2 2005/04/29 00:16:42 marka Exp $ */
+/* $Id: apl_42.c,v 1.8.18.4 2008/01/22 23:27:06 tbox Exp $ */
/* RFC3123 */
@@ -49,7 +49,7 @@ fromtext_in_apl(ARGS_FROMTEXT) {
isc_tokentype_string, ISC_TRUE));
if (token.type != isc_tokentype_string)
break;
-
+
cp = DNS_AS_STR(token);
neg = ISC_TF(*cp == '!');
if (neg)
@@ -259,7 +259,7 @@ fromstruct_in_apl(ARGS_FROMSTRUCT) {
REQUIRE(apl->common.rdtype == type);
REQUIRE(apl->common.rdclass == rdclass);
REQUIRE(apl->apl != NULL || apl->apl_len == 0);
-
+
isc_buffer_init(&b, apl->apl, apl->apl_len);
isc_buffer_add(&b, apl->apl_len);
isc_buffer_setactive(&b, apl->apl_len);
@@ -306,37 +306,88 @@ freestruct_in_apl(ARGS_FREESTRUCT) {
isc_result_t
dns_rdata_apl_first(dns_rdata_in_apl_t *apl) {
+ isc_uint32_t length;
+
+ REQUIRE(apl != NULL);
REQUIRE(apl->common.rdtype == 42);
REQUIRE(apl->common.rdclass == 1);
REQUIRE(apl->apl != NULL || apl->apl_len == 0);
+ /*
+ * If no APL return ISC_R_NOMORE.
+ */
+ if (apl->apl == NULL)
+ return (ISC_R_NOMORE);
+
+ /*
+ * Sanity check data.
+ */
+ INSIST(apl->apl_len > 3U);
+ length = apl->apl[apl->offset + 3] & 0x7f;
+ INSIST(length <= apl->apl_len);
+
apl->offset = 0;
- return ((apl->apl_len != 0) ? ISC_R_SUCCESS : ISC_R_NOMORE);
+ return (ISC_R_SUCCESS);
}
isc_result_t
dns_rdata_apl_next(dns_rdata_in_apl_t *apl) {
+ isc_uint32_t length;
+
+ REQUIRE(apl != NULL);
REQUIRE(apl->common.rdtype == 42);
REQUIRE(apl->common.rdclass == 1);
REQUIRE(apl->apl != NULL || apl->apl_len == 0);
- if (apl->offset + 3 < apl->apl_len)
+ /*
+ * No APL or have already reached the end return ISC_R_NOMORE.
+ */
+ if (apl->apl == NULL || apl->offset == apl->apl_len)
return (ISC_R_NOMORE);
+
+ /*
+ * Sanity check data.
+ */
+ INSIST(apl->offset < apl->apl_len);
+ INSIST(apl->apl_len > 3U);
+ INSIST(apl->offset <= apl->apl_len - 4U);
+ length = apl->apl[apl->offset + 3] & 0x7f;
+ /*
+ * 16 to 32 bits promotion as 'length' is 32 bits so there is
+ * no overflow problems.
+ */
+ INSIST(length + apl->offset <= apl->apl_len);
+
apl->offset += apl->apl[apl->offset + 3] & 0x7f;
return ((apl->offset >= apl->apl_len) ? ISC_R_SUCCESS : ISC_R_NOMORE);
}
isc_result_t
dns_rdata_apl_current(dns_rdata_in_apl_t *apl, dns_rdata_apl_ent_t *ent) {
+ isc_uint32_t length;
+ REQUIRE(apl != NULL);
REQUIRE(apl->common.rdtype == 42);
REQUIRE(apl->common.rdclass == 1);
REQUIRE(ent != NULL);
REQUIRE(apl->apl != NULL || apl->apl_len == 0);
+ REQUIRE(apl->offset <= apl->apl_len);
- if (apl->offset >= apl->apl_len)
+ if (apl->offset == apl->apl_len)
return (ISC_R_NOMORE);
+ /*
+ * Sanity check data.
+ */
+ INSIST(apl->apl_len > 3U);
+ INSIST(apl->offset <= apl->apl_len - 4U);
+ length = apl->apl[apl->offset + 3] & 0x7f;
+ /*
+ * 16 to 32 bits promotion as 'length' is 32 bits so there is
+ * no overflow problems.
+ */
+ INSIST(length + apl->offset <= apl->apl_len);
+
ent->family = (apl->apl[apl->offset] << 8) + apl->apl[apl->offset + 1];
ent->prefix = apl->apl[apl->offset + 2];
ent->length = apl->apl[apl->offset + 3] & 0x7f;
diff --git a/lib/dns/rdata/in_1/naptr_35.c b/lib/dns/rdata/in_1/naptr_35.c
index 0e5961a..9a880ea 100644
--- a/lib/dns/rdata/in_1/naptr_35.c
+++ b/lib/dns/rdata/in_1/naptr_35.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: naptr_35.c,v 1.47.18.2 2005/04/29 00:16:42 marka Exp $ */
+/* $Id: naptr_35.c,v 1.47.18.4 2008/02/15 23:45:53 tbox Exp $ */
/* Reviewed: Thu Mar 16 16:52:50 PST 2000 by bwelling */
@@ -154,7 +154,7 @@ totext_in_naptr(ARGS_TOTEXT) {
static inline isc_result_t
fromwire_in_naptr(ARGS_FROMWIRE) {
- dns_name_t name;
+ dns_name_t name;
isc_region_t sr;
REQUIRE(type == 35);
@@ -165,7 +165,7 @@ fromwire_in_naptr(ARGS_FROMWIRE) {
dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
- dns_name_init(&name, NULL);
+ dns_name_init(&name, NULL);
/*
* Order, preference.
@@ -321,8 +321,8 @@ fromstruct_in_naptr(ARGS_FROMSTRUCT) {
REQUIRE(naptr->common.rdtype == type);
REQUIRE(naptr->common.rdclass == rdclass);
REQUIRE(naptr->flags != NULL || naptr->flags_len == 0);
- REQUIRE(naptr->service != NULL && naptr->service_len == 0);
- REQUIRE(naptr->regexp != NULL && naptr->regexp_len == 0);
+ REQUIRE(naptr->service != NULL || naptr->service_len == 0);
+ REQUIRE(naptr->regexp != NULL || naptr->regexp_len == 0);
UNUSED(type);
UNUSED(rdclass);
diff --git a/lib/dns/request.c b/lib/dns/request.c
index c0348fe..64a3a4e 100644
--- a/lib/dns/request.c
+++ b/lib/dns/request.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: request.c,v 1.72.18.5.42.2 2008/07/23 07:28:56 tbox Exp $ */
+/* $Id: request.c,v 1.72.18.8 2008/07/22 03:51:44 marka Exp $ */
/*! \file */
@@ -121,6 +121,7 @@ static isc_result_t req_render(dns_message_t *message, isc_buffer_t **buffer,
static void req_senddone(isc_task_t *task, isc_event_t *event);
static void req_response(isc_task_t *task, isc_event_t *event);
static void req_timeout(isc_task_t *task, isc_event_t *event);
+static isc_socket_t * req_getsocket(dns_request_t *request);
static void req_connected(isc_task_t *task, isc_event_t *event);
static void req_sendevent(dns_request_t *request, isc_result_t result);
static void req_cancel(dns_request_t *request);
@@ -146,6 +147,7 @@ dns_requestmgr_create(isc_mem_t *mctx,
isc_socket_t *socket;
isc_result_t result;
int i;
+ unsigned int dispattr;
req_log(ISC_LOG_DEBUG(3), "dns_requestmgr_create");
@@ -154,13 +156,14 @@ dns_requestmgr_create(isc_mem_t *mctx,
REQUIRE(socketmgr != NULL);
REQUIRE(taskmgr != NULL);
REQUIRE(dispatchmgr != NULL);
+ UNUSED(socket);
if (dispatchv4 != NULL) {
- socket = dns_dispatch_getsocket(dispatchv4);
- REQUIRE(isc_socket_gettype(socket) == isc_sockettype_udp);
+ dispattr = dns_dispatch_getattributes(dispatchv4);
+ REQUIRE((dispattr & DNS_DISPATCHATTR_UDP) != 0);
}
if (dispatchv6 != NULL) {
- socket = dns_dispatch_getsocket(dispatchv6);
- REQUIRE(isc_socket_gettype(socket) == isc_sockettype_udp);
+ dispattr = dns_dispatch_getattributes(dispatchv6);
+ REQUIRE((dispattr & DNS_DISPATCHATTR_UDP) != 0);
}
requestmgr = isc_mem_get(mctx, sizeof(*requestmgr));
@@ -425,12 +428,19 @@ req_send(dns_request_t *request, isc_task_t *task, isc_sockaddr_t *address) {
isc_region_t r;
isc_socket_t *socket;
isc_result_t result;
+ unsigned int dispattr;
req_log(ISC_LOG_DEBUG(3), "req_send: request %p", request);
REQUIRE(VALID_REQUEST(request));
- socket = dns_dispatch_getsocket(request->dispatch);
+ dispattr = dns_dispatch_getattributes(request->dispatch);
+ socket = req_getsocket(request);
isc_buffer_usedregion(request->query, &r);
+ /*
+ * We could connect the socket when we are using an exclusive dispatch
+ * as we do in resolver.c, but we prefer implementation simplicity
+ * at this moment.
+ */
result = isc_socket_sendto(socket, &r, task, req_senddone,
request, address, NULL);
if (result == ISC_R_SUCCESS)
@@ -685,7 +695,7 @@ dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
REQUIRE(action != NULL);
REQUIRE(requestp != NULL && *requestp == NULL);
REQUIRE(timeout > 0);
- if (srcaddr != NULL)
+ if (srcaddr != NULL)
REQUIRE(isc_sockaddr_pf(srcaddr) == isc_sockaddr_pf(destaddr));
mctx = requestmgr->mctx;
@@ -733,7 +743,7 @@ dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
result = DNS_R_FORMERR;
goto cleanup;
}
-
+
if ((options & DNS_REQUESTOPT_TCP) != 0 || r.length > 512)
tcp = ISC_TRUE;
@@ -742,14 +752,16 @@ dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf,
if (result != ISC_R_SUCCESS)
goto cleanup;
- socket = dns_dispatch_getsocket(request->dispatch);
- INSIST(socket != NULL);
- result = dns_dispatch_addresponse(request->dispatch, destaddr, task,
- req_response, request, &id,
- &request->dispentry);
+ result = dns_dispatch_addresponse2(request->dispatch, destaddr, task,
+ req_response, request, &id,
+ &request->dispentry,
+ requestmgr->socketmgr);
if (result != ISC_R_SUCCESS)
goto cleanup;
+ socket = req_getsocket(request);
+ INSIST(socket != NULL);
+
result = isc_buffer_allocate(mctx, &request->query,
r.length + (tcp ? 2 : 0));
if (result != ISC_R_SUCCESS)
@@ -857,7 +869,7 @@ dns_request_createvia2(dns_requestmgr_t *requestmgr, dns_message_t *message,
udpretries, task, action, arg,
requestp));
}
-
+
isc_result_t
dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr,
@@ -883,7 +895,7 @@ dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
REQUIRE(action != NULL);
REQUIRE(requestp != NULL && *requestp == NULL);
REQUIRE(timeout > 0);
- if (srcaddr != NULL)
+ if (srcaddr != NULL)
REQUIRE(isc_sockaddr_pf(srcaddr) == isc_sockaddr_pf(destaddr));
mctx = requestmgr->mctx;
@@ -935,13 +947,14 @@ dns_request_createvia3(dns_requestmgr_t *requestmgr, dns_message_t *message,
if (result != ISC_R_SUCCESS)
goto cleanup;
- socket = dns_dispatch_getsocket(request->dispatch);
- INSIST(socket != NULL);
- result = dns_dispatch_addresponse(request->dispatch, destaddr, task,
- req_response, request, &id,
- &request->dispentry);
+ result = dns_dispatch_addresponse2(request->dispatch, destaddr, task,
+ req_response, request, &id,
+ &request->dispentry,
+ requestmgr->socketmgr);
if (result != ISC_R_SUCCESS)
goto cleanup;
+ socket = req_getsocket(request);
+ INSIST(socket != NULL);
message->id = id;
if (setkey) {
@@ -1137,7 +1150,7 @@ do_cancel(isc_task_t *task, isc_event_t *event) {
if (!DNS_REQUEST_CANCELED(request))
req_cancel(request);
send_if_done(request, ISC_R_CANCELED);
- UNLOCK(&request->requestmgr->locks[request->hash]);
+ UNLOCK(&request->requestmgr->locks[request->hash]);
}
void
@@ -1226,6 +1239,21 @@ dns_request_destroy(dns_request_t **requestp) {
*** Private: request.
***/
+static isc_socket_t *
+req_getsocket(dns_request_t *request) {
+ unsigned int dispattr;
+ isc_socket_t *socket;
+
+ dispattr = dns_dispatch_getattributes(request->dispatch);
+ if ((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
+ INSIST(request->dispentry != NULL);
+ socket = dns_dispatch_getentrysocket(request->dispentry);
+ } else
+ socket = dns_dispatch_getsocket(request->dispatch);
+
+ return (socket);
+}
+
static void
req_connected(isc_task_t *task, isc_event_t *event) {
isc_socketevent_t *sevent = (isc_socketevent_t *)event;
@@ -1425,6 +1453,7 @@ req_destroy(dns_request_t *request) {
static void
req_cancel(dns_request_t *request) {
isc_socket_t *socket;
+ unsigned int dispattr;
REQUIRE(VALID_REQUEST(request));
@@ -1437,16 +1466,23 @@ req_cancel(dns_request_t *request) {
if (request->timer != NULL)
isc_timer_detach(&request->timer);
+ dispattr = dns_dispatch_getattributes(request->dispatch);
+ socket = NULL;
+ if (DNS_REQUEST_CONNECTING(request) || DNS_REQUEST_SENDING(request)) {
+ if ((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0) {
+ if (request->dispentry != NULL) {
+ socket = dns_dispatch_getentrysocket(
+ request->dispentry);
+ }
+ } else
+ socket = dns_dispatch_getsocket(request->dispatch);
+ if (DNS_REQUEST_CONNECTING(request) && socket != NULL)
+ isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_CONNECT);
+ if (DNS_REQUEST_SENDING(request) && socket != NULL)
+ isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_SEND);
+ }
if (request->dispentry != NULL)
dns_dispatch_removeresponse(&request->dispentry, NULL);
- if (DNS_REQUEST_CONNECTING(request)) {
- socket = dns_dispatch_getsocket(request->dispatch);
- isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_CONNECT);
- }
- if (DNS_REQUEST_SENDING(request)) {
- socket = dns_dispatch_getsocket(request->dispatch);
- isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_SEND);
- }
dns_dispatch_detach(&request->dispatch);
}
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
index cdf5788..dc648c9 100644
--- a/lib/dns/resolver.c
+++ b/lib/dns/resolver.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: resolver.c,v 1.284.18.66.8.4 2008/07/24 05:00:48 jinmei Exp $ */
+/* $Id: resolver.c,v 1.284.18.79 2008/10/17 22:02:13 jinmei Exp $ */
/*! \file */
@@ -121,6 +121,7 @@ typedef struct query {
isc_mem_t * mctx;
dns_dispatchmgr_t * dispatchmgr;
dns_dispatch_t * dispatch;
+ isc_boolean_t exclusivesocket;
dns_adbaddrinfo_t * addrinfo;
isc_socket_t * tcpsocket;
isc_time_t start;
@@ -213,7 +214,7 @@ struct fetchctx {
unsigned int restarts;
/*%
- * The number of timeouts that have occurred since we
+ * The number of timeouts that have occurred since we
* last successfully received a response packet. This
* is used for EDNS0 black hole detection.
*/
@@ -221,7 +222,7 @@ struct fetchctx {
/*%
* Look aside state for DS lookups.
*/
- dns_name_t nsname;
+ dns_name_t nsname;
dns_fetch_t * nsfetch;
dns_rdataset_t nsrrset;
@@ -296,8 +297,8 @@ struct dns_resolver {
unsigned int magic;
isc_mem_t * mctx;
isc_mutex_t lock;
- isc_mutex_t nlock;
- isc_mutex_t primelock;
+ isc_mutex_t nlock;
+ isc_mutex_t primelock;
dns_rdataclass_t rdclass;
isc_socketmgr_t * socketmgr;
isc_timermgr_t * timermgr;
@@ -307,7 +308,9 @@ struct dns_resolver {
unsigned int options;
dns_dispatchmgr_t * dispatchmgr;
dns_dispatch_t * dispatchv4;
+ isc_boolean_t exclusivev4;
dns_dispatch_t * dispatchv6;
+ isc_boolean_t exclusivev6;
unsigned int nbuckets;
fctxbucket_t * buckets;
isc_uint32_t lame_ttl;
@@ -331,7 +334,7 @@ struct dns_resolver {
isc_eventlist_t whenshutdown;
unsigned int activebuckets;
isc_boolean_t priming;
- unsigned int spillat;
+ unsigned int spillat; /* clients-per-query */
/* Locked by primelock. */
dns_fetch_t * primefetch;
/* Locked by nlock. */
@@ -369,8 +372,10 @@ static isc_result_t ncache_adderesult(dns_message_t *message,
isc_stdtime_t now, dns_ttl_t maxttl,
dns_rdataset_t *ardataset,
isc_result_t *eresultp);
-static void validated(isc_task_t *task, isc_event_t *event);
+static void validated(isc_task_t *task, isc_event_t *event);
static void maybe_destroy(fetchctx_t *fctx);
+static void add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
+ isc_result_t reason);
static isc_result_t
valcreate(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, dns_name_t *name,
@@ -562,6 +567,7 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
unsigned int factor;
dns_adbfind_t *find;
dns_adbaddrinfo_t *addrinfo;
+ isc_socket_t *socket;
query = *queryp;
fctx = query->fctx;
@@ -643,35 +649,48 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,
0, factor);
}
- if (query->dispentry != NULL)
- dns_dispatch_removeresponse(&query->dispentry, deventp);
-
- ISC_LIST_UNLINK(fctx->queries, query, link);
-
- if (query->tsig != NULL)
- isc_buffer_free(&query->tsig);
-
- if (query->tsigkey != NULL)
- dns_tsigkey_detach(&query->tsigkey);
-
/*
* Check for any outstanding socket events. If they exist, cancel
* them and let the event handlers finish the cleanup. The resolver
* only needs to worry about managing the connect and send events;
* the dispatcher manages the recv events.
*/
- if (RESQUERY_CONNECTING(query))
+ if (RESQUERY_CONNECTING(query)) {
/*
* Cancel the connect.
*/
- isc_socket_cancel(query->tcpsocket, NULL,
- ISC_SOCKCANCEL_CONNECT);
- else if (RESQUERY_SENDING(query))
+ if (query->tcpsocket != NULL) {
+ isc_socket_cancel(query->tcpsocket, NULL,
+ ISC_SOCKCANCEL_CONNECT);
+ } else if (query->dispentry != NULL) {
+ INSIST(query->exclusivesocket);
+ socket = dns_dispatch_getentrysocket(query->dispentry);
+ if (socket != NULL)
+ isc_socket_cancel(socket, NULL,
+ ISC_SOCKCANCEL_CONNECT);
+ }
+ } else if (RESQUERY_SENDING(query)) {
/*
* Cancel the pending send.
*/
- isc_socket_cancel(dns_dispatch_getsocket(query->dispatch),
- NULL, ISC_SOCKCANCEL_SEND);
+ if (query->exclusivesocket && query->dispentry != NULL)
+ socket = dns_dispatch_getentrysocket(query->dispentry);
+ else
+ socket = dns_dispatch_getsocket(query->dispatch);
+ if (socket != NULL)
+ isc_socket_cancel(socket, NULL, ISC_SOCKCANCEL_SEND);
+ }
+
+ if (query->dispentry != NULL)
+ dns_dispatch_removeresponse(&query->dispentry, deventp);
+
+ ISC_LIST_UNLINK(fctx->queries, query, link);
+
+ if (query->tsig != NULL)
+ isc_buffer_free(&query->tsig);
+
+ if (query->tsigkey != NULL)
+ dns_tsigkey_detach(&query->tsigkey);
if (query->dispatch != NULL)
dns_dispatch_detach(&query->dispatch);
@@ -777,6 +796,8 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
unsigned int count = 0;
isc_interval_t i;
isc_boolean_t logit = ISC_FALSE;
+ unsigned int old_spillat;
+ unsigned int new_spillat = 0; /* initialized to silence compiler warnings */
/*
* Caller must be holding the appropriate bucket lock.
@@ -800,7 +821,7 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
fctx->type == dns_rdatatype_any ||
fctx->type == dns_rdatatype_rrsig ||
fctx->type == dns_rdatatype_sig);
-
+
/*
* Negative results must be indicated in event->result.
*/
@@ -819,11 +840,15 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
(count < fctx->res->spillatmax || fctx->res->spillatmax == 0)) {
LOCK(&fctx->res->lock);
if (count == fctx->res->spillat && !fctx->res->exiting) {
+ old_spillat = fctx->res->spillat;
fctx->res->spillat += 5;
if (fctx->res->spillat > fctx->res->spillatmax &&
fctx->res->spillatmax != 0)
fctx->res->spillat = fctx->res->spillatmax;
- logit = ISC_TRUE;
+ new_spillat = fctx->res->spillat;
+ if (new_spillat != old_spillat) {
+ logit = ISC_TRUE;
+ }
isc_interval_set(&i, 20 * 60, 0);
result = isc_timer_reset(fctx->res->spillattimer,
isc_timertype_ticker, NULL,
@@ -835,7 +860,7 @@ fctx_sendevents(fetchctx_t *fctx, isc_result_t result) {
isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
"clients-per-query increased to %u",
- count + 1);
+ new_spillat);
}
}
@@ -864,43 +889,25 @@ fctx_done(fetchctx_t *fctx, isc_result_t result) {
}
static void
-resquery_senddone(isc_task_t *task, isc_event_t *event) {
+process_sendevent(resquery_t *query, isc_event_t *event) {
isc_socketevent_t *sevent = (isc_socketevent_t *)event;
- resquery_t *query = event->ev_arg;
isc_boolean_t retry = ISC_FALSE;
isc_result_t result;
fetchctx_t *fctx;
- REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
-
- QTRACE("senddone");
-
- /*
- * XXXRTH
- *
- * Currently we don't wait for the senddone event before retrying
- * a query. This means that if we get really behind, we may end
- * up doing extra work!
- */
-
- UNUSED(task);
-
- INSIST(RESQUERY_SENDING(query));
-
- query->sends--;
fctx = query->fctx;
if (RESQUERY_CANCELED(query)) {
- if (query->sends == 0) {
+ if (query->sends == 0 && query->connects == 0) {
/*
* This query was canceled while the
- * isc_socket_sendto() was in progress.
+ * isc_socket_sendto/connect() was in progress.
*/
if (query->tcpsocket != NULL)
isc_socket_detach(&query->tcpsocket);
resquery_destroy(&query);
}
- } else
+ } else {
switch (sevent->result) {
case ISC_R_SUCCESS:
break;
@@ -914,6 +921,7 @@ resquery_senddone(isc_task_t *task, isc_event_t *event) {
/*
* No route to remote.
*/
+ add_bad(fctx, query->addrinfo, sevent->result);
fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
retry = ISC_TRUE;
break;
@@ -922,6 +930,7 @@ resquery_senddone(isc_task_t *task, isc_event_t *event) {
fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
break;
}
+ }
isc_event_free(&event);
@@ -939,9 +948,51 @@ resquery_senddone(isc_task_t *task, isc_event_t *event) {
}
}
+static void
+resquery_udpconnected(isc_task_t *task, isc_event_t *event) {
+ resquery_t *query = event->ev_arg;
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
+
+ QTRACE("udpconnected");
+
+ UNUSED(task);
+
+ INSIST(RESQUERY_CONNECTING(query));
+
+ query->connects--;
+
+ process_sendevent(query, event);
+}
+
+static void
+resquery_senddone(isc_task_t *task, isc_event_t *event) {
+ resquery_t *query = event->ev_arg;
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
+
+ QTRACE("senddone");
+
+ /*
+ * XXXRTH
+ *
+ * Currently we don't wait for the senddone event before retrying
+ * a query. This means that if we get really behind, we may end
+ * up doing extra work!
+ */
+
+ UNUSED(task);
+
+ INSIST(RESQUERY_SENDING(query));
+
+ query->sends--;
+
+ process_sendevent(query, event);
+}
+
static inline isc_result_t
fctx_addopt(dns_message_t *message, unsigned int version, isc_uint16_t udpsize)
-{
+{
dns_rdataset_t *rdataset;
dns_rdatalist_t *rdatalist;
dns_rdata_t *rdata;
@@ -1001,9 +1052,9 @@ fctx_setretryinterval(fetchctx_t *fctx, unsigned int rtt) {
* list, and then we do exponential back-off.
*/
if (fctx->restarts < 3)
- us = 500000;
+ us = 800000;
else
- us = (500000 << (fctx->restarts - 2));
+ us = (800000 << (fctx->restarts - 2));
/*
* Double the round-trip time.
@@ -1077,6 +1128,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
*/
query->dispatchmgr = res->dispatchmgr;
query->dispatch = NULL;
+ query->exclusivesocket = ISC_FALSE;
query->tcpsocket = NULL;
if (res->view->peers != NULL) {
dns_peer_t *peer = NULL;
@@ -1159,53 +1211,21 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,
if (result != ISC_R_SUCCESS)
goto cleanup_query;
} else {
- isc_sockaddr_t localaddr;
- unsigned int attrs, attrmask;
- dns_dispatch_t *disp_base;
-
- attrs = 0;
- attrs |= DNS_DISPATCHATTR_UDP;
- attrs |= DNS_DISPATCHATTR_RANDOMPORT;
-
- attrmask = 0;
- attrmask |= DNS_DISPATCHATTR_UDP;
- attrmask |= DNS_DISPATCHATTR_TCP;
- attrmask |= DNS_DISPATCHATTR_IPV4;
- attrmask |= DNS_DISPATCHATTR_IPV6;
-
switch (isc_sockaddr_pf(&addrinfo->sockaddr)) {
- case AF_INET:
- disp_base = res->dispatchv4;
- attrs |= DNS_DISPATCHATTR_IPV4;
+ case PF_INET:
+ dns_dispatch_attach(res->dispatchv4,
+ &query->dispatch);
+ query->exclusivesocket = res->exclusivev4;
break;
- case AF_INET6:
- disp_base = res->dispatchv6;
- attrs |= DNS_DISPATCHATTR_IPV6;
+ case PF_INET6:
+ dns_dispatch_attach(res->dispatchv6,
+ &query->dispatch);
+ query->exclusivesocket = res->exclusivev6;
break;
default:
result = ISC_R_NOTIMPLEMENTED;
goto cleanup_query;
}
-
- result = dns_dispatch_getlocaladdress(disp_base,
- &localaddr);
- if (result != ISC_R_SUCCESS)
- goto cleanup_query;
- if (isc_sockaddr_getport(&localaddr) == 0) {
- result = dns_dispatch_getudp(res->dispatchmgr,
- res->socketmgr,
- res->taskmgr,
- &localaddr,
- 4096, 1000, 32768,
- 16411, 16433,
- attrs, attrmask,
- &query->dispatch);
- if (result != ISC_R_SUCCESS)
- goto cleanup_query;
- } else {
- dns_dispatch_attach(disp_base,
- &query->dispatch);
- }
}
/*
* We should always have a valid dispatcher here. If we
@@ -1378,13 +1398,14 @@ resquery_send(resquery_t *query) {
/*
* Get a query id from the dispatch.
*/
- result = dns_dispatch_addresponse(query->dispatch,
- &query->addrinfo->sockaddr,
- task,
- resquery_response,
- query,
- &query->id,
- &query->dispentry);
+ result = dns_dispatch_addresponse2(query->dispatch,
+ &query->addrinfo->sockaddr,
+ task,
+ resquery_response,
+ query,
+ &query->id,
+ &query->dispentry,
+ res->socketmgr);
if (result != ISC_R_SUCCESS)
goto cleanup_temps;
@@ -1593,12 +1614,24 @@ resquery_send(resquery_t *query) {
*/
dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);
- socket = dns_dispatch_getsocket(query->dispatch);
+ if (query->exclusivesocket)
+ socket = dns_dispatch_getentrysocket(query->dispentry);
+ else
+ socket = dns_dispatch_getsocket(query->dispatch);
/*
* Send the query!
*/
- if ((query->options & DNS_FETCHOPT_TCP) == 0)
+ if ((query->options & DNS_FETCHOPT_TCP) == 0) {
address = &query->addrinfo->sockaddr;
+ if (query->exclusivesocket) {
+ result = isc_socket_connect(socket, address, task,
+ resquery_udpconnected,
+ query);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup_message;
+ query->connects++;
+ }
+ }
isc_buffer_usedregion(buffer, &r);
/*
@@ -1731,7 +1764,7 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
}
isc_event_free(&event);
-
+
if (retry) {
/*
* Behave as if the idle timer has expired. For TCP
@@ -1921,8 +1954,8 @@ add_bad(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, isc_result_t reason) {
if (reason == DNS_R_LAME) /* already logged */
return;
- if (reason == DNS_R_UNEXPECTEDRCODE &&
- fctx->rmessage->opcode == dns_rcode_servfail &&
+ if (reason == DNS_R_UNEXPECTEDRCODE &&
+ fctx->rmessage->rcode == dns_rcode_servfail &&
ISFORWARDER(addrinfo))
return;
@@ -2196,6 +2229,13 @@ fctx_getaddresses(fetchctx_t *fctx) {
}
while (sa != NULL) {
+ if ((isc_sockaddr_pf(sa) == AF_INET &&
+ fctx->res->dispatchv4 == NULL) ||
+ (isc_sockaddr_pf(sa) == AF_INET6 &&
+ fctx->res->dispatchv6 == NULL)) {
+ sa = ISC_LIST_NEXT(sa, link);
+ continue;
+ }
ai = NULL;
result = dns_adb_findaddrinfo(fctx->adb,
sa, &ai, 0); /* XXXMLG */
@@ -2366,7 +2406,7 @@ possibly_mark(fetchctx_t *fctx, dns_adbaddrinfo_t *addr)
isc_netaddr_fromsockaddr(&ipaddr, sa);
blackhole = dns_dispatchmgr_getblackhole(res->dispatchmgr);
(void) dns_peerlist_peerbyaddr(res->view->peers, &ipaddr, &peer);
-
+
if (blackhole != NULL) {
int match;
@@ -2799,7 +2839,7 @@ fctx_doshutdown(isc_task_t *task, isc_event_t *event) {
dns_validator_cancel(validator);
validator = ISC_LIST_NEXT(validator, link);
}
-
+
if (fctx->nsfetch != NULL)
dns_resolver_cancelfetch(fctx->nsfetch);
@@ -3252,9 +3292,9 @@ is_lame(fetchctx_t *fctx) {
static inline void
log_lame(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo) {
char namebuf[DNS_NAME_FORMATSIZE];
- char domainbuf[DNS_NAME_FORMATSIZE];
+ char domainbuf[DNS_NAME_FORMATSIZE];
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
-
+
dns_name_format(&fctx->name, namebuf, sizeof(namebuf));
dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));
isc_sockaddr_format(&addrinfo->sockaddr, addrbuf, sizeof(addrbuf));
@@ -3822,9 +3862,9 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo,
sizeof(typebuf));
dns_rdataclass_format(rdataset->rdclass, classbuf,
sizeof(classbuf));
- isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+ isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,
- "check-names %s %s/%s/%s",
+ "check-names %s %s/%s/%s",
fail ? "failure" : "warning",
namebuf, typebuf, classbuf);
if (fail) {
@@ -4411,7 +4451,7 @@ chase_additional(fetchctx_t *fctx) {
again:
rescan = ISC_FALSE;
-
+
for (result = dns_message_firstname(fctx->rmessage, section);
result == ISC_R_SUCCESS;
result = dns_message_nextname(fctx->rmessage, section)) {
@@ -4491,7 +4531,7 @@ dname_target(dns_rdataset_t *rdataset, dns_name_t *qname, dns_name_t *oname,
return (DNS_R_FORMERR);
}
dns_fixedname_init(&prefix);
- dns_name_split(qname, nlabels, dns_fixedname_name(&prefix), NULL);
+ dns_name_split(qname, nlabels, dns_fixedname_name(&prefix), NULL);
dns_fixedname_init(fixeddname);
result = dns_name_concatenate(dns_fixedname_name(&prefix),
&dname.dname,
@@ -4650,7 +4690,7 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname,
}
/*
- * A negative response has a SOA record (Type 2)
+ * A negative response has a SOA record (Type 2)
* and a optional NS RRset (Type 1) or it has neither
* a SOA or a NS RRset (Type 3, handled above) or
* rcode is NXDOMAIN (handled above) in which case
@@ -5363,7 +5403,7 @@ checknamessection(dns_message_t *message, dns_section_t section) {
dns_name_t *name;
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdataset_t *rdataset;
-
+
for (result = dns_message_firstname(message, section);
result == ISC_R_SUCCESS;
result = dns_message_nextname(message, section))
@@ -5382,7 +5422,7 @@ checknamessection(dns_message_t *message, dns_section_t section) {
ISC_FALSE) ||
!dns_rdata_checknames(&rdata, name, NULL))
{
- rdataset->attributes |=
+ rdataset->attributes |=
DNS_RDATASETATTR_CHECKNAMES;
}
dns_rdata_reset(&rdata);
@@ -5512,6 +5552,19 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
* There's no hope for this query.
*/
keep_trying = ISC_TRUE;
+
+ /*
+ * If this is a network error on an exclusive query
+ * socket, mark the server as bad so that we won't try
+ * it for this fetch again.
+ */
+ if (query->exclusivesocket &&
+ (devent->result == ISC_R_HOSTUNREACH ||
+ devent->result == ISC_R_NETUNREACH ||
+ devent->result == ISC_R_CONNREFUSED ||
+ devent->result == ISC_R_CANCELED)) {
+ broken_server = devent->result;
+ }
}
goto done;
}
@@ -5662,12 +5715,17 @@ resquery_response(isc_task_t *task, isc_event_t *event) {
*/
if (message->rcode != dns_rcode_noerror &&
message->rcode != dns_rcode_nxdomain) {
- if ((message->rcode == dns_rcode_formerr ||
- message->rcode == dns_rcode_notimp ||
- message->rcode == dns_rcode_servfail) &&
+ if (((message->rcode == dns_rcode_formerr ||
+ message->rcode == dns_rcode_notimp) ||
+ (message->rcode == dns_rcode_servfail &&
+ dns_message_getopt(message) == NULL)) &&
(query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
/*
* It's very likely they don't like EDNS0.
+ * If the response code is SERVFAIL, also check if the
+ * response contains an OPT RR and don't cache the
+ * failure since it can be returned for various other
+ * reasons.
*
* XXXRTH We should check if the question
* we're asking requires EDNS0, and
@@ -6154,7 +6212,7 @@ spillattimer_countdown(isc_task_t *task, isc_event_t *event) {
REQUIRE(VALID_RESOLVER(res));
UNUSED(task);
-
+
LOCK(&res->lock);
INSIST(!res->exiting);
if (res->spillat > res->spillatmin) {
@@ -6181,7 +6239,7 @@ isc_result_t
dns_resolver_create(dns_view_t *view,
isc_taskmgr_t *taskmgr, unsigned int ntasks,
isc_socketmgr_t *socketmgr,
- isc_timermgr_t *timermgr,
+ isc_timermgr_t *timermgr,
unsigned int options,
dns_dispatchmgr_t *dispatchmgr,
dns_dispatch_t *dispatchv4,
@@ -6193,6 +6251,7 @@ dns_resolver_create(dns_view_t *view,
unsigned int i, buckets_created = 0;
isc_task_t *task = NULL;
char name[16];
+ unsigned dispattr;
/*
* Create a resolver.
@@ -6259,11 +6318,20 @@ dns_resolver_create(dns_view_t *view,
}
res->dispatchv4 = NULL;
- if (dispatchv4 != NULL)
+ if (dispatchv4 != NULL) {
dns_dispatch_attach(dispatchv4, &res->dispatchv4);
+ dispattr = dns_dispatch_getattributes(dispatchv4);
+ res->exclusivev4 =
+ ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
+ }
+
res->dispatchv6 = NULL;
- if (dispatchv6 != NULL)
+ if (dispatchv6 != NULL) {
dns_dispatch_attach(dispatchv6, &res->dispatchv6);
+ dispattr = dns_dispatch_getattributes(dispatchv6);
+ res->exclusivev6 =
+ ISC_TF((dispattr & DNS_DISPATCHATTR_EXCLUSIVE) != 0);
+ }
res->references = 1;
res->exiting = ISC_FALSE;
@@ -6380,7 +6448,7 @@ prime_done(isc_task_t *task, isc_event_t *event) {
UNLOCK(&res->primelock);
UNLOCK(&res->lock);
-
+
if (fevent->result == ISC_R_SUCCESS &&
res->view->cache != NULL && res->view->hints != NULL) {
dns_cache_attachdb(res->view->cache, &db);
@@ -6546,12 +6614,12 @@ dns_resolver_shutdown(dns_resolver_t *res) {
fctx != NULL;
fctx = ISC_LIST_NEXT(fctx, link))
fctx_shutdown(fctx);
- if (res->dispatchv4 != NULL) {
+ if (res->dispatchv4 != NULL && !res->exclusivev4) {
sock = dns_dispatch_getsocket(res->dispatchv4);
isc_socket_cancel(sock, res->buckets[i].task,
ISC_SOCKCANCEL_ALL);
}
- if (res->dispatchv6 != NULL) {
+ if (res->dispatchv6 != NULL && !res->exclusivev6) {
sock = dns_dispatch_getsocket(res->dispatchv6);
isc_socket_cancel(sock, res->buckets[i].task,
ISC_SOCKCANCEL_ALL);
@@ -6665,6 +6733,7 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
isc_event_t *event;
unsigned int count = 0;
unsigned int spillat;
+ unsigned int spillatmin;
UNUSED(forwarders);
@@ -6695,6 +6764,7 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
LOCK(&res->lock);
spillat = res->spillat;
+ spillatmin = res->spillatmin;
UNLOCK(&res->lock);
LOCK(&res->buckets[bucketnum].lock);
@@ -6711,7 +6781,7 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
break;
}
}
-
+
/*
* Is this a duplicate?
*/
@@ -6728,7 +6798,8 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name,
count++;
}
}
- if (count >= res->spillatmin && res->spillatmin != 0) {
+ if (count >= spillatmin && spillatmin != 0) {
+ INSIST(fctx != NULL);
if (count >= spillat)
fctx->spilled = ISC_TRUE;
if (fctx->spilled) {
@@ -7004,7 +7075,7 @@ free_algorithm(void *node, void *arg) {
isc_mem_put(mctx, algorithms, *algorithms);
}
-
+
void
dns_resolver_reset_algorithms(dns_resolver_t *resolver) {
@@ -7048,7 +7119,7 @@ dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
mask = 1 << (alg%8);
result = dns_rbt_addnode(resolver->algorithms, name, &node);
-
+
if (result == ISC_R_SUCCESS || result == ISC_R_EXISTS) {
algorithms = node->data;
if (algorithms == NULL || len > *algorithms) {
@@ -7064,7 +7135,7 @@ dns_resolver_disable_algorithm(dns_resolver_t *resolver, dns_name_t *name,
*new = len;
node->data = new;
if (algorithms != NULL)
- isc_mem_put(resolver->mctx, algorithms,
+ isc_mem_put(resolver->mctx, algorithms,
*algorithms);
} else
algorithms[len-1] |= mask;
@@ -7132,7 +7203,7 @@ dns_resolver_resetmustbesecure(dns_resolver_t *resolver) {
RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
#endif
}
-
+
static isc_boolean_t yes = ISC_TRUE, no = ISC_FALSE;
isc_result_t
@@ -7152,7 +7223,7 @@ dns_resolver_setmustbesecure(dns_resolver_t *resolver, dns_name_t *name,
if (result != ISC_R_SUCCESS)
goto cleanup;
}
- result = dns_rbt_addname(resolver->mustbesecure, name,
+ result = dns_rbt_addname(resolver->mustbesecure, name,
value ? &yes : &no);
cleanup:
#if USE_MBSLOCK
diff --git a/lib/dns/rootns.c b/lib/dns/rootns.c
index f20a49d..a988bea 100644
--- a/lib/dns/rootns.c
+++ b/lib/dns/rootns.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: rootns.c,v 1.26.18.5 2007/10/31 03:02:45 tbox Exp $ */
+/* $Id: rootns.c,v 1.26.18.7 2008/02/05 23:46:09 tbox Exp $ */
/*! \file */
@@ -45,8 +45,6 @@ static char root_ns[] =
";\n"
"; Internet Root Nameservers\n"
";\n"
-"; Thu Sep 23 17:57:37 PDT 1999\n"
-";\n"
"$TTL 518400\n"
". 518400 IN NS A.ROOT-SERVERS.NET.\n"
". 518400 IN NS B.ROOT-SERVERS.NET.\n"
@@ -62,25 +60,31 @@ static char root_ns[] =
". 518400 IN NS L.ROOT-SERVERS.NET.\n"
". 518400 IN NS M.ROOT-SERVERS.NET.\n"
"A.ROOT-SERVERS.NET. 3600000 IN A 198.41.0.4\n"
+"A.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:503:BA3E::2:30\n"
"B.ROOT-SERVERS.NET. 3600000 IN A 192.228.79.201\n"
"C.ROOT-SERVERS.NET. 3600000 IN A 192.33.4.12\n"
"D.ROOT-SERVERS.NET. 3600000 IN A 128.8.10.90\n"
"E.ROOT-SERVERS.NET. 3600000 IN A 192.203.230.10\n"
"F.ROOT-SERVERS.NET. 3600000 IN A 192.5.5.241\n"
+"F.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:2F::F\n"
"G.ROOT-SERVERS.NET. 3600000 IN A 192.112.36.4\n"
"H.ROOT-SERVERS.NET. 3600000 IN A 128.63.2.53\n"
+"H.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:1::803F:235\n"
"I.ROOT-SERVERS.NET. 3600000 IN A 192.36.148.17\n"
"J.ROOT-SERVERS.NET. 3600000 IN A 192.58.128.30\n"
+"J.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:503:C27::2:30\n"
"K.ROOT-SERVERS.NET. 3600000 IN A 193.0.14.129\n"
+"K.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:7FD::1\n"
"L.ROOT-SERVERS.NET. 3600000 IN A 199.7.83.42\n"
-"M.ROOT-SERVERS.NET. 3600000 IN A 202.12.27.33\n";
+"M.ROOT-SERVERS.NET. 3600000 IN A 202.12.27.33\n"
+"M.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:DC3::35\n";
static isc_result_t
in_rootns(dns_rdataset_t *rootns, dns_name_t *name) {
isc_result_t result;
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdata_ns_t ns;
-
+
if (!dns_rdataset_isassociated(rootns))
return (ISC_R_NOTFOUND);
@@ -99,7 +103,7 @@ in_rootns(dns_rdataset_t *rootns, dns_name_t *name) {
return (result);
}
-static isc_result_t
+static isc_result_t
check_node(dns_rdataset_t *rootns, dns_name_t *name,
dns_rdatasetiter_t *rdsiter) {
isc_result_t result;
@@ -227,7 +231,7 @@ dns_rootns_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
* Default to using the Internet root servers.
*/
result = dns_master_loadbuffer(&source, &db->origin,
- &db->origin, db->rdclass,
+ &db->origin, db->rdclass,
DNS_MASTER_HINT,
&callbacks, db->mctx);
} else
@@ -262,11 +266,11 @@ report(dns_view_t *view, dns_name_t *name, isc_boolean_t missing,
isc_buffer_t buffer;
isc_result_t result;
- if (strcmp(view->name, "_bind") != 0 &&
- strcmp(view->name, "_default") != 0) {
- viewname = view->name;
- sep = ": view ";
- }
+ if (strcmp(view->name, "_bind") != 0 &&
+ strcmp(view->name, "_default") != 0) {
+ viewname = view->name;
+ sep = ": view ";
+ }
dns_name_format(name, namebuf, sizeof(namebuf));
dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
@@ -346,7 +350,7 @@ check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db,
report(view, name, ISC_FALSE, &rdata);
result = dns_rdataset_next(&hintrrset);
}
- }
+ }
if (hresult == ISC_R_NOTFOUND &&
(rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
result = dns_rdataset_first(&rootrrset);
@@ -387,7 +391,7 @@ check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db,
dns_rdata_reset(&rdata);
result = dns_rdataset_next(&hintrrset);
}
- }
+ }
if (hresult == ISC_R_NOTFOUND &&
(rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
result = dns_rdataset_first(&rootrrset);
@@ -421,11 +425,11 @@ dns_root_checkhints(dns_view_t *view, dns_db_t *hints, dns_db_t *db) {
isc_stdtime_get(&now);
- if (strcmp(view->name, "_bind") != 0 &&
- strcmp(view->name, "_default") != 0) {
- viewname = view->name;
- sep = ": view ";
- }
+ if (strcmp(view->name, "_bind") != 0 &&
+ strcmp(view->name, "_default") != 0) {
+ viewname = view->name;
+ sep = ": view ";
+ }
dns_rdataset_init(&hintns);
dns_rdataset_init(&rootns);
@@ -453,7 +457,7 @@ dns_root_checkhints(dns_view_t *view, dns_db_t *hints, dns_db_t *db) {
dns_result_totext(result));
goto cleanup;
}
-
+
/*
* Look for missing root NS names.
*/
@@ -472,7 +476,7 @@ dns_root_checkhints(dns_view_t *view, dns_db_t *hints, dns_db_t *db) {
"checkhints%s%s: unable to find root "
"NS '%s' in hints", sep, viewname,
namebuf);
- } else
+ } else
check_address_records(view, hints, db, &ns.name, now);
dns_rdata_reset(&rdata);
result = dns_rdataset_next(&rootns);
diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c
index fe53778..effb2bf 100644
--- a/lib/dns/sdb.c
+++ b/lib/dns/sdb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: sdb.c,v 1.45.18.13 2007/08/28 07:20:05 tbox Exp $ */
+/* $Id: sdb.c,v 1.45.18.16 2008/01/17 23:45:58 tbox Exp $ */
/*! \file */
@@ -310,7 +310,7 @@ dns_sdb_putrdata(dns_sdblookup_t *lookup, dns_rdatatype_t typeval, dns_ttl_t ttl
ISC_LIST_INIT(rdatalist->rdata);
ISC_LINK_INIT(rdatalist, link);
ISC_LIST_APPEND(lookup->lists, rdatalist, link);
- } else
+ } else
if (rdatalist->ttl != ttl)
return (DNS_R_BADTTL);
@@ -337,7 +337,7 @@ dns_sdb_putrdata(dns_sdblookup_t *lookup, dns_rdatatype_t typeval, dns_ttl_t ttl
isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
return (result);
}
-
+
isc_result_t
dns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl,
@@ -380,7 +380,7 @@ dns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl,
datalen = strlen(data);
size = initial_size(datalen);
- for (;;) {
+ do {
isc_buffer_init(&b, data, datalen);
isc_buffer_add(&b, datalen);
result = isc_lex_openbuffer(lex, &b);
@@ -638,7 +638,7 @@ newversion(dns_db_t *db, dns_dbversion_t **versionp) {
}
static void
-attachversion(dns_db_t *db, dns_dbversion_t *source,
+attachversion(dns_db_t *db, dns_dbversion_t *source,
dns_dbversion_t **targetp)
{
REQUIRE(source != NULL && source == (void *) &dummy);
@@ -792,7 +792,7 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
return (result);
}
}
-
+
*nodep = node;
return (ISC_R_SUCCESS);
}
@@ -1120,7 +1120,7 @@ allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
sdb_rdatasetiter_t *iterator;
REQUIRE(version == NULL || version == &dummy);
-
+
UNUSED(version);
UNUSED(now);
diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c
index e4dbdc7..998ea36 100644
--- a/lib/dns/tkey.c
+++ b/lib/dns/tkey.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -16,7 +16,7 @@
*/
/*
- * $Id: tkey.c,v 1.76.18.5 2005/11/30 03:44:39 marka Exp $
+ * $Id: tkey.c,v 1.76.18.7 2008/01/02 23:46:02 tbox Exp $
*/
/*! \file */
#include <config.h>
@@ -379,7 +379,7 @@ process_dhtkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name,
isc_buffer_base(&secret),
isc_buffer_usedlength(&secret),
ISC_TRUE, signer, tkeyin->inception,
- tkeyin->expire, msg->mctx, ring, NULL));
+ tkeyin->expire, ring->mctx, ring, NULL));
/* This key is good for a long time */
tkeyout->inception = tkeyin->inception;
@@ -440,7 +440,7 @@ process_gsstkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name,
result = dns_tsigkey_createfromkey(name, &tkeyin->algorithm,
dstkey, ISC_TRUE, signer,
tkeyin->inception, tkeyin->expire,
- msg->mctx, ring, NULL);
+ ring->mctx, ring, NULL);
#if 1
if (result != ISC_R_SUCCESS)
goto failure;
@@ -1106,7 +1106,7 @@ dns_tkey_processdhresponse(dns_message_t *qmsg, dns_message_t *rmsg,
result = dns_tsigkey_create(tkeyname, &rtkey.algorithm,
r.base, r.length, ISC_TRUE,
NULL, rtkey.inception, rtkey.expire,
- rmsg->mctx, ring, outkey);
+ ring->mctx, ring, outkey);
isc_buffer_free(&shared);
dns_rdata_freestruct(&rtkey);
dst_key_free(&theirkey);
@@ -1176,7 +1176,7 @@ dns_tkey_processgssresponse(dns_message_t *qmsg, dns_message_t *rmsg,
RETERR(dns_tsigkey_createfromkey(tkeyname, DNS_TSIG_GSSAPI_NAME,
dstkey, ISC_TRUE, NULL,
rtkey.inception, rtkey.expire,
- rmsg->mctx, ring, outkey));
+ ring->mctx, ring, outkey));
dns_rdata_freestruct(&rtkey);
return (result);
diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c
index cca1f99..f21832f 100644
--- a/lib/dns/tsig.c
+++ b/lib/dns/tsig.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2002 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -16,7 +16,7 @@
*/
/*
- * $Id: tsig.c,v 1.117.18.11 2007/09/26 23:46:34 tbox Exp $
+ * $Id: tsig.c,v 1.117.18.14 2008/01/17 23:46:03 tbox Exp $
*/
/*! \file */
#include <config.h>
@@ -105,12 +105,12 @@ static unsigned char hmacsha1_ndata[] = "\011hmac-sha1";
static unsigned char hmacsha1_offsets[] = { 0, 10 };
static dns_name_t hmacsha1 = {
- DNS_NAME_MAGIC,
- hmacsha1_ndata, 11, 2,
- DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
- hmacsha1_offsets, NULL,
- {(void *)-1, (void *)-1},
- {NULL, NULL}
+ DNS_NAME_MAGIC,
+ hmacsha1_ndata, 11, 2,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ hmacsha1_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
};
LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha1_name = &hmacsha1;
@@ -119,12 +119,12 @@ static unsigned char hmacsha224_ndata[] = "\013hmac-sha224";
static unsigned char hmacsha224_offsets[] = { 0, 12 };
static dns_name_t hmacsha224 = {
- DNS_NAME_MAGIC,
- hmacsha224_ndata, 13, 2,
- DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
- hmacsha224_offsets, NULL,
- {(void *)-1, (void *)-1},
- {NULL, NULL}
+ DNS_NAME_MAGIC,
+ hmacsha224_ndata, 13, 2,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ hmacsha224_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
};
LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha224_name = &hmacsha224;
@@ -133,12 +133,12 @@ static unsigned char hmacsha256_ndata[] = "\013hmac-sha256";
static unsigned char hmacsha256_offsets[] = { 0, 12 };
static dns_name_t hmacsha256 = {
- DNS_NAME_MAGIC,
- hmacsha256_ndata, 13, 2,
- DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
- hmacsha256_offsets, NULL,
- {(void *)-1, (void *)-1},
- {NULL, NULL}
+ DNS_NAME_MAGIC,
+ hmacsha256_ndata, 13, 2,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ hmacsha256_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
};
LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha256_name = &hmacsha256;
@@ -147,12 +147,12 @@ static unsigned char hmacsha384_ndata[] = "\013hmac-sha384";
static unsigned char hmacsha384_offsets[] = { 0, 12 };
static dns_name_t hmacsha384 = {
- DNS_NAME_MAGIC,
- hmacsha384_ndata, 13, 2,
- DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
- hmacsha384_offsets, NULL,
- {(void *)-1, (void *)-1},
- {NULL, NULL}
+ DNS_NAME_MAGIC,
+ hmacsha384_ndata, 13, 2,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ hmacsha384_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
};
LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha384_name = &hmacsha384;
@@ -161,12 +161,12 @@ static unsigned char hmacsha512_ndata[] = "\013hmac-sha512";
static unsigned char hmacsha512_offsets[] = { 0, 12 };
static dns_name_t hmacsha512 = {
- DNS_NAME_MAGIC,
- hmacsha512_ndata, 13, 2,
- DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
- hmacsha512_offsets, NULL,
- {(void *)-1, (void *)-1},
- {NULL, NULL}
+ DNS_NAME_MAGIC,
+ hmacsha512_ndata, 13, 2,
+ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE,
+ hmacsha512_offsets, NULL,
+ {(void *)-1, (void *)-1},
+ {NULL, NULL}
};
LIBDNS_EXTERNAL_DATA dns_name_t *dns_tsig_hmacsha512_name = &hmacsha512;
@@ -323,7 +323,8 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
tkey->generated = generated;
tkey->inception = inception;
tkey->expire = expire;
- tkey->mctx = mctx;
+ tkey->mctx = NULL;
+ isc_mem_attach(mctx, &tkey->mctx);
tkey->magic = TSIG_MAGIC;
@@ -509,7 +510,7 @@ tsigkey_free(dns_tsigkey_t *key) {
isc_mem_put(key->mctx, key->creator, sizeof(dns_name_t));
}
isc_refcount_destroy(&key->refs);
- isc_mem_put(key->mctx, key, sizeof(dns_tsigkey_t));
+ isc_mem_putanddetach(&key->mctx, key, sizeof(dns_tsigkey_t));
}
void
@@ -981,7 +982,7 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg,
return (DNS_R_FORMERR);
}
if (tsig.siglen > 0 && digestbits != 0 &&
- tsig.siglen < ((digestbits + 1) / 8)) {
+ tsig.siglen < ((digestbits + 1) / 8)) {
msg->tsigstatus = dns_tsigerror_badtrunc;
tsig_log(msg->tsigkey, 2,
"truncated signature length too small");
@@ -1442,7 +1443,8 @@ dns_tsigkeyring_create(isc_mem_t *mctx, dns_tsig_keyring_t **ringp) {
return (result);
}
- ring->mctx = mctx;
+ ring->mctx = NULL;
+ isc_mem_attach(mctx, &ring->mctx);
*ringp = ring;
return (ISC_R_SUCCESS);
@@ -1460,5 +1462,5 @@ dns_tsigkeyring_destroy(dns_tsig_keyring_t **ringp) {
dns_rbt_destroy(&ring->keys);
isc_rwlock_destroy(&ring->lock);
- isc_mem_put(ring->mctx, ring, sizeof(dns_tsig_keyring_t));
+ isc_mem_putanddetach(&ring->mctx, ring, sizeof(dns_tsig_keyring_t));
}
diff --git a/lib/dns/validator.c b/lib/dns/validator.c
index 9538b302..e686336 100644
--- a/lib/dns/validator.c
+++ b/lib/dns/validator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: validator.c,v 1.119.18.35 2007/09/26 04:39:45 each Exp $ */
+/* $Id: validator.c,v 1.119.18.41 2008/08/21 04:59:42 marka Exp $ */
/*! \file */
@@ -55,7 +55,7 @@
* dlv_validator_start -> validator_start -> validate -> proveunsecure
*
* validator_start -> validate -> nsecvalidate (secure wildcard answer)
- *
+ *
* \li When called with rdataset, sigrdataset and with DNS_VALIDATOR_DLV:
* validator_start -> startfinddlvsep -> dlv_validator_start ->
* validator_start -> validate -> proveunsecure
@@ -134,7 +134,8 @@ static isc_result_t
nsecvalidate(dns_validator_t *val, isc_boolean_t resume);
static isc_result_t
-proveunsecure(dns_validator_t *val, isc_boolean_t resume);
+proveunsecure(dns_validator_t *val, isc_boolean_t have_ds,
+ isc_boolean_t resume);
static void
validator_logv(dns_validator_t *val, isc_logcategory_t *category,
@@ -365,7 +366,7 @@ dsfetched(isc_task_t *task, isc_event_t *event) {
"falling back to insecurity proof (%s)",
dns_result_totext(eresult));
val->attributes |= VALATTR_INSECURITY;
- result = proveunsecure(val, ISC_FALSE);
+ result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
if (result != DNS_R_WAIT)
validator_done(val, result);
} else {
@@ -444,7 +445,7 @@ dsfetched2(isc_task_t *task, isc_event_t *event) {
validator_done(val, result);
}
} else {
- result = proveunsecure(val, ISC_TRUE);
+ result = proveunsecure(val, ISC_FALSE, ISC_TRUE);
if (result != DNS_R_WAIT)
validator_done(val, result);
}
@@ -453,11 +454,12 @@ dsfetched2(isc_task_t *task, isc_event_t *event) {
eresult == DNS_R_NCACHENXDOMAIN)
{
/*
- * There is a DS which may or may not be a zone cut.
+ * There is a DS which may or may not be a zone cut.
* In either case we are still in a secure zone resume
* validation.
*/
- result = proveunsecure(val, ISC_TRUE);
+ result = proveunsecure(val, ISC_TF(eresult == ISC_R_SUCCESS),
+ ISC_TRUE);
if (result != DNS_R_WAIT)
validator_done(val, result);
} else {
@@ -558,7 +560,7 @@ dsvalidated(isc_task_t *task, isc_event_t *event) {
validator_log(val, ISC_LOG_DEBUG(3),
"dsset with trust %d", val->frdataset.trust);
if ((val->attributes & VALATTR_INSECURITY) != 0)
- result = proveunsecure(val, ISC_TRUE);
+ result = proveunsecure(val, ISC_TRUE, ISC_TRUE);
else
result = validatezonekey(val);
if (result != DNS_R_WAIT)
@@ -779,7 +781,7 @@ authvalidated(isc_task_t *task, isc_event_t *event) {
} else {
dns_name_t **proofs = val->event->proofs;
dns_name_t *wild = dns_fixedname_name(&val->wild);
-
+
if (rdataset->trust == dns_trust_secure)
val->seensig = ISC_TRUE;
@@ -787,7 +789,7 @@ authvalidated(isc_task_t *task, isc_event_t *event) {
rdataset->trust == dns_trust_secure &&
((val->attributes & VALATTR_NEEDNODATA) != 0 ||
(val->attributes & VALATTR_NEEDNOQNAME) != 0) &&
- (val->attributes & VALATTR_FOUNDNODATA) == 0 &&
+ (val->attributes & VALATTR_FOUNDNODATA) == 0 &&
(val->attributes & VALATTR_FOUNDNOQNAME) == 0 &&
nsecnoexistnodata(val, val->event->name, devent->name,
rdataset, &exists, &data, wild)
@@ -900,7 +902,7 @@ view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
/* End of zone chain. */
if (!dns_name_issubdomain(name, &nsec.next)) {
/*
- * XXXMPA We could look for a parent NSEC
+ * XXXMPA We could look for a parent NSEC
* at nsec.next and if found retest with
* this NSEC.
*/
@@ -937,10 +939,11 @@ view_find(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type) {
dns_rdata_freestruct(&nsec);
result = DNS_R_NCACHENXDOMAIN;
} else if (result != ISC_R_SUCCESS &&
- result != DNS_R_NCACHENXDOMAIN &&
- result != DNS_R_NCACHENXRRSET &&
- result != DNS_R_NXRRSET &&
- result != ISC_R_NOTFOUND) {
+ result != DNS_R_NCACHENXDOMAIN &&
+ result != DNS_R_NCACHENXRRSET &&
+ result != DNS_R_EMPTYNAME &&
+ result != DNS_R_NXRRSET &&
+ result != ISC_R_NOTFOUND) {
goto notfound;
}
return (result);
@@ -1196,6 +1199,7 @@ get_key(dns_validator_t *val, dns_rdata_rrsig_t *siginfo) {
return (DNS_R_WAIT);
} else if (result == DNS_R_NCACHENXDOMAIN ||
result == DNS_R_NCACHENXRRSET ||
+ result == DNS_R_EMPTYNAME ||
result == DNS_R_NXDOMAIN ||
result == DNS_R_NXRRSET)
{
@@ -1246,7 +1250,8 @@ isselfsigned(dns_validator_t *val) {
{
dns_rdata_reset(&rdata);
dns_rdataset_current(rdataset, &rdata);
- (void)dns_rdata_tostruct(&rdata, &key, NULL);
+ result = dns_rdata_tostruct(&rdata, &key, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
keytag = compute_keytag(&rdata, &key);
for (result = dns_rdataset_first(sigrdataset);
result == ISC_R_SUCCESS;
@@ -1254,7 +1259,8 @@ isselfsigned(dns_validator_t *val) {
{
dns_rdata_reset(&sigrdata);
dns_rdataset_current(sigrdataset, &sigrdata);
- (void)dns_rdata_tostruct(&sigrdata, &sig, NULL);
+ result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
if (sig.algorithm == key.algorithm &&
sig.keyid == keytag)
@@ -1514,7 +1520,8 @@ dlv_validatezonekey(dns_validator_t *val) {
result = dns_rdataset_next(&val->dlv)) {
dns_rdata_reset(&dlvrdata);
dns_rdataset_current(&val->dlv, &dlvrdata);
- dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
+ result = dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
if (!dns_resolver_algorithm_supported(val->view->resolver,
val->event->name,
@@ -1534,12 +1541,13 @@ dlv_validatezonekey(dns_validator_t *val) {
{
dns_rdata_reset(&dlvrdata);
dns_rdataset_current(&val->dlv, &dlvrdata);
- (void)dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
+ result = dns_rdata_tostruct(&dlvrdata, &dlv, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
if (!dns_resolver_digest_supported(val->view->resolver,
dlv.digest_type))
continue;
-
+
if (dlv.digest_type != digest_type)
continue;
@@ -1559,7 +1567,8 @@ dlv_validatezonekey(dns_validator_t *val) {
{
dns_rdata_reset(&keyrdata);
dns_rdataset_current(&trdataset, &keyrdata);
- (void)dns_rdata_tostruct(&keyrdata, &key, NULL);
+ result = dns_rdata_tostruct(&keyrdata, &key, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
keytag = compute_keytag(&keyrdata, &key);
if (dlv.key_tag != keytag ||
dlv.algorithm != key.algorithm)
@@ -1594,7 +1603,8 @@ dlv_validatezonekey(dns_validator_t *val) {
dns_rdata_reset(&sigrdata);
dns_rdataset_current(val->event->sigrdataset,
&sigrdata);
- (void)dns_rdata_tostruct(&sigrdata, &sig, NULL);
+ result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
if (dlv.key_tag != sig.keyid &&
dlv.algorithm != sig.algorithm)
continue;
@@ -1691,7 +1701,8 @@ validatezonekey(dns_validator_t *val) {
dns_rdata_reset(&sigrdata);
dns_rdataset_current(val->event->sigrdataset,
&sigrdata);
- (void)dns_rdata_tostruct(&sigrdata, &sig, NULL);
+ result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
result = dns_keytable_findkeynode(val->keytable,
val->event->name,
sig.algorithm,
@@ -1745,7 +1756,7 @@ validatezonekey(dns_validator_t *val) {
* the RRset is invalid.
*/
dns_name_format(val->event->name, namebuf,
- sizeof(namebuf));
+ sizeof(namebuf));
validator_log(val, ISC_LOG_DEBUG(2),
"unable to find a DNSKEY which verifies "
"the DNSKEY RRset and also matches one "
@@ -1796,8 +1807,9 @@ validatezonekey(dns_validator_t *val) {
if (result != ISC_R_SUCCESS)
return (result);
return (DNS_R_WAIT);
- } else if (result == DNS_R_NCACHENXDOMAIN ||
+ } else if (result == DNS_R_NCACHENXDOMAIN ||
result == DNS_R_NCACHENXRRSET ||
+ result == DNS_R_EMPTYNAME ||
result == DNS_R_NXDOMAIN ||
result == DNS_R_NXRRSET)
{
@@ -1848,7 +1860,8 @@ validatezonekey(dns_validator_t *val) {
result = dns_rdataset_next(val->dsset)) {
dns_rdata_reset(&dsrdata);
dns_rdataset_current(val->dsset, &dsrdata);
- dns_rdata_tostruct(&dsrdata, &ds, NULL);
+ result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
if (!dns_resolver_algorithm_supported(val->view->resolver,
val->event->name,
@@ -1868,7 +1881,8 @@ validatezonekey(dns_validator_t *val) {
{
dns_rdata_reset(&dsrdata);
dns_rdataset_current(val->dsset, &dsrdata);
- (void)dns_rdata_tostruct(&dsrdata, &ds, NULL);
+ result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
if (!dns_resolver_digest_supported(val->view->resolver,
ds.digest_type))
@@ -1896,7 +1910,8 @@ validatezonekey(dns_validator_t *val) {
{
dns_rdata_reset(&keyrdata);
dns_rdataset_current(&trdataset, &keyrdata);
- (void)dns_rdata_tostruct(&keyrdata, &key, NULL);
+ result = dns_rdata_tostruct(&keyrdata, &key, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
keytag = compute_keytag(&keyrdata, &key);
if (ds.key_tag != keytag ||
ds.algorithm != key.algorithm)
@@ -1915,7 +1930,7 @@ validatezonekey(dns_validator_t *val) {
"no DNSKEY matching DS");
continue;
}
-
+
for (result = dns_rdataset_first(val->event->sigrdataset);
result == ISC_R_SUCCESS;
result = dns_rdataset_next(val->event->sigrdataset))
@@ -1923,7 +1938,8 @@ validatezonekey(dns_validator_t *val) {
dns_rdata_reset(&sigrdata);
dns_rdataset_current(val->event->sigrdataset,
&sigrdata);
- (void)dns_rdata_tostruct(&sigrdata, &sig, NULL);
+ result = dns_rdata_tostruct(&sigrdata, &sig, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
if (ds.key_tag != sig.keyid ||
ds.algorithm != sig.algorithm)
continue;
@@ -1994,7 +2010,7 @@ start_positive_validation(dns_validator_t *val) {
* exclusive we stop when one is found.
*
* Returns
- * \li ISC_R_SUCCESS
+ * \li ISC_R_SUCCESS
*/
static isc_result_t
checkwildcard(dns_validator_t *val) {
@@ -2213,7 +2229,7 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) {
validator_log(val, ISC_LOG_DEBUG(3),
"nonexistence proof(s) not found");
val->attributes |= VALATTR_INSECURITY;
- return (proveunsecure(val, ISC_FALSE));
+ return (proveunsecure(val, ISC_FALSE, ISC_FALSE));
}
static isc_boolean_t
@@ -2226,7 +2242,8 @@ check_ds(dns_validator_t *val, dns_name_t *name, dns_rdataset_t *rdataset) {
result == ISC_R_SUCCESS;
result = dns_rdataset_next(rdataset)) {
dns_rdataset_current(rdataset, &dsrdata);
- (void)dns_rdata_tostruct(&dsrdata, &ds, NULL);
+ result = dns_rdata_tostruct(&dsrdata, &ds, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
if (dns_resolver_digest_supported(val->view->resolver,
ds.digest_type) &&
@@ -2242,7 +2259,7 @@ check_ds(dns_validator_t *val, dns_name_t *name, dns_rdataset_t *rdataset) {
/*%
* Callback from fetching a DLV record.
- *
+ *
* Resumes the DLV lookup process.
*/
static void
@@ -2316,7 +2333,7 @@ dlvfetched(isc_task_t *task, isc_event_t *event) {
/*%
* Start the DLV lookup proccess.
- *
+ *
* Returns
* \li ISC_R_SUCCESS
* \li DNS_R_WAIT
@@ -2450,6 +2467,7 @@ finddlvsep(dns_validator_t *val, isc_boolean_t resume) {
}
if (result != DNS_R_NXRRSET &&
result != DNS_R_NXDOMAIN &&
+ result != DNS_R_EMPTYNAME &&
result != DNS_R_NCACHENXRRSET &&
result != DNS_R_NCACHENXDOMAIN)
return (result);
@@ -2486,7 +2504,8 @@ finddlvsep(dns_validator_t *val, isc_boolean_t resume) {
* \li DNS_R_NOTINSECURE
*/
static isc_result_t
-proveunsecure(dns_validator_t *val, isc_boolean_t resume) {
+proveunsecure(dns_validator_t *val, isc_boolean_t have_ds, isc_boolean_t resume)
+{
isc_result_t result;
dns_fixedname_t fixedsecroot;
dns_name_t *secroot;
@@ -2508,7 +2527,7 @@ proveunsecure(dns_validator_t *val, isc_boolean_t resume) {
dns_name_split(secroot, 1, NULL, secroot);
result = dns_keytable_finddeepestmatch(val->keytable,
secroot, secroot);
-
+
if (result == ISC_R_NOTFOUND) {
validator_log(val, ISC_LOG_DEBUG(3),
"not beneath secure root");
@@ -2534,12 +2553,19 @@ proveunsecure(dns_validator_t *val, isc_boolean_t resume) {
val->labels = dns_name_countlabels(secroot) + 1;
} else {
validator_log(val, ISC_LOG_DEBUG(3), "resuming proveunsecure");
- if (val->frdataset.trust >= dns_trust_secure &&
+ /*
+ * If we have a DS rdataset and it is secure then check if
+ * the DS rdataset has a supported algorithm combination.
+ * If not this is a insecure delegation as far as this
+ * resolver is concerned. Fall back to DLV if available.
+ */
+ if (have_ds && val->frdataset.trust >= dns_trust_secure &&
!check_ds(val, dns_fixedname_name(&val->fname),
&val->frdataset)) {
dns_name_format(dns_fixedname_name(&val->fname),
namebuf, sizeof(namebuf));
- if (val->mustbesecure) {
+ if ((val->view->dlv == NULL || DLVTRIED(val)) &&
+ val->mustbesecure) {
validator_log(val, ISC_LOG_WARNING,
"must be secure failure at '%s'",
namebuf);
@@ -2784,7 +2810,7 @@ validator_start(isc_task_t *task, isc_event_t *event) {
validator_log(val, ISC_LOG_DEBUG(3),
"falling back to insecurity proof");
val->attributes |= VALATTR_INSECURITY;
- result = proveunsecure(val, ISC_FALSE);
+ result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
if (result == DNS_R_NOTINSECURE)
result = saved_result;
}
@@ -2798,7 +2824,7 @@ validator_start(isc_task_t *task, isc_event_t *event) {
"attempting insecurity proof");
val->attributes |= VALATTR_INSECURITY;
- result = proveunsecure(val, ISC_FALSE);
+ result = proveunsecure(val, ISC_FALSE, ISC_FALSE);
} else if (val->event->rdataset == NULL &&
val->event->sigrdataset == NULL)
{
diff --git a/lib/dns/view.c b/lib/dns/view.c
index d5a78d5..4851cf0 100644
--- a/lib/dns/view.c
+++ b/lib/dns/view.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: view.c,v 1.126.18.14 2007/08/28 07:20:05 tbox Exp $ */
+/* $Id: view.c,v 1.126.18.16 2008/06/17 23:46:03 tbox Exp $ */
/*! \file */
@@ -315,7 +315,7 @@ destroy(dns_view_t *view) {
name = ISC_LIST_HEAD(view->rootexclude[i]);
while (name != NULL) {
ISC_LIST_UNLINK(view->rootexclude[i],
- name, link);
+ name, link);
dns_name_free(name, view->mctx);
isc_mem_put(view->mctx, name, sizeof(*name));
name = ISC_LIST_HEAD(view->rootexclude[i]);
@@ -846,17 +846,6 @@ dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
}
cleanup:
- if (result == DNS_R_NXDOMAIN || result == DNS_R_NXRRSET) {
- /*
- * We don't care about any DNSSEC proof data in these cases.
- */
- if (dns_rdataset_isassociated(rdataset))
- dns_rdataset_disassociate(rdataset);
- if (sigrdataset != NULL &&
- dns_rdataset_isassociated(sigrdataset))
- dns_rdataset_disassociate(sigrdataset);
- }
-
if (dns_rdataset_isassociated(&zrdataset)) {
dns_rdataset_disassociate(&zrdataset);
if (dns_rdataset_isassociated(&zsigrdataset))
@@ -936,7 +925,7 @@ dns_view_simplefind(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
isc_result_t
dns_view_findzonecut(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
isc_stdtime_t now, unsigned int options,
- isc_boolean_t use_hints,
+ isc_boolean_t use_hints,
dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
{
return(dns_view_findzonecut2(view, name, fname, now, options,
@@ -1348,7 +1337,7 @@ dns_view_isdelegationonly(dns_view_t *view, dns_name_t *name) {
return (ISC_TRUE);
}
-void
+void
dns_view_setrootdelonly(dns_view_t *view, isc_boolean_t value) {
REQUIRE(DNS_VIEW_VALID(view));
view->rootdelonly = value;
diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c
index f95773f..7171a37 100644
--- a/lib/dns/xfrin.c
+++ b/lib/dns/xfrin.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: xfrin.c,v 1.135.18.16.10.3 2008/07/23 23:16:43 marka Exp $ */
+/* $Id: xfrin.c,v 1.135.18.23 2008/09/25 04:15:52 marka Exp $ */
/*! \file */
@@ -248,7 +248,7 @@ static isc_result_t
axfr_init(dns_xfrin_ctx_t *xfr) {
isc_result_t result;
- xfr->is_ixfr = ISC_FALSE;
+ xfr->is_ixfr = ISC_FALSE;
if (xfr->db != NULL)
dns_db_detach(&xfr->db);
@@ -426,6 +426,10 @@ xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, isc_uint32_t ttl,
{
isc_result_t result;
+ if (rdata->type == dns_rdatatype_none ||
+ dns_rdatatype_ismeta(rdata->type))
+ FAIL(DNS_R_FORMERR);
+
redo:
switch (xfr->state) {
case XFRST_SOAQUERY:
@@ -892,8 +896,8 @@ render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf) {
CHECK(dns_message_renderend(msg));
result = ISC_R_SUCCESS;
failure:
- if (cleanup_cctx)
- dns_compress_invalidate(&cctx);
+ if (cleanup_cctx)
+ dns_compress_invalidate(&cctx);
return (result);
}
@@ -1051,6 +1055,8 @@ xfrin_send_request(dns_xfrin_ctx_t *xfr) {
xfr->id++;
xfr->nmsg = 0;
msg->id = xfr->id;
+ if (xfr->tsigctx != NULL)
+ dst_context_destroy(&xfr->tsigctx);
CHECK(render(msg, xfr->mctx, &xfr->qbuffer));
@@ -1186,7 +1192,10 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
+
msg->tsigctx = xfr->tsigctx;
+ xfr->tsigctx = NULL;
+
if (xfr->nmsg > 0)
msg->tcp_continuation = 1;
@@ -1299,9 +1308,11 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
xfr->nmsg++;
/*
- * Copy the context back.
+ * Take the context back.
*/
+ INSIST(xfr->tsigctx == NULL);
xfr->tsigctx = msg->tsigctx;
+ msg->tsigctx = NULL;
dns_message_destroy(&msg);
@@ -1397,6 +1408,9 @@ maybe_free(dns_xfrin_ctx_t *xfr) {
if (xfr->tcpmsg_valid)
dns_tcpmsg_invalidate(&xfr->tcpmsg);
+ if (xfr->tsigctx != NULL)
+ dst_context_destroy(&xfr->tsigctx);
+
if ((xfr->name.attributes & DNS_NAMEATTR_DYNAMIC) != 0)
dns_name_free(&xfr->name, xfr->mctx);
@@ -1438,7 +1452,7 @@ xfrin_logv(int level, const char *zonetext, isc_sockaddr_t *masteraddr,
static void
xfrin_log1(int level, const char *zonetext, isc_sockaddr_t *masteraddr,
- const char *fmt, ...)
+ const char *fmt, ...)
{
va_list ap;
diff --git a/lib/dns/zone.c b/lib/dns/zone.c
index fa6ac46..36f303c 100644
--- a/lib/dns/zone.c
+++ b/lib/dns/zone.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zone.c,v 1.410.18.52 2007/08/30 05:15:03 marka Exp $ */
+/* $Id: zone.c,v 1.410.18.55 2008/10/24 01:43:17 tbox Exp $ */
/*! \file */
@@ -813,10 +813,10 @@ dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
isc_result_t result = ISC_R_SUCCESS;
void *mem;
char **tmp, *tmp2;
-
+
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(argv != NULL && *argv == NULL);
-
+
LOCK_ZONE(zone);
size = (zone->db_argc + 1) * sizeof(char *);
for (i = 0; i < zone->db_argc; i++)
@@ -927,7 +927,7 @@ void
dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache) {
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(acache != NULL);
-
+
LOCK_ZONE(zone);
if (zone->acache != NULL)
dns_acache_detach(&zone->acache);
@@ -1425,7 +1425,7 @@ zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
dns_fixedname_t fixed;
dns_name_t *foundname;
int level;
-
+
/*
* Outside of zone.
*/
@@ -1507,7 +1507,7 @@ zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
dns_fixedname_t fixed;
dns_name_t *foundname;
int level;
-
+
/*
* "." means the services does not exist.
*/
@@ -1598,7 +1598,7 @@ zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
dns_rdataset_t a;
dns_rdataset_t aaaa;
int level;
-
+
/*
* Outside of zone.
*/
@@ -1636,7 +1636,7 @@ zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
if (tresult == ISC_R_SUCCESS) {
dns_rdataset_disassociate(&aaaa);
return (ISC_TRUE);
- }
+ }
if (tresult == DNS_R_DELEGATION)
dns_rdataset_disassociate(&aaaa);
if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
@@ -1660,14 +1660,16 @@ zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
const char *what;
- if (dns_name_issubdomain(name, owner))
+ isc_boolean_t required = ISC_FALSE;
+ if (dns_name_issubdomain(name, owner)) {
what = "REQUIRED GLUE ";
- else if (result == DNS_R_DELEGATION)
+ required = ISC_TRUE;
+ } else if (result == DNS_R_DELEGATION)
what = "SIBLING GLUE ";
else
what = "";
- if (result != DNS_R_DELEGATION ||
+ if (result != DNS_R_DELEGATION || required ||
DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
dns_zone_log(zone, level, "%s/NS '%s' has no %s"
"address records (A or AAAA)",
@@ -1749,7 +1751,7 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) {
if (dns_name_equal(name, &zone->origin))
goto checkmx;
- result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
+ result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
0, 0, &rdataset, NULL);
if (result != ISC_R_SUCCESS)
goto checkmx;
@@ -1771,7 +1773,7 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) {
dns_rdataset_disassociate(&rdataset);
checkmx:
- result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
+ result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
0, 0, &rdataset, NULL);
if (result != ISC_R_SUCCESS)
goto checksrv;
@@ -1790,7 +1792,7 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) {
checksrv:
if (zone->rdclass != dns_rdataclass_in)
goto next;
- result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
+ result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
0, 0, &rdataset, NULL);
if (result != ISC_R_SUCCESS)
goto next;
@@ -1848,12 +1850,12 @@ zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
for (result = dns_rdataset_first(&rdataset);
result == ISC_R_SUCCESS;
- result = dns_rdataset_next(&rdataset))
+ result = dns_rdataset_next(&rdataset))
{
dns_rdataset_current(&rdataset, &rdata);
result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
INSIST(result == ISC_R_SUCCESS);
-
+
if ((dnskey.algorithm == DST_ALG_RSASHA1 ||
dnskey.algorithm == DST_ALG_RSAMD5) &&
dnskey.datalen > 1 && dnskey.data[0] == 1 &&
@@ -1885,7 +1887,7 @@ zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
dns_db_detachnode(db, &node);
if (version != NULL)
dns_db_closeversion(db, &version, ISC_FALSE);
-
+
}
static isc_result_t
@@ -2039,7 +2041,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
} else if (!isc_serial_ge(serial, zone->serial))
dns_zone_log(zone, ISC_LOG_ERROR,
"zone serial has gone backwards");
- else if (serial == zone->serial && !hasinclude)
+ else if (serial == zone->serial && !hasinclude)
dns_zone_log(zone, ISC_LOG_ERROR,
"zone serial unchanged. "
"zone may fail to transfer "
@@ -2171,7 +2173,7 @@ zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_name_t *name) {
dns_fixedname_t fixed;
dns_name_t *foundname;
int level;
-
+
if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
return (ISC_TRUE);
@@ -2760,7 +2762,7 @@ dns_zone_setmasterswithkeys(dns_zone_t *zone,
}
LOCK_ZONE(zone);
- /*
+ /*
* The refresh code assumes that 'masters' wouldn't change under it.
* If it will change then kill off any current refresh in progress
* and update the masters info. If it won't change then we can just
@@ -2815,7 +2817,7 @@ dns_zone_setmasterswithkeys(dns_zone_t *zone,
goto unlock;
}
memcpy(new, masters, count * sizeof(*new));
-
+
/*
* Similarly for mastersok.
*/
@@ -4834,7 +4836,7 @@ add_opt(dns_message_t *message, isc_uint16_t udpsize) {
if (result != ISC_R_SUCCESS)
goto cleanup;
dns_rdataset_init(rdataset);
-
+
rdatalist->type = dns_rdatatype_opt;
rdatalist->covers = 0;
@@ -4871,7 +4873,7 @@ add_opt(dns_message_t *message, isc_uint16_t udpsize) {
dns_message_puttemprdataset(message, &rdataset);
if (rdata != NULL)
dns_message_puttemprdata(message, &rdata);
-
+
return (result);
}
@@ -5161,7 +5163,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
}
}
if (key == NULL)
- (void)dns_view_getpeertsig(zone->view, &masterip, &key);
+ (void)dns_view_getpeertsig(zone->view, &masterip, &key);
if (zone->view->peers != NULL) {
dns_peer_t *peer = NULL;
@@ -5181,7 +5183,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
dns_resolver_getudpsize(zone->view->resolver);
(void)dns_peer_getudpsize(peer, &udpsize);
}
-
+
}
if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
result = add_opt(message, udpsize);
@@ -5315,7 +5317,7 @@ zone_shutdown(isc_task_t *task, isc_event_t *event) {
if (zone->writeio != NULL)
zonemgr_cancelio(zone->writeio);
- if (zone->dctx != NULL)
+ if (zone->dctx != NULL)
dns_dumpctx_cancel(zone->dctx);
}
@@ -6664,7 +6666,7 @@ zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
}
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
}
-
+
/*
* This transfer finishing freed up a transfer quota slot.
* Let any other zones waiting for quota have it.
@@ -6702,7 +6704,7 @@ zone_loaddone(void *arg, isc_result_t result) {
ENTER;
tresult = dns_db_endload(load->db, &load->callbacks.add_private);
- if (tresult != ISC_R_SUCCESS &&
+ if (tresult != ISC_R_SUCCESS &&
(result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
result = tresult;
@@ -7725,7 +7727,7 @@ zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
if (result != ISC_R_SUCCESS)
goto cleanup;
- dns_zone_log(zone, ISC_LOG_INFO, "saved '%s' as '%s'",
+ dns_zone_log(zone, ISC_LOG_WARNING, "saved '%s' as '%s'",
path, buf);
cleanup:
diff --git a/lib/isc/Makefile.in b/lib/isc/Makefile.in
index 71e4252..82afe5f 100644
--- a/lib/isc/Makefile.in
+++ b/lib/isc/Makefile.in
@@ -1,4 +1,4 @@
-# Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
# Copyright (C) 1998-2003 Internet Software Consortium.
#
# Permission to use, copy, modify, and/or distribute this software for any
@@ -13,7 +13,7 @@
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-# $Id: Makefile.in,v 1.81.18.8 2007/09/14 23:46:18 tbox Exp $
+# $Id: Makefile.in,v 1.81.18.10 2008/06/24 23:45:55 tbox Exp $
srcdir = @srcdir@
VPATH = @srcdir@
@@ -56,7 +56,7 @@ OBJS = @ISC_EXTRA_OBJS@ \
hash.@O@ heap.@O@ hex.@O@ hmacmd5.@O@ hmacsha.@O@\
lex.@O@ lfsr.@O@ lib.@O@ log.@O@ md5.@O@ \
mem.@O@ mutexblock.@O@ netaddr.@O@ netscope.@O@ ondestroy.@O@ \
- parseint.@O@ quota.@O@ random.@O@ \
+ parseint.@O@ portset.@O@ quota.@O@ random.@O@ \
ratelimiter.@O@ refcount.@O@ region.@O@ result.@O@ rwlock.@O@ \
serial.@O@ sha1.@O@ sha2.@O@ sockaddr.@O@ string.@O@ \
strtoul.@O@ symtab.@O@ task.@O@ taskpool.@O@ timer.@O@ \
@@ -69,7 +69,7 @@ SRCS = @ISC_EXTRA_SRCS@ \
heap.c hex.c hmacmd5.c hmacsha.c \
lex.c lfsr.c lib.c log.c \
md5.c mem.c mutexblock.c netaddr.c netscope.c ondestroy.c \
- parseint.c quota.c random.c \
+ parseint.c portset.c quota.c random.c \
ratelimiter.c refcount.c region.c result.c rwlock.c \
serial.c sha1.c sha2.c sockaddr.c string.c strtoul.c symtab.c \
task.c taskpool.c timer.c version.c
diff --git a/lib/isc/api b/lib/isc/api
index f40dfe0..0b8a3bc 100644
--- a/lib/isc/api
+++ b/lib/isc/api
@@ -1,3 +1,3 @@
-LIBINTERFACE = 35
-LIBREVISION = 0
+LIBINTERFACE = 36
+LIBREVISION = 2
LIBAGE = 0
diff --git a/lib/isc/assertions.c b/lib/isc/assertions.c
index b3fcf4a..3eb27e0 100644
--- a/lib/isc/assertions.c
+++ b/lib/isc/assertions.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1997-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: assertions.c,v 1.17.18.2 2005/04/29 00:16:44 marka Exp $ */
+/* $Id: assertions.c,v 1.17.18.4 2008/10/15 23:46:06 tbox Exp $ */
/*! \file */
@@ -30,6 +30,7 @@
/*%
* Forward.
*/
+/* coverity[+kill] */
static void
default_callback(const char *, int, isc_assertiontype_t, const char *);
diff --git a/lib/isc/include/isc/assertions.h b/lib/isc/include/isc/assertions.h
index c1e68a1..fcf0eb8 100644
--- a/lib/isc/include/isc/assertions.h
+++ b/lib/isc/include/isc/assertions.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1997-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -16,7 +16,7 @@
*/
/*
- * $Id: assertions.h,v 1.18.18.2 2005/04/29 00:16:52 marka Exp $
+ * $Id: assertions.h,v 1.18.18.4 2008/10/15 23:46:06 tbox Exp $
*/
/*! \file assertions.h
*/
@@ -40,6 +40,7 @@ typedef enum {
typedef void (*isc_assertioncallback_t)(const char *, int, isc_assertiontype_t,
const char *);
+/* coverity[+kill] */
LIBISC_EXTERNAL_DATA extern isc_assertioncallback_t isc_assertion_failed;
void
@@ -48,14 +49,14 @@ isc_assertion_setcallback(isc_assertioncallback_t);
const char *
isc_assertion_typetotext(isc_assertiontype_t type);
-#ifdef ISC_CHECK_ALL
+#if defined(ISC_CHECK_ALL) || defined(__COVERITY__)
#define ISC_CHECK_REQUIRE 1
#define ISC_CHECK_ENSURE 1
#define ISC_CHECK_INSIST 1
#define ISC_CHECK_INVARIANT 1
#endif
-#ifdef ISC_CHECK_NONE
+#if defined(ISC_CHECK_NONE) && !defined(__COVERITY__)
#define ISC_CHECK_REQUIRE 0
#define ISC_CHECK_ENSURE 0
#define ISC_CHECK_INSIST 0
diff --git a/lib/isc/include/isc/lex.h b/lib/isc/include/isc/lex.h
index 8c6624a..cb9cc18 100644
--- a/lib/isc/include/isc/lex.h
+++ b/lib/isc/include/isc/lex.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: lex.h,v 1.30.18.3 2005/06/04 00:39:05 marka Exp $ */
+/* $Id: lex.h,v 1.30.18.5 2008/05/30 23:46:01 tbox Exp $ */
#ifndef ISC_LEX_H
#define ISC_LEX_H 1
@@ -86,7 +86,7 @@ ISC_LANG_BEGINDECLS
#define ISC_LEXOPT_DNSMULTILINE 0x20 /*%< Handle '(' and ')'. */
#define ISC_LEXOPT_NOMORE 0x40 /*%< Want "no more" token. */
-#define ISC_LEXOPT_CNUMBER 0x80 /*%< Regognize octal and hex. */
+#define ISC_LEXOPT_CNUMBER 0x80 /*%< Recognize octal and hex. */
#define ISC_LEXOPT_ESCAPE 0x100 /*%< Recognize escapes. */
#define ISC_LEXOPT_QSTRINGMULTILINE 0x200 /*%< Allow multiline "" strings */
#define ISC_LEXOPT_OCTAL 0x400 /*%< Expect a octal number. */
diff --git a/lib/isc/include/isc/mem.h b/lib/isc/include/isc/mem.h
index dc68bcb..2c3c54e 100644
--- a/lib/isc/include/isc/mem.h
+++ b/lib/isc/include/isc/mem.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2006, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1997-2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: mem.h,v 1.59.18.9 2006/01/04 23:50:23 marka Exp $ */
+/* $Id: mem.h,v 1.59.18.11 2008/02/07 23:45:56 tbox Exp $ */
#ifndef ISC_MEM_H
#define ISC_MEM_H 1
@@ -156,7 +156,7 @@ LIBISC_EXTERNAL_DATA extern unsigned int isc_mem_debugging;
#define isc_mem_strdup(c, p) isc__mem_strdup((c), (p) _ISC_MEM_FILELINE)
#define isc_mempool_get(c) isc__mempool_get((c) _ISC_MEM_FILELINE)
-/*%
+/*%
* isc_mem_putanddetach() is a convienence function for use where you
* have a structure with an attached memory context.
*
@@ -215,7 +215,7 @@ LIBISC_EXTERNAL_DATA extern unsigned int isc_mem_debugging;
#endif
/*@{*/
-isc_result_t
+isc_result_t
isc_mem_create(size_t max_size, size_t target_size,
isc_mem_t **mctxp);
@@ -223,12 +223,12 @@ isc_result_t
isc_mem_create2(size_t max_size, size_t target_size,
isc_mem_t **mctxp, unsigned int flags);
-isc_result_t
+isc_result_t
isc_mem_createx(size_t max_size, size_t target_size,
isc_memalloc_t memalloc, isc_memfree_t memfree,
void *arg, isc_mem_t **mctxp);
-isc_result_t
+isc_result_t
isc_mem_createx2(size_t max_size, size_t target_size,
isc_memalloc_t memalloc, isc_memfree_t memfree,
void *arg, isc_mem_t **mctxp, unsigned int flags);
@@ -265,9 +265,9 @@ isc_mem_createx2(size_t max_size, size_t target_size,
/*@}*/
/*@{*/
-void
+void
isc_mem_attach(isc_mem_t *, isc_mem_t **);
-void
+void
isc_mem_detach(isc_mem_t **);
/*!<
* \brief Attach to / detach from a memory context.
@@ -275,7 +275,7 @@ isc_mem_detach(isc_mem_t **);
* This is intended for applications that use multiple memory contexts
* in such a way that it is not obvious when the last allocations from
* a given context has been freed and destroying the context is safe.
- *
+ *
* Most applications do not need to call these functions as they can
* simply create a single memory context at the beginning of main()
* and destroy it at the end of main(), thereby guaranteeing that it
@@ -283,13 +283,13 @@ isc_mem_detach(isc_mem_t **);
*/
/*@}*/
-void
+void
isc_mem_destroy(isc_mem_t **);
/*%<
* Destroy a memory context.
*/
-isc_result_t
+isc_result_t
isc_mem_ondestroy(isc_mem_t *ctx,
isc_task_t *task,
isc_event_t **event);
@@ -298,13 +298,13 @@ isc_mem_ondestroy(isc_mem_t *ctx,
* been successfully destroyed.
*/
-void
+void
isc_mem_stats(isc_mem_t *mctx, FILE *out);
/*%<
* Print memory usage statistics for 'mctx' on the stream 'out'.
*/
-void
+void
isc_mem_setdestroycheck(isc_mem_t *mctx,
isc_boolean_t on);
/*%<
@@ -313,9 +313,9 @@ isc_mem_setdestroycheck(isc_mem_t *mctx,
*/
/*@{*/
-void
+void
isc_mem_setquota(isc_mem_t *, size_t);
-size_t
+size_t
isc_mem_getquota(isc_mem_t *);
/*%<
* Set/get the memory quota of 'mctx'. This is a hard limit
@@ -324,7 +324,7 @@ isc_mem_getquota(isc_mem_t *);
*/
/*@}*/
-size_t
+size_t
isc_mem_inuse(isc_mem_t *mctx);
/*%<
* Get an estimate of the number of memory in use in 'mctx', in bytes.
@@ -336,13 +336,29 @@ void
isc_mem_setwater(isc_mem_t *mctx, isc_mem_water_t water, void *water_arg,
size_t hiwater, size_t lowater);
/*%<
- * Set high and low water marks for this memory context.
- *
- * When the memory
- * usage of 'mctx' exceeds 'hiwater', '(water)(water_arg, #ISC_MEM_HIWATER)'
- * will be called. When the usage drops below 'lowater', 'water' will
- * again be called, this time with #ISC_MEM_LOWATER.
- *
+ * Set high and low water marks for this memory context.
+ *
+ * When the memory usage of 'mctx' exceeds 'hiwater',
+ * '(water)(water_arg, #ISC_MEM_HIWATER)' will be called. 'water' needs to
+ * call isc_mem_waterack() with #ISC_MEM_HIWATER to acknowlege the state
+ * change. 'water' may be called multiple times.
+ *
+ * When the usage drops below 'lowater', 'water' will again be called, this
+ * time with #ISC_MEM_LOWATER. 'water' need to calls isc_mem_waterack() with
+ * #ISC_MEM_LOWATER to acknowlege the change.
+ *
+ * static void
+ * water(void *arg, int mark) {
+ * struct foo *foo = arg;
+ *
+ * LOCK(&foo->marklock);
+ * if (foo->mark != mark) {
+ * foo->mark = mark;
+ * ....
+ * isc_mem_waterack(foo->mctx, mark);
+ * }
+ * UNLOCK(&foo->marklock);
+ * }
* If 'water' is NULL then 'water_arg', 'hi_water' and 'lo_water' are
* ignored and the state is reset.
*
@@ -353,6 +369,12 @@ isc_mem_setwater(isc_mem_t *mctx, isc_mem_water_t water, void *water_arg,
*/
void
+isc_mem_waterack(isc_mem_t *ctx, int mark);
+/*%<
+ * Called to acknowledge changes in signalled by calls to 'water'.
+ */
+
+void
isc_mem_printactive(isc_mem_t *mctx, FILE *file);
/*%<
* Print to 'file' all active memory in 'mctx'.
@@ -520,22 +542,22 @@ isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit);
/*
* Pseudo-private functions for use via macros. Do not call directly.
*/
-void *
+void *
isc__mem_get(isc_mem_t *, size_t _ISC_MEM_FLARG);
-void
+void
isc__mem_putanddetach(isc_mem_t **, void *,
size_t _ISC_MEM_FLARG);
-void
+void
isc__mem_put(isc_mem_t *, void *, size_t _ISC_MEM_FLARG);
-void *
+void *
isc__mem_allocate(isc_mem_t *, size_t _ISC_MEM_FLARG);
-void
+void
isc__mem_free(isc_mem_t *, void * _ISC_MEM_FLARG);
-char *
+char *
isc__mem_strdup(isc_mem_t *, const char *_ISC_MEM_FLARG);
-void *
+void *
isc__mempool_get(isc_mempool_t * _ISC_MEM_FLARG);
-void
+void
isc__mempool_put(isc_mempool_t *, void * _ISC_MEM_FLARG);
ISC_LANG_ENDDECLS
diff --git a/lib/isc/include/isc/msgs.h b/lib/isc/include/isc/msgs.h
index 97b2108..0970647 100644
--- a/lib/isc/include/isc/msgs.h
+++ b/lib/isc/include/isc/msgs.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: msgs.h,v 1.9.18.2 2005/04/29 00:16:59 marka Exp $ */
+/* $Id: msgs.h,v 1.9.18.4 2008/08/08 06:27:56 tbox Exp $ */
#ifndef ISC_MSGS_H
#define ISC_MSGS_H 1
@@ -57,7 +57,7 @@
/*@{*/
/*!
- * Message numbers
+ * Message numbers
* are only required to be unique per message set,
* but are unique throughout the entire catalog to not be as confusing when
* debugging.
@@ -153,7 +153,10 @@
#define ISC_MSG_ACCEPTRETURNED 1418 /*%< accept() returned %d/%s */
#define ISC_MSG_TOOMANYFDS 1419 /*%< %s: too many open file descriptors */
#define ISC_MSG_ZEROPORT 1420 /*%< dropping source port zero packet */
-#define ISC_MSG_FILTER 1420 /*%< setsockopt(SO_ACCEPTFILTER): %s */
+#define ISC_MSG_FILTER 1421 /*%< setsockopt(SO_ACCEPTFILTER): %s */
+
+#define ISC_MSG_TOOMANYHANDLES 1422 /*%< %s: too many open WSA event handles: %s */
+
#define ISC_MSG_AWAKE 1502 /*%< "awake" */
#define ISC_MSG_WORKING 1503 /*%< "working" */
diff --git a/lib/isc/include/isc/platform.h.in b/lib/isc/include/isc/platform.h.in
index 0531edf..afcd4df 100644
--- a/lib/isc/include/isc/platform.h.in
+++ b/lib/isc/include/isc/platform.h.in
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: platform.h.in,v 1.34.18.9 2007/09/13 05:04:01 each Exp $ */
+/* $Id: platform.h.in,v 1.34.18.11 2008/06/24 23:45:55 tbox Exp $ */
#ifndef ISC_PLATFORM_H
#define ISC_PLATFORM_H 1
@@ -140,6 +140,21 @@
*/
@ISC_PLATFORM_FIXIN6ISADDR@
+/*! \brief
+ * Define if the system supports kqueue multiplexing
+ */
+@ISC_PLATFORM_HAVEKQUEUE@
+
+/*! \brief
+ * Define if the system supports epoll multiplexing
+ */
+@ISC_PLATFORM_HAVEEPOLL@
+
+/*! \brief
+ * Define if the system supports /dev/poll multiplexing
+ */
+@ISC_PLATFORM_HAVEDEVPOLL@
+
/*
*** Printing.
***/
@@ -224,19 +239,19 @@
/*
* If the "xadd" operation is available on this architecture,
- * ISC_PLATFORM_HAVEXADD will be defined.
+ * ISC_PLATFORM_HAVEXADD will be defined.
*/
@ISC_PLATFORM_HAVEXADD@
/*
* If the "atomic swap" operation is available on this architecture,
- * ISC_PLATFORM_HAVEATOMICSTORE" will be defined.
+ * ISC_PLATFORM_HAVEATOMICSTORE" will be defined.
*/
@ISC_PLATFORM_HAVEATOMICSTORE@
/*
* If the "compare-and-exchange" operation is available on this architecture,
- * ISC_PLATFORM_HAVECMPXCHG will be defined.
+ * ISC_PLATFORM_HAVECMPXCHG will be defined.
*/
@ISC_PLATFORM_HAVECMPXCHG@
diff --git a/lib/isc/include/isc/portset.h b/lib/isc/include/isc/portset.h
new file mode 100644
index 0000000..6396e5c
--- /dev/null
+++ b/lib/isc/include/isc/portset.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2008 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: portset.h,v 1.3.4.1 2008/06/24 03:42:10 marka Exp $ */
+
+/*! \file isc/portset.h
+ * \brief Transport Protocol Port Manipuration Module
+ *
+ * This module provides simple utilities to handle a set of transport protocol
+ * (UDP or TCP) port numbers, e.g., for creating an ACL list. An isc_portset_t
+ * object is an opaque instance of a port set, for which the user can add or
+ * remove a specific port or a range of consecutive ports. This object is
+ * expected to be used as a temporary work space only, and does not protect
+ * simultaneous access from multiple threads. Therefore it must not be stored
+ * in a place that can be accessed from multiple threads.
+ */
+
+#ifndef ISC_PORTSET_H
+#define ISC_PORTSET_H 1
+
+/***
+ *** Imports
+ ***/
+
+#include <isc/net.h>
+
+/***
+ *** Functions
+ ***/
+
+ISC_LANG_BEGINDECLS
+
+isc_result_t
+isc_portset_create(isc_mem_t *mctx, isc_portset_t **portsetp);
+/*%<
+ * Create a port set and initialize it as an empty set.
+ *
+ * Requires:
+ *\li 'mctx' to be valid.
+ *\li 'portsetp' to be non NULL and '*portsetp' to be NULL;
+ *
+ * Returns:
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOMEMORY
+ */
+
+void
+isc_portset_destroy(isc_mem_t *mctx, isc_portset_t **portsetp);
+/*%<
+ * Destroy a port set.
+ *
+ * Requires:
+ *\li 'mctx' to be valid and must be the same context given when the port set
+ * was created.
+ *\li '*portsetp' to be a valid set.
+ */
+
+isc_boolean_t
+isc_portset_isset(isc_portset_t *portset, in_port_t port);
+/*%<
+ * Test whether the given port is stored in the portset.
+ *
+ * Requires:
+ *\li 'portset' to be a valid set.
+ *
+ * Returns
+ * \li #ISC_TRUE if the port is found, ISC_FALSE otherwise.
+ */
+
+unsigned int
+isc_portset_nports(isc_portset_t *portset);
+/*%<
+ * Provides the number of ports stored in the given portset.
+ *
+ * Requires:
+ *\li 'portset' to be a valid set.
+ *
+ * Returns
+ * \li the number of ports stored in portset.
+ */
+
+void
+isc_portset_add(isc_portset_t *portset, in_port_t port);
+/*%<
+ * Add the given port to the portset. The port may or may not be stored in
+ * the portset.
+ *
+ * Requires:
+ *\li 'portlist' to be valid.
+ */
+
+void
+isc_portset_remove(isc_portset_t *portset, in_port_t port);
+/*%<
+ * Remove the given port to the portset. The port may or may not be stored in
+ * the portset.
+ *
+ * Requires:
+ *\li 'portlist' to be valid.
+ */
+
+void
+isc_portset_addrange(isc_portset_t *portset, in_port_t port_lo,
+ in_port_t port_hi);
+/*%<
+ * Add a subset of [port_lo, port_hi] (inclusive) to the portset. Ports in the
+ * subset may or may not be stored in portset.
+ *
+ * Requires:
+ *\li 'portlist' to be valid.
+ *\li port_lo <= port_hi
+ */
+
+void
+isc_portset_removerange(isc_portset_t *portset, in_port_t port_lo,
+ in_port_t port_hi);
+/*%<
+ * Subtract a subset of [port_lo, port_hi] (inclusive) from the portset. Ports
+ * in the subset may or may not be stored in portset.
+ *
+ * Requires:
+ *\li 'portlist' to be valid.
+ *\li port_lo <= port_hi
+ */
+
+ISC_LANG_ENDDECLS
+
+#endif /* ISC_NETADDR_H */
diff --git a/lib/isc/include/isc/resource.h b/lib/isc/include/isc/resource.h
index 18cd0ad..8c33c89 100644
--- a/lib/isc/include/isc/resource.h
+++ b/lib/isc/include/isc/resource.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: resource.h,v 1.5.18.2.52.2 2008/07/23 23:48:17 tbox Exp $ */
+/* $Id: resource.h,v 1.5.18.4 2008/08/01 23:45:58 tbox Exp $ */
#ifndef ISC_RESOURCE_H
#define ISC_RESOURCE_H 1
@@ -82,16 +82,13 @@ isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value);
*/
isc_result_t
-isc_resource_curlimit(isc_resource_t resource, isc_resourcevalue_t *value);
-/*
- * Get the current limit on a resource.
- *
- * Requires:
- * 'resource' is a valid member of the isc_resource_t enumeration.
+isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value);
+/*%<
+ * Same as isc_resource_getlimit(), but returns the current (soft) limit.
*
* Returns:
- * ISC_R_SUCCESS Success.
- * ISC_R_NOTIMPLEMENTED 'resource' is not a type known by the OS.
+ *\li #ISC_R_SUCCESS Success.
+ *\li #ISC_R_NOTIMPLEMENTED 'resource' is not a type known by the OS.
*/
ISC_LANG_ENDDECLS
diff --git a/lib/isc/include/isc/socket.h b/lib/isc/include/isc/socket.h
index 951a063..a9a22c8 100644
--- a/lib/isc/include/isc/socket.h
+++ b/lib/isc/include/isc/socket.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: socket.h,v 1.57.18.6.46.4 2008/07/23 23:16:43 marka Exp $ */
+/* $Id: socket.h,v 1.57.18.15 2008/09/04 08:03:08 marka Exp $ */
#ifndef ISC_SOCKET_H
#define ISC_SOCKET_H 1
@@ -318,8 +318,53 @@ isc_socket_detach(isc_socket_t **socketp);
*/
isc_result_t
+isc_socket_open(isc_socket_t *sock);
+/*%<
+ * Open a new socket file descriptor of the given socket structure. It simply
+ * opens a new descriptor; all of the other parameters including the socket
+ * type are inherited from the existing socket. This function is provided to
+ * avoid overhead of destroying and creating sockets when many short-lived
+ * sockets are frequently opened and closed. When the efficiency is not an
+ * issue, it should be safer to detach the unused socket and re-create a new
+ * one. This optimization may not be available for some systems, in which
+ * case this function will return ISC_R_NOTIMPLEMENTED and must not be used.
+ *
+ * Requires:
+ *
+ * \li there must be no other reference to this socket.
+ *
+ * \li 'socket' is a valid and previously closed by isc_socket_close()
+ *
+ * Returns:
+ * Same as isc_socket_create().
+ * \li ISC_R_NOTIMPLEMENTED
+ */
+
+isc_result_t
+isc_socket_close(isc_socket_t *sock);
+/*%<
+ * Close a socket file descriptor of the given socket structure. This function
+ * is provided as an alternative to destroying an unused socket when overhead
+ * destroying/re-creating sockets can be significant, and is expected to be
+ * used with isc_socket_open(). This optimization may not be available for some
+ * systems, in which case this function will return ISC_R_NOTIMPLEMENTED and
+ * must not be used.
+ *
+ * Requires:
+ *
+ * \li The socket must have a valid descriptor.
+ *
+ * \li There must be no other reference to this socket.
+ *
+ * \li There must be no pending I/O requests.
+ *
+ * Returns:
+ * \li #ISC_R_NOTIMPLEMENTED
+ */
+
+isc_result_t
isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *addressp,
- unsigned int options);
+ unsigned int options);
/*%<
* Bind 'socket' to '*addressp'.
*
@@ -644,8 +689,15 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region,
isc_result_t
isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp);
+
+isc_result_t
+isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
+ unsigned int maxsocks);
/*%<
- * Create a socket manager.
+ * Create a socket manager. If "maxsocks" is non-zero, it specifies the
+ * maximum number of sockets that the created manager should handle.
+ * isc_socketmgr_create() is equivalent of isc_socketmgr_create2() with
+ * "maxsocks" being zero.
*
* Notes:
*
@@ -666,6 +718,23 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp);
*\li #ISC_R_SUCCESS
*\li #ISC_R_NOMEMORY
*\li #ISC_R_UNEXPECTED
+ *\li #ISC_R_NOTIMPLEMENTED
+ */
+
+isc_result_t
+isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp);
+/*%<
+ * Returns in "*nsockp" the maximum number of sockets this manager may open.
+ *
+ * Requires:
+ *
+ *\li '*manager' is a valid isc_socketmgr_t.
+ *\li 'nsockp' is not NULL.
+ *
+ * Returns:
+ *
+ *\li #ISC_R_SUCCESS
+ *\li #ISC_R_NOTIMPLEMENTED
*/
void
@@ -738,7 +807,7 @@ isc_socket_cleanunix(isc_sockaddr_t *addr, isc_boolean_t active);
isc_result_t
isc_socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm,
- isc_uint32_t owner, isc_uint32_t group);
+ isc_uint32_t owner, isc_uint32_t group);
/*%<
* Set ownership and file permissions on the UNIX domain socket.
*
diff --git a/lib/isc/include/isc/timer.h b/lib/isc/include/isc/timer.h
index 6e78be9..7a7f614 100644
--- a/lib/isc/include/isc/timer.h
+++ b/lib/isc/include/isc/timer.h
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: timer.h,v 1.31.18.3.52.2 2008/07/24 23:48:09 tbox Exp $ */
+/* $Id: timer.h,v 1.31.18.5 2008/06/24 23:45:55 tbox Exp $ */
#ifndef ISC_TIMER_H
#define ISC_TIMER_H 1
diff --git a/lib/isc/include/isc/types.h b/lib/isc/include/isc/types.h
index 35a0be7..b501b2c 100644
--- a/lib/isc/include/isc/types.h
+++ b/lib/isc/include/isc/types.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: types.h,v 1.35.18.2 2005/04/29 00:17:04 marka Exp $ */
+/* $Id: types.h,v 1.35.18.4 2008/06/24 23:45:55 tbox Exp $ */
#ifndef ISC_TYPES_H
#define ISC_TYPES_H 1
@@ -65,6 +65,7 @@ typedef struct isc_mempool isc_mempool_t; /*%< Memory Pool */
typedef struct isc_msgcat isc_msgcat_t; /*%< Message Catalog */
typedef struct isc_ondestroy isc_ondestroy_t; /*%< On Destroy */
typedef struct isc_netaddr isc_netaddr_t; /*%< Net Address */
+typedef struct isc_portset isc_portset_t; /*%< Port Set */
typedef struct isc_quota isc_quota_t; /*%< Quota */
typedef struct isc_random isc_random_t; /*%< Random */
typedef struct isc_ratelimiter isc_ratelimiter_t; /*%< Rate Limiter */
diff --git a/lib/isc/mem.c b/lib/isc/mem.c
index aec6118..408770d 100644
--- a/lib/isc/mem.c
+++ b/lib/isc/mem.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1997-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: mem.c,v 1.116.18.18 2007/10/30 23:31:43 marka Exp $ */
+/* $Id: mem.c,v 1.116.18.21 2008/02/07 23:45:56 tbox Exp $ */
/*! \file */
@@ -193,7 +193,7 @@ struct isc_mempool {
if ((isc_mem_debugging & (ISC_MEM_DEBUGTRACE | \
ISC_MEM_DEBUGRECORD)) != 0 && \
b != NULL) \
- add_trace_entry(a, b, c, d, e); \
+ add_trace_entry(a, b, c, d, e); \
} while (0)
#define DELETE_TRACE(a, b, c, d, e) delete_trace_entry(a, b, c, d, e)
@@ -314,7 +314,7 @@ delete_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size,
static inline size_t
rmsize(size_t size) {
/*
- * round down to ALIGNMENT_SIZE
+ * round down to ALIGNMENT_SIZE
*/
return (size & (~(ALIGNMENT_SIZE - 1)));
}
@@ -603,7 +603,7 @@ mem_get(isc_mem_t *ctx, size_t size) {
ret = (ctx->memalloc)(ctx->arg, size);
if (ret == NULL)
- ctx->memalloc_failures++;
+ ctx->memalloc_failures++;
#if ISC_MEM_FILL
if (ret != NULL)
@@ -705,7 +705,7 @@ isc_mem_createx(size_t init_max_size, size_t target_size,
{
return (isc_mem_createx2(init_max_size, target_size, memalloc, memfree,
arg, ctxp, ISC_MEMFLAG_DEFAULT));
-
+
}
isc_result_t
@@ -882,7 +882,7 @@ destroy(isc_mem_t *ctx) {
dl != NULL;
dl = ISC_LIST_HEAD(ctx->debuglist[i])) {
ISC_LIST_UNLINK(ctx->debuglist[i],
- dl, link);
+ dl, link);
free(dl);
}
}
@@ -907,7 +907,8 @@ destroy(isc_mem_t *ctx) {
for (i = 0; i < ctx->basic_table_count; i++)
(ctx->memfree)(ctx->arg, ctx->basic_table[i]);
(ctx->memfree)(ctx->arg, ctx->freelists);
- (ctx->memfree)(ctx->arg, ctx->basic_table);
+ if (ctx->basic_table != NULL)
+ (ctx->memfree)(ctx->arg, ctx->basic_table);
}
ondest = ctx->ondestroy;
@@ -1085,7 +1086,6 @@ isc__mem_get(isc_mem_t *ctx, size_t size FLARG) {
ADD_TRACE(ctx, ptr, size, file, line);
if (ctx->hi_water != 0U && !ctx->hi_called &&
ctx->inuse > ctx->hi_water) {
- ctx->hi_called = ISC_TRUE;
call_water = ISC_TRUE;
}
if (ctx->inuse > ctx->maxinuse) {
@@ -1141,10 +1141,8 @@ isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG)
* when the context was pushed over hi_water but then had
* isc_mem_setwater() called with 0 for hi_water and lo_water.
*/
- if (ctx->hi_called &&
+ if (ctx->hi_called &&
(ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) {
- ctx->hi_called = ISC_FALSE;
-
if (ctx->water != NULL)
call_water = ISC_TRUE;
}
@@ -1154,6 +1152,18 @@ isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG)
(ctx->water)(ctx->water_arg, ISC_MEM_LOWATER);
}
+void
+isc_mem_waterack(isc_mem_t *ctx, int flag) {
+ REQUIRE(VALID_CONTEXT(ctx));
+
+ MCTXLOCK(ctx, &ctx->lock);
+ if (flag == ISC_MEM_LOWATER)
+ ctx->hi_called = ISC_FALSE;
+ else if (flag == ISC_MEM_HIWATER)
+ ctx->hi_called = ISC_TRUE;
+ MCTXUNLOCK(ctx, &ctx->lock);
+}
+
#if ISC_MEM_TRACKLINES
static void
print_active(isc_mem_t *mctx, FILE *out) {
@@ -1169,11 +1179,11 @@ print_active(isc_mem_t *mctx, FILE *out) {
"memory allocations:\n"));
found = ISC_FALSE;
format = isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
- ISC_MSG_PTRFILELINE,
+ ISC_MSG_PTRFILELINE,
"\tptr %p size %u file %s line %u\n");
for (i = 0; i <= mctx->max_size; i++) {
dl = ISC_LIST_HEAD(mctx->debuglist[i]);
-
+
if (dl != NULL)
found = ISC_TRUE;
@@ -1371,7 +1381,7 @@ isc__mem_free(isc_mem_t *ctx, void *ptr FLARG) {
* when the context was pushed over hi_water but then had
* isc_mem_setwater() called with 0 for hi_water and lo_water.
*/
- if (ctx->hi_called &&
+ if (ctx->hi_called &&
(ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) {
ctx->hi_called = ISC_FALSE;
@@ -1461,7 +1471,7 @@ isc_mem_inuse(isc_mem_t *ctx) {
void
isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
- size_t hiwater, size_t lowater)
+ size_t hiwater, size_t lowater)
{
isc_boolean_t callwater = ISC_FALSE;
isc_mem_water_t oldwater;
@@ -1492,7 +1502,7 @@ isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
ctx->hi_called = ISC_FALSE;
}
MCTXUNLOCK(ctx, &ctx->lock);
-
+
if (callwater && oldwater != NULL)
(oldwater)(oldwater_arg, ISC_MEM_LOWATER);
}
@@ -1931,7 +1941,7 @@ isc_mem_printallactive(FILE *file) {
#endif
}
-void
+void
isc_mem_checkdestroyed(FILE *file) {
RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
diff --git a/lib/isc/portset.c b/lib/isc/portset.c
new file mode 100644
index 0000000..0265c89
--- /dev/null
+++ b/lib/isc/portset.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2008 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: portset.c,v 1.2.4.3 2008/06/24 23:27:11 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <isc/mem.h>
+#include <isc/portset.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#define ISC_PORTSET_BUFSIZE (65536 / (sizeof(isc_uint32_t) * 8))
+
+/*%
+ * Internal representation of portset. It's an array of 32-bit integers, each
+ * bit corresponding to a single port in the ascending order. For example,
+ * the second most significant bit of buf[0] corresponds to port 1.
+ */
+struct isc_portset {
+ unsigned int nports; /*%< number of ports in the set */
+ isc_uint32_t buf[ISC_PORTSET_BUFSIZE];
+};
+
+static inline isc_boolean_t
+portset_isset(isc_portset_t *portset, in_port_t port) {
+ return (ISC_TF((portset->buf[port >> 5] & (1 << (port & 31))) != 0));
+}
+
+static inline void
+portset_add(isc_portset_t *portset, in_port_t port) {
+ if (!portset_isset(portset, port)) {
+ portset->nports++;
+ portset->buf[port >> 5] |= (1 << (port & 31));
+ }
+}
+
+static inline void
+portset_remove(isc_portset_t *portset, in_port_t port) {
+ if (portset_isset(portset, port)) {
+ portset->nports--;
+ portset->buf[port >> 5] &= ~(1 << (port & 31));
+ }
+}
+
+isc_result_t
+isc_portset_create(isc_mem_t *mctx, isc_portset_t **portsetp) {
+ isc_portset_t *portset;
+
+ REQUIRE(portsetp != NULL && *portsetp == NULL);
+
+ portset = isc_mem_get(mctx, sizeof(*portset));
+ if (portset == NULL)
+ return (ISC_R_NOMEMORY);
+
+ /* Make the set 'empty' by default */
+ memset(portset, 0, sizeof(*portset));
+ *portsetp = portset;
+
+ return (ISC_R_SUCCESS);
+}
+
+void
+isc_portset_destroy(isc_mem_t *mctx, isc_portset_t **portsetp) {
+ isc_portset_t *portset;
+
+ REQUIRE(portsetp != NULL);
+ portset = *portsetp;
+
+ isc_mem_put(mctx, portset, sizeof(*portset));
+}
+
+isc_boolean_t
+isc_portset_isset(isc_portset_t *portset, in_port_t port) {
+ REQUIRE(portset != NULL);
+
+ return (portset_isset(portset, port));
+}
+
+unsigned int
+isc_portset_nports(isc_portset_t *portset) {
+ REQUIRE(portset != NULL);
+
+ return (portset->nports);
+}
+
+void
+isc_portset_add(isc_portset_t *portset, in_port_t port) {
+ REQUIRE(portset != NULL);
+
+ portset_add(portset, port);
+}
+
+void
+isc_portset_remove(isc_portset_t *portset, in_port_t port) {
+ portset_remove(portset, port);
+}
+
+void
+isc_portset_addrange(isc_portset_t *portset, in_port_t port_lo,
+ in_port_t port_hi)
+{
+ in_port_t p;
+
+ REQUIRE(portset != NULL);
+ REQUIRE(port_lo <= port_hi);
+
+ p = port_lo;
+ do {
+ portset_add(portset, p);
+ } while (p++ < port_hi);
+}
+
+void
+isc_portset_removerange(isc_portset_t *portset, in_port_t port_lo,
+ in_port_t port_hi)
+{
+ in_port_t p;
+
+ REQUIRE(portset != NULL);
+ REQUIRE(port_lo <= port_hi);
+
+ p = port_lo;
+ do {
+ portset_remove(portset, p);
+ } while (p++ < port_hi);
+}
diff --git a/lib/isc/print.c b/lib/isc/print.c
index 59c528b..191ad24 100644
--- a/lib/isc/print.c
+++ b/lib/isc/print.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2006, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: print.c,v 1.27.18.3 2006/04/17 18:27:33 explorer Exp $ */
+/* $Id: print.c,v 1.27.18.5 2008/02/18 23:46:01 tbox Exp $ */
/*! \file */
@@ -246,8 +246,24 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
head = "";
tmpui = tmpi;
}
- sprintf(buf, "%" ISC_PRINT_QUADFORMAT "u",
- tmpui);
+ if (tmpui <= 0xffffffffU)
+ sprintf(buf, "%lu",
+ (unsigned long)tmpui);
+ else {
+ unsigned long mid;
+ unsigned long lo;
+ unsigned long hi;
+ lo = tmpui % 1000000000;
+ tmpui /= 1000000000;
+ mid = tmpui % 1000000000;
+ hi = tmpui / 1000000000;
+ if (hi != 0)
+ sprintf(buf, "%lu", hi);
+ else
+ buf[0] = '\n';
+ sprintf(buf + strlen(buf), "%lu", mid);
+ sprintf(buf + strlen(buf), "%lu", lo);
+ }
goto printint;
case 'o':
if (q)
@@ -256,10 +272,29 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
tmpui = va_arg(ap, long int);
else
tmpui = va_arg(ap, int);
- sprintf(buf,
- alt ? "%#" ISC_PRINT_QUADFORMAT "o"
- : "%" ISC_PRINT_QUADFORMAT "o",
- tmpui);
+ if (tmpui <= 0xffffffffU)
+ sprintf(buf, alt ? "%#lo" : "%lo",
+ (unsigned long)tmpui);
+ else {
+ unsigned long mid;
+ unsigned long lo;
+ unsigned long hi;
+ lo = tmpui % 010000000000;
+ tmpui /= 010000000000;
+ mid = tmpui % 010000000000;
+ hi = tmpui / 010000000000;
+ if (hi != 0) {
+ sprintf(buf,
+ alt ? "%#lo" : "%lo",
+ hi);
+ sprintf(buf + strlen(buf),
+ "%lo", mid);
+ } else
+ sprintf(buf,
+ alt ? "%#lo" : "%lo",
+ mid);
+ sprintf(buf + strlen(buf), "%lo", lo);
+ }
goto printint;
case 'u':
if (q)
@@ -268,8 +303,24 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
tmpui = va_arg(ap, unsigned long int);
else
tmpui = va_arg(ap, unsigned int);
- sprintf(buf, "%" ISC_PRINT_QUADFORMAT "u",
- tmpui);
+ if (tmpui <= 0xffffffffU)
+ sprintf(buf, "%lu",
+ (unsigned long)tmpui);
+ else {
+ unsigned long mid;
+ unsigned long lo;
+ unsigned long hi;
+ lo = tmpui % 1000000000;
+ tmpui /= 1000000000;
+ mid = tmpui % 1000000000;
+ hi = tmpui / 1000000000;
+ if (hi != 0)
+ sprintf(buf, "%lu", hi);
+ else
+ buf[0] = '\n';
+ sprintf(buf + strlen(buf), "%lu", mid);
+ sprintf(buf + strlen(buf), "%lu", lo);
+ }
goto printint;
case 'x':
if (q)
@@ -283,8 +334,15 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
if (precision > 2)
precision -= 2;
}
- sprintf(buf, "%" ISC_PRINT_QUADFORMAT "x",
- tmpui);
+ if (tmpui <= 0xffffffffU)
+ sprintf(buf, "%lx",
+ (unsigned long)tmpui);
+ else {
+ unsigned long hi = tmpui>>32;
+ unsigned long lo = tmpui & 0xffffffff;
+ sprintf(buf, "%lx", hi);
+ sprintf(buf + strlen(buf), "%lx", lo);
+ }
goto printint;
case 'X':
if (q)
@@ -298,8 +356,15 @@ isc_print_vsnprintf(char *str, size_t size, const char *format, va_list ap) {
if (precision > 2)
precision -= 2;
}
- sprintf(buf, "%" ISC_PRINT_QUADFORMAT "X",
- tmpui);
+ if (tmpui <= 0xffffffffU)
+ sprintf(buf, "%lX",
+ (unsigned long)tmpui);
+ else {
+ unsigned long hi = tmpui>>32;
+ unsigned long lo = tmpui & 0xffffffff;
+ sprintf(buf, "%lX", hi);
+ sprintf(buf + strlen(buf), "%lX", lo);
+ }
goto printint;
printint:
if (precision != 0 || width != 0) {
diff --git a/lib/isc/pthreads/mutex.c b/lib/isc/pthreads/mutex.c
index 7716980..afbc861 100644
--- a/lib/isc/pthreads/mutex.c
+++ b/lib/isc/pthreads/mutex.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000-2002 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: mutex.c,v 1.8.18.4 2005/07/12 01:22:32 marka Exp $ */
+/* $Id: mutex.c,v 1.8.18.6 2008/04/04 23:46:02 tbox Exp $ */
/*! \file */
@@ -36,23 +36,23 @@
/*% Operations on timevals; adapted from FreeBSD's sys/time.h */
#define timevalclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0)
#define timevaladd(vvp, uvp) \
- do { \
- (vvp)->tv_sec += (uvp)->tv_sec; \
- (vvp)->tv_usec += (uvp)->tv_usec; \
- if ((vvp)->tv_usec >= 1000000) { \
- (vvp)->tv_sec++; \
- (vvp)->tv_usec -= 1000000; \
- } \
- } while (0)
+ do { \
+ (vvp)->tv_sec += (uvp)->tv_sec; \
+ (vvp)->tv_usec += (uvp)->tv_usec; \
+ if ((vvp)->tv_usec >= 1000000) { \
+ (vvp)->tv_sec++; \
+ (vvp)->tv_usec -= 1000000; \
+ } \
+ } while (0)
#define timevalsub(vvp, uvp) \
- do { \
- (vvp)->tv_sec -= (uvp)->tv_sec; \
- (vvp)->tv_usec -= (uvp)->tv_usec; \
- if ((vvp)->tv_usec < 0) { \
- (vvp)->tv_sec--; \
- (vvp)->tv_usec += 1000000; \
- } \
- } while (0)
+ do { \
+ (vvp)->tv_sec -= (uvp)->tv_sec; \
+ (vvp)->tv_usec -= (uvp)->tv_usec; \
+ if ((vvp)->tv_usec < 0) { \
+ (vvp)->tv_sec--; \
+ (vvp)->tv_usec += 1000000; \
+ } \
+ } while (0)
/*@}*/
@@ -77,8 +77,11 @@ struct isc_mutexstats {
isc_mutexlocker_t lockers[ISC_MUTEX_MAX_LOCKERS];
};
-#define TABLESIZE (8 * 1024)
-static isc_mutexstats_t stats[TABLESIZE];
+#ifndef ISC_MUTEX_PROFTABLESIZE
+#define ISC_MUTEX_PROFTABLESIZE (16 * 1024)
+#endif
+static isc_mutexstats_t stats[ISC_MUTEX_PROFTABLESIZE];
+static int stats_next = 0;
static isc_boolean_t stats_init = ISC_FALSE;
static pthread_mutex_t statslock = PTHREAD_MUTEX_INITIALIZER;
@@ -95,21 +98,19 @@ isc_mutex_init_profile(isc_mutex_t *mp, const char *file, int line) {
RUNTIME_CHECK(pthread_mutex_lock(&statslock) == 0);
- if (stats_init == ISC_FALSE) {
- for (i = 0; i < TABLESIZE; i++) {
- stats[i].file = NULL;
- }
+ if (stats_init == ISC_FALSE)
stats_init = ISC_TRUE;
- }
- mp->stats = NULL;
- for (i = 0; i < TABLESIZE; i++) {
- if (stats[i].file == NULL) {
- mp->stats = &stats[i];
- break;
- }
- }
- RUNTIME_CHECK(mp->stats != NULL);
+ /*
+ * If all statistics entries have been used, give up and trigger an
+ * assertion failure. There would be no other way to deal with this
+ * because we'd like to keep record of all locks for the purpose of
+ * debugging and the number of necessary locks is unpredictable.
+ * If this failure is triggered while debugging, named should be
+ * rebuilt with an increased ISC_MUTEX_PROFTABLESIZE.
+ */
+ RUNTIME_CHECK(stats_next < ISC_MUTEX_PROFTABLESIZE);
+ mp->stats = &stats[stats_next++];
RUNTIME_CHECK(pthread_mutex_unlock(&statslock) == 0);
@@ -196,10 +197,9 @@ void
isc_mutex_statsprofile(FILE *fp) {
isc_mutexlocker_t *locker;
int i, j;
+
fprintf(fp, "Mutex stats (in us)\n");
- for (i = 0; i < TABLESIZE; i++) {
- if (stats[i].file == NULL)
- continue;
+ for (i = 0; i < stats_next; i++) {
fprintf(fp, "%-12s %4d: %10u %lu.%06lu %lu.%06lu\n",
stats[i].file, stats[i].line, stats[i].count,
stats[i].locked_total.tv_sec,
@@ -236,7 +236,7 @@ isc_mutex_init_errcheck(isc_mutex_t *mp)
if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK) != 0)
return (ISC_R_UNEXPECTED);
-
+
err = pthread_mutex_init(mp, &attr) != 0)
if (err == ENOMEM)
return (ISC_R_NOMEMORY);
@@ -251,6 +251,7 @@ pthread_mutexattr_t isc__mutex_attrs = {
};
#endif
+#if !(ISC_MUTEX_DEBUG && defined(PTHREAD_MUTEX_ERRORCHECK)) && !ISC_MUTEX_PROFILE
isc_result_t
isc__mutex_init(isc_mutex_t *mp, const char *file, unsigned int line) {
char strbuf[ISC_STRERRORSIZE];
@@ -268,3 +269,4 @@ isc__mutex_init(isc_mutex_t *mp, const char *file, unsigned int line) {
}
return (result);
}
+#endif
diff --git a/lib/isc/timer.c b/lib/isc/timer.c
index d594307..c27281d 100644
--- a/lib/isc/timer.c
+++ b/lib/isc/timer.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: timer.c,v 1.73.18.7.10.3 2008/07/29 18:35:53 jinmei Exp $ */
+/* $Id: timer.c,v 1.73.18.10 2008/08/22 05:59:04 marka Exp $ */
/*! \file */
@@ -225,7 +225,7 @@ schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) {
"*** POKED TIMER ***");
}
}
-
+
if (timer->index == 1 && signal_ok) {
XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER,
ISC_MSG_SIGNALSCHED,
diff --git a/lib/isc/unix/app.c b/lib/isc/unix/app.c
index b71d766..c119362 100644
--- a/lib/isc/unix/app.c
+++ b/lib/isc/unix/app.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: app.c,v 1.50.18.2.50.1 2008/07/29 04:47:31 each Exp $ */
+/* $Id: app.c,v 1.50.18.8 2008/10/15 03:41:17 marka Exp $ */
/*! \file */
@@ -30,6 +30,9 @@
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
+#ifdef HAVE_EPOLL
+#include <sys/epoll.h>
+#endif
#include <isc/app.h>
#include <isc/boolean.h>
@@ -59,11 +62,11 @@ static isc_boolean_t running = ISC_FALSE;
/*!
* We assume that 'want_shutdown' can be read and written atomically.
*/
-static isc_boolean_t want_shutdown = ISC_FALSE;
+static volatile isc_boolean_t want_shutdown = ISC_FALSE;
/*
* We assume that 'want_reload' can be read and written atomically.
*/
-static isc_boolean_t want_reload = ISC_FALSE;
+static volatile isc_boolean_t want_reload = ISC_FALSE;
static isc_boolean_t blocked = ISC_FALSE;
#ifdef ISC_PLATFORM_USETHREADS
@@ -87,13 +90,13 @@ static pthread_t main_thread;
#ifndef HAVE_SIGWAIT
static void
exit_action(int arg) {
- UNUSED(arg);
+ UNUSED(arg);
want_shutdown = ISC_TRUE;
}
static void
reload_action(int arg) {
- UNUSED(arg);
+ UNUSED(arg);
want_reload = ISC_TRUE;
}
#endif
@@ -297,14 +300,13 @@ isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action,
* Event loop for nonthreaded programs.
*/
static isc_result_t
-evloop() {
+evloop(void) {
isc_result_t result;
while (!want_shutdown) {
int n;
isc_time_t when, now;
struct timeval tv, *tvp;
- fd_set *readfds, *writefds;
- int maxfd;
+ isc_socketwait_t *swait;
isc_boolean_t readytasks;
isc_boolean_t call_timer_dispatch = ISC_FALSE;
@@ -331,15 +333,15 @@ evloop() {
}
}
- isc__socketmgr_getfdsets(&readfds, &writefds, &maxfd);
- n = select(maxfd, readfds, writefds, NULL, tvp);
+ swait = NULL;
+ n = isc__socketmgr_waitevents(tvp, &swait);
if (n == 0 || call_timer_dispatch) {
/*
* We call isc__timermgr_dispatch() only when
* necessary, in order to reduce overhead. If the
* select() call indicates a timeout, we need the
- * dispatch. Even if not, if we set the 0-timeout
+ * dispatch. Even if not, if we set the 0-timeout
* for the select() call, we need to check the timer
* events. In the 'readytasks' case, there may be no
* timeout event actually, but there is no other way
@@ -352,8 +354,7 @@ evloop() {
isc__timermgr_dispatch();
}
if (n > 0)
- (void)isc__socketmgr_dispatch(readfds, writefds,
- maxfd);
+ (void)isc__socketmgr_dispatch(swait);
(void)isc__taskmgr_dispatch();
if (want_reload) {
@@ -423,7 +424,7 @@ isc__nothread_signal_hack(isc_condition_t *cp) {
signalled = ISC_TRUE;
return (ISC_R_SUCCESS);
}
-
+
#endif /* ISC_PLATFORM_USETHREADS */
isc_result_t
@@ -434,10 +435,10 @@ isc_app_run(void) {
#ifdef ISC_PLATFORM_USETHREADS
sigset_t sset;
char strbuf[ISC_STRERRORSIZE];
-#endif /* ISC_PLATFORM_USETHREADS */
#ifdef HAVE_SIGWAIT
int sig;
#endif
+#endif /* ISC_PLATFORM_USETHREADS */
#ifdef HAVE_LINUXTHREADS
REQUIRE(main_thread == pthread_self());
@@ -676,7 +677,7 @@ isc_app_unblock(void) {
REQUIRE(blockedthread == pthread_self());
RUNTIME_CHECK(sigemptyset(&sset) == 0 &&
- sigaddset(&sset, SIGINT) == 0 &&
+ sigaddset(&sset, SIGINT) == 0 &&
sigaddset(&sset, SIGTERM) == 0);
RUNTIME_CHECK(pthread_sigmask(SIG_BLOCK, &sset, NULL) == 0);
#endif /* ISC_PLATFORM_USETHREADS */
diff --git a/lib/isc/unix/include/isc/net.h b/lib/isc/unix/include/isc/net.h
index bdd8c14..948e7b1 100644
--- a/lib/isc/unix/include/isc/net.h
+++ b/lib/isc/unix/include/isc/net.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: net.h,v 1.39.18.4 2005/04/27 05:02:37 sra Exp $ */
+/* $Id: net.h,v 1.39.18.6 2008/06/24 23:45:55 tbox Exp $ */
#ifndef ISC_NET_H
#define ISC_NET_H 1
@@ -104,7 +104,7 @@
/*%
* Required for some pre RFC2133 implementations.
* IN6ADDR_ANY_INIT and IN6ADDR_LOOPBACK_INIT were added in
- * draft-ietf-ipngwg-bsd-api-04.txt or draft-ietf-ipngwg-bsd-api-05.txt.
+ * draft-ietf-ipngwg-bsd-api-04.txt or draft-ietf-ipngwg-bsd-api-05.txt.
* If 's6_addr' is defined then assume that there is a union and three
* levels otherwise assume two levels required.
*/
@@ -202,7 +202,7 @@ extern const struct in6_addr isc_net_in6addrloop;
#ifdef ISC_PLATFORM_FIXIN6ISADDR
#undef IN6_IS_ADDR_GEOGRAPHIC
-/*!
+/*!
* \brief
* Fix UnixWare 7.1.1's broken IN6_IS_ADDR_* definitions.
*/
@@ -324,6 +324,23 @@ isc_net_probeunix(void);
* Returns whether UNIX domain sockets are supported.
*/
+isc_result_t
+isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high);
+/*%<
+ * Returns system's default range of ephemeral UDP ports, if defined.
+ * If the range is not available or unknown, ISC_NET_PORTRANGELOW and
+ * ISC_NET_PORTRANGEHIGH will be returned.
+ *
+ * Requires:
+ *
+ *\li 'low' and 'high' must be non NULL.
+ *
+ * Returns:
+ *
+ *\li *low and *high will be the ports specifying the low and high ends of
+ * the range.
+ */
+
#ifdef ISC_PLATFORM_NEEDNTOP
const char *
isc_net_ntop(int af, const void *src, char *dst, size_t size);
diff --git a/lib/isc/unix/net.c b/lib/isc/unix/net.c
index 1de6b32..600ac92 100644
--- a/lib/isc/unix/net.c
+++ b/lib/isc/unix/net.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -15,10 +15,19 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: net.c,v 1.29.18.6 2007/09/13 23:46:26 tbox Exp $ */
+/* $Id: net.c,v 1.29.18.9 2008/07/04 05:52:05 each Exp $ */
#include <config.h>
+#include <sys/types.h>
+
+#if defined(HAVE_SYS_SYSCTL_H)
+#if defined(HAVE_SYS_PARAM_H)
+#include <sys/param.h>
+#endif
+#include <sys/sysctl.h>
+#endif
+
#include <errno.h>
#include <unistd.h>
@@ -30,6 +39,59 @@
#include <isc/string.h>
#include <isc/util.h>
+/*%
+ * Definitions about UDP port range specification. This is a total mess of
+ * portability variants: some use sysctl (but the sysctl names vary), some use
+ * system-specific interfaces, some have the same interface for IPv4 and IPv6,
+ * some separate them, etc...
+ */
+
+/*%
+ * The last resort defaults: use all non well known port space
+ */
+#ifndef ISC_NET_PORTRANGELOW
+#define ISC_NET_PORTRANGELOW 1024
+#endif /* ISC_NET_PORTRANGELOW */
+#ifndef ISC_NET_PORTRANGEHIGH
+#define ISC_NET_PORTRANGEHIGH 65535
+#endif /* ISC_NET_PORTRANGEHIGH */
+
+#ifdef HAVE_SYSCTLBYNAME
+
+/*%
+ * sysctl variants
+ */
+#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
+#define USE_SYSCTL_PORTRANGE
+#define SYSCTL_V4PORTRANGE_LOW "net.inet.ip.portrange.hifirst"
+#define SYSCTL_V4PORTRANGE_HIGH "net.inet.ip.portrange.hilast"
+#define SYSCTL_V6PORTRANGE_LOW "net.inet.ip.portrange.hifirst"
+#define SYSCTL_V6PORTRANGE_HIGH "net.inet.ip.portrange.hilast"
+#endif
+
+#ifdef __NetBSD__
+#define USE_SYSCTL_PORTRANGE
+#define SYSCTL_V4PORTRANGE_LOW "net.inet.ip.anonportmin"
+#define SYSCTL_V4PORTRANGE_HIGH "net.inet.ip.anonportmax"
+#define SYSCTL_V6PORTRANGE_LOW "net.inet6.ip6.anonportmin"
+#define SYSCTL_V6PORTRANGE_HIGH "net.inet6.ip6.anonportmax"
+#endif
+
+#else /* !HAVE_SYSCTLBYNAME */
+
+#ifdef __OpenBSD__
+#define USE_SYSCTL_PORTRANGE
+#define SYSCTL_V4PORTRANGE_LOW { CTL_NET, PF_INET, IPPROTO_IP, \
+ IPCTL_IPPORT_HIFIRSTAUTO }
+#define SYSCTL_V4PORTRANGE_HIGH { CTL_NET, PF_INET, IPPROTO_IP, \
+ IPCTL_IPPORT_HILASTAUTO }
+/* Same for IPv6 */
+#define SYSCTL_V6PORTRANGE_LOW SYSCTL_V4PORTRANGE_LOW
+#define SYSCTL_V6PORTRANGE_HIGH SYSCTL_V4PORTRANGE_HIGH
+#endif
+
+#endif /* HAVE_SYSCTLBYNAME */
+
#if defined(ISC_PLATFORM_HAVEIPV6)
# if defined(ISC_PLATFORM_NEEDIN6ADDRANY)
const struct in6_addr isc_net_in6addrany = IN6ADDR_ANY_INIT;
@@ -338,6 +400,101 @@ isc_net_probe_ipv6pktinfo(void) {
return (ipv6pktinfo_result);
}
+#if defined(USE_SYSCTL_PORTRANGE)
+#if defined(HAVE_SYSCTLBYNAME)
+static isc_result_t
+getudpportrange_sysctl(int af, in_port_t *low, in_port_t *high) {
+ int port_low, port_high;
+ size_t portlen;
+ const char *sysctlname_lowport, *sysctlname_hiport;
+
+ if (af == AF_INET) {
+ sysctlname_lowport = SYSCTL_V4PORTRANGE_LOW;
+ sysctlname_hiport = SYSCTL_V4PORTRANGE_HIGH;
+ } else {
+ sysctlname_lowport = SYSCTL_V6PORTRANGE_LOW;
+ sysctlname_hiport = SYSCTL_V6PORTRANGE_HIGH;
+ }
+ portlen = sizeof(portlen);
+ if (sysctlbyname(sysctlname_lowport, &port_low, &portlen,
+ NULL, 0) < 0) {
+ return (ISC_R_FAILURE);
+ }
+ portlen = sizeof(portlen);
+ if (sysctlbyname(sysctlname_hiport, &port_high, &portlen,
+ NULL, 0) < 0) {
+ return (ISC_R_FAILURE);
+ }
+ if ((port_low & ~0xffff) != 0 || (port_high & ~0xffff) != 0)
+ return (ISC_R_RANGE);
+
+ *low = (in_port_t)port_low;
+ *high = (in_port_t)port_high;
+
+ return (ISC_R_SUCCESS);
+}
+#else /* !HAVE_SYSCTLBYNAME */
+static isc_result_t
+getudpportrange_sysctl(int af, in_port_t *low, in_port_t *high) {
+ int mib_lo4[4] = SYSCTL_V4PORTRANGE_LOW;
+ int mib_hi4[4] = SYSCTL_V4PORTRANGE_HIGH;
+ int mib_lo6[4] = SYSCTL_V6PORTRANGE_LOW;
+ int mib_hi6[4] = SYSCTL_V6PORTRANGE_HIGH;
+ int *mib_lo, *mib_hi, miblen;
+ int port_low, port_high;
+ size_t portlen;
+
+ if (af == AF_INET) {
+ mib_lo = mib_lo4;
+ mib_hi = mib_hi4;
+ miblen = sizeof(mib_lo4) / sizeof(mib_lo4[0]);
+ } else {
+ mib_lo = mib_lo6;
+ mib_hi = mib_hi6;
+ miblen = sizeof(mib_lo6) / sizeof(mib_lo6[0]);
+ }
+
+ portlen = sizeof(portlen);
+ if (sysctl(mib_lo, miblen, &port_low, &portlen, NULL, 0) < 0) {
+ return (ISC_R_FAILURE);
+ }
+
+ portlen = sizeof(portlen);
+ if (sysctl(mib_hi, miblen, &port_high, &portlen, NULL, 0) < 0) {
+ return (ISC_R_FAILURE);
+ }
+
+ if ((port_low & ~0xffff) != 0 || (port_high & ~0xffff) != 0)
+ return (ISC_R_RANGE);
+
+ *low = (in_port_t) port_low;
+ *high = (in_port_t) port_high;
+
+ return (ISC_R_SUCCESS);
+}
+#endif /* HAVE_SYSCTLBYNAME */
+#endif /* USE_SYSCTL_PORTRANGE */
+
+isc_result_t
+isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high) {
+ int result = ISC_R_FAILURE;
+
+ REQUIRE(low != NULL && high != NULL);
+
+#if defined(USE_SYSCTL_PORTRANGE)
+ result = getudpportrange_sysctl(af, low, high);
+#else
+ UNUSED(af);
+#endif
+
+ if (result != ISC_R_SUCCESS) {
+ *low = ISC_NET_PORTRANGELOW;
+ *high = ISC_NET_PORTRANGEHIGH;
+ }
+
+ return (ISC_R_SUCCESS); /* we currently never fail in this function */
+}
+
void
isc_net_disableipv4(void) {
initialize();
diff --git a/lib/isc/unix/resource.c b/lib/isc/unix/resource.c
index 0264976..e9bc5fd 100644
--- a/lib/isc/unix/resource.c
+++ b/lib/isc/unix/resource.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: resource.c,v 1.12.944.4 2008/07/28 22:44:46 marka Exp $ */
+/* $Id: resource.c,v 1.12.18.6 2008/08/05 07:17:05 marka Exp $ */
#include <config.h>
@@ -32,7 +32,7 @@
#include <linux/fs.h> /* To get the large NR_OPEN. */
#endif
-#ifdef __hpux
+#if defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H)
#include <sys/dyntune.h>
#endif
@@ -48,13 +48,13 @@ resource2rlim(isc_resource_t resource, int *rlim_resource) {
break;
case isc_resource_cputime:
*rlim_resource = RLIMIT_CPU;
- break;
+ break;
case isc_resource_datasize:
*rlim_resource = RLIMIT_DATA;
- break;
+ break;
case isc_resource_filesize:
*rlim_resource = RLIMIT_FSIZE;
- break;
+ break;
case isc_resource_lockedmemory:
#ifdef RLIMIT_MEMLOCK
*rlim_resource = RLIMIT_MEMLOCK;
@@ -87,7 +87,7 @@ resource2rlim(isc_resource_t resource, int *rlim_resource) {
*rlim_resource = RLIMIT_STACK;
break;
default:
- /*
+ /*
* This test is not very robust if isc_resource_t
* changes, but generates a clear assertion message.
*/
@@ -140,51 +140,6 @@ isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value) {
rlim_value = value;
}
- /*
- * The BIND 8 documentation reports:
- *
- * Note: on some operating systems the server cannot set an
- * unlimited value and cannot determine the maximum number of
- * open files the kernel can support. On such systems, choosing
- * unlimited will cause the server to use the larger of the
- * rlim_max for RLIMIT_NOFILE and the value returned by
- * sysconf(_SC_OPEN_MAX). If the actual kernel limit is larger
- * than this value, use limit files to specify the limit
- * explicitly.
- *
- * The CHANGES for 8.1.2-T3A also mention:
- *
- * 352. [bug] Because of problems with setting an infinite
- * rlim_max for RLIMIT_NOFILE on some systems, previous versions
- * of the server implemented "limit files unlimited" by setting
- * the limit to the value returned by sysconf(_SC_OPEN_MAX). The
- * server will now use RLIM_INFINITY on systems which allow it.
- *
- * At some point the BIND 8 server stopped using SC_OPEN_MAX for this
- * purpose at all, but it isn't clear to me when or why, as my access
- * to the CVS archive is limited at the time of this writing. What
- * BIND 8 *does* do is to set RLIMIT_NOFILE to either RLIMIT_INFINITY
- * on a half dozen operating systems or to FD_SETSIZE on the rest,
- * the latter of which is probably fewer than the real limit. (Note
- * that libisc's socket module will have problems with any fd over
- * FD_SETSIZE. This should be fixed in the socket module, not a
- * limitation here. BIND 8's eventlib also has a problem, making
- * its RLIMIT_INFINITY setting useless, because it closes and ignores
- * any fd over FD_SETSIZE.)
- *
- * More troubling is the reference to some operating systems not being
- * able to set an unlimited value for the number of open files. I'd
- * hate to put in code that is really only there to support archaic
- * systems that the rest of libisc won't work on anyway. So what this
- * extremely verbose comment is here to say is the following:
- *
- * I'm aware there might be an issue with not limiting the value
- * for RLIMIT_NOFILE on some systems, but since I don't know yet
- * what those systems are and what the best workaround is (use
- * sysconf()? rlim_max from getrlimit()? FD_SETSIZE?) so nothing
- * is currently being done to clamp the value for open files.
- */
-
rl.rlim_cur = rl.rlim_max = rlim_value;
unixresult = setrlimit(unixresource, &rl);
@@ -215,7 +170,7 @@ isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value) {
if (unixresult == 0)
return (ISC_R_SUCCESS);
}
-#elif defined(__hpux)
+#elif defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H)
if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) {
uint64_t maxfiles;
if (gettune("maxfiles_lim", &maxfiles) == 0) {
@@ -255,7 +210,7 @@ isc_resource_getlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
}
isc_result_t
-isc_resource_curlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
+isc_resource_getcurlimit(isc_resource_t resource, isc_resourcevalue_t *value) {
int unixresult;
int unixresource;
struct rlimit rl;
diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c
index 1b4da78..3239614 100644
--- a/lib/isc/unix/socket.c
+++ b/lib/isc/unix/socket.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: socket.c,v 1.237.18.29.10.6 2008/07/29 04:47:31 each Exp $ */
+/* $Id: socket.c,v 1.237.18.56 2008/11/12 03:58:36 marka Exp $ */
/*! \file */
@@ -25,9 +25,6 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
-#ifdef ISC_PLATFORM_HAVESYSUNH
-#include <sys/un.h>
-#endif
#include <sys/time.h>
#include <sys/uio.h>
@@ -58,6 +55,19 @@
#include <isc/thread.h>
#include <isc/util.h>
+#ifdef ISC_PLATFORM_HAVESYSUNH
+#include <sys/un.h>
+#endif
+#ifdef ISC_PLATFORM_HAVEKQUEUE
+#include <sys/event.h>
+#endif
+#ifdef ISC_PLATFORM_HAVEEPOLL
+#include <sys/epoll.h>
+#endif
+#ifdef ISC_PLATFORM_HAVEDEVPOLL
+#include <sys/devpoll.h>
+#endif
+
#include "errno2result.h"
#ifndef ISC_PLATFORM_USETHREADS
@@ -65,9 +75,46 @@
#endif /* ISC_PLATFORM_USETHREADS */
/*%
- * Max number of open sockets. In the vast majority of cases the default size
- * of FD_SETSIZE should be fine, and this constant should be increased only
- * when absolutely necessary and possible, i.e., the server is exhausting all
+ * Choose the most preferable multiplex method.
+ */
+#ifdef ISC_PLATFORM_HAVEKQUEUE
+#define USE_KQUEUE
+#elif defined (ISC_PLATFORM_HAVEEPOLL)
+#define USE_EPOLL
+#elif defined (ISC_PLATFORM_HAVEDEVPOLL)
+#define USE_DEVPOLL
+typedef struct {
+ unsigned int want_read : 1,
+ want_write : 1;
+} pollinfo_t;
+#else
+#define USE_SELECT
+#endif /* ISC_PLATFORM_HAVEKQUEUE */
+
+#ifndef ISC_PLATFORM_USETHREADS
+#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL)
+struct isc_socketwait {
+ int nevents;
+};
+#elif defined (USE_SELECT)
+struct isc_socketwait {
+ fd_set *readset;
+ fd_set *writeset;
+ int nfds;
+ int maxfd;
+};
+#endif /* USE_KQUEUE */
+#endif /* !ISC_PLATFORM_USETHREADS */
+
+/*%
+ * Maximum number of allowable open sockets. This is also the maximum
+ * allowable socket file descriptor.
+ *
+ * Care should be taken before modifying this value for select():
+ * The API standard doesn't ensure select() accept more than (the system default
+ * of) FD_SETSIZE descriptors, and the default size should in fact be fine in
+ * the vast majority of cases. This constant should therefore be increased only
+ * when absolutely necessary and possible, i.e., the server is exhausting all
* available file descriptors (up to FD_SETSIZE) and the select() function
* and FD_xxx macros support larger values than FD_SETSIZE (which may not
* always by true, but we keep using some of them to ensure as much
@@ -78,18 +125,72 @@
* As a special note, this value shouldn't have to be touched if
* this is a build for an authoritative only DNS server.
*/
-
-#ifndef ISC_SOCKET_FDSETSIZE
-#define ISC_SOCKET_FDSETSIZE FD_SETSIZE
-#endif
-
+#ifndef ISC_SOCKET_MAXSOCKETS
+#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL)
+#define ISC_SOCKET_MAXSOCKETS 4096
+#elif defined(USE_SELECT)
+#define ISC_SOCKET_MAXSOCKETS FD_SETSIZE
+#endif /* USE_KQUEUE... */
+#endif /* ISC_SOCKET_MAXSOCKETS */
+
+#ifdef USE_SELECT
/*%
- * Mac OS X needs a special definition to support larger values in select()
+ * Mac OS X needs a special definition to support larger values in select().
+ * We always define this because a larger value can be specified run-time.
*/
-#if ISC_SOCKET_FDSETSIZE > FD_SETSIZE
#ifdef __APPLE__
#define _DARWIN_UNLIMITED_SELECT
#endif /* __APPLE__ */
+#endif /* USE_SELECT */
+
+#ifdef ISC_SOCKET_USE_POLLWATCH
+/*%
+ * If this macro is defined, enable workaround for a Solaris /dev/poll kernel
+ * bug: DP_POLL ioctl could keep sleeping even if socket I/O is possible for
+ * some of the specified FD. The idea is based on the observation that it's
+ * likely for a busy server to keep receiving packets. It specifically works
+ * as follows: the socket watcher is first initialized with the state of
+ * "poll_idle". While it's in the idle state it keeps sleeping until a socket
+ * event occurs. When it wakes up for a socket I/O event, it moves to the
+ * poll_active state, and sets the poll timeout to a short period
+ * (ISC_SOCKET_POLLWATCH_TIMEOUT msec). If timeout occurs in this state, the
+ * watcher goes to the poll_checking state with the same timeout period.
+ * In this state, the watcher tries to detect whether this is a break
+ * during intermittent events or the kernel bug is triggered. If the next
+ * polling reports an event within the short period, the previous timeout is
+ * likely to be a kernel bug, and so the watcher goes back to the active state.
+ * Otherwise, it moves to the idle state again.
+ *
+ * It's not clear whether this is a thread-related bug, but since we've only
+ * seen this with threads, this workaround is used only when enabling threads.
+ */
+
+typedef enum { poll_idle, poll_active, poll_checking } pollstate_t;
+
+#ifndef ISC_SOCKET_POLLWATCH_TIMEOUT
+#define ISC_SOCKET_POLLWATCH_TIMEOUT 10
+#endif /* ISC_SOCKET_POLLWATCH_TIMEOUT */
+#endif /* ISC_SOCKET_USE_POLLWATCH */
+
+/*%
+ * Size of per-FD lock buckets.
+ */
+#ifdef ISC_PLATFORM_USETHREADS
+#define FDLOCK_COUNT 1024
+#define FDLOCK_ID(fd) ((fd) % FDLOCK_COUNT)
+#else
+#define FDLOCK_COUNT 1
+#define FDLOCK_ID(fd) 0
+#endif /* ISC_PLATFORM_USETHREADS */
+
+/*%
+ * Maximum number of events communicated with the kernel. There should normally
+ * be no need for having a large number.
+ */
+#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL)
+#ifndef ISC_SOCKET_MAXEVENTS
+#define ISC_SOCKET_MAXEVENTS 64
+#endif
#endif
/*%
@@ -230,22 +331,50 @@ struct isc_socketmgr {
unsigned int magic;
isc_mem_t *mctx;
isc_mutex_t lock;
+ isc_mutex_t *fdlock;
+#ifdef USE_KQUEUE
+ int kqueue_fd;
+ int nevents;
+ struct kevent *events;
+#endif /* USE_KQUEUE */
+#ifdef USE_EPOLL
+ int epoll_fd;
+ int nevents;
+ struct epoll_event *events;
+#endif /* USE_EPOLL */
+#ifdef USE_DEVPOLL
+ int devpoll_fd;
+ int nevents;
+ struct pollfd *events;
+#endif /* USE_DEVPOLL */
+#ifdef USE_SELECT
int fd_bufsize;
- int fdsize;
+#endif /* USE_SELECT */
+ unsigned int maxsocks;
+#ifdef ISC_PLATFORM_USETHREADS
+ int pipe_fds[2];
+#endif
+
+ /* Locked by fdlock. */
+ isc_socket_t **fds;
+ int *fdstate;
+#ifdef USE_DEVPOLL
+ pollinfo_t *fdpollinfo;
+#endif
+
/* Locked by manager lock. */
ISC_LIST(isc_socket_t) socklist;
+#ifdef USE_SELECT
fd_set *read_fds;
fd_set *read_fds_copy;
fd_set *write_fds;
fd_set *write_fds_copy;
- isc_socket_t **fds;
- int *fdstate;
int maxfd;
- int reserved; /* unlocked */
+#endif /* USE_SELECT */
+ int reserved; /* unlocked */
#ifdef ISC_PLATFORM_USETHREADS
isc_thread_t watcher;
isc_condition_t shutdown_ok;
- int pipe_fds[2];
#else /* ISC_PLATFORM_USETHREADS */
unsigned int refs;
#endif /* ISC_PLATFORM_USETHREADS */
@@ -284,8 +413,9 @@ static void build_msghdr_send(isc_socket_t *, isc_socketevent_t *,
struct msghdr *, struct iovec *, size_t *);
static void build_msghdr_recv(isc_socket_t *, isc_socketevent_t *,
struct msghdr *, struct iovec *, size_t *);
-static void cleanup_fdsets(isc_socketmgr_t *, isc_mem_t *);
-static isc_result_t create_fdsets(isc_socketmgr_t *, isc_mem_t *);
+#ifdef ISC_PLATFORM_USETHREADS
+static isc_boolean_t process_ctlfd(isc_socketmgr_t *manager);
+#endif
#define SELECT_POKE_SHUTDOWN (-1)
#define SELECT_POKE_NOTHING (-2)
@@ -354,9 +484,195 @@ socket_log(isc_socket_t *sock, isc_sockaddr_t *address,
}
}
+#if defined(_AIX) && defined(ISC_NET_BSD44MSGHDR) && \
+ defined(USE_CMSG) && defined(IPV6_RECVPKTINFO)
+/*
+ * AIX has a kernel bug where IPV6_RECVPKTINFO gets cleared by
+ * setting IPV6_V6ONLY.
+ */
+static void
+FIX_IPV6_RECVPKTINFO(isc_socket_t *sock)
+{
+ char strbuf[ISC_STRERRORSIZE];
+ int on = 1;
+
+ if (sock->pf != AF_INET6 || sock->type != isc_sockettype_udp)
+ return;
+
+ if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
+ (void *)&on, sizeof(on)) < 0) {
+
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "setsockopt(%d, IPV6_RECVPKTINFO) "
+ "%s: %s", sock->fd,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ }
+}
+#else
+#define FIX_IPV6_RECVPKTINFO(sock) (void)0
+#endif
+
+static inline isc_result_t
+watch_fd(isc_socketmgr_t *manager, int fd, int msg) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+#ifdef USE_KQUEUE
+ struct kevent evchange;
+
+ memset(&evchange, 0, sizeof(evchange));
+ if (msg == SELECT_POKE_READ)
+ evchange.filter = EVFILT_READ;
+ else
+ evchange.filter = EVFILT_WRITE;
+ evchange.flags = EV_ADD;
+ evchange.ident = fd;
+ if (kevent(manager->kqueue_fd, &evchange, 1, NULL, 0, NULL) != 0)
+ result = isc__errno2result(errno);
+
+ return (result);
+#elif defined(USE_EPOLL)
+ struct epoll_event event;
+
+ if (msg == SELECT_POKE_READ)
+ event.events = EPOLLIN;
+ else
+ event.events = EPOLLOUT;
+ event.data.fd = fd;
+ if (epoll_ctl(manager->epoll_fd, EPOLL_CTL_ADD, fd, &event) == -1 &&
+ errno != EEXIST) {
+ result = isc__errno2result(errno);
+ }
+
+ return (result);
+#elif defined(USE_DEVPOLL)
+ struct pollfd pfd;
+ int lockid = FDLOCK_ID(fd);
+
+ memset(&pfd, 0, sizeof(pfd));
+ if (msg == SELECT_POKE_READ)
+ pfd.events = POLLIN;
+ else
+ pfd.events = POLLOUT;
+ pfd.fd = fd;
+ pfd.revents = 0;
+ LOCK(&manager->fdlock[lockid]);
+ if (write(manager->devpoll_fd, &pfd, sizeof(pfd)) == -1)
+ result = isc__errno2result(errno);
+ else {
+ if (msg == SELECT_POKE_READ)
+ manager->fdpollinfo[fd].want_read = 1;
+ else
+ manager->fdpollinfo[fd].want_write = 1;
+ }
+ UNLOCK(&manager->fdlock[lockid]);
+
+ return (result);
+#elif defined(USE_SELECT)
+ LOCK(&manager->lock);
+ if (msg == SELECT_POKE_READ)
+ FD_SET(fd, manager->read_fds);
+ if (msg == SELECT_POKE_WRITE)
+ FD_SET(fd, manager->write_fds);
+ UNLOCK(&manager->lock);
+
+ return (result);
+#endif
+}
+
+static inline isc_result_t
+unwatch_fd(isc_socketmgr_t *manager, int fd, int msg) {
+ isc_result_t result = ISC_R_SUCCESS;
+
+#ifdef USE_KQUEUE
+ struct kevent evchange;
+
+ memset(&evchange, 0, sizeof(evchange));
+ if (msg == SELECT_POKE_READ)
+ evchange.filter = EVFILT_READ;
+ else
+ evchange.filter = EVFILT_WRITE;
+ evchange.flags = EV_DELETE;
+ evchange.ident = fd;
+ if (kevent(manager->kqueue_fd, &evchange, 1, NULL, 0, NULL) != 0)
+ result = isc__errno2result(errno);
+
+ return (result);
+#elif defined(USE_EPOLL)
+ struct epoll_event event;
+
+ if (msg == SELECT_POKE_READ)
+ event.events = EPOLLIN;
+ else
+ event.events = EPOLLOUT;
+ event.data.fd = fd;
+ if (epoll_ctl(manager->epoll_fd, EPOLL_CTL_DEL, fd, &event) == -1 &&
+ errno != ENOENT) {
+ char strbuf[ISC_STRERRORSIZE];
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "epoll_ctl(DEL), %d: %s", fd, strbuf);
+ result = ISC_R_UNEXPECTED;
+ }
+ return (result);
+#elif defined(USE_DEVPOLL)
+ struct pollfd pfds[2];
+ size_t writelen = sizeof(pfds[0]);
+ int lockid = FDLOCK_ID(fd);
+
+ memset(pfds, 0, sizeof(pfds));
+ pfds[0].events = POLLREMOVE;
+ pfds[0].fd = fd;
+
+ /*
+ * Canceling read or write polling via /dev/poll is tricky. Since it
+ * only provides a way of canceling per FD, we may need to re-poll the
+ * socket for the other operation.
+ */
+ LOCK(&manager->fdlock[lockid]);
+ if (msg == SELECT_POKE_READ &&
+ manager->fdpollinfo[fd].want_write == 1) {
+ pfds[1].events = POLLOUT;
+ pfds[1].fd = fd;
+ writelen += sizeof(pfds[1]);
+ }
+ if (msg == SELECT_POKE_WRITE &&
+ manager->fdpollinfo[fd].want_read == 1) {
+ pfds[1].events = POLLIN;
+ pfds[1].fd = fd;
+ writelen += sizeof(pfds[1]);
+ }
+
+ if (write(manager->devpoll_fd, pfds, writelen) == -1)
+ result = isc__errno2result(errno);
+ else {
+ if (msg == SELECT_POKE_READ)
+ manager->fdpollinfo[fd].want_read = 0;
+ else
+ manager->fdpollinfo[fd].want_write = 0;
+ }
+ UNLOCK(&manager->fdlock[lockid]);
+
+ return (result);
+#elif defined(USE_SELECT)
+ LOCK(&manager->lock);
+ if (msg == SELECT_POKE_READ)
+ FD_CLR(fd, manager->read_fds);
+ else if (msg == SELECT_POKE_WRITE)
+ FD_CLR(fd, manager->write_fds);
+ UNLOCK(&manager->lock);
+
+ return (result);
+#endif
+}
+
static void
wakeup_socket(isc_socketmgr_t *manager, int fd, int msg) {
- isc_socket_t *sock;
+ isc_result_t result;
+ int lockid = FDLOCK_ID(fd);
/*
* This is a wakeup on a socket. If the socket is not in the
@@ -364,27 +680,54 @@ wakeup_socket(isc_socketmgr_t *manager, int fd, int msg) {
* or writes.
*/
- INSIST(fd >= 0 && fd < manager->fdsize);
+ INSIST(fd >= 0 && fd < (int)manager->maxsocks);
- if (manager->fdstate[fd] == CLOSE_PENDING) {
+ if (msg == SELECT_POKE_CLOSE) {
+ /* No one should be updating fdstate, so no need to lock it */
+ INSIST(manager->fdstate[fd] == CLOSE_PENDING);
manager->fdstate[fd] = CLOSED;
- FD_CLR(fd, manager->read_fds);
- FD_CLR(fd, manager->write_fds);
+ (void)unwatch_fd(manager, fd, SELECT_POKE_READ);
+ (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE);
(void)close(fd);
return;
}
- if (manager->fdstate[fd] != MANAGED)
- return;
- sock = manager->fds[fd];
+ LOCK(&manager->fdlock[lockid]);
+ if (manager->fdstate[fd] == CLOSE_PENDING) {
+ UNLOCK(&manager->fdlock[lockid]);
+ /*
+ * We accept (and ignore) any error from unwatch_fd() as we are
+ * closing the socket, hoping it doesn't leave dangling state in
+ * the kernel.
+ * Note that unwatch_fd() must be called after releasing the
+ * fdlock; otherwise it could cause deadlock due to a lock order
+ * reversal.
+ */
+ (void)unwatch_fd(manager, fd, SELECT_POKE_READ);
+ (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE);
+ return;
+ }
+ if (manager->fdstate[fd] != MANAGED) {
+ UNLOCK(&manager->fdlock[lockid]);
+ return;
+ }
+ UNLOCK(&manager->fdlock[lockid]);
/*
* Set requested bit.
*/
- if (msg == SELECT_POKE_READ)
- FD_SET(sock->fd, manager->read_fds);
- if (msg == SELECT_POKE_WRITE)
- FD_SET(sock->fd, manager->write_fds);
+ result = watch_fd(manager, fd, msg);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * XXXJT: what should we do? Ignoring the failure of watching
+ * a socket will make the application dysfunctional, but there
+ * seems to be no reasonable recovery process.
+ */
+ isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
+ "failed to start watching FD (%d): %s",
+ fd, isc_result_totext(result));
+ }
}
#ifdef ISC_PLATFORM_USETHREADS
@@ -452,7 +795,7 @@ select_readmsg(isc_socketmgr_t *mgr, int *fd, int *msg) {
"read() failed "
"during watcher poke: %s"),
strbuf);
-
+
return;
}
INSIST(cc == sizeof(buf));
@@ -557,7 +900,7 @@ cmsg_space(ISC_SOCKADDR_LEN_T len) {
return ((char *)cmsgp - (char *)msg.msg_control);
else
return (0);
-#endif
+#endif
}
#endif /* USE_CMSG */
@@ -631,7 +974,7 @@ process_cmsg(isc_socket_t *sock, struct msghdr *msg, isc_socketevent_t *dev) {
"interface received on ifindex %u",
dev->pktinfo.ipi6_ifindex);
if (IN6_IS_ADDR_MULTICAST(&pktinfop->ipi6_addr))
- dev->attributes |= ISC_SOCKEVENTATTR_MULTICAST;
+ dev->attributes |= ISC_SOCKEVENTATTR_MULTICAST;
goto next;
}
#endif
@@ -679,7 +1022,7 @@ build_msghdr_send(isc_socket_t *sock, isc_socketevent_t *dev,
memset(msg, 0, sizeof(*msg));
- if (sock->type == isc_sockettype_udp) {
+ if (!sock->connected) {
msg->msg_name = (void *)&dev->address.type.sa;
msg->msg_namelen = dev->address.length;
} else {
@@ -964,15 +1307,17 @@ dump_msg(struct msghdr *msg) {
unsigned int i;
printf("MSGHDR %p\n", msg);
- printf("\tname %p, namelen %d\n", msg->msg_name, msg->msg_namelen);
- printf("\tiov %p, iovlen %d\n", msg->msg_iov, msg->msg_iovlen);
+ printf("\tname %p, namelen %ld\n", msg->msg_name,
+ (long) msg->msg_namelen);
+ printf("\tiov %p, iovlen %ld\n", msg->msg_iov,
+ (long) msg->msg_iovlen);
for (i = 0; i < (unsigned int)msg->msg_iovlen; i++)
- printf("\t\t%d\tbase %p, len %d\n", i,
+ printf("\t\t%d\tbase %p, len %ld\n", i,
msg->msg_iov[i].iov_base,
- msg->msg_iov[i].iov_len);
+ (long) msg->msg_iov[i].iov_len);
#ifdef ISC_NET_BSD44MSGHDR
- printf("\tcontrol %p, controllen %d\n", msg->msg_control,
- msg->msg_controllen);
+ printf("\tcontrol %p, controllen %ld\n", msg->msg_control,
+ (long) msg->msg_controllen);
#endif
}
#endif
@@ -1014,7 +1359,7 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
isc__strerror(recv_errno, strbuf, sizeof(strbuf));
socket_log(sock, NULL, IOEVENT,
isc_msgcat, ISC_MSGSET_SOCKET,
- ISC_MSG_DOIORECV,
+ ISC_MSG_DOIORECV,
"doio_recv: recvmsg(%d) %d bytes, err %d/%s",
sock->fd, cc, recv_errno, strbuf);
}
@@ -1040,6 +1385,14 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
/* HPUX 11.11 can return EADDRNOTAVAIL. */
SOFT_OR_HARD(EADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL);
ALWAYS_HARD(ENOBUFS, ISC_R_NORESOURCES);
+ /*
+ * HPUX returns EPROTO and EINVAL on receiving some ICMP/ICMPv6
+ * errors.
+ */
+#ifdef EPROTO
+ SOFT_OR_HARD(EPROTO, ISC_R_HOSTUNREACH);
+#endif
+ SOFT_OR_HARD(EINVAL, ISC_R_HOSTUNREACH);
#undef SOFT_OR_HARD
#undef ALWAYS_HARD
@@ -1062,7 +1415,7 @@ doio_recv(isc_socket_t *sock, isc_socketevent_t *dev) {
if (isc_log_wouldlog(isc_lctx, IOEVENT_LEVEL)) {
socket_log(sock, &dev->address, IOEVENT,
isc_msgcat, ISC_MSGSET_SOCKET,
- ISC_MSG_ZEROPORT,
+ ISC_MSG_ZEROPORT,
"dropping source port zero packet");
}
return (DOIO_SOFT);
@@ -1245,7 +1598,54 @@ doio_send(isc_socket_t *sock, isc_socketevent_t *dev) {
* references exist.
*/
static void
+closesocket(isc_socketmgr_t *manager, isc_sockettype_t type, int fd) {
+ int lockid = FDLOCK_ID(fd);
+
+ UNUSED(type);
+
+ /*
+ * No one has this socket open, so the watcher doesn't have to be
+ * poked, and the socket doesn't have to be locked.
+ */
+ LOCK(&manager->fdlock[lockid]);
+ manager->fds[fd] = NULL;
+ manager->fdstate[fd] = CLOSE_PENDING;
+ UNLOCK(&manager->fdlock[lockid]);
+ select_poke(manager, fd, SELECT_POKE_CLOSE);
+
+ /*
+ * update manager->maxfd here (XXX: this should be implemented more
+ * efficiently)
+ */
+#ifdef USE_SELECT
+ LOCK(&manager->lock);
+ if (manager->maxfd == fd) {
+ int i;
+
+ manager->maxfd = 0;
+ for (i = fd - 1; i >= 0; i--) {
+ lockid = FDLOCK_ID(i);
+
+ LOCK(&manager->fdlock[lockid]);
+ if (manager->fdstate[i] == MANAGED) {
+ manager->maxfd = i;
+ UNLOCK(&manager->fdlock[lockid]);
+ break;
+ }
+ UNLOCK(&manager->fdlock[lockid]);
+ }
+#ifdef ISC_PLATFORM_USETHREADS
+ if (manager->maxfd < manager->pipe_fds[0])
+ manager->maxfd = manager->pipe_fds[0];
+#endif
+ }
+ UNLOCK(&manager->lock);
+#endif /* USE_SELECT */
+}
+
+static void
destroy(isc_socket_t **sockp) {
+ int fd;
isc_socket_t *sock = *sockp;
isc_socketmgr_t *manager = sock->manager;
@@ -1256,17 +1656,16 @@ destroy(isc_socket_t **sockp) {
INSIST(ISC_LIST_EMPTY(sock->recv_list));
INSIST(ISC_LIST_EMPTY(sock->send_list));
INSIST(sock->connect_ev == NULL);
- REQUIRE(sock->fd >= 0 && sock->fd < (int)manager->fdsize);
+ REQUIRE(sock->fd == -1 || sock->fd < (int)manager->maxsocks);
+
+ if (sock->fd >= 0) {
+ fd = sock->fd;
+ sock->fd = -1;
+ closesocket(manager, sock->type, fd);
+ }
LOCK(&manager->lock);
- /*
- * No one has this socket open, so the watcher doesn't have to be
- * poked, and the socket doesn't have to be locked.
- */
- manager->fds[sock->fd] = NULL;
- manager->fdstate[sock->fd] = CLOSE_PENDING;
- select_poke(manager, sock->fd, SELECT_POKE_CLOSE);
ISC_LIST_UNLINK(manager->socklist, sock, link);
#ifdef ISC_PLATFORM_USETHREADS
@@ -1274,10 +1673,6 @@ destroy(isc_socket_t **sockp) {
SIGNAL(&manager->shutdown_ok);
#endif /* ISC_PLATFORM_USETHREADS */
- /*
- * XXX should reset manager->maxfd here
- */
-
UNLOCK(&manager->lock);
free_socket(sockp);
@@ -1465,18 +1860,11 @@ clear_bsdcompat(void) {
}
#endif
-/*%
- * 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_result_t
-isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
- isc_socket_t **socketp)
-{
- isc_socket_t *sock = NULL;
- isc_result_t result;
+static isc_result_t
+opensocket(isc_socketmgr_t *manager, isc_socket_t *sock) {
+ char strbuf[ISC_STRERRORSIZE];
+ const char *err = "socket";
+ int tries = 0;
#if defined(USE_CMSG) || defined(SO_BSDCOMPAT)
int on = 1;
#endif
@@ -1484,38 +1872,27 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
ISC_SOCKADDR_LEN_T optlen;
int size;
#endif
- char strbuf[ISC_STRERRORSIZE];
- const char *err = "socket";
- int try = 0;
- REQUIRE(VALID_MANAGER(manager));
- REQUIRE(socketp != NULL && *socketp == NULL);
-
- result = allocate_socket(manager, type, &sock);
- if (result != ISC_R_SUCCESS)
- return (result);
-
- sock->pf = pf;
again:
- switch (type) {
+ switch (sock->type) {
case isc_sockettype_udp:
- sock->fd = socket(pf, SOCK_DGRAM, IPPROTO_UDP);
+ sock->fd = socket(sock->pf, SOCK_DGRAM, IPPROTO_UDP);
break;
case isc_sockettype_tcp:
- sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP);
+ sock->fd = socket(sock->pf, SOCK_STREAM, IPPROTO_TCP);
break;
case isc_sockettype_unix:
- sock->fd = socket(pf, SOCK_STREAM, 0);
+ sock->fd = socket(sock->pf, SOCK_STREAM, 0);
break;
}
- if (sock->fd == -1 && errno == EINTR && try++ < 42)
+ if (sock->fd == -1 && errno == EINTR && tries++ < 42)
goto again;
#ifdef F_DUPFD
/*
* Leave a space for stdio and TCP to work in.
*/
- if (manager->reserved != 0 && type == isc_sockettype_udp &&
+ if (manager->reserved != 0 && sock->type == isc_sockettype_udp &&
sock->fd >= 0 && sock->fd < manager->reserved) {
int new, tmp;
new = fcntl(sock->fd, F_DUPFD, manager->reserved);
@@ -1535,20 +1912,18 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
}
#endif
- if (sock->fd >= (int)manager->fdsize) {
+ if (sock->fd >= (int)manager->maxsocks) {
(void)close(sock->fd);
isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL,
ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
isc_msgcat, ISC_MSGSET_SOCKET,
ISC_MSG_TOOMANYFDS,
- "%s: too many open file descriptors", "socket");
- free_socket(&sock);
+ "socket: file descriptor exceeds limit (%d/%u)",
+ sock->fd, manager->maxsocks);
return (ISC_R_NORESOURCES);
}
-
- if (sock->fd < 0) {
- free_socket(&sock);
+ if (sock->fd < 0) {
switch (errno) {
case EMFILE:
case ENFILE:
@@ -1580,14 +1955,13 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
if (make_nonblock(sock->fd) != ISC_R_SUCCESS) {
(void)close(sock->fd);
- free_socket(&sock);
return (ISC_R_UNEXPECTED);
}
#ifdef SO_BSDCOMPAT
RUNTIME_CHECK(isc_once_do(&bsdcompat_once,
clear_bsdcompat) == ISC_R_SUCCESS);
- if (type != isc_sockettype_unix && bsdcompat &&
+ if (sock->type != isc_sockettype_unix && bsdcompat &&
setsockopt(sock->fd, SOL_SOCKET, SO_BSDCOMPAT,
(void *)&on, sizeof(on)) < 0) {
isc__strerror(errno, strbuf, sizeof(strbuf));
@@ -1601,8 +1975,22 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
}
#endif
+#ifdef SO_NOSIGPIPE
+ if (setsockopt(sock->fd, SOL_SOCKET, SO_NOSIGPIPE,
+ (void *)&on, sizeof(on)) < 0) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "setsockopt(%d, SO_NOSIGPIPE) %s: %s",
+ sock->fd,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"),
+ strbuf);
+ /* Press on... */
+ }
+#endif
+
#if defined(USE_CMSG) || defined(SO_RCVBUF)
- if (type == isc_sockettype_udp) {
+ if (sock->type == isc_sockettype_udp) {
#if defined(USE_CMSG)
#if defined(SO_TIMESTAMP)
@@ -1612,7 +2000,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
isc__strerror(errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"setsockopt(%d, SO_TIMESTAMP) %s: %s",
- sock->fd,
+ sock->fd,
isc_msgcat_get(isc_msgcat,
ISC_MSGSET_GENERAL,
ISC_MSG_FAILED,
@@ -1623,7 +2011,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
#endif /* SO_TIMESTAMP */
#if defined(ISC_PLATFORM_HAVEIPV6)
- if (pf == AF_INET6 && sock->recvcmsgbuflen == 0U) {
+ if (sock->pf == AF_INET6 && sock->recvcmsgbuflen == 0U) {
/*
* Warn explicitly because this anomaly can be hidden
* in usual operation (and unexpectedly appear later).
@@ -1635,7 +2023,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
#ifdef IPV6_RECVPKTINFO
/* RFC 3542 */
- if ((pf == AF_INET6)
+ if ((sock->pf == AF_INET6)
&& (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
(void *)&on, sizeof(on)) < 0)) {
isc__strerror(errno, strbuf, sizeof(strbuf));
@@ -1650,7 +2038,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
}
#else
/* RFC 2292 */
- if ((pf == AF_INET6)
+ if ((sock->pf == AF_INET6)
&& (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_PKTINFO,
(void *)&on, sizeof(on)) < 0)) {
isc__strerror(errno, strbuf, sizeof(strbuf));
@@ -1667,7 +2055,7 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
#endif /* ISC_PLATFORM_HAVEIN6PKTINFO */
#ifdef IPV6_USE_MIN_MTU /* RFC 3542, not too common yet*/
/* use minimum MTU */
- if (pf == AF_INET6) {
+ if (sock->pf == AF_INET6) {
(void)setsockopt(sock->fd, IPPROTO_IPV6,
IPV6_USE_MIN_MTU,
(void *)&on, sizeof(on));
@@ -1676,6 +2064,27 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
#endif /* ISC_PLATFORM_HAVEIPV6 */
#endif /* defined(USE_CMSG) */
+#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
+ /*
+ * Turn off Path MTU discovery on IPv4/UDP sockets.
+ */
+ if (sock->pf == AF_INET) {
+ int action = IP_PMTUDISC_DONT;
+ (void)setsockopt(sock->fd, IPPROTO_IP, IP_MTU_DISCOVER,
+ &action, sizeof(action));
+ }
+#endif
+#if defined(IP_DONTFRAG)
+ /*
+ * Turn off Path MTU discovery on IPv4/UDP sockets.
+ */
+ if (sock->pf == AF_INET) {
+ int off = 0;
+ (void)setsockopt(sock->fd, IPPROTO_IP, IP_DONTFRAG,
+ &off, sizeof(off));
+ }
+#endif
+
#if defined(SO_RCVBUF)
optlen = sizeof(size);
if (getsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF,
@@ -1699,22 +2108,61 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
}
#endif /* defined(USE_CMSG) || defined(SO_RCVBUF) */
+ 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_result_t
+isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
+ isc_socket_t **socketp)
+{
+ isc_socket_t *sock = NULL;
+ isc_result_t result;
+ int lockid;
+
+ REQUIRE(VALID_MANAGER(manager));
+ REQUIRE(socketp != NULL && *socketp == NULL);
+
+ result = allocate_socket(manager, type, &sock);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ sock->pf = pf;
+ result = opensocket(manager, sock);
+ if (result != ISC_R_SUCCESS) {
+ free_socket(&sock);
+ return (result);
+ }
+
sock->references = 1;
*socketp = sock;
- LOCK(&manager->lock);
-
/*
* Note we don't have to lock the socket like we normally would because
* there are no external references to it yet.
*/
+ lockid = FDLOCK_ID(sock->fd);
+ LOCK(&manager->fdlock[lockid]);
manager->fds[sock->fd] = sock;
manager->fdstate[sock->fd] = MANAGED;
+#ifdef USE_DEVPOLL
+ INSIST(sock->manager->fdpollinfo[sock->fd].want_read == 0 &&
+ sock->manager->fdpollinfo[sock->fd].want_write == 0);
+#endif
+ UNLOCK(&manager->fdlock[lockid]);
+
+ LOCK(&manager->lock);
ISC_LIST_APPEND(manager->socklist, sock, link);
+#ifdef USE_SELECT
if (manager->maxfd < sock->fd)
manager->maxfd = sock->fd;
-
+#endif
UNLOCK(&manager->lock);
socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,
@@ -1723,6 +2171,48 @@ isc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,
return (ISC_R_SUCCESS);
}
+isc_result_t
+isc_socket_open(isc_socket_t *sock) {
+ isc_result_t result;
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ REQUIRE(sock->references == 1);
+ UNLOCK(&sock->lock);
+ /*
+ * We don't need to retain the lock hereafter, since no one else has
+ * this socket.
+ */
+ REQUIRE(sock->fd == -1);
+
+ result = opensocket(sock->manager, sock);
+ if (result != ISC_R_SUCCESS)
+ sock->fd = -1;
+
+ if (result == ISC_R_SUCCESS) {
+ int lockid = FDLOCK_ID(sock->fd);
+
+ LOCK(&sock->manager->fdlock[lockid]);
+ sock->manager->fds[sock->fd] = sock;
+ sock->manager->fdstate[sock->fd] = MANAGED;
+#ifdef USE_DEVPOLL
+ INSIST(sock->manager->fdpollinfo[sock->fd].want_read == 0 &&
+ sock->manager->fdpollinfo[sock->fd].want_write == 0);
+#endif
+ UNLOCK(&sock->manager->fdlock[lockid]);
+
+#ifdef USE_SELECT
+ LOCK(&sock->manager->lock);
+ if (sock->manager->maxfd < sock->fd)
+ sock->manager->maxfd = sock->fd;
+ UNLOCK(&sock->manager->lock);
+#endif
+ }
+
+ return (result);
+}
+
/*
* Attach to a socket. Caller must explicitly detach when it is done.
*/
@@ -1764,6 +2254,44 @@ isc_socket_detach(isc_socket_t **socketp) {
*socketp = NULL;
}
+isc_result_t
+isc_socket_close(isc_socket_t *sock) {
+ int fd;
+
+ REQUIRE(VALID_SOCKET(sock));
+
+ LOCK(&sock->lock);
+ REQUIRE(sock->references == 1);
+ UNLOCK(&sock->lock);
+ /*
+ * We don't need to retain the lock hereafter, since no one else has
+ * this socket.
+ */
+
+ REQUIRE(sock->fd >= 0 && sock->fd < (int)sock->manager->maxsocks);
+
+ INSIST(!sock->connecting);
+ INSIST(!sock->pending_recv);
+ INSIST(!sock->pending_send);
+ INSIST(!sock->pending_accept);
+ INSIST(ISC_LIST_EMPTY(sock->recv_list));
+ INSIST(ISC_LIST_EMPTY(sock->send_list));
+ INSIST(ISC_LIST_EMPTY(sock->accept_list));
+ INSIST(sock->connect_ev == NULL);
+
+ fd = sock->fd;
+ sock->fd = -1;
+ sock->listener = 0;
+ sock->connected = 0;
+ sock->connecting = 0;
+ sock->bound = 0;
+ isc_sockaddr_any(&sock->address);
+
+ closesocket(sock->manager, sock->type, fd);
+
+ return (ISC_R_SUCCESS);
+}
+
/*
* I/O is possible on a given socket. Schedule an event to this task that
* will call an internal function to do the I/O. This will charge the
@@ -1993,7 +2521,7 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
*/
addrlen = sizeof(dev->newsocket->address.type);
- memset(&dev->newsocket->address.type.sa, 0, addrlen);
+ memset(&dev->newsocket->address.type, 0, addrlen);
fd = accept(sock->fd, &dev->newsocket->address.type.sa,
(void *)&addrlen);
@@ -2070,19 +2598,20 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"internal_accept(): "
"accept() returned peer address "
- "family %u (expected %u)",
+ "family %u (expected %u)",
dev->newsocket->address.
type.sa.sa_family,
sock->pf);
(void)close(fd);
goto soft_error;
- } else if (fd >= (int)manager->fdsize) {
+ } else if (fd >= (int)manager->maxsocks) {
isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL,
ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
isc_msgcat, ISC_MSGSET_SOCKET,
ISC_MSG_TOOMANYFDS,
- "%s: too many open file descriptors",
- "accept");
+ "accept: "
+ "file descriptor exceeds limit (%d/%u)",
+ fd, manager->maxsocks);
(void)close(fd);
goto soft_error;
}
@@ -2116,6 +2645,13 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
* -1 means the new socket didn't happen.
*/
if (fd != -1) {
+ int lockid = FDLOCK_ID(fd);
+
+ LOCK(&manager->fdlock[lockid]);
+ manager->fds[fd] = dev->newsocket;
+ manager->fdstate[fd] = MANAGED;
+ UNLOCK(&manager->fdlock[lockid]);
+
LOCK(&manager->lock);
ISC_LIST_APPEND(manager->socklist, dev->newsocket, link);
@@ -2128,10 +2664,10 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
*/
dev->address = dev->newsocket->address;
- manager->fds[fd] = dev->newsocket;
- manager->fdstate[fd] = MANAGED;
+#ifdef USE_SELECT
if (manager->maxfd < fd)
manager->maxfd = fd;
+#endif
socket_log(sock, &dev->newsocket->address, CREATION,
isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN,
@@ -2143,7 +2679,7 @@ internal_accept(isc_task_t *me, isc_event_t *ev) {
dev->newsocket->references--;
free_socket(&dev->newsocket);
}
-
+
/*
* Fill in the done event details and send it off.
*/
@@ -2280,77 +2816,256 @@ internal_send(isc_task_t *me, isc_event_t *ev) {
UNLOCK(&sock->lock);
}
+/*
+ * Process read/writes on each fd here. Avoid locking
+ * and unlocking twice if both reads and writes are possible.
+ */
static void
-process_fds(isc_socketmgr_t *manager, int maxfd,
- fd_set *readfds, fd_set *writefds)
+process_fd(isc_socketmgr_t *manager, int fd, isc_boolean_t readable,
+ isc_boolean_t writeable)
{
- int i;
isc_socket_t *sock;
isc_boolean_t unlock_sock;
-
- REQUIRE(maxfd <= (int)manager->fdsize);
+ int lockid = FDLOCK_ID(fd);
/*
- * Process read/writes on other fds here. Avoid locking
- * and unlocking twice if both reads and writes are possible.
+ * If the socket is going to be closed, don't do more I/O.
*/
- for (i = 0; i < maxfd; i++) {
+ LOCK(&manager->fdlock[lockid]);
+ if (manager->fdstate[fd] == CLOSE_PENDING) {
+ UNLOCK(&manager->fdlock[lockid]);
+
+ (void)unwatch_fd(manager, fd, SELECT_POKE_READ);
+ (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE);
+ return;
+ }
+
+ sock = manager->fds[fd];
+ UNLOCK(&manager->fdlock[lockid]);
+ unlock_sock = ISC_FALSE;
+ if (readable) {
+ if (sock == NULL) {
+ (void)unwatch_fd(manager, fd, SELECT_POKE_READ);
+ goto check_write;
+ }
+ unlock_sock = ISC_TRUE;
+ LOCK(&sock->lock);
+ if (!SOCK_DEAD(sock)) {
+ if (sock->listener)
+ dispatch_accept(sock);
+ else
+ dispatch_recv(sock);
+ }
+ (void)unwatch_fd(manager, fd, SELECT_POKE_READ);
+ }
+check_write:
+ if (writeable) {
+ if (sock == NULL) {
+ (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE);
+ return;
+ }
+ if (!unlock_sock) {
+ unlock_sock = ISC_TRUE;
+ LOCK(&sock->lock);
+ }
+ if (!SOCK_DEAD(sock)) {
+ if (sock->connecting)
+ dispatch_connect(sock);
+ else
+ dispatch_send(sock);
+ }
+ (void)unwatch_fd(manager, fd, SELECT_POKE_WRITE);
+ }
+ if (unlock_sock)
+ UNLOCK(&sock->lock);
+}
+
+#ifdef USE_KQUEUE
+static isc_boolean_t
+process_fds(isc_socketmgr_t *manager, struct kevent *events, int nevents) {
+ int i;
+ isc_boolean_t readable, writable;
+ isc_boolean_t done = ISC_FALSE;
#ifdef ISC_PLATFORM_USETHREADS
- if (i == manager->pipe_fds[0] || i == manager->pipe_fds[1])
+ isc_boolean_t have_ctlevent = ISC_FALSE;
+#endif
+
+ if (nevents == manager->nevents) {
+ /*
+ * This is not an error, but something unexpected. If this
+ * happens, it may indicate the need for increasing
+ * ISC_SOCKET_MAXEVENTS.
+ */
+ manager_log(manager, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_INFO,
+ "maximum number of FD events (%d) received",
+ nevents);
+ }
+
+ for (i = 0; i < nevents; i++) {
+ REQUIRE(events[i].ident < manager->maxsocks);
+#ifdef ISC_PLATFORM_USETHREADS
+ if (events[i].ident == (uintptr_t)manager->pipe_fds[0]) {
+ have_ctlevent = ISC_TRUE;
continue;
-#endif /* ISC_PLATFORM_USETHREADS */
+ }
+#endif
+ readable = ISC_TF(events[i].filter == EVFILT_READ);
+ writable = ISC_TF(events[i].filter == EVFILT_WRITE);
+ process_fd(manager, events[i].ident, readable, writable);
+ }
- if (manager->fdstate[i] == CLOSE_PENDING) {
- manager->fdstate[i] = CLOSED;
- FD_CLR(i, manager->read_fds);
- FD_CLR(i, manager->write_fds);
+#ifdef ISC_PLATFORM_USETHREADS
+ if (have_ctlevent)
+ done = process_ctlfd(manager);
+#endif
- (void)close(i);
+ return (done);
+}
+#elif defined(USE_EPOLL)
+static isc_boolean_t
+process_fds(isc_socketmgr_t *manager, struct epoll_event *events, int nevents) {
+ int i;
+ isc_boolean_t done = ISC_FALSE;
+#ifdef ISC_PLATFORM_USETHREADS
+ isc_boolean_t have_ctlevent = ISC_FALSE;
+#endif
+
+ if (nevents == manager->nevents) {
+ manager_log(manager, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_INFO,
+ "maximum number of FD events (%d) received",
+ nevents);
+ }
+ for (i = 0; i < nevents; i++) {
+ REQUIRE(events[i].data.fd < (int)manager->maxsocks);
+#ifdef ISC_PLATFORM_USETHREADS
+ if (events[i].data.fd == manager->pipe_fds[0]) {
+ have_ctlevent = ISC_TRUE;
continue;
}
-
- sock = manager->fds[i];
- unlock_sock = ISC_FALSE;
- if (FD_ISSET(i, readfds)) {
- if (sock == NULL) {
- FD_CLR(i, manager->read_fds);
- goto check_write;
- }
- unlock_sock = ISC_TRUE;
- LOCK(&sock->lock);
- if (!SOCK_DEAD(sock)) {
- if (sock->listener)
- dispatch_accept(sock);
- else
- dispatch_recv(sock);
- }
- FD_CLR(i, manager->read_fds);
+#endif
+ if ((events[i].events & EPOLLERR) != 0 ||
+ (events[i].events & EPOLLHUP) != 0) {
+ /*
+ * epoll does not set IN/OUT bits on an erroneous
+ * condition, so we need to try both anyway. This is a
+ * bit inefficient, but should be okay for such rare
+ * events. Note also that the read or write attempt
+ * won't block because we use non-blocking sockets.
+ */
+ events[i].events |= (EPOLLIN | EPOLLOUT);
}
- check_write:
- if (FD_ISSET(i, writefds)) {
- if (sock == NULL) {
- FD_CLR(i, manager->write_fds);
- continue;
- }
- if (!unlock_sock) {
- unlock_sock = ISC_TRUE;
- LOCK(&sock->lock);
- }
- if (!SOCK_DEAD(sock)) {
- if (sock->connecting)
- dispatch_connect(sock);
- else
- dispatch_send(sock);
- }
- FD_CLR(i, manager->write_fds);
+ process_fd(manager, events[i].data.fd,
+ (events[i].events & EPOLLIN) != 0,
+ (events[i].events & EPOLLOUT) != 0);
+ }
+
+#ifdef ISC_PLATFORM_USETHREADS
+ if (have_ctlevent)
+ done = process_ctlfd(manager);
+#endif
+
+ return (done);
+}
+#elif defined(USE_DEVPOLL)
+static isc_boolean_t
+process_fds(isc_socketmgr_t *manager, struct pollfd *events, int nevents) {
+ int i;
+ isc_boolean_t done = ISC_FALSE;
+#ifdef ISC_PLATFORM_USETHREADS
+ isc_boolean_t have_ctlevent = ISC_FALSE;
+#endif
+
+ if (nevents == manager->nevents) {
+ manager_log(manager, ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET, ISC_LOG_INFO,
+ "maximum number of FD events (%d) received",
+ nevents);
+ }
+
+ for (i = 0; i < nevents; i++) {
+ REQUIRE(events[i].fd < (int)manager->maxsocks);
+#ifdef ISC_PLATFORM_USETHREADS
+ if (events[i].fd == manager->pipe_fds[0]) {
+ have_ctlevent = ISC_TRUE;
+ continue;
}
- if (unlock_sock)
- UNLOCK(&sock->lock);
+#endif
+ process_fd(manager, events[i].fd,
+ (events[i].events & POLLIN) != 0,
+ (events[i].events & POLLOUT) != 0);
+ }
+
+#ifdef ISC_PLATFORM_USETHREADS
+ if (have_ctlevent)
+ done = process_ctlfd(manager);
+#endif
+
+ return (done);
+}
+#elif defined(USE_SELECT)
+static void
+process_fds(isc_socketmgr_t *manager, int maxfd,
+ fd_set *readfds, fd_set *writefds)
+{
+ int i;
+
+ REQUIRE(maxfd <= (int)manager->maxsocks);
+
+ for (i = 0; i < maxfd; i++) {
+#ifdef ISC_PLATFORM_USETHREADS
+ if (i == manager->pipe_fds[0] || i == manager->pipe_fds[1])
+ continue;
+#endif /* ISC_PLATFORM_USETHREADS */
+ process_fd(manager, i, FD_ISSET(i, readfds),
+ FD_ISSET(i, writefds));
}
}
+#endif
#ifdef ISC_PLATFORM_USETHREADS
+static isc_boolean_t
+process_ctlfd(isc_socketmgr_t *manager) {
+ int msg, fd;
+
+ for (;;) {
+ select_readmsg(manager, &fd, &msg);
+
+ manager_log(manager, IOEVENT,
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_SOCKET,
+ ISC_MSG_WATCHERMSG,
+ "watcher got message %d "
+ "for socket %d"), msg, fd);
+
+ /*
+ * Nothing to read?
+ */
+ if (msg == SELECT_POKE_NOTHING)
+ break;
+
+ /*
+ * Handle shutdown message. We really should
+ * jump out of this loop right away, but
+ * it doesn't matter if we have to do a little
+ * more work first.
+ */
+ if (msg == SELECT_POKE_SHUTDOWN)
+ return (ISC_TRUE);
+
+ /*
+ * This is a wakeup on a socket. Look
+ * at the event queue for both read and write,
+ * and decide if we need to watch on it now
+ * or not.
+ */
+ wakeup_socket(manager, fd, msg);
+ }
+
+ return (ISC_FALSE);
+}
+
/*
* This is the thread that will loop forever, always in a select or poll
* call.
@@ -2364,98 +3079,116 @@ watcher(void *uap) {
isc_boolean_t done;
int ctlfd;
int cc;
- int msg, fd;
+#ifdef USE_KQUEUE
+ const char *fnname = "kevent()";
+#elif defined (USE_EPOLL)
+ const char *fnname = "epoll_wait()";
+#elif defined(USE_DEVPOLL)
+ const char *fnname = "ioctl(DP_POLL)";
+ struct dvpoll dvp;
+#elif defined (USE_SELECT)
+ const char *fnname = "select()";
int maxfd;
+#endif
char strbuf[ISC_STRERRORSIZE];
+#ifdef ISC_SOCKET_USE_POLLWATCH
+ pollstate_t pollstate = poll_idle;
+#endif
/*
* Get the control fd here. This will never change.
*/
- LOCK(&manager->lock);
ctlfd = manager->pipe_fds[0];
-
done = ISC_FALSE;
while (!done) {
do {
+#ifdef USE_KQUEUE
+ cc = kevent(manager->kqueue_fd, NULL, 0,
+ manager->events, manager->nevents, NULL);
+#elif defined(USE_EPOLL)
+ cc = epoll_wait(manager->epoll_fd, manager->events,
+ manager->nevents, -1);
+#elif defined(USE_DEVPOLL)
+ dvp.dp_fds = manager->events;
+ dvp.dp_nfds = manager->nevents;
+#ifndef ISC_SOCKET_USE_POLLWATCH
+ dvp.dp_timeout = -1;
+#else
+ if (pollstate == poll_idle)
+ dvp.dp_timeout = -1;
+ else
+ dvp.dp_timeout = ISC_SOCKET_POLLWATCH_TIMEOUT;
+#endif /* ISC_SOCKET_USE_POLLWATCH */
+ cc = ioctl(manager->devpoll_fd, DP_POLL, &dvp);
+#elif defined(USE_SELECT)
+ LOCK(&manager->lock);
memcpy(manager->read_fds_copy, manager->read_fds,
manager->fd_bufsize);
memcpy(manager->write_fds_copy, manager->write_fds,
manager->fd_bufsize);
maxfd = manager->maxfd + 1;
-
UNLOCK(&manager->lock);
cc = select(maxfd, manager->read_fds_copy,
manager->write_fds_copy, NULL, NULL);
- if (cc < 0) {
- if (!SOFT_ERROR(errno)) {
- isc__strerror(errno, strbuf,
- sizeof(strbuf));
- FATAL_ERROR(__FILE__, __LINE__,
- "select() %s: %s",
- isc_msgcat_get(isc_msgcat,
- ISC_MSGSET_GENERAL,
- ISC_MSG_FAILED,
- "failed"),
- strbuf);
- }
+#endif /* USE_KQUEUE */
+
+ if (cc < 0 && !SOFT_ERROR(errno)) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ FATAL_ERROR(__FILE__, __LINE__,
+ "%s %s: %s", fnname,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"), strbuf);
}
- LOCK(&manager->lock);
+#if defined(USE_DEVPOLL) && defined(ISC_SOCKET_USE_POLLWATCH)
+ if (cc == 0) {
+ if (pollstate == poll_active)
+ pollstate = poll_checking;
+ else if (pollstate == poll_checking)
+ pollstate = poll_idle;
+ } else if (cc > 0) {
+ if (pollstate == poll_checking) {
+ /*
+ * XXX: We'd like to use a more
+ * verbose log level as it's actually an
+ * unexpected event, but the kernel bug
+ * reportedly happens pretty frequently
+ * (and it can also be a false positive)
+ * so it would be just too noisy.
+ */
+ manager_log(manager,
+ ISC_LOGCATEGORY_GENERAL,
+ ISC_LOGMODULE_SOCKET,
+ ISC_LOG_DEBUG(1),
+ ISC_LOG_INFO,
+ "unexpected POLL timeout");
+ }
+ pollstate = poll_active;
+ }
+#endif
} while (cc < 0);
+#if defined(USE_KQUEUE) || defined (USE_EPOLL) || defined (USE_DEVPOLL)
+ done = process_fds(manager, manager->events, cc);
+#elif defined(USE_SELECT)
+ process_fds(manager, maxfd, manager->read_fds_copy,
+ manager->write_fds_copy);
/*
* Process reads on internal, control fd.
*/
- if (FD_ISSET(ctlfd, manager->read_fds_copy)) {
- for (;;) {
- select_readmsg(manager, &fd, &msg);
-
- manager_log(manager, IOEVENT,
- isc_msgcat_get(isc_msgcat,
- ISC_MSGSET_SOCKET,
- ISC_MSG_WATCHERMSG,
- "watcher got message %d"),
- msg);
-
- /*
- * Nothing to read?
- */
- if (msg == SELECT_POKE_NOTHING)
- break;
-
- /*
- * Handle shutdown message. We really should
- * jump out of this loop right away, but
- * it doesn't matter if we have to do a little
- * more work first.
- */
- if (msg == SELECT_POKE_SHUTDOWN) {
- done = ISC_TRUE;
-
- break;
- }
-
- /*
- * This is a wakeup on a socket. Look
- * at the event queue for both read and write,
- * and decide if we need to watch on it now
- * or not.
- */
- wakeup_socket(manager, fd, msg);
- }
- }
-
- process_fds(manager, maxfd, manager->read_fds_copy,
- manager->write_fds_copy);
+ if (FD_ISSET(ctlfd, manager->read_fds_copy))
+ done = process_ctlfd(manager);
+#endif
}
manager_log(manager, TRACE,
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
ISC_MSG_EXITING, "watcher exiting"));
- UNLOCK(&manager->lock);
return ((isc_threadresult_t)0);
}
#endif /* ISC_PLATFORM_USETHREADS */
@@ -2469,69 +3202,187 @@ isc__socketmgr_setreserved(isc_socketmgr_t *manager, isc_uint32_t reserved) {
}
/*
- * Initialize fdsets in socketmgr structure.
+ * Create a new socket manager.
*/
+
static isc_result_t
-create_fdsets(isc_socketmgr_t *manager, isc_mem_t *mctx) {
-#if ISC_SOCKET_FDSETSIZE > FD_SETSIZE
- manager->fdsize = ISC_SOCKET_FDSETSIZE;
- manager->fd_bufsize = howmany(ISC_SOCKET_FDSETSIZE, NFDBITS) *
+setup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
+ isc_result_t result;
+
+#ifdef USE_KQUEUE
+ manager->nevents = ISC_SOCKET_MAXEVENTS;
+ manager->events = isc_mem_get(mctx, sizeof(struct kevent) *
+ manager->nevents);
+ if (manager->events == NULL)
+ return (ISC_R_NOMEMORY);
+ manager->kqueue_fd = kqueue();
+ if (manager->kqueue_fd == -1) {
+ result = isc__errno2result(errno);
+ isc_mem_put(mctx, manager->events,
+ sizeof(struct kevent) * manager->nevents);
+ return (result);
+ }
+
+#ifdef ISC_PLATFORM_USETHREADS
+ result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
+ if (result != ISC_R_SUCCESS) {
+ close(manager->kqueue_fd);
+ isc_mem_put(mctx, manager->events,
+ sizeof(struct kevent) * manager->nevents);
+ return (result);
+ }
+#endif /* ISC_PLATFORM_USETHREADS */
+#elif defined(USE_EPOLL)
+ manager->nevents = ISC_SOCKET_MAXEVENTS;
+ manager->events = isc_mem_get(mctx, sizeof(struct epoll_event) *
+ manager->nevents);
+ if (manager->events == NULL)
+ return (ISC_R_NOMEMORY);
+ manager->epoll_fd = epoll_create(manager->nevents);
+ if (manager->epoll_fd == -1) {
+ result = isc__errno2result(errno);
+ isc_mem_put(mctx, manager->events,
+ sizeof(struct epoll_event) * manager->nevents);
+ return (result);
+ }
+#ifdef ISC_PLATFORM_USETHREADS
+ result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
+ if (result != ISC_R_SUCCESS) {
+ close(manager->epoll_fd);
+ isc_mem_put(mctx, manager->events,
+ sizeof(struct epoll_event) * manager->nevents);
+ return (result);
+ }
+#endif /* ISC_PLATFORM_USETHREADS */
+#elif defined(USE_DEVPOLL)
+ /*
+ * XXXJT: /dev/poll seems to reject large numbers of events,
+ * so we should be careful about redefining ISC_SOCKET_MAXEVENTS.
+ */
+ manager->nevents = ISC_SOCKET_MAXEVENTS;
+ manager->events = isc_mem_get(mctx, sizeof(struct pollfd) *
+ manager->nevents);
+ if (manager->events == NULL)
+ return (ISC_R_NOMEMORY);
+ /*
+ * Note: fdpollinfo should be able to support all possible FDs, so
+ * it must have maxsocks entries (not nevents).
+ */
+ manager->fdpollinfo = isc_mem_get(mctx, sizeof(pollinfo_t) *
+ manager->maxsocks);
+ if (manager->fdpollinfo == NULL) {
+ isc_mem_put(mctx, manager->events,
+ sizeof(pollinfo_t) * manager->maxsocks);
+ return (ISC_R_NOMEMORY);
+ }
+ memset(manager->fdpollinfo, 0, sizeof(pollinfo_t) * manager->maxsocks);
+ manager->devpoll_fd = open("/dev/poll", O_RDWR);
+ if (manager->devpoll_fd == -1) {
+ result = isc__errno2result(errno);
+ isc_mem_put(mctx, manager->events,
+ sizeof(struct pollfd) * manager->nevents);
+ isc_mem_put(mctx, manager->fdpollinfo,
+ sizeof(pollinfo_t) * manager->maxsocks);
+ return (result);
+ }
+#ifdef ISC_PLATFORM_USETHREADS
+ result = watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
+ if (result != ISC_R_SUCCESS) {
+ close(manager->devpoll_fd);
+ isc_mem_put(mctx, manager->events,
+ sizeof(struct pollfd) * manager->nevents);
+ isc_mem_put(mctx, manager->fdpollinfo,
+ sizeof(pollinfo_t) * manager->maxsocks);
+ return (result);
+ }
+#endif /* ISC_PLATFORM_USETHREADS */
+#elif defined(USE_SELECT)
+ UNUSED(result);
+
+#if ISC_SOCKET_MAXSOCKETS > FD_SETSIZE
+ /*
+ * Note: this code should also cover the case of MAXSOCKETS <=
+ * FD_SETSIZE, but we separate the cases to avoid possible portability
+ * issues regarding howmany() and the actual representation of fd_set.
+ */
+ manager->fd_bufsize = howmany(manager->maxsocks, NFDBITS) *
sizeof(fd_mask);
#else
- manager->fdsize = FD_SETSIZE;
manager->fd_bufsize = sizeof(fd_set);
#endif
- manager->fds = NULL;
- manager->fdstate = NULL;
manager->read_fds = NULL;
manager->read_fds_copy = NULL;
manager->write_fds = NULL;
manager->write_fds_copy = NULL;
- manager->fds = isc_mem_get(mctx,
- manager->fdsize * sizeof(manager->fds[0]));
- if (manager->fds == NULL)
- goto fail;
-
- manager->fdstate = isc_mem_get(mctx, manager->fdsize *
- sizeof(manager->fdstate[0]));
- if (manager->fdstate == NULL)
- goto fail;
-
manager->read_fds = isc_mem_get(mctx, manager->fd_bufsize);
- if (manager->read_fds == NULL)
- goto fail;
- manager->read_fds_copy = isc_mem_get(mctx, manager->fd_bufsize);
- if (manager->read_fds_copy == NULL)
- goto fail;
- manager->write_fds = isc_mem_get(mctx, manager->fd_bufsize);
- if (manager->write_fds == NULL)
- goto fail;
- manager->write_fds_copy = isc_mem_get(mctx, manager->fd_bufsize);
- if (manager->write_fds_copy == NULL)
- goto fail;
+ if (manager->read_fds != NULL)
+ manager->read_fds_copy = isc_mem_get(mctx, manager->fd_bufsize);
+ if (manager->read_fds_copy != NULL)
+ manager->write_fds = isc_mem_get(mctx, manager->fd_bufsize);
+ if (manager->write_fds != NULL) {
+ manager->write_fds_copy = isc_mem_get(mctx,
+ manager->fd_bufsize);
+ }
+ if (manager->write_fds_copy == NULL) {
+ if (manager->write_fds != NULL) {
+ isc_mem_put(mctx, manager->write_fds,
+ manager->fd_bufsize);
+ }
+ if (manager->read_fds_copy != NULL) {
+ isc_mem_put(mctx, manager->read_fds_copy,
+ manager->fd_bufsize);
+ }
+ if (manager->read_fds != NULL) {
+ isc_mem_put(mctx, manager->read_fds,
+ manager->fd_bufsize);
+ }
+ return (ISC_R_NOMEMORY);
+ }
+ memset(manager->read_fds, 0, manager->fd_bufsize);
+ memset(manager->write_fds, 0, manager->fd_bufsize);
- return (ISC_R_SUCCESS);
+#ifdef ISC_PLATFORM_USETHREADS
+ (void)watch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
+ manager->maxfd = manager->pipe_fds[0];
+#else /* ISC_PLATFORM_USETHREADS */
+ manager->maxfd = 0;
+#endif /* ISC_PLATFORM_USETHREADS */
+#endif /* USE_KQUEUE */
- fail:
- cleanup_fdsets(manager, mctx);
- return (ISC_R_NOMEMORY);
+ return (ISC_R_SUCCESS);
}
-/*
- * Clean up fdsets in socketmgr structure.
- */
static void
-cleanup_fdsets(isc_socketmgr_t *manager, isc_mem_t *mctx) {
- if (manager->fds != NULL) {
- isc_mem_put(mctx, manager->fds,
- manager->fdsize * sizeof(manager->fds[0]));
- }
- if (manager->fdstate != NULL) {
- isc_mem_put(mctx, manager->fdstate,
- manager->fdsize * sizeof(manager->fdstate[0]));
+cleanup_watcher(isc_mem_t *mctx, isc_socketmgr_t *manager) {
+#ifdef ISC_PLATFORM_USETHREADS
+ isc_result_t result;
+
+ result = unwatch_fd(manager, manager->pipe_fds[0], SELECT_POKE_READ);
+ if (result != ISC_R_SUCCESS) {
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "epoll_ctl(DEL) %s",
+ isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED, "failed"));
}
+#endif /* ISC_PLATFORM_USETHREADS */
+
+#ifdef USE_KQUEUE
+ close(manager->kqueue_fd);
+ isc_mem_put(mctx, manager->events,
+ sizeof(struct kevent) * manager->nevents);
+#elif defined(USE_EPOLL)
+ close(manager->epoll_fd);
+ isc_mem_put(mctx, manager->events,
+ sizeof(struct epoll_event) * manager->nevents);
+#elif defined(USE_DEVPOLL)
+ close(manager->devpoll_fd);
+ isc_mem_put(mctx, manager->events,
+ sizeof(struct pollfd) * manager->nevents);
+ isc_mem_put(mctx, manager->fdpollinfo,
+ sizeof(pollinfo_t) * manager->maxsocks);
+#elif defined(USE_SELECT)
if (manager->read_fds != NULL)
isc_mem_put(mctx, manager->read_fds, manager->fd_bufsize);
if (manager->read_fds_copy != NULL)
@@ -2540,13 +3391,19 @@ cleanup_fdsets(isc_socketmgr_t *manager, isc_mem_t *mctx) {
isc_mem_put(mctx, manager->write_fds, manager->fd_bufsize);
if (manager->write_fds_copy != NULL)
isc_mem_put(mctx, manager->write_fds_copy, manager->fd_bufsize);
+#endif /* USE_KQUEUE */
}
-/*
- * Create a new socket manager.
- */
isc_result_t
isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
+ return (isc_socketmgr_create2(mctx, managerp, 0));
+}
+
+isc_result_t
+isc_socketmgr_create2(isc_mem_t *mctx, isc_socketmgr_t **managerp,
+ unsigned int maxsocks)
+{
+ int i;
isc_socketmgr_t *manager;
#ifdef ISC_PLATFORM_USETHREADS
char strbuf[ISC_STRERRORSIZE];
@@ -2557,43 +3414,71 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
#ifndef ISC_PLATFORM_USETHREADS
if (socketmgr != NULL) {
+ /* Don't allow maxsocks to be updated */
+ if (maxsocks > 0 && socketmgr->maxsocks != maxsocks)
+ return (ISC_R_EXISTS);
+
socketmgr->refs++;
*managerp = socketmgr;
return (ISC_R_SUCCESS);
}
#endif /* ISC_PLATFORM_USETHREADS */
+ if (maxsocks == 0)
+ maxsocks = ISC_SOCKET_MAXSOCKETS;
+
manager = isc_mem_get(mctx, sizeof(*manager));
if (manager == NULL)
return (ISC_R_NOMEMORY);
- result = create_fdsets(manager, mctx);
- if (result != ISC_R_SUCCESS) {
- cleanup_fdsets(manager, mctx);
- isc_mem_put(mctx, manager, sizeof(*manager));
- return (result);
+ /* zero-clear so that necessary cleanup on failure will be easy */
+ memset(manager, 0, sizeof(*manager));
+ manager->maxsocks = maxsocks;
+ manager->reserved = 0;
+ manager->fds = isc_mem_get(mctx,
+ manager->maxsocks * sizeof(isc_socket_t *));
+ if (manager->fds == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto free_manager;
+ }
+ manager->fdstate = isc_mem_get(mctx, manager->maxsocks * sizeof(int));
+ if (manager->fds == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto free_manager;
}
manager->magic = SOCKET_MANAGER_MAGIC;
manager->mctx = NULL;
- memset(manager->fds, 0, sizeof(manager->fds[0]) * manager->fdsize);
+ memset(manager->fds, 0, manager->maxsocks * sizeof(isc_socket_t *));
ISC_LIST_INIT(manager->socklist);
result = isc_mutex_init(&manager->lock);
- if (result != ISC_R_SUCCESS) {
- cleanup_fdsets(manager, mctx);
- isc_mem_put(mctx, manager, sizeof(*manager));
- return (result);
+ if (result != ISC_R_SUCCESS)
+ goto free_manager;
+ manager->fdlock = isc_mem_get(mctx, FDLOCK_COUNT * sizeof(isc_mutex_t));
+ if (manager->fdlock == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto cleanup_lock;
}
+ for (i = 0; i < FDLOCK_COUNT; i++) {
+ result = isc_mutex_init(&manager->fdlock[i]);
+ if (result != ISC_R_SUCCESS) {
+ while (--i >= 0)
+ DESTROYLOCK(&manager->fdlock[i]);
+ isc_mem_put(mctx, manager->fdlock,
+ FDLOCK_COUNT * sizeof(isc_mutex_t));
+ manager->fdlock = NULL;
+ goto cleanup_lock;
+ }
+ }
+
#ifdef ISC_PLATFORM_USETHREADS
if (isc_condition_init(&manager->shutdown_ok) != ISC_R_SUCCESS) {
- cleanup_fdsets(manager, mctx);
- DESTROYLOCK(&manager->lock);
- isc_mem_put(mctx, manager, sizeof(*manager));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_condition_init() %s",
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
ISC_MSG_FAILED, "failed"));
- return (ISC_R_UNEXPECTED);
+ result = ISC_R_UNEXPECTED;
+ goto cleanup_lock;
}
/*
@@ -2601,17 +3486,14 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
* select/poll loop when something internal needs to be done.
*/
if (pipe(manager->pipe_fds) != 0) {
- cleanup_fdsets(manager, mctx);
- DESTROYLOCK(&manager->lock);
- isc_mem_put(mctx, manager, sizeof(*manager));
isc__strerror(errno, strbuf, sizeof(strbuf));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"pipe() %s: %s",
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
ISC_MSG_FAILED, "failed"),
strbuf);
-
- return (ISC_R_UNEXPECTED);
+ result = ISC_R_UNEXPECTED;
+ goto cleanup_condition;
}
RUNTIME_CHECK(make_nonblock(manager->pipe_fds[0]) == ISC_R_SUCCESS);
@@ -2625,33 +3507,23 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
/*
* Set up initial state for the select loop
*/
- memset(manager->read_fds, 0, manager->fd_bufsize);
- memset(manager->write_fds, 0, manager->fd_bufsize);
-#ifdef ISC_PLATFORM_USETHREADS
- FD_SET(manager->pipe_fds[0], manager->read_fds);
- manager->maxfd = manager->pipe_fds[0];
-#else /* ISC_PLATFORM_USETHREADS */
- manager->maxfd = 0;
-#endif /* ISC_PLATFORM_USETHREADS */
- manager->reserved = 0;
- memset(manager->fdstate, 0,
- manager->fdsize * sizeof(manager->fdstate[0]));
-
+ result = setup_watcher(mctx, manager);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+ memset(manager->fdstate, 0, manager->maxsocks * sizeof(int));
#ifdef ISC_PLATFORM_USETHREADS
/*
* Start up the select/poll thread.
*/
if (isc_thread_create(watcher, manager, &manager->watcher) !=
ISC_R_SUCCESS) {
- (void)close(manager->pipe_fds[0]);
- (void)close(manager->pipe_fds[1]);
- DESTROYLOCK(&manager->lock);
- isc_mem_put(mctx, manager, sizeof(*manager));
UNEXPECTED_ERROR(__FILE__, __LINE__,
"isc_thread_create() %s",
isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
ISC_MSG_FAILED, "failed"));
- return (ISC_R_UNEXPECTED);
+ cleanup_watcher(mctx, manager);
+ result = ISC_R_UNEXPECTED;
+ goto cleanup;
}
#endif /* ISC_PLATFORM_USETHREADS */
isc_mem_attach(mctx, &manager->mctx);
@@ -2662,6 +3534,52 @@ isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp) {
*managerp = manager;
return (ISC_R_SUCCESS);
+
+cleanup:
+#ifdef ISC_PLATFORM_USETHREADS
+ (void)close(manager->pipe_fds[0]);
+ (void)close(manager->pipe_fds[1]);
+#endif /* ISC_PLATFORM_USETHREADS */
+
+#ifdef ISC_PLATFORM_USETHREADS
+cleanup_condition:
+ (void)isc_condition_destroy(&manager->shutdown_ok);
+#endif /* ISC_PLATFORM_USETHREADS */
+
+
+cleanup_lock:
+ if (manager->fdlock != NULL) {
+ for (i = 0; i < FDLOCK_COUNT; i++)
+ DESTROYLOCK(&manager->fdlock[i]);
+ }
+ DESTROYLOCK(&manager->lock);
+
+free_manager:
+ if (manager->fdlock != NULL) {
+ isc_mem_put(mctx, manager->fdlock,
+ FDLOCK_COUNT * sizeof(isc_mutex_t));
+ }
+ if (manager->fdstate != NULL) {
+ isc_mem_put(mctx, manager->fdstate,
+ manager->maxsocks * sizeof(int));
+ }
+ if (manager->fds != NULL) {
+ isc_mem_put(mctx, manager->fds,
+ manager->maxsocks * sizeof(isc_socket_t *));
+ }
+ isc_mem_put(mctx, manager, sizeof(*manager));
+
+ return (result);
+}
+
+isc_result_t
+isc_socketmgr_getmaxsockets(isc_socketmgr_t *manager, unsigned int *nsockp) {
+ REQUIRE(VALID_MANAGER(manager));
+ REQUIRE(nsockp != NULL);
+
+ *nsockp = manager->maxsocks;
+
+ return (ISC_R_SUCCESS);
}
void
@@ -2735,18 +3653,30 @@ isc_socketmgr_destroy(isc_socketmgr_t **managerp) {
/*
* Clean up.
*/
+ cleanup_watcher(manager->mctx, manager);
+
#ifdef ISC_PLATFORM_USETHREADS
(void)close(manager->pipe_fds[0]);
(void)close(manager->pipe_fds[1]);
(void)isc_condition_destroy(&manager->shutdown_ok);
#endif /* ISC_PLATFORM_USETHREADS */
- for (i = 0; i < (int)manager->fdsize; i++)
- if (manager->fdstate[i] == CLOSE_PENDING)
+ for (i = 0; i < (int)manager->maxsocks; i++)
+ if (manager->fdstate[i] == CLOSE_PENDING) /* no need to lock */
(void)close(i);
+ isc_mem_put(manager->mctx, manager->fds,
+ manager->maxsocks * sizeof(isc_socket_t *));
+ isc_mem_put(manager->mctx, manager->fdstate,
+ manager->maxsocks * sizeof(int));
+
+ if (manager->fdlock != NULL) {
+ for (i = 0; i < FDLOCK_COUNT; i++)
+ DESTROYLOCK(&manager->fdlock[i]);
+ isc_mem_put(manager->mctx, manager->fdlock,
+ FDLOCK_COUNT * sizeof(isc_mutex_t));
+ }
DESTROYLOCK(&manager->lock);
- cleanup_fdsets(manager, manager->mctx);
manager->magic = 0;
mctx= manager->mctx;
isc_mem_put(mctx, manager, sizeof(*manager));
@@ -2799,7 +3729,7 @@ socket_recv(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
* Enqueue the request. If the socket was previously not being
* watched, poke the watcher to start paying attention to it.
*/
- if (ISC_LIST_EMPTY(sock->recv_list))
+ if (ISC_LIST_EMPTY(sock->recv_list) && !sock->pending_recv)
select_poke(sock->manager, sock->fd, SELECT_POKE_READ);
ISC_LIST_ENQUEUE(sock->recv_list, dev, ev_link);
@@ -2996,7 +3926,8 @@ socket_send(isc_socket_t *sock, isc_socketevent_t *dev, isc_task_t *task,
* not being watched, poke the watcher to start
* paying attention to it.
*/
- if (ISC_LIST_EMPTY(sock->send_list))
+ if (ISC_LIST_EMPTY(sock->send_list) &&
+ !sock->pending_send)
select_poke(sock->manager, sock->fd,
SELECT_POKE_WRITE);
ISC_LIST_ENQUEUE(sock->send_list, dev, ev_link);
@@ -3286,7 +4217,7 @@ isc_socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm,
} else
strcpy(path, ".");
#endif
-
+
if (chmod(path, perm) < 0) {
isc__strerror(errno, strbuf, sizeof(strbuf));
isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
@@ -3315,7 +4246,7 @@ isc_socket_permunix(isc_sockaddr_t *sockaddr, isc_uint32_t perm,
}
isc_result_t
-isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
+isc_socket_bind(isc_socket_t *sock, isc_sockaddr_t *sockaddr,
unsigned int options) {
char strbuf[ISC_STRERRORSIZE];
int on = 1;
@@ -3446,7 +4377,7 @@ isc_socket_listen(isc_socket_t *sock, unsigned int backlog) {
}
/*
- * This should try to do agressive accept() XXXMLG
+ * This should try to do aggressive accept() XXXMLG
*/
isc_result_t
isc_socket_accept(isc_socket_t *sock,
@@ -3557,6 +4488,16 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
sock->address = *addr;
cc = connect(sock->fd, &addr->type.sa, addr->length);
if (cc < 0) {
+ /*
+ * HP-UX "fails" to connect a UDP socket and sets errno to
+ * EINPROGRESS if it's non-blocking. We'd rather regard this as
+ * a success and let the user detect it if it's really an error
+ * at the time of sending a packet on the socket.
+ */
+ if (sock->type == isc_sockettype_udp && errno == EINPROGRESS) {
+ cc = 0;
+ goto success;
+ }
if (SOFT_ERROR(errno) || errno == EINPROGRESS)
goto queue;
@@ -3598,6 +4539,7 @@ isc_socket_connect(isc_socket_t *sock, isc_sockaddr_t *addr,
/*
* If connect completed, fire off the done event.
*/
+ success:
if (cc == 0) {
sock->connected = 1;
sock->bound = 1;
@@ -3957,37 +4899,107 @@ isc_socket_ipv6only(isc_socket_t *sock, isc_boolean_t yes) {
#ifdef IPV6_V6ONLY
if (sock->pf == AF_INET6) {
- (void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY,
- (void *)&onoff, sizeof(onoff));
+ if (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY,
+ (void *)&onoff, sizeof(int)) < 0) {
+ char strbuf[ISC_STRERRORSIZE];
+
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "setsockopt(%d, IPV6_V6ONLY) "
+ "%s: %s", sock->fd,
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ }
}
+ FIX_IPV6_RECVPKTINFO(sock); /* AIX */
#endif
}
#ifndef ISC_PLATFORM_USETHREADS
-void
-isc__socketmgr_getfdsets(fd_set **readset, fd_set **writeset, int *maxfd) {
+/* In our assumed scenario, we can simply use a single static object. */
+static isc_socketwait_t swait_private;
+
+int
+isc__socketmgr_waitevents(struct timeval *tvp, isc_socketwait_t **swaitp) {
+ int n;
+#ifdef USE_KQUEUE
+ struct timespec ts, *tsp;
+#endif
+#ifdef USE_EPOLL
+ int timeout;
+#endif
+#ifdef USE_DEVPOLL
+ struct dvpoll dvp;
+#endif
+
+ REQUIRE(swaitp != NULL && *swaitp == NULL);
+
if (socketmgr == NULL)
- *maxfd = 0;
- else {
- /* Prepare duplicates of fd_sets, as select() will modify */
- memcpy(socketmgr->read_fds_copy, socketmgr->read_fds,
- socketmgr->fd_bufsize);
- memcpy(socketmgr->write_fds_copy, socketmgr->write_fds,
- socketmgr->fd_bufsize);
- *readset = socketmgr->read_fds_copy;
- *writeset = socketmgr->write_fds_copy;
- *maxfd = socketmgr->maxfd + 1;
- }
+ return (0);
+
+#ifdef USE_KQUEUE
+ if (tvp != NULL) {
+ ts.tv_sec = tvp->tv_sec;
+ ts.tv_nsec = tvp->tv_usec * 1000;
+ tsp = &ts;
+ } else
+ tsp = NULL;
+ swait_private.nevents = kevent(socketmgr->kqueue_fd, NULL, 0,
+ socketmgr->events, socketmgr->nevents,
+ tsp);
+ n = swait_private.nevents;
+#elif defined(USE_EPOLL)
+ if (tvp != NULL)
+ timeout = tvp->tv_sec * 1000 + (tvp->tv_usec + 999) / 1000;
+ else
+ timeout = -1;
+ swait_private.nevents = epoll_wait(socketmgr->epoll_fd,
+ socketmgr->events,
+ socketmgr->nevents, timeout);
+ n = swait_private.nevents;
+#elif defined(USE_DEVPOLL)
+ dvp.dp_fds = socketmgr->events;
+ dvp.dp_nfds = socketmgr->nevents;
+ if (tvp != NULL) {
+ dvp.dp_timeout = tvp->tv_sec * 1000 +
+ (tvp->tv_usec + 999) / 1000;
+ } else
+ dvp.dp_timeout = -1;
+ swait_private.nevents = ioctl(socketmgr->devpoll_fd, DP_POLL, &dvp);
+ n = swait_private.nevents;
+#elif defined(USE_SELECT)
+ memcpy(socketmgr->read_fds_copy, socketmgr->read_fds,
+ socketmgr->fd_bufsize);
+ memcpy(socketmgr->write_fds_copy, socketmgr->write_fds,
+ socketmgr->fd_bufsize);
+
+ swait_private.readset = socketmgr->read_fds_copy;
+ swait_private.writeset = socketmgr->write_fds_copy;
+ swait_private.maxfd = socketmgr->maxfd + 1;
+
+ n = select(swait_private.maxfd, swait_private.readset,
+ swait_private.writeset, NULL, tvp);
+#endif
+
+ *swaitp = &swait_private;
+ return (n);
}
isc_result_t
-isc__socketmgr_dispatch(fd_set *readset, fd_set *writeset, int maxfd) {
- isc_socketmgr_t *manager = socketmgr;
+isc__socketmgr_dispatch(isc_socketwait_t *swait) {
+ REQUIRE(swait == &swait_private);
- if (manager == NULL)
+ if (socketmgr == NULL)
return (ISC_R_NOTFOUND);
- process_fds(manager, maxfd, readset, writeset);
+#if defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL)
+ (void)process_fds(socketmgr, socketmgr->events, swait->nevents);
return (ISC_R_SUCCESS);
+#elif defined(USE_SELECT)
+ process_fds(socketmgr, swait->maxfd, swait->readset, swait->writeset);
+ return (ISC_R_SUCCESS);
+#endif
}
#endif /* ISC_PLATFORM_USETHREADS */
diff --git a/lib/isc/unix/socket_p.h b/lib/isc/unix/socket_p.h
index 4f9cf27..b7da860 100644
--- a/lib/isc/unix/socket_p.h
+++ b/lib/isc/unix/socket_p.h
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 2000, 2001 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: socket_p.h,v 1.7.18.2.52.1 2008/07/29 04:47:31 each Exp $ */
+/* $Id: socket_p.h,v 1.7.18.4 2008/06/24 23:45:55 tbox Exp $ */
#ifndef ISC_SOCKET_P_H
#define ISC_SOCKET_P_H
@@ -26,10 +26,7 @@
#include <sys/select.h>
#endif
-void
-isc__socketmgr_getfdsets(fd_set **readset, fd_set **writeset, int *maxfd);
-
-isc_result_t
-isc__socketmgr_dispatch(fd_set *readset, fd_set *writeset, int maxfd);
-
+typedef struct isc_socketwait isc_socketwait_t;
+int isc__socketmgr_waitevents(struct timeval *, isc_socketwait_t **);
+isc_result_t isc__socketmgr_dispatch(isc_socketwait_t *);
#endif /* ISC_SOCKET_P_H */
diff --git a/lib/isc/unix/time.c b/lib/isc/unix/time.c
index bac24d7..facc12b 100644
--- a/lib/isc/unix/time.c
+++ b/lib/isc/unix/time.c
@@ -1,8 +1,8 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004, 2005, 2008 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1998-2001, 2003 Internet Software Consortium.
*
- * Permission to use, copy, modify, and distribute this software for any
+ * 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.
*
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: time.c,v 1.47.18.2 2005/04/29 00:17:09 marka Exp $ */
+/* $Id: time.c,v 1.47.18.4 2008/02/18 23:46:01 tbox Exp $ */
/*! \file */
@@ -227,7 +227,7 @@ isc_time_nowplusinterval(isc_time_t *t, const isc_interval_t *i) {
t->seconds = tv.tv_sec + i->seconds;
t->nanoseconds = tv.tv_usec * NS_PER_US + i->nanoseconds;
- if (t->nanoseconds > NS_PER_S) {
+ if (t->nanoseconds >= NS_PER_S) {
t->seconds++;
t->nanoseconds -= NS_PER_S;
}
@@ -410,5 +410,5 @@ isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len) {
snprintf(buf + flen, len - flen,
".%03u", t->nanoseconds / 1000000);
else
- snprintf(buf, len, "99-Bad-9999 99:99:99.999");
+ snprintf(buf, len, "99-Bad-9999 99:99:99.999");
}
diff --git a/lib/isccfg/api b/lib/isccfg/api
index d94beab..510e9a9 100644
--- a/lib/isccfg/api
+++ b/lib/isccfg/api
@@ -1,3 +1,3 @@
LIBINTERFACE = 30
-LIBREVISION = 4
+LIBREVISION = 5
LIBAGE = 0
diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c
index b04b3ab..a13d0a5 100644
--- a/lib/isccfg/namedconf.c
+++ b/lib/isccfg/namedconf.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: namedconf.c,v 1.30.18.38.50.2 2008/07/23 23:48:17 tbox Exp $ */
+/* $Id: namedconf.c,v 1.30.18.43 2008/09/04 08:03:08 marka Exp $ */
/*! \file */
@@ -36,7 +36,7 @@
/*% Check a return value. */
#define CHECK(op) \
- do { result = (op); \
+ do { result = (op); \
if (result != ISC_R_SUCCESS) goto cleanup; \
} while (0)
@@ -247,7 +247,7 @@ static cfg_type_t cfg_type_pubkey = {
* Note that the old parser allows quotes around the RR type names.
*/
static cfg_type_t cfg_type_rrtypelist = {
- "rrtypelist", cfg_parse_spacelist, cfg_print_spacelist, cfg_doc_terminal,
+ "rrtypelist", cfg_parse_spacelist, cfg_print_spacelist, cfg_doc_terminal,
&cfg_rep_list, &cfg_type_astring
};
@@ -269,7 +269,7 @@ static cfg_type_t cfg_type_matchtype = {
*/
static cfg_tuplefielddef_t grant_fields[] = {
{ "mode", &cfg_type_mode, 0 },
- { "identity", &cfg_type_astring, 0 }, /* domain name */
+ { "identity", &cfg_type_astring, 0 }, /* domain name */
{ "matchtype", &cfg_type_matchtype, 0 },
{ "name", &cfg_type_astring, 0 }, /* domain name */
{ "types", &cfg_type_rrtypelist, 0 },
@@ -363,7 +363,7 @@ static cfg_tuplefielddef_t rrsetorderingelement_fields[] = {
{ "class", &cfg_type_optional_wild_class, 0 },
{ "type", &cfg_type_optional_wild_type, 0 },
{ "name", &cfg_type_optional_wild_name, 0 },
- { "order", &cfg_type_ustring, 0 }, /* must be literal "order" */
+ { "order", &cfg_type_ustring, 0 }, /* must be literal "order" */
{ "ordering", &cfg_type_ustring, 0 },
{ NULL, NULL, 0 }
};
@@ -544,11 +544,19 @@ static cfg_type_t cfg_type_serverid = {
/*%
* Port list.
*/
+static cfg_tuplefielddef_t porttuple_fields[] = {
+ { "loport", &cfg_type_uint32, 0 },
+ { "hiport", &cfg_type_uint32, 0 },
+ { NULL, NULL, 0 }
+};
+static cfg_type_t cfg_type_porttuple = {
+ "porttuple", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
+ &cfg_rep_tuple, porttuple_fields
+};
+
static isc_result_t
-parse_port(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+parse_port(cfg_parser_t *pctx, cfg_obj_t **ret) {
isc_result_t result;
-
- UNUSED(type);
CHECK(cfg_parse_uint32(pctx, NULL, ret));
if ((*ret)->value.uint32 > 0xffff) {
@@ -556,18 +564,60 @@ parse_port(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
cfg_obj_destroy(pctx, ret);
result = ISC_R_RANGE;
}
+
+ cleanup:
+ return (result);
+}
+
+static isc_result_t
+parse_portrange(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
+ isc_result_t result;
+ cfg_obj_t *obj = NULL;
+
+ UNUSED(type);
+
+ CHECK(cfg_peektoken(pctx, ISC_LEXOPT_NUMBER | ISC_LEXOPT_CNUMBER));
+ if (pctx->token.type == isc_tokentype_number)
+ CHECK(parse_port(pctx, ret));
+ else {
+ CHECK(cfg_gettoken(pctx, 0));
+ if (pctx->token.type != isc_tokentype_string ||
+ strcasecmp(TOKEN_STRING(pctx), "range") != 0) {
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
+ "expected integer or 'range'");
+ return (ISC_R_UNEXPECTEDTOKEN);
+ }
+ CHECK(cfg_create_tuple(pctx, &cfg_type_porttuple, &obj));
+ CHECK(parse_port(pctx, &obj->value.tuple[0]));
+ CHECK(parse_port(pctx, &obj->value.tuple[1]));
+ if (obj->value.tuple[0]->value.uint32 >
+ obj->value.tuple[1]->value.uint32) {
+ cfg_parser_error(pctx, CFG_LOG_NOPREP,
+ "low port '%u' must not be larger "
+ "than high port",
+ obj->value.tuple[0]->value.uint32);
+ result = ISC_R_RANGE;
+ goto cleanup;
+ }
+ *ret = obj;
+ obj = NULL;
+ }
+
cleanup:
+ if (obj != NULL)
+ cfg_obj_destroy(pctx, &obj);
return (result);
}
-static cfg_type_t cfg_type_port = {
- "port", parse_port, NULL, cfg_doc_terminal,
+static cfg_type_t cfg_type_portrange = {
+ "portrange", parse_portrange, NULL, cfg_doc_terminal,
NULL, NULL
};
static cfg_type_t cfg_type_bracketed_portlist = {
- "bracketed_sockaddrlist", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list,
- &cfg_rep_list, &cfg_type_port
+ "bracketed_sockaddrlist", cfg_parse_bracketed_list,
+ cfg_print_bracketed_list, cfg_doc_bracketed_list,
+ &cfg_rep_list, &cfg_type_portrange
};
/*%
@@ -595,7 +645,7 @@ namedconf_or_view_clauses[] = {
{ "key", &cfg_type_key, CFG_CLAUSEFLAG_MULTI },
{ "zone", &cfg_type_zone, CFG_CLAUSEFLAG_MULTI },
/* only 1 DLZ per view allowed */
- { "dlz", &cfg_type_dynamically_loadable_zones, 0 },
+ { "dlz", &cfg_type_dynamically_loadable_zones, 0 },
{ "server", &cfg_type_server, CFG_CLAUSEFLAG_MULTI },
{ "trusted-keys", &cfg_type_trustedkeys, CFG_CLAUSEFLAG_MULTI },
{ NULL, NULL, 0 }
@@ -606,6 +656,8 @@ namedconf_or_view_clauses[] = {
*/
static cfg_clausedef_t
options_clauses[] = {
+ { "use-v4-udp-ports", &cfg_type_bracketed_portlist, 0 },
+ { "use-v6-udp-ports", &cfg_type_bracketed_portlist, 0 },
{ "avoid-v4-udp-ports", &cfg_type_bracketed_portlist, 0 },
{ "avoid-v6-udp-ports", &cfg_type_bracketed_portlist, 0 },
{ "blackhole", &cfg_type_bracketed_aml, 0 },
@@ -684,9 +736,9 @@ static cfg_type_t cfg_type_disablealgorithm = {
};
static cfg_tuplefielddef_t mustbesecure_fields[] = {
- { "name", &cfg_type_astring, 0 },
- { "value", &cfg_type_boolean, 0 },
- { NULL, NULL, 0 }
+ { "name", &cfg_type_astring, 0 },
+ { "value", &cfg_type_boolean, 0 },
+ { NULL, NULL, 0 }
};
static cfg_type_t cfg_type_mustbesecure = {
@@ -911,7 +963,7 @@ view_clausesets[] = {
namedconf_or_view_clauses,
view_clauses,
zone_clauses,
- dynamically_loadable_zones_clauses,
+ dynamically_loadable_zones_clauses,
NULL
};
static cfg_type_t cfg_type_viewopts = {
@@ -926,22 +978,22 @@ zone_clausesets[] = {
NULL
};
static cfg_type_t cfg_type_zoneopts = {
- "zoneopts", cfg_parse_map, cfg_print_map,
+ "zoneopts", cfg_parse_map, cfg_print_map,
cfg_doc_map, &cfg_rep_map, zone_clausesets };
-
+
/*% The "dynamically loadable zones" statement syntax. */
-
+
static cfg_clausedef_t *
dynamically_loadable_zones_clausesets[] = {
dynamically_loadable_zones_clauses,
- NULL
+ NULL
};
static cfg_type_t cfg_type_dynamically_loadable_zones_opts = {
- "dynamically_loadable_zones_opts", cfg_parse_map,
+ "dynamically_loadable_zones_opts", cfg_parse_map,
cfg_print_map, cfg_doc_map, &cfg_rep_map,
- dynamically_loadable_zones_clausesets
+ dynamically_loadable_zones_clausesets
};
-
+
/*%
* Clauses that can be found within the 'key' statement.
*/
@@ -959,7 +1011,7 @@ key_clausesets[] = {
};
static cfg_type_t cfg_type_key = {
"key", cfg_parse_named_map, cfg_print_map,
- cfg_doc_map, &cfg_rep_map, key_clausesets
+ cfg_doc_map, &cfg_rep_map, key_clausesets
};
@@ -1155,7 +1207,7 @@ static isc_result_t
parse_maybe_optional_keyvalue(cfg_parser_t *pctx, const cfg_type_t *type,
isc_boolean_t optional, cfg_obj_t **ret)
{
- isc_result_t result;
+ isc_result_t result;
cfg_obj_t *obj = NULL;
const keyword_type_t *kw = type->of;
@@ -1184,7 +1236,7 @@ static isc_result_t
parse_enum_or_other(cfg_parser_t *pctx, const cfg_type_t *enumtype,
const cfg_type_t *othertype, cfg_obj_t **ret)
{
- isc_result_t result;
+ isc_result_t result;
CHECK(cfg_peektoken(pctx, 0));
if (pctx->token.type == isc_tokentype_string &&
cfg_is_enum(TOKEN_STRING(pctx), enumtype->of)) {
@@ -1259,17 +1311,17 @@ parse_notify_type(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
}
static cfg_type_t cfg_type_notifytype = {
"notifytype", parse_notify_type, cfg_print_ustring, doc_enum_or_other,
- &cfg_rep_string, notify_enums,
+ &cfg_rep_string, notify_enums,
};
static const char *ixfrdiff_enums[] = { "master", "slave", NULL };
static isc_result_t
parse_ixfrdiff_type(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
- return (parse_enum_or_other(pctx, type, &cfg_type_boolean, ret));
+ return (parse_enum_or_other(pctx, type, &cfg_type_boolean, ret));
}
static cfg_type_t cfg_type_ixfrdifftype = {
- "ixfrdiff", parse_ixfrdiff_type, cfg_print_ustring, doc_enum_or_other,
- &cfg_rep_string, ixfrdiff_enums,
+ "ixfrdiff", parse_ixfrdiff_type, cfg_print_ustring, doc_enum_or_other,
+ &cfg_rep_string, ixfrdiff_enums,
};
static keyword_type_t key_kw = { "key", &cfg_type_astring };
@@ -1286,7 +1338,7 @@ static cfg_type_t cfg_type_optional_keyref = {
/*%
* A "controls" statement is represented as a map with the multivalued
- * "inet" and "unix" clauses.
+ * "inet" and "unix" clauses.
*/
static keyword_type_t controls_allow_kw = {
@@ -1423,14 +1475,14 @@ parse_querysource(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
"address") == 0)
{
/* read "address" */
- CHECK(cfg_gettoken(pctx, 0));
+ CHECK(cfg_gettoken(pctx, 0));
CHECK(cfg_parse_rawaddr(pctx, *flagp,
&netaddr));
have_address++;
} else if (strcasecmp(TOKEN_STRING(pctx), "port") == 0)
{
/* read "port" */
- CHECK(cfg_gettoken(pctx, 0));
+ CHECK(cfg_gettoken(pctx, 0));
CHECK(cfg_parse_rawport(pctx,
CFG_ADDR_WILDOK,
&port));
@@ -1492,7 +1544,7 @@ static cfg_type_t cfg_type_querysource = {
static isc_result_t
parse_addrmatchelt(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
- isc_result_t result;
+ isc_result_t result;
UNUSED(type);
CHECK(cfg_peektoken(pctx, CFG_LEXOPT_QSTRING));
@@ -1700,6 +1752,7 @@ static isc_result_t
parse_logversions(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
return (parse_enum_or_other(pctx, type, &cfg_type_uint32, ret));
}
+
static cfg_type_t cfg_type_logversions = {
"logversions", parse_logversions, cfg_print_ustring, cfg_doc_terminal,
&cfg_rep_string, logversions_enums
@@ -1716,9 +1769,9 @@ static isc_result_t
parse_logfile(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
isc_result_t result;
cfg_obj_t *obj = NULL;
- const cfg_tuplefielddef_t *fields = type->of;
+ const cfg_tuplefielddef_t *fields = type->of;
- CHECK(cfg_create_tuple(pctx, type, &obj));
+ CHECK(cfg_create_tuple(pctx, type, &obj));
/* Parse the mandatory "file" field */
CHECK(cfg_parse_obj(pctx, fields[0].type, &obj->value.tuple[0]));
@@ -1727,7 +1780,7 @@ parse_logfile(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
for (;;) {
CHECK(cfg_peektoken(pctx, 0));
if (pctx->token.type == isc_tokentype_string) {
- CHECK(cfg_gettoken(pctx, 0));
+ CHECK(cfg_gettoken(pctx, 0));
if (strcasecmp(TOKEN_STRING(pctx),
"versions") == 0 &&
obj->value.tuple[1] == NULL) {
@@ -1756,7 +1809,7 @@ parse_logfile(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) {
return (ISC_R_SUCCESS);
cleanup:
- CLEANUP_OBJ(obj);
+ CLEANUP_OBJ(obj);
return (result);
}
@@ -1773,8 +1826,19 @@ print_logfile(cfg_printer_t *pctx, const cfg_obj_t *obj) {
}
}
+
+static void
+doc_logfile(cfg_printer_t *pctx, const cfg_type_t *type) {
+ UNUSED(type);
+ cfg_print_cstr(pctx, "<quoted_string>");
+ cfg_print_chars(pctx, " ", 1);
+ cfg_print_cstr(pctx, "[ versions ( \"unlimited\" | <integer> ) ]");
+ cfg_print_chars(pctx, " ", 1);
+ cfg_print_cstr(pctx, "[ size <size> ]");
+}
+
static cfg_type_t cfg_type_logfile = {
- "log_file", parse_logfile, print_logfile, cfg_doc_terminal,
+ "log_file", parse_logfile, print_logfile, doc_logfile,
&cfg_rep_tuple, logfile_fields
};
@@ -1805,8 +1869,8 @@ static cfg_type_t cfg_type_lwres_view = {
};
static cfg_type_t cfg_type_lwres_searchlist = {
- "lwres_searchlist", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list,
- &cfg_rep_list, &cfg_type_astring };
+ "lwres_searchlist", cfg_parse_bracketed_list, cfg_print_bracketed_list,
+ cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_astring };
static cfg_clausedef_t
lwres_clauses[] = {
@@ -1925,15 +1989,15 @@ doc_sockaddrnameport(cfg_printer_t *pctx, const cfg_type_t *type) {
cfg_print_chars(pctx, "( ", 2);
cfg_print_cstr(pctx, "<quoted_string>");
cfg_print_chars(pctx, " ", 1);
- cfg_print_cstr(pctx, "[port <integer>]");
+ cfg_print_cstr(pctx, "[ port <integer> ]");
cfg_print_chars(pctx, " | ", 3);
cfg_print_cstr(pctx, "<ipv4_address>");
cfg_print_chars(pctx, " ", 1);
- cfg_print_cstr(pctx, "[port <integer>]");
+ cfg_print_cstr(pctx, "[ port <integer> ]");
cfg_print_chars(pctx, " | ", 3);
cfg_print_cstr(pctx, "<ipv6_address>");
cfg_print_chars(pctx, " ", 1);
- cfg_print_cstr(pctx, "[port <integer>]");
+ cfg_print_cstr(pctx, "[ port <integer> ]");
cfg_print_chars(pctx, " )", 2);
}
@@ -1941,7 +2005,7 @@ static isc_result_t
parse_sockaddrnameport(cfg_parser_t *pctx, const cfg_type_t *type,
cfg_obj_t **ret)
{
- isc_result_t result;
+ isc_result_t result;
cfg_obj_t *obj = NULL;
UNUSED(type);
@@ -1952,9 +2016,9 @@ parse_sockaddrnameport(cfg_parser_t *pctx, const cfg_type_t *type,
CHECK(cfg_parse_sockaddr(pctx, &cfg_type_sockaddr, ret));
else {
const cfg_tuplefielddef_t *fields =
- cfg_type_nameport.of;
+ cfg_type_nameport.of;
CHECK(cfg_create_tuple(pctx, &cfg_type_nameport,
- &obj));
+ &obj));
CHECK(cfg_parse_obj(pctx, fields[0].type,
&obj->value.tuple[0]));
CHECK(cfg_parse_obj(pctx, fields[1].type,
@@ -1968,7 +2032,7 @@ parse_sockaddrnameport(cfg_parser_t *pctx, const cfg_type_t *type,
return (ISC_R_UNEXPECTEDTOKEN);
}
cleanup:
- CLEANUP_OBJ(obj);
+ CLEANUP_OBJ(obj);
return (result);
}
@@ -2011,11 +2075,11 @@ doc_masterselement(cfg_printer_t *pctx, const cfg_type_t *type) {
cfg_print_chars(pctx, " | ", 3);
cfg_print_cstr(pctx, "<ipv4_address>");
cfg_print_chars(pctx, " ", 1);
- cfg_print_cstr(pctx, "[port <integer>]");
+ cfg_print_cstr(pctx, "[ port <integer> ]");
cfg_print_chars(pctx, " | ", 3);
cfg_print_cstr(pctx, "<ipv6_address>");
cfg_print_chars(pctx, " ", 1);
- cfg_print_cstr(pctx, "[port <integer>]");
+ cfg_print_cstr(pctx, "[ port <integer> ]");
cfg_print_chars(pctx, " )", 2);
}
@@ -2023,7 +2087,7 @@ static isc_result_t
parse_masterselement(cfg_parser_t *pctx, const cfg_type_t *type,
cfg_obj_t **ret)
{
- isc_result_t result;
+ isc_result_t result;
cfg_obj_t *obj = NULL;
UNUSED(type);
@@ -2040,7 +2104,7 @@ parse_masterselement(cfg_parser_t *pctx, const cfg_type_t *type,
return (ISC_R_UNEXPECTEDTOKEN);
}
cleanup:
- CLEANUP_OBJ(obj);
+ CLEANUP_OBJ(obj);
return (result);
}
diff --git a/lib/lwres/api b/lib/lwres/api
index 510e9a9..0be3ae7 100644
--- a/lib/lwres/api
+++ b/lib/lwres/api
@@ -1,3 +1,3 @@
LIBINTERFACE = 30
-LIBREVISION = 5
+LIBREVISION = 6
LIBAGE = 0
OpenPOWER on IntegriCloud