[Midnightbsd-cvs] src: bin/named:

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Wed Mar 25 14:00:30 EDT 2009


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


Modified Files:
--------------
    src/contrib/bind9/bin/named:
        client.c (r1.4 -> r1.5)
        query.c (r1.4 -> r1.5)
        server.c (r1.2 -> r1.3)

-------------- next part --------------
Index: client.c
===================================================================
RCS file: /home/cvs/src/contrib/bind9/bin/named/client.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -L contrib/bind9/bin/named/client.c -L contrib/bind9/bin/named/client.c -u -r1.4 -r1.5
--- contrib/bind9/bin/named/client.c
+++ contrib/bind9/bin/named/client.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: client.c,v 1.219.18.28.10.1 2008/05/22 21:28:04 each Exp $ */
+/* $Id: client.c,v 1.219.18.31 2008/05/22 23:46:03 tbox Exp $ */
 
 #include <config.h>
 
@@ -132,7 +132,7 @@
 #define MANAGER_MAGIC			ISC_MAGIC('N', 'S', 'C', 'm')
 #define VALID_MANAGER(m)		ISC_MAGIC_VALID(m, MANAGER_MAGIC)
 
-/*! 
+/*!
  * Client object states.  Ordering is significant: higher-numbered
  * states are generally "more active", meaning that the client can
  * have more dynamically allocated data, outstanding events, etc.
@@ -286,7 +286,7 @@
 	 *
 	 * Keep the view attached until any outstanding updates complete.
 	 */
-	if (client->nupdates == 0 && 
+	if (client->nupdates == 0 &&
 	    client->newstate == NS_CLIENTSTATE_FREED && client->view != NULL)
 		dns_view_detach(&client->view);
 
@@ -817,7 +817,7 @@
 		isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);
 		if (ns_g_server->blackholeacl != NULL &&
 		    dns_acl_match(&netaddr, NULL,
-			    	  ns_g_server->blackholeacl,
+				  ns_g_server->blackholeacl,
 				  &ns_g_server->aclenv,
 				  &match, NULL) == ISC_R_SUCCESS &&
 		    match > 0)
@@ -834,7 +834,7 @@
 	isc_buffer_usedregion(buffer, &r);
 
 	CTRACE("sendto");
-	
+
 	result = isc_socket_sendto2(socket, &r, client->task,
 				    address, pktinfo,
 				    client->sendevent, sockflags);
@@ -1108,8 +1108,8 @@
 	/*
 	 * FORMERR loop avoidance:  If we sent a FORMERR message
 	 * with the same ID to the same client less than two
-	 * seconds ago, assume that we are in an infinite error 
-	 * packet dialog with a server for some protocol whose 
+	 * seconds ago, assume that we are in an infinite error
+	 * packet dialog with a server for some protocol whose
 	 * error responses look enough like DNS queries to
 	 * elicit a FORMERR response.  Drop a packet to break
 	 * the loop.
@@ -1534,7 +1534,7 @@
 	 * For IPv6 UDP queries, we get this from the pktinfo structure (if
 	 * supported).
 	 * If all the attempts fail (this can happen due to memory shortage,
-	 * etc), we regard this as an error for safety. 
+	 * etc), we regard this as an error for safety.
 	 */
 	if ((client->interface->flags & NS_INTERFACEFLAG_ANYADDR) == 0)
 		isc_netaddr_fromsockaddr(&destaddr, &client->interface->addr);
@@ -1595,7 +1595,7 @@
 							   view);
 			if (sigresult == ISC_R_SUCCESS)
 				tsig = client->message->tsigname;
-				
+
 			if (allowed(&netaddr, tsig, view->matchclients) &&
 			    allowed(&destaddr, tsig, view->matchdestinations) &&
 			    !((client->message->flags & DNS_MESSAGEFLAG_RD)
@@ -1726,7 +1726,7 @@
 
 	ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT,
 		      ISC_LOG_DEBUG(3), ra ? "recursion available" :
-		      			     "recursion not available");
+					     "recursion not available");
 
 	/*
 	 * Adjust maximum UDP response size for this client.
@@ -1820,10 +1820,10 @@
 			return (result);
 
 		manager->mctxpool[manager->nextmctx] = clientmctx;
-		manager->nextmctx++;
-		if (manager->nextmctx == NMCTXS)
-			manager->nextmctx = 0;
 	}
+	manager->nextmctx++;
+	if (manager->nextmctx == NMCTXS)
+		manager->nextmctx = 0;
 #else
 	clientmctx = manager->mctx;
 #endif
@@ -2093,7 +2093,7 @@
 
 		if (ns_g_server->blackholeacl != NULL &&
 		    dns_acl_match(&netaddr, NULL,
-			    	  ns_g_server->blackholeacl,
+				  ns_g_server->blackholeacl,
 				  &ns_g_server->aclenv,
 				  &match, NULL) == ISC_R_SUCCESS &&
 		    match > 0)
@@ -2482,7 +2482,7 @@
 	isc_result_t result =
 		ns_client_checkaclsilent(client, acl, default_allow);
 
-	if (result == ISC_R_SUCCESS) 
+	if (result == ISC_R_SUCCESS)
 		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
 			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),
 			      "%s approved", opname);
@@ -2538,16 +2538,16 @@
 
 void
 ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdatatype_t type,
-		 dns_rdataclass_t rdclass, char *buf, size_t len) 
+		 dns_rdataclass_t rdclass, char *buf, size_t len)
 {
-        char namebuf[DNS_NAME_FORMATSIZE];
-        char typebuf[DNS_RDATATYPE_FORMATSIZE];
-        char classbuf[DNS_RDATACLASS_FORMATSIZE];
-
-        dns_name_format(name, namebuf, sizeof(namebuf));
-        dns_rdatatype_format(type, typebuf, sizeof(typebuf));
-        dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
-        (void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf,
+	char namebuf[DNS_NAME_FORMATSIZE];
+	char typebuf[DNS_RDATATYPE_FORMATSIZE];
+	char classbuf[DNS_RDATACLASS_FORMATSIZE];
+
+	dns_name_format(name, namebuf, sizeof(namebuf));
+	dns_rdatatype_format(type, typebuf, sizeof(typebuf));
+	dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
+	(void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf,
 		       classbuf);
 }
 
@@ -2575,7 +2575,7 @@
 			isc_mem_put(client->mctx, buf, len);
 			len += 1024;
 		} else if (result == ISC_R_SUCCESS)
-		        ns_client_log(client, NS_LOGCATEGORY_UNMATCHED,
+			ns_client_log(client, NS_LOGCATEGORY_UNMATCHED,
 				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),
 				      "%s\n%.*s", reason,
 				       (int)isc_buffer_usedlength(&buffer),
@@ -2595,7 +2595,7 @@
 	const char *sep;
 
 	REQUIRE(VALID_MANAGER(manager));
-	      
+
 	LOCK(&manager->lock);
 	client = ISC_LIST_HEAD(manager->recursing);
 	while (client != NULL) {
Index: query.c
===================================================================
RCS file: /home/cvs/src/contrib/bind9/bin/named/query.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -L contrib/bind9/bin/named/query.c -L contrib/bind9/bin/named/query.c -u -r1.4 -r1.5
--- contrib/bind9/bin/named/query.c
+++ contrib/bind9/bin/named/query.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: query.c,v 1.257.18.40 2007/09/26 03:08:14 each Exp $ */
+/* $Id: query.c,v 1.257.18.46 2008/10/15 22:33:01 marka Exp $ */
 
 /*! \file */
 
