- 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@
}
/** 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) {
/* 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 */
/* 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);
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))
* 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);
}
}
/* 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 */
#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 */
* 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);
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)
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;
}
}
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);
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
} else {
RCODE_SET(q->packet, RCODE_REFUSE);
}
+ } else {
+ RCODE_SET(q->packet, RCODE_REFUSE);
}
break;
default:
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) {
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
* 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);
}
/* 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 */
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,
!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;
}
}
/* 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);
%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
| 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
{