summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbrad <brad@openbsd.org>2014-12-18 23:26:12 +0000
committerbrad <brad@openbsd.org>2014-12-18 23:26:12 +0000
commit03739794338fecca6d43568785393dd5cbab400f (patch)
tree7d56bc6cbc0ab8a7122626d4bfa07d310441a5ab
parentan hex -> a hex; (diff)
downloadwireguard-openbsd-03739794338fecca6d43568785393dd5cbab400f.tar.xz
wireguard-openbsd-03739794338fecca6d43568785393dd5cbab400f.zip
Merge in some commits from upstream..
- Fix that failure to add tcp to tcp base does not leak the socket. - Fixes for wildcard addition and deletion, speedup for some cases. - Fix that queries for noname CH TXT are REFUSED instead of nodata. - Fix #616: retry xfer for zones with no content after command. - Fix that expired zones stay expired after a server restart. - RFC 7344: CDS and CDNSKEY (read in). ok sthen@
-rw-r--r--usr.sbin/nsd/difffile.c20
-rw-r--r--usr.sbin/nsd/dns.c11
-rw-r--r--usr.sbin/nsd/dns.h2
-rw-r--r--usr.sbin/nsd/namedb.c22
-rw-r--r--usr.sbin/nsd/namedb.h1
-rw-r--r--usr.sbin/nsd/nsd-control.8.in4
-rw-r--r--usr.sbin/nsd/query.c2
-rw-r--r--usr.sbin/nsd/remote.c10
-rw-r--r--usr.sbin/nsd/server.c14
-rw-r--r--usr.sbin/nsd/xfrd-disk.c4
-rw-r--r--usr.sbin/nsd/xfrd.c9
-rw-r--r--usr.sbin/nsd/xfrd.h3
-rw-r--r--usr.sbin/nsd/zparser.y6
13 files changed, 87 insertions, 21 deletions
diff --git a/usr.sbin/nsd/difffile.c b/usr.sbin/nsd/difffile.c
index 5510714f364..c9c8026369e 100644
--- a/usr.sbin/nsd/difffile.c
+++ b/usr.sbin/nsd/difffile.c
@@ -236,8 +236,8 @@ has_data_below(domain_type* top)
}
/** check if domain with 0 rrsets has become empty (nonexist) */
-static void
-rrset_zero_nonexist_check(domain_type* domain)
+static domain_type*
+rrset_zero_nonexist_check(domain_type* domain, domain_type* ce)
{
/* is the node now an empty node (completely deleted) */
if(domain->rrsets == 0) {
@@ -248,13 +248,18 @@ rrset_zero_nonexist_check(domain_type* domain)
/* nonexist this domain and all parent empty nonterminals */
domain_type* p = domain;
while(p != NULL && p->rrsets == 0) {
- if(has_data_below(p))
- break;
+ if(p == ce || has_data_below(p))
+ return p;
p->is_existing = 0;
+ /* fixup wildcard child of parent */
+ if(p->parent &&
+ p->parent->wildcard_child_closest_match == p)
+ p->parent->wildcard_child_closest_match = domain_previous_existing_child(p);
p = p->parent;
}
}
}
+ return NULL;
}
/** remove rrset. Adjusts zone params. Does not remove domain */
@@ -682,7 +687,7 @@ delete_RR(namedb_type* db, const dname_type* dname,
/* delete entire rrset */
rrset_delete(db, domain, rrset);
/* check if domain is now nonexisting (or parents) */
- rrset_zero_nonexist_check(domain);
+ rrset_zero_nonexist_check(domain, NULL);
#ifdef NSEC3
/* cleanup nsec3 */
nsec3_delete_rrset_trigger(db, domain, zone, type);
@@ -914,9 +919,10 @@ delete_zone_rrs(namedb_type* db, zone_type* zone)
domain = next;
}
- /* check if data deleteions have created nonexisting domain entries,
+ /* check if data deletions have created nonexisting domain entries,
* but after deleting domains so the checks are faster */
if(nonexist_check) {
+ domain_type* ce = NULL; /* for speeding up has_data_below */
DEBUG(DEBUG_XFRD, 1, (LOG_INFO, "axfrdel: zero rrset check"));
domain = zone->apex;
while(domain && domain_is_subdomain(domain, zone->apex))
@@ -926,7 +932,7 @@ delete_zone_rrs(namedb_type* db, zone_type* zone)
* sub-zones, since we only spuriously check empty
* nonterminals */
if(domain->is_existing)
- rrset_zero_nonexist_check(domain);
+ ce = rrset_zero_nonexist_check(domain, ce);
domain = domain_next(domain);
}
}
diff --git a/usr.sbin/nsd/dns.c b/usr.sbin/nsd/dns.c
index a54fc9871c0..5d80f8a11ba 100644
--- a/usr.sbin/nsd/dns.c
+++ b/usr.sbin/nsd/dns.c
@@ -289,9 +289,14 @@ static rrtype_descriptor_type rrtype_descriptors[(RRTYPE_DESCRIPTORS_LENGTH+1)]
/* 58 - TALINK */
{ 58, NULL, T_UTYPE, 1, 1, { RDATA_WF_BINARY }, { RDATA_ZF_UNKNOWN } },
/* 59 - CDS */
- { 59, NULL, T_UTYPE, 1, 1, { RDATA_WF_BINARY }, { RDATA_ZF_UNKNOWN } },
- /* 60 */
- { 60, NULL, T_UTYPE, 1, 1, { RDATA_WF_BINARY }, { RDATA_ZF_UNKNOWN } },
+ { TYPE_CDS, "CDS", T_CDS, 4, 4,
+ { RDATA_WF_SHORT, RDATA_WF_BYTE, RDATA_WF_BYTE, RDATA_WF_BINARY },
+ { RDATA_ZF_SHORT, RDATA_ZF_ALGORITHM, RDATA_ZF_BYTE, RDATA_ZF_HEX } },
+ /* 60 - CDNSKEY */
+ { TYPE_CDNSKEY, "CDNSKEY", T_CDNSKEY, 4, 4,
+ { RDATA_WF_SHORT, RDATA_WF_BYTE, RDATA_WF_BYTE, RDATA_WF_BINARY },
+ { RDATA_ZF_SHORT, RDATA_ZF_BYTE, RDATA_ZF_ALGORITHM,
+ RDATA_ZF_BASE64 } },
/* 61 */
{ 61, NULL, T_UTYPE, 1, 1, { RDATA_WF_BINARY }, { RDATA_ZF_UNKNOWN } },
/* 62 */
diff --git a/usr.sbin/nsd/dns.h b/usr.sbin/nsd/dns.h
index 2b0734764ec..077f00d2f27 100644
--- a/usr.sbin/nsd/dns.h
+++ b/usr.sbin/nsd/dns.h
@@ -136,6 +136,8 @@ typedef enum nsd_rc nsd_rc_type;
#define TYPE_NSEC3 50 /* NSEC3, secure denial, prevents zonewalking */
#define TYPE_NSEC3PARAM 51 /* NSEC3PARAM at zone apex nsec3 parameters */
#define TYPE_TLSA 52 /* RFC 6698 */
+#define TYPE_CDS 59 /* RFC 7344 */
+#define TYPE_CDNSKEY 60 /* RFC 7344 */
#define TYPE_SPF 99 /* RFC 4408 */
diff --git a/usr.sbin/nsd/namedb.c b/usr.sbin/nsd/namedb.c
index 4fb23671550..b30e96b01c7 100644
--- a/usr.sbin/nsd/namedb.c
+++ b/usr.sbin/nsd/namedb.c
@@ -249,7 +249,7 @@ do_deldomain(namedb_type* db, domain_type* domain)
* one-smaller than this domain as closest-match. */
if(domain->parent->wildcard_child_closest_match == domain)
domain->parent->wildcard_child_closest_match =
- domain_previous(domain);
+ domain_previous_existing_child(domain);
/* actual removal */
radix_delete(db->domains->nametree, domain->rnode);
@@ -456,6 +456,17 @@ domain_table_iterate(domain_table_type* table,
return error;
}
+domain_type *domain_previous_existing_child(domain_type* domain)
+{
+ domain_type* parent = domain->parent;
+ domain = domain_previous(domain);
+ while(domain && !domain->is_existing) {
+ if(domain == parent) /* do not walk back above parent */
+ return parent;
+ domain = domain_previous(domain);
+ }
+ return domain;
+}
void
domain_add_rrset(domain_type* domain, rrset_type* rrset)
@@ -474,6 +485,15 @@ domain_add_rrset(domain_type* domain, rrset_type* rrset)
while (domain && !domain->is_existing) {
domain->is_existing = 1;
+ /* does this name in existance update the parent's
+ * wildcard closest match? */
+ if(domain->parent
+ && label_compare(dname_name(domain_dname(domain)),
+ (const uint8_t *) "\001*") <= 0
+ && dname_compare(domain_dname(domain),
+ domain_dname(domain->parent->wildcard_child_closest_match)) > 0) {
+ domain->parent->wildcard_child_closest_match = domain;
+ }
domain = domain->parent;
}
}
diff --git a/usr.sbin/nsd/namedb.h b/usr.sbin/nsd/namedb.h
index 76f78dfa648..34cf9e288bd 100644
--- a/usr.sbin/nsd/namedb.h
+++ b/usr.sbin/nsd/namedb.h
@@ -250,6 +250,7 @@ int domain_is_glue(domain_type* domain, zone_type* zone);
rrset_type* domain_find_non_cname_rrset(domain_type* domain, zone_type* zone);
domain_type* domain_wildcard_child(domain_type* domain);
+domain_type *domain_previous_existing_child(domain_type* domain);
int zone_is_secure(zone_type* zone);
diff --git a/usr.sbin/nsd/nsd-control.8.in b/usr.sbin/nsd/nsd-control.8.in
index 2ee2e4c8d0a..f5aa2cbe4e4 100644
--- a/usr.sbin/nsd/nsd-control.8.in
+++ b/usr.sbin/nsd/nsd-control.8.in
@@ -108,7 +108,9 @@ Attempt to update slave zones that are hosted on this server by contacting
the masters. The masters are configured via 'request\-xfr:' lists.
If a zone is given, that zone is updated. Usually NSD receives a NOTIFY
from the masters (configured via 'allow\-notify:' acl list) that a new zone
-serial has to be transferred.
+serial has to be transferred. For zones with no content, NSD may have backed
+off from asking often because the masters did not respond, but this command
+will reset the backoff to its initial timeout, for frequent retries.
.TP
.B force_transfer [<zone>]
Force update slave zones that are hosted on this server. Even if the
diff --git a/usr.sbin/nsd/query.c b/usr.sbin/nsd/query.c
index d5afe789cf0..f8cb1b496c0 100644
--- a/usr.sbin/nsd/query.c
+++ b/usr.sbin/nsd/query.c
@@ -528,6 +528,8 @@ answer_chaos(struct nsd *nsd, query_type *q)
} else {
RCODE_SET(q->packet, RCODE_REFUSE);
}
+ } else {
+ RCODE_SET(q->packet, RCODE_REFUSE);
}
break;
default:
diff --git a/usr.sbin/nsd/remote.c b/usr.sbin/nsd/remote.c
index 759136c9645..82b49990216 100644
--- a/usr.sbin/nsd/remote.c
+++ b/usr.sbin/nsd/remote.c
@@ -567,10 +567,16 @@ remote_accept_callback(int fd, short event, void* arg)
event_set(&n->c, newfd, EV_PERSIST|EV_TIMEOUT|EV_READ,
remote_control_callback, n);
- if(event_base_set(xfrd->event_base, &n->c) != 0)
+ if(event_base_set(xfrd->event_base, &n->c) != 0) {
log_msg(LOG_ERR, "remote_accept: cannot set event_base");
- if(event_add(&n->c, &n->tval) != 0)
+ free(n);
+ goto close_exit;
+ }
+ if(event_add(&n->c, &n->tval) != 0) {
log_msg(LOG_ERR, "remote_accept: cannot add event");
+ free(n);
+ goto close_exit;
+ }
n->event_added = 1;
if(2 <= verbosity) {
diff --git a/usr.sbin/nsd/server.c b/usr.sbin/nsd/server.c
index 22cfff7897c..0c8ca29c754 100644
--- a/usr.sbin/nsd/server.c
+++ b/usr.sbin/nsd/server.c
@@ -2522,10 +2522,18 @@ handle_tcp_accept(int fd, short event, void* arg)
event_set(&tcp_data->event, s, EV_PERSIST | EV_READ | EV_TIMEOUT,
handle_tcp_reading, tcp_data);
- if(event_base_set(data->event.ev_base, &tcp_data->event) != 0)
- log_msg(LOG_ERR, "cannot set tcp event base");
- if(event_add(&tcp_data->event, &timeout) != 0)
+ if(event_base_set(data->event.ev_base, &tcp_data->event) != 0) {
log_msg(LOG_ERR, "cannot set tcp event base");
+ close(s);
+ region_destroy(tcp_region);
+ return;
+ }
+ if(event_add(&tcp_data->event, &timeout) != 0) {
+ log_msg(LOG_ERR, "cannot add tcp to event base");
+ close(s);
+ region_destroy(tcp_region);
+ return;
+ }
/*
* Keep track of the total number of TCP handlers installed so
diff --git a/usr.sbin/nsd/xfrd-disk.c b/usr.sbin/nsd/xfrd-disk.c
index a095bbfacf9..a2f3e8af01d 100644
--- a/usr.sbin/nsd/xfrd-disk.c
+++ b/usr.sbin/nsd/xfrd-disk.c
@@ -308,6 +308,10 @@ xfrd_read_state(struct xfrd_state* xfrd)
* contents trumps the contents of this cache */
/* zone->soa_disk_acquired = soa_disk_acquired_read; */
zone->soa_notified_acquired = soa_notified_acquired_read;
+ if (zone->state == xfrd_zone_expired)
+ {
+ xfrd_send_expire_notification(zone);
+ }
xfrd_handle_incoming_soa(zone, &incoming_soa, incoming_acquired);
}
diff --git a/usr.sbin/nsd/xfrd.c b/usr.sbin/nsd/xfrd.c
index 0ea9ea651d3..54b9650d458 100644
--- a/usr.sbin/nsd/xfrd.c
+++ b/usr.sbin/nsd/xfrd.c
@@ -76,8 +76,6 @@ static void xfrd_handle_reload(int fd, short event, void* arg);
/* handle child timeout */
static void xfrd_handle_child_timer(int fd, short event, void* arg);
-/* send expiry notifications to nsd */
-static void xfrd_send_expire_notification(xfrd_zone_t* zone);
/* send ixfr request, returns fd of connection to read on */
static int xfrd_send_ixfr_request_udp(xfrd_zone_t* zone);
/* obtain udp socket slot */
@@ -1147,7 +1145,7 @@ xfrd_handle_incoming_soa(xfrd_zone_t* zone,
xfrd_send_notify(xfrd->notify_zones, zone->apex, &zone->soa_nsd);
}
-static void
+void
xfrd_send_expire_notification(xfrd_zone_t* zone)
{
task_new_expire(xfrd->nsd->task[xfrd->nsd->mytask], xfrd->last_task,
@@ -2087,6 +2085,11 @@ xfrd_handle_notify_and_start_xfr(xfrd_zone_t* zone, xfrd_soa_t* soa)
!zone->tcp_waiting && !zone->udp_waiting) {
xfrd_set_refresh_now(zone);
}
+ /* zones with no content start expbackoff again; this is also
+ * for nsd-control started transfer commands, and also when
+ * the master apparantly sends notifies (is back up) */
+ if(zone->soa_disk_acquired == 0)
+ zone->fresh_xfr_timeout = XFRD_TRANSFER_TIMEOUT_START;
}
}
diff --git a/usr.sbin/nsd/xfrd.h b/usr.sbin/nsd/xfrd.h
index 5c731f6c085..e29a0d52e97 100644
--- a/usr.sbin/nsd/xfrd.h
+++ b/usr.sbin/nsd/xfrd.h
@@ -342,6 +342,9 @@ void xfrd_process_task_result(xfrd_state_t* xfrd, struct udb_base* taskudb);
/* set to reload right away (for user controlled reload events) */
void xfrd_set_reload_now(xfrd_state_t* xfrd);
+/* send expiry notifications to nsd */
+void xfrd_send_expire_notification(xfrd_zone_t* zone);
+
/* handle incoming notify (soa or NULL) and start zone xfr if necessary */
void xfrd_handle_notify_and_start_xfr(xfrd_zone_t* zone, xfrd_soa_t* soa);
diff --git a/usr.sbin/nsd/zparser.y b/usr.sbin/nsd/zparser.y
index 4855784f7e2..f916a74d936 100644
--- a/usr.sbin/nsd/zparser.y
+++ b/usr.sbin/nsd/zparser.y
@@ -67,7 +67,7 @@ nsec3_add_params(const char* hash_algo_str, const char* flag_str,
%token <type> T_OPT T_APL T_UINFO T_UID T_GID T_UNSPEC T_TKEY T_TSIG T_IXFR
%token <type> T_AXFR T_MAILB T_MAILA T_DS T_DLV T_SSHFP T_RRSIG T_NSEC T_DNSKEY
%token <type> T_SPF T_NSEC3 T_IPSECKEY T_DHCID T_NSEC3PARAM T_TLSA
-%token <type> T_NID T_L32 T_L64 T_LP T_EUI48 T_EUI64 T_CAA
+%token <type> T_NID T_L32 T_L64 T_LP T_EUI48 T_EUI64 T_CAA T_CDS T_CDNSKEY
/* other tokens */
%token DOLLAR_TTL DOLLAR_ORIGIN NL SP
@@ -612,6 +612,10 @@ type_and_rdata:
| T_EUI64 sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
| T_CAA sp rdata_caa
| T_CAA sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
+ | T_CDS sp rdata_ds
+ | T_CDS sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
+ | T_CDNSKEY sp rdata_dnskey
+ | T_CDNSKEY sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
| T_UTYPE sp rdata_unknown { $$ = $1; parse_unknown_rdata($1, $3); }
| STR error NL
{