@@ -2298,7 +2298,7 @@
 static isc_boolean_t
 get_key(ns_client_t *client, dns_db_t *db, dns_rdata_rrsig_t *rrsig,
 	dns_rdataset_t *keyrdataset, dst_key_t **keyp)
-{ 
+{
 	isc_result_t result;
 	dns_dbnode_t *node = NULL;
 	isc_boolean_t secure = ISC_FALSE;
@@ -2331,12 +2331,12 @@
 		isc_buffer_init(&b, rdata.data, rdata.length);
 		isc_buffer_add(&b, rdata.length);
 		result = dst_key_fromdns(&rrsig->signer, rdata.rdclass, &b,
-                                         client->mctx, keyp);
+					 client->mctx, keyp);
 		if (result != ISC_R_SUCCESS)
 			continue;
 		if (rrsig->algorithm == (dns_secalg_t)dst_key_alg(*keyp) &&
-                    rrsig->keyid == (dns_keytag_t)dst_key_id(*keyp) &&
-                    dst_key_iszonekey(*keyp)) {
+		    rrsig->keyid == (dns_keytag_t)dst_key_id(*keyp) &&
+		    dst_key_iszonekey(*keyp)) {
 			secure = ISC_TRUE;
 			break;
 		}
@@ -2354,7 +2354,7 @@
 	isc_boolean_t ignore = ISC_FALSE;
 
 	dns_fixedname_init(&fixed);
-	
+
 again:
 	result = dns_dnssec_verify2(name, rdataset, key, ignore, mctx,
 				    rdata, NULL);
@@ -2382,7 +2382,7 @@
 
 	if (sigrdataset == NULL || !dns_rdataset_isassociated(sigrdataset))
 		return (ISC_FALSE);
-	
+
 	for (result = dns_rdataset_first(sigrdataset);
 	     result == ISC_R_SUCCESS;
 	     result = dns_rdataset_next(sigrdataset)) {
@@ -2757,6 +2757,13 @@
 						   &olabels);
 			(void)dns_name_fullcompare(name, &nsec.next, &order,
 						   &nlabels);
+			/*
+			 * Check for a pathological condition created when
+			 * serving some malformed signed zones and bail out.
+			 */
+			if (dns_name_countlabels(name) == nlabels)
+				goto cleanup;
+
 			if (olabels > nlabels)
 				dns_name_split(name, olabels, NULL, wname);
 			else
@@ -2924,13 +2931,14 @@
 
 static isc_result_t
 query_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain,
-	      dns_rdataset_t *nameservers)
+	      dns_rdataset_t *nameservers, isc_boolean_t resuming)
 {
 	isc_result_t result;
 	dns_rdataset_t *rdataset, *sigrdataset;
 	isc_sockaddr_t *peeraddr;
 
-	inc_stats(client, dns_statscounter_recursion);
+	if (!resuming)
+		inc_stats(client, dns_statscounter_recursion);
 
 	/*
 	 * We are about to recurse, which means that this client will
@@ -3162,11 +3170,11 @@
 
  cleanup:
 	if (nsec != NULL)
-                query_putrdataset(client, &nsec);
-        if (nsecsig != NULL)
-                query_putrdataset(client, &nsecsig);
-        if (fname != NULL)
-                query_releasename(client, &fname);
+		query_putrdataset(client, &nsec);
+	if (nsecsig != NULL)
+		query_putrdataset(client, &nsecsig);
+	if (fname != NULL)
+		query_releasename(client, &fname);
 }
 
 static inline void
@@ -3269,12 +3277,12 @@
 	dns_rdata_soa_t soa;
 	dns_rdataset_t found;
 	isc_result_t result;
-	
+
 	for (i = 0; i < (sizeof(rfc1918names)/sizeof(*rfc1918names)); i++) {
 		if (dns_name_issubdomain(fname, &rfc1918names[i])) {
 			dns_rdataset_init(&found);
 			result = dns_ncache_getrdataset(rdataset,
-						        &rfc1918names[i],
+							&rfc1918names[i],
 							dns_rdatatype_soa,
 							&found);
 			if (result != ISC_R_SUCCESS)
@@ -3335,6 +3343,7 @@
 	unsigned int options;
 	isc_boolean_t empty_wild;
 	dns_rdataset_t *noqname;
+	isc_boolean_t resuming;
 
 	CTRACE("query_find");
 
@@ -3360,6 +3369,8 @@
 	need_wildcardproof = ISC_FALSE;
 	empty_wild = ISC_FALSE;
 	options = 0;
+	resuming = ISC_FALSE;
+	is_zone = ISC_FALSE;
 
 	if (event != NULL) {
 		/*
@@ -3369,7 +3380,6 @@
 
 		want_restart = ISC_FALSE;
 		authoritative = ISC_FALSE;
-		is_zone = ISC_FALSE;
 
 		qtype = event->qtype;
 		if (qtype == dns_rdatatype_rrsig || qtype == dns_rdatatype_sig)
@@ -3402,6 +3412,7 @@
 		}
 
 		result = event->result;
+		resuming = ISC_TRUE;
 
 		goto resume;
 	}
@@ -3602,7 +3613,7 @@
 			 */
 			if (RECURSIONOK(client)) {
 				result = query_recurse(client, qtype,
-						       NULL, NULL);
+						       NULL, NULL, resuming);
 				if (result == ISC_R_SUCCESS)
 					client->query.attributes |=
 						NS_QUERYATTR_RECURSING;
@@ -3773,10 +3784,12 @@
 				 */
 				if (dns_rdatatype_atparent(type))
 					result = query_recurse(client, qtype,
-							       NULL, NULL);
+							       NULL, NULL,
+							       resuming);
 				else
 					result = query_recurse(client, qtype,
-							       fname, rdataset);
+							       fname, rdataset,
+							       resuming);
 				if (result == ISC_R_SUCCESS)
 					client->query.attributes |=
 						NS_QUERYATTR_RECURSING;
