mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-02-26 09:57:26 +03:00
commit
dcabda4155
1
.gitignore
vendored
1
.gitignore
vendored
@ -251,6 +251,7 @@
|
||||
/test-rbtree
|
||||
/test-replace-var
|
||||
/test-resolve
|
||||
/test-resolve-tables
|
||||
/test-ring
|
||||
/test-rlimit-util
|
||||
/test-sched-prio
|
||||
|
14
Makefile.am
14
Makefile.am
@ -1499,6 +1499,7 @@ tests += \
|
||||
test-af-list \
|
||||
test-arphrd-list \
|
||||
test-dns-domain \
|
||||
test-resolve-tables \
|
||||
test-install-root \
|
||||
test-rlimit-util \
|
||||
test-signal-util
|
||||
@ -1663,6 +1664,17 @@ test_dns_domain_LDADD = \
|
||||
libsystemd-network.la \
|
||||
libshared.la
|
||||
|
||||
test_resolve_tables_SOURCES = \
|
||||
src/resolve/test-resolve-tables.c \
|
||||
src/shared/test-tables.h \
|
||||
src/resolve/dns-type.c \
|
||||
src/resolve/dns-type.h \
|
||||
src/resolve/dns_type-from-name.h \
|
||||
src/resolve/dns_type-to-name.h
|
||||
|
||||
test_resolve_tables_LDADD = \
|
||||
libshared.la
|
||||
|
||||
if ENABLE_EFI
|
||||
manual_tests += \
|
||||
test-boot-timestamp
|
||||
@ -5286,6 +5298,8 @@ lib_LTLIBRARIES += \
|
||||
|
||||
systemd_resolve_SOURCES = \
|
||||
src/resolve/resolve-tool.c \
|
||||
src/resolve/resolved-dns-dnssec.c \
|
||||
src/resolve/resolved-dns-dnssec.h \
|
||||
src/resolve/resolved-dns-packet.c \
|
||||
src/resolve/resolved-dns-packet.h \
|
||||
src/resolve/resolved-dns-rr.c \
|
||||
|
@ -131,8 +131,8 @@
|
||||
<listitem><para>Takes a boolean argument or
|
||||
<literal>allow-downgrade</literal>. If true all DNS lookups are
|
||||
DNSSEC-validated locally (excluding LLMNR and Multicast
|
||||
DNS). If a response for a lookup request is detected invalid
|
||||
this is returned as lookup failure to applications. Note that
|
||||
DNS). If the response to a lookup request is detected to be invalid
|
||||
a lookup failure is returned to applications. Note that
|
||||
this mode requires a DNS server that supports DNSSEC. If the
|
||||
DNS server does not properly support DNSSEC all validations
|
||||
will fail. If set to <literal>allow-downgrade</literal> DNSSEC
|
||||
@ -153,7 +153,7 @@
|
||||
is built into the resolver, additional trust anchors may be
|
||||
defined with
|
||||
<citerefentry><refentrytitle>dnssec-trust-anchors.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||
Trust anchors may change in regular intervals, and old trust
|
||||
Trust anchors may change at regular intervals, and old trust
|
||||
anchors may be revoked. In such a case DNSSEC validation is
|
||||
not possible until new trust anchors are configured locally or
|
||||
the resolver software package is updated with the new root
|
||||
|
@ -64,14 +64,14 @@
|
||||
<cmdsynopsis>
|
||||
<command>systemd-resolve</command>
|
||||
<arg choice="opt" rep="repeat">OPTIONS</arg>
|
||||
<command>--type=<replaceable>TYPE</replaceable></command>
|
||||
<command> --type=<replaceable>TYPE</replaceable></command>
|
||||
<arg choice="plain" rep="repeat"><replaceable>RRDOMAIN</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
|
||||
<cmdsynopsis>
|
||||
<command>systemd-resolve</command>
|
||||
<arg choice="opt" rep="repeat">OPTIONS</arg>
|
||||
<command>--service</command>
|
||||
<command> --service</command>
|
||||
<arg choice="plain"><arg choice="opt"><arg choice="opt"><replaceable>NAME</replaceable></arg>
|
||||
<replaceable>TYPE</replaceable></arg> <replaceable>DOMAIN</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
@ -79,13 +79,13 @@
|
||||
<cmdsynopsis>
|
||||
<command>systemd-resolve</command>
|
||||
<arg choice="opt" rep="repeat">OPTIONS</arg>
|
||||
<command>--statistics</command>
|
||||
<command> --statistics</command>
|
||||
</cmdsynopsis>
|
||||
|
||||
<cmdsynopsis>
|
||||
<command>systemd-resolve</command>
|
||||
<arg choice="opt" rep="repeat">OPTIONS</arg>
|
||||
<command>--reset-statistics</command>
|
||||
<command> --reset-statistics</command>
|
||||
</cmdsynopsis>
|
||||
|
||||
</refsynopsisdiv>
|
||||
@ -101,7 +101,8 @@
|
||||
done, and a hostname is retrieved for the specified addresses.</para>
|
||||
|
||||
<para>The <option>--type=</option> switch may be used to specify a DNS resource record type (A, AAAA, SOA, MX, ...) in
|
||||
order to request a specific DNS resource record, instead of the address or reverse address lookups.</para>
|
||||
order to request a specific DNS resource record, instead of the address or reverse address lookups.
|
||||
The special value <literal>help</literal> may be used to list known values.</para>
|
||||
|
||||
<para>The <option>--service</option> switch may be used to resolve <ulink
|
||||
url="https://tools.ietf.org/html/rfc2782">SRV</ulink> and <ulink
|
||||
@ -157,7 +158,9 @@
|
||||
same time. The setting <literal>llmnr</literal> is identical to specifying this switch once with
|
||||
<literal>llmnr-ipv4</literal> and once via <literal>llmnr-ipv6</literal>. Note that this option does not force
|
||||
the service to resolve the operation with the specified protocol, as that might require a suitable network
|
||||
interface and configuration.</para></listitem>
|
||||
interface and configuration.
|
||||
The special value <literal>help</literal> may be used to list known values.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@ -168,7 +171,9 @@
|
||||
|
||||
<listitem><para>Specifies the DNS resource record type (e.g. A, AAAA, MX, …) and class (e.g. IN, ANY, …) to
|
||||
look up. If these options are used a DNS resource record set matching the specified class and type is
|
||||
requested. The class defaults to IN if only a type is specified.</para></listitem>
|
||||
requested. The class defaults to IN if only a type is specified.
|
||||
The special value <literal>help</literal> may be used to list known values.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -514,14 +514,14 @@ int unbase64char(char c) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
char *base64mem(const void *p, size_t l) {
|
||||
ssize_t base64mem(const void *p, size_t l, char **out) {
|
||||
char *r, *z;
|
||||
const uint8_t *x;
|
||||
|
||||
/* three input bytes makes four output bytes, padding is added so we must round up */
|
||||
z = r = malloc(4 * (l + 2) / 3 + 1);
|
||||
if (!r)
|
||||
return NULL;
|
||||
return -ENOMEM;
|
||||
|
||||
for (x = p; x < (const uint8_t*) p + (l / 3) * 3; x += 3) {
|
||||
/* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ */
|
||||
@ -549,9 +549,64 @@ char *base64mem(const void *p, size_t l) {
|
||||
}
|
||||
|
||||
*z = 0;
|
||||
return r;
|
||||
*out = r;
|
||||
return z - r;
|
||||
}
|
||||
|
||||
static int base64_append_width(char **prefix, int plen,
|
||||
const char *sep, int indent,
|
||||
const void *p, size_t l,
|
||||
int width) {
|
||||
|
||||
_cleanup_free_ char *x = NULL;
|
||||
char *t, *s;
|
||||
ssize_t slen, len, avail;
|
||||
int line, lines;
|
||||
|
||||
len = base64mem(p, l, &x);
|
||||
if (len <= 0)
|
||||
return len;
|
||||
|
||||
lines = (len + width - 1) / width;
|
||||
|
||||
slen = sep ? strlen(sep) : 0;
|
||||
t = realloc(*prefix, plen + 1 + slen + (indent + width + 1) * lines);
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(t + plen, sep, slen);
|
||||
|
||||
for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) {
|
||||
int act = MIN(width, avail);
|
||||
|
||||
if (line > 0 || sep) {
|
||||
memset(s, ' ', indent);
|
||||
s += indent;
|
||||
}
|
||||
|
||||
memcpy(s, x + width * line, act);
|
||||
s += act;
|
||||
*(s++) = line < lines - 1 ? '\n' : '\0';
|
||||
avail -= act;
|
||||
}
|
||||
assert(avail == 0);
|
||||
|
||||
*prefix = t;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int base64_append(char **prefix, int plen,
|
||||
const void *p, size_t l,
|
||||
int indent, int width) {
|
||||
if (plen > width / 2 || plen + indent > width)
|
||||
/* leave indent on the left, keep last column free */
|
||||
return base64_append_width(prefix, plen, "\n", indent, p, l, width - indent - 1);
|
||||
else
|
||||
/* leave plen on the left, keep last column free */
|
||||
return base64_append_width(prefix, plen, NULL, plen, p, l, width - plen - 1);
|
||||
};
|
||||
|
||||
|
||||
int unbase64mem(const char *p, size_t l, void **mem, size_t *_len) {
|
||||
_cleanup_free_ uint8_t *r = NULL;
|
||||
int a, b, c, d;
|
||||
|
@ -49,7 +49,10 @@ int unbase64char(char c) _const_;
|
||||
char *base32hexmem(const void *p, size_t l, bool padding);
|
||||
int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *len);
|
||||
|
||||
char *base64mem(const void *p, size_t l);
|
||||
ssize_t base64mem(const void *p, size_t l, char **out);
|
||||
int base64_append(char **prefix, int plen,
|
||||
const void *p, size_t l,
|
||||
int margin, int width);
|
||||
int unbase64mem(const char *p, size_t l, void **mem, size_t *len);
|
||||
|
||||
void hexdump(FILE *f, const void *p, size_t s);
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "dns-type.h"
|
||||
#include "parse-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
typedef const struct {
|
||||
@ -41,10 +42,19 @@ int dns_type_from_string(const char *s) {
|
||||
assert(s);
|
||||
|
||||
sc = lookup_dns_type(s, strlen(s));
|
||||
if (!sc)
|
||||
return _DNS_TYPE_INVALID;
|
||||
if (sc)
|
||||
return sc->id;
|
||||
|
||||
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) {
|
||||
@ -228,3 +238,33 @@ int dns_class_from_string(const char *s) {
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
@ -87,6 +87,7 @@ enum {
|
||||
DNS_TYPE_TALINK,
|
||||
DNS_TYPE_CDS,
|
||||
DNS_TYPE_CDNSKEY,
|
||||
DNS_TYPE_OPENPGPKEY,
|
||||
|
||||
DNS_TYPE_SPF = 0x63,
|
||||
DNS_TYPE_NID,
|
||||
@ -138,8 +139,18 @@ int dns_type_to_af(uint16_t t);
|
||||
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 type);
|
||||
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);
|
||||
|
@ -900,6 +900,12 @@ static int reset_statistics(sd_bus *bus) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void help_protocol_types(void) {
|
||||
if (arg_legend)
|
||||
puts("Known protocol types:");
|
||||
puts("dns\nllmnr\nllmnr-ipv4\nllmnr-ipv6");
|
||||
}
|
||||
|
||||
static void help_dns_types(void) {
|
||||
int i;
|
||||
const char *t;
|
||||
@ -930,22 +936,22 @@ static void help(void) {
|
||||
printf("%s [OPTIONS...] NAME...\n"
|
||||
"%s [OPTIONS...] --service [[NAME] TYPE] DOMAIN\n\n"
|
||||
"Resolve domain names, IPv4 and IPv6 addresses, DNS resource records, and services.\n\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
" -4 Resolve IPv4 addresses\n"
|
||||
" -6 Resolve IPv6 addresses\n"
|
||||
" -i --interface=INTERFACE Look on interface\n"
|
||||
" -p --protocol=PROTOCOL Look via protocol\n"
|
||||
" -t --type=TYPE Query RR with DNS type\n"
|
||||
" -c --class=CLASS Query RR with DNS class\n"
|
||||
" --service Resolve service (SRV)\n"
|
||||
" --service-address=BOOL Do [not] resolve address for services\n"
|
||||
" --service-txt=BOOL Do [not] resolve TXT records for services\n"
|
||||
" --cname=BOOL Do [not] follow CNAME redirects\n"
|
||||
" --search=BOOL Do [not] use search domains\n"
|
||||
" --legend=BOOL Do [not] print column headers and meta information\n"
|
||||
" --statistics Show resolver statistics\n"
|
||||
" --reset-statistics Reset resolver statistics\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
" -4 Resolve IPv4 addresses\n"
|
||||
" -6 Resolve IPv6 addresses\n"
|
||||
" -i --interface=INTERFACE Look on interface\n"
|
||||
" -p --protocol=PROTOCOL|help Look via protocol\n"
|
||||
" -t --type=TYPE|help Query RR with DNS type\n"
|
||||
" -c --class=CLASS|help Query RR with DNS class\n"
|
||||
" --service Resolve service (SRV)\n"
|
||||
" --service-address=BOOL Do [not] resolve address for services\n"
|
||||
" --service-txt=BOOL Do [not] resolve TXT records for services\n"
|
||||
" --cname=BOOL Do [not] follow CNAME redirects\n"
|
||||
" --search=BOOL Do [not] use search domains\n"
|
||||
" --legend=BOOL Do [not] print column headers and meta information\n"
|
||||
" --statistics Show resolver statistics\n"
|
||||
" --reset-statistics Reset resolver statistics\n"
|
||||
, program_invocation_short_name, program_invocation_short_name);
|
||||
}
|
||||
|
||||
@ -1061,7 +1067,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
if (streq(optarg, "dns"))
|
||||
if (streq(optarg, "help")) {
|
||||
help_protocol_types();
|
||||
return 0;
|
||||
} else if (streq(optarg, "dns"))
|
||||
arg_flags |= SD_RESOLVED_DNS;
|
||||
else if (streq(optarg, "llmnr"))
|
||||
arg_flags |= SD_RESOLVED_LLMNR;
|
||||
|
@ -1058,11 +1058,28 @@ int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *star
|
||||
|
||||
break;
|
||||
|
||||
case DNS_TYPE_TLSA:
|
||||
r = dns_packet_append_uint8(p, rr->tlsa.cert_usage, NULL);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = dns_packet_append_uint8(p, rr->tlsa.selector, NULL);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = dns_packet_append_uint8(p, rr->tlsa.matching_type, NULL);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = dns_packet_append_blob(p, rr->tlsa.data, rr->tlsa.data_size, NULL);
|
||||
break;
|
||||
|
||||
case DNS_TYPE_OPT:
|
||||
case DNS_TYPE_OPENPGPKEY:
|
||||
case _DNS_TYPE_INVALID: /* unparseable */
|
||||
default:
|
||||
|
||||
r = dns_packet_append_blob(p, rr->generic.data, rr->generic.size, NULL);
|
||||
r = dns_packet_append_blob(p, rr->generic.data, rr->generic.data_size, NULL);
|
||||
break;
|
||||
}
|
||||
if (r < 0)
|
||||
@ -1976,10 +1993,36 @@ int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool *ret_cache_fl
|
||||
break;
|
||||
}
|
||||
|
||||
case DNS_TYPE_TLSA:
|
||||
r = dns_packet_read_uint8(p, &rr->tlsa.cert_usage, NULL);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = dns_packet_read_uint8(p, &rr->tlsa.selector, NULL);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = dns_packet_read_uint8(p, &rr->tlsa.matching_type, NULL);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
r = dns_packet_read_memdup(p, rdlength - 3,
|
||||
&rr->tlsa.data, &rr->tlsa.data_size,
|
||||
NULL);
|
||||
if (rr->tlsa.data_size <= 0) {
|
||||
/* the accepted size depends on the algorithm, but for now
|
||||
just ensure that the value is greater than zero */
|
||||
r = -EBADMSG;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case DNS_TYPE_OPT: /* we only care about the header of OPT for now. */
|
||||
case DNS_TYPE_OPENPGPKEY:
|
||||
default:
|
||||
unparseable:
|
||||
r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.size, NULL);
|
||||
r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.data_size, NULL);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
break;
|
||||
@ -2021,7 +2064,7 @@ static bool opt_is_good(DnsResourceRecord *rr, bool *rfc6975) {
|
||||
return false;
|
||||
|
||||
p = rr->opt.data;
|
||||
l = rr->opt.size;
|
||||
l = rr->opt.data_size;
|
||||
while (l > 0) {
|
||||
uint16_t option_code, option_length;
|
||||
|
||||
|
@ -25,11 +25,13 @@
|
||||
#include "dns-domain.h"
|
||||
#include "dns-type.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "resolved-dns-dnssec.h"
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "resolved-dns-rr.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "terminal-util.h"
|
||||
|
||||
DnsResourceKey* dns_resource_key_new(uint16_t class, uint16_t type, const char *name) {
|
||||
DnsResourceKey *k;
|
||||
@ -486,6 +488,11 @@ DnsResourceRecord* dns_resource_record_unref(DnsResourceRecord *rr) {
|
||||
case DNS_TYPE_AAAA:
|
||||
break;
|
||||
|
||||
case DNS_TYPE_TLSA:
|
||||
free(rr->tlsa.data);
|
||||
break;
|
||||
|
||||
case DNS_TYPE_OPENPGPKEY:
|
||||
default:
|
||||
free(rr->generic.data);
|
||||
}
|
||||
@ -564,6 +571,10 @@ int dns_resource_record_new_address(DnsResourceRecord **ret, int family, const u
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define FIELD_EQUAL(a, b, field) \
|
||||
((a).field ## _size == (b).field ## _size && \
|
||||
memcmp((a).field, (b).field, (a).field ## _size) == 0)
|
||||
|
||||
int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecord *b) {
|
||||
int r;
|
||||
|
||||
@ -645,36 +656,30 @@ int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecor
|
||||
return a->ds.key_tag == b->ds.key_tag &&
|
||||
a->ds.algorithm == b->ds.algorithm &&
|
||||
a->ds.digest_type == b->ds.digest_type &&
|
||||
a->ds.digest_size == b->ds.digest_size &&
|
||||
memcmp(a->ds.digest, b->ds.digest, a->ds.digest_size) == 0;
|
||||
FIELD_EQUAL(a->ds, b->ds, digest);
|
||||
|
||||
case DNS_TYPE_SSHFP:
|
||||
return a->sshfp.algorithm == b->sshfp.algorithm &&
|
||||
a->sshfp.fptype == b->sshfp.fptype &&
|
||||
a->sshfp.fingerprint_size == b->sshfp.fingerprint_size &&
|
||||
memcmp(a->sshfp.fingerprint, b->sshfp.fingerprint, a->sshfp.fingerprint_size) == 0;
|
||||
FIELD_EQUAL(a->sshfp, b->sshfp, fingerprint);
|
||||
|
||||
case DNS_TYPE_DNSKEY:
|
||||
return a->dnskey.flags == b->dnskey.flags &&
|
||||
a->dnskey.protocol == b->dnskey.protocol &&
|
||||
a->dnskey.algorithm == b->dnskey.algorithm &&
|
||||
a->dnskey.key_size == b->dnskey.key_size &&
|
||||
memcmp(a->dnskey.key, b->dnskey.key, a->dnskey.key_size) == 0;
|
||||
FIELD_EQUAL(a->dnskey, b->dnskey, key);
|
||||
|
||||
case DNS_TYPE_RRSIG:
|
||||
/* do the fast comparisons first */
|
||||
if (a->rrsig.type_covered != b->rrsig.type_covered ||
|
||||
a->rrsig.algorithm != b->rrsig.algorithm ||
|
||||
a->rrsig.labels != b->rrsig.labels ||
|
||||
a->rrsig.original_ttl != b->rrsig.original_ttl ||
|
||||
a->rrsig.expiration != b->rrsig.expiration ||
|
||||
a->rrsig.inception != b->rrsig.inception ||
|
||||
a->rrsig.key_tag != b->rrsig.key_tag ||
|
||||
a->rrsig.signature_size != b->rrsig.signature_size ||
|
||||
memcmp(a->rrsig.signature, b->rrsig.signature, a->rrsig.signature_size) != 0)
|
||||
return false;
|
||||
|
||||
return dns_name_equal(a->rrsig.signer, b->rrsig.signer);
|
||||
return a->rrsig.type_covered == b->rrsig.type_covered &&
|
||||
a->rrsig.algorithm == b->rrsig.algorithm &&
|
||||
a->rrsig.labels == b->rrsig.labels &&
|
||||
a->rrsig.original_ttl == b->rrsig.original_ttl &&
|
||||
a->rrsig.expiration == b->rrsig.expiration &&
|
||||
a->rrsig.inception == b->rrsig.inception &&
|
||||
a->rrsig.key_tag == b->rrsig.key_tag &&
|
||||
FIELD_EQUAL(a->rrsig, b->rrsig, signature) &&
|
||||
dns_name_equal(a->rrsig.signer, b->rrsig.signer);
|
||||
|
||||
case DNS_TYPE_NSEC:
|
||||
return dns_name_equal(a->nsec.next_domain_name, b->nsec.next_domain_name) &&
|
||||
@ -682,16 +687,20 @@ int dns_resource_record_equal(const DnsResourceRecord *a, const DnsResourceRecor
|
||||
|
||||
case DNS_TYPE_NSEC3:
|
||||
return a->nsec3.algorithm == b->nsec3.algorithm &&
|
||||
a->nsec3.flags == b->nsec3.flags &&
|
||||
a->nsec3.iterations == b->nsec3.iterations &&
|
||||
a->nsec3.salt_size == b->nsec3.salt_size &&
|
||||
memcmp(a->nsec3.salt, b->nsec3.salt, a->nsec3.salt_size) == 0 &&
|
||||
memcmp(a->nsec3.next_hashed_name, b->nsec3.next_hashed_name, a->nsec3.next_hashed_name_size) == 0 &&
|
||||
bitmap_equal(a->nsec3.types, b->nsec3.types);
|
||||
a->nsec3.flags == b->nsec3.flags &&
|
||||
a->nsec3.iterations == b->nsec3.iterations &&
|
||||
FIELD_EQUAL(a->nsec3, b->nsec3, salt) &&
|
||||
FIELD_EQUAL(a->nsec3, b->nsec3, next_hashed_name) &&
|
||||
bitmap_equal(a->nsec3.types, b->nsec3.types);
|
||||
|
||||
case DNS_TYPE_TLSA:
|
||||
return a->tlsa.cert_usage == b->tlsa.cert_usage &&
|
||||
a->tlsa.selector == b->tlsa.selector &&
|
||||
a->tlsa.matching_type == b->tlsa.matching_type &&
|
||||
FIELD_EQUAL(a->tlsa, b->tlsa, data);
|
||||
|
||||
default:
|
||||
return a->generic.size == b->generic.size &&
|
||||
memcmp(a->generic.data, b->generic.data, a->generic.size) == 0;
|
||||
return FIELD_EQUAL(a->generic, b->generic, data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -958,23 +967,47 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
|
||||
|
||||
case DNS_TYPE_DNSKEY: {
|
||||
_cleanup_free_ char *alg = NULL;
|
||||
char *ss;
|
||||
int n, n1;
|
||||
uint16_t key_tag;
|
||||
|
||||
key_tag = dnssec_keytag(rr, true);
|
||||
|
||||
r = dnssec_algorithm_to_string_alloc(rr->dnskey.algorithm, &alg);
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
|
||||
t = base64mem(rr->dnskey.key, rr->dnskey.key_size);
|
||||
if (!t)
|
||||
return NULL;
|
||||
|
||||
r = asprintf(&s, "%s %u %u %s %s",
|
||||
r = asprintf(&s, "%s %n%u %u %s %n",
|
||||
k,
|
||||
&n1,
|
||||
rr->dnskey.flags,
|
||||
rr->dnskey.protocol,
|
||||
alg,
|
||||
t);
|
||||
&n);
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
|
||||
r = base64_append(&s, n,
|
||||
rr->dnskey.key, rr->dnskey.key_size,
|
||||
8, columns());
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
|
||||
r = asprintf(&ss, "%s\n"
|
||||
"%*s-- Flags:%s%s%s\n"
|
||||
"%*s-- Key tag: %u",
|
||||
s,
|
||||
n1, "",
|
||||
rr->dnskey.flags & DNSKEY_FLAG_SEP ? " SEP" : "",
|
||||
rr->dnskey.flags & DNSKEY_FLAG_REVOKE ? " REVOKE" : "",
|
||||
rr->dnskey.flags & DNSKEY_FLAG_ZONE_KEY ? " ZONE_KEY" : "",
|
||||
n1, "",
|
||||
key_tag);
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
free(s);
|
||||
s = ss;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -982,6 +1015,7 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
|
||||
_cleanup_free_ char *alg = NULL;
|
||||
char expiration[strlen("YYYYMMDDHHmmSS") + 1], inception[strlen("YYYYMMDDHHmmSS") + 1];
|
||||
const char *type;
|
||||
int n;
|
||||
|
||||
type = dns_type_to_string(rr->rrsig.type_covered);
|
||||
|
||||
@ -989,10 +1023,6 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
|
||||
t = base64mem(rr->rrsig.signature, rr->rrsig.signature_size);
|
||||
if (!t)
|
||||
return NULL;
|
||||
|
||||
r = format_timestamp_dns(expiration, sizeof(expiration), rr->rrsig.expiration);
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
@ -1004,7 +1034,7 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
|
||||
/* TYPE?? follows
|
||||
* http://tools.ietf.org/html/rfc3597#section-5 */
|
||||
|
||||
r = asprintf(&s, "%s %s%.*u %s %u %u %s %s %u %s %s",
|
||||
r = asprintf(&s, "%s %s%.*u %s %u %u %s %s %u %s %n",
|
||||
k,
|
||||
type ?: "TYPE",
|
||||
type ? 0 : 1, type ? 0u : (unsigned) rr->rrsig.type_covered,
|
||||
@ -1015,9 +1045,16 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
|
||||
inception,
|
||||
rr->rrsig.key_tag,
|
||||
rr->rrsig.signer,
|
||||
t);
|
||||
&n);
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
|
||||
r = base64_append(&s, n,
|
||||
rr->rrsig.signature, rr->rrsig.signature_size,
|
||||
8, columns());
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1065,13 +1102,70 @@ const char *dns_resource_record_to_string(DnsResourceRecord *rr) {
|
||||
break;
|
||||
}
|
||||
|
||||
case DNS_TYPE_TLSA: {
|
||||
const char *cert_usage, *selector, *matching_type;
|
||||
char *ss;
|
||||
int n;
|
||||
|
||||
cert_usage = tlsa_cert_usage_to_string(rr->tlsa.cert_usage);
|
||||
selector = tlsa_selector_to_string(rr->tlsa.selector);
|
||||
matching_type = tlsa_matching_type_to_string(rr->tlsa.matching_type);
|
||||
|
||||
r = asprintf(&s, "%s %u %u %u %n",
|
||||
k,
|
||||
rr->tlsa.cert_usage,
|
||||
rr->tlsa.selector,
|
||||
rr->tlsa.matching_type,
|
||||
&n);
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
|
||||
r = base64_append(&s, n,
|
||||
rr->tlsa.data, rr->tlsa.data_size,
|
||||
8, columns());
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
|
||||
r = asprintf(&ss, "%s\n"
|
||||
"%*s-- Cert. usage: %s\n"
|
||||
"%*s-- Selector: %s\n"
|
||||
"%*s-- Matching type: %s",
|
||||
s,
|
||||
n - 6, "", cert_usage,
|
||||
n - 6, "", selector,
|
||||
n - 6, "", matching_type);
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
free(s);
|
||||
s = ss;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DNS_TYPE_OPENPGPKEY: {
|
||||
int n;
|
||||
|
||||
r = asprintf(&s, "%s %n",
|
||||
k,
|
||||
&n);
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
|
||||
r = base64_append(&s, n,
|
||||
rr->generic.data, rr->generic.data_size,
|
||||
8, columns());
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
t = hexmem(rr->generic.data, rr->generic.size);
|
||||
t = hexmem(rr->generic.data, rr->generic.data_size);
|
||||
if (!t)
|
||||
return NULL;
|
||||
|
||||
/* Format as documented in RFC 3597, Section 5 */
|
||||
r = asprintf(&s, "%s \\# %zu %s", k, rr->generic.size, t);
|
||||
r = asprintf(&s, "%s \\# %zu %s", k, rr->generic.data_size, t);
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
break;
|
||||
@ -1331,8 +1425,16 @@ static void dns_resource_record_hash_func(const void *i, struct siphash *state)
|
||||
/* FIXME: We leave the bitmaps out */
|
||||
break;
|
||||
|
||||
case DNS_TYPE_TLSA:
|
||||
siphash24_compress(&rr->tlsa.cert_usage, sizeof(rr->tlsa.cert_usage), state);
|
||||
siphash24_compress(&rr->tlsa.selector, sizeof(rr->tlsa.selector), state);
|
||||
siphash24_compress(&rr->tlsa.matching_type, sizeof(rr->tlsa.matching_type), state);
|
||||
siphash24_compress(&rr->tlsa.data, rr->tlsa.data_size, state);
|
||||
break;
|
||||
|
||||
case DNS_TYPE_OPENPGPKEY:
|
||||
default:
|
||||
siphash24_compress(rr->generic.data, rr->generic.size, state);
|
||||
siphash24_compress(rr->generic.data, rr->generic.data_size, state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ struct DnsResourceRecord {
|
||||
union {
|
||||
struct {
|
||||
void *data;
|
||||
size_t size;
|
||||
size_t data_size;
|
||||
} generic, opt;
|
||||
|
||||
struct {
|
||||
@ -242,6 +242,15 @@ struct DnsResourceRecord {
|
||||
size_t next_hashed_name_size;
|
||||
Bitmap *types;
|
||||
} nsec3;
|
||||
|
||||
/* https://tools.ietf.org/html/draft-ietf-dane-protocol-23 */
|
||||
struct {
|
||||
uint8_t cert_usage;
|
||||
uint8_t selector;
|
||||
uint8_t matching_type;
|
||||
void *data;
|
||||
size_t data_size;
|
||||
} tlsa;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -657,7 +657,9 @@ DnsServer *manager_set_dns_server(Manager *m, DnsServer *s) {
|
||||
return s;
|
||||
|
||||
if (s)
|
||||
log_info("Switching to system DNS server %s.", dns_server_string(s));
|
||||
log_info("Switching to %s DNS server %s.",
|
||||
dns_server_type_to_string(s->type),
|
||||
dns_server_string(s));
|
||||
|
||||
dns_server_unref(m->current_dns_server);
|
||||
m->current_dns_server = dns_server_ref(s);
|
||||
@ -675,7 +677,7 @@ DnsServer *manager_get_dns_server(Manager *m) {
|
||||
/* Try to read updates resolv.conf */
|
||||
manager_read_resolv_conf(m);
|
||||
|
||||
/* If no DNS server was chose so far, pick the first one */
|
||||
/* If no DNS server was chosen so far, pick the first one */
|
||||
if (!m->current_dns_server)
|
||||
manager_set_dns_server(m, m->dns_servers);
|
||||
|
||||
@ -723,6 +725,13 @@ void manager_next_dns_server(Manager *m) {
|
||||
manager_set_dns_server(m, m->dns_servers);
|
||||
}
|
||||
|
||||
static const char* const dns_server_type_table[_DNS_SERVER_TYPE_MAX] = {
|
||||
[DNS_SERVER_SYSTEM] = "system",
|
||||
[DNS_SERVER_FALLBACK] = "fallback",
|
||||
[DNS_SERVER_LINK] = "link",
|
||||
};
|
||||
DEFINE_STRING_TABLE_LOOKUP(dns_server_type, DnsServerType);
|
||||
|
||||
static const char* const dns_server_feature_level_table[_DNS_SERVER_FEATURE_LEVEL_MAX] = {
|
||||
[DNS_SERVER_FEATURE_LEVEL_TCP] = "TCP",
|
||||
[DNS_SERVER_FEATURE_LEVEL_UDP] = "UDP",
|
||||
|
@ -30,6 +30,10 @@ typedef enum DnsServerType {
|
||||
DNS_SERVER_FALLBACK,
|
||||
DNS_SERVER_LINK,
|
||||
} DnsServerType;
|
||||
#define _DNS_SERVER_TYPE_MAX (DNS_SERVER_LINK + 1)
|
||||
|
||||
const char* dns_server_type_to_string(DnsServerType i) _const_;
|
||||
DnsServerType dns_server_type_from_string(const char *s) _pure_;
|
||||
|
||||
typedef enum DnsServerFeatureLevel {
|
||||
DNS_SERVER_FEATURE_LEVEL_TCP,
|
||||
|
@ -288,7 +288,7 @@ static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *
|
||||
|
||||
r = manager_write_resolv_conf(m);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Could not update resolv.conf: %m");
|
||||
log_warning_errno(r, "Could not update "PRIVATE_RESOLV_CONF": %m");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -226,8 +226,6 @@ static int write_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSet *doma
|
||||
|
||||
int manager_write_resolv_conf(Manager *m) {
|
||||
|
||||
#define PRIVATE_RESOLV_CONF "/run/systemd/resolve/resolv.conf"
|
||||
|
||||
_cleanup_ordered_set_free_ OrderedSet *dns = NULL, *domains = NULL;
|
||||
_cleanup_free_ char *temp_path = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
|
@ -23,5 +23,7 @@
|
||||
|
||||
#include "resolved-manager.h"
|
||||
|
||||
#define PRIVATE_RESOLV_CONF "/run/systemd/resolve/resolv.conf"
|
||||
|
||||
int manager_read_resolv_conf(Manager *m);
|
||||
int manager_write_resolv_conf(Manager *m);
|
||||
|
@ -91,7 +91,7 @@ int main(int argc, char *argv[]) {
|
||||
* symlink */
|
||||
r = manager_write_resolv_conf(m);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Could not create resolv.conf: %m");
|
||||
log_warning_errno(r, "Could not create "PRIVATE_RESOLV_CONF": %m");
|
||||
|
||||
sd_notify(false,
|
||||
"READY=1\n"
|
||||
|
27
src/resolve/test-resolve-tables.c
Normal file
27
src/resolve/test-resolve-tables.c
Normal file
@ -0,0 +1,27 @@
|
||||
/***
|
||||
This file is part of systemd
|
||||
|
||||
Copyright 2013 Zbigniew Jędrzejewski-Szmek
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include "dns-type.h"
|
||||
#include "test-tables.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
test_table_sparse(dns_type, DNS_TYPE);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
@ -28,18 +28,25 @@ static inline void _test_table(const char *name,
|
||||
reverse_t reverse,
|
||||
int size,
|
||||
bool sparse) {
|
||||
int i;
|
||||
int i, boring = 0;
|
||||
|
||||
for (i = -1; i < size + 1; i++) {
|
||||
const char* val = lookup(i);
|
||||
int rev;
|
||||
|
||||
if (val)
|
||||
if (val) {
|
||||
rev = reverse(val);
|
||||
else
|
||||
boring = 0;
|
||||
} else {
|
||||
rev = reverse("--no-such--value----");
|
||||
boring += i >= 0;
|
||||
}
|
||||
|
||||
if (boring < 1 || i == size)
|
||||
printf("%s: %d → %s → %d\n", name, i, val, rev);
|
||||
else if (boring == 1)
|
||||
printf("%*s ...\n", (int) strlen(name), "");
|
||||
|
||||
printf("%s: %d → %s → %d\n", name, i, val, rev);
|
||||
assert_se(!(i >= 0 && i < size ?
|
||||
sparse ? rev != i && rev != -1 : val == NULL || rev != i :
|
||||
val != NULL || rev != -1));
|
||||
|
@ -545,38 +545,31 @@ static void test_unbase32hexmem(void) {
|
||||
static void test_base64mem(void) {
|
||||
char *b64;
|
||||
|
||||
b64 = base64mem("", strlen(""));
|
||||
assert_se(b64);
|
||||
assert_se(base64mem("", strlen(""), &b64) == 0);
|
||||
assert_se(streq(b64, ""));
|
||||
free(b64);
|
||||
|
||||
b64 = base64mem("f", strlen("f"));
|
||||
assert_se(b64);
|
||||
assert_se(base64mem("f", strlen("f"), &b64) == 4);
|
||||
assert_se(streq(b64, "Zg=="));
|
||||
free(b64);
|
||||
|
||||
b64 = base64mem("fo", strlen("fo"));
|
||||
assert_se(b64);
|
||||
assert_se(base64mem("fo", strlen("fo"), &b64) == 4);
|
||||
assert_se(streq(b64, "Zm8="));
|
||||
free(b64);
|
||||
|
||||
b64 = base64mem("foo", strlen("foo"));
|
||||
assert_se(b64);
|
||||
assert_se(base64mem("foo", strlen("foo"), &b64) == 4);
|
||||
assert_se(streq(b64, "Zm9v"));
|
||||
free(b64);
|
||||
|
||||
b64 = base64mem("foob", strlen("foob"));
|
||||
assert_se(b64);
|
||||
assert_se(base64mem("foob", strlen("foob"), &b64) == 8);
|
||||
assert_se(streq(b64, "Zm9vYg=="));
|
||||
free(b64);
|
||||
|
||||
b64 = base64mem("fooba", strlen("fooba"));
|
||||
assert_se(b64);
|
||||
assert_se(base64mem("fooba", strlen("fooba"), &b64) == 8);
|
||||
assert_se(streq(b64, "Zm9vYmE="));
|
||||
free(b64);
|
||||
|
||||
b64 = base64mem("foobar", strlen("foobar"));
|
||||
assert_se(b64);
|
||||
assert_se(base64mem("foobar", strlen("foobar"), &b64) == 8);
|
||||
assert_se(streq(b64, "Zm9vYmFy"));
|
||||
free(b64);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user