Commit 07d2d309 authored by Jeremy C. Reed's avatar Jeremy C. Reed
Browse files

[master]Merge branch 'master' of ssh://git.bind10.isc.org//var/bind10/git/bind10

parents 60b9a13f 8e0d333e
482. [func] team
Memory footprint of the in-memory data source has been
substantially improved. For example, b10-auth now requires much
less memory than BIND 9 named for loading and serving the same
zone in-memory. This is a transparent change in terms of user
operation; there's no need to update or change the configuration
to enable this feature.
Notes: multiple instances of b10-auth still make separate copies
of the memory image. Also, loading zones in memory still suspends
query processing, so manual reloading or reloading after incoming
transfer may cause service disruption for huge zones.
(Multiple Trac tickets)
481. [bug] vorner
The abbreviated form of IP addresses in ACLs is accepted
(eg. "from": ["127.0.01", "::1"] now works).
(Trac #2191, git 48b6e91386b46eed383126ad98dddfafc9f7e75e)
480. [doc] vorner
Added documentation about global TSIG key ring to the Guide.
(Trac #2189, git 52177bb31f5fb8e134aecb9fd039c368684ad2df)
479. [func] marcin
Refactored perfdhcp tool to C++, added missing unit tests and removed
the old code. The new code uses libdhcp++ (src/lib/dhcp) for DHCP
packet management, network interface management and packet transmission.
packet management, network interface management and packet
transmission.
(Trac #1954, git 8d56105742f3043ed4b561f26241f3e4331f51dc)
(Trac #1955, git 6f914bb2c388eb4dd3e5c55297f8988ab9529b3f)
(Trac #1956, git 6f914bb2c388eb4dd3e5c55297f8988ab9529b3f)
......
......@@ -1193,11 +1193,11 @@ AC_CONFIG_FILES([Makefile
src/lib/exceptions/tests/Makefile
src/lib/datasrc/Makefile
src/lib/datasrc/memory/Makefile
src/lib/datasrc/memory/tests/Makefile
src/lib/datasrc/memory/tests/testdata/Makefile
src/lib/datasrc/memory/benchmarks/Makefile
src/lib/datasrc/tests/Makefile
src/lib/datasrc/tests/testdata/Makefile
src/lib/datasrc/tests/memory/Makefile
src/lib/datasrc/tests/memory/testdata/Makefile
src/lib/xfr/Makefile
src/lib/xfr/tests/Makefile
src/lib/log/Makefile
......
......@@ -1310,6 +1310,89 @@ TODO
many modules. So we show them here in one place.
</para>
<section id='common-tsig'>
<title>TSIG keys</title>
<para>
TSIG is a way to sign requests and responses in DNS. It is defined in
RFC 2845 and uses symmetric cryptography to sign the DNS messages. If
you want to make any use of TSIG (to authenticate transfers or DDNS,
for example), you need to set up shared secrets between the endpoints.
</para>
<para>
BIND 10 uses a global key ring for the secrets. It doesn't currently
mean they would be stored differently, they are just in one place of
the configuration.
</para>
<section id='tsig-key-syntax'>
<title>Key anatomy and syntax</title>
<para>
Each key has three attributes. One is a name by which it is referred
both in DNS packets and the rest of the configuration. Another is the
algorithm used to compute the signature. And the last part is a
base64 encoded secret, which might be any blob of data.
</para>
<para>
The parts are written into a string, concatenated together by colons.
So if you wanted to have a key called "example.key", used as a
HMAC-MD5 key with secret "secret", you'd write it as:
<screen>"example.key.:c2VjcmV0:hmac-md5"</screen>
</para>
<para>
The HMAC-MD5 algorithm is the default, so you can omit it. You could
write the same key as:
<screen>"example.key.:c2VjcmV0"</screen>
</para>
<para>
You can also use these algorithms (which may not be omitted from the
key definition if used):
<itemizedlist>
<listitem>hmac-sha1</listitem>
<listitem>hmac-sha224</listitem>
<listitem>hmac-sha256</listitem>
<listitem>hmac-sha384</listitem>
<listitem>hmac-sha512</listitem>
</itemizedlist>
</para>
<para>
The name of the key must be a valid DNS name.
</para>
</section>
<section id='tsig-key-ring'>
<title>Key ring</title>
<para>
The key ring lives in the configuration in "tsig_keys/keys". Most of
the system uses the keys from there &mdash; ACLs, authoritative server to
sign responses to signed queries, and <command>b10-xfrout</command>
to sign transfers. The <command>b10-xfrin</command> uses its own
configuration for keys, but that will be fixed in Trac ticket
<ulink url="http://bind10.isc.org/ticket/1351">#1351</ulink>.
</para>
<para>
The key ring is just a list of strings, each describing one key. So,
to add a new key, you can do this:
<screen>&gt; <userinput>config add tsig_keys/keys "example.key.:c2VjcmV0"</userinput>
&gt; <userinput>config show tsig_keys/keys</userinput>
tsig_keys/keys[0] "example.key.:c2VjcmV0" string (modified)
&gt; <userinput>config commit</userinput></screen>
</para>
<para>
You can keep as many keys as you want in the key ring, but each must
have a different name.
</para>
</section>
</section>
<section id='common-acl'>
<title>ACLs</title>
......@@ -1375,9 +1458,9 @@ AND_MATCH := "ALL": [ RULE_RAW, RULE_RAW, ... ]
<para>
The other is TSIG key by which the message was signed. The ACL
contains only the name (under the name "key"), the key itself
must be stored in the global keyring. This property is applicable only
to the DNS context.
<!-- TODO: Section for the keyring and link to it.-->
must be stored in the global key ring (see <xref
linkend="tsig-key-ring"/>).
This property is applicable only to the DNS context.
</para>
<para>
......@@ -1403,18 +1486,6 @@ AND_MATCH := "ALL": [ RULE_RAW, RULE_RAW, ... ]
will work in a similar way.
</para>
<note>
<simpara>
The list form is currently rejected due to an
implementation bug. There is a plan to fix it relatively
soon, so the syntax is kept here, but note that it won't
work until the bug is fixed. To keep track of the status
of the issue, see
<ulink url="http://bind10.isc.org/ticket/2191">Trac #2191</ulink>.
Until then, the value must be a single string.
</simpara>
</note>
<para>
If that is not enough, you can compose the matching conditions
to logical expressions. They are called "ANY", "ALL" and "NOT".
......@@ -2151,7 +2222,7 @@ Xfrout/transfer_acl[0] {"action": "ACCEPT"} any (default)</screen>
<para>
If you want to require TSIG in access control, a system wide TSIG
"key ring" must be configured.
key ring must be configured (see <xref linkend="tsig-key-ring"/>).
In this example, we allow client matching both the IP address
and key.
</para>
......@@ -2161,7 +2232,7 @@ Xfrout/transfer_acl[0] {"action": "ACCEPT"} any (default)</screen>
&gt; <userinput>config commit</userinput></screen>
<para>Both <command>b10-xfrout</command> and <command>b10-auth</command>
will use the system wide keyring to check
will use the system wide key ring to check
TSIGs in the incoming messages and to sign responses.</para>
<para>
......@@ -2371,11 +2442,12 @@ what is XfroutClient xfr_client??
&gt; <userinput>config commit</userinput>
</screen>
The TSIG key must be configured system wide
(see <xref linkend="xfrout"/>.)
(see <xref linkend="common-tsig"/>).
</para>
<para>
Full description of ACLs can be found in <xref linkend="common-acl" />.
The full description of ACLs can be found in <xref
linkend="common-acl" />.
</para>
<note><simpara>
......
......@@ -57,12 +57,6 @@ b10_auth_SOURCES += common.h common.cc
b10_auth_SOURCES += statistics.cc statistics.h
b10_auth_SOURCES += datasrc_configurator.h
b10_auth_SOURCES += main.cc
# This is a temporary workaround for #1206, where the InMemoryClient has been
# moved to an ldopened library. We could add that library to LDADD, but that
# is nonportable. This should've been moot after #1207, but there is still
# one dependency; the in-memory-specific zone loader call is still in
# auth.
b10_auth_SOURCES += ${top_srcdir}/src/lib/datasrc/memory_datasrc.cc
nodist_b10_auth_SOURCES = auth_messages.h auth_messages.cc
EXTRA_DIST += auth_messages.mes
......
......@@ -41,10 +41,7 @@
#include <asiodns/dns_service.h>
#include <datasrc/query.h>
#include <datasrc/data_source.h>
#include <datasrc/static_datasrc.h>
#include <datasrc/sqlite3_datasrc.h>
#include <datasrc/client_list.h>
#include <xfr/xfrout_client.h>
......
......@@ -17,12 +17,6 @@ query_bench_SOURCES += ../auth_srv.h ../auth_srv.cc
query_bench_SOURCES += ../auth_config.h ../auth_config.cc
query_bench_SOURCES += ../statistics.h ../statistics.cc
query_bench_SOURCES += ../auth_log.h ../auth_log.cc
# This is a temporary workaround for #1206, where the InMemoryClient has been
# moved to an ldopened library. We could add that library to LDADD, but that
# is nonportable. When #1207 is done this becomes moot anyway, and the
# specific workaround is not needed anymore, so we can then remove this
# line again.
query_bench_SOURCES += ${top_srcdir}/src/lib/datasrc/memory_datasrc.cc
nodist_query_bench_SOURCES = ../auth_messages.h ../auth_messages.cc
......
......@@ -52,13 +52,6 @@ run_unittests_SOURCES += query_unittest.cc
run_unittests_SOURCES += statistics_unittest.cc
run_unittests_SOURCES += datasrc_configurator_unittest.cc
run_unittests_SOURCES += run_unittests.cc
# This is a temporary workaround for #1206, where the InMemoryClient has been
# moved to an ldopened library. We could add that library to LDADD, but that
# is nonportable. This should've been moot after #1207, but there is still
# one dependency; the in-memory-specific zone loader call is still in
# auth.
run_unittests_SOURCES += ${top_srcdir}/src/lib/datasrc/memory_datasrc.cc
nodist_run_unittests_SOURCES = ../auth_messages.h ../auth_messages.cc
......
......@@ -15,6 +15,7 @@
#include <config.h>
#include <util/io/sockaddr_util.h>
#include <util/memory_segment_local.h>
#include <dns/message.h>
#include <dns/messagerenderer.h>
......@@ -1393,16 +1394,19 @@ public:
const isc::datasrc::DataSourceClientPtr
client(new FakeClient(info.data_src_client_ != NULL ?
info.data_src_client_ :
info.cache_.get(),
info.getCacheClient(),
throw_when, isc_exception, fake_rrset));
clients_.push_back(client);
data_sources_.push_back(DataSourceInfo(client.get(),
isc::datasrc::DataSourceClientContainerPtr(), false));
data_sources_.push_back(
DataSourceInfo(client.get(),
isc::datasrc::DataSourceClientContainerPtr(),
false, RRClass::IN(), mem_sgmt_));
}
}
private:
const boost::shared_ptr<isc::datasrc::ConfigurableClientList> real_;
vector<isc::datasrc::DataSourceClientPtr> clients_;
MemorySegmentLocal mem_sgmt_;
};
} // end anonymous namespace for throwing proxy classes
......
......@@ -42,12 +42,22 @@ server is about to open sockets on the specified port.
The IPv4 DHCP server has received a packet that it is unable to
interpret. The reason why the packet is invalid is included in the message.
% DHCP4_PACKET_RECEIVE_FAIL error on attempt to receive packet: %1
The IPv4 DHCP server tried to receive a packet but an error
occured during this attempt. The reason for the error is included in
the message.
% DHCP4_PACKET_RECEIVED %1 (type %2) packet received on interface %3
A debug message noting that the server has received the specified type of
packet on the specified interface. Note that a packet marked as UNKNOWN
may well be a valid DHCP packet, just a type not expected by the server
(e.g. it will report a received OFFER packet as UNKNOWN).
% DHCP4_PACKET_SEND_FAIL failed to send DHCPv4 packet: %1
This error is output if the IPv4 DHCP server fails to send an assembled
DHCP message to a client. The reason for the error is included in the
message.
% DHCP4_PACK_FAIL failed to assemble response correctly
This error is output if the server failed to assemble the data to be
returned to the client into a valid packet. The cause is most likely
......
......@@ -73,9 +73,15 @@ Dhcpv4Srv::run() {
int timeout = 1000;
// client's message and server's response
Pkt4Ptr query = IfaceMgr::instance().receive4(timeout);
Pkt4Ptr query;
Pkt4Ptr rsp;
try {
query = IfaceMgr::instance().receive4(timeout);
} catch (const std::exception& e) {
LOG_ERROR(dhcp4_logger, DHCP4_PACKET_RECEIVE_FAIL).arg(e.what());
}
if (query) {
try {
query->unpack();
......@@ -141,7 +147,11 @@ Dhcpv4Srv::run() {
.arg(rsp->getType()).arg(rsp->toText());
if (rsp->pack()) {
IfaceMgr::instance().send(rsp);
try {
IfaceMgr::instance().send(rsp);
} catch (const std::exception& e) {
LOG_ERROR(dhcp4_logger, DHCP4_PACKET_SEND_FAIL).arg(e.what());
}
} else {
LOG_ERROR(dhcp4_logger, DHCP4_PACK_FAIL);
}
......
......@@ -45,12 +45,22 @@ server is about to open sockets on the specified port.
% DHCP6_PACKET_PARSE_FAIL failed to parse incoming packet
The IPv6 DHCP server has received a packet that it is unable to interpret.
% DHCP6_PACKET_RECEIVE_FAIL error on attempt to receive packet: %1
The IPv6 DHCP server tried to receive a packet but an error
occured during this attempt. The reason for the error is included in
the message.
% DHCP6_PACKET_RECEIVED %1 (type %2) packet received
A debug message noting that the server has received the specified type
of packet. Note that a packet marked as UNKNOWN may well be a valid
DHCP packet, just a type not expected by the server (e.g. it will report
a received OFFER packet as UNKNOWN).
% DHCP6_PACKET_SEND_FAIL failed to send DHCPv6 packet: %1
This error is output if the IPv6 DHCP server fails to send an assembled
DHCP message to a client. The reason for the error is included in the
message.
% DHCP6_PACK_FAIL failed to assemble response correctly
This error is output if the server failed to assemble the data to be
returned to the client into a valid packet. The reason is most likely
......
......@@ -84,9 +84,15 @@ bool Dhcpv6Srv::run() {
int timeout = 1000;
// client's message and server's response
Pkt6Ptr query = IfaceMgr::instance().receive6(timeout);
Pkt6Ptr query;
Pkt6Ptr rsp;
try {
query = IfaceMgr::instance().receive6(timeout);
} catch (const std::exception& e) {
LOG_ERROR(dhcp6_logger, DHCP6_PACKET_RECEIVE_FAIL).arg(e.what());
}
if (query) {
if (!query->unpack()) {
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_DETAIL,
......@@ -154,7 +160,11 @@ bool Dhcpv6Srv::run() {
.arg(rsp->getType()).arg(rsp->toText());
if (rsp->pack()) {
IfaceMgr::instance().send(rsp);
try {
IfaceMgr::instance().send(rsp);
} catch (const std::exception& e) {
LOG_ERROR(dhcp6_logger, DHCP6_PACKET_SEND_FAIL).arg(e.what());
}
} else {
LOG_ERROR(dhcp6_logger, DHCP6_PACK_FAIL);
}
......
......@@ -136,10 +136,6 @@ public:
virtual boost::shared_ptr<RequestCheck>
create(const std::string& name, isc::data::ConstElementPtr definition,
const acl::Loader<RequestContext>& loader);
/// Until we are sure how the various rules work for this case, we won't
/// allow unexpected special interpretation for list definitions.
virtual bool allowListAbbreviation() const { return (false); }
};
} // end of namespace "internal"
......
......@@ -62,6 +62,18 @@ TEST(DNSACL, getRequestLoader) {
" \"from\": \"192.0.2.1\"}]")));
}
// Check we can abbreviate the IP address lists and TSIG keys
TEST(DNSACL, abbreviated) {
dns::RequestLoader* l(&getRequestLoader());
EXPECT_NO_THROW(l->load(Element::fromJSON("[{\"action\": \"DROP\","
" \"from\": [\"127.0.0.1\","
" \"::1\"]}]")));
EXPECT_NO_THROW(l->load(Element::fromJSON("[{\"action\": \"DROP\","
" \"key\": [\"key.example.\","
" \"other.\"]}]")));
}
class RequestCheckCreatorTest : public ::testing::Test {
protected:
dns::internal::RequestCheckCreator creator_;
......@@ -78,7 +90,7 @@ TEST_F(RequestCheckCreatorTest, names) {
}
TEST_F(RequestCheckCreatorTest, allowListAbbreviation) {
EXPECT_FALSE(creator_.allowListAbbreviation());
EXPECT_TRUE(creator_.allowListAbbreviation());
}
// The following two tests check the creator for the form of
......
SUBDIRS = . memory tests
SUBDIRS = memory . tests
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += -I$(top_srcdir)/src/lib/dns -I$(top_builddir)/src/lib/dns
......@@ -21,11 +21,7 @@ CLEANFILES += datasrc_config.h
CLEANFILES += static.zone
lib_LTLIBRARIES = libb10-datasrc.la
libb10_datasrc_la_SOURCES = data_source.h data_source.cc
libb10_datasrc_la_SOURCES += static_datasrc.h static_datasrc.cc
libb10_datasrc_la_SOURCES += sqlite3_datasrc.h sqlite3_datasrc.cc
libb10_datasrc_la_SOURCES += query.h query.cc
libb10_datasrc_la_SOURCES += cache.h cache.cc
libb10_datasrc_la_SOURCES = data_source.h
libb10_datasrc_la_SOURCES += rbnode_rrset.h
libb10_datasrc_la_SOURCES += rbtree.h
libb10_datasrc_la_SOURCES += zonetable.h zonetable.cc
......@@ -64,6 +60,7 @@ libb10_datasrc_la_LIBADD = $(top_builddir)/src/lib/exceptions/libb10-exceptions.
libb10_datasrc_la_LIBADD += $(top_builddir)/src/lib/dns/libb10-dns++.la
libb10_datasrc_la_LIBADD += $(top_builddir)/src/lib/log/libb10-log.la
libb10_datasrc_la_LIBADD += $(top_builddir)/src/lib/cc/libb10-cc.la
libb10_datasrc_la_LIBADD += $(builddir)/memory/libdatasrc_memory.la
libb10_datasrc_la_LIBADD += $(SQLITE_LIBS)
BUILT_SOURCES = datasrc_config.h datasrc_messages.h datasrc_messages.cc
......
// Copyright (C) 2010 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.
#include <stdint.h>
#include <map>
#include <dns/question.h>
#include <dns/rrclass.h>
#include <dns/rrset.h>
#include <dns/rrtype.h>
#include <list>
#include <datasrc/cache.h>
#include <datasrc/logger.h>
using namespace std;
using namespace isc::dns;
namespace isc {
namespace datasrc {
/// \brief A \c CacheEntry object contains the data stored with
/// each \c CacheNode: a pointer to the cached RRset (empty in
/// the case of a negative cache entry), and a copy of the
/// query-response flags that were returned when the RRset
/// was originally looked up in the low-level data source.
class CacheEntry {
private:
/// The copy constructor and the assignment operator are intentionally
/// defined as private.
CacheEntry(const CacheEntry& source);
CacheEntry& operator=(const CacheEntry& source);
public:
CacheEntry(RRsetPtr r, uint32_t f) : rrset(r), flags(f) {};
RRsetPtr rrset;
uint32_t flags;
};
typedef boost::shared_ptr<CacheEntry> CacheEntryPtr;
/// \brief A \c CacheNode is a node in the \c HotCache LRU queue. It
/// contains a pointer to a \c CacheEntry, a reference to the \c Question
/// that we are answering, a lifespan during which this entry remains
/// valid, and pointers to the next and previous entries in the list.
class CacheNode {
private:
/// \name Constructors and Assignment Operator
///
/// Note: The copy constructor and the assignment operator are intentionally
/// defined as private.
//@{
CacheNode(const CacheNode& source);
CacheNode& operator=(const CacheNode& source);
public:
/// \brief Constructor for positive cache entry.
///
/// \param rrset The \c RRset to cache.
/// \param flags The query response flags returned from the low-level
/// data source when this \c RRset was looked up.
/// \param lifespan How long the cache node is to be considered valid.
CacheNode(const RRsetPtr rrset, uint32_t flags, time_t lifespan);
/// \brief Constructor for negative cache entry.
///
/// \param name Query name
/// \param rrclass Query class
/// \param rrtype Query type
/// \param flags Query response flags returned from the low-level
/// data source, indicating why this lookup failed (name not found,
/// type not found, etc).
/// \param lifespan How long the cache node is to be considered valid.
CacheNode(const Name& name,
const RRClass& rrclass,
const RRType& rrtype,
uint32_t flags,
time_t lifespan);
//@}
/// \name Getter and Setter Methods
//@{
/// \brief Returns a pointer to the cached RRset (or an empty
/// RRsetPtr for negative cache entries).
/// \return \c RRsetPtr
RRsetPtr getRRset() const { return (entry->rrset); }
/// \brief Returns name associated with cached node
///
/// This is the name associated with the RRset if it is a positive
/// entry, and the associated question name if the RRSet is NULL
/// and this is a negative entry (together with an indication that
/// this is a negative entry).
string getNodeName() const {
if (getRRset()) {
return (getRRset()->getName().toText());
}
return (std::string("negative entry for ") + question.toText());
}
/// \brief Returns the query response flags associated with the data.
///
/// \return \c uint32_t
uint32_t getFlags() const { return (entry->flags); }
/// \brief Is this record still valid?
///
/// \return True if the expiration time has not yet passed,
/// or false if it has.
bool isValid() const;
//@}
// An iterator referencing this entry in the LRU list. This
// permits unit-time removal using list::erase().
list<CacheNodePtr>::iterator lru_entry_;
/// The \c Question (name/rrclass/rrtype) answered by this cache node
const isc::dns::Question question;
private:
// The cached RRset data
CacheEntryPtr entry;
// When this record should be discarded
time_t expiry;
};
// CacheNode constructor for a positive cache entry
CacheNode::CacheNode(const RRsetPtr rrset, const uint32_t flags,
const time_t lifespan) :
question(Question(rrset->getName(), rrset->getClass(), rrset->getType()))
{
const time_t now = time(NULL);
expiry = now + lifespan;
entry = CacheEntryPtr(new CacheEntry(rrset, flags));
}
// CacheNode constructor for a negative cache entry
CacheNode::CacheNode(const Name& name,
const RRClass& rrclass,
const RRType& rrtype,
const uint32_t flags,
const time_t lifespan) :
question(Question(name, rrclass, rrtype))
{
const time_t now = time(NULL);
expiry = now + lifespan;
entry = CacheEntryPtr(new CacheEntry(RRsetPtr(), flags));
}
// Returns true if the node has not yet expired.