@@ -4220,7 +4233,8 @@
 						result = query_recurse(client,
 								       qtype,
 								       NULL,
-								       NULL);
+								       NULL,
+								       resuming);
 						if (result == ISC_R_SUCCESS)
 						    client->query.attributes |=
 							NS_QUERYATTR_RECURSING;
@@ -4437,6 +4451,7 @@
 	dns_rdataset_t *rdataset;
 	ns_client_t *qclient;
 	dns_rdatatype_t qtype;
+	isc_boolean_t want_ad;
 
 	CTRACE("ns_query_start");
 
@@ -4576,6 +4591,15 @@
 		client->query.attributes &= ~NS_QUERYATTR_SECURE;
 
 	/*
+	 * Set 'want_ad' if the client has set AD in the query.
+	 * This allows AD to be returned on queries without DO set.
+	 */
+	if ((message->flags & DNS_MESSAGEFLAG_AD) != 0)
+		want_ad = ISC_TRUE;
+	else
+		want_ad = ISC_FALSE;
+
+	/*
 	 * This is an ordinary query.
 	 */
 	result = dns_message_reply(message, ISC_TRUE);
@@ -4594,7 +4618,7 @@
 	 * Set AD.  We must clear it if we add non-validated data to a
 	 * response.
 	 */
-	if (WANTDNSSEC(client))
+	if (WANTDNSSEC(client) || want_ad)
 		message->flags |= DNS_MESSAGEFLAG_AD;
 
 	qclient = NULL;
Index: server.c
===================================================================
RCS file: /home/cvs/src/contrib/bind9/bin/named/server.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -L contrib/bind9/bin/named/server.c -L contrib/bind9/bin/named/server.c -u -r1.2 -r1.3
--- contrib/bind9/bin/named/server.c
+++ contrib/bind9/bin/named/server.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,13 +15,14 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: server.c,v 1.419.18.57.10.1 2008/05/22 21:28:04 each Exp $ */
+/* $Id: server.c,v 1.419.18.68 2008/09/04 23:46:08 tbox Exp $ */
 
 /*! \file */
 
 #include <config.h>
 
 #include <stdlib.h>
+#include <unistd.h>
 
 #include <isc/app.h>
 #include <isc/base64.h>
@@ -31,8 +32,10 @@
 #include <isc/hash.h>
 #include <isc/lex.h>
 #include <isc/parseint.h>
+#include <isc/portset.h>
 #include <isc/print.h>
 #include <isc/resource.h>
+#include <isc/socket.h>
 #include <isc/stdio.h>
 #include <isc/string.h>
 #include <isc/task.h>
@@ -197,6 +200,7 @@
 #endif
 
 	/* RFC 3330 */
+	{ "0.IN-ADDR.ARPA", ISC_FALSE },	/* THIS NETWORK */
 	{ "127.IN-ADDR.ARPA", ISC_FALSE },	/* LOOPBACK */
 	{ "254.169.IN-ADDR.ARPA", ISC_FALSE },	/* LINK LOCAL */
 	{ "2.0.192.IN-ADDR.ARPA", ISC_FALSE },	/* TEST NET */
@@ -438,7 +442,7 @@
 	*target = keytable; /* Transfer ownership. */
 	keytable = NULL;
 	result = ISC_R_SUCCESS;
-	
+
  cleanup:
 	return (result);
 }
@@ -454,7 +458,7 @@
 	isc_boolean_t value;
 	isc_result_t result;
 	isc_buffer_t b;
-	
+
 	dns_fixedname_init(&fixed);
 	name = dns_fixedname_name(&fixed);
 	for (element = cfg_list_first(mbs);
@@ -472,7 +476,7 @@
 	}
 
 	result = ISC_R_SUCCESS;
-	
+
  cleanup:
 	return (result);
 }
