+4566. [func] Query logging now includes the ECS option if one
+ was included in the query. [RT #44476]
+
4565. [cleanup] The inline macro versions of isc_buffer_put*()
did not implement automatic buffer reallocation.
[RT #44216]
count++;
}
if (((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) &&
- (client->ecs_addr.family == AF_INET ||
- client->ecs_addr.family == AF_INET6 ||
- client->ecs_addr.family == AF_UNSPEC))
+ (client->ecs.addr.family == AF_INET ||
+ client->ecs.addr.family == AF_INET6 ||
+ client->ecs.addr.family == AF_UNSPEC))
{
isc_buffer_t buf;
isc_uint8_t addr[16];
/* Add CLIENT-SUBNET option. */
- plen = client->ecs_addrlen;
+ plen = client->ecs.source;
/* Round up prefix len to a multiple of 8 */
addrl = (plen + 7) / 8;
- switch (client->ecs_addr.family) {
+ switch (client->ecs.addr.family) {
case AF_UNSPEC:
INSIST(plen == 0);
family = 0;
case AF_INET:
INSIST(plen <= 32);
family = 1;
- memmove(addr, &client->ecs_addr.type, addrl);
+ memmove(addr, &client->ecs.addr.type, addrl);
break;
case AF_INET6:
INSIST(plen <= 128);
family = 2;
- memmove(addr, &client->ecs_addr.type, addrl);
+ memmove(addr, &client->ecs.addr.type, addrl);
break;
default:
INSIST(0);
/* family */
isc_buffer_putuint16(&buf, family);
/* source prefix-length */
- isc_buffer_putuint8(&buf, client->ecs_addrlen);
+ isc_buffer_putuint8(&buf, client->ecs.source);
/* scope prefix-length */
- isc_buffer_putuint8(&buf, client->ecs_scope);
+ isc_buffer_putuint8(&buf, client->ecs.scope);
/* address */
if (addrl > 0) {
}
}
- memmove(&client->ecs_addr, &caddr, sizeof(caddr));
- client->ecs_addrlen = addrlen;
- client->ecs_scope = 0;
+ memmove(&client->ecs.addr, &caddr, sizeof(caddr));
+ client->ecs.source = addrlen;
+ client->ecs.scope = 0;
client->attributes |= NS_CLIENTATTR_HAVEECS;
isc_buffer_forward(buf, (unsigned int)optlen);
else
opt = dns_message_getopt(client->message);
- client->ecs_addrlen = 0;
- client->ecs_scope = 0;
+ client->ecs.source = 0;
+ client->ecs.scope = 0;
if (opt != NULL) {
/*
}
if ((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) {
- addr = &client->ecs_addr;
- scope = &client->ecs_scope;
+ addr = &client->ecs.addr;
+ scope = &client->ecs.scope;
}
- if (allowed(&netaddr, tsig, addr, client->ecs_addrlen,
+ if (allowed(&netaddr, tsig, addr, client->ecs.source,
scope, view->matchclients) &&
allowed(&client->destaddr, tsig, NULL,
0, NULL, view->matchdestinations) &&
client->recursionquota = NULL;
client->interface = NULL;
client->peeraddr_valid = ISC_FALSE;
- client->ecs_addrlen = 0;
- client->ecs_scope = 0;
+ dns_ecs_init(&client->ecs);
#ifdef ALLOW_FILTER_AAAA
client->filter_aaaa = dns_aaaa_ok;
#endif
}
if ((client->attributes & NS_CLIENTATTR_HAVEECS) != 0) {
- ecs_addr = &client->ecs_addr;
- ecs_addrlen = client->ecs_addrlen;
+ ecs_addr = &client->ecs.addr;
+ ecs_addrlen = client->ecs.source;
}
result = dns_acl_match2(netaddr, client->signer,
#include <isc/queue.h>
#include <dns/db.h>
+#include <dns/ecs.h>
#include <dns/fixedname.h>
#include <dns/name.h>
#include <dns/rdataclass.h>
isc_boolean_t peeraddr_valid;
isc_netaddr_t destaddr;
- isc_netaddr_t ecs_addr; /*%< EDNS client subnet */
- isc_uint8_t ecs_addrlen;
- isc_uint8_t ecs_scope;
+ dns_ecs_t ecs; /*%< EDNS client subnet sent by client */
struct in6_pktinfo pktinfo;
isc_dscp_t dscp;
/*% Client presented a COOKIE. */
#define WANTCOOKIE(c) (((c)->attributes & \
NS_CLIENTATTR_WANTCOOKIE) != 0)
+/*% Client presented a CLIENT-SUBNET option. */
+#define HAVEECS(c) (((c)->attributes & \
+ NS_CLIENTATTR_HAVEECS) != 0)
/*% No authority? */
#define NOAUTHORITY(c) (((c)->query.attributes & \
NS_QUERYATTR_NOAUTHORITY) != 0)
char typename[DNS_RDATATYPE_FORMATSIZE];
char classname[DNS_RDATACLASS_FORMATSIZE];
char onbuf[ISC_NETADDR_FORMATSIZE];
+ char ecsbuf[DNS_ECS_FORMATSIZE + sizeof(" [ECS ]") - 1] = { 0 };
char ednsbuf[sizeof("E(255)")] = { 0 };
dns_rdataset_t *rdataset;
int level = ISC_LOG_INFO;
snprintf(ednsbuf, sizeof(ednsbuf), "E(%d)",
client->ednsversion);
+ if (HAVEECS(client)) {
+ strlcpy(ecsbuf, " [ECS ", sizeof(ecsbuf));
+ dns_ecs_format(&client->ecs, ecsbuf + 6, sizeof(ecsbuf) - 6);
+ strlcat(ecsbuf, "]", sizeof(ecsbuf));
+ }
+
ns_client_log(client, NS_LOGCATEGORY_QUERIES, NS_LOGMODULE_QUERY,
- level, "query: %s %s %s %s%s%s%s%s%s%s (%s)", namebuf,
- classname, typename, WANTRECURSION(client) ? "+" : "-",
+ level, "query: %s %s %s %s%s%s%s%s%s%s (%s)%s",
+ namebuf, classname, typename,
+ WANTRECURSION(client) ? "+" : "-",
(client->signer != NULL) ? "S" : "", ednsbuf,
TCP(client) ? "T" : "",
((extflags & DNS_MESSAGEEXTFLAG_DO) != 0) ? "D" : "",
((flags & DNS_MESSAGEFLAG_CD) != 0) ? "C" : "",
HAVECOOKIE(client) ? "V" : WANTCOOKIE(client) ? "K" : "",
- onbuf);
+ onbuf, ecsbuf);
}
static inline void
ret=0
# first enable it with querylog on option
$RNDC -s 10.53.0.4 -p 9956 -c ns4/key6.conf querylog on >/dev/null 2>&1 || ret=1
-# query for builtin and check if query was logged
-$DIG @10.53.0.4 -p 5300 -c ch -t txt foo12345.bind > /dev/null || ret 1
grep "query logging is now on" ns4/named.run > /dev/null || ret=1
-grep "query: foo12345.bind CH TXT" ns4/named.run > /dev/null || ret=1
+# query for builtin and check if query was logged (without +subnet)
+$DIG @10.53.0.4 -p 5300 -c ch -t txt foo12345.bind > /dev/null || ret 1
+grep "query: foo12345.bind CH TXT.*(.*)$" ns4/named.run > /dev/null || ret=1
+# query for another builtin zone and check if query was logged (with +subnet=127.0.0.1)
+$DIG +subnet=127.0.0.1 @10.53.0.4 -p 5300 -c ch -t txt foo12346.bind > /dev/null || ret 1
+grep "query: foo12346.bind CH TXT.*\[ECS 127\.0\.0\.1\/32\/0]" ns4/named.run > /dev/null || ret=1
+# query for another builtin zone and check if query was logged (with +subnet=127.0.0.1/24)
+$DIG +subnet=127.0.0.1/24 @10.53.0.4 -p 5300 -c ch -t txt foo12347.bind > /dev/null || ret 1
+grep "query: foo12347.bind CH TXT.*\[ECS 127\.0\.0\.0\/24\/0]" ns4/named.run > /dev/null || ret=1
+# query for another builtin zone and check if query was logged (with +subnet=::1)
+$DIG +subnet=::1 @10.53.0.4 -p 5300 -c ch -t txt foo12348.bind > /dev/null || ret 1
+grep "query: foo12348.bind CH TXT.*\[ECS \:\:1\/128\/0]" ns4/named.run > /dev/null || ret=1
# toggle query logging and check again
$RNDC -s 10.53.0.4 -p 9956 -c ns4/key6.conf querylog > /dev/null 2>&1 || ret=1
-# query for another builtin zone and check if query was logged
-$DIG @10.53.0.4 -p 5300 -c ch -t txt foo9876.bind > /dev/null || ret 1
grep "query logging is now off" ns4/named.run > /dev/null || ret=1
-grep "query: foo9876.bind CH TXT" ns4/named.run > /dev/null && ret=1
+# query for another builtin zone and check if query was logged (without +subnet)
+$DIG @10.53.0.4 -p 5300 -c ch -t txt foo9876.bind > /dev/null || ret 1
+grep "query: foo9876.bind CH TXT.*(.*)$" ns4/named.run > /dev/null && ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
address and port number, and the query name,
class and type. Next, it reports whether the
Recursion Desired flag was set (+ if set, -
- if not set), if the query was signed (S),
- EDNS was in used along with the EDNS version
- number (E(#)), if TCP was used (T), if DO
- (DNSSEC Ok) was set (D), if CD (Checking
- Disabled) was set (C), if a valid DNS Server
- COOKIE was received (V), or if a DNS COOKIE
- option without a valid Server COOKIE was
+ if not set), whether the query was signed (S),
+ whether EDNS was in use along with the EDNS version
+ number (E(#)), whether TCP was used (T), whether
+ DO (DNSSEC Ok) was set (D), whether CD (Checking
+ Disabled) was set (C), whether a valid DNS Server
+ COOKIE was received (V), and whether a DNS
+ COOKIE option without a valid Server COOKIE was
present (K). After this the destination
address the query was sent to is reported.
+ Finally, if any CLIENT-SUBNET option
+ was present in the client query, it is
+ included in square brackets in the format
+ [ECS <replaceable>address/source/scope</replaceable>].
</para>
<para>
in <filename>named.conf</filename>. [RT #43154]
</para>
</listitem>
+ <listitem>
+ <para>
+ Query logging now includes the ECS option, if one was
+ present in the query, in the format
+ "[ECS <replaceable>address/source/scope</replaceable>]".
+ </para>
+ </listitem>
</itemizedlist>
</section>
DNSOBJS = acache.@O@ acl.@O@ adb.@O@ badcache.@O@ byaddr.@O@ \
cache.@O@ callbacks.@O@ catz.@O@ clientinfo.@O@ compress.@O@ \
db.@O@ dbiterator.@O@ dbtable.@O@ diff.@O@ dispatch.@O@ \
- dlz.@O@ dns64.@O@ dnssec.@O@ ds.@O@ dyndb.@O@ forward.@O@ \
- ipkeylist.@O@ iptable.@O@ journal.@O@ keydata.@O@ \
+ dlz.@O@ dns64.@O@ dnssec.@O@ ds.@O@ dyndb.@O@ ecs.@O@ \
+ forward.@O@ ipkeylist.@O@ iptable.@O@ journal.@O@ keydata.@O@ \
keytable.@O@ lib.@O@ log.@O@ lookup.@O@ \
master.@O@ masterdump.@O@ message.@O@ \
name.@O@ ncache.@O@ nsec.@O@ nsec3.@O@ nta.@O@ \
DNSSRCS = acache.c acl.c adb.c badcache. byaddr.c \
cache.c callbacks.c clientinfo.c compress.c \
db.c dbiterator.c dbtable.c diff.c dispatch.c \
- dlz.c dns64.c dnssec.c ds.c dyndb.c forward.c \
+ dlz.c dns64.c dnssec.c ds.c dyndb.c ecs.c forward.c \
ipkeylist.c iptable.c journal.c keydata.c keytable.c lib.c \
log.c lookup.c master.c masterdump.c message.c \
name.c ncache.c nsec.c nsec3.c nta.c \
--- /dev/null
+/*
+ * Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <string.h>
+
+#include <isc/netaddr.h>
+#include <isc/print.h>
+#include <isc/util.h>
+
+#include <dns/ecs.h>
+#include <dns/types.h>
+
+void
+dns_ecs_init(dns_ecs_t *ecs) {
+ isc_netaddr_unspec(&ecs->addr);
+ ecs->source = 0;
+ /*
+ * XXXMUKS: Fix me when resolver ECS gets merged where scope
+ * gets initialized to 0xff.
+ */
+ ecs->scope = 0;
+}
+
+void
+dns_ecs_format(dns_ecs_t *ecs, char *buf, size_t size) {
+ size_t len;
+
+ REQUIRE(ecs != NULL);
+ REQUIRE(buf != NULL);
+ REQUIRE(size >= DNS_ECS_FORMATSIZE);
+
+ isc_netaddr_format(&ecs->addr, buf, size);
+ len = strlen(buf);
+ INSIST(size >= len);
+ buf += len;
+ size -= len;
+ snprintf(buf, size, "/%u/%u", ecs->source, ecs->scope);
+}
client.h clientinfo.h compress.h \
db.h dbiterator.h dbtable.h diff.h dispatch.h \
dlz.h dlz_dlopen.h dns64.h dnssec.h ds.h dsdigest.h \
- dnstap.h dyndb.h \
+ dnstap.h dyndb.h ecs.h \
edns.h ecdb.h events.h fixedname.h forward.h geoip.h \
ipkeylist.h iptable.h \
journal.h keydata.h keyflags.h keytable.h keyvalues.h \
--- /dev/null
+/*
+ * Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef DNS_ECS_H
+#define DNS_ECS_H 1
+
+#include <isc/netaddr.h>
+#include <isc/types.h>
+#include <dns/types.h>
+
+struct dns_ecs {
+ isc_netaddr_t addr;
+ isc_uint8_t source;
+ isc_uint8_t scope;
+};
+
+#define DNS_ECS_FORMATSIZE (ISC_NETADDR_FORMATSIZE + 8) /* <address>/NNN/NNN */
+
+ISC_LANG_BEGINDECLS
+
+void
+dns_ecs_init(dns_ecs_t *ecs);
+/*%<
+ * Initialize a DNS ECS structure.
+ *
+ * Requires:
+ * \li 'ecs' is not NULL and points to a valid dns_ecs structure.
+ */
+
+void
+dns_ecs_format(dns_ecs_t *ecs, char *buf, size_t size);
+/*%<
+ * Format an ECS record as text. Result is guaranteed to be null-terminated.
+ *
+ * Requires:
+ * \li 'ecs' is not NULL.
+ * \li 'buf' is not NULL.
+ * \li 'size' is at least DNS_ECS_FORMATSIZE
+ */
+
+#endif /* DNS_ECS_H */
typedef struct dns_dtmsg dns_dtmsg_t;
typedef isc_uint16_t dns_dtmsgtype_t;
typedef struct dns_dumpctx dns_dumpctx_t;
+typedef struct dns_ecs dns_ecs_t;
typedef struct dns_ednsopt dns_ednsopt_t;
typedef struct dns_fetch dns_fetch_t;
typedef struct dns_fixedname dns_fixedname_t;
dns_dyndb_destroyctx
dns_ecdb_register
dns_ecdb_unregister
+dns_ecs_init
+dns_ecs_format
dns_fwdtable_add
dns_fwdtable_addfwd
dns_fwdtable_create
# End Source File
# Begin Source File
+SOURCE=..\include\dns\ecs.h
+# End Source File
+# Begin Source File
+
SOURCE=..\include\dns\edns.h
# End Source File
# Begin Source File
# End Source File
# Begin Source File
+SOURCE=..\ecs.c
+# End Source File
+# Begin Source File
+
SOURCE=..\forward.c
# End Source File
@IF GEOIP
-@erase "$(INTDIR)\dst_result.obj"
-@erase "$(INTDIR)\dyndb.obj"
-@erase "$(INTDIR)\ecdb.obj"
+ -@erase "$(INTDIR)\ecs.obj"
-@erase "$(INTDIR)\forward.obj"
@IF GEOIP
-@erase "$(INTDIR)\geoip.obj"
"$(INTDIR)\ds.obj" \
"$(INTDIR)\dyndb.obj" \
"$(INTDIR)\ecdb.obj" \
+ "$(INTDIR)\ecs.obj" \
"$(INTDIR)\forward.obj" \
@IF GEOIP
"$(INTDIR)\geoip.obj" \
-@erase "$(INTDIR)\dyndb.sbr"
-@erase "$(INTDIR)\ecdb.obj"
-@erase "$(INTDIR)\ecdb.sbr"
+ -@erase "$(INTDIR)\ecs.obj"
+ -@erase "$(INTDIR)\ecs.sbr"
-@erase "$(INTDIR)\forward.obj"
-@erase "$(INTDIR)\forward.sbr"
@IF GEOIP
"$(INTDIR)\ds.sbr" \
"$(INTDIR)\dyndb.sbr" \
"$(INTDIR)\ecdb.sbr" \
+ "$(INTDIR)\ecs.sbr" \
"$(INTDIR)\forward.sbr" \
@IF GEOIP
"$(INTDIR)\geoip.sbr" \
"$(INTDIR)\ds.obj" \
"$(INTDIR)\dyndb.obj" \
"$(INTDIR)\ecdb.obj" \
+ "$(INTDIR)\ecs.obj" \
"$(INTDIR)\forward.obj" \
@IF GEOIP
"$(INTDIR)\geoip.obj" \
$(CPP) $(CPP_PROJ) $(SOURCE)
+!ENDIF
+
+SOURCE=..\ecs.c
+
+!IF "$(CFG)" == "libdns - @PLATFORM@ Release"
+
+
+"$(INTDIR)\ecs.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "libdns - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\ecs.obj" "$(INTDIR)\ecs.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
!ENDIF
SOURCE=..\forward.c
<ClCompile Include="..\ecdb.c">
<Filter>Library Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\ecs.c">
+ <Filter>Library Source Files</Filter>
+ </ClCompile>
<ClCompile Include="..\forward.c">
<Filter>Library Source Files</Filter>
</ClCompile>
<ClInclude Include="..\include\dns\ecdb.h">
<Filter>Library Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\include\dns\ecs.h">
+ <Filter>Library Header Files</Filter>
+ </ClInclude>
<ClInclude Include="..\include\dns\edns.h">
<Filter>Library Header Files</Filter>
</ClInclude>
<ClCompile Include="..\dst_result.c" />
<ClCompile Include="..\dyndb.c" />
<ClCompile Include="..\ecdb.c" />
+ <ClCompile Include="..\ecs.c" />
<ClCompile Include="..\forward.c" />
@IF GEOIP
<ClCompile Include="..\geoip.c" />
<ClInclude Include="..\include\dns\dsdigest.h" />
<ClInclude Include="..\include\dns\dyndb.h" />
<ClInclude Include="..\include\dns\ecdb.h" />
+ <ClInclude Include="..\include\dns\ecs.h" />
<ClInclude Include="..\include\dns\edns.h" />
<ClInclude Include="..\include\dns\enumclass.h" />
<ClInclude Include="..\include\dns\enumtype.h" />
* Return the IPv6 wildcard address.
*/
+void
+isc_netaddr_unspec(isc_netaddr_t *netaddr);
+/*%<
+ * Initialize as AF_UNSPEC address.
+ */
+
isc_boolean_t
isc_netaddr_ismulticast(const isc_netaddr_t *na);
/*%<
netaddr->type.in6 = in6addr_any;
}
+void
+isc_netaddr_unspec(isc_netaddr_t *netaddr) {
+ memset(netaddr, 0, sizeof(*netaddr));
+ netaddr->family = AF_UNSPEC;
+}
+
isc_boolean_t
isc_netaddr_ismulticast(const isc_netaddr_t *na) {
switch (na->family) {
isc_netaddr_prefixok
isc_netaddr_setzone
isc_netaddr_totext
+isc_netaddr_unspec
isc_netscope_pton
isc_ntpaths_get
isc_ntpaths_init