$Id: patch-bind-8.4.1.0-dickhead.diff 131 2003-09-18 08:24:07Z sam $
diff -puriN bind-8.4.1.0.old/src/bin/named/ns_config.c bind-8.4.1.0/src/bin/named/ns_config.c
--- bind-8.4.1.0.old/src/bin/named/ns_config.c	2003-05-26 06:08:57.000000000 +0200
+++ bind-8.4.1.0/src/bin/named/ns_config.c	2003-09-16 18:19:12.000000000 +0200
@@ -1168,6 +1168,7 @@ new_options() {
 	op->query_acl = NULL;
 	op->transfer_acl = NULL;
 	op->recursion_acl = NULL;
+	op->dickheads = NULL;
 	op->sortlist = NULL;
 	op->topology = NULL;
 	op->data_size = 0UL;	/* use system default */
@@ -1231,6 +1232,8 @@ free_options(options op) {
 		free_ip_match_list(op->recursion_acl);
 	if (op->transfer_acl)
 		free_ip_match_list(op->transfer_acl);
+	if (op->dickheads)
+		free_ip_match_list(op->dickheads);
 	if (op->sortlist)
 		free_ip_match_list(op->sortlist);
 	if (op->ordering)
diff -puriN bind-8.4.1.0.old/src/bin/named/ns_defs.h bind-8.4.1.0/src/bin/named/ns_defs.h
--- bind-8.4.1.0.old/src/bin/named/ns_defs.h	2003-06-02 02:41:48.000000000 +0200
+++ bind-8.4.1.0/src/bin/named/ns_defs.h	2003-09-16 18:15:54.000000000 +0200
@@ -863,6 +863,7 @@ typedef struct options {
 	ip_match_list recursion_acl;
 	ip_match_list transfer_acl;
 	ip_match_list blackhole_acl;
+	ip_match_list dickheads;
 	ip_match_list topology;
 	ip_match_list sortlist;
 	enum severity check_names[num_trans];
diff -puriN bind-8.4.1.0.old/src/bin/named/ns_lexer.c bind-8.4.1.0/src/bin/named/ns_lexer.c
--- bind-8.4.1.0.old/src/bin/named/ns_lexer.c	2003-05-26 06:08:58.000000000 +0200
+++ bind-8.4.1.0/src/bin/named/ns_lexer.c	2003-09-16 18:17:43.000000000 +0200
@@ -252,6 +252,7 @@ static struct keyword keywords[] = {
 	{"debug", T_DEBUG},
 	{"default", T_DEFAULT},
 	{"dialup", T_DIALUP},
+	{"dickheads", T_DICKHEADS},
 	{"directory", T_DIRECTORY}, 
 	{"dump-file", T_DUMP_FILE},
 	{"dynamic", T_DYNAMIC},
diff -puriN bind-8.4.1.0.old/src/bin/named/ns_parser.y bind-8.4.1.0/src/bin/named/ns_parser.y
--- bind-8.4.1.0.old/src/bin/named/ns_parser.y	2003-09-16 11:22:36.000000000 +0200
+++ bind-8.4.1.0/src/bin/named/ns_parser.y	2003-09-16 18:23:58.000000000 +0200
@@ -221,6 +221,9 @@ int yyparse();
 %token			T_ALLOW_RECURSION
 %token			T_BLACKHOLE
 
+/* Items used for "dickheads" clauses: */
+%token			T_DICKHEADS
+
 /* Items related to the "key" statement: */
 %token			T_SEC_KEY T_ALGID T_SECRET
 %type	<keyi>		key_ref
@@ -576,6 +579,16 @@ option: /* Empty */
 		} else
 			current_options->blackhole_acl = $3;
 	}
+	| T_DICKHEADS '{' address_match_list '}'
+	{
+		if (current_options->dickheads) {
+			parser_warning(0,
+			   "options dickheads already set; skipping");
+			free_ip_match_list($3);
+		} else {
+			current_options->dickheads = $3;
+		}
+	}
 	| T_TOPOLOGY '{' address_match_list '}'
 	{
 		if (current_options->topology) {
diff -puriN bind-8.4.1.0.old/src/bin/named/ns_resp.c bind-8.4.1.0/src/bin/named/ns_resp.c
--- bind-8.4.1.0.old/src/bin/named/ns_resp.c	2003-09-16 11:22:36.000000000 +0200
+++ bind-8.4.1.0/src/bin/named/ns_resp.c	2003-09-16 20:06:15.000000000 +0200
@@ -1003,6 +1003,24 @@ ns_info(ns_log_resp_checks,
 				validanswer = 0;
 				continue;
 			}
+		        /*
+		         * Check for dickheads' A records.
+		         */
+			if (type == T_A) {
+				struct sockaddr_storage addr;
+				memset(&addr, 0, sizeof addr);
+				addr.ss_family = AF_INET;
+				satosin(sstosa(&addr))->sin_addr = ina_get (dp->d_data);
+				if (server_options->dickheads != NULL &&
+				    ip_match_address(server_options->dickheads,
+						     sstosa(&addr)) == 1) {
+					ns_debug(ns_log_default, 1,
+						 "refused dickhead answer '%s'",
+						 sa_ntoa(sstosa(&addr)));
+					goto nxdomain;
+				}
+			}
+
 			if (type == T_CNAME &&
 			    qtype != T_CNAME && qtype != T_ANY) {
 				strcpy(aname, (char *)dp->d_data);
@@ -1684,6 +1702,21 @@ ns_info(ns_log_resp_checks,
 	free_nsp(nsp);
 	return;
 	
+  nxdomain:
+	nameserIncr(sstosa(&qp->q_from), nssSentNXD);
+	hp = (HEADER *)(qp->q_cmsglen ? qp->q_cmsg : qp->q_msg);
+	hp->rcode = NXDOMAIN;
+	hp->qr = 1;
+	hp->id = qp->q_id;
+	hp->rd = 1;
+	hp->ra = (NS_OPTION_P(OPTION_NORECURSE) == 0);
+	(void) send_msg((u_char *)hp,
+			(qp->q_cmsglen ? qp->q_cmsglen : qp->q_msglen),
+			qp);
+	qremove(qp);
+	free_nsp(nsp);
+	return;
+
  servfail:
 	nameserIncr(sstosa(&qp->q_from), nssSentFail);
 	hp = (HEADER *)(qp->q_cmsglen ? qp->q_cmsg : qp->q_msg);