@@ -482,13 +486,15 @@
  */
 static isc_result_t
 get_view_querysource_dispatch(const cfg_obj_t **maps,
-			      int af, dns_dispatch_t **dispatchp)
+			      int af, dns_dispatch_t **dispatchp,
+			      isc_boolean_t is_firstview)
 {
 	isc_result_t result;
 	dns_dispatch_t *disp;
 	isc_sockaddr_t sa;
 	unsigned int attrs, attrmask;
 	const cfg_obj_t *obj = NULL;
+	unsigned int maxdispatchbuffers;
 
 	/*
 	 * Make compiler happy.
@@ -540,12 +546,18 @@
 		attrs |= DNS_DISPATCHATTR_IPV6;
 		break;
 	}
-
-	if (isc_sockaddr_getport(&sa) != 0) {
+	if (isc_sockaddr_getport(&sa) == 0) {
+		attrs |= DNS_DISPATCHATTR_EXCLUSIVE;
+		maxdispatchbuffers = 4096;
+	} else {
 		INSIST(obj != NULL);
-		cfg_obj_log(obj, ns_g_lctx, ISC_LOG_INFO,
-			    "using specific query-source port suppresses port "
-			    "randomization and can be insecure.");
+		if (is_firstview) {
+			cfg_obj_log(obj, ns_g_lctx, ISC_LOG_INFO,
+				    "using specific query-source port "
+				    "suppresses port randomization and can be "
+				    "insecure.");
+		}
+		maxdispatchbuffers = 1000;
 	}
 
 	attrmask = 0;
@@ -557,7 +569,7 @@
 	disp = NULL;
 	result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
 				     ns_g_taskmgr, &sa, 4096,
-				     1024, 32768, 16411, 16433,
+				     maxdispatchbuffers, 32768, 16411, 16433,
 				     attrs, attrmask, &disp);
 	if (result != ISC_R_SUCCESS) {
 		isc_sockaddr_t any;
@@ -609,7 +621,7 @@
 		return (result);
 
 	obj = cfg_tuple_get(ent, "name");
-	if (cfg_obj_isstring(obj)) 
+	if (cfg_obj_isstring(obj))
 		str = cfg_obj_asstring(obj);
 	else
 		str = "*";
@@ -662,7 +674,7 @@
 	cfg_obj_asnetprefix(cfg_map_getname(cpeer), &na, &prefixlen);
 
 	peer = NULL;
-	result = dns_peer_new(mctx, &na, &peer);
+	result = dns_peer_newprefix(mctx, &na, prefixlen, &peer);
 	if (result != ISC_R_SUCCESS)
 		return (result);
 
@@ -840,7 +852,7 @@
 
 	dns_fixedname_init(&fixed);
 	name = dns_fixedname_name(&fixed);
-	
+
 	for (element = cfg_list_first(disablelist);
 	     element != NULL;
 	     element = cfg_list_next(element))
@@ -911,9 +923,9 @@
 	const cfg_obj_t *alternates;
 	const cfg_obj_t *zonelist;
 #ifdef DLZ
- 	const cfg_obj_t *dlz;
- 	unsigned int dlzargc;
- 	char **dlzargv;
+	const cfg_obj_t *dlz;
+	unsigned int dlzargc;
+	char **dlzargv;
 #endif
 	const cfg_obj_t *disabled;
 	const cfg_obj_t *obj;
@@ -1064,7 +1076,7 @@
 				result = ISC_R_NOMEMORY;
 				goto cleanup;
 			}
-			
+
 			result = dns_dlzstrtoargv(mctx, s, &dlzargc, &dlzargv);
 			if (result != ISC_R_SUCCESS) {
 				isc_mem_free(mctx, s);
@@ -1183,8 +1195,12 @@
 	 *
 	 * XXXRTH  Hardwired number of tasks.
 	 */
-	CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4));
-	CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6));
+	CHECK(get_view_querysource_dispatch(maps, AF_INET, &dispatch4,
+					    ISC_TF(ISC_LIST_PREV(view, link)
+						   == NULL)));
+	CHECK(get_view_querysource_dispatch(maps, AF_INET6, &dispatch6,
+					    ISC_TF(ISC_LIST_PREV(view, link)
+						   == NULL)));
 	if (dispatch4 == NULL && dispatch6 == NULL) {
 		UNEXPECTED_ERROR(__FILE__, __LINE__,
 				 "unable to obtain neither an IPv4 nor"
@@ -1223,7 +1239,7 @@
 	result = ns_config_get(maps, "zero-no-soa-ttl-cache", &obj);
 	INSIST(result == ISC_R_SUCCESS);
 	dns_resolver_setzeronosoattl(view->resolver, cfg_obj_asboolean(obj));
-	
+
 	/*
 	 * Set the resolver's EDNS UDP size.
 	 */
@@ -1236,7 +1252,7 @@
 	if (udpsize > 4096)
 		udpsize = 4096;
 	dns_resolver_setudpsize(view->resolver, (isc_uint16_t)udpsize);
-	
+
 	/*
 	 * Set the maximum UDP response size.
 	 */
@@ -1273,7 +1289,7 @@
 	(void)ns_config_get(maps, "forward", &forwardtype);
 	(void)ns_config_get(maps, "forwarders", &forwarders);
 	if (forwarders != NULL)
-		CHECK(configure_forward(config, view, dns_rootname, 
+		CHECK(configure_forward(config, view, dns_rootname,
 					forwarders, forwardtype));
 
 	/*
@@ -1293,7 +1309,7 @@
 	/*
 	 * If we still have no hints, this is a non-IN view with no
 	 * "hints zone" configured.  Issue a warning, except if this
-	 * is a root server.  Root servers never need to consult 
+	 * is a root server.  Root servers never need to consult
 	 * their hints, so it's no point requiring users to configure
 	 * them.
 	 */
@@ -1416,7 +1432,7 @@
 		view->transfer_format = dns_one_answer;
 	else
 		INSIST(0);
-	
+
 	/*
 	 * Set sources where additional data and CNAME/DNAME
 	 * targets for authoritative answers may be found.
@@ -1516,7 +1532,7 @@
 	dns_resolver_setclientsperquery(view->resolver,
 					cfg_obj_asuint32(obj),
 					max_clients_per_query);
-			
+
 	obj = NULL;
 	result = ns_config_get(maps, "dnssec-enable", &obj);
 	INSIST(result == ISC_R_SUCCESS);
@@ -1745,14 +1761,14 @@
 			if (result == ISC_R_SUCCESS &&
 			    forwarders->fwdpolicy == dns_fwdpolicy_only)
 				continue;
-						
+
 			if (!rfc1918 && empty_zones[empty_zone].rfc1918) {
 				if (logit) {
 					isc_log_write(ns_g_lctx,
 						      NS_LOGCATEGORY_GENERAL,
 						      NS_LOGMODULE_SERVER,
 						      ISC_LOG_WARNING,
-					              "Warning%s%s: "
+						      "Warning%s%s: "
 						      "'empty-zones-enable/"
 						      "disable-empty-zone' "
 						      "not set: disabling "
@@ -1794,7 +1810,7 @@
 			dns_zone_setclass(zone, view->rdclass);
 			dns_zone_settype(zone, dns_zone_master);
 			CHECK(dns_zone_setdbtype(zone, empty_dbtypec,
-					 	 empty_dbtype));
+						 empty_dbtype));
 			if (view->queryacl != NULL)
 				dns_zone_setqueryacl(zone, view->queryacl);
 			dns_zone_setdialup(zone, dns_dialuptype_no);
@@ -1809,7 +1825,7 @@
 			dns_zone_detach(&zone);
 		}
 	}
-	
+
 	result = ISC_R_SUCCESS;
 
  cleanup:
@@ -2125,7 +2141,7 @@
 							       "name"));
 		else
 			vname = "<default view>";
-	
+
 		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
 			      NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
 			      "zone '%s': wrong class for view '%s'",
@@ -2499,7 +2515,7 @@
 	}
 
 	ns_interfacemgr_adjust(server->interfacemgr, list, ISC_TRUE);
-	
+
  clean:
 	ns_listenlist_detach(&list);
 	return;
@@ -2588,7 +2604,7 @@
 
 	*field = copy;
 	return (ISC_R_SUCCESS);
-}	
+}
 
 /*
  * Replace the current value of '*field', a dynamically allocated
@@ -2630,7 +2646,7 @@
 	result = isc_resource_setlimit(resourceid, value);
 	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
 		      result == ISC_R_SUCCESS ?
-		      	ISC_LOG_DEBUG(3) : ISC_LOG_WARNING,
+			ISC_LOG_DEBUG(3) : ISC_LOG_WARNING,
 		      "set maximum %s to %" ISC_PRINT_QUADFORMAT "d: %s",
 		      description, value, isc_result_totext(result));
 }
@@ -2647,31 +2663,48 @@
 	SETLIMIT("files", openfiles, "open files");
 }
 
-static isc_result_t
-portlist_fromconf(dns_portlist_t *portlist, unsigned int family,
-		  const cfg_obj_t *ports)
+static void
+portset_fromconf(isc_portset_t *portset, const cfg_obj_t *ports,
+		 isc_boolean_t positive)
 {
 	const cfg_listelt_t *element;
-	isc_result_t result = ISC_R_SUCCESS;
 
 	for (element = cfg_list_first(ports);
 	     element != NULL;
 	     element = cfg_list_next(element)) {
 		const cfg_obj_t *obj = cfg_listelt_value(element);
-		in_port_t port = (in_port_t)cfg_obj_asuint32(obj);
-		
-		result = dns_portlist_add(portlist, family, port);
-		if (result != ISC_R_SUCCESS)
-			break;
+
+		if (cfg_obj_isuint32(obj)) {
+			in_port_t port = (in_port_t)cfg_obj_asuint32(obj);
+
+			if (positive)
+				isc_portset_add(portset, port);
+			else
+				isc_portset_remove(portset, port);
+		} else {
+			const cfg_obj_t *obj_loport, *obj_hiport;
+			in_port_t loport, hiport;
+
+			obj_loport = cfg_tuple_get(obj, "loport");
+			loport = (in_port_t)cfg_obj_asuint32(obj_loport);
+			obj_hiport = cfg_tuple_get(obj, "hiport");
+			hiport = (in_port_t)cfg_obj_asuint32(obj_hiport);
+
+			if (positive)
+				isc_portset_addrange(portset, loport, hiport);
+			else {
+				isc_portset_removerange(portset, loport,
+							hiport);
+			}
+		}
 	}
-	return (result);
 }
 
 static isc_result_t
 removed(dns_zone_t *zone, void *uap) {
 	const char *type;
 
-        if (dns_zone_getview(zone) != uap)
+	if (dns_zone_getview(zone) != uap)
 		return (ISC_R_SUCCESS);
 
 	switch (dns_zone_gettype(zone)) {
@@ -2696,34 +2729,39 @@
 load_configuration(const char *filename, ns_server_t *server,
 		   isc_boolean_t first_time)
 {
-	isc_result_t result;
-	isc_interval_t interval;
-	cfg_parser_t *parser = NULL;
+	cfg_aclconfctx_t aclconfctx;
 	cfg_obj_t *config;
+	cfg_parser_t *parser = NULL;
+	const cfg_listelt_t *element;
+	const cfg_obj_t *builtin_views;
+	const cfg_obj_t *maps[3];
+	const cfg_obj_t *obj;
 	const cfg_obj_t *options;
+	const cfg_obj_t *usev4ports, *avoidv4ports, *usev6ports, *avoidv6ports;
 	const cfg_obj_t *views;
-	const cfg_obj_t *obj;
-	const cfg_obj_t *v4ports, *v6ports;
-	const cfg_obj_t *maps[3];
-	const cfg_obj_t *builtin_views;
-	const cfg_listelt_t *element;
 	dns_view_t *view = NULL;
 	dns_view_t *view_next;
-	dns_viewlist_t viewlist;
 	dns_viewlist_t tmpviewlist;
-	cfg_aclconfctx_t aclconfctx;
-	isc_uint32_t interface_interval;
+	dns_viewlist_t viewlist;
+	in_port_t listen_port, udpport_low, udpport_high;
+	int i;
+	isc_interval_t interval;
+	isc_portset_t *v4portset = NULL;
+	isc_portset_t *v6portset = NULL;
+	isc_resourcevalue_t nfiles;
+	isc_result_t result;
 	isc_uint32_t heartbeat_interval;
+	isc_uint32_t interface_interval;
+	isc_uint32_t reserved;
 	isc_uint32_t udpsize;
-	in_port_t listen_port;
-	int i;
+	unsigned int maxsocks;
 
 	cfg_aclconfctx_init(&aclconfctx);
 	ISC_LIST_INIT(viewlist);
 
 	/* Ensure exclusive access to configuration data. */
 	result = isc_task_beginexclusive(server->task);
-	RUNTIME_CHECK(result == ISC_R_SUCCESS);	
+	RUNTIME_CHECK(result == ISC_R_SUCCESS);
 
 	/*
 	 * Parse the global default pseudo-config file.
@@ -2797,6 +2835,48 @@
 	set_limits(maps);
 
 	/*
+	 * Check if max number of open sockets that the system allows is
+	 * sufficiently large.  Failing this condition is not necessarily fatal,
+	 * but may cause subsequent runtime failures for a busy recursive
+	 * server.
+	 */
+	result = isc_socketmgr_getmaxsockets(ns_g_socketmgr, &maxsocks);
+	if (result != ISC_R_SUCCESS)
+		maxsocks = 0;
+	result = isc_resource_getcurlimit(isc_resource_openfiles, &nfiles);
+	if (result == ISC_R_SUCCESS && (isc_resourcevalue_t)maxsocks > nfiles) {
+		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+			      NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+			      "max open files (%" ISC_PRINT_QUADFORMAT "u)"
+			      " is smaller than max sockets (%u)",
+			      nfiles, maxsocks);
+	}
+
+	/*
+	 * Set the number of socket reserved for TCP, stdio etc.
+	 */
+	obj = NULL;
+	result = ns_config_get(maps, "reserved-sockets", &obj);
+	INSIST(result == ISC_R_SUCCESS);
+	reserved = cfg_obj_asuint32(obj);
+	if (maxsocks != 0) {
+		if (maxsocks < 128U)			/* Prevent underflow. */
+			reserved = 0;
+		else if (reserved > maxsocks - 128U)	/* Minimum UDP space. */
+			reserved = maxsocks - 128;
+	}
+	/* Minimum TCP/stdio space. */
+	if (reserved < 128U)
+		reserved = 128;
+	if (reserved + 128U > maxsocks && maxsocks != 0) {
+		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+			      NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
+			      "less than 128 UDP sockets available after "
+			      "applying 'reserved-sockets' and 'maxsockets'");
+	}
+	isc__socketmgr_setreserved(ns_g_socketmgr, reserved);
+
+	/*
 	 * Configure various server options.
 	 */
 	configure_server_quota(maps, "transfers-out", &server->xfroutquota);
@@ -2820,24 +2900,64 @@
 	INSIST(result == ISC_R_SUCCESS);
 	server->aclenv.match_mapped = cfg_obj_asboolean(obj);
 
-	v4ports = NULL;
-	v6ports = NULL;
-	(void)ns_config_get(maps, "avoid-v4-udp-ports", &v4ports);
-	(void)ns_config_get(maps, "avoid-v6-udp-ports", &v6ports);
-	if (v4ports != NULL || v6ports != NULL) {
-		dns_portlist_t *portlist = NULL;
-		result = dns_portlist_create(ns_g_mctx, &portlist);
-		if (result == ISC_R_SUCCESS && v4ports != NULL)
-			result = portlist_fromconf(portlist, AF_INET, v4ports);
-		if (result == ISC_R_SUCCESS && v6ports != NULL)
-			portlist_fromconf(portlist, AF_INET6, v6ports);
-		if (result == ISC_R_SUCCESS)
-			dns_dispatchmgr_setblackportlist(ns_g_dispatchmgr, portlist);
-		if (portlist != NULL)
-			dns_portlist_detach(&portlist);
-		CHECK(result);
-	} else
-		dns_dispatchmgr_setblackportlist(ns_g_dispatchmgr, NULL);
+	/*
+	 * Configure sets of UDP query source ports.
+	 */
+	CHECKM(isc_portset_create(ns_g_mctx, &v4portset),
+	       "creating UDP port set");
+	CHECKM(isc_portset_create(ns_g_mctx, &v6portset),
+	       "creating UDP port set");
+
+	usev4ports = NULL;
+	usev6ports = NULL;
+	avoidv4ports = NULL;
+	avoidv6ports = NULL;
+
+	(void)ns_config_get(maps, "use-v4-udp-ports", &usev4ports);
+	if (usev4ports != NULL)
+		portset_fromconf(v4portset, usev4ports, ISC_TRUE);
+	else {
+		CHECKM(isc_net_getudpportrange(AF_INET, &udpport_low,
+					       &udpport_high),
+		       "get the default UDP/IPv4 port range");
+		if (udpport_low == udpport_high)
+			isc_portset_add(v4portset, udpport_low);
+		else {
+			isc_portset_addrange(v4portset, udpport_low,
+					     udpport_high);
+		}
+		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+			      NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+			      "using default UDP/IPv4 port range: [%d, %d]",
+			      udpport_low, udpport_high);
+	}
+	(void)ns_config_get(maps, "avoid-v4-udp-ports", &avoidv4ports);
+	if (avoidv4ports != NULL)
+		portset_fromconf(v4portset, avoidv4ports, ISC_FALSE);
+
+	(void)ns_config_get(maps, "use-v6-udp-ports", &usev6ports);
+	if (usev6ports != NULL)
+		portset_fromconf(v6portset, usev6ports, ISC_TRUE);
+	else {
+		CHECKM(isc_net_getudpportrange(AF_INET6, &udpport_low,
+					       &udpport_high),
+		       "get the default UDP/IPv6 port range");
+		if (udpport_low == udpport_high)
+			isc_portset_add(v6portset, udpport_low);
+		else {
+			isc_portset_addrange(v6portset, udpport_low,
+					     udpport_high);
+		}
+		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+			      NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+			      "using default UDP/IPv6 port range: [%d, %d]",
+			      udpport_low, udpport_high);
+	}
+	(void)ns_config_get(maps, "avoid-v6-udp-ports", &avoidv6ports);
+	if (avoidv6ports != NULL)
+		portset_fromconf(v6portset, avoidv6ports, ISC_FALSE);
+
+	dns_dispatchmgr_setavailports(ns_g_dispatchmgr, v4portset, v6portset);
 
 	/*
 	 * Set the EDNS UDP size when we don't match a view.
@@ -2998,7 +3118,7 @@
 				      NULL, &interval, ISC_FALSE));
 	}
 	server->heartbeat_interval = heartbeat_interval;
-	
+
 	isc_interval_set(&interval, 1200, 0);
 	CHECK(isc_timer_reset(server->pps_timer, isc_timertype_ticker, NULL,
 			      &interval, ISC_FALSE));
@@ -3146,6 +3266,15 @@
 		ns_os_changeuser();
 
 	/*
+	 * Check that the working directory is writable.
+	 */
+	if (access(".", W_OK) != 0) {
+		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+			      NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
+			      "the working directory is not writable");
+	}
+
+	/*
 	 * Configure the logging system.
 	 *
 	 * Do this after changing UID to make sure that any log
@@ -3238,7 +3367,7 @@
 		ns_os_writepidfile(lwresd_g_defaultpidfile, first_time);
 	else
 		ns_os_writepidfile(ns_g_defaultpidfile, first_time);
-	
+
 	obj = NULL;
 	if (options != NULL &&
 	    cfg_map_get(options, "memstatistics-file", &obj) == ISC_R_SUCCESS)
@@ -3305,6 +3434,12 @@
 	result = ISC_R_SUCCESS;
 
  cleanup:
+	if (v4portset != NULL)
+		isc_portset_destroy(ns_g_mctx, &v4portset);
+
+	if (v6portset != NULL)
+		isc_portset_destroy(ns_g_mctx, &v6portset);
+
 	cfg_aclconfctx_destroy(&aclconfctx);
 
 	if (parser != NULL) {
@@ -3375,7 +3510,7 @@
 	 */
 	CHECK(dns_zonemgr_forcemaint(server->zonemgr));
  cleanup:
