$Id: patch-bind-8.3.3-dickhead.diff 133 2003-09-19 00:25:11Z sam $
diff -puriN bind-8.3.3-old/src/bin/named/ns_config.c bind-8.3.3/src/bin/named/ns_config.c
--- bind-8.3.3-old/src/bin/named/ns_config.c	2002-05-24 05:04:59.000000000 +0200
+++ bind-8.3.3/src/bin/named/ns_config.c	2003-09-19 01:55:51.000000000 +0200
@@ -1124,6 +1124,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 */
@@ -1185,6 +1186,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.3.3-old/src/bin/named/ns_defs.h bind-8.3.3/src/bin/named/ns_defs.h
--- bind-8.3.3-old/src/bin/named/ns_defs.h	2002-06-26 05:27:19.000000000 +0200
+++ bind-8.3.3/src/bin/named/ns_defs.h	2003-09-19 01:55:51.000000000 +0200
@@ -773,6 +773,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.3.3-old/src/bin/named/ns_lexer.c bind-8.3.3/src/bin/named/ns_lexer.c
--- bind-8.3.3-old/src/bin/named/ns_lexer.c	2002-05-24 05:05:03.000000000 +0200
+++ bind-8.3.3/src/bin/named/ns_lexer.c	2003-09-19 01:55:51.000000000 +0200
@@ -248,6 +248,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.3.3-old/src/bin/named/ns_parser.y bind-8.3.3/src/bin/named/ns_parser.y
--- bind-8.3.3-old/src/bin/named/ns_parser.y	2002-05-24 05:05:01.000000000 +0200
+++ bind-8.3.3/src/bin/named/ns_parser.y	2003-09-19 01:55:51.000000000 +0200
@@ -217,6 +217,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
@@ -530,6 +533,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.3.3-old/src/bin/named/ns_resp.c bind-8.3.3/src/bin/named/ns_resp.c
--- bind-8.3.3-old/src/bin/named/ns_resp.c	2002-06-27 05:09:19.000000000 +0200
+++ bind-8.3.3/src/bin/named/ns_resp.c	2003-09-19 02:07:32.000000000 +0200
@@ -983,6 +983,21 @@ tcp_retry:
 				validanswer = 0;
 				continue;
 			}
+		        /*
+		         * Check for dickheads' A records.
+		         */
+			if (type == T_A) {
+				struct in_addr addr = ina_get (dp->d_data);
+				if (server_options->dickheads != NULL &&
+				    ip_match_address(server_options->dickheads,
+						      addr) == 1) {
+					ns_debug(ns_log_default, 1,
+						 "refused dickhead answer '%s'",
+						 inet_ntoa(addr));
+					goto nxdomain;
+				}
+			}
+
 			if (type == T_CNAME &&
 			    qtype != T_CNAME && qtype != T_ANY) {
 				strcpy(aname, (char *)dp->d_data);
@@ -1679,6 +1694,21 @@ tcp_retry:
 	free_nsp(nsp);
 	return;
 	
+  nxdomain:
+	nameserIncr(qp->q_from.sin_addr, 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(qp->q_from.sin_addr, nssSentFail);
 	hp = (HEADER *)(qp->q_cmsglen ? qp->q_cmsg : qp->q_msg);

