resolved: move DNS RR/key/answer/question/packet tools to shared/
We want to reuse these generic DNS concepts in resolved hook implementations, hence move them to shared code. (This also enables us to immediately remove som SVCB record handling duplicate definitions.) No real code changes, just some moving around of things.
This commit is contained in:
@@ -1,315 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "dns-type.h"
|
||||
#include "parse-util.h"
|
||||
#include "string-util.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 GPERF_LEN_TYPE len);
|
||||
|
||||
#include "dns_type-from-name.inc"
|
||||
#include "dns_type-to-name.inc"
|
||||
|
||||
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_CLASS_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_zone_transfer(uint16_t type) {
|
||||
|
||||
/* Zone transfers, either normal or incremental */
|
||||
|
||||
return IN_SET(type,
|
||||
DNS_TYPE_AXFR,
|
||||
DNS_TYPE_IXFR);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "shared-forward.h"
|
||||
|
||||
/* DNS record types, taken from
|
||||
* http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml.
|
||||
*/
|
||||
enum {
|
||||
/* 0 is reserved */
|
||||
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_SMIMEA, /* RFC 8162 */
|
||||
/* 0x36 (54) is not assigned */
|
||||
DNS_TYPE_HIP = 0x37,
|
||||
DNS_TYPE_NINFO,
|
||||
DNS_TYPE_RKEY,
|
||||
DNS_TYPE_TALINK,
|
||||
DNS_TYPE_CDS,
|
||||
DNS_TYPE_CDNSKEY,
|
||||
DNS_TYPE_OPENPGPKEY,
|
||||
DNS_TYPE_CSYNC,
|
||||
DNS_TYPE_ZONEMD,
|
||||
DNS_TYPE_SVCB, /* RFC 9460 */
|
||||
DNS_TYPE_HTTPS, /* RFC 9460 */
|
||||
/* 0x42…0x62 (66…98) are not assigned */
|
||||
DNS_TYPE_SPF = 0x63,
|
||||
DNS_TYPE_UINFO,
|
||||
DNS_TYPE_UID,
|
||||
DNS_TYPE_GID,
|
||||
DNS_TYPE_UNSPEC,
|
||||
DNS_TYPE_NID,
|
||||
DNS_TYPE_L32,
|
||||
DNS_TYPE_L64,
|
||||
DNS_TYPE_LP,
|
||||
DNS_TYPE_EUI48,
|
||||
DNS_TYPE_EUI64,
|
||||
/* 0x6e…0xf8 (110…248) are not assigned */
|
||||
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_AVC,
|
||||
DNS_TYPE_DOA,
|
||||
DNS_TYPE_AMTRELAY,
|
||||
DNS_TYPE_RESINFO,
|
||||
/* 0x106…0x7fff (262…32767) are not assigned */
|
||||
DNS_TYPE_TA = 0x8000,
|
||||
DNS_TYPE_DLV,
|
||||
/* 32770…65279 are not assigned */
|
||||
/* 65280…65534 are for private use */
|
||||
/* 65535 is reserved */
|
||||
_DNS_TYPE_MAX,
|
||||
_DNS_TYPE_INVALID = -EINVAL,
|
||||
};
|
||||
|
||||
assert_cc(DNS_TYPE_SMIMEA == 53);
|
||||
assert_cc(DNS_TYPE_HTTPS == 65);
|
||||
assert_cc(DNS_TYPE_EUI64 == 109);
|
||||
assert_cc(DNS_TYPE_RESINFO == 261);
|
||||
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 = -EINVAL,
|
||||
};
|
||||
|
||||
#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);
|
||||
bool dns_type_is_zone_transfer(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)
|
||||
@@ -1,16 +0,0 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
BEGIN{
|
||||
print "const char *dns_type_to_string(int type) {"
|
||||
print " switch (type) {"
|
||||
}
|
||||
{
|
||||
printf " case DNS_TYPE_%s: return ", $1;
|
||||
sub(/_/, "-");
|
||||
printf "\"%s\";\n", $1
|
||||
}
|
||||
END{
|
||||
print " default: return NULL;"
|
||||
print " }"
|
||||
print "}"
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "dns-packet.h"
|
||||
#include "fuzz.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
#include "sd-json.h"
|
||||
|
||||
#include "dns-packet.h"
|
||||
#include "dns-rr.h"
|
||||
#include "fuzz.h"
|
||||
#include "memstream-util.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "string-util.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
"""Generate %-from-name.gperf from %-list.txt
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
name, prefix, input = sys.argv[1:]
|
||||
|
||||
print("""\
|
||||
%{
|
||||
_Pragma("GCC diagnostic ignored \\"-Wimplicit-fallthrough\\"")
|
||||
#if __GNUC__ >= 15
|
||||
_Pragma("GCC diagnostic ignored \\"-Wzero-as-null-pointer-constant\\"")
|
||||
#endif
|
||||
%}""")
|
||||
print("""\
|
||||
struct {}_name {{ const char* name; int id; }};
|
||||
%null-strings
|
||||
%%""".format(name))
|
||||
|
||||
for line in open(input):
|
||||
line = line.rstrip()
|
||||
s = line.replace('_', '-')
|
||||
print("{}, {}{}".format(s, prefix, line))
|
||||
@@ -1,2 +0,0 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
s/.* DNS_TYPE_(\w+).*/\1/p
|
||||
+2
-39
@@ -8,19 +8,14 @@ systemd_resolved_sources = files(
|
||||
'resolved.c',
|
||||
)
|
||||
systemd_resolved_extract_sources = files(
|
||||
'dns-type.c',
|
||||
'resolved-bus.c',
|
||||
'resolved-conf.c',
|
||||
'resolved-dns-answer.c',
|
||||
'resolved-dns-browse-services.c',
|
||||
'resolved-dns-cache.c',
|
||||
'resolved-dns-delegate.c',
|
||||
'resolved-dns-delegate-bus.c',
|
||||
'resolved-dns-dnssec.c',
|
||||
'resolved-dns-packet.c',
|
||||
'resolved-dns-query.c',
|
||||
'resolved-dns-question.c',
|
||||
'resolved-dns-rr.c',
|
||||
'resolved-dns-scope.c',
|
||||
'resolved-dns-search-domain.c',
|
||||
'resolved-dns-server.c',
|
||||
@@ -46,38 +41,6 @@ systemd_resolved_extract_sources = files(
|
||||
|
||||
############################################################
|
||||
|
||||
dns_type_list_txt = custom_target(
|
||||
input : ['generate-dns_type-list.sed', 'dns-type.h'],
|
||||
output : 'dns_type-list.txt',
|
||||
command : [sed, '-n', '-r', '-f', '@INPUT0@', '@INPUT1@'],
|
||||
capture : true)
|
||||
|
||||
gperf_file = custom_target(
|
||||
input : dns_type_list_txt,
|
||||
output : 'dns_type-from-name.gperf',
|
||||
command : [files('generate-dns_type-gperf.py'),
|
||||
'dns_type',
|
||||
'DNS_TYPE_',
|
||||
'@INPUT@'],
|
||||
capture : true)
|
||||
|
||||
dns_type_from_name_inc = custom_target(
|
||||
input : gperf_file,
|
||||
output : 'dns_type-from-name.inc',
|
||||
command : [gperf,
|
||||
'-L', 'ANSI-C', '-t', '--ignore-case',
|
||||
'-N', 'lookup_dns_type',
|
||||
'-H', 'hash_dns_type_name',
|
||||
'-p', '-C',
|
||||
'@INPUT@'],
|
||||
capture : true)
|
||||
|
||||
dns_type_to_name_inc = custom_target(
|
||||
input : ['dns_type-to-name.awk', dns_type_list_txt],
|
||||
output : 'dns_type-to-name.inc',
|
||||
command : [awk, '-f', '@INPUT0@', '@INPUT1@'],
|
||||
capture : true)
|
||||
|
||||
resolved_gperf_c = custom_target(
|
||||
input : 'resolved-gperf.gperf',
|
||||
output : 'resolved-gperf.c',
|
||||
@@ -93,8 +56,8 @@ resolved_dns_delegate_gperf_c = custom_target(
|
||||
output : 'resolved-dns-delegate-gperf.c',
|
||||
command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@'])
|
||||
|
||||
generated_sources += [dns_type_from_name_inc, dns_type_to_name_inc, resolved_gperf_c, resolved_dnssd_gperf_c, resolved_dns_delegate_gperf_c]
|
||||
systemd_resolved_extract_sources += [dns_type_from_name_inc, dns_type_to_name_inc, resolved_gperf_c, resolved_dnssd_gperf_c, resolved_dns_delegate_gperf_c]
|
||||
generated_sources += [resolved_gperf_c, resolved_dnssd_gperf_c, resolved_dns_delegate_gperf_c]
|
||||
systemd_resolved_extract_sources += [resolved_gperf_c, resolved_dnssd_gperf_c, resolved_dns_delegate_gperf_c]
|
||||
|
||||
if conf.get('ENABLE_DNS_OVER_TLS') == 1
|
||||
systemd_resolved_extract_sources += files(
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include "bus-message-util.h"
|
||||
#include "bus-util.h"
|
||||
#include "dns-domain.h"
|
||||
#include "dns-packet.h"
|
||||
#include "dns-rr.h"
|
||||
#include "errno-list.h"
|
||||
#include "errno-util.h"
|
||||
#include "escape.h"
|
||||
@@ -42,8 +44,6 @@
|
||||
#include "resolve-util.h"
|
||||
#include "resolvectl.h"
|
||||
#include "resolved-def.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "resolved-util.h"
|
||||
#include "socket-netlink.h"
|
||||
#include "sort-util.h"
|
||||
|
||||
@@ -11,20 +11,20 @@
|
||||
#include "bus-object.h"
|
||||
#include "bus-polkit.h"
|
||||
#include "bus-util.h"
|
||||
#include "dns-answer.h"
|
||||
#include "dns-domain.h"
|
||||
#include "dns-packet.h"
|
||||
#include "dns-question.h"
|
||||
#include "dns-rr.h"
|
||||
#include "format-util.h"
|
||||
#include "path-util.h"
|
||||
#include "resolve-util.h"
|
||||
#include "resolved-bus.h"
|
||||
#include "resolved-def.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-delegate.h"
|
||||
#include "resolved-dns-delegate-bus.h"
|
||||
#include "resolved-dns-delegate.h"
|
||||
#include "resolved-dns-dnssec.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-query.h"
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "resolved-dns-scope.h"
|
||||
#include "resolved-dns-search-domain.h"
|
||||
#include "resolved-dns-server.h"
|
||||
@@ -32,10 +32,10 @@
|
||||
#include "resolved-dns-stub.h"
|
||||
#include "resolved-dns-synthesize.h"
|
||||
#include "resolved-dns-transaction.h"
|
||||
#include "resolved-dnssd.h"
|
||||
#include "resolved-dnssd-bus.h"
|
||||
#include "resolved-link.h"
|
||||
#include "resolved-dnssd.h"
|
||||
#include "resolved-link-bus.h"
|
||||
#include "resolved-link.h"
|
||||
#include "resolved-manager.h"
|
||||
#include "resolved-resolv-conf.h"
|
||||
#include "set.h"
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "resolved-forward.h"
|
||||
#include "time-util.h"
|
||||
|
||||
/* Input + Output: The various protocols we can use */
|
||||
#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)
|
||||
|
||||
/* Input: Don't follow CNAMEs/DNAMEs */
|
||||
#define SD_RESOLVED_NO_CNAME (UINT64_C(1) << 5)
|
||||
|
||||
/* Input: When doing service (SRV) resolving, don't resolve associated mDNS-style TXT records */
|
||||
#define SD_RESOLVED_NO_TXT (UINT64_C(1) << 6)
|
||||
|
||||
/* Input: When doing service (SRV) resolving, don't resolve A/AAA RR for included hostname */
|
||||
#define SD_RESOLVED_NO_ADDRESS (UINT64_C(1) << 7)
|
||||
|
||||
/* Input: Don't apply search domain logic to request */
|
||||
#define SD_RESOLVED_NO_SEARCH (UINT64_C(1) << 8)
|
||||
|
||||
/* Output: Result is authenticated */
|
||||
#define SD_RESOLVED_AUTHENTICATED (UINT64_C(1) << 9)
|
||||
|
||||
/* Input: Don't DNSSEC validate request */
|
||||
#define SD_RESOLVED_NO_VALIDATE (UINT64_C(1) << 10)
|
||||
|
||||
/* Input: Don't answer request from locally synthesized records (which includes /etc/hosts) */
|
||||
#define SD_RESOLVED_NO_SYNTHESIZE (UINT64_C(1) << 11)
|
||||
|
||||
/* Input: Don't answer request from cache */
|
||||
#define SD_RESOLVED_NO_CACHE (UINT64_C(1) << 12)
|
||||
|
||||
/* Input: Don't answer request from locally registered public LLMNR/mDNS RRs */
|
||||
#define SD_RESOLVED_NO_ZONE (UINT64_C(1) << 13)
|
||||
|
||||
/* Input: Don't answer request from locally configured trust anchors. */
|
||||
#define SD_RESOLVED_NO_TRUST_ANCHOR (UINT64_C(1) << 14)
|
||||
|
||||
/* Input: Don't go to network for this request */
|
||||
#define SD_RESOLVED_NO_NETWORK (UINT64_C(1) << 15)
|
||||
|
||||
/* Input: Require that request is answered from a "primary" answer, i.e. not from RRs acquired as
|
||||
* side-effect of a previous transaction */
|
||||
#define SD_RESOLVED_REQUIRE_PRIMARY (UINT64_C(1) << 16)
|
||||
|
||||
/* Input: If reply is answered from cache, the TTLs will be adjusted by age of cache entry */
|
||||
#define SD_RESOLVED_CLAMP_TTL (UINT64_C(1) << 17)
|
||||
|
||||
/* Output: Result was only sent via encrypted channels, or never left this system */
|
||||
#define SD_RESOLVED_CONFIDENTIAL (UINT64_C(1) << 18)
|
||||
|
||||
/* Output: Result was (at least partially) synthesized locally */
|
||||
#define SD_RESOLVED_SYNTHETIC (UINT64_C(1) << 19)
|
||||
|
||||
/* Output: Result was (at least partially) answered from cache */
|
||||
#define SD_RESOLVED_FROM_CACHE (UINT64_C(1) << 20)
|
||||
|
||||
/* Output: Result was (at least partially) answered from local zone */
|
||||
#define SD_RESOLVED_FROM_ZONE (UINT64_C(1) << 21)
|
||||
|
||||
/* Output: Result was (at least partially) answered from trust anchor */
|
||||
#define SD_RESOLVED_FROM_TRUST_ANCHOR (UINT64_C(1) << 22)
|
||||
|
||||
/* Output: Result was (at least partially) answered from network */
|
||||
#define SD_RESOLVED_FROM_NETWORK (UINT64_C(1) << 23)
|
||||
|
||||
/* Input: Don't answer request with stale data */
|
||||
#define SD_RESOLVED_NO_STALE (UINT64_C(1) << 24)
|
||||
|
||||
/* Input: Allow single-label lookups to Internet DNS servers */
|
||||
#define SD_RESOLVED_RELAX_SINGLE_LABEL \
|
||||
(UINT64_C(1) << 25)
|
||||
|
||||
/* Input: To differentiate between a probe and a continuous query. */
|
||||
#define SD_RESOLVED_QUERY_CONTINUOUS \
|
||||
(UINT64_C(1) << 26)
|
||||
|
||||
#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)
|
||||
|
||||
#define SD_RESOLVED_FROM_MASK (SD_RESOLVED_FROM_CACHE|SD_RESOLVED_FROM_ZONE|SD_RESOLVED_FROM_TRUST_ANCHOR|SD_RESOLVED_FROM_NETWORK)
|
||||
|
||||
#define SD_RESOLVED_QUERY_TIMEOUT_USEC (120 * USEC_PER_SEC)
|
||||
@@ -1,868 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "dns-domain.h"
|
||||
#include "log.h"
|
||||
#include "random-util.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "siphash24.h"
|
||||
#include "string-util.h"
|
||||
|
||||
static DnsAnswerItem *dns_answer_item_free(DnsAnswerItem *item) {
|
||||
if (!item)
|
||||
return NULL;
|
||||
|
||||
dns_resource_record_unref(item->rr);
|
||||
dns_resource_record_unref(item->rrsig);
|
||||
|
||||
return mfree(item);
|
||||
}
|
||||
|
||||
DEFINE_PRIVATE_TRIVIAL_REF_UNREF_FUNC(DnsAnswerItem, dns_answer_item, dns_answer_item_free);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsAnswerItem*, dns_answer_item_unref);
|
||||
|
||||
static void dns_answer_item_hash_func(const DnsAnswerItem *a, struct siphash *state) {
|
||||
assert(a);
|
||||
assert(state);
|
||||
|
||||
siphash24_compress_typesafe(a->ifindex, state);
|
||||
|
||||
dns_resource_record_hash_func(a->rr, state);
|
||||
}
|
||||
|
||||
static int dns_answer_item_compare_func(const DnsAnswerItem *a, const DnsAnswerItem *b) {
|
||||
int r;
|
||||
|
||||
assert(a);
|
||||
assert(b);
|
||||
|
||||
r = CMP(a->ifindex, b->ifindex);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
return dns_resource_record_compare_func(a->rr, b->rr);
|
||||
}
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
|
||||
dns_answer_item_hash_ops,
|
||||
DnsAnswerItem,
|
||||
dns_answer_item_hash_func,
|
||||
dns_answer_item_compare_func,
|
||||
dns_answer_item_unref);
|
||||
|
||||
static int dns_answer_reserve_internal(DnsAnswer *a, size_t n) {
|
||||
size_t m;
|
||||
|
||||
assert(a);
|
||||
assert(a->items);
|
||||
|
||||
m = ordered_set_size(a->items);
|
||||
assert(m <= UINT16_MAX); /* We can only place 64K RRs in an answer at max */
|
||||
|
||||
n = saturate_add(m, n, UINT16_MAX);
|
||||
|
||||
/* Higher multipliers give slightly higher efficiency through hash collisions, but the gains
|
||||
* quickly drop off after 2. */
|
||||
return ordered_set_reserve(a->items, n * 2);
|
||||
}
|
||||
|
||||
DnsAnswer *dns_answer_new(size_t n) {
|
||||
_cleanup_ordered_set_free_ OrderedSet *s = NULL;
|
||||
_cleanup_(dns_answer_unrefp) DnsAnswer *a = NULL;
|
||||
|
||||
if (n > UINT16_MAX)
|
||||
n = UINT16_MAX;
|
||||
|
||||
s = ordered_set_new(&dns_answer_item_hash_ops);
|
||||
if (!s)
|
||||
return NULL;
|
||||
|
||||
a = new(DnsAnswer, 1);
|
||||
if (!a)
|
||||
return NULL;
|
||||
|
||||
*a = (DnsAnswer) {
|
||||
.n_ref = 1,
|
||||
.items = TAKE_PTR(s),
|
||||
};
|
||||
|
||||
if (dns_answer_reserve_internal(a, n) < 0)
|
||||
return NULL;
|
||||
|
||||
return TAKE_PTR(a);
|
||||
}
|
||||
|
||||
static DnsAnswer *dns_answer_free(DnsAnswer *a) {
|
||||
assert(a);
|
||||
|
||||
ordered_set_free(a->items);
|
||||
return mfree(a);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsAnswer, dns_answer, dns_answer_free);
|
||||
|
||||
static int dns_answer_add_raw(
|
||||
DnsAnswer *a,
|
||||
DnsResourceRecord *rr,
|
||||
int ifindex,
|
||||
DnsAnswerFlags flags,
|
||||
DnsResourceRecord *rrsig,
|
||||
usec_t until) {
|
||||
|
||||
_cleanup_(dns_answer_item_unrefp) DnsAnswerItem *item = NULL;
|
||||
int r;
|
||||
|
||||
assert(rr);
|
||||
|
||||
if (!a)
|
||||
return -ENOSPC;
|
||||
|
||||
if (dns_answer_size(a) >= UINT16_MAX)
|
||||
return -ENOSPC;
|
||||
|
||||
item = new(DnsAnswerItem, 1);
|
||||
if (!item)
|
||||
return -ENOMEM;
|
||||
|
||||
*item = (DnsAnswerItem) {
|
||||
.n_ref = 1,
|
||||
.rr = dns_resource_record_ref(rr),
|
||||
.ifindex = ifindex,
|
||||
.flags = flags,
|
||||
.until = until,
|
||||
.rrsig = dns_resource_record_ref(rrsig),
|
||||
};
|
||||
|
||||
r = ordered_set_put(a->items, item);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
TAKE_PTR(item);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dns_answer_add_raw_all(DnsAnswer *a, DnsAnswer *source) {
|
||||
DnsAnswerItem *item;
|
||||
int r;
|
||||
|
||||
DNS_ANSWER_FOREACH_ITEM(item, source) {
|
||||
r = dns_answer_add_raw(
|
||||
a,
|
||||
item->rr,
|
||||
item->ifindex,
|
||||
item->flags,
|
||||
item->rrsig,
|
||||
/* until= */ USEC_INFINITY);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_answer_add_full(
|
||||
DnsAnswer *a,
|
||||
DnsResourceRecord *rr,
|
||||
int ifindex,
|
||||
DnsAnswerFlags flags,
|
||||
DnsResourceRecord *rrsig,
|
||||
usec_t until) {
|
||||
|
||||
DnsAnswerItem tmp, *exist;
|
||||
|
||||
assert(rr);
|
||||
|
||||
if (!a)
|
||||
return -ENOSPC;
|
||||
if (a->n_ref > 1)
|
||||
return -EBUSY;
|
||||
|
||||
tmp = (DnsAnswerItem) {
|
||||
.rr = rr,
|
||||
.ifindex = ifindex,
|
||||
};
|
||||
|
||||
exist = ordered_set_get(a->items, &tmp);
|
||||
if (exist) {
|
||||
/* There's already an RR of the same RRset in place! Let's see if the TTLs more or
|
||||
* less match. RFC 2181, Section 5.2 suggests clients should reject RRsets
|
||||
* containing RRs with differing TTLs. We are more tolerant of this situation except
|
||||
* if one RR has a zero TTL and the other a nonzero TTL. In mDNS, zero TTLs are
|
||||
* special, so we must error in that case. */
|
||||
if ((rr->ttl == 0) != (exist->rr->ttl == 0)) {
|
||||
if ((exist->flags | flags) & DNS_ANSWER_REFUSE_TTL_NO_MATCH)
|
||||
return log_debug_errno(
|
||||
SYNTHETIC_ERRNO(EINVAL),
|
||||
"Refusing to merge RRs with zero TTL and non-zero TTL: %s vs. %s",
|
||||
dns_resource_record_to_string(rr),
|
||||
dns_resource_record_to_string(exist->rr));
|
||||
|
||||
log_debug("Merging RRs with zero TTL and non-zero TTL (not RFC 2181/5.2 compliant): %s vs. %s",
|
||||
dns_resource_record_to_string(rr),
|
||||
dns_resource_record_to_string(exist->rr));
|
||||
}
|
||||
|
||||
/* Entry already exists, keep the entry with the higher TTL. */
|
||||
if (rr->ttl > exist->rr->ttl) {
|
||||
DNS_RR_REPLACE(exist->rr, dns_resource_record_ref(rr));
|
||||
|
||||
/* Update RRSIG and RR at the same time */
|
||||
if (rrsig)
|
||||
DNS_RR_REPLACE(exist->rrsig, dns_resource_record_ref(rrsig));
|
||||
}
|
||||
|
||||
exist->flags |= flags;
|
||||
|
||||
if (rr->key->type == DNS_TYPE_RRSIG) {
|
||||
/* If the rr is RRSIG, then move the rr to the end. */
|
||||
assert_se(ordered_set_remove(a->items, exist) == exist);
|
||||
assert_se(ordered_set_put(a->items, exist) == 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return dns_answer_add_raw(a, rr, ifindex, flags, rrsig, until);
|
||||
}
|
||||
|
||||
static int dns_answer_add_all(DnsAnswer *a, DnsAnswer *b) {
|
||||
DnsAnswerItem *item;
|
||||
int r;
|
||||
|
||||
DNS_ANSWER_FOREACH_ITEM(item, b) {
|
||||
r = dns_answer_add(a, item->rr, item->ifindex, item->flags, item->rrsig);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_answer_add_extend_full(
|
||||
DnsAnswer **a,
|
||||
DnsResourceRecord *rr,
|
||||
int ifindex,
|
||||
DnsAnswerFlags flags,
|
||||
DnsResourceRecord *rrsig,
|
||||
usec_t until) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(a);
|
||||
assert(rr);
|
||||
|
||||
r = dns_answer_reserve_or_clone(a, 1);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return dns_answer_add_full(*a, rr, ifindex, flags, rrsig, until);
|
||||
}
|
||||
|
||||
int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl, int ifindex) {
|
||||
_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 = strjoin("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, ifindex, DNS_ANSWER_AUTHENTICATED, NULL);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool 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;
|
||||
}
|
||||
|
||||
bool dns_answer_contains(DnsAnswer *answer, DnsResourceRecord *rr) {
|
||||
DnsResourceRecord *i;
|
||||
|
||||
DNS_ANSWER_FOREACH(i, answer)
|
||||
if (dns_resource_record_equal(i, rr))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int dns_answer_find_soa(
|
||||
DnsAnswer *a,
|
||||
const DnsResourceKey *key,
|
||||
DnsResourceRecord **ret,
|
||||
DnsAnswerFlags *ret_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)
|
||||
goto not_found;
|
||||
|
||||
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)
|
||||
goto not_found;
|
||||
|
||||
if (ret)
|
||||
*ret = soa;
|
||||
if (ret_flags)
|
||||
*ret_flags = soa_flags;
|
||||
|
||||
return 1;
|
||||
|
||||
not_found:
|
||||
if (ret)
|
||||
*ret = NULL;
|
||||
if (ret_flags)
|
||||
*ret_flags = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_answer_find_cname_or_dname(
|
||||
DnsAnswer *a,
|
||||
const DnsResourceKey *key,
|
||||
DnsResourceRecord **ret,
|
||||
DnsAnswerFlags *ret_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 (ret_flags)
|
||||
*ret_flags = rr_flags;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret)
|
||||
*ret = NULL;
|
||||
if (ret_flags)
|
||||
*ret_flags = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_answer_merge(DnsAnswer *a, DnsAnswer *b, DnsAnswer **ret) {
|
||||
_cleanup_(dns_answer_unrefp) DnsAnswer *k = NULL;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
if (a == b) {
|
||||
*ret = dns_answer_ref(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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(dns_answer_size(a) + dns_answer_size(b));
|
||||
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 = TAKE_PTR(k);
|
||||
|
||||
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_REPLACE(*a, merged);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_answer_remove_by_key(DnsAnswer **a, const DnsResourceKey *key) {
|
||||
DnsAnswerItem *item;
|
||||
bool found = false;
|
||||
int r;
|
||||
|
||||
assert(a);
|
||||
assert(key);
|
||||
|
||||
/* Remove all entries matching the specified key from *a */
|
||||
|
||||
DNS_ANSWER_FOREACH_ITEM(item, *a) {
|
||||
r = dns_resource_key_equal(item->rr->key, key);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0) {
|
||||
dns_answer_item_unref(ordered_set_remove((*a)->items, item));
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return 0;
|
||||
|
||||
if (dns_answer_isempty(*a))
|
||||
*a = dns_answer_unref(*a); /* Return NULL for the empty answer */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dns_answer_remove_by_rr(DnsAnswer **a, DnsResourceRecord *rr) {
|
||||
_unused_ _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr_ref = dns_resource_record_ref(rr);
|
||||
DnsAnswerItem *item;
|
||||
bool found = false;
|
||||
int r;
|
||||
|
||||
assert(a);
|
||||
assert(rr);
|
||||
|
||||
/* Remove all entries matching the specified RR from *a */
|
||||
|
||||
DNS_ANSWER_FOREACH_ITEM(item, *a) {
|
||||
r = dns_resource_record_equal(item->rr, rr);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0) {
|
||||
dns_answer_item_unref(ordered_set_remove((*a)->items, item));
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return 0;
|
||||
|
||||
if (dns_answer_isempty(*a))
|
||||
*a = dns_answer_unref(*a); /* Return NULL for the empty answer */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dns_answer_remove_by_answer_keys(DnsAnswer **a, DnsAnswer *b) {
|
||||
_cleanup_(dns_resource_key_unrefp) DnsResourceKey *prev = NULL;
|
||||
DnsAnswerItem *item;
|
||||
int r;
|
||||
|
||||
/* Removes all items from '*a' that have a matching key in 'b' */
|
||||
|
||||
DNS_ANSWER_FOREACH_ITEM(item, b) {
|
||||
|
||||
if (prev && dns_resource_key_equal(item->rr->key, prev)) /* Skip this one, we already looked at it */
|
||||
continue;
|
||||
|
||||
r = dns_answer_remove_by_key(a, item->rr->key);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (!*a)
|
||||
return 0; /* a is already empty. */
|
||||
|
||||
/* Let's remember this entry's RR key, to optimize the loop a bit: if we have an RRset with
|
||||
* more than one item then we don't need to remove the key multiple times */
|
||||
DNS_RESOURCE_KEY_REPLACE(prev, dns_resource_key_ref(item->rr->key));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_answer_copy_by_key(
|
||||
DnsAnswer **a,
|
||||
DnsAnswer *source,
|
||||
const DnsResourceKey *key,
|
||||
DnsAnswerFlags or_flags,
|
||||
DnsResourceRecord *rrsig) {
|
||||
|
||||
DnsAnswerItem *item;
|
||||
int r;
|
||||
|
||||
assert(a);
|
||||
assert(key);
|
||||
|
||||
/* Copy all RRs matching the specified key from source into *a */
|
||||
|
||||
DNS_ANSWER_FOREACH_ITEM(item, source) {
|
||||
|
||||
r = dns_resource_key_equal(item->rr->key, key);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
continue;
|
||||
|
||||
r = dns_answer_add_extend(a, item->rr, item->ifindex, item->flags|or_flags, rrsig ?: item->rrsig);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_answer_move_by_key(
|
||||
DnsAnswer **to,
|
||||
DnsAnswer **from,
|
||||
const DnsResourceKey *key,
|
||||
DnsAnswerFlags or_flags,
|
||||
DnsResourceRecord *rrsig) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(to);
|
||||
assert(from);
|
||||
assert(key);
|
||||
|
||||
r = dns_answer_copy_by_key(to, *from, key, or_flags, rrsig);
|
||||
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) {
|
||||
_cleanup_free_ DnsAnswerItem **items = NULL;
|
||||
DnsAnswerItem **p, *item;
|
||||
size_t n;
|
||||
|
||||
n = dns_answer_size(a);
|
||||
if (n <= 1)
|
||||
return;
|
||||
|
||||
/* RFC 4795, Section 2.6 suggests we should order entries
|
||||
* depending on whether the sender is a link-local address. */
|
||||
|
||||
p = items = new(DnsAnswerItem*, n);
|
||||
if (!items)
|
||||
return (void) log_oom();
|
||||
|
||||
/* Order preferred address records and other records to the beginning of the array */
|
||||
DNS_ANSWER_FOREACH_ITEM(item, a)
|
||||
if (dns_resource_record_is_link_local_address(item->rr) == prefer_link_local)
|
||||
*p++ = dns_answer_item_ref(item);
|
||||
|
||||
/* Order address records that are not preferred to the end of the array */
|
||||
DNS_ANSWER_FOREACH_ITEM(item, a)
|
||||
if (dns_resource_record_is_link_local_address(item->rr) != prefer_link_local)
|
||||
*p++ = dns_answer_item_ref(item);
|
||||
|
||||
assert((size_t) (p - items) == n);
|
||||
|
||||
ordered_set_clear(a->items);
|
||||
for (size_t i = 0; i < n; i++)
|
||||
assert_se(ordered_set_put(a->items, items[i]) >= 0);
|
||||
}
|
||||
|
||||
int dns_answer_reserve(DnsAnswer **a, size_t n_free) {
|
||||
assert(a);
|
||||
|
||||
if (n_free <= 0)
|
||||
return 0;
|
||||
|
||||
if (!*a) {
|
||||
DnsAnswer *n;
|
||||
|
||||
n = dns_answer_new(n_free);
|
||||
if (!n)
|
||||
return -ENOMEM;
|
||||
|
||||
*a = n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((*a)->n_ref > 1)
|
||||
return -EBUSY;
|
||||
|
||||
return dns_answer_reserve_internal(*a, n_free);
|
||||
}
|
||||
|
||||
int dns_answer_reserve_or_clone(DnsAnswer **a, size_t n_free) {
|
||||
_cleanup_(dns_answer_unrefp) DnsAnswer *n = NULL;
|
||||
size_t ns;
|
||||
int r;
|
||||
|
||||
assert(a);
|
||||
|
||||
r = dns_answer_reserve(a, n_free);
|
||||
if (r != -EBUSY)
|
||||
return r;
|
||||
|
||||
ns = dns_answer_size(*a);
|
||||
assert(ns <= UINT16_MAX); /* Maximum number of RRs we can stick into a DNS packet section */
|
||||
|
||||
ns = saturate_add(ns, n_free, UINT16_MAX);
|
||||
|
||||
n = dns_answer_new(ns);
|
||||
if (!n)
|
||||
return -ENOMEM;
|
||||
|
||||
r = dns_answer_add_raw_all(n, *a);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
DNS_ANSWER_REPLACE(*a, TAKE_PTR(n));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is not used in the code base, but is useful when debugging. Do not delete.
|
||||
*/
|
||||
void dns_answer_dump(DnsAnswer *answer, FILE *f) {
|
||||
DnsAnswerItem *item;
|
||||
|
||||
if (!f)
|
||||
f = stdout;
|
||||
|
||||
DNS_ANSWER_FOREACH_ITEM(item, answer) {
|
||||
const char *t;
|
||||
|
||||
fputc('\t', f);
|
||||
|
||||
t = dns_resource_record_to_string(item->rr);
|
||||
if (!t) {
|
||||
log_oom();
|
||||
continue;
|
||||
}
|
||||
|
||||
fputs(t, f);
|
||||
fputs("\t;", f);
|
||||
fprintf(f, " ttl=%" PRIu32, item->rr->ttl);
|
||||
|
||||
if (item->ifindex != 0)
|
||||
fprintf(f, " ifindex=%i", item->ifindex);
|
||||
if (item->rrsig)
|
||||
fputs(" rrsig", f);
|
||||
if (item->flags & DNS_ANSWER_AUTHENTICATED)
|
||||
fputs(" authenticated", f);
|
||||
if (item->flags & DNS_ANSWER_CACHEABLE)
|
||||
fputs(" cacheable", f);
|
||||
if (item->flags & DNS_ANSWER_SHARED_OWNER)
|
||||
fputs(" shared-owner", f);
|
||||
if (item->flags & DNS_ANSWER_CACHE_FLUSH)
|
||||
fputs(" cache-flush", f);
|
||||
if (item->flags & DNS_ANSWER_GOODBYE)
|
||||
fputs(" goodbye", f);
|
||||
if (item->flags & DNS_ANSWER_SECTION_ANSWER)
|
||||
fputs(" section-answer", f);
|
||||
if (item->flags & DNS_ANSWER_SECTION_AUTHORITY)
|
||||
fputs(" section-authority", f);
|
||||
if (item->flags & DNS_ANSWER_SECTION_ADDITIONAL)
|
||||
fputs(" section-additional", f);
|
||||
|
||||
fputc('\n', f);
|
||||
}
|
||||
}
|
||||
|
||||
int 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;
|
||||
}
|
||||
|
||||
void dns_answer_randomize(DnsAnswer *a) {
|
||||
_cleanup_free_ DnsAnswerItem **items = NULL;
|
||||
DnsAnswerItem **p, *item;
|
||||
size_t n;
|
||||
|
||||
/* Permutes the answer list randomly (Knuth shuffle) */
|
||||
|
||||
n = dns_answer_size(a);
|
||||
if (n <= 1)
|
||||
return;
|
||||
|
||||
p = items = new(DnsAnswerItem*, n);
|
||||
if (!items)
|
||||
return (void) log_oom();
|
||||
|
||||
DNS_ANSWER_FOREACH_ITEM(item, a)
|
||||
*p++ = dns_answer_item_ref(item);
|
||||
|
||||
assert((size_t) (p - items) == n);
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
size_t k;
|
||||
|
||||
k = random_u64_range(n);
|
||||
if (k == i)
|
||||
continue;
|
||||
|
||||
SWAP_TWO(items[i], items[k]);
|
||||
}
|
||||
|
||||
ordered_set_clear(a->items);
|
||||
for (size_t i = 0; i < n; i++)
|
||||
assert_se(ordered_set_put(a->items, items[i]) >= 0);
|
||||
}
|
||||
|
||||
uint32_t dns_answer_min_ttl(DnsAnswer *a) {
|
||||
uint32_t ttl = UINT32_MAX;
|
||||
DnsResourceRecord *rr;
|
||||
|
||||
/* Return the smallest TTL of all RRs in this answer */
|
||||
|
||||
DNS_ANSWER_FOREACH(rr, a) {
|
||||
/* Don't consider OPT (where the TTL field is used for other purposes than an actual TTL) */
|
||||
|
||||
if (dns_type_is_pseudo(rr->key->type) ||
|
||||
dns_class_is_pseudo(rr->key->class))
|
||||
continue;
|
||||
|
||||
ttl = MIN(ttl, rr->ttl);
|
||||
}
|
||||
|
||||
return ttl;
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "ordered-set.h"
|
||||
#include "resolved-forward.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 << 0, /* Item has been authenticated */
|
||||
DNS_ANSWER_CACHEABLE = 1 << 1, /* Item is subject to caching */
|
||||
DNS_ANSWER_SHARED_OWNER = 1 << 2, /* For mDNS: RRset may be owner by multiple peers */
|
||||
DNS_ANSWER_CACHE_FLUSH = 1 << 3, /* For mDNS: sets cache-flush bit in the rrclass of response records */
|
||||
DNS_ANSWER_GOODBYE = 1 << 4, /* For mDNS: item is subject to disappear */
|
||||
DNS_ANSWER_SECTION_ANSWER = 1 << 5, /* When parsing: RR originates from answer section */
|
||||
DNS_ANSWER_SECTION_AUTHORITY = 1 << 6, /* When parsing: RR originates from authority section */
|
||||
DNS_ANSWER_SECTION_ADDITIONAL = 1 << 7, /* When parsing: RR originates from additional section */
|
||||
DNS_ANSWER_REFUSE_TTL_NO_MATCH = 1 << 8, /* For mDNS; refuse to merge a zero TTL RR with a nonzero TTL RR */
|
||||
|
||||
DNS_ANSWER_MASK_SECTIONS = DNS_ANSWER_SECTION_ANSWER|
|
||||
DNS_ANSWER_SECTION_AUTHORITY|
|
||||
DNS_ANSWER_SECTION_ADDITIONAL,
|
||||
} DnsAnswerFlags;
|
||||
|
||||
typedef struct DnsAnswerItem {
|
||||
unsigned n_ref;
|
||||
DnsResourceRecord *rr;
|
||||
DnsResourceRecord *rrsig; /* Optionally, also store RRSIG RR that successfully validates this item */
|
||||
int ifindex;
|
||||
DnsAnswerFlags flags;
|
||||
usec_t until;
|
||||
} DnsAnswerItem;
|
||||
|
||||
typedef struct DnsAnswer {
|
||||
unsigned n_ref;
|
||||
OrderedSet *items;
|
||||
} DnsAnswer;
|
||||
|
||||
DnsAnswer *dns_answer_new(size_t n);
|
||||
DnsAnswer *dns_answer_ref(DnsAnswer *a);
|
||||
DnsAnswer *dns_answer_unref(DnsAnswer *a);
|
||||
|
||||
#define DNS_ANSWER_REPLACE(a, b) \
|
||||
do { \
|
||||
typeof(a)* _a = &(a); \
|
||||
typeof(b) _b = (b); \
|
||||
dns_answer_unref(*_a); \
|
||||
*_a = _b; \
|
||||
} while(0)
|
||||
|
||||
int dns_answer_add_full(DnsAnswer *a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags, DnsResourceRecord *rrsig, usec_t until);
|
||||
int dns_answer_add_extend_full(DnsAnswer **a, DnsResourceRecord *rr, int ifindex, DnsAnswerFlags flags, DnsResourceRecord *rrsig, usec_t until);
|
||||
int dns_answer_add_soa(DnsAnswer *a, const char *name, uint32_t ttl, int ifindex);
|
||||
|
||||
int dns_answer_match_key(DnsAnswer *a, const DnsResourceKey *key, DnsAnswerFlags *ret_flags);
|
||||
bool dns_answer_contains_nsec_or_nsec3(DnsAnswer *a);
|
||||
int dns_answer_contains_zone_nsec3(DnsAnswer *answer, const char *zone);
|
||||
bool dns_answer_contains(DnsAnswer *answer, DnsResourceRecord *rr);
|
||||
|
||||
int dns_answer_find_soa(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *ret_flags);
|
||||
int dns_answer_find_cname_or_dname(DnsAnswer *a, const DnsResourceKey *key, DnsResourceRecord **ret, DnsAnswerFlags *ret_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, size_t n_free);
|
||||
int dns_answer_reserve_or_clone(DnsAnswer **a, size_t 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_remove_by_answer_keys(DnsAnswer **a, DnsAnswer *b);
|
||||
|
||||
int dns_answer_copy_by_key(DnsAnswer **a, DnsAnswer *source, const DnsResourceKey *key, DnsAnswerFlags or_flags, DnsResourceRecord *rrsig);
|
||||
int dns_answer_move_by_key(DnsAnswer **to, DnsAnswer **from, const DnsResourceKey *key, DnsAnswerFlags or_flags, DnsResourceRecord *rrsig);
|
||||
|
||||
int dns_answer_has_dname_for_cname(DnsAnswer *a, DnsResourceRecord *cname);
|
||||
|
||||
static inline int dns_answer_add_extend(DnsAnswer **a, DnsResourceRecord *rr,
|
||||
int ifindex, DnsAnswerFlags flags, DnsResourceRecord *rrsig) {
|
||||
return dns_answer_add_extend_full(a, rr, ifindex, flags, rrsig, /* until= */ USEC_INFINITY);
|
||||
}
|
||||
|
||||
static inline int dns_answer_add(DnsAnswer *a, DnsResourceRecord *rr,
|
||||
int ifindex, DnsAnswerFlags flags, DnsResourceRecord *rrsig) {
|
||||
return dns_answer_add_full(a, rr, ifindex, flags, rrsig, /* until= */ USEC_INFINITY);
|
||||
}
|
||||
|
||||
static inline size_t dns_answer_size(DnsAnswer *a) {
|
||||
return a ? ordered_set_size(a->items) : 0;
|
||||
}
|
||||
|
||||
static inline bool dns_answer_isempty(DnsAnswer *a) {
|
||||
return dns_answer_size(a) <= 0;
|
||||
}
|
||||
|
||||
void dns_answer_dump(DnsAnswer *answer, FILE *f);
|
||||
|
||||
void dns_answer_randomize(DnsAnswer *a);
|
||||
|
||||
uint32_t dns_answer_min_ttl(DnsAnswer *a);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsAnswer*, dns_answer_unref);
|
||||
|
||||
typedef struct DnsAnswerIterator {
|
||||
Iterator iterator;
|
||||
DnsAnswer *answer;
|
||||
DnsAnswerItem *item;
|
||||
} DnsAnswerIterator;
|
||||
|
||||
#define _DNS_ANSWER_FOREACH(kk, a, i) \
|
||||
for (DnsAnswerIterator i = { .iterator = ITERATOR_FIRST, .answer = (a) }; \
|
||||
i.answer && \
|
||||
ordered_set_iterate(i.answer->items, &i.iterator, (void**) &(i.item)) && \
|
||||
(kk = i.item->rr, true); )
|
||||
|
||||
#define DNS_ANSWER_FOREACH(rr, a) _DNS_ANSWER_FOREACH(rr, a, UNIQ_T(i, UNIQ))
|
||||
|
||||
#define _DNS_ANSWER_FOREACH_IFINDEX(kk, ifi, a, i) \
|
||||
for (DnsAnswerIterator i = { .iterator = ITERATOR_FIRST, .answer = (a) }; \
|
||||
i.answer && \
|
||||
ordered_set_iterate(i.answer->items, &i.iterator, (void**) &(i.item)) && \
|
||||
(kk = i.item->rr, ifi = i.item->ifindex, true); )
|
||||
|
||||
#define DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, a) _DNS_ANSWER_FOREACH_IFINDEX(rr, ifindex, a, UNIQ_T(i, UNIQ))
|
||||
|
||||
#define _DNS_ANSWER_FOREACH_FLAGS(kk, fl, a, i) \
|
||||
for (DnsAnswerIterator i = { .iterator = ITERATOR_FIRST, .answer = (a) }; \
|
||||
i.answer && \
|
||||
ordered_set_iterate(i.answer->items, &i.iterator, (void**) &(i.item)) && \
|
||||
(kk = i.item->rr, fl = i.item->flags, true); )
|
||||
|
||||
#define DNS_ANSWER_FOREACH_FLAGS(rr, flags, a) _DNS_ANSWER_FOREACH_FLAGS(rr, flags, a, UNIQ_T(i, UNIQ))
|
||||
|
||||
#define _DNS_ANSWER_FOREACH_ITEM(it, a, i) \
|
||||
for (DnsAnswerIterator i = { .iterator = ITERATOR_FIRST, .answer = (a) }; \
|
||||
i.answer && \
|
||||
ordered_set_iterate(i.answer->items, &i.iterator, (void**) &(i.item)) && \
|
||||
(it = i.item, true); )
|
||||
|
||||
#define DNS_ANSWER_FOREACH_ITEM(item, a) _DNS_ANSWER_FOREACH_ITEM(item, a, UNIQ_T(i, UNIQ))
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
#include "af-list.h"
|
||||
#include "alloc-util.h"
|
||||
#include "event-util.h"
|
||||
#include "dns-domain.h"
|
||||
#include "dns-question.h"
|
||||
#include "dns-rr.h"
|
||||
#include "event-util.h"
|
||||
#include "log.h"
|
||||
#include "random-util.h"
|
||||
#include "resolved-dns-browse-services.h"
|
||||
#include "resolved-dns-cache.h"
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-dns-query.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "resolved-dns-scope.h"
|
||||
#include "resolved-manager.h"
|
||||
#include "string-table.h"
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "sd-varlink.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
|
||||
#include "dns-answer.h"
|
||||
#include "dns-question.h"
|
||||
#include "dns-rr.h"
|
||||
|
||||
typedef struct DnsServiceBrowser DnsServiceBrowser;
|
||||
typedef struct DnssdDiscoveredService DnssdDiscoveredService;
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
#include "af-list.h"
|
||||
#include "alloc-util.h"
|
||||
#include "bitmap.h"
|
||||
#include "dns-answer.h"
|
||||
#include "dns-domain.h"
|
||||
#include "dns-packet.h"
|
||||
#include "dns-rr.h"
|
||||
#include "format-ifname.h"
|
||||
#include "log.h"
|
||||
#include "prioq.h"
|
||||
#include "resolve-util.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-cache.h"
|
||||
#include "resolved-dns-dnssec.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "string-util.h"
|
||||
#include "time-util.h"
|
||||
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "bitmap.h"
|
||||
#include "dns-answer.h"
|
||||
#include "dns-domain.h"
|
||||
#include "dns-rr.h"
|
||||
#include "dns-type.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "log.h"
|
||||
#include "memory-util.h"
|
||||
#include "memstream-util.h"
|
||||
#include "openssl-util.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-dnssec.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "sort-util.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
@@ -45,32 +45,6 @@ REENABLE_WARNING;
|
||||
* 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;
|
||||
|
||||
/* 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 (size_t 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);
|
||||
}
|
||||
|
||||
#if HAVE_OPENSSL
|
||||
|
||||
static int rr_compare(DnsResourceRecord * const *a, DnsResourceRecord * const *b) {
|
||||
|
||||
@@ -59,8 +59,6 @@ int dnssec_verify_dnskey_by_ds_search(DnsResourceRecord *dnskey, DnsAnswer *vali
|
||||
|
||||
int dnssec_has_rrsig(DnsAnswer *a, const DnsResourceKey *key);
|
||||
|
||||
uint16_t dnssec_keytag(DnsResourceRecord *dnskey, bool mask_revoke);
|
||||
|
||||
int dnssec_nsec3_hash(DnsResourceRecord *nsec3, const char *name, void *ret);
|
||||
|
||||
typedef enum DnssecNsecResult {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,399 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip6.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#include "in-addr-util.h"
|
||||
#include "memory-util.h"
|
||||
#include "resolved-def.h"
|
||||
#include "resolved-forward.h"
|
||||
#include "sparse-endian.h"
|
||||
|
||||
typedef enum DnsProtocol {
|
||||
DNS_PROTOCOL_DNS,
|
||||
DNS_PROTOCOL_MDNS,
|
||||
DNS_PROTOCOL_LLMNR,
|
||||
_DNS_PROTOCOL_MAX,
|
||||
_DNS_PROTOCOL_INVALID = -EINVAL,
|
||||
} DnsProtocol;
|
||||
|
||||
typedef struct DnsPacketHeader {
|
||||
uint16_t id;
|
||||
be16_t flags;
|
||||
be16_t qdcount;
|
||||
be16_t ancount;
|
||||
be16_t nscount;
|
||||
be16_t arcount;
|
||||
} _packed_ DnsPacketHeader;
|
||||
|
||||
#define DNS_PACKET_HEADER_SIZE sizeof(DnsPacketHeader)
|
||||
#define UDP4_PACKET_HEADER_SIZE (sizeof(struct iphdr) + sizeof(struct udphdr))
|
||||
#define UDP6_PACKET_HEADER_SIZE (sizeof(struct ip6_hdr) + sizeof(struct udphdr))
|
||||
|
||||
assert_cc(sizeof(struct ip6_hdr) == 40);
|
||||
assert_cc(sizeof(struct iphdr) == 20);
|
||||
assert_cc(sizeof(struct udphdr) == 8);
|
||||
assert_cc(sizeof(DnsPacketHeader) == 12);
|
||||
|
||||
/* The various DNS protocols deviate in how large a packet can grow, but the TCP transport has a 16-bit size
|
||||
* field, hence that appears to be the absolute maximum. */
|
||||
#define DNS_PACKET_SIZE_MAX 0xFFFFu
|
||||
|
||||
/* The default size to use for allocation when we don't know how large
|
||||
* the packet will turn out to be. */
|
||||
#define DNS_PACKET_SIZE_START 512u
|
||||
|
||||
/* RFC 1035 say 512 is the maximum, for classic unicast DNS */
|
||||
#define DNS_PACKET_UNICAST_SIZE_MAX 512u
|
||||
|
||||
/* With EDNS0 we can use larger packets, default to 1232, which is what is commonly used */
|
||||
#define DNS_PACKET_UNICAST_SIZE_LARGE_MAX 1232u
|
||||
|
||||
typedef struct DnsPacket {
|
||||
unsigned n_ref;
|
||||
DnsProtocol protocol;
|
||||
size_t size, allocated, rindex, max_size, fragsize;
|
||||
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;
|
||||
|
||||
/* For support of truncated packets */
|
||||
DnsPacket *more;
|
||||
|
||||
/* Packet reception metadata */
|
||||
usec_t timestamp; /* CLOCK_BOOTTIME (or CLOCK_MONOTONIC if the former doesn't exist) */
|
||||
int ifindex;
|
||||
int family, ipproto;
|
||||
union in_addr_union sender, destination;
|
||||
uint16_t sender_port, destination_port;
|
||||
uint32_t ttl;
|
||||
|
||||
bool on_stack;
|
||||
bool extracted;
|
||||
bool refuse_compression;
|
||||
bool canonical_form;
|
||||
|
||||
/* Note: fields should be ordered to minimize alignment gaps. Use pahole! */
|
||||
} DnsPacket;
|
||||
|
||||
static inline uint8_t* DNS_PACKET_DATA(const 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)
|
||||
|
||||
#define DNS_PACKET_FLAG_CD (UINT16_C(1) << 4)
|
||||
#define DNS_PACKET_FLAG_AD (UINT16_C(1) << 5)
|
||||
#define DNS_PACKET_FLAG_TC (UINT16_C(1) << 9)
|
||||
|
||||
uint16_t dns_packet_rcode(DnsPacket *p);
|
||||
uint16_t dns_packet_payload_size_max(DnsPacket *p);
|
||||
bool dns_packet_do(DnsPacket *p);
|
||||
bool dns_packet_version_supported(DnsPacket *p);
|
||||
|
||||
static inline bool DNS_PACKET_IS_FRAGMENTED(DnsPacket *p) {
|
||||
assert(p);
|
||||
|
||||
/* For ingress packets: was this packet fragmented according to our knowledge? */
|
||||
|
||||
return p->fragsize != 0;
|
||||
}
|
||||
|
||||
/* 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 min_alloc_dsize, size_t max_size);
|
||||
int dns_packet_new_query(DnsPacket **p, DnsProtocol protocol, size_t min_alloc_dsize, bool dnssec_checking_disabled);
|
||||
|
||||
int dns_packet_dup(DnsPacket **ret, DnsPacket *p);
|
||||
|
||||
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);
|
||||
|
||||
#define DNS_PACKET_REPLACE(a, b) \
|
||||
do { \
|
||||
typeof(a)* _a = &(a); \
|
||||
typeof(b) _b = (b); \
|
||||
dns_packet_unref(*_a); \
|
||||
*_a = _b; \
|
||||
} while(0)
|
||||
|
||||
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, const DnsAnswerFlags flags, size_t *start);
|
||||
int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, const DnsAnswerFlags flags, size_t *start, size_t *rdata_start);
|
||||
int dns_packet_append_opt(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, bool include_rfc6975, const char *nsid, int rcode, size_t *ret_start);
|
||||
int dns_packet_append_question(DnsPacket *p, DnsQuestion *q);
|
||||
int dns_packet_append_answer(DnsPacket *p, DnsAnswer *a, unsigned *completed);
|
||||
|
||||
int dns_packet_patch_max_udp_size(DnsPacket *p, uint16_t max_udp_size);
|
||||
int dns_packet_patch_ttls(DnsPacket *p, usec_t timestamp);
|
||||
|
||||
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_or_qu, 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);
|
||||
|
||||
bool dns_packet_equal(const DnsPacket *a, const DnsPacket *b);
|
||||
|
||||
int dns_packet_ede_rcode(DnsPacket *p, int *ret_ede_rcode, char **ret_ede_msg);
|
||||
bool dns_ede_rcode_is_dnssec(int ede_rcode);
|
||||
int dns_packet_has_nsid_request(DnsPacket *p);
|
||||
|
||||
/* 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_DSOTYPENI = 11,
|
||||
/* 12-15 are unassigned. */
|
||||
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_BADCOOKIE = 23,
|
||||
/* 24-3840 are unassigned. */
|
||||
/* 3841-4095 are for private use. */
|
||||
/* 4096-65534 are unassigned. */
|
||||
_DNS_RCODE_MAX_DEFINED,
|
||||
_DNS_RCODE_MAX = 65535, /* reserved */
|
||||
_DNS_RCODE_INVALID = -EINVAL,
|
||||
};
|
||||
|
||||
/* https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-11 */
|
||||
enum {
|
||||
DNS_EDNS_OPT_RESERVED = 0, /* RFC 6891 */
|
||||
DNS_EDNS_OPT_LLQ = 1, /* RFC 8764 */
|
||||
DNS_EDNS_OPT_UL = 2,
|
||||
DNS_EDNS_OPT_NSID = 3, /* RFC 5001 */
|
||||
/* DNS_EDNS_OPT_RESERVED = 4 */
|
||||
DNS_EDNS_OPT_DAU = 5, /* RFC 6975 */
|
||||
DNS_EDNS_OPT_DHU = 6, /* RFC 6975 */
|
||||
DNS_EDNS_OPT_N3U = 7, /* RFC 6975 */
|
||||
DNS_EDNS_OPT_CLIENT_SUBNET = 8, /* RFC 7871 */
|
||||
DNS_EDNS_OPT_EXPIRE = 9, /* RFC 7314 */
|
||||
DNS_EDNS_OPT_COOKIE = 10, /* RFC 7873 */
|
||||
DNS_EDNS_OPT_TCP_KEEPALIVE = 11, /* RFC 7828 */
|
||||
DNS_EDNS_OPT_PADDING = 12, /* RFC 7830 */
|
||||
DNS_EDNS_OPT_CHAIN = 13, /* RFC 7901 */
|
||||
DNS_EDNS_OPT_KEY_TAG = 14, /* RFC 8145 */
|
||||
DNS_EDNS_OPT_EXT_ERROR = 15, /* RFC 8914 */
|
||||
DNS_EDNS_OPT_CLIENT_TAG = 16,
|
||||
DNS_EDNS_OPT_SERVER_TAG = 17,
|
||||
_DNS_EDNS_OPT_MAX_DEFINED,
|
||||
_DNS_EDNS_OPT_INVALID = -EINVAL,
|
||||
};
|
||||
|
||||
/* https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#extended-dns-error-codes */
|
||||
enum {
|
||||
DNS_EDE_RCODE_OTHER = 0, /* RFC 8914, Section 4.1 */
|
||||
DNS_EDE_RCODE_UNSUPPORTED_DNSKEY_ALG = 1, /* RFC 8914, Section 4.2 */
|
||||
DNS_EDE_RCODE_UNSUPPORTED_DS_DIGEST = 2, /* RFC 8914, Section 4.3 */
|
||||
DNS_EDE_RCODE_STALE_ANSWER = 3, /* RFC 8914, Section 4.4 */
|
||||
DNS_EDE_RCODE_FORGED_ANSWER = 4, /* RFC 8914, Section 4.5 */
|
||||
DNS_EDE_RCODE_DNSSEC_INDETERMINATE = 5, /* RFC 8914, Section 4.6 */
|
||||
DNS_EDE_RCODE_DNSSEC_BOGUS = 6, /* RFC 8914, Section 4.7 */
|
||||
DNS_EDE_RCODE_SIG_EXPIRED = 7, /* RFC 8914, Section 4.8 */
|
||||
DNS_EDE_RCODE_SIG_NOT_YET_VALID = 8, /* RFC 8914, Section 4.9 */
|
||||
DNS_EDE_RCODE_DNSKEY_MISSING = 9, /* RFC 8914, Section 4.10 */
|
||||
DNS_EDE_RCODE_RRSIG_MISSING = 10, /* RFC 8914, Section 4.11 */
|
||||
DNS_EDE_RCODE_NO_ZONE_KEY_BIT = 11, /* RFC 8914, Section 4.12 */
|
||||
DNS_EDE_RCODE_NSEC_MISSING = 12, /* RFC 8914, Section 4.13 */
|
||||
DNS_EDE_RCODE_CACHED_ERROR = 13, /* RFC 8914, Section 4.14 */
|
||||
DNS_EDE_RCODE_NOT_READY = 14, /* RFC 8914, Section 4.15 */
|
||||
DNS_EDE_RCODE_BLOCKED = 15, /* RFC 8914, Section 4.16 */
|
||||
DNS_EDE_RCODE_CENSORED = 16, /* RFC 8914, Section 4.17 */
|
||||
DNS_EDE_RCODE_FILTERED = 17, /* RFC 8914, Section 4.18 */
|
||||
DNS_EDE_RCODE_PROHIBITED = 18, /* RFC 8914, Section 4.19 */
|
||||
DNS_EDE_RCODE_STALE_NXDOMAIN_ANSWER = 19, /* RFC 8914, Section 4.20 */
|
||||
DNS_EDE_RCODE_NOT_AUTHORITATIVE = 20, /* RFC 8914, Section 4.21 */
|
||||
DNS_EDE_RCODE_NOT_SUPPORTED = 21, /* RFC 8914, Section 4.22 */
|
||||
DNS_EDE_RCODE_UNREACH_AUTHORITY = 22, /* RFC 8914, Section 4.23 */
|
||||
DNS_EDE_RCODE_NET_ERROR = 23, /* RFC 8914, Section 4.24 */
|
||||
DNS_EDE_RCODE_INVALID_DATA = 24, /* RFC 8914, Section 4.25 */
|
||||
DNS_EDE_RCODE_SIG_NEVER = 25,
|
||||
DNS_EDE_RCODE_TOO_EARLY = 26, /* RFC 9250 */
|
||||
DNS_EDE_RCODE_UNSUPPORTED_NSEC3_ITER = 27, /* RFC 9276 */
|
||||
DNS_EDE_RCODE_TRANSPORT_POLICY = 28,
|
||||
DNS_EDE_RCODE_SYNTHESIZED = 29,
|
||||
_DNS_EDE_RCODE_MAX_DEFINED,
|
||||
_DNS_EDE_RCODE_INVALID = -EINVAL,
|
||||
};
|
||||
|
||||
const char* dns_rcode_to_string(int i) _const_;
|
||||
int dns_rcode_from_string(const char *s) _pure_;
|
||||
const char* format_dns_rcode(int i, char buf[static DECIMAL_STR_MAX(int)]);
|
||||
#define FORMAT_DNS_RCODE(i) format_dns_rcode(i, (char [DECIMAL_STR_MAX(int)]) {})
|
||||
|
||||
const char* dns_ede_rcode_to_string(int i) _const_;
|
||||
const char* format_dns_ede_rcode(int i, char buf[static DECIMAL_STR_MAX(int)]);
|
||||
#define FORMAT_DNS_EDE_RCODE(i) format_dns_ede_rcode(i, (char [DECIMAL_STR_MAX(int)]) {})
|
||||
|
||||
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 } })
|
||||
|
||||
extern const struct hash_ops dns_packet_hash_ops;
|
||||
|
||||
/* https://www.iana.org/assignments/dns-svcb/dns-svcb.xhtml#dns-svcparamkeys */
|
||||
enum {
|
||||
DNS_SVC_PARAM_KEY_MANDATORY = 0, /* RFC 9460 § 8 */
|
||||
DNS_SVC_PARAM_KEY_ALPN = 1, /* RFC 9460 § 7.1 */
|
||||
DNS_SVC_PARAM_KEY_NO_DEFAULT_ALPN = 2, /* RFC 9460 § 7.1 */
|
||||
DNS_SVC_PARAM_KEY_PORT = 3, /* RFC 9460 § 7.2 */
|
||||
DNS_SVC_PARAM_KEY_IPV4HINT = 4, /* RFC 9460 § 7.3 */
|
||||
DNS_SVC_PARAM_KEY_ECH = 5, /* RFC 9460 */
|
||||
DNS_SVC_PARAM_KEY_IPV6HINT = 6, /* RFC 9460 § 7.3 */
|
||||
DNS_SVC_PARAM_KEY_DOHPATH = 7, /* RFC 9461 */
|
||||
DNS_SVC_PARAM_KEY_OHTTP = 8,
|
||||
_DNS_SVC_PARAM_KEY_MAX_DEFINED,
|
||||
DNS_SVC_PARAM_KEY_INVALID = 65535 /* RFC 9460 */
|
||||
};
|
||||
|
||||
const char* dns_svc_param_key_to_string(int i) _const_;
|
||||
const char* format_dns_svc_param_key(uint16_t i, char buf[static DECIMAL_STR_MAX(uint16_t)+3]);
|
||||
#define FORMAT_DNS_SVC_PARAM_KEY(i) format_dns_svc_param_key(i, (char [DECIMAL_STR_MAX(uint16_t)+3]) {})
|
||||
|
||||
static inline uint64_t SD_RESOLVED_FLAGS_MAKE(
|
||||
DnsProtocol protocol,
|
||||
int family,
|
||||
bool authenticated,
|
||||
bool confidential) {
|
||||
uint64_t f;
|
||||
|
||||
/* Converts a protocol + family into a flags field as used in queries and responses */
|
||||
|
||||
f = (authenticated ? SD_RESOLVED_AUTHENTICATED : 0) |
|
||||
(confidential ? SD_RESOLVED_CONFIDENTIAL : 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;
|
||||
}
|
||||
}
|
||||
|
||||
static inline size_t dns_packet_size_max(DnsPacket *p) {
|
||||
assert(p);
|
||||
|
||||
/* Why not insist on a fully initialized max_size during DnsPacket construction? Well, this way it's easy to
|
||||
* allocate a transient, throw-away DnsPacket on the stack by simple zero initialization, without having to
|
||||
* deal with explicit field initialization. */
|
||||
|
||||
return p->max_size != 0 ? p->max_size : DNS_PACKET_SIZE_MAX;
|
||||
}
|
||||
|
||||
static inline size_t udp_header_size(int af) {
|
||||
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return UDP4_PACKET_HEADER_SIZE;
|
||||
case AF_INET6:
|
||||
return UDP6_PACKET_HEADER_SIZE;
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
size_t dns_packet_size_unfragmented(DnsPacket *p);
|
||||
@@ -4,16 +4,16 @@
|
||||
#include "sd-varlink.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "dns-answer.h"
|
||||
#include "dns-domain.h"
|
||||
#include "dns-packet.h"
|
||||
#include "dns-question.h"
|
||||
#include "dns-rr.h"
|
||||
#include "dns-type.h"
|
||||
#include "event-util.h"
|
||||
#include "glyph-util.h"
|
||||
#include "log.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-query.h"
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "resolved-dns-scope.h"
|
||||
#include "resolved-dns-search-domain.h"
|
||||
#include "resolved-dns-synthesize.h"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "dns-packet.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "list.h"
|
||||
#include "resolved-dns-browse-services.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-transaction.h"
|
||||
#include "resolved-forward.h"
|
||||
|
||||
|
||||
@@ -1,601 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "dns-domain.h"
|
||||
#include "dns-type.h"
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "socket-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
DnsQuestion *dns_question_new(size_t n) {
|
||||
DnsQuestion *q;
|
||||
|
||||
if (n > UINT16_MAX) /* We can only place 64K key in an question section at max */
|
||||
n = UINT16_MAX;
|
||||
|
||||
q = malloc0(offsetof(DnsQuestion, items) + sizeof(DnsQuestionItem) * n);
|
||||
if (!q)
|
||||
return NULL;
|
||||
|
||||
q->n_ref = 1;
|
||||
q->n_allocated = n;
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
static DnsQuestion *dns_question_free(DnsQuestion *q) {
|
||||
DnsResourceKey *key;
|
||||
|
||||
assert(q);
|
||||
|
||||
DNS_QUESTION_FOREACH(key, q)
|
||||
dns_resource_key_unref(key);
|
||||
|
||||
return mfree(q);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsQuestion, dns_question, dns_question_free);
|
||||
|
||||
int dns_question_add_raw(DnsQuestion *q, DnsResourceKey *key, DnsQuestionFlags flags) {
|
||||
/* Insert without checking for duplicates. */
|
||||
|
||||
assert(key);
|
||||
assert(q);
|
||||
|
||||
if (q->n_keys >= q->n_allocated)
|
||||
return -ENOSPC;
|
||||
|
||||
q->items[q->n_keys++] = (DnsQuestionItem) {
|
||||
.key = dns_resource_key_ref(key),
|
||||
.flags = flags,
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dns_question_add_raw_all(DnsQuestion *a, DnsQuestion *b) {
|
||||
DnsQuestionItem *item;
|
||||
int r;
|
||||
|
||||
DNS_QUESTION_FOREACH_ITEM(item, b) {
|
||||
r = dns_question_add_raw(a, item->key, item->flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_question_add(DnsQuestion *q, DnsResourceKey *key, DnsQuestionFlags flags) {
|
||||
DnsQuestionItem *item;
|
||||
int r;
|
||||
|
||||
assert(key);
|
||||
|
||||
if (!q)
|
||||
return -ENOSPC;
|
||||
|
||||
DNS_QUESTION_FOREACH_ITEM(item, q) {
|
||||
r = dns_resource_key_equal(item->key, key);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0 && item->flags == flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return dns_question_add_raw(q, key, flags);
|
||||
}
|
||||
|
||||
static int dns_question_add_all(DnsQuestion *a, DnsQuestion *b) {
|
||||
DnsQuestionItem *item;
|
||||
int r;
|
||||
|
||||
DNS_QUESTION_FOREACH_ITEM(item, b) {
|
||||
r = dns_question_add(a, item->key, item->flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_question_matches_rr(DnsQuestion *q, DnsResourceRecord *rr, const char *search_domain) {
|
||||
DnsResourceKey *key;
|
||||
int r;
|
||||
|
||||
assert(rr);
|
||||
|
||||
if (!q)
|
||||
return 0;
|
||||
|
||||
DNS_QUESTION_FOREACH(key, q) {
|
||||
r = dns_resource_key_match_rr(key, 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) {
|
||||
DnsResourceKey *key;
|
||||
int r;
|
||||
|
||||
assert(rr);
|
||||
|
||||
if (!q)
|
||||
return 0;
|
||||
|
||||
if (!IN_SET(rr->key->type, DNS_TYPE_CNAME, DNS_TYPE_DNAME))
|
||||
return 0;
|
||||
|
||||
DNS_QUESTION_FOREACH(key, q) {
|
||||
/* 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;
|
||||
|
||||
r = dns_resource_key_match_cname_or_dname(key, rr->key, search_domain);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_question_is_valid_for_query(DnsQuestion *q) {
|
||||
const char *name;
|
||||
size_t 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->items[0].key);
|
||||
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->items[i].key);
|
||||
|
||||
if (i > 0) {
|
||||
r = dns_name_equal(dns_resource_key_name(q->items[i].key), name);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!dns_type_is_valid_query(q->items[i].key->type))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dns_question_contains_key(DnsQuestion *q, const DnsResourceKey *k) {
|
||||
size_t j;
|
||||
int r;
|
||||
|
||||
assert(k);
|
||||
|
||||
if (!q)
|
||||
return 0;
|
||||
|
||||
for (j = 0; j < q->n_keys; j++) {
|
||||
r = dns_resource_key_equal(q->items[j].key, k);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dns_question_contains_item(DnsQuestion *q, const DnsQuestionItem *i) {
|
||||
DnsQuestionItem *item;
|
||||
int r;
|
||||
|
||||
assert(i);
|
||||
|
||||
DNS_QUESTION_FOREACH_ITEM(item, q) {
|
||||
if (item->flags != i->flags)
|
||||
continue;
|
||||
r = dns_resource_key_equal(item->key, i->key);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int dns_question_is_equal(DnsQuestion *a, DnsQuestion *b) {
|
||||
DnsQuestionItem *item;
|
||||
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 items in a are also contained b, and vice versa */
|
||||
|
||||
DNS_QUESTION_FOREACH_ITEM(item, a) {
|
||||
r = dns_question_contains_item(b, item);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
}
|
||||
DNS_QUESTION_FOREACH_ITEM(item, b) {
|
||||
r = dns_question_contains_item(a, item);
|
||||
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, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(n);
|
||||
|
||||
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->items[0].key);
|
||||
}
|
||||
|
||||
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 IPv6 is off and the request has an unspecified lookup family, restrict it automatically to
|
||||
* IPv4. */
|
||||
if (family == AF_UNSPEC && !socket_ipv6_is_enabled())
|
||||
family = AF_INET;
|
||||
|
||||
if (convert_idna) {
|
||||
r = dns_name_apply_idna(name, &buf);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0 && !streq(name, buf))
|
||||
name = buf;
|
||||
else
|
||||
/* We did not manage to create convert the idna name, or it's
|
||||
* the same as the original name. We assume the caller already
|
||||
* created an unconverted question, so let's not repeat work
|
||||
* unnecessarily. */
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
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, 0);
|
||||
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, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(q);
|
||||
|
||||
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, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(q);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dns_question_new_service_pointer(DnsQuestion **ret, const char *type, const char *domain, 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);
|
||||
|
||||
if (!domain)
|
||||
return -EINVAL;
|
||||
|
||||
if (type) {
|
||||
if (convert_idna) {
|
||||
r = dns_name_apply_idna(domain, &buf);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
domain = buf;
|
||||
}
|
||||
|
||||
r = dns_service_join(NULL, type, domain, &joined);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
name = joined;
|
||||
} else
|
||||
name = domain;
|
||||
|
||||
|
||||
q = dns_question_new(1);
|
||||
if (!q)
|
||||
return -ENOMEM;
|
||||
|
||||
key = dns_resource_key_new(DNS_CLASS_IN, DNS_TYPE_PTR, name);
|
||||
if (!key)
|
||||
return -ENOMEM;
|
||||
|
||||
r = dns_question_add(q, key, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(q);
|
||||
|
||||
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;
|
||||
if (r > 0)
|
||||
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, 0);
|
||||
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, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(q);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is not used in the code base, but is useful when debugging. Do not delete.
|
||||
*/
|
||||
void dns_question_dump(DnsQuestion *question, FILE *f) {
|
||||
DnsResourceKey *k;
|
||||
|
||||
if (!f)
|
||||
f = stdout;
|
||||
|
||||
DNS_QUESTION_FOREACH(k, question) {
|
||||
char buf[DNS_RESOURCE_KEY_STRING_MAX];
|
||||
|
||||
fputc('\t', f);
|
||||
fputs(dns_resource_key_to_string(k, buf, sizeof(buf)), f);
|
||||
fputc('\n', f);
|
||||
}
|
||||
}
|
||||
|
||||
int dns_question_merge(DnsQuestion *a, DnsQuestion *b, DnsQuestion **ret) {
|
||||
_cleanup_(dns_question_unrefp) DnsQuestion *k = NULL;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
if (a == b || dns_question_size(b) <= 0) {
|
||||
*ret = dns_question_ref(a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dns_question_size(a) <= 0) {
|
||||
*ret = dns_question_ref(b);
|
||||
return 0;
|
||||
}
|
||||
|
||||
k = dns_question_new(dns_question_size(a) + dns_question_size(b));
|
||||
if (!k)
|
||||
return -ENOMEM;
|
||||
|
||||
r = dns_question_add_raw_all(k, a);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dns_question_add_all(k, b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(k);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "resolved-forward.h"
|
||||
|
||||
/* A simple array of resource keys */
|
||||
|
||||
typedef enum DnsQuestionFlags {
|
||||
DNS_QUESTION_WANTS_UNICAST_REPLY = 1 << 0, /* For mDNS: sender is willing to accept unicast replies */
|
||||
} DnsQuestionFlags;
|
||||
|
||||
typedef struct DnsQuestionItem {
|
||||
DnsResourceKey *key;
|
||||
DnsQuestionFlags flags;
|
||||
} DnsQuestionItem;
|
||||
|
||||
typedef struct DnsQuestion {
|
||||
unsigned n_ref;
|
||||
size_t n_keys, n_allocated;
|
||||
DnsQuestionItem items[];
|
||||
} DnsQuestion;
|
||||
|
||||
DnsQuestion *dns_question_new(size_t 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_new_service_pointer(DnsQuestion **ret, const char *type, const char *domain, bool convert_idna);
|
||||
|
||||
int dns_question_add_raw(DnsQuestion *q, DnsResourceKey *key, DnsQuestionFlags flags);
|
||||
int dns_question_add(DnsQuestion *q, DnsResourceKey *key, DnsQuestionFlags flags);
|
||||
|
||||
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_key(DnsQuestion *q, const DnsResourceKey *k);
|
||||
int dns_question_is_equal(DnsQuestion *a, DnsQuestion *b);
|
||||
|
||||
int dns_question_cname_redirect(DnsQuestion *q, const DnsResourceRecord *cname, DnsQuestion **ret);
|
||||
|
||||
void dns_question_dump(DnsQuestion *q, FILE *f);
|
||||
|
||||
const char* dns_question_first_name(DnsQuestion *q);
|
||||
|
||||
static inline DnsResourceKey *dns_question_first_key(DnsQuestion *q) {
|
||||
return (q && q->n_keys > 0) ? q->items[0].key : NULL;
|
||||
}
|
||||
|
||||
static inline size_t dns_question_size(DnsQuestion *q) {
|
||||
return q ? q->n_keys : 0;
|
||||
}
|
||||
|
||||
static inline bool dns_question_isempty(DnsQuestion *q) {
|
||||
return dns_question_size(q) <= 0;
|
||||
}
|
||||
|
||||
int dns_question_merge(DnsQuestion *a, DnsQuestion *b, DnsQuestion **ret);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQuestion*, dns_question_unref);
|
||||
|
||||
#define _DNS_QUESTION_FOREACH(u, k, q) \
|
||||
for (size_t UNIQ_T(i, u) = ({ \
|
||||
(k) = ((q) && (q)->n_keys > 0) ? (q)->items[0].key : NULL; \
|
||||
0; \
|
||||
}); \
|
||||
(q) && (UNIQ_T(i, u) < (q)->n_keys); \
|
||||
UNIQ_T(i, u)++, (k) = (UNIQ_T(i, u) < (q)->n_keys ? (q)->items[UNIQ_T(i, u)].key : NULL))
|
||||
|
||||
#define DNS_QUESTION_FOREACH(key, q) _DNS_QUESTION_FOREACH(UNIQ, key, q)
|
||||
|
||||
#define _DNS_QUESTION_FOREACH_ITEM(u, item, q) \
|
||||
for (size_t UNIQ_T(i, u) = ({ \
|
||||
(item) = dns_question_isempty(q) ? NULL : (q)->items; \
|
||||
0; \
|
||||
}); \
|
||||
UNIQ_T(i, u) < dns_question_size(q); \
|
||||
UNIQ_T(i, u)++, (item) = (UNIQ_T(i, u) < dns_question_size(q) ? (q)->items + UNIQ_T(i, u) : NULL))
|
||||
|
||||
#define DNS_QUESTION_FOREACH_ITEM(item, q) _DNS_QUESTION_FOREACH_ITEM(UNIQ, item, q)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,444 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "dns-def.h"
|
||||
#include "dns-type.h"
|
||||
#include "list.h"
|
||||
#include "resolved-forward.h"
|
||||
|
||||
/* 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_OR_QU (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_ED25519 = 15, /* RFC 8080 */
|
||||
DNSSEC_ALGORITHM_ED448 = 16, /* RFC 8080 */
|
||||
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
|
||||
};
|
||||
|
||||
/* SSHFP algorithm identifiers, see
|
||||
* https://www.iana.org/assignments/dns-sshfp-rr-parameters/dns-sshfp-rr-parameters.xhtml */
|
||||
enum {
|
||||
SSHFP_ALGORITHM_RSA = 1, /* RFC 4255 */
|
||||
SSHFP_ALGORITHM_DSA = 2, /* RFC 4255 */
|
||||
SSHFP_ALGORITHM_ECDSA = 3, /* RFC 6594 */
|
||||
SSHFP_ALGORITHM_ED25519 = 4, /* RFC 7479 */
|
||||
/* unassigned */
|
||||
SSHFP_ALGORITHM_ED448 = 6, /* RFC 8709 */
|
||||
_SSHFP_ALGORITHM_MAX_DEFINED
|
||||
};
|
||||
/* A helper to align printed output */
|
||||
#define SSHFP_ALGORITHM_FMT "%-7s"
|
||||
|
||||
/* SSHFP key-type identifiers, see
|
||||
* https://www.iana.org/assignments/dns-sshfp-rr-parameters/dns-sshfp-rr-parameters.xhtml */
|
||||
enum {
|
||||
SSHFP_KEY_TYPE_SHA1 = 1, /* RFC 4255 */
|
||||
SSHFP_KEY_TYPE_SHA256 = 2, /* RFC 4255 */
|
||||
_SSHFP_KEY_TYPE_MAX_DEFINED
|
||||
};
|
||||
/* A helper to align printed output */
|
||||
#define SSHFP_KEY_TYPE_FMT "%-7s"
|
||||
|
||||
typedef 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()! */
|
||||
} DnsResourceKey;
|
||||
|
||||
/* 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 = UINT_MAX, \
|
||||
.class = c, \
|
||||
.type = t, \
|
||||
._name = (char*) n, \
|
||||
})
|
||||
|
||||
typedef struct DnsTxtItem {
|
||||
size_t length;
|
||||
LIST_FIELDS(DnsTxtItem, items);
|
||||
uint8_t data[];
|
||||
} DnsTxtItem;
|
||||
|
||||
typedef struct DnsSvcParam {
|
||||
uint16_t key;
|
||||
size_t length;
|
||||
LIST_FIELDS(DnsSvcParam, params);
|
||||
union {
|
||||
DECLARE_FLEX_ARRAY(uint8_t, value);
|
||||
DECLARE_FLEX_ARRAY(struct in_addr, value_in_addr);
|
||||
DECLARE_FLEX_ARRAY(struct in6_addr, value_in6_addr);
|
||||
};
|
||||
} DnsSvcParam;
|
||||
|
||||
typedef struct DnsResourceRecord {
|
||||
unsigned n_ref;
|
||||
uint32_t ttl;
|
||||
usec_t expiry; /* RRSIG signature expiry */
|
||||
|
||||
DnsResourceKey *key;
|
||||
|
||||
char *to_string;
|
||||
|
||||
/* How many labels to strip to determine "signer" of the RRSIG (aka, the zone). -1 if not signed. */
|
||||
uint8_t 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. */
|
||||
uint8_t n_skip_labels_source;
|
||||
|
||||
bool unparsable;
|
||||
bool wire_format_canonical;
|
||||
|
||||
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 {
|
||||
char *name;
|
||||
uint16_t priority;
|
||||
uint16_t weight;
|
||||
uint16_t port;
|
||||
} 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 {
|
||||
char *exchange;
|
||||
uint16_t priority;
|
||||
} 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 {
|
||||
void *fingerprint;
|
||||
size_t fingerprint_size;
|
||||
|
||||
uint8_t algorithm;
|
||||
uint8_t fptype;
|
||||
} sshfp;
|
||||
|
||||
/* http://tools.ietf.org/html/rfc4034#section-2.1 */
|
||||
struct {
|
||||
void* key;
|
||||
size_t key_size;
|
||||
|
||||
uint16_t flags;
|
||||
uint8_t protocol;
|
||||
uint8_t algorithm;
|
||||
} dnskey;
|
||||
|
||||
/* http://tools.ietf.org/html/rfc4034#section-3.1 */
|
||||
struct {
|
||||
char *signer;
|
||||
void *signature;
|
||||
size_t signature_size;
|
||||
|
||||
uint16_t type_covered;
|
||||
uint8_t algorithm;
|
||||
uint8_t labels;
|
||||
uint32_t original_ttl;
|
||||
uint32_t expiration;
|
||||
uint32_t inception;
|
||||
uint16_t key_tag;
|
||||
} 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 {
|
||||
void *digest;
|
||||
size_t digest_size;
|
||||
|
||||
uint16_t key_tag;
|
||||
uint8_t algorithm;
|
||||
uint8_t digest_type;
|
||||
} ds;
|
||||
|
||||
struct {
|
||||
Bitmap *types;
|
||||
void *salt;
|
||||
size_t salt_size;
|
||||
void *next_hashed_name;
|
||||
size_t next_hashed_name_size;
|
||||
|
||||
uint8_t algorithm;
|
||||
uint8_t flags;
|
||||
uint16_t iterations;
|
||||
} nsec3;
|
||||
|
||||
/* https://tools.ietf.org/html/draft-ietf-dane-protocol-23 */
|
||||
struct {
|
||||
void *data;
|
||||
size_t data_size;
|
||||
|
||||
uint8_t cert_usage;
|
||||
uint8_t selector;
|
||||
uint8_t matching_type;
|
||||
} tlsa;
|
||||
|
||||
/* https://tools.ietf.org/html/rfc9460 */
|
||||
struct {
|
||||
uint16_t priority;
|
||||
char *target_name;
|
||||
DnsSvcParam *params;
|
||||
} svcb, https;
|
||||
|
||||
/* https://tools.ietf.org/html/rfc6844 */
|
||||
struct {
|
||||
char *tag;
|
||||
void *value;
|
||||
size_t value_size;
|
||||
|
||||
uint8_t flags;
|
||||
} caa;
|
||||
|
||||
/* https://datatracker.ietf.org/doc/html/rfc2915 */
|
||||
struct {
|
||||
uint16_t order;
|
||||
uint16_t preference;
|
||||
char *flags;
|
||||
char *services;
|
||||
char *regexp;
|
||||
char *replacement;
|
||||
} naptr;
|
||||
};
|
||||
|
||||
/* Note: fields should be ordered to minimize alignment gaps. Use pahole! */
|
||||
} DnsResourceRecord;
|
||||
|
||||
/* We use uint8_t for label counts above, and UINT8_MAX/-1 has special meaning. */
|
||||
assert_cc(DNS_N_LABELS_MAX < UINT8_MAX);
|
||||
|
||||
static inline const void* DNS_RESOURCE_RECORD_RDATA(const 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(const 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;
|
||||
}
|
||||
|
||||
static inline uint8_t DNS_RESOURCE_RECORD_OPT_VERSION_SUPPORTED(const DnsResourceRecord *rr) {
|
||||
assert(rr);
|
||||
assert(rr->key->type == DNS_TYPE_OPT);
|
||||
|
||||
return ((rr->ttl >> 16) & 0xFF) == 0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
#define DNS_RESOURCE_KEY_REPLACE(a, b) \
|
||||
do { \
|
||||
typeof(a)* _a = &(a); \
|
||||
typeof(b) _b = (b); \
|
||||
dns_resource_key_unref(*_a); \
|
||||
*_a = _b; \
|
||||
} while(0)
|
||||
|
||||
const char* dns_resource_key_name(const DnsResourceKey *key);
|
||||
bool dns_resource_key_is_address(const DnsResourceKey *key);
|
||||
bool dns_resource_key_is_dnssd_ptr(const DnsResourceKey *key);
|
||||
bool dns_resource_key_is_dnssd_two_label_ptr(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, const void **ret);
|
||||
|
||||
#define DNS_RESOURCE_KEY_TO_STRING(key) \
|
||||
dns_resource_key_to_string(key, (char[DNS_RESOURCE_KEY_STRING_MAX]) {}, DNS_RESOURCE_KEY_STRING_MAX)
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsResourceKey*, dns_resource_key_unref);
|
||||
|
||||
static inline bool dns_key_is_shared(const DnsResourceKey *key) {
|
||||
return 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);
|
||||
|
||||
#define DNS_RR_REPLACE(a, b) \
|
||||
do { \
|
||||
typeof(a)* _a = &(a); \
|
||||
typeof(b) _b = (b); \
|
||||
dns_resource_record_unref(*_a); \
|
||||
*_a = _b; \
|
||||
} while(0)
|
||||
|
||||
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);
|
||||
int dns_resource_record_payload_equal(const DnsResourceRecord *a, const DnsResourceRecord *b);
|
||||
|
||||
const char* dns_resource_record_to_string(DnsResourceRecord *rr);
|
||||
DnsResourceRecord *dns_resource_record_copy(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);
|
||||
|
||||
int dns_resource_record_clamp_ttl(DnsResourceRecord **rr, uint32_t max_ttl);
|
||||
|
||||
bool dns_resource_record_is_link_local_address(DnsResourceRecord *rr);
|
||||
|
||||
int dns_resource_record_get_cname_target(DnsResourceKey *key, DnsResourceRecord *cname, char **ret);
|
||||
|
||||
DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i);
|
||||
bool dns_txt_item_equal(DnsTxtItem *a, DnsTxtItem *b);
|
||||
DnsTxtItem *dns_txt_item_copy(DnsTxtItem *i);
|
||||
int dns_txt_item_new_empty(DnsTxtItem **ret);
|
||||
|
||||
DnsSvcParam *dns_svc_param_free_all(DnsSvcParam *i);
|
||||
bool dns_svc_params_equal(DnsSvcParam *a, DnsSvcParam *b);
|
||||
DnsSvcParam *dns_svc_params_copy(DnsSvcParam *first);
|
||||
|
||||
int dns_resource_record_new_from_raw(DnsResourceRecord **ret, const void *data, size_t size);
|
||||
|
||||
int dns_resource_key_to_json(DnsResourceKey *key, sd_json_variant **ret);
|
||||
int dns_resource_key_from_json(sd_json_variant *v, DnsResourceKey **ret);
|
||||
int dns_resource_record_to_json(DnsResourceRecord *rr, sd_json_variant **ret);
|
||||
|
||||
void dns_resource_key_hash_func(const DnsResourceKey *k, struct siphash *state);
|
||||
int dns_resource_key_compare_func(const DnsResourceKey *x, const DnsResourceKey *y);
|
||||
void dns_resource_record_hash_func(const DnsResourceRecord *i, struct siphash *state);
|
||||
int dns_resource_record_compare_func(const DnsResourceRecord *x, const DnsResourceRecord *y);
|
||||
|
||||
extern const struct hash_ops dns_resource_key_hash_ops;
|
||||
extern const struct hash_ops dns_resource_record_hash_ops;
|
||||
extern const struct hash_ops dns_resource_record_hash_ops_by_key;
|
||||
|
||||
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_;
|
||||
|
||||
int sshfp_algorithm_to_string_alloc(int i, char **ret);
|
||||
int sshfp_algorithm_from_string(const char *s) _pure_;
|
||||
|
||||
int sshfp_key_type_to_string_alloc(int i, char **ret);
|
||||
int sshfp_key_type_from_string(const char *s) _pure_;
|
||||
@@ -7,20 +7,20 @@
|
||||
|
||||
#include "af-list.h"
|
||||
#include "alloc-util.h"
|
||||
#include "dns-answer.h"
|
||||
#include "dns-domain.h"
|
||||
#include "dns-packet.h"
|
||||
#include "dns-question.h"
|
||||
#include "dns-rr.h"
|
||||
#include "dns-type.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "hostname-util.h"
|
||||
#include "log.h"
|
||||
#include "random-util.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-browse-services.h"
|
||||
#include "resolved-dns-delegate.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-query.h"
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "resolved-dns-scope.h"
|
||||
#include "resolved-dns-search-domain.h"
|
||||
#include "resolved-dns-server.h"
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "dns-def.h"
|
||||
#include "dns-packet.h"
|
||||
#include "list.h"
|
||||
#include "ratelimit.h"
|
||||
#include "resolve-util.h"
|
||||
#include "resolved-dns-cache.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-zone.h"
|
||||
#include "resolved-forward.h"
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "dns-domain.h"
|
||||
#include "dns-packet.h"
|
||||
#include "errno-util.h"
|
||||
#include "extract-word.h"
|
||||
#include "fd-util.h"
|
||||
@@ -13,7 +14,6 @@
|
||||
#include "resolved-bus.h"
|
||||
#include "resolved-dns-cache.h"
|
||||
#include "resolved-dns-delegate.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-scope.h"
|
||||
#include "resolved-dns-search-domain.h"
|
||||
#include "resolved-dns-server.h"
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
#include "sd-event.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "dns-packet.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "iovec-util.h"
|
||||
#include "log.h"
|
||||
#include "missing-network.h"
|
||||
#include "ordered-set.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-server.h"
|
||||
#include "resolved-dns-stream.h"
|
||||
#include "resolved-manager.h"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "dns-packet.h"
|
||||
#include "list.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dnstls.h"
|
||||
#include "resolved-forward.h"
|
||||
#include "socket-util.h"
|
||||
|
||||
@@ -7,17 +7,17 @@
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "capability-util.h"
|
||||
#include "dns-answer.h"
|
||||
#include "dns-packet.h"
|
||||
#include "dns-question.h"
|
||||
#include "dns-rr.h"
|
||||
#include "dns-type.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "log.h"
|
||||
#include "missing-network.h"
|
||||
#include "resolve-util.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-query.h"
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "resolved-dns-stream.h"
|
||||
#include "resolved-dns-stub.h"
|
||||
#include "resolved-dns-transaction.h"
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "dns-answer.h"
|
||||
#include "dns-domain.h"
|
||||
#include "dns-packet.h"
|
||||
#include "dns-question.h"
|
||||
#include "dns-rr.h"
|
||||
#include "dns-type.h"
|
||||
#include "env-util.h"
|
||||
#include "hostname-util.h"
|
||||
@@ -9,10 +13,6 @@
|
||||
#include "log.h"
|
||||
#include "missing-network.h"
|
||||
#include "resolved-def.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "resolved-dns-synthesize.h"
|
||||
#include "resolved-manager.h"
|
||||
#include "socket-util.h"
|
||||
|
||||
@@ -5,19 +5,19 @@
|
||||
|
||||
#include "af-list.h"
|
||||
#include "alloc-util.h"
|
||||
#include "dns-answer.h"
|
||||
#include "dns-domain.h"
|
||||
#include "dns-packet.h"
|
||||
#include "dns-question.h"
|
||||
#include "dns-rr.h"
|
||||
#include "errno-list.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "glyph-util.h"
|
||||
#include "log.h"
|
||||
#include "random-util.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-cache.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-query.h"
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "resolved-dns-scope.h"
|
||||
#include "resolved-dns-server.h"
|
||||
#include "resolved-dns-stream.h"
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
#include "alloc-util.h"
|
||||
#include "conf-files.h"
|
||||
#include "constants.h"
|
||||
#include "dns-answer.h"
|
||||
#include "dns-domain.h"
|
||||
#include "dns-rr.h"
|
||||
#include "extract-word.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
@@ -13,9 +15,7 @@
|
||||
#include "log.h"
|
||||
#include "nulstr-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-dnssec.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "resolved-dns-trust-anchor.h"
|
||||
#include "set.h"
|
||||
#include "string-util.h"
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "dns-answer.h"
|
||||
#include "dns-domain.h"
|
||||
#include "dns-packet.h"
|
||||
#include "dns-rr.h"
|
||||
#include "list.h"
|
||||
#include "log.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "resolved-dns-scope.h"
|
||||
#include "resolved-dns-transaction.h"
|
||||
#include "resolved-dns-zone.h"
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
#include "conf-parser.h"
|
||||
#include "constants.h"
|
||||
#include "dns-domain.h"
|
||||
#include "dns-rr.h"
|
||||
#include "extract-word.h"
|
||||
#include "hashmap.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "path-util.h"
|
||||
#include "resolved-conf.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "resolved-dns-zone.h"
|
||||
#include "resolved-dnssd.h"
|
||||
#include "resolved-manager.h"
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
#include "sd-event.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "dns-answer.h"
|
||||
#include "dns-domain.h"
|
||||
#include "dns-question.h"
|
||||
#include "dns-rr.h"
|
||||
#include "extract-word.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "hostname-util.h"
|
||||
#include "log.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "resolved-etc-hosts.h"
|
||||
#include "resolved-manager.h"
|
||||
#include "set.h"
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "dns-domain.h"
|
||||
#include "dns-packet.h"
|
||||
#include "dns-rr.h"
|
||||
#include "env-file.h"
|
||||
#include "extract-word.h"
|
||||
#include "fd-util.h"
|
||||
@@ -18,8 +20,6 @@
|
||||
#include "netif-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "resolved-dns-browse-services.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "resolved-dns-scope.h"
|
||||
#include "resolved-dns-search-domain.h"
|
||||
#include "resolved-dns-server.h"
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
|
||||
#include "sd-event.h"
|
||||
|
||||
#include "dns-packet.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "hashmap.h"
|
||||
#include "log.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-scope.h"
|
||||
#include "resolved-dns-transaction.h"
|
||||
#include "resolved-link.h"
|
||||
|
||||
@@ -14,7 +14,11 @@
|
||||
#include "alloc-util.h"
|
||||
#include "daemon-util.h"
|
||||
#include "dirent-util.h"
|
||||
#include "dns-answer.h"
|
||||
#include "dns-domain.h"
|
||||
#include "dns-packet.h"
|
||||
#include "dns-question.h"
|
||||
#include "dns-rr.h"
|
||||
#include "errno-util.h"
|
||||
#include "event-util.h"
|
||||
#include "fd-util.h"
|
||||
@@ -30,12 +34,8 @@
|
||||
#include "random-util.h"
|
||||
#include "resolved-bus.h"
|
||||
#include "resolved-conf.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-delegate.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-query.h"
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "resolved-dns-scope.h"
|
||||
#include "resolved-dns-search-domain.h"
|
||||
#include "resolved-dns-server.h"
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
#include "sd-event.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "dns-answer.h"
|
||||
#include "dns-domain.h"
|
||||
#include "dns-packet.h"
|
||||
#include "dns-question.h"
|
||||
#include "dns-rr.h"
|
||||
#include "fd-util.h"
|
||||
#include "log.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "resolved-dns-scope.h"
|
||||
#include "resolved-dns-transaction.h"
|
||||
#include "resolved-link.h"
|
||||
|
||||
@@ -4,19 +4,19 @@
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "bus-polkit.h"
|
||||
#include "dns-answer.h"
|
||||
#include "dns-domain.h"
|
||||
#include "dns-packet.h"
|
||||
#include "dns-question.h"
|
||||
#include "dns-rr.h"
|
||||
#include "dns-type.h"
|
||||
#include "errno-util.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "iovec-util.h"
|
||||
#include "json-util.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-browse-services.h"
|
||||
#include "resolved-dns-dnssec.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-query.h"
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "resolved-dns-scope.h"
|
||||
#include "resolved-dns-search-domain.h"
|
||||
#include "resolved-dns-server.h"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "dns-answer.h"
|
||||
#include "dns-rr.h"
|
||||
#include "dns-type.h"
|
||||
#include "memstream-util.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "strv.h"
|
||||
#include "tests.h"
|
||||
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
|
||||
#include "sd-json.h"
|
||||
|
||||
#include "dns-answer.h"
|
||||
#include "dns-packet.h"
|
||||
#include "dns-rr.h"
|
||||
#include "dns-type.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "resolve-util.h"
|
||||
#include "resolved-def.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-cache.h"
|
||||
#include "resolved-dns-dnssec.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "tests.h"
|
||||
#include "time-util.h"
|
||||
#include "tmpfile-util.h"
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "dns-answer.h"
|
||||
#include "dns-packet.h"
|
||||
#include "dns-question.h"
|
||||
#include "dns-rr.h"
|
||||
#include "dns-type.h"
|
||||
#include "list.h"
|
||||
#include "log.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "tests.h"
|
||||
|
||||
#define BIT_QR (1 << 7)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "dns-answer.h"
|
||||
#include "dns-packet.h"
|
||||
#include "dns-question.h"
|
||||
#include "dns-rr.h"
|
||||
#include "dns-type.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "tests.h"
|
||||
|
||||
#define BIT_QR (1 << 7)
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
#include "sd-id128.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "dns-packet.h"
|
||||
#include "dns-rr.h"
|
||||
#include "fileio.h"
|
||||
#include "glob-util.h"
|
||||
#include "log.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "siphash24.h"
|
||||
#include "strv.h"
|
||||
#include "tests.h"
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
#include "sd-event.h"
|
||||
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "dns-answer.h"
|
||||
#include "dns-packet.h"
|
||||
#include "dns-question.h"
|
||||
#include "dns-rr.h"
|
||||
#include "resolved-dns-query.h"
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "resolved-dns-scope.h"
|
||||
#include "resolved-dns-search-domain.h"
|
||||
#include "resolved-dns-server.h"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "dns-question.h"
|
||||
#include "dns-rr.h"
|
||||
#include "dns-type.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "memstream-util.h"
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "tests.h"
|
||||
|
||||
/* ================================================================
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
#include "sd-json.h"
|
||||
|
||||
#include "dns-packet.h"
|
||||
#include "dns-rr.h"
|
||||
#include "dns-type.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "tests.h"
|
||||
|
||||
/* ================================================================
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "dns-answer.h"
|
||||
#include "dns-packet.h"
|
||||
#include "dns-question.h"
|
||||
#include "dns-rr.h"
|
||||
#include "resolved-dns-synthesize.h"
|
||||
#include "resolved-manager.h"
|
||||
#include "tests.h"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "dns-answer.h"
|
||||
#include "dns-packet.h"
|
||||
#include "dns-rr.h"
|
||||
#include "dns-type.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "resolved-dns-scope.h"
|
||||
#include "resolved-dns-zone.h"
|
||||
#include "resolved-manager.h"
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "bitmap.h"
|
||||
#include "dns-answer.h"
|
||||
#include "dns-rr.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-dnssec.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "string-util.h"
|
||||
#include "tests.h"
|
||||
#include "time-util.h"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "dns-packet.h"
|
||||
#include "dns-type.h"
|
||||
#include "resolved-dns-dnssec.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "test-tables.h"
|
||||
#include "tests.h"
|
||||
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
#include "sd-daemon.h"
|
||||
#include "sd-event.h"
|
||||
|
||||
#include "dns-packet.h"
|
||||
#include "dns-question.h"
|
||||
#include "dns-type.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "iovec-util.h"
|
||||
#include "log.h"
|
||||
#include "main-func.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-manager.h"
|
||||
#include "socket-netlink.h"
|
||||
#include "socket-util.h"
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
#include "sd-event.h"
|
||||
#include "sd-netlink.h"
|
||||
|
||||
#include "dns-packet.h"
|
||||
#include "netlink-internal.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-scope.h"
|
||||
#include "resolved-dns-server.h"
|
||||
#include "resolved-link.h"
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
#include "sd-json.h"
|
||||
|
||||
#include "dns-answer.h"
|
||||
#include "dns-packet.h"
|
||||
#include "dns-rr.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "log.h"
|
||||
#include "resolved-dns-answer.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "tests.h"
|
||||
|
||||
TEST(dns_packet_new) {
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
|
||||
#include "sd-event.h"
|
||||
|
||||
#include "dns-packet.h"
|
||||
#include "dns-question.h"
|
||||
#include "dns-rr.h"
|
||||
#include "fd-util.h"
|
||||
#include "log.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "random-util.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-question.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "resolved-dns-server.h"
|
||||
#include "resolved-dns-stream.h"
|
||||
#include "resolved-dnstls.h"
|
||||
|
||||
Reference in New Issue
Block a user