diff -urN nsd-3.2.5/configparser.y nsd-3.2.5-new/configparser.y
--- nsd-3.2.5/configparser.y	2010-02-24 11:46:56.000000000 +0100
+++ nsd-3.2.5-new/configparser.y	2010-04-28 14:34:03.000000000 +0200
@@ -21,6 +21,7 @@
 #include "configyyrename.h"
 int c_lex(void);
 void c_error(const char *message);
+void cfg_parser_insert_current_zone ();
 
 #ifdef __cplusplus
 extern "C"
@@ -70,6 +71,8 @@
 			yyerror("duplicate server: element.");
 		}
 		server_settings_seen = 1;
+		cfg_parser_insert_current_zone();
+		cfg_parser->current_zone = cfg_parser->default_zone_options;
 	}
 	;
 contents_server: contents_server content_server | ;
@@ -79,7 +82,9 @@
 	server_statistics | server_chroot | server_username | server_zonesdir |
 	server_difffile | server_xfrdfile | server_xfrd_reload_timeout |
 	server_tcp_query_count | server_tcp_timeout | server_ipv4_edns_size |
-	server_ipv6_edns_size | server_verbosity | server_hide_version;
+	server_ipv6_edns_size | server_verbosity | server_hide_version |
+	zone_allow_notify | zone_request_xfr | zone_notify | zone_notify_retry |
+	zone_provide_xfr | zone_outgoing_interface | zone_allow_axfr_fallback;
 server_ip_address: VAR_IP_ADDRESS STRING 
 	{ 
 		OUTYY(("P(server_ip_address:%s)\n", $2)); 
@@ -291,23 +296,8 @@
 zonestart: VAR_ZONE
 	{ 
 		OUTYY(("\nP(zone:)\n")); 
-		if(cfg_parser->current_zone) {
-			if(!cfg_parser->current_zone->name) 
-				c_error("previous zone has no name");
-			else {
-				if(!nsd_options_insert_zone(cfg_parser->opt, 
-					cfg_parser->current_zone))
-					c_error("duplicate zone");
-			}
-			if(!cfg_parser->current_zone->zonefile) 
-				c_error("previous zone has no zonefile");
-		}
+		cfg_parser_insert_current_zone();
 		cfg_parser->current_zone = zone_options_create(cfg_parser->opt->region);
-		cfg_parser->current_allow_notify = 0;
-		cfg_parser->current_request_xfr = 0;
-		cfg_parser->current_notify = 0;
-		cfg_parser->current_provide_xfr = 0;
-		cfg_parser->current_outgoing_interface = 0;
 	}
 	;
 contents_zone: contents_zone content_zone | content_zone;
@@ -435,7 +425,8 @@
 		OUTYY(("P(zone_allow_axfr_fallback:%s)\n", $2)); 
 		if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
 			yyerror("expected yes or no.");
-		else cfg_parser->current_zone->allow_axfr_fallback = (strcmp($2, "yes")==0);
+		else cfg_parser->current_zone->allow_axfr_fallback =
+			(strcmp($2, "yes")==0) ? ALLOW_AXFR_FALLBACK : DISALLOW_AXFR_FALLBACK;
 	}
 	;
 
diff -urN nsd-3.2.5/options.c nsd-3.2.5-new/options.c
--- nsd-3.2.5/options.c	2010-04-22 14:26:48.000000000 +0200
+++ nsd-3.2.5-new/options.c	2010-04-22 14:38:08.000000000 +0200
@@ -77,11 +77,33 @@
 	return 1;
 }
 
