diff options
author | dougb <dougb@FreeBSD.org> | 2008-12-23 22:47:56 +0000 |
---|---|---|
committer | dougb <dougb@FreeBSD.org> | 2008-12-23 22:47:56 +0000 |
commit | c673a416c3c80055f220808cf9464c00fa1c5042 (patch) | |
tree | 6caf68c956b10fe118ac0bb9f368df80b7d0818e /contrib/bind9/lib | |
parent | cabae62b0ba1d31f524c393e294d3a5e08d543fc (diff) | |
parent | fa25a858e20428b15ec892d020272b1f70eaa725 (diff) | |
download | FreeBSD-src-c673a416c3c80055f220808cf9464c00fa1c5042.zip FreeBSD-src-c673a416c3c80055f220808cf9464c00fa1c5042.tar.gz |
Merge from vendor/bind9/dist as of the 9.4.3 import
Diffstat (limited to 'contrib/bind9/lib')
100 files changed, 4995 insertions, 1626 deletions
diff --git a/contrib/bind9/lib/bind/aclocal.m4 b/contrib/bind9/lib/bind/aclocal.m4 new file mode 100644 index 0000000..110ed87 --- /dev/null +++ b/contrib/bind9/lib/bind/aclocal.m4 @@ -0,0 +1,2 @@ +sinclude(../../libtool.m4)dnl + diff --git a/contrib/bind9/lib/bind/api b/contrib/bind9/lib/bind/api index a87852a..7ffeba8 100644 --- a/contrib/bind9/lib/bind/api +++ b/contrib/bind9/lib/bind/api @@ -1,3 +1,3 @@ -LIBINTERFACE = 4 -LIBREVISION = 10 -LIBAGE = 0 +LIBINTERFACE = 5 +LIBREVISION = 2 +LIBAGE = 1 diff --git a/contrib/bind9/lib/bind/bsd/Makefile.in b/contrib/bind9/lib/bind/bsd/Makefile.in index cf70c10..72a52f6 100644 --- a/contrib/bind9/lib/bind/bsd/Makefile.in +++ b/contrib/bind9/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/contrib/bind9/lib/bind/bsd/strerror.c b/contrib/bind9/lib/bind/bsd/strerror.c index 5743398..325cd52 100644 --- a/contrib/bind9/lib/bind/bsd/strerror.c +++ b/contrib/bind9/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/contrib/bind9/lib/bind/bsd/strtoul.c b/contrib/bind9/lib/bind/bsd/strtoul.c index f419227..c2efeda 100644 --- a/contrib/bind9/lib/bind/bsd/strtoul.c +++ b/contrib/bind9/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/contrib/bind9/lib/bind/config.h.in b/contrib/bind9/lib/bind/config.h.in new file mode 100644 index 0000000..5e2a83d --- /dev/null +++ b/contrib/bind9/lib/bind/config.h.in @@ -0,0 +1,68 @@ +#undef _SOCKADDR_LEN +#undef HAVE_FCNTL_H +#undef HAVE_PATHS_H +#undef HAVE_INTTYPES_H +#undef HAVE_STROPTS_H +#undef HAVE_SYS_TIMERS_H +#undef HAVE_SYS_SELECT_H +#undef HAVE_MEMORY_H +#undef SYS_CDEFS_H +#undef _POSIX_PTHREAD_SEMANTICS +#undef POSIX_GETPWUID_R +#undef POSIX_GETPWNAM_R +#undef POSIX_GETGRGID_R +#undef POSIX_GETGRNAM_R +#undef HAVE_MEMMOVE +#undef HAVE_MEMCHR +#undef SPRINTF_CHAR +#undef VSPRINTF_CHAR +#undef USE_SYSERROR_LIST +#undef NEED_STRTOUL +#undef NEED_SUN4PROTOS +#undef REENABLE_SEND + +#undef NEED_SETGROUPENT +#undef NEED_GETGROUPLIST + +/* define if prototype for getgrnam_r() is required */ +#undef NEED_GETGRNAM_R +#undef NEED_GETGRGID_R +#undef NEED_GETGRENT_R +#undef NEED_SETGRENT_R +#undef NEED_ENDGRENT_R + +#undef NEED_INNETGR_R +#undef NEED_SETNETGRENT_R +#undef NEED_ENDNETGRENT_R + +#undef NEED_GETPWNAM_R +#undef NEED_GETPWUID_R +#undef NEED_SETPWENT_R +#undef NEED_SETPASSENT_R +#undef NEED_SETPWENT_R +#undef NEED_GETPWENT_R +#undef NEED_ENDPWENT_R + +#undef NEED_SETPASSENT + +#undef HAS_PW_CLASS + +#undef ssize_t +#undef uintptr_t + +/* Shut up warnings about sputaux in stdio.h on BSD/OS pre-4.1 */ +#undef SHUTUP_SPUTAUX +#ifdef SHUTUP_SPUTAUX +struct __sFILE; +extern __inline int __sputaux(int _c, struct __sFILE *_p); +#endif +#undef BROKEN_IN6ADDR_INIT_MACROS +#undef HAVE_STRLCAT +/* Shut up warnings about missing braces */ +#undef SHUTUP_MUTEX_INITIALIZER +#ifdef SHUTUP_MUTEX_INITIALIZER +#define LIBBIND_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER } +#else +#define LIBBIND_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +#endif + diff --git a/contrib/bind9/lib/bind/configure.in b/contrib/bind9/lib/bind/configure.in index 6e98c5c..9b9b53b 100644 --- a/contrib/bind9/lib/bind/configure.in +++ b/contrib/bind9/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/contrib/bind9/lib/bind/dst/Makefile.in b/contrib/bind9/lib/bind/dst/Makefile.in index c802840..a841d49 100644 --- a/contrib/bind9/lib/bind/dst/Makefile.in +++ b/contrib/bind9/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/contrib/bind9/lib/bind/dst/dst_api.c b/contrib/bind9/lib/bind/dst/dst_api.c index a622ae3..5bcd80a 100644 --- a/contrib/bind9/lib/bind/dst/dst_api.c +++ b/contrib/bind9/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/contrib/bind9/lib/bind/dst/hmac_link.c b/contrib/bind9/lib/bind/dst/hmac_link.c index b97a996..cbd68f4 100644 --- a/contrib/bind9/lib/bind/dst/hmac_link.c +++ b/contrib/bind9/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/contrib/bind9/lib/bind/dst/support.c b/contrib/bind9/lib/bind/dst/support.c index ec228d0..263f957 100644 --- a/contrib/bind9/lib/bind/dst/support.c +++ b/contrib/bind9/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/contrib/bind9/lib/bind/include/Makefile.in b/contrib/bind9/lib/bind/include/Makefile.in index d07ea7a..17a69bf 100644 --- a/contrib/bind9/lib/bind/include/Makefile.in +++ b/contrib/bind9/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/contrib/bind9/lib/bind/include/arpa/nameser.h b/contrib/bind9/lib/bind/include/arpa/nameser.h index b3a7849..8f8d8a7 100644 --- a/contrib/bind9/lib/bind/include/arpa/nameser.h +++ b/contrib/bind9/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/contrib/bind9/lib/bind/include/isc/assertions.h b/contrib/bind9/lib/bind/include/isc/assertions.h index 2ed768d..100e586 100644 --- a/contrib/bind9/lib/bind/include/isc/assertions.h +++ b/contrib/bind9/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/contrib/bind9/lib/bind/include/isc/eventlib.h b/contrib/bind9/lib/bind/include/isc/eventlib.h index 598c71c..5003823 100644 --- a/contrib/bind9/lib/bind/include/isc/eventlib.h +++ b/contrib/bind9/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/contrib/bind9/lib/bind/include/isc/misc.h b/contrib/bind9/lib/bind/include/isc/misc.h index d2e98ac..0cd1487 100644 --- a/contrib/bind9/lib/bind/include/isc/misc.h +++ b/contrib/bind9/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/contrib/bind9/lib/bind/include/isc/platform.h.in b/contrib/bind9/lib/bind/include/isc/platform.h.in new file mode 100644 index 0000000..40ab5d7 --- /dev/null +++ b/contrib/bind9/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/contrib/bind9/lib/bind/include/netdb.h b/contrib/bind9/lib/bind/include/netdb.h index 66dd13d..b74c646 100644 --- a/contrib/bind9/lib/bind/include/netdb.h +++ b/contrib/bind9/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/contrib/bind9/lib/bind/include/resolv.h b/contrib/bind9/lib/bind/include/resolv.h index 66d84fc..eebc62e 100644 --- a/contrib/bind9/lib/bind/include/resolv.h +++ b/contrib/bind9/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/contrib/bind9/lib/bind/inet/Makefile.in b/contrib/bind9/lib/bind/inet/Makefile.in index 7eb297c..7b84896 100644 --- a/contrib/bind9/lib/bind/inet/Makefile.in +++ b/contrib/bind9/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/contrib/bind9/lib/bind/inet/inet_net_pton.c b/contrib/bind9/lib/bind/inet/inet_net_pton.c index d3de33b..71a8715 100644 --- a/contrib/bind9/lib/bind/inet/inet_net_pton.c +++ b/contrib/bind9/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/contrib/bind9/lib/bind/inet/inet_network.c b/contrib/bind9/lib/bind/inet/inet_network.c index 4758a00..47976cf 100644 --- a/contrib/bind9/lib/bind/inet/inet_network.c +++ b/contrib/bind9/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/contrib/bind9/lib/bind/irs/Makefile.in b/contrib/bind9/lib/bind/irs/Makefile.in index ce6f5f2..e4f38f7 100644 --- a/contrib/bind9/lib/bind/irs/Makefile.in +++ b/contrib/bind9/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/contrib/bind9/lib/bind/irs/dns_ho.c b/contrib/bind9/lib/bind/irs/dns_ho.c index d1d6f5a..db7ff02 100644 --- a/contrib/bind9/lib/bind/irs/dns_ho.c +++ b/contrib/bind9/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/contrib/bind9/lib/bind/irs/getnetgrent.c b/contrib/bind9/lib/bind/irs/getnetgrent.c index a11fa08..1e6ff9b 100644 --- a/contrib/bind9/lib/bind/irs/getnetgrent.c +++ b/contrib/bind9/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/contrib/bind9/lib/bind/irs/getnetgrent_r.c b/contrib/bind9/lib/bind/irs/getnetgrent_r.c index 261d9b7..3ff5542 100644 --- a/contrib/bind9/lib/bind/irs/getnetgrent_r.c +++ b/contrib/bind9/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/contrib/bind9/lib/bind/irs/irp.c b/contrib/bind9/lib/bind/irs/irp.c index 85a053d..aae4e7b 100644 --- a/contrib/bind9/lib/bind/irs/irp.c +++ b/contrib/bind9/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/contrib/bind9/lib/bind/isc/Makefile.in b/contrib/bind9/lib/bind/isc/Makefile.in index 3cbb640..70b0548 100644 --- a/contrib/bind9/lib/bind/isc/Makefile.in +++ b/contrib/bind9/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/contrib/bind9/lib/bind/isc/assertions.c b/contrib/bind9/lib/bind/isc/assertions.c index c03464d..e4bd42a 100644 --- a/contrib/bind9/lib/bind/isc/assertions.c +++ b/contrib/bind9/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/contrib/bind9/lib/bind/isc/bitncmp.c b/contrib/bind9/lib/bind/isc/bitncmp.c index 8764db1..9bbbd24 100644 --- a/contrib/bind9/lib/bind/isc/bitncmp.c +++ b/contrib/bind9/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/contrib/bind9/lib/bind/isc/ctl_clnt.c b/contrib/bind9/lib/bind/isc/ctl_clnt.c index eca8e7f..7627200 100644 --- a/contrib/bind9/lib/bind/isc/ctl_clnt.c +++ b/contrib/bind9/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/contrib/bind9/lib/bind/isc/ctl_srvr.c b/contrib/bind9/lib/bind/isc/ctl_srvr.c index 52137c0..1ab3f8a 100644 --- a/contrib/bind9/lib/bind/isc/ctl_srvr.c +++ b/contrib/bind9/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/contrib/bind9/lib/bind/isc/logging.c b/contrib/bind9/lib/bind/isc/logging.c index ca7049c..0cabc4d 100644 --- a/contrib/bind9/lib/bind/isc/logging.c +++ b/contrib/bind9/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/contrib/bind9/lib/bind/nameser/Makefile.in b/contrib/bind9/lib/bind/nameser/Makefile.in index d033eee..fcb7ed7 100644 --- a/contrib/bind9/lib/bind/nameser/Makefile.in +++ b/contrib/bind9/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/contrib/bind9/lib/bind/port_after.h.in b/contrib/bind9/lib/bind/port_after.h.in index f248d23..daddae6 100644 --- a/contrib/bind9/lib/bind/port_after.h.in +++ b/contrib/bind9/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/contrib/bind9/lib/bind/port_before.h.in b/contrib/bind9/lib/bind/port_before.h.in index 1f6ff1a..eb0c3fc 100644 --- a/contrib/bind9/lib/bind/port_before.h.in +++ b/contrib/bind9/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/contrib/bind9/lib/bind/resolv/Makefile.in b/contrib/bind9/lib/bind/resolv/Makefile.in index cc661b6..557f020 100644 --- a/contrib/bind9/lib/bind/resolv/Makefile.in +++ b/contrib/bind9/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/contrib/bind9/lib/bind/resolv/res_debug.c b/contrib/bind9/lib/bind/resolv/res_debug.c index 2ed234e..71dc676 100644 --- a/contrib/bind9/lib/bind/resolv/res_debug.c +++ b/contrib/bind9/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/contrib/bind9/lib/bind/resolv/res_mkquery.c b/contrib/bind9/lib/bind/resolv/res_mkquery.c index 50e4a9e..049f6c5 100644 --- a/contrib/bind9/lib/bind/resolv/res_mkquery.c +++ b/contrib/bind9/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/contrib/bind9/lib/bind/resolv/res_query.c b/contrib/bind9/lib/bind/resolv/res_query.c index c160e93..8c01cb0 100644 --- a/contrib/bind9/lib/bind/resolv/res_query.c +++ b/contrib/bind9/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/contrib/bind9/lib/bind/resolv/res_send.c b/contrib/bind9/lib/bind/resolv/res_send.c index 39dc998..5154fe2 100644 --- a/contrib/bind9/lib/bind/resolv/res_send.c +++ b/contrib/bind9/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/contrib/bind9/lib/bind9/api b/contrib/bind9/lib/bind9/api index 93632d1..3a74aee 100644 --- a/contrib/bind9/lib/bind9/api +++ b/contrib/bind9/lib/bind9/api @@ -1,3 +1,3 @@ LIBINTERFACE = 31 -LIBREVISION = 0 +LIBREVISION = 1 LIBAGE = 1 diff --git a/contrib/bind9/lib/bind9/check.c b/contrib/bind9/lib/bind9/check.c index 6cfdc93..2967650 100644 --- a/contrib/bind9/lib/bind9/check.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/acache.c b/contrib/bind9/lib/dns/acache.c index 5787a5a..cd56c3c 100644 --- a/contrib/bind9/lib/dns/acache.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/adb.c b/contrib/bind9/lib/dns/adb.c index c65c474..ae5dec8 100644 --- a/contrib/bind9/lib/dns/adb.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/api b/contrib/bind9/lib/dns/api index 7ad5506..7949ab0 100644 --- a/contrib/bind9/lib/dns/api +++ b/contrib/bind9/lib/dns/api @@ -1,3 +1,3 @@ -LIBINTERFACE = 35 +LIBINTERFACE = 36 LIBREVISION = 1 LIBAGE = 0 diff --git a/contrib/bind9/lib/dns/cache.c b/contrib/bind9/lib/dns/cache.c index 011dbf7..c9b4a95 100644 --- a/contrib/bind9/lib/dns/cache.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/dispatch.c b/contrib/bind9/lib/dns/dispatch.c index 617fde8..794cdb5 100644 --- a/contrib/bind9/lib/dns/dispatch.c +++ b/contrib/bind9/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, ®ion, 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, ®ion, 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, ®ion, 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/contrib/bind9/lib/dns/dst_parse.c b/contrib/bind9/lib/dns/dst_parse.c index aad7998..ce361ef 100644 --- a/contrib/bind9/lib/dns/dst_parse.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/dst_parse.h b/contrib/bind9/lib/dns/dst_parse.h index 8656f59..665fcfc 100644 --- a/contrib/bind9/lib/dns/dst_parse.h +++ b/contrib/bind9/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/contrib/bind9/lib/dns/include/dns/dispatch.h b/contrib/bind9/lib/dns/include/dns/dispatch.h index 914993b..8c14320 100644 --- a/contrib/bind9/lib/dns/include/dns/dispatch.h +++ b/contrib/bind9/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 <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/contrib/bind9/lib/dns/journal.c b/contrib/bind9/lib/dns/journal.c index 6cfb5af..4e4010f 100644 --- a/contrib/bind9/lib/dns/journal.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/master.c b/contrib/bind9/lib/dns/master.c index aa04be0..b04f2eb 100644 --- a/contrib/bind9/lib/dns/master.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/masterdump.c b/contrib/bind9/lib/dns/masterdump.c index 03716e2..1ffdfcb 100644 --- a/contrib/bind9/lib/dns/masterdump.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/message.c b/contrib/bind9/lib/dns/message.c index e8e4948..8c56377 100644 --- a/contrib/bind9/lib/dns/message.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/rbt.c b/contrib/bind9/lib/dns/rbt.c index b8db99a..4d3ca3a 100644 --- a/contrib/bind9/lib/dns/rbt.c +++ b/contrib/bind9/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, ¤t, 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/contrib/bind9/lib/dns/rbtdb.c b/contrib/bind9/lib/dns/rbtdb.c index 1d729d0..462a718 100644 --- a/contrib/bind9/lib/dns/rbtdb.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/rdata/generic/nsec_47.c b/contrib/bind9/lib/dns/rdata/generic/nsec_47.c index f3e56ca..dd39105 100644 --- a/contrib/bind9/lib/dns/rdata/generic/nsec_47.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/rdata/generic/nsec_47.h b/contrib/bind9/lib/dns/rdata/generic/nsec_47.h index ff03483..5c52447 100644 --- a/contrib/bind9/lib/dns/rdata/generic/nsec_47.h +++ b/contrib/bind9/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/contrib/bind9/lib/dns/rdata/generic/txt_16.c b/contrib/bind9/lib/dns/rdata/generic/txt_16.c index fa3ffef..01ca87a 100644 --- a/contrib/bind9/lib/dns/rdata/generic/txt_16.c +++ b/contrib/bind9/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(®ion); isc_region_consume(®ion, 1); - if (region.length <= length) + if (region.length < length) return (ISC_R_UNEXPECTEDEND); isc_region_consume(®ion, length); } diff --git a/contrib/bind9/lib/dns/rdata/in_1/apl_42.c b/contrib/bind9/lib/dns/rdata/in_1/apl_42.c index 42b2e7f..2fce328 100644 --- a/contrib/bind9/lib/dns/rdata/in_1/apl_42.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/rdata/in_1/naptr_35.c b/contrib/bind9/lib/dns/rdata/in_1/naptr_35.c index 0e5961a..9a880ea 100644 --- a/contrib/bind9/lib/dns/rdata/in_1/naptr_35.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/request.c b/contrib/bind9/lib/dns/request.c index c0348fe..64a3a4e 100644 --- a/contrib/bind9/lib/dns/request.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/resolver.c b/contrib/bind9/lib/dns/resolver.c index cdf5788..dc648c9 100644 --- a/contrib/bind9/lib/dns/resolver.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/rootns.c b/contrib/bind9/lib/dns/rootns.c index f20a49d..a988bea 100644 --- a/contrib/bind9/lib/dns/rootns.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/sdb.c b/contrib/bind9/lib/dns/sdb.c index fe53778..effb2bf 100644 --- a/contrib/bind9/lib/dns/sdb.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/tkey.c b/contrib/bind9/lib/dns/tkey.c index e4dbdc7..998ea36 100644 --- a/contrib/bind9/lib/dns/tkey.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/tsig.c b/contrib/bind9/lib/dns/tsig.c index cca1f99..f21832f 100644 --- a/contrib/bind9/lib/dns/tsig.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/validator.c b/contrib/bind9/lib/dns/validator.c index 9538b302..e686336 100644 --- a/contrib/bind9/lib/dns/validator.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/view.c b/contrib/bind9/lib/dns/view.c index d5a78d5..4851cf0 100644 --- a/contrib/bind9/lib/dns/view.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/xfrin.c b/contrib/bind9/lib/dns/xfrin.c index f95773f..7171a37 100644 --- a/contrib/bind9/lib/dns/xfrin.c +++ b/contrib/bind9/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/contrib/bind9/lib/dns/zone.c b/contrib/bind9/lib/dns/zone.c index fa6ac46..36f303c 100644 --- a/contrib/bind9/lib/dns/zone.c +++ b/contrib/bind9/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/contrib/bind9/lib/isc/Makefile.in b/contrib/bind9/lib/isc/Makefile.in index 71e4252..82afe5f 100644 --- a/contrib/bind9/lib/isc/Makefile.in +++ b/contrib/bind9/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/contrib/bind9/lib/isc/api b/contrib/bind9/lib/isc/api index f40dfe0..0b8a3bc 100644 --- a/contrib/bind9/lib/isc/api +++ b/contrib/bind9/lib/isc/api @@ -1,3 +1,3 @@ -LIBINTERFACE = 35 -LIBREVISION = 0 +LIBINTERFACE = 36 +LIBREVISION = 2 LIBAGE = 0 diff --git a/contrib/bind9/lib/isc/assertions.c b/contrib/bind9/lib/isc/assertions.c index b3fcf4a..3eb27e0 100644 --- a/contrib/bind9/lib/isc/assertions.c +++ b/contrib/bind9/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/contrib/bind9/lib/isc/include/isc/assertions.h b/contrib/bind9/lib/isc/include/isc/assertions.h index c1e68a1..fcf0eb8 100644 --- a/contrib/bind9/lib/isc/include/isc/assertions.h +++ b/contrib/bind9/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/contrib/bind9/lib/isc/include/isc/lex.h b/contrib/bind9/lib/isc/include/isc/lex.h index 8c6624a..cb9cc18 100644 --- a/contrib/bind9/lib/isc/include/isc/lex.h +++ b/contrib/bind9/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/contrib/bind9/lib/isc/include/isc/mem.h b/contrib/bind9/lib/isc/include/isc/mem.h index dc68bcb..2c3c54e 100644 --- a/contrib/bind9/lib/isc/include/isc/mem.h +++ b/contrib/bind9/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/contrib/bind9/lib/isc/include/isc/msgs.h b/contrib/bind9/lib/isc/include/isc/msgs.h index 97b2108..0970647 100644 --- a/contrib/bind9/lib/isc/include/isc/msgs.h +++ b/contrib/bind9/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/contrib/bind9/lib/isc/include/isc/platform.h.in b/contrib/bind9/lib/isc/include/isc/platform.h.in index 0531edf..afcd4df 100644 --- a/contrib/bind9/lib/isc/include/isc/platform.h.in +++ b/contrib/bind9/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/contrib/bind9/lib/isc/include/isc/portset.h b/contrib/bind9/lib/isc/include/isc/portset.h new file mode 100644 index 0000000..6396e5c --- /dev/null +++ b/contrib/bind9/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/contrib/bind9/lib/isc/include/isc/resource.h b/contrib/bind9/lib/isc/include/isc/resource.h index 18cd0ad..8c33c89 100644 --- a/contrib/bind9/lib/isc/include/isc/resource.h +++ b/contrib/bind9/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/contrib/bind9/lib/isc/include/isc/socket.h b/contrib/bind9/lib/isc/include/isc/socket.h index 951a063..a9a22c8 100644 --- a/contrib/bind9/lib/isc/include/isc/socket.h +++ b/contrib/bind9/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/contrib/bind9/lib/isc/include/isc/timer.h b/contrib/bind9/lib/isc/include/isc/timer.h index 6e78be9..7a7f614 100644 --- a/contrib/bind9/lib/isc/include/isc/timer.h +++ b/contrib/bind9/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/contrib/bind9/lib/isc/include/isc/types.h b/contrib/bind9/lib/isc/include/isc/types.h index 35a0be7..b501b2c 100644 --- a/contrib/bind9/lib/isc/include/isc/types.h +++ b/contrib/bind9/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/contrib/bind9/lib/isc/mem.c b/contrib/bind9/lib/isc/mem.c index aec6118..408770d 100644 --- a/contrib/bind9/lib/isc/mem.c +++ b/contrib/bind9/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/contrib/bind9/lib/isc/portset.c b/contrib/bind9/lib/isc/portset.c new file mode 100644 index 0000000..0265c89 --- /dev/null +++ b/contrib/bind9/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/contrib/bind9/lib/isc/print.c b/contrib/bind9/lib/isc/print.c index 59c528b..191ad24 100644 --- a/contrib/bind9/lib/isc/print.c +++ b/contrib/bind9/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/contrib/bind9/lib/isc/pthreads/mutex.c b/contrib/bind9/lib/isc/pthreads/mutex.c index 7716980..afbc861 100644 --- a/contrib/bind9/lib/isc/pthreads/mutex.c +++ b/contrib/bind9/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/contrib/bind9/lib/isc/timer.c b/contrib/bind9/lib/isc/timer.c index d594307..c27281d 100644 --- a/contrib/bind9/lib/isc/timer.c +++ b/contrib/bind9/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/contrib/bind9/lib/isc/unix/app.c b/contrib/bind9/lib/isc/unix/app.c index b71d766..c119362 100644 --- a/contrib/bind9/lib/isc/unix/app.c +++ b/contrib/bind9/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/contrib/bind9/lib/isc/unix/include/isc/net.h b/contrib/bind9/lib/isc/unix/include/isc/net.h index bdd8c14..948e7b1 100644 --- a/contrib/bind9/lib/isc/unix/include/isc/net.h +++ b/contrib/bind9/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/contrib/bind9/lib/isc/unix/net.c b/contrib/bind9/lib/isc/unix/net.c index 1de6b32..600ac92 100644 --- a/contrib/bind9/lib/isc/unix/net.c +++ b/contrib/bind9/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/contrib/bind9/lib/isc/unix/resource.c b/contrib/bind9/lib/isc/unix/resource.c index 0264976..e9bc5fd 100644 --- a/contrib/bind9/lib/isc/unix/resource.c +++ b/contrib/bind9/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/contrib/bind9/lib/isc/unix/socket.c b/contrib/bind9/lib/isc/unix/socket.c index 1b4da78..3239614 100644 --- a/contrib/bind9/lib/isc/unix/socket.c +++ b/contrib/bind9/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/contrib/bind9/lib/isc/unix/socket_p.h b/contrib/bind9/lib/isc/unix/socket_p.h index 4f9cf27..b7da860 100644 --- a/contrib/bind9/lib/isc/unix/socket_p.h +++ b/contrib/bind9/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/contrib/bind9/lib/isc/unix/time.c b/contrib/bind9/lib/isc/unix/time.c index bac24d7..facc12b 100644 --- a/contrib/bind9/lib/isc/unix/time.c +++ b/contrib/bind9/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/contrib/bind9/lib/isccfg/api b/contrib/bind9/lib/isccfg/api index d94beab..510e9a9 100644 --- a/contrib/bind9/lib/isccfg/api +++ b/contrib/bind9/lib/isccfg/api @@ -1,3 +1,3 @@ LIBINTERFACE = 30 -LIBREVISION = 4 +LIBREVISION = 5 LIBAGE = 0 diff --git a/contrib/bind9/lib/isccfg/namedconf.c b/contrib/bind9/lib/isccfg/namedconf.c index b04b3ab..a13d0a5 100644 --- a/contrib/bind9/lib/isccfg/namedconf.c +++ b/contrib/bind9/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/contrib/bind9/lib/lwres/api b/contrib/bind9/lib/lwres/api index 510e9a9..0be3ae7 100644 --- a/contrib/bind9/lib/lwres/api +++ b/contrib/bind9/lib/lwres/api @@ -1,3 +1,3 @@ LIBINTERFACE = 30 -LIBREVISION = 5 +LIBREVISION = 6 LIBAGE = 0 |