[Midnightbsd-cvs] src: contrib/bind9: merge

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Wed Mar 25 14:02:42 EDT 2009


Log Message:
-----------
merge

Modified Files:
--------------
    src/contrib/bind9:
        CHANGES (r1.5 -> r1.6)
        version (r1.5 -> r1.6)
    src/contrib/bind9/doc/arm:
        Bv9ARM-book.xml (r1.2 -> r1.3)
        Bv9ARM.ch06.html (r1.2 -> r1.3)
    src/contrib/bind9/lib/dns:
        api (r1.2 -> r1.3)
        dispatch.c (r1.4 -> r1.5)
        openssldsa_link.c (r1.2 -> r1.3)
        opensslrsa_link.c (r1.2 -> r1.3)
        resolver.c (r1.6 -> r1.7)
        validator.c (r1.3 -> r1.4)
    src/contrib/bind9/lib/dns/include/dns:
        dispatch.h (r1.4 -> r1.5)

-------------- next part --------------
Index: CHANGES
===================================================================
RCS file: /home/cvs/src/contrib/bind9/CHANGES,v
retrieving revision 1.5
retrieving revision 1.6
diff -L contrib/bind9/CHANGES -L contrib/bind9/CHANGES -u -r1.5 -r1.6
--- contrib/bind9/CHANGES
+++ contrib/bind9/CHANGES
@@ -1,17 +1,461 @@
-	--- 9.4.2-P1 released ---
+	--- 9.4.3-P1 released ---
 