+void cfg_parser_insert_current_zone()
+{
+	if (cfg_parser->current_zone && cfg_parser->current_zone != cfg_parser->default_zone_options) {
+		if(!cfg_parser->current_zone->name)
+			c_error("previous zone has no name");
+		else {
+			if(!nsd_options_insert_zone(cfg_parser->opt, cfg_parser->current_zone))
+				c_error("duplicate zone");
+		}
+		if(!cfg_parser->current_zone->zonefile)
+			c_error("previous zone has no zonefile");
+	}
+
+	/* reset current_zone parser settings */
+	cfg_parser->current_zone = 0;
+	cfg_parser->current_allow_notify = 0;
+	cfg_parser->current_request_xfr = 0;
+	cfg_parser->current_notify = 0;
+	cfg_parser->current_provide_xfr = 0;
+	cfg_parser->current_outgoing_interface = 0;
+}
+
 int parse_options_file(nsd_options_t* opt, const char* file)
 {
 	FILE *in = 0;
 	zone_options_t* zone;
-	acl_options_t* acl;
+	acl_options_t* acl, *prev_acl;
 
 	if(!cfg_parser)
 		cfg_parser = (config_parser_state_t*)region_alloc(
@@ -102,6 +124,10 @@
 	cfg_parser->current_notify = 0;
 	cfg_parser->current_provide_xfr = 0;
 
+	cfg_parser->default_zone_options = zone_options_create(cfg_parser->opt->region);
+	cfg_parser->default_zone_options->allow_axfr_fallback = ALLOW_AXFR_FALLBACK;
+	cfg_parser->default_zone_options->notify_retry = 5;
+
 	in = fopen(cfg_parser->filename, "r");
 	if(!in) {
 		fprintf(stderr, "Could not open %s: %s\n", file, strerror(errno));
@@ -111,17 +137,8 @@
 	c_parse();
 	fclose(in);
 
-	if(cfg_parser->current_zone) {
-		if(!cfg_parser->current_zone->name)
-			c_error("last zone has no name");
-		else {
-			if(!nsd_options_insert_zone(opt,
-				cfg_parser->current_zone))
-				c_error("duplicate zone");
-		}
-		if(!cfg_parser->current_zone->zonefile)
-			c_error("last zone has no zonefile");
-	}
+	cfg_parser_insert_current_zone();
+
 	if(opt->keys)
 	{
 		if(!opt->keys->name)
@@ -131,14 +148,72 @@
 		if(!opt->keys->secret)
 			c_error("last key has no secret blob");
 	}
+
+	/* lookup keys for default acls */
+	for (acl=cfg_parser->default_zone_options->allow_notify; acl; acl=acl->next)
+	{
+		if(acl->nokey || acl->blocked)
+			continue;
+		acl->key_options = key_options_find(opt, acl->key_name);
+		if(!acl->key_options)
+			c_error_msg("key %s in default allow-notify could not be found",
+				acl->key_name, zone->name);
+	}
+	for (acl=cfg_parser->default_zone_options->notify; acl; acl=acl->next)
+	{
+		if(acl->nokey || acl->blocked)
+			continue;
+		acl->key_options = key_options_find(opt, acl->key_name);
+		if(!acl->key_options)
+			c_error_msg("key %s in default notify could not be found",
+				acl->key_name);
+	}
+	for (acl=cfg_parser->default_zone_options->request_xfr; acl; acl=acl->next)
+	{
+		if(acl->nokey || acl->blocked)
+			continue;
+		acl->key_options = key_options_find(opt, acl->key_name);
+		if(!acl->key_options)
+			c_error_msg("key %s in default request-xfr could not be found",
+				acl->key_name);
+	}
+	for (acl=cfg_parser->default_zone_options->provide_xfr; acl; acl=acl->next)
+	{
+		if(acl->nokey || acl->blocked)
+			continue;
+		acl->key_options = key_options_find(opt, acl->key_name);
+		if(!acl->key_options)
+			c_error_msg("key %s in default provide-xfr could not be found",
+				acl->key_name);
+	}
+
 	RBTREE_FOR(zone, zone_options_t*, opt->zone_options)
 	{
 		if(!zone->name)
 			continue;
 		if(!zone->zonefile)
 			continue;
-		/* lookup keys for acls */
-		for(acl=zone->allow_notify; acl; acl=acl->next)
+
+		/* set default allow_axfr_fallback and notify_retry */
+		if (zone->allow_axfr_fallback == ALLOW_AXFR_FALLBACK_UNSET)
+			zone->allow_axfr_fallback = cfg_parser->default_zone_options->allow_axfr_fallback;
+		if (zone->notify_retry == NOTIFY_RETRY_UNSET)
+			zone->notify_retry = cfg_parser->default_zone_options->notify_retry;
+
+		/* append default outgoing interfaces, if any */
+		if (cfg_parser->default_zone_options->outgoing_interface) {
+			if (zone->outgoing_interface) {
+				prev_acl=zone->outgoing_interface;
+				while (prev_acl->next)
+					prev_acl = prev_acl->next;
+				prev_acl->next = cfg_parser->default_zone_options->outgoing_interface;
+			}
+			else
+				zone->outgoing_interface = cfg_parser->default_zone_options->outgoing_interface;
+		}
+
+		/* lookup keys for acls and append global acls */
+		for(acl=zone->allow_notify, prev_acl=0; acl; prev_acl=acl, acl=acl->next)
 		{
 			if(acl->nokey || acl->blocked)
 				continue;
@@ -147,7 +222,13 @@
 				c_error_msg("key %s in zone %s could not be found",
 					acl->key_name, zone->name);
 		}
-		for(acl=zone->notify; acl; acl=acl->next)
+		if (cfg_parser->default_zone_options->allow_notify) {
+			if (!prev_acl)
+				zone->allow_notify = cfg_parser->default_zone_options->allow_notify;
+			else
+				prev_acl->next = cfg_parser->default_zone_options->allow_notify;
+		}
+		for(acl=zone->notify, prev_acl=0; acl; prev_acl=acl, acl=acl->next)
 		{
 			if(acl->nokey || acl->blocked)
 				continue;
@@ -156,7 +237,13 @@
 				c_error_msg("key %s in zone %s could not be found",
 					acl->key_name, zone->name);
 		}
-		for(acl=zone->request_xfr; acl; acl=acl->next)
+		if (cfg_parser->default_zone_options->notify) {
+			if (!prev_acl)
+				zone->notify = cfg_parser->default_zone_options->notify;
+			else
+				prev_acl->next = cfg_parser->default_zone_options->notify;
+		}
+		for(acl=zone->request_xfr, prev_acl=0; acl; prev_acl=acl, acl=acl->next)
 		{
 			if(acl->nokey || acl->blocked)
 				continue;
@@ -165,7 +252,13 @@
 				c_error_msg("key %s in zone %s could not be found",
 					acl->key_name, zone->name);
 		}
-		for(acl=zone->provide_xfr; acl; acl=acl->next)
+		if (cfg_parser->default_zone_options->request_xfr) {
+			if (!prev_acl)
+				zone->request_xfr = cfg_parser->default_zone_options->request_xfr;
+			else
+				prev_acl->next = cfg_parser->default_zone_options->request_xfr;
+		}
+		for(acl=zone->provide_xfr, prev_acl=0; acl; prev_acl=acl, acl=acl->next)
 		{
 			if(acl->nokey || acl->blocked)
 				continue;
@@ -174,6 +267,12 @@
 				c_error_msg("key %s in zone %s could not be found",
 					acl->key_name, zone->name);
 		}
+		if (cfg_parser->default_zone_options->provide_xfr) {
+			if (!prev_acl)
+				zone->provide_xfr = cfg_parser->default_zone_options->provide_xfr;
+			else
+				prev_acl->next = cfg_parser->default_zone_options->provide_xfr;
+		}
 	}
 
 	if(cfg_parser->errors > 0)
@@ -225,10 +324,13 @@
 	zone->allow_notify = 0;
 	zone->request_xfr = 0;
 	zone->notify = 0;
-	zone->notify_retry = 5;
 	zone->provide_xfr = 0;
 	zone->outgoing_interface = 0;
-	zone->allow_axfr_fallback = 1;
+
+	/* default values of these settings are assigned from default_zone_options in parse_options_file() */
+	zone->notify_retry = NOTIFY_RETRY_UNSET;
+	zone->allow_axfr_fallback = ALLOW_AXFR_FALLBACK_UNSET;
+
 	return zone;
 }
 
diff -urN nsd-3.2.5/options.h nsd-3.2.5-new/options.h
--- nsd-3.2.5/options.h	2010-04-22 14:26:48.000000000 +0200
+++ nsd-3.2.5-new/options.h	2010-04-22 14:29:03.000000000 +0200
@@ -91,6 +91,12 @@
 	uint8_t notify_retry;
 };
 
+#define DISALLOW_AXFR_FALLBACK		0
+#define ALLOW_AXFR_FALLBACK		1
+#define ALLOW_AXFR_FALLBACK_UNSET	2
+
+#define NOTIFY_RETRY_UNSET		255
+
 union acl_addr_storage {
 #ifdef INET6
 	struct in_addr addr;
@@ -152,6 +158,7 @@
 	int line;
 	int errors;
 	nsd_options_t* opt;
+	zone_options_t* default_zone_options;
 	zone_options_t* current_zone;
 	key_options_t* current_key;
 	ip_address_option_t* current_ip_address_option;
