summaryrefslogtreecommitdiff
path: root/src/grp-resolve/systemd-resolved
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2016-08-10 15:48:20 -0400
committerLuke Shumaker <lukeshu@sbcglobal.net>2016-08-10 15:48:20 -0400
commitc73db02271a67e9ceb42115dde6be997ec4b89ef (patch)
tree7bf9b14a3e741cfa37a2f93be964538b959964a5 /src/grp-resolve/systemd-resolved
parentae3660f9eb1618b0cc54bf5dffcc5d13ced8922e (diff)
split up grp-{hostname,locale}, grp-resolve/systemd-resolve{,d}; shell completion
Diffstat (limited to 'src/grp-resolve/systemd-resolved')
-rw-r--r--src/grp-resolve/systemd-resolved/Makefile109
-rw-r--r--src/grp-resolve/systemd-resolved/dns-type.c324
-rw-r--r--src/grp-resolve/systemd-resolved/dns-type.h161
-rw-r--r--src/grp-resolve/systemd-resolved/resolve-tool.c1485
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-def.h38
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-answer.c859
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-answer.h144
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-dnssec.c2199
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-dnssec.h103
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-packet.c2256
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-packet.h270
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-question.c469
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-question.h70
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-rr.c1595
-rw-r--r--src/grp-resolve/systemd-resolved/resolved-dns-rr.h343
-rw-r--r--src/grp-resolve/systemd-resolved/test-data/_443._tcp.fedoraproject.org.pktsbin169 -> 0 bytes
-rw-r--r--src/grp-resolve/systemd-resolved/test-data/_openpgpkey.fedoraproject.org.pktsbin986 -> 0 bytes
-rw-r--r--src/grp-resolve/systemd-resolved/test-data/fake-caa.pktsbin196 -> 0 bytes
-rw-r--r--src/grp-resolve/systemd-resolved/test-data/fedoraproject.org.pktsbin1483 -> 0 bytes
-rw-r--r--src/grp-resolve/systemd-resolved/test-data/gandi.net.pktsbin1010 -> 0 bytes
-rw-r--r--src/grp-resolve/systemd-resolved/test-data/google.com.pktsbin747 -> 0 bytes
-rw-r--r--src/grp-resolve/systemd-resolved/test-data/kyhwana.org.pktsbin1803 -> 0 bytes
-rw-r--r--src/grp-resolve/systemd-resolved/test-data/root.pktsbin1061 -> 0 bytes
-rw-r--r--src/grp-resolve/systemd-resolved/test-data/sw1a1aa-sw1a2aa-sw1a2ab-sw1a2ac.find.me.uk.pktsbin330 -> 0 bytes
-rw-r--r--src/grp-resolve/systemd-resolved/test-data/teamits.com.pktsbin1021 -> 0 bytes
-rw-r--r--src/grp-resolve/systemd-resolved/test-data/zbyszek@fedoraproject.org.pktsbin2533 -> 0 bytes
-rw-r--r--src/grp-resolve/systemd-resolved/test-dns-packet.c115
-rw-r--r--src/grp-resolve/systemd-resolved/test-dnssec-complex.c237
-rw-r--r--src/grp-resolve/systemd-resolved/test-dnssec.c344
-rw-r--r--src/grp-resolve/systemd-resolved/test-resolve-tables.c65
30 files changed, 2 insertions, 11184 deletions
diff --git a/src/grp-resolve/systemd-resolved/Makefile b/src/grp-resolve/systemd-resolved/Makefile
index 8574d3f71a..7a2cff2f2e 100644
--- a/src/grp-resolve/systemd-resolved/Makefile
+++ b/src/grp-resolve/systemd-resolved/Makefile
@@ -23,31 +23,7 @@
include $(dir $(lastword $(MAKEFILE_LIST)))/../../../config.mk
include $(topsrcdir)/build-aux/Makefile.head.mk
-
-$(outdir)/dns_type-list.txt: $(srcdir)/dns-type.h
- $(AM_V_GEN)$(SED) -n -r 's/.* DNS_TYPE_(\w+).*/\1/p' <$< >$@
-
-$(outdir)/dns_type-to-name.h: $(outdir)/dns_type-list.txt
- $(AM_V_GEN)$(AWK) 'BEGIN{ print "const char *dns_type_to_string(int type) {\n\tswitch(type) {" } {printf " case DNS_TYPE_%s: return ", $$1; sub(/_/, "-"); printf "\"%s\";\n", $$1 } END{ print " default: return NULL;\n\t}\n}\n" }' <$< >$@
-
-$(outdir)/dns_type-from-name.gperf: $(outdir)/dns_type-list.txt
- $(AM_V_GEN)$(AWK) 'BEGIN{ print "struct dns_type_name { const char* name; int id; };"; print "%null-strings"; print "%%";} { s=$$1; sub(/_/, "-", s); printf "%s, ", $$s; printf "DNS_TYPE_%s\n", $$1 }' <$< >$@
-
-ifneq ($(ENABLE_RESOLVED),)
-
-basic_dns_sources = \
- src/resolve/resolved-dns-dnssec.c \
- src/resolve/resolved-dns-dnssec.h \
- src/resolve/resolved-dns-packet.c \
- src/resolve/resolved-dns-packet.h \
- src/resolve/resolved-dns-rr.c \
- src/resolve/resolved-dns-rr.h \
- src/resolve/resolved-dns-answer.c \
- src/resolve/resolved-dns-answer.h \
- src/resolve/resolved-dns-question.c \
- src/resolve/resolved-dns-question.h \
- src/resolve/dns-type.c \
- src/resolve/dns-type.h
+basic_dns_sources =
systemd_resolved_SOURCES = \
src/resolve/resolved.c \
@@ -130,87 +106,6 @@ GENERAL_ALIASES += \
nodist_pkgsysconf_DATA += \
src/resolve/resolved.conf
-systemd_resolve_SOURCES = \
- src/resolve/resolve-tool.c \
- $(basic_dns_sources) \
- src/shared/gcrypt-util.c \
- src/shared/gcrypt-util.h
-
-nodist_systemd_resolve_SOURCES = \
- src/resolve/dns_type-from-name.h \
- src/resolve/dns_type-to-name.h
-
-systemd_resolve_LDADD = \
- libshared.la
-
-bin_PROGRAMS += \
- systemd-resolve
-
-dist_bashcompletion_data += \
- shell-completion/bash/systemd-resolve
-
-dist_zshcompletion_data += \
- shell-completion/zsh/_systemd-resolve
-
-tests += \
- test-dns-packet \
- test-resolve-tables \
- test-dnssec
-
-manual_tests += \
- test-dnssec-complex
-
-test_resolve_tables_SOURCES = \
- src/resolve/test-resolve-tables.c \
- src/resolve/dns_type-from-name.h \
- src/resolve/dns_type-to-name.h \
- $(basic_dns_sources) \
- src/shared/test-tables.h
-
-test_resolve_tables_LDADD = \
- libshared.la
-
-test_dns_packet_SOURCES = \
- src/resolve/test-dns-packet.c \
- $(basic_dns_sources)
-
-test_dns_packet_CPPFLAGS = \
- $(AM_CPPFLAGS) \
- -DRESOLVE_TEST_DIR=\"$(abs_top_srcdir)/src/resolve/test-data\"
-
-test_dns_packet_LDADD = \
- libshared.la
-
-EXTRA_DIST += \
- src/resolve/test-data/_openpgpkey.fedoraproject.org.pkts \
- src/resolve/test-data/fedoraproject.org.pkts \
- src/resolve/test-data/gandi.net.pkts \
- src/resolve/test-data/google.com.pkts \
- src/resolve/test-data/root.pkts \
- src/resolve/test-data/sw1a1aa-sw1a2aa-sw1a2ab-sw1a2ac.find.me.uk.pkts \
- src/resolve/test-data/teamits.com.pkts \
- src/resolve/test-data/zbyszek@fedoraproject.org.pkts \
- src/resolve/test-data/_443._tcp.fedoraproject.org.pkts \
- src/resolve/test-data/kyhwana.org.pkts \
- src/resolve/test-data/fake-caa.pkts
-
-test_dnssec_SOURCES = \
- src/resolve/test-dnssec.c \
- $(basic_dns_sources)
-
-test_dnssec_LDADD = \
- libshared.la
-
-test_dnssec_complex_SOURCES = \
- src/resolve/test-dnssec-complex.c \
- src/resolve/dns-type.c \
- src/resolve/dns-type.h
-
-test_dnssec_complex_LDADD = \
- libshared.la
-
-endif # ENABLE_RESOLVED
-
gperf_txt_sources += \
src/resolve/dns_type-list.txt
@@ -221,8 +116,8 @@ EXTRA_DIST += \
units/systemd-resolved.service.m4.in \
src/resolve/resolved.conf.in
+systemd_resolved_LDADD += libbasic-dns.la
-$(outdir)/dns-type.o: $(outdir)/dns_type-from-name.h $(outdir)/dns_type-to-name.h
sd.CPPFLAGS += -DPKGSYSCONFDIR=\"$(pkgsysconfdir)\"
include $(topsrcdir)/build-aux/Makefile.tail.mk
diff --git a/src/grp-resolve/systemd-resolved/dns-type.c b/src/grp-resolve/systemd-resolved/dns-type.c
deleted file mode 100644
index 6d5b9d616f..0000000000
--- a/src/grp-resolve/systemd-resolved/dns-type.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <sys/socket.h>
-
-#include "basic/parse-util.h"
-#include "basic/string-util.h"
-
-#include "dns-type.h"
-
-typedef const struct {
- uint16_t type;
- const char *name;
-} dns_type;
-
-static const struct dns_type_name *
-lookup_dns_type (register const char *str, register unsigned int len);
-
-#include "dns_type-from-name.h"
-#include "dns_type-to-name.h"
-
-int dns_type_from_string(const char *s) {
- const struct dns_type_name *sc;
-
- assert(s);
-
- sc = lookup_dns_type(s, strlen(s));
- if (sc)
- return sc->id;
-
- s = startswith_no_case(s, "TYPE");
- if (s) {
- unsigned x;
-
- if (safe_atou(s, &x) >= 0 &&
- x <= UINT16_MAX)
- return (int) x;
- }
-
- return _DNS_TYPE_INVALID;
-}
-
-bool dns_type_is_pseudo(uint16_t type) {
-
- /* Checks whether the specified type is a "pseudo-type". What
- * a "pseudo-type" precisely is, is defined only very weakly,
- * but apparently entails all RR types that are not actually
- * stored as RRs on the server and should hence also not be
- * cached. We use this list primarily to validate NSEC type
- * bitfields, and to verify what to cache. */
-
- return IN_SET(type,
- 0, /* A Pseudo RR type, according to RFC 2931 */
- DNS_TYPE_ANY,
- DNS_TYPE_AXFR,
- DNS_TYPE_IXFR,
- DNS_TYPE_OPT,
- DNS_TYPE_TSIG,
- DNS_TYPE_TKEY
- );
-}
-
-bool dns_class_is_pseudo(uint16_t class) {
- return class == DNS_TYPE_ANY;
-}
-
-bool dns_type_is_valid_query(uint16_t type) {
-
- /* The types valid as questions in packets */
-
- return !IN_SET(type,
- 0,
- DNS_TYPE_OPT,
- DNS_TYPE_TSIG,
- DNS_TYPE_TKEY,
-
- /* RRSIG are technically valid as questions, but we refuse doing explicit queries for them, as
- * they aren't really payload, but signatures for payload, and cannot be validated on their
- * own. After all they are the signatures, and have no signatures of their own validating
- * them. */
- DNS_TYPE_RRSIG);
-}
-
-bool dns_type_is_valid_rr(uint16_t type) {
-
- /* The types valid as RR in packets (but not necessarily
- * stored on servers). */
-
- return !IN_SET(type,
- DNS_TYPE_ANY,
- DNS_TYPE_AXFR,
- DNS_TYPE_IXFR);
-}
-
-bool dns_class_is_valid_rr(uint16_t class) {
- return class != DNS_CLASS_ANY;
-}
-
-bool dns_type_may_redirect(uint16_t type) {
- /* The following record types should never be redirected using
- * CNAME/DNAME RRs. See
- * <https://tools.ietf.org/html/rfc4035#section-2.5>. */
-
- if (dns_type_is_pseudo(type))
- return false;
-
- return !IN_SET(type,
- DNS_TYPE_CNAME,
- DNS_TYPE_DNAME,
- DNS_TYPE_NSEC3,
- DNS_TYPE_NSEC,
- DNS_TYPE_RRSIG,
- DNS_TYPE_NXT,
- DNS_TYPE_SIG,
- DNS_TYPE_KEY);
-}
-
-bool dns_type_may_wildcard(uint16_t type) {
-
- /* The following records may not be expanded from wildcard RRsets */
-
- if (dns_type_is_pseudo(type))
- return false;
-
- return !IN_SET(type,
- DNS_TYPE_NSEC3,
- DNS_TYPE_SOA,
-
- /* Prohibited by https://tools.ietf.org/html/rfc4592#section-4.4 */
- DNS_TYPE_DNAME);
-}
-
-bool dns_type_apex_only(uint16_t type) {
-
- /* Returns true for all RR types that may only appear signed in a zone apex */
-
- return IN_SET(type,
- DNS_TYPE_SOA,
- DNS_TYPE_NS, /* this one can appear elsewhere, too, but not signed */
- DNS_TYPE_DNSKEY,
- DNS_TYPE_NSEC3PARAM);
-}
-
-bool dns_type_is_dnssec(uint16_t type) {
- return IN_SET(type,
- DNS_TYPE_DS,
- DNS_TYPE_DNSKEY,
- DNS_TYPE_RRSIG,
- DNS_TYPE_NSEC,
- DNS_TYPE_NSEC3,
- DNS_TYPE_NSEC3PARAM);
-}
-
-bool dns_type_is_obsolete(uint16_t type) {
- return IN_SET(type,
- /* Obsoleted by RFC 973 */
- DNS_TYPE_MD,
- DNS_TYPE_MF,
- DNS_TYPE_MAILA,
-
- /* Kinda obsoleted by RFC 2505 */
- DNS_TYPE_MB,
- DNS_TYPE_MG,
- DNS_TYPE_MR,
- DNS_TYPE_MINFO,
- DNS_TYPE_MAILB,
-
- /* RFC1127 kinda obsoleted this by recommending against its use */
- DNS_TYPE_WKS,
-
- /* Declared historical by RFC 6563 */
- DNS_TYPE_A6,
-
- /* Obsoleted by DNSSEC-bis */
- DNS_TYPE_NXT,
-
- /* RFC 1035 removed support for concepts that needed this from RFC 883 */
- DNS_TYPE_NULL);
-}
-
-bool dns_type_needs_authentication(uint16_t type) {
-
- /* Returns true for all (non-obsolete) RR types where records are not useful if they aren't
- * authenticated. I.e. everything that contains crypto keys. */
-
- return IN_SET(type,
- DNS_TYPE_CERT,
- DNS_TYPE_SSHFP,
- DNS_TYPE_IPSECKEY,
- DNS_TYPE_DS,
- DNS_TYPE_DNSKEY,
- DNS_TYPE_TLSA,
- DNS_TYPE_CDNSKEY,
- DNS_TYPE_OPENPGPKEY,
- DNS_TYPE_CAA);
-}
-
-int dns_type_to_af(uint16_t t) {
- switch (t) {
-
- case DNS_TYPE_A:
- return AF_INET;
-
- case DNS_TYPE_AAAA:
- return AF_INET6;
-
- case DNS_TYPE_ANY:
- return AF_UNSPEC;
-
- default:
- return -EINVAL;
- }
-}
-
-const char *dns_class_to_string(uint16_t class) {
-
- switch (class) {
-
- case DNS_CLASS_IN:
- return "IN";
-
- case DNS_CLASS_ANY:
- return "ANY";
- }
-
- return NULL;
-}
-
-int dns_class_from_string(const char *s) {
-
- if (!s)
- return _DNS_CLASS_INVALID;
-
- if (strcaseeq(s, "IN"))
- return DNS_CLASS_IN;
- else if (strcaseeq(s, "ANY"))
- return DNS_CLASS_ANY;
-
- return _DNS_CLASS_INVALID;
-}
-
-const char* tlsa_cert_usage_to_string(uint8_t cert_usage) {
-
- switch (cert_usage) {
-
- case 0:
- return "CA constraint";
-
- case 1:
- return "Service certificate constraint";
-
- case 2:
- return "Trust anchor assertion";
-
- case 3:
- return "Domain-issued certificate";
-
- case 4 ... 254:
- return "Unassigned";
-
- case 255:
- return "Private use";
- }
-
- return NULL; /* clang cannot count that we covered everything */
-}
-
-const char* tlsa_selector_to_string(uint8_t selector) {
- switch (selector) {
-
- case 0:
- return "Full Certificate";
-
- case 1:
- return "SubjectPublicKeyInfo";
-
- case 2 ... 254:
- return "Unassigned";
-
- case 255:
- return "Private use";
- }
-
- return NULL;
-}
-
-const char* tlsa_matching_type_to_string(uint8_t selector) {
-
- switch (selector) {
-
- case 0:
- return "No hash used";
-
- case 1:
- return "SHA-256";
-
- case 2:
- return "SHA-512";
-
- case 3 ... 254:
- return "Unassigned";
-
- case 255:
- return "Private use";
- }
-
- return NULL;
-}
diff --git a/src/grp-resolve/systemd-resolved/dns-type.h b/src/grp-resolve/systemd-resolved/dns-type.h
deleted file mode 100644
index a8ee105e16..0000000000
--- a/src/grp-resolve/systemd-resolved/dns-type.h
+++ /dev/null
@@ -1,161 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "basic/macro.h"
-
-/* DNS record types, taken from
- * http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml.
- */
-enum {
- /* Normal records */
- DNS_TYPE_A = 0x01,
- DNS_TYPE_NS,
- DNS_TYPE_MD,
- DNS_TYPE_MF,
- DNS_TYPE_CNAME,
- DNS_TYPE_SOA,
- DNS_TYPE_MB,
- DNS_TYPE_MG,
- DNS_TYPE_MR,
- DNS_TYPE_NULL,
- DNS_TYPE_WKS,
- DNS_TYPE_PTR,
- DNS_TYPE_HINFO,
- DNS_TYPE_MINFO,
- DNS_TYPE_MX,
- DNS_TYPE_TXT,
- DNS_TYPE_RP,
- DNS_TYPE_AFSDB,
- DNS_TYPE_X25,
- DNS_TYPE_ISDN,
- DNS_TYPE_RT,
- DNS_TYPE_NSAP,
- DNS_TYPE_NSAP_PTR,
- DNS_TYPE_SIG,
- DNS_TYPE_KEY,
- DNS_TYPE_PX,
- DNS_TYPE_GPOS,
- DNS_TYPE_AAAA,
- DNS_TYPE_LOC,
- DNS_TYPE_NXT,
- DNS_TYPE_EID,
- DNS_TYPE_NIMLOC,
- DNS_TYPE_SRV,
- DNS_TYPE_ATMA,
- DNS_TYPE_NAPTR,
- DNS_TYPE_KX,
- DNS_TYPE_CERT,
- DNS_TYPE_A6,
- DNS_TYPE_DNAME,
- DNS_TYPE_SINK,
- DNS_TYPE_OPT, /* EDNS0 option */
- DNS_TYPE_APL,
- DNS_TYPE_DS,
- DNS_TYPE_SSHFP,
- DNS_TYPE_IPSECKEY,
- DNS_TYPE_RRSIG,
- DNS_TYPE_NSEC,
- DNS_TYPE_DNSKEY,
- DNS_TYPE_DHCID,
- DNS_TYPE_NSEC3,
- DNS_TYPE_NSEC3PARAM,
- DNS_TYPE_TLSA,
-
- DNS_TYPE_HIP = 0x37,
- DNS_TYPE_NINFO,
- DNS_TYPE_RKEY,
- DNS_TYPE_TALINK,
- DNS_TYPE_CDS,
- DNS_TYPE_CDNSKEY,
- DNS_TYPE_OPENPGPKEY,
-
- DNS_TYPE_SPF = 0x63,
- DNS_TYPE_NID,
- DNS_TYPE_L32,
- DNS_TYPE_L64,
- DNS_TYPE_LP,
- DNS_TYPE_EUI48,
- DNS_TYPE_EUI64,
-
- DNS_TYPE_TKEY = 0xF9,
- DNS_TYPE_TSIG,
- DNS_TYPE_IXFR,
- DNS_TYPE_AXFR,
- DNS_TYPE_MAILB,
- DNS_TYPE_MAILA,
- DNS_TYPE_ANY,
- DNS_TYPE_URI,
- DNS_TYPE_CAA,
- DNS_TYPE_TA = 0x8000,
- DNS_TYPE_DLV,
-
- _DNS_TYPE_MAX,
- _DNS_TYPE_INVALID = -1
-};
-
-assert_cc(DNS_TYPE_SSHFP == 44);
-assert_cc(DNS_TYPE_TLSA == 52);
-assert_cc(DNS_TYPE_ANY == 255);
-
-/* DNS record classes, see RFC 1035 */
-enum {
- DNS_CLASS_IN = 0x01,
- DNS_CLASS_ANY = 0xFF,
-
- _DNS_CLASS_MAX,
- _DNS_CLASS_INVALID = -1
-};
-
-#define _DNS_CLASS_STRING_MAX (sizeof "CLASS" + DECIMAL_STR_MAX(uint16_t))
-#define _DNS_TYPE_STRING_MAX (sizeof "CLASS" + DECIMAL_STR_MAX(uint16_t))
-
-bool dns_type_is_pseudo(uint16_t type);
-bool dns_type_is_valid_query(uint16_t type);
-bool dns_type_is_valid_rr(uint16_t type);
-bool dns_type_may_redirect(uint16_t type);
-bool dns_type_is_dnssec(uint16_t type);
-bool dns_type_is_obsolete(uint16_t type);
-bool dns_type_may_wildcard(uint16_t type);
-bool dns_type_apex_only(uint16_t type);
-bool dns_type_needs_authentication(uint16_t type);
-int dns_type_to_af(uint16_t type);
-
-bool dns_class_is_pseudo(uint16_t class);
-bool dns_class_is_valid_rr(uint16_t class);
-
-/* TYPE?? follows http://tools.ietf.org/html/rfc3597#section-5 */
-const char *dns_type_to_string(int type);
-int dns_type_from_string(const char *s);
-
-const char *dns_class_to_string(uint16_t class);
-int dns_class_from_string(const char *name);
-
-/* https://tools.ietf.org/html/draft-ietf-dane-protocol-23#section-7.2 */
-const char *tlsa_cert_usage_to_string(uint8_t cert_usage);
-
-/* https://tools.ietf.org/html/draft-ietf-dane-protocol-23#section-7.3 */
-const char *tlsa_selector_to_string(uint8_t selector);
-
-/* https://tools.ietf.org/html/draft-ietf-dane-protocol-23#section-7.4 */
-const char *tlsa_matching_type_to_string(uint8_t selector);
-
-/* https://tools.ietf.org/html/rfc6844#section-5.1 */
-#define CAA_FLAG_CRITICAL (1u << 7)
diff --git a/src/grp-resolve/systemd-resolved/resolve-tool.c b/src/grp-resolve/systemd-resolved/resolve-tool.c
deleted file mode 100644
index d9f28576b7..0000000000
--- a/src/grp-resolve/systemd-resolved/resolve-tool.c
+++ /dev/null
@@ -1,1485 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <getopt.h>
-#include <net/if.h>
-
-#include <systemd/sd-bus.h>
-
-#include "basic/af-list.h"
-#include "basic/alloc-util.h"
-#include "basic/escape.h"
-#include "basic/in-addr-util.h"
-#include "basic/parse-util.h"
-#include "basic/terminal-util.h"
-#include "sd-bus/bus-error.h"
-#include "shared/bus-util.h"
-#include "shared/gcrypt-util.h"
-
-#include "resolved-def.h"
-#include "resolved-dns-packet.h"
-
-#define DNS_CALL_TIMEOUT_USEC (45*USEC_PER_SEC)
-
-static int arg_family = AF_UNSPEC;
-static int arg_ifindex = 0;
-static uint16_t arg_type = 0;
-static uint16_t arg_class = 0;
-static bool arg_legend = true;
-static uint64_t arg_flags = 0;
-
-typedef enum ServiceFamily {
- SERVICE_FAMILY_TCP,
- SERVICE_FAMILY_UDP,
- SERVICE_FAMILY_SCTP,
- _SERVICE_FAMILY_INVALID = -1,
-} ServiceFamily;
-static ServiceFamily arg_service_family = SERVICE_FAMILY_TCP;
-
-typedef enum RawType {
- RAW_NONE,
- RAW_PAYLOAD,
- RAW_PACKET,
-} RawType;
-static RawType arg_raw = RAW_NONE;
-
-static enum {
- MODE_RESOLVE_HOST,
- MODE_RESOLVE_RECORD,
- MODE_RESOLVE_SERVICE,
- MODE_RESOLVE_OPENPGP,
- MODE_RESOLVE_TLSA,
- MODE_STATISTICS,
- MODE_RESET_STATISTICS,
-} arg_mode = MODE_RESOLVE_HOST;
-
-static ServiceFamily service_family_from_string(const char *s) {
- if (s == NULL || streq(s, "tcp"))
- return SERVICE_FAMILY_TCP;
- if (streq(s, "udp"))
- return SERVICE_FAMILY_UDP;
- if (streq(s, "sctp"))
- return SERVICE_FAMILY_SCTP;
- return _SERVICE_FAMILY_INVALID;
-}
-
-static const char* service_family_to_string(ServiceFamily service) {
- switch(service) {
- case SERVICE_FAMILY_TCP:
- return "_tcp";
- case SERVICE_FAMILY_UDP:
- return "_udp";
- case SERVICE_FAMILY_SCTP:
- return "_sctp";
- default:
- assert_not_reached("invalid service");
- }
-}
-
-static void print_source(uint64_t flags, usec_t rtt) {
- char rtt_str[FORMAT_TIMESTAMP_MAX];
-
- if (!arg_legend)
- return;
-
- if (flags == 0)
- return;
-
- fputs("\n-- Information acquired via", stdout);
-
- if (flags != 0)
- printf(" protocol%s%s%s%s%s",
- flags & SD_RESOLVED_DNS ? " DNS" :"",
- flags & SD_RESOLVED_LLMNR_IPV4 ? " LLMNR/IPv4" : "",
- flags & SD_RESOLVED_LLMNR_IPV6 ? " LLMNR/IPv6" : "",
- flags & SD_RESOLVED_MDNS_IPV4 ? "mDNS/IPv4" : "",
- flags & SD_RESOLVED_MDNS_IPV6 ? "mDNS/IPv6" : "");
-
- assert_se(format_timespan(rtt_str, sizeof(rtt_str), rtt, 100));
-
- printf(" in %s", rtt_str);
-
- fputc('.', stdout);
- fputc('\n', stdout);
-
- printf("-- Data is authenticated: %s\n", yes_no(flags & SD_RESOLVED_AUTHENTICATED));
-}
-
-static int resolve_host(sd_bus *bus, const char *name) {
-
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- const char *canonical = NULL;
- char ifname[IF_NAMESIZE] = "";
- unsigned c = 0;
- int r;
- uint64_t flags;
- usec_t ts;
-
- assert(name);
-
- if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname))
- return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex);
-
- log_debug("Resolving %s (family %s, interface %s).", name, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
-
- r = sd_bus_message_new_method_call(
- bus,
- &req,
- "org.freedesktop.resolve1",
- "/org/freedesktop/resolve1",
- "org.freedesktop.resolve1.Manager",
- "ResolveHostname");
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append(req, "isit", arg_ifindex, name, arg_family, arg_flags);
- if (r < 0)
- return bus_log_create_error(r);
-
- ts = now(CLOCK_MONOTONIC);
-
- r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
- if (r < 0)
- return log_error_errno(r, "%s: resolve call failed: %s", name, bus_error_message(&error, r));
-
- ts = now(CLOCK_MONOTONIC) - ts;
-
- r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
- _cleanup_free_ char *pretty = NULL;
- int ifindex, family;
- const void *a;
- size_t sz;
-
- assert_cc(sizeof(int) == sizeof(int32_t));
-
- r = sd_bus_message_read(reply, "ii", &ifindex, &family);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_read_array(reply, 'y', &a, &sz);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (!IN_SET(family, AF_INET, AF_INET6)) {
- log_debug("%s: skipping entry with family %d (%s)", name, family, af_to_name(family) ?: "unknown");
- continue;
- }
-
- if (sz != FAMILY_ADDRESS_SIZE(family)) {
- log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name, sz, af_to_name(family) ?: "unknown");
- return -EINVAL;
- }
-
- ifname[0] = 0;
- if (ifindex > 0 && !if_indextoname(ifindex, ifname))
- log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
-
- r = in_addr_to_string(family, a, &pretty);
- if (r < 0)
- return log_error_errno(r, "Failed to print address for %s: %m", name);
-
- printf("%*s%s %s%s%s\n",
- (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ",
- pretty,
- isempty(ifname) ? "" : "%", ifname);
-
- c++;
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_read(reply, "st", &canonical, &flags);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (!streq(name, canonical))
- printf("%*s%s (%s)\n",
- (int) strlen(name), c == 0 ? name : "", c == 0 ? ":" : " ",
- canonical);
-
- if (c == 0) {
- log_error("%s: no addresses found", name);
- return -ESRCH;
- }
-
- print_source(flags, ts);
-
- return 0;
-}
-
-static int resolve_address(sd_bus *bus, int family, const union in_addr_union *address, int ifindex) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *pretty = NULL;
- char ifname[IF_NAMESIZE] = "";
- uint64_t flags;
- unsigned c = 0;
- usec_t ts;
- int r;
-
- assert(bus);
- assert(IN_SET(family, AF_INET, AF_INET6));
- assert(address);
-
- if (ifindex <= 0)
- ifindex = arg_ifindex;
-
- r = in_addr_to_string(family, address, &pretty);
- if (r < 0)
- return log_oom();
-
- if (ifindex > 0 && !if_indextoname(ifindex, ifname))
- return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
-
- log_debug("Resolving %s%s%s.", pretty, isempty(ifname) ? "" : "%", ifname);
-
- r = sd_bus_message_new_method_call(
- bus,
- &req,
- "org.freedesktop.resolve1",
- "/org/freedesktop/resolve1",
- "org.freedesktop.resolve1.Manager",
- "ResolveAddress");
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append(req, "ii", ifindex, family);
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append_array(req, 'y', address, FAMILY_ADDRESS_SIZE(family));
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append(req, "t", arg_flags);
- if (r < 0)
- return bus_log_create_error(r);
-
- ts = now(CLOCK_MONOTONIC);
-
- r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
- if (r < 0) {
- log_error("%s: resolve call failed: %s", pretty, bus_error_message(&error, r));
- return r;
- }
-
- ts = now(CLOCK_MONOTONIC) - ts;
-
- r = sd_bus_message_enter_container(reply, 'a', "(is)");
- if (r < 0)
- return bus_log_create_error(r);
-
- while ((r = sd_bus_message_enter_container(reply, 'r', "is")) > 0) {
- const char *n;
-
- assert_cc(sizeof(int) == sizeof(int32_t));
-
- r = sd_bus_message_read(reply, "is", &ifindex, &n);
- if (r < 0)
- return r;
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return r;
-
- ifname[0] = 0;
- if (ifindex > 0 && !if_indextoname(ifindex, ifname))
- log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
-
- printf("%*s%*s%*s%s %s\n",
- (int) strlen(pretty), c == 0 ? pretty : "",
- isempty(ifname) ? 0 : 1, c > 0 || isempty(ifname) ? "" : "%",
- (int) strlen(ifname), c == 0 ? ifname : "",
- c == 0 ? ":" : " ",
- n);
-
- c++;
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_read(reply, "t", &flags);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (c == 0) {
- log_error("%s: no names found", pretty);
- return -ESRCH;
- }
-
- print_source(flags, ts);
-
- return 0;
-}
-
-static int parse_address(const char *s, int *family, union in_addr_union *address, int *ifindex) {
- const char *percent, *a;
- int ifi = 0;
- int r;
-
- percent = strchr(s, '%');
- if (percent) {
- if (parse_ifindex(percent+1, &ifi) < 0) {
- ifi = if_nametoindex(percent+1);
- if (ifi <= 0)
- return -EINVAL;
- }
-
- a = strndupa(s, percent - s);
- } else
- a = s;
-
- r = in_addr_from_string_auto(a, family, address);
- if (r < 0)
- return r;
-
- *ifindex = ifi;
- return 0;
-}
-
-static int output_rr_packet(const void *d, size_t l, int ifindex) {
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
- _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
- int r;
- char ifname[IF_NAMESIZE] = "";
-
- r = dns_packet_new(&p, DNS_PROTOCOL_DNS, 0);
- if (r < 0)
- return log_oom();
-
- p->refuse_compression = true;
-
- r = dns_packet_append_blob(p, d, l, NULL);
- if (r < 0)
- return log_oom();
-
- r = dns_packet_read_rr(p, &rr, NULL, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to parse RR: %m");
-
- if (arg_raw == RAW_PAYLOAD) {
- void *data;
- ssize_t k;
-
- k = dns_resource_record_payload(rr, &data);
- if (k < 0)
- return log_error_errno(k, "Cannot dump RR: %m");
- fwrite(data, 1, k, stdout);
- } else {
- const char *s;
-
- s = dns_resource_record_to_string(rr);
- if (!s)
- return log_oom();
-
- if (ifindex > 0 && !if_indextoname(ifindex, ifname))
- log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
-
- printf("%s%s%s\n", s, isempty(ifname) ? "" : " # interface ", ifname);
- }
-
- return 0;
-}
-
-static int resolve_record(sd_bus *bus, const char *name, uint16_t class, uint16_t type) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- char ifname[IF_NAMESIZE] = "";
- unsigned n = 0;
- uint64_t flags;
- int r;
- usec_t ts;
- bool needs_authentication = false;
-
- assert(name);
-
- if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname))
- return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex);
-
- log_debug("Resolving %s %s %s (interface %s).", name, dns_class_to_string(class), dns_type_to_string(type), isempty(ifname) ? "*" : ifname);
-
- r = sd_bus_message_new_method_call(
- bus,
- &req,
- "org.freedesktop.resolve1",
- "/org/freedesktop/resolve1",
- "org.freedesktop.resolve1.Manager",
- "ResolveRecord");
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append(req, "isqqt", arg_ifindex, name, class, type, arg_flags);
- if (r < 0)
- return bus_log_create_error(r);
-
- ts = now(CLOCK_MONOTONIC);
-
- r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
- if (r < 0) {
- log_error("%s: resolve call failed: %s", name, bus_error_message(&error, r));
- return r;
- }
-
- ts = now(CLOCK_MONOTONIC) - ts;
-
- r = sd_bus_message_enter_container(reply, 'a', "(iqqay)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_enter_container(reply, 'r', "iqqay")) > 0) {
- uint16_t c, t;
- int ifindex;
- const void *d;
- size_t l;
-
- assert_cc(sizeof(int) == sizeof(int32_t));
-
- r = sd_bus_message_read(reply, "iqq", &ifindex, &c, &t);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_read_array(reply, 'y', &d, &l);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (arg_raw == RAW_PACKET) {
- uint64_t u64 = htole64(l);
-
- fwrite(&u64, sizeof(u64), 1, stdout);
- fwrite(d, 1, l, stdout);
- } else {
- r = output_rr_packet(d, l, ifindex);
- if (r < 0)
- return r;
- }
-
- if (dns_type_needs_authentication(t))
- needs_authentication = true;
-
- n++;
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_read(reply, "t", &flags);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (n == 0) {
- log_error("%s: no records found", name);
- return -ESRCH;
- }
-
- print_source(flags, ts);
-
- if ((flags & SD_RESOLVED_AUTHENTICATED) == 0 && needs_authentication) {
- fflush(stdout);
-
- fprintf(stderr, "\n%s"
- "WARNING: The resources shown contain cryptographic key data which could not be\n"
- " authenticated. It is not suitable to authenticate any communication.\n"
- " This is usually indication that DNSSEC authentication was not enabled\n"
- " or is not available for the selected protocol or DNS servers.%s\n",
- ansi_highlight_red(),
- ansi_normal());
- }
-
- return 0;
-}
-
-static int resolve_rfc4501(sd_bus *bus, const char *name) {
- uint16_t type = 0, class = 0;
- const char *p, *q, *n;
- int r;
-
- assert(bus);
- assert(name);
- assert(startswith(name, "dns:"));
-
- /* Parse RFC 4501 dns: URIs */
-
- p = name + 4;
-
- if (p[0] == '/') {
- const char *e;
-
- if (p[1] != '/')
- goto invalid;
-
- e = strchr(p + 2, '/');
- if (!e)
- goto invalid;
-
- if (e != p + 2)
- log_warning("DNS authority specification not supported; ignoring specified authority.");
-
- p = e + 1;
- }
-
- q = strchr(p, '?');
- if (q) {
- n = strndupa(p, q - p);
- q++;
-
- for (;;) {
- const char *f;
-
- f = startswith_no_case(q, "class=");
- if (f) {
- _cleanup_free_ char *t = NULL;
- const char *e;
-
- if (class != 0) {
- log_error("DNS class specified twice.");
- return -EINVAL;
- }
-
- e = strchrnul(f, ';');
- t = strndup(f, e - f);
- if (!t)
- return log_oom();
-
- r = dns_class_from_string(t);
- if (r < 0) {
- log_error("Unknown DNS class %s.", t);
- return -EINVAL;
- }
-
- class = r;
-
- if (*e == ';') {
- q = e + 1;
- continue;
- }
-
- break;
- }
-
- f = startswith_no_case(q, "type=");
- if (f) {
- _cleanup_free_ char *t = NULL;
- const char *e;
-
- if (type != 0) {
- log_error("DNS type specified twice.");
- return -EINVAL;
- }
-
- e = strchrnul(f, ';');
- t = strndup(f, e - f);
- if (!t)
- return log_oom();
-
- r = dns_type_from_string(t);
- if (r < 0) {
- log_error("Unknown DNS type %s.", t);
- return -EINVAL;
- }
-
- type = r;
-
- if (*e == ';') {
- q = e + 1;
- continue;
- }
-
- break;
- }
-
- goto invalid;
- }
- } else
- n = p;
-
- if (class == 0)
- class = arg_class ?: DNS_CLASS_IN;
- if (type == 0)
- type = arg_type ?: DNS_TYPE_A;
-
- return resolve_record(bus, n, class, type);
-
-invalid:
- log_error("Invalid DNS URI: %s", name);
- return -EINVAL;
-}
-
-static int resolve_service(sd_bus *bus, const char *name, const char *type, const char *domain) {
- const char *canonical_name, *canonical_type, *canonical_domain;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- char ifname[IF_NAMESIZE] = "";
- size_t indent, sz;
- uint64_t flags;
- const char *p;
- unsigned c;
- usec_t ts;
- int r;
-
- assert(bus);
- assert(domain);
-
- if (isempty(name))
- name = NULL;
- if (isempty(type))
- type = NULL;
-
- if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname))
- return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex);
-
- if (name)
- log_debug("Resolving service \"%s\" of type %s in %s (family %s, interface %s).", name, type, domain, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
- else if (type)
- log_debug("Resolving service type %s of %s (family %s, interface %s).", type, domain, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
- else
- log_debug("Resolving service type %s (family %s, interface %s).", domain, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname);
-
- r = sd_bus_message_new_method_call(
- bus,
- &req,
- "org.freedesktop.resolve1",
- "/org/freedesktop/resolve1",
- "org.freedesktop.resolve1.Manager",
- "ResolveService");
- if (r < 0)
- return bus_log_create_error(r);
-
- r = sd_bus_message_append(req, "isssit", arg_ifindex, name, type, domain, arg_family, arg_flags);
- if (r < 0)
- return bus_log_create_error(r);
-
- ts = now(CLOCK_MONOTONIC);
-
- r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
- if (r < 0)
- return log_error_errno(r, "Resolve call failed: %s", bus_error_message(&error, r));
-
- ts = now(CLOCK_MONOTONIC) - ts;
-
- r = sd_bus_message_enter_container(reply, 'a', "(qqqsa(iiay)s)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- indent =
- (name ? strlen(name) + 1 : 0) +
- (type ? strlen(type) + 1 : 0) +
- strlen(domain) + 2;
-
- c = 0;
- while ((r = sd_bus_message_enter_container(reply, 'r', "qqqsa(iiay)s")) > 0) {
- uint16_t priority, weight, port;
- const char *hostname, *canonical;
-
- r = sd_bus_message_read(reply, "qqqs", &priority, &weight, &port, &hostname);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (name)
- printf("%*s%s", (int) strlen(name), c == 0 ? name : "", c == 0 ? "/" : " ");
- if (type)
- printf("%*s%s", (int) strlen(type), c == 0 ? type : "", c == 0 ? "/" : " ");
-
- printf("%*s%s %s:%u [priority=%u, weight=%u]\n",
- (int) strlen(domain), c == 0 ? domain : "",
- c == 0 ? ":" : " ",
- hostname, port,
- priority, weight);
-
- r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
- if (r < 0)
- return bus_log_parse_error(r);
-
- while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
- _cleanup_free_ char *pretty = NULL;
- int ifindex, family;
- const void *a;
-
- assert_cc(sizeof(int) == sizeof(int32_t));
-
- r = sd_bus_message_read(reply, "ii", &ifindex, &family);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_read_array(reply, 'y', &a, &sz);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (!IN_SET(family, AF_INET, AF_INET6)) {
- log_debug("%s: skipping entry with family %d (%s)", name, family, af_to_name(family) ?: "unknown");
- continue;
- }
-
- if (sz != FAMILY_ADDRESS_SIZE(family)) {
- log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name, sz, af_to_name(family) ?: "unknown");
- return -EINVAL;
- }
-
- ifname[0] = 0;
- if (ifindex > 0 && !if_indextoname(ifindex, ifname))
- log_warning_errno(errno, "Failed to resolve interface name for index %i: %m", ifindex);
-
- r = in_addr_to_string(family, a, &pretty);
- if (r < 0)
- return log_error_errno(r, "Failed to print address for %s: %m", name);
-
- printf("%*s%s%s%s\n", (int) indent, "", pretty, isempty(ifname) ? "" : "%s", ifname);
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_read(reply, "s", &canonical);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (!streq(hostname, canonical))
- printf("%*s(%s)\n", (int) indent, "", canonical);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- c++;
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_enter_container(reply, 'a', "ay");
- if (r < 0)
- return bus_log_parse_error(r);
-
- c = 0;
- while ((r = sd_bus_message_read_array(reply, 'y', (const void**) &p, &sz)) > 0) {
- _cleanup_free_ char *escaped = NULL;
-
- escaped = cescape_length(p, sz);
- if (!escaped)
- return log_oom();
-
- printf("%*s%s\n", (int) indent, "", escaped);
- c++;
- }
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_exit_container(reply);
- if (r < 0)
- return bus_log_parse_error(r);
-
- r = sd_bus_message_read(reply, "ssst", &canonical_name, &canonical_type, &canonical_domain, &flags);
- if (r < 0)
- return bus_log_parse_error(r);
-
- if (isempty(canonical_name))
- canonical_name = NULL;
- if (isempty(canonical_type))
- canonical_type = NULL;
-
- if (!streq_ptr(name, canonical_name) ||
- !streq_ptr(type, canonical_type) ||
- !streq_ptr(domain, canonical_domain)) {
-
- printf("%*s(", (int) indent, "");
-
- if (canonical_name)
- printf("%s/", canonical_name);
- if (canonical_type)
- printf("%s/", canonical_type);
-
- printf("%s)\n", canonical_domain);
- }
-
- print_source(flags, ts);
-
- return 0;
-}
-
-static int resolve_openpgp(sd_bus *bus, const char *address) {
- const char *domain, *full;
- int r;
- _cleanup_free_ char *hashed = NULL;
-
- assert(bus);
- assert(address);
-
- domain = strrchr(address, '@');
- if (!domain) {
- log_error("Address does not contain '@': \"%s\"", address);
- return -EINVAL;
- } else if (domain == address || domain[1] == '\0') {
- log_error("Address starts or ends with '@': \"%s\"", address);
- return -EINVAL;
- }
- domain++;
-
- r = string_hashsum_sha224(address, domain - 1 - address, &hashed);
- if (r < 0)
- return log_error_errno(r, "Hashing failed: %m");
-
- full = strjoina(hashed, "._openpgpkey.", domain);
- log_debug("Looking up \"%s\".", full);
-
- return resolve_record(bus, full,
- arg_class ?: DNS_CLASS_IN,
- arg_type ?: DNS_TYPE_OPENPGPKEY);
-}
-
-static int resolve_tlsa(sd_bus *bus, const char *address) {
- const char *port;
- uint16_t port_num = 443;
- _cleanup_free_ char *full = NULL;
- int r;
-
- assert(bus);
- assert(address);
-
- port = strrchr(address, ':');
- if (port) {
- r = safe_atou16(port + 1, &port_num);
- if (r < 0 || port_num == 0)
- return log_error_errno(r, "Invalid port \"%s\".", port + 1);
-
- address = strndupa(address, port - address);
- }
-
- r = asprintf(&full, "_%u.%s.%s",
- port_num,
- service_family_to_string(arg_service_family),
- address);
- if (r < 0)
- return log_oom();
-
- log_debug("Looking up \"%s\".", full);
-
- return resolve_record(bus, full,
- arg_class ?: DNS_CLASS_IN,
- arg_type ?: DNS_TYPE_TLSA);
-}
-
-static int show_statistics(sd_bus *bus) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- uint64_t n_current_transactions, n_total_transactions,
- cache_size, n_cache_hit, n_cache_miss,
- n_dnssec_secure, n_dnssec_insecure, n_dnssec_bogus, n_dnssec_indeterminate;
- int r, dnssec_supported;
-
- assert(bus);
-
- r = sd_bus_get_property_trivial(bus,
- "org.freedesktop.resolve1",
- "/org/freedesktop/resolve1",
- "org.freedesktop.resolve1.Manager",
- "DNSSECSupported",
- &error,
- 'b',
- &dnssec_supported);
- if (r < 0)
- return log_error_errno(r, "Failed to get DNSSEC supported state: %s", bus_error_message(&error, r));
-
- printf("DNSSEC supported by current servers: %s%s%s\n\n",
- ansi_highlight(),
- yes_no(dnssec_supported),
- ansi_normal());
-
- r = sd_bus_get_property(bus,
- "org.freedesktop.resolve1",
- "/org/freedesktop/resolve1",
- "org.freedesktop.resolve1.Manager",
- "TransactionStatistics",
- &error,
- &reply,
- "(tt)");
- if (r < 0)
- return log_error_errno(r, "Failed to get transaction statistics: %s", bus_error_message(&error, r));
-
- r = sd_bus_message_read(reply, "(tt)",
- &n_current_transactions,
- &n_total_transactions);
- if (r < 0)
- return bus_log_parse_error(r);
-
- printf("%sTransactions%s\n"
- "Current Transactions: %" PRIu64 "\n"
- " Total Transactions: %" PRIu64 "\n",
- ansi_highlight(),
- ansi_normal(),
- n_current_transactions,
- n_total_transactions);
-
- reply = sd_bus_message_unref(reply);
-
- r = sd_bus_get_property(bus,
- "org.freedesktop.resolve1",
- "/org/freedesktop/resolve1",
- "org.freedesktop.resolve1.Manager",
- "CacheStatistics",
- &error,
- &reply,
- "(ttt)");
- if (r < 0)
- return log_error_errno(r, "Failed to get cache statistics: %s", bus_error_message(&error, r));
-
- r = sd_bus_message_read(reply, "(ttt)",
- &cache_size,
- &n_cache_hit,
- &n_cache_miss);
- if (r < 0)
- return bus_log_parse_error(r);
-
- printf("\n%sCache%s\n"
- " Current Cache Size: %" PRIu64 "\n"
- " Cache Hits: %" PRIu64 "\n"
- " Cache Misses: %" PRIu64 "\n",
- ansi_highlight(),
- ansi_normal(),
- cache_size,
- n_cache_hit,
- n_cache_miss);
-
- reply = sd_bus_message_unref(reply);
-
- r = sd_bus_get_property(bus,
- "org.freedesktop.resolve1",
- "/org/freedesktop/resolve1",
- "org.freedesktop.resolve1.Manager",
- "DNSSECStatistics",
- &error,
- &reply,
- "(tttt)");
- if (r < 0)
- return log_error_errno(r, "Failed to get DNSSEC statistics: %s", bus_error_message(&error, r));
-
- r = sd_bus_message_read(reply, "(tttt)",
- &n_dnssec_secure,
- &n_dnssec_insecure,
- &n_dnssec_bogus,
- &n_dnssec_indeterminate);
- if (r < 0)
- return bus_log_parse_error(r);
-
- printf("\n%sDNSSEC Verdicts%s\n"
- " Secure: %" PRIu64 "\n"
- " Insecure: %" PRIu64 "\n"
- " Bogus: %" PRIu64 "\n"
- " Indeterminate: %" PRIu64 "\n",
- ansi_highlight(),
- ansi_normal(),
- n_dnssec_secure,
- n_dnssec_insecure,
- n_dnssec_bogus,
- n_dnssec_indeterminate);
-
- return 0;
-}
-
-static int reset_statistics(sd_bus *bus) {
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- int r;
-
- r = sd_bus_call_method(bus,
- "org.freedesktop.resolve1",
- "/org/freedesktop/resolve1",
- "org.freedesktop.resolve1.Manager",
- "ResetStatistics",
- &error,
- NULL,
- NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to reset statistics: %s", bus_error_message(&error, r));
-
- return 0;
-}
-
-static void help_protocol_types(void) {
- if (arg_legend)
- puts("Known protocol types:");
- puts("dns\nllmnr\nllmnr-ipv4\nllmnr-ipv6");
-}
-
-static void help_dns_types(void) {
- int i;
- const char *t;
-
- if (arg_legend)
- puts("Known DNS RR types:");
- for (i = 0; i < _DNS_TYPE_MAX; i++) {
- t = dns_type_to_string(i);
- if (t)
- puts(t);
- }
-}
-
-static void help_dns_classes(void) {
- int i;
- const char *t;
-
- if (arg_legend)
- puts("Known DNS RR classes:");
- for (i = 0; i < _DNS_CLASS_MAX; i++) {
- t = dns_class_to_string(i);
- if (t)
- puts(t);
- }
-}
-
-static void help(void) {
- printf("%1$s [OPTIONS...] HOSTNAME|ADDRESS...\n"
- "%1$s [OPTIONS...] --service [[NAME] TYPE] DOMAIN\n"
- "%1$s [OPTIONS...] --openpgp EMAIL@DOMAIN...\n"
- "%1$s [OPTIONS...] --statistics\n"
- "%1$s [OPTIONS...] --reset-statistics\n"
- "\n"
- "Resolve domain names, IPv4 and IPv6 addresses, DNS resource records, and services.\n\n"
- " -h --help Show this help\n"
- " --version Show package version\n"
- " -4 Resolve IPv4 addresses\n"
- " -6 Resolve IPv6 addresses\n"
- " -i --interface=INTERFACE Look on interface\n"
- " -p --protocol=PROTO|help Look via protocol\n"
- " -t --type=TYPE|help Query RR with DNS type\n"
- " -c --class=CLASS|help Query RR with DNS class\n"
- " --service Resolve service (SRV)\n"
- " --service-address=BOOL Resolve address for services (default: yes)\n"
- " --service-txt=BOOL Resolve TXT records for services (default: yes)\n"
- " --openpgp Query OpenPGP public key\n"
- " --tlsa Query TLS public key\n"
- " --cname=BOOL Follow CNAME redirects (default: yes)\n"
- " --search=BOOL Use search domains for single-label names\n"
- " (default: yes)\n"
- " --raw[=payload|packet] Dump the answer as binary data\n"
- " --legend=BOOL Print headers and additional info (default: yes)\n"
- " --statistics Show resolver statistics\n"
- " --reset-statistics Reset resolver statistics\n"
- , program_invocation_short_name);
-}
-
-static int parse_argv(int argc, char *argv[]) {
- enum {
- ARG_VERSION = 0x100,
- ARG_LEGEND,
- ARG_SERVICE,
- ARG_CNAME,
- ARG_SERVICE_ADDRESS,
- ARG_SERVICE_TXT,
- ARG_OPENPGP,
- ARG_TLSA,
- ARG_RAW,
- ARG_SEARCH,
- ARG_STATISTICS,
- ARG_RESET_STATISTICS,
- };
-
- static const struct option options[] = {
- { "help", no_argument, NULL, 'h' },
- { "version", no_argument, NULL, ARG_VERSION },
- { "type", required_argument, NULL, 't' },
- { "class", required_argument, NULL, 'c' },
- { "legend", required_argument, NULL, ARG_LEGEND },
- { "interface", required_argument, NULL, 'i' },
- { "protocol", required_argument, NULL, 'p' },
- { "cname", required_argument, NULL, ARG_CNAME },
- { "service", no_argument, NULL, ARG_SERVICE },
- { "service-address", required_argument, NULL, ARG_SERVICE_ADDRESS },
- { "service-txt", required_argument, NULL, ARG_SERVICE_TXT },
- { "openpgp", no_argument, NULL, ARG_OPENPGP },
- { "tlsa", optional_argument, NULL, ARG_TLSA },
- { "raw", optional_argument, NULL, ARG_RAW },
- { "search", required_argument, NULL, ARG_SEARCH },
- { "statistics", no_argument, NULL, ARG_STATISTICS, },
- { "reset-statistics", no_argument, NULL, ARG_RESET_STATISTICS },
- {}
- };
-
- int c, r;
-
- assert(argc >= 0);
- assert(argv);
-
- while ((c = getopt_long(argc, argv, "h46i:t:c:p:", options, NULL)) >= 0)
- switch(c) {
-
- case 'h':
- help();
- return 0; /* done */;
-
- case ARG_VERSION:
- return version();
-
- case '4':
- arg_family = AF_INET;
- break;
-
- case '6':
- arg_family = AF_INET6;
- break;
-
- case 'i': {
- int ifi;
-
- if (parse_ifindex(optarg, &ifi) >= 0)
- arg_ifindex = ifi;
- else {
- ifi = if_nametoindex(optarg);
- if (ifi <= 0)
- return log_error_errno(errno, "Unknown interface %s: %m", optarg);
-
- arg_ifindex = ifi;
- }
-
- break;
- }
-
- case 't':
- if (streq(optarg, "help")) {
- help_dns_types();
- return 0;
- }
-
- r = dns_type_from_string(optarg);
- if (r < 0) {
- log_error("Failed to parse RR record type %s", optarg);
- return r;
- }
- arg_type = (uint16_t) r;
- assert((int) arg_type == r);
-
- arg_mode = MODE_RESOLVE_RECORD;
- break;
-
- case 'c':
- if (streq(optarg, "help")) {
- help_dns_classes();
- return 0;
- }
-
- r = dns_class_from_string(optarg);
- if (r < 0) {
- log_error("Failed to parse RR record class %s", optarg);
- return r;
- }
- arg_class = (uint16_t) r;
- assert((int) arg_class == r);
-
- break;
-
- case ARG_LEGEND:
- r = parse_boolean(optarg);
- if (r < 0)
- return log_error_errno(r, "Failed to parse --legend= argument");
-
- arg_legend = r;
- break;
-
- case 'p':
- if (streq(optarg, "help")) {
- help_protocol_types();
- return 0;
- } else if (streq(optarg, "dns"))
- arg_flags |= SD_RESOLVED_DNS;
- else if (streq(optarg, "llmnr"))
- arg_flags |= SD_RESOLVED_LLMNR;
- else if (streq(optarg, "llmnr-ipv4"))
- arg_flags |= SD_RESOLVED_LLMNR_IPV4;
- else if (streq(optarg, "llmnr-ipv6"))
- arg_flags |= SD_RESOLVED_LLMNR_IPV6;
- else {
- log_error("Unknown protocol specifier: %s", optarg);
- return -EINVAL;
- }
-
- break;
-
- case ARG_SERVICE:
- arg_mode = MODE_RESOLVE_SERVICE;
- break;
-
- case ARG_OPENPGP:
- arg_mode = MODE_RESOLVE_OPENPGP;
- break;
-
- case ARG_TLSA:
- arg_mode = MODE_RESOLVE_TLSA;
- arg_service_family = service_family_from_string(optarg);
- if (arg_service_family < 0) {
- log_error("Unknown service family \"%s\".", optarg);
- return -EINVAL;
- }
- break;
-
- case ARG_RAW:
- if (on_tty()) {
- log_error("Refusing to write binary data to tty.");
- return -ENOTTY;
- }
-
- if (optarg == NULL || streq(optarg, "payload"))
- arg_raw = RAW_PAYLOAD;
- else if (streq(optarg, "packet"))
- arg_raw = RAW_PACKET;
- else {
- log_error("Unknown --raw specifier \"%s\".", optarg);
- return -EINVAL;
- }
-
- arg_legend = false;
- break;
-
- case ARG_CNAME:
- r = parse_boolean(optarg);
- if (r < 0)
- return log_error_errno(r, "Failed to parse --cname= argument.");
- SET_FLAG(arg_flags, SD_RESOLVED_NO_CNAME, r == 0);
- break;
-
- case ARG_SERVICE_ADDRESS:
- r = parse_boolean(optarg);
- if (r < 0)
- return log_error_errno(r, "Failed to parse --service-address= argument.");
- SET_FLAG(arg_flags, SD_RESOLVED_NO_ADDRESS, r == 0);
- break;
-
- case ARG_SERVICE_TXT:
- r = parse_boolean(optarg);
- if (r < 0)
- return log_error_errno(r, "Failed to parse --service-txt= argument.");
- SET_FLAG(arg_flags, SD_RESOLVED_NO_TXT, r == 0);
- break;
-
- case ARG_SEARCH:
- r = parse_boolean(optarg);
- if (r < 0)
- return log_error_errno(r, "Failed to parse --search argument.");
- SET_FLAG(arg_flags, SD_RESOLVED_NO_SEARCH, r == 0);
- break;
-
- case ARG_STATISTICS:
- arg_mode = MODE_STATISTICS;
- break;
-
- case ARG_RESET_STATISTICS:
- arg_mode = MODE_RESET_STATISTICS;
- break;
-
- case '?':
- return -EINVAL;
-
- default:
- assert_not_reached("Unhandled option");
- }
-
- if (arg_type == 0 && arg_class != 0) {
- log_error("--class= may only be used in conjunction with --type=.");
- return -EINVAL;
- }
-
- if (arg_type != 0 && arg_mode == MODE_RESOLVE_SERVICE) {
- log_error("--service and --type= may not be combined.");
- return -EINVAL;
- }
-
- if (arg_type != 0 && arg_class == 0)
- arg_class = DNS_CLASS_IN;
-
- if (arg_class != 0 && arg_type == 0)
- arg_type = DNS_TYPE_A;
-
- return 1 /* work to do */;
-}
-
-int main(int argc, char **argv) {
- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
- int r;
-
- log_parse_environment();
- log_open();
-
- r = parse_argv(argc, argv);
- if (r <= 0)
- goto finish;
-
- r = sd_bus_open_system(&bus);
- if (r < 0) {
- log_error_errno(r, "sd_bus_open_system: %m");
- goto finish;
- }
-
- switch (arg_mode) {
-
- case MODE_RESOLVE_HOST:
- if (optind >= argc) {
- log_error("No arguments passed.");
- r = -EINVAL;
- goto finish;
- }
-
- while (argv[optind]) {
- int family, ifindex, k;
- union in_addr_union a;
-
- if (startswith(argv[optind], "dns:"))
- k = resolve_rfc4501(bus, argv[optind]);
- else {
- k = parse_address(argv[optind], &family, &a, &ifindex);
- if (k >= 0)
- k = resolve_address(bus, family, &a, ifindex);
- else
- k = resolve_host(bus, argv[optind]);
- }
-
- if (r == 0)
- r = k;
-
- optind++;
- }
- break;
-
- case MODE_RESOLVE_RECORD:
- if (optind >= argc) {
- log_error("No arguments passed.");
- r = -EINVAL;
- goto finish;
- }
-
- while (argv[optind]) {
- int k;
-
- k = resolve_record(bus, argv[optind], arg_class, arg_type);
- if (r == 0)
- r = k;
-
- optind++;
- }
- break;
-
- case MODE_RESOLVE_SERVICE:
- if (argc < optind + 1) {
- log_error("Domain specification required.");
- r = -EINVAL;
- goto finish;
-
- } else if (argc == optind + 1)
- r = resolve_service(bus, NULL, NULL, argv[optind]);
- else if (argc == optind + 2)
- r = resolve_service(bus, NULL, argv[optind], argv[optind+1]);
- else if (argc == optind + 3)
- r = resolve_service(bus, argv[optind], argv[optind+1], argv[optind+2]);
- else {
- log_error("Too many arguments.");
- r = -EINVAL;
- goto finish;
- }
-
- break;
-
- case MODE_RESOLVE_OPENPGP:
- if (argc < optind + 1) {
- log_error("E-mail address required.");
- r = -EINVAL;
- goto finish;
-
- }
-
- r = 0;
- while (optind < argc) {
- int k;
-
- k = resolve_openpgp(bus, argv[optind++]);
- if (k < 0)
- r = k;
- }
- break;
-
- case MODE_RESOLVE_TLSA:
- if (argc < optind + 1) {
- log_error("Domain name required.");
- r = -EINVAL;
- goto finish;
-
- }
-
- r = 0;
- while (optind < argc) {
- int k;
-
- k = resolve_tlsa(bus, argv[optind++]);
- if (k < 0)
- r = k;
- }
- break;
-
- case MODE_STATISTICS:
- if (argc > optind) {
- log_error("Too many arguments.");
- r = -EINVAL;
- goto finish;
- }
-
- r = show_statistics(bus);
- break;
-
- case MODE_RESET_STATISTICS:
- if (argc > optind) {
- log_error("Too many arguments.");
- r = -EINVAL;
- goto finish;
- }
-
- r = reset_statistics(bus);
- break;
- }
-
-finish:
- return r == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
-}
diff --git a/src/grp-resolve/systemd-resolved/resolved-def.h b/src/grp-resolve/systemd-resolved/resolved-def.h
deleted file mode 100644
index c4c1915b18..0000000000
--- a/src/grp-resolve/systemd-resolved/resolved-def.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <inttypes.h>
-
-#define SD_RESOLVED_DNS (UINT64_C(1) << 0)
-#define SD_RESOLVED_LLMNR_IPV4 (UINT64_C(1) << 1)
-#define SD_RESOLVED_LLMNR_IPV6 (UINT64_C(1) << 2)
-#define SD_RESOLVED_MDNS_IPV4 (UINT64_C(1) << 3)
-#define SD_RESOLVED_MDNS_IPV6 (UINT64_C(1) << 4)
-#define SD_RESOLVED_NO_CNAME (UINT64_C(1) << 5)
-#define SD_RESOLVED_NO_TXT (UINT64_C(1) << 6)
-#define SD_RESOLVED_NO_ADDRESS (UINT64_C(1) << 7)
-#define SD_RESOLVED_NO_SEARCH (UINT64_C(1) << 8)
-#define SD_RESOLVED_AUTHENTICATED (UINT64_C(1) << 9)
-
-#define SD_RESOLVED_LLMNR (SD_RESOLVED_LLMNR_IPV4|SD_RESOLVED_LLMNR_IPV6)
-#define SD_RESOLVED_MDNS (SD_RESOLVED_MDNS_IPV4|SD_RESOLVED_MDNS_IPV6)
-
-#define SD_RESOLVED_PROTOCOLS_ALL (SD_RESOLVED_MDNS|SD_RESOLVED_LLMNR|SD_RESOLVED_DNS)
diff --git a/src/grp-resolve/systemd-resolved/resolved-dns-answer.c b/src/grp-resolve/systemd-resolved/resolved-dns-answer.c
deleted file mode 100644
index 1ade0507db..0000000000
--- a/src/grp-resolve/systemd-resolved/resolved-dns-answer.c
+++ /dev/null
@@ -1,859 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "basic/alloc-util.h"
-#include "basic/string-util.h"
-#include "shared/dns-domain.h"
-
-#include "resolved-dns-answer.h"
-#include "resolved-dns-dnssec.h"
-
-DnsAnswer *dns_answer_new(unsigned n) {
- DnsAnswer *a;
-
- a = malloc0(offsetof(DnsAnswer, items) + sizeof(DnsAnswerItem) * n);
- if (!a)
- return NULL;
-
- a->n_ref = 1;
- a->n_allocated = n;
-
- return a;
-}
-
-DnsAnswer *dns_answer_ref(DnsAnswer *a) {
- if (!a)
- return NULL;
-
- assert(a->n_ref > 0);
- a->n_ref++;
- return a;
-}
-
-static void dns_answer_flush(DnsAnswer *a) {
- DnsResourceRecord *rr;
-
- if (!a)
- return;
-
- DNS_ANSWER_FOREACH(rr, a)
- dns_resource_record_unref(rr);
-
- a->n_rrs = 0;
-}
-
-DnsAnswer *dns_answer_unref(DnsAnswer *a) {
- if (!a)
- return NULL;
-
- assert(a->n_ref > 0);
-
- if (a->n_ref == 1) {
- dns_answer_flush(a);
- free(a);
- } else
- a->n_ref--;
-
- return NULL;
-}
-
-static int dns_answer_add_raw(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) {
- assert(rr);
-
- if (!a)
- return -ENOSPC;
-
- if (a->n_rrs >= a->n_allocated)
- return -ENOSPC;
-
- a->items[a->n_rrs++] = (DnsAnswerItem) {
- .rr = dns_resource_record_ref(rr),
- .ifindex = ifindex,
- .flags = flags,
- };
-
- return 1;
-}
-
-static int dns_answer_add_raw_all(DnsAnswer *a, DnsAnswer *source) {
- DnsResourceRecord *rr;
- DnsAnswerFlags flags;
- int ifindex, r;
-
- DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, source) {
- r = dns_answer_add_raw(a, rr, ifindex, flags);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) {
- unsigned i;
- int r;
-
- assert(rr);
-
- if (!a)
- return -ENOSPC;
- if (a->n_ref > 1)
- return -EBUSY;
-
- for (i = 0; i < a->n_rrs; i++) {
- if (a->items[i].ifindex != ifindex)
- continue;
-
- r = dns_resource_record_equal(a->items[i].rr, rr);
- if (r < 0)
- return r;
- if (r > 0) {
- /* Don't mix contradicting TTLs (see below) */
- if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0))
- return -EINVAL;
-
- /* Entry already exists, keep the entry with
- * the higher RR. */
- if (rr->ttl > a->items[i].rr->ttl) {
- dns_resource_record_ref(rr);
- dns_resource_record_unref(a->items[i].rr);
- a->items[i].rr = rr;
- }
-
- a->items[i].flags |= flags;
- return 0;
- }
-
- r = dns_resource_key_equal(a->items[i].rr->key, rr->key);
- if (r < 0)
- return r;
- if (r > 0) {
- /* There's already an RR of the same RRset in
- * place! Let's see if the TTLs more or less
- * match. We don't really care if they match
- * precisely, but we do care whether one is 0
- * and the other is not. See RFC 2181, Section
- * 5.2.*/
-
- if ((rr->ttl == 0) != (a->items[i].rr->ttl == 0))
- return -EINVAL;
- }
- }
-
- return dns_answer_add_raw(a, rr, ifindex, flags);
-}
-
-static int dns_answer_add_all(DnsAnswer *a, DnsAnswer *b) {
- DnsResourceRecord *rr;
- DnsAnswerFlags flags;
- int ifindex, r;
-
- DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, b) {
- r = dns_answer_add(a, rr, ifindex, flags);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags) {
- int r;
-
- assert(a);
- assert(rr);
-
- r = dns_answer_reserve_or_clone(a, 1);
- if (r < 0)
- return r;
-
- return dns_answer_add(*a, rr, ifindex, flags);
-}
-
-int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl) {
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *soa = NULL;
-
- soa = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_SOA, name);
- if (!soa)
- return -ENOMEM;
-
- soa->ttl = ttl;
-
- soa->soa.mname = strdup(name);
- if (!soa->soa.mname)
- return -ENOMEM;
-
- soa->soa.rname = strappend("root.", name);
- if (!soa->soa.rname)
- return -ENOMEM;
-
- soa->soa.serial = 1;
- soa->soa.refresh = 1;
- soa->soa.retry = 1;
- soa->soa.expire = 1;
- soa->soa.minimum = ttl;
-
- return dns_answer_add(a, soa, 0, DNS_ANSWER_AUTHENTICATED);
-}
-
-int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *ret_flags) {
- DnsAnswerFlags flags = 0, i_flags;
- DnsResourceRecord *i;
- bool found = false;
- int r;
-
- assert(key);
-
- DNS_ANSWER_FOREACH_FLAGS(i, i_flags, a) {
- r = dns_resource_key_match_rr(key, i, NULL);
- if (r < 0)
- return r;
- if (r == 0)
- continue;
-
- if (!ret_flags)
- return 1;
-
- if (found)
- flags &= i_flags;
- else {
- flags = i_flags;
- found = true;
- }
- }
-
- if (ret_flags)
- *ret_flags = flags;
-
- return found;
-}
-
-int dns_answer_contains_rr(DnsAnswer *a, DnsResourceRecord *rr, DnsAnswerFlags *ret_flags) {
- DnsAnswerFlags flags = 0, i_flags;
- DnsResourceRecord *i;
- bool found = false;
- int r;
-
- assert(rr);
-
- DNS_ANSWER_FOREACH_FLAGS(i, i_flags, a) {
- r = dns_resource_record_equal(i, rr);
- if (r < 0)
- return r;
- if (r == 0)
- continue;
-
- if (!ret_flags)
- return 1;
-
- if (found)
- flags &= i_flags;
- else {
- flags = i_flags;
- found = true;
- }
- }
-
- if (ret_flags)
- *ret_flags = flags;
-
- return found;
-}
-
-int dns_answer_contains_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *ret_flags) {
- DnsAnswerFlags flags = 0, i_flags;
- DnsResourceRecord *i;
- bool found = false;
- int r;
-
- assert(key);
-
- DNS_ANSWER_FOREACH_FLAGS(i, i_flags, a) {
- r = dns_resource_key_equal(i->key, key);
- if (r < 0)
- return r;
- if (r == 0)
- continue;
-
- if (!ret_flags)
- return true;
-
- if (found)
- flags &= i_flags;
- else {
- flags = i_flags;
- found = true;
- }
- }
-
- if (ret_flags)
- *ret_flags = flags;
-
- return found;
-}
-
-int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a) {
- DnsResourceRecord *i;
-
- DNS_ANSWER_FOREACH(i, a) {
- if (IN_SET(i->key->type, DNS_TYPE_NSEC, DNS_TYPE_NSEC3))
- return true;
- }
-
- return false;
-}
-
-int dns_answer_contains_zone_nsec3(DnsAnswer *answer, const char *zone) {
- DnsResourceRecord *rr;
- int r;
-
- /* Checks whether the specified answer contains at least one NSEC3 RR in the specified zone */
-
- DNS_ANSWER_FOREACH(rr, answer) {
- const char *p;
-
- if (rr->key->type != DNS_TYPE_NSEC3)
- continue;
-
- p = dns_resource_key_name(rr->key);
- r = dns_name_parent(&p);
- if (r < 0)
- return r;
- if (r == 0)
- continue;
-
- r = dns_name_equal(p, zone);
- if (r != 0)
- return r;
- }
-
- return false;
-}
-
-int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags) {
- DnsResourceRecord *rr, *soa = NULL;
- DnsAnswerFlags rr_flags, soa_flags = 0;
- int r;
-
- assert(key);
-
- /* For a SOA record we can never find a matching SOA record */
- if (key->type == DNS_TYPE_SOA)
- return 0;
-
- DNS_ANSWER_FOREACH_FLAGS(rr, rr_flags, a) {
- r = dns_resource_key_match_soa(key, rr->key);
- if (r < 0)
- return r;
- if (r > 0) {
-
- if (soa) {
- r = dns_name_endswith(dns_resource_key_name(rr->key), dns_resource_key_name(soa->key));
- if (r < 0)
- return r;
- if (r > 0)
- continue;
- }
-
- soa = rr;
- soa_flags = rr_flags;
- }
- }
-
- if (!soa)
- return 0;
-
- if (ret)
- *ret = soa;
- if (flags)
- *flags = soa_flags;
-
- return 1;
-}
-
-int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags) {
- DnsResourceRecord *rr;
- DnsAnswerFlags rr_flags;
- int r;
-
- assert(key);
-
- /* For a {C,D}NAME record we can never find a matching {C,D}NAME record */
- if (!dns_type_may_redirect(key->type))
- return 0;
-
- DNS_ANSWER_FOREACH_FLAGS(rr, rr_flags, a) {
- r = dns_resource_key_match_cname_or_dname(key, rr->key, NULL);
- if (r < 0)
- return r;
- if (r > 0) {
- if (ret)
- *ret = rr;
- if (flags)
- *flags = rr_flags;
- return 1;
- }
- }
-
- return 0;
-}
-
-int dns_answer_merge(DnsAnswer *a, DnsAnswer *b, DnsAnswer **ret) {
- _cleanup_(dns_answer_unrefp) DnsAnswer *k = NULL;
- int r;
-
- assert(ret);
-
- if (dns_answer_size(a) <= 0) {
- *ret = dns_answer_ref(b);
- return 0;
- }
-
- if (dns_answer_size(b) <= 0) {
- *ret = dns_answer_ref(a);
- return 0;
- }
-
- k = dns_answer_new(a->n_rrs + b->n_rrs);
- if (!k)
- return -ENOMEM;
-
- r = dns_answer_add_raw_all(k, a);
- if (r < 0)
- return r;
-
- r = dns_answer_add_all(k, b);
- if (r < 0)
- return r;
-
- *ret = k;
- k = NULL;
-
- return 0;
-}
-
-int dns_answer_extend(DnsAnswer **a, DnsAnswer *b) {
- DnsAnswer *merged;
- int r;
-
- assert(a);
-
- r = dns_answer_merge(*a, b, &merged);
- if (r < 0)
- return r;
-
- dns_answer_unref(*a);
- *a = merged;
-
- return 0;
-}
-
-int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key) {
- bool found = false, other = false;
- DnsResourceRecord *rr;
- unsigned i;
- int r;
-
- assert(a);
- assert(key);
-
- /* Remove all entries matching the specified key from *a */
-
- DNS_ANSWER_FOREACH(rr, *a) {
- r = dns_resource_key_equal(rr->key, key);
- if (r < 0)
- return r;
- if (r > 0)
- found = true;
- else
- other = true;
-
- if (found && other)
- break;
- }
-
- if (!found)
- return 0;
-
- if (!other) {
- *a = dns_answer_unref(*a); /* Return NULL for the empty answer */
- return 1;
- }
-
- if ((*a)->n_ref > 1) {
- _cleanup_(dns_answer_unrefp) DnsAnswer *copy = NULL;
- DnsAnswerFlags flags;
- int ifindex;
-
- copy = dns_answer_new((*a)->n_rrs);
- if (!copy)
- return -ENOMEM;
-
- DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, *a) {
- r = dns_resource_key_equal(rr->key, key);
- if (r < 0)
- return r;
- if (r > 0)
- continue;
-
- r = dns_answer_add_raw(copy, rr, ifindex, flags);
- if (r < 0)
- return r;
- }
-
- dns_answer_unref(*a);
- *a = copy;
- copy = NULL;
-
- return 1;
- }
-
- /* Only a single reference, edit in-place */
-
- i = 0;
- for (;;) {
- if (i >= (*a)->n_rrs)
- break;
-
- r = dns_resource_key_equal((*a)->items[i].rr->key, key);
- if (r < 0)
- return r;
- if (r > 0) {
- /* Kill this entry */
-
- dns_resource_record_unref((*a)->items[i].rr);
- memmove((*a)->items + i, (*a)->items + i + 1, sizeof(DnsAnswerItem) * ((*a)->n_rrs - i - 1));
- (*a)->n_rrs--;
- continue;
-
- } else
- /* Keep this entry */
- i++;
- }
-
- return 1;
-}
-
-int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rm) {
- bool found = false, other = false;
- DnsResourceRecord *rr;
- unsigned i;
- int r;
-
- assert(a);
- assert(rm);
-
- /* Remove all entries matching the specified RR from *a */
-
- DNS_ANSWER_FOREACH(rr, *a) {
- r = dns_resource_record_equal(rr, rm);
- if (r < 0)
- return r;
- if (r > 0)
- found = true;
- else
- other = true;
-
- if (found && other)
- break;
- }
-
- if (!found)
- return 0;
-
- if (!other) {
- *a = dns_answer_unref(*a); /* Return NULL for the empty answer */
- return 1;
- }
-
- if ((*a)->n_ref > 1) {
- _cleanup_(dns_answer_unrefp) DnsAnswer *copy = NULL;
- DnsAnswerFlags flags;
- int ifindex;
-
- copy = dns_answer_new((*a)->n_rrs);
- if (!copy)
- return -ENOMEM;
-
- DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, *a) {
- r = dns_resource_record_equal(rr, rm);
- if (r < 0)
- return r;
- if (r > 0)
- continue;
-
- r = dns_answer_add_raw(copy, rr, ifindex, flags);
- if (r < 0)
- return r;
- }
-
- dns_answer_unref(*a);
- *a = copy;
- copy = NULL;
-
- return 1;
- }
-
- /* Only a single reference, edit in-place */
-
- i = 0;
- for (;;) {
- if (i >= (*a)->n_rrs)
- break;
-
- r = dns_resource_record_equal((*a)->items[i].rr, rm);
- if (r < 0)
- return r;
- if (r > 0) {
- /* Kill this entry */
-
- dns_resource_record_unref((*a)->items[i].rr);
- memmove((*a)->items + i, (*a)->items + i + 1, sizeof(DnsAnswerItem) * ((*a)->n_rrs - i - 1));
- (*a)->n_rrs--;
- continue;
-
- } else
- /* Keep this entry */
- i++;
- }
-
- return 1;
-}
-
-int dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKey *key, DnsAnswerFlags or_flags) {
- DnsResourceRecord *rr_source;
- int ifindex_source, r;
- DnsAnswerFlags flags_source;
-
- assert(a);
- assert(key);
-
- /* Copy all RRs matching the specified key from source into *a */
-
- DNS_ANSWER_FOREACH_FULL(rr_source, ifindex_source, flags_source, source) {
-
- r = dns_resource_key_equal(rr_source->key, key);
- if (r < 0)
- return r;
- if (r == 0)
- continue;
-
- /* Make space for at least one entry */
- r = dns_answer_reserve_or_clone(a, 1);
- if (r < 0)
- return r;
-
- r = dns_answer_add(*a, rr_source, ifindex_source, flags_source|or_flags);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-int dns_answer_move_by_key(DnsAnswer **to, DnsAnswer **from, const DnsResourceKey *key, DnsAnswerFlags or_flags) {
- int r;
-
- assert(to);
- assert(from);
- assert(key);
-
- r = dns_answer_copy_by_key(to, *from, key, or_flags);
- if (r < 0)
- return r;
-
- return dns_answer_remove_by_key(from, key);
-}
-
-void dns_answer_order_by_scope(DnsAnswer *a, bool prefer_link_local) {
- DnsAnswerItem *items;
- unsigned i, start, end;
-
- if (!a)
- return;
-
- if (a->n_rrs <= 1)
- return;
-
- start = 0;
- end = a->n_rrs-1;
-
- /* RFC 4795, Section 2.6 suggests we should order entries
- * depending on whether the sender is a link-local address. */
-
- items = newa(DnsAnswerItem, a->n_rrs);
- for (i = 0; i < a->n_rrs; i++) {
-
- if (a->items[i].rr->key->class == DNS_CLASS_IN &&
- ((a->items[i].rr->key->type == DNS_TYPE_A && in_addr_is_link_local(AF_INET, (union in_addr_union*) &a->items[i].rr->a.in_addr) != prefer_link_local) ||
- (a->items[i].rr->key->type == DNS_TYPE_AAAA && in_addr_is_link_local(AF_INET6, (union in_addr_union*) &a->items[i].rr->aaaa.in6_addr) != prefer_link_local)))
- /* Order address records that are are not preferred to the end of the array */
- items[end--] = a->items[i];
- else
- /* Order all other records to the beginning of the array */
- items[start++] = a->items[i];
- }
-
- assert(start == end+1);
- memcpy(a->items, items, sizeof(DnsAnswerItem) * a->n_rrs);
-}
-
-int dns_answer_reserve(DnsAnswer **a, unsigned n_free) {
- DnsAnswer *n;
-
- assert(a);
-
- if (n_free <= 0)
- return 0;
-
- if (*a) {
- unsigned ns;
-
- if ((*a)->n_ref > 1)
- return -EBUSY;
-
- ns = (*a)->n_rrs + n_free;
-
- if ((*a)->n_allocated >= ns)
- return 0;
-
- /* Allocate more than we need */
- ns *= 2;
-
- n = realloc(*a, offsetof(DnsAnswer, items) + sizeof(DnsAnswerItem) * ns);
- if (!n)
- return -ENOMEM;
-
- n->n_allocated = ns;
- } else {
- n = dns_answer_new(n_free);
- if (!n)
- return -ENOMEM;
- }
-
- *a = n;
- return 0;
-}
-
-int dns_answer_reserve_or_clone(DnsAnswer **a, unsigned n_free) {
- _cleanup_(dns_answer_unrefp) DnsAnswer *n = NULL;
- int r;
-
- assert(a);
-
- /* Tries to extend the DnsAnswer object. And if that's not
- * possible, since we are not the sole owner, then allocate a
- * new, appropriately sized one. Either way, after this call
- * the object will only have a single reference, and has room
- * for at least the specified number of RRs. */
-
- r = dns_answer_reserve(a, n_free);
- if (r != -EBUSY)
- return r;
-
- assert(*a);
-
- n = dns_answer_new(((*a)->n_rrs + n_free) * 2);
- if (!n)
- return -ENOMEM;
-
- r = dns_answer_add_raw_all(n, *a);
- if (r < 0)
- return r;
-
- dns_answer_unref(*a);
- *a = n;
- n = NULL;
-
- return 0;
-}
-
-void dns_answer_dump(DnsAnswer *answer, FILE *f) {
- DnsResourceRecord *rr;
- DnsAnswerFlags flags;
- int ifindex;
-
- if (!f)
- f = stdout;
-
- DNS_ANSWER_FOREACH_FULL(rr, ifindex, flags, answer) {
- const char *t;
-
- fputc('\t', f);
-
- t = dns_resource_record_to_string(rr);
- if (!t) {
- log_oom();
- continue;
- }
-
- fputs(t, f);
-
- if (ifindex != 0 || flags & (DNS_ANSWER_AUTHENTICATED|DNS_ANSWER_CACHEABLE|DNS_ANSWER_SHARED_OWNER))
- fputs("\t;", f);
-
- if (ifindex != 0)
- printf(" ifindex=%i", ifindex);
- if (flags & DNS_ANSWER_AUTHENTICATED)
- fputs(" authenticated", f);
- if (flags & DNS_ANSWER_CACHEABLE)
- fputs(" cachable", f);
- if (flags & DNS_ANSWER_SHARED_OWNER)
- fputs(" shared-owner", f);
-
- fputc('\n', f);
- }
-}
-
-bool dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname) {
- DnsResourceRecord *rr;
- int r;
-
- assert(cname);
-
- /* Checks whether the answer contains a DNAME record that indicates that the specified CNAME record is
- * synthesized from it */
-
- if (cname->key->type != DNS_TYPE_CNAME)
- return 0;
-
- DNS_ANSWER_FOREACH(rr, a) {
- _cleanup_free_ char *n = NULL;
-
- if (rr->key->type != DNS_TYPE_DNAME)
- continue;
- if (rr->key->class != cname->key->class)
- continue;
-
- r = dns_name_change_suffix(cname->cname.name, rr->dname.name, dns_resource_key_name(rr->key), &n);
- if (r < 0)
- return r;
- if (r == 0)
- continue;
-
- r = dns_name_equal(n, dns_resource_key_name(cname->key));
- if (r < 0)
- return r;
- if (r > 0)
- return 1;
-
- }
-
- return 0;
-}
diff --git a/src/grp-resolve/systemd-resolved/resolved-dns-answer.h b/src/grp-resolve/systemd-resolved/resolved-dns-answer.h
deleted file mode 100644
index 92557a410a..0000000000
--- a/src/grp-resolve/systemd-resolved/resolved-dns-answer.h
+++ /dev/null
@@ -1,144 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "basic/macro.h"
-
-typedef struct DnsAnswer DnsAnswer;
-typedef struct DnsAnswerItem DnsAnswerItem;
-
-#include "resolved-dns-rr.h"
-
-/* A simple array of resource records. We keep track of the
- * originating ifindex for each RR where that makes sense, so that we
- * can qualify A and AAAA RRs referring to a local link with the
- * right ifindex.
- *
- * Note that we usually encode the empty DnsAnswer object as a simple NULL. */
-
-typedef enum DnsAnswerFlags {
- DNS_ANSWER_AUTHENTICATED = 1, /* Item has been authenticated */
- DNS_ANSWER_CACHEABLE = 2, /* Item is subject to caching */
- DNS_ANSWER_SHARED_OWNER = 4, /* For mDNS: RRset may be owner by multiple peers */
-} DnsAnswerFlags;
-
-struct DnsAnswerItem {
- DnsResourceRecord *rr;
- int ifindex;
- DnsAnswerFlags flags;
-};
-
-struct DnsAnswer {
- unsigned n_ref;
- unsigned n_rrs, n_allocated;
- DnsAnswerItem items[0];
-};
-
-DnsAnswer *dns_answer_new(unsigned n);
-DnsAnswer *dns_answer_ref(DnsAnswer *a);
-DnsAnswer *dns_answer_unref(DnsAnswer *a);
-
-int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags);
-int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags);
-int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl);
-
-int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *combined_flags);
-int dns_answer_contains_rr(DnsAnswer *a, DnsResourceRecord *rr, DnsAnswerFlags *combined_flags);
-int dns_answer_contains_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *combined_flags);
-int dns_answer_contains_nsec_or_nsec3(DnsAnswer *a);
-int dns_answer_contains_zone_nsec3(DnsAnswer *answer, const char *zone);
-
-int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags);
-int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *flags);
-
-int dns_answer_merge(DnsAnswer *a, DnsAnswer *b, DnsAnswer **ret);
-int dns_answer_extend(DnsAnswer **a, DnsAnswer *b);
-
-void dns_answer_order_by_scope(DnsAnswer *a, bool prefer_link_local);
-
-int dns_answer_reserve(DnsAnswer **a, unsigned n_free);
-int dns_answer_reserve_or_clone(DnsAnswer **a, unsigned n_free);
-
-int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key);
-int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rr);
-
-int dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKey *key, DnsAnswerFlags or_flags);
-int dns_answer_move_by_key(DnsAnswer **to, DnsAnswer **from, const DnsResourceKey *key, DnsAnswerFlags or_flags);
-
-bool dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname);
-
-static inline unsigned dns_answer_size(DnsAnswer *a) {
- return a ? a->n_rrs : 0;
-}
-
-void dns_answer_dump(DnsAnswer *answer, FILE *f);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(DnsAnswer*, dns_answer_unref);
-
-#define _DNS_ANSWER_FOREACH(q, kk, a) \
- for (unsigned UNIQ_T(i, q) = ({ \
- (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \
- 0; \
- }); \
- (a) && (UNIQ_T(i, q) < (a)->n_rrs); \
- UNIQ_T(i, q)++, (kk) = (UNIQ_T(i, q) < (a)->n_rrs ? (a)->items[UNIQ_T(i, q)].rr : NULL))
-
-#define DNS_ANSWER_FOREACH(kk, a) _DNS_ANSWER_FOREACH(UNIQ, kk, a)
-
-#define _DNS_ANSWER_FOREACH_IFINDEX(q, kk, ifi, a) \
- for (unsigned UNIQ_T(i, q) = ({ \
- (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \
- (ifi) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].ifindex : 0; \
- 0; \
- }); \
- (a) && (UNIQ_T(i, q) < (a)->n_rrs); \
- UNIQ_T(i, q)++, \
- (kk) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].rr : NULL), \
- (ifi) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].ifindex : 0))
-
-#define DNS_ANSWER_FOREACH_IFINDEX(kk, ifindex, a) _DNS_ANSWER_FOREACH_IFINDEX(UNIQ, kk, ifindex, a)
-
-#define _DNS_ANSWER_FOREACH_FLAGS(q, kk, fl, a) \
- for (unsigned UNIQ_T(i, q) = ({ \
- (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \
- (fl) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].flags : 0; \
- 0; \
- }); \
- (a) && (UNIQ_T(i, q) < (a)->n_rrs); \
- UNIQ_T(i, q)++, \
- (kk) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].rr : NULL), \
- (fl) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].flags : 0))
-
-#define DNS_ANSWER_FOREACH_FLAGS(kk, flags, a) _DNS_ANSWER_FOREACH_FLAGS(UNIQ, kk, flags, a)
-
-#define _DNS_ANSWER_FOREACH_FULL(q, kk, ifi, fl, a) \
- for (unsigned UNIQ_T(i, q) = ({ \
- (kk) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].rr : NULL; \
- (ifi) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].ifindex : 0; \
- (fl) = ((a) && (a)->n_rrs > 0) ? (a)->items[0].flags : 0; \
- 0; \
- }); \
- (a) && (UNIQ_T(i, q) < (a)->n_rrs); \
- UNIQ_T(i, q)++, \
- (kk) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].rr : NULL), \
- (ifi) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].ifindex : 0), \
- (fl) = ((UNIQ_T(i, q) < (a)->n_rrs) ? (a)->items[UNIQ_T(i, q)].flags : 0))
-
-#define DNS_ANSWER_FOREACH_FULL(kk, ifindex, flags, a) _DNS_ANSWER_FOREACH_FULL(UNIQ, kk, ifindex, flags, a)
diff --git a/src/grp-resolve/systemd-resolved/resolved-dns-dnssec.c b/src/grp-resolve/systemd-resolved/resolved-dns-dnssec.c
deleted file mode 100644
index 39afbada25..0000000000
--- a/src/grp-resolve/systemd-resolved/resolved-dns-dnssec.c
+++ /dev/null
@@ -1,2199 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#ifdef HAVE_GCRYPT
-#include <gcrypt.h>
-#endif
-
-#include "basic/alloc-util.h"
-#include "shared/dns-domain.h"
-#include "shared/gcrypt-util.h"
-#include "basic/hexdecoct.h"
-#include "resolved-dns-dnssec.h"
-#include "resolved-dns-packet.h"
-#include "basic/string-table.h"
-
-#define VERIFY_RRS_MAX 256
-#define MAX_KEY_SIZE (32*1024)
-
-/* Permit a maximum clock skew of 1h 10min. This should be enough to deal with DST confusion */
-#define SKEW_MAX (1*USEC_PER_HOUR + 10*USEC_PER_MINUTE)
-
-/* Maximum number of NSEC3 iterations we'll do. RFC5155 says 2500 shall be the maximum useful value */
-#define NSEC3_ITERATIONS_MAX 2500
-
-/*
- * The DNSSEC Chain of trust:
- *
- * Normal RRs are protected via RRSIG RRs in combination with DNSKEY RRs, all in the same zone
- * DNSKEY RRs are either protected like normal RRs, or via a DS from a zone "higher" up the tree
- * DS RRs are protected like normal RRs
- *
- * Example chain:
- * Normal RR → RRSIG/DNSKEY+ → DS → RRSIG/DNSKEY+ → DS → ... → DS → RRSIG/DNSKEY+ → DS
- */
-
-uint16_t dnssec_keytag(DnsResourceRecord *dnskey, bool mask_revoke) {
- const uint8_t *p;
- uint32_t sum, f;
- size_t i;
-
- /* The algorithm from RFC 4034, Appendix B. */
-
- assert(dnskey);
- assert(dnskey->key->type == DNS_TYPE_DNSKEY);
-
- f = (uint32_t) dnskey->dnskey.flags;
-
- if (mask_revoke)
- f &= ~DNSKEY_FLAG_REVOKE;
-
- sum = f + ((((uint32_t) dnskey->dnskey.protocol) << 8) + (uint32_t) dnskey->dnskey.algorithm);
-
- p = dnskey->dnskey.key;
-
- for (i = 0; i < dnskey->dnskey.key_size; i++)
- sum += (i & 1) == 0 ? (uint32_t) p[i] << 8 : (uint32_t) p[i];
-
- sum += (sum >> 16) & UINT32_C(0xFFFF);
-
- return sum & UINT32_C(0xFFFF);
-}
-
-int dnssec_canonicalize(const char *n, char *buffer, size_t buffer_max) {
- size_t c = 0;
- int r;
-
- /* Converts the specified hostname into DNSSEC canonicalized
- * form. */
-
- if (buffer_max < 2)
- return -ENOBUFS;
-
- for (;;) {
- r = dns_label_unescape(&n, buffer, buffer_max);
- if (r < 0)
- return r;
- if (r == 0)
- break;
-
- if (buffer_max < (size_t) r + 2)
- return -ENOBUFS;
-
- /* The DNSSEC canonical form is not clear on what to
- * do with dots appearing in labels, the way DNS-SD
- * does it. Refuse it for now. */
-
- if (memchr(buffer, '.', r))
- return -EINVAL;
-
- ascii_strlower_n(buffer, (size_t) r);
- buffer[r] = '.';
-
- buffer += r + 1;
- c += r + 1;
-
- buffer_max -= r + 1;
- }
-
- if (c <= 0) {
- /* Not even a single label: this is the root domain name */
-
- assert(buffer_max > 2);
- buffer[0] = '.';
- buffer[1] = 0;
-
- return 1;
- }
-
- return (int) c;
-}
-
-#ifdef HAVE_GCRYPT
-
-static int rr_compare(const void *a, const void *b) {
- DnsResourceRecord **x = (DnsResourceRecord**) a, **y = (DnsResourceRecord**) b;
- size_t m;
- int r;
-
- /* Let's order the RRs according to RFC 4034, Section 6.3 */
-
- assert(x);
- assert(*x);
- assert((*x)->wire_format);
- assert(y);
- assert(*y);
- assert((*y)->wire_format);
-
- m = MIN(DNS_RESOURCE_RECORD_RDATA_SIZE(*x), DNS_RESOURCE_RECORD_RDATA_SIZE(*y));
-
- r = memcmp(DNS_RESOURCE_RECORD_RDATA(*x), DNS_RESOURCE_RECORD_RDATA(*y), m);
- if (r != 0)
- return r;
-
- if (DNS_RESOURCE_RECORD_RDATA_SIZE(*x) < DNS_RESOURCE_RECORD_RDATA_SIZE(*y))
- return -1;
- else if (DNS_RESOURCE_RECORD_RDATA_SIZE(*x) > DNS_RESOURCE_RECORD_RDATA_SIZE(*y))
- return 1;
-
- return 0;
-}
-
-static int dnssec_rsa_verify_raw(
- const char *hash_algorithm,
- const void *signature, size_t signature_size,
- const void *data, size_t data_size,
- const void *exponent, size_t exponent_size,
- const void *modulus, size_t modulus_size) {
-
- gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL;
- gcry_mpi_t n = NULL, e = NULL, s = NULL;
- gcry_error_t ge;
- int r;
-
- assert(hash_algorithm);
-
- ge = gcry_mpi_scan(&s, GCRYMPI_FMT_USG, signature, signature_size, NULL);
- if (ge != 0) {
- r = -EIO;
- goto finish;
- }
-
- ge = gcry_mpi_scan(&e, GCRYMPI_FMT_USG, exponent, exponent_size, NULL);
- if (ge != 0) {
- r = -EIO;
- goto finish;
- }
-
- ge = gcry_mpi_scan(&n, GCRYMPI_FMT_USG, modulus, modulus_size, NULL);
- if (ge != 0) {
- r = -EIO;
- goto finish;
- }
-
- ge = gcry_sexp_build(&signature_sexp,
- NULL,
- "(sig-val (rsa (s %m)))",
- s);
-
- if (ge != 0) {
- r = -EIO;
- goto finish;
- }
-
- ge = gcry_sexp_build(&data_sexp,
- NULL,
- "(data (flags pkcs1) (hash %s %b))",
- hash_algorithm,
- (int) data_size,
- data);
- if (ge != 0) {
- r = -EIO;
- goto finish;
- }
-
- ge = gcry_sexp_build(&public_key_sexp,
- NULL,
- "(public-key (rsa (n %m) (e %m)))",
- n,
- e);
- if (ge != 0) {
- r = -EIO;
- goto finish;
- }
-
- ge = gcry_pk_verify(signature_sexp, data_sexp, public_key_sexp);
- if (gpg_err_code(ge) == GPG_ERR_BAD_SIGNATURE)
- r = 0;
- else if (ge != 0) {
- log_debug("RSA signature check failed: %s", gpg_strerror(ge));
- r = -EIO;
- } else
- r = 1;
-
-finish:
- if (e)
- gcry_mpi_release(e);
- if (n)
- gcry_mpi_release(n);
- if (s)
- gcry_mpi_release(s);
-
- if (public_key_sexp)
- gcry_sexp_release(public_key_sexp);
- if (signature_sexp)
- gcry_sexp_release(signature_sexp);
- if (data_sexp)
- gcry_sexp_release(data_sexp);
-
- return r;
-}
-
-static int dnssec_rsa_verify(
- const char *hash_algorithm,
- const void *hash, size_t hash_size,
- DnsResourceRecord *rrsig,
- DnsResourceRecord *dnskey) {
-
- size_t exponent_size, modulus_size;
- void *exponent, *modulus;
-
- assert(hash_algorithm);
- assert(hash);
- assert(hash_size > 0);
- assert(rrsig);
- assert(dnskey);
-
- if (*(uint8_t*) dnskey->dnskey.key == 0) {
- /* exponent is > 255 bytes long */
-
- exponent = (uint8_t*) dnskey->dnskey.key + 3;
- exponent_size =
- ((size_t) (((uint8_t*) dnskey->dnskey.key)[1]) << 8) |
- ((size_t) ((uint8_t*) dnskey->dnskey.key)[2]);
-
- if (exponent_size < 256)
- return -EINVAL;
-
- if (3 + exponent_size >= dnskey->dnskey.key_size)
- return -EINVAL;
-
- modulus = (uint8_t*) dnskey->dnskey.key + 3 + exponent_size;
- modulus_size = dnskey->dnskey.key_size - 3 - exponent_size;
-
- } else {
- /* exponent is <= 255 bytes long */
-
- exponent = (uint8_t*) dnskey->dnskey.key + 1;
- exponent_size = (size_t) ((uint8_t*) dnskey->dnskey.key)[0];
-
- if (exponent_size <= 0)
- return -EINVAL;
-
- if (1 + exponent_size >= dnskey->dnskey.key_size)
- return -EINVAL;
-
- modulus = (uint8_t*) dnskey->dnskey.key + 1 + exponent_size;
- modulus_size = dnskey->dnskey.key_size - 1 - exponent_size;
- }
-
- return dnssec_rsa_verify_raw(
- hash_algorithm,
- rrsig->rrsig.signature, rrsig->rrsig.signature_size,
- hash, hash_size,
- exponent, exponent_size,
- modulus, modulus_size);
-}
-
-static int dnssec_ecdsa_verify_raw(
- const char *hash_algorithm,
- const char *curve,
- const void *signature_r, size_t signature_r_size,
- const void *signature_s, size_t signature_s_size,
- const void *data, size_t data_size,
- const void *key, size_t key_size) {
-
- gcry_sexp_t public_key_sexp = NULL, data_sexp = NULL, signature_sexp = NULL;
- gcry_mpi_t q = NULL, r = NULL, s = NULL;
- gcry_error_t ge;
- int k;
-
- assert(hash_algorithm);
-
- ge = gcry_mpi_scan(&r, GCRYMPI_FMT_USG, signature_r, signature_r_size, NULL);
- if (ge != 0) {
- k = -EIO;
- goto finish;
- }
-
- ge = gcry_mpi_scan(&s, GCRYMPI_FMT_USG, signature_s, signature_s_size, NULL);
- if (ge != 0) {
- k = -EIO;
- goto finish;
- }
-
- ge = gcry_mpi_scan(&q, GCRYMPI_FMT_USG, key, key_size, NULL);
- if (ge != 0) {
- k = -EIO;
- goto finish;
- }
-
- ge = gcry_sexp_build(&signature_sexp,
- NULL,
- "(sig-val (ecdsa (r %m) (s %m)))",
- r,
- s);
- if (ge != 0) {
- k = -EIO;
- goto finish;
- }
-
- ge = gcry_sexp_build(&data_sexp,
- NULL,
- "(data (flags rfc6979) (hash %s %b))",
- hash_algorithm,
- (int) data_size,
- data);
- if (ge != 0) {
- k = -EIO;
- goto finish;
- }
-
- ge = gcry_sexp_build(&public_key_sexp,
- NULL,
- "(public-key (ecc (curve %s) (q %m)))",
- curve,
- q);
- if (ge != 0) {
- k = -EIO;
- goto finish;
- }
-
- ge = gcry_pk_verify(signature_sexp, data_sexp, public_key_sexp);
- if (gpg_err_code(ge) == GPG_ERR_BAD_SIGNATURE)
- k = 0;
- else if (ge != 0) {
- log_debug("ECDSA signature check failed: %s", gpg_strerror(ge));
- k = -EIO;
- } else
- k = 1;
-finish:
- if (r)
- gcry_mpi_release(r);
- if (s)
- gcry_mpi_release(s);
- if (q)
- gcry_mpi_release(q);
-
- if (public_key_sexp)
- gcry_sexp_release(public_key_sexp);
- if (signature_sexp)
- gcry_sexp_release(signature_sexp);
- if (data_sexp)
- gcry_sexp_release(data_sexp);
-
- return k;
-}
-
-static int dnssec_ecdsa_verify(
- const char *hash_algorithm,
- int algorithm,
- const void *hash, size_t hash_size,
- DnsResourceRecord *rrsig,
- DnsResourceRecord *dnskey) {
-
- const char *curve;
- size_t key_size;
- uint8_t *q;
-
- assert(hash);
- assert(hash_size);
- assert(rrsig);
- assert(dnskey);
-
- if (algorithm == DNSSEC_ALGORITHM_ECDSAP256SHA256) {
- key_size = 32;
- curve = "NIST P-256";
- } else if (algorithm == DNSSEC_ALGORITHM_ECDSAP384SHA384) {
- key_size = 48;
- curve = "NIST P-384";
- } else
- return -EOPNOTSUPP;
-
- if (dnskey->dnskey.key_size != key_size * 2)
- return -EINVAL;
-
- if (rrsig->rrsig.signature_size != key_size * 2)
- return -EINVAL;
-
- q = alloca(key_size*2 + 1);
- q[0] = 0x04; /* Prepend 0x04 to indicate an uncompressed key */
- memcpy(q+1, dnskey->dnskey.key, key_size*2);
-
- return dnssec_ecdsa_verify_raw(
- hash_algorithm,
- curve,
- rrsig->rrsig.signature, key_size,
- (uint8_t*) rrsig->rrsig.signature + key_size, key_size,
- hash, hash_size,
- q, key_size*2+1);
-}
-
-static void md_add_uint8(gcry_md_hd_t md, uint8_t v) {
- gcry_md_write(md, &v, sizeof(v));
-}
-
-static void md_add_uint16(gcry_md_hd_t md, uint16_t v) {
- v = htobe16(v);
- gcry_md_write(md, &v, sizeof(v));
-}
-
-static void md_add_uint32(gcry_md_hd_t md, uint32_t v) {
- v = htobe32(v);
- gcry_md_write(md, &v, sizeof(v));
-}
-
-static int dnssec_rrsig_prepare(DnsResourceRecord *rrsig) {
- int n_key_labels, n_signer_labels;
- const char *name;
- int r;
-
- /* Checks whether the specified RRSIG RR is somewhat valid, and initializes the .n_skip_labels_source and
- * .n_skip_labels_signer fields so that we can use them later on. */
-
- assert(rrsig);
- assert(rrsig->key->type == DNS_TYPE_RRSIG);
-
- /* Check if this RRSIG RR is already prepared */
- if (rrsig->n_skip_labels_source != (unsigned) -1)
- return 0;
-
- if (rrsig->rrsig.inception > rrsig->rrsig.expiration)
- return -EINVAL;
-
- name = dns_resource_key_name(rrsig->key);
-
- n_key_labels = dns_name_count_labels(name);
- if (n_key_labels < 0)
- return n_key_labels;
- if (rrsig->rrsig.labels > n_key_labels)
- return -EINVAL;
-
- n_signer_labels = dns_name_count_labels(rrsig->rrsig.signer);
- if (n_signer_labels < 0)
- return n_signer_labels;
- if (n_signer_labels > rrsig->rrsig.labels)
- return -EINVAL;
-
- r = dns_name_skip(name, n_key_labels - n_signer_labels, &name);
- if (r < 0)
- return r;
- if (r == 0)
- return -EINVAL;
-
- /* Check if the signer is really a suffix of us */
- r = dns_name_equal(name, rrsig->rrsig.signer);
- if (r < 0)
- return r;
- if (r == 0)
- return -EINVAL;
-
- rrsig->n_skip_labels_source = n_key_labels - rrsig->rrsig.labels;
- rrsig->n_skip_labels_signer = n_key_labels - n_signer_labels;
-
- return 0;
-}
-
-static int dnssec_rrsig_expired(DnsResourceRecord *rrsig, usec_t realtime) {
- usec_t expiration, inception, skew;
-
- assert(rrsig);
- assert(rrsig->key->type == DNS_TYPE_RRSIG);
-
- if (realtime == USEC_INFINITY)
- realtime = now(CLOCK_REALTIME);
-
- expiration = rrsig->rrsig.expiration * USEC_PER_SEC;
- inception = rrsig->rrsig.inception * USEC_PER_SEC;
-
- /* Consider inverted validity intervals as expired */
- if (inception > expiration)
- return true;
-
- /* Permit a certain amount of clock skew of 10% of the valid
- * time range. This takes inspiration from unbound's
- * resolver. */
- skew = (expiration - inception) / 10;
- if (skew > SKEW_MAX)
- skew = SKEW_MAX;
-
- if (inception < skew)
- inception = 0;
- else
- inception -= skew;
-
- if (expiration + skew < expiration)
- expiration = USEC_INFINITY;
- else
- expiration += skew;
-
- return realtime < inception || realtime > expiration;
-}
-
-static int algorithm_to_gcrypt_md(uint8_t algorithm) {
-
- /* Translates a DNSSEC signature algorithm into a gcrypt
- * digest identifier.
- *
- * Note that we implement all algorithms listed as "Must
- * implement" and "Recommended to Implement" in RFC6944. We
- * don't implement any algorithms that are listed as
- * "Optional" or "Must Not Implement". Specifically, we do not
- * implement RSAMD5, DSASHA1, DH, DSA-NSEC3-SHA1, and
- * GOST-ECC. */
-
- switch (algorithm) {
-
- case DNSSEC_ALGORITHM_RSASHA1:
- case DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1:
- return GCRY_MD_SHA1;
-
- case DNSSEC_ALGORITHM_RSASHA256:
- case DNSSEC_ALGORITHM_ECDSAP256SHA256:
- return GCRY_MD_SHA256;
-
- case DNSSEC_ALGORITHM_ECDSAP384SHA384:
- return GCRY_MD_SHA384;
-
- case DNSSEC_ALGORITHM_RSASHA512:
- return GCRY_MD_SHA512;
-
- default:
- return -EOPNOTSUPP;
- }
-}
-
-static void dnssec_fix_rrset_ttl(
- DnsResourceRecord *list[],
- unsigned n,
- DnsResourceRecord *rrsig,
- usec_t realtime) {
-
- unsigned k;
-
- assert(list);
- assert(n > 0);
- assert(rrsig);
-
- for (k = 0; k < n; k++) {
- DnsResourceRecord *rr = list[k];
-
- /* Pick the TTL as the minimum of the RR's TTL, the
- * RR's original TTL according to the RRSIG and the
- * RRSIG's own TTL, see RFC 4035, Section 5.3.3 */
- rr->ttl = MIN3(rr->ttl, rrsig->rrsig.original_ttl, rrsig->ttl);
- rr->expiry = rrsig->rrsig.expiration * USEC_PER_SEC;
-
- /* Copy over information about the signer and wildcard source of synthesis */
- rr->n_skip_labels_source = rrsig->n_skip_labels_source;
- rr->n_skip_labels_signer = rrsig->n_skip_labels_signer;
- }
-
- rrsig->expiry = rrsig->rrsig.expiration * USEC_PER_SEC;
-}
-
-int dnssec_verify_rrset(
- DnsAnswer *a,
- const DnsResourceKey *key,
- DnsResourceRecord *rrsig,
- DnsResourceRecord *dnskey,
- usec_t realtime,
- DnssecResult *result) {
-
- uint8_t wire_format_name[DNS_WIRE_FOMAT_HOSTNAME_MAX];
- DnsResourceRecord **list, *rr;
- const char *source, *name;
- gcry_md_hd_t md = NULL;
- int r, md_algorithm;
- size_t k, n = 0;
- size_t hash_size;
- void *hash;
- bool wildcard;
-
- assert(key);
- assert(rrsig);
- assert(dnskey);
- assert(result);
- assert(rrsig->key->type == DNS_TYPE_RRSIG);
- assert(dnskey->key->type == DNS_TYPE_DNSKEY);
-
- /* Verifies that the RRSet matches the specified "key" in "a",
- * using the signature "rrsig" and the key "dnskey". It's
- * assumed that RRSIG and DNSKEY match. */
-
- md_algorithm = algorithm_to_gcrypt_md(rrsig->rrsig.algorithm);
- if (md_algorithm == -EOPNOTSUPP) {
- *result = DNSSEC_UNSUPPORTED_ALGORITHM;
- return 0;
- }
- if (md_algorithm < 0)
- return md_algorithm;
-
- r = dnssec_rrsig_prepare(rrsig);
- if (r == -EINVAL) {
- *result = DNSSEC_INVALID;
- return r;
- }
- if (r < 0)
- return r;
-
- r = dnssec_rrsig_expired(rrsig, realtime);
- if (r < 0)
- return r;
- if (r > 0) {
- *result = DNSSEC_SIGNATURE_EXPIRED;
- return 0;
- }
-
- name = dns_resource_key_name(key);
-
- /* Some keys may only appear signed in the zone apex, and are invalid anywhere else. (SOA, NS...) */
- if (dns_type_apex_only(rrsig->rrsig.type_covered)) {
- r = dns_name_equal(rrsig->rrsig.signer, name);
- if (r < 0)
- return r;
- if (r == 0) {
- *result = DNSSEC_INVALID;
- return 0;
- }
- }
-
- /* OTOH DS RRs may not appear in the zone apex, but are valid everywhere else. */
- if (rrsig->rrsig.type_covered == DNS_TYPE_DS) {
- r = dns_name_equal(rrsig->rrsig.signer, name);
- if (r < 0)
- return r;
- if (r > 0) {
- *result = DNSSEC_INVALID;
- return 0;
- }
- }
-
- /* Determine the "Source of Synthesis" and whether this is a wildcard RRSIG */
- r = dns_name_suffix(name, rrsig->rrsig.labels, &source);
- if (r < 0)
- return r;
- if (r > 0 && !dns_type_may_wildcard(rrsig->rrsig.type_covered)) {
- /* We refuse to validate NSEC3 or SOA RRs that are synthesized from wildcards */
- *result = DNSSEC_INVALID;
- return 0;
- }
- if (r == 1) {
- /* If we stripped a single label, then let's see if that maybe was "*". If so, we are not really
- * synthesized from a wildcard, we are the wildcard itself. Treat that like a normal name. */
- r = dns_name_startswith(name, "*");
- if (r < 0)
- return r;
- if (r > 0)
- source = name;
-
- wildcard = r == 0;
- } else
- wildcard = r > 0;
-
- /* Collect all relevant RRs in a single array, so that we can look at the RRset */
- list = newa(DnsResourceRecord *, dns_answer_size(a));
-
- DNS_ANSWER_FOREACH(rr, a) {
- r = dns_resource_key_equal(key, rr->key);
- if (r < 0)
- return r;
- if (r == 0)
- continue;
-
- /* We need the wire format for ordering, and digest calculation */
- r = dns_resource_record_to_wire_format(rr, true);
- if (r < 0)
- return r;
-
- list[n++] = rr;
-
- if (n > VERIFY_RRS_MAX)
- return -E2BIG;
- }
-
- if (n <= 0)
- return -ENODATA;
-
- /* Bring the RRs into canonical order */
- qsort_safe(list, n, sizeof(DnsResourceRecord*), rr_compare);
-
- /* OK, the RRs are now in canonical order. Let's calculate the digest */
- initialize_libgcrypt(false);
-
- hash_size = gcry_md_get_algo_dlen(md_algorithm);
- assert(hash_size > 0);
-
- gcry_md_open(&md, md_algorithm, 0);
- if (!md)
- return -EIO;
-
- md_add_uint16(md, rrsig->rrsig.type_covered);
- md_add_uint8(md, rrsig->rrsig.algorithm);
- md_add_uint8(md, rrsig->rrsig.labels);
- md_add_uint32(md, rrsig->rrsig.original_ttl);
- md_add_uint32(md, rrsig->rrsig.expiration);
- md_add_uint32(md, rrsig->rrsig.inception);
- md_add_uint16(md, rrsig->rrsig.key_tag);
-
- r = dns_name_to_wire_format(rrsig->rrsig.signer, wire_format_name, sizeof(wire_format_name), true);
- if (r < 0)
- goto finish;
- gcry_md_write(md, wire_format_name, r);
-
- /* Convert the source of synthesis into wire format */
- r = dns_name_to_wire_format(source, wire_format_name, sizeof(wire_format_name), true);
- if (r < 0)
- goto finish;
-
- for (k = 0; k < n; k++) {
- size_t l;
-
- rr = list[k];
-
- /* Hash the source of synthesis. If this is a wildcard, then prefix it with the *. label */
- if (wildcard)
- gcry_md_write(md, (uint8_t[]) { 1, '*'}, 2);
- gcry_md_write(md, wire_format_name, r);
-
- md_add_uint16(md, rr->key->type);
- md_add_uint16(md, rr->key->class);
- md_add_uint32(md, rrsig->rrsig.original_ttl);
-
- l = DNS_RESOURCE_RECORD_RDATA_SIZE(rr);
- assert(l <= 0xFFFF);
-
- md_add_uint16(md, (uint16_t) l);
- gcry_md_write(md, DNS_RESOURCE_RECORD_RDATA(rr), l);
- }
-
- hash = gcry_md_read(md, 0);
- if (!hash) {
- r = -EIO;
- goto finish;
- }
-
- switch (rrsig->rrsig.algorithm) {
-
- case DNSSEC_ALGORITHM_RSASHA1:
- case DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1:
- case DNSSEC_ALGORITHM_RSASHA256:
- case DNSSEC_ALGORITHM_RSASHA512:
- r = dnssec_rsa_verify(
- gcry_md_algo_name(md_algorithm),
- hash, hash_size,
- rrsig,
- dnskey);
- break;
-
- case DNSSEC_ALGORITHM_ECDSAP256SHA256:
- case DNSSEC_ALGORITHM_ECDSAP384SHA384:
- r = dnssec_ecdsa_verify(
- gcry_md_algo_name(md_algorithm),
- rrsig->rrsig.algorithm,
- hash, hash_size,
- rrsig,
- dnskey);
- break;
- }
-
- if (r < 0)
- goto finish;
-
- /* Now, fix the ttl, expiry, and remember the synthesizing source and the signer */
- if (r > 0)
- dnssec_fix_rrset_ttl(list, n, rrsig, realtime);
-
- if (r == 0)
- *result = DNSSEC_INVALID;
- else if (wildcard)
- *result = DNSSEC_VALIDATED_WILDCARD;
- else
- *result = DNSSEC_VALIDATED;
-
- r = 0;
-
-finish:
- gcry_md_close(md);
- return r;
-}
-
-int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok) {
-
- assert(rrsig);
- assert(dnskey);
-
- /* Checks if the specified DNSKEY RR matches the key used for
- * the signature in the specified RRSIG RR */
-
- if (rrsig->key->type != DNS_TYPE_RRSIG)
- return -EINVAL;
-
- if (dnskey->key->type != DNS_TYPE_DNSKEY)
- return 0;
- if (dnskey->key->class != rrsig->key->class)
- return 0;
- if ((dnskey->dnskey.flags & DNSKEY_FLAG_ZONE_KEY) == 0)
- return 0;
- if (!revoked_ok && (dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE))
- return 0;
- if (dnskey->dnskey.protocol != 3)
- return 0;
- if (dnskey->dnskey.algorithm != rrsig->rrsig.algorithm)
- return 0;
-
- if (dnssec_keytag(dnskey, false) != rrsig->rrsig.key_tag)
- return 0;
-
- return dns_name_equal(dns_resource_key_name(dnskey->key), rrsig->rrsig.signer);
-}
-
-int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig) {
- assert(key);
- assert(rrsig);
-
- /* Checks if the specified RRSIG RR protects the RRSet of the specified RR key. */
-
- if (rrsig->key->type != DNS_TYPE_RRSIG)
- return 0;
- if (rrsig->key->class != key->class)
- return 0;
- if (rrsig->rrsig.type_covered != key->type)
- return 0;
-
- return dns_name_equal(dns_resource_key_name(rrsig->key), dns_resource_key_name(key));
-}
-
-int dnssec_verify_rrset_search(
- DnsAnswer *a,
- const DnsResourceKey *key,
- DnsAnswer *validated_dnskeys,
- usec_t realtime,
- DnssecResult *result,
- DnsResourceRecord **ret_rrsig) {
-
- bool found_rrsig = false, found_invalid = false, found_expired_rrsig = false, found_unsupported_algorithm = false;
- DnsResourceRecord *rrsig;
- int r;
-
- assert(key);
- assert(result);
-
- /* Verifies all RRs from "a" that match the key "key" against DNSKEYs in "validated_dnskeys" */
-
- if (!a || a->n_rrs <= 0)
- return -ENODATA;
-
- /* Iterate through each RRSIG RR. */
- DNS_ANSWER_FOREACH(rrsig, a) {
- DnsResourceRecord *dnskey;
- DnsAnswerFlags flags;
-
- /* Is this an RRSIG RR that applies to RRs matching our key? */
- r = dnssec_key_match_rrsig(key, rrsig);
- if (r < 0)
- return r;
- if (r == 0)
- continue;
-
- found_rrsig = true;
-
- /* Look for a matching key */
- DNS_ANSWER_FOREACH_FLAGS(dnskey, flags, validated_dnskeys) {
- DnssecResult one_result;
-
- if ((flags & DNS_ANSWER_AUTHENTICATED) == 0)
- continue;
-
- /* Is this a DNSKEY RR that matches they key of our RRSIG? */
- r = dnssec_rrsig_match_dnskey(rrsig, dnskey, false);
- if (r < 0)
- return r;
- if (r == 0)
- continue;
-
- /* Take the time here, if it isn't set yet, so
- * that we do all validations with the same
- * time. */
- if (realtime == USEC_INFINITY)
- realtime = now(CLOCK_REALTIME);
-
- /* Yay, we found a matching RRSIG with a matching
- * DNSKEY, awesome. Now let's verify all entries of
- * the RRSet against the RRSIG and DNSKEY
- * combination. */
-
- r = dnssec_verify_rrset(a, key, rrsig, dnskey, realtime, &one_result);
- if (r < 0)
- return r;
-
- switch (one_result) {
-
- case DNSSEC_VALIDATED:
- case DNSSEC_VALIDATED_WILDCARD:
- /* Yay, the RR has been validated,
- * return immediately, but fix up the expiry */
- if (ret_rrsig)
- *ret_rrsig = rrsig;
-
- *result = one_result;
- return 0;
-
- case DNSSEC_INVALID:
- /* If the signature is invalid, let's try another
- key and/or signature. After all they
- key_tags and stuff are not unique, and
- might be shared by multiple keys. */
- found_invalid = true;
- continue;
-
- case DNSSEC_UNSUPPORTED_ALGORITHM:
- /* If the key algorithm is
- unsupported, try another
- RRSIG/DNSKEY pair, but remember we
- encountered this, so that we can
- return a proper error when we
- encounter nothing better. */
- found_unsupported_algorithm = true;
- continue;
-
- case DNSSEC_SIGNATURE_EXPIRED:
- /* If the signature is expired, try
- another one, but remember it, so
- that we can return this */
- found_expired_rrsig = true;
- continue;
-
- default:
- assert_not_reached("Unexpected DNSSEC validation result");
- }
- }
- }
-
- if (found_expired_rrsig)
- *result = DNSSEC_SIGNATURE_EXPIRED;
- else if (found_unsupported_algorithm)
- *result = DNSSEC_UNSUPPORTED_ALGORITHM;
- else if (found_invalid)
- *result = DNSSEC_INVALID;
- else if (found_rrsig)
- *result = DNSSEC_MISSING_KEY;
- else
- *result = DNSSEC_NO_SIGNATURE;
-
- if (ret_rrsig)
- *ret_rrsig = NULL;
-
- return 0;
-}
-
-int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key) {
- DnsResourceRecord *rr;
- int r;
-
- /* Checks whether there's at least one RRSIG in 'a' that proctects RRs of the specified key */
-
- DNS_ANSWER_FOREACH(rr, a) {
- r = dnssec_key_match_rrsig(key, rr);
- if (r < 0)
- return r;
- if (r > 0)
- return 1;
- }
-
- return 0;
-}
-
-static int digest_to_gcrypt_md(uint8_t algorithm) {
-
- /* Translates a DNSSEC digest algorithm into a gcrypt digest identifier */
-
- switch (algorithm) {
-
- case DNSSEC_DIGEST_SHA1:
- return GCRY_MD_SHA1;
-
- case DNSSEC_DIGEST_SHA256:
- return GCRY_MD_SHA256;
-
- case DNSSEC_DIGEST_SHA384:
- return GCRY_MD_SHA384;
-
- default:
- return -EOPNOTSUPP;
- }
-}
-
-int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, bool mask_revoke) {
- char owner_name[DNSSEC_CANONICAL_HOSTNAME_MAX];
- gcry_md_hd_t md = NULL;
- size_t hash_size;
- int md_algorithm, r;
- void *result;
-
- assert(dnskey);
- assert(ds);
-
- /* Implements DNSKEY verification by a DS, according to RFC 4035, section 5.2 */
-
- if (dnskey->key->type != DNS_TYPE_DNSKEY)
- return -EINVAL;
- if (ds->key->type != DNS_TYPE_DS)
- return -EINVAL;
- if ((dnskey->dnskey.flags & DNSKEY_FLAG_ZONE_KEY) == 0)
- return -EKEYREJECTED;
- if (!mask_revoke && (dnskey->dnskey.flags & DNSKEY_FLAG_REVOKE))
- return -EKEYREJECTED;
- if (dnskey->dnskey.protocol != 3)
- return -EKEYREJECTED;
-
- if (dnskey->dnskey.algorithm != ds->ds.algorithm)
- return 0;
- if (dnssec_keytag(dnskey, mask_revoke) != ds->ds.key_tag)
- return 0;
-
- initialize_libgcrypt(false);
-
- md_algorithm = digest_to_gcrypt_md(ds->ds.digest_type);
- if (md_algorithm < 0)
- return md_algorithm;
-
- hash_size = gcry_md_get_algo_dlen(md_algorithm);
- assert(hash_size > 0);
-
- if (ds->ds.digest_size != hash_size)
- return 0;
-
- r = dnssec_canonicalize(dns_resource_key_name(dnskey->key), owner_name, sizeof(owner_name));
- if (r < 0)
- return r;
-
- gcry_md_open(&md, md_algorithm, 0);
- if (!md)
- return -EIO;
-
- gcry_md_write(md, owner_name, r);
- if (mask_revoke)
- md_add_uint16(md, dnskey->dnskey.flags & ~DNSKEY_FLAG_REVOKE);
- else
- md_add_uint16(md, dnskey->dnskey.flags);
- md_add_uint8(md, dnskey->dnskey.protocol);
- md_add_uint8(md, dnskey->dnskey.algorithm);
- gcry_md_write(md, dnskey->dnskey.key, dnskey->dnskey.key_size);
-
- result = gcry_md_read(md, 0);
- if (!result) {
- r = -EIO;
- goto finish;
- }
-
- r = memcmp(result, ds->ds.digest, ds->ds.digest_size) != 0;
-
-finish:
- gcry_md_close(md);
- return r;
-}
-
-int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds) {
- DnsResourceRecord *ds;
- DnsAnswerFlags flags;
- int r;
-
- assert(dnskey);
-
- if (dnskey->key->type != DNS_TYPE_DNSKEY)
- return 0;
-
- DNS_ANSWER_FOREACH_FLAGS(ds, flags, validated_ds) {
-
- if ((flags & DNS_ANSWER_AUTHENTICATED) == 0)
- continue;
-
- if (ds->key->type != DNS_TYPE_DS)
- continue;
- if (ds->key->class != dnskey->key->class)
- continue;
-
- r = dns_name_equal(dns_resource_key_name(dnskey->key), dns_resource_key_name(ds->key));
- if (r < 0)
- return r;
- if (r == 0)
- continue;
-
- r = dnssec_verify_dnskey_by_ds(dnskey, ds, false);
- if (IN_SET(r, -EKEYREJECTED, -EOPNOTSUPP))
- return 0; /* The DNSKEY is revoked or otherwise invalid, or we don't support the digest algorithm */
- if (r < 0)
- return r;
- if (r > 0)
- return 1;
- }
-
- return 0;
-}
-
-static int nsec3_hash_to_gcrypt_md(uint8_t algorithm) {
-
- /* Translates a DNSSEC NSEC3 hash algorithm into a gcrypt digest identifier */
-
- switch (algorithm) {
-
- case NSEC3_ALGORITHM_SHA1:
- return GCRY_MD_SHA1;
-
- default:
- return -EOPNOTSUPP;
- }
-}
-
-int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
- uint8_t wire_format[DNS_WIRE_FOMAT_HOSTNAME_MAX];
- gcry_md_hd_t md = NULL;
- size_t hash_size;
- int algorithm;
- void *result;
- unsigned k;
- int r;
-
- assert(nsec3);
- assert(name);
- assert(ret);
-
- if (nsec3->key->type != DNS_TYPE_NSEC3)
- return -EINVAL;
-
- if (nsec3->nsec3.iterations > NSEC3_ITERATIONS_MAX) {
- log_debug("Ignoring NSEC3 RR %s with excessive number of iterations.", dns_resource_record_to_string(nsec3));
- return -EOPNOTSUPP;
- }
-
- algorithm = nsec3_hash_to_gcrypt_md(nsec3->nsec3.algorithm);
- if (algorithm < 0)
- return algorithm;
-
- initialize_libgcrypt(false);
-
- hash_size = gcry_md_get_algo_dlen(algorithm);
- assert(hash_size > 0);
-
- if (nsec3->nsec3.next_hashed_name_size != hash_size)
- return -EINVAL;
-
- r = dns_name_to_wire_format(name, wire_format, sizeof(wire_format), true);
- if (r < 0)
- return r;
-
- gcry_md_open(&md, algorithm, 0);
- if (!md)
- return -EIO;
-
- gcry_md_write(md, wire_format, r);
- gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size);
-
- result = gcry_md_read(md, 0);
- if (!result) {
- r = -EIO;
- goto finish;
- }
-
- for (k = 0; k < nsec3->nsec3.iterations; k++) {
- uint8_t tmp[hash_size];
- memcpy(tmp, result, hash_size);
-
- gcry_md_reset(md);
- gcry_md_write(md, tmp, hash_size);
- gcry_md_write(md, nsec3->nsec3.salt, nsec3->nsec3.salt_size);
-
- result = gcry_md_read(md, 0);
- if (!result) {
- r = -EIO;
- goto finish;
- }
- }
-
- memcpy(ret, result, hash_size);
- r = (int) hash_size;
-
-finish:
- gcry_md_close(md);
- return r;
-}
-
-static int nsec3_is_good(DnsResourceRecord *rr, DnsResourceRecord *nsec3) {
- const char *a, *b;
- int r;
-
- assert(rr);
-
- if (rr->key->type != DNS_TYPE_NSEC3)
- return 0;
-
- /* RFC 5155, Section 8.2 says we MUST ignore NSEC3 RRs with flags != 0 or 1 */
- if (!IN_SET(rr->nsec3.flags, 0, 1))
- return 0;
-
- /* Ignore NSEC3 RRs whose algorithm we don't know */
- if (nsec3_hash_to_gcrypt_md(rr->nsec3.algorithm) < 0)
- return 0;
- /* Ignore NSEC3 RRs with an excessive number of required iterations */
- if (rr->nsec3.iterations > NSEC3_ITERATIONS_MAX)
- return 0;
-
- /* Ignore NSEC3 RRs generated from wildcards. If these NSEC3 RRs weren't correctly signed we can't make this
- * check (since rr->n_skip_labels_source is -1), but that's OK, as we won't trust them anyway in that case. */
- if (rr->n_skip_labels_source != 0 && rr->n_skip_labels_source != (unsigned) -1)
- return 0;
- /* Ignore NSEC3 RRs that are located anywhere else than one label below the zone */
- if (rr->n_skip_labels_signer != 1 && rr->n_skip_labels_signer != (unsigned) -1)
- return 0;
-
- if (!nsec3)
- return 1;
-
- /* If a second NSEC3 RR is specified, also check if they are from the same zone. */
-
- if (nsec3 == rr) /* Shortcut */
- return 1;
-
- if (rr->key->class != nsec3->key->class)
- return 0;
- if (rr->nsec3.algorithm != nsec3->nsec3.algorithm)
- return 0;
- if (rr->nsec3.iterations != nsec3->nsec3.iterations)
- return 0;
- if (rr->nsec3.salt_size != nsec3->nsec3.salt_size)
- return 0;
- if (memcmp(rr->nsec3.salt, nsec3->nsec3.salt, rr->nsec3.salt_size) != 0)
- return 0;
-
- a = dns_resource_key_name(rr->key);
- r = dns_name_parent(&a); /* strip off hash */
- if (r < 0)
- return r;
- if (r == 0)
- return 0;
-
- b = dns_resource_key_name(nsec3->key);
- r = dns_name_parent(&b); /* strip off hash */
- if (r < 0)
- return r;
- if (r == 0)
- return 0;
-
- /* Make sure both have the same parent */
- return dns_name_equal(a, b);
-}
-
-static int nsec3_hashed_domain_format(const uint8_t *hashed, size_t hashed_size, const char *zone, char **ret) {
- _cleanup_free_ char *l = NULL;
- char *j;
-
- assert(hashed);
- assert(hashed_size > 0);
- assert(zone);
- assert(ret);
-
- l = base32hexmem(hashed, hashed_size, false);
- if (!l)
- return -ENOMEM;
-
- j = strjoin(l, ".", zone, NULL);
- if (!j)
- return -ENOMEM;
-
- *ret = j;
- return (int) hashed_size;
-}
-
-static int nsec3_hashed_domain_make(DnsResourceRecord *nsec3, const char *domain, const char *zone, char **ret) {
- uint8_t hashed[DNSSEC_HASH_SIZE_MAX];
- int hashed_size;
-
- assert(nsec3);
- assert(domain);
- assert(zone);
- assert(ret);
-
- hashed_size = dnssec_nsec3_hash(nsec3, domain, hashed);
- if (hashed_size < 0)
- return hashed_size;
-
- return nsec3_hashed_domain_format(hashed, (size_t) hashed_size, zone, ret);
-}
-
-/* See RFC 5155, Section 8
- * First try to find a NSEC3 record that matches our query precisely, if that fails, find the closest
- * enclosure. Secondly, find a proof that there is no closer enclosure and either a proof that there
- * is no wildcard domain as a direct descendant of the closest enclosure, or find an NSEC3 record that
- * matches the wildcard domain.
- *
- * Based on this we can prove either the existence of the record in @key, or NXDOMAIN or NODATA, or
- * that there is no proof either way. The latter is the case if a the proof of non-existence of a given
- * name uses an NSEC3 record with the opt-out bit set. Lastly, if we are given insufficient NSEC3 records
- * to conclude anything we indicate this by returning NO_RR. */
-static int dnssec_test_nsec3(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) {
- _cleanup_free_ char *next_closer_domain = NULL, *wildcard_domain = NULL;
- const char *zone, *p, *pp = NULL, *wildcard;
- DnsResourceRecord *rr, *enclosure_rr, *zone_rr, *wildcard_rr = NULL;
- DnsAnswerFlags flags;
- int hashed_size, r;
- bool a, no_closer = false, no_wildcard = false, optout = false;
-
- assert(key);
- assert(result);
-
- /* First step, find the zone name and the NSEC3 parameters of the zone.
- * it is sufficient to look for the longest common suffix we find with
- * any NSEC3 RR in the response. Any NSEC3 record will do as all NSEC3
- * records from a given zone in a response must use the same
- * parameters. */
- zone = dns_resource_key_name(key);
- for (;;) {
- DNS_ANSWER_FOREACH_FLAGS(zone_rr, flags, answer) {
- r = nsec3_is_good(zone_rr, NULL);
- if (r < 0)
- return r;
- if (r == 0)
- continue;
-
- r = dns_name_equal_skip(dns_resource_key_name(zone_rr->key), 1, zone);
- if (r < 0)
- return r;
- if (r > 0)
- goto found_zone;
- }
-
- /* Strip one label from the front */
- r = dns_name_parent(&zone);
- if (r < 0)
- return r;
- if (r == 0)
- break;
- }
-
- *result = DNSSEC_NSEC_NO_RR;
- return 0;
-
-found_zone:
- /* Second step, find the closest encloser NSEC3 RR in 'answer' that matches 'key' */
- p = dns_resource_key_name(key);
- for (;;) {
- _cleanup_free_ char *hashed_domain = NULL;
-
- hashed_size = nsec3_hashed_domain_make(zone_rr, p, zone, &hashed_domain);
- if (hashed_size == -EOPNOTSUPP) {
- *result = DNSSEC_NSEC_UNSUPPORTED_ALGORITHM;
- return 0;
- }
- if (hashed_size < 0)
- return hashed_size;
-
- DNS_ANSWER_FOREACH_FLAGS(enclosure_rr, flags, answer) {
-
- r = nsec3_is_good(enclosure_rr, zone_rr);
- if (r < 0)
- return r;
- if (r == 0)
- continue;
-
- if (enclosure_rr->nsec3.next_hashed_name_size != (size_t) hashed_size)
- continue;
-
- r = dns_name_equal(dns_resource_key_name(enclosure_rr->key), hashed_domain);
- if (r < 0)
- return r;
- if (r > 0) {
- a = flags & DNS_ANSWER_AUTHENTICATED;
- goto found_closest_encloser;
- }
- }
-
- /* We didn't find the closest encloser with this name,
- * but let's remember this domain name, it might be
- * the next closer name */
-
- pp = p;
-
- /* Strip one label from the front */
- r = dns_name_parent(&p);
- if (r < 0)
- return r;
- if (r == 0)
- break;
- }
-
- *result = DNSSEC_NSEC_NO_RR;
- return 0;
-
-found_closest_encloser:
- /* We found a closest encloser in 'p'; next closer is 'pp' */
-
- if (!pp) {
- /* We have an exact match! If we area looking for a DS RR, then we must insist that we got the NSEC3 RR
- * from the parent. Otherwise the one from the child. Do so, by checking whether SOA and NS are
- * appropriately set. */
-
- if (key->type == DNS_TYPE_DS) {
- if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA))
- return -EBADMSG;
- } else {
- if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_NS) &&
- !bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA))
- return -EBADMSG;
- }
-
- /* No next closer NSEC3 RR. That means there's a direct NSEC3 RR for our key. */
- if (bitmap_isset(enclosure_rr->nsec3.types, key->type))
- *result = DNSSEC_NSEC_FOUND;
- else if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_CNAME))
- *result = DNSSEC_NSEC_CNAME;
- else
- *result = DNSSEC_NSEC_NODATA;
-
- if (authenticated)
- *authenticated = a;
- if (ttl)
- *ttl = enclosure_rr->ttl;
-
- return 0;
- }
-
- /* Ensure this is not a DNAME domain, see RFC5155, section 8.3. */
- if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_DNAME))
- return -EBADMSG;
-
- /* Ensure that this data is from the delegated domain
- * (i.e. originates from the "lower" DNS server), and isn't
- * just glue records (i.e. doesn't originate from the "upper"
- * DNS server). */
- if (bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_NS) &&
- !bitmap_isset(enclosure_rr->nsec3.types, DNS_TYPE_SOA))
- return -EBADMSG;
-
- /* Prove that there is no next closer and whether or not there is a wildcard domain. */
-
- wildcard = strjoina("*.", p);
- r = nsec3_hashed_domain_make(enclosure_rr, wildcard, zone, &wildcard_domain);
- if (r < 0)
- return r;
- if (r != hashed_size)
- return -EBADMSG;
-
- r = nsec3_hashed_domain_make(enclosure_rr, pp, zone, &next_closer_domain);
- if (r < 0)
- return r;
- if (r != hashed_size)
- return -EBADMSG;
-
- DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
- _cleanup_free_ char *next_hashed_domain = NULL;
-
- r = nsec3_is_good(rr, zone_rr);
- if (r < 0)
- return r;
- if (r == 0)
- continue;
-
- r = nsec3_hashed_domain_format(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, zone, &next_hashed_domain);
- if (r < 0)
- return r;
-
- r = dns_name_between(dns_resource_key_name(rr->key), next_closer_domain, next_hashed_domain);
- if (r < 0)
- return r;
- if (r > 0) {
- if (rr->nsec3.flags & 1)
- optout = true;
-
- a = a && (flags & DNS_ANSWER_AUTHENTICATED);
-
- no_closer = true;
- }
-
- r = dns_name_equal(dns_resource_key_name(rr->key), wildcard_domain);
- if (r < 0)
- return r;
- if (r > 0) {
- a = a && (flags & DNS_ANSWER_AUTHENTICATED);
-
- wildcard_rr = rr;
- }
-
- r = dns_name_between(dns_resource_key_name(rr->key), wildcard_domain, next_hashed_domain);
- if (r < 0)
- return r;
- if (r > 0) {
- if (rr->nsec3.flags & 1)
- /* This only makes sense if we have a wildcard delegation, which is
- * very unlikely, see RFC 4592, Section 4.2, but we cannot rely on
- * this not happening, so hence cannot simply conclude NXDOMAIN as
- * we would wish */
- optout = true;
-
- a = a && (flags & DNS_ANSWER_AUTHENTICATED);
-
- no_wildcard = true;
- }
- }
-
- if (wildcard_rr && no_wildcard)
- return -EBADMSG;
-
- if (!no_closer) {
- *result = DNSSEC_NSEC_NO_RR;
- return 0;
- }
-
- if (wildcard_rr) {
- /* A wildcard exists that matches our query. */
- if (optout)
- /* This is not specified in any RFC to the best of my knowledge, but
- * if the next closer enclosure is covered by an opt-out NSEC3 RR
- * it means that we cannot prove that the source of synthesis is
- * correct, as there may be a closer match. */
- *result = DNSSEC_NSEC_OPTOUT;
- else if (bitmap_isset(wildcard_rr->nsec3.types, key->type))
- *result = DNSSEC_NSEC_FOUND;
- else if (bitmap_isset(wildcard_rr->nsec3.types, DNS_TYPE_CNAME))
- *result = DNSSEC_NSEC_CNAME;
- else
- *result = DNSSEC_NSEC_NODATA;
- } else {
- if (optout)
- /* The RFC only specifies that we have to care for optout for NODATA for
- * DS records. However, children of an insecure opt-out delegation should
- * also be considered opt-out, rather than verified NXDOMAIN.
- * Note that we do not require a proof of wildcard non-existence if the
- * next closer domain is covered by an opt-out, as that would not provide
- * any additional information. */
- *result = DNSSEC_NSEC_OPTOUT;
- else if (no_wildcard)
- *result = DNSSEC_NSEC_NXDOMAIN;
- else {
- *result = DNSSEC_NSEC_NO_RR;
-
- return 0;
- }
- }
-
- if (authenticated)
- *authenticated = a;
-
- if (ttl)
- *ttl = enclosure_rr->ttl;
-
- return 0;
-}
-
-static int dnssec_nsec_wildcard_equal(DnsResourceRecord *rr, const char *name) {
- char label[DNS_LABEL_MAX];
- const char *n;
- int r;
-
- assert(rr);
- assert(rr->key->type == DNS_TYPE_NSEC);
-
- /* Checks whether the specified RR has a name beginning in "*.", and if the rest is a suffix of our name */
-
- if (rr->n_skip_labels_source != 1)
- return 0;
-
- n = dns_resource_key_name(rr->key);
- r = dns_label_unescape(&n, label, sizeof(label));
- if (r <= 0)
- return r;
- if (r != 1 || label[0] != '*')
- return 0;
-
- return dns_name_endswith(name, n);
-}
-
-static int dnssec_nsec_in_path(DnsResourceRecord *rr, const char *name) {
- const char *nn, *common_suffix;
- int r;
-
- assert(rr);
- assert(rr->key->type == DNS_TYPE_NSEC);
-
- /* Checks whether the specified nsec RR indicates that name is an empty non-terminal (ENT)
- *
- * A couple of examples:
- *
- * NSEC bar → waldo.foo.bar: indicates that foo.bar exists and is an ENT
- * NSEC waldo.foo.bar → yyy.zzz.xoo.bar: indicates that xoo.bar and zzz.xoo.bar exist and are ENTs
- * NSEC yyy.zzz.xoo.bar → bar: indicates pretty much nothing about ENTs
- */
-
- /* First, determine parent of next domain. */
- nn = rr->nsec.next_domain_name;
- r = dns_name_parent(&nn);
- if (r <= 0)
- return r;
-
- /* If the name we just determined is not equal or child of the name we are interested in, then we can't say
- * anything at all. */
- r = dns_name_endswith(nn, name);
- if (r <= 0)
- return r;
-
- /* If the name we we are interested in is not a prefix of the common suffix of the NSEC RR's owner and next domain names, then we can't say anything either. */
- r = dns_name_common_suffix(dns_resource_key_name(rr->key), rr->nsec.next_domain_name, &common_suffix);
- if (r < 0)
- return r;
-
- return dns_name_endswith(name, common_suffix);
-}
-
-static int dnssec_nsec_from_parent_zone(DnsResourceRecord *rr, const char *name) {
- int r;
-
- assert(rr);
- assert(rr->key->type == DNS_TYPE_NSEC);
-
- /* Checks whether this NSEC originates to the parent zone or the child zone. */
-
- r = dns_name_parent(&name);
- if (r <= 0)
- return r;
-
- r = dns_name_equal(name, dns_resource_key_name(rr->key));
- if (r <= 0)
- return r;
-
- /* DNAME, and NS without SOA is an indication for a delegation. */
- if (bitmap_isset(rr->nsec.types, DNS_TYPE_DNAME))
- return 1;
-
- if (bitmap_isset(rr->nsec.types, DNS_TYPE_NS) && !bitmap_isset(rr->nsec.types, DNS_TYPE_SOA))
- return 1;
-
- return 0;
-}
-
-static int dnssec_nsec_covers(DnsResourceRecord *rr, const char *name) {
- const char *common_suffix, *p;
- int r;
-
- assert(rr);
- assert(rr->key->type == DNS_TYPE_NSEC);
-
- /* Checks whether the "Next Closer" is witin the space covered by the specified RR. */
-
- r = dns_name_common_suffix(dns_resource_key_name(rr->key), rr->nsec.next_domain_name, &common_suffix);
- if (r < 0)
- return r;
-
- for (;;) {
- p = name;
- r = dns_name_parent(&name);
- if (r < 0)
- return r;
- if (r == 0)
- return 0;
-
- r = dns_name_equal(name, common_suffix);
- if (r < 0)
- return r;
- if (r > 0)
- break;
- }
-
- /* p is now the "Next Closer". */
-
- return dns_name_between(dns_resource_key_name(rr->key), p, rr->nsec.next_domain_name);
-}
-
-static int dnssec_nsec_covers_wildcard(DnsResourceRecord *rr, const char *name) {
- const char *common_suffix, *wc;
- int r;
-
- assert(rr);
- assert(rr->key->type == DNS_TYPE_NSEC);
-
- /* Checks whether the "Wildcard at the Closest Encloser" is within the space covered by the specified
- * RR. Specifically, checks whether 'name' has the common suffix of the NSEC RR's owner and next names as
- * suffix, and whether the NSEC covers the name generated by that suffix prepended with an asterisk label.
- *
- * NSEC bar → waldo.foo.bar: indicates that *.bar and *.foo.bar do not exist
- * NSEC waldo.foo.bar → yyy.zzz.xoo.bar: indicates that *.xoo.bar and *.zzz.xoo.bar do not exist (and more ...)
- * NSEC yyy.zzz.xoo.bar → bar: indicates that a number of wildcards don#t exist either...
- */
-
- r = dns_name_common_suffix(dns_resource_key_name(rr->key), rr->nsec.next_domain_name, &common_suffix);
- if (r < 0)
- return r;
-
- /* If the common suffix is not shared by the name we are interested in, it has nothing to say for us. */
- r = dns_name_endswith(name, common_suffix);
- if (r <= 0)
- return r;
-
- wc = strjoina("*.", common_suffix);
- return dns_name_between(dns_resource_key_name(rr->key), wc, rr->nsec.next_domain_name);
-}
-
-int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) {
- bool have_nsec3 = false, covering_rr_authenticated = false, wildcard_rr_authenticated = false;
- DnsResourceRecord *rr, *covering_rr = NULL, *wildcard_rr = NULL;
- DnsAnswerFlags flags;
- const char *name;
- int r;
-
- assert(key);
- assert(result);
-
- /* Look for any NSEC/NSEC3 RRs that say something about the specified key. */
-
- name = dns_resource_key_name(key);
-
- DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
-
- if (rr->key->class != key->class)
- continue;
-
- have_nsec3 = have_nsec3 || (rr->key->type == DNS_TYPE_NSEC3);
-
- if (rr->key->type != DNS_TYPE_NSEC)
- continue;
-
- /* The following checks only make sense for NSEC RRs that are not expanded from a wildcard */
- r = dns_resource_record_is_synthetic(rr);
- if (r < 0)
- return r;
- if (r > 0)
- continue;
-
- /* Check if this is a direct match. If so, we have encountered a NODATA case */
- r = dns_name_equal(dns_resource_key_name(rr->key), name);
- if (r < 0)
- return r;
- if (r == 0) {
- /* If it's not a direct match, maybe it's a wild card match? */
- r = dnssec_nsec_wildcard_equal(rr, name);
- if (r < 0)
- return r;
- }
- if (r > 0) {
- if (key->type == DNS_TYPE_DS) {
- /* If we look for a DS RR and the server sent us the NSEC RR of the child zone
- * we have a problem. For DS RRs we want the NSEC RR from the parent */
- if (bitmap_isset(rr->nsec.types, DNS_TYPE_SOA))
- continue;
- } else {
- /* For all RR types, ensure that if NS is set SOA is set too, so that we know
- * we got the child's NSEC. */
- if (bitmap_isset(rr->nsec.types, DNS_TYPE_NS) &&
- !bitmap_isset(rr->nsec.types, DNS_TYPE_SOA))
- continue;
- }
-
- if (bitmap_isset(rr->nsec.types, key->type))
- *result = DNSSEC_NSEC_FOUND;
- else if (bitmap_isset(rr->nsec.types, DNS_TYPE_CNAME))
- *result = DNSSEC_NSEC_CNAME;
- else
- *result = DNSSEC_NSEC_NODATA;
-
- if (authenticated)
- *authenticated = flags & DNS_ANSWER_AUTHENTICATED;
- if (ttl)
- *ttl = rr->ttl;
-
- return 0;
- }
-
- /* Check if the name we are looking for is an empty non-terminal within the owner or next name
- * of the NSEC RR. */
- r = dnssec_nsec_in_path(rr, name);
- if (r < 0)
- return r;
- if (r > 0) {
- *result = DNSSEC_NSEC_NODATA;
-
- if (authenticated)
- *authenticated = flags & DNS_ANSWER_AUTHENTICATED;
- if (ttl)
- *ttl = rr->ttl;
-
- return 0;
- }
-
- /* The following two "covering" checks, are not useful if the NSEC is from the parent */
- r = dnssec_nsec_from_parent_zone(rr, name);
- if (r < 0)
- return r;
- if (r > 0)
- continue;
-
- /* Check if this NSEC RR proves the absence of an explicit RR under this name */
- r = dnssec_nsec_covers(rr, name);
- if (r < 0)
- return r;
- if (r > 0 && (!covering_rr || !covering_rr_authenticated)) {
- covering_rr = rr;
- covering_rr_authenticated = flags & DNS_ANSWER_AUTHENTICATED;
- }
-
- /* Check if this NSEC RR proves the absence of a wildcard RR under this name */
- r = dnssec_nsec_covers_wildcard(rr, name);
- if (r < 0)
- return r;
- if (r > 0 && (!wildcard_rr || !wildcard_rr_authenticated)) {
- wildcard_rr = rr;
- wildcard_rr_authenticated = flags & DNS_ANSWER_AUTHENTICATED;
- }
- }
-
- if (covering_rr && wildcard_rr) {
- /* If we could prove that neither the name itself, nor the wildcard at the closest encloser exists, we
- * proved the NXDOMAIN case. */
- *result = DNSSEC_NSEC_NXDOMAIN;
-
- if (authenticated)
- *authenticated = covering_rr_authenticated && wildcard_rr_authenticated;
- if (ttl)
- *ttl = MIN(covering_rr->ttl, wildcard_rr->ttl);
-
- return 0;
- }
-
- /* OK, this was not sufficient. Let's see if NSEC3 can help. */
- if (have_nsec3)
- return dnssec_test_nsec3(answer, key, result, authenticated, ttl);
-
- /* No approproate NSEC RR found, report this. */
- *result = DNSSEC_NSEC_NO_RR;
- return 0;
-}
-
-static int dnssec_nsec_test_enclosed(DnsAnswer *answer, uint16_t type, const char *name, const char *zone, bool *authenticated) {
- DnsResourceRecord *rr;
- DnsAnswerFlags flags;
- int r;
-
- assert(name);
- assert(zone);
-
- /* Checks whether there's an NSEC/NSEC3 that proves that the specified 'name' is non-existing in the specified
- * 'zone'. The 'zone' must be a suffix of the 'name'. */
-
- DNS_ANSWER_FOREACH_FLAGS(rr, flags, answer) {
- bool found = false;
-
- if (rr->key->type != type && type != DNS_TYPE_ANY)
- continue;
-
- switch (rr->key->type) {
-
- case DNS_TYPE_NSEC:
-
- /* We only care for NSEC RRs from the indicated zone */
- r = dns_resource_record_is_signer(rr, zone);
- if (r < 0)
- return r;
- if (r == 0)
- continue;
-
- r = dns_name_between(dns_resource_key_name(rr->key), name, rr->nsec.next_domain_name);
- if (r < 0)
- return r;
-
- found = r > 0;
- break;
-
- case DNS_TYPE_NSEC3: {
- _cleanup_free_ char *hashed_domain = NULL, *next_hashed_domain = NULL;
-
- /* We only care for NSEC3 RRs from the indicated zone */
- r = dns_resource_record_is_signer(rr, zone);
- if (r < 0)
- return r;
- if (r == 0)
- continue;
-
- r = nsec3_is_good(rr, NULL);
- if (r < 0)
- return r;
- if (r == 0)
- break;
-
- /* Format the domain we are testing with the NSEC3 RR's hash function */
- r = nsec3_hashed_domain_make(
- rr,
- name,
- zone,
- &hashed_domain);
- if (r < 0)
- return r;
- if ((size_t) r != rr->nsec3.next_hashed_name_size)
- break;
-
- /* Format the NSEC3's next hashed name as proper domain name */
- r = nsec3_hashed_domain_format(
- rr->nsec3.next_hashed_name,
- rr->nsec3.next_hashed_name_size,
- zone,
- &next_hashed_domain);
- if (r < 0)
- return r;
-
- r = dns_name_between(dns_resource_key_name(rr->key), hashed_domain, next_hashed_domain);
- if (r < 0)
- return r;
-
- found = r > 0;
- break;
- }
-
- default:
- continue;
- }
-
- if (found) {
- if (authenticated)
- *authenticated = flags & DNS_ANSWER_AUTHENTICATED;
- return 1;
- }
- }
-
- return 0;
-}
-
-static int dnssec_test_positive_wildcard_nsec3(
- DnsAnswer *answer,
- const char *name,
- const char *source,
- const char *zone,
- bool *authenticated) {
-
- const char *next_closer = NULL;
- int r;
-
- /* Run a positive NSEC3 wildcard proof. Specifically:
- *
- * A proof that the "next closer" of the generating wildcard does not exist.
- *
- * Note a key difference between the NSEC3 and NSEC versions of the proof. NSEC RRs don't have to exist for
- * empty non-transients. NSEC3 RRs however have to. This means it's sufficient to check if the next closer name
- * exists for the NSEC3 RR and we are done.
- *
- * To prove that a.b.c.d.e.f is rightfully synthesized from a wildcard *.d.e.f all we have to check is that
- * c.d.e.f does not exist. */
-
- for (;;) {
- next_closer = name;
- r = dns_name_parent(&name);
- if (r < 0)
- return r;
- if (r == 0)
- return 0;
-
- r = dns_name_equal(name, source);
- if (r < 0)
- return r;
- if (r > 0)
- break;
- }
-
- return dnssec_nsec_test_enclosed(answer, DNS_TYPE_NSEC3, next_closer, zone, authenticated);
-}
-
-static int dnssec_test_positive_wildcard_nsec(
- DnsAnswer *answer,
- const char *name,
- const char *source,
- const char *zone,
- bool *_authenticated) {
-
- bool authenticated = true;
- int r;
-
- /* Run a positive NSEC wildcard proof. Specifically:
- *
- * A proof that there's neither a wildcard name nor a non-wildcard name that is a suffix of the name "name" and
- * a prefix of the synthesizing source "source" in the zone "zone".
- *
- * See RFC 5155, Section 8.8 and RFC 4035, Section 5.3.4
- *
- * Note that if we want to prove that a.b.c.d.e.f is rightfully synthesized from a wildcard *.d.e.f, then we
- * have to prove that none of the following exist:
- *
- * 1) a.b.c.d.e.f
- * 2) *.b.c.d.e.f
- * 3) b.c.d.e.f
- * 4) *.c.d.e.f
- * 5) c.d.e.f
- *
- */
-
- for (;;) {
- _cleanup_free_ char *wc = NULL;
- bool a = false;
-
- /* Check if there's an NSEC or NSEC3 RR that proves that the mame we determined is really non-existing,
- * i.e between the owner name and the next name of an NSEC RR. */
- r = dnssec_nsec_test_enclosed(answer, DNS_TYPE_NSEC, name, zone, &a);
- if (r <= 0)
- return r;
-
- authenticated = authenticated && a;
-
- /* Strip one label off */
- r = dns_name_parent(&name);
- if (r <= 0)
- return r;
-
- /* Did we reach the source of synthesis? */
- r = dns_name_equal(name, source);
- if (r < 0)
- return r;
- if (r > 0) {
- /* Successful exit */
- *_authenticated = authenticated;
- return 1;
- }
-
- /* Safety check, that the source of synthesis is still our suffix */
- r = dns_name_endswith(name, source);
- if (r < 0)
- return r;
- if (r == 0)
- return -EBADMSG;
-
- /* Replace the label we stripped off with an asterisk */
- wc = strappend("*.", name);
- if (!wc)
- return -ENOMEM;
-
- /* And check if the proof holds for the asterisk name, too */
- r = dnssec_nsec_test_enclosed(answer, DNS_TYPE_NSEC, wc, zone, &a);
- if (r <= 0)
- return r;
-
- authenticated = authenticated && a;
- /* In the next iteration we'll check the non-asterisk-prefixed version */
- }
-}
-
-int dnssec_test_positive_wildcard(
- DnsAnswer *answer,
- const char *name,
- const char *source,
- const char *zone,
- bool *authenticated) {
-
- int r;
-
- assert(name);
- assert(source);
- assert(zone);
- assert(authenticated);
-
- r = dns_answer_contains_zone_nsec3(answer, zone);
- if (r < 0)
- return r;
- if (r > 0)
- return dnssec_test_positive_wildcard_nsec3(answer, name, source, zone, authenticated);
- else
- return dnssec_test_positive_wildcard_nsec(answer, name, source, zone, authenticated);
-}
-
-#else
-
-int dnssec_verify_rrset(
- DnsAnswer *a,
- const DnsResourceKey *key,
- DnsResourceRecord *rrsig,
- DnsResourceRecord *dnskey,
- usec_t realtime,
- DnssecResult *result) {
-
- return -EOPNOTSUPP;
-}
-
-int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok) {
-
- return -EOPNOTSUPP;
-}
-
-int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig) {
-
- return -EOPNOTSUPP;
-}
-
-int dnssec_verify_rrset_search(
- DnsAnswer *a,
- const DnsResourceKey *key,
- DnsAnswer *validated_dnskeys,
- usec_t realtime,
- DnssecResult *result,
- DnsResourceRecord **ret_rrsig) {
-
- return -EOPNOTSUPP;
-}
-
-int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key) {
-
- return -EOPNOTSUPP;
-}
-
-int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, bool mask_revoke) {
-
- return -EOPNOTSUPP;
-}
-
-int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds) {
-
- return -EOPNOTSUPP;
-}
-
-int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret) {
-
- return -EOPNOTSUPP;
-}
-
-int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl) {
-
- return -EOPNOTSUPP;
-}
-
-int dnssec_test_positive_wildcard(
- DnsAnswer *answer,
- const char *name,
- const char *source,
- const char *zone,
- bool *authenticated) {
-
- return -EOPNOTSUPP;
-}
-
-#endif
-
-static const char* const dnssec_result_table[_DNSSEC_RESULT_MAX] = {
- [DNSSEC_VALIDATED] = "validated",
- [DNSSEC_VALIDATED_WILDCARD] = "validated-wildcard",
- [DNSSEC_INVALID] = "invalid",
- [DNSSEC_SIGNATURE_EXPIRED] = "signature-expired",
- [DNSSEC_UNSUPPORTED_ALGORITHM] = "unsupported-algorithm",
- [DNSSEC_NO_SIGNATURE] = "no-signature",
- [DNSSEC_MISSING_KEY] = "missing-key",
- [DNSSEC_UNSIGNED] = "unsigned",
- [DNSSEC_FAILED_AUXILIARY] = "failed-auxiliary",
- [DNSSEC_NSEC_MISMATCH] = "nsec-mismatch",
- [DNSSEC_INCOMPATIBLE_SERVER] = "incompatible-server",
-};
-DEFINE_STRING_TABLE_LOOKUP(dnssec_result, DnssecResult);
-
-static const char* const dnssec_verdict_table[_DNSSEC_VERDICT_MAX] = {
- [DNSSEC_SECURE] = "secure",
- [DNSSEC_INSECURE] = "insecure",
- [DNSSEC_BOGUS] = "bogus",
- [DNSSEC_INDETERMINATE] = "indeterminate",
-};
-DEFINE_STRING_TABLE_LOOKUP(dnssec_verdict, DnssecVerdict);
diff --git a/src/grp-resolve/systemd-resolved/resolved-dns-dnssec.h b/src/grp-resolve/systemd-resolved/resolved-dns-dnssec.h
deleted file mode 100644
index 81879e287f..0000000000
--- a/src/grp-resolve/systemd-resolved/resolved-dns-dnssec.h
+++ /dev/null
@@ -1,103 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-typedef enum DnssecResult DnssecResult;
-typedef enum DnssecVerdict DnssecVerdict;
-
-#include "shared/dns-domain.h"
-
-#include "resolved-dns-answer.h"
-#include "resolved-dns-rr.h"
-
-enum DnssecResult {
- /* These five are returned by dnssec_verify_rrset() */
- DNSSEC_VALIDATED,
- DNSSEC_VALIDATED_WILDCARD, /* Validated via a wildcard RRSIG, further NSEC/NSEC3 checks necessary */
- DNSSEC_INVALID,
- DNSSEC_SIGNATURE_EXPIRED,
- DNSSEC_UNSUPPORTED_ALGORITHM,
-
- /* These two are added by dnssec_verify_rrset_search() */
- DNSSEC_NO_SIGNATURE,
- DNSSEC_MISSING_KEY,
-
- /* These two are added by the DnsTransaction logic */
- DNSSEC_UNSIGNED,
- DNSSEC_FAILED_AUXILIARY,
- DNSSEC_NSEC_MISMATCH,
- DNSSEC_INCOMPATIBLE_SERVER,
-
- _DNSSEC_RESULT_MAX,
- _DNSSEC_RESULT_INVALID = -1
-};
-
-enum DnssecVerdict {
- DNSSEC_SECURE,
- DNSSEC_INSECURE,
- DNSSEC_BOGUS,
- DNSSEC_INDETERMINATE,
-
- _DNSSEC_VERDICT_MAX,
- _DNSSEC_VERDICT_INVALID = -1
-};
-
-#define DNSSEC_CANONICAL_HOSTNAME_MAX (DNS_HOSTNAME_MAX + 2)
-
-/* The longest digest we'll ever generate, of all digest algorithms we support */
-#define DNSSEC_HASH_SIZE_MAX (MAX(20, 32))
-
-int dnssec_rrsig_match_dnskey(DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, bool revoked_ok);
-int dnssec_key_match_rrsig(const DnsResourceKey *key, DnsResourceRecord *rrsig);
-
-int dnssec_verify_rrset(DnsAnswer *answer, const DnsResourceKey *key, DnsResourceRecord *rrsig, DnsResourceRecord *dnskey, usec_t realtime, DnssecResult *result);
-int dnssec_verify_rrset_search(DnsAnswer *answer, const DnsResourceKey *key, DnsAnswer *validated_dnskeys, usec_t realtime, DnssecResult *result, DnsResourceRecord **rrsig);
-
-int dnssec_verify_dnskey_by_ds(DnsResourceRecord *dnskey, DnsResourceRecord *ds, bool mask_revoke);
-int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *validated_ds);
-
-int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key);
-
-uint16_t dnssec_keytag(DnsResourceRecord *dnskey, bool mask_revoke);
-
-int dnssec_canonicalize(const char *n, char *buffer, size_t buffer_max);
-
-int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret);
-
-typedef enum DnssecNsecResult {
- DNSSEC_NSEC_NO_RR, /* No suitable NSEC/NSEC3 RR found */
- DNSSEC_NSEC_CNAME, /* Didn't find what was asked for, but did find CNAME */
- DNSSEC_NSEC_UNSUPPORTED_ALGORITHM,
- DNSSEC_NSEC_NXDOMAIN,
- DNSSEC_NSEC_NODATA,
- DNSSEC_NSEC_FOUND,
- DNSSEC_NSEC_OPTOUT,
-} DnssecNsecResult;
-
-int dnssec_nsec_test(DnsAnswer *answer, DnsResourceKey *key, DnssecNsecResult *result, bool *authenticated, uint32_t *ttl);
-
-
-int dnssec_test_positive_wildcard(DnsAnswer *a, const char *name, const char *source, const char *zone, bool *authenticated);
-
-const char* dnssec_result_to_string(DnssecResult m) _const_;
-DnssecResult dnssec_result_from_string(const char *s) _pure_;
-
-const char* dnssec_verdict_to_string(DnssecVerdict m) _const_;
-DnssecVerdict dnssec_verdict_from_string(const char *s) _pure_;
diff --git a/src/grp-resolve/systemd-resolved/resolved-dns-packet.c b/src/grp-resolve/systemd-resolved/resolved-dns-packet.c
deleted file mode 100644
index 37c0244b7e..0000000000
--- a/src/grp-resolve/systemd-resolved/resolved-dns-packet.c
+++ /dev/null
@@ -1,2256 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
- ***/
-
-#include "basic/alloc-util.h"
-#include "basic/string-table.h"
-#include "basic/strv.h"
-#include "basic/unaligned.h"
-#include "basic/utf8.h"
-#include "basic/util.h"
-#include "shared/dns-domain.h"
-
-#include "resolved-dns-packet.h"
-
-#define EDNS0_OPT_DO (1<<15)
-
-typedef struct DnsPacketRewinder {
- DnsPacket *packet;
- size_t saved_rindex;
-} DnsPacketRewinder;
-
-static void rewind_dns_packet(DnsPacketRewinder *rewinder) {
- if (rewinder->packet)
- dns_packet_rewind(rewinder->packet, rewinder->saved_rindex);
-}
-
-#define INIT_REWINDER(rewinder, p) do { rewinder.packet = p; rewinder.saved_rindex = p->rindex; } while (0)
-#define CANCEL_REWINDER(rewinder) do { rewinder.packet = NULL; } while (0)
-
-int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
- DnsPacket *p;
- size_t a;
-
- assert(ret);
-
- if (mtu <= UDP_PACKET_HEADER_SIZE)
- a = DNS_PACKET_SIZE_START;
- else
- a = mtu - UDP_PACKET_HEADER_SIZE;
-
- if (a < DNS_PACKET_HEADER_SIZE)
- a = DNS_PACKET_HEADER_SIZE;
-
- /* round up to next page size */
- a = PAGE_ALIGN(ALIGN(sizeof(DnsPacket)) + a) - ALIGN(sizeof(DnsPacket));
-
- /* make sure we never allocate more than useful */
- if (a > DNS_PACKET_SIZE_MAX)
- a = DNS_PACKET_SIZE_MAX;
-
- p = malloc0(ALIGN(sizeof(DnsPacket)) + a);
- if (!p)
- return -ENOMEM;
-
- p->size = p->rindex = DNS_PACKET_HEADER_SIZE;
- p->allocated = a;
- p->protocol = protocol;
- p->opt_start = p->opt_size = (size_t) -1;
- p->n_ref = 1;
-
- *ret = p;
-
- return 0;
-}
-
-void dns_packet_set_flags(DnsPacket *p, bool dnssec_checking_disabled, bool truncated) {
-
- DnsPacketHeader *h;
-
- assert(p);
-
- h = DNS_PACKET_HEADER(p);
-
- switch(p->protocol) {
- case DNS_PROTOCOL_LLMNR:
- assert(!truncated);
-
- h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
- 0 /* opcode */,
- 0 /* c */,
- 0 /* tc */,
- 0 /* t */,
- 0 /* ra */,
- 0 /* ad */,
- 0 /* cd */,
- 0 /* rcode */));
- break;
-
- case DNS_PROTOCOL_MDNS:
- h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
- 0 /* opcode */,
- 0 /* aa */,
- truncated /* tc */,
- 0 /* rd (ask for recursion) */,
- 0 /* ra */,
- 0 /* ad */,
- 0 /* cd */,
- 0 /* rcode */));
- break;
-
- default:
- assert(!truncated);
-
- h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
- 0 /* opcode */,
- 0 /* aa */,
- 0 /* tc */,
- 1 /* rd (ask for recursion) */,
- 0 /* ra */,
- 0 /* ad */,
- dnssec_checking_disabled /* cd */,
- 0 /* rcode */));
- }
-}
-
-int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu, bool dnssec_checking_disabled) {
- DnsPacket *p;
- int r;
-
- assert(ret);
-
- r = dns_packet_new(&p, protocol, mtu);
- if (r < 0)
- return r;
-
- /* Always set the TC bit to 0 initially.
- * If there are multiple packets later, we'll update the bit shortly before sending.
- */
- dns_packet_set_flags(p, dnssec_checking_disabled, false);
-
- *ret = p;
- return 0;
-}
-
-DnsPacket *dns_packet_ref(DnsPacket *p) {
-
- if (!p)
- return NULL;
-
- assert(!p->on_stack);
-
- assert(p->n_ref > 0);
- p->n_ref++;
- return p;
-}
-
-static void dns_packet_free(DnsPacket *p) {
- char *s;
-
- assert(p);
-
- dns_question_unref(p->question);
- dns_answer_unref(p->answer);
- dns_resource_record_unref(p->opt);
-
- while ((s = hashmap_steal_first_key(p->names)))
- free(s);
- hashmap_free(p->names);
-
- free(p->_data);
-
- if (!p->on_stack)
- free(p);
-}
-
-DnsPacket *dns_packet_unref(DnsPacket *p) {
- if (!p)
- return NULL;
-
- assert(p->n_ref > 0);
-
- dns_packet_unref(p->more);
-
- if (p->n_ref == 1)
- dns_packet_free(p);
- else
- p->n_ref--;
-
- return NULL;
-}
-
-int dns_packet_validate(DnsPacket *p) {
- assert(p);
-
- if (p->size < DNS_PACKET_HEADER_SIZE)
- return -EBADMSG;
-
- if (p->size > DNS_PACKET_SIZE_MAX)
- return -EBADMSG;
-
- return 1;
-}
-
-int dns_packet_validate_reply(DnsPacket *p) {
- int r;
-
- assert(p);
-
- r = dns_packet_validate(p);
- if (r < 0)
- return r;
-
- if (DNS_PACKET_QR(p) != 1)
- return 0;
-
- if (DNS_PACKET_OPCODE(p) != 0)
- return -EBADMSG;
-
- switch (p->protocol) {
-
- case DNS_PROTOCOL_LLMNR:
- /* RFC 4795, Section 2.1.1. says to discard all replies with QDCOUNT != 1 */
- if (DNS_PACKET_QDCOUNT(p) != 1)
- return -EBADMSG;
-
- break;
-
- case DNS_PROTOCOL_MDNS:
- /* RFC 6762, Section 18 */
- if (DNS_PACKET_RCODE(p) != 0)
- return -EBADMSG;
-
- break;
-
- default:
- break;
- }
-
- return 1;
-}
-
-int dns_packet_validate_query(DnsPacket *p) {
- int r;
-
- assert(p);
-
- r = dns_packet_validate(p);
- if (r < 0)
- return r;
-
- if (DNS_PACKET_QR(p) != 0)
- return 0;
-
- if (DNS_PACKET_OPCODE(p) != 0)
- return -EBADMSG;
-
- if (DNS_PACKET_TC(p))
- return -EBADMSG;
-
- switch (p->protocol) {
-
- case DNS_PROTOCOL_LLMNR:
- /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */
- if (DNS_PACKET_QDCOUNT(p) != 1)
- return -EBADMSG;
-
- /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */
- if (DNS_PACKET_ANCOUNT(p) > 0)
- return -EBADMSG;
-
- /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */
- if (DNS_PACKET_NSCOUNT(p) > 0)
- return -EBADMSG;
-
- break;
-
- case DNS_PROTOCOL_MDNS:
- /* RFC 6762, Section 18 */
- if (DNS_PACKET_AA(p) != 0 ||
- DNS_PACKET_RD(p) != 0 ||
- DNS_PACKET_RA(p) != 0 ||
- DNS_PACKET_AD(p) != 0 ||
- DNS_PACKET_CD(p) != 0 ||
- DNS_PACKET_RCODE(p) != 0)
- return -EBADMSG;
-
- break;
-
- default:
- break;
- }
-
- return 1;
-}
-
-static int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start) {
- assert(p);
-
- if (p->size + add > p->allocated) {
- size_t a;
-
- a = PAGE_ALIGN((p->size + add) * 2);
- if (a > DNS_PACKET_SIZE_MAX)
- a = DNS_PACKET_SIZE_MAX;
-
- if (p->size + add > a)
- return -EMSGSIZE;
-
- if (p->_data) {
- void *d;
-
- d = realloc(p->_data, a);
- if (!d)
- return -ENOMEM;
-
- p->_data = d;
- } else {
- p->_data = malloc(a);
- if (!p->_data)
- return -ENOMEM;
-
- memcpy(p->_data, (uint8_t*) p + ALIGN(sizeof(DnsPacket)), p->size);
- memzero((uint8_t*) p->_data + p->size, a - p->size);
- }
-
- p->allocated = a;
- }
-
- if (start)
- *start = p->size;
-
- if (ret)
- *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->size;
-
- p->size += add;
- return 0;
-}
-
-void dns_packet_truncate(DnsPacket *p, size_t sz) {
- Iterator i;
- char *s;
- void *n;
-
- assert(p);
-
- if (p->size <= sz)
- return;
-
- HASHMAP_FOREACH_KEY(n, s, p->names, i) {
-
- if (PTR_TO_SIZE(n) < sz)
- continue;
-
- hashmap_remove(p->names, s);
- free(s);
- }
-
- p->size = sz;
-}
-
-int dns_packet_append_blob(DnsPacket *p, const void *d, size_t l, size_t *start) {
- void *q;
- int r;
-
- assert(p);
-
- r = dns_packet_extend(p, l, &q, start);
- if (r < 0)
- return r;
-
- memcpy(q, d, l);
- return 0;
-}
-
-int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start) {
- void *d;
- int r;
-
- assert(p);
-
- r = dns_packet_extend(p, sizeof(uint8_t), &d, start);
- if (r < 0)
- return r;
-
- ((uint8_t*) d)[0] = v;
-
- return 0;
-}
-
-int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start) {
- void *d;
- int r;
-
- assert(p);
-
- r = dns_packet_extend(p, sizeof(uint16_t), &d, start);
- if (r < 0)
- return r;
-
- unaligned_write_be16(d, v);
-
- return 0;
-}
-
-int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start) {
- void *d;
- int r;
-
- assert(p);
-
- r = dns_packet_extend(p, sizeof(uint32_t), &d, start);
- if (r < 0)
- return r;
-
- unaligned_write_be32(d, v);
-
- return 0;
-}
-
-int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start) {
- assert(p);
- assert(s);
-
- return dns_packet_append_raw_string(p, s, strlen(s), start);
-}
-
-int dns_packet_append_raw_string(DnsPacket *p, const void *s, size_t size, size_t *start) {
- void *d;
- int r;
-
- assert(p);
- assert(s || size == 0);
-
- if (size > 255)
- return -E2BIG;
-
- r = dns_packet_extend(p, 1 + size, &d, start);
- if (r < 0)
- return r;
-
- ((uint8_t*) d)[0] = (uint8_t) size;
-
- memcpy_safe(((uint8_t*) d) + 1, s, size);
-
- return 0;
-}
-
-int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, bool canonical_candidate, size_t *start) {
- uint8_t *w;
- int r;
-
- /* Append a label to a packet. Optionally, does this in DNSSEC
- * canonical form, if this label is marked as a candidate for
- * it, and the canonical form logic is enabled for the
- * packet */
-
- assert(p);
- assert(d);
-
- if (l > DNS_LABEL_MAX)
- return -E2BIG;
-
- r = dns_packet_extend(p, 1 + l, (void**) &w, start);
- if (r < 0)
- return r;
-
- *(w++) = (uint8_t) l;
-
- if (p->canonical_form && canonical_candidate) {
- size_t i;
-
- /* Generate in canonical form, as defined by DNSSEC
- * RFC 4034, Section 6.2, i.e. all lower-case. */
-
- for (i = 0; i < l; i++)
- w[i] = (uint8_t) ascii_tolower(d[i]);
- } else
- /* Otherwise, just copy the string unaltered. This is
- * essential for DNS-SD, where the casing of labels
- * matters and needs to be retained. */
- memcpy(w, d, l);
-
- return 0;
-}
-
-int dns_packet_append_name(
- DnsPacket *p,
- const char *name,
- bool allow_compression,
- bool canonical_candidate,
- size_t *start) {
-
- size_t saved_size;
- int r;
-
- assert(p);
- assert(name);
-
- if (p->refuse_compression)
- allow_compression = false;
-
- saved_size = p->size;
-
- while (!dns_name_is_root(name)) {
- const char *z = name;
- char label[DNS_LABEL_MAX];
- size_t n = 0;
-
- if (allow_compression)
- n = PTR_TO_SIZE(hashmap_get(p->names, name));
- if (n > 0) {
- assert(n < p->size);
-
- if (n < 0x4000) {
- r = dns_packet_append_uint16(p, 0xC000 | n, NULL);
- if (r < 0)
- goto fail;
-
- goto done;
- }
- }
-
- r = dns_label_unescape(&name, label, sizeof(label));
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_label(p, label, r, canonical_candidate, &n);
- if (r < 0)
- goto fail;
-
- if (allow_compression) {
- _cleanup_free_ char *s = NULL;
-
- s = strdup(z);
- if (!s) {
- r = -ENOMEM;
- goto fail;
- }
-
- r = hashmap_ensure_allocated(&p->names, &dns_name_hash_ops);
- if (r < 0)
- goto fail;
-
- r = hashmap_put(p->names, s, SIZE_TO_PTR(n));
- if (r < 0)
- goto fail;
-
- s = NULL;
- }
- }
-
- r = dns_packet_append_uint8(p, 0, NULL);
- if (r < 0)
- return r;
-
-done:
- if (start)
- *start = saved_size;
-
- return 0;
-
-fail:
- dns_packet_truncate(p, saved_size);
- return r;
-}
-
-int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, size_t *start) {
- size_t saved_size;
- int r;
-
- assert(p);
- assert(k);
-
- saved_size = p->size;
-
- r = dns_packet_append_name(p, dns_resource_key_name(k), true, true, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint16(p, k->type, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint16(p, k->class, NULL);
- if (r < 0)
- goto fail;
-
- if (start)
- *start = saved_size;
-
- return 0;
-
-fail:
- dns_packet_truncate(p, saved_size);
- return r;
-}
-
-static int dns_packet_append_type_window(DnsPacket *p, uint8_t window, uint8_t length, const uint8_t *types, size_t *start) {
- size_t saved_size;
- int r;
-
- assert(p);
- assert(types);
- assert(length > 0);
-
- saved_size = p->size;
-
- r = dns_packet_append_uint8(p, window, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, length, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_blob(p, types, length, NULL);
- if (r < 0)
- goto fail;
-
- if (start)
- *start = saved_size;
-
- return 0;
-fail:
- dns_packet_truncate(p, saved_size);
- return r;
-}
-
-static int dns_packet_append_types(DnsPacket *p, Bitmap *types, size_t *start) {
- Iterator i;
- uint8_t window = 0;
- uint8_t entry = 0;
- uint8_t bitmaps[32] = {};
- unsigned n;
- size_t saved_size;
- int r;
-
- assert(p);
-
- saved_size = p->size;
-
- BITMAP_FOREACH(n, types, i) {
- assert(n <= 0xffff);
-
- if ((n >> 8) != window && bitmaps[entry / 8] != 0) {
- r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
- if (r < 0)
- goto fail;
-
- zero(bitmaps);
- }
-
- window = n >> 8;
- entry = n & 255;
-
- bitmaps[entry / 8] |= 1 << (7 - (entry % 8));
- }
-
- if (bitmaps[entry / 8] != 0) {
- r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
- if (r < 0)
- goto fail;
- }
-
- if (start)
- *start = saved_size;
-
- return 0;
-fail:
- dns_packet_truncate(p, saved_size);
- return r;
-}
-
-/* Append the OPT pseudo-RR described in RFC6891 */
-int dns_packet_append_opt(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, size_t *start) {
- size_t saved_size;
- int r;
-
- assert(p);
- /* we must never advertise supported packet size smaller than the legacy max */
- assert(max_udp_size >= DNS_PACKET_UNICAST_SIZE_MAX);
-
- if (p->opt_start != (size_t) -1)
- return -EBUSY;
-
- assert(p->opt_size == (size_t) -1);
-
- saved_size = p->size;
-
- /* empty name */
- r = dns_packet_append_uint8(p, 0, NULL);
- if (r < 0)
- return r;
-
- /* type */
- r = dns_packet_append_uint16(p, DNS_TYPE_OPT, NULL);
- if (r < 0)
- goto fail;
-
- /* maximum udp packet that can be received */
- r = dns_packet_append_uint16(p, max_udp_size, NULL);
- if (r < 0)
- goto fail;
-
- /* extended RCODE and VERSION */
- r = dns_packet_append_uint16(p, 0, NULL);
- if (r < 0)
- goto fail;
-
- /* flags: DNSSEC OK (DO), see RFC3225 */
- r = dns_packet_append_uint16(p, edns0_do ? EDNS0_OPT_DO : 0, NULL);
- if (r < 0)
- goto fail;
-
- /* RDLENGTH */
-
- if (edns0_do) {
- /* If DO is on, also append RFC6975 Algorithm data */
-
- static const uint8_t rfc6975[] = {
-
- 0, 5, /* OPTION_CODE: DAU */
- 0, 6, /* LIST_LENGTH */
- DNSSEC_ALGORITHM_RSASHA1,
- DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1,
- DNSSEC_ALGORITHM_RSASHA256,
- DNSSEC_ALGORITHM_RSASHA512,
- DNSSEC_ALGORITHM_ECDSAP256SHA256,
- DNSSEC_ALGORITHM_ECDSAP384SHA384,
-
- 0, 6, /* OPTION_CODE: DHU */
- 0, 3, /* LIST_LENGTH */
- DNSSEC_DIGEST_SHA1,
- DNSSEC_DIGEST_SHA256,
- DNSSEC_DIGEST_SHA384,
-
- 0, 7, /* OPTION_CODE: N3U */
- 0, 1, /* LIST_LENGTH */
- NSEC3_ALGORITHM_SHA1,
- };
-
- r = dns_packet_append_uint16(p, sizeof(rfc6975), NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_blob(p, rfc6975, sizeof(rfc6975), NULL);
- } else
- r = dns_packet_append_uint16(p, 0, NULL);
-
- if (r < 0)
- goto fail;
-
- DNS_PACKET_HEADER(p)->arcount = htobe16(DNS_PACKET_ARCOUNT(p) + 1);
-
- p->opt_start = saved_size;
- p->opt_size = p->size - saved_size;
-
- if (start)
- *start = saved_size;
-
- return 0;
-
-fail:
- dns_packet_truncate(p, saved_size);
- return r;
-}
-
-int dns_packet_truncate_opt(DnsPacket *p) {
- assert(p);
-
- if (p->opt_start == (size_t) -1) {
- assert(p->opt_size == (size_t) -1);
- return 0;
- }
-
- assert(p->opt_size != (size_t) -1);
- assert(DNS_PACKET_ARCOUNT(p) > 0);
-
- if (p->opt_start + p->opt_size != p->size)
- return -EBUSY;
-
- dns_packet_truncate(p, p->opt_start);
- DNS_PACKET_HEADER(p)->arcount = htobe16(DNS_PACKET_ARCOUNT(p) - 1);
- p->opt_start = p->opt_size = (size_t) -1;
-
- return 1;
-}
-
-int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start, size_t *rdata_start) {
- size_t saved_size, rdlength_offset, end, rdlength, rds;
- int r;
-
- assert(p);
- assert(rr);
-
- saved_size = p->size;
-
- r = dns_packet_append_key(p, rr->key, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->ttl, NULL);
- if (r < 0)
- goto fail;
-
- /* Initially we write 0 here */
- r = dns_packet_append_uint16(p, 0, &rdlength_offset);
- if (r < 0)
- goto fail;
-
- rds = p->size - saved_size;
-
- switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
-
- case DNS_TYPE_SRV:
- r = dns_packet_append_uint16(p, rr->srv.priority, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint16(p, rr->srv.weight, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint16(p, rr->srv.port, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_name(p, rr->srv.name, true, false, NULL);
- break;
-
- case DNS_TYPE_PTR:
- case DNS_TYPE_NS:
- case DNS_TYPE_CNAME:
- case DNS_TYPE_DNAME:
- r = dns_packet_append_name(p, rr->ptr.name, true, false, NULL);
- break;
-
- case DNS_TYPE_HINFO:
- r = dns_packet_append_string(p, rr->hinfo.cpu, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_string(p, rr->hinfo.os, NULL);
- break;
-
- case DNS_TYPE_SPF: /* exactly the same as TXT */
- case DNS_TYPE_TXT:
-
- if (!rr->txt.items) {
- /* RFC 6763, section 6.1 suggests to generate
- * single empty string for an empty array. */
-
- r = dns_packet_append_raw_string(p, NULL, 0, NULL);
- if (r < 0)
- goto fail;
- } else {
- DnsTxtItem *i;
-
- LIST_FOREACH(items, i, rr->txt.items) {
- r = dns_packet_append_raw_string(p, i->data, i->length, NULL);
- if (r < 0)
- goto fail;
- }
- }
-
- r = 0;
- break;
-
- case DNS_TYPE_A:
- r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
- break;
-
- case DNS_TYPE_AAAA:
- r = dns_packet_append_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
- break;
-
- case DNS_TYPE_SOA:
- r = dns_packet_append_name(p, rr->soa.mname, true, false, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_name(p, rr->soa.rname, true, false, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->soa.serial, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->soa.refresh, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->soa.retry, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->soa.expire, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->soa.minimum, NULL);
- break;
-
- case DNS_TYPE_MX:
- r = dns_packet_append_uint16(p, rr->mx.priority, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_name(p, rr->mx.exchange, true, false, NULL);
- break;
-
- case DNS_TYPE_LOC:
- r = dns_packet_append_uint8(p, rr->loc.version, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->loc.size, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->loc.horiz_pre, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->loc.vert_pre, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->loc.latitude, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->loc.longitude, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->loc.altitude, NULL);
- break;
-
- case DNS_TYPE_DS:
- r = dns_packet_append_uint16(p, rr->ds.key_tag, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->ds.algorithm, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->ds.digest_type, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_blob(p, rr->ds.digest, rr->ds.digest_size, NULL);
- break;
-
- case DNS_TYPE_SSHFP:
- r = dns_packet_append_uint8(p, rr->sshfp.algorithm, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->sshfp.fptype, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_blob(p, rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, NULL);
- break;
-
- case DNS_TYPE_DNSKEY:
- r = dns_packet_append_uint16(p, rr->dnskey.flags, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->dnskey.protocol, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->dnskey.algorithm, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_blob(p, rr->dnskey.key, rr->dnskey.key_size, NULL);
- break;
-
- case DNS_TYPE_RRSIG:
- r = dns_packet_append_uint16(p, rr->rrsig.type_covered, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->rrsig.algorithm, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->rrsig.labels, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->rrsig.original_ttl, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->rrsig.expiration, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint32(p, rr->rrsig.inception, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint16(p, rr->rrsig.key_tag, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_name(p, rr->rrsig.signer, false, true, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_blob(p, rr->rrsig.signature, rr->rrsig.signature_size, NULL);
- break;
-
- case DNS_TYPE_NSEC:
- r = dns_packet_append_name(p, rr->nsec.next_domain_name, false, false, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_types(p, rr->nsec.types, NULL);
- if (r < 0)
- goto fail;
-
- break;
-
- case DNS_TYPE_NSEC3:
- r = dns_packet_append_uint8(p, rr->nsec3.algorithm, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->nsec3.flags, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint16(p, rr->nsec3.iterations, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->nsec3.salt_size, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_blob(p, rr->nsec3.salt, rr->nsec3.salt_size, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->nsec3.next_hashed_name_size, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_blob(p, rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_types(p, rr->nsec3.types, NULL);
- if (r < 0)
- goto fail;
-
- break;
-
- case DNS_TYPE_TLSA:
- r = dns_packet_append_uint8(p, rr->tlsa.cert_usage, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->tlsa.selector, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_uint8(p, rr->tlsa.matching_type, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_blob(p, rr->tlsa.data, rr->tlsa.data_size, NULL);
- break;
-
- case DNS_TYPE_CAA:
- r = dns_packet_append_uint8(p, rr->caa.flags, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_string(p, rr->caa.tag, NULL);
- if (r < 0)
- goto fail;
-
- r = dns_packet_append_blob(p, rr->caa.value, rr->caa.value_size, NULL);
- break;
-
- case DNS_TYPE_OPT:
- case DNS_TYPE_OPENPGPKEY:
- case _DNS_TYPE_INVALID: /* unparseable */
- default:
-
- r = dns_packet_append_blob(p, rr->generic.data, rr->generic.data_size, NULL);
- break;
- }
- if (r < 0)
- goto fail;
-
- /* Let's calculate the actual data size and update the field */
- rdlength = p->size - rdlength_offset - sizeof(uint16_t);
- if (rdlength > 0xFFFF) {
- r = -ENOSPC;
- goto fail;
- }
-
- end = p->size;
- p->size = rdlength_offset;
- r = dns_packet_append_uint16(p, rdlength, NULL);
- if (r < 0)
- goto fail;
- p->size = end;
-
- if (start)
- *start = saved_size;
-
- if (rdata_start)
- *rdata_start = rds;
-
- return 0;
-
-fail:
- dns_packet_truncate(p, saved_size);
- return r;
-}
-
-int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
- assert(p);
-
- if (p->rindex + sz > p->size)
- return -EMSGSIZE;
-
- if (ret)
- *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
-
- if (start)
- *start = p->rindex;
-
- p->rindex += sz;
- return 0;
-}
-
-void dns_packet_rewind(DnsPacket *p, size_t idx) {
- assert(p);
- assert(idx <= p->size);
- assert(idx >= DNS_PACKET_HEADER_SIZE);
-
- p->rindex = idx;
-}
-
-int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
- const void *q;
- int r;
-
- assert(p);
- assert(d);
-
- r = dns_packet_read(p, sz, &q, start);
- if (r < 0)
- return r;
-
- memcpy(d, q, sz);
- return 0;
-}
-
-static int dns_packet_read_memdup(
- DnsPacket *p, size_t size,
- void **ret, size_t *ret_size,
- size_t *ret_start) {
-
- const void *src;
- size_t start;
- int r;
-
- assert(p);
- assert(ret);
-
- r = dns_packet_read(p, size, &src, &start);
- if (r < 0)
- return r;
-
- if (size <= 0)
- *ret = NULL;
- else {
- void *copy;
-
- copy = memdup(src, size);
- if (!copy)
- return -ENOMEM;
-
- *ret = copy;
- }
-
- if (ret_size)
- *ret_size = size;
- if (ret_start)
- *ret_start = start;
-
- return 0;
-}
-
-int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
- const void *d;
- int r;
-
- assert(p);
-
- r = dns_packet_read(p, sizeof(uint8_t), &d, start);
- if (r < 0)
- return r;
-
- *ret = ((uint8_t*) d)[0];
- return 0;
-}
-
-int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
- const void *d;
- int r;
-
- assert(p);
-
- r = dns_packet_read(p, sizeof(uint16_t), &d, start);
- if (r < 0)
- return r;
-
- *ret = unaligned_read_be16(d);
-
- return 0;
-}
-
-int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
- const void *d;
- int r;
-
- assert(p);
-
- r = dns_packet_read(p, sizeof(uint32_t), &d, start);
- if (r < 0)
- return r;
-
- *ret = unaligned_read_be32(d);
-
- return 0;
-}
-
-int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
- _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
- const void *d;
- char *t;
- uint8_t c;
- int r;
-
- assert(p);
- INIT_REWINDER(rewinder, p);
-
- r = dns_packet_read_uint8(p, &c, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read(p, c, &d, NULL);
- if (r < 0)
- return r;
-
- if (memchr(d, 0, c))
- return -EBADMSG;
-
- t = strndup(d, c);
- if (!t)
- return -ENOMEM;
-
- if (!utf8_is_valid(t)) {
- free(t);
- return -EBADMSG;
- }
-
- *ret = t;
-
- if (start)
- *start = rewinder.saved_rindex;
- CANCEL_REWINDER(rewinder);
-
- return 0;
-}
-
-int dns_packet_read_raw_string(DnsPacket *p, const void **ret, size_t *size, size_t *start) {
- _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
- uint8_t c;
- int r;
-
- assert(p);
- INIT_REWINDER(rewinder, p);
-
- r = dns_packet_read_uint8(p, &c, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read(p, c, ret, NULL);
- if (r < 0)
- return r;
-
- if (size)
- *size = c;
- if (start)
- *start = rewinder.saved_rindex;
- CANCEL_REWINDER(rewinder);
-
- return 0;
-}
-
-int dns_packet_read_name(
- DnsPacket *p,
- char **_ret,
- bool allow_compression,
- size_t *start) {
-
- _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
- size_t after_rindex = 0, jump_barrier;
- _cleanup_free_ char *ret = NULL;
- size_t n = 0, allocated = 0;
- bool first = true;
- int r;
-
- assert(p);
- assert(_ret);
- INIT_REWINDER(rewinder, p);
- jump_barrier = p->rindex;
-
- if (p->refuse_compression)
- allow_compression = false;
-
- for (;;) {
- uint8_t c, d;
-
- r = dns_packet_read_uint8(p, &c, NULL);
- if (r < 0)
- return r;
-
- if (c == 0)
- /* End of name */
- break;
- else if (c <= 63) {
- const char *label;
-
- /* Literal label */
- r = dns_packet_read(p, c, (const void**) &label, NULL);
- if (r < 0)
- return r;
-
- if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
- return -ENOMEM;
-
- if (first)
- first = false;
- else
- ret[n++] = '.';
-
- r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX);
- if (r < 0)
- return r;
-
- n += r;
- continue;
- } else if (allow_compression && (c & 0xc0) == 0xc0) {
- uint16_t ptr;
-
- /* Pointer */
- r = dns_packet_read_uint8(p, &d, NULL);
- if (r < 0)
- return r;
-
- ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
- if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= jump_barrier)
- return -EBADMSG;
-
- if (after_rindex == 0)
- after_rindex = p->rindex;
-
- /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */
- jump_barrier = ptr;
- p->rindex = ptr;
- } else
- return -EBADMSG;
- }
-
- if (!GREEDY_REALLOC(ret, allocated, n + 1))
- return -ENOMEM;
-
- ret[n] = 0;
-
- if (after_rindex != 0)
- p->rindex= after_rindex;
-
- *_ret = ret;
- ret = NULL;
-
- if (start)
- *start = rewinder.saved_rindex;
- CANCEL_REWINDER(rewinder);
-
- return 0;
-}
-
-static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *start) {
- uint8_t window;
- uint8_t length;
- const uint8_t *bitmap;
- uint8_t bit = 0;
- unsigned i;
- bool found = false;
- _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
- int r;
-
- assert(p);
- assert(types);
- INIT_REWINDER(rewinder, p);
-
- r = bitmap_ensure_allocated(types);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint8(p, &window, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint8(p, &length, NULL);
- if (r < 0)
- return r;
-
- if (length == 0 || length > 32)
- return -EBADMSG;
-
- r = dns_packet_read(p, length, (const void **)&bitmap, NULL);
- if (r < 0)
- return r;
-
- for (i = 0; i < length; i++) {
- uint8_t bitmask = 1 << 7;
-
- if (!bitmap[i]) {
- found = false;
- bit += 8;
- continue;
- }
-
- found = true;
-
- while (bitmask) {
- if (bitmap[i] & bitmask) {
- uint16_t n;
-
- n = (uint16_t) window << 8 | (uint16_t) bit;
-
- /* Ignore pseudo-types. see RFC4034 section 4.1.2 */
- if (dns_type_is_pseudo(n))
- continue;
-
- r = bitmap_set(*types, n);
- if (r < 0)
- return r;
- }
-
- bit++;
- bitmask >>= 1;
- }
- }
-
- if (!found)
- return -EBADMSG;
-
- if (start)
- *start = rewinder.saved_rindex;
- CANCEL_REWINDER(rewinder);
-
- return 0;
-}
-
-static int dns_packet_read_type_windows(DnsPacket *p, Bitmap **types, size_t size, size_t *start) {
- _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
- int r;
-
- INIT_REWINDER(rewinder, p);
-
- while (p->rindex < rewinder.saved_rindex + size) {
- r = dns_packet_read_type_window(p, types, NULL);
- if (r < 0)
- return r;
-
- /* don't read past end of current RR */
- if (p->rindex > rewinder.saved_rindex + size)
- return -EBADMSG;
- }
-
- if (p->rindex != rewinder.saved_rindex + size)
- return -EBADMSG;
-
- if (start)
- *start = rewinder.saved_rindex;
- CANCEL_REWINDER(rewinder);
-
- return 0;
-}
-
-int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, bool *ret_cache_flush, size_t *start) {
- _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
- _cleanup_free_ char *name = NULL;
- bool cache_flush = false;
- uint16_t class, type;
- DnsResourceKey *key;
- int r;
-
- assert(p);
- assert(ret);
- INIT_REWINDER(rewinder, p);
-
- r = dns_packet_read_name(p, &name, true, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint16(p, &type, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint16(p, &class, NULL);
- if (r < 0)
- return r;
-
- if (p->protocol == DNS_PROTOCOL_MDNS) {
- /* See RFC6762, Section 10.2 */
-
- if (type != DNS_TYPE_OPT && (class & MDNS_RR_CACHE_FLUSH)) {
- class &= ~MDNS_RR_CACHE_FLUSH;
- cache_flush = true;
- }
- }
-
- key = dns_resource_key_new_consume(class, type, name);
- if (!key)
- return -ENOMEM;
-
- name = NULL;
- *ret = key;
-
- if (ret_cache_flush)
- *ret_cache_flush = cache_flush;
- if (start)
- *start = rewinder.saved_rindex;
- CANCEL_REWINDER(rewinder);
-
- return 0;
-}
-
-static bool loc_size_ok(uint8_t size) {
- uint8_t m = size >> 4, e = size & 0xF;
-
- return m <= 9 && e <= 9 && (m > 0 || e == 0);
-}
-
-int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool *ret_cache_flush, size_t *start) {
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
- _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
- size_t offset;
- uint16_t rdlength;
- bool cache_flush;
- int r;
-
- assert(p);
- assert(ret);
-
- INIT_REWINDER(rewinder, p);
-
- r = dns_packet_read_key(p, &key, &cache_flush, NULL);
- if (r < 0)
- return r;
-
- if (!dns_class_is_valid_rr(key->class) || !dns_type_is_valid_rr(key->type))
- return -EBADMSG;
-
- rr = dns_resource_record_new(key);
- if (!rr)
- return -ENOMEM;
-
- r = dns_packet_read_uint32(p, &rr->ttl, NULL);
- if (r < 0)
- return r;
-
- /* RFC 2181, Section 8, suggests to
- * treat a TTL with the MSB set as a zero TTL. */
- if (rr->ttl & UINT32_C(0x80000000))
- rr->ttl = 0;
-
- r = dns_packet_read_uint16(p, &rdlength, NULL);
- if (r < 0)
- return r;
-
- if (p->rindex + rdlength > p->size)
- return -EBADMSG;
-
- offset = p->rindex;
-
- switch (rr->key->type) {
-
- case DNS_TYPE_SRV:
- r = dns_packet_read_uint16(p, &rr->srv.priority, NULL);
- if (r < 0)
- return r;
- r = dns_packet_read_uint16(p, &rr->srv.weight, NULL);
- if (r < 0)
- return r;
- r = dns_packet_read_uint16(p, &rr->srv.port, NULL);
- if (r < 0)
- return r;
- r = dns_packet_read_name(p, &rr->srv.name, true, NULL);
- break;
-
- case DNS_TYPE_PTR:
- case DNS_TYPE_NS:
- case DNS_TYPE_CNAME:
- case DNS_TYPE_DNAME:
- r = dns_packet_read_name(p, &rr->ptr.name, true, NULL);
- break;
-
- case DNS_TYPE_HINFO:
- r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
- break;
-
- case DNS_TYPE_SPF: /* exactly the same as TXT */
- case DNS_TYPE_TXT:
- if (rdlength <= 0) {
- DnsTxtItem *i;
- /* RFC 6763, section 6.1 suggests to treat
- * empty TXT RRs as equivalent to a TXT record
- * with a single empty string. */
-
- i = malloc0(offsetof(DnsTxtItem, data) + 1); /* for safety reasons we add an extra NUL byte */
- if (!i)
- return -ENOMEM;
-
- rr->txt.items = i;
- } else {
- DnsTxtItem *last = NULL;
-
- while (p->rindex < offset + rdlength) {
- DnsTxtItem *i;
- const void *data;
- size_t sz;
-
- r = dns_packet_read_raw_string(p, &data, &sz, NULL);
- if (r < 0)
- return r;
-
- i = malloc0(offsetof(DnsTxtItem, data) + sz + 1); /* extra NUL byte at the end */
- if (!i)
- return -ENOMEM;
-
- memcpy(i->data, data, sz);
- i->length = sz;
-
- LIST_INSERT_AFTER(items, rr->txt.items, last, i);
- last = i;
- }
- }
-
- r = 0;
- break;
-
- case DNS_TYPE_A:
- r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
- break;
-
- case DNS_TYPE_AAAA:
- r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
- break;
-
- case DNS_TYPE_SOA:
- r = dns_packet_read_name(p, &rr->soa.mname, true, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_name(p, &rr->soa.rname, true, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
- break;
-
- case DNS_TYPE_MX:
- r = dns_packet_read_uint16(p, &rr->mx.priority, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_name(p, &rr->mx.exchange, true, NULL);
- break;
-
- case DNS_TYPE_LOC: {
- uint8_t t;
- size_t pos;
-
- r = dns_packet_read_uint8(p, &t, &pos);
- if (r < 0)
- return r;
-
- if (t == 0) {
- rr->loc.version = t;
-
- r = dns_packet_read_uint8(p, &rr->loc.size, NULL);
- if (r < 0)
- return r;
-
- if (!loc_size_ok(rr->loc.size))
- return -EBADMSG;
-
- r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL);
- if (r < 0)
- return r;
-
- if (!loc_size_ok(rr->loc.horiz_pre))
- return -EBADMSG;
-
- r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL);
- if (r < 0)
- return r;
-
- if (!loc_size_ok(rr->loc.vert_pre))
- return -EBADMSG;
-
- r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL);
- if (r < 0)
- return r;
-
- break;
- } else {
- dns_packet_rewind(p, pos);
- rr->unparseable = true;
- goto unparseable;
- }
- }
-
- case DNS_TYPE_DS:
- r = dns_packet_read_uint16(p, &rr->ds.key_tag, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint8(p, &rr->ds.algorithm, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint8(p, &rr->ds.digest_type, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_memdup(p, rdlength - 4,
- &rr->ds.digest, &rr->ds.digest_size,
- NULL);
- if (r < 0)
- return r;
-
- if (rr->ds.digest_size <= 0)
- /* the accepted size depends on the algorithm, but for now
- just ensure that the value is greater than zero */
- return -EBADMSG;
-
- break;
-
- case DNS_TYPE_SSHFP:
- r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_memdup(p, rdlength - 2,
- &rr->sshfp.fingerprint, &rr->sshfp.fingerprint_size,
- NULL);
-
- if (rr->sshfp.fingerprint_size <= 0)
- /* the accepted size depends on the algorithm, but for now
- just ensure that the value is greater than zero */
- return -EBADMSG;
-
- break;
-
- case DNS_TYPE_DNSKEY:
- r = dns_packet_read_uint16(p, &rr->dnskey.flags, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint8(p, &rr->dnskey.protocol, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_memdup(p, rdlength - 4,
- &rr->dnskey.key, &rr->dnskey.key_size,
- NULL);
-
- if (rr->dnskey.key_size <= 0)
- /* the accepted size depends on the algorithm, but for now
- just ensure that the value is greater than zero */
- return -EBADMSG;
-
- break;
-
- case DNS_TYPE_RRSIG:
- r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint8(p, &rr->rrsig.algorithm, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint8(p, &rr->rrsig.labels, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint32(p, &rr->rrsig.original_ttl, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint32(p, &rr->rrsig.expiration, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint32(p, &rr->rrsig.inception, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint16(p, &rr->rrsig.key_tag, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_name(p, &rr->rrsig.signer, false, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_memdup(p, offset + rdlength - p->rindex,
- &rr->rrsig.signature, &rr->rrsig.signature_size,
- NULL);
-
- if (rr->rrsig.signature_size <= 0)
- /* the accepted size depends on the algorithm, but for now
- just ensure that the value is greater than zero */
- return -EBADMSG;
-
- break;
-
- case DNS_TYPE_NSEC: {
-
- /*
- * RFC6762, section 18.14 explictly states mDNS should use name compression.
- * This contradicts RFC3845, section 2.1.1
- */
-
- bool allow_compressed = p->protocol == DNS_PROTOCOL_MDNS;
-
- r = dns_packet_read_name(p, &rr->nsec.next_domain_name, allow_compressed, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL);
-
- /* We accept empty NSEC bitmaps. The bit indicating the presence of the NSEC record itself
- * is redundant and in e.g., RFC4956 this fact is used to define a use for NSEC records
- * without the NSEC bit set. */
-
- break;
- }
- case DNS_TYPE_NSEC3: {
- uint8_t size;
-
- r = dns_packet_read_uint8(p, &rr->nsec3.algorithm, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint8(p, &rr->nsec3.flags, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint16(p, &rr->nsec3.iterations, NULL);
- if (r < 0)
- return r;
-
- /* this may be zero */
- r = dns_packet_read_uint8(p, &size, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_memdup(p, size, &rr->nsec3.salt, &rr->nsec3.salt_size, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint8(p, &size, NULL);
- if (r < 0)
- return r;
-
- if (size <= 0)
- return -EBADMSG;
-
- r = dns_packet_read_memdup(p, size,
- &rr->nsec3.next_hashed_name, &rr->nsec3.next_hashed_name_size,
- NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_type_windows(p, &rr->nsec3.types, offset + rdlength - p->rindex, NULL);
-
- /* empty non-terminals can have NSEC3 records, so empty bitmaps are allowed */
-
- break;
- }
-
- case DNS_TYPE_TLSA:
- r = dns_packet_read_uint8(p, &rr->tlsa.cert_usage, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint8(p, &rr->tlsa.selector, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_uint8(p, &rr->tlsa.matching_type, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_memdup(p, rdlength - 3,
- &rr->tlsa.data, &rr->tlsa.data_size,
- NULL);
-
- if (rr->tlsa.data_size <= 0)
- /* the accepted size depends on the algorithm, but for now
- just ensure that the value is greater than zero */
- return -EBADMSG;
-
- break;
-
- case DNS_TYPE_CAA:
- r = dns_packet_read_uint8(p, &rr->caa.flags, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_string(p, &rr->caa.tag, NULL);
- if (r < 0)
- return r;
-
- r = dns_packet_read_memdup(p,
- rdlength + offset - p->rindex,
- &rr->caa.value, &rr->caa.value_size, NULL);
-
- break;
-
- case DNS_TYPE_OPT: /* we only care about the header of OPT for now. */
- case DNS_TYPE_OPENPGPKEY:
- default:
- unparseable:
- r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.data_size, NULL);
-
- break;
- }
- if (r < 0)
- return r;
- if (p->rindex != offset + rdlength)
- return -EBADMSG;
-
- *ret = rr;
- rr = NULL;
-
- if (ret_cache_flush)
- *ret_cache_flush = cache_flush;
- if (start)
- *start = rewinder.saved_rindex;
- CANCEL_REWINDER(rewinder);
-
- return 0;
-}
-
-static bool opt_is_good(DnsResourceRecord *rr, bool *rfc6975) {
- const uint8_t* p;
- bool found_dau_dhu_n3u = false;
- size_t l;
-
- /* Checks whether the specified OPT RR is well-formed and whether it contains RFC6975 data (which is not OK in
- * a reply). */
-
- assert(rr);
- assert(rr->key->type == DNS_TYPE_OPT);
-
- /* Check that the version is 0 */
- if (((rr->ttl >> 16) & UINT32_C(0xFF)) != 0)
- return false;
-
- p = rr->opt.data;
- l = rr->opt.data_size;
- while (l > 0) {
- uint16_t option_code, option_length;
-
- /* At least four bytes for OPTION-CODE and OPTION-LENGTH are required */
- if (l < 4U)
- return false;
-
- option_code = unaligned_read_be16(p);
- option_length = unaligned_read_be16(p + 2);
-
- if (l < option_length + 4U)
- return false;
-
- /* RFC 6975 DAU, DHU or N3U fields found. */
- if (IN_SET(option_code, 5, 6, 7))
- found_dau_dhu_n3u = true;
-
- p += option_length + 4U;
- l -= option_length + 4U;
- }
-
- *rfc6975 = found_dau_dhu_n3u;
- return true;
-}
-
-int dns_packet_extract(DnsPacket *p) {
- _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
- _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
- _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder = {};
- unsigned n, i;
- int r;
-
- if (p->extracted)
- return 0;
-
- INIT_REWINDER(rewinder, p);
- dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
-
- n = DNS_PACKET_QDCOUNT(p);
- if (n > 0) {
- question = dns_question_new(n);
- if (!question)
- return -ENOMEM;
-
- for (i = 0; i < n; i++) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
- bool cache_flush;
-
- r = dns_packet_read_key(p, &key, &cache_flush, NULL);
- if (r < 0)
- return r;
-
- if (cache_flush)
- return -EBADMSG;
-
- if (!dns_type_is_valid_query(key->type))
- return -EBADMSG;
-
- r = dns_question_add(question, key);
- if (r < 0)
- return r;
- }
- }
-
- n = DNS_PACKET_RRCOUNT(p);
- if (n > 0) {
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *previous = NULL;
- bool bad_opt = false;
-
- answer = dns_answer_new(n);
- if (!answer)
- return -ENOMEM;
-
- for (i = 0; i < n; i++) {
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
- bool cache_flush;
-
- r = dns_packet_read_rr(p, &rr, &cache_flush, NULL);
- if (r < 0)
- return r;
-
- /* Try to reduce memory usage a bit */
- if (previous)
- dns_resource_key_reduce(&rr->key, &previous->key);
-
- if (rr->key->type == DNS_TYPE_OPT) {
- bool has_rfc6975;
-
- if (p->opt || bad_opt) {
- /* Multiple OPT RRs? if so, let's ignore all, because there's something wrong
- * with the server, and if one is valid we wouldn't know which one. */
- log_debug("Multiple OPT RRs detected, ignoring all.");
- bad_opt = true;
- continue;
- }
-
- if (!dns_name_is_root(dns_resource_key_name(rr->key))) {
- /* If the OPT RR is not owned by the root domain, then it is bad, let's ignore
- * it. */
- log_debug("OPT RR is not owned by root domain, ignoring.");
- bad_opt = true;
- continue;
- }
-
- if (i < DNS_PACKET_ANCOUNT(p) + DNS_PACKET_NSCOUNT(p)) {
- /* OPT RR is in the wrong section? Some Belkin routers do this. This is a hint
- * the EDNS implementation is borked, like the Belkin one is, hence ignore
- * it. */
- log_debug("OPT RR in wrong section, ignoring.");
- bad_opt = true;
- continue;
- }
-
- if (!opt_is_good(rr, &has_rfc6975)) {
- log_debug("Malformed OPT RR, ignoring.");
- bad_opt = true;
- continue;
- }
-
- if (has_rfc6975) {
- /* If the OPT RR contains RFC6975 algorithm data, then this is indication that
- * the server just copied the OPT it got from us (which contained that data)
- * back into the reply. If so, then it doesn't properly support EDNS, as
- * RFC6975 makes it very clear that the algorithm data should only be contained
- * in questions, never in replies. Crappy Belkin routers copy the OPT data for
- * example, hence let's detect this so that we downgrade early. */
- log_debug("OPT RR contained RFC6975 data, ignoring.");
- bad_opt = true;
- continue;
- }
-
- p->opt = dns_resource_record_ref(rr);
- } else {
-
- /* According to RFC 4795, section 2.9. only the RRs from the Answer section shall be
- * cached. Hence mark only those RRs as cacheable by default, but not the ones from the
- * Additional or Authority sections. */
-
- r = dns_answer_add(answer, rr, p->ifindex,
- (i < DNS_PACKET_ANCOUNT(p) ? DNS_ANSWER_CACHEABLE : 0) |
- (p->protocol == DNS_PROTOCOL_MDNS && !cache_flush ? DNS_ANSWER_SHARED_OWNER : 0));
- if (r < 0)
- return r;
- }
-
- /* Remember this RR, so that we potentically can merge it's ->key object with the next RR. Note
- * that we only do this if we actually decided to keep the RR around. */
- dns_resource_record_unref(previous);
- previous = dns_resource_record_ref(rr);
- }
-
- if (bad_opt)
- p->opt = dns_resource_record_unref(p->opt);
- }
-
- p->question = question;
- question = NULL;
-
- p->answer = answer;
- answer = NULL;
-
- p->extracted = true;
-
- /* no CANCEL, always rewind */
- return 0;
-}
-
-int dns_packet_is_reply_for(DnsPacket *p, const DnsResourceKey *key) {
- int r;
-
- assert(p);
- assert(key);
-
- /* Checks if the specified packet is a reply for the specified
- * key and the specified key is the only one in the question
- * section. */
-
- if (DNS_PACKET_QR(p) != 1)
- return 0;
-
- /* Let's unpack the packet, if that hasn't happened yet. */
- r = dns_packet_extract(p);
- if (r < 0)
- return r;
-
- if (p->question->n_keys != 1)
- return 0;
-
- return dns_resource_key_equal(p->question->keys[0], key);
-}
-
-static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
- [DNS_RCODE_SUCCESS] = "SUCCESS",
- [DNS_RCODE_FORMERR] = "FORMERR",
- [DNS_RCODE_SERVFAIL] = "SERVFAIL",
- [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
- [DNS_RCODE_NOTIMP] = "NOTIMP",
- [DNS_RCODE_REFUSED] = "REFUSED",
- [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
- [DNS_RCODE_YXRRSET] = "YRRSET",
- [DNS_RCODE_NXRRSET] = "NXRRSET",
- [DNS_RCODE_NOTAUTH] = "NOTAUTH",
- [DNS_RCODE_NOTZONE] = "NOTZONE",
- [DNS_RCODE_BADVERS] = "BADVERS",
- [DNS_RCODE_BADKEY] = "BADKEY",
- [DNS_RCODE_BADTIME] = "BADTIME",
- [DNS_RCODE_BADMODE] = "BADMODE",
- [DNS_RCODE_BADNAME] = "BADNAME",
- [DNS_RCODE_BADALG] = "BADALG",
- [DNS_RCODE_BADTRUNC] = "BADTRUNC",
-};
-DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
-
-static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
- [DNS_PROTOCOL_DNS] = "dns",
- [DNS_PROTOCOL_MDNS] = "mdns",
- [DNS_PROTOCOL_LLMNR] = "llmnr",
-};
-DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);
diff --git a/src/grp-resolve/systemd-resolved/resolved-dns-packet.h b/src/grp-resolve/systemd-resolved/resolved-dns-packet.h
deleted file mode 100644
index 2e0eba83b6..0000000000
--- a/src/grp-resolve/systemd-resolved/resolved-dns-packet.h
+++ /dev/null
@@ -1,270 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
- ***/
-
-#include <netinet/ip.h>
-#include <netinet/udp.h>
-
-#include "basic/hashmap.h"
-#include "basic/in-addr-util.h"
-#include "basic/macro.h"
-#include "basic/sparse-endian.h"
-
-typedef struct DnsPacket DnsPacket;
-typedef struct DnsPacketHeader DnsPacketHeader;
-
-#include "resolved-def.h"
-#include "resolved-dns-answer.h"
-#include "resolved-dns-question.h"
-#include "resolved-dns-rr.h"
-
-typedef enum DnsProtocol {
- DNS_PROTOCOL_DNS,
- DNS_PROTOCOL_MDNS,
- DNS_PROTOCOL_LLMNR,
- _DNS_PROTOCOL_MAX,
- _DNS_PROTOCOL_INVALID = -1
-} DnsProtocol;
-
-struct DnsPacketHeader {
- uint16_t id;
- be16_t flags;
- be16_t qdcount;
- be16_t ancount;
- be16_t nscount;
- be16_t arcount;
-};
-
-#define DNS_PACKET_HEADER_SIZE sizeof(DnsPacketHeader)
-#define UDP_PACKET_HEADER_SIZE (sizeof(struct iphdr) + sizeof(struct udphdr))
-
-/* The various DNS protocols deviate in how large a packet can grow,
- but the TCP transport has a 16bit size field, hence that appears to
- be the absolute maximum. */
-#define DNS_PACKET_SIZE_MAX 0xFFFF
-
-/* RFC 1035 say 512 is the maximum, for classic unicast DNS */
-#define DNS_PACKET_UNICAST_SIZE_MAX 512
-
-/* With EDNS0 we can use larger packets, default to 4096, which is what is commonly used */
-#define DNS_PACKET_UNICAST_SIZE_LARGE_MAX 4096
-
-#define DNS_PACKET_SIZE_START 512
-
-struct DnsPacket {
- int n_ref;
- DnsProtocol protocol;
- size_t size, allocated, rindex;
- void *_data; /* don't access directly, use DNS_PACKET_DATA()! */
- Hashmap *names; /* For name compression */
- size_t opt_start, opt_size;
-
- /* Parsed data */
- DnsQuestion *question;
- DnsAnswer *answer;
- DnsResourceRecord *opt;
-
- /* Packet reception metadata */
- int ifindex;
- int family, ipproto;
- union in_addr_union sender, destination;
- uint16_t sender_port, destination_port;
- uint32_t ttl;
-
- /* For support of truncated packets */
- DnsPacket *more;
-
- bool on_stack:1;
- bool extracted:1;
- bool refuse_compression:1;
- bool canonical_form:1;
-};
-
-static inline uint8_t* DNS_PACKET_DATA(DnsPacket *p) {
- if (_unlikely_(!p))
- return NULL;
-
- if (p->_data)
- return p->_data;
-
- return ((uint8_t*) p) + ALIGN(sizeof(DnsPacket));
-}
-
-#define DNS_PACKET_HEADER(p) ((DnsPacketHeader*) DNS_PACKET_DATA(p))
-#define DNS_PACKET_ID(p) DNS_PACKET_HEADER(p)->id
-#define DNS_PACKET_QR(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 15) & 1)
-#define DNS_PACKET_OPCODE(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 11) & 15)
-#define DNS_PACKET_AA(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 10) & 1)
-#define DNS_PACKET_TC(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 9) & 1)
-#define DNS_PACKET_RD(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 8) & 1)
-#define DNS_PACKET_RA(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 7) & 1)
-#define DNS_PACKET_AD(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 5) & 1)
-#define DNS_PACKET_CD(p) ((be16toh(DNS_PACKET_HEADER(p)->flags) >> 4) & 1)
-
-static inline uint16_t DNS_PACKET_RCODE(DnsPacket *p) {
- uint16_t rcode;
-
- if (p->opt)
- rcode = (uint16_t) (p->opt->ttl >> 24);
- else
- rcode = 0;
-
- return rcode | (be16toh(DNS_PACKET_HEADER(p)->flags) & 15);
-}
-
-/* LLMNR defines some bits differently */
-#define DNS_PACKET_LLMNR_C(p) DNS_PACKET_AA(p)
-#define DNS_PACKET_LLMNR_T(p) DNS_PACKET_RD(p)
-
-#define DNS_PACKET_QDCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->qdcount)
-#define DNS_PACKET_ANCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->ancount)
-#define DNS_PACKET_NSCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->nscount)
-#define DNS_PACKET_ARCOUNT(p) be16toh(DNS_PACKET_HEADER(p)->arcount)
-
-#define DNS_PACKET_MAKE_FLAGS(qr, opcode, aa, tc, rd, ra, ad, cd, rcode) \
- (((uint16_t) !!(qr) << 15) | \
- ((uint16_t) ((opcode) & 15) << 11) | \
- ((uint16_t) !!(aa) << 10) | /* on LLMNR: c */ \
- ((uint16_t) !!(tc) << 9) | \
- ((uint16_t) !!(rd) << 8) | /* on LLMNR: t */ \
- ((uint16_t) !!(ra) << 7) | \
- ((uint16_t) !!(ad) << 5) | \
- ((uint16_t) !!(cd) << 4) | \
- ((uint16_t) ((rcode) & 15)))
-
-static inline unsigned DNS_PACKET_RRCOUNT(DnsPacket *p) {
- return
- (unsigned) DNS_PACKET_ANCOUNT(p) +
- (unsigned) DNS_PACKET_NSCOUNT(p) +
- (unsigned) DNS_PACKET_ARCOUNT(p);
-}
-
-int dns_packet_new(DnsPacket **p, DnsProtocol protocol, size_t mtu);
-int dns_packet_new_query(DnsPacket **p, DnsProtocol protocol, size_t mtu, bool dnssec_checking_disabled);
-
-void dns_packet_set_flags(DnsPacket *p, bool dnssec_checking_disabled, bool truncated);
-
-DnsPacket *dns_packet_ref(DnsPacket *p);
-DnsPacket *dns_packet_unref(DnsPacket *p);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(DnsPacket*, dns_packet_unref);
-
-int dns_packet_validate(DnsPacket *p);
-int dns_packet_validate_reply(DnsPacket *p);
-int dns_packet_validate_query(DnsPacket *p);
-
-int dns_packet_is_reply_for(DnsPacket *p, const DnsResourceKey *key);
-
-int dns_packet_append_blob(DnsPacket *p, const void *d, size_t sz, size_t *start);
-int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start);
-int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start);
-int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start);
-int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start);
-int dns_packet_append_raw_string(DnsPacket *p, const void *s, size_t size, size_t *start);
-int dns_packet_append_label(DnsPacket *p, const char *s, size_t l, bool canonical_candidate, size_t *start);
-int dns_packet_append_name(DnsPacket *p, const char *name, bool allow_compression, bool canonical_candidate, size_t *start);
-int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *key, size_t *start);
-int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start, size_t *rdata_start);
-int dns_packet_append_opt(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, size_t *start);
-
-void dns_packet_truncate(DnsPacket *p, size_t sz);
-int dns_packet_truncate_opt(DnsPacket *p);
-
-int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start);
-int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start);
-int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start);
-int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start);
-int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start);
-int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start);
-int dns_packet_read_raw_string(DnsPacket *p, const void **ret, size_t *size, size_t *start);
-int dns_packet_read_name(DnsPacket *p, char **ret, bool allow_compression, size_t *start);
-int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, bool *ret_cache_flush, size_t *start);
-int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool *ret_cache_flush, size_t *start);
-
-void dns_packet_rewind(DnsPacket *p, size_t idx);
-
-int dns_packet_skip_question(DnsPacket *p);
-int dns_packet_extract(DnsPacket *p);
-
-static inline bool DNS_PACKET_SHALL_CACHE(DnsPacket *p) {
- /* Never cache data originating from localhost, under the
- * assumption, that it's coming from a locally DNS forwarder
- * or server, that is caching on its own. */
-
- return in_addr_is_localhost(p->family, &p->sender) == 0;
-}
-
-/* https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6 */
-enum {
- DNS_RCODE_SUCCESS = 0,
- DNS_RCODE_FORMERR = 1,
- DNS_RCODE_SERVFAIL = 2,
- DNS_RCODE_NXDOMAIN = 3,
- DNS_RCODE_NOTIMP = 4,
- DNS_RCODE_REFUSED = 5,
- DNS_RCODE_YXDOMAIN = 6,
- DNS_RCODE_YXRRSET = 7,
- DNS_RCODE_NXRRSET = 8,
- DNS_RCODE_NOTAUTH = 9,
- DNS_RCODE_NOTZONE = 10,
- DNS_RCODE_BADVERS = 16,
- DNS_RCODE_BADSIG = 16, /* duplicate value! */
- DNS_RCODE_BADKEY = 17,
- DNS_RCODE_BADTIME = 18,
- DNS_RCODE_BADMODE = 19,
- DNS_RCODE_BADNAME = 20,
- DNS_RCODE_BADALG = 21,
- DNS_RCODE_BADTRUNC = 22,
- _DNS_RCODE_MAX_DEFINED
-};
-
-const char* dns_rcode_to_string(int i) _const_;
-int dns_rcode_from_string(const char *s) _pure_;
-
-const char* dns_protocol_to_string(DnsProtocol p) _const_;
-DnsProtocol dns_protocol_from_string(const char *s) _pure_;
-
-#define LLMNR_MULTICAST_IPV4_ADDRESS ((struct in_addr) { .s_addr = htobe32(224U << 24 | 252U) })
-#define LLMNR_MULTICAST_IPV6_ADDRESS ((struct in6_addr) { .s6_addr = { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03 } })
-
-#define MDNS_MULTICAST_IPV4_ADDRESS ((struct in_addr) { .s_addr = htobe32(224U << 24 | 251U) })
-#define MDNS_MULTICAST_IPV6_ADDRESS ((struct in6_addr) { .s6_addr = { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb } })
-
-static inline uint64_t SD_RESOLVED_FLAGS_MAKE(DnsProtocol protocol, int family, bool authenticated) {
- uint64_t f;
-
- /* Converts a protocol + family into a flags field as used in queries and responses */
-
- f = authenticated ? SD_RESOLVED_AUTHENTICATED : 0;
-
- switch (protocol) {
- case DNS_PROTOCOL_DNS:
- return f|SD_RESOLVED_DNS;
-
- case DNS_PROTOCOL_LLMNR:
- return f|(family == AF_INET6 ? SD_RESOLVED_LLMNR_IPV6 : SD_RESOLVED_LLMNR_IPV4);
-
- case DNS_PROTOCOL_MDNS:
- return f|(family == AF_INET6 ? SD_RESOLVED_MDNS_IPV6 : SD_RESOLVED_MDNS_IPV4);
-
- default:
- return f;
- }
-}
diff --git a/src/grp-resolve/systemd-resolved/resolved-dns-question.c b/src/grp-resolve/systemd-resolved/resolved-dns-question.c
deleted file mode 100644
index ee53dbff9d..0000000000
--- a/src/grp-resolve/systemd-resolved/resolved-dns-question.c
+++ /dev/null
@@ -1,469 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "basic/alloc-util.h"
-#include "shared/dns-domain.h"
-
-#include "dns-type.h"
-#include "resolved-dns-question.h"
-
-DnsQuestion *dns_question_new(unsigned n) {
- DnsQuestion *q;
-
- assert(n > 0);
-
- q = malloc0(offsetof(DnsQuestion, keys) + sizeof(DnsResourceKey*) * n);
- if (!q)
- return NULL;
-
- q->n_ref = 1;
- q->n_allocated = n;
-
- return q;
-}
-
-DnsQuestion *dns_question_ref(DnsQuestion *q) {
- if (!q)
- return NULL;
-
- assert(q->n_ref > 0);
- q->n_ref++;
- return q;
-}
-
-DnsQuestion *dns_question_unref(DnsQuestion *q) {
- if (!q)
- return NULL;
-
- assert(q->n_ref > 0);
-
- if (q->n_ref == 1) {
- unsigned i;
-
- for (i = 0; i < q->n_keys; i++)
- dns_resource_key_unref(q->keys[i]);
- free(q);
- } else
- q->n_ref--;
-
- return NULL;
-}
-
-int dns_question_add(DnsQuestion *q, DnsResourceKey *key) {
- unsigned i;
- int r;
-
- assert(key);
-
- if (!q)
- return -ENOSPC;
-
- for (i = 0; i < q->n_keys; i++) {
- r = dns_resource_key_equal(q->keys[i], key);
- if (r < 0)
- return r;
- if (r > 0)
- return 0;
- }
-
- if (q->n_keys >= q->n_allocated)
- return -ENOSPC;
-
- q->keys[q->n_keys++] = dns_resource_key_ref(key);
- return 0;
-}
-
-int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain) {
- unsigned i;
- int r;
-
- assert(rr);
-
- if (!q)
- return 0;
-
- for (i = 0; i < q->n_keys; i++) {
- r = dns_resource_key_match_rr(q->keys[i], rr, search_domain);
- if (r != 0)
- return r;
- }
-
- return 0;
-}
-
-int dns_question_matches_cname_or_dname(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain) {
- unsigned i;
- int r;
-
- assert(rr);
-
- if (!q)
- return 0;
-
- if (!IN_SET(rr->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME))
- return 0;
-
- for (i = 0; i < q->n_keys; i++) {
- /* For a {C,D}NAME record we can never find a matching {C,D}NAME record */
- if (!dns_type_may_redirect(q->keys[i]->type))
- return 0;
-
- r = dns_resource_key_match_cname_or_dname(q->keys[i], rr->key, search_domain);
- if (r != 0)
- return r;
- }
-
- return 0;
-}
-
-int dns_question_is_valid_for_query(DnsQuestion *q) {
- const char *name;
- unsigned i;
- int r;
-
- if (!q)
- return 0;
-
- if (q->n_keys <= 0)
- return 0;
-
- if (q->n_keys > 65535)
- return 0;
-
- name = dns_resource_key_name(q->keys[0]);
- if (!name)
- return 0;
-
- /* Check that all keys in this question bear the same name */
- for (i = 0; i < q->n_keys; i++) {
- assert(q->keys[i]);
-
- if (i > 0) {
- r = dns_name_equal(dns_resource_key_name(q->keys[i]), name);
- if (r <= 0)
- return r;
- }
-
- if (!dns_type_is_valid_query(q->keys[i]->type))
- return 0;
- }
-
- return 1;
-}
-
-int dns_question_contains(DnsQuestion *a, const DnsResourceKey *k) {
- unsigned j;
- int r;
-
- assert(k);
-
- if (!a)
- return 0;
-
- for (j = 0; j < a->n_keys; j++) {
- r = dns_resource_key_equal(a->keys[j], k);
- if (r != 0)
- return r;
- }
-
- return 0;
-}
-
-int dns_question_is_equal(DnsQuestion *a, DnsQuestion *b) {
- unsigned j;
- int r;
-
- if (a == b)
- return 1;
-
- if (!a)
- return !b || b->n_keys == 0;
- if (!b)
- return a->n_keys == 0;
-
- /* Checks if all keys in a are also contained b, and vice versa */
-
- for (j = 0; j < a->n_keys; j++) {
- r = dns_question_contains(b, a->keys[j]);
- if (r <= 0)
- return r;
- }
-
- for (j = 0; j < b->n_keys; j++) {
- r = dns_question_contains(a, b->keys[j]);
- if (r <= 0)
- return r;
- }
-
- return 1;
-}
-
-int dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname, DnsQuestion **ret) {
- _cleanup_(dns_question_unrefp) DnsQuestion *n = NULL;
- DnsResourceKey *key;
- bool same = true;
- int r;
-
- assert(cname);
- assert(ret);
- assert(IN_SET(cname->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME));
-
- if (dns_question_size(q) <= 0) {
- *ret = NULL;
- return 0;
- }
-
- DNS_QUESTION_FOREACH(key, q) {
- _cleanup_free_ char *destination = NULL;
- const char *d;
-
- if (cname->key->type == DNS_TYPE_CNAME)
- d = cname->cname.name;
- else {
- r = dns_name_change_suffix(dns_resource_key_name(key), dns_resource_key_name(cname->key), cname->dname.name, &destination);
- if (r < 0)
- return r;
- if (r == 0)
- continue;
-
- d = destination;
- }
-
- r = dns_name_equal(dns_resource_key_name(key), d);
- if (r < 0)
- return r;
-
- if (r == 0) {
- same = false;
- break;
- }
- }
-
- /* Fully the same, indicate we didn't do a thing */
- if (same) {
- *ret = NULL;
- return 0;
- }
-
- n = dns_question_new(q->n_keys);
- if (!n)
- return -ENOMEM;
-
- /* Create a new question, and patch in the new name */
- DNS_QUESTION_FOREACH(key, q) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *k = NULL;
-
- k = dns_resource_key_new_redirect(key, cname);
- if (!k)
- return -ENOMEM;
-
- r = dns_question_add(n, k);
- if (r < 0)
- return r;
- }
-
- *ret = n;
- n = NULL;
-
- return 1;
-}
-
-const char *dns_question_first_name(DnsQuestion *q) {
-
- if (!q)
- return NULL;
-
- if (q->n_keys < 1)
- return NULL;
-
- return dns_resource_key_name(q->keys[0]);
-}
-
-int dns_question_new_address(DnsQuestion **ret, int family, const char *name, bool convert_idna) {
- _cleanup_(dns_question_unrefp) DnsQuestion *q = NULL;
- _cleanup_free_ char *buf = NULL;
- int r;
-
- assert(ret);
- assert(name);
-
- if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
- return -EAFNOSUPPORT;
-
- if (convert_idna) {
- r = dns_name_apply_idna(name, &buf);
- if (r < 0)
- return r;
-
- name = buf;
- }
-
- q = dns_question_new(family == AF_UNSPEC ? 2 : 1);
- if (!q)
- return -ENOMEM;
-
- if (family != AF_INET6) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
-
- key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_A, name);
- if (!key)
- return -ENOMEM;
-
- r = dns_question_add(q, key);
- if (r < 0)
- return r;
- }
-
- if (family != AF_INET) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
-
- key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_AAAA, name);
- if (!key)
- return -ENOMEM;
-
- r = dns_question_add(q, key);
- if (r < 0)
- return r;
- }
-
- *ret = q;
- q = NULL;
-
- return 0;
-}
-
-int dns_question_new_reverse(DnsQuestion **ret, int family, const union in_addr_union *a) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
- _cleanup_(dns_question_unrefp) DnsQuestion *q = NULL;
- _cleanup_free_ char *reverse = NULL;
- int r;
-
- assert(ret);
- assert(a);
-
- if (!IN_SET(family, AF_INET, AF_INET6, AF_UNSPEC))
- return -EAFNOSUPPORT;
-
- r = dns_name_reverse(family, a, &reverse);
- if (r < 0)
- return r;
-
- q = dns_question_new(1);
- if (!q)
- return -ENOMEM;
-
- key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, reverse);
- if (!key)
- return -ENOMEM;
-
- reverse = NULL;
-
- r = dns_question_add(q, key);
- if (r < 0)
- return r;
-
- *ret = q;
- q = NULL;
-
- return 0;
-}
-
-int dns_question_new_service(
- DnsQuestion **ret,
- const char *service,
- const char *type,
- const char *domain,
- bool with_txt,
- bool convert_idna) {
-
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
- _cleanup_(dns_question_unrefp) DnsQuestion *q = NULL;
- _cleanup_free_ char *buf = NULL, *joined = NULL;
- const char *name;
- int r;
-
- assert(ret);
-
- /* We support three modes of invocation:
- *
- * 1. Only a domain is specified, in which case we assume a properly encoded SRV RR name, including service
- * type and possibly a service name. If specified in this way we assume it's already IDNA converted if
- * that's necessary.
- *
- * 2. Both service type and a domain specified, in which case a normal SRV RR is assumed, without a DNS-SD
- * style prefix. In this case we'll IDNA convert the domain, if that's requested.
- *
- * 3. All three of service name, type and domain are specified, in which case a DNS-SD service is put
- * together. The service name is never IDNA converted, and the domain is if requested.
- *
- * It's not supported to specify a service name without a type, or no domain name.
- */
-
- if (!domain)
- return -EINVAL;
-
- if (type) {
- if (convert_idna) {
- r = dns_name_apply_idna(domain, &buf);
- if (r < 0)
- return r;
-
- domain = buf;
- }
-
- r = dns_service_join(service, type, domain, &joined);
- if (r < 0)
- return r;
-
- name = joined;
- } else {
- if (service)
- return -EINVAL;
-
- name = domain;
- }
-
- q = dns_question_new(1 + with_txt);
- if (!q)
- return -ENOMEM;
-
- key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_SRV, name);
- if (!key)
- return -ENOMEM;
-
- r = dns_question_add(q, key);
- if (r < 0)
- return r;
-
- if (with_txt) {
- dns_resource_key_unref(key);
- key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_TXT, name);
- if (!key)
- return -ENOMEM;
-
- r = dns_question_add(q, key);
- if (r < 0)
- return r;
- }
-
- *ret = q;
- q = NULL;
-
- return 0;
-}
diff --git a/src/grp-resolve/systemd-resolved/resolved-dns-question.h b/src/grp-resolve/systemd-resolved/resolved-dns-question.h
deleted file mode 100644
index 320bf53488..0000000000
--- a/src/grp-resolve/systemd-resolved/resolved-dns-question.h
+++ /dev/null
@@ -1,70 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "basic/macro.h"
-
-typedef struct DnsQuestion DnsQuestion;
-
-#include "resolved-dns-rr.h"
-
-/* A simple array of resource keys */
-
-struct DnsQuestion {
- unsigned n_ref;
- unsigned n_keys, n_allocated;
- DnsResourceKey* keys[0];
-};
-
-DnsQuestion *dns_question_new(unsigned n);
-DnsQuestion *dns_question_ref(DnsQuestion *q);
-DnsQuestion *dns_question_unref(DnsQuestion *q);
-
-int dns_question_new_address(DnsQuestion **ret, int family, const char *name, bool convert_idna);
-int dns_question_new_reverse(DnsQuestion **ret, int family, const union in_addr_union *a);
-int dns_question_new_service(DnsQuestion **ret, const char *service, const char *type, const char *domain, bool with_txt, bool convert_idna);
-
-int dns_question_add(DnsQuestion *q, DnsResourceKey *key);
-
-int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain);
-int dns_question_matches_cname_or_dname(DnsQuestion *q, DnsResourceRecord *rr, const char* search_domain);
-int dns_question_is_valid_for_query(DnsQuestion *q);
-int dns_question_contains(DnsQuestion *a, const DnsResourceKey *k);
-int dns_question_is_equal(DnsQuestion *a, DnsQuestion *b);
-
-int dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname, DnsQuestion **ret);
-
-const char *dns_question_first_name(DnsQuestion *q);
-
-static inline unsigned dns_question_size(DnsQuestion *q) {
- return q ? q->n_keys : 0;
-}
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQuestion*, dns_question_unref);
-
-#define _DNS_QUESTION_FOREACH(u, key, q) \
- for (unsigned UNIQ_T(i, u) = ({ \
- (key) = ((q) && (q)->n_keys > 0) ? (q)->keys[0] : NULL; \
- 0; \
- }); \
- (q) && (UNIQ_T(i, u) < (q)->n_keys); \
- UNIQ_T(i, u)++, (key) = (UNIQ_T(i, u) < (q)->n_keys ? (q)->keys[UNIQ_T(i, u)] : NULL))
-
-#define DNS_QUESTION_FOREACH(key, q) _DNS_QUESTION_FOREACH(UNIQ, key, q)
diff --git a/src/grp-resolve/systemd-resolved/resolved-dns-rr.c b/src/grp-resolve/systemd-resolved/resolved-dns-rr.c
deleted file mode 100644
index c6a60b65b7..0000000000
--- a/src/grp-resolve/systemd-resolved/resolved-dns-rr.c
+++ /dev/null
@@ -1,1595 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <math.h>
-
-#include "basic/alloc-util.h"
-#include "basic/escape.h"
-#include "basic/hexdecoct.h"
-#include "basic/string-table.h"
-#include "basic/string-util.h"
-#include "basic/strv.h"
-#include "basic/terminal-util.h"
-#include "shared/dns-domain.h"
-
-#include "dns-type.h"
-#include "resolved-dns-dnssec.h"
-#include "resolved-dns-packet.h"
-#include "resolved-dns-rr.h"
-
-DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name) {
- DnsResourceKey *k;
- size_t l;
-
- assert(name);
-
- l = strlen(name);
- k = malloc0(sizeof(DnsResourceKey) + l + 1);
- if (!k)
- return NULL;
-
- k->n_ref = 1;
- k->class = class;
- k->type = type;
-
- strcpy((char*) k + sizeof(DnsResourceKey), name);
-
- return k;
-}
-
-DnsResourceKey* dns_resource_key_new_redirect(const DnsResourceKey *key, const DnsResourceRecord *cname) {
- int r;
-
- assert(key);
- assert(cname);
-
- assert(IN_SET(cname->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME));
-
- if (cname->key->type == DNS_TYPE_CNAME)
- return dns_resource_key_new(key->class, key->type, cname->cname.name);
- else {
- DnsResourceKey *k;
- char *destination = NULL;
-
- r = dns_name_change_suffix(dns_resource_key_name(key), dns_resource_key_name(cname->key), cname->dname.name, &destination);
- if (r < 0)
- return NULL;
- if (r == 0)
- return dns_resource_key_ref((DnsResourceKey*) key);
-
- k = dns_resource_key_new_consume(key->class, key->type, destination);
- if (!k) {
- free(destination);
- return NULL;
- }
-
- return k;
- }
-}
-
-int dns_resource_key_new_append_suffix(DnsResourceKey **ret, DnsResourceKey *key, char *name) {
- DnsResourceKey *new_key;
- char *joined;
- int r;
-
- assert(ret);
- assert(key);
- assert(name);
-
- if (dns_name_is_root(name)) {
- *ret = dns_resource_key_ref(key);
- return 0;
- }
-
- r = dns_name_concat(dns_resource_key_name(key), name, &joined);
- if (r < 0)
- return r;
-
- new_key = dns_resource_key_new_consume(key->class, key->type, joined);
- if (!new_key) {
- free(joined);
- return -ENOMEM;
- }
-
- *ret = new_key;
- return 0;
-}
-
-DnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name) {
- DnsResourceKey *k;
-
- assert(name);
-
- k = new0(DnsResourceKey, 1);
- if (!k)
- return NULL;
-
- k->n_ref = 1;
- k->class = class;
- k->type = type;
- k->_name = name;
-
- return k;
-}
-
-DnsResourceKey* dns_resource_key_ref(DnsResourceKey *k) {
-
- if (!k)
- return NULL;
-
- /* Static/const keys created with DNS_RESOURCE_KEY_CONST will
- * set this to -1, they should not be reffed/unreffed */
- assert(k->n_ref != (unsigned) -1);
-
- assert(k->n_ref > 0);
- k->n_ref++;
-
- return k;
-}
-
-DnsResourceKey* dns_resource_key_unref(DnsResourceKey *k) {
- if (!k)
- return NULL;
-
- assert(k->n_ref != (unsigned) -1);
- assert(k->n_ref > 0);
-
- if (k->n_ref == 1) {
- free(k->_name);
- free(k);
- } else
- k->n_ref--;
-
- return NULL;
-}
-
-const char* dns_resource_key_name(const DnsResourceKey *key) {
- const char *name;
-
- if (!key)
- return NULL;
-
- if (key->_name)
- name = key->_name;
- else
- name = (char*) key + sizeof(DnsResourceKey);
-
- if (dns_name_is_root(name))
- return ".";
- else
- return name;
-}
-
-bool dns_resource_key_is_address(const DnsResourceKey *key) {
- assert(key);
-
- /* Check if this is an A or AAAA resource key */
-
- return key->class == DNS_CLASS_IN && IN_SET(key->type, DNS_TYPE_A, DNS_TYPE_AAAA);
-}
-
-int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b) {
- int r;
-
- if (a == b)
- return 1;
-
- r = dns_name_equal(dns_resource_key_name(a), dns_resource_key_name(b));
- if (r <= 0)
- return r;
-
- if (a->class != b->class)
- return 0;
-
- if (a->type != b->type)
- return 0;
-
- return 1;
-}
-
-int dns_resource_key_match_rr(const DnsResourceKey *key, DnsResourceRecord *rr, const char *search_domain) {
- int r;
-
- assert(key);
- assert(rr);
-
- if (key == rr->key)
- return 1;
-
- /* Checks if an rr matches the specified key. If a search
- * domain is specified, it will also be checked if the key
- * with the search domain suffixed might match the RR. */
-
- if (rr->key->class != key->class && key->class != DNS_CLASS_ANY)
- return 0;
-
- if (rr->key->type != key->type && key->type != DNS_TYPE_ANY)
- return 0;
-
- r = dns_name_equal(dns_resource_key_name(rr->key), dns_resource_key_name(key));
- if (r != 0)
- return r;
-
- if (search_domain) {
- _cleanup_free_ char *joined = NULL;
-
- r = dns_name_concat(dns_resource_key_name(key), search_domain, &joined);
- if (r < 0)
- return r;
-
- return dns_name_equal(dns_resource_key_name(rr->key), joined);
- }
-
- return 0;
-}
-
-int dns_resource_key_match_cname_or_dname(const DnsResourceKey *key, const DnsResourceKey *cname, const char *search_domain) {
- int r;
-
- assert(key);
- assert(cname);
-
- if (cname->class != key->class && key->class != DNS_CLASS_ANY)
- return 0;
-
- if (cname->type == DNS_TYPE_CNAME)
- r = dns_name_equal(dns_resource_key_name(key), dns_resource_key_name(cname));
- else if (cname->type == DNS_TYPE_DNAME)
- r = dns_name_endswith(dns_resource_key_name(key), dns_resource_key_name(cname));
- else
- return 0;
-
- if (r != 0)
- return r;
-
- if (search_domain) {
- _cleanup_free_ char *joined = NULL;
-
- r = dns_name_concat(dns_resource_key_name(key), search_domain, &joined);
- if (r < 0)
- return r;
-
- if (cname->type == DNS_TYPE_CNAME)
- return dns_name_equal(joined, dns_resource_key_name(cname));
- else if (cname->type == DNS_TYPE_DNAME)
- return dns_name_endswith(joined, dns_resource_key_name(cname));
- }
-
- return 0;
-}
-
-int dns_resource_key_match_soa(const DnsResourceKey *key, const DnsResourceKey *soa) {
- assert(soa);
- assert(key);
-
- /* Checks whether 'soa' is a SOA record for the specified key. */
-
- if (soa->class != key->class)
- return 0;
-
- if (soa->type != DNS_TYPE_SOA)
- return 0;
-
- return dns_name_endswith(dns_resource_key_name(key), dns_resource_key_name(soa));
-}
-
-static void dns_resource_key_hash_func(const void *i, struct siphash *state) {
- const DnsResourceKey *k = i;
-
- assert(k);
-
- dns_name_hash_func(dns_resource_key_name(k), state);
- siphash24_compress(&k->class, sizeof(k->class), state);
- siphash24_compress(&k->type, sizeof(k->type), state);
-}
-
-static int dns_resource_key_compare_func(const void *a, const void *b) {
- const DnsResourceKey *x = a, *y = b;
- int ret;
-
- ret = dns_name_compare_func(dns_resource_key_name(x), dns_resource_key_name(y));
- if (ret != 0)
- return ret;
-
- if (x->type < y->type)
- return -1;
- if (x->type > y->type)
- return 1;
-
- if (x->class < y->class)
- return -1;
- if (x->class > y->class)
- return 1;
-
- return 0;
-}
-
-const struct hash_ops dns_resource_key_hash_ops = {
- .hash = dns_resource_key_hash_func,
- .compare = dns_resource_key_compare_func
-};
-
-char* dns_resource_key_to_string(const DnsResourceKey *key, char *buf, size_t buf_size) {
- const char *c, *t;
- char *ans = buf;
-
- /* If we cannot convert the CLASS/TYPE into a known string,
- use the format recommended by RFC 3597, Section 5. */
-
- c = dns_class_to_string(key->class);
- t = dns_type_to_string(key->type);
-
- snprintf(buf, buf_size, "%s %s%s%.0u %s%s%.0u",
- dns_resource_key_name(key),
- c ?: "", c ? "" : "CLASS", c ? 0 : key->class,
- t ?: "", t ? "" : "TYPE", t ? 0 : key->class);
-
- return ans;
-}
-
-bool dns_resource_key_reduce(DnsResourceKey **a, DnsResourceKey **b) {
- assert(a);
- assert(b);
-
- /* Try to replace one RR key by another if they are identical, thus saving a bit of memory. Note that we do
- * this only for RR keys, not for RRs themselves, as they carry a lot of additional metadata (where they come
- * from, validity data, and suchlike), and cannot be replaced so easily by other RRs that have the same
- * superficial data. */
-
- if (!*a)
- return false;
- if (!*b)
- return false;
-
- /* We refuse merging const keys */
- if ((*a)->n_ref == (unsigned) -1)
- return false;
- if ((*b)->n_ref == (unsigned) -1)
- return false;
-
- /* Already the same? */
- if (*a == *b)
- return true;
-
- /* Are they really identical? */
- if (dns_resource_key_equal(*a, *b) <= 0)
- return false;
-
- /* Keep the one which already has more references. */
- if ((*a)->n_ref > (*b)->n_ref) {
- dns_resource_key_unref(*b);
- *b = dns_resource_key_ref(*a);
- } else {
- dns_resource_key_unref(*a);
- *a = dns_resource_key_ref(*b);
- }
-
- return true;
-}
-
-DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key) {
- DnsResourceRecord *rr;
-
- rr = new0(DnsResourceRecord, 1);
- if (!rr)
- return NULL;
-
- rr->n_ref = 1;
- rr->key = dns_resource_key_ref(key);
- rr->expiry = USEC_INFINITY;
- rr->n_skip_labels_signer = rr->n_skip_labels_source = (unsigned) -1;
-
- return rr;
-}
-
-DnsResourceRecord* dns_resource_record_new_full(uint16_t class, uint16_t type, const char *name) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
-
- key = dns_resource_key_new(class, type, name);
- if (!key)
- return NULL;
-
- return dns_resource_record_new(key);
-}
-
-DnsResourceRecord* dns_resource_record_ref(DnsResourceRecord *rr) {
- if (!rr)
- return NULL;
-
- assert(rr->n_ref > 0);
- rr->n_ref++;
-
- return rr;
-}
-
-DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) {
- if (!rr)
- return NULL;
-
- assert(rr->n_ref > 0);
-
- if (rr->n_ref > 1) {
- rr->n_ref--;
- return NULL;
- }
-
- if (rr->key) {
- switch(rr->key->type) {
-
- case DNS_TYPE_SRV:
- free(rr->srv.name);
- break;
-
- case DNS_TYPE_PTR:
- case DNS_TYPE_NS:
- case DNS_TYPE_CNAME:
- case DNS_TYPE_DNAME:
- free(rr->ptr.name);
- break;
-
- case DNS_TYPE_HINFO:
- free(rr->hinfo.cpu);
- free(rr->hinfo.os);
- break;
-
- case DNS_TYPE_TXT:
- case DNS_TYPE_SPF:
- dns_txt_item_free_all(rr->txt.items);
- break;
-
- case DNS_TYPE_SOA:
- free(rr->soa.mname);
- free(rr->soa.rname);
- break;
-
- case DNS_TYPE_MX:
- free(rr->mx.exchange);
- break;
-
- case DNS_TYPE_DS:
- free(rr->ds.digest);
- break;
-
- case DNS_TYPE_SSHFP:
- free(rr->sshfp.fingerprint);
- break;
-
- case DNS_TYPE_DNSKEY:
- free(rr->dnskey.key);
- break;
-
- case DNS_TYPE_RRSIG:
- free(rr->rrsig.signer);
- free(rr->rrsig.signature);
- break;
-
- case DNS_TYPE_NSEC:
- free(rr->nsec.next_domain_name);
- bitmap_free(rr->nsec.types);
- break;
-
- case DNS_TYPE_NSEC3:
- free(rr->nsec3.next_hashed_name);
- free(rr->nsec3.salt);
- bitmap_free(rr->nsec3.types);
- break;
-
- case DNS_TYPE_LOC:
- case DNS_TYPE_A:
- case DNS_TYPE_AAAA:
- break;
-
- case DNS_TYPE_TLSA:
- free(rr->tlsa.data);
- break;
-
- case DNS_TYPE_CAA:
- free(rr->caa.tag);
- free(rr->caa.value);
- break;
-
- case DNS_TYPE_OPENPGPKEY:
- default:
- free(rr->generic.data);
- }
-
- free(rr->wire_format);
- dns_resource_key_unref(rr->key);
- }
-
- free(rr->to_string);
- free(rr);
-
- return NULL;
-}
-
-int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *hostname) {
- _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
- _cleanup_free_ char *ptr = NULL;
- int r;
-
- assert(ret);
- assert(address);
- assert(hostname);
-
- r = dns_name_reverse(family, address, &ptr);
- if (r < 0)
- return r;
-
- key = dns_resource_key_new_consume(DNS_CLASS_IN, DNS_TYPE_PTR, ptr);
- if (!key)
- return -ENOMEM;
-
- ptr = NULL;
-
- rr = dns_resource_record_new(key);
- if (!rr)
- return -ENOMEM;
-
- rr->ptr.name = strdup(hostname);
- if (!rr->ptr.name)
- return -ENOMEM;
-
- *ret = rr;
- rr = NULL;
-
- return 0;
-}
-
-int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name) {
- DnsResourceRecord *rr;
-
- assert(ret);
- assert(address);
- assert(family);
-
- if (family == AF_INET) {
-
- rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, name);
- if (!rr)
- return -ENOMEM;
-
- rr->a.in_addr = address->in;
-
- } else if (family == AF_INET6) {
-
- rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_AAAA, name);
- if (!rr)
- return -ENOMEM;
-
- rr->aaaa.in6_addr = address->in6;
- } else
- return -EAFNOSUPPORT;
-
- *ret = rr;
-
- return 0;
-}
-
-#define FIELD_EQUAL(a, b, field) \
- ((a).field ## _size == (b).field ## _size && \
- memcmp((a).field, (b).field, (a).field ## _size) == 0)
-
-int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
- int r;
-
- assert(a);
- assert(b);
-
- if (a == b)
- return 1;
-
- r = dns_resource_key_equal(a->key, b->key);
- if (r <= 0)
- return r;
-
- if (a->unparseable != b->unparseable)
- return 0;
-
- switch (a->unparseable ? _DNS_TYPE_INVALID : a->key->type) {
-
- case DNS_TYPE_SRV:
- r = dns_name_equal(a->srv.name, b->srv.name);
- if (r <= 0)
- return r;
-
- return a->srv.priority == b->srv.priority &&
- a->srv.weight == b->srv.weight &&
- a->srv.port == b->srv.port;
-
- case DNS_TYPE_PTR:
- case DNS_TYPE_NS:
- case DNS_TYPE_CNAME:
- case DNS_TYPE_DNAME:
- return dns_name_equal(a->ptr.name, b->ptr.name);
-
- case DNS_TYPE_HINFO:
- return strcaseeq(a->hinfo.cpu, b->hinfo.cpu) &&
- strcaseeq(a->hinfo.os, b->hinfo.os);
-
- case DNS_TYPE_SPF: /* exactly the same as TXT */
- case DNS_TYPE_TXT:
- return dns_txt_item_equal(a->txt.items, b->txt.items);
-
- case DNS_TYPE_A:
- return memcmp(&a->a.in_addr, &b->a.in_addr, sizeof(struct in_addr)) == 0;
-
- case DNS_TYPE_AAAA:
- return memcmp(&a->aaaa.in6_addr, &b->aaaa.in6_addr, sizeof(struct in6_addr)) == 0;
-
- case DNS_TYPE_SOA:
- r = dns_name_equal(a->soa.mname, b->soa.mname);
- if (r <= 0)
- return r;
- r = dns_name_equal(a->soa.rname, b->soa.rname);
- if (r <= 0)
- return r;
-
- return a->soa.serial == b->soa.serial &&
- a->soa.refresh == b->soa.refresh &&
- a->soa.retry == b->soa.retry &&
- a->soa.expire == b->soa.expire &&
- a->soa.minimum == b->soa.minimum;
-
- case DNS_TYPE_MX:
- if (a->mx.priority != b->mx.priority)
- return 0;
-
- return dns_name_equal(a->mx.exchange, b->mx.exchange);
-
- case DNS_TYPE_LOC:
- assert(a->loc.version == b->loc.version);
-
- return a->loc.size == b->loc.size &&
- a->loc.horiz_pre == b->loc.horiz_pre &&
- a->loc.vert_pre == b->loc.vert_pre &&
- a->loc.latitude == b->loc.latitude &&
- a->loc.longitude == b->loc.longitude &&
- a->loc.altitude == b->loc.altitude;
-
- case DNS_TYPE_DS:
- return a->ds.key_tag == b->ds.key_tag &&
- a->ds.algorithm == b->ds.algorithm &&
- a->ds.digest_type == b->ds.digest_type &&
- FIELD_EQUAL(a->ds, b->ds, digest);
-
- case DNS_TYPE_SSHFP:
- return a->sshfp.algorithm == b->sshfp.algorithm &&
- a->sshfp.fptype == b->sshfp.fptype &&
- FIELD_EQUAL(a->sshfp, b->sshfp, fingerprint);
-
- case DNS_TYPE_DNSKEY:
- return a->dnskey.flags == b->dnskey.flags &&
- a->dnskey.protocol == b->dnskey.protocol &&
- a->dnskey.algorithm == b->dnskey.algorithm &&
- FIELD_EQUAL(a->dnskey, b->dnskey, key);
-
- case DNS_TYPE_RRSIG:
- /* do the fast comparisons first */
- return a->rrsig.type_covered == b->rrsig.type_covered &&
- a->rrsig.algorithm == b->rrsig.algorithm &&
- a->rrsig.labels == b->rrsig.labels &&
- a->rrsig.original_ttl == b->rrsig.original_ttl &&
- a->rrsig.expiration == b->rrsig.expiration &&
- a->rrsig.inception == b->rrsig.inception &&
- a->rrsig.key_tag == b->rrsig.key_tag &&
- FIELD_EQUAL(a->rrsig, b->rrsig, signature) &&
- dns_name_equal(a->rrsig.signer, b->rrsig.signer);
-
- case DNS_TYPE_NSEC:
- return dns_name_equal(a->nsec.next_domain_name, b->nsec.next_domain_name) &&
- bitmap_equal(a->nsec.types, b->nsec.types);
-
- case DNS_TYPE_NSEC3:
- return a->nsec3.algorithm == b->nsec3.algorithm &&
- a->nsec3.flags == b->nsec3.flags &&
- a->nsec3.iterations == b->nsec3.iterations &&
- FIELD_EQUAL(a->nsec3, b->nsec3, salt) &&
- FIELD_EQUAL(a->nsec3, b->nsec3, next_hashed_name) &&
- bitmap_equal(a->nsec3.types, b->nsec3.types);
-
- case DNS_TYPE_TLSA:
- return a->tlsa.cert_usage == b->tlsa.cert_usage &&
- a->tlsa.selector == b->tlsa.selector &&
- a->tlsa.matching_type == b->tlsa.matching_type &&
- FIELD_EQUAL(a->tlsa, b->tlsa, data);
-
- case DNS_TYPE_CAA:
- return a->caa.flags == b->caa.flags &&
- streq(a->caa.tag, b->caa.tag) &&
- FIELD_EQUAL(a->caa, b->caa, value);
-
- case DNS_TYPE_OPENPGPKEY:
- default:
- return FIELD_EQUAL(a->generic, b->generic, data);
- }
-}
-
-static char* format_location(uint32_t latitude, uint32_t longitude, uint32_t altitude,
- uint8_t size, uint8_t horiz_pre, uint8_t vert_pre) {
- char *s;
- char NS = latitude >= 1U<<31 ? 'N' : 'S';
- char EW = longitude >= 1U<<31 ? 'E' : 'W';
-
- int lat = latitude >= 1U<<31 ? (int) (latitude - (1U<<31)) : (int) ((1U<<31) - latitude);
- int lon = longitude >= 1U<<31 ? (int) (longitude - (1U<<31)) : (int) ((1U<<31) - longitude);
- double alt = altitude >= 10000000u ? altitude - 10000000u : -(double)(10000000u - altitude);
- double siz = (size >> 4) * exp10((double) (size & 0xF));
- double hor = (horiz_pre >> 4) * exp10((double) (horiz_pre & 0xF));
- double ver = (vert_pre >> 4) * exp10((double) (vert_pre & 0xF));
-
- if (asprintf(&s, "%d %d %.3f %c %d %d %.3f %c %.2fm %.2fm %.2fm %.2fm",
- (lat / 60000 / 60),
- (lat / 60000) % 60,
- (lat % 60000) / 1000.,
- NS,
- (lon / 60000 / 60),
- (lon / 60000) % 60,
- (lon % 60000) / 1000.,
- EW,
- alt / 100.,
- siz / 100.,
- hor / 100.,
- ver / 100.) < 0)
- return NULL;
-
- return s;
-}
-
-static int format_timestamp_dns(char *buf, size_t l, time_t sec) {
- struct tm tm;
-
- assert(buf);
- assert(l > strlen("YYYYMMDDHHmmSS"));
-
- if (!gmtime_r(&sec, &tm))
- return -EINVAL;
-
- if (strftime(buf, l, "%Y%m%d%H%M%S", &tm) <= 0)
- return -EINVAL;
-
- return 0;
-}
-
-static char *format_types(Bitmap *types) {
- _cleanup_strv_free_ char **strv = NULL;
- _cleanup_free_ char *str = NULL;
- Iterator i;
- unsigned type;
- int r;
-
- BITMAP_FOREACH(type, types, i) {
- if (dns_type_to_string(type)) {
- r = strv_extend(&strv, dns_type_to_string(type));
- if (r < 0)
- return NULL;
- } else {
- char *t;
-
- r = asprintf(&t, "TYPE%u", type);
- if (r < 0)
- return NULL;
-
- r = strv_consume(&strv, t);
- if (r < 0)
- return NULL;
- }
- }
-
- str = strv_join(strv, " ");
- if (!str)
- return NULL;
-
- return strjoin("( ", str, " )", NULL);
-}
-
-static char *format_txt(DnsTxtItem *first) {
- DnsTxtItem *i;
- size_t c = 1;
- char *p, *s;
-
- LIST_FOREACH(items, i, first)
- c += i->length * 4 + 3;
-
- p = s = new(char, c);
- if (!s)
- return NULL;
-
- LIST_FOREACH(items, i, first) {
- size_t j;
-
- if (i != first)
- *(p++) = ' ';
-
- *(p++) = '"';
-
- for (j = 0; j < i->length; j++) {
- if (i->data[j] < ' ' || i->data[j] == '"' || i->data[j] >= 127) {
- *(p++) = '\\';
- *(p++) = '0' + (i->data[j] / 100);
- *(p++) = '0' + ((i->data[j] / 10) % 10);
- *(p++) = '0' + (i->data[j] % 10);
- } else
- *(p++) = i->data[j];
- }
-
- *(p++) = '"';
- }
-
- *p = 0;
- return s;
-}
-
-const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
- _cleanup_free_ char *t = NULL;
- char *s, k[DNS_RESOURCE_KEY_STRING_MAX];
- int r;
-
- assert(rr);
-
- if (rr->to_string)
- return rr->to_string;
-
- dns_resource_key_to_string(rr->key, k, sizeof(k));
-
- switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
-
- case DNS_TYPE_SRV:
- r = asprintf(&s, "%s %u %u %u %s",
- k,
- rr->srv.priority,
- rr->srv.weight,
- rr->srv.port,
- strna(rr->srv.name));
- if (r < 0)
- return NULL;
- break;
-
- case DNS_TYPE_PTR:
- case DNS_TYPE_NS:
- case DNS_TYPE_CNAME:
- case DNS_TYPE_DNAME:
- s = strjoin(k, " ", rr->ptr.name, NULL);
- if (!s)
- return NULL;
-
- break;
-
- case DNS_TYPE_HINFO:
- s = strjoin(k, " ", rr->hinfo.cpu, " ", rr->hinfo.os, NULL);
- if (!s)
- return NULL;
- break;
-
- case DNS_TYPE_SPF: /* exactly the same as TXT */
- case DNS_TYPE_TXT:
- t = format_txt(rr->txt.items);
- if (!t)
- return NULL;
-
- s = strjoin(k, " ", t, NULL);
- if (!s)
- return NULL;
- break;
-
- case DNS_TYPE_A: {
- _cleanup_free_ char *x = NULL;
-
- r = in_addr_to_string(AF_INET, (const union in_addr_union*) &rr->a.in_addr, &x);
- if (r < 0)
- return NULL;
-
- s = strjoin(k, " ", x, NULL);
- if (!s)
- return NULL;
- break;
- }
-
- case DNS_TYPE_AAAA:
- r = in_addr_to_string(AF_INET6, (const union in_addr_union*) &rr->aaaa.in6_addr, &t);
- if (r < 0)
- return NULL;
-
- s = strjoin(k, " ", t, NULL);
- if (!s)
- return NULL;
- break;
-
- case DNS_TYPE_SOA:
- r = asprintf(&s, "%s %s %s %u %u %u %u %u",
- k,
- strna(rr->soa.mname),
- strna(rr->soa.rname),
- rr->soa.serial,
- rr->soa.refresh,
- rr->soa.retry,
- rr->soa.expire,
- rr->soa.minimum);
- if (r < 0)
- return NULL;
- break;
-
- case DNS_TYPE_MX:
- r = asprintf(&s, "%s %u %s",
- k,
- rr->mx.priority,
- rr->mx.exchange);
- if (r < 0)
- return NULL;
- break;
-
- case DNS_TYPE_LOC:
- assert(rr->loc.version == 0);
-
- t = format_location(rr->loc.latitude,
- rr->loc.longitude,
- rr->loc.altitude,
- rr->loc.size,
- rr->loc.horiz_pre,
- rr->loc.vert_pre);
- if (!t)
- return NULL;
-
- s = strjoin(k, " ", t, NULL);
- if (!s)
- return NULL;
- break;
-
- case DNS_TYPE_DS:
- t = hexmem(rr->ds.digest, rr->ds.digest_size);
- if (!t)
- return NULL;
-
- r = asprintf(&s, "%s %u %u %u %s",
- k,
- rr->ds.key_tag,
- rr->ds.algorithm,
- rr->ds.digest_type,
- t);
- if (r < 0)
- return NULL;
- break;
-
- case DNS_TYPE_SSHFP:
- t = hexmem(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size);
- if (!t)
- return NULL;
-
- r = asprintf(&s, "%s %u %u %s",
- k,
- rr->sshfp.algorithm,
- rr->sshfp.fptype,
- t);
- if (r < 0)
- return NULL;
- break;
-
- case DNS_TYPE_DNSKEY: {
- _cleanup_free_ char *alg = NULL;
- char *ss;
- int n;
- uint16_t key_tag;
-
- key_tag = dnssec_keytag(rr, true);
-
- r = dnssec_algorithm_to_string_alloc(rr->dnskey.algorithm, &alg);
- if (r < 0)
- return NULL;
-
- r = asprintf(&s, "%s %u %u %s %n",
- k,
- rr->dnskey.flags,
- rr->dnskey.protocol,
- alg,
- &n);
- if (r < 0)
- return NULL;
-
- r = base64_append(&s, n,
- rr->dnskey.key, rr->dnskey.key_size,
- 8, columns());
- if (r < 0)
- return NULL;
-
- r = asprintf(&ss, "%s\n"
- " -- Flags:%s%s%s\n"
- " -- Key tag: %u",
- s,
- rr->dnskey.flags & DNSKEY_FLAG_SEP ? " SEP" : "",
- rr->dnskey.flags & DNSKEY_FLAG_REVOKE ? " REVOKE" : "",
- rr->dnskey.flags & DNSKEY_FLAG_ZONE_KEY ? " ZONE_KEY" : "",
- key_tag);
- if (r < 0)
- return NULL;
- free(s);
- s = ss;
-
- break;
- }
-
- case DNS_TYPE_RRSIG: {
- _cleanup_free_ char *alg = NULL;
- char expiration[strlen("YYYYMMDDHHmmSS") + 1], inception[strlen("YYYYMMDDHHmmSS") + 1];
- const char *type;
- int n;
-
- type = dns_type_to_string(rr->rrsig.type_covered);
-
- r = dnssec_algorithm_to_string_alloc(rr->rrsig.algorithm, &alg);
- if (r < 0)
- return NULL;
-
- r = format_timestamp_dns(expiration, sizeof(expiration), rr->rrsig.expiration);
- if (r < 0)
- return NULL;
-
- r = format_timestamp_dns(inception, sizeof(inception), rr->rrsig.inception);
- if (r < 0)
- return NULL;
-
- /* TYPE?? follows
- * http://tools.ietf.org/html/rfc3597#section-5 */
-
- r = asprintf(&s, "%s %s%.*u %s %u %u %s %s %u %s %n",
- k,
- type ?: "TYPE",
- type ? 0 : 1, type ? 0u : (unsigned) rr->rrsig.type_covered,
- alg,
- rr->rrsig.labels,
- rr->rrsig.original_ttl,
- expiration,
- inception,
- rr->rrsig.key_tag,
- rr->rrsig.signer,
- &n);
- if (r < 0)
- return NULL;
-
- r = base64_append(&s, n,
- rr->rrsig.signature, rr->rrsig.signature_size,
- 8, columns());
- if (r < 0)
- return NULL;
-
- break;
- }
-
- case DNS_TYPE_NSEC:
- t = format_types(rr->nsec.types);
- if (!t)
- return NULL;
-
- r = asprintf(&s, "%s %s %s",
- k,
- rr->nsec.next_domain_name,
- t);
- if (r < 0)
- return NULL;
- break;
-
- case DNS_TYPE_NSEC3: {
- _cleanup_free_ char *salt = NULL, *hash = NULL;
-
- if (rr->nsec3.salt_size > 0) {
- salt = hexmem(rr->nsec3.salt, rr->nsec3.salt_size);
- if (!salt)
- return NULL;
- }
-
- hash = base32hexmem(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, false);
- if (!hash)
- return NULL;
-
- t = format_types(rr->nsec3.types);
- if (!t)
- return NULL;
-
- r = asprintf(&s, "%s %"PRIu8" %"PRIu8" %"PRIu16" %s %s %s",
- k,
- rr->nsec3.algorithm,
- rr->nsec3.flags,
- rr->nsec3.iterations,
- rr->nsec3.salt_size > 0 ? salt : "-",
- hash,
- t);
- if (r < 0)
- return NULL;
-
- break;
- }
-
- case DNS_TYPE_TLSA: {
- const char *cert_usage, *selector, *matching_type;
-
- cert_usage = tlsa_cert_usage_to_string(rr->tlsa.cert_usage);
- selector = tlsa_selector_to_string(rr->tlsa.selector);
- matching_type = tlsa_matching_type_to_string(rr->tlsa.matching_type);
-
- t = hexmem(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size);
- if (!t)
- return NULL;
-
- r = asprintf(&s,
- "%s %u %u %u %s\n"
- " -- Cert. usage: %s\n"
- " -- Selector: %s\n"
- " -- Matching type: %s",
- k,
- rr->tlsa.cert_usage,
- rr->tlsa.selector,
- rr->tlsa.matching_type,
- t,
- cert_usage,
- selector,
- matching_type);
- if (r < 0)
- return NULL;
-
- break;
- }
-
- case DNS_TYPE_CAA: {
- _cleanup_free_ char *value;
-
- value = octescape(rr->caa.value, rr->caa.value_size);
- if (!value)
- return NULL;
-
- r = asprintf(&s, "%s %u %s \"%s\"%s%s%s%.0u",
- k,
- rr->caa.flags,
- rr->caa.tag,
- value,
- rr->caa.flags ? "\n -- Flags:" : "",
- rr->caa.flags & CAA_FLAG_CRITICAL ? " critical" : "",
- rr->caa.flags & ~CAA_FLAG_CRITICAL ? " " : "",
- rr->caa.flags & ~CAA_FLAG_CRITICAL);
- if (r < 0)
- return NULL;
-
- break;
- }
-
- case DNS_TYPE_OPENPGPKEY: {
- int n;
-
- r = asprintf(&s, "%s %n",
- k,
- &n);
- if (r < 0)
- return NULL;
-
- r = base64_append(&s, n,
- rr->generic.data, rr->generic.data_size,
- 8, columns());
- if (r < 0)
- return NULL;
- break;
- }
-
- default:
- t = hexmem(rr->generic.data, rr->generic.data_size);
- if (!t)
- return NULL;
-
- /* Format as documented in RFC 3597, Section 5 */
- r = asprintf(&s, "%s \\# %zu %s", k, rr->generic.data_size, t);
- if (r < 0)
- return NULL;
- break;
- }
-
- rr->to_string = s;
- return s;
-}
-
-ssize_t dns_resource_record_payload(DnsResourceRecord *rr, void **out) {
- assert(rr);
- assert(out);
-
- switch(rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
- case DNS_TYPE_SRV:
- case DNS_TYPE_PTR:
- case DNS_TYPE_NS:
- case DNS_TYPE_CNAME:
- case DNS_TYPE_DNAME:
- case DNS_TYPE_HINFO:
- case DNS_TYPE_SPF:
- case DNS_TYPE_TXT:
- case DNS_TYPE_A:
- case DNS_TYPE_AAAA:
- case DNS_TYPE_SOA:
- case DNS_TYPE_MX:
- case DNS_TYPE_LOC:
- case DNS_TYPE_DS:
- case DNS_TYPE_DNSKEY:
- case DNS_TYPE_RRSIG:
- case DNS_TYPE_NSEC:
- case DNS_TYPE_NSEC3:
- return -EINVAL;
-
- case DNS_TYPE_SSHFP:
- *out = rr->sshfp.fingerprint;
- return rr->sshfp.fingerprint_size;
-
- case DNS_TYPE_TLSA:
- *out = rr->tlsa.data;
- return rr->tlsa.data_size;
-
-
- case DNS_TYPE_OPENPGPKEY:
- default:
- *out = rr->generic.data;
- return rr->generic.data_size;
- }
-}
-
-int dns_resource_record_to_wire_format(DnsResourceRecord *rr, bool canonical) {
-
- DnsPacket packet = {
- .n_ref = 1,
- .protocol = DNS_PROTOCOL_DNS,
- .on_stack = true,
- .refuse_compression = true,
- .canonical_form = canonical,
- };
-
- size_t start, rds;
- int r;
-
- assert(rr);
-
- /* Generates the RR in wire-format, optionally in the
- * canonical form as discussed in the DNSSEC RFC 4034, Section
- * 6.2. We allocate a throw-away DnsPacket object on the stack
- * here, because we need some book-keeping for memory
- * management, and can reuse the DnsPacket serializer, that
- * can generate the canonical form, too, but also knows label
- * compression and suchlike. */
-
- if (rr->wire_format && rr->wire_format_canonical == canonical)
- return 0;
-
- r = dns_packet_append_rr(&packet, rr, &start, &rds);
- if (r < 0)
- return r;
-
- assert(start == 0);
- assert(packet._data);
-
- free(rr->wire_format);
- rr->wire_format = packet._data;
- rr->wire_format_size = packet.size;
- rr->wire_format_rdata_offset = rds;
- rr->wire_format_canonical = canonical;
-
- packet._data = NULL;
- dns_packet_unref(&packet);
-
- return 0;
-}
-
-int dns_resource_record_signer(DnsResourceRecord *rr, const char **ret) {
- const char *n;
- int r;
-
- assert(rr);
- assert(ret);
-
- /* Returns the RRset's signer, if it is known. */
-
- if (rr->n_skip_labels_signer == (unsigned) -1)
- return -ENODATA;
-
- n = dns_resource_key_name(rr->key);
- r = dns_name_skip(n, rr->n_skip_labels_signer, &n);
- if (r < 0)
- return r;
- if (r == 0)
- return -EINVAL;
-
- *ret = n;
- return 0;
-}
-
-int dns_resource_record_source(DnsResourceRecord *rr, const char **ret) {
- const char *n;
- int r;
-
- assert(rr);
- assert(ret);
-
- /* Returns the RRset's synthesizing source, if it is known. */
-
- if (rr->n_skip_labels_source == (unsigned) -1)
- return -ENODATA;
-
- n = dns_resource_key_name(rr->key);
- r = dns_name_skip(n, rr->n_skip_labels_source, &n);
- if (r < 0)
- return r;
- if (r == 0)
- return -EINVAL;
-
- *ret = n;
- return 0;
-}
-
-int dns_resource_record_is_signer(DnsResourceRecord *rr, const char *zone) {
- const char *signer;
- int r;
-
- assert(rr);
-
- r = dns_resource_record_signer(rr, &signer);
- if (r < 0)
- return r;
-
- return dns_name_equal(zone, signer);
-}
-
-int dns_resource_record_is_synthetic(DnsResourceRecord *rr) {
- int r;
-
- assert(rr);
-
- /* Returns > 0 if the RR is generated from a wildcard, and is not the asterisk name itself */
-
- if (rr->n_skip_labels_source == (unsigned) -1)
- return -ENODATA;
-
- if (rr->n_skip_labels_source == 0)
- return 0;
-
- if (rr->n_skip_labels_source > 1)
- return 1;
-
- r = dns_name_startswith(dns_resource_key_name(rr->key), "*");
- if (r < 0)
- return r;
-
- return !r;
-}
-
-void dns_resource_record_hash_func(const void *i, struct siphash *state) {
- const DnsResourceRecord *rr = i;
-
- assert(rr);
-
- dns_resource_key_hash_func(rr->key, state);
-
- switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
-
- case DNS_TYPE_SRV:
- siphash24_compress(&rr->srv.priority, sizeof(rr->srv.priority), state);
- siphash24_compress(&rr->srv.weight, sizeof(rr->srv.weight), state);
- siphash24_compress(&rr->srv.port, sizeof(rr->srv.port), state);
- dns_name_hash_func(rr->srv.name, state);
- break;
-
- case DNS_TYPE_PTR:
- case DNS_TYPE_NS:
- case DNS_TYPE_CNAME:
- case DNS_TYPE_DNAME:
- dns_name_hash_func(rr->ptr.name, state);
- break;
-
- case DNS_TYPE_HINFO:
- string_hash_func(rr->hinfo.cpu, state);
- string_hash_func(rr->hinfo.os, state);
- break;
-
- case DNS_TYPE_TXT:
- case DNS_TYPE_SPF: {
- DnsTxtItem *j;
-
- LIST_FOREACH(items, j, rr->txt.items) {
- siphash24_compress(j->data, j->length, state);
-
- /* Add an extra NUL byte, so that "a" followed by "b" doesn't result in the same hash as "ab"
- * followed by "". */
- siphash24_compress_byte(0, state);
- }
- break;
- }
-
- case DNS_TYPE_A:
- siphash24_compress(&rr->a.in_addr, sizeof(rr->a.in_addr), state);
- break;
-
- case DNS_TYPE_AAAA:
- siphash24_compress(&rr->aaaa.in6_addr, sizeof(rr->aaaa.in6_addr), state);
- break;
-
- case DNS_TYPE_SOA:
- dns_name_hash_func(rr->soa.mname, state);
- dns_name_hash_func(rr->soa.rname, state);
- siphash24_compress(&rr->soa.serial, sizeof(rr->soa.serial), state);
- siphash24_compress(&rr->soa.refresh, sizeof(rr->soa.refresh), state);
- siphash24_compress(&rr->soa.retry, sizeof(rr->soa.retry), state);
- siphash24_compress(&rr->soa.expire, sizeof(rr->soa.expire), state);
- siphash24_compress(&rr->soa.minimum, sizeof(rr->soa.minimum), state);
- break;
-
- case DNS_TYPE_MX:
- siphash24_compress(&rr->mx.priority, sizeof(rr->mx.priority), state);
- dns_name_hash_func(rr->mx.exchange, state);
- break;
-
- case DNS_TYPE_LOC:
- siphash24_compress(&rr->loc.version, sizeof(rr->loc.version), state);
- siphash24_compress(&rr->loc.size, sizeof(rr->loc.size), state);
- siphash24_compress(&rr->loc.horiz_pre, sizeof(rr->loc.horiz_pre), state);
- siphash24_compress(&rr->loc.vert_pre, sizeof(rr->loc.vert_pre), state);
- siphash24_compress(&rr->loc.latitude, sizeof(rr->loc.latitude), state);
- siphash24_compress(&rr->loc.longitude, sizeof(rr->loc.longitude), state);
- siphash24_compress(&rr->loc.altitude, sizeof(rr->loc.altitude), state);
- break;
-
- case DNS_TYPE_SSHFP:
- siphash24_compress(&rr->sshfp.algorithm, sizeof(rr->sshfp.algorithm), state);
- siphash24_compress(&rr->sshfp.fptype, sizeof(rr->sshfp.fptype), state);
- siphash24_compress(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, state);
- break;
-
- case DNS_TYPE_DNSKEY:
- siphash24_compress(&rr->dnskey.flags, sizeof(rr->dnskey.flags), state);
- siphash24_compress(&rr->dnskey.protocol, sizeof(rr->dnskey.protocol), state);
- siphash24_compress(&rr->dnskey.algorithm, sizeof(rr->dnskey.algorithm), state);
- siphash24_compress(rr->dnskey.key, rr->dnskey.key_size, state);
- break;
-
- case DNS_TYPE_RRSIG:
- siphash24_compress(&rr->rrsig.type_covered, sizeof(rr->rrsig.type_covered), state);
- siphash24_compress(&rr->rrsig.algorithm, sizeof(rr->rrsig.algorithm), state);
- siphash24_compress(&rr->rrsig.labels, sizeof(rr->rrsig.labels), state);
- siphash24_compress(&rr->rrsig.original_ttl, sizeof(rr->rrsig.original_ttl), state);
- siphash24_compress(&rr->rrsig.expiration, sizeof(rr->rrsig.expiration), state);
- siphash24_compress(&rr->rrsig.inception, sizeof(rr->rrsig.inception), state);
- siphash24_compress(&rr->rrsig.key_tag, sizeof(rr->rrsig.key_tag), state);
- dns_name_hash_func(rr->rrsig.signer, state);
- siphash24_compress(rr->rrsig.signature, rr->rrsig.signature_size, state);
- break;
-
- case DNS_TYPE_NSEC:
- dns_name_hash_func(rr->nsec.next_domain_name, state);
- /* FIXME: we leave out the type bitmap here. Hash
- * would be better if we'd take it into account
- * too. */
- break;
-
- case DNS_TYPE_DS:
- siphash24_compress(&rr->ds.key_tag, sizeof(rr->ds.key_tag), state);
- siphash24_compress(&rr->ds.algorithm, sizeof(rr->ds.algorithm), state);
- siphash24_compress(&rr->ds.digest_type, sizeof(rr->ds.digest_type), state);
- siphash24_compress(rr->ds.digest, rr->ds.digest_size, state);
- break;
-
- case DNS_TYPE_NSEC3:
- siphash24_compress(&rr->nsec3.algorithm, sizeof(rr->nsec3.algorithm), state);
- siphash24_compress(&rr->nsec3.flags, sizeof(rr->nsec3.flags), state);
- siphash24_compress(&rr->nsec3.iterations, sizeof(rr->nsec3.iterations), state);
- siphash24_compress(rr->nsec3.salt, rr->nsec3.salt_size, state);
- siphash24_compress(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, state);
- /* FIXME: We leave the bitmaps out */
- break;
-
- case DNS_TYPE_TLSA:
- siphash24_compress(&rr->tlsa.cert_usage, sizeof(rr->tlsa.cert_usage), state);
- siphash24_compress(&rr->tlsa.selector, sizeof(rr->tlsa.selector), state);
- siphash24_compress(&rr->tlsa.matching_type, sizeof(rr->tlsa.matching_type), state);
- siphash24_compress(rr->tlsa.data, rr->tlsa.data_size, state);
- break;
-
- case DNS_TYPE_CAA:
- siphash24_compress(&rr->caa.flags, sizeof(rr->caa.flags), state);
- string_hash_func(rr->caa.tag, state);
- siphash24_compress(rr->caa.value, rr->caa.value_size, state);
- break;
-
- case DNS_TYPE_OPENPGPKEY:
- default:
- siphash24_compress(rr->generic.data, rr->generic.data_size, state);
- break;
- }
-}
-
-static int dns_resource_record_compare_func(const void *a, const void *b) {
- const DnsResourceRecord *x = a, *y = b;
- int ret;
-
- ret = dns_resource_key_compare_func(x->key, y->key);
- if (ret != 0)
- return ret;
-
- if (dns_resource_record_equal(x, y))
- return 0;
-
- /* This is a bit dirty, we don't implement proper ordering, but
- * the hashtable doesn't need ordering anyway, hence we don't
- * care. */
- return x < y ? -1 : 1;
-}
-
-const struct hash_ops dns_resource_record_hash_ops = {
- .hash = dns_resource_record_hash_func,
- .compare = dns_resource_record_compare_func,
-};
-
-DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i) {
- DnsTxtItem *n;
-
- if (!i)
- return NULL;
-
- n = i->items_next;
-
- free(i);
- return dns_txt_item_free_all(n);
-}
-
-bool dns_txt_item_equal(DnsTxtItem *a, DnsTxtItem *b) {
-
- if (a == b)
- return true;
-
- if (!a != !b)
- return false;
-
- if (!a)
- return true;
-
- if (a->length != b->length)
- return false;
-
- if (memcmp(a->data, b->data, a->length) != 0)
- return false;
-
- return dns_txt_item_equal(a->items_next, b->items_next);
-}
-
-static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = {
- /* Mnemonics as listed on https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
- [DNSSEC_ALGORITHM_RSAMD5] = "RSAMD5",
- [DNSSEC_ALGORITHM_DH] = "DH",
- [DNSSEC_ALGORITHM_DSA] = "DSA",
- [DNSSEC_ALGORITHM_ECC] = "ECC",
- [DNSSEC_ALGORITHM_RSASHA1] = "RSASHA1",
- [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1] = "DSA-NSEC3-SHA1",
- [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1] = "RSASHA1-NSEC3-SHA1",
- [DNSSEC_ALGORITHM_RSASHA256] = "RSASHA256",
- [DNSSEC_ALGORITHM_RSASHA512] = "RSASHA512",
- [DNSSEC_ALGORITHM_ECC_GOST] = "ECC-GOST",
- [DNSSEC_ALGORITHM_ECDSAP256SHA256] = "ECDSAP256SHA256",
- [DNSSEC_ALGORITHM_ECDSAP384SHA384] = "ECDSAP384SHA384",
- [DNSSEC_ALGORITHM_INDIRECT] = "INDIRECT",
- [DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS",
- [DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID",
-};
-DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_algorithm, int, 255);
-
-static const char* const dnssec_digest_table[_DNSSEC_DIGEST_MAX_DEFINED] = {
- /* Names as listed on https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
- [DNSSEC_DIGEST_SHA1] = "SHA-1",
- [DNSSEC_DIGEST_SHA256] = "SHA-256",
- [DNSSEC_DIGEST_GOST_R_34_11_94] = "GOST_R_34.11-94",
- [DNSSEC_DIGEST_SHA384] = "SHA-384",
-};
-DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_digest, int, 255);
diff --git a/src/grp-resolve/systemd-resolved/resolved-dns-rr.h b/src/grp-resolve/systemd-resolved/resolved-dns-rr.h
deleted file mode 100644
index daf9c8c210..0000000000
--- a/src/grp-resolve/systemd-resolved/resolved-dns-rr.h
+++ /dev/null
@@ -1,343 +0,0 @@
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
- ***/
-
-#include <netinet/in.h>
-
-#include "basic/bitmap.h"
-#include "basic/hashmap.h"
-#include "basic/in-addr-util.h"
-#include "basic/list.h"
-#include "basic/string-util.h"
-
-#include "dns-type.h"
-
-typedef struct DnsResourceKey DnsResourceKey;
-typedef struct DnsResourceRecord DnsResourceRecord;
-typedef struct DnsTxtItem DnsTxtItem;
-
-/* DNSKEY RR flags */
-#define DNSKEY_FLAG_SEP (UINT16_C(1) << 0)
-#define DNSKEY_FLAG_REVOKE (UINT16_C(1) << 7)
-#define DNSKEY_FLAG_ZONE_KEY (UINT16_C(1) << 8)
-
-/* mDNS RR flags */
-#define MDNS_RR_CACHE_FLUSH (UINT16_C(1) << 15)
-
-/* DNSSEC algorithm identifiers, see
- * http://tools.ietf.org/html/rfc4034#appendix-A.1 and
- * https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
-enum {
- DNSSEC_ALGORITHM_RSAMD5 = 1,
- DNSSEC_ALGORITHM_DH,
- DNSSEC_ALGORITHM_DSA,
- DNSSEC_ALGORITHM_ECC,
- DNSSEC_ALGORITHM_RSASHA1,
- DNSSEC_ALGORITHM_DSA_NSEC3_SHA1,
- DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1,
- DNSSEC_ALGORITHM_RSASHA256 = 8, /* RFC 5702 */
- DNSSEC_ALGORITHM_RSASHA512 = 10, /* RFC 5702 */
- DNSSEC_ALGORITHM_ECC_GOST = 12, /* RFC 5933 */
- DNSSEC_ALGORITHM_ECDSAP256SHA256 = 13, /* RFC 6605 */
- DNSSEC_ALGORITHM_ECDSAP384SHA384 = 14, /* RFC 6605 */
- DNSSEC_ALGORITHM_INDIRECT = 252,
- DNSSEC_ALGORITHM_PRIVATEDNS,
- DNSSEC_ALGORITHM_PRIVATEOID,
- _DNSSEC_ALGORITHM_MAX_DEFINED
-};
-
-/* DNSSEC digest identifiers, see
- * https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
-enum {
- DNSSEC_DIGEST_SHA1 = 1,
- DNSSEC_DIGEST_SHA256 = 2, /* RFC 4509 */
- DNSSEC_DIGEST_GOST_R_34_11_94 = 3, /* RFC 5933 */
- DNSSEC_DIGEST_SHA384 = 4, /* RFC 6605 */
- _DNSSEC_DIGEST_MAX_DEFINED
-};
-
-/* DNSSEC NSEC3 hash algorithms, see
- * https://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml */
-enum {
- NSEC3_ALGORITHM_SHA1 = 1,
- _NSEC3_ALGORITHM_MAX_DEFINED
-};
-
-struct DnsResourceKey {
- unsigned n_ref; /* (unsigned -1) for const keys, see below */
- uint16_t class, type;
- char *_name; /* don't access directly, use dns_resource_key_name()! */
-};
-
-/* Creates a temporary resource key. This is only useful to quickly
- * look up something, without allocating a full DnsResourceKey object
- * for it. Note that it is not OK to take references to this kind of
- * resource key object. */
-#define DNS_RESOURCE_KEY_CONST(c, t, n) \
- ((DnsResourceKey) { \
- .n_ref = (unsigned) -1, \
- .class = c, \
- .type = t, \
- ._name = (char*) n, \
- })
-
-
-struct DnsTxtItem {
- size_t length;
- LIST_FIELDS(DnsTxtItem, items);
- uint8_t data[];
-};
-
-struct DnsResourceRecord {
- unsigned n_ref;
- DnsResourceKey *key;
-
- char *to_string;
-
- uint32_t ttl;
- usec_t expiry; /* RRSIG signature expiry */
-
- /* How many labels to strip to determine "signer" of the RRSIG (aka, the zone). -1 if not signed. */
- unsigned n_skip_labels_signer;
- /* How many labels to strip to determine "synthesizing source" of this RR, i.e. the wildcard's immediate parent. -1 if not signed. */
- unsigned n_skip_labels_source;
-
- bool unparseable:1;
-
- bool wire_format_canonical:1;
- void *wire_format;
- size_t wire_format_size;
- size_t wire_format_rdata_offset;
-
- union {
- struct {
- void *data;
- size_t data_size;
- } generic, opt;
-
- struct {
- uint16_t priority;
- uint16_t weight;
- uint16_t port;
- char *name;
- } srv;
-
- struct {
- char *name;
- } ptr, ns, cname, dname;
-
- struct {
- char *cpu;
- char *os;
- } hinfo;
-
- struct {
- DnsTxtItem *items;
- } txt, spf;
-
- struct {
- struct in_addr in_addr;
- } a;
-
- struct {
- struct in6_addr in6_addr;
- } aaaa;
-
- struct {
- char *mname;
- char *rname;
- uint32_t serial;
- uint32_t refresh;
- uint32_t retry;
- uint32_t expire;
- uint32_t minimum;
- } soa;
-
- struct {
- uint16_t priority;
- char *exchange;
- } mx;
-
- /* https://tools.ietf.org/html/rfc1876 */
- struct {
- uint8_t version;
- uint8_t size;
- uint8_t horiz_pre;
- uint8_t vert_pre;
- uint32_t latitude;
- uint32_t longitude;
- uint32_t altitude;
- } loc;
-
- /* https://tools.ietf.org/html/rfc4255#section-3.1 */
- struct {
- uint8_t algorithm;
- uint8_t fptype;
- void *fingerprint;
- size_t fingerprint_size;
- } sshfp;
-
- /* http://tools.ietf.org/html/rfc4034#section-2.1 */
- struct {
- uint16_t flags;
- uint8_t protocol;
- uint8_t algorithm;
- void* key;
- size_t key_size;
- } dnskey;
-
- /* http://tools.ietf.org/html/rfc4034#section-3.1 */
- struct {
- uint16_t type_covered;
- uint8_t algorithm;
- uint8_t labels;
- uint32_t original_ttl;
- uint32_t expiration;
- uint32_t inception;
- uint16_t key_tag;
- char *signer;
- void *signature;
- size_t signature_size;
- } rrsig;
-
- /* https://tools.ietf.org/html/rfc4034#section-4.1 */
- struct {
- char *next_domain_name;
- Bitmap *types;
- } nsec;
-
- /* https://tools.ietf.org/html/rfc4034#section-5.1 */
- struct {
- uint16_t key_tag;
- uint8_t algorithm;
- uint8_t digest_type;
- void *digest;
- size_t digest_size;
- } ds;
-
- struct {
- uint8_t algorithm;
- uint8_t flags;
- uint16_t iterations;
- void *salt;
- size_t salt_size;
- void *next_hashed_name;
- size_t next_hashed_name_size;
- Bitmap *types;
- } nsec3;
-
- /* https://tools.ietf.org/html/draft-ietf-dane-protocol-23 */
- struct {
- uint8_t cert_usage;
- uint8_t selector;
- uint8_t matching_type;
- void *data;
- size_t data_size;
- } tlsa;
-
- /* https://tools.ietf.org/html/rfc6844 */
- struct {
- uint8_t flags;
- char *tag;
- void *value;
- size_t value_size;
- } caa;
- };
-};
-
-static inline const void* DNS_RESOURCE_RECORD_RDATA(DnsResourceRecord *rr) {
- if (!rr)
- return NULL;
-
- if (!rr->wire_format)
- return NULL;
-
- assert(rr->wire_format_rdata_offset <= rr->wire_format_size);
- return (uint8_t*) rr->wire_format + rr->wire_format_rdata_offset;
-}
-
-static inline size_t DNS_RESOURCE_RECORD_RDATA_SIZE(DnsResourceRecord *rr) {
- if (!rr)
- return 0;
- if (!rr->wire_format)
- return 0;
-
- assert(rr->wire_format_rdata_offset <= rr->wire_format_size);
- return rr->wire_format_size - rr->wire_format_rdata_offset;
-}
-
-DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name);
-DnsResourceKey* dns_resource_key_new_redirect(const DnsResourceKey *key, const DnsResourceRecord *cname);
-int dns_resource_key_new_append_suffix(DnsResourceKey **ret, DnsResourceKey *key, char *name);
-DnsResourceKey* dns_resource_key_new_consume(uint16_t class, uint16_t type, char *name);
-DnsResourceKey* dns_resource_key_ref(DnsResourceKey *key);
-DnsResourceKey* dns_resource_key_unref(DnsResourceKey *key);
-const char* dns_resource_key_name(const DnsResourceKey *key);
-bool dns_resource_key_is_address(const DnsResourceKey *key);
-int dns_resource_key_equal(const DnsResourceKey *a, const DnsResourceKey *b);
-int dns_resource_key_match_rr(const DnsResourceKey *key, DnsResourceRecord *rr, const char *search_domain);
-int dns_resource_key_match_cname_or_dname(const DnsResourceKey *key, const DnsResourceKey *cname, const char *search_domain);
-int dns_resource_key_match_soa(const DnsResourceKey *key, const DnsResourceKey *soa);
-
-/* _DNS_{CLASS,TYPE}_STRING_MAX include one byte for NUL, which we use for space instead below.
- * DNS_HOSTNAME_MAX does not include the NUL byte, so we need to add 1. */
-#define DNS_RESOURCE_KEY_STRING_MAX (_DNS_CLASS_STRING_MAX + _DNS_TYPE_STRING_MAX + DNS_HOSTNAME_MAX + 1)
-
-char* dns_resource_key_to_string(const DnsResourceKey *key, char *buf, size_t buf_size);
-ssize_t dns_resource_record_payload(DnsResourceRecord *rr, void **out);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceKey*, dns_resource_key_unref);
-
-static inline bool dns_key_is_shared(const DnsResourceKey *key) {
- return IN_SET(key->type, DNS_TYPE_PTR);
-}
-
-bool dns_resource_key_reduce(DnsResourceKey **a, DnsResourceKey **b);
-
-DnsResourceRecord* dns_resource_record_new(DnsResourceKey *key);
-DnsResourceRecord* dns_resource_record_new_full(uint16_t class, uint16_t type, const char *name);
-DnsResourceRecord* dns_resource_record_ref(DnsResourceRecord *rr);
-DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr);
-int dns_resource_record_new_reverse(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name);
-int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const union in_addr_union *address, const char *name);
-int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b);
-const char* dns_resource_record_to_string(DnsResourceRecord *rr);
-DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceRecord*, dns_resource_record_unref);
-
-int dns_resource_record_to_wire_format(DnsResourceRecord *rr, bool canonical);
-
-int dns_resource_record_signer(DnsResourceRecord *rr, const char **ret);
-int dns_resource_record_source(DnsResourceRecord *rr, const char **ret);
-int dns_resource_record_is_signer(DnsResourceRecord *rr, const char *zone);
-int dns_resource_record_is_synthetic(DnsResourceRecord *rr);
-
-DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i);
-bool dns_txt_item_equal(DnsTxtItem *a, DnsTxtItem *b);
-
-void dns_resource_record_hash_func(const void *i, struct siphash *state);
-
-extern const struct hash_ops dns_resource_key_hash_ops;
-extern const struct hash_ops dns_resource_record_hash_ops;
-
-int dnssec_algorithm_to_string_alloc(int i, char **ret);
-int dnssec_algorithm_from_string(const char *s) _pure_;
-
-int dnssec_digest_to_string_alloc(int i, char **ret);
-int dnssec_digest_from_string(const char *s) _pure_;
diff --git a/src/grp-resolve/systemd-resolved/test-data/_443._tcp.fedoraproject.org.pkts b/src/grp-resolve/systemd-resolved/test-data/_443._tcp.fedoraproject.org.pkts
deleted file mode 100644
index a383c6286d..0000000000
--- a/src/grp-resolve/systemd-resolved/test-data/_443._tcp.fedoraproject.org.pkts
+++ /dev/null
Binary files differ
diff --git a/src/grp-resolve/systemd-resolved/test-data/_openpgpkey.fedoraproject.org.pkts b/src/grp-resolve/systemd-resolved/test-data/_openpgpkey.fedoraproject.org.pkts
deleted file mode 100644
index 15de02e997..0000000000
--- a/src/grp-resolve/systemd-resolved/test-data/_openpgpkey.fedoraproject.org.pkts
+++ /dev/null
Binary files differ
diff --git a/src/grp-resolve/systemd-resolved/test-data/fake-caa.pkts b/src/grp-resolve/systemd-resolved/test-data/fake-caa.pkts
deleted file mode 100644
index 1c3ecc5491..0000000000
--- a/src/grp-resolve/systemd-resolved/test-data/fake-caa.pkts
+++ /dev/null
Binary files differ
diff --git a/src/grp-resolve/systemd-resolved/test-data/fedoraproject.org.pkts b/src/grp-resolve/systemd-resolved/test-data/fedoraproject.org.pkts
deleted file mode 100644
index 17874844d9..0000000000
--- a/src/grp-resolve/systemd-resolved/test-data/fedoraproject.org.pkts
+++ /dev/null
Binary files differ
diff --git a/src/grp-resolve/systemd-resolved/test-data/gandi.net.pkts b/src/grp-resolve/systemd-resolved/test-data/gandi.net.pkts
deleted file mode 100644
index 5ef51e0c8e..0000000000
--- a/src/grp-resolve/systemd-resolved/test-data/gandi.net.pkts
+++ /dev/null
Binary files differ
diff --git a/src/grp-resolve/systemd-resolved/test-data/google.com.pkts b/src/grp-resolve/systemd-resolved/test-data/google.com.pkts
deleted file mode 100644
index f98c4cd855..0000000000
--- a/src/grp-resolve/systemd-resolved/test-data/google.com.pkts
+++ /dev/null
Binary files differ
diff --git a/src/grp-resolve/systemd-resolved/test-data/kyhwana.org.pkts b/src/grp-resolve/systemd-resolved/test-data/kyhwana.org.pkts
deleted file mode 100644
index e28a725c9a..0000000000
--- a/src/grp-resolve/systemd-resolved/test-data/kyhwana.org.pkts
+++ /dev/null
Binary files differ
diff --git a/src/grp-resolve/systemd-resolved/test-data/root.pkts b/src/grp-resolve/systemd-resolved/test-data/root.pkts
deleted file mode 100644
index 54ba668c75..0000000000
--- a/src/grp-resolve/systemd-resolved/test-data/root.pkts
+++ /dev/null
Binary files differ
diff --git a/src/grp-resolve/systemd-resolved/test-data/sw1a1aa-sw1a2aa-sw1a2ab-sw1a2ac.find.me.uk.pkts b/src/grp-resolve/systemd-resolved/test-data/sw1a1aa-sw1a2aa-sw1a2ab-sw1a2ac.find.me.uk.pkts
deleted file mode 100644
index a854249532..0000000000
--- a/src/grp-resolve/systemd-resolved/test-data/sw1a1aa-sw1a2aa-sw1a2ab-sw1a2ac.find.me.uk.pkts
+++ /dev/null
Binary files differ
diff --git a/src/grp-resolve/systemd-resolved/test-data/teamits.com.pkts b/src/grp-resolve/systemd-resolved/test-data/teamits.com.pkts
deleted file mode 100644
index 11deb39677..0000000000
--- a/src/grp-resolve/systemd-resolved/test-data/teamits.com.pkts
+++ /dev/null
Binary files differ
diff --git a/src/grp-resolve/systemd-resolved/test-data/zbyszek@fedoraproject.org.pkts b/src/grp-resolve/systemd-resolved/test-data/zbyszek@fedoraproject.org.pkts
deleted file mode 100644
index f0a6f982df..0000000000
--- a/src/grp-resolve/systemd-resolved/test-data/zbyszek@fedoraproject.org.pkts
+++ /dev/null
Binary files differ
diff --git a/src/grp-resolve/systemd-resolved/test-dns-packet.c b/src/grp-resolve/systemd-resolved/test-dns-packet.c
deleted file mode 100644
index 18d04b930d..0000000000
--- a/src/grp-resolve/systemd-resolved/test-dns-packet.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/***
- This file is part of systemd
-
- Copyright 2016 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <glob.h>
-#include <net/if.h>
-
-#include "basic/alloc-util.h"
-#include "basic/fileio.h"
-#include "basic/glob-util.h"
-#include "basic/log.h"
-#include "basic/macro.h"
-#include "basic/string-util.h"
-#include "basic/strv.h"
-
-#include "resolved-dns-packet.h"
-#include "resolved-dns-rr.h"
-
-#define HASH_KEY SD_ID128_MAKE(d3,1e,48,90,4b,fa,4c,fe,af,9d,d5,a1,d7,2e,8a,b1)
-
-static uint64_t hash(DnsResourceRecord *rr) {
- struct siphash state;
-
- siphash24_init(&state, HASH_KEY.bytes);
- dns_resource_record_hash_func(rr, &state);
- return siphash24_finalize(&state);
-}
-
-static void test_packet_from_file(const char* filename, bool canonical) {
- _cleanup_free_ char *data = NULL;
- size_t data_size, packet_size, offset;
-
- assert_se(read_full_file(filename, &data, &data_size) >= 0);
- assert_se(data);
- assert_se(data_size > 8);
-
- log_info("============== %s %s==============", filename, canonical ? "canonical " : "");
-
- for (offset = 0; offset < data_size; offset += 8 + packet_size) {
- _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL, *p2 = NULL;
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL, *rr2 = NULL;
- const char *s, *s2;
- uint64_t hash1, hash2;
-
- packet_size = le64toh( *(uint64_t*)(data + offset) );
- assert_se(packet_size > 0);
- assert_se(offset + 8 + packet_size <= data_size);
-
- assert_se(dns_packet_new(&p, DNS_PROTOCOL_DNS, 0) >= 0);
-
- assert_se(dns_packet_append_blob(p, data + offset + 8, packet_size, NULL) >= 0);
- assert_se(dns_packet_read_rr(p, &rr, NULL, NULL) >= 0);
-
- s = dns_resource_record_to_string(rr);
- assert_se(s);
- puts(s);
-
- hash1 = hash(rr);
-
- assert_se(dns_resource_record_to_wire_format(rr, canonical) >= 0);
-
- assert_se(dns_packet_new(&p2, DNS_PROTOCOL_DNS, 0) >= 0);
- assert_se(dns_packet_append_blob(p2, rr->wire_format, rr->wire_format_size, NULL) >= 0);
- assert_se(dns_packet_read_rr(p2, &rr2, NULL, NULL) >= 0);
-
- s2 = dns_resource_record_to_string(rr);
- assert_se(s2);
- assert_se(streq(s, s2));
-
- hash2 = hash(rr);
- assert_se(hash1 == hash2);
- }
-}
-
-int main(int argc, char **argv) {
- int i, N;
- _cleanup_globfree_ glob_t g = {};
- char **fnames;
-
- log_parse_environment();
-
- if (argc >= 2) {
- N = argc - 1;
- fnames = argv + 1;
- } else {
- assert_se(glob(RESOLVE_TEST_DIR "/*.pkts", GLOB_NOSORT, NULL, &g) == 0);
- N = g.gl_pathc;
- fnames = g.gl_pathv;
- }
-
- for (i = 0; i < N; i++) {
- test_packet_from_file(fnames[i], false);
- puts("");
- test_packet_from_file(fnames[i], true);
- if (i + 1 < N)
- puts("");
- }
-
- return EXIT_SUCCESS;
-}
diff --git a/src/grp-resolve/systemd-resolved/test-dnssec-complex.c b/src/grp-resolve/systemd-resolved/test-dnssec-complex.c
deleted file mode 100644
index ef78cd1ea5..0000000000
--- a/src/grp-resolve/systemd-resolved/test-dnssec-complex.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2016 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <netinet/ip.h>
-
-#include <systemd/sd-bus.h>
-
-#include "basic/af-list.h"
-#include "basic/alloc-util.h"
-#include "basic/random-util.h"
-#include "basic/string-util.h"
-#include "basic/time-util.h"
-#include "sd-bus/bus-common-errors.h"
-
-#include "dns-type.h"
-
-#define DNS_CALL_TIMEOUT_USEC (45*USEC_PER_SEC)
-
-static void prefix_random(const char *name, char **ret) {
- uint64_t i, u;
- char *m = NULL;
-
- u = 1 + (random_u64() & 3);
-
- for (i = 0; i < u; i++) {
- _cleanup_free_ char *b = NULL;
- char *x;
-
- assert_se(asprintf(&b, "x%" PRIu64 "x", random_u64()));
- x = strjoin(b, ".", name, NULL);
- assert_se(x);
-
- free(m);
- m = x;
- }
-
- *ret = m;
- }
-
-static void test_rr_lookup(sd_bus *bus, const char *name, uint16_t type, const char *result) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *m = NULL;
- int r;
-
- /* If the name starts with a dot, we prefix one to three random labels */
- if (startswith(name, ".")) {
- prefix_random(name + 1, &m);
- name = m;
- }
-
- assert_se(sd_bus_message_new_method_call(
- bus,
- &req,
- "org.freedesktop.resolve1",
- "/org/freedesktop/resolve1",
- "org.freedesktop.resolve1.Manager",
- "ResolveRecord") >= 0);
-
- assert_se(sd_bus_message_append(req, "isqqt", 0, name, DNS_CLASS_IN, type, UINT64_C(0)) >= 0);
-
- r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
-
- if (r < 0) {
- assert_se(result);
- assert_se(sd_bus_error_has_name(&error, result));
- log_info("[OK] %s/%s resulted in <%s>.", name, dns_type_to_string(type), error.name);
- } else {
- assert_se(!result);
- log_info("[OK] %s/%s succeeded.", name, dns_type_to_string(type));
- }
-}
-
-static void test_hostname_lookup(sd_bus *bus, const char *name, int family, const char *result) {
- _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
- _cleanup_free_ char *m = NULL;
- const char *af;
- int r;
-
- af = family == AF_UNSPEC ? "AF_UNSPEC" : af_to_name(family);
-
- /* If the name starts with a dot, we prefix one to three random labels */
- if (startswith(name, ".")) {
- prefix_random(name + 1, &m);
- name = m;
- }
-
- assert_se(sd_bus_message_new_method_call(
- bus,
- &req,
- "org.freedesktop.resolve1",
- "/org/freedesktop/resolve1",
- "org.freedesktop.resolve1.Manager",
- "ResolveHostname") >= 0);
-
- assert_se(sd_bus_message_append(req, "isit", 0, name, family, UINT64_C(0)) >= 0);
-
- r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
-
- if (r < 0) {
- assert_se(result);
- assert_se(sd_bus_error_has_name(&error, result));
- log_info("[OK] %s/%s resulted in <%s>.", name, af, error.name);
- } else {
- assert_se(!result);
- log_info("[OK] %s/%s succeeded.", name, af);
- }
-
-}
-
-int main(int argc, char* argv[]) {
- _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
-
- /* Note that this is a manual test as it requires:
- *
- * Full network access
- * A DNSSEC capable DNS server
- * That zones contacted are still set up as they were when I wrote this.
- */
-
- assert_se(sd_bus_open_system(&bus) >= 0);
-
- /* Normally signed */
- test_rr_lookup(bus, "www.eurid.eu", DNS_TYPE_A, NULL);
- test_hostname_lookup(bus, "www.eurid.eu", AF_UNSPEC, NULL);
-
- test_rr_lookup(bus, "sigok.verteiltesysteme.net", DNS_TYPE_A, NULL);
- test_hostname_lookup(bus, "sigok.verteiltesysteme.net", AF_UNSPEC, NULL);
-
- /* Normally signed, NODATA */
- test_rr_lookup(bus, "www.eurid.eu", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
- test_rr_lookup(bus, "sigok.verteiltesysteme.net", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
-
- /* Invalid signature */
- test_rr_lookup(bus, "sigfail.verteiltesysteme.net", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED);
- test_hostname_lookup(bus, "sigfail.verteiltesysteme.net", AF_INET, BUS_ERROR_DNSSEC_FAILED);
-
- /* Invalid signature, RSA, wildcard */
- test_rr_lookup(bus, ".wilda.rhybar.0skar.cz", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED);
- test_hostname_lookup(bus, ".wilda.rhybar.0skar.cz", AF_INET, BUS_ERROR_DNSSEC_FAILED);
-
- /* Invalid signature, ECDSA, wildcard */
- test_rr_lookup(bus, ".wilda.rhybar.ecdsa.0skar.cz", DNS_TYPE_A, BUS_ERROR_DNSSEC_FAILED);
- test_hostname_lookup(bus, ".wilda.rhybar.ecdsa.0skar.cz", AF_INET, BUS_ERROR_DNSSEC_FAILED);
-
- /* NXDOMAIN in NSEC domain */
- test_rr_lookup(bus, "hhh.nasa.gov", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN");
- test_hostname_lookup(bus, "hhh.nasa.gov", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN");
-
- /* wildcard, NSEC zone */
- test_rr_lookup(bus, ".wilda.nsec.0skar.cz", DNS_TYPE_A, NULL);
- test_hostname_lookup(bus, ".wilda.nsec.0skar.cz", AF_INET, NULL);
-
- /* wildcard, NSEC zone, NODATA */
- test_rr_lookup(bus, ".wilda.nsec.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
-
- /* wildcard, NSEC3 zone */
- test_rr_lookup(bus, ".wilda.0skar.cz", DNS_TYPE_A, NULL);
- test_hostname_lookup(bus, ".wilda.0skar.cz", AF_INET, NULL);
-
- /* wildcard, NSEC3 zone, NODATA */
- test_rr_lookup(bus, ".wilda.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
-
- /* wildcard, NSEC zone, CNAME */
- test_rr_lookup(bus, ".wild.nsec.0skar.cz", DNS_TYPE_A, NULL);
- test_hostname_lookup(bus, ".wild.nsec.0skar.cz", AF_UNSPEC, NULL);
- test_hostname_lookup(bus, ".wild.nsec.0skar.cz", AF_INET, NULL);
-
- /* wildcard, NSEC zone, NODATA, CNAME */
- test_rr_lookup(bus, ".wild.nsec.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
-
- /* wildcard, NSEC3 zone, CNAME */
- test_rr_lookup(bus, ".wild.0skar.cz", DNS_TYPE_A, NULL);
- test_hostname_lookup(bus, ".wild.0skar.cz", AF_UNSPEC, NULL);
- test_hostname_lookup(bus, ".wild.0skar.cz", AF_INET, NULL);
-
- /* wildcard, NSEC3 zone, NODATA, CNAME */
- test_rr_lookup(bus, ".wild.0skar.cz", DNS_TYPE_RP, BUS_ERROR_NO_SUCH_RR);
-
- /* NODATA due to empty non-terminal in NSEC domain */
- test_rr_lookup(bus, "herndon.nasa.gov", DNS_TYPE_A, BUS_ERROR_NO_SUCH_RR);
- test_hostname_lookup(bus, "herndon.nasa.gov", AF_UNSPEC, BUS_ERROR_NO_SUCH_RR);
- test_hostname_lookup(bus, "herndon.nasa.gov", AF_INET, BUS_ERROR_NO_SUCH_RR);
- test_hostname_lookup(bus, "herndon.nasa.gov", AF_INET6, BUS_ERROR_NO_SUCH_RR);
-
- /* NXDOMAIN in NSEC root zone: */
- test_rr_lookup(bus, "jasdhjas.kjkfgjhfjg", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN");
- test_hostname_lookup(bus, "jasdhjas.kjkfgjhfjg", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN");
- test_hostname_lookup(bus, "jasdhjas.kjkfgjhfjg", AF_INET, _BUS_ERROR_DNS "NXDOMAIN");
- test_hostname_lookup(bus, "jasdhjas.kjkfgjhfjg", AF_INET6, _BUS_ERROR_DNS "NXDOMAIN");
-
- /* NXDOMAIN in NSEC3 .com zone: */
- test_rr_lookup(bus, "kjkfgjhfjgsdfdsfd.com", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN");
- test_hostname_lookup(bus, "kjkfgjhfjgsdfdsfd.com", AF_INET, _BUS_ERROR_DNS "NXDOMAIN");
- test_hostname_lookup(bus, "kjkfgjhfjgsdfdsfd.com", AF_INET6, _BUS_ERROR_DNS "NXDOMAIN");
- test_hostname_lookup(bus, "kjkfgjhfjgsdfdsfd.com", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN");
-
- /* Unsigned A */
- test_rr_lookup(bus, "poettering.de", DNS_TYPE_A, NULL);
- test_rr_lookup(bus, "poettering.de", DNS_TYPE_AAAA, NULL);
- test_hostname_lookup(bus, "poettering.de", AF_UNSPEC, NULL);
- test_hostname_lookup(bus, "poettering.de", AF_INET, NULL);
- test_hostname_lookup(bus, "poettering.de", AF_INET6, NULL);
-
-#ifdef HAVE_LIBIDN
- /* Unsigned A with IDNA conversion necessary */
- test_hostname_lookup(bus, "pöttering.de", AF_UNSPEC, NULL);
- test_hostname_lookup(bus, "pöttering.de", AF_INET, NULL);
- test_hostname_lookup(bus, "pöttering.de", AF_INET6, NULL);
-#endif
-
- /* DNAME, pointing to NXDOMAIN */
- test_rr_lookup(bus, ".ireallyhpoethisdoesnexist.xn--kprw13d.", DNS_TYPE_A, _BUS_ERROR_DNS "NXDOMAIN");
- test_rr_lookup(bus, ".ireallyhpoethisdoesnexist.xn--kprw13d.", DNS_TYPE_RP, _BUS_ERROR_DNS "NXDOMAIN");
- test_hostname_lookup(bus, ".ireallyhpoethisdoesntexist.xn--kprw13d.", AF_UNSPEC, _BUS_ERROR_DNS "NXDOMAIN");
- test_hostname_lookup(bus, ".ireallyhpoethisdoesntexist.xn--kprw13d.", AF_INET, _BUS_ERROR_DNS "NXDOMAIN");
- test_hostname_lookup(bus, ".ireallyhpoethisdoesntexist.xn--kprw13d.", AF_INET6, _BUS_ERROR_DNS "NXDOMAIN");
-
- return 0;
-}
diff --git a/src/grp-resolve/systemd-resolved/test-dnssec.c b/src/grp-resolve/systemd-resolved/test-dnssec.c
deleted file mode 100644
index 1f05196d8e..0000000000
--- a/src/grp-resolve/systemd-resolved/test-dnssec.c
+++ /dev/null
@@ -1,344 +0,0 @@
-/***
- This file is part of systemd.
-
- Copyright 2015 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-
-#include "basic/alloc-util.h"
-#include "basic/hexdecoct.h"
-#include "basic/string-util.h"
-
-#include "resolved-dns-dnssec.h"
-#include "resolved-dns-rr.h"
-
-static void test_dnssec_canonicalize_one(const char *original, const char *canonical, int r) {
- char canonicalized[DNSSEC_CANONICAL_HOSTNAME_MAX];
-
- assert_se(dnssec_canonicalize(original, canonicalized, sizeof(canonicalized)) == r);
- if (r < 0)
- return;
-
- assert_se(streq(canonicalized, canonical));
-}
-
-static void test_dnssec_canonicalize(void) {
- test_dnssec_canonicalize_one("", ".", 1);
- test_dnssec_canonicalize_one(".", ".", 1);
- test_dnssec_canonicalize_one("foo", "foo.", 4);
- test_dnssec_canonicalize_one("foo.", "foo.", 4);
- test_dnssec_canonicalize_one("FOO.", "foo.", 4);
- test_dnssec_canonicalize_one("FOO.bar.", "foo.bar.", 8);
- test_dnssec_canonicalize_one("FOO..bar.", NULL, -EINVAL);
-}
-
-#ifdef HAVE_GCRYPT
-
-static void test_dnssec_verify_dns_key(void) {
-
- static const uint8_t ds1_fprint[] = {
- 0x46, 0x8B, 0xC8, 0xDD, 0xC7, 0xE8, 0x27, 0x03, 0x40, 0xBB, 0x8A, 0x1F, 0x3B, 0x2E, 0x45, 0x9D,
- 0x80, 0x67, 0x14, 0x01,
- };
- static const uint8_t ds2_fprint[] = {
- 0x8A, 0xEE, 0x80, 0x47, 0x05, 0x5F, 0x83, 0xD1, 0x48, 0xBA, 0x8F, 0xF6, 0xDD, 0xA7, 0x60, 0xCE,
- 0x94, 0xF7, 0xC7, 0x5E, 0x52, 0x4C, 0xF2, 0xE9, 0x50, 0xB9, 0x2E, 0xCB, 0xEF, 0x96, 0xB9, 0x98,
- };
- static const uint8_t dnskey_blob[] = {
- 0x03, 0x01, 0x00, 0x01, 0xa8, 0x12, 0xda, 0x4f, 0xd2, 0x7d, 0x54, 0x14, 0x0e, 0xcc, 0x5b, 0x5e,
- 0x45, 0x9c, 0x96, 0x98, 0xc0, 0xc0, 0x85, 0x81, 0xb1, 0x47, 0x8c, 0x7d, 0xe8, 0x39, 0x50, 0xcc,
- 0xc5, 0xd0, 0xf2, 0x00, 0x81, 0x67, 0x79, 0xf6, 0xcc, 0x9d, 0xad, 0x6c, 0xbb, 0x7b, 0x6f, 0x48,
- 0x97, 0x15, 0x1c, 0xfd, 0x0b, 0xfe, 0xd3, 0xd7, 0x7d, 0x9f, 0x81, 0x26, 0xd3, 0xc5, 0x65, 0x49,
- 0xcf, 0x46, 0x62, 0xb0, 0x55, 0x6e, 0x47, 0xc7, 0x30, 0xef, 0x51, 0xfb, 0x3e, 0xc6, 0xef, 0xde,
- 0x27, 0x3f, 0xfa, 0x57, 0x2d, 0xa7, 0x1d, 0x80, 0x46, 0x9a, 0x5f, 0x14, 0xb3, 0xb0, 0x2c, 0xbe,
- 0x72, 0xca, 0xdf, 0xb2, 0xff, 0x36, 0x5b, 0x4f, 0xec, 0x58, 0x8e, 0x8d, 0x01, 0xe9, 0xa9, 0xdf,
- 0xb5, 0x60, 0xad, 0x52, 0x4d, 0xfc, 0xa9, 0x3e, 0x8d, 0x35, 0x95, 0xb3, 0x4e, 0x0f, 0xca, 0x45,
- 0x1b, 0xf7, 0xef, 0x3a, 0x88, 0x25, 0x08, 0xc7, 0x4e, 0x06, 0xc1, 0x62, 0x1a, 0xce, 0xd8, 0x77,
- 0xbd, 0x02, 0x65, 0xf8, 0x49, 0xfb, 0xce, 0xf6, 0xa8, 0x09, 0xfc, 0xde, 0xb2, 0x09, 0x9d, 0x39,
- 0xf8, 0x63, 0x9c, 0x32, 0x42, 0x7c, 0xa0, 0x30, 0x86, 0x72, 0x7a, 0x4a, 0xc6, 0xd4, 0xb3, 0x2d,
- 0x24, 0xef, 0x96, 0x3f, 0xc2, 0xda, 0xd3, 0xf2, 0x15, 0x6f, 0xda, 0x65, 0x4b, 0x81, 0x28, 0x68,
- 0xf4, 0xfe, 0x3e, 0x71, 0x4f, 0x50, 0x96, 0x72, 0x58, 0xa1, 0x89, 0xdd, 0x01, 0x61, 0x39, 0x39,
- 0xc6, 0x76, 0xa4, 0xda, 0x02, 0x70, 0x3d, 0xc0, 0xdc, 0x8d, 0x70, 0x72, 0x04, 0x90, 0x79, 0xd4,
- 0xec, 0x65, 0xcf, 0x49, 0x35, 0x25, 0x3a, 0x14, 0x1a, 0x45, 0x20, 0xeb, 0x31, 0xaf, 0x92, 0xba,
- 0x20, 0xd3, 0xcd, 0xa7, 0x13, 0x44, 0xdc, 0xcf, 0xf0, 0x27, 0x34, 0xb9, 0xe7, 0x24, 0x6f, 0x73,
- 0xe7, 0xea, 0x77, 0x03,
- };
-
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *dnskey = NULL, *ds1 = NULL, *ds2 = NULL;
-
- /* The two DS RRs in effect for nasa.gov on 2015-12-01. */
- ds1 = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "nasa.gov");
- assert_se(ds1);
-
- ds1->ds.key_tag = 47857;
- ds1->ds.algorithm = DNSSEC_ALGORITHM_RSASHA256;
- ds1->ds.digest_type = DNSSEC_DIGEST_SHA1;
- ds1->ds.digest_size = sizeof(ds1_fprint);
- ds1->ds.digest = memdup(ds1_fprint, ds1->ds.digest_size);
- assert_se(ds1->ds.digest);
-
- log_info("DS1: %s", strna(dns_resource_record_to_string(ds1)));
-
- ds2 = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DS, "NASA.GOV");
- assert_se(ds2);
-
- ds2->ds.key_tag = 47857;
- ds2->ds.algorithm = DNSSEC_ALGORITHM_RSASHA256;
- ds2->ds.digest_type = DNSSEC_DIGEST_SHA256;
- ds2->ds.digest_size = sizeof(ds2_fprint);
- ds2->ds.digest = memdup(ds2_fprint, ds2->ds.digest_size);
- assert_se(ds2->ds.digest);
-
- log_info("DS2: %s", strna(dns_resource_record_to_string(ds2)));
-
- dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nasa.GOV");
- assert_se(dnskey);
-
- dnskey->dnskey.flags = 257;
- dnskey->dnskey.protocol = 3;
- dnskey->dnskey.algorithm = DNSSEC_ALGORITHM_RSASHA256;
- dnskey->dnskey.key_size = sizeof(dnskey_blob);
- dnskey->dnskey.key = memdup(dnskey_blob, sizeof(dnskey_blob));
- assert_se(dnskey->dnskey.key);
-
- log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey)));
- log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey, false));
-
- assert_se(dnssec_verify_dnskey_by_ds(dnskey, ds1, false) > 0);
- assert_se(dnssec_verify_dnskey_by_ds(dnskey, ds2, false) > 0);
-}
-
-static void test_dnssec_verify_rrset(void) {
-
- static const uint8_t signature_blob[] = {
- 0x7f, 0x79, 0xdd, 0x5e, 0x89, 0x79, 0x18, 0xd0, 0x34, 0x86, 0x8c, 0x72, 0x77, 0x75, 0x48, 0x4d,
- 0xc3, 0x7d, 0x38, 0x04, 0xab, 0xcd, 0x9e, 0x4c, 0x82, 0xb0, 0x92, 0xca, 0xe9, 0x66, 0xe9, 0x6e,
- 0x47, 0xc7, 0x68, 0x8c, 0x94, 0xf6, 0x69, 0xcb, 0x75, 0x94, 0xe6, 0x30, 0xa6, 0xfb, 0x68, 0x64,
- 0x96, 0x1a, 0x84, 0xe1, 0xdc, 0x16, 0x4c, 0x83, 0x6c, 0x44, 0xf2, 0x74, 0x4d, 0x74, 0x79, 0x8f,
- 0xf3, 0xf4, 0x63, 0x0d, 0xef, 0x5a, 0xe7, 0xe2, 0xfd, 0xf2, 0x2b, 0x38, 0x7c, 0x28, 0x96, 0x9d,
- 0xb6, 0xcd, 0x5c, 0x3b, 0x57, 0xe2, 0x24, 0x78, 0x65, 0xd0, 0x9e, 0x77, 0x83, 0x09, 0x6c, 0xff,
- 0x3d, 0x52, 0x3f, 0x6e, 0xd1, 0xed, 0x2e, 0xf9, 0xee, 0x8e, 0xa6, 0xbe, 0x9a, 0xa8, 0x87, 0x76,
- 0xd8, 0x77, 0xcc, 0x96, 0xa0, 0x98, 0xa1, 0xd1, 0x68, 0x09, 0x43, 0xcf, 0x56, 0xd9, 0xd1, 0x66,
- };
-
- static const uint8_t dnskey_blob[] = {
- 0x03, 0x01, 0x00, 0x01, 0x9b, 0x49, 0x9b, 0xc1, 0xf9, 0x9a, 0xe0, 0x4e, 0xcf, 0xcb, 0x14, 0x45,
- 0x2e, 0xc9, 0xf9, 0x74, 0xa7, 0x18, 0xb5, 0xf3, 0xde, 0x39, 0x49, 0xdf, 0x63, 0x33, 0x97, 0x52,
- 0xe0, 0x8e, 0xac, 0x50, 0x30, 0x8e, 0x09, 0xd5, 0x24, 0x3d, 0x26, 0xa4, 0x49, 0x37, 0x2b, 0xb0,
- 0x6b, 0x1b, 0xdf, 0xde, 0x85, 0x83, 0xcb, 0x22, 0x4e, 0x60, 0x0a, 0x91, 0x1a, 0x1f, 0xc5, 0x40,
- 0xb1, 0xc3, 0x15, 0xc1, 0x54, 0x77, 0x86, 0x65, 0x53, 0xec, 0x10, 0x90, 0x0c, 0x91, 0x00, 0x5e,
- 0x15, 0xdc, 0x08, 0x02, 0x4c, 0x8c, 0x0d, 0xc0, 0xac, 0x6e, 0xc4, 0x3e, 0x1b, 0x80, 0x19, 0xe4,
- 0xf7, 0x5f, 0x77, 0x51, 0x06, 0x87, 0x61, 0xde, 0xa2, 0x18, 0x0f, 0x40, 0x8b, 0x79, 0x72, 0xfa,
- 0x8d, 0x1a, 0x44, 0x47, 0x0d, 0x8e, 0x3a, 0x2d, 0xc7, 0x39, 0xbf, 0x56, 0x28, 0x97, 0xd9, 0x20,
- 0x4f, 0x00, 0x51, 0x3b,
- };
-
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *a = NULL, *rrsig = NULL, *dnskey = NULL;
- _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
- DnssecResult result;
-
- a = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_A, "nAsA.gov");
- assert_se(a);
-
- a->a.in_addr.s_addr = inet_addr("52.0.14.116");
-
- log_info("A: %s", strna(dns_resource_record_to_string(a)));
-
- rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "NaSa.GOV.");
- assert_se(rrsig);
-
- rrsig->rrsig.type_covered = DNS_TYPE_A;
- rrsig->rrsig.algorithm = DNSSEC_ALGORITHM_RSASHA256;
- rrsig->rrsig.labels = 2;
- rrsig->rrsig.original_ttl = 600;
- rrsig->rrsig.expiration = 0x5683135c;
- rrsig->rrsig.inception = 0x565b7da8;
- rrsig->rrsig.key_tag = 63876;
- rrsig->rrsig.signer = strdup("Nasa.Gov.");
- assert_se(rrsig->rrsig.signer);
- rrsig->rrsig.signature_size = sizeof(signature_blob);
- rrsig->rrsig.signature = memdup(signature_blob, rrsig->rrsig.signature_size);
- assert_se(rrsig->rrsig.signature);
-
- log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig)));
-
- dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nASA.gOV");
- assert_se(dnskey);
-
- dnskey->dnskey.flags = 256;
- dnskey->dnskey.protocol = 3;
- dnskey->dnskey.algorithm = DNSSEC_ALGORITHM_RSASHA256;
- dnskey->dnskey.key_size = sizeof(dnskey_blob);
- dnskey->dnskey.key = memdup(dnskey_blob, sizeof(dnskey_blob));
- assert_se(dnskey->dnskey.key);
-
- log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey)));
- log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey, false));
-
- assert_se(dnssec_key_match_rrsig(a->key, rrsig) > 0);
- assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0);
-
- answer = dns_answer_new(1);
- assert_se(answer);
- assert_se(dns_answer_add(answer, a, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
-
- /* Validate the RR as it if was 2015-12-2 today */
- assert_se(dnssec_verify_rrset(answer, a->key, rrsig, dnskey, 1449092754*USEC_PER_SEC, &result) >= 0);
- assert_se(result == DNSSEC_VALIDATED);
-}
-
-static void test_dnssec_verify_rrset2(void) {
-
- static const uint8_t signature_blob[] = {
- 0x48, 0x45, 0xc8, 0x8b, 0xc0, 0x14, 0x92, 0xf5, 0x15, 0xc6, 0x84, 0x9d, 0x2f, 0xe3, 0x32, 0x11,
- 0x7d, 0xf1, 0xe6, 0x87, 0xb9, 0x42, 0xd3, 0x8b, 0x9e, 0xaf, 0x92, 0x31, 0x0a, 0x53, 0xad, 0x8b,
- 0xa7, 0x5c, 0x83, 0x39, 0x8c, 0x28, 0xac, 0xce, 0x6e, 0x9c, 0x18, 0xe3, 0x31, 0x16, 0x6e, 0xca,
- 0x38, 0x31, 0xaf, 0xd9, 0x94, 0xf1, 0x84, 0xb1, 0xdf, 0x5a, 0xc2, 0x73, 0x22, 0xf6, 0xcb, 0xa2,
- 0xe7, 0x8c, 0x77, 0x0c, 0x74, 0x2f, 0xc2, 0x13, 0xb0, 0x93, 0x51, 0xa9, 0x4f, 0xae, 0x0a, 0xda,
- 0x45, 0xcc, 0xfd, 0x43, 0x99, 0x36, 0x9a, 0x0d, 0x21, 0xe0, 0xeb, 0x30, 0x65, 0xd4, 0xa0, 0x27,
- 0x37, 0x3b, 0xe4, 0xc1, 0xc5, 0xa1, 0x2a, 0xd1, 0x76, 0xc4, 0x7e, 0x64, 0x0e, 0x5a, 0xa6, 0x50,
- 0x24, 0xd5, 0x2c, 0xcc, 0x6d, 0xe5, 0x37, 0xea, 0xbd, 0x09, 0x34, 0xed, 0x24, 0x06, 0xa1, 0x22,
- };
-
- static const uint8_t dnskey_blob[] = {
- 0x03, 0x01, 0x00, 0x01, 0xc3, 0x7f, 0x1d, 0xd1, 0x1c, 0x97, 0xb1, 0x13, 0x34, 0x3a, 0x9a, 0xea,
- 0xee, 0xd9, 0x5a, 0x11, 0x1b, 0x17, 0xc7, 0xe3, 0xd4, 0xda, 0x20, 0xbc, 0x5d, 0xba, 0x74, 0xe3,
- 0x37, 0x99, 0xec, 0x25, 0xce, 0x93, 0x7f, 0xbd, 0x22, 0x73, 0x7e, 0x14, 0x71, 0xe0, 0x60, 0x07,
- 0xd4, 0x39, 0x8b, 0x5e, 0xe9, 0xba, 0x25, 0xe8, 0x49, 0xe9, 0x34, 0xef, 0xfe, 0x04, 0x5c, 0xa5,
- 0x27, 0xcd, 0xa9, 0xda, 0x70, 0x05, 0x21, 0xab, 0x15, 0x82, 0x24, 0xc3, 0x94, 0xf5, 0xd7, 0xb7,
- 0xc4, 0x66, 0xcb, 0x32, 0x6e, 0x60, 0x2b, 0x55, 0x59, 0x28, 0x89, 0x8a, 0x72, 0xde, 0x88, 0x56,
- 0x27, 0x95, 0xd9, 0xac, 0x88, 0x4f, 0x65, 0x2b, 0x68, 0xfc, 0xe6, 0x41, 0xc1, 0x1b, 0xef, 0x4e,
- 0xd6, 0xc2, 0x0f, 0x64, 0x88, 0x95, 0x5e, 0xdd, 0x3a, 0x02, 0x07, 0x50, 0xa9, 0xda, 0xa4, 0x49,
- 0x74, 0x62, 0xfe, 0xd7,
- };
-
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *nsec = NULL, *rrsig = NULL, *dnskey = NULL;
- _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
- DnssecResult result;
-
- nsec = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_NSEC, "nasa.gov");
- assert_se(nsec);
-
- nsec->nsec.next_domain_name = strdup("3D-Printing.nasa.gov");
- assert_se(nsec->nsec.next_domain_name);
-
- nsec->nsec.types = bitmap_new();
- assert_se(nsec->nsec.types);
- assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_A) >= 0);
- assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_NS) >= 0);
- assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_SOA) >= 0);
- assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_MX) >= 0);
- assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_TXT) >= 0);
- assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_RRSIG) >= 0);
- assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_NSEC) >= 0);
- assert_se(bitmap_set(nsec->nsec.types, DNS_TYPE_DNSKEY) >= 0);
- assert_se(bitmap_set(nsec->nsec.types, 65534) >= 0);
-
- log_info("NSEC: %s", strna(dns_resource_record_to_string(nsec)));
-
- rrsig = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_RRSIG, "NaSa.GOV.");
- assert_se(rrsig);
-
- rrsig->rrsig.type_covered = DNS_TYPE_NSEC;
- rrsig->rrsig.algorithm = DNSSEC_ALGORITHM_RSASHA256;
- rrsig->rrsig.labels = 2;
- rrsig->rrsig.original_ttl = 300;
- rrsig->rrsig.expiration = 0x5689002f;
- rrsig->rrsig.inception = 0x56617230;
- rrsig->rrsig.key_tag = 30390;
- rrsig->rrsig.signer = strdup("Nasa.Gov.");
- assert_se(rrsig->rrsig.signer);
- rrsig->rrsig.signature_size = sizeof(signature_blob);
- rrsig->rrsig.signature = memdup(signature_blob, rrsig->rrsig.signature_size);
- assert_se(rrsig->rrsig.signature);
-
- log_info("RRSIG: %s", strna(dns_resource_record_to_string(rrsig)));
-
- dnskey = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, "nASA.gOV");
- assert_se(dnskey);
-
- dnskey->dnskey.flags = 256;
- dnskey->dnskey.protocol = 3;
- dnskey->dnskey.algorithm = DNSSEC_ALGORITHM_RSASHA256;
- dnskey->dnskey.key_size = sizeof(dnskey_blob);
- dnskey->dnskey.key = memdup(dnskey_blob, sizeof(dnskey_blob));
- assert_se(dnskey->dnskey.key);
-
- log_info("DNSKEY: %s", strna(dns_resource_record_to_string(dnskey)));
- log_info("DNSKEY keytag: %u", dnssec_keytag(dnskey, false));
-
- assert_se(dnssec_key_match_rrsig(nsec->key, rrsig) > 0);
- assert_se(dnssec_rrsig_match_dnskey(rrsig, dnskey, false) > 0);
-
- answer = dns_answer_new(1);
- assert_se(answer);
- assert_se(dns_answer_add(answer, nsec, 0, DNS_ANSWER_AUTHENTICATED) >= 0);
-
- /* Validate the RR as it if was 2015-12-11 today */
- assert_se(dnssec_verify_rrset(answer, nsec->key, rrsig, dnskey, 1449849318*USEC_PER_SEC, &result) >= 0);
- assert_se(result == DNSSEC_VALIDATED);
-}
-
-static void test_dnssec_nsec3_hash(void) {
- static const uint8_t salt[] = { 0xB0, 0x1D, 0xFA, 0xCE };
- static const uint8_t next_hashed_name[] = { 0x84, 0x10, 0x26, 0x53, 0xc9, 0xfa, 0x4d, 0x85, 0x6c, 0x97, 0x82, 0xe2, 0x8f, 0xdf, 0x2d, 0x5e, 0x87, 0x69, 0xc4, 0x52 };
- _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
- uint8_t h[DNSSEC_HASH_SIZE_MAX];
- _cleanup_free_ char *b = NULL;
- int k;
-
- /* The NSEC3 RR for eurid.eu on 2015-12-14. */
- rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_NSEC3, "PJ8S08RR45VIQDAQGE7EN3VHKNROTBMM.eurid.eu.");
- assert_se(rr);
-
- rr->nsec3.algorithm = DNSSEC_DIGEST_SHA1;
- rr->nsec3.flags = 1;
- rr->nsec3.iterations = 1;
- rr->nsec3.salt = memdup(salt, sizeof(salt));
- assert_se(rr->nsec3.salt);
- rr->nsec3.salt_size = sizeof(salt);
- rr->nsec3.next_hashed_name = memdup(next_hashed_name, sizeof(next_hashed_name));
- assert_se(rr->nsec3.next_hashed_name);
- rr->nsec3.next_hashed_name_size = sizeof(next_hashed_name);
-
- log_info("NSEC3: %s", strna(dns_resource_record_to_string(rr)));
-
- k = dnssec_nsec3_hash(rr, "eurid.eu", &h);
- assert_se(k >= 0);
-
- b = base32hexmem(h, k, false);
- assert_se(b);
- assert_se(strcasecmp(b, "PJ8S08RR45VIQDAQGE7EN3VHKNROTBMM") == 0);
-}
-
-#endif
-
-int main(int argc, char*argv[]) {
-
- test_dnssec_canonicalize();
-
-#ifdef HAVE_GCRYPT
- test_dnssec_verify_dns_key();
- test_dnssec_verify_rrset();
- test_dnssec_verify_rrset2();
- test_dnssec_nsec3_hash();
-#endif
-
- return 0;
-}
diff --git a/src/grp-resolve/systemd-resolved/test-resolve-tables.c b/src/grp-resolve/systemd-resolved/test-resolve-tables.c
deleted file mode 100644
index 0eaab70687..0000000000
--- a/src/grp-resolve/systemd-resolved/test-resolve-tables.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/***
- This file is part of systemd
-
- Copyright 2013 Zbigniew Jędrzejewski-Szmek
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include "shared/test-tables.h"
-
-#include "dns-type.h"
-
-int main(int argc, char **argv) {
- uint16_t i;
-
- test_table_sparse(dns_type, DNS_TYPE);
-
- log_info("/* DNS_TYPE */");
- for (i = 0; i < _DNS_TYPE_MAX; i++) {
- const char *s;
-
- s = dns_type_to_string(i);
- assert_se(s == NULL || strlen(s) < _DNS_TYPE_STRING_MAX);
-
- if (s)
- log_info("%-*s %s%s%s%s%s%s%s%s%s",
- (int) _DNS_TYPE_STRING_MAX - 1, s,
- dns_type_is_pseudo(i) ? "pseudo " : "",
- dns_type_is_valid_query(i) ? "valid_query " : "",
- dns_type_is_valid_rr(i) ? "is_valid_rr " : "",
- dns_type_may_redirect(i) ? "may_redirect " : "",
- dns_type_is_dnssec(i) ? "dnssec " : "",
- dns_type_is_obsolete(i) ? "obsolete " : "",
- dns_type_may_wildcard(i) ? "wildcard " : "",
- dns_type_apex_only(i) ? "apex_only " : "",
- dns_type_needs_authentication(i) ? "needs_authentication" : "");
- }
-
- log_info("/* DNS_CLASS */");
- for (i = 0; i < _DNS_CLASS_MAX; i++) {
- const char *s;
-
- s = dns_class_to_string(i);
- assert_se(s == NULL || strlen(s) < _DNS_CLASS_STRING_MAX);
-
- if (s)
- log_info("%-*s %s%s",
- (int) _DNS_CLASS_STRING_MAX - 1, s,
- dns_class_is_pseudo(i) ? "is_pseudo " : "",
- dns_class_is_valid_rr(i) ? "is_valid_rr " : "");
- }
-
- return EXIT_SUCCESS;
-}