-2375.   [security]      Fully randomize UDP query ports to improve
-			forgery resilience. [RT #17949]
-	--- 9.4.2-P1 released ---
+2522.	[security]	Handle -1 from DSA_do_verify().
 
-2375.   [security]      Fully randomize UDP query ports to improve
-			forgery resilience. [RT #17949]
-	--- 9.4.2-P1 released ---
+2498.	[bug]		Removed a bogus function argument used with
+			ISC_SOCKET_USE_POLLWATCH: it could cause compiler
+			warning or crash named with the debug 1 level
+			of logging. [RT #18917]
+
+	--- 9.4.3 released ---
+
+2490.	[port]		aix: work around a kernel bug where IPV6_RECVPKTINFO
+			is cleared when IPV6_V6ONLY is set. [RT #18785]
+
+2489.	[port]		solaris: Workaround Solaris's kernel bug about
+			/dev/poll:
+			http://bugs.opensolaris.org/view_bug.do?bug_id=6724237
+			Define ISC_SOCKET_USE_POLLWATCH at build time to enable
+			this workaround. [RT #18870]
+
+	--- 9.4.3rc1 released ---
+
+2473.	[port]		linux: raise the limit on open files to the possible
+			maximum value before spawning threads; 'files'
+		        specified in named.conf doesn't seem to work with
+			threads as expected. [RT #18784]
+
+2472.	[port]		linux: check the number of available cpu's before
+			calling chroot as it depends on "/proc". [RT #16923]
+
+2471.	[bug]		named-checkzone was not reporting missing manditory
+			glue when sibling checks were disabled. [RT #18768]
+
+2469.	[port]		solaris: Work around Solaris's select() limitations.
+			[RT #18769]
+
+2468.	[bug]		Resolver could try unreachable servers multiple times.
+			[RT #18739]
+
+2467.	[bug]		Failure of fcntl(F_DUPFD) wasn't logged. [RT #18740]
+
+2466.	[doc]		ARM: explain max-cache-ttl 0 SERVFAIL issue.
+			[RT #18302]
+
+2465.	[bug]		Adb's handling of lame addresses was different
+			for IPv4 and IPv6. [RT #18738]
+
+2463.   [port]          linux: POSIX doesn't include the IPv6 Advanced Socket
+			API and glibc hides parts of the IPv6 Advanced Socket
+			API as a result.  This is stupid as it breaks how the
+			two halves (Basic and Advanced) of the IPv6 Socket API				were designed to be used but we have to live with it.
+			Define _GNU_SOURCE to pull in the IPv6 Advanced Socket
+			API. [RT #18388]
+
+2462.	[doc]		Document -m (enable memory usage debugging)
+			option for dig. [RT #18757]
+
+2461.	[port]		sunos: Change #2363 was not complete. [RT #17513]
+
+2458.	[doc]		ARM: update and correction for max-cache-size.
+			[RT #18294]
+
+2455.	[bug]		Stop metadata being transfered via axfr/ixfr.
+			[RT #18639]
+
+2453.	[bug]		Remove NULL pointer dereference in dns_journal_print().
+			[RT #18316]
+
+2449.	[bug]		libbind: Out of bounds reference in dns_ho.c:addrsort.
+			[RT #18044]
+
+2445.	[doc]		ARM out-of-date on empty reverse zones (list includes
+			RFC1918 address, but these are not yet compiled in).
+			[RT #18578]
+
+2444.	[port]		Linux, FreeBSD, AIX: Turn off path mtu discovery
+			(clear DF) for UDP responses and requests.
+
+	--- 9.4.3b3 released ---
+
+2443.	[bug]		win32: UDP connect() would not generate an event,
+			and so connected UDP sockets would never clean up.
+			Fix this by doing an immediate WSAConnect() rather
+			than an io completion port type for UDP.
+
+2438.	[bug]		Timeouts could be logged incorrectly under win32.
+			[RT #18617]
+
+2437.	[bug]		Sockets could be closed too early, leading to
+			inconsistent states in the socket module. [RT #18298]
+
+2436.	[security]	win32: UDP client handler can be shutdown. [RT #18576]
+
+2433.	[tuning]	Set initial timeout to 800ms.
+
+2432.	[bug]		More Windows socket handling improvements.  Stop
+			using I/O events and use IO Completion Ports
+			throughout.  Rewrite the receive path logic to make
+			it easier to support multiple simultaneous
+			requestrs in the future.  Add stricter consistency
+			checking as a compile-time option (define
+			ISC_SOCKET_CONSISTENCY_CHECKS; defaults to off).
+
+2430.	[bug]		win32: isc_interval_set() could round down to
+			zero if the input was less than NS_INTERVAL
+			nanoseconds.  Round up instead. [RT #18549]
+
+2429.	[doc]		nsupdate should be in section 1 of the man pages.
+			[RT #18283]
+
+2426.	[bug]		libbind: inet_net_pton() can sometimes return the
+			wrong value if excessively large netmasks are
+			supplied. [RT #18512]
+
+2425.	[bug]		named didn't detect unavailable query source addresses
+			at load time. [RT #18536]
+
+2424.	[port]		configure now probes for a working epoll
+			implementation.  Allow the use of kqueue,
+			epoll and /dev/poll to be selected at compile
+			time. [RT #18277]
+			
+2422.	[bug]		Handle the special return value of a empty node as
+			if it was a NXRRSET in the validator. [RT #18447]
+
+2421.	[func]		Add new command line option '-S' for named to specify
+			the max number of sockets. [RT #18493]
+			Use caution: this option may not work for some
+			operating systems without rebuilding named.
+
+2420.	[bug]		Windows socket handling cleanup.  Let the io
+			completion event send out cancelled read/write
+			done events, which keeps us from writing to memeory
+			we no longer have ownership of.  Add debugging
+			socket_log() function.  Rework TCP socket handling
+			to not leak sockets.
+
+2417.	[bug]		Connecting UDP sockets for outgoing queries could
+			unexpectedly fail with an 'address already in use'
+			error. [RT #18411]
+
+2416.	[func]		Log file descriptors that cause exceeding the
+			internal maximum. [RT #18460]
+
+2414.	[bug]		A masterdump context held the database lock too long,
+			causing various troubles such as dead lock and
+			recursive lock acquisition. [RT #18311, #18456]
+
+2413.	[bug]		Fixed an unreachable code path in socket.c. [RT #18442]
+
+2412.	[bug]		win32: address a resourse leak. [RT #18374]
+
+2411.	[bug]		Allow using a larger number of sockets than FD_SETSIZE
+			for select().  To enable this, set ISC_SOCKET_MAXSOCKETS
+			at compilation time.  [RT #18433]
 
-2375.   [security]      Fully randomize UDP query ports to improve
+2410.	[bug]		Correctly delete m_versionInfo. [RT #18432]
+
+2408.	[bug]		A duplicate TCP dispatch event could be sent, which
+			could then trigger an assertion failure in
+			resquery_response().  [RT #18275]
+
+2407.	[port]		hpux: test for sys/dyntune.h. [RT #18421]
+
+2404.	[port]		hpux: files unlimited support.
+
+2403.	[bug]		TSIG context leak. [RT #18341]
+
+2402.	[port]		Support Solaris 2.11 and over. [RT #18362]
+
+2401.	[bug]		Expect to get E[MN]FILE errno internal_accept()
+			(from accept() or fcntl() system calls). [RT #18358]
+
+2399.	[bug]		Abort timeout queries to reduce the number of open
+			UDP sockets. [RT #18367]
+
+2398.	[bug]           Improve file descriptor management.  New,
+			temporary, named.conf option reserved-sockets,
+			default 512. [RT #18344]
+
+2396.	[bug]		Don't set SO_REUSEADDR for randomized ports.
+			[RT #18336]
+
+2395.	[port]		Avoid warning and no effect from "files unlimited"
+			on Linux when running as root. [RT #18335]
+
+2394.	[bug]		Default configuration options set the limit for
+			open files to 'unlimited' as described in the
+			documentation. [RT #18331]
+
+2392.	[bug]		remove 'grep -q' from acl test script, some platforms
+			don't support it. [RT #18253]
+
+2391	[port]		hpux: cover additional recvmsg() error codes.
+			[RT #18301]
+
+2390	[bug]		dispatch.c could make a false warning on 'odd socket'.
+			[RT #18301].
+
+2389	[bug]		Move the "working directory writable" check to after
+			the ns_os_changeuser() call. [RT #18326]
+
+2386.	[func]		Add warning about too small 'open files' limit.
+			[RT #18269]
+
+	--- 9.4.3b2 released ---
+
+2385.	[bug]		A condition variable in socket.c could leak in
+			rare error handling [RT #17968].
+
+2384.	[security]	Additional support for query port randomization (change
+			#2375) including performance improvement and port range
+			specification.  [RT #17949, #18098]
+
+2383.	[bug]		named could double queries when they resulted in
+			SERVFAIL due to overkilling EDNS0 failure detection.
+			[RT #18182]
+
+2382.	[doc]		Add descriptions of IPSECKEY, SPF and SSHFP to ARM.
+
+2381.	[port]		dlz/mysql: support multiple install layouts for
+			mysql.  <prefix>/include/{,mysql/}mysql.h and
+			<prefix>/lib/{,mysql/}. [RT #18152]
+
+2380.	[bug]		dns_view_find() was not returning NXDOMAIN/NXRRSET
+			proofs which, in turn, caused validation failures
+			for insecure zones immediately below a secure zone
+			the server was authoritative for. [RT #18112] 
+
+2379.	[contrib]	queryperf/gen-data-queryperf.py: removed redundant
+			TLDs and supported RRs with TTLs [RT #17972]
+
+2377.	[bug]		Address race condition in dnssec-signzone. [RT #18142]
+
+2376.	[bug]		Change #2144 was not complete.
+
+2375.	[security]	Fully randomize UDP query ports to improve
 			forgery resilience. [RT #17949]
 
+2372.	[bug]		fixed incorrect TAG_HMACSHA256_BITS value [RT #18047]
+
+2369.	[bug]		libbind: Array bounds overrun on read in bitncmp().
+			[RT #18054]
+
+2364.	[bug]		named could trigger a assertion when serving a
+			malformed signed zone. [RT #17828]
+
+2363.	[port]		sunos: pre-set "lt_cv_sys_max_cmd_len=4096;".
+			[RT #17513]
+
+2361.	[bug]		"recursion" statistics counter could be counted
+			multiple times for a single query.  [RT #17990]
+
+	--- 9.4.3b1 released ---
+
+2358.	[doc]		Update host's default query description. [RT #17934]
+
+2356.	[bug]		Built in mutex profiler was not scalable enough.
+			[RT #17436]
+
+2353.	[func]		libbind: nsid support. [RT #17091]
+
+2350.	[port]		win32: IPv6 support. [RT #17797]
+
+2347.	[bug]		Delete now traverses the RB tree in the canonical
+			order. [RT #17451]
+
+2345.	[bug]		named-checkconf failed to detect when forwarders
+			were set at both the options/view level and in
+			a root zone. [RT #17671]
+
+2344.	[bug]		Improve "logging{ file ...; };" documentation.
+			[RT #17888]
+
+2343.	[bug]		(Seemingly) duplicate IPv6 entries could be
+			created in ADB. [RT #17837]
+
+2341.	[bug]		libbind: add missing -I../include for off source
+			tree builds. [RT #17606]
+
+2340.	[port]		openbsd: interface configuration. [RT #17700]
+
+2339.	[port]		tru64: support for libbind. [RT #17589]
+
+2338.	[bug]		check_ds() could be called with a non DS rdataset.
+			[RT #17598]
+
+2337.	[bug]		BUILD_LDFLAGS was not being correctly set.  [RT #17614]
+
+2335.	[port]		sunos:  libbind and *printf() support for long long.
+			[RT #17513]
+
+2334.	[bug]		Bad REQUIRES in fromstruct_in_naptr(),  off by one
+			bug in fromstruct_txt(). [RT #17609]
+
+2333.	[bug]		Fix off by one error in isc_time_nowplusinterval().
+			[RT #17608]
+
+2332.	[contrib]	query-loc-0.4.0. [RT #17602]
+
+2331.	[bug]		Failure to regenerate any signatures was not being
+			reported nor being past back to the UPDATE client.
+			[RT #17570]
+
+2330.	[bug]		Remove potential race condition when handling
+			over memory events. [RT #17572]
+
+			WARNING: API CHANGE: over memory callback
+			function now needs to call isc_mem_waterack().
+			See <isc/mem.h> for details.
+
+2329.	[bug]		Clearer help text for dig's '-x' and '-i' options.
+
+2328.	[maint]		Add AAAA addresses for A.ROOT-SERVERS.NET,
+			F.ROOT-SERVERS.NET, H.ROOT-SERVERS.NET,
+			J.ROOT-SERVERS.NET, K.ROOT-SERVERS.NET and
+			M.ROOT-SERVERS.NET.
+
+2326.	[bug]		It was possible to trigger a INSIST in the acache
+			processing.
+
+2325.	[port]		Linux: use capset() function if available. [RT #17557]
+
+2323.	[port]		tru64: namespace clash. [RT #17547]
+
+2322.	[port]		MacOS: work around the limitation of setrlimit()
+			for RLIMIT_NOFILE. [RT #17526]
+
+2319.	[bug]		Silence Coverity warnings in
+			lib/dns/rdata/in_1/apl_42.c. [RT #17469]
+
+2318.	[port]		sunos fixes for libbind.  [RT #17514]
+
+2314.	[bug]		Uninitialized memory use on error path in
+			bin/named/lwdnoop.c.  [RT #17476]
+
+2313.	[cleanup]	Silence Coverity warnings. Handle private stacks.
+			[RT #17447] [RT #17478]
+
+2312.	[cleanup]	Silence Coverity warning in lib/isc/unix/socket.c.
+			[RT #17458]
+
+2311.	[func]		Update ACL regression test. [RT #17462]
+
+2310.	[bug]		dig, host, nslookup: flush stdout before emitting
+			debug/fatal messages.  [RT #17501]
+
+2308.	[cleanup]	Silence Coverity warning in bin/named/controlconf.c.
+			[RT #17495]
+
+2307.	[bug]		Remove infinite loop from lib/dns/sdb.c. [RT #17496]
+
+2306.	[bug]		Remove potential race from lib/dns/resolver.c.
+			[RT #17470]
+
+2305.	[security]	inet_network() buffer overflow. CVE-2008-0122.
+
+2304.	[bug]		Check returns from all dns_rdata_tostruct() calls.
+			[RT #17460]
+
+2303.	[bug]		Remove unnecessary code from bin/named/lwdgnba.c.
+			[RT #17471]
+
+2302.	[bug]		Fix memset() calls in lib/tests/t_api.c. [RT #17472]
+
+2301.	[bug]		Remove resource leak and fix error messages in
+			bin/tests/system/lwresd/lwtest.c. [RT #17474]
+
+2300.	[bug]		Fixed failure to close open file in
+			bin/tests/names/t_names.c. [RT #17473]
+
+2299.	[bug]		Remove unnecessary NULL check in
+			bin/nsupdate/nsupdate.c. [RT #17475]
+
+2298.	[bug]		isc_mutex_lock() failure not caught in
+			bin/tests/timers/t_timers.c. [RT #17468]
+
+2297.	[bug]		isc_entropy_createfilesource() failure not caught in
+			bin/tests/dst/t_dst.c. [RT #17467]
+
+2296.	[port]		Allow docbook stylesheet location to be specified to
+			configure. [RT #17457]
+
+2295.	[bug]		Silence static overrun error in bin/named/lwaddr.c.
+			[RT #17459]
+
+2293.	[func]		Add ACL regression test. [RT #17375]
+
+2292.	[bug]		Log if the working directory is not writable.
+			[RT #17312]
+
+2291.	[bug]		PR_SET_DUMPABLE may be set too late.  Also report
+			failure to set PR_SET_DUMPABLE. [RT #17312]
+
+2290.	[bug]		Let AD in the query signal that the client wants AD
+			set in the response. [RT #17301]
+
+2288.	[port]		win32: mark service as running when we have finished
+			loading.  [RT #17441]
+
+2287.	[bug]		Use 'volatile' if the compiler supports it. [RT #17413]
+
+2284.	[bug]		Memory leak in UPDATE prerequisite processing.
+			[RT #17377]
+
+2283.	[bug]		TSIG keys were not attaching to the memory
+			context.  TSIG keys should use the rings
+			memory context rather than the clients memory
+			context. [RT #17377]
+
+2279.	[bug]		Use setsockopt(SO_NOSIGPIPE), when available,
+			to protect applications from receiving spurious
+			SIGPIPE signals when using the resolver.
+
+2278.	[bug]		win32: handle the case where Windows returns no
+			search list or DNS suffix. [RT #17354]
+
+2277.	[bug]		Empty zone names were not correctly being caught at
+			in the post parse checks. [RT #17357]
+
+2273.	[bug]		Adjust log level to WARNING when saving inconsistent
+			stub/slave master and journal files. [RT# 17279]
+
+2272.	[bug]		Handle illegal dnssec-lookaside trust-anchor names.
+			[RT #17262]
+
+2270.	[bug]		dns_db_closeversion() version->writer could be reset
+			before it is tested. [RT #17290]
+
+2269.	[contrib]	dbus memory leaks and missing va_end calls. [RT #17232]
+
+2268.	[bug]		0.IN-ADDR.ARPA was missing from the empty zones
+			list.
+
+2266.	[bug]		client.c:get_clientmctx() returned the same mctx
+			once the pool of mctx's was filled. [RT #17218]
+
+2265.	[bug]		Test that the memory context's basic_table is non NULL
+			before freeing.  [RT #17265]
+
+2264.	[bug]		Server prefix length was being ignored. [RT #17308]
+
+2263.	[bug]		"named-checkconf -z" failed to set default value
+			for "check-integrity".  [RT #17306]
+
+2262.	[bug]		Error status from all but the last view could be
+			lost. [RT #17292]
+
+2260.	[bug]		Reported wrong clients-per-query when increasing the
+			value. [RT #17236]
+
+2247.	[doc]		Sort doc/misc/options. [RT #17067]
+
+2246.	[bug]		Make the startup of test servers (ans.pl) more
+			robust. [RT #17147]
+
 	--- 9.4.2 released ---
+
 	--- 9.4.2rc2 released ---
 
 2259.	[bug]		Reverse incorrect LIBINTERFACE bump of libisc
@@ -27,7 +471,7 @@
 2256.	[bug]		win32: Correctly register the installation location of
 			bindevt.dll. [RT #17159]
 
-2255.	[bug]		L.ROOT-SERVERS.NET is now 199.7.83.42.
+2255.	[maint]		L.ROOT-SERVERS.NET is now 199.7.83.42.
 
 2254.	[bug]		timer.c:dispatch() failed to lock timer->lock
 			when reading timer->idle allowing it to see
@@ -40,16 +484,16 @@
 			reality. Note there is behaviour change for BIND 9.5.
 			[RT #17113]
 
-2249.   [bug]           Only set Authentic Data bit if client requested
-                        DNSSEC, per RFC 3655 [RT #17175]
+2249.	[bug]		Only set Authentic Data bit if client requested
+			DNSSEC, per RFC 3655 [RT #17175]
 
-2248.   [cleanup]       Fix several errors reported by Coverity. [RT #17160]
+2248.	[cleanup]	Fix several errors reported by Coverity. [RT #17160]
 
 2245.	[bug]		Validating lack of DS records at trust anchors wasn't
 			working. [RT #17151]
 
 2238.	[bug]		It was possible to trigger a REQUIRE when a
-			validation was cancelled. [RT #17106]
+			validation was canceled. [RT #17106]
 
 2237.	[bug]		libbind: res_init() was not thread aware. [RT #17123]
 
@@ -58,8 +502,8 @@
 
 2235.	[bug]		<isc/atomic.h> was not being installed. [RT #17135]
 
-2234.   [port]          Correct some compiler warnings on SCO OSr5 [RT #17134]
-  
+2234.	[port]		Correct some compiler warnings on SCO OSr5 [RT #17134]
+
 2232.	[bug]		dns_adb_findaddrinfo() could fail and return
 			ISC_R_SUCCESS. [RT #17137]
 
@@ -74,7 +518,7 @@
 2227.	[cleanup]	Tidied up the FAQ. [RT #17121]
 
 2225.	[bug]		More support for systems with no IPv4 addresses.
-		        [RT #17111]
+			[RT #17111]
 
 2224.	[bug]		Defer journal compaction if a xfrin is in progress.
 			[RT #17119]
@@ -88,15 +532,15 @@
 
 2220.	[bug]		win32: Address a race condition in final shutdown of
 			the Windows socket code. [RT #17028]
-			
-2219.	[bug]		Apply zone consistancy checks to additions, not
+
+2219.	[bug]		Apply zone consistency checks to additions, not
 			removals, when updating. [RT #17049]
 
 2218.	[bug]		Remove unnecessary REQUIRE from dns_validator_create().
 			[RT #16976]
 
 2216.	[cleanup]	Fix a number of errors reported by Coverity.
-		        [RT #17094]
+			[RT #17094]
 
 2215.	[bug]		Bad REQUIRE check isc_hmacsha1_verify(). [RT #17094]
 
@@ -139,13 +583,13 @@
 			localhost;) is used.
 
 			[RT #16987]
-	
+
 2205.	[bug]		libbind: change #2119 broke thread support. [RT #16982]
 
 2203.	[security]	Query id generation was cryptographically weak.
 			[RT # 16915]
 
-2202.	[security]	The default acls for allow-query-cache and 
+2202.	[security]	The default acls for allow-query-cache and
 			allow-recursion were not being applied. [RT #16960]
 
 2200.	[bug]		The search for cached NSEC records was stopping to
@@ -180,7 +624,7 @@
 
 2187.	[bug]		query_addds(), query_addwildcardproof() and
 			query_addnxrrsetnsec() should take a version
-			arguement. [RT #16368]
+			argument. [RT #16368]
 
 2186.	[port]		cygwin: libbind: check for struct sockaddr_storage
 			independently of IPv6. [RT #16482]
@@ -207,7 +651,7 @@
 			debug level 10+. [RT #16798]
 
 2176.	[contrib]	dbus update to handle race condition during
-			initialisation (Bugzilla 235809). [RT #16842]
+			initialization (Bugzilla 235809). [RT #16842]
 
 2175.	[bug]		win32: windows broadcast condition variable support
 			was broken. [RT #16592]
@@ -238,7 +682,7 @@
 			a server address as a name to be looked up, causing
 			unexpected output. [RT #16743]
 
-2164.	[bug]		The code to determine how named-checkzone / 
+2164.	[bug]		The code to determine how named-checkzone /
 			named-compilezone was called failed under windows.
 			[RT #16764]
 
@@ -252,7 +696,7 @@
 
 2159.	[bug]		Array bounds overrun in acache processing. [RT #16710]
 
-2158.	[bug]		ns_client_isself() failed to initialise key
+2158.	[bug]		ns_client_isself() failed to initialize key
 			leading to a REQUIRE failure. [RT #16688]
 
 2156.	[bug]		Fix node reference leaks in lookup.c:lookup_find(),
@@ -327,7 +771,7 @@
 2136.	[bug]		nslookup/host looped if there was no search list
 			and the host didn't exist. [RT #16657]
 
-2135.	[bug]		Uninitialised rdataset in sdlz.c. [RT# 16656]
+2135.	[bug]		Uninitialized rdataset in sdlz.c. [RT# 16656]
 
 2133.	[port]		powerpc:  Support both IBM and MacOS Power PC
 			assembler syntaxes. [RT #16647]
@@ -343,7 +787,7 @@
 
 2127.	[port]		Improved OpenSSL 0.9.8 support. [RT #16563]
 
-2126.	[security]	Serialise validation of type ANY responses. [RT #16555]
+2126.	[security]	Serialize validation of type ANY responses. [RT #16555]
 
 2125.	[bug]		dns_zone_getzeronosoattl() REQUIRE failure if DLZ
 			was defined. [RT #16574]
@@ -383,7 +827,7 @@
 2111.	[bug]		Fix a number of errors reported by Coverity.
 			[RT #16507]
 
-2110.	[bug]		"minimal-response yes;" interacted badly with BIND 8
+2110.	[bug]		"minimal-responses yes;" interacted badly with BIND 8
 			priming queries. [RT #16491]
 
 2109.	[port]		libbind: silence aix 5.3 compiler warnings. [RT #16502]
@@ -395,7 +839,7 @@
 2103.	[port]		Add /usr/sfw to list of locations for OpenSSL
 			under Solaris.
 
-2102.	[port]		Silence solaris 10 warnings.
+2102.	[port]		Silence Solaris 10 warnings.
 
 	--- 9.4.0b4 released ---
 
@@ -405,7 +849,7 @@
 2100.	[port]		win32: copy libeay32.dll to Build\Debug.
 			Copy Debug\named-checkzone to Debug\named-compilezone.
 
-2099.	[port]		win32: more manifiest issues.
+2099.	[port]		win32: more manifest issues.
 
 2098.	[bug]		Race in rbtdb.c:no_references(), which occasionally
 			triggered an INSIST failure about the node lock
@@ -421,14 +865,14 @@
 
 2095.	[port]		libbind: alway prototype inet_cidr_ntop_ipv6() and
 			net_cidr_ntop_ipv6(). [RT #16388]
- 
+
 2094.	[contrib]	Update named-bootconf.  [RT# 16404]
 
 2093.	[bug]		named-checkzone -s was broken.
 
 2092.	[bug]		win32: dig, host, nslookup.  Use registry config
 			if resolv.conf does not exist or no nameservers
-			listed. [RT #15877] 
+			listed. [RT #15877]
 
 2091.	[port]		dighost.c: race condition on cleanup. [RT #16417]
 
@@ -471,7 +915,7 @@
 2078.	[bug]		dnssec-checkzone output style "default" was badly
 			named.  It is now called "relative". [RT #16326]
 
-2077.	[bug]		'dnssec-signzone -O raw' wasn't outputing the
+2077.	[bug]		'dnssec-signzone -O raw' wasn't outputting the
 			complete signed zone. [RT #16326]
 
 2076.	[bug]		Several files were missing #include <config.h>
@@ -556,7 +1000,7 @@
 			[RT #16287]
 
 2049.	[bug]		Restore SOA before AXFR when falling back from
-			a attempted IXFR when transfering in a zone.
+			a attempted IXFR when transferring in a zone.
 			Allow a initial SOA query before attempting
 			a AXFR to be requested. [RT #16156]
 
@@ -565,7 +1009,7 @@
 			the OS always returned the same local port.
 			[RT #16182]
 
-2047.	[bug]		Failed to initialise the interface flags to zero.
+2047.	[bug]		Failed to initialize the interface flags to zero.
 			[RT #16245]
 
 2046.	[bug]		rbtdb.c:rdataset_setadditional() could cause duplicate
@@ -605,7 +1049,7 @@
 
 2034.	[bug]		gcc: set -fno-strict-aliasing. [RT #16124]
 
-2033.	[bug]		We wern't creating multiple client memory contexts
+2033.	[bug]		We weren't creating multiple client memory contexts
 			on demand as expected. [RT #16095]
 
 	--- 9.4.0a6 released ---
@@ -621,7 +1065,7 @@
 2029.	[bug]		host printed out the server multiple times when
 			specified on the command line. [RT #15992]
 
-2028.	[port]		linux: socket.c compatability for old systems.
+2028.	[port]		linux: socket.c compatibility for old systems.
 			[RT #16015]
 
 2027.	[port]		libbind: Solaris x86 support. [RT #16020]
@@ -631,7 +1075,7 @@
 
 2025.	[func]		Update "zone serial unchanged" message. [RT #16026]
 
-2024.	[bug]		named emited spurious "zone serial unchanged"
+2024.	[bug]		named emitted spurious "zone serial unchanged"
 			messages on reload. [RT #16027]
 
 2023.	[bug]		"make install" should create ${localstatedir}/run and
@@ -659,7 +1103,7 @@
 	--- 9.4.0a5 released ---
 
 2015.	[cleanup]	use-additional-cache is now acache-enable for
-			consistancy.  Default acache-enable off in BIND 9.4
+			consistency.  Default acache-enable off in BIND 9.4
 			as it requires memory usage to be configured.
 			It may be enabled by default in BIND 9.5 once we
 			have more experience with it.
@@ -679,9 +1123,9 @@
 
 	--- 9.4.0a4 released ---
 
-2009.	[bug]		libbind: coverity fixes. [RT #15808]
+2009.	[bug]		libbind: Coverity fixes. [RT #15808]
 
-2008.	[func]		It is now posssible to enable/disable DNSSEC
+2008.	[func]		It is now possible to enable/disable DNSSEC
 			validation from rndc.  This is useful for the
 			mobile hosts where the current connection point
 			breaks DNSSEC (firewall/proxy).  [RT #15592]
@@ -693,7 +1137,7 @@
 			be changed to yes in 9.5.0.  [RT #15674]
 
 2006.	[security]	Allow-query-cache and allow-recursion now default
-			to the builtin acls "localnets" and "localhost".
+			to the built in acls "localnets" and "localhost".
 
 			This is being done to make caching servers less
 			attractive as reflective amplifying targets for
@@ -741,7 +1185,7 @@
 
 1994.	[port]		OpenSSL 0.9.8 support. [RT #15694]
 
-1993.	[bug]		Log messsage, via syslog, were missing the space
+1993.	[bug]		Log messages, via syslog, were missing the space
 			after the timestamp if "print-time yes" was specified.
 			[RT #15844]
 
@@ -749,11 +1193,11 @@
 			view.  [RT #15825]
 
 1991.	[cleanup]	The configuration data, once read, should be treated
-			as readonly.  Expand the use of const to enforce this
+			as read only.  Expand the use of const to enforce this
 			at compile time. [RT #15813]
 
 1990.	[bug]		libbind:  isc's override of broken gettimeofday()
-			implementions was not always effective.
+			implementations was not always effective.
 			[RT #15709]
 
 1989.	[bug]		win32: don't check the service password when
@@ -775,7 +1219,7 @@
 			server for the zone.  Also any zones that contain
 			DLV records should be removed when upgrading a slave
 			zone.  You do not however have to upgrade all
-			servers for a zone with DLV records simultaniously.
+			servers for a zone with DLV records simultaneously.
 
 1984.	[func]		dig, nslookup and host now advertise a 4096 byte
 			EDNS UDP buffer size by default. [RT #15855]
@@ -812,7 +1256,7 @@
 1973.	[func]		TSIG HMACSHA1, HMACSHA224, HMACSHA256, HMACSHA384 and
 			HMACSHA512 support. [RT #13606]
 
-1972.	[contrib]	DBUS dynamic forwarders integation from
+1972.	[contrib]	DBUS dynamic forwarders integration from
 			Jason Vas Dias <jvdias at redhat.com>.
 
 1971.	[port]		linux: make detection of missing IF_NAMESIZE more
@@ -836,7 +1280,7 @@
 
 1964.	[func]		Separate out MX and SRV to CNAME checks. [RT #15723]
 
-1963.	[port]		Tru64 4.0E doesn't support send() and recv(). 
+1963.	[port]		Tru64 4.0E doesn't support send() and recv().
 			[RT #15586]
 
 1962.	[bug]		Named failed to clear old update-policy when it
@@ -862,7 +1306,7 @@
 			by native compiler.  See README for additional
 			cross compile support information. [RT #15148]
 
-1955.	[bug]		Pre-allocate the cache cleaning interator. [RT #14998]
+1955.	[bug]		Pre-allocate the cache cleaning iterator. [RT #14998]
 
 1954.	[func]		Named now falls back to advertising EDNS with a
 			512 byte receive buffer if the initial EDNS queries
@@ -879,7 +1323,7 @@
 1951.	[security]	Drop queries from particular well known ports.
 			Don't return FORMERR to queries from particular
 			well known ports.  [RT #15636]
-			
+
 1950.	[port]		Solaris 2.5.1 and earlier cannot bind() then connect()
 			a TCP socket. This prevents the source address being
 			set for TCP connections. [RT #15628]
@@ -898,10 +1342,10 @@
 1946.	[bug]		resume_dslookup() could trigger a REQUIRE failure
 			when using forwarders. [RT #15549]
 
-1945.	[cleanup]	dnssec-keygen: RSA (RSAMD5) is nolonger recommended.
+1945.	[cleanup]	dnssec-keygen: RSA (RSAMD5) is no longer recommended.
 			To generate a RSAMD5 key you must explicitly request
 			RSAMD5. [RT #13780]
-			
+
 1944.	[cleanup]	isc_hash_create() does not need a read/write lock.
 			[RT #15522]
 
@@ -992,15 +1436,15 @@
 1917.	[doc]		funcsynopsisinfo wasn't being treated as verbatim
 			when generating man pages. [RT #15385]
 
-1916.	[func]		Integrate contibuted IDN code from JPNIC. [RT #15383]
+1916.	[func]		Integrate contributed IDN code from JPNIC. [RT #15383]
 
 1915.	[bug]		dig +ndots was broken. [RT #15215]
 
 1914.	[protocol]	DS is required to accept mnemonic algorithms
 			(RFC 4034).  Still emit numeric algorithms for
-			compatability with RFC 3658. [RT #15354]
+			compatibility with RFC 3658. [RT #15354]
 
-1913.	[func]		Integrate contibuted DLZ code into named. [RT #11382]
+1913.	[func]		Integrate contributed DLZ code into named. [RT #11382]
 
 1912.	[port]		aix: atomic locking for powerpc. [RT #15020]
 
@@ -1023,7 +1467,7 @@
 			[RT #15034]
 
 1905.	[bug]		Strings returned from cfg_obj_asstring() should be
-			treated as read-only.  The prototype for 
+			treated as read-only.  The prototype for
 			cfg_obj_asstring() has been updated to reflect this.
 			[RT #15256]
 
@@ -1072,7 +1516,7 @@
 1891.	[port]		freebsd: pthread_mutex_init can fail if it runs out
 			of memory. [RT #14995]
 
-1890.	[func]		Raise the UDP recieve buffer size to 32k if it is
+1890.	[func]		Raise the UDP receive buffer size to 32k if it is
 			less than 32k. [RT #14953]
 
 1889.	[port]		sunos: non blocking i/o support. [RT #14951]
@@ -1112,7 +1556,7 @@
 			[RT #2471]
 
 1877.	[bug]		Fix unreasonably low quantum on call to
-			dns_rbt_destroy2().  Remove unnecessay unhash_node()
+			dns_rbt_destroy2().  Remove unnecessary unhash_node()
 			call. [RT #14919]
 
 1876.	[func]		Additional memory debugging support to track size
@@ -1153,10 +1597,10 @@
 1863.	[bug]		rrset-order "fixed" error messages not complete.
 
 1862.	[func]		Add additional zone data constancy checks.
-			named-checkzone has extended checking of NS, MX and 
+			named-checkzone has extended checking of NS, MX and
 			SRV record and the hosts they reference.
 			named has extended post zone load checks.
-			New zone options: check-mx and integrity-check. 
+			New zone options: check-mx and integrity-check.
 			[RT #4940]
 
 1861.	[bug]		dig could trigger a INSIST on certain malformed
@@ -1194,24 +1638,24 @@
 1850.	[bug]		Memory leak in lwres_getipnodebyaddr(). [RT #14591]
 
 1849.	[doc]		All forms of the man pages (docbook, man, html) should
-			have consistant copyright dates.
+			have consistent copyright dates.
 
 1848.	[bug]		Improve SMF integration. [RT #13238]
 
 1847.	[bug]		isc_ondestroy_init() is called too late in
-			dns_rbtdb_create()/dns_rbtdb64_create(). 
+			dns_rbtdb_create()/dns_rbtdb64_create().
 			[RT #13661]
-			
+
 1846.	[contrib]	query-loc-0.3.0 from Stephane Bortzmeyer
 			<bortzmeyer at nic.fr>.
 
-1845.	[bug]		Improve error reporting to distingish between
+1845.	[bug]		Improve error reporting to distinguish between
 			accept()/fcntl() and socket()/fcntl() errors.
 			[RT #13745]
 
 1844.	[bug]		inet_pton() accepted more that 4 hexadecimal digits
 			for each 16 bit piece of the IPv6 address.  The text
-			representation of a IPv6 address has been tighted
+			representation of a IPv6 address has been tightened
 			to disallow this (draft-ietf-ipv6-addr-arch-v4-02.txt).
 			[RT #5662]
 
@@ -1439,7 +1883,7 @@
 1765.	[bug]		configure --with-openssl=auto failed. [RT #12937]
 
 1764.	[bug]		dns_zone_replacedb failed to emit a error message
-			if there was no SOA record in the replacment db.
+			if there was no SOA record in the replacement db.
 			[RT #13016]
 
 1763.	[func]		Perform sanity checks on NS records which refer to
@@ -1467,7 +1911,7 @@
 1755.	[func]		allow-update is now settable at the options / view
 			level. [RT #6636]
 
-1754.	[bug]		We wern't always attempting to query the parent
+1754.	[bug]		We weren't always attempting to query the parent
 			server for the DS records at the zone cut.
 			[RT #12774]
 
@@ -1487,8 +1931,8 @@
 			[RT #12866]
 
 1748.	[func]		dig now returns the byte count for axfr/ixfr.
-			
-1747.	[bug]		BIND 8 compatability: named/named-checkconf failed
+
+1747.	[bug]		BIND 8 compatibility: named/named-checkconf failed
 			to parse "host-statistics-max" in named.conf.
 
 1746.	[func]		Make public the function to read a key file,
@@ -1505,7 +1949,7 @@
 			requested number of worker threads then destruction
 			of the manager would trigger an INSIST() failure.
 			[RT #12790]
-			
+
 1742.	[bug]		Deleting all records at a node then adding a
 			previously existing record, in a single UPDATE
 			transaction, failed to leave / regenerate the
@@ -1516,7 +1960,7 @@
 
 1740.	[bug]		Replace rbt's hash algorithm as it performed badly
 			with certain zones. [RT #12729]
-			
+
 			NOTE: a hash context now needs to be established
 			via isc_hash_create() if the application was not
 			already doing this.
@@ -1531,7 +1975,7 @@
 
 1736.	[bug]		dst_key_fromnamedfile() could fail to read a
 			public key. [RT #12687]
-			
+
 1735.	[bug]		'dig +sigtrace' could die with a REQUIRE failure.
 			[RE #12688]
 
@@ -1571,7 +2015,7 @@
 			[RT #12519]
 
 1721.	[bug]		Error message from the journal processing were not
-			always identifing the relevent journal. [RT #12519]
+			always identifying the relevant journal. [RT #12519]
 
 1720.	[bug]		'dig +chase' did not terminate on a RFC 2308 Type 1
 			negative response. [RT #12506]
@@ -1628,7 +2072,7 @@
 1703.	[bug]		named would loop sending NOTIFY messages when it
 			failed to receive a response. [RT #12322]
 
-1702.	[bug]		also-notify should not be applied to builtin zones.
+1702.	[bug]		also-notify should not be applied to built in zones.
 			[RT #12323]
 
 1701.	[doc]		A minimal named.conf man page.
@@ -1708,7 +2152,7 @@
 
 1675.	[bug]		named would sometimes add extra NSEC records to
 			the authority section.
-			
+
 1674.	[port]		linux: increase buffer size used to scan
 			/proc/net/if_inet6.
 
@@ -1780,7 +2224,7 @@
 
 1648.	[func]		Update dnssec-lookaside named.conf syntax to support
 			multiple dnssec-lookaside namespaces (not yet
-			implemented).  
+			implemented).
 
 1647.	[bug]		It was possible trigger a INSIST when chasing a DS
 			record that required walking back over a empty node.
@@ -1793,7 +2237,7 @@
 			masters with keys are specified.
 
 1644.	[bug]		Update the journal modification time after a
-			sucessfull refresh query. [RT #11436]
+			successful refresh query. [RT #11436]
 
 1643.	[bug]		dns_db_closeversion() could leak memory / node
 			references. [RT #11163]
@@ -1810,11 +2254,11 @@
 
 1638.	[bug]		"ixfr-from-differences" could generate a REQUIRE
 			failure if the journal open failed. [RT #11347]
-			
+
 1637.	[bug]		Node reference leak on error in addnoqname().
 
 1636.	[bug]		The dump done callback could get ISC_R_SUCCESS even if
-			a error had occured.  The database version no longer
+			a error had occurred.  The database version no longer
 			matched the version of the database that was dumped.
 
 1635.	[bug]		Memory leak on error in query_addds().
@@ -1904,21 +2348,21 @@
 1607.	[bug]		dig, host and nslookup were still using random()
 			to generate query ids. [RT# 11013]
 
-1606.	[bug]	 	DLV insecurity proof was failing.
+1606.	[bug]		DLV insecurity proof was failing.
 
 1605.	[func]		New dns_db_find() option DNS_DBFIND_COVERINGNSEC.
 
 1604.	[bug]		A xfrout_ctx_create() failure would result in
 			xfrout_ctx_destroy() being called with a
 			partially initialized structure.
-			
+
 1603.	[bug]		nsupdate: set interactive based on isatty().
 			[RT# 10929]
 
 1602.	[bug]		Logging to a file failed unless a size was specified.
 			[RT# 10925]
 
-1601.	[bug]		Silence spurious warning 'both "recursion no;" and 
+1601.	[bug]		Silence spurious warning 'both "recursion no;" and
 			"allow-recursion" active' warning from view "_bind".
 			[RT# 10920]
 
@@ -2009,7 +2453,7 @@
 1568.	[bug]		nsupdate now reports that the update failed in
 			interactive mode. [RT# 10236]
 
-1567.	[bug]		B.ROOT-SERVERS.NET is now 192.228.79.201.
+1567.	[maint]		B.ROOT-SERVERS.NET is now 192.228.79.201.
 
 1566.	[port]		Support for the cmsg framework on Solaris and HP/UX.
 			This also solved the problem that match-destinations
@@ -2178,7 +2622,7 @@
 			type, class and responding nameserver.
 
 1511.	[bug]		delegation-only was generating false positives
-			on negative answers from subzones.
+			on negative answers from sub-zones.
 
 1510.	[func]		New view option "root-delegation-only".  Apply
 			delegation-only check to all TLDs and root.
@@ -2512,7 +2956,7 @@
 1398.	[doc]		ARM: notify-also should have been also-notify.
 			[RT #4345]
 
-1397.	[bug]		J.ROOT-SERVERS.NET is now 192.58.128.30.
+1397.	[maint]		J.ROOT-SERVERS.NET is now 192.58.128.30.
 
 1396.	[func]		dnssec-signzone: adjust the default signing time by
 			1 hour to allow for clock skew.
@@ -3859,7 +4303,7 @@
 
  954.	[bug]		When requesting AXFRs or IXFRs using dig, host, or
 			nslookup, the RD bit should not be set as zone
-			transfers are inherently nonrecursive. [RT #1575]
+			transfers are inherently non-recursive. [RT #1575]
 
  953.	[func]		The /var/run/named.key file from change #843
 			has been replaced by /etc/rndc.key.  Both
@@ -4174,7 +4618,7 @@
  860.	[func]		Drop cross class glue in zone transfers.
 
  859.	[bug]		Cache cleaning now won't swamp the CPU if there
-			is a persistent overlimit condition.
+			is a persistent over limit condition.
 
  858.	[func]		isc_mem_setwater() no longer requires that when the
 			callback function is non-NULL then its hi_water
@@ -4350,7 +4794,7 @@
  811.	[bug]		Parentheses were not quoted in zone dumps. [RT #1194]
 
  810.	[bug]		The signer name in SIG records was not properly
-			downcased when signing/verifying records. [RT #1186]
+			down-cased when signing/verifying records. [RT #1186]
 
  809.	[bug]		Configuring a non-local address as a transfer-source
 			could cause an assertion failure during load.
@@ -4362,9 +4806,9 @@
 			ignored like it should be.
 
  806.	[bug]		DNS_R_SEENINCLUDE was failing to propagate back up
-			the calling stack to the zone maintence level, causing
-			zones to not reload when an included file was touched
-			but the top-level zone file was not.
+			the calling stack to the zone maintenance level,
+			causing zones to not reload when an included file was
+			touched but the top-level zone file was not.
 
  805.	[bug]		When using "forward only", missing root hints should
 			not cause queries to fail. [RT #1143]
@@ -4404,7 +4848,7 @@
 			in rndc.conf.
 
  793.	[cleanup]	The DNSSEC tools could create filenames that were
-			illegal or contained shell metacharacters.  They
+			illegal or contained shell meta-characters.  They
 			now use a different text encoding of names that
 			doesn't have these problems. [RT #1101]
 
@@ -4428,7 +4872,7 @@
 			names when mapping them into file names.
 
  786.	[bug]		When DNSSEC signing/verifying data, owner names were
-			not properly downcased.
+			not properly down-cased.
 
  785.	[bug]		A race condition in the resolver could cause
 			an assertion failure. [RT #673, #872, #1048]
@@ -4447,7 +4891,7 @@
 
  780.	[bug]		Error handling code dealing with out of memory or
 			other rare errors could lead to assertion failures
-			by calling functions on unitialized names. [RT #1065]
+			by calling functions on uninitialized names. [RT #1065]
 
  779.	[func]		Added the "minimal-responses" option.
 
@@ -4590,7 +5034,7 @@
  735.	[doc]		Add BIND 4 migration notes.
 
  734.	[bug]		An attempt to re-lock the zone lock could occur if
-			the server was shutdown during a zone tranfer.
+			the server was shutdown during a zone transfer.
 			[RT #830]
 
  733.	[bug]		Reference counts of dns_acl_t objects need to be
@@ -4730,7 +5174,7 @@
  688.	[func]		"make tags" now works on systems with the
 			"Exuberant Ctags" etags.
 
- 687.	[bug]		Only say we have IPv6, with sufficent functionality,
+ 687.	[bug]		Only say we have IPv6, with sufficient functionality,
 			if it has actually been tested. [RT #586]
 
  686.	[bug]		dig and nslookup can now be properly aborted during
@@ -5048,7 +5492,7 @@
 	--- 9.1.0b1 released ---
 
  591.	[bug]		Work around non-reentrancy in openssl by disabling
-			precomputation in keys.
+			pre-computation in keys.
 
  590.	[doc]		There are now man pages for the lwres library in
 			doc/man/lwres.
@@ -5097,7 +5541,7 @@
 			source address for notify messages.
 
  577.	[func]		Log illegal RDATA combinations. e.g. multiple
-			singlton types, cname and other data.
+			singleton types, cname and other data.
 
  576.	[doc]		isc_log_create() description did not match reality.
 
@@ -5108,7 +5552,7 @@
 			have their responses validated and would leak memory.
 
  573.	[bug]		The journal files of IXFRed slave zones were
-			inadvertantly discarded on server reload, causing
+			inadvertently discarded on server reload, causing
 			"journal out of sync with zone" errors on subsequent
 			reloads. [RT #482]
 
@@ -5277,7 +5721,7 @@
 			others).
 
  519.	[bug]		dns_name_split() would improperly split some bitstring
-			labels, zeroing a few of the least signficant bits in
+			labels, zeroing a few of the least significant bits in
 			the prefix part.  When such an improperly created
 			prefix was returned to the RBT database, the bogus
 			label was dutifully stored, corrupting the tree.
@@ -5305,7 +5749,7 @@
  513.	[func]		New functionality added to rdnc and server to allow
 			individual zones to be refreshed or reloaded.
 
- 512.	[bug]		The zone transfer code could throw an execption with
+ 512.	[bug]		The zone transfer code could throw an exception with
 			an invalid IXFR stream.
 
  511.	[bug]		The message code could throw an assertion on an
@@ -5496,7 +5940,7 @@
  452.	[bug]		Warn if the unimplemented option "statistics-file"
 			is specified in named.conf. [RT #301]
 
- 451.	[func]		Update forwarding implememted.
+ 451.	[func]		Update forwarding implemented.
 
  450.	[func]		New function ns_client_sendraw().
 
@@ -5597,7 +6041,7 @@
 			e.g. due to corrupt zones with multiple SOA records.
 			[RT #279]
 
- 423.	[bug]		When responding to a recusive query, errors that occur
+ 423.	[bug]		When responding to a recursive query, errors that occur
 			after following a CNAME should cause the query to fail.
 			[RT #274]
 
@@ -5642,7 +6086,7 @@
 
  409.	[bug]		If named was shut down early in the startup
 			process, ns_omapi_shutdown() would attempt to lock
-			an unintialized mutex. [RT #262]
+			an uninitialized mutex. [RT #262]
 
  408.	[bug]		stub zones could leak memory and reference counts if
 			all the masters were unreachable.
@@ -5709,7 +6153,7 @@
 			making the functions dns_zone_adddbarg()
 			and dns_zone_cleardbargs() unnecessary.
 
- 389.	[bug]		Attempting to send a reqeust over IPv6 using
+ 389.	[bug]		Attempting to send a request over IPv6 using
 			dns_request_create() on a system without IPv6
 			support caused an assertion failure [RT #235].
 
@@ -5766,7 +6210,7 @@
 			of a very large RRset could cause an assertion failure
 			during logging.
 
- 370.	[bug]		The error messages for rollforward failures were
+ 370.	[bug]		The error messages for roll-forward failures were
 			overly terse.
 
  369.	[func]		Support new named.conf options, view and zone
@@ -5909,7 +6353,7 @@
 
  328.	[func]		Added isc_base64_decodestring().
 
- 327.	[bug]		rndc.conf parser wasn't correctly recognising an IP
+ 327.	[bug]		rndc.conf parser wasn't correctly recognizing an IP
 			address where a host specification was required.
 
  326.	[func]		'keys' in an 'inet' control statement is now
@@ -5939,7 +6383,7 @@
 			where they previously didn't.
 
  321.	[bug]		When synthesizing a CNAME RR for a DNAME
-			response, query_addcname() failed to intitialize
+			response, query_addcname() failed to initialize
 			the type and class of the CNAME dns_rdata_t,
 			causing random failures.
 
@@ -6215,7 +6659,7 @@
 
 	--- 9.0.0b4 released ---
 
- 253.	[func]		resolv.conf parser now recognises ';' and '#' as
+ 253.	[func]		resolv.conf parser now recognizes ';' and '#' as
 			comments (anywhere in line, not just as the beginning).
 
  252.	[bug]		resolv.conf parser mishandled masks on sortlists.
@@ -6285,7 +6729,7 @@
 			requiring a quoted string.
 
  233.	[cleanup]	Convert all config structure integer values to unsigned
-			integer (isc_uint32_t) to match grammer.
+			integer (isc_uint32_t) to match grammar.
 
  232.	[bug]		Allow slave zones to not have a file.
 
@@ -6322,7 +6766,7 @@
 			from confparser.c, because of yacc's code, are
 			unfortunately to be expected.)
 
- 223.	[func]		Several functions were reprototyped to qualify one
+ 223.	[func]		Several functions were re-prototyped to qualify one
 			or more of their arguments with "const".  Similarly,
 			several functions that return pointers now have
 			those pointers qualified with const.
@@ -6487,7 +6931,7 @@
  183.	[func]		ISC_LOG_PRINTTAG option for log channels.  Useful
 			for logging the program name or other identifier.
 
- 182.	[cleanup]	New commandline parameters for dnssec tools
+ 182.	[cleanup]	New command-line parameters for dnssec tools
 
  181.	[func]		Added dst_key_buildfilename and dst_key_parsefilename
 
@@ -6532,7 +6976,7 @@
 			--with-mit-pthreads option is no longer needed
 			and has been removed.
 
- 170.	[cleanup]	Remove inter server consistancy checks from zone,
+ 170.	[cleanup]	Remove inter server consistency checks from zone,
 			these should return as a separate module in 9.1.
 			dns_zone_checkservers(), dns_zone_checkparents(),
 			dns_zone_checkchildren(), dns_zone_checkglue().
@@ -6625,7 +7069,7 @@
 			than continuing to itemize every header which changed,
 			this changelog entry just notes that if a header file
 			did not need another header file that it was including
-			in order to provide its advertized functionality, the
+			in order to provide its advertised functionality, the
 			inclusion of the other header file was removed.  See
 			util/check-includes for how this was tested.
 
@@ -7017,7 +7461,7 @@
 
   31.	[bug]		Use ${LIBTOOL} to compile bin/named/main. at O@.
 
-  30.	[func]		config file grammer change to support optional
+  30.	[func]		config file grammar change to support optional
 			class type for a view.
 
   29.	[func]		support new config file view options:
@@ -7081,7 +7525,7 @@
   13.	[bug]		lib/dns/master.c and lib/dns/xfrin.c didn't ignore
 			out-of-zone data.
 
-  12.	[bug]		Fixed possible unitialized variable error.
+  12.	[bug]		Fixed possible uninitialized variable error.
 
   11.	[bug]		axfr_rrstream_first() didn't check the result code of
 			db_rr_iterator_first(), possibly causing an assertion
Index: version
===================================================================
RCS file: /home/cvs/src/contrib/bind9/version,v
retrieving revision 1.5
retrieving revision 1.6
diff -L contrib/bind9/version -L contrib/bind9/version -u -r1.5 -r1.6
--- contrib/bind9/version
+++ contrib/bind9/version
@@ -1,10 +1,10 @@
-# $Id: version,v 1.29.134.18.8.1 2008/05/22 21:28:03 each Exp $
+# $Id: version,v 1.29.134.23.2.1 2008/12/24 00:21:22 marka Exp $
 #
 # This file must follow /bin/sh rules.  It is imported directly via
 # configure.
 #
 MAJORVER=9
 MINORVER=4
-PATCHVER=2
+PATCHVER=3
 RELEASETYPE=-P
 RELEASEVER=1
Index: Bv9ARM.ch06.html
===================================================================
RCS file: /home/cvs/src/contrib/bind9/doc/arm/Bv9ARM.ch06.html,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/bind9/doc/arm/Bv9ARM.ch06.html -L contrib/bind9/doc/arm/Bv9ARM.ch06.html -u -r1.2 -r1.3
--- contrib/bind9/doc/arm/Bv9ARM.ch06.html
+++ contrib/bind9/doc/arm/Bv9ARM.ch06.html
@@ -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 distribute this software for any
@@ -14,7 +14,7 @@
  - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  - PERFORMANCE OF THIS SOFTWARE.
 -->
-<!-- $Id: Bv9ARM.ch06.html,v 1.82.18.73.8.1 2008/05/27 22:07:34 each Exp $ -->
+<!-- $Id: Bv9ARM.ch06.html,v 1.82.18.88 2008/10/18 01:29:58 tbox Exp $ -->
 <html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
@@ -48,52 +48,52 @@
 <dt><span class="sect1"><a href="Bv9ARM.ch06.html#configuration_file_elements">Configuration File Elements</a></span></dt>
 <dd><dl>
 <dt><span class="sect2"><a href="Bv9ARM.ch06.html#address_match_lists">Address Match Lists</a></span></dt>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2573480">Comment Syntax</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2573436">Comment Syntax</a></span></dt>
 </dl></dd>
 <dt><span class="sect1"><a href="Bv9ARM.ch06.html#Configuration_File_Grammar">Configuration File Grammar</a></span></dt>
 <dd><dl>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574092"><span><strong class="command">acl</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574117"><span><strong class="command">acl</strong></span> Statement Grammar</a></span></dt>
 <dt><span class="sect2"><a href="Bv9ARM.ch06.html#acl"><span><strong class="command">acl</strong></span> Statement Definition and
           Usage</a></span></dt>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574282"><span><strong class="command">controls</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574307"><span><strong class="command">controls</strong></span> Statement Grammar</a></span></dt>
 <dt><span class="sect2"><a href="Bv9ARM.ch06.html#controls_statement_definition_and_usage"><span><strong class="command">controls</strong></span> Statement Definition and
           Usage</a></span></dt>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574711"><span><strong class="command">include</strong></span> Statement Grammar</a></span></dt>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574726"><span><strong class="command">include</strong></span> Statement Definition and
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574736"><span><strong class="command">include</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574753"><span><strong class="command">include</strong></span> Statement Definition and
           Usage</a></span></dt>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574749"><span><strong class="command">key</strong></span> Statement Grammar</a></span></dt>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574771"><span><strong class="command">key</strong></span> Statement Definition and Usage</a></span></dt>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574930"><span><strong class="command">logging</strong></span> Statement Grammar</a></span></dt>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2575056"><span><strong class="command">logging</strong></span> Statement Definition and
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574776"><span><strong class="command">key</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574800"><span><strong class="command">key</strong></span> Statement Definition and Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2574958"><span><strong class="command">logging</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2575084"><span><strong class="command">logging</strong></span> Statement Definition and
           Usage</a></span></dt>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2576406"><span><strong class="command">lwres</strong></span> Statement Grammar</a></span></dt>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2576480"><span><strong class="command">lwres</strong></span> Statement Definition and Usage</a></span></dt>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2576544"><span><strong class="command">masters</strong></span> Statement Grammar</a></span></dt>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2576587"><span><strong class="command">masters</strong></span> Statement Definition and
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2576435"><span><strong class="command">lwres</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2576508"><span><strong class="command">lwres</strong></span> Statement Definition and Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2576572"><span><strong class="command">masters</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2576616"><span><strong class="command">masters</strong></span> Statement Definition and
           Usage</a></span></dt>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2576602"><span><strong class="command">options</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2576631"><span><strong class="command">options</strong></span> Statement Grammar</a></span></dt>
 <dt><span class="sect2"><a href="Bv9ARM.ch06.html#options"><span><strong class="command">options</strong></span> Statement Definition and
           Usage</a></span></dt>
 <dt><span class="sect2"><a href="Bv9ARM.ch06.html#server_statement_grammar"><span><strong class="command">server</strong></span> Statement Grammar</a></span></dt>
 <dt><span class="sect2"><a href="Bv9ARM.ch06.html#server_statement_definition_and_usage"><span><strong class="command">server</strong></span> Statement Definition and
             Usage</a></span></dt>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2585361"><span><strong class="command">trusted-keys</strong></span> Statement Grammar</a></span></dt>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2585410"><span><strong class="command">trusted-keys</strong></span> Statement Definition
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2585614"><span><strong class="command">trusted-keys</strong></span> Statement Grammar</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2585666"><span><strong class="command">trusted-keys</strong></span> Statement Definition
             and Usage</a></span></dt>
 <dt><span class="sect2"><a href="Bv9ARM.ch06.html#view_statement_grammar"><span><strong class="command">view</strong></span> Statement Grammar</a></span></dt>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2585490"><span><strong class="command">view</strong></span> Statement Definition and Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2585748"><span><strong class="command">view</strong></span> Statement Definition and Usage</a></span></dt>
 <dt><span class="sect2"><a href="Bv9ARM.ch06.html#zone_statement_grammar"><span><strong class="command">zone</strong></span>
             Statement Grammar</a></span></dt>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2586798"><span><strong class="command">zone</strong></span> Statement Definition and Usage</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2587332"><span><strong class="command">zone</strong></span> Statement Definition and Usage</a></span></dt>
 </dl></dd>
-<dt><span class="sect1"><a href="Bv9ARM.ch06.html#id2589080">Zone File</a></span></dt>
+<dt><span class="sect1"><a href="Bv9ARM.ch06.html#id2589477">Zone File</a></span></dt>
 <dd><dl>
 <dt><span class="sect2"><a href="Bv9ARM.ch06.html#types_of_resource_records_and_when_to_use_them">Types of Resource Records and When to Use Them</a></span></dt>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2591101">Discussion of MX Records</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2591500">Discussion of MX Records</a></span></dt>
 <dt><span class="sect2"><a href="Bv9ARM.ch06.html#Setting_TTLs">Setting TTLs</a></span></dt>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2591653">Inverse Mapping in IPv4</a></span></dt>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2591848">Other Zone File Directives</a></span></dt>
-<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2592173"><acronym class="acronym">BIND</acronym> Master File Extension: the  <span><strong class="command">$GENERATE</strong></span> Directive</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2592188">Inverse Mapping in IPv4</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2592384">Other Zone File Directives</a></span></dt>
+<dt><span class="sect2"><a href="Bv9ARM.ch06.html#id2592572"><acronym class="acronym">BIND</acronym> Master File Extension: the  <span><strong class="command">$GENERATE</strong></span> Directive</a></span></dt>
 <dt><span class="sect2"><a href="Bv9ARM.ch06.html#zonefile_format">Additional File Formats</a></span></dt>
 </dl></dd>
 </dl>
@@ -355,6 +355,33 @@
 <tr>
 <td>
                 <p>
+                  <code class="varname">port_list</code>
+                </p>
+              </td>
+<td>
+                <p>
+                  A list of an <code class="varname">ip_port</code> or a port
+                  range.
+                  A port range is specified in the form of
+                  <strong class="userinput"><code>range</code></strong> followed by
+                  two <code class="varname">ip_port</code>s,
+                  <code class="varname">port_low</code> and
+                  <code class="varname">port_high</code>, which represents
+                  port numbers from <code class="varname">port_low</code> through
+                  <code class="varname">port_high</code>, inclusive.
+                  <code class="varname">port_low</code> must not be larger than
+                  <code class="varname">port_high</code>.
+                  For example,
+                  <strong class="userinput"><code>range 1024 65535</code></strong> represents
+                  ports from 1024 through 65535.
+                  In either case an asterisk (`*') character is not
+                  allowed as a valid <code class="varname">ip_port</code>.
+                </p>
+              </td>
+</tr>
+<tr>
+<td>
+                <p>
                   <code class="varname">size_spec</code>
                 </p>
               </td>
@@ -428,7 +455,7 @@
 <a name="address_match_lists"></a>Address Match Lists</h3></div></div></div>
 <div class="sect3" lang="en">
 <div class="titlepage"><div><div><h4 class="title">
-<a name="id2573277"></a>Syntax</h4></div></div></div>
+<a name="id2573302"></a>Syntax</h4></div></div></div>
 <pre class="programlisting"><code class="varname">address_match_list</code> = address_match_list_element ;
   [<span class="optional"> address_match_list_element; ... </span>]
 <code class="varname">address_match_list_element</code> = [<span class="optional"> ! </span>] (ip_address [<span class="optional">/length</span>] |
@@ -437,7 +464,7 @@
 </div>
 <div class="sect3" lang="en">
 <div class="titlepage"><div><div><h4 class="title">
-<a name="id2573305"></a>Definition and Usage</h4></div></div></div>
+<a name="id2573330"></a>Definition and Usage</h4></div></div></div>
 <p>
             Address match lists are primarily used to determine access
             control for various server operations. They are also used in
@@ -515,7 +542,7 @@
 </div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2573480"></a>Comment Syntax</h3></div></div></div>
+<a name="id2573436"></a>Comment Syntax</h3></div></div></div>
 <p>
           The <acronym class="acronym">BIND</acronym> 9 comment syntax allows for
           comments to appear
@@ -525,7 +552,7 @@
         </p>
 <div class="sect3" lang="en">
 <div class="titlepage"><div><div><h4 class="title">
-<a name="id2573495"></a>Syntax</h4></div></div></div>
+<a name="id2573588"></a>Syntax</h4></div></div></div>
 <p>
             </p>
 <pre class="programlisting">/* This is a <acronym class="acronym">BIND</acronym> comment as in C */</pre>
@@ -540,7 +567,7 @@
 </div>
 <div class="sect3" lang="en">
 <div class="titlepage"><div><div><h4 class="title">
-<a name="id2573525"></a>Definition and Usage</h4></div></div></div>
+<a name="id2573618"></a>Definition and Usage</h4></div></div></div>
 <p>
             Comments may appear anywhere that whitespace may appear in
             a <acronym class="acronym">BIND</acronym> configuration file.
@@ -774,7 +801,7 @@
       </p>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2574092"></a><span><strong class="command">acl</strong></span> Statement Grammar</h3></div></div></div>
+<a name="id2574117"></a><span><strong class="command">acl</strong></span> Statement Grammar</h3></div></div></div>
 <pre class="programlisting"><span><strong class="command">acl</strong></span> acl-name {
     address_match_list
 };
@@ -857,7 +884,7 @@
 </div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2574282"></a><span><strong class="command">controls</strong></span> Statement Grammar</h3></div></div></div>
+<a name="id2574307"></a><span><strong class="command">controls</strong></span> Statement Grammar</h3></div></div></div>
 <pre class="programlisting"><span><strong class="command">controls</strong></span> {
    [ inet ( ip_addr | * ) [ port ip_port ] allow { <em class="replaceable"><code> address_match_list </code></em> }
                 keys { <em class="replaceable"><code>key_list</code></em> }; ]
@@ -979,12 +1006,12 @@
 </div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2574711"></a><span><strong class="command">include</strong></span> Statement Grammar</h3></div></div></div>
-<pre class="programlisting">include <em class="replaceable"><code>filename</code></em>;</pre>
+<a name="id2574736"></a><span><strong class="command">include</strong></span> Statement Grammar</h3></div></div></div>
+<pre class="programlisting"><span><strong class="command">include</strong></span> <em class="replaceable"><code>filename</code></em>;</pre>
 </div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2574726"></a><span><strong class="command">include</strong></span> Statement Definition and
+<a name="id2574753"></a><span><strong class="command">include</strong></span> Statement Definition and
           Usage</h3></div></div></div>
 <p>
           The <span><strong class="command">include</strong></span> statement inserts the
@@ -999,8 +1026,8 @@
 </div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2574749"></a><span><strong class="command">key</strong></span> Statement Grammar</h3></div></div></div>
-<pre class="programlisting">key <em class="replaceable"><code>key_id</code></em> {
+<a name="id2574776"></a><span><strong class="command">key</strong></span> Statement Grammar</h3></div></div></div>
+<pre class="programlisting"><span><strong class="command">key</strong></span> <em class="replaceable"><code>key_id</code></em> {
     algorithm <em class="replaceable"><code>string</code></em>;
     secret <em class="replaceable"><code>string</code></em>;
 };
@@ -1008,7 +1035,7 @@
 </div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2574771"></a><span><strong class="command">key</strong></span> Statement Definition and Usage</h3></div></div></div>
+<a name="id2574800"></a><span><strong class="command">key</strong></span> Statement Definition and Usage</h3></div></div></div>
 <p>
           The <span><strong class="command">key</strong></span> statement defines a shared
           secret key for use with TSIG (see <a href="Bv9ARM.ch04.html#tsig" title="TSIG">the section called “TSIG”</a>)
@@ -1055,7 +1082,7 @@
 </div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2574930"></a><span><strong class="command">logging</strong></span> Statement Grammar</h3></div></div></div>
+<a name="id2574958"></a><span><strong class="command">logging</strong></span> Statement Grammar</h3></div></div></div>
 <pre class="programlisting"><span><strong class="command">logging</strong></span> {
    [ <span><strong class="command">channel</strong></span> <em class="replaceable"><code>channel_name</code></em> {
      ( <span><strong class="command">file</strong></span> <em class="replaceable"><code>path name</code></em>
@@ -1079,7 +1106,7 @@
 </div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2575056"></a><span><strong class="command">logging</strong></span> Statement Definition and
+<a name="id2575084"></a><span><strong class="command">logging</strong></span> Statement Definition and
           Usage</h3></div></div></div>
 <p>
           The <span><strong class="command">logging</strong></span> statement configures a
@@ -1113,7 +1140,7 @@
         </p>
 <div class="sect3" lang="en">
 <div class="titlepage"><div><div><h4 class="title">
-<a name="id2575108"></a>The <span><strong class="command">channel</strong></span> Phrase</h4></div></div></div>
+<a name="id2575137"></a>The <span><strong class="command">channel</strong></span> Phrase</h4></div></div></div>
 <p>
             All log output goes to one or more <span class="emphasis"><em>channels</em></span>;
             you can make as many of them as you want.
@@ -1632,7 +1659,7 @@
 </div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2576406"></a><span><strong class="command">lwres</strong></span> Statement Grammar</h3></div></div></div>
+<a name="id2576435"></a><span><strong class="command">lwres</strong></span> Statement Grammar</h3></div></div></div>
 <p>
            This is the grammar of the <span><strong class="command">lwres</strong></span>
           statement in the <code class="filename">named.conf</code> file:
@@ -1647,7 +1674,7 @@
 </div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2576480"></a><span><strong class="command">lwres</strong></span> Statement Definition and Usage</h3></div></div></div>
+<a name="id2576508"></a><span><strong class="command">lwres</strong></span> Statement Definition and Usage</h3></div></div></div>
 <p>
           The <span><strong class="command">lwres</strong></span> statement configures the
           name
@@ -1698,14 +1725,14 @@
 </div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2576544"></a><span><strong class="command">masters</strong></span> Statement Grammar</h3></div></div></div>
+<a name="id2576572"></a><span><strong class="command">masters</strong></span> Statement Grammar</h3></div></div></div>
 <pre class="programlisting">
 <span><strong class="command">masters</strong></span> <em class="replaceable"><code>name</code></em> [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] { ( <em class="replaceable"><code>masters_list</code></em> | <em class="replaceable"><code>ip_addr</code></em> [<span class="optional">port <em class="replaceable"><code>ip_port</code></em></span>] [<span class="optional">key <em class="replaceable"><code>key</code></em></span>] ) ; [<span class="optional">...</span>] };
 </pre>
 </div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2576587"></a><span><strong class="command">masters</strong></span> Statement Definition and
+<a name="id2576616"></a><span><strong class="command">masters</strong></span> Statement Definition and
           Usage</h3></div></div></div>
 <p><span><strong class="command">masters</strong></span>
           lists allow for a common set of masters to be easily used by
@@ -1714,12 +1741,12 @@
 </div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2576602"></a><span><strong class="command">options</strong></span> Statement Grammar</h3></div></div></div>
+<a name="id2576631"></a><span><strong class="command">options</strong></span> Statement Grammar</h3></div></div></div>
 <p>
           This is the grammar of the <span><strong class="command">options</strong></span>
           statement in the <code class="filename">named.conf</code> file:
         </p>
-<pre class="programlisting">options {
+<pre class="programlisting"><span><strong class="command">options</strong></span> {
     [<span class="optional"> version <em class="replaceable"><code>version_string</code></em>; </span>]
     [<span class="optional"> hostname <em class="replaceable"><code>hostname_string</code></em>; </span>]
     [<span class="optional"> server-id <em class="replaceable"><code>server_id_string</code></em>; </span>]
@@ -1780,7 +1807,9 @@
     [<span class="optional"> update-check-ksk <em class="replaceable"><code>yes_or_no</code></em>; </span>]
     [<span class="optional"> allow-v6-synthesis { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
     [<span class="optional"> blackhole { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
+    [<span class="optional"> use-v4-udp-ports { <em class="replaceable"><code>port_list</code></em> }; </span>]
     [<span class="optional"> avoid-v4-udp-ports { <em class="replaceable"><code>port_list</code></em> }; </span>]
+    [<span class="optional"> use-v6-udp-ports { <em class="replaceable"><code>port_list</code></em> }; </span>]
     [<span class="optional"> avoid-v6-udp-ports { <em class="replaceable"><code>port_list</code></em> }; </span>]
     [<span class="optional"> listen-on [<span class="optional"> port <em class="replaceable"><code>ip_port</code></em> </span>] { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
     [<span class="optional"> listen-on-v6 [<span class="optional"> port <em class="replaceable"><code>ip_port</code></em> </span>] { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
@@ -1797,6 +1826,7 @@
     [<span class="optional"> max-transfer-idle-in <em class="replaceable"><code>number</code></em>; </span>]
     [<span class="optional"> max-transfer-idle-out <em class="replaceable"><code>number</code></em>; </span>]
     [<span class="optional"> tcp-clients <em class="replaceable"><code>number</code></em>; </span>]
+    [<span class="optional"> reserved-sockets <em class="replaceable"><code>number</code></em>; </span>]
     [<span class="optional"> recursive-clients <em class="replaceable"><code>number</code></em>; </span>]
     [<span class="optional"> serial-query-rate <em class="replaceable"><code>number</code></em>; </span>]
     [<span class="optional"> serial-queries <em class="replaceable"><code>number</code></em>; </span>]
@@ -2739,11 +2769,12 @@
                   to address (A or AAAA) records and that glue
                   address records exist for delegated zones.  For
                   MX and SRV records only in-zone hostnames are
-                  checked (for out-of-zone hostnames use named-checkzone).
+                  checked (for out-of-zone hostnames use
+                  <span><strong class="command">named-checkzone</strong></span>).
                   For NS records only names below top of zone are
                   checked (for out-of-zone names and glue consistency
-                  checks use named-checkzone).  The default is
-                  <span><strong class="command">yes</strong></span>.
+                  checks use <span><strong class="command">named-checkzone</strong></span>).
+                  The default is <span><strong class="command">yes</strong></span>.
                 </p></dd>
 <dt><span class="term"><span><strong class="command">check-mx-cname</strong></span></span></dt>
 <dd><p>
@@ -2789,7 +2820,7 @@
 </div>
 <div class="sect3" lang="en">
 <div class="titlepage"><div><div><h4 class="title">
-<a name="id2580536"></a>Forwarding</h4></div></div></div>
+<a name="id2580525"></a>Forwarding</h4></div></div></div>
 <p>
             The forwarding facility can be used to create a large site-wide
             cache on a few servers, reducing traffic over links to external
@@ -2833,7 +2864,7 @@
 </div>
 <div class="sect3" lang="en">
 <div class="titlepage"><div><div><h4 class="title">
-<a name="id2580595"></a>Dual-stack Servers</h4></div></div></div>
+<a name="id2580721"></a>Dual-stack Servers</h4></div></div></div>
 <p>
             Dual-stack servers are used as servers of last resort to work
             around
@@ -2988,7 +3019,7 @@
 </div>
 <div class="sect3" lang="en">
 <div class="titlepage"><div><div><h4 class="title">
-<a name="id2581153"></a>Interfaces</h4></div></div></div>
+<a name="id2581142"></a>Interfaces</h4></div></div></div>
 <p>
             The interfaces and ports that the server will answer queries
             from may be specified using the <span><strong class="command">listen-on</strong></span> option. <span><strong class="command">listen-on</strong></span> takes
@@ -3068,7 +3099,7 @@
 </div>
 <div class="sect3" lang="en">
 <div class="titlepage"><div><div><h4 class="title">
-<a name="id2581241"></a>Query Address</h4></div></div></div>
+<a name="query_address"></a>Query Address</h4></div></div></div>
 <p>
             If the server doesn't know the answer to a question, it will
             query other name servers. <span><strong class="command">query-source</strong></span> specifies
@@ -3077,23 +3108,83 @@
             If <span><strong class="command">address</strong></span> is <span><strong class="command">*</strong></span> (asterisk) or is omitted,
             a wildcard IP address (<span><strong class="command">INADDR_ANY</strong></span>)
             will be used.
+          </p>
+<p>
             If <span><strong class="command">port</strong></span> is <span><strong class="command">*</strong></span> or is omitted,
-	    a random unprivileged port number is picked up and will be
-            used for each query.
-	    It is generally strongly discouraged to
-	    specify a particular port for the
-	    <span><strong class="command">query-source</strong></span> or
-	    <span><strong class="command">query-source-v6</strong></span>
-	    options; it implicitly disables the use of randomized port numbers
-	    and leads to insecure operation.
-	    The <span><strong class="command">avoid-v4-udp-ports</strong></span>
-	    and <span><strong class="command">avoid-v6-udp-ports</strong></span> options can be used
-	    to prevent named
-	    from selecting certain ports. The defaults are:
+            a random port number from a pre-configured
+            range is picked up and will be used for each query.
+            The port range(s) is that specified in
+            the <span><strong class="command">use-v4-udp-ports</strong></span> (for IPv4)
+            and <span><strong class="command">use-v6-udp-ports</strong></span> (for IPv6)
+            options, excluding the ranges specified in
+            the <span><strong class="command">avoid-v4-udp-ports</strong></span>
+            and <span><strong class="command">avoid-v6-udp-ports</strong></span> options, respectively.
+          </p>
+<p>
+            The defaults of the <span><strong class="command">query-source</strong></span> and
+            <span><strong class="command">query-source-v6</strong></span> options
+            are:
           </p>
 <pre class="programlisting">query-source address * port *;
 query-source-v6 address * port *;
 </pre>
+<p>
+            If <span><strong class="command">use-v4-udp-ports</strong></span> or
+            <span><strong class="command">use-v6-udp-ports</strong></span> is unspecified,
+            <span><strong class="command">named</strong></span> will check if the operating
+            system provides a programming interface to retrieve the
+            system's default range for ephemeral ports.
+            If such an interface is available,
+            <span><strong class="command">named</strong></span> will use the corresponding system
+            default range; otherwise, it will use its own defaults:
+         </p>
+<pre class="programlisting">use-v4-udp-ports { range 1024 65535; };
+use-v6-udp-ports { range 1024 65535; };
+</pre>
+<p>
+            Note: make sure the ranges be sufficiently large for
+            security.  A desirable size depends on various parameters,
+            but we generally recommend it contain at least 16384 ports
+            (14 bits of entropy).
+            Note also that the system's default range when used may be
+            too small for this purpose, and that the range may even be
+            changed while <span><strong class="command">named</strong></span> is running; the new
+            range will automatically be applied when <span><strong class="command">named</strong></span>
+            is reloaded.
+            It is encouraged to
+            configure <span><strong class="command">use-v4-udp-ports</strong></span> and
+            <span><strong class="command">use-v6-udp-ports</strong></span> explicitly so that the
+            ranges are sufficiently large and are reasonably
+            independent from the ranges used by other applications.
+          </p>
+<p>
+            Note: the operational configuration
+            where <span><strong class="command">named</strong></span> runs may prohibit the use
+            of some ports.  For example, UNIX systems will not allow
+            <span><strong class="command">named</strong></span> running without a root privilege
+            to use ports less than 1024.
+            If such ports are included in the specified (or detected)
+            set of query ports, the corresponding query attempts will
+            fail, resulting in resolution failures or delay.
+            It is therefore important to configure the set of ports
+            that can be safely used in the expected operational environment.
+          </p>
+<p>
+            The defaults of the <span><strong class="command">avoid-v4-udp-ports</strong></span> and
+            <span><strong class="command">avoid-v6-udp-ports</strong></span> options
+            are:
+          </p>
+<pre class="programlisting">avoid-v4-udp-ports {};
+avoid-v6-udp-ports {};
+</pre>
+<p>
+            Note: it is generally strongly discouraged to
+            specify a particular port for the
+            <span><strong class="command">query-source</strong></span> or
+            <span><strong class="command">query-source-v6</strong></span> options;
+            it implicitly disables the use of randomized port numbers
+            and can be insecure.
+          </p>
 <div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
 <h3 class="title">Note</h3>
 <p>
@@ -3356,21 +3447,49 @@
 </div>
 <div class="sect3" lang="en">
 <div class="titlepage"><div><div><h4 class="title">
-<a name="id2581988"></a>Bad UDP Port Lists</h4></div></div></div>
-<p><span><strong class="command">avoid-v4-udp-ports</strong></span>
-            and <span><strong class="command">avoid-v6-udp-ports</strong></span> specify a list
-            of IPv4 and IPv6 UDP ports that will not be used as system
-            assigned source ports for UDP sockets.  These lists
-            prevent named from choosing as its random source port a
-            port that is blocked by your firewall.  If a query went
-            out with such a source port, the answer would not get by
-            the firewall and the name server would have to query
-            again.
+<a name="id2582140"></a>UDP Port Lists</h4></div></div></div>
+<p>
+            <span><strong class="command">use-v4-udp-ports</strong></span>,
+            <span><strong class="command">avoid-v4-udp-ports</strong></span>,
+            <span><strong class="command">use-v6-udp-ports</strong></span>, and
+            <span><strong class="command">avoid-v6-udp-ports</strong></span>
+            specify a list of IPv4 and IPv6 UDP ports that will be
+            used or not used as source ports for UDP messages.
+            See <a href="Bv9ARM.ch06.html#query_address" title="Query Address">the section called “Query Address”</a> about how the
+            available ports are determined.
+            For example, with the following configuration
           </p>
+<pre class="programlisting">
+use-v6-udp-ports { range 32768 65535; };
+avoid-v6-udp-ports { 40000; range 50000 60000; };
+</pre>
+<p>
+             UDP ports of IPv6 messages sent
+             from <span><strong class="command">named</strong></span> will be in one
+             of the following ranges: 32768 to 39999, 40001 to 49999,
+             and 60001 to 65535.
+           </p>
+<p>
+             <span><strong class="command">avoid-v4-udp-ports</strong></span> and
+             <span><strong class="command">avoid-v6-udp-ports</strong></span> can be used
+             to prevent <span><strong class="command">named</strong></span> from choosing as its random source port a
+             port that is blocked by your firewall or a port that is
+             used by other applications;
+             if a query went out with a source port blocked by a
+             firewall, the
+             answer would not get by the firewall and the name server would
+             have to query again.
+             Note: the desired range can also be represented only with
+             <span><strong class="command">use-v4-udp-ports</strong></span> and
+             <span><strong class="command">use-v6-udp-ports</strong></span>, and the
+             <span><strong class="command">avoid-</strong></span> options are redundant in that
+             sense; they are provided for backward compatibility and
+             to possibly simplify the port specification.
+           </p>
 </div>
 <div class="sect3" lang="en">
 <div class="titlepage"><div><div><h4 class="title">
-<a name="id2582003"></a>Operating System Resource Limits</h4></div></div></div>
+<a name="id2582200"></a>Operating System Resource Limits</h4></div></div></div>
 <p>
             The server's usage of many system resources can be limited.
             Scaled values are allowed when specifying resource limits.  For
@@ -3429,7 +3548,7 @@
 </div>
 <div class="sect3" lang="en">
 <div class="titlepage"><div><div><h4 class="title">
-<a name="id2582186"></a>Server  Resource Limits</h4></div></div></div>
+<a name="id2582452"></a>Server  Resource Limits</h4></div></div></div>
 <p>
             The following options set limits on the server's
             resource consumption that are enforced internally by the
@@ -3478,19 +3597,42 @@
                   connections that the server will accept.
                   The default is <code class="literal">100</code>.
                 </p></dd>
+<dt><span class="term"><span><strong class="command">reserved-sockets</strong></span></span></dt>
+<dd>
+<p>
+                  The number of file descriptors reserved for TCP, stdio,
+                  etc.  This needs to be big enough to cover the number of
+                  interfaces named listens on, tcp-clients as well as
+                  to provide room for outgoing TCP queries and incoming zone
+                  transfers.  The default is <code class="literal">512</code>.
+                  The minimum value is <code class="literal">128</code> and the
+                  maximum value is <code class="literal">128</code> less than
+                  maxsockets (-S).  This option may be removed in the future.
+                </p>
+<p>
+                  This option has little effect on Windows.
+                </p>
+</dd>
 <dt><span class="term"><span><strong class="command">max-cache-size</strong></span></span></dt>
 <dd><p>
                   The maximum amount of memory to use for the
-                  server's cache, in bytes.  When the amount of data in the
-                  cache
+                  server's cache, in bytes.
+                  When the amount of data in the cache
                   reaches this limit, the server will cause records to expire
-                  prematurely so that the limit is not exceeded.  In a server
-                  with
-                  multiple views, the limit applies separately to the cache of
-                  each
-                  view.  The default is <code class="literal">unlimited</code>, meaning that
-                  records are purged from the cache only when their TTLs
-                  expire.
+                  prematurely so that the limit is not exceeded.
+                  A value of 0 is special, meaning that
+                  records are purged from the cache only when their
+                  TTLs expire.
+                  Another special keyword <strong class="userinput"><code>unlimited</code></strong>
+                  means the maximum value of 32-bit unsigned integers
+                  (0xffffffff), which may not have the same effect as
+                  0 on machines that support more than 32 bits of
+                  memory space.
+                  Any positive values less than 2MB will be ignored reset
+                  to 2MB.
+                  In a server with multiple views, the limit applies
+                  separately to the cache of each view.
+                  The default is 0.
                 </p></dd>
 <dt><span class="term"><span><strong class="command">tcp-listen-queue</strong></span></span></dt>
 <dd><p>
@@ -3507,7 +3649,7 @@
 </div>
 <div class="sect3" lang="en">
 <div class="titlepage"><div><div><h4 class="title">
-<a name="id2582320"></a>Periodic Task Intervals</h4></div></div></div>
+<a name="id2582682"></a>Periodic Task Intervals</h4></div></div></div>
 <div class="variablelist"><dl>
 <dt><span class="term"><span><strong class="command">cleaning-interval</strong></span></span></dt>
 <dd><p>
@@ -3837,6 +3979,10 @@
                   Sets the maximum time for which the server will
                   cache ordinary (positive) answers. The default is
                   one week (7 days).
+                  A value of zero may cause all queries to return
+                  SERVFAIL, because of lost caches of intermediate
+                  RRsets (such as NS and glue AAAA/A records) in the
+                  resolution process.
                 </p></dd>
 <dt><span class="term"><span><strong class="command">min-roots</strong></span></span></dt>
 <dd>
@@ -4062,27 +4208,11 @@
             The current list of empty zones is:
             </p>
 <div class="itemizedlist"><ul type="disc">
-<li>10.IN-ADDR.ARPA</li>
+<li>0.IN-ADDR.ARPA</li>
 <li>127.IN-ADDR.ARPA</li>
 <li>254.169.IN-ADDR.ARPA</li>
-<li>16.172.IN-ADDR.ARPA</li>
-<li>17.172.IN-ADDR.ARPA</li>
-<li>18.172.IN-ADDR.ARPA</li>
-<li>19.172.IN-ADDR.ARPA</li>
-<li>20.172.IN-ADDR.ARPA</li>
-<li>21.172.IN-ADDR.ARPA</li>
-<li>22.172.IN-ADDR.ARPA</li>
-<li>23.172.IN-ADDR.ARPA</li>
-<li>24.172.IN-ADDR.ARPA</li>
-<li>25.172.IN-ADDR.ARPA</li>
-<li>26.172.IN-ADDR.ARPA</li>
-<li>27.172.IN-ADDR.ARPA</li>
-<li>28.172.IN-ADDR.ARPA</li>
-<li>29.172.IN-ADDR.ARPA</li>
-<li>30.172.IN-ADDR.ARPA</li>
-<li>31.172.IN-ADDR.ARPA</li>
-<li>168.192.IN-ADDR.ARPA</li>
 <li>2.0.192.IN-ADDR.ARPA</li>
+<li>255.255.255.255.IN-ADDR.ARPA</li>
 <li>0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA</li>
 <li>1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA</li>
 <li>D.F.IP6.ARPA</li>
@@ -4292,8 +4422,10 @@
             <span><strong class="command">success</strong></span>,
             <span><strong class="command">referral</strong></span>,
             <span><strong class="command">nxrrset</strong></span>,
-            <span><strong class="command">nxdomain</strong></span>, or
-            <span><strong class="command">failure</strong></span>
+            <span><strong class="command">nxdomain</strong></span>,
+            <span><strong class="command">failure</strong></span>,
+            <span><strong class="command">duplicate</strong></span>, or
+            <span><strong class="command">dropped</strong></span>
             to be incremented, and may additionally cause the
             <span><strong class="command">recursion</strong></span> counter to be
             incremented.
@@ -4397,7 +4529,7 @@
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
 <a name="server_statement_grammar"></a><span><strong class="command">server</strong></span> Statement Grammar</h3></div></div></div>
-<pre class="programlisting">server <em class="replaceable"><code>ip_addr[/prefixlen]</code></em> {
+<pre class="programlisting"><span><strong class="command">server</strong></span> <em class="replaceable"><code>ip_addr[/prefixlen]</code></em> {
     [<span class="optional"> bogus <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
     [<span class="optional"> provide-ixfr <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
     [<span class="optional"> request-ixfr <em class="replaceable"><code>yes_or_no</code></em> ; </span>]
@@ -4587,8 +4719,8 @@
 </div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2585361"></a><span><strong class="command">trusted-keys</strong></span> Statement Grammar</h3></div></div></div>
-<pre class="programlisting">trusted-keys {
+<a name="id2585614"></a><span><strong class="command">trusted-keys</strong></span> Statement Grammar</h3></div></div></div>
+<pre class="programlisting"><span><strong class="command">trusted-keys</strong></span> {
     <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>number</code></em> <em class="replaceable"><code>number</code></em> <em class="replaceable"><code>number</code></em> <em class="replaceable"><code>string</code></em> ;
     [<span class="optional"> <em class="replaceable"><code>string</code></em> <em class="replaceable"><code>number</code></em> <em class="replaceable"><code>number</code></em> <em class="replaceable"><code>number</code></em> <em class="replaceable"><code>string</code></em> ; [<span class="optional">...</span>]</span>]
 };
@@ -4596,7 +4728,7 @@
 </div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2585410"></a><span><strong class="command">trusted-keys</strong></span> Statement Definition
+<a name="id2585666"></a><span><strong class="command">trusted-keys</strong></span> Statement Definition
             and Usage</h3></div></div></div>
 <p>
             The <span><strong class="command">trusted-keys</strong></span> statement defines
@@ -4627,7 +4759,7 @@
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
 <a name="view_statement_grammar"></a><span><strong class="command">view</strong></span> Statement Grammar</h3></div></div></div>
-<pre class="programlisting">view <em class="replaceable"><code>view_name</code></em>
+<pre class="programlisting"><span><strong class="command">view</strong></span> <em class="replaceable"><code>view_name</code></em>
       [<span class="optional"><em class="replaceable"><code>class</code></em></span>] {
       match-clients { <em class="replaceable"><code>address_match_list</code></em> };
       match-destinations { <em class="replaceable"><code>address_match_list</code></em> };
@@ -4639,7 +4771,7 @@
 </div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2585490"></a><span><strong class="command">view</strong></span> Statement Definition and Usage</h3></div></div></div>
+<a name="id2585748"></a><span><strong class="command">view</strong></span> Statement Definition and Usage</h3></div></div></div>
 <p>
             The <span><strong class="command">view</strong></span> statement is a powerful
             feature
@@ -4680,7 +4812,7 @@
 <p>
             Zones defined within a <span><strong class="command">view</strong></span>
             statement will
-            be only be accessible to clients that match the <span><strong class="command">view</strong></span>.
+            only be accessible to clients that match the <span><strong class="command">view</strong></span>.
             By defining a zone of the same name in multiple views, different
             zone data can be given to different clients, for example,
             "internal"
@@ -4759,7 +4891,7 @@
 <div class="titlepage"><div><div><h3 class="title">
 <a name="zone_statement_grammar"></a><span><strong class="command">zone</strong></span>
             Statement Grammar</h3></div></div></div>
-<pre class="programlisting">zone <em class="replaceable"><code>zone_name</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em></span>] {
+<pre class="programlisting"><span><strong class="command">zone</strong></span> <em class="replaceable"><code>zone_name</code></em> [<span class="optional"><em class="replaceable"><code>class</code></em></span>] {
     type master;
     [<span class="optional"> allow-query { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
     [<span class="optional"> allow-transfer { <em class="replaceable"><code>address_match_list</code></em> }; </span>]
@@ -4891,10 +5023,10 @@
 </div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2586798"></a><span><strong class="command">zone</strong></span> Statement Definition and Usage</h3></div></div></div>
+<a name="id2587332"></a><span><strong class="command">zone</strong></span> Statement Definition and Usage</h3></div></div></div>
 <div class="sect3" lang="en">
 <div class="titlepage"><div><div><h4 class="title">
-<a name="id2586806"></a>Zone Types</h4></div></div></div>
+<a name="id2587339"></a>Zone Types</h4></div></div></div>
 <div class="informaltable"><table border="1">
 <colgroup>
 <col>
@@ -5103,7 +5235,7 @@
 </div>
 <div class="sect3" lang="en">
 <div class="titlepage"><div><div><h4 class="title">
-<a name="id2587362"></a>Class</h4></div></div></div>
+<a name="id2587690"></a>Class</h4></div></div></div>
 <p>
               The zone's name may optionally be followed by a class. If
               a class is not specified, class <code class="literal">IN</code> (for <code class="varname">Internet</code>),
@@ -5125,7 +5257,7 @@
 </div>
 <div class="sect3" lang="en">
 <div class="titlepage"><div><div><h4 class="title">
-<a name="id2587395"></a>Zone Options</h4></div></div></div>
+<a name="id2587723"></a>Zone Options</h4></div></div></div>
 <div class="variablelist"><dl>
 <dt><span class="term"><span><strong class="command">allow-notify</strong></span></span></dt>
 <dd><p>
@@ -5613,7 +5745,7 @@
 </div>
 <div class="sect1" lang="en">
 <div class="titlepage"><div><div><h2 class="title" style="clear: both">
-<a name="id2589080"></a>Zone File</h2></div></div></div>
+<a name="id2589477"></a>Zone File</h2></div></div></div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
 <a name="types_of_resource_records_and_when_to_use_them"></a>Types of Resource Records and When to Use Them</h3></div></div></div>
@@ -5626,7 +5758,7 @@
           </p>
 <div class="sect3" lang="en">
 <div class="titlepage"><div><div><h4 class="title">
-<a name="id2589098"></a>Resource Records</h4></div></div></div>
+<a name="id2589495"></a>Resource Records</h4></div></div></div>
 <p>
               A domain name identifies a node.  Each node has a set of
               resource information, which may be empty.  The set of resource
@@ -5890,6 +6022,19 @@
 <tr>
 <td>
                       <p>
+                        IPSECKEY
+                      </p>
+                    </td>
+<td>
+                      <p>
+                        Provides a method for storing IPsec keying material in
+                        DNS.  Described in RFC 4025.
+                      </p>
+                    </td>
+</tr>
+<tr>
+<td>
+                      <p>
                         ISDN
                       </p>
                     </td>
@@ -6128,6 +6273,19 @@
 <tr>
 <td>
                       <p>
+                        SPF
+                      </p>
+                    </td>
+<td>
+                      <p>
+                        Contains the Sender Policy Framework information
+                        for a given email domain.  Described in RFC 4408.
+                      </p>
+                    </td>
+</tr>
+<tr>
+<td>
+                      <p>
                         SRV
                       </p>
                     </td>
@@ -6141,6 +6299,19 @@
 <tr>
 <td>
                       <p>
+                        SSHFP
+                      </p>
+                    </td>
+<td>
+                      <p>
+                        Provides a way to securly publish a secure shell key's
+                        fingerprint.  Described in RFC 4255.
+                      </p>
+                    </td>
+</tr>
+<tr>
+<td>
+                      <p>
                         TXT
                       </p>
                     </td>
@@ -6277,7 +6448,7 @@
 </div>
 <div class="sect3" lang="en">
 <div class="titlepage"><div><div><h4 class="title">
-<a name="id2590513"></a>Textual expression of RRs</h4></div></div></div>
+<a name="id2590912"></a>Textual expression of RRs</h4></div></div></div>
 <p>
               RRs are represented in binary form in the packets of the DNS
               protocol, and are usually represented in highly encoded form
@@ -6480,7 +6651,7 @@
 </div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2591101"></a>Discussion of MX Records</h3></div></div></div>
+<a name="id2591500"></a>Discussion of MX Records</h3></div></div></div>
 <p>
             As described above, domain servers store information as a
             series of resource records, each of which contains a particular
@@ -6738,7 +6909,7 @@
 </div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2591653"></a>Inverse Mapping in IPv4</h3></div></div></div>
+<a name="id2592188"></a>Inverse Mapping in IPv4</h3></div></div></div>
 <p>
             Reverse name resolution (that is, translation from IP address
             to name) is achieved by means of the <span class="emphasis"><em>in-addr.arpa</em></span> domain
@@ -6799,7 +6970,7 @@
 </div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2591848"></a>Other Zone File Directives</h3></div></div></div>
+<a name="id2592384"></a>Other Zone File Directives</h3></div></div></div>
 <p>
             The Master File Format was initially defined in RFC 1035 and
             has subsequently been extended. While the Master File Format
@@ -6814,7 +6985,7 @@
           </p>
 <div class="sect3" lang="en">
 <div class="titlepage"><div><div><h4 class="title">
-<a name="id2591870"></a>The <span><strong class="command">$ORIGIN</strong></span> Directive</h4></div></div></div>
+<a name="id2592406"></a>The <span><strong class="command">$ORIGIN</strong></span> Directive</h4></div></div></div>
 <p>
               Syntax: <span><strong class="command">$ORIGIN</strong></span>
               <em class="replaceable"><code>domain-name</code></em>
@@ -6842,7 +7013,7 @@
 </div>
 <div class="sect3" lang="en">
 <div class="titlepage"><div><div><h4 class="title">
-<a name="id2592000"></a>The <span><strong class="command">$INCLUDE</strong></span> Directive</h4></div></div></div>
+<a name="id2592467"></a>The <span><strong class="command">$INCLUDE</strong></span> Directive</h4></div></div></div>
 <p>
               Syntax: <span><strong class="command">$INCLUDE</strong></span>
               <em class="replaceable"><code>filename</code></em>
@@ -6878,7 +7049,7 @@
 </div>
 <div class="sect3" lang="en">
 <div class="titlepage"><div><div><h4 class="title">
-<a name="id2592069"></a>The <span><strong class="command">$TTL</strong></span> Directive</h4></div></div></div>
+<a name="id2592536"></a>The <span><strong class="command">$TTL</strong></span> Directive</h4></div></div></div>
 <p>
               Syntax: <span><strong class="command">$TTL</strong></span>
               <em class="replaceable"><code>default-ttl</code></em>
@@ -6897,7 +7068,7 @@
 </div>
 <div class="sect2" lang="en">
 <div class="titlepage"><div><div><h3 class="title">
-<a name="id2592173"></a><acronym class="acronym">BIND</acronym> Master File Extension: the  <span><strong class="command">$GENERATE</strong></span> Directive</h3></div></div></div>
+<a name="id2592572"></a><acronym class="acronym">BIND</acronym> Master File Extension: the  <span><strong class="command">$GENERATE</strong></span> Directive</h3></div></div></div>
 <p>
             Syntax: <span><strong class="command">$GENERATE</strong></span>
             <em class="replaceable"><code>range</code></em>
@@ -6922,7 +7093,7 @@
 <p>
             is equivalent to
           </p>
-<pre class="programlisting">0.0.0.192.IN-ADDR.ARPA NS SERVER1.EXAMPLE.
+<pre class="programlisting">0.0.0.192.IN-ADDR.ARPA. NS SERVER1.EXAMPLE.
 0.0.0.192.IN-ADDR.ARPA. NS SERVER2.EXAMPLE.
 1.0.0.192.IN-ADDR.ARPA. CNAME 1.0.0.0.192.IN-ADDR.ARPA.
 2.0.0.192.IN-ADDR.ARPA. CNAME 2.0.0.0.192.IN-ADDR.ARPA.
Index: Bv9ARM-book.xml
===================================================================
RCS file: /home/cvs/src/contrib/bind9/doc/arm/Bv9ARM-book.xml,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/bind9/doc/arm/Bv9ARM-book.xml -L contrib/bind9/doc/arm/Bv9ARM-book.xml -u -r1.2 -r1.3
--- contrib/bind9/doc/arm/Bv9ARM-book.xml
+++ contrib/bind9/doc/arm/Bv9ARM-book.xml
@@ -2,7 +2,7 @@
                "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
 	       [<!ENTITY mdash "—">]>
 <!--
- - 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
@@ -18,7 +18,7 @@
  - PERFORMANCE OF THIS SOFTWARE.
 -->
 
-<!-- File: $Id: Bv9ARM-book.xml,v 1.241.18.82.8.1 2008/05/22 21:28:04 each Exp $ -->
+<!-- File: $Id: Bv9ARM-book.xml,v 1.241.18.97 2008/10/17 19:37:35 jreed Exp $ -->
 <book xmlns:xi="http://www.w3.org/2001/XInclude">
   <title>BIND 9 Administrator Reference Manual</title>
 
@@ -28,6 +28,7 @@
       <year>2005</year>
       <year>2006</year>
       <year>2007</year>
+      <year>2008</year>
       <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
     </copyright>
     <copyright>
@@ -638,13 +639,11 @@
       <title>Supported Operating Systems</title>
       <para>
         ISC <acronym>BIND</acronym> 9 compiles and runs on a large
-        number
-        of Unix-like operating system and on NT-derived versions of
-        Microsoft Windows such as Windows 2000 and Windows XP.  For an
-        up-to-date
-        list of supported systems, see the README file in the top level
-        directory
-        of the BIND 9 source distribution.
+        number of Unix-like operating systems, and on some versions of
+        Microsoft Windows including Windows XP, Windows 2003, and
+        Windows 2008.  For an up-to-date list of supported systems,
+        see the README file in the top level directory of the BIND 9
+        source distribution.
       </para>
     </sect1>
   </chapter>
@@ -2929,6 +2928,33 @@
             <row rowsep="0">
               <entry colname="1">
                 <para>
+                  <varname>port_list</varname>
+                </para>
+              </entry>
+              <entry colname="2">
+                <para>
+		  A list of an <varname>ip_port</varname> or a port
+		  range.
+		  A port range is specified in the form of
+		  <userinput>range</userinput> followed by
+		  two <varname>ip_port</varname>s,
+		  <varname>port_low</varname> and
+		  <varname>port_high</varname>, which represents
+		  port numbers from <varname>port_low</varname> through
+		  <varname>port_high</varname>, inclusive.
+		  <varname>port_low</varname> must not be larger than
+		  <varname>port_high</varname>.
+		  For example,
+		  <userinput>range 1024 65535</userinput> represents
+		  ports from 1024 through 65535.
+		  In either case an asterisk (`*') character is not
+		  allowed as a valid <varname>ip_port</varname>.
+                </para>
+              </entry>
+            </row>
+            <row rowsep="0">
+              <entry colname="1">
+                <para>
                   <varname>size_spec</varname>
                 </para>
               </entry>
@@ -3581,7 +3607,7 @@
       </sect2>
       <sect2>
         <title><command>include</command> Statement Grammar</title>
-        <programlisting>include <replaceable>filename</replaceable>;</programlisting>
+        <programlisting><command>include</command> <replaceable>filename</replaceable>;</programlisting>
       </sect2>
       <sect2>
         <title><command>include</command> Statement Definition and
@@ -3602,7 +3628,7 @@
       <sect2>
         <title><command>key</command> Statement Grammar</title>
 
-<programlisting>key <replaceable>key_id</replaceable> {
+<programlisting><command>key</command> <replaceable>key_id</replaceable> {
     algorithm <replaceable>string</replaceable>;
     secret <replaceable>string</replaceable>;
 };
@@ -4363,7 +4389,7 @@
           statement in the <filename>named.conf</filename> file:
         </para>
 
-<programlisting>options {
+<programlisting><command>options</command> {
     <optional> version <replaceable>version_string</replaceable>; </optional>
     <optional> hostname <replaceable>hostname_string</replaceable>; </optional>
     <optional> server-id <replaceable>server_id_string</replaceable>; </optional>
@@ -4424,7 +4450,9 @@
     <optional> update-check-ksk <replaceable>yes_or_no</replaceable>; </optional>
     <optional> allow-v6-synthesis { <replaceable>address_match_list</replaceable> }; </optional>
     <optional> blackhole { <replaceable>address_match_list</replaceable> }; </optional>
+    <optional> use-v4-udp-ports { <replaceable>port_list</replaceable> }; </optional>
     <optional> avoid-v4-udp-ports { <replaceable>port_list</replaceable> }; </optional>
+    <optional> use-v6-udp-ports { <replaceable>port_list</replaceable> }; </optional>
     <optional> avoid-v6-udp-ports { <replaceable>port_list</replaceable> }; </optional>
     <optional> listen-on <optional> port <replaceable>ip_port</replaceable> </optional> { <replaceable>address_match_list</replaceable> }; </optional>
     <optional> listen-on-v6 <optional> port <replaceable>ip_port</replaceable> </optional> { <replaceable>address_match_list</replaceable> }; </optional>
@@ -4441,6 +4469,7 @@
     <optional> max-transfer-idle-in <replaceable>number</replaceable>; </optional>
     <optional> max-transfer-idle-out <replaceable>number</replaceable>; </optional>
     <optional> tcp-clients <replaceable>number</replaceable>; </optional>
+    <optional> reserved-sockets <replaceable>number</replaceable>; </optional>
     <optional> recursive-clients <replaceable>number</replaceable>; </optional>
     <optional> serial-query-rate <replaceable>number</replaceable>; </optional>
     <optional> serial-queries <replaceable>number</replaceable>; </optional>
@@ -5625,11 +5654,12 @@
 		  to address (A or AAAA) records and that glue
 		  address records exist for delegated zones.  For
 		  MX and SRV records only in-zone hostnames are
-		  checked (for out-of-zone hostnames use named-checkzone).
+		  checked (for out-of-zone hostnames use
+		  <command>named-checkzone</command>).
 		  For NS records only names below top of zone are
 		  checked (for out-of-zone names and glue consistency
-		  checks use named-checkzone).  The default is
-		  <command>yes</command>.
+		  checks use <command>named-checkzone</command>).
+	          The default is <command>yes</command>.
 		</para>
 	      </listitem>
 	    </varlistentry>
@@ -6056,7 +6086,7 @@
           </para>
         </sect3>
 
-        <sect3>
+        <sect3 id="query_address">
           <title>Query Address</title>
           <para>
             If the server doesn't know the answer to a question, it will
@@ -6066,25 +6096,94 @@
             If <command>address</command> is <command>*</command> (asterisk) or is omitted,
             a wildcard IP address (<command>INADDR_ANY</command>)
             will be used.
+	  </para>
+
+	  <para>
             If <command>port</command> is <command>*</command> or is omitted,
-	    a random unprivileged port number is picked up and will be
-	    used for each query.
-	    It is generally strongly discouraged to
-	    specify a particular port for the
-	    <command>query-source</command> or
-	    <command>query-source-v6</command> options;
-	    it implicitly disables the use of randomized port numbers
-	    and leads to insecure operation.
-            The <command>avoid-v4-udp-ports</command>
-            and <command>avoid-v6-udp-ports</command> options can be used
-            to prevent named
-            from selecting certain ports. The defaults are:
+	    a random port number from a pre-configured
+	    range is picked up and will be used for each query.
+	    The port range(s) is that specified in
+	    the <command>use-v4-udp-ports</command> (for IPv4)
+            and <command>use-v6-udp-ports</command> (for IPv6)
+	    options, excluding the ranges specified in
+	    the <command>avoid-v4-udp-ports</command>
+            and <command>avoid-v6-udp-ports</command> options, respectively.
+	  </para>
+
+          <para>
+	    The defaults of the <command>query-source</command> and
+	    <command>query-source-v6</command> options
+	    are:
           </para>
 
 <programlisting>query-source address * port *;
 query-source-v6 address * port *;
 </programlisting>
 
+          <para>
+	    If <command>use-v4-udp-ports</command> or
+            <command>use-v6-udp-ports</command> is unspecified,
+	    <command>named</command> will check if the operating
+	    system provides a programming interface to retrieve the
+	    system's default range for ephemeral ports.
+	    If such an interface is available,
+	    <command>named</command> will use the corresponding system
+	    default range; otherwise, it will use its own defaults:
+         </para>
+
+<programlisting>use-v4-udp-ports { range 1024 65535; };
+use-v6-udp-ports { range 1024 65535; };
+</programlisting>
+
+          <para>
+	    Note: make sure the ranges be sufficiently large for
+	    security.  A desirable size depends on various parameters,
+	    but we generally recommend it contain at least 16384 ports
+	    (14 bits of entropy).
+	    Note also that the system's default range when used may be
+	    too small for this purpose, and that the range may even be
+	    changed while <command>named</command> is running; the new
+	    range will automatically be applied when <command>named</command>
+	    is reloaded.
+	    It is encouraged to
+	    configure <command>use-v4-udp-ports</command> and
+            <command>use-v6-udp-ports</command> explicitly so that the
+            ranges are sufficiently large and are reasonably
+            independent from the ranges used by other applications.
+          </para>
+
+	  <para>
+	    Note: the operational configuration
+	    where <command>named</command> runs may prohibit the use
+	    of some ports.  For example, UNIX systems will not allow
+	    <command>named</command> running without a root privilege
+	    to use ports less than 1024.
+	    If such ports are included in the specified (or detected)
+	    set of query ports, the corresponding query attempts will
+	    fail, resulting in resolution failures or delay.
+	    It is therefore important to configure the set of ports
+	    that can be safely used in the expected operational environment.
+	  </para>
+
+          <para>
+	    The defaults of the <command>avoid-v4-udp-ports</command> and
+	    <command>avoid-v6-udp-ports</command> options
+	    are:
+          </para>
+
+<programlisting>avoid-v4-udp-ports {};
+avoid-v6-udp-ports {};
+</programlisting>
+
+	  <para>
+	    Note: it is generally strongly discouraged to
+            specify a particular port for the
+	    <command>query-source</command> or
+	    <command>query-source-v6</command> options;
+	    it implicitly disables the use of randomized port numbers
+	    and can be insecure.
+          </para>
+
           <note>
             <para>
               The address specified in the <command>query-source</command> option
@@ -6430,17 +6529,48 @@
         </sect3>
 
         <sect3>
-          <title>Bad UDP Port Lists</title>
-          <para><command>avoid-v4-udp-ports</command>
-	    and <command>avoid-v6-udp-ports</command> specify a list
-            of IPv4 and IPv6 UDP ports that will not be used as system
-            assigned source ports for UDP sockets.  These lists
-            prevent named from choosing as its random source port a
-            port that is blocked by your firewall.  If a query went
-            out with such a source port, the answer would not get by
-            the firewall and the name server would have to query
-            again.
+          <title>UDP Port Lists</title>
+          <para>
+	    <command>use-v4-udp-ports</command>,
+	    <command>avoid-v4-udp-ports</command>,
+	    <command>use-v6-udp-ports</command>, and
+	    <command>avoid-v6-udp-ports</command>
+	    specify a list of IPv4 and IPv6 UDP ports that will be
+	    used or not used as source ports for UDP messages.
+	    See <xref linkend="query_address"/> about how the
+	    available ports are determined.
+	    For example, with the following configuration
           </para>
+
+<programlisting>
+use-v6-udp-ports { range 32768 65535; };
+avoid-v6-udp-ports { 40000; range 50000 60000; };
+</programlisting>
+
+	   <para>
+	     UDP ports of IPv6 messages sent
+	     from <command>named</command> will be in one
+	     of the following ranges: 32768 to 39999, 40001 to 49999,
+	     and 60001 to 65535.
+	   </para>
+
+	   <para>
+	     <command>avoid-v4-udp-ports</command> and
+	     <command>avoid-v6-udp-ports</command> can be used
+             to prevent <command>named</command> from choosing as its random source port a
+             port that is blocked by your firewall or a port that is
+             used by other applications;
+	     if a query went out with a source port blocked by a
+             firewall, the
+	     answer would not get by the firewall and the name server would
+             have to query again.
+	     Note: the desired range can also be represented only with
+	     <command>use-v4-udp-ports</command> and
+	     <command>use-v6-udp-ports</command>, and the
+	     <command>avoid-</command> options are redundant in that
+	     sense; they are provided for backward compatibility and
+	     to possibly simplify the port specification.
+	   </para>
         </sect3>
 
         <sect3>
@@ -6606,20 +6736,46 @@
             </varlistentry>
 
             <varlistentry>
+              <term><command>reserved-sockets</command></term>
+              <listitem>
+                <para>
+		  The number of file descriptors reserved for TCP, stdio,
+		  etc.  This needs to be big enough to cover the number of
+		  interfaces named listens on, tcp-clients as well as
+		  to provide room for outgoing TCP queries and incoming zone
+		  transfers.  The default is <literal>512</literal>.
+		  The minimum value is <literal>128</literal> and the
+		  maximum value is <literal>128</literal> less than
+		  maxsockets (-S).  This option may be removed in the future.
+                </para>
+                <para>
+		  This option has little effect on Windows.
+                </para>
+              </listitem>
+            </varlistentry>
+
+            <varlistentry>
               <term><command>max-cache-size</command></term>
               <listitem>
                 <para>
                   The maximum amount of memory to use for the
-                  server's cache, in bytes.  When the amount of data in the
-                  cache
+                  server's cache, in bytes.
+                  When the amount of data in the cache
                   reaches this limit, the server will cause records to expire
-                  prematurely so that the limit is not exceeded.  In a server
-                  with
-                  multiple views, the limit applies separately to the cache of
-                  each
-                  view.  The default is <literal>unlimited</literal>, meaning that
-                  records are purged from the cache only when their TTLs
-                  expire.
+                  prematurely so that the limit is not exceeded.
+                  A value of 0 is special, meaning that
+                  records are purged from the cache only when their
+                  TTLs expire.
+                  Another special keyword <userinput>unlimited</userinput>
+                  means the maximum value of 32-bit unsigned integers
+                  (0xffffffff), which may not have the same effect as
+                  0 on machines that support more than 32 bits of
+                  memory space.
+                  Any positive values less than 2MB will be ignored reset
+                  to 2MB.
+                  In a server with multiple views, the limit applies
+                  separately to the cache of each view.
+                  The default is 0.
                 </para>
               </listitem>
             </varlistentry>
@@ -7022,6 +7178,10 @@
 		  Sets the maximum time for which the server will
                   cache ordinary (positive) answers. The default is
                   one week (7 days).
+		  A value of zero may cause all queries to return
+		  SERVFAIL, because of lost caches of intermediate
+		  RRsets (such as NS and glue AAAA/A records) in the
+		  resolution process.
                 </para>
               </listitem>
             </varlistentry>
@@ -7301,9 +7461,8 @@
 	  <para>
 	    The current list of empty zones is:
 	    <itemizedlist>
+<!-- XXX: The RFC1918 addresses are #defined out in sources currently.
 	      <listitem>10.IN-ADDR.ARPA</listitem>
-	      <listitem>127.IN-ADDR.ARPA</listitem>
-	      <listitem>254.169.IN-ADDR.ARPA</listitem>
 	      <listitem>16.172.IN-ADDR.ARPA</listitem>
 	      <listitem>17.172.IN-ADDR.ARPA</listitem>
 	      <listitem>18.172.IN-ADDR.ARPA</listitem>
@@ -7321,7 +7480,12 @@
 	      <listitem>30.172.IN-ADDR.ARPA</listitem>
 	      <listitem>31.172.IN-ADDR.ARPA</listitem>
 	      <listitem>168.192.IN-ADDR.ARPA</listitem>
+XXX: end of RFC1918 addresses #defined out -->
+	      <listitem>0.IN-ADDR.ARPA</listitem>
+	      <listitem>127.IN-ADDR.ARPA</listitem>
+	      <listitem>254.169.IN-ADDR.ARPA</listitem>
 	      <listitem>2.0.192.IN-ADDR.ARPA</listitem>
+	      <listitem>255.255.255.255.IN-ADDR.ARPA</listitem>
 	      <listitem>0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA</listitem>
 	      <listitem>1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA</listitem>
 	      <listitem>D.F.IP6.ARPA</listitem>
@@ -7548,8 +7712,10 @@
             <command>success</command>,
             <command>referral</command>,
             <command>nxrrset</command>,
-            <command>nxdomain</command>, or
-            <command>failure</command>
+            <command>nxdomain</command>,
+            <command>failure</command>,
+            <command>duplicate</command>, or
+            <command>dropped</command>
             to be incremented, and may additionally cause the
             <command>recursion</command> counter to be
             incremented.
@@ -7680,7 +7846,7 @@
       <sect2 id="server_statement_grammar">
         <title><command>server</command> Statement Grammar</title>
 
-<programlisting>server <replaceable>ip_addr[/prefixlen]</replaceable> {
+<programlisting><command>server</command> <replaceable>ip_addr[/prefixlen]</replaceable> {
     <optional> bogus <replaceable>yes_or_no</replaceable> ; </optional>
     <optional> provide-ixfr <replaceable>yes_or_no</replaceable> ; </optional>
     <optional> request-ixfr <replaceable>yes_or_no</replaceable> ; </optional>
@@ -7889,7 +8055,7 @@
         <sect2>
           <title><command>trusted-keys</command> Statement Grammar</title>
 
-<programlisting>trusted-keys {
+<programlisting><command>trusted-keys</command> {
     <replaceable>string</replaceable> <replaceable>number</replaceable> <replaceable>number</replaceable> <replaceable>number</replaceable> <replaceable>string</replaceable> ;
     <optional> <replaceable>string</replaceable> <replaceable>number</replaceable> <replaceable>number</replaceable> <replaceable>number</replaceable> <replaceable>string</replaceable> ; <optional>...</optional></optional>
 };
@@ -7930,7 +8096,7 @@
         <sect2 id="view_statement_grammar">
           <title><command>view</command> Statement Grammar</title>
 
-<programlisting>view <replaceable>view_name</replaceable>
+<programlisting><command>view</command> <replaceable>view_name</replaceable>
       <optional><replaceable>class</replaceable></optional> {
       match-clients { <replaceable>address_match_list</replaceable> };
       match-destinations { <replaceable>address_match_list</replaceable> };
@@ -7986,7 +8152,7 @@
           <para>
             Zones defined within a <command>view</command>
             statement will
-            be only be accessible to clients that match the <command>view</command>.
+            only be accessible to clients that match the <command>view</command>.
             By defining a zone of the same name in multiple views, different
             zone data can be given to different clients, for example,
             "internal"
@@ -8071,7 +8237,7 @@
           <title><command>zone</command>
             Statement Grammar</title>
 
-<programlisting>zone <replaceable>zone_name</replaceable> <optional><replaceable>class</replaceable></optional> {
+<programlisting><command>zone</command> <replaceable>zone_name</replaceable> <optional><replaceable>class</replaceable></optional> {
     type master;
     <optional> allow-query { <replaceable>address_match_list</replaceable> }; </optional>
     <optional> allow-transfer { <replaceable>address_match_list</replaceable> }; </optional>
@@ -9417,6 +9583,19 @@
                   <row rowsep="0">
                     <entry colname="1">
                       <para>
+                        IPSECKEY
+                      </para>
+                    </entry>
+                    <entry colname="2">
+                      <para>
+			Provides a method for storing IPsec keying material in
+			DNS.  Described in RFC 4025.
+                      </para>
+                    </entry>
+                  </row>
+                  <row rowsep="0">
+                    <entry colname="1">
+                      <para>
                         ISDN
                       </para>
                     </entry>
@@ -9655,6 +9834,19 @@
                   <row rowsep="0">
                     <entry colname="1">
                       <para>
+                        SPF
+                      </para>
+                    </entry>
+                    <entry colname="2">
+                      <para>
+			Contains the Sender Policy Framework information
+			for a given email domain.  Described in RFC 4408.
+                      </para>
+                    </entry>
+                  </row>
+                  <row rowsep="0">
+                    <entry colname="1">
+                      <para>
                         SRV
                       </para>
                     </entry>
@@ -9668,6 +9860,19 @@
                   <row rowsep="0">
                     <entry colname="1">
                       <para>
+                        SSHFP
+                      </para>
+                    </entry>
+                    <entry colname="2">
+                      <para>
+			Provides a way to securly publish a secure shell key's
+			fingerprint.  Described in RFC 4255.
+                      </para>
+                    </entry>
+                  </row>
+                  <row rowsep="0">
+                    <entry colname="1">
+                      <para>
                         TXT
                       </para>
                     </entry>
@@ -10450,7 +10655,7 @@
             is equivalent to
           </para>
 
-<programlisting>0.0.0.192.IN-ADDR.ARPA NS SERVER1.EXAMPLE.
+<programlisting>0.0.0.192.IN-ADDR.ARPA. NS SERVER1.EXAMPLE.
 0.0.0.192.IN-ADDR.ARPA. NS SERVER2.EXAMPLE.
 1.0.0.192.IN-ADDR.ARPA. CNAME 1.0.0.0.192.IN-ADDR.ARPA.
 2.0.0.192.IN-ADDR.ARPA. CNAME 2.0.0.0.192.IN-ADDR.ARPA.
Index: opensslrsa_link.c
===================================================================
RCS file: /home/cvs/src/contrib/bind9/lib/dns/opensslrsa_link.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/bind9/lib/dns/opensslrsa_link.c -L contrib/bind9/lib/dns/opensslrsa_link.c -u -r1.2 -r1.3
--- contrib/bind9/lib/dns/opensslrsa_link.c
+++ contrib/bind9/lib/dns/opensslrsa_link.c
@@ -17,7 +17,7 @@
 
 /*
  * Principal Author: Brian Wellington
- * $Id: opensslrsa_link.c,v 1.1.6.11 2006/11/07 21:28:49 marka Exp $
+ * $Id: opensslrsa_link.c,v 1.1.6.11.58.1 2008/12/24 00:21:22 marka Exp $
  */
 #ifdef OPENSSL
 
Index: validator.c
===================================================================
RCS file: /home/cvs/src/contrib/bind9/lib/dns/validator.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -L contrib/bind9/lib/dns/validator.c -L contrib/bind9/lib/dns/validator.c -u -r1.3 -r1.4
--- contrib/bind9/lib/dns/validator.c
+++ 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 @@
 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 @@
 			      "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 @@
 					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 @@
 		   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 @@
 		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 @@
 	} 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 @@
 		    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 @@
 			/* 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 @@
 		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 @@
 		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 @@
 	{
 		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 @@
 		{
 			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 @@
 	     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 @@
 	{
 		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 @@
 		{
 			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 @@
 			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 @@
 			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 @@
 			 * 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 @@
 			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 @@
 	     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 @@
 	{
 		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 @@
 		{
 			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 @@
 				      "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 @@
 			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 @@
  * 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 @@
 	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 @@
 	     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 @@
 
 /*%
  * Callback from fetching a DLV record.
- * 
+ *
  * Resumes the DLV lookup process.
  */
 static void
@@ -2316,7 +2333,7 @@
 
 /*%
  * Start the DLV lookup proccess.
- * 
+ *
  * Returns
  * \li	ISC_R_SUCCESS
  * \li	DNS_R_WAIT
@@ -2450,6 +2467,7 @@
 		}
 		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 @@
  * \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 @@
 			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 @@
 		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_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 @@
 			      "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)
 	{
Index: resolver.c
===================================================================
RCS file: /home/cvs/src/contrib/bind9/lib/dns/resolver.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -L contrib/bind9/lib/dns/resolver.c -L contrib/bind9/lib/dns/resolver.c -u -r1.6 -r1.7
--- contrib/bind9/lib/dns/resolver.c
+++ contrib/bind9/lib/dns/resolver.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: resolver.c,v 1.284.18.66.8.1 2008/05/22 21:28:06 each Exp $ */
+/* $Id: resolver.c,v 1.284.18.79 2008/10/17 22:02:13 jinmei Exp $ */
 
 /*! \file */
 
@@ -121,6 +121,7 @@
 	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 @@
 	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 @@
 	/*%
 	 * 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 @@
 	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 @@
 	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 @@
 	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 @@
 				      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 @@
 	unsigned int factor;
 	dns_adbfind_t *find;
 	dns_adbaddrinfo_t *addrinfo;
+	isc_socket_t *socket;
 
 	query = *queryp;
 	fctx = query->fctx;
@@ -643,35 +649,48 @@
 							   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 @@
 	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->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 @@
 	    (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 @@
 			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 @@
 }
 
 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 @@
 			/*
 			 * 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 @@
 			fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);
 			break;
 		}
+	}
 
 	isc_event_free(&event);
 
@@ -939,9 +948,51 @@
 	}
 }
 
+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 @@
 	 * 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 @@
 	 */
 	query->dispatchmgr = res->dispatchmgr;
 	query->dispatch = NULL;
+	query->exclusivesocket = ISC_FALSE;
 	query->tcpsocket = NULL;
 	if (res->view->peers != NULL) {
 		dns_peer_t *peer = NULL;
@@ -1123,7 +1175,7 @@
 			goto cleanup_query;
 
 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
-		result = isc_socket_bind(query->tcpsocket, &addr);
+		result = isc_socket_bind(query->tcpsocket, &addr, 0);
 		if (result != ISC_R_SUCCESS)
 			goto cleanup_socket;
 #endif
@@ -1159,53 +1211,21 @@
 			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 @@
 	/*
 	 * 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 @@
 	 */
 	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 @@
 	}
 
 	isc_event_free(&event);
-	
+
 	if (retry) {
 		/*
 		 * Behave as if the idle timer has expired.  For TCP
@@ -1921,8 +1954,8 @@
 	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 @@
 	}
 
 	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 @@
 	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;
 
@@ -2689,6 +2729,8 @@
 static void
 fctx_timeout(isc_task_t *task, isc_event_t *event) {
 	fetchctx_t *fctx = event->ev_arg;
+	isc_timerevent_t *tevent = (isc_timerevent_t *)event;
+	resquery_t *query;
 
 	REQUIRE(VALID_FCTX(fctx));
 
@@ -2704,8 +2746,18 @@
 		fctx->timeouts++;
 		/*
 		 * We could cancel the running queries here, or we could let
-		 * them keep going.  Right now we choose the latter...
-		 */
+		 * them keep going.  Since we normally use separate sockets for
+		 * different queries, we adopt the former approach to reduce
+		 * the number of open sockets: cancel the oldest query if it
+		 * expired after the query had started (this is usually the
+		 * case but is not always so, depending on the task schedule
+		 * timing).
+		 */
+		query = ISC_LIST_HEAD(fctx->queries);
+		if (query != NULL &&
+		    isc_time_compare(&tevent->due, &query->start) >= 0) {
+			fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);
+		}
 		fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;
 		/*
 		 * Our timer has triggered.  Reestablish the fctx lifetime
@@ -2787,7 +2839,7 @@
 		dns_validator_cancel(validator);
 		validator = ISC_LIST_NEXT(validator, link);
 	}
-	
+
 	if (fctx->nsfetch != NULL)
 		dns_resolver_cancelfetch(fctx->nsfetch);
 
@@ -3240,9 +3292,9 @@
 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));
@@ -3810,9 +3862,9 @@
 					     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) {
@@ -4399,7 +4451,7 @@
 
  again:
 	rescan = ISC_FALSE;
-	
+
 	for (result = dns_message_firstname(fctx->rmessage, section);
 	     result == ISC_R_SUCCESS;
 	     result = dns_message_nextname(fctx->rmessage, section)) {
@@ -4479,7 +4531,7 @@
 		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,
@@ -4638,7 +4690,7 @@
 	}
 
 	/*
-	 * 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
@@ -5351,7 +5403,7 @@
 	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))
@@ -5370,7 +5422,7 @@
 							  ISC_FALSE) ||
 				    !dns_rdata_checknames(&rdata, name, NULL))
 				{
-					rdataset->attributes |= 
+					rdataset->attributes |=
 						DNS_RDATASETATTR_CHECKNAMES;
 				}
 				dns_rdata_reset(&rdata);
@@ -5500,6 +5552,19 @@
 			 * 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;
 	}
@@ -5650,12 +5715,17 @@
 	 */
 	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
@@ -6142,7 +6212,7 @@
 	REQUIRE(VALID_RESOLVER(res));
 
 	UNUSED(task);
-	
+
 	LOCK(&res->lock);
 	INSIST(!res->exiting);
 	if (res->spillat > res->spillatmin) {
@@ -6169,7 +6239,7 @@
 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,
@@ -6181,6 +6251,7 @@
 	unsigned int i, buckets_created = 0;
 	isc_task_t *task = NULL;
 	char name[16];
+	unsigned dispattr;
 
 	/*
 	 * Create a resolver.
@@ -6247,11 +6318,20 @@
 	}
 
 	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;
@@ -6368,7 +6448,7 @@
 	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);
@@ -6534,12 +6614,12 @@
 			     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);
@@ -6653,6 +6733,7 @@
 	isc_event_t *event;
 	unsigned int count = 0;
 	unsigned int spillat;
+	unsigned int spillatmin;
 
 	UNUSED(forwarders);
 
@@ -6683,6 +6764,7 @@
 
 	LOCK(&res->lock);
 	spillat = res->spillat;
+	spillatmin = res->spillatmin;
 	UNLOCK(&res->lock);
 	LOCK(&res->buckets[bucketnum].lock);
 
@@ -6699,7 +6781,7 @@
 				break;
 		}
 	}
-	
+
 	/*
 	 * Is this a duplicate?
 	 */
@@ -6716,7 +6798,8 @@
 			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) {
@@ -6992,7 +7075,7 @@
 
 	isc_mem_put(mctx, algorithms, *algorithms);
 }
- 
+
 void
 dns_resolver_reset_algorithms(dns_resolver_t *resolver) {
 
@@ -7036,7 +7119,7 @@
 	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) {
@@ -7052,7 +7135,7 @@
 			*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;
@@ -7120,7 +7203,7 @@
 	RWUNLOCK(&resolver->mbslock, isc_rwlocktype_write);
 #endif
 }
- 
+
 static isc_boolean_t yes = ISC_TRUE, no = ISC_FALSE;
 
 isc_result_t
@@ -7140,7 +7223,7 @@
 		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
Index: openssldsa_link.c
===================================================================
RCS file: /home/cvs/src/contrib/bind9/lib/dns/openssldsa_link.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/bind9/lib/dns/openssldsa_link.c -L contrib/bind9/lib/dns/openssldsa_link.c -u -r1.2 -r1.3
--- contrib/bind9/lib/dns/openssldsa_link.c
+++ contrib/bind9/lib/dns/openssldsa_link.c
@@ -16,7 +16,7 @@
  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: openssldsa_link.c,v 1.1.6.9 2007/08/28 07:20:04 tbox Exp $ */
+/* $Id: openssldsa_link.c,v 1.1.6.9.28.1 2008/12/24 00:21:22 marka Exp $ */
 
 #ifdef OPENSSL
 
Index: dispatch.c
===================================================================
RCS file: /home/cvs/src/contrib/bind9/lib/dns/dispatch.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -L contrib/bind9/lib/dns/dispatch.c -L contrib/bind9/lib/dns/dispatch.c -u -r1.4 -r1.5
--- contrib/bind9/lib/dns/dispatch.c
+++ contrib/bind9/lib/dns/dispatch.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: dispatch.c,v 1.116.18.19.12.1 2008/05/22 21:28:06 each 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 @@
 	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 @@
 	isc_mempool_t		       *rpool;	/*%< memory pool for replies */
 	isc_mempool_t		       *dpool;  /*%< dispatch allocations */
 	isc_mempool_t		       *bpool;	/*%< memory pool for buffers */
+	isc_mempool_t		       *spool;	/*%< memory pool for dispsocs */
 
-	isc_entropy_t		       *entropy; /*%< entropy source */
+	/*%
+	 * 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 @@
 	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 @@
 				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 @@
 #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 @@
 
 #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_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_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,17 +385,38 @@
 	}
 }
 
-/*
- * ARC4 random number generator obtained from OpenBSD
+/*%
+ * 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
+ * for these two.
+ *
+ * The original copyright follows:
+ * Copyright (c) 1996, David Mazieres <dm at uun.org>
+ * Copyright (c) 2008, Damien Miller <djm at openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
  */
 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
@@ -329,7 +460,7 @@
 }
 
 static void
-dispatch_arc4stir(dns_dispatchmgr_t *mgr) {
+dispatch_arc4stir(arc4ctx_t *actx) {
 	int i;
 	union {
 		unsigned char rnd[128];
@@ -337,51 +468,55 @@
 	} 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);
@@ -403,7 +538,7 @@
 	 * to re-roll.
 	 */
 	for (;;) {
-		r = dispatch_arc4random(mgr);
+		r = dispatch_arc4random(actx);
 		if (r >= min)
 			break;
 	}
@@ -486,13 +621,15 @@
 	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).
  *
@@ -504,6 +641,8 @@
 	dns_dispatch_t *disp;
 	dns_dispatchmgr_t *mgr;
 	isc_boolean_t killmgr;
+	dispsocket_t *dispsocket;
+	int i;
 
 	INSIST(event->ev_type == DNS_EVENT_DISPATCHCONTROL);
 
@@ -517,10 +656,16 @@
 
 	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);
@@ -531,14 +676,210 @@
 		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;
 
@@ -547,7 +888,7 @@
 	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);
 		}
@@ -621,6 +962,26 @@
 	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:
  *
@@ -636,14 +997,13 @@
  *	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;
@@ -652,8 +1012,8 @@
 	dns_qid_t *qid;
 	isc_netaddr_t netaddr;
 	int match;
-
-	UNUSED(task);
+	int result;
+	isc_boolean_t qidlocked = ISC_FALSE;
 
 	LOCK(&disp->lock);
 
@@ -664,7 +1024,7 @@
 		     "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
@@ -674,6 +1034,19 @@
 		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.
@@ -686,12 +1059,32 @@
 		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)
@@ -710,7 +1103,7 @@
 	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))) {
@@ -752,18 +1145,32 @@
 		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
@@ -773,7 +1180,7 @@
 	if (disp != resp->disp) {
 		isc_sockaddr_t a1;
 		isc_sockaddr_t a2;
-		
+
 		/*
 		 * Check that the socket types and ports match.
 		 */
@@ -786,11 +1193,11 @@
 
 		/*
 		 * 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.
 		 */
@@ -808,6 +1215,7 @@
 		}
 	}
 
+  sendresponse:
 	queue_response = resp->item_out;
 	rev = allocate_event(resp->disp);
 	if (rev == NULL) {
@@ -822,7 +1230,7 @@
 	 */
 	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;
@@ -841,14 +1249,23 @@
 		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);
@@ -911,7 +1328,7 @@
 		switch (tcpmsg->result) {
 		case ISC_R_CANCELED:
 			break;
-			
+
 		case ISC_R_EOF:
 			dispatch_log(disp, LVL(90), "shutting down on EOF");
 			do_cancel(disp);
@@ -948,7 +1365,7 @@
 		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;
 	}
 
@@ -991,8 +1408,7 @@
 	 */
 	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"));
@@ -1033,7 +1449,7 @@
 	 * Restart recv() to get the next packet.
 	 */
  restart:
-	startrecv(disp);
+	(void)startrecv(disp, NULL);
 
 	UNLOCK(&disp->lock);
 
@@ -1043,22 +1459,33 @@
 /*
  * 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) {
 		/*
@@ -1068,28 +1495,38 @@
 		region.length = disp->mgr->buffersize;
 		region.base = allocate_udp_buffer(disp);
 		if (region.base == NULL)
-			return;
-		res = isc_socket_recv(disp->socket, &region, 1,
-				      disp->task, udp_recv, disp);
-		if (res != ISC_R_SUCCESS) {
-			free_buffer(disp, region.base, region.length);
-			disp->shutdown_why = res;
-			disp->shutting_down = 1;
-			do_cancel(disp);
-			return;
+			return (ISC_R_NOMEMORY);
+		if (dispsock != NULL) {
+			res = isc_socket_recv(socket, &region, 1,
+					      dispsock->task, udp_exrecv,
+					      dispsock);
+			if (res != ISC_R_SUCCESS) {
+				free_buffer(disp, region.base, region.length);
+				return (res);
+			}
+		} else {
+			res = isc_socket_recv(socket, &region, 1,
+					      disp->task[0], udp_shrecv, disp);
+			if (res != ISC_R_SUCCESS) {
+				free_buffer(disp, region.base, region.length);
+				disp->shutdown_why = res;
+				disp->shutting_down = 1;
+				do_cancel(disp);
+				return (ISC_R_SUCCESS); /* recover by cancel */
+			}
+			INSIST(disp->recv_pending == 0);
+			disp->recv_pending = 1;
 		}
-		INSIST(disp->recv_pending == 0);
-		disp->recv_pending = 1;
 		break;
 
 	case isc_sockettype_tcp:
-		res = dns_tcpmsg_readmessage(&disp->tcpmsg, disp->task,
+		res = dns_tcpmsg_readmessage(&disp->tcpmsg, disp->task[0],
 					     tcp_recv, disp);
 		if (res != ISC_R_SUCCESS) {
 			disp->shutdown_why = res;
 			disp->shutting_down = 1;
 			do_cancel(disp);
-			return;
+			return (ISC_R_SUCCESS); /* recover by cancel */
 		}
 		INSIST(disp->recv_pending == 0);
 		disp->recv_pending = 1;
@@ -1098,6 +1535,8 @@
 		INSIST(0);
 		break;
 	}
+
+	return (ISC_R_SUCCESS);
 }
 
 /*
@@ -1150,6 +1589,7 @@
 	isc_mempool_destroy(&mgr->rpool);
 	isc_mempool_destroy(&mgr->dpool);
 	isc_mempool_destroy(&mgr->bpool);
+	isc_mempool_destroy(&mgr->spool);
 
 	DESTROYLOCK(&mgr->pool_lock);
 
@@ -1163,32 +1603,46 @@
 	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,
-	      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);
+	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);
 	}
 
@@ -1196,6 +1650,24 @@
 	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.
  */
@@ -1206,6 +1678,8 @@
 {
 	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);
@@ -1218,7 +1692,6 @@
 	isc_mem_attach(mctx, &mgr->mctx);
 
 	mgr->blackhole = NULL;
-	mgr->portlist = NULL;
 
 	result = isc_mutex_init(&mgr->lock);
 	if (result != ISC_R_SUCCESS)
@@ -1273,20 +1746,43 @@
 	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:
@@ -1325,22 +1821,88 @@
 				 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;
 
@@ -1367,24 +1929,39 @@
 		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;
 
@@ -1395,8 +1972,10 @@
 
  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
@@ -1422,30 +2001,56 @@
 		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)))
@@ -1455,17 +2060,20 @@
 	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>.
@@ -1507,10 +2115,10 @@
 	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) {
@@ -1537,7 +2145,8 @@
 
 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;
@@ -1559,16 +2168,35 @@
 		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;
@@ -1590,6 +2218,10 @@
 	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));
 }
@@ -1633,6 +2265,10 @@
 	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)
@@ -1685,6 +2321,8 @@
 	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;
@@ -1730,7 +2368,7 @@
 		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;
 
@@ -1738,8 +2376,9 @@
 	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;
 
@@ -1752,7 +2391,7 @@
 		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;
@@ -1766,7 +2405,7 @@
 	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;
 
@@ -1776,7 +2415,7 @@
 	 * Error returns.
 	 */
  kill_task:
-	isc_task_detach(&disp->task);
+	isc_task_detach(&disp->task[0]);
  kill_socket:
 	isc_socket_detach(&disp->socket);
  deallocate_dispatch:
@@ -1811,13 +2450,13 @@
 	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;
 	}
@@ -1838,7 +2477,7 @@
 		{
 			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);
 		}
 
@@ -1875,6 +2514,101 @@
 #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,
@@ -1885,10 +2619,7 @@
 	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.
@@ -1898,66 +2629,46 @@
 	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, &sock);
-		if (result == ISC_R_ADDRINUSE) {
-			if (++k == 1024)
-				attributes &= ~DNS_DISPATCHATTR_RANDOMPORT;
-			goto getsocket;
-		}
-		localport = prt;
-	} else
-		result = create_socket(sockmgr, localaddr, &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,
@@ -1968,8 +2679,6 @@
 		goto kill_task;
 	}
 
-	isc_task_setname(disp->task, "udpdispatch", disp);
-
 	attributes &= ~DNS_DISPATCHATTR_TCP;
 	attributes |= DNS_DISPATCHATTR_UDP;
 	disp->attributes = attributes;
@@ -1980,26 +2689,25 @@
 	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);
 }
 
@@ -2025,6 +2733,7 @@
 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));
@@ -2039,8 +2748,14 @@
 	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;
 	}
 
@@ -2049,26 +2764,32 @@
 	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);
 
@@ -2082,23 +2803,75 @@
 		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) {
@@ -2111,6 +2884,8 @@
 	if (res == NULL) {
 		UNLOCK(&qid->lock);
 		UNLOCK(&disp->lock);
+		if (dispsocket != NULL)
+			destroy_dispsocket(disp, &dispsocket);
 		return (ISC_R_NOMEMORY);
 	}
 
@@ -2120,11 +2895,14 @@
 	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);
@@ -2136,27 +2914,62 @@
 		    "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);
 }
 
@@ -2167,6 +2980,7 @@
 	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;
@@ -2204,8 +3018,14 @@
 	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;
 	}
 
@@ -2241,6 +3061,12 @@
 	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
 	 */
@@ -2257,12 +3083,12 @@
 	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
@@ -2277,13 +3103,15 @@
 	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.
 	 */
@@ -2316,6 +3144,16 @@
 	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) {
 
@@ -2349,11 +3187,27 @@
 	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!
@@ -2365,13 +3219,13 @@
 		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);
 		}
 	}
@@ -2395,7 +3249,7 @@
 	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;
@@ -2414,8 +3268,8 @@
 	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
Index: api
===================================================================
RCS file: /home/cvs/src/contrib/bind9/lib/dns/api,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/bind9/lib/dns/api -L contrib/bind9/lib/dns/api -u -r1.2 -r1.3
--- contrib/bind9/lib/dns/api
+++ contrib/bind9/lib/dns/api
@@ -1,3 +1,3 @@
-LIBINTERFACE = 35
-LIBREVISION = 0
+LIBINTERFACE = 36
+LIBREVISION = 2
 LIBAGE = 0
Index: dispatch.h
===================================================================
RCS file: /home/cvs/src/contrib/bind9/lib/dns/include/dns/dispatch.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -L contrib/bind9/lib/dns/include/dns/dispatch.h -L contrib/bind9/lib/dns/include/dns/dispatch.h -u -r1.4 -r1.5
--- contrib/bind9/lib/dns/include/dns/dispatch.h
+++ contrib/bind9/lib/dns/include/dns/dispatch.h
@@ -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: dispatch.h,v 1.48.18.5.12.1 2008/05/22 21:28:06 each 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 @@
  *	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 @@
  *	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 @@
 #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 @@
 
 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 @@
  */
 
 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 @@
  *
  *\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 @@
  *\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 @@
  *\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 @@
  *\li	addrp to be non null.
  *
  * Returns:
- *\li	ISC_R_SUCCESS	
+ *\li	ISC_R_SUCCESS
  *\li	ISC_R_NOTIMPLEMENTED
  */
 
@@ -408,6 +434,16 @@
  *\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 @@
  *	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.


More information about the Midnightbsd-cvs mailing list