-	isc_task_endexclusive(server->task);	
+	isc_task_endexclusive(server->task);
 	return (result);
 }
 
@@ -3403,7 +3538,7 @@
 	 */
 	dns_zonemgr_resumexfrs(server->zonemgr);
  cleanup:
-	isc_task_endexclusive(server->task);	
+	isc_task_endexclusive(server->task);
 	return (result);
 }
 
@@ -3462,7 +3597,7 @@
 		      ISC_LOG_NOTICE, "running");
 }
 
-void 
+void
 ns_server_flushonshutdown(ns_server_t *server, isc_boolean_t flush) {
 
 	REQUIRE(NS_SERVER_VALID(server));
@@ -3596,7 +3731,7 @@
 	server->interface_timer = NULL;
 	server->heartbeat_timer = NULL;
 	server->pps_timer = NULL;
-	
+
 	server->interface_interval = 0;
 	server->heartbeat_interval = 0;
 
@@ -3619,7 +3754,7 @@
 
 	server->hostname_set = ISC_FALSE;
 	server->hostname = NULL;
-	server->version_set = ISC_FALSE;	
+	server->version_set = ISC_FALSE;
 	server->version = NULL;
 	server->server_usehostname = ISC_FALSE;
 	server->server_id = NULL;
@@ -3775,7 +3910,7 @@
 	result = dns_dispatch_getudp(ns_g_dispatchmgr, ns_g_socketmgr,
 				     ns_g_taskmgr, &dispatch->addr, 4096,
 				     1000, 32768, 16411, 16433,
-				     attrs, attrmask, &dispatch->dispatch); 
+				     attrs, attrmask, &dispatch->dispatch);
 	if (result != ISC_R_SUCCESS)
 		goto cleanup;
 
