mirror of
https://github.com/systemd/systemd
synced 2025-09-30 17:24:46 +02:00
Compare commits
13 Commits
8c9c68b593
...
c39e36203f
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c39e36203f | ||
![]() |
f24cbe56d7 | ||
![]() |
fcf99d0ec7 | ||
![]() |
d711322c13 | ||
![]() |
547f9b0dc5 | ||
![]() |
49ef064c8d | ||
![]() |
a9fd8837d4 | ||
![]() |
94378145e6 | ||
![]() |
ae49ce8761 | ||
![]() |
894c7b7708 | ||
![]() |
18674159eb | ||
![]() |
abf4e5c1d3 | ||
![]() |
aee9d18c8d |
2
.github/workflows/build_test.sh
vendored
2
.github/workflows/build_test.sh
vendored
@ -95,7 +95,7 @@ apt-get -y install "${PACKAGES[@]}"
|
|||||||
# support all the features we need (like --optimization=). Since the build-dep
|
# support all the features we need (like --optimization=). Since the build-dep
|
||||||
# command above installs the distro versions, let's install the pip ones just
|
# command above installs the distro versions, let's install the pip ones just
|
||||||
# locally and add the local bin directory to the $PATH.
|
# locally and add the local bin directory to the $PATH.
|
||||||
pip3 install --user -U meson ninja
|
pip3 install --user -U meson==0.56.2 ninja
|
||||||
export PATH="$HOME/.local/bin:$PATH"
|
export PATH="$HOME/.local/bin:$PATH"
|
||||||
|
|
||||||
$CC --version
|
$CC --version
|
||||||
|
@ -262,6 +262,65 @@
|
|||||||
returned.</para></listitem>
|
returned.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--validate=</option><replaceable>BOOL</replaceable></term>
|
||||||
|
|
||||||
|
<listitem><para>Takes a boolean parameter; used in conjunction with <command>query</command>. If true
|
||||||
|
(the default), DNSSEC validation is applied as usual — under the condition that it is enabled for the
|
||||||
|
network and for <filename>systemd-resolved.service</filename> as a whole. If false, DNSSEC validation
|
||||||
|
is disabled for the specific query, regardless of whether it is enabled for the network or in the
|
||||||
|
service. Note that setting this option to true does not force DNSSEC validation on systems/networks
|
||||||
|
where DNSSEC is turned off. This option is only suitable to turn off such validation where otherwise
|
||||||
|
enabled, not enable validation where otherwise disabled.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--synthesize=</option><replaceable>BOOL</replaceable></term>
|
||||||
|
|
||||||
|
<listitem><para>Takes a boolean parameter; used in conjunction with <command>query</command>. If true
|
||||||
|
(the default), select domains are resolved on the local system, among them
|
||||||
|
<literal>localhost</literal> and <literal>_gateway</literal> or entries from
|
||||||
|
<filename>/etc/hosts</filename>. If false these domains are not resolved locally, and either fail (in
|
||||||
|
case of <literal>localhost</literal> or <literal>_gateway</literal> and suchlike) or go to the
|
||||||
|
network via regular DNS/mDNS/LLMNR lookups (in case of <filename>/etc/hosts</filename>
|
||||||
|
entries).</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--cache=</option><replaceable>BOOL</replaceable></term>
|
||||||
|
|
||||||
|
<listitem><para>Takes a boolean parameter; used in conjunction with <command>query</command>. If true
|
||||||
|
(the default), lookups use the local DNS resource record cache. If false, lookups are routed to the
|
||||||
|
network instead, regardless if already available in the local cache.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--zone=</option><replaceable>BOOL</replaceable></term>
|
||||||
|
|
||||||
|
<listitem><para>Takes a boolean parameter; used in conjunction with <command>query</command>. If true
|
||||||
|
(the default), lookups are answered from locally registered LLMNR or mDNS resource records, if
|
||||||
|
defined. If false, locally registered LLMNR/mDNS records are not considered for the lookup
|
||||||
|
request.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--trust-anchor=</option><replaceable>BOOL</replaceable></term>
|
||||||
|
|
||||||
|
<listitem><para>Takes a boolean parameter; used in conjunction with <command>query</command>. If true
|
||||||
|
(the default), lookups for DS and DNSKEY are answered from the local DNSSEC trust anchors if
|
||||||
|
possible. If false, the local trust store is not considered for the lookup request.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--network=</option><replaceable>BOOL</replaceable></term>
|
||||||
|
|
||||||
|
<listitem><para>Takes a boolean parameter; used in conjunction with <command>query</command>. If true
|
||||||
|
(the default), lookups are answered via DNS, LLMNR or mDNS network requests if they cannot be
|
||||||
|
synthesized locally, or be answered from the local cache, zone or trust anchors (see above). If false,
|
||||||
|
the request is not answered from the network and will thus fail if none of the indicated sources can
|
||||||
|
answer them.</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--search=</option><replaceable>BOOL</replaceable></term>
|
<term><option>--search=</option><replaceable>BOOL</replaceable></term>
|
||||||
|
|
||||||
|
@ -76,6 +76,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
|
|||||||
SD_BUS_ERROR_MAP(BUS_ERROR_LINK_BUSY, EBUSY),
|
SD_BUS_ERROR_MAP(BUS_ERROR_LINK_BUSY, EBUSY),
|
||||||
SD_BUS_ERROR_MAP(BUS_ERROR_NETWORK_DOWN, ENETDOWN),
|
SD_BUS_ERROR_MAP(BUS_ERROR_NETWORK_DOWN, ENETDOWN),
|
||||||
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SOURCE, ESRCH),
|
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SOURCE, ESRCH),
|
||||||
|
SD_BUS_ERROR_MAP(BUS_ERROR_STUB_LOOP, ELOOP),
|
||||||
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DNSSD_SERVICE, ENOENT),
|
SD_BUS_ERROR_MAP(BUS_ERROR_NO_SUCH_DNSSD_SERVICE, ENOENT),
|
||||||
SD_BUS_ERROR_MAP(BUS_ERROR_DNSSD_SERVICE_EXISTS, EEXIST),
|
SD_BUS_ERROR_MAP(BUS_ERROR_DNSSD_SERVICE_EXISTS, EEXIST),
|
||||||
|
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
#define BUS_ERROR_LINK_BUSY "org.freedesktop.resolve1.LinkBusy"
|
#define BUS_ERROR_LINK_BUSY "org.freedesktop.resolve1.LinkBusy"
|
||||||
#define BUS_ERROR_NETWORK_DOWN "org.freedesktop.resolve1.NetworkDown"
|
#define BUS_ERROR_NETWORK_DOWN "org.freedesktop.resolve1.NetworkDown"
|
||||||
#define BUS_ERROR_NO_SOURCE "org.freedesktop.resolve1.NoSource"
|
#define BUS_ERROR_NO_SOURCE "org.freedesktop.resolve1.NoSource"
|
||||||
|
#define BUS_ERROR_STUB_LOOP "org.freedesktop.resolve1.StubLoop"
|
||||||
#define BUS_ERROR_NO_SUCH_DNSSD_SERVICE "org.freedesktop.resolve1.NoSuchDnssdService"
|
#define BUS_ERROR_NO_SUCH_DNSSD_SERVICE "org.freedesktop.resolve1.NoSuchDnssdService"
|
||||||
#define BUS_ERROR_DNSSD_SERVICE_EXISTS "org.freedesktop.resolve1.DnssdServiceExists"
|
#define BUS_ERROR_DNSSD_SERVICE_EXISTS "org.freedesktop.resolve1.DnssdServiceExists"
|
||||||
#define _BUS_ERROR_DNS "org.freedesktop.resolve1.DnsError."
|
#define _BUS_ERROR_DNS "org.freedesktop.resolve1.DnsError."
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "env-util.h"
|
||||||
#include "errno-util.h"
|
#include "errno-util.h"
|
||||||
#include "in-addr-util.h"
|
#include "in-addr-util.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
@ -184,6 +185,21 @@ static const JsonDispatch address_parameters_dispatch_table[] = {
|
|||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static uint64_t query_flags(void) {
|
||||||
|
uint64_t f = 0;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
/* Allow callers to turn off validation, when we resolve via nss-resolve */
|
||||||
|
|
||||||
|
r = getenv_bool_secure("SYSTEMD_NSS_RESOLVE_VALIDATE");
|
||||||
|
if (r < 0 && r != -ENXIO)
|
||||||
|
log_debug_errno(r, "Failed to parse $SYSTEMD_NSS_RESOLVE_VALIDATE value, ignoring.");
|
||||||
|
else if (r == 0)
|
||||||
|
f |= SD_RESOLVED_NO_VALIDATE;
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
enum nss_status _nss_resolve_gethostbyname4_r(
|
enum nss_status _nss_resolve_gethostbyname4_r(
|
||||||
const char *name,
|
const char *name,
|
||||||
struct gaih_addrtuple **pat,
|
struct gaih_addrtuple **pat,
|
||||||
@ -215,7 +231,8 @@ enum nss_status _nss_resolve_gethostbyname4_r(
|
|||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
r = json_build(&cparams, JSON_BUILD_OBJECT(
|
r = json_build(&cparams, JSON_BUILD_OBJECT(
|
||||||
JSON_BUILD_PAIR("name", JSON_BUILD_STRING(name))));
|
JSON_BUILD_PAIR("name", JSON_BUILD_STRING(name)),
|
||||||
|
JSON_BUILD_PAIR("flags", JSON_BUILD_UNSIGNED(query_flags()))));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
@ -367,7 +384,8 @@ enum nss_status _nss_resolve_gethostbyname3_r(
|
|||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
r = json_build(&cparams, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("name", JSON_BUILD_STRING(name)),
|
r = json_build(&cparams, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("name", JSON_BUILD_STRING(name)),
|
||||||
JSON_BUILD_PAIR("family", JSON_BUILD_INTEGER(af))));
|
JSON_BUILD_PAIR("family", JSON_BUILD_INTEGER(af)),
|
||||||
|
JSON_BUILD_PAIR("flags", JSON_BUILD_UNSIGNED(query_flags()))));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
@ -571,7 +589,8 @@ enum nss_status _nss_resolve_gethostbyaddr2_r(
|
|||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
r = json_build(&cparams, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("address", JSON_BUILD_BYTE_ARRAY(addr, len)),
|
r = json_build(&cparams, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("address", JSON_BUILD_BYTE_ARRAY(addr, len)),
|
||||||
JSON_BUILD_PAIR("family", JSON_BUILD_INTEGER(af))));
|
JSON_BUILD_PAIR("family", JSON_BUILD_INTEGER(af)),
|
||||||
|
JSON_BUILD_PAIR("flags", JSON_BUILD_UNSIGNED(query_flags()))));
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
@ -2620,8 +2620,14 @@ static int native_help(void) {
|
|||||||
" --service-address=BOOL Resolve address for services (default: yes)\n"
|
" --service-address=BOOL Resolve address for services (default: yes)\n"
|
||||||
" --service-txt=BOOL Resolve TXT records for services (default: yes)\n"
|
" --service-txt=BOOL Resolve TXT records for services (default: yes)\n"
|
||||||
" --cname=BOOL Follow CNAME redirects (default: yes)\n"
|
" --cname=BOOL Follow CNAME redirects (default: yes)\n"
|
||||||
" --search=BOOL Use search domains for single-label names\n"
|
" --validate=BOOL Allow DNSSEC validation (default: yes)\n"
|
||||||
" (default: yes)\n"
|
" --synthesize=BOOL Allow synthetic response (default: yes)\n"
|
||||||
|
" --cache=BOOL Allow response from cache (default: yes)\n"
|
||||||
|
" --zone=BOOL Allow response from locally registered mDNS/LLMNR\n"
|
||||||
|
" records (default: yes)\n"
|
||||||
|
" --trust-anchor=BOOL Allow response from local trust anchor (default: yes)\n"
|
||||||
|
" --network=BOOL Allow response from network (default: yes)\n"
|
||||||
|
" --search=BOOL Use search domains for single-label names (default: yes)\n"
|
||||||
" --raw[=payload|packet] Dump the answer as binary data\n"
|
" --raw[=payload|packet] Dump the answer as binary data\n"
|
||||||
" --legend=BOOL Print headers and additional info (default: yes)\n"
|
" --legend=BOOL Print headers and additional info (default: yes)\n"
|
||||||
"\nSee the %s for details.\n",
|
"\nSee the %s for details.\n",
|
||||||
@ -2961,6 +2967,12 @@ static int native_parse_argv(int argc, char *argv[]) {
|
|||||||
ARG_VERSION = 0x100,
|
ARG_VERSION = 0x100,
|
||||||
ARG_LEGEND,
|
ARG_LEGEND,
|
||||||
ARG_CNAME,
|
ARG_CNAME,
|
||||||
|
ARG_VALIDATE,
|
||||||
|
ARG_SYNTHESIZE,
|
||||||
|
ARG_CACHE,
|
||||||
|
ARG_ZONE,
|
||||||
|
ARG_TRUST_ANCHOR,
|
||||||
|
ARG_NETWORK,
|
||||||
ARG_SERVICE_ADDRESS,
|
ARG_SERVICE_ADDRESS,
|
||||||
ARG_SERVICE_TXT,
|
ARG_SERVICE_TXT,
|
||||||
ARG_RAW,
|
ARG_RAW,
|
||||||
@ -2977,6 +2989,12 @@ static int native_parse_argv(int argc, char *argv[]) {
|
|||||||
{ "interface", required_argument, NULL, 'i' },
|
{ "interface", required_argument, NULL, 'i' },
|
||||||
{ "protocol", required_argument, NULL, 'p' },
|
{ "protocol", required_argument, NULL, 'p' },
|
||||||
{ "cname", required_argument, NULL, ARG_CNAME },
|
{ "cname", required_argument, NULL, ARG_CNAME },
|
||||||
|
{ "validate", required_argument, NULL, ARG_VALIDATE },
|
||||||
|
{ "synthesize", required_argument, NULL, ARG_SYNTHESIZE },
|
||||||
|
{ "cache", required_argument, NULL, ARG_CACHE },
|
||||||
|
{ "zone", required_argument, NULL, ARG_ZONE },
|
||||||
|
{ "trust-anchor", required_argument, NULL, ARG_TRUST_ANCHOR },
|
||||||
|
{ "network", required_argument, NULL, ARG_NETWORK },
|
||||||
{ "service-address", required_argument, NULL, ARG_SERVICE_ADDRESS },
|
{ "service-address", required_argument, NULL, ARG_SERVICE_ADDRESS },
|
||||||
{ "service-txt", required_argument, NULL, ARG_SERVICE_TXT },
|
{ "service-txt", required_argument, NULL, ARG_SERVICE_TXT },
|
||||||
{ "raw", optional_argument, NULL, ARG_RAW },
|
{ "raw", optional_argument, NULL, ARG_RAW },
|
||||||
@ -3100,6 +3118,48 @@ static int native_parse_argv(int argc, char *argv[]) {
|
|||||||
SET_FLAG(arg_flags, SD_RESOLVED_NO_CNAME, r == 0);
|
SET_FLAG(arg_flags, SD_RESOLVED_NO_CNAME, r == 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ARG_VALIDATE:
|
||||||
|
r = parse_boolean(optarg);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to parse --validate= argument.");
|
||||||
|
SET_FLAG(arg_flags, SD_RESOLVED_NO_VALIDATE, r == 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ARG_SYNTHESIZE:
|
||||||
|
r = parse_boolean(optarg);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to parse --synthesize= argument.");
|
||||||
|
SET_FLAG(arg_flags, SD_RESOLVED_NO_SYNTHESIZE, r == 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ARG_CACHE:
|
||||||
|
r = parse_boolean(optarg);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to parse --cache= argument.");
|
||||||
|
SET_FLAG(arg_flags, SD_RESOLVED_NO_CACHE, r == 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ARG_ZONE:
|
||||||
|
r = parse_boolean(optarg);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to parse --zone= argument.");
|
||||||
|
SET_FLAG(arg_flags, SD_RESOLVED_NO_ZONE, r == 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ARG_TRUST_ANCHOR:
|
||||||
|
r = parse_boolean(optarg);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to parse --trust-anchor= argument.");
|
||||||
|
SET_FLAG(arg_flags, SD_RESOLVED_NO_TRUST_ANCHOR, r == 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ARG_NETWORK:
|
||||||
|
r = parse_boolean(optarg);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to parse --network= argument.");
|
||||||
|
SET_FLAG(arg_flags, SD_RESOLVED_NO_NETWORK, r == 0);
|
||||||
|
break;
|
||||||
|
|
||||||
case ARG_SERVICE_ADDRESS:
|
case ARG_SERVICE_ADDRESS:
|
||||||
r = parse_boolean(optarg);
|
r = parse_boolean(optarg);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -104,6 +104,9 @@ static int reply_query_state(DnsQuery *q) {
|
|||||||
case DNS_TRANSACTION_NO_SOURCE:
|
case DNS_TRANSACTION_NO_SOURCE:
|
||||||
return sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_NO_SOURCE, "All suitable resolution sources turned off");
|
return sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_NO_SOURCE, "All suitable resolution sources turned off");
|
||||||
|
|
||||||
|
case DNS_TRANSACTION_STUB_LOOP:
|
||||||
|
return sd_bus_reply_method_errorf(q->bus_request, BUS_ERROR_STUB_LOOP, "Configured DNS server loops back to us");
|
||||||
|
|
||||||
case DNS_TRANSACTION_RCODE_FAILURE: {
|
case DNS_TRANSACTION_RCODE_FAILURE: {
|
||||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||||
|
|
||||||
|
@ -740,16 +740,21 @@ int dns_answer_reserve(DnsAnswer **a, size_t n_free) {
|
|||||||
if ((*a)->n_ref > 1)
|
if ((*a)->n_ref > 1)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
ns = (*a)->n_rrs + n_free;
|
ns = (*a)->n_rrs;
|
||||||
if (ns > UINT16_MAX) /* Maximum number of RRs we can stick into a DNS packet section */
|
assert(ns <= UINT16_MAX); /* Maximum number of RRs we can stick into a DNS packet section */
|
||||||
|
|
||||||
|
if (n_free > UINT16_MAX - ns) /* overflow check */
|
||||||
ns = UINT16_MAX;
|
ns = UINT16_MAX;
|
||||||
|
else
|
||||||
|
ns += n_free;
|
||||||
|
|
||||||
if ((*a)->n_allocated >= ns)
|
if ((*a)->n_allocated >= ns)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Allocate more than we need */
|
/* Allocate more than we need, but not more than UINT16_MAX */
|
||||||
|
if (ns <= UINT16_MAX/2)
|
||||||
ns *= 2;
|
ns *= 2;
|
||||||
if (ns > UINT16_MAX)
|
else
|
||||||
ns = UINT16_MAX;
|
ns = UINT16_MAX;
|
||||||
|
|
||||||
/* This must be done before realloc() below. Otherwise, the original DnsAnswer object
|
/* This must be done before realloc() below. Otherwise, the original DnsAnswer object
|
||||||
@ -780,24 +785,36 @@ 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_reserve_or_clone(DnsAnswer **a, size_t n_free) {
|
||||||
_cleanup_(dns_answer_unrefp) DnsAnswer *n = NULL;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(a);
|
assert(a);
|
||||||
|
|
||||||
/* Tries to extend the DnsAnswer object. And if that's not
|
/* Tries to extend the DnsAnswer object. And if that's not possible, since we are not the sole owner,
|
||||||
* possible, since we are not the sole owner, then allocate a
|
* then allocate a new, appropriately sized one. Either way, after this call the object will only
|
||||||
* new, appropriately sized one. Either way, after this call
|
* have a single reference, and has room for at least the specified number of RRs. */
|
||||||
* the object will only have a single reference, and has room
|
|
||||||
* for at least the specified number of RRs. */
|
|
||||||
|
|
||||||
r = dns_answer_reserve(a, n_free);
|
if (*a && (*a)->n_ref > 1) {
|
||||||
if (r != -EBUSY)
|
_cleanup_(dns_answer_unrefp) DnsAnswer *n = NULL;
|
||||||
return r;
|
size_t ns;
|
||||||
|
|
||||||
assert(*a);
|
ns = (*a)->n_rrs;
|
||||||
|
assert(ns <= UINT16_MAX); /* Maximum number of RRs we can stick into a DNS packet section */
|
||||||
|
|
||||||
n = dns_answer_new(((*a)->n_rrs + n_free) * 2);
|
if (n_free > UINT16_MAX - ns) /* overflow check */
|
||||||
|
ns = UINT16_MAX;
|
||||||
|
else if (n_free > 0) { /* Increase size and double the result, just in case — except if the
|
||||||
|
* increase is specified as 0, in which case we just allocate the
|
||||||
|
* exact amount as before, under the assumption this is just a request
|
||||||
|
* to copy the answer. */
|
||||||
|
ns += n_free;
|
||||||
|
|
||||||
|
if (ns <= UINT16_MAX/2) /* overflow check */
|
||||||
|
ns *= 2;
|
||||||
|
else
|
||||||
|
ns = UINT16_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = dns_answer_new(ns);
|
||||||
if (!n)
|
if (!n)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -806,7 +823,12 @@ int dns_answer_reserve_or_clone(DnsAnswer **a, size_t n_free) {
|
|||||||
return r;
|
return r;
|
||||||
|
|
||||||
dns_answer_unref(*a);
|
dns_answer_unref(*a);
|
||||||
*a = TAKE_PTR(n);
|
assert_se(*a = TAKE_PTR(n));
|
||||||
|
} else if (n_free > 0) {
|
||||||
|
r = dns_answer_reserve(a, n_free);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2253,6 +2253,18 @@ static int dns_packet_extract_answer(DnsPacket *p, DnsAnswer **ret_answer) {
|
|||||||
bool cache_flush = false;
|
bool cache_flush = false;
|
||||||
size_t start;
|
size_t start;
|
||||||
|
|
||||||
|
if (p->rindex == p->size) {
|
||||||
|
/* If we reached the end of the packet already, but there are still more RRs
|
||||||
|
* declared, then that's a corrupt packet. Let's accept the packet anyway, since it's
|
||||||
|
* apparently a common bug in routers. Let's however suppress OPT support in this
|
||||||
|
* case, so that we force the rest of the logic into lowest DNS baseline support. Or
|
||||||
|
* to say this differently: if the DNS server doesn't even get the RR counts right,
|
||||||
|
* it's highly unlikely it gets EDNS right. */
|
||||||
|
log_debug("More resource records declared in packet than included, suppressing OPT.");
|
||||||
|
bad_opt = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
r = dns_packet_read_rr(p, &rr, &cache_flush, &start);
|
r = dns_packet_read_rr(p, &rr, &cache_flush, &start);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@ -2352,8 +2364,10 @@ static int dns_packet_extract_answer(DnsPacket *p, DnsAnswer **ret_answer) {
|
|||||||
previous = dns_resource_record_ref(rr);
|
previous = dns_resource_record_ref(rr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bad_opt)
|
if (bad_opt) {
|
||||||
p->opt = dns_resource_record_unref(p->opt);
|
p->opt = dns_resource_record_unref(p->opt);
|
||||||
|
p->opt_start = p->opt_size = SIZE_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
*ret_answer = TAKE_PTR(answer);
|
*ret_answer = TAKE_PTR(answer);
|
||||||
|
|
||||||
@ -2380,6 +2394,12 @@ int dns_packet_extract(DnsPacket *p) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
if (p->rindex < p->size) {
|
||||||
|
log_debug("Trailing garbage in packet, suppressing OPT.");
|
||||||
|
p->opt = dns_resource_record_unref(p->opt);
|
||||||
|
p->opt_start = p->opt_size = SIZE_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
p->question = TAKE_PTR(question);
|
p->question = TAKE_PTR(question);
|
||||||
p->answer = TAKE_PTR(answer);
|
p->answer = TAKE_PTR(answer);
|
||||||
|
|
||||||
@ -2535,6 +2555,10 @@ static int dns_packet_compare_func(const DnsPacket *x, const DnsPacket *y) {
|
|||||||
|
|
||||||
DEFINE_HASH_OPS(dns_packet_hash_ops, DnsPacket, dns_packet_hash_func, dns_packet_compare_func);
|
DEFINE_HASH_OPS(dns_packet_hash_ops, DnsPacket, dns_packet_hash_func, dns_packet_compare_func);
|
||||||
|
|
||||||
|
bool dns_packet_equal(const DnsPacket *a, const DnsPacket *b) {
|
||||||
|
return dns_packet_compare_func(a, b) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
|
static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
|
||||||
[DNS_RCODE_SUCCESS] = "SUCCESS",
|
[DNS_RCODE_SUCCESS] = "SUCCESS",
|
||||||
[DNS_RCODE_FORMERR] = "FORMERR",
|
[DNS_RCODE_FORMERR] = "FORMERR",
|
||||||
|
@ -227,6 +227,8 @@ void dns_packet_rewind(DnsPacket *p, size_t idx);
|
|||||||
int dns_packet_skip_question(DnsPacket *p);
|
int dns_packet_skip_question(DnsPacket *p);
|
||||||
int dns_packet_extract(DnsPacket *p);
|
int dns_packet_extract(DnsPacket *p);
|
||||||
|
|
||||||
|
bool dns_packet_equal(const DnsPacket *a, const DnsPacket *b);
|
||||||
|
|
||||||
/* https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6 */
|
/* https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6 */
|
||||||
enum {
|
enum {
|
||||||
DNS_RCODE_SUCCESS = 0,
|
DNS_RCODE_SUCCESS = 0,
|
||||||
|
@ -1126,7 +1126,7 @@ void dns_scope_check_conflicts(DnsScope *scope, DnsPacket *p) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (manager_our_packet(scope->manager, p))
|
if (manager_packet_from_local_address(scope->manager, p))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
r = dns_packet_extract(p);
|
r = dns_packet_extract(p);
|
||||||
|
@ -85,6 +85,15 @@ DnsStubListenerExtra *dns_stub_listener_extra_free(DnsStubListenerExtra *p) {
|
|||||||
return mfree(p);
|
return mfree(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t dns_stub_listener_extra_port(DnsStubListenerExtra *p) {
|
||||||
|
assert(p);
|
||||||
|
|
||||||
|
if (p->port > 0)
|
||||||
|
return p->port;
|
||||||
|
|
||||||
|
return 53;
|
||||||
|
}
|
||||||
|
|
||||||
static int dns_stub_collect_answer_by_question(
|
static int dns_stub_collect_answer_by_question(
|
||||||
DnsAnswer **reply,
|
DnsAnswer **reply,
|
||||||
DnsAnswer *answer,
|
DnsAnswer *answer,
|
||||||
@ -639,6 +648,7 @@ static void dns_stub_query_complete(DnsQuery *q) {
|
|||||||
case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED:
|
case DNS_TRANSACTION_RR_TYPE_UNSUPPORTED:
|
||||||
case DNS_TRANSACTION_NETWORK_DOWN:
|
case DNS_TRANSACTION_NETWORK_DOWN:
|
||||||
case DNS_TRANSACTION_NO_SOURCE:
|
case DNS_TRANSACTION_NO_SOURCE:
|
||||||
|
case DNS_TRANSACTION_STUB_LOOP:
|
||||||
(void) dns_stub_send_reply(q, DNS_RCODE_SERVFAIL);
|
(void) dns_stub_send_reply(q, DNS_RCODE_SERVFAIL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -688,6 +698,11 @@ static void dns_stub_process_query(Manager *m, DnsStubListenerExtra *l, DnsStrea
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (manager_packet_from_our_transaction(m, p)) {
|
||||||
|
log_debug("Got our own packet looped back, ignoring.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
r = dns_packet_extract(p);
|
r = dns_packet_extract(p);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_debug_errno(r, "Failed to extract resources from incoming packet, ignoring packet: %m");
|
log_debug_errno(r, "Failed to extract resources from incoming packet, ignoring packet: %m");
|
||||||
@ -951,13 +966,13 @@ static int manager_dns_stub_fd_extra(Manager *m, DnsStubListenerExtra *l, int ty
|
|||||||
if (l->family == AF_INET)
|
if (l->family == AF_INET)
|
||||||
sa = (union sockaddr_union) {
|
sa = (union sockaddr_union) {
|
||||||
.in.sin_family = l->family,
|
.in.sin_family = l->family,
|
||||||
.in.sin_port = htobe16(l->port != 0 ? l->port : 53U),
|
.in.sin_port = htobe16(dns_stub_listener_extra_port(l)),
|
||||||
.in.sin_addr = l->address.in,
|
.in.sin_addr = l->address.in,
|
||||||
};
|
};
|
||||||
else
|
else
|
||||||
sa = (union sockaddr_union) {
|
sa = (union sockaddr_union) {
|
||||||
.in6.sin6_family = l->family,
|
.in6.sin6_family = l->family,
|
||||||
.in6.sin6_port = htobe16(l->port != 0 ? l->port : 53U),
|
.in6.sin6_port = htobe16(dns_stub_listener_extra_port(l)),
|
||||||
.in6.sin6_addr = l->address.in6,
|
.in6.sin6_addr = l->address.in6,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ extern const struct hash_ops dns_stub_listener_extra_hash_ops;
|
|||||||
|
|
||||||
int dns_stub_listener_extra_new(Manager *m, DnsStubListenerExtra **ret);
|
int dns_stub_listener_extra_new(Manager *m, DnsStubListenerExtra **ret);
|
||||||
DnsStubListenerExtra *dns_stub_listener_extra_free(DnsStubListenerExtra *p);
|
DnsStubListenerExtra *dns_stub_listener_extra_free(DnsStubListenerExtra *p);
|
||||||
|
uint16_t dns_stub_listener_extra_port(DnsStubListenerExtra *p);
|
||||||
|
|
||||||
void manager_dns_stub_stop(Manager *m);
|
void manager_dns_stub_stop(Manager *m);
|
||||||
int manager_dns_stub_start(Manager *m);
|
int manager_dns_stub_start(Manager *m);
|
||||||
|
@ -317,8 +317,9 @@ static void dns_transaction_tentative(DnsTransaction *t, DnsPacket *p) {
|
|||||||
|
|
||||||
assert(t);
|
assert(t);
|
||||||
assert(p);
|
assert(p);
|
||||||
|
assert(t->scope->protocol == DNS_PROTOCOL_LLMNR);
|
||||||
|
|
||||||
if (manager_our_packet(t->scope->manager, p) != 0)
|
if (manager_packet_from_local_address(t->scope->manager, p) != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
(void) in_addr_to_string(p->family, &p->sender, &pretty);
|
(void) in_addr_to_string(p->family, &p->sender, &pretty);
|
||||||
@ -639,6 +640,9 @@ static int dns_transaction_emit_tcp(DnsTransaction *t) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
if (manager_server_is_stub(t->scope->manager, t->server))
|
||||||
|
return -ELOOP;
|
||||||
|
|
||||||
if (!t->bypass) {
|
if (!t->bypass) {
|
||||||
if (!dns_server_dnssec_supported(t->server) && dns_type_is_dnssec(dns_transaction_key(t)->type))
|
if (!dns_server_dnssec_supported(t->server) && dns_type_is_dnssec(dns_transaction_key(t)->type))
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
@ -1303,6 +1307,9 @@ static int dns_transaction_emit_udp(DnsTransaction *t) {
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
if (manager_server_is_stub(t->scope->manager, t->server))
|
||||||
|
return -ELOOP;
|
||||||
|
|
||||||
if (t->current_feature_level < DNS_SERVER_FEATURE_LEVEL_UDP || DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level))
|
if (t->current_feature_level < DNS_SERVER_FEATURE_LEVEL_UDP || DNS_SERVER_FEATURE_LEVEL_IS_TLS(t->current_feature_level))
|
||||||
return -EAGAIN; /* Sorry, can't do UDP, try TCP! */
|
return -EAGAIN; /* Sorry, can't do UDP, try TCP! */
|
||||||
|
|
||||||
@ -1845,7 +1852,23 @@ int dns_transaction_go(DnsTransaction *t) {
|
|||||||
if (IN_SET(r, -EMSGSIZE, -EAGAIN))
|
if (IN_SET(r, -EMSGSIZE, -EAGAIN))
|
||||||
r = dns_transaction_emit_tcp(t);
|
r = dns_transaction_emit_tcp(t);
|
||||||
}
|
}
|
||||||
|
if (r == -ELOOP) {
|
||||||
|
if (t->scope->protocol != DNS_PROTOCOL_DNS)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
/* One of our own stub listeners */
|
||||||
|
log_debug_errno(r, "Detected that specified DNS server is our own extra listener, switching DNS servers.");
|
||||||
|
|
||||||
|
dns_scope_next_dns_server(t->scope);
|
||||||
|
|
||||||
|
if (dns_scope_get_dns_server(t->scope) == t->server) {
|
||||||
|
log_debug_errno(r, "Still pointing to extra listener after switching DNS servers, refusing operation.");
|
||||||
|
dns_transaction_complete(t, DNS_TRANSACTION_STUB_LOOP);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dns_transaction_go(t);
|
||||||
|
}
|
||||||
if (r == -ESRCH) {
|
if (r == -ESRCH) {
|
||||||
/* No servers to send this to? */
|
/* No servers to send this to? */
|
||||||
dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
|
dns_transaction_complete(t, DNS_TRANSACTION_NO_SERVERS);
|
||||||
@ -3386,6 +3409,7 @@ static const char* const dns_transaction_state_table[_DNS_TRANSACTION_STATE_MAX]
|
|||||||
[DNS_TRANSACTION_NETWORK_DOWN] = "network-down",
|
[DNS_TRANSACTION_NETWORK_DOWN] = "network-down",
|
||||||
[DNS_TRANSACTION_NOT_FOUND] = "not-found",
|
[DNS_TRANSACTION_NOT_FOUND] = "not-found",
|
||||||
[DNS_TRANSACTION_NO_SOURCE] = "no-source",
|
[DNS_TRANSACTION_NO_SOURCE] = "no-source",
|
||||||
|
[DNS_TRANSACTION_STUB_LOOP] = "stub-loop",
|
||||||
};
|
};
|
||||||
DEFINE_STRING_TABLE_LOOKUP(dns_transaction_state, DnsTransactionState);
|
DEFINE_STRING_TABLE_LOOKUP(dns_transaction_state, DnsTransactionState);
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ enum DnsTransactionState {
|
|||||||
DNS_TRANSACTION_NETWORK_DOWN,
|
DNS_TRANSACTION_NETWORK_DOWN,
|
||||||
DNS_TRANSACTION_NOT_FOUND, /* like NXDOMAIN, but when LLMNR/TCP connections fail */
|
DNS_TRANSACTION_NOT_FOUND, /* like NXDOMAIN, but when LLMNR/TCP connections fail */
|
||||||
DNS_TRANSACTION_NO_SOURCE, /* All suitable DnsTransactionSource turned off */
|
DNS_TRANSACTION_NO_SOURCE, /* All suitable DnsTransactionSource turned off */
|
||||||
|
DNS_TRANSACTION_STUB_LOOP,
|
||||||
_DNS_TRANSACTION_STATE_MAX,
|
_DNS_TRANSACTION_STATE_MAX,
|
||||||
_DNS_TRANSACTION_STATE_INVALID = -EINVAL,
|
_DNS_TRANSACTION_STATE_INVALID = -EINVAL,
|
||||||
};
|
};
|
||||||
|
@ -83,7 +83,7 @@ static int on_llmnr_packet(sd_event_source *s, int fd, uint32_t revents, void *u
|
|||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (manager_our_packet(m, p))
|
if (manager_packet_from_local_address(m, p))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
scope = manager_find_scope(m, p);
|
scope = manager_find_scope(m, p);
|
||||||
|
@ -1255,13 +1255,31 @@ LinkAddress* manager_find_link_address(Manager *m, int family, const union in_ad
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool manager_our_packet(Manager *m, DnsPacket *p) {
|
bool manager_packet_from_local_address(Manager *m, DnsPacket *p) {
|
||||||
assert(m);
|
assert(m);
|
||||||
assert(p);
|
assert(p);
|
||||||
|
|
||||||
|
/* Let's see if this packet comes from an IP address we have on any local interface */
|
||||||
|
|
||||||
return !!manager_find_link_address(m, p->family, &p->sender);
|
return !!manager_find_link_address(m, p->family, &p->sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool manager_packet_from_our_transaction(Manager *m, DnsPacket *p) {
|
||||||
|
DnsTransaction *t;
|
||||||
|
|
||||||
|
assert(m);
|
||||||
|
assert(p);
|
||||||
|
|
||||||
|
/* Let's see if we have a transaction with a query message with the exact same binary contents as the
|
||||||
|
* one we just got. If so, it's almost definitely a packet loop of some kind. */
|
||||||
|
|
||||||
|
t = hashmap_get(m->dns_transactions, UINT_TO_PTR(DNS_PACKET_ID(p)));
|
||||||
|
if (!t)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return t->sent && dns_packet_equal(t->sent, p);
|
||||||
|
}
|
||||||
|
|
||||||
DnsScope* manager_find_scope(Manager *m, DnsPacket *p) {
|
DnsScope* manager_find_scope(Manager *m, DnsPacket *p) {
|
||||||
Link *l;
|
Link *l;
|
||||||
|
|
||||||
@ -1600,3 +1618,27 @@ bool manager_next_dnssd_names(Manager *m) {
|
|||||||
|
|
||||||
return tried;
|
return tried;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool manager_server_is_stub(Manager *m, DnsServer *s) {
|
||||||
|
DnsStubListenerExtra *l;
|
||||||
|
|
||||||
|
assert(m);
|
||||||
|
assert(s);
|
||||||
|
|
||||||
|
/* Safety check: we generally already skip the main stub when parsing configuration. But let's be
|
||||||
|
* extra careful, and check here again */
|
||||||
|
if (s->family == AF_INET &&
|
||||||
|
s->address.in.s_addr == htobe32(INADDR_DNS_STUB) &&
|
||||||
|
dns_server_port(s) == 53)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* Main reason to call this is to check server data against the extra listeners, and filter things
|
||||||
|
* out. */
|
||||||
|
ORDERED_SET_FOREACH(l, m->dns_extra_stub_listeners)
|
||||||
|
if (s->family == l->family &&
|
||||||
|
in_addr_equal(s->family, &s->address, &l->address) &&
|
||||||
|
dns_server_port(s) == dns_stub_listener_extra_port(l))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@ -165,7 +165,9 @@ LinkAddress* manager_find_link_address(Manager *m, int family, const union in_ad
|
|||||||
void manager_refresh_rrs(Manager *m);
|
void manager_refresh_rrs(Manager *m);
|
||||||
int manager_next_hostname(Manager *m);
|
int manager_next_hostname(Manager *m);
|
||||||
|
|
||||||
bool manager_our_packet(Manager *m, DnsPacket *p);
|
bool manager_packet_from_local_address(Manager *m, DnsPacket *p);
|
||||||
|
bool manager_packet_from_our_transaction(Manager *m, DnsPacket *p);
|
||||||
|
|
||||||
DnsScope* manager_find_scope(Manager *m, DnsPacket *p);
|
DnsScope* manager_find_scope(Manager *m, DnsPacket *p);
|
||||||
|
|
||||||
void manager_verify_all(Manager *m);
|
void manager_verify_all(Manager *m);
|
||||||
@ -195,3 +197,5 @@ void manager_reset_server_features(Manager *m);
|
|||||||
void manager_cleanup_saved_user(Manager *m);
|
void manager_cleanup_saved_user(Manager *m);
|
||||||
|
|
||||||
bool manager_next_dnssd_names(Manager *m);
|
bool manager_next_dnssd_names(Manager *m);
|
||||||
|
|
||||||
|
bool manager_server_is_stub(Manager *m, DnsServer *s);
|
||||||
|
@ -254,7 +254,7 @@ static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *us
|
|||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if (manager_our_packet(m, p))
|
if (manager_packet_from_local_address(m, p))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
scope = manager_find_scope(m, p);
|
scope = manager_find_scope(m, p);
|
||||||
|
@ -60,6 +60,9 @@ static int reply_query_state(DnsQuery *q) {
|
|||||||
case DNS_TRANSACTION_NO_SOURCE:
|
case DNS_TRANSACTION_NO_SOURCE:
|
||||||
return varlink_error(q->varlink_request, "io.systemd.Resolve.NoSource", NULL);
|
return varlink_error(q->varlink_request, "io.systemd.Resolve.NoSource", NULL);
|
||||||
|
|
||||||
|
case DNS_TRANSACTION_STUB_LOOP:
|
||||||
|
return varlink_error(q->varlink_request, "io.systemd.Resolve.StubLoop", NULL);
|
||||||
|
|
||||||
case DNS_TRANSACTION_NOT_FOUND:
|
case DNS_TRANSACTION_NOT_FOUND:
|
||||||
/* We return this as NXDOMAIN. This is only generated when a host doesn't implement LLMNR/TCP, and we
|
/* We return this as NXDOMAIN. This is only generated when a host doesn't implement LLMNR/TCP, and we
|
||||||
* thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */
|
* thus quickly know that we cannot resolve an in-addr.arpa or ip6.arpa address. */
|
||||||
|
@ -22,6 +22,10 @@ Wants=time-set.target
|
|||||||
AmbientCapabilities=CAP_SYS_TIME
|
AmbientCapabilities=CAP_SYS_TIME
|
||||||
BusName=org.freedesktop.timesync1
|
BusName=org.freedesktop.timesync1
|
||||||
CapabilityBoundingSet=CAP_SYS_TIME
|
CapabilityBoundingSet=CAP_SYS_TIME
|
||||||
|
# Turn off DNSSEC validation for hostname look-ups, since those need the
|
||||||
|
# correct time to work, but we likely won't acquire that without NTP. Let's
|
||||||
|
# break this chicken-and-egg cycle here.
|
||||||
|
Environment=SYSTEMD_NSS_RESOLVE_VALIDATE=0
|
||||||
ExecStart=!!@rootlibexecdir@/systemd-timesyncd
|
ExecStart=!!@rootlibexecdir@/systemd-timesyncd
|
||||||
LockPersonality=yes
|
LockPersonality=yes
|
||||||
MemoryDenyWriteExecute=yes
|
MemoryDenyWriteExecute=yes
|
||||||
|
Loading…
x
Reference in New Issue
Block a user