diff options
| author | Xin LI <delphij@FreeBSD.org> | 2015-04-08 17:52:54 +0000 |
|---|---|---|
| committer | Xin LI <delphij@FreeBSD.org> | 2015-04-08 17:52:54 +0000 |
| commit | 7ba7a5de74780dee4ec54bace1ec36427be1d8b8 (patch) | |
| tree | a5a1890b0b884a1d303e90c4130c3b731772abd5 /lib/dns | |
| parent | a2bc50f814b6966b412ba90221460066a8b31951 (diff) | |
Vendor import of BIND 9.9.7vendor/bind9/9.9.7
Diffstat (limited to 'lib/dns')
45 files changed, 1077 insertions, 352 deletions
diff --git a/lib/dns/adb.c b/lib/dns/adb.c index c75ea59f751f..da77bb6c92a5 100644 --- a/lib/dns/adb.c +++ b/lib/dns/adb.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -1768,12 +1768,12 @@ new_adbentry(dns_adb_t *adb) { ISC_LINK_INIT(e, plink); LOCK(&adb->entriescntlock); adb->entriescnt++; - if (!adb->growentries_sent && adb->growentries_sent && + if (!adb->growentries_sent && adb->excl != NULL && adb->entriescnt > (adb->nentries * 8)) { isc_event_t *event = &adb->growentries; inc_adb_irefcnt(adb); - isc_task_send(adb->task, &event); + isc_task_send(adb->excl, &event); adb->growentries_sent = ISC_TRUE; } UNLOCK(&adb->entriescntlock); @@ -3805,11 +3805,11 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) { goto out; /* XXXMLG Don't pound on bad servers. */ if (address_type == DNS_ADBFIND_INET) { - name->expire_v4 = ISC_MIN(name->expire_v4, now + 300); + name->expire_v4 = ISC_MIN(name->expire_v4, now + 10); name->fetch_err = FIND_ERR_FAILURE; inc_stats(adb, dns_resstatscounter_gluefetchv4fail); } else { - name->expire_v6 = ISC_MIN(name->expire_v6, now + 300); + name->expire_v6 = ISC_MIN(name->expire_v6, now + 10); name->fetch6_err = FIND_ERR_FAILURE; inc_stats(adb, dns_resstatscounter_gluefetchv6fail); } diff --git a/lib/dns/api b/lib/dns/api index b11beb8343db..83640ba56b2e 100644 --- a/lib/dns/api +++ b/lib/dns/api @@ -4,6 +4,6 @@ # 9.8: 80-89, 120-129 # 9.9: 90-109 # 9.9-sub: 130-139 -LIBINTERFACE = 105 +LIBINTERFACE = 107 LIBREVISION = 0 LIBAGE = 1 diff --git a/lib/dns/diff.c b/lib/dns/diff.c index 4517dade38dc..b6d4152999f8 100644 --- a/lib/dns/diff.c +++ b/lib/dns/diff.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007-2009, 2011, 2013, 2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007-2009, 2011, 2013-2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -390,9 +390,6 @@ diff_apply(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *ver, * Issue a warning and continue. */ if (warn) { - char classbuf[DNS_RDATATYPE_FORMATSIZE]; - char namebuf[DNS_NAME_FORMATSIZE]; - dns_name_format(dns_db_origin(db), namebuf, sizeof(namebuf)); diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index 129895431ddf..1c113eccb235 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011-2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -3038,6 +3038,8 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, if (result != ISC_R_SUCCESS) return (result); + disp->socktype = isc_sockettype_udp; + if ((attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0) { result = get_udpsocket(mgr, disp, sockmgr, localaddr, &sock, dup_socket); @@ -3087,7 +3089,6 @@ dispatch_createudp(dns_dispatchmgr_t *mgr, isc_socketmgr_t *sockmgr, isc_mempool_setname(disp->portpool, "disp_portpool"); isc_mempool_setfreemax(disp->portpool, 128); } - disp->socktype = isc_sockettype_udp; disp->socket = sock; disp->local = *localaddr; @@ -3233,6 +3234,17 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest, dns_messageid_t *idp, dns_dispentry_t **resp, isc_socketmgr_t *sockmgr) { + return (dns_dispatch_addresponse3(disp, 0, dest, task, action, arg, + idp, resp, sockmgr)); +} + +isc_result_t +dns_dispatch_addresponse3(dns_dispatch_t *disp, unsigned int options, + isc_sockaddr_t *dest, isc_task_t *task, + isc_taskaction_t action, void *arg, + dns_messageid_t *idp, dns_dispentry_t **resp, + isc_socketmgr_t *sockmgr) +{ dns_dispentry_t *res; unsigned int bucket; in_port_t localport = 0; @@ -3320,10 +3332,14 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest, } /* - * Try somewhat hard to find an unique ID. + * Try somewhat hard to find an unique ID unless FIXEDID is set + * in which case we use the id passed in via *idp. */ LOCK(&qid->lock); - id = (dns_messageid_t)dispatch_random(DISP_ARC4CTX(disp)); + if ((options & DNS_DISPATCHOPT_FIXEDID) != 0) + id = *idp; + else + id = (dns_messageid_t)dispatch_random(DISP_ARC4CTX(disp)); ok = ISC_FALSE; i = 0; do { @@ -3332,6 +3348,8 @@ dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest, ok = ISC_TRUE; break; } + if ((disp->attributes & DNS_DISPATCHATTR_FIXEDID) != 0) + break; id += qid->qid_increment; id &= 0x0000ffff; } while (i++ < 64); @@ -3419,7 +3437,7 @@ dns_dispatch_addresponse(dns_dispatch_t *disp, isc_sockaddr_t *dest, REQUIRE(VALID_DISPATCH(disp)); REQUIRE((disp->attributes & DNS_DISPATCHATTR_EXCLUSIVE) == 0); - return (dns_dispatch_addresponse2(disp, dest, task, action, arg, + return (dns_dispatch_addresponse3(disp, 0, dest, task, action, arg, idp, resp, NULL)); } diff --git a/lib/dns/gen.c b/lib/dns/gen.c index ff41de6d624a..7a7dafb46100 100644 --- a/lib/dns/gen.c +++ b/lib/dns/gen.c @@ -23,10 +23,12 @@ */ #define _CRT_SECURE_NO_DEPRECATE 1 /* - * We use snprintf. + * We use snprintf which was defined late in Windows even it is in C99. */ +#if _MSC_VER < 1900 #define snprintf _snprintf #endif +#endif #include <sys/types.h> diff --git a/lib/dns/include/dns/dispatch.h b/lib/dns/include/dns/dispatch.h index 1235f7ca40f3..f9e45db3b179 100644 --- a/lib/dns/include/dns/dispatch.h +++ b/lib/dns/include/dns/dispatch.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011, 2012, 2014 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -143,10 +143,14 @@ struct dns_dispatchset { #define DNS_DISPATCHATTR_NOLISTEN 0x00000020U #define DNS_DISPATCHATTR_MAKEQUERY 0x00000040U #define DNS_DISPATCHATTR_CONNECTED 0x00000080U -/*#define DNS_DISPATCHATTR_RANDOMPORT 0x00000100U*/ +#define DNS_DISPATCHATTR_FIXEDID 0x00000100U #define DNS_DISPATCHATTR_EXCLUSIVE 0x00000200U /*@}*/ +/* + */ +#define DNS_DISPATCHOPT_FIXEDID 0x00000001U + isc_result_t dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy, dns_dispatchmgr_t **mgrp); @@ -370,6 +374,13 @@ dns_dispatch_starttcp(dns_dispatch_t *disp); */ isc_result_t +dns_dispatch_addresponse3(dns_dispatch_t *disp, unsigned int options, + isc_sockaddr_t *dest, isc_task_t *task, + isc_taskaction_t action, void *arg, + isc_uint16_t *idp, dns_dispentry_t **resp, + isc_socketmgr_t *sockmgr); + +isc_result_t dns_dispatch_addresponse2(dns_dispatch_t *disp, isc_sockaddr_t *dest, isc_task_t *task, isc_taskaction_t action, void *arg, isc_uint16_t *idp, dns_dispentry_t **resp, diff --git a/lib/dns/include/dns/log.h b/lib/dns/include/dns/log.h index e8c8c105473e..488b48e33de2 100644 --- a/lib/dns/include/dns/log.h +++ b/lib/dns/include/dns/log.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -44,6 +44,7 @@ LIBDNS_EXTERNAL_DATA extern isc_logmodule_t dns_modules[]; #define DNS_LOGCATEGORY_EDNS_DISABLED (&dns_categories[11]) #define DNS_LOGCATEGORY_RPZ (&dns_categories[12]) #define DNS_LOGCATEGORY_RRL (&dns_categories[13]) +#define DNS_LOGCATEGORY_CNAME (&dns_categories[14]) /* Backwards compatibility. */ #define DNS_LOGCATEGORY_GENERAL ISC_LOGCATEGORY_GENERAL diff --git a/lib/dns/include/dns/rbt.h b/lib/dns/include/dns/rbt.h index 8b382b5ed6be..947e7c177a47 100644 --- a/lib/dns/include/dns/rbt.h +++ b/lib/dns/include/dns/rbt.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2014, 2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -115,6 +115,9 @@ struct dns_rbtnode { unsigned int oldnamelen : 8; /*%< range is 1..255 */ /*@}*/ + /* node needs to be cleaned from rpz */ + unsigned int rpz : 1; + #ifdef DNS_RBT_USEHASH unsigned int hashval; #endif diff --git a/lib/dns/include/dns/request.h b/lib/dns/include/dns/request.h index 8c792ddd5774..f5ec69614aec 100644 --- a/lib/dns/include/dns/request.h +++ b/lib/dns/include/dns/request.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009, 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2010, 2014 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -48,6 +48,7 @@ #define DNS_REQUESTOPT_TCP 0x00000001U #define DNS_REQUESTOPT_CASE 0x00000002U +#define DNS_REQUESTOPT_FIXEDID 0x00000004U typedef struct dns_requestevent { ISC_EVENT_COMMON(struct dns_requestevent); diff --git a/lib/dns/journal.c b/lib/dns/journal.c index 2d0b3f5f7494..a21ec2e8a348 100644 --- a/lib/dns/journal.c +++ b/lib/dns/journal.c @@ -1391,6 +1391,8 @@ roll_forward(dns_journal_t *j, dns_db_t *db, unsigned int options) { dns_diff_clear(&diff); + INSIST(ver == NULL); + return (result); } diff --git a/lib/dns/keytable.c b/lib/dns/keytable.c index 56fefcd2c122..29f129ffbf5f 100644 --- a/lib/dns/keytable.c +++ b/lib/dns/keytable.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009, 2010, 2013, 2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2010, 2013-2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -275,16 +275,17 @@ dns_keytable_deletekeynode(dns_keytable_t *keytable, dst_key_t *dstkey) { } knode = node->data; - if (knode->next == NULL && - (knode->key == NULL || - dst_key_compare(knode->key, dstkey) == ISC_TRUE)) { + if (knode->next == NULL && knode->key != NULL && + dst_key_compare(knode->key, dstkey) == ISC_TRUE) + { result = dns_rbt_deletenode(keytable->table, node, ISC_FALSE); goto finish; } kprev = (dns_keynode_t **) &node->data; while (knode != NULL) { - if (dst_key_compare(knode->key, dstkey) == ISC_TRUE) + if (knode->key != NULL && + dst_key_compare(knode->key, dstkey) == ISC_TRUE) break; kprev = &knode->next; knode = knode->next; diff --git a/lib/dns/log.c b/lib/dns/log.c index 75e0d79ba34b..70055aaf887b 100644 --- a/lib/dns/log.c +++ b/lib/dns/log.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -46,6 +46,7 @@ LIBDNS_EXTERNAL_DATA isc_logcategory_t dns_categories[] = { { "edns-disabled", 0 }, { "rpz", 0 }, { "rate-limit", 0 }, + { "cname", 0 }, { NULL, 0 } }; diff --git a/lib/dns/master.c b/lib/dns/master.c index dcea97a0bdd4..1fde70c3b6ec 100644 --- a/lib/dns/master.c +++ b/lib/dns/master.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011-2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -209,7 +209,7 @@ task_send(dns_loadctx_t *lctx); static void loadctx_destroy(dns_loadctx_t *lctx); -#define GETTOKEN(lexer, options, token, eol) \ +#define GETTOKENERR(lexer, options, token, eol, err) \ do { \ result = gettoken(lexer, options, token, eol, callbacks); \ switch (result) { \ @@ -222,6 +222,7 @@ loadctx_destroy(dns_loadctx_t *lctx); SETRESULT(lctx, result); \ LOGIT(result); \ read_till_eol = ISC_TRUE; \ + err \ goto next_line; \ } else \ goto log_and_cleanup; \ @@ -237,6 +238,8 @@ loadctx_destroy(dns_loadctx_t *lctx); goto log_and_cleanup; \ } \ } while (0) +#define GETTOKEN(lexer, options, token, eol) \ + GETTOKENERR(lexer, options, token, eol, {} ) #define COMMITALL \ do { \ @@ -377,13 +380,19 @@ gettoken(isc_lex_t *lex, unsigned int options, isc_token_t *token, if (eol != ISC_TRUE) if (token->type == isc_tokentype_eol || token->type == isc_tokentype_eof) { + unsigned long int line; + const char *what; + const char *file; + file = isc_lex_getsourcename(lex); + line = isc_lex_getsourceline(lex); + if (token->type == isc_tokentype_eol) { + line--; + what = "line"; + } else + what = "file"; (*callbacks->error)(callbacks, "dns_master_load: %s:%lu: unexpected end of %s", - isc_lex_getsourcename(lex), - isc_lex_getsourceline(lex), - (token->type == - isc_tokentype_eol) ? - "line" : "file"); + file, line, what); return (ISC_R_UNEXPECTEDEND); } return (ISC_R_SUCCESS); @@ -505,6 +514,7 @@ incctx_create(isc_mem_t *mctx, dns_name_t *origin, dns_incctx_t **ictxp) { ictx->drop = ISC_FALSE; ictx->glue_line = 0; ictx->current_line = 0; + ictx->origin_changed = ISC_TRUE; *ictxp = ictx; return (ISC_R_SUCCESS); @@ -807,6 +817,7 @@ generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs, isc_textregion_t r; int i, n, start, stop, step = 0; dns_incctx_t *ictx; + char dummy; ictx = lctx->inc; callbacks = lctx->callbacks; @@ -823,9 +834,9 @@ generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs, } isc_buffer_init(&target, target_mem, target_size); - n = sscanf(range, "%d-%d/%d", &start, &stop, &step); - if ((n < 2) || (start < 0) || (stop < 0) || (step < 0) || - (stop < start)) + n = sscanf(range, "%d-%d%[/]%d", &start, &stop, &dummy, &step); + if ((n != 2 && n != 4) || (start < 0) || (stop < 0) || + (n == 4 && step < 1) || (stop < start)) { (*callbacks->error)(callbacks, "%s: %s:%lu: invalid range '%s'", @@ -1109,7 +1120,6 @@ load_text(dns_loadctx_t *lctx) { line = isc_lex_getsourceline(lctx->lex); source = isc_lex_getsourcename(lctx->lex); ictx = lctx->inc; - EXPECTEOL; continue; } done = ISC_TRUE; @@ -1145,7 +1155,9 @@ load_text(dns_loadctx_t *lctx) { finish_origin = ISC_TRUE; } else if (strcasecmp(DNS_AS_STR(token), "$TTL") == 0) { - GETTOKEN(lctx->lex, 0, &token, ISC_FALSE); + GETTOKENERR(lctx->lex, 0, &token, ISC_FALSE, + lctx->ttl = 0; + lctx->default_ttl_known = ISC_TRUE;); result = dns_ttl_fromtext(&token.value.as_textregion, &lctx->ttl); @@ -1197,7 +1209,6 @@ load_text(dns_loadctx_t *lctx) { token.type == isc_tokentype_eof) { if (token.type == isc_tokentype_eof) WARNUNEXPECTEDEOF(lctx->lex); - isc_lex_ungettoken(lctx->lex, &token); /* * No origin field. */ @@ -1416,6 +1427,7 @@ load_text(dns_loadctx_t *lctx) { } if (finish_include) { finish_include = ISC_FALSE; + EXPECTEOL; result = pushfile(include_file, new_name, lctx); if (MANYERRS(lctx, result)) { SETRESULT(lctx, result); @@ -1426,6 +1438,7 @@ load_text(dns_loadctx_t *lctx) { goto insist_and_cleanup; } ictx = lctx->inc; + ictx->origin_changed = ISC_TRUE; source = isc_lex_getsourcename(lctx->lex); line = isc_lex_getsourceline(lctx->lex); POST(line); @@ -2046,6 +2059,11 @@ pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx) { if (result != ISC_R_SUCCESS) return (result); + /* + * Push origin_changed. + */ + new->origin_changed = ictx->origin_changed; + /* Set current domain. */ if (ictx->glue != NULL || ictx->current != NULL) { for (new_in_use = 0; new_in_use < NBUFS; new_in_use++) @@ -2070,8 +2088,7 @@ pushfile(const char *master_file, dns_name_t *origin, dns_loadctx_t *lctx) { return (ISC_R_SUCCESS); cleanup: - if (new != NULL) - incctx_destroy(lctx->mctx, new); + incctx_destroy(lctx->mctx, new); return (result); } diff --git a/lib/dns/masterdump.c b/lib/dns/masterdump.c index 01f797cb99ed..7e53a735c47e 100644 --- a/lib/dns/masterdump.c +++ b/lib/dns/masterdump.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011-2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -994,7 +994,6 @@ dump_rdataset_raw(isc_mem_t *mctx, dns_name_t *name, dns_rdataset_t *rdataset, do { dns_rdata_t rdata = DNS_RDATA_INIT; - isc_region_t r; dns_rdataset_current(rdataset, &rdata); dns_rdata_toregion(&rdata, &r); diff --git a/lib/dns/message.c b/lib/dns/message.c index d76eb4fb26c6..b95e48ea2641 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,8 +15,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ - /*! \file */ /*** @@ -3268,7 +3266,7 @@ dns_message_pseudosectiontotext(dns_message_t *msg, ADD_STRING(target, "; NSID"); } else { ADD_STRING(target, "; OPT="); - sprintf(buf, "%u", optcode); + snprintf(buf, sizeof(buf), "%u", optcode); ADD_STRING(target, buf); } diff --git a/lib/dns/name.c b/lib/dns/name.c index 5207f74b4240..3b7ff3f962bf 100644 --- a/lib/dns/name.c +++ b/lib/dns/name.c @@ -579,6 +579,7 @@ dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2, if (name1 == name2) { *orderp = 0; + *nlabelsp = name1->labels; return (dns_namereln_equal); } diff --git a/lib/dns/nsec3.c b/lib/dns/nsec3.c index ef43c35d27bb..11ae837a54a8 100644 --- a/lib/dns/nsec3.c +++ b/lib/dns/nsec3.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2008-2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2006, 2008-2015 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -2057,8 +2057,6 @@ dns_nsec3_noexistnodata(dns_rdatatype_t type, dns_name_t* name, (scope >= 0 && (order > 0 || memcmp(hash, nsec3.next, length) < 0))) { - char namebuf[DNS_NAME_FORMATSIZE]; - dns_name_format(qname, namebuf, sizeof(namebuf)); (*logit)(arg, ISC_LOG_DEBUG(3), "NSEC3 proves " "name does not exist: '%s'", namebuf); diff --git a/lib/dns/openssldh_link.c b/lib/dns/openssldh_link.c index cb9fb77d4219..953e8fd50e4a 100644 --- a/lib/dns/openssldh_link.c +++ b/lib/dns/openssldh_link.c @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2004-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2004-2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -93,7 +93,7 @@ openssldh_computesecret(const dst_key_t *pub, const dst_key_t *priv, if (r.length < len) return (ISC_R_NOSPACE); ret = DH_compute_key(r.base, dhpub->pub_key, dhpriv); - if (ret == 0) + if (ret <= 0) return (dst__openssl_toresult2("DH_compute_key", DST_R_COMPUTESECRETFAILURE)); isc_buffer_add(secret, len); diff --git a/lib/dns/opensslecdsa_link.c b/lib/dns/opensslecdsa_link.c index 40081c2df856..34f8ba03b092 100644 --- a/lib/dns/opensslecdsa_link.c +++ b/lib/dns/opensslecdsa_link.c @@ -295,10 +295,13 @@ opensslecdsa_generate(dst_key_t *key, int unused, void (*callback)(int)) { UNUSED(unused); UNUSED(callback); - if (key->key_alg == DST_ALG_ECDSA256) + if (key->key_alg == DST_ALG_ECDSA256) { group_nid = NID_X9_62_prime256v1; - else + key->key_size = DNS_KEY_ECDSA256SIZE * 4; + } else { group_nid = NID_secp384r1; + key->key_size = DNS_KEY_ECDSA384SIZE * 4; + } eckey = EC_KEY_new_by_curve_name(group_nid); if (eckey == NULL) @@ -433,6 +436,7 @@ opensslecdsa_fromdns(dst_key_t *key, isc_buffer_t *data) { isc_buffer_forward(data, len); key->keydata.pkey = pkey; + key->key_size = len * 4; ret = ISC_R_SUCCESS; err: @@ -581,6 +585,10 @@ opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { DST_RET (dst__openssl_toresult(DST_R_OPENSSLFAILURE)); } key->keydata.pkey = pkey; + if (key->key_alg == DST_ALG_ECDSA256) + key->key_size = DNS_KEY_ECDSA256SIZE * 4; + else + key->key_size = DNS_KEY_ECDSA384SIZE * 4; ret = ISC_R_SUCCESS; err: diff --git a/lib/dns/opensslgost_link.c b/lib/dns/opensslgost_link.c index b0578661f97f..a01e9f32bb25 100644 --- a/lib/dns/opensslgost_link.c +++ b/lib/dns/opensslgost_link.c @@ -196,6 +196,7 @@ opensslgost_generate(dst_key_t *key, int unused, void (*callback)(int)) { DST_RET(dst__openssl_toresult2("EVP_PKEY_keygen", DST_R_OPENSSLFAILURE)); key->keydata.pkey = pkey; + key->key_size = EVP_PKEY_bits(pkey); EVP_PKEY_CTX_free(ctx); return (ISC_R_SUCCESS); @@ -281,6 +282,7 @@ opensslgost_fromdns(dst_key_t *key, isc_buffer_t *data) { return (dst__openssl_toresult2("d2i_PUBKEY", DST_R_OPENSSLFAILURE)); key->keydata.pkey = pkey; + key->key_size = EVP_PKEY_bits(pkey); return (ISC_R_SUCCESS); } diff --git a/lib/dns/private.c b/lib/dns/private.c index 6521279f2d9b..c29522c52990 100644 --- a/lib/dns/private.c +++ b/lib/dns/private.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2009, 2011, 2012, 2015 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -162,7 +162,6 @@ dns_private_chains(dns_db_t *db, dns_dbversion_t *ver, for (result = dns_rdataset_first(&privateset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&privateset)) { - unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE]; dns_rdata_t private = DNS_RDATA_INIT; dns_rdata_t rdata = DNS_RDATA_INIT; diff --git a/lib/dns/rbt.c b/lib/dns/rbt.c index 0e9c5f950569..1b6121de7945 100644 --- a/lib/dns/rbt.c +++ b/lib/dns/rbt.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007-2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007-2009, 2011-2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -1446,6 +1446,8 @@ create_node(isc_mem_t *mctx, dns_name_t *name, dns_rbtnode_t **nodep) { LEFT(node) = NULL; DOWN(node) = NULL; DATA(node) = NULL; + node->rpz = 0; + #ifdef DNS_RBT_USEHASH HASHNEXT(node) = NULL; HASHVAL(node) = 0; diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index a8ad8329c73b..a1398d3d1ab1 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -1636,7 +1636,7 @@ delete_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) switch (node->nsec) { case DNS_RBT_NSEC_NORMAL: #ifdef BIND9 - if (rbtdb->rpz_cidr != NULL) { + if (rbtdb->rpz_cidr != NULL && node->rpz) { dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); dns_rbt_fullnamefromnode(node, name); @@ -1677,7 +1677,7 @@ delete_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) } } #ifdef BIND9 - if (rbtdb->rpz_cidr != NULL) + if (rbtdb->rpz_cidr != NULL && node->rpz) dns_rpz_cidr_deleteip(rbtdb->rpz_cidr, name); #endif result = dns_rbt_deletenode(rbtdb->tree, node, ISC_FALSE); @@ -2192,7 +2192,6 @@ setnsec3parameters(dns_db_t *db, rbtdb_version_t *version) { unsigned int count, length; dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db; - RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); version->havensec3 = ISC_FALSE; node = rbtdb->origin_node; NODE_LOCK(&(rbtdb->node_locks[node->locknum].lock), @@ -2269,7 +2268,6 @@ setnsec3parameters(dns_db_t *db, rbtdb_version_t *version) { unlock: NODE_UNLOCK(&(rbtdb->node_locks[node->locknum].lock), isc_rwlocktype_read); - RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_read); } #endif @@ -2313,7 +2311,6 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { dns_rbtnode_t *rbtnode; unsigned int refs; rdatasetheader_t *header; - isc_boolean_t writer; REQUIRE(VALID_RBTDB(rbtdb)); version = (rbtdb_version_t *)*versionp; @@ -2335,7 +2332,6 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { RBTDB_LOCK(&rbtdb->lock, isc_rwlocktype_write); serial = version->serial; - writer = version->writer; if (version->writer) { if (commit) { unsigned cur_ref; @@ -2392,6 +2388,11 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { link); } /* + * Update the zone's secure status. + */ + if (!IS_CACHE(rbtdb)) + iszonesecure(db, version, rbtdb->origin_node); + /* * Become the current version. */ version->writer = ISC_FALSE; @@ -2469,12 +2470,6 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { least_serial = rbtdb->least_serial; RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write); - /* - * Update the zone's secure status. - */ - if (writer && commit && !IS_CACHE(rbtdb)) - iszonesecure(db, version, rbtdb->origin_node); - if (cleanup_version != NULL) { INSIST(EMPTY(cleanup_version->changed_list)); isc_mem_put(rbtdb->common.mctx, cleanup_version, @@ -2679,6 +2674,7 @@ findnodeintree(dns_rbtdb_t *rbtdb, dns_rbt_t *tree, dns_name_t *name, fname = dns_fixedname_name(&fnamef); dns_rbt_fullnamefromnode(node, fname); dns_rpz_cidr_addip(rbtdb->rpz_cidr, fname); + node->rpz = 1; } #endif dns_rbt_namefromnode(node, &nodename); @@ -5882,8 +5878,6 @@ allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, currentversion(db, (dns_dbversion_t **) (void *)(&rbtversion)); else { - unsigned int refs; - INSIST(rbtversion->rbtdb == rbtdb); isc_refcount_increment(&rbtversion->references, @@ -7099,7 +7093,6 @@ loadnode(dns_rbtdb_t *rbtdb, dns_name_t *name, dns_rbtnode_t **nodep, "dns_rbt_addnode(NSEC): %s", isc_result_totext(tmpresult), isc_result_totext(noderesult)); - } /* @@ -7109,8 +7102,10 @@ loadnode(dns_rbtdb_t *rbtdb, dns_name_t *name, dns_rbtnode_t **nodep, done: #ifdef BIND9 - if (noderesult == ISC_R_SUCCESS && rbtdb->rpz_cidr != NULL) + if (noderesult == ISC_R_SUCCESS && rbtdb->rpz_cidr != NULL) { dns_rpz_cidr_addip(rbtdb->rpz_cidr, name); + node->rpz = 1; + } #endif if (noderesult == ISC_R_SUCCESS || noderesult == ISC_R_EXISTS) *nodep = node; diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c index 08bfa34aa678..9e1eebe70d29 100644 --- a/lib/dns/rdata.c +++ b/lib/dns/rdata.c @@ -1168,12 +1168,12 @@ txt_totext(isc_region_t *source, isc_boolean_t quote, isc_buffer_t *target) { continue; } /* - * Escape double quote, semi-colon, backslash. - * If we are not enclosing the string in double - * quotes also escape at sign. + * Escape double quote and backslash. If we are not + * enclosing the string in double quotes also escape + * at sign and semicolon. */ - if (*sp == 0x22 || *sp == 0x3b || *sp == 0x5c || - (!quote && *sp == 0x40)) { + if (*sp == 0x22 || *sp == 0x5c || + (!quote && (*sp == 0x40 || *sp == 0x3b))) { if (tl < 2) return (ISC_R_NOSPACE); *tp++ = '\\'; diff --git a/lib/dns/rdata/generic/cdnskey_60.c b/lib/dns/rdata/generic/cdnskey_60.c index a1e681403b75..624f581725e0 100644 --- a/lib/dns/rdata/generic/cdnskey_60.c +++ b/lib/dns/rdata/generic/cdnskey_60.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2014, 2015 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -27,7 +27,7 @@ #include <dst/dst.h> -#define RRTYPE_CDNSKEY_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC) +#define RRTYPE_CDNSKEY_ATTRIBUTES 0 static inline isc_result_t fromtext_cdnskey(ARGS_FROMTEXT) { diff --git a/lib/dns/rdata/generic/cds_59.c b/lib/dns/rdata/generic/cds_59.c index fcf49662c46a..ff7ff6315790 100644 --- a/lib/dns/rdata/generic/cds_59.c +++ b/lib/dns/rdata/generic/cds_59.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2014, 2015 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -21,8 +21,7 @@ #ifndef RDATA_GENERIC_CDS_59_C #define RDATA_GENERIC_CDS_59_C -#define RRTYPE_CDS_ATTRIBUTES \ - (DNS_RDATATYPEATTR_DNSSEC|DNS_RDATATYPEATTR_ATPARENT) +#define RRTYPE_CDS_ATTRIBUTES 0 #include <isc/sha1.h> #include <isc/sha2.h> diff --git a/lib/dns/rdata/generic/keydata_65533.c b/lib/dns/rdata/generic/keydata_65533.c index fae2bce8dbeb..00cf084eb62a 100644 --- a/lib/dns/rdata/generic/keydata_65533.c +++ b/lib/dns/rdata/generic/keydata_65533.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2009, 2011-2013, 2015 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,11 +14,12 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ - #ifndef GENERIC_KEYDATA_65533_C #define GENERIC_KEYDATA_65533_C 1 +#include <isc/time.h> +#include <isc/stdtime.h> + #include <dst/dst.h> #define RRTYPE_KEYDATA_ATTRIBUTES (0) @@ -97,7 +98,7 @@ totext_keydata(ARGS_TOTEXT) { char buf[sizeof("64000")]; unsigned int flags; unsigned char algorithm; - unsigned long when; + unsigned long refresh, add, remove; char algbuf[DNS_NAME_FORMATSIZE]; const char *keyinfo; @@ -109,21 +110,21 @@ totext_keydata(ARGS_TOTEXT) { dns_rdata_toregion(rdata, &sr); /* refresh timer */ - when = uint32_fromregion(&sr); + refresh = uint32_fromregion(&sr); isc_region_consume(&sr, 4); - RETERR(dns_time32_totext(when, target)); + RETERR(dns_time32_totext(refresh, target)); RETERR(str_totext(" ", target)); /* add hold-down */ - when = uint32_fromregion(&sr); + add = uint32_fromregion(&sr); isc_region_consume(&sr, 4); - RETERR(dns_time32_totext(when, target)); + RETERR(dns_time32_totext(add, target)); RETERR(str_totext(" ", target)); /* remove hold-down */ - when = uint32_fromregion(&sr); + remove = uint32_fromregion(&sr); isc_region_consume(&sr, 4); - RETERR(dns_time32_totext(when, target)); + RETERR(dns_time32_totext(remove, target)); RETERR(str_totext(" ", target)); /* flags */ @@ -176,6 +177,10 @@ totext_keydata(ARGS_TOTEXT) { if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) { isc_region_t tmpr; + char rbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; + char abuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; + char dbuf[ISC_FORMATHTTPTIMESTAMP_SIZE]; + isc_time_t t; RETERR(str_totext(" ; ", target)); RETERR(str_totext(keyinfo, target)); @@ -189,6 +194,47 @@ totext_keydata(ARGS_TOTEXT) { isc_region_consume(&tmpr, 12); sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm)); RETERR(str_totext(buf, target)); + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) { + isc_stdtime_t now; + + isc_stdtime_get(&now); + + RETERR(str_totext(tctx->linebreak, target)); + RETERR(str_totext("; next refresh: ", target)); + isc_time_set(&t, refresh, 0); + isc_time_formathttptimestamp(&t, rbuf, sizeof(rbuf)); + RETERR(str_totext(rbuf, target)); + + if (add == 0) { + RETERR(str_totext(tctx->linebreak, target)); + RETERR(str_totext("; no trust", target)); + } else { + RETERR(str_totext(tctx->linebreak, target)); + if (add < now) { + RETERR(str_totext("; trusted since: ", + target)); + } else { + RETERR(str_totext("; trust pending: ", + target)); + } + isc_time_set(&t, add, 0); + isc_time_formathttptimestamp(&t, abuf, + sizeof(abuf)); + RETERR(str_totext(abuf, target)); + } + + if (remove != 0) { + RETERR(str_totext(tctx->linebreak, target)); + RETERR(str_totext("; removal pending: ", + target)); + isc_time_set(&t, remove, 0); + isc_time_formathttptimestamp(&t, dbuf, + sizeof(dbuf)); + RETERR(str_totext(dbuf, target)); + } + } + } return (ISC_R_SUCCESS); } diff --git a/lib/dns/rdata/generic/nsec3_50.c b/lib/dns/rdata/generic/nsec3_50.c index 35fcf5d58229..eb4f68dca2a1 100644 --- a/lib/dns/rdata/generic/nsec3_50.c +++ b/lib/dns/rdata/generic/nsec3_50.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009, 2011, 2012, 2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2008, 2009, 2011, 2012, 2014, 2015 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -140,7 +140,7 @@ totext_nsec3(ARGS_TOTEXT) { unsigned int window, len; unsigned char hash; unsigned char flags; - char buf[sizeof("65535 ")]; + char buf[sizeof("TYPE65535")]; isc_uint32_t iterations; isc_boolean_t first; @@ -224,7 +224,6 @@ totext_nsec3(ARGS_TOTEXT) { if (dns_rdatatype_isknown(t)) { RETERR(dns_rdatatype_totext(t, target)); } else { - char buf[sizeof("TYPE65535")]; sprintf(buf, "TYPE%u", t); RETERR(str_totext(buf, target)); } diff --git a/lib/dns/rdata/generic/openpgpkey_61.c b/lib/dns/rdata/generic/openpgpkey_61.c new file mode 100644 index 000000000000..7b2a88bbd312 --- /dev/null +++ b/lib/dns/rdata/generic/openpgpkey_61.c @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef RDATA_GENERIC_OPENPGPKEY_61_C +#define RDATA_GENERIC_OPENPGPKEY_61_C + +#define RRTYPE_OPENPGPKEY_ATTRIBUTES 0 + +static inline isc_result_t +fromtext_openpgpkey(ARGS_FROMTEXT) { + + REQUIRE(type == 61); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(callbacks); + UNUSED(options); + UNUSED(origin); + + /* + * Keyring. + */ + return (isc_base64_tobuffer(lexer, target, -1)); +} + +static inline isc_result_t +totext_openpgpkey(ARGS_TOTEXT) { + isc_region_t sr; + + REQUIRE(rdata->type == 61); + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, &sr); + + /* + * Keyring + */ + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext("( ", target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&sr, 60, "", target)); + else + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" )", target)); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_openpgpkey(ARGS_FROMWIRE) { + isc_region_t sr; + + REQUIRE(type == 61); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(dctx); + UNUSED(options); + + /* + * Keyring. + */ + isc_buffer_activeregion(source, &sr); + isc_buffer_forward(source, sr.length); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline isc_result_t +towire_openpgpkey(ARGS_TOWIRE) { + isc_region_t sr; + + REQUIRE(rdata->type == 61); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_openpgpkey(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == 61); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_openpgpkey(ARGS_FROMSTRUCT) { + dns_rdata_openpgpkey_t *sig = source; + + REQUIRE(type == 61); + REQUIRE(source != NULL); + REQUIRE(sig->common.rdtype == type); + REQUIRE(sig->common.rdclass == rdclass); + REQUIRE(sig->keyring != NULL && sig->length != 0); + + UNUSED(type); + UNUSED(rdclass); + + /* + * Keyring. + */ + return (mem_tobuffer(target, sig->keyring, sig->length)); +} + +static inline isc_result_t +tostruct_openpgpkey(ARGS_TOSTRUCT) { + isc_region_t sr; + dns_rdata_openpgpkey_t *sig = target; + + REQUIRE(rdata->type == 61); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + sig->common.rdclass = rdata->rdclass; + sig->common.rdtype = rdata->type; + ISC_LINK_INIT(&sig->common, link); + + dns_rdata_toregion(rdata, &sr); + + /* + * Keyring. + */ + sig->length = sr.length; + sig->keyring = mem_maybedup(mctx, sr.base, sig->length); + if (sig->keyring == NULL) + goto cleanup; + + sig->mctx = mctx; + return (ISC_R_SUCCESS); + + cleanup: + return (ISC_R_NOMEMORY); +} + +static inline void +freestruct_openpgpkey(ARGS_FREESTRUCT) { + dns_rdata_openpgpkey_t *sig = (dns_rdata_openpgpkey_t *) source; + + REQUIRE(source != NULL); + REQUIRE(sig->common.rdtype == 61); + + if (sig->mctx == NULL) + return; + + if (sig->keyring != NULL) + isc_mem_free(sig->mctx, sig->keyring); + sig->mctx = NULL; +} + +static inline isc_result_t +additionaldata_openpgpkey(ARGS_ADDLDATA) { + REQUIRE(rdata->type == 61); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_openpgpkey(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == 61); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline isc_boolean_t +checkowner_openpgpkey(ARGS_CHECKOWNER) { + + REQUIRE(type == 61); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (ISC_TRUE); +} + +static inline isc_boolean_t +checknames_openpgpkey(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == 61); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (ISC_TRUE); +} + +static inline int +casecompare_openpgpkey(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == 61); + REQUIRE(rdata1->length != 0); + REQUIRE(rdata2->length != 0); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + + return (isc_region_compare(&r1, &r2)); +} + +#endif /* RDATA_GENERIC_OPENPGPKEY_61_C */ diff --git a/lib/dns/rdata/generic/openpgpkey_61.h b/lib/dns/rdata/generic/openpgpkey_61.h new file mode 100644 index 000000000000..2219422230c2 --- /dev/null +++ b/lib/dns/rdata/generic/openpgpkey_61.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef GENERIC_OPENPGPKEY_61_H +#define GENERIC_OPENPGPKEY_61_H 1 + +typedef struct dns_rdata_openpgpkey { + dns_rdatacommon_t common; + isc_mem_t * mctx; + isc_uint16_t length; + unsigned char * keyring; +} dns_rdata_openpgpkey_t; + +#endif /* GENERIC_OPENPGPKEY_61_H */ diff --git a/lib/dns/rdata/generic/opt_41.c b/lib/dns/rdata/generic/opt_41.c index ae09abf71e91..ba3fef001a15 100644 --- a/lib/dns/rdata/generic/opt_41.c +++ b/lib/dns/rdata/generic/opt_41.c @@ -326,4 +326,63 @@ casecompare_opt(ARGS_COMPARE) { return (compare_opt(rdata1, rdata2)); } +isc_result_t +dns_rdata_opt_first(dns_rdata_opt_t *opt) { + + REQUIRE(opt != NULL); + REQUIRE(opt->common.rdtype == 41); + REQUIRE(opt->options != NULL || opt->length == 0); + + if (opt->length == 0) + return (ISC_R_NOMORE); + + opt->offset = 0; + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_rdata_opt_next(dns_rdata_opt_t *opt) { + isc_region_t r; + isc_uint16_t length; + + REQUIRE(opt != NULL); + REQUIRE(opt->common.rdtype == 41); + REQUIRE(opt->options != NULL && opt->length != 0); + REQUIRE(opt->offset < opt->length); + + INSIST(opt->offset + 4 <= opt->length); + r.base = opt->options + opt->offset + 2; + r.length = opt->length - opt->offset - 2; + length = uint16_fromregion(&r); + INSIST(opt->offset + 4 + length <= opt->length); + opt->offset = opt->offset + 4 + length; + if (opt->offset == opt->length) + return (ISC_R_NOMORE); + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_rdata_opt_current(dns_rdata_opt_t *opt, dns_rdata_opt_opcode_t *opcode) { + isc_region_t r; + + REQUIRE(opt != NULL); + REQUIRE(opcode != NULL); + REQUIRE(opt->common.rdtype == 41); + REQUIRE(opt->options != NULL); + REQUIRE(opt->offset < opt->length); + + INSIST(opt->offset + 4 <= opt->length); + r.base = opt->options + opt->offset; + r.length = opt->length - opt->offset; + + opcode->opcode = uint16_fromregion(&r); + isc_region_consume(&r, 2); + opcode->length = uint16_fromregion(&r); + isc_region_consume(&r, 2); + opcode->data = r.base; + INSIST(opt->offset + 4 + opcode->length <= opt->length); + + return (ISC_R_SUCCESS); +} + #endif /* RDATA_GENERIC_OPT_41_C */ diff --git a/lib/dns/rdata/generic/rrsig_46.c b/lib/dns/rdata/generic/rrsig_46.c index 5dd5a31a7ca8..d4e8767fed88 100644 --- a/lib/dns/rdata/generic/rrsig_46.c +++ b/lib/dns/rdata/generic/rrsig_46.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012, 2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012, 2014, 2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -178,7 +178,6 @@ totext_rrsig(ARGS_TOTEXT) { if (dns_rdatatype_isknown(covered) && covered != 0) { RETERR(dns_rdatatype_totext(covered, target)); } else { - char buf[sizeof("TYPE65535")]; sprintf(buf, "TYPE%u", covered); RETERR(str_totext(buf, target)); } diff --git a/lib/dns/rdata/generic/sig_24.c b/lib/dns/rdata/generic/sig_24.c index 803a864067f0..86aa38a696b6 100644 --- a/lib/dns/rdata/generic/sig_24.c +++ b/lib/dns/rdata/generic/sig_24.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012, 2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -154,7 +154,6 @@ totext_sig(ARGS_TOTEXT) { if (dns_rdatatype_isknown(covered) && covered != 0) { RETERR(dns_rdatatype_totext(covered, target)); } else { - char buf[sizeof("65535")]; sprintf(buf, "%u", covered); RETERR(str_totext(buf, target)); } diff --git a/lib/dns/rdata/generic/spf_99.h b/lib/dns/rdata/generic/spf_99.h index be5e9789842a..35ec9bc9ff95 100644 --- a/lib/dns/rdata/generic/spf_99.h +++ b/lib/dns/rdata/generic/spf_99.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2014 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -21,31 +21,21 @@ /* $Id: spf_99.h,v 1.4 2007/06/19 23:47:17 tbox Exp $ */ typedef struct dns_rdata_spf_string { - isc_uint8_t length; - unsigned char *data; + isc_uint8_t length; + unsigned char *data; } dns_rdata_spf_string_t; typedef struct dns_rdata_spf { - dns_rdatacommon_t common; - isc_mem_t *mctx; - unsigned char *txt; - isc_uint16_t txt_len; - /* private */ - isc_uint16_t offset; + dns_rdatacommon_t common; + isc_mem_t *mctx; + unsigned char *txt; + isc_uint16_t txt_len; + /* private */ + isc_uint16_t offset; } dns_rdata_spf_t; /* * ISC_LANG_BEGINDECLS and ISC_LANG_ENDDECLS are already done * via rdatastructpre.h and rdatastructsuf.h. */ - -isc_result_t -dns_rdata_spf_first(dns_rdata_spf_t *); - -isc_result_t -dns_rdata_spf_next(dns_rdata_spf_t *); - -isc_result_t -dns_rdata_spf_current(dns_rdata_spf_t *, dns_rdata_spf_string_t *); - #endif /* GENERIC_SPF_99_H */ diff --git a/lib/dns/rdata/generic/txt_16.c b/lib/dns/rdata/generic/txt_16.c index 41e270279216..0cbe3ea6f15a 100644 --- a/lib/dns/rdata/generic/txt_16.c +++ b/lib/dns/rdata/generic/txt_16.c @@ -247,4 +247,59 @@ casecompare_txt(ARGS_COMPARE) { return (compare_txt(rdata1, rdata2)); } +isc_result_t +dns_rdata_txt_first(dns_rdata_txt_t *txt) { + + REQUIRE(txt != NULL); + REQUIRE(txt->common.rdtype == 16); + REQUIRE(txt->txt != NULL || txt->txt_len == 0); + + if (txt->txt_len == 0) + return (ISC_R_NOMORE); + + txt->offset = 0; + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_rdata_txt_next(dns_rdata_txt_t *txt) { + isc_region_t r; + isc_uint8_t length; + + REQUIRE(txt != NULL); + REQUIRE(txt->common.rdtype == 16); + REQUIRE(txt->txt != NULL && txt->txt_len != 0); + + INSIST(txt->offset + 1 <= txt->txt_len); + r.base = txt->txt + txt->offset; + r.length = txt->txt_len - txt->offset; + length = uint8_fromregion(&r); + INSIST(txt->offset + 1 + length <= txt->txt_len); + txt->offset = txt->offset + 1 + length; + if (txt->offset == txt->txt_len) + return (ISC_R_NOMORE); + return (ISC_R_SUCCESS); +} + +isc_result_t +dns_rdata_txt_current(dns_rdata_txt_t *txt, dns_rdata_txt_string_t *string) { + isc_region_t r; + + REQUIRE(txt != NULL); + REQUIRE(string != NULL); + REQUIRE(txt->common.rdtype == 16); + REQUIRE(txt->txt != NULL); + REQUIRE(txt->offset < txt->txt_len); + + INSIST(txt->offset + 1 <= txt->txt_len); + r.base = txt->txt + txt->offset; + r.length = txt->txt_len - txt->offset; + + string->length = uint8_fromregion(&r); + isc_region_consume(&r, 1); + string->data = r.base; + INSIST(txt->offset + 1 + string->length <= txt->txt_len); + + return (ISC_R_SUCCESS); +} #endif /* RDATA_GENERIC_TXT_16_C */ diff --git a/lib/dns/rdataset.c b/lib/dns/rdataset.c index 026d771235cc..ab02d32e0998 100644 --- a/lib/dns/rdataset.c +++ b/lib/dns/rdataset.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2012, 2014, 2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -80,6 +80,7 @@ dns_rdataset_init(dns_rdataset_t *rdataset) { rdataset->privateuint4 = 0; rdataset->private5 = NULL; rdataset->private6 = NULL; + rdataset->private7 = NULL; rdataset->resign = 0; } @@ -415,7 +416,6 @@ towiresorted(dns_rdataset_t *rdataset, const dns_name_t *owner_name, * 'Random' order. */ for (i = 0; i < count; i++) { - dns_rdata_t rdata; isc_uint32_t val; isc_random_get(&val); diff --git a/lib/dns/request.c b/lib/dns/request.c index 1316e6994110..59e166eb0257 100644 --- a/lib/dns/request.c +++ b/lib/dns/request.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -686,6 +686,7 @@ dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, dns_messageid_t id; isc_boolean_t tcp = ISC_FALSE; isc_region_t r; + unsigned int dispopt = 0; REQUIRE(VALID_REQUESTMGR(requestmgr)); REQUIRE(msgbuf != NULL); @@ -751,9 +752,14 @@ dns_request_createraw3(dns_requestmgr_t *requestmgr, isc_buffer_t *msgbuf, if (result != ISC_R_SUCCESS) goto cleanup; - result = dns_dispatch_addresponse2(request->dispatch, destaddr, task, - req_response, request, &id, - &request->dispentry, + if ((options & DNS_REQUESTOPT_FIXEDID) != 0) { + id = (r.base[0] << 8) | r.base[1]; + dispopt |= DNS_DISPATCHOPT_FIXEDID; + } + + result = dns_dispatch_addresponse3(request->dispatch, dispopt, + destaddr, task, req_response, + request, &id, &request->dispentry, requestmgr->socketmgr); if (result != ISC_R_SUCCESS) goto cleanup; diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index befe3cafe0f2..d33c43ed82af 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -1673,6 +1673,24 @@ add_triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) { ISC_LIST_INITANDAPPEND(fctx->edns512, sa, link); } +static isc_boolean_t +wouldvalidate(fetchctx_t *fctx) { + isc_boolean_t secure_domain; + isc_result_t result; + + if (!fctx->res->view->enablevalidation) + return (ISC_FALSE); + + if (fctx->res->view->dlv != NULL) + return (ISC_TRUE); + + result = dns_view_issecuredomain(fctx->res->view, &fctx->name, + &secure_domain); + if (result != ISC_R_SUCCESS) + return (ISC_FALSE); + return (secure_domain); +} + static isc_result_t resquery_send(resquery_t *query) { fetchctx_t *fctx; @@ -1842,11 +1860,12 @@ resquery_send(resquery_t *query) { if ((triededns512(fctx, &query->addrinfo->sockaddr) || fctx->timeouts >= (MAX_EDNS0_TIMEOUTS * 2)) && (query->options & DNS_FETCHOPT_NOEDNS0) == 0 && - !EDNSOK(query->addrinfo)) { + (!EDNSOK(query->addrinfo) || !wouldvalidate(fctx))) { + query->options |= DNS_FETCHOPT_NOEDNS0; + fctx->reason = "disabling EDNS"; } else if ((triededns(fctx, &query->addrinfo->sockaddr) || fctx->timeouts >= MAX_EDNS0_TIMEOUTS) && - (query->options & DNS_FETCHOPT_NOEDNS0) == 0 && - !EDNSOK(query->addrinfo)) { + (query->options & DNS_FETCHOPT_NOEDNS0) == 0) { query->options |= DNS_FETCHOPT_EDNS512; fctx->reason = "reducing the advertised EDNS UDP " "packet size to 512 octets"; @@ -2504,11 +2523,19 @@ findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port, fctx->depth + 1, fctx->qc, &find); if (result != ISC_R_SUCCESS) { if (result == DNS_R_ALIAS) { + char namebuf[DNS_NAME_FORMATSIZE]; + /* * XXXRTH Follow the CNAME/DNAME chain? */ dns_adb_destroyfind(&find); fctx->adberr++; + dns_name_format(name, namebuf, sizeof(namebuf)); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_CNAME, + DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO, + "skipping nameserver '%s' because it " + "is a CNAME, while resolving '%s'", + namebuf, fctx->info); } } else if (!ISC_LIST_EMPTY(find->list)) { /* @@ -2725,6 +2752,10 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) { stdoptions |= DNS_ADBFIND_INET; if (res->dispatches6 != NULL) stdoptions |= DNS_ADBFIND_INET6; + + if ((stdoptions & DNS_ADBFIND_ADDRESSMASK) == 0) + return (DNS_R_SERVFAIL); + isc_stdtime_get(&now); INSIST(ISC_LIST_EMPTY(fctx->finds)); @@ -3055,6 +3086,16 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) { REQUIRE(!ADDRWAIT(fctx)); + /* We've already exceeded maximum query count */ + if (isc_counter_used(fctx->qc) > fctx->res->maxqueries) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, + DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), + "exceeded max queries resolving '%s'", + fctx->info); + fctx_done(fctx, DNS_R_SERVFAIL, __LINE__); + return; + } + addrinfo = fctx_nextaddress(fctx); if (addrinfo == NULL) { /* @@ -3092,14 +3133,16 @@ fctx_try(fetchctx_t *fctx, isc_boolean_t retrying, isc_boolean_t badcache) { } } - result = isc_counter_increment(fctx->qc); - if (result != ISC_R_SUCCESS) { - isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, - DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), - "exceeded max queries resolving '%s'", - fctx->info); - fctx_done(fctx, DNS_R_SERVFAIL, __LINE__); - return; + if (dns_name_countlabels(&fctx->domain) > 2) { + result = isc_counter_increment(fctx->qc); + if (result != ISC_R_SUCCESS) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, + DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), + "exceeded max queries resolving '%s'", + fctx->info); + fctx_done(fctx, DNS_R_SERVFAIL, __LINE__); + return; + } } result = fctx_query(fctx, addrinfo, fctx->options); @@ -4248,7 +4291,11 @@ validated(isc_task_t *task, isc_event_t *event) { inc_stats(res, dns_resstatscounter_valnegsuccess); - if (fctx->rmessage->rcode == dns_rcode_nxdomain) + /* + * Cache DS NXDOMAIN seperately to other types. + */ + if (fctx->rmessage->rcode == dns_rcode_nxdomain && + fctx->type != dns_rdatatype_ds) covers = dns_rdatatype_any; else covers = fctx->type; @@ -7481,7 +7528,12 @@ resquery_response(isc_task_t *task, isc_event_t *event) { */ if (WANTNCACHE(fctx)) { dns_rdatatype_t covers; - if (message->rcode == dns_rcode_nxdomain) + + /* + * Cache DS NXDOMAIN seperately to other types. + */ + if (message->rcode == dns_rcode_nxdomain && + fctx->type != dns_rdatatype_ds) covers = dns_rdatatype_any; else covers = fctx->type; diff --git a/lib/dns/rootns.c b/lib/dns/rootns.c index a3d9bd8d6084..21c532c39696 100644 --- a/lib/dns/rootns.c +++ b/lib/dns/rootns.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2008, 2010, 2012-2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2008, 2010, 2012-2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -211,7 +211,7 @@ dns_rootns_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone, rdclass, 0, NULL, &db); if (result != ISC_R_SUCCESS) - return (result); + goto failure; dns_rdatacallbacks_init(&callbacks); @@ -222,7 +222,7 @@ dns_rootns_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, result = dns_db_beginload(db, &callbacks.add, &callbacks.add_private); if (result != ISC_R_SUCCESS) - return (result); + goto failure; if (filename != NULL) { /* * Load the hints from the specified filename. @@ -245,7 +245,7 @@ dns_rootns_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, if (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) result = eresult; if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) - goto db_detach; + goto failure; if (check_hints(db) != ISC_R_SUCCESS) isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_HINTS, ISC_LOG_WARNING, @@ -254,8 +254,14 @@ dns_rootns_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, *target = db; return (ISC_R_SUCCESS); - db_detach: - dns_db_detach(&db); + failure: + isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_HINTS, + ISC_LOG_ERROR, "could not configure root hints from " + "'%s': %s", (filename != NULL) ? filename : "<BUILT-IN>", + isc_result_totext(result)); + + if (db != NULL) + dns_db_detach(&db); return (result); } diff --git a/lib/dns/spnego_asn1.c b/lib/dns/spnego_asn1.c index a90f1be63c2c..8dc4ba803022 100644 --- a/lib/dns/spnego_asn1.c +++ b/lib/dns/spnego_asn1.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006, 2007, 2012, 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2006, 2007, 2012, 2013, 2015 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -486,13 +486,13 @@ decode_NegTokenInit(const unsigned char *p, size_t len, NegTokenInit * data, siz e = der_get_length(p, len, &newlen, &l); FORW; { - int dce_fix; + int mydce_fix; oldlen = len; - if ((dce_fix = fix_dce(newlen, &len)) < 0) + if ((mydce_fix = fix_dce(newlen, &len)) < 0) return ASN1_BAD_FORMAT; e = decode_MechTypeList(p, len, &(data)->mechTypes, &l); FORW; - if (dce_fix) { + if (mydce_fix) { e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l); FORW; } else @@ -513,16 +513,16 @@ decode_NegTokenInit(const unsigned char *p, size_t len, NegTokenInit * data, siz e = der_get_length(p, len, &newlen, &l); FORW; { - int dce_fix; + int mydce_fix; oldlen = len; - if ((dce_fix = fix_dce(newlen, &len)) < 0) + if ((mydce_fix = fix_dce(newlen, &len)) < 0) return ASN1_BAD_FORMAT; (data)->reqFlags = malloc(sizeof(*(data)->reqFlags)); if ((data)->reqFlags == NULL) return ENOMEM; e = decode_ContextFlags(p, len, (data)->reqFlags, &l); FORW; - if (dce_fix) { + if (mydce_fix) { e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l); FORW; } else @@ -543,16 +543,16 @@ decode_NegTokenInit(const unsigned char *p, size_t len, NegTokenInit * data, siz e = der_get_length(p, len, &newlen, &l); FORW; { - int dce_fix; + int mydce_fix; oldlen = len; - if ((dce_fix = fix_dce(newlen, &len)) < 0) + if ((mydce_fix = fix_dce(newlen, &len)) < 0) return ASN1_BAD_FORMAT; (data)->mechToken = malloc(sizeof(*(data)->mechToken)); if ((data)->mechToken == NULL) return ENOMEM; e = decode_octet_string(p, len, (data)->mechToken, &l); FORW; - if (dce_fix) { + if (mydce_fix) { e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l); FORW; } else @@ -573,16 +573,16 @@ decode_NegTokenInit(const unsigned char *p, size_t len, NegTokenInit * data, siz e = der_get_length(p, len, &newlen, &l); FORW; { - int dce_fix; + int mydce_fix; oldlen = len; - if ((dce_fix = fix_dce(newlen, &len)) < 0) + if ((mydce_fix = fix_dce(newlen, &len)) < 0) return ASN1_BAD_FORMAT; (data)->mechListMIC = malloc(sizeof(*(data)->mechListMIC)); if ((data)->mechListMIC == NULL) return ENOMEM; e = decode_octet_string(p, len, (data)->mechListMIC, &l); FORW; - if (dce_fix) { + if (mydce_fix) { e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l); FORW; } else @@ -710,16 +710,16 @@ decode_NegTokenResp(const unsigned char *p, size_t len, NegTokenResp * data, siz e = der_get_length(p, len, &newlen, &l); FORW; { - int dce_fix; + int mydce_fix; oldlen = len; - if ((dce_fix = fix_dce(newlen, &len)) < 0) + if ((mydce_fix = fix_dce(newlen, &len)) < 0) return ASN1_BAD_FORMAT; (data)->negState = malloc(sizeof(*(data)->negState)); if ((data)->negState == NULL) return ENOMEM; e = decode_enumerated(p, len, (data)->negState, &l); FORW; - if (dce_fix) { + if (mydce_fix) { e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l); FORW; } else @@ -740,16 +740,16 @@ decode_NegTokenResp(const unsigned char *p, size_t len, NegTokenResp * data, siz e = der_get_length(p, len, &newlen, &l); FORW; { - int dce_fix; + int mydce_fix; oldlen = len; - if ((dce_fix = fix_dce(newlen, &len)) < 0) + if ((mydce_fix = fix_dce(newlen, &len)) < 0) return ASN1_BAD_FORMAT; (data)->supportedMech = malloc(sizeof(*(data)->supportedMech)); if ((data)->supportedMech == NULL) return ENOMEM; e = decode_MechType(p, len, (data)->supportedMech, &l); FORW; - if (dce_fix) { + if (mydce_fix) { e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l); FORW; } else @@ -770,16 +770,16 @@ decode_NegTokenResp(const unsigned char *p, size_t len, NegTokenResp * data, siz e = der_get_length(p, len, &newlen, &l); FORW; { - int dce_fix; + int mydce_fix; oldlen = len; - if ((dce_fix = fix_dce(newlen, &len)) < 0) + if ((mydce_fix = fix_dce(newlen, &len)) < 0) return ASN1_BAD_FORMAT; (data)->responseToken = malloc(sizeof(*(data)->responseToken)); if ((data)->responseToken == NULL) return ENOMEM; e = decode_octet_string(p, len, (data)->responseToken, &l); FORW; - if (dce_fix) { + if (mydce_fix) { e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l); FORW; } else @@ -800,16 +800,16 @@ decode_NegTokenResp(const unsigned char *p, size_t len, NegTokenResp * data, siz e = der_get_length(p, len, &newlen, &l); FORW; { - int dce_fix; + int mydce_fix; oldlen = len; - if ((dce_fix = fix_dce(newlen, &len)) < 0) + if ((mydce_fix = fix_dce(newlen, &len)) < 0) return ASN1_BAD_FORMAT; (data)->mechListMIC = malloc(sizeof(*(data)->mechListMIC)); if ((data)->mechListMIC == NULL) return ENOMEM; e = decode_octet_string(p, len, (data)->mechListMIC, &l); FORW; - if (dce_fix) { + if (mydce_fix) { e = der_match_tag_and_length(p, len, (Der_class) 0, (Der_type) 0, 0, &reallen, &l); FORW; } else diff --git a/lib/dns/tkey.c b/lib/dns/tkey.c index 11b4f49eb04b..f46577f01d7b 100644 --- a/lib/dns/tkey.c +++ b/lib/dns/tkey.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -859,7 +859,7 @@ buildquery(dns_message_t *msg, dns_name_t *name, dns_rdataset_t *question = NULL, *tkeyset = NULL; dns_rdatalist_t *tkeylist = NULL; dns_rdata_t *rdata = NULL; - isc_buffer_t *dynbuf = NULL; + isc_buffer_t *dynbuf = NULL, *anamebuf = NULL, *qnamebuf = NULL; isc_result_t result; REQUIRE(msg != NULL); @@ -875,6 +875,8 @@ buildquery(dns_message_t *msg, dns_name_t *name, dns_rdatatype_tkey); RETERR(isc_buffer_allocate(msg->mctx, &dynbuf, 4096)); + RETERR(isc_buffer_allocate(msg->mctx, &anamebuf, DNS_NAME_MAXWIRE)); + RETERR(isc_buffer_allocate(msg->mctx, &qnamebuf, DNS_NAME_MAXWIRE)); RETERR(dns_message_gettemprdata(msg, &rdata)); RETERR(dns_rdata_fromstruct(rdata, dns_rdataclass_any, @@ -894,15 +896,16 @@ buildquery(dns_message_t *msg, dns_name_t *name, RETERR(dns_rdatalist_tordataset(tkeylist, tkeyset)); dns_name_init(qname, NULL); - dns_name_clone(name, qname); + dns_name_copy(name, qname, qnamebuf); dns_name_init(aname, NULL); - dns_name_clone(name, aname); + dns_name_copy(name, aname, anamebuf); ISC_LIST_APPEND(qname->list, question, link); ISC_LIST_APPEND(aname->list, tkeyset, link); dns_message_addname(msg, qname, DNS_SECTION_QUESTION); + dns_message_takebuffer(msg, &qnamebuf); /* * Windows 2000 needs this in the answer section, not the additional @@ -912,6 +915,7 @@ buildquery(dns_message_t *msg, dns_name_t *name, dns_message_addname(msg, aname, DNS_SECTION_ANSWER); else dns_message_addname(msg, aname, DNS_SECTION_ADDITIONAL); + dns_message_takebuffer(msg, &anamebuf); return (ISC_R_SUCCESS); @@ -926,6 +930,10 @@ buildquery(dns_message_t *msg, dns_name_t *name, } if (dynbuf != NULL) isc_buffer_free(&dynbuf); + if (qnamebuf != NULL) + isc_buffer_free(&qnamebuf); + if (anamebuf != NULL) + isc_buffer_free(&anamebuf); printf("buildquery error\n"); return (result); } @@ -1389,6 +1397,7 @@ dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg, dst_key_t *dstkey = NULL; isc_result_t result; unsigned char array[1024]; + isc_boolean_t freertkey = ISC_FALSE; REQUIRE(qmsg != NULL); REQUIRE(rmsg != NULL); @@ -1401,6 +1410,7 @@ dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg, RETERR(find_tkey(rmsg, &tkeyname, &rtkeyrdata, DNS_SECTION_ANSWER)); RETERR(dns_rdata_tostruct(&rtkeyrdata, &rtkey, NULL)); + freertkey = ISC_TRUE; if (win2k == ISC_TRUE) RETERR(find_tkey(qmsg, &tkeyname, &qtkeyrdata, @@ -1453,7 +1463,8 @@ dns_tkey_gssnegotiate(dns_message_t *qmsg, dns_message_t *rmsg, /* * XXXSRA This probably leaks memory from qtkey. */ - dns_rdata_freestruct(&rtkey); + if (freertkey) + dns_rdata_freestruct(&rtkey); if (dstkey != NULL) dst_key_free(&dstkey); return (result); diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c index 1ddca181a4ab..307cb2577b41 100644 --- a/lib/dns/tsig.c +++ b/lib/dns/tsig.c @@ -275,12 +275,12 @@ keyring_add(dns_tsig_keyring_t *ring, dns_name_t *name, } result = dns_rbt_addname(ring->keys, name, tkey); - if (tkey->generated) { + if (result == ISC_R_SUCCESS && tkey->generated) { /* * Add the new key to the LRU list and remove the least * recently used key if there are too many keys on the list. */ - ISC_LIST_INITANDAPPEND(ring->lru, tkey, link); + ISC_LIST_APPEND(ring->lru, tkey, link); if (ring->generated++ > ring->maxgenerated) remove_fromring(ISC_LIST_HEAD(ring->lru)); } @@ -419,6 +419,7 @@ dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm, tkey->expire = expire; tkey->mctx = NULL; isc_mem_attach(mctx, &tkey->mctx); + ISC_LINK_INIT(tkey, link); tkey->magic = TSIG_MAGIC; diff --git a/lib/dns/validator.c b/lib/dns/validator.c index 0b203d882923..565e7e1d62ab 100644 --- a/lib/dns/validator.c +++ b/lib/dns/validator.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -2062,9 +2062,6 @@ validatezonekey(dns_validator_t *val) { "the DNSKEY RRset and also matches a " "trusted key for '%s'", namebuf); - validator_log(val, ISC_LOG_NOTICE, - "please check the 'trusted-keys' for " - "'%s' in named.conf.", namebuf); return (DNS_R_NOVALIDKEY); } diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 5db28449b8f7..fbaeab14c699 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,8 +15,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ - /*! \file */ #include <config.h> @@ -444,6 +442,10 @@ typedef struct { #define DNS_ZONEFLG_LOADPENDING 0x10000000U /*%< Loading scheduled */ #define DNS_ZONEFLG_NODELAY 0x20000000U #define DNS_ZONEFLG_SENDSECURE 0x40000000U +#define DNS_ZONEFLG_NEEDSTARTUPNOTIFY 0x80000000U /*%< need to send out notify + * due to the zone just + * being loaded for the + * first time. */ #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0) #define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0) @@ -482,6 +484,8 @@ struct dns_zonemgr { isc_pool_t * mctxpool; isc_ratelimiter_t * notifyrl; isc_ratelimiter_t * refreshrl; + isc_ratelimiter_t * startupnotifyrl; + isc_ratelimiter_t * startuprefreshrl; isc_rwlock_t rwlock; isc_mutex_t iolock; isc_rwlock_t urlock; @@ -494,7 +498,10 @@ struct dns_zonemgr { /* Configuration data. */ isc_uint32_t transfersin; isc_uint32_t transfersperns; + unsigned int notifyrate; + unsigned int startupnotifyrate; unsigned int serialqueryrate; + unsigned int startupserialqueryrate; /* Locked by iolock */ isc_uint32_t iolimit; @@ -521,9 +528,11 @@ struct dns_notify { isc_sockaddr_t dst; dns_tsigkey_t *key; ISC_LINK(dns_notify_t) link; + isc_event_t *event; }; #define DNS_NOTIFY_NOSOA 0x0001U +#define DNS_NOTIFY_STARTUP 0x0002U /*% * dns_stub holds state while performing a 'stub' transfer. @@ -564,6 +573,7 @@ struct dns_forward { isc_sockaddr_t addr; dns_updatecallback_t callback; void *callback_arg; + unsigned int options; ISC_LINK(dns_forward_t) link; }; @@ -651,6 +661,16 @@ struct dns_asyncload { #define DAY (24*HOUR) #define MONTH (30*DAY) +/* + * These can be overridden by the -T mkeytimers option on the command + * line, so that we can test with shorter periods than specified in + * RFC 5011. + */ +unsigned int dns_zone_mkey_hour = HOUR; +unsigned int dns_zone_mkey_day = (24 * HOUR); +unsigned int dns_zone_mkey_month = (30 * DAY); + + #define SEND_BUFFER_SIZE 2048 static void zone_settimer(dns_zone_t *, isc_time_t *); @@ -742,6 +762,8 @@ static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff); static void zone_rekey(dns_zone_t *zone); static isc_result_t zone_send_securedb(dns_zone_t *zone, dns_db_t *db); +static void setrl(isc_ratelimiter_t *rl, unsigned int *rate, + unsigned int value); #define ENTER zone_debuglog(zone, me, 1, "enter") @@ -2328,6 +2350,8 @@ zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name, DNS_DBFIND_GLUEOK, 0, NULL, foundname, &aaaa, NULL); if (tresult == ISC_R_SUCCESS) { + if (dns_rdataset_isassociated(&a)) + dns_rdataset_disassociate(&a); dns_rdataset_disassociate(&aaaa); return (ISC_TRUE); } @@ -3175,7 +3199,7 @@ check_nsec3param(dns_zone_t *zone, dns_db_t *db) { */ static void set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key, - isc_stdtime_t now) + isc_stdtime_t now, isc_boolean_t force) { const char me[] = "set_refreshkeytimer"; isc_stdtime_t then; @@ -3184,6 +3208,8 @@ set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key, ENTER; then = key->refresh; + if (force) + then = now; if (key->addhd > now && key->addhd < then) then = key->addhd; if (key->removehd > now && key->removehd < then) @@ -3263,8 +3289,9 @@ create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, dst_key_name(key), 0, &rdata)); *changed = ISC_TRUE; + /* Refresh new keys from the zone apex as soon as possible. */ - set_refreshkeytimer(zone, &keydata, now); + set_refreshkeytimer(zone, &keydata, now, ISC_TRUE); skip: result = dns_keytable_nextkeynode(keytable, keynode, &nextnode); @@ -3420,8 +3447,8 @@ load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) { continue; RUNTIME_CHECK(result == ISC_R_SUCCESS); - /* Set the key refresh timer. */ - set_refreshkeytimer(zone, &keydata, now); + /* Set the key refresh timer to force a fast refresh. */ + set_refreshkeytimer(zone, &keydata, now, ISC_TRUE); /* If the removal timer is nonzero, this key was revoked. */ if (keydata.removehd != 0) { @@ -3615,6 +3642,8 @@ failure: if (ver != NULL) dns_db_closeversion(db, &ver, ISC_TF(result == ISC_R_SUCCESS)); + INSIST(ver == NULL); + return (result); } @@ -3687,7 +3716,8 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) { result = dns_keytable_find(sr, rrname, &keynode); if ((result != ISC_R_SUCCESS && result != DNS_R_PARTIALMATCH) || - dns_keynode_managed(keynode) == ISC_FALSE) { + dns_keynode_managed(keynode) == ISC_FALSE) + { CHECK(delete_keydata(db, ver, &diff, rrname, rdataset)); changed = ISC_TRUE; @@ -3777,6 +3807,8 @@ sync_keyzone(dns_zone_t *zone, dns_db_t *db) { dns_db_closeversion(db, &ver, commit); dns_diff_clear(&diff); + INSIST(ver == NULL); + return (result); } @@ -4210,7 +4242,8 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, zone_attachdb(zone, db); ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write); DNS_ZONE_SETFLAG(zone, - DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY); + DNS_ZONEFLG_LOADED| + DNS_ZONEFLG_NEEDSTARTUPNOTIFY); if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) && inline_raw(zone)) { @@ -5383,8 +5416,8 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_rdataset_t rdataset; unsigned int i; dns_rdata_rrsig_t rrsig; - isc_boolean_t found, changed; - isc_int64_t warn = 0, maybe = 0; + isc_boolean_t found; + isc_int64_t timewarn = 0, timemaybe = 0; dns_rdataset_init(&rdataset); @@ -5409,7 +5442,6 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, goto failure; } - changed = ISC_FALSE; for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { @@ -5425,8 +5457,6 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN, name, rdataset.ttl, &rdata); - if (incremental) - changed = ISC_TRUE; if (result != ISC_R_SUCCESS) break; deleted = ISC_TRUE; @@ -5445,7 +5475,6 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, result = offline(db, ver, zonediff, name, rdataset.ttl, &rdata); - changed = ISC_TRUE; if (result != ISC_R_SUCCESS) break; } @@ -5494,22 +5523,23 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, { isc_int64_t timeexpire = dns_time64_from32(rrsig.timeexpire); - if (warn != 0 && warn > timeexpire) - warn = timeexpire; + if (timewarn != 0 && + timewarn > timeexpire) + timewarn = timeexpire; if (rdata.flags & DNS_RDATA_OFFLINE) { - if (maybe == 0 || - maybe > timeexpire) - maybe = timeexpire; + if (timemaybe == 0 || + timemaybe > timeexpire) + timemaybe = timeexpire; break; } - if (warn == 0) - warn = maybe; - if (warn == 0 || warn > timeexpire) - warn = timeexpire; + if (timewarn == 0) + timewarn = timemaybe; + if (timewarn == 0 || + timewarn > timeexpire) + timewarn = timeexpire; result = offline(db, ver, zonediff, name, rdataset.ttl, &rdata); - changed = ISC_TRUE; break; } result = update_one_rr(db, ver, zonediff->diff, @@ -5532,18 +5562,16 @@ del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, break; } - if (changed && (rdataset.attributes & DNS_RDATASETATTR_RESIGN) != 0) - dns_db_resigned(db, &rdataset, ver); - dns_rdataset_disassociate(&rdataset); if (result == ISC_R_NOMORE) result = ISC_R_SUCCESS; - if (warn > 0) { + if (timewarn > 0) { #if defined(STDTIME_ON_32BITS) - isc_stdtime_t stdwarn = (isc_stdtime_t)warn; - if (warn == stdwarn) + isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn; + if (timewarn == stdwarn) #endif - set_key_expiry_warning(zone, (isc_stdtime_t)warn, now); + set_key_expiry_warning(zone, (isc_stdtime_t)timewarn, + now); #if defined(STDTIME_ON_32BITS) else dns_zone_log(zone, ISC_LOG_ERROR, @@ -5769,8 +5797,7 @@ zone_resigninc(dns_zone_t *zone) { dns_result_totext(result)); break; } - result = dns_db_getsigningtime(db, &rdataset, - dns_fixedname_name(&fixed)); + result = dns_db_getsigningtime(db, &rdataset, name); if (nkeys == 0 && result == ISC_R_NOTFOUND) { result = ISC_R_SUCCESS; break; @@ -5857,6 +5884,8 @@ zone_resigninc(dns_zone_t *zone) { isc_interval_set(&ival, 300, 0); isc_time_nowplusinterval(&zone->resigntime, &ival); } + + INSIST(version == NULL); } static isc_result_t @@ -7331,15 +7360,17 @@ zone_nsec3chain(dns_zone_t *zone) { LOCK_ZONE(zone); if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) { - isc_interval_t i; + isc_interval_t interval; if (zone->update_disabled || result != ISC_R_SUCCESS) - isc_interval_set(&i, 60, 0); /* 1 minute */ + isc_interval_set(&interval, 60, 0); /* 1 minute */ else - isc_interval_set(&i, 0, 10000000); /* 10 ms */ - isc_time_nowplusinterval(&zone->nsec3chaintime, &i); + isc_interval_set(&interval, 0, 10000000); /* 10 ms */ + isc_time_nowplusinterval(&zone->nsec3chaintime, &interval); } else isc_time_settoepoch(&zone->nsec3chaintime); UNLOCK_ZONE(zone); + + INSIST(version == NULL); } static isc_result_t @@ -7879,19 +7910,22 @@ zone_sign(dns_zone_t *zone) { dns_db_detach(&db); if (ISC_LIST_HEAD(zone->signing) != NULL) { - isc_interval_t i; + isc_interval_t interval; if (zone->update_disabled || result != ISC_R_SUCCESS) - isc_interval_set(&i, 60, 0); /* 1 minute */ + isc_interval_set(&interval, 60, 0); /* 1 minute */ else - isc_interval_set(&i, 0, 10000000); /* 10 ms */ - isc_time_nowplusinterval(&zone->signingtime, &i); + isc_interval_set(&interval, 0, 10000000); /* 10 ms */ + isc_time_nowplusinterval(&zone->signingtime, &interval); } else isc_time_settoepoch(&zone->signingtime); + + INSIST(version == NULL); } static isc_result_t normalize_key(dns_rdata_t *rr, dns_rdata_t *target, - unsigned char *data, int size) { + unsigned char *data, int size) +{ dns_rdata_dnskey_t dnskey; dns_rdata_keydata_t keydata; isc_buffer_t buf; @@ -7988,11 +8022,11 @@ refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) { if (dns_rdataset_isassociated(&kfetch->dnskeysigset)) rdset = &kfetch->dnskeysigset; else - return (now + HOUR); + return (now + dns_zone_mkey_hour); result = dns_rdataset_first(rdset); if (result != ISC_R_SUCCESS) - return (now + HOUR); + return (now + dns_zone_mkey_hour); dns_rdataset_current(rdset, &sigrr); result = dns_rdata_tostruct(&sigrr, &sig, NULL); @@ -8007,11 +8041,11 @@ refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) { t = exp; } - if (t > (15*DAY)) - t = (15*DAY); + if (t > (15 * dns_zone_mkey_day)) + t = (15 * dns_zone_mkey_day); - if (t < HOUR) - t = HOUR; + if (t < dns_zone_mkey_hour) + t = dns_zone_mkey_hour; } else { t = sig.originalttl / 10; @@ -8021,11 +8055,11 @@ refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) { t = exp; } - if (t > DAY) - t = DAY; + if (t > dns_zone_mkey_day) + t = dns_zone_mkey_day; - if (t < HOUR) - t = HOUR; + if (t < dns_zone_mkey_hour) + t = dns_zone_mkey_hour; } return (now + t); @@ -8068,7 +8102,7 @@ minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff) if (result != ISC_R_SUCCESS) goto failure; keydata.refresh = refresh_time(kfetch, ISC_TRUE); - set_refreshkeytimer(zone, &keydata, now); + set_refreshkeytimer(zone, &keydata, now, ISC_FALSE); dns_rdata_reset(&rdata); isc_buffer_init(&keyb, key_buf, sizeof(key_buf)); @@ -8111,8 +8145,8 @@ revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) { /* Generate a key from keydata */ isc_buffer_init(&keyb, key_buf, sizeof(key_buf)); dns_keydata_todnskey(keydata, &dnskey, NULL); - dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey, - &dnskey, &keyb); + dns_rdata_fromstruct(&rr, keydata->common.rdclass, + dns_rdatatype_dnskey, &dnskey, &keyb); result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey); if (result != ISC_R_SUCCESS) return (ISC_FALSE); @@ -8120,7 +8154,8 @@ revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) { /* See if that key generated any of the signatures */ for (result = dns_rdataset_first(&kfetch->dnskeysigset); result == ISC_R_SUCCESS; - result = dns_rdataset_next(&kfetch->dnskeysigset)) { + result = dns_rdataset_next(&kfetch->dnskeysigset)) + { dns_fixedname_t fixed; dns_fixedname_init(&fixed); @@ -8130,8 +8165,8 @@ revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) { RUNTIME_CHECK(result == ISC_R_SUCCESS); if (dst_key_alg(dstkey) == sig.algorithm && - (dst_key_id(dstkey) == sig.keyid || - dst_key_rid(dstkey) == sig.keyid)) { + dst_key_rid(dstkey) == sig.keyid) + { result = dns_dnssec_verify2(keyname, &kfetch->dnskeyset, dstkey, ISC_FALSE, mctx, &sigrr, @@ -8246,6 +8281,12 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { } /* + * Clear any cached trust level, as we need to run validation + * over again; trusted keys might have changed. + */ + kfetch->dnskeyset.trust = kfetch->dnskeysigset.trust = dns_trust_none; + + /* * Validate the dnskeyset against the current trusted keys. */ for (result = dns_rdataset_first(&kfetch->dnskeysigset); @@ -8278,7 +8319,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { dns_zone_log(zone, ISC_LOG_DEBUG(3), "Verifying DNSKEY set for zone " - "'%s': %s", namebuf, + "'%s' using key %d/%d: %s", + namebuf, sig.keyid, sig.algorithm, dns_result_totext(result)); if (result == ISC_R_SUCCESS) { @@ -8286,8 +8328,6 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { dns_trust_secure; kfetch->dnskeysigset.trust = dns_trust_secure; - dns_keytable_detachkeynode(secroots, - &keynode); break; } } @@ -8298,6 +8338,9 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { keynode = nextnode; } + if (keynode != NULL) + dns_keytable_detachkeynode(secroots, &keynode); + if (kfetch->dnskeyset.trust == dns_trust_secure) break; } @@ -8342,31 +8385,34 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { isc_boolean_t deletekey = ISC_FALSE; if (!secure) { - if (now > keydata.removehd) + if (keydata.removehd != 0 && + keydata.removehd <= now) deletekey = ISC_TRUE; - } else if (now < keydata.addhd) { + } else if (keydata.addhd == 0) { + deletekey = ISC_TRUE; + } else if (keydata.addhd > now) { dns_zone_log(zone, ISC_LOG_WARNING, "Pending key unexpectedly missing " "from %s; restarting acceptance " "timer", namebuf); - keydata.addhd = now + MONTH; + if (keydata.addhd < now + dns_zone_mkey_month) + keydata.addhd = + now + dns_zone_mkey_month; keydata.refresh = refresh_time(kfetch, ISC_FALSE); - } else if (keydata.addhd == 0) { - keydata.addhd = now; } else if (keydata.removehd == 0) { dns_zone_log(zone, ISC_LOG_WARNING, "Active key unexpectedly missing " "from %s", namebuf); - keydata.refresh = now + HOUR; - } else if (now > keydata.removehd) { + keydata.refresh = now + dns_zone_mkey_hour; + } else if (keydata.removehd <= now) { deletekey = ISC_TRUE; } else { keydata.refresh = refresh_time(kfetch, ISC_FALSE); } - if (secure || deletekey) { + if (secure || deletekey) { /* Delete old version */ CHECK(update_one_rr(kfetch->db, ver, &diff, DNS_DIFFOP_DEL, keyname, 0, @@ -8387,7 +8433,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { DNS_DIFFOP_ADD, keyname, 0, &keydatarr)); - set_refreshkeytimer(zone, &keydata, now); + set_refreshkeytimer(zone, &keydata, now, ISC_FALSE); } } @@ -8409,7 +8455,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { */ for (result = dns_rdataset_first(&kfetch->dnskeyset); result == ISC_R_SUCCESS; - result = dns_rdataset_next(&kfetch->dnskeyset)) { + result = dns_rdataset_next(&kfetch->dnskeyset)) + { isc_boolean_t revoked = ISC_FALSE; isc_boolean_t newkey = ISC_FALSE; isc_boolean_t updatekey = ISC_FALSE; @@ -8445,34 +8492,43 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { dns_view_untrust(zone->view, keyname, &dnskey, mctx); + /* But ensure there's a null key */ + fail_secure(zone, keyname); + /* If initializing, delete now */ if (keydata.addhd == 0) deletekey = ISC_TRUE; - else - keydata.removehd = now + MONTH; + else { + keydata.removehd = now + + dns_zone_mkey_month; + keydata.flags |= + DNS_KEYFLAG_REVOKE; + } } else if (keydata.removehd < now) { /* Scheduled for removal */ deletekey = ISC_TRUE; } - } else if (revoked) { - if (secure && keydata.removehd == 0) { - dns_zone_log(zone, ISC_LOG_WARNING, - "Active key for zone " - "'%s' is revoked but " - "did not self-sign; " - "ignoring.", namebuf); - continue; - } + } else if (revoked && keydata.removehd == 0) { + dns_zone_log(zone, ISC_LOG_WARNING, + "Active key for zone " + "'%s' is revoked but " + "did not self-sign; " + "ignoring.", namebuf); + continue; } else if (secure) { if (keydata.removehd != 0) { /* * Key isn't revoked--but it * seems it used to be. * Remove it now and add it - * back as if it were a fresh key. + * back as if it were a fresh key, + * with a 30 day acceptance timer. */ deletekey = ISC_TRUE; newkey = ISC_TRUE; + keydata.removehd = 0; + keydata.addhd = + now + dns_zone_mkey_month; } else if (keydata.addhd > now) pending++; else if (keydata.addhd == 0) @@ -8480,6 +8536,13 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { if (keydata.addhd <= now) trustkey = ISC_TRUE; + } else if (keydata.addhd > now) { + /* + * Not secure, and key is pending: + * reset the acceptance timer + */ + pending++; + keydata.addhd = now + dns_zone_mkey_month; } if (!deletekey && !newkey) @@ -8541,7 +8604,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { RUNTIME_CHECK(result == ISC_R_SUCCESS); dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0, NULL); - keydata.addhd = initializing ? now : now + MONTH; + keydata.addhd = initializing + ? now : now + dns_zone_mkey_month; keydata.refresh = refresh_time(kfetch, ISC_FALSE); dns_rdata_reset(&keydatarr); isc_buffer_init(&keyb, key_buf, sizeof(key_buf)); @@ -8564,7 +8628,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { if (secure && !deletekey) { INSIST(newkey || updatekey); - set_refreshkeytimer(zone, &keydata, now); + set_refreshkeytimer(zone, &keydata, now, ISC_FALSE); } } @@ -8593,7 +8657,7 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { zone_needdump(zone, 30); } - failure: + failure: dns_diff_clear(&diff); if (ver != NULL) @@ -8624,6 +8688,8 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { UNLOCK_ZONE(zone); if (free_needed) zone_free(zone); + + INSIST(ver == NULL); } /* @@ -8776,7 +8842,7 @@ zone_refreshkeys(dns_zone_t *zone) { char timebuf[80]; TIME_NOW(&timenow); - DNS_ZONE_TIME_ADD(&timenow, HOUR, &timethen); + DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen); zone->refreshkeytime = timethen; zone_settimer(zone, &timenow); @@ -8796,6 +8862,8 @@ zone_refreshkeys(dns_zone_t *zone) { dns_db_closeversion(db, &ver, commit); } dns_db_detach(&db); + + INSIST(ver == NULL); } static void @@ -8868,7 +8936,8 @@ zone_maintenance(dns_zone_t *zone) { * Slaves send notifies before backing up to disk, masters after. */ if (zone->type == dns_zone_slave && - DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) && + (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) || + DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) && isc_time_compare(&now, &zone->notifytime) >= 0) zone_notify(zone, &now); @@ -8908,7 +8977,8 @@ zone_maintenance(dns_zone_t *zone) { switch (zone->type) { case dns_zone_master: case dns_zone_redirect: - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) && + if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) || + DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))&& isc_time_compare(&now, &zone->notifytime) >= 0) zone_notify(zone, &now); default: @@ -9537,21 +9607,51 @@ dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) { } static isc_boolean_t -notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) { +notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name, + isc_sockaddr_t *addr, dns_tsigkey_t *key) +{ dns_notify_t *notify; + dns_zonemgr_t *zmgr; + isc_result_t result; for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL; notify = ISC_LIST_NEXT(notify, link)) { if (notify->request != NULL) continue; + if ((flags & DNS_NOTIFY_STARTUP) == 0) + notify->flags &= ~DNS_NOTIFY_STARTUP; if (name != NULL && dns_name_dynamic(¬ify->ns) && dns_name_equal(name, ¬ify->ns)) - return (ISC_TRUE); - if (addr != NULL && isc_sockaddr_equal(addr, ¬ify->dst)) - return (ISC_TRUE); + goto requeue; + if (addr != NULL && isc_sockaddr_equal(addr, ¬ify->dst) && + notify->key == key) + goto requeue; } return (ISC_FALSE); + +requeue: + /* + * If we are enqueued on the startup ratelimiter and this is + * not a startup notify, re-enqueue on the normal notify + * ratelimiter. + */ + if (notify->event != NULL && (flags & DNS_NOTIFY_STARTUP) == 0) { + zmgr = notify->zone->zmgr; + result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl, + notify->event); + if (result != ISC_R_SUCCESS) + return (ISC_TRUE); + result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl, + notify->zone->task, + ¬ify->event); + if (result != ISC_R_SUCCESS) { + isc_event_free(¬ify->event); + return (ISC_FALSE); + } + } + + return (ISC_TRUE); } static isc_boolean_t @@ -9649,6 +9749,7 @@ notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) { notify->find = NULL; notify->request = NULL; notify->key = NULL; + notify->event = NULL; isc_sockaddr_any(¬ify->dst); dns_name_init(¬ify->ns, NULL); ISC_LINK_INIT(notify, link); @@ -9724,22 +9825,27 @@ notify_find_address(dns_notify_t *notify) { static isc_result_t -notify_send_queue(dns_notify_t *notify) { +notify_send_queue(dns_notify_t *notify, isc_boolean_t startup) { isc_event_t *e; isc_result_t result; - e = isc_event_allocate(notify->mctx, NULL, - DNS_EVENT_NOTIFYSENDTOADDR, - notify_send_toaddr, - notify, sizeof(isc_event_t)); + INSIST(notify->event == NULL); + e = isc_event_allocate(notify->mctx, NULL, DNS_EVENT_NOTIFYSENDTOADDR, + notify_send_toaddr, notify, sizeof(isc_event_t)); if (e == NULL) return (ISC_R_NOMEMORY); + if (startup) + notify->event = e; e->ev_arg = notify; e->ev_sender = NULL; - result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl, + result = isc_ratelimiter_enqueue(startup + ? notify->zone->zmgr->startupnotifyrl + : notify->zone->zmgr->notifyrl, notify->zone->task, &e); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) { isc_event_free(&e); + notify->event = NULL; + } return (result); } @@ -9762,6 +9868,8 @@ notify_send_toaddr(isc_task_t *task, isc_event_t *event) { LOCK_ZONE(notify->zone); + notify->event = NULL; + if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) { result = ISC_R_CANCELED; goto cleanup; @@ -9871,6 +9979,8 @@ notify_send(dns_notify_t *notify) { isc_sockaddr_t dst; isc_result_t result; dns_notify_t *new = NULL; + unsigned int flags; + isc_boolean_t startup; /* * Zone lock held by caller. @@ -9882,20 +9992,21 @@ notify_send(dns_notify_t *notify) { ai != NULL; ai = ISC_LIST_NEXT(ai, publink)) { dst = ai->sockaddr; - if (notify_isqueued(notify->zone, NULL, &dst)) + if (notify_isqueued(notify->zone, notify->flags, NULL, &dst, + NULL)) continue; if (notify_isself(notify->zone, &dst)) continue; new = NULL; - result = notify_create(notify->mctx, - (notify->flags & DNS_NOTIFY_NOSOA), - &new); + flags = notify->flags & DNS_NOTIFY_NOSOA; + result = notify_create(notify->mctx, flags, &new); if (result != ISC_R_SUCCESS) goto cleanup; zone_iattach(notify->zone, &new->zone); ISC_LIST_APPEND(new->zone->notifies, new, link); new->dst = dst; - result = notify_send_queue(new); + startup = ISC_TF((notify->flags & DNS_NOTIFY_STARTUP) != 0); + result = notify_send_queue(new, startup); if (result != ISC_R_SUCCESS) goto cleanup; new = NULL; @@ -9934,18 +10045,20 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { dns_rdataset_t nsrdset; dns_rdataset_t soardset; isc_result_t result; - dns_notify_t *notify = NULL; unsigned int i; isc_sockaddr_t dst; isc_boolean_t isqueued; dns_notifytype_t notifytype; unsigned int flags = 0; isc_boolean_t loggednotify = ISC_FALSE; + isc_boolean_t startup; REQUIRE(DNS_ZONE_VALID(zone)); LOCK_ZONE(zone); + startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY); DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY); + DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY); notifytype = zone->notifytype; DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime); UNLOCK_ZONE(zone); @@ -9970,6 +10083,12 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { flags |= DNS_NOTIFY_NOSOA; /* + * Record that this was a notify due to starting up. + */ + if (startup) + flags |= DNS_NOTIFY_STARTUP; + + /* * Get SOA RRset. */ ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); @@ -10012,31 +10131,41 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { LOCK_ZONE(zone); for (i = 0; i < zone->notifycnt; i++) { dns_tsigkey_t *key = NULL; + dns_notify_t *notify = NULL; + + if ((zone->notifykeynames != NULL) && + (zone->notifykeynames[i] != NULL)) { + dns_view_t *view = dns_zone_getview(zone); + dns_name_t *keyname = zone->notifykeynames[i]; + (void)dns_view_gettsig(view, keyname, &key); + } dst = zone->notify[i]; - if (notify_isqueued(zone, NULL, &dst)) + if (notify_isqueued(zone, flags, NULL, &dst, key)) { + if (key != NULL) + dns_tsigkey_detach(&key); continue; + } result = notify_create(zone->mctx, flags, ¬ify); - if (result != ISC_R_SUCCESS) + if (result != ISC_R_SUCCESS) { + if (key != NULL) + dns_tsigkey_detach(&key); continue; + } zone_iattach(zone, ¬ify->zone); notify->dst = dst; - if ((zone->notifykeynames != NULL) && - (zone->notifykeynames[i] != NULL)) { - dns_view_t *view = dns_zone_getview(zone); - dns_name_t *keyname = zone->notifykeynames[i]; - result = dns_view_gettsig(view, keyname, &key); - if (result == ISC_R_SUCCESS) { - notify->key = key; - key = NULL; - } + INSIST(notify->key == NULL); + + if (key != NULL) { + notify->key = key; + key = NULL; } ISC_LIST_APPEND(zone->notifies, notify, link); - result = notify_send_queue(notify); + result = notify_send_queue(notify, startup); if (result != ISC_R_SUCCESS) notify_destroy(notify, ISC_TRUE); if (!loggednotify) { @@ -10045,7 +10174,6 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { serial); loggednotify = ISC_TRUE; } - notify = NULL; } UNLOCK_ZONE(zone); @@ -10064,6 +10192,8 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { result = dns_rdataset_first(&nsrdset); while (result == ISC_R_SUCCESS) { + dns_notify_t *notify = NULL; + dns_rdataset_current(&nsrdset, &rdata); result = dns_rdata_tostruct(&rdata, &ns, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); @@ -10086,7 +10216,7 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { } LOCK_ZONE(zone); - isqueued = notify_isqueued(zone, &ns.name, NULL); + isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL); UNLOCK_ZONE(zone); if (isqueued) { result = dns_rdataset_next(&nsrdset); @@ -10107,7 +10237,6 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) { ISC_LIST_APPEND(zone->notifies, notify, link); UNLOCK_ZONE(zone); notify_find_address(notify); - notify = NULL; result = dns_rdataset_next(&nsrdset); } dns_rdataset_disassociate(&nsrdset); @@ -10715,12 +10844,12 @@ refresh_callback(isc_task_t *task, isc_event_t *event) { serial = soa.serial; if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) { - unsigned int soacount; - result = zone_get_from_db(zone, zone->db, NULL, &soacount, + unsigned int dbsoacount; + result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount, &oldserial, NULL, NULL, NULL, NULL, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); - RUNTIME_CHECK(soacount > 0U); + RUNTIME_CHECK(dbsoacount > 0U); zone_debuglog(zone, me, 1, "serial: new %u, old %u", serial, oldserial); } else @@ -11004,14 +11133,11 @@ soa_query(isc_task_t *task, isc_event_t *event) { goto cleanup; } - /* - * XXX Optimisation: Create message when zone is setup and reuse. - */ + again: result = create_query(zone, dns_rdatatype_soa, &message); if (result != ISC_R_SUCCESS) goto cleanup; - again: INSIST(zone->masterscnt > 0); INSIST(zone->curmaster < zone->masterscnt); @@ -11116,9 +11242,9 @@ soa_query(isc_task_t *task, isc_event_t *event) { if (result != ISC_R_SUCCESS) { zone_idetach(&dummy); zone_debuglog(zone, me, 1, - "dns_request_createvia2() failed: %s", + "dns_request_createvia4() failed: %s", dns_result_totext(result)); - goto cleanup; + goto skip_master; } else { if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET) inc_stats(zone, dns_zonestatscounter_soaoutv4); @@ -11144,6 +11270,7 @@ soa_query(isc_task_t *task, isc_event_t *event) { skip_master: if (key != NULL) dns_tsigkey_detach(&key); + dns_message_destroy(&message); /* * Skip to next failed / untried master. */ @@ -11526,7 +11653,8 @@ zone_settimer(dns_zone_t *zone, isc_time_t *now) { /* FALLTHROUGH */ case dns_zone_master: - if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY)) + if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) || + DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) next = zone->notifytime; if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) { @@ -12586,9 +12714,12 @@ notify_done(isc_task_t *task, isc_event_t *event) { isc_event_free(&event); if (message != NULL && message->rcode == dns_rcode_formerr && (notify->flags & DNS_NOTIFY_NOSOA) == 0) { + isc_boolean_t startup; + notify->flags |= DNS_NOTIFY_NOSOA; dns_request_destroy(¬ify->request); - result = notify_send_queue(notify); + startup = ISC_TF((notify->flags & DNS_NOTIFY_STARTUP) != 0); + result = notify_send_queue(notify, startup); if (result != ISC_R_SUCCESS) notify_destroy(notify, ISC_FALSE); } else { @@ -12614,7 +12745,7 @@ update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) { } static isc_result_t -sync_secure_journal(dns_zone_t *zone, dns_journal_t *journal, +sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal, isc_uint32_t start, isc_uint32_t end, dns_difftuple_t **soatuplep, dns_diff_t *diff) { @@ -12658,9 +12789,9 @@ sync_secure_journal(dns_zone_t *zone, dns_journal_t *journal, /* Sanity. */ if (n_soa == 0) { - dns_zone_log(zone->raw, ISC_LOG_ERROR, + dns_zone_log(raw, ISC_LOG_ERROR, "corrupt journal file: '%s'\n", - zone->raw->journal); + raw->journal); return (ISC_R_FAILURE); } @@ -12689,7 +12820,7 @@ sync_secure_journal(dns_zone_t *zone, dns_journal_t *journal, } static isc_result_t -sync_secure_db(dns_zone_t *seczone, dns_db_t *secdb, +sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb, dns_dbversion_t *secver, dns_difftuple_t **soatuple, dns_diff_t *diff) { @@ -12701,13 +12832,12 @@ sync_secure_db(dns_zone_t *seczone, dns_db_t *secdb, dns_rdata_soa_t oldsoa, newsoa; REQUIRE(DNS_ZONE_VALID(seczone)); - REQUIRE(inline_secure(seczone)); REQUIRE(soatuple != NULL && *soatuple == NULL); if (!seczone->sourceserialset) return (DNS_R_UNCHANGED); - dns_db_attach(seczone->raw->db, &rawdb); + dns_db_attach(raw->db, &rawdb); dns_db_currentversion(rawdb, &rawver); result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL); dns_db_closeversion(rawdb, &rawver, ISC_FALSE); @@ -12794,7 +12924,7 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) { isc_result_t result; dns_journal_t *rjournal = NULL; isc_uint32_t start, end; - dns_zone_t *zone; + dns_zone_t *zone, *raw = NULL; dns_db_t *db = NULL; dns_dbversion_t *newver = NULL, *oldver = NULL; dns_diff_t diff; @@ -12819,10 +12949,14 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) { dns_db_attach(zone->db, &db); ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); + if (zone->raw != NULL) + dns_zone_attach(zone->raw, &raw); + UNLOCK_ZONE(zone); + /* * zone->db may be NULL if the load from disk failed. */ - if (db == NULL || !inline_secure(zone)) { + if (db == NULL || raw == NULL) { result = ISC_R_FAILURE; goto failure; } @@ -12836,7 +12970,7 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) { * If that fails, then we'll fall back to a direct comparison * between raw and secure zones. */ - result = dns_journal_open(zone->raw->mctx, zone->raw->journal, + result = dns_journal_open(raw->mctx, raw->journal, DNS_JOURNAL_WRITE, &rjournal); if (result != ISC_R_SUCCESS) goto failure; @@ -12875,12 +13009,12 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) { * zone. If that fails, we recover by syncing up the databases * directly. */ - result = sync_secure_journal(zone, rjournal, start, end, + result = sync_secure_journal(zone, raw, rjournal, start, end, &soatuple, &diff); if (result == DNS_R_UNCHANGED) goto failure; else if (result != ISC_R_SUCCESS) - CHECK(sync_secure_db(zone, db, oldver, &soatuple, &diff)); + CHECK(sync_secure_db(zone, raw, db, oldver, &soatuple, &diff)); CHECK(dns_diff_apply(&diff, db, newver)); @@ -12913,6 +13047,7 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) { dns_journal_set_sourceserial(rjournal, end); dns_journal_commit(rjournal); + LOCK_ZONE(zone); DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY); zone->sourceserial = end; @@ -12921,12 +13056,14 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) { TIME_NOW(&timenow); zone_settimer(zone, &timenow); + UNLOCK_ZONE(zone); dns_db_closeversion(db, &oldver, ISC_FALSE); dns_db_closeversion(db, &newver, ISC_TRUE); failure: - UNLOCK_ZONE(zone); + if (raw != NULL) + dns_zone_detach(&raw); if (result != ISC_R_SUCCESS) dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_serial: %s", dns_result_totext(result)); @@ -12945,6 +13082,9 @@ receive_secure_serial(isc_task_t *task, isc_event_t *event) { dns_journal_destroy(&rjournal); dns_diff_clear(&diff); dns_zone_idetach(&zone); + + INSIST(oldver == NULL); + INSIST(newver == NULL); } static isc_result_t @@ -13380,6 +13520,8 @@ receive_secure_db(isc_task_t *task, isc_event_t *event) { if (db != NULL) { if (node != NULL) dns_db_detachnode(db, &node); + if (version != NULL) + dns_db_closeversion(db, &version, ISC_FALSE); dns_db_detach(&db); } if (rawnode != NULL) @@ -13388,6 +13530,8 @@ receive_secure_db(isc_task_t *task, isc_event_t *event) { if (dbiterator != NULL) dns_dbiterator_destroy(&dbiterator); dns_zone_idetach(&zone); + + INSIST(version == NULL); } static isc_result_t @@ -14288,7 +14432,7 @@ sendtomaster(dns_forward_t *forward) { result = dns_request_createraw(forward->zone->view->requestmgr, forward->msgbuf, &src, &forward->addr, - DNS_REQUESTOPT_TCP, 15 /* XXX */, + forward->options, 15 /* XXX */, forward->zone->task, forward_callback, forward, &forward->request); @@ -14435,6 +14579,13 @@ dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg, forward->callback_arg = callback_arg; ISC_LINK_INIT(forward, link); forward->magic = FORWARD_MAGIC; + forward->options = DNS_REQUESTOPT_TCP; + /* + * If we have a SIG(0) signed message we need to preserve the + * query id as that is included in the SIG(0) computation. + */ + if (msg->sig0 != NULL) + forward->options |= DNS_REQUESTOPT_FIXEDID; mr = dns_message_getrawmessage(msg); if (mr == NULL) { @@ -14495,7 +14646,6 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, { dns_zonemgr_t *zmgr; isc_result_t result; - isc_interval_t interval; zmgr = isc_mem_get(mctx, sizeof(*zmgr)); if (zmgr == NULL) @@ -14512,6 +14662,8 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, zmgr->task = NULL; zmgr->notifyrl = NULL; zmgr->refreshrl = NULL; + zmgr->startupnotifyrl = NULL; + zmgr->startuprefreshrl = NULL; ISC_LIST_INIT(zmgr->zones); ISC_LIST_INIT(zmgr->waiting_for_xfrin); ISC_LIST_INIT(zmgr->xfrin_in_progress); @@ -14544,15 +14696,21 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, if (result != ISC_R_SUCCESS) goto free_notifyrl; - /* default to 20 refresh queries / notifies per second. */ - isc_interval_set(&interval, 0, 1000000000/2); - result = isc_ratelimiter_setinterval(zmgr->notifyrl, &interval); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - isc_ratelimiter_setpertic(zmgr->notifyrl, 10); + result = isc_ratelimiter_create(mctx, timermgr, zmgr->task, + &zmgr->startupnotifyrl); + if (result != ISC_R_SUCCESS) + goto free_refreshrl; - result = isc_ratelimiter_setinterval(zmgr->refreshrl, &interval); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - isc_ratelimiter_setpertic(zmgr->refreshrl, 10); + result = isc_ratelimiter_create(mctx, timermgr, zmgr->task, + &zmgr->startuprefreshrl); + if (result != ISC_R_SUCCESS) + goto free_startupnotifyrl; + + /* default to 20 refresh queries / notifies per second. */ + setrl(zmgr->notifyrl, &zmgr->notifyrate, 20); + setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20); + setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20); + setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20); zmgr->iolimit = 1; zmgr->ioactive = 0; @@ -14561,7 +14719,7 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, result = isc_mutex_init(&zmgr->iolock); if (result != ISC_R_SUCCESS) - goto free_refreshrl; + goto free_startuprefreshrl; zmgr->magic = ZONEMGR_MAGIC; @@ -14572,6 +14730,10 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, free_iolock: DESTROYLOCK(&zmgr->iolock); #endif + free_startuprefreshrl: + isc_ratelimiter_detach(&zmgr->startuprefreshrl); + free_startupnotifyrl: + isc_ratelimiter_detach(&zmgr->startupnotifyrl); free_refreshrl: isc_ratelimiter_detach(&zmgr->refreshrl); free_notifyrl: @@ -14775,6 +14937,8 @@ dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) { isc_ratelimiter_shutdown(zmgr->notifyrl); isc_ratelimiter_shutdown(zmgr->refreshrl); + isc_ratelimiter_shutdown(zmgr->startupnotifyrl); + isc_ratelimiter_shutdown(zmgr->startuprefreshrl); if (zmgr->task != NULL) isc_task_destroy(&zmgr->task); @@ -14908,6 +15072,8 @@ zonemgr_free(dns_zonemgr_t *zmgr) { DESTROYLOCK(&zmgr->iolock); isc_ratelimiter_detach(&zmgr->notifyrl); isc_ratelimiter_detach(&zmgr->refreshrl); + isc_ratelimiter_detach(&zmgr->startupnotifyrl); + isc_ratelimiter_detach(&zmgr->startuprefreshrl); isc_rwlock_destroy(&zmgr->urlock); isc_rwlock_destroy(&zmgr->rwlock); @@ -15270,15 +15436,13 @@ dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) { } #endif -void -dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) { +static void +setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) { isc_interval_t interval; isc_uint32_t s, ns; isc_uint32_t pertic; isc_result_t result; - REQUIRE(DNS_ZONEMGR_VALID(zmgr)); - if (value == 0) value = 1; @@ -15298,15 +15462,26 @@ dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) { isc_interval_set(&interval, s, ns); - result = isc_ratelimiter_setinterval(zmgr->notifyrl, &interval); + result = isc_ratelimiter_setinterval(rl, &interval); RUNTIME_CHECK(result == ISC_R_SUCCESS); - isc_ratelimiter_setpertic(zmgr->notifyrl, pertic); + isc_ratelimiter_setpertic(rl, pertic); - result = isc_ratelimiter_setinterval(zmgr->refreshrl, &interval); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - isc_ratelimiter_setpertic(zmgr->refreshrl, pertic); + *rate = value; +} - zmgr->serialqueryrate = value; +void +dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) { + + REQUIRE(DNS_ZONEMGR_VALID(zmgr)); + + setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value); + + /* Seperately controlled in BIND 9.11.x */ + setrl(zmgr->notifyrl, &zmgr->notifyrate, 20); + setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20); + + /* XXXMPA seperate out once we have the code to support this. */ + setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value); } unsigned int @@ -16627,6 +16802,8 @@ zone_rekey(dns_zone_t *zone) { dns_db_detachnode(db, &node); if (db != NULL) dns_db_detach(&db); + + INSIST(ver == NULL); return; failure: @@ -16964,6 +17141,9 @@ keydone(isc_task_t *task, isc_event_t *event) { dns_diff_clear(&diff); isc_event_free(&event); dns_zone_idetach(&zone); + + INSIST(oldver == NULL); + INSIST(newver == NULL); } isc_result_t @@ -17199,6 +17379,9 @@ setnsec3param(isc_task_t *task, isc_event_t *event) { dns_diff_clear(&diff); isc_event_free(&event); dns_zone_idetach(&zone); + + INSIST(oldver == NULL); + INSIST(newver == NULL); } isc_result_t diff --git a/lib/dns/zt.c b/lib/dns/zt.c index eb1e42472475..33c974b1d972 100644 --- a/lib/dns/zt.c +++ b/lib/dns/zt.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2011, 2012, 2014 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -396,16 +396,16 @@ freezezones(dns_zone_t *zone, void *uap) { result = DNS_R_FROZEN; if (result == ISC_R_SUCCESS) result = dns_zone_flush(zone); + if (result == ISC_R_SUCCESS) + dns_zone_setupdatedisabled(zone, freeze); } else { if (frozen) { - result = dns_zone_load(zone); + result = dns_zone_loadandthaw(zone); if (result == DNS_R_CONTINUE || result == DNS_R_UPTODATE) result = ISC_R_SUCCESS; } } - if (result == ISC_R_SUCCESS) - dns_zone_setupdatedisabled(zone, freeze); view = dns_zone_getview(zone); if (strcmp(view->name, "_bind") == 0 || strcmp(view->name, "_default") == 0) |