@@ -3878,7 +4013,7 @@
 			break;
 	} while (*res == '\0');
 	return (res);
-}                       
+}
 
 /*
  * Find the zone specified in the control channel command 'args',
@@ -3936,14 +4071,14 @@
 	} else {
 		rdclass = dns_rdataclass_in;
 	}
-	
+
 	if (viewtxt == NULL)
 		viewtxt = "_default";
 	result = dns_viewlist_find(&server->viewlist, viewtxt,
 				   rdclass, &view);
 	if (result != ISC_R_SUCCESS)
 		goto fail1;
-	
+
 	result = dns_zt_find(view->zonetable, dns_fixedname_name(&name),
 			     0, NULL, zonep);
 	/* Partial match? */
@@ -3962,7 +4097,7 @@
 	isc_result_t result;
 	dns_zone_t *zone = NULL;
 	dns_zonetype_t type;
-	
+
 	result = zone_from_args(server, args, &zone);
 	if (result != ISC_R_SUCCESS)
 		return (result);
@@ -3975,7 +4110,7 @@
 		result = ISC_R_NOTFOUND;
 	dns_zone_detach(&zone);
 	return (result);
-}	
+}
 
 /*
  * Act on a "reload" command from the command channel.
@@ -3986,7 +4121,7 @@
 	dns_zone_t *zone = NULL;
 	dns_zonetype_t type;
 	const char *msg = NULL;
-	
+
 	result = zone_from_args(server, args, &zone);
 	if (result != ISC_R_SUCCESS)
 		return (result);
@@ -4003,7 +4138,7 @@
 		} else {
 			result = dns_zone_load(zone);
 			dns_zone_detach(&zone);
-			switch (result) {	
+			switch (result) {
 			case ISC_R_SUCCESS:
 				 msg = "zone reload successful";
 				 break;
@@ -4025,7 +4160,7 @@
 		isc_buffer_putmem(text, (const unsigned char *)msg,
 				  strlen(msg) + 1);
 	return (result);
-}	
+}
 
 /*
  * Act on a "reconfig" command from the command channel.
@@ -4052,14 +4187,14 @@
 		return (result);
 	if (zone == NULL)
 		return (ISC_R_UNEXPECTEDEND);
-	
+
 	dns_zone_notify(zone);
 	dns_zone_detach(&zone);
 	if (sizeof(msg) <= isc_buffer_availablelength(text))
 		isc_buffer_putmem(text, msg, sizeof(msg));
 
 	return (ISC_R_SUCCESS);
-}	
+}
 
 /*
  * Act on a "refresh" command from the command channel.
@@ -4086,17 +4221,17 @@
 			isc_buffer_putmem(text, msg1, sizeof(msg1));
 		return (ISC_R_SUCCESS);
 	}
-		
+
 	dns_zone_detach(&zone);
 	if (sizeof(msg2) <= isc_buffer_availablelength(text))
 		isc_buffer_putmem(text, msg2, sizeof(msg2));
 	return (ISC_R_FAILURE);
-}	
+}
 
 isc_result_t
 ns_server_togglequerylog(ns_server_t *server) {
 	server->log_queries = server->log_queries ? ISC_FALSE : ISC_TRUE;
-	
+
 	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
 		      NS_LOGMODULE_SERVER, ISC_LOG_INFO,
 		      "query logging is now %s",
@@ -4200,15 +4335,15 @@
 
 	CHECKMF(isc_stdio_open(server->statsfile, "a", &fp),
 		"could not open statistics dump file", server->statsfile);
-	
+
 	ncounters = DNS_STATS_NCOUNTERS;
 	fprintf(fp, "+++ Statistics Dump +++ (%lu)\n", (unsigned long)now);
-	
+
 	for (i = 0; i < ncounters; i++)
 		fprintf(fp, "%s %" ISC_PRINT_QUADFORMAT "u\n",
 			dns_statscounter_names[i],
 			server->querystats[i]);
-	
+
 	zone = NULL;
 	for (result = dns_zone_first(server->zonemgr, &zone);
 	     result == ISC_R_SUCCESS;
@@ -4219,7 +4354,7 @@
 			char zonename[DNS_NAME_FORMATSIZE];
 			dns_view_t *view;
 			char *viewname;
-			
+
 			dns_name_format(dns_zone_getorigin(zone),
 					zonename, sizeof(zonename));
 			view = dns_zone_getview(zone);
@@ -4239,7 +4374,7 @@
 	if (result == ISC_R_NOMORE)
 		result = ISC_R_SUCCESS;
 	CHECK(result);
-	
+
 	fprintf(fp, "--- Statistics Dump --- (%lu)\n", (unsigned long)now);
 
  cleanup:
@@ -4267,7 +4402,7 @@
 add_view_tolist(struct dumpcontext *dctx, dns_view_t *view) {
 	struct viewlistentry *vle;
 	isc_result_t result = ISC_R_SUCCESS;
-	
+
 	/*
 	 * Prevent duplicate views.
 	 */
