diff options
Diffstat (limited to 'lib/dns')
61 files changed, 2257 insertions, 490 deletions
diff --git a/lib/dns/Makefile.in b/lib/dns/Makefile.in index a3e3e9a4e86a..eec4c9ef0e77 100644 --- a/lib/dns/Makefile.in +++ b/lib/dns/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC") # Copyright (C) 1998-2003 Internet Software Consortium. # # Permission to use, copy, modify, and/or distribute this software for any @@ -142,7 +142,7 @@ installdirs: $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${libdir} install:: timestamp installdirs - ${LIBTOOL_MODE_INSTALL} ${INSTALL_DATA} libdns.@A@ ${DESTDIR}${libdir} + ${LIBTOOL_MODE_INSTALL} ${INSTALL_LIBRARY} libdns.@A@ ${DESTDIR}${libdir} clean distclean:: rm -f libdns.@A@ timestamp diff --git a/lib/dns/acl.c b/lib/dns/acl.c index dbc6f9cb4f3a..8d3718a22b27 100644 --- a/lib/dns/acl.c +++ b/lib/dns/acl.c @@ -290,6 +290,9 @@ dns_acl_merge(dns_acl_t *dest, dns_acl_t *source, isc_boolean_t pos) if (newmem == NULL) return (ISC_R_NOMEMORY); + /* Zero. */ + memset(newmem, 0, newalloc * sizeof(dns_aclelement_t)); + /* Copy in the original elements */ memmove(newmem, dest->elements, dest->length * sizeof(dns_aclelement_t)); diff --git a/lib/dns/adb.c b/lib/dns/adb.c index 10d51bc44143..c75ea59f751f 100644 --- a/lib/dns/adb.c +++ b/lib/dns/adb.c @@ -15,8 +15,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: adb.c,v 1.264 2011/12/05 17:10:51 each Exp $ */ - /*! \file * * \note @@ -157,7 +155,7 @@ struct dns_adb { unsigned int *entry_refcnt; isc_event_t cevent; - isc_boolean_t cevent_sent; + isc_boolean_t cevent_out; isc_boolean_t shutting_down; isc_eventlist_t whenshutdown; isc_event_t growentries; @@ -201,6 +199,7 @@ struct dns_adbfetch { unsigned int magic; dns_fetch_t *fetch; dns_rdataset_t rdataset; + unsigned int depth; }; /*% @@ -245,6 +244,7 @@ struct dns_adbentry { isc_sockaddr_t sockaddr; isc_stdtime_t expires; + isc_stdtime_t lastage; /*%< * A nonzero 'expires' field indicates that the entry should * persist until that time. This allows entries found @@ -300,8 +300,7 @@ static inline isc_boolean_t dec_entry_refcnt(dns_adb_t *, isc_boolean_t, static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *); static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *); static void clean_target(dns_adb_t *, dns_name_t *); -static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, - unsigned int); +static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t, unsigned int); static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t); static isc_boolean_t check_expire_entry(dns_adb_t *, dns_adbentry_t **, isc_stdtime_t); @@ -309,6 +308,7 @@ static void cancel_fetches_at_name(dns_adbname_t *); static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t, dns_rdatatype_t); static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t, + unsigned int, isc_counter_t *qc, dns_rdatatype_t); static inline void check_exit(dns_adb_t *); static void destroy(dns_adb_t *); @@ -321,6 +321,9 @@ static inline isc_boolean_t unlink_entry(dns_adb_t *, dns_adbentry_t *); static isc_boolean_t kill_name(dns_adbname_t **, isc_eventtype_t); static void water(void *, int); static void dump_entry(FILE *, dns_adbentry_t *, isc_boolean_t, isc_stdtime_t); +static void adjustsrtt(dns_adbaddrinfo_t *addr, unsigned int rtt, + unsigned int factor, isc_stdtime_t now); +static void shutdown_task(isc_task_t *task, isc_event_t *ev); /* * MUST NOT overlap DNS_ADBFIND_* flags! @@ -344,7 +347,7 @@ static void dump_entry(FILE *, dns_adbentry_t *, isc_boolean_t, isc_stdtime_t); * Private flag(s) for entries. * MUST NOT overlap FCTX_ADDRINFO_xxx and DNS_FETCHOPT_NOEDNS0. */ -#define ENTRY_IS_DEAD 0x80000000 +#define ENTRY_IS_DEAD 0x00400000 /* * To the name, address classes are all that really exist. If it has a @@ -1498,10 +1501,13 @@ check_exit(dns_adb_t *adb) { * If there aren't any external references either, we're * done. Send the control event to initiate shutdown. */ - INSIST(!adb->cevent_sent); /* Sanity check. */ + INSIST(!adb->cevent_out); /* Sanity check. */ + ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL, + DNS_EVENT_ADBCONTROL, shutdown_task, adb, + adb, NULL, NULL); event = &adb->cevent; isc_task_send(adb->task, &event); - adb->cevent_sent = ISC_TRUE; + adb->cevent_out = ISC_TRUE; } } @@ -1756,6 +1762,7 @@ new_adbentry(dns_adb_t *adb) { e->flags = 0; isc_random_get(&r); e->srtt = (r & 0x1f) + 1; + e->lastage = 0; e->expires = 0; ISC_LIST_INIT(e->lameinfo); ISC_LINK_INIT(e, plink); @@ -2430,10 +2437,9 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr, adb->view = view; adb->taskmgr = taskmgr; adb->next_cleanbucket = 0; - ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL, - DNS_EVENT_ADBCONTROL, shutdown_task, adb, - adb, NULL, NULL); - adb->cevent_sent = ISC_FALSE; + ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), + 0, NULL, 0, NULL, NULL, NULL, NULL, NULL); + adb->cevent_out = ISC_FALSE; adb->shutting_down = ISC_FALSE; ISC_LIST_INIT(adb->whenshutdown); @@ -2467,7 +2473,7 @@ dns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr, "intializing table sizes to %u\n", nbuckets[11]); adb->nentries = nbuckets[11]; - adb->nnames= nbuckets[11]; + adb->nnames = nbuckets[11]; } @@ -2740,9 +2746,28 @@ dns_adb_whenshutdown(dns_adb_t *adb, isc_task_t *task, isc_event_t **eventp) { UNLOCK(&adb->lock); } +static void +shutdown_stage2(isc_task_t *task, isc_event_t *event) { + dns_adb_t *adb; + + UNUSED(task); + + adb = event->ev_arg; + INSIST(DNS_ADB_VALID(adb)); + + LOCK(&adb->lock); + INSIST(adb->shutting_down); + adb->cevent_out = ISC_FALSE; + (void)shutdown_names(adb); + (void)shutdown_entries(adb); + if (dec_adb_irefcnt(adb)) + check_exit(adb); + UNLOCK(&adb->lock); +} + void dns_adb_shutdown(dns_adb_t *adb) { - isc_boolean_t need_check_exit; + isc_event_t *event; /* * Shutdown 'adb'. @@ -2753,11 +2778,16 @@ dns_adb_shutdown(dns_adb_t *adb) { if (!adb->shutting_down) { adb->shutting_down = ISC_TRUE; isc_mem_setwater(adb->mctx, water, adb, 0, 0); - need_check_exit = shutdown_names(adb); - if (!need_check_exit) - need_check_exit = shutdown_entries(adb); - if (need_check_exit) - check_exit(adb); + /* + * Isolate shutdown_names and shutdown_entries calls. + */ + inc_adb_irefcnt(adb); + ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL, + DNS_EVENT_ADBCONTROL, shutdown_stage2, adb, + adb, NULL, NULL); + adb->cevent_out = ISC_TRUE; + event = &adb->cevent; + isc_task_send(adb->task, &event); } UNLOCK(&adb->lock); @@ -2770,6 +2800,19 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, isc_stdtime_t now, dns_name_t *target, in_port_t port, dns_adbfind_t **findp) { + return (dns_adb_createfind2(adb, task, action, arg, name, + qname, qtype, options, now, + target, port, 0, NULL, findp)); +} + +isc_result_t +dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, + void *arg, dns_name_t *name, dns_name_t *qname, + dns_rdatatype_t qtype, unsigned int options, + isc_stdtime_t now, dns_name_t *target, + in_port_t port, unsigned int depth, isc_counter_t *qc, + dns_adbfind_t **findp) +{ dns_adbfind_t *find; dns_adbname_t *adbname; int bucket; @@ -3000,7 +3043,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, * Start V4. */ if (WANT_INET(wanted_fetches) && - fetch_name(adbname, start_at_zone, + fetch_name(adbname, start_at_zone, depth, qc, dns_rdatatype_a) == ISC_R_SUCCESS) { DP(DEF_LEVEL, "dns_adb_createfind: started A fetch for name %p", @@ -3011,7 +3054,7 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, * Start V6. */ if (WANT_INET6(wanted_fetches) && - fetch_name(adbname, start_at_zone, + fetch_name(adbname, start_at_zone, depth, qc, dns_rdatatype_aaaa) == ISC_R_SUCCESS) { DP(DEF_LEVEL, "dns_adb_createfind: " @@ -3754,6 +3797,12 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) { DP(DEF_LEVEL, "adb: fetch of '%s' %s failed: %s", buf, address_type == DNS_ADBFIND_INET ? "A" : "AAAA", dns_result_totext(dev->result)); + /* + * Don't record a failure unless this is the initial + * fetch of a chain. + */ + if (fetch->depth > 1) + 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); @@ -3791,9 +3840,8 @@ fetch_callback(isc_task_t *task, isc_event_t *ev) { } static isc_result_t -fetch_name(dns_adbname_t *adbname, - isc_boolean_t start_at_zone, - dns_rdatatype_t type) +fetch_name(dns_adbname_t *adbname, isc_boolean_t start_at_zone, + unsigned int depth, isc_counter_t *qc, dns_rdatatype_t type) { isc_result_t result; dns_adbfetch_t *fetch = NULL; @@ -3838,12 +3886,14 @@ fetch_name(dns_adbname_t *adbname, result = ISC_R_NOMEMORY; goto cleanup; } - - result = dns_resolver_createfetch(adb->view->resolver, &adbname->name, - type, name, nameservers, NULL, - options, adb->task, fetch_callback, - adbname, &fetch->rdataset, NULL, - &fetch->fetch); + fetch->depth = depth; + + result = dns_resolver_createfetch3(adb->view->resolver, &adbname->name, + type, name, nameservers, NULL, + NULL, 0, options, depth, qc, + adb->task, fetch_callback, adbname, + &fetch->rdataset, NULL, + &fetch->fetch); if (result != ISC_R_SUCCESS) goto cleanup; @@ -3912,8 +3962,7 @@ dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int rtt, unsigned int factor) { int bucket; - unsigned int new_srtt; - isc_stdtime_t now; + isc_stdtime_t now = 0; REQUIRE(DNS_ADB_VALID(adb)); REQUIRE(DNS_ADBADDRINFO_VALID(addr)); @@ -3922,21 +3971,53 @@ dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr, bucket = addr->entry->lock_bucket; LOCK(&adb->entrylocks[bucket]); - if (factor == DNS_ADB_RTTADJAGE) - new_srtt = addr->entry->srtt * 98 / 100; - else + if (addr->entry->expires == 0 || factor == DNS_ADB_RTTADJAGE) + isc_stdtime_get(&now); + adjustsrtt(addr, rtt, factor, now); + + UNLOCK(&adb->entrylocks[bucket]); +} + +void +dns_adb_agesrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr, isc_stdtime_t now) { + int bucket; + + REQUIRE(DNS_ADB_VALID(adb)); + REQUIRE(DNS_ADBADDRINFO_VALID(addr)); + + bucket = addr->entry->lock_bucket; + LOCK(&adb->entrylocks[bucket]); + + adjustsrtt(addr, 0, DNS_ADB_RTTADJAGE, now); + + UNLOCK(&adb->entrylocks[bucket]); +} + +static void +adjustsrtt(dns_adbaddrinfo_t *addr, unsigned int rtt, unsigned int factor, + isc_stdtime_t now) +{ + isc_uint64_t new_srtt; + + if (factor == DNS_ADB_RTTADJAGE) { + if (addr->entry->lastage != now) { + new_srtt = addr->entry->srtt; + new_srtt <<= 9; + new_srtt -= addr->entry->srtt; + new_srtt >>= 9; + addr->entry->lastage = now; + } else + new_srtt = addr->entry->srtt; + } else new_srtt = (addr->entry->srtt / 10 * factor) + (rtt / 10 * (10 - factor)); - addr->entry->srtt = new_srtt; - addr->srtt = new_srtt; + new_srtt &= 0xffffffff; + addr->entry->srtt = (unsigned int) new_srtt; + addr->srtt = (unsigned int) new_srtt; - if (addr->entry->expires == 0) { - isc_stdtime_get(&now); + if (addr->entry->expires == 0) addr->entry->expires = now + ADB_ENTRY_WINDOW; - } - - UNLOCK(&adb->entrylocks[bucket]); } void @@ -3949,6 +4030,9 @@ dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr, REQUIRE(DNS_ADB_VALID(adb)); REQUIRE(DNS_ADBADDRINFO_VALID(addr)); + REQUIRE((bits & ENTRY_IS_DEAD) == 0); + REQUIRE((mask & ENTRY_IS_DEAD) == 0); + bucket = addr->entry->lock_bucket; LOCK(&adb->entrylocks[bucket]); diff --git a/lib/dns/api b/lib/dns/api index cc5437d0be7b..b11beb8343db 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 = 102 -LIBREVISION = 2 -LIBAGE = 2 +LIBINTERFACE = 105 +LIBREVISION = 0 +LIBAGE = 1 diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c index 7af8e644b197..129895431ddf 100644 --- a/lib/dns/dispatch.c +++ b/lib/dns/dispatch.c @@ -819,14 +819,19 @@ deref_portentry(dns_dispatch_t *disp, dispportentry_t **portentryp) { portentry, link); isc_mempool_put(disp->portpool, portentry); } - UNLOCK(&qid->lock); + /* + * Set '*portentryp' to NULL inside the lock so that + * dispsock->portentry does not change in socket_search. + */ *portentryp = NULL; + + UNLOCK(&qid->lock); } /*% * Find a dispsocket for socket address 'dest', and port number 'port'. - * Return NULL if no such entry exists. + * Return NULL if no such entry exists. Requires qid->lock to be held. */ static dispsocket_t * socket_search(dns_qid_t *qid, isc_sockaddr_t *dest, in_port_t port, @@ -1322,8 +1327,8 @@ udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) { } else { free_buffer(disp, ev->region.base, ev->region.length); - UNLOCK(&disp->lock); isc_event_free(&ev_in); + UNLOCK(&disp->lock); return; } } else if (ev->result != ISC_R_SUCCESS) { @@ -1334,8 +1339,8 @@ udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) { "odd socket result in udp_recv(): %s", isc_result_totext(ev->result)); - UNLOCK(&disp->lock); isc_event_free(&ev_in); + UNLOCK(&disp->lock); return; } @@ -1510,9 +1515,8 @@ udp_recv(isc_event_t *ev_in, dns_dispatch_t *disp, dispsocket_t *dispsock) { */ deactivate_dispsocket(disp, dispsock); } - UNLOCK(&disp->lock); - isc_event_free(&ev_in); + UNLOCK(&disp->lock); } /* @@ -1694,9 +1698,8 @@ tcp_recv(isc_task_t *task, isc_event_t *ev_in) { restart: (void)startrecv(disp, NULL); - UNLOCK(&disp->lock); - isc_event_free(&ev_in); + UNLOCK(&disp->lock); } /* @@ -2286,9 +2289,12 @@ dns_dispatchmgr_setudp(dns_dispatchmgr_t *mgr, /* Create or adjust socket pool */ if (mgr->spool != NULL) { - if (maxrequests < DNS_DISPATCH_POOLSOCKS * 2) - isc_mempool_setmaxalloc(mgr->spool, DNS_DISPATCH_POOLSOCKS * 2); - isc_mempool_setfreemax(mgr->spool, DNS_DISPATCH_POOLSOCKS * 2); + if (maxrequests < DNS_DISPATCH_POOLSOCKS * 2) { + isc_mempool_setmaxalloc(mgr->spool, + DNS_DISPATCH_POOLSOCKS * 2); + isc_mempool_setfreemax(mgr->spool, + DNS_DISPATCH_POOLSOCKS * 2); + } UNLOCK(&mgr->buffer_lock); return (ISC_R_SUCCESS); } diff --git a/lib/dns/dns64.c b/lib/dns/dns64.c index 7d47c66933b5..9bc3cd8266df 100644 --- a/lib/dns/dns64.c +++ b/lib/dns/dns64.c @@ -63,7 +63,7 @@ dns_dns64_create(isc_mem_t *mctx, isc_netaddr_t *prefix, unsigned int nbytes = 16; REQUIRE(prefix != NULL && prefix->family == AF_INET6); - /* Legal prefix lengths from draft-ietf-behave-address-format-04. */ + /* Legal prefix lengths from rfc6052.txt. */ REQUIRE(prefixlen == 32 || prefixlen == 40 || prefixlen == 48 || prefixlen == 56 || prefixlen == 64 || prefixlen == 96); REQUIRE(isc_netaddr_prefixok(prefix, prefixlen) == ISC_R_SUCCESS); @@ -73,7 +73,7 @@ dns_dns64_create(isc_mem_t *mctx, isc_netaddr_t *prefix, static const unsigned char zeros[16]; REQUIRE(prefix->family == AF_INET6); nbytes = prefixlen / 8 + 4; - /* Bits 64-71 are zeros. draft-ietf-behave-address-format-04 */ + /* Bits 64-71 are zeros. rfc6052.txt */ if (prefixlen >= 32 && prefixlen <= 64) nbytes++; REQUIRE(memcmp(suffix->type.in6.s6_addr, zeros, nbytes) == 0); @@ -169,13 +169,13 @@ dns_dns64_aaaafroma(const dns_dns64_t *dns64, const isc_netaddr_t *reqaddr, INSIST(nbytes <= 12); /* Copy prefix. */ memmove(aaaa, dns64->bits, nbytes); - /* Bits 64-71 are zeros. draft-ietf-behave-address-format-04 */ + /* Bits 64-71 are zeros. rfc6052.txt */ if (nbytes == 8) aaaa[nbytes++] = 0; /* Copy mapped address. */ for (i = 0; i < 4U; i++) { aaaa[nbytes++] = a[i]; - /* Bits 64-71 are zeros. draft-ietf-behave-address-format-04 */ + /* Bits 64-71 are zeros. rfc6052.txt */ if (nbytes == 8) aaaa[nbytes++] = 0; } diff --git a/lib/dns/dnssec.c b/lib/dns/dnssec.c index d7addc681430..6a749ea56b32 100644 --- a/lib/dns/dnssec.c +++ b/lib/dns/dnssec.c @@ -1247,7 +1247,10 @@ get_hints(dns_dnsseckey_t *key, isc_stdtime_t now) { /* Metadata says activate (so we must also publish) */ if (actset && active <= now) { key->hint_sign = ISC_TRUE; - key->hint_publish = ISC_TRUE; + + /* Only publish if publish time has already passed. */ + if (pubset && publish <= now) + key->hint_publish = ISC_TRUE; } /* @@ -1522,7 +1525,7 @@ dns_dnssec_keylistfromrdataset(dns_name_t *origin, const char *directory, isc_mem_t *mctx, dns_rdataset_t *keyset, dns_rdataset_t *keysigs, dns_rdataset_t *soasigs, isc_boolean_t savekeys, - isc_boolean_t public, + isc_boolean_t publickey, dns_dnsseckeylist_t *keylist) { dns_rdataset_t keys; @@ -1551,7 +1554,7 @@ dns_dnssec_keylistfromrdataset(dns_name_t *origin, if (!dns_name_equal(origin, dst_key_name(pubkey))) goto skip; - if (public) { + if (publickey) { RETERR(addkey(keylist, &pubkey, savekeys, mctx)); goto skip; } diff --git a/lib/dns/ecdb.c b/lib/dns/ecdb.c index 8b3f7740081b..22cd810a773c 100644 --- a/lib/dns/ecdb.c +++ b/lib/dns/ecdb.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2011, 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2009-2011, 2013, 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 @@ -14,8 +14,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ecdb.c,v 1.10 2011/12/20 00:06:53 marka Exp $ */ - #include "config.h" #include <isc/result.h> @@ -772,19 +770,24 @@ rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust) { static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) { - ecdb_rdatasetiter_t *ecdbiterator; isc_mem_t *mctx; + union { + dns_rdatasetiter_t *rdatasetiterator; + ecdb_rdatasetiter_t *ecdbiterator; + } u; REQUIRE(iteratorp != NULL); - ecdbiterator = (ecdb_rdatasetiter_t *)*iteratorp; - REQUIRE(DNS_RDATASETITER_VALID(&ecdbiterator->common)); + REQUIRE(DNS_RDATASETITER_VALID(*iteratorp)); - mctx = ecdbiterator->common.db->mctx; + u.rdatasetiterator = *iteratorp; - ecdbiterator->common.magic = 0; + mctx = u.ecdbiterator->common.db->mctx; + u.ecdbiterator->common.magic = 0; - dns_db_detachnode(ecdbiterator->common.db, &ecdbiterator->common.node); - isc_mem_put(mctx, ecdbiterator, sizeof(ecdb_rdatasetiter_t)); + dns_db_detachnode(u.ecdbiterator->common.db, + &u.ecdbiterator->common.node); + isc_mem_put(mctx, u.ecdbiterator, + sizeof(ecdb_rdatasetiter_t)); *iteratorp = NULL; } diff --git a/lib/dns/gen.c b/lib/dns/gen.c index b934c9990fb3..ff41de6d624a 100644 --- a/lib/dns/gen.c +++ b/lib/dns/gen.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2012, 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2012-2014 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -331,15 +331,20 @@ insert_into_typenames(int type, const char *typename, const char *attr) { exit(1); } + /* XXXMUKS: This is redundant due to the INSIST above. */ if (strlen(typename) > sizeof(ttn->typename) - 1) { fprintf(stderr, "Error: type name %s is too long\n", typename); exit(1); } + strncpy(ttn->typename, typename, sizeof(ttn->typename)); - ttn->type = type; + ttn->typename[sizeof(ttn->typename) - 1] = '\0'; strncpy(ttn->macroname, ttn->typename, sizeof(ttn->macroname)); + ttn->macroname[sizeof(ttn->macroname) - 1] = '\0'; + + ttn->type = type; c = strlen(ttn->macroname); while (c > 0) { if (ttn->macroname[c - 1] == '-') @@ -365,7 +370,10 @@ insert_into_typenames(int type, const char *typename, const char *attr) { attr, typename); exit(1); } + strncpy(ttn->attr, attr, sizeof(ttn->attr)); + ttn->attr[sizeof(ttn->attr) - 1] = '\0'; + ttn->sorted = 0; if (maxtype < type) maxtype = type; @@ -394,11 +402,17 @@ add(int rdclass, const char *classname, int type, const char *typename, newtt->next = NULL; newtt->rdclass = rdclass; newtt->type = type; + strncpy(newtt->classname, classname, sizeof(newtt->classname)); + newtt->classname[sizeof(newtt->classname) - 1] = '\0'; + strncpy(newtt->typename, typename, sizeof(newtt->typename)); + newtt->typename[sizeof(newtt->typename) - 1] = '\0'; + if (strncmp(dirname, "./", 2) == 0) dirname += 2; strncpy(newtt->dirname, dirname, sizeof(newtt->dirname)); + newtt->dirname[sizeof(newtt->dirname) - 1] = '\0'; tt = types; oldtt = NULL; @@ -437,6 +451,7 @@ add(int rdclass, const char *classname, int type, const char *typename, } newcc->rdclass = rdclass; strncpy(newcc->classname, classname, sizeof(newcc->classname)); + newcc->classname[sizeof(newcc->classname) - 1] = '\0'; cc = classes; oldcc = NULL; diff --git a/lib/dns/gssapictx.c b/lib/dns/gssapictx.c index d4209d378a76..f28c07aba436 100644 --- a/lib/dns/gssapictx.c +++ b/lib/dns/gssapictx.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, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -233,7 +233,7 @@ check_config(const char *gss_name) { krb5_free_context(krb5_ctx); return; } - p = strchr(gss_name, '/'); + p = strchr(gss_name, '@'); if (p == NULL) { gss_log(ISC_LOG_ERROR, "badly formatted " "tkey-gssapi-credentials (%s)", gss_name); diff --git a/lib/dns/include/dns/Makefile.in b/lib/dns/include/dns/Makefile.in index 6ff682f70d37..640a63e2c8e7 100644 --- a/lib/dns/include/dns/Makefile.in +++ b/lib/dns/include/dns/Makefile.in @@ -21,18 +21,22 @@ top_srcdir = @top_srcdir@ @BIND9_VERSION@ -HEADERS = acl.h adb.h byaddr.h cache.h callbacks.h cert.h compress.h \ +HEADERS = acache.h acl.h adb.h bit.h byaddr.h cache.h callbacks.h cert.h \ client.h clientinfo.h compress.h \ db.h dbiterator.h dbtable.h diff.h dispatch.h \ - dlz.h dnssec.h ds.h events.h fixedname.h iptable.h journal.h \ - keyflags.h keytable.h keyvalues.h lib.h log.h \ - master.h masterdump.h message.h name.h ncache.h nsec.h \ - peer.h portlist.h private.h rbt.h rcode.h \ - rdata.h rdataclass.h rdatalist.h rdataset.h rdatasetiter.h \ - rdataslab.h rdatatype.h request.h resolver.h result.h \ - rootns.h rpz.h sdb.h sdlz.h secalg.h secproto.h soa.h ssu.h \ - tcpmsg.h time.h tkey.h tsec.h tsig.h ttl.h types.h \ - validator.h version.h view.h xfrin.h zone.h zonekey.h zt.h + dlz.h dlz_dlopen.h dns64.h dnssec.h ds.h \ + ecdb.h events.h fixedname.h forward.h iptable.h \ + journal.h keydata.h keyflags.h keytable.h keyvalues.h \ + lib.h lookup.h log.h master.h masterdump.h message.h \ + name.h ncache.h nsec.h nsec3.h opcode.h order.h \ + peer.h portlist.h private.h \ + rbt.h rcode.h rdata.h rdataclass.h rdatalist.h \ + rdataset.h rdatasetiter.h rdataslab.h rdatatype.h request.h \ + resolver.h result.h rootns.h rpz.h rriterator.h rrl.h \ + sdb.h sdlz.h secalg.h secproto.h soa.h ssu.h stats.h \ + tcpmsg.h time.h timer.h tkey.h tsec.h tsig.h ttl.h types.h \ + update.h validator.h version.h view.h xfrin.h \ + zone.h zonekey.h zt.h GENHEADERS = enumclass.h enumtype.h rdatastruct.h diff --git a/lib/dns/include/dns/adb.h b/lib/dns/include/dns/adb.h index a5a312406aff..8222bd211006 100644 --- a/lib/dns/include/dns/adb.h +++ b/lib/dns/include/dns/adb.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008, 2011, 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2008, 2011, 2013, 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 @@ -334,6 +334,13 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, dns_rdatatype_t qtype, unsigned int options, isc_stdtime_t now, dns_name_t *target, in_port_t port, dns_adbfind_t **find); +isc_result_t +dns_adb_createfind2(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action, + void *arg, dns_name_t *name, dns_name_t *qname, + dns_rdatatype_t qtype, unsigned int options, + isc_stdtime_t now, dns_name_t *target, in_port_t port, + unsigned int depth, isc_counter_t *qc, + dns_adbfind_t **find); /*%< * Main interface for clients. The adb will look up the name given in * "name" and will build up a list of found addresses, and perhaps start @@ -510,7 +517,12 @@ dns_adb_marklame(dns_adb_t *adb, dns_adbaddrinfo_t *addr, dns_name_t *qname, */ /* - * A reasonable default for RTT adjustments + * Reasonable defaults for RTT adjustments + * + * (Note: these values function both as scaling factors and as + * indicators of the type of RTT adjustment operation taking place. + * Adjusting the scaling factors is fine, as long as they all remain + * unique values.) */ #define DNS_ADB_RTTADJDEFAULT 7 /*%< default scale */ #define DNS_ADB_RTTADJREPLACE 0 /*%< replace with our rtt */ @@ -521,18 +533,6 @@ dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int rtt, unsigned int factor); /*%< * Mix the round trip time into the existing smoothed rtt. - - * The formula used - * (where srtt is the existing rtt value, and rtt and factor are arguments to - * this function): - * - *\code - * new_srtt = (old_srtt / 10 * factor) + (rtt / 10 * (10 - factor)); - *\endcode - * - * XXXRTH Do we want to publish the formula? What if we want to change how - * this works later on? Recommend/require that the units are - * microseconds? * * Requires: * @@ -549,6 +549,24 @@ dns_adb_adjustsrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr, */ void +dns_adb_agesrtt(dns_adb_t *adb, dns_adbaddrinfo_t *addr, isc_stdtime_t now); +/* + * dns_adb_agesrtt is equivalent to dns_adb_adjustsrtt with factor + * equal to DNS_ADB_RTTADJAGE and the current time passed in. + * + * Requires: + * + *\li adb be valid. + * + *\li addr be valid. + * + * Note: + * + *\li The srtt in addr will be updated to reflect the new global + * srtt value. This may include changes made by others. + */ + +void dns_adb_changeflags(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int bits, unsigned int mask); /*% diff --git a/lib/dns/include/dns/dns64.h b/lib/dns/include/dns/dns64.h index eb8f8d6436a6..4d0e80158541 100644 --- a/lib/dns/include/dns/dns64.h +++ b/lib/dns/include/dns/dns64.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2010, 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 @@ -84,7 +84,7 @@ dns_dns64_create(isc_mem_t *mctx, isc_netaddr_t *prefix, * zero. * 'client' to be NULL or a valid acl. * 'mapped' to be NULL or a valid acl. - * 'exculded' to be NULL or a valid acl. + * 'excluded' to be NULL or a valid acl. * * Returns: * ISC_R_SUCCESS diff --git a/lib/dns/include/dns/dnssec.h b/lib/dns/include/dns/dnssec.h index 7202d99b5da9..936454fc465e 100644 --- a/lib/dns/include/dns/dnssec.h +++ b/lib/dns/include/dns/dnssec.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2007, 2009-2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2007, 2009-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 @@ -314,11 +314,11 @@ dns_dnssec_keylistfromrdataset(dns_name_t *origin, const char *directory, isc_mem_t *mctx, dns_rdataset_t *keyset, dns_rdataset_t *keysigs, dns_rdataset_t *soasigs, isc_boolean_t savekeys, - isc_boolean_t public, + isc_boolean_t publickey, dns_dnsseckeylist_t *keylist); /*%< * Append the contents of a DNSKEY rdataset 'keyset' to 'keylist'. - * Omit duplicates. If 'public' is ISC_FALSE, search 'directory' for + * Omit duplicates. If 'publickey' is ISC_FALSE, search 'directory' for * matching key files, and load the private keys that go with * the public ones. If 'savekeys' is ISC_TRUE, mark the keys so * they will not be deleted or inactivated regardless of metadata. diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index 6b2f39fc9583..c678238d2224 100644 --- a/lib/dns/include/dns/message.h +++ b/lib/dns/include/dns/message.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010, 2012, 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2010, 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 @@ -106,6 +106,10 @@ /*%< EDNS0 extended OPT codes */ #define DNS_OPT_NSID 0x0003 /*%< NSID opt code */ #define DNS_OPT_CLIENT_SUBNET 0x0008 /*%< client subnet opt code */ +#define DNS_OPT_EXPIRE 0x0009 /*%< EXPIRE opt code */ + +/*%< The number of EDNS options we know about. */ +#define DNS_EDNSOPTIONS 3 #define DNS_MESSAGE_REPLYPRESERVE (DNS_MESSAGEFLAG_RD|DNS_MESSAGEFLAG_CD) #define DNS_MESSAGEEXTFLAG_REPLYPRESERVE (DNS_MESSAGEEXTFLAG_DO) diff --git a/lib/dns/include/dns/rbt.h b/lib/dns/include/dns/rbt.h index 3e9dc886576f..8b382b5ed6be 100644 --- a/lib/dns/include/dns/rbt.h +++ b/lib/dns/include/dns/rbt.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 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 @@ -914,6 +914,31 @@ dns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name); #define dns_rbtnode_refinit(node, n) ((node)->references = (n)) #define dns_rbtnode_refdestroy(node) REQUIRE((node)->references == 0) #define dns_rbtnode_refcurrent(node) ((node)->references) + +#if (__STDC_VERSION__ + 0) >= 199901L || defined __GNUC__ +static inline void +dns_rbtnode_refincrement0(dns_rbtnode_t *node, unsigned int *refs) { + node->references++; + if (refs != NULL) + *refs = node->references; +} + +static inline void +dns_rbtnode_refincrement(dns_rbtnode_t *node, unsigned int *refs) { + REQUIRE(node->references > 0); + node->references++; + if (refs != NULL) + *refs = node->references; +} + +static inline void +dns_rbtnode_refdecrement(dns_rbtnode_t *node, unsigned int *refs) { + REQUIRE(node->references > 0); + node->references--; + if (refs != NULL) + *refs = node->references; +} +#else #define dns_rbtnode_refincrement0(node, refs) \ do { \ unsigned int *_tmp = (unsigned int *)(refs); \ @@ -935,6 +960,7 @@ dns_rbtnodechain_nextflat(dns_rbtnodechain_t *chain, dns_name_t *name); if ((refs) != NULL) \ (*refs) = (node)->references; \ } while (0) +#endif #endif /* DNS_RBT_USEISCREFCOUNT */ ISC_LANG_ENDDECLS diff --git a/lib/dns/include/dns/rdataset.h b/lib/dns/include/dns/rdataset.h index 31bcd15f1424..c266d14655ee 100644 --- a/lib/dns/include/dns/rdataset.h +++ b/lib/dns/include/dns/rdataset.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-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 @@ -199,7 +199,8 @@ struct dns_rdataset { #define DNS_RDATASETATTR_NXDOMAIN 0x00002000 #define DNS_RDATASETATTR_NOQNAME 0x00004000 #define DNS_RDATASETATTR_CHECKNAMES 0x00008000 /*%< Used by resolver. */ -#define DNS_RDATASETATTR_REQUIREDGLUE 0x00010000 +#define DNS_RDATASETATTR_REQUIRED 0x00010000 +#define DNS_RDATASETATTR_REQUIREDGLUE DNS_RDATASETATTR_REQUIRED #define DNS_RDATASETATTR_LOADORDER 0x00020000 #define DNS_RDATASETATTR_RESIGN 0x00040000 #define DNS_RDATASETATTR_CLOSEST 0x00080000 @@ -673,7 +674,7 @@ dns_rdataset_trimttl(dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, const char * dns_trust_totext(dns_trust_t trust); -/* +/*%< * Display trust in textual form. */ diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h index 095269ea2dd2..a533f4ed2b24 100644 --- a/lib/dns/include/dns/resolver.h +++ b/lib/dns/include/dns/resolver.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2012, 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 @@ -97,6 +97,7 @@ typedef struct dns_fetchevent { UDP buffer. */ #define DNS_FETCHOPT_WANTNSID 0x80 /*%< Request NSID */ +/* Reserved in use by adb.c 0x00400000 */ #define DNS_FETCHOPT_EDNSVERSIONSET 0x00800000 #define DNS_FETCHOPT_EDNSVERSIONMASK 0xff000000 #define DNS_FETCHOPT_EDNSVERSIONSHIFT 24 @@ -274,6 +275,18 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset, dns_fetch_t **fetchp); +isc_result_t +dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name, + dns_rdatatype_t type, + dns_name_t *domain, dns_rdataset_t *nameservers, + dns_forwarders_t *forwarders, + isc_sockaddr_t *client, isc_uint16_t id, + unsigned int options, unsigned int depth, + isc_counter_t *qc, isc_task_t *task, + isc_taskaction_t action, void *arg, + dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset, + dns_fetch_t **fetchp); /*%< * Recurse to answer a question. * @@ -575,6 +588,30 @@ dns_resolver_printbadcache(dns_resolver_t *resolver, FILE *fp); * \li resolver to be valid. */ +void +dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth); +unsigned int +dns_resolver_getmaxdepth(dns_resolver_t *resolver); +/*% + * Get and set how many NS indirections will be followed when looking for + * nameserver addresses. + * + * Requires: + * \li resolver to be valid. + */ + +void +dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries); +unsigned int +dns_resolver_getmaxqueries(dns_resolver_t *resolver); +/*% + * Get and set how many iterative queries will be allowed before + * terminating a recursive query. + * + * Requires: + * \li resolver to be valid. + */ + ISC_LANG_ENDDECLS #endif /* DNS_RESOLVER_H */ diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index 704e5fe3e999..b9d6084f351c 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-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 @@ -140,6 +140,7 @@ struct dns_view { dns_acl_t * updateacl; dns_acl_t * upfwdacl; dns_acl_t * denyansweracl; + dns_acl_t * nocasecompress; dns_rbt_t * answeracl_exclude; dns_rbt_t * denyanswernames; dns_rbt_t * answernames_exclude; @@ -711,6 +712,7 @@ dns_viewlist_findzone(dns_viewlist_t *list, dns_name_t *name, isc_boolean_t allc * Returns: *\li #ISC_R_SUCCESS A matching zone was found. *\li #ISC_R_NOTFOUND No matching zone was found. + *\li #ISC_R_MULTIPLE Multiple zones with the same name were found. */ isc_result_t diff --git a/lib/dns/keytable.c b/lib/dns/keytable.c index c49847f326ad..56fefcd2c122 100644 --- a/lib/dns/keytable.c +++ b/lib/dns/keytable.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009, 2010, 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2010, 2013, 2014 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -174,6 +174,7 @@ insert(dns_keytable_t *keytable, isc_boolean_t managed, for (k = node->data; k != NULL; k = k->next) { if (k->key == NULL) { k->key = *keyp; + *keyp = NULL; /* transfer ownership */ break; } if (dst_key_compare(k->key, *keyp) == ISC_TRUE) @@ -182,7 +183,7 @@ insert(dns_keytable_t *keytable, isc_boolean_t managed, if (k == NULL) result = ISC_R_SUCCESS; - else + else if (*keyp != NULL) dst_key_free(keyp); } @@ -575,6 +576,8 @@ dns_keytable_dump(dns_keytable_t *keytable, FILE *fp) dns_rbtnodechain_current(&chain, NULL, NULL, &node); for (knode = node->data; knode != NULL; knode = knode->next) { + if (knode->key == NULL) + continue; dst_key_format(knode->key, pbuf, sizeof(pbuf)); fprintf(fp, "%s ; %s\n", pbuf, knode->managed ? "managed" : "trusted"); diff --git a/lib/dns/master.c b/lib/dns/master.c index 9e796e6e0ac7..dcea97a0bdd4 100644 --- a/lib/dns/master.c +++ b/lib/dns/master.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2011-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 @@ -91,6 +91,8 @@ #define DNS_MASTER_LHS 2048 #define DNS_MASTER_RHS MINTSIZ +#define CHECKNAMESFAIL(x) (((x) & DNS_MASTER_CHECKNAMESFAIL) != 0) + typedef ISC_LIST(dns_rdatalist_t) rdatalist_head_t; typedef struct dns_incctx dns_incctx_t; @@ -798,13 +800,12 @@ generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs, dns_rdatalist_t rdatalist; dns_rdatatype_t type; rdatalist_head_t head; - int n; int target_size = MINTSIZ; /* only one rdata at a time */ isc_buffer_t buffer; isc_buffer_t target; isc_result_t result; isc_textregion_t r; - unsigned int start, stop, step, i; + int i, n, start, stop, step = 0; dns_incctx_t *ictx; ictx = lctx->inc; @@ -822,8 +823,10 @@ generate(dns_loadctx_t *lctx, char *range, char *lhs, char *gtype, char *rhs, } isc_buffer_init(&target, target_mem, target_size); - n = sscanf(range, "%u-%u/%u", &start, &stop, &step); - if (n < 2 || stop < start) { + n = sscanf(range, "%d-%d/%d", &start, &stop, &step); + if ((n < 2) || (start < 0) || (stop < 0) || (step < 0) || + (stop < start)) + { (*callbacks->error)(callbacks, "%s: %s:%lu: invalid range '%s'", "$GENERATE", source, line, range); @@ -1759,7 +1762,8 @@ load_text(dns_loadctx_t *lctx) { dns_name_format(name, namebuf, sizeof(namebuf)); result = DNS_R_BADOWNERNAME; desc = dns_result_totext(result); - if ((lctx->options & DNS_MASTER_CHECKNAMESFAIL) != 0) { + if (CHECKNAMESFAIL(lctx->options) || + type == dns_rdatatype_nsec3) { (*callbacks->error)(callbacks, "%s:%lu: %s: %s", source, line, @@ -2132,7 +2136,7 @@ load_raw(dns_loadctx_t *lctx) { isc_result_totext(result)); return (result); } - isc_buffer_add(&target, commonlen); + isc_buffer_add(&target, (unsigned int)commonlen); header.format = isc_buffer_getuint32(&target); if (header.format != dns_masterformat_raw) { (*callbacks->error)(callbacks, @@ -2165,7 +2169,7 @@ load_raw(dns_loadctx_t *lctx) { return (result); } - isc_buffer_add(&target, remainder); + isc_buffer_add(&target, (unsigned int)remainder); header.dumptime = isc_buffer_getuint32(&target); if (header.version == DNS_RAWFORMAT_VERSION) { header.flags = isc_buffer_getuint32(&target); @@ -2275,7 +2279,7 @@ load_raw(dns_loadctx_t *lctx) { rdatalist.covers = isc_buffer_getuint16(&target); rdatalist.ttl = isc_buffer_getuint32(&target); rdcount = isc_buffer_getuint32(&target); - if (rdcount == 0) { + if (rdcount == 0 || rdcount > 0xffff) { result = ISC_R_RANGE; goto cleanup; } diff --git a/lib/dns/message.c b/lib/dns/message.c index 901c6b6d991d..d76eb4fb26c6 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -1377,6 +1377,16 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, covers = 0; /* + * Check the ownername of NSEC3 records + */ + if (rdtype == dns_rdatatype_nsec3 && + !dns_rdata_checkowner(name, msg->rdclass, rdtype, + ISC_FALSE)) { + result = DNS_R_BADOWNERNAME; + goto cleanup; + } + + /* * If we are doing a dynamic update or this is a meta-type, * don't bother searching for a name, just append this one * to the end of the message. @@ -3196,7 +3206,8 @@ dns_message_pseudosectiontotext(dns_message_t *msg, dns_pseudosection_t section, const dns_master_style_t *style, dns_messagetextflag_t flags, - isc_buffer_t *target) { + isc_buffer_t *target) +{ dns_rdataset_t *ps = NULL; dns_name_t *name = NULL; isc_result_t result; @@ -3270,8 +3281,11 @@ dns_message_pseudosectiontotext(dns_message_t *msg, sprintf(buf, "%02x ", optdata[i]); ADD_STRING(target, buf); } + for (i = 0; i < optlen; i++) { ADD_STRING(target, " ("); + if (!isc_buffer_availablelength(target)) + return (ISC_R_NOSPACE); if (isprint(optdata[i])) isc_buffer_putmem(target, &optdata[i], diff --git a/lib/dns/name.c b/lib/dns/name.c index 9b24ed363804..5207f74b4240 100644 --- a/lib/dns/name.c +++ b/lib/dns/name.c @@ -53,7 +53,6 @@ typedef enum { typedef enum { fw_start = 0, fw_ordinary, - fw_copy, fw_newcurrent } fw_state; @@ -1161,7 +1160,7 @@ dns_name_fromtext(dns_name_t *name, isc_buffer_t *source, count++; CONVERTTOASCII(c); if (downcase) - c = maptolower[(int)c]; + c = maptolower[c & 0xff]; *ndata++ = c; nrem--; nused++; @@ -1185,7 +1184,7 @@ dns_name_fromtext(dns_name_t *name, isc_buffer_t *source, count++; CONVERTTOASCII(c); if (downcase) - c = maptolower[(int)c]; + c = maptolower[c & 0xff]; *ndata++ = c; nrem--; nused++; @@ -1200,7 +1199,7 @@ dns_name_fromtext(dns_name_t *name, isc_buffer_t *source, if (!isdigit(c & 0xff)) return (DNS_R_BADESCAPE); value *= 10; - value += digitvalue[(int)c]; + value += digitvalue[c & 0xff]; digits++; if (digits == 3) { if (value > 255) @@ -1252,7 +1251,7 @@ dns_name_fromtext(dns_name_t *name, isc_buffer_t *source, while (n2 > 0) { c = *label++; if (downcase) - c = maptolower[(int)c]; + c = maptolower[c & 0xff]; *ndata++ = c; n2--; } @@ -1859,7 +1858,6 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source, 0) return (DNS_R_DISALLOWED); new_current = c & 0x3F; - n = 1; state = fw_newcurrent; } else return (DNS_R_BADLABELTYPE); @@ -1867,8 +1865,6 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source, case fw_ordinary: if (downcase) c = maptolower[c]; - /* FALLTHROUGH */ - case fw_copy: *ndata++ = c; n--; if (n == 0) @@ -1877,9 +1873,6 @@ dns_name_fromwire(dns_name_t *name, isc_buffer_t *source, case fw_newcurrent: new_current *= 256; new_current += c; - n--; - if (n != 0) - break; if (new_current >= biggest_pointer) return (DNS_R_BADPOINTER); biggest_pointer = new_current; diff --git a/lib/dns/nsec.c b/lib/dns/nsec.c index 5d1197d093b0..6183ef281c02 100644 --- a/lib/dns/nsec.c +++ b/lib/dns/nsec.c @@ -436,7 +436,7 @@ dns_nsec_noexistnodata(dns_rdatatype_t type, dns_name_t *name, nlabels, &common); } result = dns_name_concatenate(dns_wildcardname, &common, - wild, NULL); + wild, NULL); if (result != ISC_R_SUCCESS) { dns_rdata_freestruct(&nsec); (*logit)(arg, ISC_LOG_DEBUG(3), diff --git a/lib/dns/nsec3.c b/lib/dns/nsec3.c index 3724118cb3fe..ef43c35d27bb 100644 --- a/lib/dns/nsec3.c +++ b/lib/dns/nsec3.c @@ -253,11 +253,11 @@ dns_nsec3_hashname(dns_fixedname_t *result, if (hash_length != NULL) *hash_length = len; - /* convert the hash to base32hex */ + /* convert the hash to base32hex non-padded */ region.base = rethash; region.length = (unsigned int)len; isc_buffer_init(&namebuffer, nametext, sizeof nametext); - isc_base32hex_totext(®ion, 1, "", &namebuffer); + isc_base32hexnp_totext(®ion, 1, "", &namebuffer); /* convert the hex to a domain name */ dns_fixedname_init(result); @@ -269,7 +269,8 @@ unsigned int dns_nsec3_hashlength(dns_hash_t hash) { switch (hash) { - case dns_hash_sha1: return(ISC_SHA1_DIGESTLENGTH); + case dns_hash_sha1: + return(ISC_SHA1_DIGESTLENGTH); } return (0); } @@ -277,7 +278,8 @@ dns_nsec3_hashlength(dns_hash_t hash) { isc_boolean_t dns_nsec3_supportedhash(dns_hash_t hash) { switch (hash) { - case dns_hash_sha1: return (ISC_TRUE); + case dns_hash_sha1: + return (ISC_TRUE); } return (ISC_FALSE); } @@ -565,6 +567,7 @@ dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version, CHECK(dns_nsec3_hashname(&fixed, nexthash, &next_length, name, origin, hash, iterations, salt, salt_length)); + INSIST(next_length <= sizeof(nexthash)); /* * Create the node if it doesn't exist and hold @@ -842,8 +845,8 @@ dns_nsec3_addnsec3(dns_db_t *db, dns_dbversion_t *version, dns_db_detachnode(db, &newnode); } while (1); - if (result == ISC_R_NOMORE) - result = ISC_R_SUCCESS; + /* result cannot be ISC_R_NOMORE here */ + INSIST(result != ISC_R_NOMORE); failure: if (dbit != NULL) @@ -2072,6 +2075,9 @@ dns_nsec3_noexistnodata(dns_rdatatype_t type, dns_name_t* name, if ((nsec3.flags & DNS_NSEC3FLAG_OPTOUT) != 0) (*logit)(arg, ISC_LOG_DEBUG(3), "NSEC3 indicates optout"); + else + (*logit)(arg, ISC_LOG_DEBUG(3), + "NSEC3 indicates secure range"); *optout = ISC_TF(nsec3.flags & DNS_NSEC3FLAG_OPTOUT); } diff --git a/lib/dns/openssl_link.c b/lib/dns/openssl_link.c index 56465aa00645..a0a2724f41c1 100644 --- a/lib/dns/openssl_link.c +++ b/lib/dns/openssl_link.c @@ -1,5 +1,5 @@ /* - * Portions Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC") + * Portions Copyright (C) 2004-2012, 2014 Internet Systems Consortium, Inc. ("ISC") * Portions Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -242,8 +242,7 @@ dst__openssl_init(const char *engine) { } void -dst__openssl_destroy() { - +dst__openssl_destroy(void) { /* * Sequence taken from apps_shutdown() in <apps/apps.h>. */ diff --git a/lib/dns/peer.c b/lib/dns/peer.c index ec9e08cb27b7..b17bbea1328a 100644 --- a/lib/dns/peer.c +++ b/lib/dns/peer.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2009, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2009, 2012, 2014 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -300,10 +300,15 @@ peer_delete(dns_peer_t **peer) { isc_mem_put(mem, p->key, sizeof(dns_name_t)); } - if (p->transfer_source != NULL) { + if (p->query_source != NULL) + isc_mem_put(mem, p->query_source, sizeof(*p->query_source)); + + if (p->notify_source != NULL) + isc_mem_put(mem, p->notify_source, sizeof(*p->notify_source)); + + if (p->transfer_source != NULL) isc_mem_put(mem, p->transfer_source, sizeof(*p->transfer_source)); - } isc_mem_put(mem, p, sizeof(*p)); diff --git a/lib/dns/rbt.c b/lib/dns/rbt.c index d97fcce28eb9..0e9c5f950569 100644 --- a/lib/dns/rbt.c +++ b/lib/dns/rbt.c @@ -15,8 +15,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ - /*! \file */ /* Principal Authors: DCL */ @@ -134,7 +132,10 @@ struct dns_rbt { * of memory concerns, when chains were first implemented). */ #define ADD_LEVEL(chain, node) \ - (chain)->levels[(chain)->level_count++] = (node) + do { \ + INSIST((chain)->level_count < DNS_RBT_LEVELBLOCK); \ + (chain)->levels[(chain)->level_count++] = (node); \ + } while (0) /*% * The following macros directly access normally private name variables. diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 013bf34a0a09..a8ad8329c73b 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -15,8 +15,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id$ */ - /*! \file */ /* @@ -93,6 +91,127 @@ typedef isc_uint64_t rbtdb_serial_t; #define dns_rbtdb_t dns_rbtdb64_t #define rdatasetheader_t rdatasetheader64_t #define rbtdb_version_t rbtdb_version64_t + +#define init_count init_count64 + +#define cache_methods cache_methods64 +#define dbiterator_methods dbiterator_methods64 +#define rdataset_methods rdataset_methods64 +#define rdatasetiter_methods rdatasetiter_methods64 +#define zone_methods zone_methods64 + +#define acache_callback acache_callback64 +#define acache_cancelentry acache_cancelentry64 +#define activeempty activeempty64 +#define activeemtpynode activeemtpynode64 +#define add32 add64 +#define add_changed add_changed64 +#define add_empty_wildcards add_empty_wildcards64 +#define add_wildcard_magic add_wildcard_magic64 +#define addrdataset addrdataset64 +#define allrdatasets allrdatasets64 +#define attach attach64 +#define attachnode attachnode64 +#define attachversion attachversion64 +#define beginload beginload64 +#define bind_rdataset bind_rdataset64 +#define cache_find cache_find64 +#define cache_findrdataset cache_findrdataset64 +#define cache_findzonecut cache_findzonecut64 +#define cache_zonecut_callback cache_zonecut_callback64 +#define cleanup_dead_nodes cleanup_dead_nodes64 +#define cleanup_dead_nodes_callback cleanup_dead_nodes_callback64 +#define closeversion closeversion64 +#define createiterator createiterator64 +#define currentversion currentversion64 +#define dbiterator_current dbiterator_current64 +#define dbiterator_destroy dbiterator_destroy64 +#define dbiterator_first dbiterator_first64 +#define dbiterator_last dbiterator_last64 +#define dbiterator_next dbiterator_next64 +#define dbiterator_origin dbiterator_origin64 +#define dbiterator_pause dbiterator_pause64 +#define dbiterator_prev dbiterator_prev64 +#define dbiterator_seek dbiterator_seek64 +#define decrement_reference decrement_reference64 +#define delete_callback delete_callback64 +#define delete_node delete_node64 +#define deleterdataset deleterdataset64 +#define detach detach64 +#define detachnode detachnode64 +#define dump dump64 +#define endload endload64 +#define expire_header expire_header64 +#define expirenode expirenode64 +#define find_closest_nsec find_closest_nsec64 +#define find_coveringnsec find_coveringnsec64 +#define find_deepest_zonecut find_deepest_zonecut64 +#define findnode findnode64 +#define findnodeintree findnodeintree64 +#define findnsec3node findnsec3node64 +#define flush_deletions flush_deletions64 +#define free_acachearray free_acachearray64 +#define free_noqname free_noqname64 +#define free_rbtdb free_rbtdb64 +#define free_rbtdb_callback free_rbtdb_callback64 +#define free_rdataset free_rdataset64 +#define getnsec3parameters getnsec3parameters64 +#define getoriginnode getoriginnode64 +#define getrrsetstats getrrsetstats64 +#define getsigningtime getsigningtime64 +#define isdnssec isdnssec64 +#define ispersistent ispersistent64 +#define issecure issecure64 +#define iszonesecure iszonesecure64 +#define loading_addrdataset loading_addrdataset64 +#define loadnode loadnode64 +#define matchparams matchparams64 +#define maybe_free_rbtdb maybe_free_rbtdb64 +#define new_reference new_reference64 +#define newversion newversion64 +#define nodecount nodecount64 +#define overmem overmem64 +#define previous_closest_nsec previous_closest_nsec64 +#define printnode printnode64 +#define prune_tree prune_tree64 +#define rdataset_clone rdataset_clone64 +#define rdataset_count rdataset_count64 +#define rdataset_current rdataset_current64 +#define rdataset_disassociate rdataset_disassociate64 +#define rdataset_expire rdataset_expire64 +#define rdataset_first rdataset_first64 +#define rdataset_getadditional rdataset_getadditional64 +#define rdataset_getclosest rdataset_getclosest64 +#define rdataset_getnoqname rdataset_getnoqname64 +#define rdataset_next rdataset_next64 +#define rdataset_putadditional rdataset_putadditional64 +#define rdataset_setadditional rdataset_setadditional64 +#define rdataset_settrust rdataset_settrust64 +#define rdatasetiter_current rdatasetiter_current64 +#define rdatasetiter_destroy rdatasetiter_destroy64 +#define rdatasetiter_first rdatasetiter_first64 +#define rdatasetiter_next rdatasetiter_next64 +#define reactivate_node reactivate_node64 +#define resign_delete resign_delete64 +#define resign_insert resign_insert64 +#define resign_sooner resign_sooner64 +#define resigned resigned64 +#define rpz_enabled rpz_enabled64 +#define rpz_findips rpz_findips64 +#define set_index set_index64 +#define set_ttl set_ttl64 +#define setsigningtime setsigningtime64 +#define settask settask64 +#define setup_delegation setup_delegation64 +#define subtractrdataset subtractrdataset64 +#define ttl_sooner ttl_sooner64 +#define update_header update_header64 +#define update_rrsetstats update_rrsetstats64 +#define zone_find zone_find64 +#define zone_findrdataset zone_findrdataset64 +#define zone_findzonecut zone_findzonecut64 +#define zone_zonecut_callback zone_zonecut_callback64 + #else typedef isc_uint32_t rbtdb_serial_t; #endif @@ -537,6 +656,8 @@ static void overmem_purge(dns_rbtdb_t *rbtdb, unsigned int locknum_start, isc_stdtime_t now, isc_boolean_t tree_locked); static isc_result_t resign_insert(dns_rbtdb_t *rbtdb, int idx, rdatasetheader_t *newheader); +static void resign_delete(dns_rbtdb_t *rbtdb, rbtdb_version_t *version, + rdatasetheader_t *header); static void prune_tree(isc_task_t *task, isc_event_t *event); static void rdataset_settrust(dns_rdataset_t *rdataset, dns_trust_t trust); static void rdataset_expire(dns_rdataset_t *rdataset); @@ -774,7 +895,7 @@ resign_sooner(void *v1, void *v2) { rdatasetheader_t *h1 = v1; rdatasetheader_t *h2 = v2; - if (h1->resign < h2->resign) + if (isc_serial_lt(h1->resign, h2->resign)) return (ISC_TRUE); return (ISC_FALSE); } @@ -2372,8 +2493,18 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) { lock = &rbtdb->node_locks[header->node->locknum].lock; NODE_LOCK(lock, isc_rwlocktype_write); - if (rollback) - resign_insert(rbtdb, header->node->locknum, header); + if (rollback && !IGNORE(header)) { + isc_result_t result; + result = resign_insert(rbtdb, header->node->locknum, + header); + if (result != ISC_R_SUCCESS) + isc_log_write(dns_lctx, + DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_ZONE, ISC_LOG_ERROR, + "Unable to reinsert header to " + "re-signing heap: %s\n", + dns_result_totext(result)); + } decrement_reference(rbtdb, header->node, least_serial, isc_rwlocktype_write, isc_rwlocktype_none, ISC_FALSE); @@ -5874,10 +6005,28 @@ resign_insert(dns_rbtdb_t *rbtdb, int idx, rdatasetheader_t *newheader) { return (result); } +static void +resign_delete(dns_rbtdb_t *rbtdb, rbtdb_version_t *version, + rdatasetheader_t *header) +{ + /* + * Remove the old header from the heap + */ + if (header != NULL && header->heap_index != 0) { + isc_heap_delete(rbtdb->heaps[header->node->locknum], + header->heap_index); + header->heap_index = 0; + if (version != NULL) { + new_reference(rbtdb, header->node); + ISC_LIST_APPEND(version->resigned_list, header, link); + } + } +} + static isc_result_t -add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, - rdatasetheader_t *newheader, unsigned int options, isc_boolean_t loading, - dns_rdataset_t *addedrdataset, isc_stdtime_t now) +add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, + rdatasetheader_t *newheader, unsigned int options, isc_boolean_t loading, + dns_rdataset_t *addedrdataset, isc_stdtime_t now) { rbtdb_changed_t *changed = NULL; rdatasetheader_t *topheader, *topheader_prev, *header, *sigheader; @@ -6211,6 +6360,19 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, */ newheader->down = NULL; free_rdataset(rbtdb, rbtdb->common.mctx, header); + + idx = newheader->node->locknum; + if (IS_CACHE(rbtdb)) { + ISC_LIST_PREPEND(rbtdb->rdatasets[idx], + newheader, link); + INSIST(rbtdb->heaps != NULL); + (void)isc_heap_insert(rbtdb->heaps[idx], + newheader); + } else if (RESIGN(newheader)) { + result = resign_insert(rbtdb, idx, newheader); + if (result != ISC_R_SUCCESS) + return (result); + } } else { newheader->down = topheader; topheader->next = newheader; @@ -6238,9 +6400,14 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, * will not leak... for long. */ INSIST(rbtdb->heaps != NULL); - isc_heap_insert(rbtdb->heaps[idx], newheader); - } else if (RESIGN(newheader)) - resign_insert(rbtdb, idx, newheader); + (void)isc_heap_insert(rbtdb->heaps[idx], + newheader); + } else if (RESIGN(newheader)) { + resign_delete(rbtdb, rbtversion, header); + result = resign_insert(rbtdb, idx, newheader); + if (result != ISC_R_SUCCESS) + return (result); + } } } else { /* @@ -6292,7 +6459,10 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, newheader, link); isc_heap_insert(rbtdb->heaps[idx], newheader); } else if (RESIGN(newheader)) { - resign_insert(rbtdb, idx, newheader); + resign_delete(rbtdb, rbtversion, header); + result = resign_insert(rbtdb, idx, newheader); + if (result != ISC_R_SUCCESS) + return (result); } } @@ -6601,8 +6771,8 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, } if (result == ISC_R_SUCCESS) - result = add(rbtdb, rbtnode, rbtversion, newheader, options, - ISC_FALSE, addedrdataset, now); + result = add32(rbtdb, rbtnode, rbtversion, newheader, options, + ISC_FALSE, addedrdataset, now); if (result == ISC_R_SUCCESS && delegating) rbtnode->find_callback = 1; @@ -6778,6 +6948,7 @@ subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, topheader->next = newheader; rbtnode->dirty = 1; changed->dirty = ISC_TRUE; + resign_delete(rbtdb, rbtversion, header); } else { /* * The rdataset doesn't exist, so we don't need to do anything @@ -6847,8 +7018,8 @@ deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, NODE_LOCK(&rbtdb->node_locks[rbtnode->locknum].lock, isc_rwlocktype_write); - result = add(rbtdb, rbtnode, rbtversion, newheader, DNS_DBADD_FORCE, - ISC_FALSE, NULL, 0); + result = add32(rbtdb, rbtnode, rbtversion, newheader, DNS_DBADD_FORCE, + ISC_FALSE, NULL, 0); NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock, isc_rwlocktype_write); @@ -7042,8 +7213,8 @@ loading_addrdataset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset) { } else newheader->resign = 0; - result = add(rbtdb, node, rbtdb->current_version, newheader, - DNS_DBADD_MERGE, ISC_TRUE, NULL, 0); + result = add32(rbtdb, node, rbtdb->current_version, newheader, + DNS_DBADD_MERGE, ISC_TRUE, NULL, 0); if (result == ISC_R_SUCCESS && delegating_type(rbtdb, node, rdataset->type)) node->find_callback = 1; @@ -7411,6 +7582,9 @@ resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version) INSIST(header != NULL); header--; + if (header->heap_index == 0) + return; + RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write); NODE_LOCK(&rbtdb->node_locks[node->locknum].lock, isc_rwlocktype_write); @@ -7418,11 +7592,7 @@ resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version) * Delete from heap and save to re-signed list so that it can * be restored if we backout of this change. */ - new_reference(rbtdb, node); - isc_heap_delete(rbtdb->heaps[node->locknum], header->heap_index); - header->heap_index = 0; - ISC_LIST_APPEND(rbtversion->resigned_list, header, link); - + resign_delete(rbtdb, rbtversion, header); NODE_UNLOCK(&rbtdb->node_locks[node->locknum].lock, isc_rwlocktype_write); RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write); diff --git a/lib/dns/rcode.c b/lib/dns/rcode.c index 69007f881efd..2fdb751e6dbf 100644 --- a/lib/dns/rcode.c +++ b/lib/dns/rcode.c @@ -212,11 +212,13 @@ maybe_numeric(unsigned int *valuep, isc_textregion_t *source, return (ISC_R_BADNUMBER); /* - * We have a potential number. Try to parse it with - * isc_parse_uint32(). isc_parse_uint32() requires + * We have a potential number. Try to parse it with + * isc_parse_uint32(). isc_parse_uint32() requires * null termination, so we must make a copy. */ - strncpy(buffer, source->base, NUMBERSIZE); + strncpy(buffer, source->base, sizeof(buffer)); + buffer[sizeof(buffer) - 1] = '\0'; + INSIST(buffer[source->length] == '\0'); result = isc_parse_uint32(&n, buffer, 10); diff --git a/lib/dns/rdata.c b/lib/dns/rdata.c index 5bdd1255b5f7..08bfa34aa678 100644 --- a/lib/dns/rdata.c +++ b/lib/dns/rdata.c @@ -116,7 +116,7 @@ typedef struct dns_rdata_textctx { } dns_rdata_textctx_t; static isc_result_t -txt_totext(isc_region_t *source, isc_buffer_t *target); +txt_totext(isc_region_t *source, isc_boolean_t quote, isc_buffer_t *target); static isc_result_t txt_fromtext(isc_textregion_t *source, isc_buffer_t *target); @@ -130,9 +130,6 @@ multitxt_totext(isc_region_t *source, isc_buffer_t *target); static isc_result_t multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target); -static isc_result_t -multitxt_fromwire(isc_buffer_t *source, isc_buffer_t *target); - static isc_boolean_t name_prefix(dns_name_t *name, dns_name_t *origin, dns_name_t *target); @@ -1131,7 +1128,7 @@ name_length(dns_name_t *name) { } static isc_result_t -txt_totext(isc_region_t *source, isc_buffer_t *target) { +txt_totext(isc_region_t *source, isc_boolean_t quote, isc_buffer_t *target) { unsigned int tl; unsigned int n; unsigned char *sp; @@ -1146,13 +1143,20 @@ txt_totext(isc_region_t *source, isc_buffer_t *target) { n = *sp++; REQUIRE(n + 1 <= source->length); + if (n == 0U) + REQUIRE(quote == ISC_TRUE); - if (tl < 1) - return (ISC_R_NOSPACE); - *tp++ = '"'; - tl--; + if (quote) { + if (tl < 1) + return (ISC_R_NOSPACE); + *tp++ = '"'; + tl--; + } while (n--) { - if (*sp < 0x20 || *sp >= 0x7f) { + /* + * \DDD space (0x20) if not quoting. + */ + if (*sp < (quote ? 0x20 : 0x21) || *sp >= 0x7f) { if (tl < 4) return (ISC_R_NOSPACE); *tp++ = 0x5c; @@ -1163,8 +1167,13 @@ txt_totext(isc_region_t *source, isc_buffer_t *target) { tl -= 4; continue; } - /* double quote, semi-colon, backslash */ - if (*sp == 0x22 || *sp == 0x3b || *sp == 0x5c) { + /* + * Escape double quote, semi-colon, backslash. + * If we are not enclosing the string in double + * quotes also escape at sign. + */ + if (*sp == 0x22 || *sp == 0x3b || *sp == 0x5c || + (!quote && *sp == 0x40)) { if (tl < 2) return (ISC_R_NOSPACE); *tp++ = '\\'; @@ -1175,10 +1184,12 @@ txt_totext(isc_region_t *source, isc_buffer_t *target) { *tp++ = *sp++; tl--; } - if (tl < 1) - return (ISC_R_NOSPACE); - *tp++ = '"'; - tl--; + if (quote) { + if (tl < 1) + return (ISC_R_NOSPACE); + *tp++ = '"'; + tl--; + } isc_buffer_add(target, (unsigned int)(tp - (char *)region.base)); isc_region_consume(source, *source->base + 1); return (ISC_R_SUCCESS); @@ -1274,6 +1285,9 @@ txt_fromwire(isc_buffer_t *source, isc_buffer_t *target) { return (ISC_R_SUCCESS); } +/* + * Conversion of TXT-like rdata fields without length limits. + */ static isc_result_t multitxt_totext(isc_region_t *source, isc_buffer_t *target) { unsigned int tl; @@ -1292,9 +1306,8 @@ multitxt_totext(isc_region_t *source, isc_buffer_t *target) { *tp++ = '"'; tl--; do { - n0 = n = *sp++; - - REQUIRE(n0 + 1 <= source->length); + n = source->length; + n0 = source->length - 1; while (n--) { if (*sp < 0x20 || *sp >= 0x7f) { @@ -1346,17 +1359,11 @@ multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target) { do { isc_buffer_availableregion(target, &tregion); - t0 = tregion.base; + t0 = t = tregion.base; nrem = tregion.length; if (nrem < 1) return (ISC_R_NOSPACE); - /* length byte */ - t = t0; - nrem--; - t++; - /* 255 byte character-string slice */ - if (nrem > 255) - nrem = 255; + while (n != 0) { --n; c = (*s++) & 0xff; @@ -1390,39 +1397,9 @@ multitxt_fromtext(isc_textregion_t *source, isc_buffer_t *target) { } if (escape) return (DNS_R_SYNTAX); - *t0 = (unsigned char)(t - t0 - 1); - isc_buffer_add(target, *t0 + 1); - } while (n != 0); - return (ISC_R_SUCCESS); -} - -static isc_result_t -multitxt_fromwire(isc_buffer_t *source, isc_buffer_t *target) { - unsigned int n; - isc_region_t sregion; - isc_region_t tregion; - - isc_buffer_activeregion(source, &sregion); - if (sregion.length == 0) - return(ISC_R_UNEXPECTEDEND); - n = 256U; - do { - if (n != 256U) - return (DNS_R_SYNTAX); - n = *sregion.base + 1; - if (n > sregion.length) - return (ISC_R_UNEXPECTEDEND); - isc_buffer_availableregion(target, &tregion); - if (n > tregion.length) - return (ISC_R_NOSPACE); - - if (tregion.base != sregion.base) - memmove(tregion.base, sregion.base, n); - isc_buffer_forward(source, n); - isc_buffer_add(target, n); - isc_buffer_activeregion(source, &sregion); - } while (sregion.length != 0); + isc_buffer_add(target, t - t0); + } while (n != 0); return (ISC_R_SUCCESS); } diff --git a/lib/dns/rdata/generic/caa_257.c b/lib/dns/rdata/generic/caa_257.c new file mode 100644 index 000000000000..993e3267e623 --- /dev/null +++ b/lib/dns/rdata/generic/caa_257.c @@ -0,0 +1,370 @@ +/* + * 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_CAA_257_C +#define GENERIC_CAA_257_C 1 + +#define RRTYPE_CAA_ATTRIBUTES (0) + +static unsigned char const alphanumeric[256] = { + /* 0x00-0x0f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x10-0x1f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x20-0x2f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x30-0x3f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + /* 0x40-0x4f */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 0x50-0x5f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + /* 0x60-0x6f */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + /* 0x70-0x7f */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + /* 0x80-0x8f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x90-0x9f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0xa0-0xaf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0xb0-0xbf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0xc0-0xcf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0xd0-0xdf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0xe0-0xef */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 0xf0-0xff */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static inline isc_result_t +fromtext_caa(ARGS_FROMTEXT) { + isc_token_t token; + isc_textregion_t tr; + isc_uint8_t flags; + unsigned int i; + + REQUIRE(type == 257); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + /* Flags. */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + ISC_FALSE)); + if (token.value.as_ulong > 255U) + RETTOK(ISC_R_RANGE); + flags = token.value.as_ulong; + RETERR(uint8_tobuffer(flags, target)); + + /* + * Tag + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + ISC_FALSE)); + tr = token.value.as_textregion; + for (i = 0; i < tr.length; i++) + if (!alphanumeric[(unsigned int) tr.base[i]]) + RETTOK(DNS_R_SYNTAX); + RETERR(uint8_tobuffer(tr.length, target)); + RETERR(mem_tobuffer(target, tr.base, tr.length)); + + /* + * Value + */ + RETERR(isc_lex_getmastertoken(lexer, &token, + isc_tokentype_qstring, ISC_FALSE)); + if (token.type != isc_tokentype_qstring && + token.type != isc_tokentype_string) + RETERR(DNS_R_SYNTAX); + RETERR(multitxt_fromtext(&token.value.as_textregion, target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_caa(ARGS_TOTEXT) { + isc_region_t region; + isc_uint8_t flags; + char buf[256]; + + UNUSED(tctx); + + REQUIRE(rdata->type == 257); + REQUIRE(rdata->length >= 3U); + REQUIRE(rdata->data != NULL); + + dns_rdata_toregion(rdata, ®ion); + + /* + * Flags + */ + flags = uint8_consume_fromregion(®ion); + sprintf(buf, "%u ", flags); + RETERR(str_totext(buf, target)); + + /* + * Tag + */ + RETERR(txt_totext(®ion, ISC_FALSE, target)); + RETERR(str_totext(" ", target)); + + /* + * Value + */ + RETERR(multitxt_totext(®ion, target)); + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_caa(ARGS_FROMWIRE) { + isc_region_t sr; + unsigned int len, i; + + REQUIRE(type == 257); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(dctx); + UNUSED(options); + + /* + * Flags + */ + isc_buffer_activeregion(source, &sr); + if (sr.length < 2) + return (ISC_R_UNEXPECTEDEND); + + /* + * Flags, tag length + */ + RETERR(mem_tobuffer(target, sr.base, 2)); + len = sr.base[1]; + isc_region_consume(&sr, 2); + isc_buffer_forward(source, 2); + + /* + * Zero length tag fields are illegal. + */ + if (sr.length < len || len == 0) + RETERR(DNS_R_FORMERR); + + /* Check the Tag's value */ + for (i = 0; i < len; i++) + if (!alphanumeric[sr.base[i]]) + RETERR(DNS_R_FORMERR); + /* + * Tag + Value + */ + isc_buffer_forward(source, sr.length); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline isc_result_t +towire_caa(ARGS_TOWIRE) { + isc_region_t region; + + REQUIRE(rdata->type == 257); + REQUIRE(rdata->length >= 3U); + REQUIRE(rdata->data != NULL); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, ®ion); + return (mem_tobuffer(target, region.base, region.length)); +} + +static inline int +compare_caa(ARGS_COMPARE) { + isc_region_t r1, r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == 257); + REQUIRE(rdata1->length >= 3U); + REQUIRE(rdata2->length >= 3U); + REQUIRE(rdata1->data != NULL); + REQUIRE(rdata2->data != NULL); + + dns_rdata_toregion(rdata1, &r1); + dns_rdata_toregion(rdata2, &r2); + return (isc_region_compare(&r1, &r2)); +} + +static inline isc_result_t +fromstruct_caa(ARGS_FROMSTRUCT) { + dns_rdata_caa_t *caa = source; + isc_region_t region; + unsigned int i; + + REQUIRE(type == 257); + REQUIRE(source != NULL); + REQUIRE(caa->common.rdtype == type); + REQUIRE(caa->common.rdclass == rdclass); + REQUIRE(caa->tag != NULL && caa->tag_len != 0); + REQUIRE(caa->value != NULL); + + UNUSED(type); + UNUSED(rdclass); + + /* + * Flags + */ + RETERR(uint8_tobuffer(caa->flags, target)); + + /* + * Tag length + */ + RETERR(uint8_tobuffer(caa->tag_len, target)); + + /* + * Tag + */ + region.base = caa->tag; + region.length = caa->tag_len; + for (i = 0; i < region.length; i++) + if (!alphanumeric[region.base[i]]) + RETERR(DNS_R_SYNTAX); + RETERR(isc_buffer_copyregion(target, ®ion)); + + /* + * Value + */ + region.base = caa->value; + region.length = caa->value_len; + return (isc_buffer_copyregion(target, ®ion)); +} + +static inline isc_result_t +tostruct_caa(ARGS_TOSTRUCT) { + dns_rdata_caa_t *caa = target; + isc_region_t sr; + + REQUIRE(rdata->type == 257); + REQUIRE(target != NULL); + REQUIRE(rdata->length >= 3U); + REQUIRE(rdata->data != NULL); + + caa->common.rdclass = rdata->rdclass; + caa->common.rdtype = rdata->type; + ISC_LINK_INIT(&caa->common, link); + + dns_rdata_toregion(rdata, &sr); + + /* + * Flags + */ + if (sr.length < 1) + return (ISC_R_UNEXPECTEDEND); + caa->flags = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + + /* + * Tag length + */ + if (sr.length < 1) + return (ISC_R_UNEXPECTEDEND); + caa->tag_len = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + + /* + * Tag + */ + if (sr.length < caa->tag_len) + return (ISC_R_UNEXPECTEDEND); + caa->tag = mem_maybedup(mctx, sr.base, caa->tag_len); + if (caa->tag == NULL) + return (ISC_R_NOMEMORY); + isc_region_consume(&sr, caa->tag_len); + + /* + * Value + */ + caa->value_len = sr.length; + caa->value = mem_maybedup(mctx, sr.base, sr.length); + if (caa->value == NULL) + return (ISC_R_NOMEMORY); + + caa->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_caa(ARGS_FREESTRUCT) { + dns_rdata_caa_t *caa = (dns_rdata_caa_t *) source; + + REQUIRE(source != NULL); + REQUIRE(caa->common.rdtype == 257); + + if (caa->mctx == NULL) + return; + + if (caa->tag != NULL) + isc_mem_free(caa->mctx, caa->tag); + if (caa->value != NULL) + isc_mem_free(caa->mctx, caa->value); + caa->mctx = NULL; +} + +static inline isc_result_t +additionaldata_caa(ARGS_ADDLDATA) { + REQUIRE(rdata->type == 257); + REQUIRE(rdata->data != NULL); + REQUIRE(rdata->length >= 3U); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_caa(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == 257); + REQUIRE(rdata->data != NULL); + REQUIRE(rdata->length >= 3U); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline isc_boolean_t +checkowner_caa(ARGS_CHECKOWNER) { + + REQUIRE(type == 257); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (ISC_TRUE); +} + +static inline isc_boolean_t +checknames_caa(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == 257); + REQUIRE(rdata->data != NULL); + REQUIRE(rdata->length >= 3U); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (ISC_TRUE); +} + +static inline int +casecompare_caa(ARGS_COMPARE) { + return (compare_caa(rdata1, rdata2)); +} + +#endif /* GENERIC_CAA_257_C */ diff --git a/lib/dns/rdata/generic/caa_257.h b/lib/dns/rdata/generic/caa_257.h new file mode 100644 index 000000000000..9432f0f7f1ad --- /dev/null +++ b/lib/dns/rdata/generic/caa_257.h @@ -0,0 +1,32 @@ +/* + * 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_CAA_257_H +#define GENERIC_CAA_257_H 1 + +/* $Id$ */ + +typedef struct dns_rdata_caa { + dns_rdatacommon_t common; + isc_mem_t * mctx; + isc_uint8_t flags; + unsigned char * tag; + isc_uint8_t tag_len; + unsigned char *value; + isc_uint8_t value_len; +} dns_rdata_caa_t; + +#endif /* GENERIC_CAA_257_H */ diff --git a/lib/dns/rdata/generic/cdnskey_60.c b/lib/dns/rdata/generic/cdnskey_60.c new file mode 100644 index 000000000000..a1e681403b75 --- /dev/null +++ b/lib/dns/rdata/generic/cdnskey_60.c @@ -0,0 +1,378 @@ +/* + * 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. + */ + +/* $Id$ */ + +/* + * Reviewed: Wed Mar 15 16:47:10 PST 2000 by halley. + */ + +/* RFC2535 */ + +#ifndef RDATA_GENERIC_CDNSKEY_60_C +#define RDATA_GENERIC_CDNSKEY_60_C + +#include <dst/dst.h> + +#define RRTYPE_CDNSKEY_ATTRIBUTES (DNS_RDATATYPEATTR_DNSSEC) + +static inline isc_result_t +fromtext_cdnskey(ARGS_FROMTEXT) { + isc_result_t result; + isc_token_t token; + dns_secalg_t alg; + dns_secproto_t proto; + dns_keyflags_t flags; + + REQUIRE(type == 60); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + /* flags */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + ISC_FALSE)); + RETTOK(dns_keyflags_fromtext(&flags, &token.value.as_textregion)); + RETERR(uint16_tobuffer(flags, target)); + + /* protocol */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + ISC_FALSE)); + RETTOK(dns_secproto_fromtext(&proto, &token.value.as_textregion)); + RETERR(mem_tobuffer(target, &proto, 1)); + + /* algorithm */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + ISC_FALSE)); + RETTOK(dns_secalg_fromtext(&alg, &token.value.as_textregion)); + RETERR(mem_tobuffer(target, &alg, 1)); + + /* No Key? */ + if ((flags & 0xc000) == 0xc000) + return (ISC_R_SUCCESS); + + result = isc_base64_tobuffer(lexer, target, -1); + if (result != ISC_R_SUCCESS) + return (result); + + /* Ensure there's at least enough data to compute a key ID for MD5 */ + if (alg == DST_ALG_RSAMD5 && isc_buffer_usedlength(target) < 7) + return (ISC_R_UNEXPECTEDEND); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +totext_cdnskey(ARGS_TOTEXT) { + isc_region_t sr; + char buf[sizeof("64000")]; + unsigned int flags; + unsigned char algorithm; + char algbuf[DNS_NAME_FORMATSIZE]; + const char *keyinfo; + + REQUIRE(rdata->type == 60); + REQUIRE(rdata->length != 0); + + dns_rdata_toregion(rdata, &sr); + + /* flags */ + flags = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + sprintf(buf, "%u", flags); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + if ((flags & DNS_KEYFLAG_KSK) != 0) { + if (flags & DNS_KEYFLAG_REVOKE) + keyinfo = "revoked KSK"; + else + keyinfo = "KSK"; + } else + keyinfo = "ZSK"; + + /* protocol */ + sprintf(buf, "%u", sr.base[0]); + isc_region_consume(&sr, 1); + RETERR(str_totext(buf, target)); + RETERR(str_totext(" ", target)); + + /* algorithm */ + algorithm = sr.base[0]; + sprintf(buf, "%u", algorithm); + isc_region_consume(&sr, 1); + RETERR(str_totext(buf, target)); + + /* No Key? */ + if ((flags & 0xc000) == 0xc000) + return (ISC_R_SUCCESS); + + if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0 && + algorithm == DNS_KEYALG_PRIVATEDNS) { + dns_name_t name; + dns_name_init(&name, NULL); + dns_name_fromregion(&name, &sr); + dns_name_format(&name, algbuf, sizeof(algbuf)); + } else { + dns_secalg_format((dns_secalg_t) algorithm, algbuf, + sizeof(algbuf)); + } + + /* key */ + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" (", target)); + RETERR(str_totext(tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_base64_totext(&sr, 0, "", target)); + else + RETERR(isc_base64_totext(&sr, tctx->width - 2, + tctx->linebreak, target)); + + if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) + RETERR(str_totext(tctx->linebreak, target)); + else if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" ", target)); + + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(")", target)); + + if ((tctx->flags & DNS_STYLEFLAG_RRCOMMENT) != 0) { + isc_region_t tmpr; + + RETERR(str_totext(" ; ", target)); + RETERR(str_totext(keyinfo, target)); + RETERR(str_totext("; alg = ", target)); + RETERR(str_totext(algbuf, target)); + RETERR(str_totext("; key id = ", target)); + dns_rdata_toregion(rdata, &tmpr); + sprintf(buf, "%u", dst_region_computeid(&tmpr, algorithm)); + RETERR(str_totext(buf, target)); + } + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +fromwire_cdnskey(ARGS_FROMWIRE) { + unsigned char algorithm; + isc_region_t sr; + + REQUIRE(type == 60); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(dctx); + UNUSED(options); + + isc_buffer_activeregion(source, &sr); + if (sr.length < 4) + return (ISC_R_UNEXPECTEDEND); + + algorithm = sr.base[3]; + RETERR(mem_tobuffer(target, sr.base, 4)); + isc_region_consume(&sr, 4); + isc_buffer_forward(source, 4); + + if (algorithm == DNS_KEYALG_PRIVATEDNS) { + dns_name_t name; + dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); + dns_name_init(&name, NULL); + RETERR(dns_name_fromwire(&name, source, dctx, options, target)); + } + + /* + * RSAMD5 computes key ID differently from other + * algorithms: we need to ensure there's enough data + * present for the computation + */ + if (algorithm == DST_ALG_RSAMD5 && sr.length < 3) + return (ISC_R_UNEXPECTEDEND); + + 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_cdnskey(ARGS_TOWIRE) { + isc_region_t sr; + + REQUIRE(rdata->type == 60); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_cdnskey(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == 60); + 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_cdnskey(ARGS_FROMSTRUCT) { + dns_rdata_cdnskey_t *dnskey = source; + + REQUIRE(type == 60); + REQUIRE(source != NULL); + REQUIRE(dnskey->common.rdtype == type); + REQUIRE(dnskey->common.rdclass == rdclass); + + UNUSED(type); + UNUSED(rdclass); + + /* Flags */ + RETERR(uint16_tobuffer(dnskey->flags, target)); + + /* Protocol */ + RETERR(uint8_tobuffer(dnskey->protocol, target)); + + /* Algorithm */ + RETERR(uint8_tobuffer(dnskey->algorithm, target)); + + /* Data */ + return (mem_tobuffer(target, dnskey->data, dnskey->datalen)); +} + +static inline isc_result_t +tostruct_cdnskey(ARGS_TOSTRUCT) { + dns_rdata_cdnskey_t *dnskey = target; + isc_region_t sr; + + REQUIRE(rdata->type == 60); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + dnskey->common.rdclass = rdata->rdclass; + dnskey->common.rdtype = rdata->type; + ISC_LINK_INIT(&dnskey->common, link); + + dns_rdata_toregion(rdata, &sr); + + /* Flags */ + if (sr.length < 2) + return (ISC_R_UNEXPECTEDEND); + dnskey->flags = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + + /* Protocol */ + if (sr.length < 1) + return (ISC_R_UNEXPECTEDEND); + dnskey->protocol = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + + /* Algorithm */ + if (sr.length < 1) + return (ISC_R_UNEXPECTEDEND); + dnskey->algorithm = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + + /* Data */ + dnskey->datalen = sr.length; + dnskey->data = mem_maybedup(mctx, sr.base, dnskey->datalen); + if (dnskey->data == NULL) + return (ISC_R_NOMEMORY); + + dnskey->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_cdnskey(ARGS_FREESTRUCT) { + dns_rdata_cdnskey_t *dnskey = (dns_rdata_cdnskey_t *) source; + + REQUIRE(source != NULL); + REQUIRE(dnskey->common.rdtype == 60); + + if (dnskey->mctx == NULL) + return; + + if (dnskey->data != NULL) + isc_mem_free(dnskey->mctx, dnskey->data); + dnskey->mctx = NULL; +} + +static inline isc_result_t +additionaldata_cdnskey(ARGS_ADDLDATA) { + REQUIRE(rdata->type == 60); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_cdnskey(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == 60); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline isc_boolean_t +checkowner_cdnskey(ARGS_CHECKOWNER) { + + REQUIRE(type == 60); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (ISC_TRUE); +} + +static inline isc_boolean_t +checknames_cdnskey(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == 60); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (ISC_TRUE); +} + +static inline int +casecompare_cdnskey(ARGS_COMPARE) { + + /* + * Treat ALG 253 (private DNS) subtype name case sensistively. + */ + return (compare_cdnskey(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_CDNSKEY_60_C */ diff --git a/lib/dns/rdata/generic/cdnskey_60.h b/lib/dns/rdata/generic/cdnskey_60.h new file mode 100644 index 000000000000..d284177c118d --- /dev/null +++ b/lib/dns/rdata/generic/cdnskey_60.h @@ -0,0 +1,32 @@ +/* + * 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_CDNSKEY_60_H +#define GENERIC_CDNSKEY_60_H 1 + +/* CDNSKEY records have the same RDATA fields as DNSKEY records. */ +typedef struct dns_rdata_cdnskey { + dns_rdatacommon_t common; + isc_mem_t * mctx; + isc_uint16_t flags; + isc_uint8_t protocol; + isc_uint8_t algorithm; + isc_uint16_t datalen; + unsigned char * data; +} dns_rdata_cdnskey_t; + + +#endif /* GENERIC_CDNSKEY_60_H */ diff --git a/lib/dns/rdata/generic/cds_59.c b/lib/dns/rdata/generic/cds_59.c new file mode 100644 index 000000000000..fcf49662c46a --- /dev/null +++ b/lib/dns/rdata/generic/cds_59.c @@ -0,0 +1,354 @@ +/* + * 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. + */ + +/* $Id$ */ + +/* draft-ietf-dnsext-delegation-signer-05.txt */ + +#ifndef RDATA_GENERIC_CDS_59_C +#define RDATA_GENERIC_CDS_59_C + +#define RRTYPE_CDS_ATTRIBUTES \ + (DNS_RDATATYPEATTR_DNSSEC|DNS_RDATATYPEATTR_ATPARENT) + +#include <isc/sha1.h> +#include <isc/sha2.h> + +#include <dns/ds.h> + +static inline isc_result_t +fromtext_cds(ARGS_FROMTEXT) { + isc_token_t token; + unsigned char c; + int length; + + REQUIRE(type == 59); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(origin); + UNUSED(options); + UNUSED(callbacks); + + /* + * Key tag. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + ISC_FALSE)); + if (token.value.as_ulong > 0xffffU) + RETTOK(ISC_R_RANGE); + RETERR(uint16_tobuffer(token.value.as_ulong, target)); + + /* + * Algorithm. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, + ISC_FALSE)); + RETTOK(dns_secalg_fromtext(&c, &token.value.as_textregion)); + RETERR(mem_tobuffer(target, &c, 1)); + + /* + * Digest type. + */ + RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, + ISC_FALSE)); + if (token.value.as_ulong > 0xffU) + RETTOK(ISC_R_RANGE); + RETERR(uint8_tobuffer(token.value.as_ulong, target)); + c = (unsigned char) token.value.as_ulong; + + /* + * Digest. + */ + switch (c) { + case DNS_DSDIGEST_SHA1: + length = ISC_SHA1_DIGESTLENGTH; + break; + case DNS_DSDIGEST_SHA256: + length = ISC_SHA256_DIGESTLENGTH; + break; + case DNS_DSDIGEST_GOST: + length = ISC_GOST_DIGESTLENGTH; + break; + case DNS_DSDIGEST_SHA384: + length = ISC_SHA384_DIGESTLENGTH; + break; + default: + length = -1; + break; + } + return (isc_hex_tobuffer(lexer, target, length)); +} + +static inline isc_result_t +totext_cds(ARGS_TOTEXT) { + isc_region_t sr; + char buf[sizeof("64000 ")]; + unsigned int n; + + REQUIRE(rdata->type == 59); + REQUIRE(rdata->length != 0); + + UNUSED(tctx); + + dns_rdata_toregion(rdata, &sr); + + /* + * Key tag. + */ + n = uint16_fromregion(&sr); + isc_region_consume(&sr, 2); + sprintf(buf, "%u ", n); + RETERR(str_totext(buf, target)); + + /* + * Algorithm. + */ + n = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + sprintf(buf, "%u ", n); + RETERR(str_totext(buf, target)); + + /* + * Digest type. + */ + n = uint8_fromregion(&sr); + isc_region_consume(&sr, 1); + sprintf(buf, "%u", n); + RETERR(str_totext(buf, target)); + + /* + * Digest. + */ + if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) + RETERR(str_totext(" (", target)); + RETERR(str_totext(tctx->linebreak, target)); + if (tctx->width == 0) /* No splitting */ + RETERR(isc_hex_totext(&sr, 0, "", target)); + else + RETERR(isc_hex_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_cds(ARGS_FROMWIRE) { + isc_region_t sr; + + REQUIRE(type == 59); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(dctx); + UNUSED(options); + + isc_buffer_activeregion(source, &sr); + + /* + * Check digest lengths if we know them. + */ + if (sr.length < 4 || + (sr.base[3] == DNS_DSDIGEST_SHA1 && + sr.length < 4 + ISC_SHA1_DIGESTLENGTH) || + (sr.base[3] == DNS_DSDIGEST_SHA256 && + sr.length < 4 + ISC_SHA256_DIGESTLENGTH) || + (sr.base[3] == DNS_DSDIGEST_GOST && + sr.length < 4 + ISC_GOST_DIGESTLENGTH) || + (sr.base[3] == DNS_DSDIGEST_SHA384 && + sr.length < 4 + ISC_SHA384_DIGESTLENGTH)) + return (ISC_R_UNEXPECTEDEND); + + /* + * Only copy digest lengths if we know them. + * If there is extra data dns_rdata_fromwire() will + * detect that. + */ + if (sr.base[3] == DNS_DSDIGEST_SHA1) + sr.length = 4 + ISC_SHA1_DIGESTLENGTH; + else if (sr.base[3] == DNS_DSDIGEST_SHA256) + sr.length = 4 + ISC_SHA256_DIGESTLENGTH; + else if (sr.base[3] == DNS_DSDIGEST_GOST) + sr.length = 4 + ISC_GOST_DIGESTLENGTH; + else if (sr.base[3] == DNS_DSDIGEST_SHA384) + sr.length = 4 + ISC_SHA384_DIGESTLENGTH; + + isc_buffer_forward(source, sr.length); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline isc_result_t +towire_cds(ARGS_TOWIRE) { + isc_region_t sr; + + REQUIRE(rdata->type == 59); + REQUIRE(rdata->length != 0); + + UNUSED(cctx); + + dns_rdata_toregion(rdata, &sr); + return (mem_tobuffer(target, sr.base, sr.length)); +} + +static inline int +compare_cds(ARGS_COMPARE) { + isc_region_t r1; + isc_region_t r2; + + REQUIRE(rdata1->type == rdata2->type); + REQUIRE(rdata1->rdclass == rdata2->rdclass); + REQUIRE(rdata1->type == 59); + 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_cds(ARGS_FROMSTRUCT) { + dns_rdata_cds_t *ds = source; + + REQUIRE(type == 59); + REQUIRE(source != NULL); + REQUIRE(ds->common.rdtype == type); + REQUIRE(ds->common.rdclass == rdclass); + switch (ds->digest_type) { + case DNS_DSDIGEST_SHA1: + REQUIRE(ds->length == ISC_SHA1_DIGESTLENGTH); + break; + case DNS_DSDIGEST_SHA256: + REQUIRE(ds->length == ISC_SHA256_DIGESTLENGTH); + break; + case DNS_DSDIGEST_GOST: + REQUIRE(ds->length == ISC_GOST_DIGESTLENGTH); + break; + case DNS_DSDIGEST_SHA384: + REQUIRE(ds->length == ISC_SHA384_DIGESTLENGTH); + break; + } + + UNUSED(type); + UNUSED(rdclass); + + RETERR(uint16_tobuffer(ds->key_tag, target)); + RETERR(uint8_tobuffer(ds->algorithm, target)); + RETERR(uint8_tobuffer(ds->digest_type, target)); + + return (mem_tobuffer(target, ds->digest, ds->length)); +} + +static inline isc_result_t +tostruct_cds(ARGS_TOSTRUCT) { + dns_rdata_cds_t *ds = target; + isc_region_t region; + + REQUIRE(rdata->type == 59); + REQUIRE(target != NULL); + REQUIRE(rdata->length != 0); + + ds->common.rdclass = rdata->rdclass; + ds->common.rdtype = rdata->type; + ISC_LINK_INIT(&ds->common, link); + + dns_rdata_toregion(rdata, ®ion); + + ds->key_tag = uint16_fromregion(®ion); + isc_region_consume(®ion, 2); + ds->algorithm = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + ds->digest_type = uint8_fromregion(®ion); + isc_region_consume(®ion, 1); + ds->length = region.length; + + ds->digest = mem_maybedup(mctx, region.base, region.length); + if (ds->digest == NULL) + return (ISC_R_NOMEMORY); + + ds->mctx = mctx; + return (ISC_R_SUCCESS); +} + +static inline void +freestruct_cds(ARGS_FREESTRUCT) { + dns_rdata_cds_t *ds = source; + + REQUIRE(ds != NULL); + REQUIRE(ds->common.rdtype == 59); + + if (ds->mctx == NULL) + return; + + if (ds->digest != NULL) + isc_mem_free(ds->mctx, ds->digest); + ds->mctx = NULL; +} + +static inline isc_result_t +additionaldata_cds(ARGS_ADDLDATA) { + REQUIRE(rdata->type == 59); + + UNUSED(rdata); + UNUSED(add); + UNUSED(arg); + + return (ISC_R_SUCCESS); +} + +static inline isc_result_t +digest_cds(ARGS_DIGEST) { + isc_region_t r; + + REQUIRE(rdata->type == 59); + + dns_rdata_toregion(rdata, &r); + + return ((digest)(arg, &r)); +} + +static inline isc_boolean_t +checkowner_cds(ARGS_CHECKOWNER) { + + REQUIRE(type == 59); + + UNUSED(name); + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); + + return (ISC_TRUE); +} + +static inline isc_boolean_t +checknames_cds(ARGS_CHECKNAMES) { + + REQUIRE(rdata->type == 59); + + UNUSED(rdata); + UNUSED(owner); + UNUSED(bad); + + return (ISC_TRUE); +} + +static inline int +casecompare_cds(ARGS_COMPARE) { + return (compare_cds(rdata1, rdata2)); +} + +#endif /* RDATA_GENERIC_CDS_59_C */ diff --git a/lib/dns/rdata/generic/cds_59.h b/lib/dns/rdata/generic/cds_59.h new file mode 100644 index 000000000000..099cba39468c --- /dev/null +++ b/lib/dns/rdata/generic/cds_59.h @@ -0,0 +1,31 @@ +/* + * 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_CDS_59_H +#define GENERIC_CDS_59_H 1 + +/* CDS records have the same RDATA fields as DS records. */ +typedef struct dns_rdata_cds { + dns_rdatacommon_t common; + isc_mem_t *mctx; + isc_uint16_t key_tag; + isc_uint8_t algorithm; + isc_uint8_t digest_type; + isc_uint16_t length; + unsigned char *digest; +} dns_rdata_cds_t; + +#endif /* GENERIC_CDS_59_H */ diff --git a/lib/dns/rdata/generic/gpos_27.c b/lib/dns/rdata/generic/gpos_27.c index ce71822b8237..e9ba59eacb6a 100644 --- a/lib/dns/rdata/generic/gpos_27.c +++ b/lib/dns/rdata/generic/gpos_27.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 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 @@ -61,7 +61,7 @@ totext_gpos(ARGS_TOTEXT) { dns_rdata_toregion(rdata, ®ion); for (i = 0; i < 3; i++) { - RETERR(txt_totext(®ion, target)); + RETERR(txt_totext(®ion, ISC_TRUE, target)); if (i != 2) RETERR(str_totext(" ", target)); } diff --git a/lib/dns/rdata/generic/hinfo_13.c b/lib/dns/rdata/generic/hinfo_13.c index 10b4fec79dea..411d6b56866e 100644 --- a/lib/dns/rdata/generic/hinfo_13.c +++ b/lib/dns/rdata/generic/hinfo_13.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 2009, 2014 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1998-2002 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -58,9 +58,9 @@ totext_hinfo(ARGS_TOTEXT) { REQUIRE(rdata->length != 0); dns_rdata_toregion(rdata, ®ion); - RETERR(txt_totext(®ion, target)); + RETERR(txt_totext(®ion, ISC_TRUE, target)); RETERR(str_totext(" ", target)); - return (txt_totext(®ion, target)); + return (txt_totext(®ion, ISC_TRUE, target)); } static inline isc_result_t diff --git a/lib/dns/rdata/generic/hip_55.c b/lib/dns/rdata/generic/hip_55.c index 5198497dcb07..eee581f26a95 100644 --- a/lib/dns/rdata/generic/hip_55.c +++ b/lib/dns/rdata/generic/hip_55.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2011, 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2009, 2011, 2013, 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 @@ -318,6 +318,8 @@ tostruct_hip(ARGS_TOSTRUCT) { goto cleanup; isc_region_consume(®ion, hip->hit_len); + INSIST(hip->key_len <= region.length); + hip->key = mem_maybedup(mctx, region.base, hip->key_len); if (hip->key == NULL) goto cleanup; @@ -466,23 +468,19 @@ casecompare_hip(ARGS_COMPARE) { INSIST(r1.length > 4); INSIST(r2.length > 4); - r1.length = 4; - r2.length = 4; - order = isc_region_compare(&r1, &r2); + order = memcmp(r1.base, r2.base, 4); if (order != 0) return (order); hit_len = uint8_fromregion(&r1); isc_region_consume(&r1, 2); /* hit length + algorithm */ key_len = uint16_fromregion(&r1); - - dns_rdata_toregion(rdata1, &r1); - dns_rdata_toregion(rdata2, &r2); - isc_region_consume(&r1, 4); + isc_region_consume(&r1, 2); /* key length */ isc_region_consume(&r2, 4); + INSIST(r1.length >= (unsigned) (hit_len + key_len)); INSIST(r2.length >= (unsigned) (hit_len + key_len)); - order = isc_region_compare(&r1, &r2); + order = memcmp(r1.base, r2.base, hit_len + key_len); if (order != 0) return (order); isc_region_consume(&r1, hit_len + key_len); diff --git a/lib/dns/rdata/generic/isdn_20.c b/lib/dns/rdata/generic/isdn_20.c index 0bf2146013e8..dea36f0f658a 100644 --- a/lib/dns/rdata/generic/isdn_20.c +++ b/lib/dns/rdata/generic/isdn_20.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009, 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 2013, 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 @@ -65,11 +65,11 @@ totext_isdn(ARGS_TOTEXT) { UNUSED(tctx); dns_rdata_toregion(rdata, ®ion); - RETERR(txt_totext(®ion, target)); + RETERR(txt_totext(®ion, ISC_TRUE, target)); if (region.length == 0) return (ISC_R_SUCCESS); RETERR(str_totext(" ", target)); - return (txt_totext(®ion, target)); + return (txt_totext(®ion, ISC_TRUE, target)); } static inline isc_result_t diff --git a/lib/dns/rdata/generic/naptr_35.c b/lib/dns/rdata/generic/naptr_35.c index 83439a59293e..d7452ac176fe 100644 --- a/lib/dns/rdata/generic/naptr_35.c +++ b/lib/dns/rdata/generic/naptr_35.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007-2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 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 @@ -224,19 +224,19 @@ totext_naptr(ARGS_TOTEXT) { /* * Flags. */ - RETERR(txt_totext(®ion, target)); + RETERR(txt_totext(®ion, ISC_TRUE, target)); RETERR(str_totext(" ", target)); /* * Service. */ - RETERR(txt_totext(®ion, target)); + RETERR(txt_totext(®ion, ISC_TRUE, target)); RETERR(str_totext(" ", target)); /* * Regexp. */ - RETERR(txt_totext(®ion, target)); + RETERR(txt_totext(®ion, ISC_TRUE, target)); RETERR(str_totext(" ", target)); /* diff --git a/lib/dns/rdata/generic/nsec3_50.c b/lib/dns/rdata/generic/nsec3_50.c index 19b94efa06dc..35fcf5d58229 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 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2008, 2009, 2011, 2012, 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 @@ -100,7 +100,7 @@ fromtext_nsec3(ARGS_FROMTEXT) { RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, ISC_FALSE)); isc_buffer_init(&b, bm, sizeof(bm)); - RETTOK(isc_base32hex_decodestring(DNS_AS_STR(token), &b)); + RETTOK(isc_base32hexnp_decodestring(DNS_AS_STR(token), &b)); if (isc_buffer_usedlength(&b) > 0xffU) RETTOK(ISC_R_RANGE); RETERR(uint8_tobuffer(isc_buffer_usedlength(&b), target)); @@ -191,7 +191,7 @@ totext_nsec3(ARGS_TOTEXT) { i = sr.length; sr.length = j; - RETERR(isc_base32hex_totext(&sr, 1, "", target)); + RETERR(isc_base32hexnp_totext(&sr, 1, "", target)); sr.length = i - j; if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) == 0) @@ -474,15 +474,26 @@ digest_nsec3(ARGS_DIGEST) { static inline isc_boolean_t checkowner_nsec3(ARGS_CHECKOWNER) { + unsigned char owner[NSEC3_MAX_HASH_LENGTH]; + isc_buffer_t buffer; + dns_label_t label; - REQUIRE(type == 50); + REQUIRE(type == 50); + + UNUSED(type); + UNUSED(rdclass); + UNUSED(wildcard); - UNUSED(name); - UNUSED(type); - UNUSED(rdclass); - UNUSED(wildcard); + /* + * First label is a base32hex string without padding. + */ + dns_name_getlabel(name, 0, &label); + isc_region_consume(&label, 1); + isc_buffer_init(&buffer, owner, sizeof(owner)); + if (isc_base32hexnp_decoderegion(&label, &buffer) == ISC_R_SUCCESS) + return (ISC_TRUE); - return (ISC_TRUE); + return (ISC_FALSE); } static inline isc_boolean_t diff --git a/lib/dns/rdata/generic/opt_41.c b/lib/dns/rdata/generic/opt_41.c index bd2adb5fe971..ae09abf71e91 100644 --- a/lib/dns/rdata/generic/opt_41.c +++ b/lib/dns/rdata/generic/opt_41.c @@ -151,6 +151,14 @@ fromwire_opt(ARGS_FROMWIRE) { isc_region_consume(&sregion, addrbytes); break; } + case DNS_OPT_EXPIRE: + /* + * Request has zero length. Response is 32 bits. + */ + if (length != 0 && length != 4) + return (DNS_R_FORMERR); + isc_region_consume(&sregion, length); + break; default: isc_region_consume(&sregion, length); break; diff --git a/lib/dns/rdata/generic/spf_99.c b/lib/dns/rdata/generic/spf_99.c index c7cdfc9fbbad..10e86b888f3a 100644 --- a/lib/dns/rdata/generic/spf_99.c +++ b/lib/dns/rdata/generic/spf_99.c @@ -64,7 +64,7 @@ totext_spf(ARGS_TOTEXT) { dns_rdata_toregion(rdata, ®ion); while (region.length > 0) { - RETERR(txt_totext(®ion, target)); + RETERR(txt_totext(®ion, ISC_TRUE, target)); if (region.length > 0) RETERR(str_totext(" ", target)); } diff --git a/lib/dns/rdata/generic/tkey_249.c b/lib/dns/rdata/generic/tkey_249.c index 6f1ec0253881..0c91fd221ed8 100644 --- a/lib/dns/rdata/generic/tkey_249.c +++ b/lib/dns/rdata/generic/tkey_249.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2007, 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 @@ -465,6 +465,7 @@ tostruct_tkey(ARGS_TOSTRUCT) { /* * Key. */ + INSIST(tkey->keylen + 2U <= sr.length); tkey->key = mem_maybedup(mctx, sr.base, tkey->keylen); if (tkey->key == NULL) goto cleanup; @@ -479,6 +480,7 @@ tostruct_tkey(ARGS_TOSTRUCT) { /* * Other. */ + INSIST(tkey->otherlen <= sr.length); tkey->other = mem_maybedup(mctx, sr.base, tkey->otherlen); if (tkey->other == NULL) goto cleanup; diff --git a/lib/dns/rdata/generic/tlsa_52.c b/lib/dns/rdata/generic/tlsa_52.c index 11c6d7528f98..b46556d35d4e 100644 --- a/lib/dns/rdata/generic/tlsa_52.c +++ b/lib/dns/rdata/generic/tlsa_52.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2012, 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 @@ -16,7 +16,7 @@ /* $Id$ */ -/* draft-ietf-dane-protocol-19.txt */ +/* rfc6698.txt */ #ifndef RDATA_GENERIC_TLSA_52_C #define RDATA_GENERIC_TLSA_52_C diff --git a/lib/dns/rdata/generic/tlsa_52.h b/lib/dns/rdata/generic/tlsa_52.h index 83ce9529976d..31bbf015c167 100644 --- a/lib/dns/rdata/generic/tlsa_52.h +++ b/lib/dns/rdata/generic/tlsa_52.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2012, 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 @@ -20,7 +20,7 @@ #define GENERIC_TLSA_52_H 1 /*! - * \brief per draft-ietf-dane-protocol-19.txt + * \brief per rfc6698.txt */ typedef struct dns_rdata_tlsa { dns_rdatacommon_t common; diff --git a/lib/dns/rdata/generic/txt_16.c b/lib/dns/rdata/generic/txt_16.c index 76109251a766..41e270279216 100644 --- a/lib/dns/rdata/generic/txt_16.c +++ b/lib/dns/rdata/generic/txt_16.c @@ -71,7 +71,7 @@ totext_txt(ARGS_TOTEXT) { dns_rdata_toregion(rdata, ®ion); while (region.length > 0) { - RETERR(txt_totext(®ion, target)); + RETERR(txt_totext(®ion, ISC_TRUE, target)); if (region.length > 0) RETERR(str_totext(" ", target)); } diff --git a/lib/dns/rdata/generic/uri_256.c b/lib/dns/rdata/generic/uri_256.c index 799eb694e666..3ddd790847ac 100644 --- a/lib/dns/rdata/generic/uri_256.c +++ b/lib/dns/rdata/generic/uri_256.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011, 2012 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2011, 2012, 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 @@ -115,15 +115,12 @@ fromwire_uri(ARGS_FROMWIRE) { isc_buffer_activeregion(source, ®ion); if (region.length < 4) return (ISC_R_UNEXPECTEDEND); - RETERR(mem_tobuffer(target, region.base, 4)); - isc_buffer_forward(source, 4); /* - * Target URI + * Priority, weight and target URI */ - RETERR(multitxt_fromwire(source, target)); - - return (ISC_R_SUCCESS); + isc_buffer_forward(source, region.length); + return (mem_tobuffer(target, region.base, region.length)); } static inline isc_result_t @@ -178,8 +175,6 @@ compare_uri(ARGS_COMPARE) { static inline isc_result_t fromstruct_uri(ARGS_FROMSTRUCT) { dns_rdata_uri_t *uri = source; - isc_region_t region; - isc_uint8_t len; REQUIRE(type == 256); REQUIRE(source != NULL); @@ -203,18 +198,6 @@ fromstruct_uri(ARGS_FROMSTRUCT) { /* * Target URI */ - len = 255U; - region.base = uri->target; - region.length = uri->tgt_len; - while (region.length > 0) { - REQUIRE(len == 255U); - len = uint8_fromregion(®ion); - isc_region_consume(®ion, 1); - if (region.length < len) - return (ISC_R_UNEXPECTEDEND); - isc_region_consume(®ion, len); - } - return (mem_tobuffer(target, uri->target, uri->tgt_len)); } diff --git a/lib/dns/rdata/generic/x25_19.c b/lib/dns/rdata/generic/x25_19.c index 6867fecd86f8..c5fe2d18b08c 100644 --- a/lib/dns/rdata/generic/x25_19.c +++ b/lib/dns/rdata/generic/x25_19.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2009, 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 @@ -60,7 +60,7 @@ totext_x25(ARGS_TOTEXT) { REQUIRE(rdata->length != 0); dns_rdata_toregion(rdata, ®ion); - return (txt_totext(®ion, target)); + return (txt_totext(®ion, ISC_TRUE, target)); } static inline isc_result_t diff --git a/lib/dns/rdataslab.c b/lib/dns/rdataslab.c index 1c02b60201b2..9367127d9eaf 100644 --- a/lib/dns/rdataslab.c +++ b/lib/dns/rdataslab.c @@ -148,21 +148,36 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, buflen = reservelen + 2; - nalloc = dns_rdataset_count(rdataset); - nitems = nalloc; - if (nitems == 0 && rdataset->type != 0) - return (ISC_R_FAILURE); + nitems = dns_rdataset_count(rdataset); - if (nalloc > 0xffff) - return (ISC_R_NOSPACE); + /* + * If there are no rdata then we can just need to allocate a header + * with zero a record count. + */ + if (nitems == 0) { + if (rdataset->type != 0) + return (ISC_R_FAILURE); + rawbuf = isc_mem_get(mctx, buflen); + if (rawbuf == NULL) + return (ISC_R_NOMEMORY); + region->base = rawbuf; + region->length = buflen; + rawbuf += reservelen; + *rawbuf++ = 0; + *rawbuf = 0; + return (ISC_R_SUCCESS); + } + if (nitems > 0xffff) + return (ISC_R_NOSPACE); - if (nalloc != 0) { - x = isc_mem_get(mctx, nalloc * sizeof(struct xrdata)); - if (x == NULL) - return (ISC_R_NOMEMORY); - } else - x = NULL; + /* + * Remember the original number of items. + */ + nalloc = nitems; + x = isc_mem_get(mctx, nalloc * sizeof(struct xrdata)); + if (x == NULL) + return (ISC_R_NOMEMORY); /* * Save all of the rdata members into an array. @@ -180,12 +195,12 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, #endif result = dns_rdataset_next(rdataset); } - if (result != ISC_R_NOMORE) - goto free_rdatas; - if (i != nalloc) { + if (i != nalloc || result != ISC_R_NOMORE) { /* * Somehow we iterated over fewer rdatas than - * dns_rdataset_count() said there were! + * dns_rdataset_count() said there were or there + * were more items than dns_rdataset_count said + * there were. */ result = ISC_R_FAILURE; goto free_rdatas; @@ -194,7 +209,8 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, /* * Put into DNSSEC order. */ - qsort(x, nalloc, sizeof(struct xrdata), compare_rdata); + if (nalloc > 1U) + qsort(x, nalloc, sizeof(struct xrdata), compare_rdata); /* * Remove duplicates and compute the total storage required. @@ -230,17 +246,15 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, buflen++; } } + /* * Don't forget the last item! */ - if (nalloc != 0) { #if DNS_RDATASET_FIXED - buflen += (8 + x[i-1].rdata.length); + buflen += (8 + x[i-1].rdata.length); #else - buflen += (2 + x[i-1].rdata.length); + buflen += (2 + x[i-1].rdata.length); #endif - } - /* * Provide space to store the per RR meta data. */ @@ -330,8 +344,7 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx, result = ISC_R_SUCCESS; free_rdatas: - if (x != NULL) - isc_mem_put(mctx, x, nalloc * sizeof(struct xrdata)); + isc_mem_put(mctx, x, nalloc * sizeof(struct xrdata)); return (result); } diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 2e60cd84cca2..befe3cafe0f2 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -21,6 +21,7 @@ #include <config.h> +#include <isc/counter.h> #include <isc/log.h> #include <isc/platform.h> #include <isc/print.h> @@ -131,11 +132,20 @@ #define MAXIMUM_QUERY_TIMEOUT 30 /* The maximum time in seconds for the whole query to live. */ #endif +/* The default maximum number of recursions to follow before giving up. */ +#ifndef DEFAULT_RECURSION_DEPTH +#define DEFAULT_RECURSION_DEPTH 7 +#endif + +/* The default maximum number of iterative queries to allow before giving up. */ +#ifndef DEFAULT_MAX_QUERIES +#define DEFAULT_MAX_QUERIES 50 +#endif + /*% * Maximum EDNS0 input packet size. */ #define RECV_BUFFER_SIZE 4096 /* XXXRTH Constant. */ -#define EDNSOPTS 2 /*% * This defines the maximum number of timeouts we will permit before we @@ -163,6 +173,7 @@ typedef struct query { isc_buffer_t *tsig; dns_tsigkey_t *tsigkey; isc_socketevent_t sendevent; + int ednsversion; unsigned int options; unsigned int attributes; unsigned int sends; @@ -234,12 +245,13 @@ struct fetchctx { isc_sockaddrlist_t edns; isc_sockaddrlist_t edns512; isc_sockaddrlist_t bad_edns; - dns_validator_t *validator; + dns_validator_t * validator; ISC_LIST(dns_validator_t) validators; dns_db_t * cache; dns_adb_t * adb; isc_boolean_t ns_ttl_ok; isc_uint32_t ns_ttl; + isc_counter_t * qc; /*% * The number of events we're waiting for. @@ -307,6 +319,7 @@ struct fetchctx { isc_boolean_t timeout; dns_adbaddrinfo_t *addrinfo; isc_sockaddr_t *client; + unsigned int depth; }; #define FCTX_MAGIC ISC_MAGIC('F', '!', '!', '!') @@ -343,6 +356,7 @@ typedef struct { struct dns_fetch { unsigned int magic; + isc_mem_t * mctx; fetchctx_t * private; }; @@ -418,6 +432,8 @@ struct dns_resolver { isc_timer_t * spillattimer; isc_boolean_t zero_no_soa_ttl; unsigned int query_timeout; + unsigned int maxdepth; + unsigned int maxqueries; /* Locked by lock. */ unsigned int references; @@ -449,12 +465,16 @@ struct dns_resolver { #define FCTX_ADDRINFO_MARK 0x0001 #define FCTX_ADDRINFO_FORWARDER 0x1000 #define FCTX_ADDRINFO_TRIED 0x2000 +#define FCTX_ADDRINFO_EDNSOK 0x4000 + #define UNMARKED(a) (((a)->flags & FCTX_ADDRINFO_MARK) \ == 0) #define ISFORWARDER(a) (((a)->flags & \ FCTX_ADDRINFO_FORWARDER) != 0) #define TRIED(a) (((a)->flags & \ FCTX_ADDRINFO_TRIED) != 0) +#define EDNSOK(a) (((a)->flags & \ + FCTX_ADDRINFO_EDNSOK) != 0) #define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0) #define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0) @@ -792,6 +812,7 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp, dns_adbfind_t *find; dns_adbaddrinfo_t *addrinfo; isc_socket_t *socket; + isc_stdtime_t now; query = *queryp; fctx = query->fctx; @@ -862,14 +883,13 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp, /* * Age RTTs of servers not tried. */ - factor = DNS_ADB_RTTADJAGE; + isc_stdtime_get(&now); if (finish != NULL) for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs); addrinfo != NULL; addrinfo = ISC_LIST_NEXT(addrinfo, publink)) if (UNMARKED(addrinfo)) - dns_adb_adjustsrtt(fctx->adb, addrinfo, - 0, factor); + dns_adb_agesrtt(fctx->adb, addrinfo, now); if (finish != NULL && TRIEDFIND(fctx)) for (find = ISC_LIST_HEAD(fctx->finds); @@ -879,16 +899,15 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp, addrinfo != NULL; addrinfo = ISC_LIST_NEXT(addrinfo, publink)) if (UNMARKED(addrinfo)) - dns_adb_adjustsrtt(fctx->adb, addrinfo, - 0, factor); + dns_adb_agesrtt(fctx->adb, addrinfo, + now); if (finish != NULL && TRIEDALT(fctx)) { for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs); addrinfo != NULL; addrinfo = ISC_LIST_NEXT(addrinfo, publink)) if (UNMARKED(addrinfo)) - dns_adb_adjustsrtt(fctx->adb, addrinfo, - 0, factor); + dns_adb_agesrtt(fctx->adb, addrinfo, now); for (find = ISC_LIST_HEAD(fctx->altfinds); find != NULL; find = ISC_LIST_NEXT(find, publink)) @@ -896,8 +915,8 @@ fctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp, addrinfo != NULL; addrinfo = ISC_LIST_NEXT(addrinfo, publink)) if (UNMARKED(addrinfo)) - dns_adb_adjustsrtt(fctx->adb, addrinfo, - 0, factor); + dns_adb_agesrtt(fctx->adb, addrinfo, + now); } /* @@ -1533,6 +1552,7 @@ fctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo, if (result != ISC_R_SUCCESS) goto cleanup_dispatch; } + fctx->querysent++; ISC_LIST_APPEND(fctx->queries, query, link); @@ -1674,7 +1694,7 @@ resquery_send(resquery_t *query) { isc_boolean_t cleanup_cctx = ISC_FALSE; isc_boolean_t secure_domain; isc_boolean_t connecting = ISC_FALSE; - dns_ednsopt_t ednsopts[EDNSOPTS]; + dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS]; unsigned ednsopt = 0; fctx = query->fctx; @@ -1821,12 +1841,12 @@ resquery_send(resquery_t *query) { if (fctx->timeout) { if ((triededns512(fctx, &query->addrinfo->sockaddr) || fctx->timeouts >= (MAX_EDNS0_TIMEOUTS * 2)) && - (query->options & DNS_FETCHOPT_NOEDNS0) == 0) { - query->options |= DNS_FETCHOPT_NOEDNS0; - fctx->reason = "disabling EDNS"; + (query->options & DNS_FETCHOPT_NOEDNS0) == 0 && + !EDNSOK(query->addrinfo)) { } else if ((triededns(fctx, &query->addrinfo->sockaddr) || fctx->timeouts >= MAX_EDNS0_TIMEOUTS) && - (query->options & DNS_FETCHOPT_NOEDNS0) == 0) { + (query->options & DNS_FETCHOPT_NOEDNS0) == 0 && + !EDNSOK(query->addrinfo)) { query->options |= DNS_FETCHOPT_EDNS512; fctx->reason = "reducing the advertised EDNS UDP " "packet size to 512 octets"; @@ -1859,12 +1879,13 @@ resquery_send(resquery_t *query) { if (peer != NULL) (void) dns_peer_getrequestnsid(peer, &reqnsid); if (reqnsid) { - INSIST(ednsopt < EDNSOPTS); + INSIST(ednsopt < DNS_EDNSOPTIONS); ednsopts[ednsopt].code = DNS_OPT_NSID; ednsopts[ednsopt].length = 0; ednsopts[ednsopt].value = NULL; ednsopt++; } + query->ednsversion = version; result = fctx_addopt(fctx->qmessage, version, udpsize, ednsopts, ednsopt); if (reqnsid && result == ISC_R_SUCCESS) { @@ -1876,6 +1897,7 @@ resquery_send(resquery_t *query) { * bit. */ query->options |= DNS_FETCHOPT_NOEDNS0; + query->ednsversion = -1; } } else { /* @@ -1884,8 +1906,10 @@ resquery_send(resquery_t *query) { * not using EDNS0. */ query->options |= DNS_FETCHOPT_NOEDNS0; + query->ednsversion = -1; } - } + } else + query->ednsversion = -1; /* * If we need EDNS0 to do this query and aren't using it, we lose. @@ -2186,9 +2210,9 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) { */ INSIST(!SHUTTINGDOWN(fctx)); fctx->attributes &= ~FCTX_ATTR_ADDRWAIT; - if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) + if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES) { want_try = ISC_TRUE; - else { + } else { fctx->findfail++; if (fctx->pending == 0) { /* @@ -2217,7 +2241,7 @@ fctx_finddone(isc_task_t *task, isc_event_t *event) { else if (want_done) fctx_done(fctx, ISC_R_FAILURE, __LINE__); else if (destroy) { - fctx_destroy(fctx); + fctx_destroy(fctx); if (bucket_empty) empty_bucket(res); } @@ -2471,12 +2495,13 @@ findname(fetchctx_t *fctx, dns_name_t *name, in_port_t port, * See what we know about this address. */ find = NULL; - result = dns_adb_createfind(fctx->adb, - res->buckets[fctx->bucketnum].task, - fctx_finddone, fctx, name, - &fctx->name, fctx->type, - options, now, NULL, - res->view->dstport, &find); + result = dns_adb_createfind2(fctx->adb, + res->buckets[fctx->bucketnum].task, + fctx_finddone, fctx, name, + &fctx->name, fctx->type, + options, now, NULL, + res->view->dstport, + fctx->depth + 1, fctx->qc, &find); if (result != ISC_R_SUCCESS) { if (result == DNS_R_ALIAS) { /* @@ -2584,6 +2609,14 @@ fctx_getaddresses(fetchctx_t *fctx, isc_boolean_t badcache) { res = fctx->res; + if (fctx->depth > res->maxdepth) { + isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER, + DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3), + "too much NS indirection resolving '%s'", + fctx->info); + return (DNS_R_SERVFAIL); + } + /* * Forwarders. */ @@ -3059,6 +3092,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; + } + result = fctx_query(fctx, addrinfo, fctx->options); if (result != ISC_R_SUCCESS) fctx_done(fctx, result, __LINE__); @@ -3157,6 +3200,7 @@ fctx_destroy(fetchctx_t *fctx) { isc_mem_put(fctx->mctx, sa, sizeof(*sa)); } + isc_counter_detach(&fctx->qc); isc_timer_detach(&fctx->timer); dns_message_destroy(&fctx->rmessage); dns_message_destroy(&fctx->qmessage); @@ -3485,7 +3529,8 @@ log_ns_ttl(fetchctx_t *fctx, const char *where) { static isc_result_t fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, dns_name_t *domain, dns_rdataset_t *nameservers, - unsigned int options, unsigned int bucketnum, fetchctx_t **fctxp) + unsigned int options, unsigned int bucketnum, unsigned int depth, + isc_counter_t *qc, fetchctx_t **fctxp) { fetchctx_t *fctx; isc_result_t result; @@ -3507,6 +3552,21 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, fctx = isc_mem_get(mctx, sizeof(*fctx)); if (fctx == NULL) return (ISC_R_NOMEMORY); + + fctx->qc = NULL; + if (qc != NULL) { + isc_counter_attach(qc, &fctx->qc); + } else { + result = isc_counter_create(res->mctx, + res->maxqueries, &fctx->qc); + if (result != ISC_R_SUCCESS) + goto cleanup_fetch; + } + + /* + * Make fctx->info point to a copy of a formatted string + * "name/type". + */ dns_name_format(name, buf, sizeof(buf)); dns_rdatatype_format(type, typebuf, sizeof(typebuf)); strcat(buf, "/"); /* checked */ @@ -3514,7 +3574,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, fctx->info = isc_mem_strdup(mctx, buf); if (fctx->info == NULL) { result = ISC_R_NOMEMORY; - goto cleanup_fetch; + goto cleanup_counter; } FCTXTRACE("create"); dns_name_init(&fctx->name, NULL); @@ -3537,6 +3597,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, fctx->state = fetchstate_init; fctx->want_shutdown = ISC_FALSE; fctx->cloned = ISC_FALSE; + fctx->depth = depth; ISC_LIST_INIT(fctx->queries); ISC_LIST_INIT(fctx->finds); ISC_LIST_INIT(fctx->altfinds); @@ -3615,7 +3676,7 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, */ if (dns_rdatatype_atparent(fctx->type)) findoptions |= DNS_DBFIND_NOEXACT; - result = dns_view_findzonecut(res->view, fwdname, + result = dns_view_findzonecut(res->view, name, domain, 0, findoptions, ISC_TRUE, &fctx->nameservers, @@ -3744,6 +3805,9 @@ fctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type, cleanup_info: isc_mem_free(mctx, fctx->info); + cleanup_counter: + isc_counter_detach(&fctx->qc); + cleanup_fetch: isc_mem_put(mctx, fctx, sizeof(*fctx)); @@ -4008,6 +4072,7 @@ validated(isc_task_t *task, isc_event_t *event) { isc_result_t result = ISC_R_SUCCESS; isc_stdtime_t now; isc_uint32_t ttl; + isc_uint32_t bucketnum; UNUSED(task); /* for now */ @@ -4024,7 +4089,8 @@ validated(isc_task_t *task, isc_event_t *event) { FCTXTRACE("received validation completion event"); - LOCK(&res->buckets[fctx->bucketnum].lock); + bucketnum = fctx->bucketnum; + LOCK(&res->buckets[bucketnum].lock); ISC_LIST_UNLINK(fctx->validators, vevent->validator, link); fctx->validator = NULL; @@ -4046,7 +4112,6 @@ validated(isc_task_t *task, isc_event_t *event) { * so, destroy the fctx. */ if (SHUTTINGDOWN(fctx) && !sentresponse) { - isc_uint32_t bucketnum = fctx->bucketnum; isc_boolean_t bucket_empty; bucket_empty = maybe_destroy(fctx, ISC_TRUE); UNLOCK(&res->buckets[bucketnum].lock); @@ -4149,7 +4214,7 @@ validated(isc_task_t *task, isc_event_t *event) { result = fctx->vresult; add_bad(fctx, addrinfo, result, badns_validation); isc_event_free(&event); - UNLOCK(&res->buckets[fctx->bucketnum].lock); + UNLOCK(&res->buckets[bucketnum].lock); INSIST(fctx->validator == NULL); fctx->validator = ISC_LIST_HEAD(fctx->validators); if (fctx->validator != NULL) @@ -4277,7 +4342,7 @@ validated(isc_task_t *task, isc_event_t *event) { dns_db_detachnode(fctx->cache, &node); if (SHUTTINGDOWN(fctx)) bucket_empty = maybe_destroy(fctx, ISC_TRUE); - UNLOCK(&res->buckets[fctx->bucketnum].lock); + UNLOCK(&res->buckets[bucketnum].lock); if (bucket_empty) empty_bucket(res); goto cleanup_event; @@ -4294,7 +4359,7 @@ validated(isc_task_t *task, isc_event_t *event) { * be validated. */ dns_db_detachnode(fctx->cache, &node); - UNLOCK(&res->buckets[fctx->bucketnum].lock); + UNLOCK(&res->buckets[bucketnum].lock); dns_validator_send(ISC_LIST_HEAD(fctx->validators)); goto cleanup_event; } @@ -4377,7 +4442,7 @@ validated(isc_task_t *task, isc_event_t *event) { if (node != NULL) dns_db_detachnode(fctx->cache, &node); - UNLOCK(&res->buckets[fctx->bucketnum].lock); + UNLOCK(&res->buckets[bucketnum].lock); fctx_done(fctx, result, __LINE__); /* Locks bucket. */ cleanup_event: @@ -4913,10 +4978,17 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, dns_adbaddrinfo_t *addrinfo, } } - if (valrdataset != NULL) - result = valcreate(fctx, addrinfo, name, fctx->type, - valrdataset, valsigrdataset, valoptions, - task); + if (valrdataset != NULL) { + dns_rdatatype_t vtype = fctx->type; + if (CHAINING(valrdataset)) { + if (valrdataset->type == dns_rdatatype_cname) + vtype = dns_rdatatype_cname; + else + vtype = dns_rdatatype_dname; + } + result = valcreate(fctx, addrinfo, name, vtype, valrdataset, + valsigrdataset, valoptions, task); + } if (result == ISC_R_SUCCESS && have_answer) { fctx->attributes |= FCTX_ATTR_HAVEANSWER; @@ -5657,7 +5729,7 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname, char qbuf[DNS_NAME_FORMATSIZE]; char nbuf[DNS_NAME_FORMATSIZE]; char tbuf[DNS_RDATATYPE_FORMATSIZE]; - dns_rdatatype_format(fctx->type, tbuf, + dns_rdatatype_format(type, tbuf, sizeof(tbuf)); dns_name_format(name, nbuf, sizeof(nbuf)); @@ -5666,8 +5738,8 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname, log_formerr(fctx, "unrelated %s %s in " "%s authority section", - tbuf, qbuf, nbuf); - return (DNS_R_FORMERR); + tbuf, nbuf, qbuf); + goto nextname; } if (type == dns_rdatatype_ns) { /* @@ -5730,6 +5802,7 @@ noanswer_response(fetchctx_t *fctx, dns_name_t *oqname, } } } + nextname: result = dns_message_nextname(message, section); if (result == ISC_R_NOMORE) break; @@ -7015,21 +7088,33 @@ resquery_response(isc_task_t *task, isc_event_t *event) { * EDNS may not be supported so we can now cache the lack of * EDNS support. */ - if (opt == NULL && + if (opt == NULL && !EDNSOK(query->addrinfo) && (message->rcode == dns_rcode_noerror || message->rcode == dns_rcode_nxdomain || message->rcode == dns_rcode_refused || message->rcode == dns_rcode_yxdomain) && bad_edns(fctx, &query->addrinfo->sockaddr)) { - char addrbuf[ISC_SOCKADDR_FORMATSIZE]; - isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf, - sizeof(addrbuf)); dns_adb_changeflags(fctx->adb, query->addrinfo, DNS_FETCHOPT_NOEDNS0, DNS_FETCHOPT_NOEDNS0); } /* + * If we get a non error EDNS response record the fact so we + * won't fallback to plain DNS in the future for this server. + */ + if (opt != NULL && !EDNSOK(query->addrinfo) && + (query->options & DNS_FETCHOPT_NOEDNS0) == 0 && + (message->rcode == dns_rcode_noerror || + message->rcode == dns_rcode_nxdomain || + message->rcode == dns_rcode_refused || + message->rcode == dns_rcode_yxdomain)) { + dns_adb_changeflags(fctx->adb, query->addrinfo, + FCTX_ADDRINFO_EDNSOK, + FCTX_ADDRINFO_EDNSOK); + } + + /* * Deal with truncated responses by retrying using TCP. */ if ((message->flags & DNS_MESSAGEFLAG_TC) != 0) @@ -7143,6 +7228,18 @@ resquery_response(isc_task_t *task, isc_event_t *event) { DNS_FETCHOPT_EDNSVERSIONSET; mask = DNS_FETCHOPT_EDNSVERSIONMASK | DNS_FETCHOPT_EDNSVERSIONSET; + /* + * Record that we got a good EDNS response. + */ + if (query->ednsversion > (int)version && + !EDNSOK(query->addrinfo)) { + dns_adb_changeflags(fctx->adb, query->addrinfo, + FCTX_ADDRINFO_EDNSOK, + FCTX_ADDRINFO_EDNSOK); + } + /* + * Record the supported EDNS version. + */ switch (version) { case 0: dns_adb_changeflags(fctx->adb, query->addrinfo, @@ -7731,6 +7828,8 @@ dns_resolver_create(dns_view_t *view, res->spillattimer = NULL; res->zero_no_soa_ttl = ISC_FALSE; res->query_timeout = DEFAULT_QUERY_TIMEOUT; + res->maxdepth = DEFAULT_RECURSION_DEPTH; + res->maxqueries = DEFAULT_MAX_QUERIES; res->nbuckets = ntasks; res->activebuckets = ntasks; res->buckets = isc_mem_get(view->mctx, @@ -8169,9 +8268,9 @@ dns_resolver_createfetch(dns_resolver_t *res, dns_name_t *name, dns_rdataset_t *sigrdataset, dns_fetch_t **fetchp) { - return (dns_resolver_createfetch2(res, name, type, domain, + return (dns_resolver_createfetch3(res, name, type, domain, nameservers, forwarders, NULL, 0, - options, task, action, arg, + options, 0, NULL, task, action, arg, rdataset, sigrdataset, fetchp)); } @@ -8187,6 +8286,25 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name, dns_rdataset_t *sigrdataset, dns_fetch_t **fetchp) { + return (dns_resolver_createfetch3(res, name, type, domain, + nameservers, forwarders, client, id, + options, 0, NULL, task, action, arg, + rdataset, sigrdataset, fetchp)); +} + +isc_result_t +dns_resolver_createfetch3(dns_resolver_t *res, dns_name_t *name, + dns_rdatatype_t type, + dns_name_t *domain, dns_rdataset_t *nameservers, + dns_forwarders_t *forwarders, + isc_sockaddr_t *client, dns_messageid_t id, + unsigned int options, unsigned int depth, + isc_counter_t *qc, isc_task_t *task, + isc_taskaction_t action, void *arg, + dns_rdataset_t *rdataset, + dns_rdataset_t *sigrdataset, + dns_fetch_t **fetchp) +{ dns_fetch_t *fetch; fetchctx_t *fctx = NULL; isc_result_t result = ISC_R_SUCCESS; @@ -8222,6 +8340,8 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name, fetch = isc_mem_get(res->mctx, sizeof(*fetch)); if (fetch == NULL) return (ISC_R_NOMEMORY); + fetch->mctx = NULL; + isc_mem_attach(res->mctx, &fetch->mctx); bucketnum = dns_name_fullhash(name, ISC_FALSE) % res->nbuckets; @@ -8273,11 +8393,12 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name, if (fctx == NULL) { result = fctx_create(res, name, type, domain, nameservers, - options, bucketnum, &fctx); + options, bucketnum, depth, qc, &fctx); if (result != ISC_R_SUCCESS) goto unlock; new_fctx = ISC_TRUE; - } + } else if (fctx->depth > depth) + fctx->depth = depth; result = fctx_join(fctx, task, client, id, action, arg, rdataset, sigrdataset, fetch); @@ -8312,7 +8433,7 @@ dns_resolver_createfetch2(dns_resolver_t *res, dns_name_t *name, FTRACE("created"); *fetchp = fetch; } else - isc_mem_put(res->mctx, fetch, sizeof(*fetch)); + isc_mem_putanddetach(&fetch->mctx, fetch, sizeof(*fetch)); return (result); } @@ -8403,7 +8524,7 @@ dns_resolver_destroyfetch(dns_fetch_t **fetchp) { UNLOCK(&res->buckets[bucketnum].lock); - isc_mem_put(res->mctx, fetch, sizeof(*fetch)); + isc_mem_putanddetach(&fetch->mctx, fetch, sizeof(*fetch)); *fetchp = NULL; if (bucket_empty) @@ -9049,3 +9170,27 @@ dns_resolver_settimeout(dns_resolver_t *resolver, unsigned int seconds) { resolver->query_timeout = seconds; } + +void +dns_resolver_setmaxdepth(dns_resolver_t *resolver, unsigned int maxdepth) { + REQUIRE(VALID_RESOLVER(resolver)); + resolver->maxdepth = maxdepth; +} + +unsigned int +dns_resolver_getmaxdepth(dns_resolver_t *resolver) { + REQUIRE(VALID_RESOLVER(resolver)); + return (resolver->maxdepth); +} + +void +dns_resolver_setmaxqueries(dns_resolver_t *resolver, unsigned int queries) { + REQUIRE(VALID_RESOLVER(resolver)); + resolver->maxqueries = queries; +} + +unsigned int +dns_resolver_getmaxqueries(dns_resolver_t *resolver) { + REQUIRE(VALID_RESOLVER(resolver)); + return (resolver->maxqueries); +} diff --git a/lib/dns/rootns.c b/lib/dns/rootns.c index 34971788dd89..a3d9bd8d6084 100644 --- a/lib/dns/rootns.c +++ b/lib/dns/rootns.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2007, 2008, 2010, 2012, 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004, 2005, 2007, 2008, 2010, 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 @@ -63,6 +63,7 @@ static char root_ns[] = "A.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:503:BA3E::2:30\n" "B.ROOT-SERVERS.NET. 3600000 IN A 192.228.79.201\n" "C.ROOT-SERVERS.NET. 3600000 IN A 192.33.4.12\n" +"C.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:2::c\n" "D.ROOT-SERVERS.NET. 3600000 IN A 199.7.91.13\n" "D.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:2d::d\n" "E.ROOT-SERVERS.NET. 3600000 IN A 192.203.230.10\n" diff --git a/lib/dns/rpz.c b/lib/dns/rpz.c index f617fe7b7c6a..3dd80664c7dc 100644 --- a/lib/dns/rpz.c +++ b/lib/dns/rpz.c @@ -496,16 +496,16 @@ ip2name(dns_rpz_cidr_t *cidr, const dns_rpz_cidr_key_t *tgt_ip, } if (canon_name != NULL) { - isc__buffer_init(&buffer, str, sizeof(str)); - isc__buffer_add(&buffer, len); + isc_buffer_init(&buffer, str, sizeof(str)); + isc_buffer_add(&buffer, len); result = dns_name_fromtext(canon_name, &buffer, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) return (result); } if (search_name != NULL) { - isc__buffer_init(&buffer, str, sizeof(str)); - isc__buffer_add(&buffer, len); + isc_buffer_init(&buffer, str, sizeof(str)); + isc_buffer_add(&buffer, len); if (type == DNS_RPZ_TYPE_NSIP) name = &cidr->nsip_name; else diff --git a/lib/dns/rrl.c b/lib/dns/rrl.c index 02554e9a9dfb..08fc8e712ffa 100644 --- a/lib/dns/rrl.c +++ b/lib/dns/rrl.c @@ -253,6 +253,7 @@ expand_entries(dns_rrl_t *rrl, int new) { static inline dns_rrl_bin_t * get_bin(dns_rrl_hash_t *hash, unsigned int hval) { + INSIST(hash != NULL); return (&hash->bins[hval % hash->length]); } diff --git a/lib/dns/time.c b/lib/dns/time.c index d331ca3bfe10..5dce07281195 100644 --- a/lib/dns/time.c +++ b/lib/dns/time.c @@ -35,7 +35,7 @@ #include <dns/result.h> #include <dns/time.h> -static int days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +static const int days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; isc_result_t dns_time64_totext(isc_int64_t t, isc_buffer_t *target) { @@ -161,6 +161,14 @@ dns_time64_fromtext(const char *source, isc_int64_t *target) { RANGE(1, 12, month); RANGE(1, days[month - 1] + ((month == 2 && is_leap(year)) ? 1 : 0), day); +#ifdef __COVERITY__ + /* + * Use a simplified range to silence Coverity warning (in + * arithmetic with day below). + */ + RANGE(1, 31, day); +#endif /* __COVERITY__ */ + RANGE(0, 23, hour); RANGE(0, 59, minute); RANGE(0, 60, second); /* 60 == leap second. */ diff --git a/lib/dns/tsig.c b/lib/dns/tsig.c index 00ab570d9e34..1ddca181a4ab 100644 --- a/lib/dns/tsig.c +++ b/lib/dns/tsig.c @@ -1317,7 +1317,7 @@ dns_tsig_verify(isc_buffer_t *source, dns_message_t *msg, alg == DST_ALG_HMACSHA384 || alg == DST_ALG_HMACSHA512) { isc_uint16_t digestbits = dst_key_getbits(key); if (tsig.siglen > siglen) { - tsig_log(msg->tsigkey, 2, "signature length to big"); + tsig_log(msg->tsigkey, 2, "signature length too big"); return (DNS_R_FORMERR); } if (tsig.siglen > 0 && diff --git a/lib/dns/validator.c b/lib/dns/validator.c index d7982caa777a..0b203d882923 100644 --- a/lib/dns/validator.c +++ b/lib/dns/validator.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-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -343,7 +343,7 @@ isdelegation(dns_name_t *name, dns_rdataset_t *rdataset, dns_name_getlabel(&nsec3name, 0, &hashlabel); isc_region_consume(&hashlabel, 1); isc_buffer_init(&buffer, owner, sizeof(owner)); - result = isc_base32hex_decoderegion(&hashlabel, &buffer); + result = isc_base32hexnp_decoderegion(&hashlabel, &buffer); if (result != ISC_R_SUCCESS) { dns_rdataset_disassociate(&set); continue; @@ -918,12 +918,26 @@ authvalidated(isc_task_t *task, isc_event_t *event) { devent->name; } if (!exists) { + dns_name_t *closest; + unsigned int clabels; + val->attributes |= VALATTR_FOUNDNOQNAME; - val->attributes |= VALATTR_FOUNDCLOSEST; + + closest = dns_fixedname_name(&val->closest); + clabels = dns_name_countlabels(closest); + /* + * If we are validating a wildcard response + * clabels will not be zero. We then need + * to check if the generated wilcard from + * dns_nsec_noexistnodata is consistent with + * the wildcard used to generate the response. + */ + if (clabels == 0 || + dns_name_countlabels(wild) == clabels + 1) + val->attributes |= VALATTR_FOUNDCLOSEST; /* * The NSEC noqname proof also contains * the closest encloser. - */ if (NEEDNOQNAME(val)) proofs[DNS_VALIDATOR_NOQNAMEPROOF] = @@ -2803,7 +2817,8 @@ nsecvalidate(dns_validator_t *val, isc_boolean_t resume) { if (!NEEDNODATA(val) && !NEEDNOWILDCARD(val) && NEEDNOQNAME(val)) { if (!FOUNDNOQNAME(val)) findnsec3proofs(val); - if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val)) { + if (FOUNDNOQNAME(val) && FOUNDCLOSEST(val) && + !FOUNDOPTOUT(val)) { validator_log(val, ISC_LOG_DEBUG(3), "marking as secure, noqname proof found"); marksecure(val->event); diff --git a/lib/dns/view.c b/lib/dns/view.c index 142b09edbd74..3730593b9e37 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.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) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -182,6 +182,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, view->updateacl = NULL; view->upfwdacl = NULL; view->denyansweracl = NULL; + view->nocasecompress = NULL; view->answeracl_exclude = NULL; view->denyanswernames = NULL; view->answernames_exclude = NULL; @@ -359,6 +360,8 @@ destroy(dns_view_t *view) { dns_db_detach(&view->cachedb); if (view->cache != NULL) dns_cache_detach(&view->cache); + if (view->nocasecompress != NULL) + dns_acl_detach(&view->nocasecompress); if (view->matchclients != NULL) dns_acl_detach(&view->matchclients); if (view->matchdestinations != NULL) @@ -621,6 +624,8 @@ resolver_shutdown(isc_task_t *task, isc_event_t *event) { UNUSED(task); + isc_event_free(&event); + LOCK(&view->lock); view->attributes |= DNS_VIEWATTR_RESSHUTDOWN; @@ -628,8 +633,6 @@ resolver_shutdown(isc_task_t *task, isc_event_t *event) { UNLOCK(&view->lock); - isc_event_free(&event); - if (done) destroy(view); } @@ -645,6 +648,8 @@ adb_shutdown(isc_task_t *task, isc_event_t *event) { UNUSED(task); + isc_event_free(&event); + LOCK(&view->lock); view->attributes |= DNS_VIEWATTR_ADBSHUTDOWN; @@ -652,8 +657,6 @@ adb_shutdown(isc_task_t *task, isc_event_t *event) { UNLOCK(&view->lock); - isc_event_free(&event); - if (done) destroy(view); } @@ -669,6 +672,8 @@ req_shutdown(isc_task_t *task, isc_event_t *event) { UNUSED(task); + isc_event_free(&event); + LOCK(&view->lock); view->attributes |= DNS_VIEWATTR_REQSHUTDOWN; @@ -676,8 +681,6 @@ req_shutdown(isc_task_t *task, isc_event_t *event) { UNLOCK(&view->lock); - isc_event_free(&event); - if (done) destroy(view); } @@ -1216,6 +1219,9 @@ dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname, dns_name_t *zfname; dns_rdataset_t zrdataset, zsigrdataset; dns_fixedname_t zfixedname; +#ifdef BIND9 + unsigned int ztoptions = 0; +#endif #ifndef BIND9 UNUSED(zone); @@ -1242,9 +1248,12 @@ dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname, #ifdef BIND9 zone = NULL; LOCK(&view->lock); - if (view->zonetable != NULL) - result = dns_zt_find(view->zonetable, name, 0, NULL, &zone); - else + if (view->zonetable != NULL) { + if ((options & DNS_DBFIND_NOEXACT) != 0) + ztoptions |= DNS_ZTFIND_NOEXACT; + result = dns_zt_find(view->zonetable, name, ztoptions, + NULL, &zone); + } else result = ISC_R_NOTFOUND; if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) result = dns_zone_getdb(zone, &db); @@ -1461,7 +1470,7 @@ dns_viewlist_findzone(dns_viewlist_t *list, dns_name_t *name, if (zone2 != NULL) { dns_zone_detach(&zone1); dns_zone_detach(&zone2); - return (ISC_R_NOTFOUND); + return (ISC_R_MULTIPLE); } } diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 01ff97b11dcb..7a9825bd96b0 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -2639,8 +2639,8 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) { checkspf: /* - * Check if there is a type TXT spf record without a type SPF - * RRset being present. + * Check if there is a type SPF record without an + * SPF-formatted type TXT record also being present. */ if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF)) goto next; @@ -2669,16 +2669,13 @@ integrity_checks(dns_zone_t *zone, dns_db_t *db) { dns_rdataset_disassociate(&rdataset); notxt: - if (have_spf != have_txt) { + if (have_spf && !have_txt) { char namebuf[DNS_NAME_FORMATSIZE]; - const char *found = have_txt ? "TXT" : "SPF"; - const char *need = have_txt ? "SPF" : "TXT"; dns_name_format(name, namebuf, sizeof(namebuf)); - dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found SPF/%s " - "record but no SPF/%s record found, add " - "matching type %s record", namebuf, found, - need, need); + dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found type " + "SPF record but no SPF TXT record found, " + "add matching type TXT record", namebuf); } next: @@ -4567,6 +4564,21 @@ zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount, dns_db_currentversion(db, &version); + if (nscount != NULL) + *nscount = 0; + if (soacount != NULL) + *soacount = 0; + if (serial != NULL) + *serial = 0; + if (refresh != NULL) + *refresh = 0; + if (retry != NULL) + *retry = 0; + if (expire != NULL) + *expire = 0; + if (errors != NULL) + *errors = 0; + node = NULL; result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node); if (result != ISC_R_SUCCESS) { @@ -8544,8 +8556,10 @@ keyfetch_done(isc_task_t *task, isc_event_t *event) { trust_key(zone, keyname, &dnskey, mctx); } - if (!deletekey) + if (!deletekey) { + INSIST(newkey || updatekey); set_refreshkeytimer(zone, &keydata, now); + } } /* @@ -10933,70 +10947,25 @@ create_query(dns_zone_t *zone, dns_rdatatype_t rdtype, static isc_result_t add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) { - dns_rdataset_t *rdataset = NULL; - dns_rdatalist_t *rdatalist = NULL; - dns_rdata_t *rdata = NULL; isc_result_t result; - - result = dns_message_gettemprdatalist(message, &rdatalist); - if (result != ISC_R_SUCCESS) - goto cleanup; - result = dns_message_gettemprdata(message, &rdata); - if (result != ISC_R_SUCCESS) - goto cleanup; - result = dns_message_gettemprdataset(message, &rdataset); - if (result != ISC_R_SUCCESS) - goto cleanup; - dns_rdataset_init(rdataset); - - rdatalist->type = dns_rdatatype_opt; - rdatalist->covers = 0; - - /* - * Set Maximum UDP buffer size. - */ - rdatalist->rdclass = udpsize; - - /* - * Set EXTENDED-RCODE, VERSION, DO and Z to 0. - */ - rdatalist->ttl = 0; + dns_rdataset_t *rdataset = NULL; + dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS]; + int count = 0; /* Set EDNS options if applicable */ if (reqnsid) { - unsigned char data[4]; - isc_buffer_t buf; - - isc_buffer_init(&buf, data, sizeof(data)); - isc_buffer_putuint16(&buf, DNS_OPT_NSID); - isc_buffer_putuint16(&buf, 0); - rdata->data = data; - rdata->length = sizeof(data); - } else { - rdata->data = NULL; - rdata->length = 0; + INSIST(count < DNS_EDNSOPTIONS); + ednsopts[count].code = DNS_OPT_NSID; + ednsopts[count].length = 0; + ednsopts[count].value = NULL; + count++; } - - rdata->rdclass = rdatalist->rdclass; - rdata->type = rdatalist->type; - rdata->flags = 0; - - ISC_LIST_INIT(rdatalist->rdata); - ISC_LIST_APPEND(rdatalist->rdata, rdata, link); - RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) - == ISC_R_SUCCESS); + result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0, + ednsopts, count); + if (result != ISC_R_SUCCESS) + return (result); return (dns_message_setopt(message, rdataset)); - - cleanup: - if (rdatalist != NULL) - dns_message_puttemprdatalist(message, &rdatalist); - if (rdataset != NULL) - dns_message_puttemprdataset(message, &rdataset); - if (rdata != NULL) - dns_message_puttemprdata(message, &rdata); - - return (result); } static void @@ -11846,6 +11815,8 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from, int match = 0; isc_netaddr_t netaddr; isc_sockaddr_t local, remote; + dns_tsigkey_t *tsigkey; + dns_name_t *tsig; REQUIRE(DNS_ZONE_VALID(zone)); @@ -11930,8 +11901,10 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from, * Accept notify requests from non masters if they are on * 'zone->notify_acl'. */ + tsigkey = dns_message_gettsigkey(msg); + tsig = dns_tsigkey_identity(tsigkey); if (i >= zone->masterscnt && zone->notify_acl != NULL && - dns_acl_match(&netaddr, NULL, zone->notify_acl, + dns_acl_match(&netaddr, tsig, zone->notify_acl, &zone->view->aclenv, &match, NULL) == ISC_R_SUCCESS && match > 0) @@ -13048,7 +13021,6 @@ save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) { isc_result_t result; dns_dbnode_t *node = NULL; dns_rdataset_t rdataset, prdataset; - dns_rdata_t rdata_in, prdata_in, prdata_out; dns_dbversion_t *version = NULL; nsec3param_t *nsec3param = NULL; nsec3param_t *nsec3p = NULL; @@ -13060,10 +13032,12 @@ save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) { REQUIRE(nsec3list != NULL); REQUIRE(ISC_LIST_EMPTY(*nsec3list)); + dns_rdataset_init(&rdataset); + dns_rdataset_init(&prdataset); + dns_db_attach(zone->db, &db); CHECK(dns_db_getoriginnode(db, &node)); - dns_rdataset_init(&rdataset); dns_db_currentversion(db, &version); result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec3param, @@ -13082,8 +13056,10 @@ save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) { result == ISC_R_SUCCESS; result = dns_rdataset_next(&rdataset)) { - dns_rdata_init(&rdata_in); - dns_rdataset_current(&rdataset, &rdata_in); + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_t private = DNS_RDATA_INIT; + + dns_rdataset_current(&rdataset, &rdata); isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3), "looping through nsec3param data"); @@ -13096,16 +13072,14 @@ save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) { * now transfer the data from the rdata to * the nsec3param */ - dns_rdata_init(&prdata_out); - dns_nsec3param_toprivate(&rdata_in, &prdata_out, + dns_nsec3param_toprivate(&rdata, &private, zone->privatetype, nsec3param->data, sizeof(nsec3param->data)); - nsec3param->length = prdata_out.length; + nsec3param->length = private.length; ISC_LIST_APPEND(*nsec3list, nsec3param, link); } getprivate: - dns_rdataset_init(&prdataset); result = dns_db_findrdataset(db, node, version, zone->privatetype, dns_rdatatype_none, 0, &prdataset, NULL); if (result != ISC_R_SUCCESS) @@ -13120,26 +13094,39 @@ save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) { result == ISC_R_SUCCESS; result = dns_rdataset_next(&prdataset)) { - dns_rdata_init(&prdata_in); - dns_rdataset_current(&prdataset, &prdata_in); + dns_rdata_t rdata = DNS_RDATA_INIT; + dns_rdata_t private = DNS_RDATA_INIT; + + dns_rdataset_current(&prdataset, &private); isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3), "looping through nsec3param private data"); - if (!dns_nsec3param_fromprivate(&prdata_in, &prdata_out, + /* + * Do we have a valid private record? + */ + if (!dns_nsec3param_fromprivate(&private, &rdata, buf, sizeof(buf))) continue; - if ((prdata_out.data[1] & DNS_NSEC3FLAG_REMOVE) !=0) { - prdata_out.data[1] = 0; + /* + * Remove any NSEC3PARAM records scheduled to be removed. + */ + if (NSEC3REMOVE(rdata.data[1])) { + /* + * Zero out the flags. + */ + rdata.data[1] = 0; for (nsec3p = ISC_LIST_HEAD(*nsec3list); nsec3p != NULL; nsec3p = next) { next = ISC_LIST_NEXT(nsec3p, link); - if (memcmp(prdata_out.data, nsec3p->data, - sizeof(nsec3p->data)) == 0) { + + if (nsec3p->length == rdata.length + 1 && + memcmp(rdata.data, nsec3p->data + 1, + nsec3p->length - 1) == 0) { ISC_LIST_UNLINK(*nsec3list, nsec3p, link); isc_mem_put(zone->mctx, nsec3p, @@ -13154,11 +13141,13 @@ save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) { CHECK(ISC_R_NOMEMORY); ISC_LINK_INIT(nsec3param, link); - dns_rdata_init(&prdata_out); - dns_nsec3param_toprivate(&prdata_in, &prdata_out, - zone->privatetype, nsec3param->data, - sizeof(nsec3param->data)); - nsec3param->length = prdata_out.length; + /* + * Copy the remaining private records so the nsec/nsec3 + * chain gets created. + */ + INSIST(private.length <= sizeof(nsec3param->data)); + memmove(nsec3param->data, private.data, private.length); + nsec3param->length = private.length; ISC_LIST_APPEND(*nsec3list, nsec3param, link); } @@ -13374,6 +13363,12 @@ receive_secure_db(isc_task_t *task, isc_event_t *event) { dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s", dns_result_totext(result)); + while (!ISC_LIST_EMPTY(nsec3list)) { + nsec3param_t *nsec3p; + nsec3p = ISC_LIST_HEAD(nsec3list); + ISC_LIST_UNLINK(nsec3list, nsec3p, link); + isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t)); + } if (dns_rdataset_isassociated(&rdataset)) dns_rdataset_disassociate(&rdataset); if (db != NULL) { @@ -13493,7 +13488,6 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) { !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) { isc_uint32_t serial, oldserial; - unsigned int soacount; dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs"); @@ -15691,10 +15685,12 @@ dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) { REQUIRE(DNS_ZONE_VALID(zone)); - if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES)) + if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) && + rdata->type != dns_rdatatype_nsec3) return (ISC_R_SUCCESS); - if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) { + if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) || + rdata->type == dns_rdatatype_nsec3) { level = ISC_LOG_ERROR; fail = ISC_TRUE; } |