@@ -4330,7 +4465,7 @@
 	struct dumpcontext *dctx = arg;
 	char buf[1024+32];
 	const dns_master_style_t *style;
-	
+
 	if (result != ISC_R_SUCCESS)
 		goto cleanup;
 	if (dctx->mdctx != NULL)
@@ -4487,7 +4622,7 @@
 		dctx->dumpzones = ISC_TRUE;
 		dctx->dumpcache = ISC_FALSE;
 		ptr = next_token(&args, " \t");
-	} 
+	}
 
  nextview:
 	for (view = ISC_LIST_HEAD(server->viewlist);
@@ -4607,7 +4742,7 @@
 	else
 		result = ISC_R_FAILURE;
  out:
-	isc_task_endexclusive(server->task);	
+	isc_task_endexclusive(server->task);
 	return (result);
 }
 
@@ -4650,7 +4785,7 @@
 		else
 			result = ISC_R_FAILURE;
 	}
-	isc_task_endexclusive(server->task);	
+	isc_task_endexclusive(server->task);
 	return (result);
 }
 
@@ -4707,7 +4842,7 @@
 		result = ISC_R_NOTFOUND;
 	else
 		result = ISC_R_FAILURE;
-	isc_task_endexclusive(server->task);	
+	isc_task_endexclusive(server->task);
 	return (result);
 }
 
@@ -4759,7 +4894,7 @@
 	char *journal;
 	const char *vname, *sep;
 	isc_boolean_t frozen;
-	
+
 	result = zone_from_args(server, args, &zone);
 	if (result != ISC_R_SUCCESS)
 		return (result);
@@ -4767,7 +4902,7 @@
 		result = isc_task_beginexclusive(server->task);
 		RUNTIME_CHECK(result == ISC_R_SUCCESS);
 		tresult = ISC_R_SUCCESS;
-	        for (view = ISC_LIST_HEAD(server->viewlist);
+		for (view = ISC_LIST_HEAD(server->viewlist);
 		     view != NULL;
 		     view = ISC_LIST_NEXT(view, link)) {
 			result = dns_view_freezezones(view, freeze);


More information about the Midnightbsd-cvs mailing list