mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-11 05:17:44 +03:00
Merge pull request #2437 from poettering/dnssec19
nineteenth dnssec patch
This commit is contained in:
commit
cfd77192c1
@ -24,7 +24,6 @@ right-away for being misfiled.
|
||||
code. This is a requirement for all code we merge.
|
||||
* Make sure to run "make check" locally, before posting your PR. We use a CI system, meaning we don't even look at your
|
||||
PR, if the build and tests don't pass.
|
||||
|
||||
* If you need to update the code in a existing PR, please consider opening a new PR (mentioning in it which old PR it
|
||||
replaces) and closing the old PR. This is much preferable over force-pushing a new patch set into the PR's branch, as
|
||||
commit comments aren't lost that way. That said, we don't follow this rule ourselves quite often, hence this is
|
||||
|
@ -840,6 +840,7 @@ libbasic_la_SOURCES = \
|
||||
src/basic/siphash24.h \
|
||||
src/basic/set.h \
|
||||
src/basic/ordered-set.h \
|
||||
src/basic/ordered-set.c \
|
||||
src/basic/bitmap.c \
|
||||
src/basic/bitmap.h \
|
||||
src/basic/fdset.c \
|
||||
|
13
TODO
13
TODO
@ -173,9 +173,9 @@ Features:
|
||||
- use equvalent of cat() to insert existing config as a comment, prepended with #.
|
||||
Upon editor exit, lines with one # are removed, lines with two # are left with one #, etc.
|
||||
|
||||
* exponential backoff in timesyncd and resolved when we cannot reach a server
|
||||
* exponential backoff in timesyncd when we cannot reach a server
|
||||
|
||||
* timesyncd + resolved: add ugly bus calls to set NTP and DNS servers per-interface, for usage by NM
|
||||
* timesyncd: add ugly bus calls to set NTP servers per-interface, for usage by NM
|
||||
|
||||
* extract_many_words() should probably be used by a lot of code that
|
||||
currently uses FOREACH_WORD and friends. For example, most conf
|
||||
@ -190,13 +190,7 @@ Features:
|
||||
(throughout the codebase, not only PID1)
|
||||
|
||||
* resolved:
|
||||
- put networkd events and rtnl events at a higher priority, so that
|
||||
we always process them before we process client requests
|
||||
- DNSSEC
|
||||
- add display of private key types (http://tools.ietf.org/html/rfc4034#appendix-A.1.1)?
|
||||
- synthesize negative cache entries from NSEC/NSEC3 and drop explicit negative caching of authenticated answers
|
||||
- mDNS/DNS-SD
|
||||
- mDNS RR resolving
|
||||
- service registration
|
||||
- service/domain/types browsing
|
||||
- avahi compat
|
||||
@ -204,7 +198,8 @@ Features:
|
||||
- resolved should optionally register additional per-interface LLMNR
|
||||
names, so that for the container case we can establish the same name
|
||||
(maybe "host") for referencing the server, everywhere.
|
||||
- add API so NM can push DNS server info into resolved
|
||||
- enable DNSSEC by default
|
||||
- allow clients to request DNSSEC for a single lookup even if DNSSEC is off (?)
|
||||
|
||||
* refcounting in sd-resolve is borked
|
||||
|
||||
|
@ -294,15 +294,11 @@
|
||||
<varlistentry>
|
||||
<term><varname>RemoveIPC=</varname></term>
|
||||
|
||||
<listitem><para>Controls whether System V and POSIX IPC
|
||||
objects belonging to the user shall be removed when the user
|
||||
fully logs out. Takes a boolean argument. If enabled, the user
|
||||
may not consume IPC resources after the last of the user's
|
||||
sessions terminated. This covers System V semaphores, shared
|
||||
memory and message queues, as well as POSIX shared memory and
|
||||
message queues. Note that IPC objects of the root user are
|
||||
excluded from the effect of this setting. Defaults to
|
||||
<literal>yes</literal>.</para></listitem>
|
||||
<listitem><para>Controls whether System V and POSIX IPC objects belonging to the user shall be removed when the
|
||||
user fully logs out. Takes a boolean argument. If enabled, the user may not consume IPC resources after the
|
||||
last of the user's sessions terminated. This covers System V semaphores, shared memory and message queues, as
|
||||
well as POSIX shared memory and message queues. Note that IPC objects of the root user and other system users
|
||||
are excluded from the effect of this setting. Defaults to <literal>yes</literal>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
@ -72,40 +72,40 @@
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>DNS=</varname></term>
|
||||
<listitem><para>A space-separated list of IPv4 and IPv6
|
||||
addresses to be used as system DNS servers. DNS requests are
|
||||
sent to one of the listed DNS servers in parallel to any
|
||||
per-interface DNS servers acquired from
|
||||
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
|
||||
For compatibility reasons, if this setting is not specified,
|
||||
the DNS servers listed in
|
||||
<filename>/etc/resolv.conf</filename> are used instead, if
|
||||
that file exists and any servers are configured in it. This
|
||||
setting defaults to the empty list.</para></listitem>
|
||||
<listitem><para>A space-separated list of IPv4 and IPv6 addresses to use as system DNS servers. DNS requests
|
||||
are sent to one of the listed DNS servers in parallel to suitable per-link DNS servers acquired from
|
||||
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry> or
|
||||
set at runtime by external applications. For compatibility reasons, if this setting is not specified, the DNS
|
||||
servers listed in <filename>/etc/resolv.conf</filename> are used instead, if that file exists and any servers
|
||||
are configured in it. This setting defaults to the empty list.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>FallbackDNS=</varname></term>
|
||||
<listitem><para>A space-separated list of IPv4 and IPv6
|
||||
addresses to be used as the fallback DNS servers. Any
|
||||
per-interface DNS servers obtained from
|
||||
<listitem><para>A space-separated list of IPv4 and IPv6 addresses to use as the fallback DNS servers. Any
|
||||
per-link DNS servers obtained from
|
||||
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
take precedence over this setting, as do any servers set via
|
||||
<varname>DNS=</varname> above or
|
||||
<filename>/etc/resolv.conf</filename>. This setting is hence
|
||||
only used if no other DNS server information is known. If this
|
||||
option is not given, a compiled-in list of DNS servers is used
|
||||
instead.</para></listitem>
|
||||
take precedence over this setting, as do any servers set via <varname>DNS=</varname> above or
|
||||
<filename>/etc/resolv.conf</filename>. This setting is hence only used if no other DNS server information is
|
||||
known. If this option is not given, a compiled-in list of DNS servers is used instead.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>Domains=</varname></term>
|
||||
<listitem><para>A space-separated list of search domains. For
|
||||
compatibility reasons, if this setting is not specified, the
|
||||
search domains listed in <filename>/etc/resolv.conf</filename>
|
||||
are used instead, if that file exists and any domains are
|
||||
configured in it. This setting defaults to the empty
|
||||
list.</para></listitem>
|
||||
<listitem><para>A space-separated list of domains. These domains are used as search suffixes when resolving
|
||||
single-label host names (domain names which contain no dot), in order to qualify them into fully-qualified
|
||||
domain names (FQDNs). Search domains are strictly processed in the order they are specified, until the name
|
||||
with the suffix appended is found. For compatibility reasons, if this setting is not specified, the search
|
||||
domains listed in <filename>/etc/resolv.conf</filename> are used instead, if that file exists and any domains
|
||||
are configured in it. This setting defaults to the empty list.</para>
|
||||
|
||||
<para>Specified domain names may optionally be prefixed with <literal>~</literal>. In this case they do not
|
||||
define a search path, but preferably direct DNS queries for the indicated domains to the DNS servers configured
|
||||
with the system <varname>DNS=</varname> setting (see above), in case additional, suitable per-link DNS servers
|
||||
are known. If no per-link DNS servers are known using the <literal>~</literal> syntax has no effect. Use the
|
||||
construct <literal>~.</literal> (which is composed of <literal>~</literal> to indicate a routing domain and
|
||||
<literal>.</literal> to indicate the DNS root domain that is the implied suffix of all DNS domains) to use the
|
||||
system DNS server defined with <varname>DNS=</varname> preferably for all domains.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@ -119,8 +119,8 @@
|
||||
<literal>resolve</literal>, only resolution support is enabled,
|
||||
but responding is disabled. Note that
|
||||
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
also maintains per-interface LLMNR settings. LLMNR will be
|
||||
enabled on an interface only if the per-interface and the
|
||||
also maintains per-link LLMNR settings. LLMNR will be
|
||||
enabled on a link only if the per-link and the
|
||||
global setting is on.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
@ -181,9 +181,9 @@
|
||||
|
||||
<para>In addition to this global DNSSEC setting
|
||||
<citerefentry><refentrytitle>systemd-networkd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
also maintains per-interface DNSSEC settings. For system DNS
|
||||
also maintains per-link DNSSEC settings. For system DNS
|
||||
servers (see above), only the global DNSSEC setting is in
|
||||
effect. For per-interface DNS servers the per-interface
|
||||
effect. For per-link DNS servers the per-link
|
||||
setting is in effect, unless it is unset in which case the
|
||||
global setting is used instead.</para>
|
||||
|
||||
|
@ -396,21 +396,37 @@
|
||||
described in
|
||||
<citerefentry project='man-pages'><refentrytitle>inet_pton</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
|
||||
This option may be specified more than once. This setting is read by
|
||||
<citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
|
||||
<citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>Domains=</varname></term>
|
||||
<listitem>
|
||||
<para>The domains used for DNS resolution over this link. This setting is read by
|
||||
<citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
|
||||
<para>The domains used for DNS host name resolution on this link. Takes a list of DNS domain names which
|
||||
are used as search suffixes for extending single-label host names (host names containing no dots) to become
|
||||
fully qualified domain names (FQDNs). If a single-label host name is resolved on this interface, each of
|
||||
the specified search domains are appended to it in turn, converting it into a fully qualified domain name,
|
||||
until one of them may be successfully resolved.</para>
|
||||
|
||||
<para>The specified domains are also used for routing of DNS queries: look-ups for host names ending in the
|
||||
domains specified here are preferably routed to the DNS servers configured for this interface. If a domain
|
||||
name is prefixed with <literal>~</literal>, the domain name becomes a pure "routing" domain, is used for
|
||||
DNS query routing purposes only and is not used in the described domain search logic. By specifying a
|
||||
routing domain of <literal>~.</literal> (the tilda indicating definition of a routing domain, the dot
|
||||
referring to the DNS root domain which is the implied suffix of all valid DNS names) it is possible to
|
||||
route all DNS traffic preferably to the DNS server specified for this interface. The route domain logic is
|
||||
particularly useful on multi-homed hosts with DNS servers serving particular private DNS zones on each
|
||||
interface.</para>
|
||||
|
||||
<para>This setting is read by
|
||||
<citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>NTP=</varname></term>
|
||||
<listitem>
|
||||
<para>An NTP server address. This option may be specified more than once. This setting is read by
|
||||
<citerefentry><refentrytitle>systemd-timesyncd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry></para>
|
||||
<citerefentry><refentrytitle>systemd-timesyncd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
@ -701,15 +717,20 @@
|
||||
<varlistentry>
|
||||
<term><varname>UseDomains=</varname></term>
|
||||
<listitem>
|
||||
<para>When true (not the default), the domain name
|
||||
received from the DHCP server will be used for DNS
|
||||
resolution over this link. When a name cannot be resolved
|
||||
as specified, the domain name will be used a suffix and
|
||||
name resolution of that will be attempted.</para>
|
||||
<para>Takes a boolean argument, or a the special value <literal>route</literal>. When true, the domain name
|
||||
received from the DHCP server will be used as DNS search domain over this link, similar to the effect of
|
||||
the <option>Domains=</option> setting. If set to <literal>route</literal>, the domain name received from
|
||||
the DHCP server will be used for routing DNS queries only, but not for searching, similar to the effect of
|
||||
the <option>Domains=</option> setting when the argument is prefixed with <literal>~</literal>. Defaults to
|
||||
false.</para>
|
||||
|
||||
<para>This corresponds to the <option>domain</option>
|
||||
option in <citerefentry project='man-pages'><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
and should not be enabled on untrusted networks.</para>
|
||||
<para>It is recommended to enable this option only on trusted networks, as setting this affects resolution
|
||||
of all host names, in particular to single-label names. It is generally safer to use the supplied domain
|
||||
only as routing domain, rather than as search domain, in order to not have it affect local resolution of
|
||||
single-label names.</para>
|
||||
|
||||
<para>When set to true, this setting corresponds to the <option>domain</option> option in <citerefentry
|
||||
project='man-pages'><refentrytitle>resolv.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
|
@ -1251,3 +1251,32 @@ int read_timestamp_file(const char *fn, usec_t *ret) {
|
||||
*ret = (usec_t) t;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space) {
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
/* Outputs the specified string with fputs(), but optionally prefixes it with a separator. The *space parameter
|
||||
* when specified shall initially point to a boolean variable initialized to false. It is set to true after the
|
||||
* first invocation. This call is supposed to be use in loops, where a separator shall be inserted between each
|
||||
* element, but not before the first one. */
|
||||
|
||||
if (!f)
|
||||
f = stdout;
|
||||
|
||||
if (space) {
|
||||
if (!separator)
|
||||
separator = " ";
|
||||
|
||||
if (*space) {
|
||||
r = fputs(separator, f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
*space = true;
|
||||
}
|
||||
|
||||
return fputs(s, f);
|
||||
}
|
||||
|
@ -82,3 +82,5 @@ int tempfn_random_child(const char *p, const char *extra, char **ret);
|
||||
|
||||
int write_timestamp_file_atomic(const char *fn, usec_t n);
|
||||
int read_timestamp_file(const char *fn, usec_t *ret);
|
||||
|
||||
int fputs_with_space(FILE *f, const char *s, const char *separator, bool *space);
|
||||
|
64
src/basic/ordered-set.c
Normal file
64
src/basic/ordered-set.c
Normal file
@ -0,0 +1,64 @@
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2016 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include "ordered-set.h"
|
||||
#include "strv.h"
|
||||
|
||||
int ordered_set_consume(OrderedSet *s, void *p) {
|
||||
int r;
|
||||
|
||||
r = ordered_set_put(s, p);
|
||||
if (r <= 0)
|
||||
free(p);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int ordered_set_put_strdup(OrderedSet *s, const char *p) {
|
||||
char *c;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(p);
|
||||
|
||||
c = strdup(p);
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
|
||||
r = ordered_set_consume(s, c);
|
||||
if (r == -EEXIST)
|
||||
return 0;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int ordered_set_put_strdupv(OrderedSet *s, char **l) {
|
||||
int n = 0, r;
|
||||
char **i;
|
||||
|
||||
STRV_FOREACH(i, l) {
|
||||
r = ordered_set_put_strdup(s, *i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
n += r;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
@ -62,9 +62,15 @@ static inline bool ordered_set_iterate(OrderedSet *s, Iterator *i, void **value)
|
||||
return ordered_hashmap_iterate((OrderedHashmap*) s, i, value, NULL);
|
||||
}
|
||||
|
||||
int ordered_set_consume(OrderedSet *s, void *p);
|
||||
int ordered_set_put_strdup(OrderedSet *s, const char *p);
|
||||
int ordered_set_put_strdupv(OrderedSet *s, char **l);
|
||||
|
||||
#define ORDERED_SET_FOREACH(e, s, i) \
|
||||
for ((i) = ITERATOR_FIRST; ordered_set_iterate((s), &(i), (void**)&(e)); )
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free_free);
|
||||
|
||||
#define _cleanup_ordered_set_free_ _cleanup_(ordered_set_freep)
|
||||
#define _cleanup_ordered_set_free_free_ _cleanup_(ordered_set_free_freep)
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "alloc-util.h"
|
||||
#include "escape.h"
|
||||
#include "extract-word.h"
|
||||
#include "fileio.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "util.h"
|
||||
@ -871,3 +872,22 @@ rollback:
|
||||
nl[k] = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
int fputstrv(FILE *f, char **l, const char *separator, bool *space) {
|
||||
bool b = false;
|
||||
char **s;
|
||||
int r;
|
||||
|
||||
/* Like fputs(), but for strv, and with a less stupid argument order */
|
||||
|
||||
if (!space)
|
||||
space = &b;
|
||||
|
||||
STRV_FOREACH(s, l) {
|
||||
r = fputs_with_space(f, *s, separator, space);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -169,3 +169,5 @@ char ***strv_free_free(char ***l);
|
||||
char **strv_skip(char **l, size_t n);
|
||||
|
||||
int strv_extend_n(char ***l, const char *value, size_t n);
|
||||
|
||||
int fputstrv(FILE *f, char **l, const char *separator, bool *space);
|
||||
|
@ -794,6 +794,8 @@ int main(int argc, char* argv[]) {
|
||||
IOVEC_SET_STRING(iovec[j++], core_timestamp);
|
||||
|
||||
IOVEC_SET_STRING(iovec[j++], "MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1");
|
||||
|
||||
assert_cc(2 == LOG_CRIT);
|
||||
IOVEC_SET_STRING(iovec[j++], "PRIORITY=2");
|
||||
|
||||
/* Vacuum before we write anything again */
|
||||
|
@ -372,6 +372,7 @@ static int fill_iovec_perror_and_send(const char *message, int skip, struct iove
|
||||
|
||||
xsprintf(error, "ERRNO=%i", _saved_errno_);
|
||||
|
||||
assert_cc(3 == LOG_ERR);
|
||||
IOVEC_SET_STRING(iov[skip+0], "PRIORITY=3");
|
||||
IOVEC_SET_STRING(iov[skip+1], buffer);
|
||||
IOVEC_SET_STRING(iov[skip+2], error);
|
||||
|
@ -397,8 +397,8 @@ static void process_audit_string(Server *s, int type, const char *data, size_t s
|
||||
sprintf(id_field, "_AUDIT_ID=%" PRIu64, id);
|
||||
IOVEC_SET_STRING(iov[n_iov++], id_field);
|
||||
|
||||
assert_cc(32 == LOG_AUTH);
|
||||
IOVEC_SET_STRING(iov[n_iov++], "SYSLOG_FACILITY=32");
|
||||
assert_cc(4 == LOG_FAC(LOG_AUTH));
|
||||
IOVEC_SET_STRING(iov[n_iov++], "SYSLOG_FACILITY=4");
|
||||
IOVEC_SET_STRING(iov[n_iov++], "SYSLOG_IDENTIFIER=audit");
|
||||
|
||||
type_name = audit_type_name_alloca(type);
|
||||
|
@ -866,10 +866,12 @@ void server_driver_message(Server *s, sd_id128_t message_id, const char *format,
|
||||
assert(s);
|
||||
assert(format);
|
||||
|
||||
assert_cc(3 == LOG_FAC(LOG_DAEMON));
|
||||
IOVEC_SET_STRING(iovec[n++], "SYSLOG_FACILITY=3");
|
||||
IOVEC_SET_STRING(iovec[n++], "SYSLOG_IDENTIFIER=systemd-journald");
|
||||
|
||||
IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=driver");
|
||||
assert_cc(6 == LOG_INFO);
|
||||
IOVEC_SET_STRING(iovec[n++], "PRIORITY=6");
|
||||
|
||||
if (!sd_id128_equal(message_id, SD_ID128_NULL)) {
|
||||
|
@ -353,6 +353,38 @@ static int lease_parse_string(const uint8_t *option, size_t len, char **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lease_parse_domain(const uint8_t *option, size_t len, char **ret) {
|
||||
_cleanup_free_ char *name = NULL, *normalized = NULL;
|
||||
int r;
|
||||
|
||||
assert(option);
|
||||
assert(ret);
|
||||
|
||||
r = lease_parse_string(option, len, &name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (!name) {
|
||||
*ret = mfree(*ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = dns_name_normalize(name, &normalized);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (is_localhost(normalized))
|
||||
return -EINVAL;
|
||||
|
||||
if (dns_name_is_root(normalized))
|
||||
return -EINVAL;
|
||||
|
||||
free(*ret);
|
||||
*ret = normalized;
|
||||
normalized = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lease_parse_in_addrs(const uint8_t *option, size_t len, struct in_addr **ret, size_t *n_ret) {
|
||||
assert(option);
|
||||
assert(ret);
|
||||
@ -547,59 +579,23 @@ int dhcp_lease_parse_options(uint8_t code, uint8_t len, const void *option, void
|
||||
log_debug_errno(r, "Failed to parse MTU, ignoring: %m");
|
||||
break;
|
||||
|
||||
case SD_DHCP_OPTION_DOMAIN_NAME: {
|
||||
_cleanup_free_ char *domainname = NULL, *normalized = NULL;
|
||||
|
||||
r = lease_parse_string(option, len, &domainname);
|
||||
case SD_DHCP_OPTION_DOMAIN_NAME:
|
||||
r = lease_parse_domain(option, len, &lease->domainname);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to parse domain name, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = dns_name_normalize(domainname, &normalized);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to normalize domain name '%s': %m", domainname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (is_localhost(normalized)) {
|
||||
log_debug_errno(r, "Detected 'localhost' as suggested domain name, ignoring.");
|
||||
break;
|
||||
}
|
||||
|
||||
free(lease->domainname);
|
||||
lease->domainname = normalized;
|
||||
normalized = NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SD_DHCP_OPTION_HOST_NAME: {
|
||||
_cleanup_free_ char *hostname = NULL, *normalized = NULL;
|
||||
|
||||
r = lease_parse_string(option, len, &hostname);
|
||||
case SD_DHCP_OPTION_HOST_NAME:
|
||||
r = lease_parse_domain(option, len, &lease->hostname);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to parse host name, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = dns_name_normalize(hostname, &normalized);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to normalize host name '%s', ignoring: %m", hostname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (is_localhost(normalized)) {
|
||||
log_debug_errno(r, "Detected 'localhost' as suggested host name, ignoring.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(lease->hostname);
|
||||
lease->hostname = normalized;
|
||||
normalized = NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SD_DHCP_OPTION_ROOT_PATH:
|
||||
r = lease_parse_string(option, len, &lease->root_path);
|
||||
|
@ -95,10 +95,14 @@ _public_ int sd_network_get_ntp(char ***ret) {
|
||||
return network_get_strv("NTP", ret);
|
||||
}
|
||||
|
||||
_public_ int sd_network_get_domains(char ***ret) {
|
||||
_public_ int sd_network_get_search_domains(char ***ret) {
|
||||
return network_get_strv("DOMAINS", ret);
|
||||
}
|
||||
|
||||
_public_ int sd_network_get_route_domains(char ***ret) {
|
||||
return network_get_strv("ROUTE_DOMAINS", ret);
|
||||
}
|
||||
|
||||
static int network_link_get_string(int ifindex, const char *field, char **ret) {
|
||||
_cleanup_free_ char *s = NULL, *p = NULL;
|
||||
int r;
|
||||
@ -222,10 +226,14 @@ _public_ int sd_network_link_get_ntp(int ifindex, char ***ret) {
|
||||
return network_link_get_strv(ifindex, "NTP", ret);
|
||||
}
|
||||
|
||||
_public_ int sd_network_link_get_domains(int ifindex, char ***ret) {
|
||||
_public_ int sd_network_link_get_search_domains(int ifindex, char ***ret) {
|
||||
return network_link_get_strv(ifindex, "DOMAINS", ret);
|
||||
}
|
||||
|
||||
_public_ int sd_network_link_get_route_domains(int ifindex, char ***ret) {
|
||||
return network_link_get_strv(ifindex, "ROUTE_DOMAINS", ret);
|
||||
}
|
||||
|
||||
_public_ int sd_network_link_get_carrier_bound_to(int ifindex, char ***ret) {
|
||||
return network_link_get_strv(ifindex, "CARRIER_BOUND_TO", ret);
|
||||
}
|
||||
@ -234,26 +242,6 @@ _public_ int sd_network_link_get_carrier_bound_by(int ifindex, char ***ret) {
|
||||
return network_link_get_strv(ifindex, "CARRIER_BOUND_BY", ret);
|
||||
}
|
||||
|
||||
_public_ int sd_network_link_get_wildcard_domain(int ifindex) {
|
||||
_cleanup_free_ char *p = NULL, *s = NULL;
|
||||
int r;
|
||||
|
||||
assert_return(ifindex > 0, -EINVAL);
|
||||
|
||||
if (asprintf(&p, "/run/systemd/netif/links/%d", ifindex) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
r = parse_env_file(p, NEWLINE, "WILDCARD_DOMAIN", &s, NULL);
|
||||
if (r == -ENOENT)
|
||||
return -ENODATA;
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (isempty(s))
|
||||
return -ENODATA;
|
||||
|
||||
return parse_boolean(s);
|
||||
}
|
||||
|
||||
static inline int MONITOR_TO_FD(sd_network_monitor *m) {
|
||||
return (int) (unsigned long) m - 1;
|
||||
}
|
||||
|
@ -490,6 +490,9 @@ static int dump_addresses(
|
||||
static void dump_list(const char *prefix, char **l) {
|
||||
char **i;
|
||||
|
||||
if (strv_isempty(l))
|
||||
return;
|
||||
|
||||
STRV_FOREACH(i, l) {
|
||||
printf("%*s%s\n",
|
||||
(int) strlen(prefix),
|
||||
@ -502,7 +505,7 @@ static int link_status_one(
|
||||
sd_netlink *rtnl,
|
||||
sd_hwdb *hwdb,
|
||||
const char *name) {
|
||||
_cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL;
|
||||
_cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **search_domains = NULL, **route_domains = NULL;
|
||||
_cleanup_free_ char *setup_state = NULL, *operational_state = NULL, *tz = NULL;
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL;
|
||||
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
|
||||
@ -552,7 +555,6 @@ static int link_status_one(
|
||||
return rtnl_log_parse_error(r);
|
||||
|
||||
have_mac = sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &e) >= 0;
|
||||
|
||||
if (have_mac) {
|
||||
const uint8_t *p;
|
||||
bool all_zeroes = true;
|
||||
@ -567,44 +569,35 @@ static int link_status_one(
|
||||
have_mac = false;
|
||||
}
|
||||
|
||||
sd_netlink_message_read_u32(reply, IFLA_MTU, &mtu);
|
||||
(void) sd_netlink_message_read_u32(reply, IFLA_MTU, &mtu);
|
||||
|
||||
sd_network_link_get_operational_state(ifindex, &operational_state);
|
||||
(void) sd_network_link_get_operational_state(ifindex, &operational_state);
|
||||
operational_state_to_color(operational_state, &on_color_operational, &off_color_operational);
|
||||
|
||||
sd_network_link_get_setup_state(ifindex, &setup_state);
|
||||
(void) sd_network_link_get_setup_state(ifindex, &setup_state);
|
||||
setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
|
||||
|
||||
sd_network_link_get_dns(ifindex, &dns);
|
||||
sd_network_link_get_domains(ifindex, &domains);
|
||||
r = sd_network_link_get_wildcard_domain(ifindex);
|
||||
if (r > 0) {
|
||||
char *wildcard;
|
||||
|
||||
wildcard = strdup("*");
|
||||
if (!wildcard)
|
||||
return log_oom();
|
||||
|
||||
if (strv_consume(&domains, wildcard) < 0)
|
||||
return log_oom();
|
||||
}
|
||||
(void) sd_network_link_get_dns(ifindex, &dns);
|
||||
(void) sd_network_link_get_search_domains(ifindex, &search_domains);
|
||||
(void) sd_network_link_get_route_domains(ifindex, &route_domains);
|
||||
(void) sd_network_link_get_ntp(ifindex, &ntp);
|
||||
|
||||
sprintf(devid, "n%i", ifindex);
|
||||
|
||||
(void)sd_device_new_from_device_id(&d, devid);
|
||||
(void) sd_device_new_from_device_id(&d, devid);
|
||||
|
||||
if (d) {
|
||||
(void)sd_device_get_property_value(d, "ID_NET_LINK_FILE", &link);
|
||||
(void)sd_device_get_property_value(d, "ID_NET_DRIVER", &driver);
|
||||
(void)sd_device_get_property_value(d, "ID_PATH", &path);
|
||||
(void) sd_device_get_property_value(d, "ID_NET_LINK_FILE", &link);
|
||||
(void) sd_device_get_property_value(d, "ID_NET_DRIVER", &driver);
|
||||
(void) sd_device_get_property_value(d, "ID_PATH", &path);
|
||||
|
||||
r = sd_device_get_property_value(d, "ID_VENDOR_FROM_DATABASE", &vendor);
|
||||
if (r < 0)
|
||||
(void)sd_device_get_property_value(d, "ID_VENDOR", &vendor);
|
||||
(void) sd_device_get_property_value(d, "ID_VENDOR", &vendor);
|
||||
|
||||
r = sd_device_get_property_value(d, "ID_MODEL_FROM_DATABASE", &model);
|
||||
if (r < 0)
|
||||
(void)sd_device_get_property_value(d, "ID_MODEL", &model);
|
||||
(void) sd_device_get_property_value(d, "ID_MODEL", &model);
|
||||
}
|
||||
|
||||
link_get_type_string(iftype, d, &t);
|
||||
@ -653,19 +646,13 @@ static int link_status_one(
|
||||
dump_addresses(rtnl, " Address: ", ifindex);
|
||||
dump_gateways(rtnl, hwdb, " Gateway: ", ifindex);
|
||||
|
||||
if (!strv_isempty(dns))
|
||||
dump_list(" DNS: ", dns);
|
||||
if (!strv_isempty(domains))
|
||||
dump_list(" Domain: ", domains);
|
||||
dump_list(" Search Domains: ", search_domains);
|
||||
dump_list(" Route Domains: ", route_domains);
|
||||
|
||||
(void) sd_network_link_get_ntp(ifindex, &ntp);
|
||||
if (!strv_isempty(ntp))
|
||||
dump_list(" NTP: ", ntp);
|
||||
|
||||
if (!strv_isempty(carrier_bound_to))
|
||||
dump_list("Carrier Bound To: ", carrier_bound_to);
|
||||
|
||||
if (!strv_isempty(carrier_bound_by))
|
||||
dump_list("Carrier Bound By: ", carrier_bound_by);
|
||||
|
||||
(void) sd_network_link_get_timezone(ifindex, &tz);
|
||||
@ -691,7 +678,7 @@ static int link_status(int argc, char *argv[], void *userdata) {
|
||||
|
||||
if (argc <= 1 && !arg_all) {
|
||||
_cleanup_free_ char *operational_state = NULL;
|
||||
_cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL;
|
||||
_cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **search_domains = NULL, **route_domains;
|
||||
const char *on_color_operational, *off_color_operational;
|
||||
|
||||
sd_network_get_operational_state(&operational_state);
|
||||
@ -705,15 +692,15 @@ static int link_status(int argc, char *argv[], void *userdata) {
|
||||
dump_gateways(rtnl, hwdb, " Gateway: ", 0);
|
||||
|
||||
sd_network_get_dns(&dns);
|
||||
if (!strv_isempty(dns))
|
||||
dump_list(" DNS: ", dns);
|
||||
|
||||
sd_network_get_domains(&domains);
|
||||
if (!strv_isempty(domains))
|
||||
dump_list(" Domain: ", domains);
|
||||
sd_network_get_search_domains(&search_domains);
|
||||
dump_list("Search Domains: ", search_domains);
|
||||
|
||||
sd_network_get_route_domains(&route_domains);
|
||||
dump_list(" Route Domains: ", route_domains);
|
||||
|
||||
sd_network_get_ntp(&ntp);
|
||||
if (!strv_isempty(ntp))
|
||||
dump_list(" NTP: ", ntp);
|
||||
|
||||
return 0;
|
||||
|
@ -158,7 +158,7 @@ static int dhcp_lease_lost(Link *link) {
|
||||
|
||||
log_link_warning(link, "DHCP lease lost");
|
||||
|
||||
if (link->network->dhcp_routes) {
|
||||
if (link->network->dhcp_use_routes) {
|
||||
_cleanup_free_ sd_dhcp_route **routes = NULL;
|
||||
int n, i;
|
||||
|
||||
@ -223,7 +223,7 @@ static int dhcp_lease_lost(Link *link) {
|
||||
}
|
||||
}
|
||||
|
||||
if (link->network->dhcp_mtu) {
|
||||
if (link->network->dhcp_use_mtu) {
|
||||
uint16_t mtu;
|
||||
|
||||
r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu);
|
||||
@ -238,11 +238,11 @@ static int dhcp_lease_lost(Link *link) {
|
||||
}
|
||||
}
|
||||
|
||||
if (link->network->dhcp_hostname) {
|
||||
if (link->network->dhcp_use_hostname) {
|
||||
const char *hostname = NULL;
|
||||
|
||||
if (link->network->hostname)
|
||||
hostname = link->network->hostname;
|
||||
if (link->network->dhcp_hostname)
|
||||
hostname = link->network->dhcp_hostname;
|
||||
else
|
||||
(void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
|
||||
|
||||
@ -412,7 +412,7 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
|
||||
link->dhcp_lease = sd_dhcp_lease_ref(lease);
|
||||
link_dirty(link);
|
||||
|
||||
if (link->network->dhcp_mtu) {
|
||||
if (link->network->dhcp_use_mtu) {
|
||||
uint16_t mtu;
|
||||
|
||||
r = sd_dhcp_lease_get_mtu(lease, &mtu);
|
||||
@ -423,11 +423,11 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
|
||||
}
|
||||
}
|
||||
|
||||
if (link->network->dhcp_hostname) {
|
||||
if (link->network->dhcp_use_hostname) {
|
||||
const char *hostname = NULL;
|
||||
|
||||
if (link->network->hostname)
|
||||
hostname = link->network->hostname;
|
||||
if (link->network->dhcp_hostname)
|
||||
hostname = link->network->dhcp_hostname;
|
||||
else
|
||||
(void) sd_dhcp_lease_get_hostname(lease, &hostname);
|
||||
|
||||
@ -438,7 +438,7 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
|
||||
}
|
||||
}
|
||||
|
||||
if (link->network->dhcp_timezone) {
|
||||
if (link->network->dhcp_use_timezone) {
|
||||
const char *tz = NULL;
|
||||
|
||||
(void) sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
|
||||
@ -571,14 +571,14 @@ int dhcp4_configure(Link *link) {
|
||||
return r;
|
||||
}
|
||||
|
||||
if (link->network->dhcp_mtu) {
|
||||
if (link->network->dhcp_use_mtu) {
|
||||
r = sd_dhcp_client_set_request_option(link->dhcp_client,
|
||||
SD_DHCP_OPTION_INTERFACE_MTU);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (link->network->dhcp_routes) {
|
||||
if (link->network->dhcp_use_routes) {
|
||||
r = sd_dhcp_client_set_request_option(link->dhcp_client,
|
||||
SD_DHCP_OPTION_STATIC_ROUTE);
|
||||
if (r < 0)
|
||||
@ -589,7 +589,7 @@ int dhcp4_configure(Link *link) {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Always acquire the timezone and NTP*/
|
||||
/* Always acquire the timezone and NTP */
|
||||
r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NTP_SERVER);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -598,18 +598,18 @@ int dhcp4_configure(Link *link) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (link->network->dhcp_sendhost) {
|
||||
if (link->network->dhcp_send_hostname) {
|
||||
_cleanup_free_ char *hostname = NULL;
|
||||
const char *hn = NULL;
|
||||
|
||||
if (!link->network->hostname) {
|
||||
if (!link->network->dhcp_hostname) {
|
||||
hostname = gethostname_malloc();
|
||||
if (!hostname)
|
||||
return -ENOMEM;
|
||||
|
||||
hn = hostname;
|
||||
} else
|
||||
hn = link->network->hostname;
|
||||
hn = link->network->dhcp_hostname;
|
||||
|
||||
if (!is_localhost(hn)) {
|
||||
r = sd_dhcp_client_set_hostname(link->dhcp_client, hn);
|
||||
|
@ -767,7 +767,7 @@ static int link_push_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) {
|
||||
addresses[n_addresses++] = ia;
|
||||
}
|
||||
|
||||
if (link->network->dhcp_dns &&
|
||||
if (link->network->dhcp_use_dns &&
|
||||
link->dhcp_lease) {
|
||||
const struct in_addr *da = NULL;
|
||||
int n;
|
||||
@ -812,7 +812,7 @@ static int link_push_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) {
|
||||
addresses[n_addresses++] = ia;
|
||||
}
|
||||
|
||||
if (link->network->dhcp_ntp &&
|
||||
if (link->network->dhcp_use_ntp &&
|
||||
link->dhcp_lease) {
|
||||
const struct in_addr *da = NULL;
|
||||
int n;
|
||||
@ -2729,9 +2729,10 @@ int link_save(Link *link) {
|
||||
admin_state, oper_state);
|
||||
|
||||
if (link->network) {
|
||||
char **address, **domain;
|
||||
bool space;
|
||||
sd_dhcp6_lease *dhcp6_lease = NULL;
|
||||
const char *dhcp_domainname = NULL;
|
||||
char **dhcp6_domains = NULL;
|
||||
|
||||
if (link->dhcp6_client) {
|
||||
r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease);
|
||||
@ -2743,14 +2744,9 @@ int link_save(Link *link) {
|
||||
|
||||
fputs("DNS=", f);
|
||||
space = false;
|
||||
STRV_FOREACH(address, link->network->dns) {
|
||||
if (space)
|
||||
fputc(' ', f);
|
||||
fputs(*address, f);
|
||||
space = true;
|
||||
}
|
||||
fputstrv(f, link->network->dns, NULL, &space);
|
||||
|
||||
if (link->network->dhcp_dns &&
|
||||
if (link->network->dhcp_use_dns &&
|
||||
link->dhcp_lease) {
|
||||
const struct in_addr *addresses;
|
||||
|
||||
@ -2763,7 +2759,7 @@ int link_save(Link *link) {
|
||||
}
|
||||
}
|
||||
|
||||
if (link->network->dhcp_dns && dhcp6_lease) {
|
||||
if (link->network->dhcp_use_dns && dhcp6_lease) {
|
||||
struct in6_addr *in6_addrs;
|
||||
|
||||
r = sd_dhcp6_lease_get_dns(dhcp6_lease, &in6_addrs);
|
||||
@ -2778,14 +2774,9 @@ int link_save(Link *link) {
|
||||
|
||||
fputs("NTP=", f);
|
||||
space = false;
|
||||
STRV_FOREACH(address, link->network->ntp) {
|
||||
if (space)
|
||||
fputc(' ', f);
|
||||
fputs(*address, f);
|
||||
space = true;
|
||||
}
|
||||
fputstrv(f, link->network->ntp, NULL, &space);
|
||||
|
||||
if (link->network->dhcp_ntp &&
|
||||
if (link->network->dhcp_use_ntp &&
|
||||
link->dhcp_lease) {
|
||||
const struct in_addr *addresses;
|
||||
|
||||
@ -2798,10 +2789,9 @@ int link_save(Link *link) {
|
||||
}
|
||||
}
|
||||
|
||||
if (link->network->dhcp_ntp && dhcp6_lease) {
|
||||
if (link->network->dhcp_use_ntp && dhcp6_lease) {
|
||||
struct in6_addr *in6_addrs;
|
||||
char **hosts;
|
||||
char **hostname;
|
||||
|
||||
r = sd_dhcp6_lease_get_ntp_addrs(dhcp6_lease,
|
||||
&in6_addrs);
|
||||
@ -2813,58 +2803,41 @@ int link_save(Link *link) {
|
||||
}
|
||||
|
||||
r = sd_dhcp6_lease_get_ntp_fqdn(dhcp6_lease, &hosts);
|
||||
if (r > 0) {
|
||||
STRV_FOREACH(hostname, hosts) {
|
||||
if (space)
|
||||
fputc(' ', f);
|
||||
fputs(*hostname, f);
|
||||
space = true;
|
||||
}
|
||||
}
|
||||
if (r > 0)
|
||||
fputstrv(f, hosts, NULL, &space);
|
||||
}
|
||||
|
||||
fputc('\n', f);
|
||||
|
||||
if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
|
||||
if (link->dhcp_lease)
|
||||
(void) sd_dhcp_lease_get_domainname(link->dhcp_lease, &dhcp_domainname);
|
||||
|
||||
if (dhcp6_lease)
|
||||
(void) sd_dhcp6_lease_get_domains(dhcp6_lease, &dhcp6_domains);
|
||||
}
|
||||
|
||||
fputs("DOMAINS=", f);
|
||||
space = false;
|
||||
STRV_FOREACH(domain, link->network->domains) {
|
||||
if (space)
|
||||
fputc(' ', f);
|
||||
fputs(*domain, f);
|
||||
space = true;
|
||||
}
|
||||
fputstrv(f, link->network->search_domains, NULL, &space);
|
||||
|
||||
if (link->network->dhcp_domains &&
|
||||
link->dhcp_lease) {
|
||||
const char *domainname;
|
||||
if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES && dhcp_domainname)
|
||||
fputs_with_space(f, dhcp_domainname, NULL, &space);
|
||||
|
||||
r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
|
||||
if (r >= 0) {
|
||||
if (space)
|
||||
fputc(' ', f);
|
||||
fputs(domainname, f);
|
||||
space = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (link->network->dhcp_domains && dhcp6_lease) {
|
||||
char **domains;
|
||||
|
||||
r = sd_dhcp6_lease_get_domains(dhcp6_lease, &domains);
|
||||
if (r >= 0) {
|
||||
STRV_FOREACH(domain, domains) {
|
||||
if (space)
|
||||
fputc(' ', f);
|
||||
fputs(*domain, f);
|
||||
space = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES && dhcp6_domains)
|
||||
fputstrv(f, dhcp6_domains, NULL, &space);
|
||||
|
||||
fputc('\n', f);
|
||||
|
||||
fprintf(f, "WILDCARD_DOMAIN=%s\n",
|
||||
yes_no(link->network->wildcard_domain));
|
||||
fputs("ROUTE_DOMAINS=", f);
|
||||
fputstrv(f, link->network->route_domains, NULL, NULL);
|
||||
|
||||
if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE && dhcp_domainname)
|
||||
fputs_with_space(f, dhcp_domainname, NULL, &space);
|
||||
|
||||
if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE && dhcp6_domains)
|
||||
fputstrv(f, dhcp6_domains, NULL, &space);
|
||||
|
||||
fputc('\n', f);
|
||||
|
||||
fprintf(f, "LLMNR=%s\n",
|
||||
resolve_support_to_string(link->network->llmnr));
|
||||
@ -2880,12 +2853,8 @@ int link_save(Link *link) {
|
||||
|
||||
fputs("DNSSEC_NTA=", f);
|
||||
space = false;
|
||||
SET_FOREACH(n, link->network->dnssec_negative_trust_anchors, i) {
|
||||
if (space)
|
||||
fputc(' ', f);
|
||||
fputs(n, f);
|
||||
space = true;
|
||||
}
|
||||
SET_FOREACH(n, link->network->dnssec_negative_trust_anchors, i)
|
||||
fputs_with_space(f, n, NULL, &space);
|
||||
fputc('\n', f);
|
||||
}
|
||||
|
||||
@ -2925,12 +2894,8 @@ int link_save(Link *link) {
|
||||
bool space = false;
|
||||
|
||||
fputs("CARRIER_BOUND_TO=", f);
|
||||
HASHMAP_FOREACH(carrier, link->bound_to_links, i) {
|
||||
if (space)
|
||||
fputc(' ', f);
|
||||
fputs(carrier->ifname, f);
|
||||
space = true;
|
||||
}
|
||||
HASHMAP_FOREACH(carrier, link->bound_to_links, i)
|
||||
fputs_with_space(f, carrier->ifname, NULL, &space);
|
||||
|
||||
fputc('\n', f);
|
||||
}
|
||||
@ -2940,12 +2905,8 @@ int link_save(Link *link) {
|
||||
bool space = false;
|
||||
|
||||
fputs("CARRIER_BOUND_BY=", f);
|
||||
HASHMAP_FOREACH(carrier, link->bound_by_links, i) {
|
||||
if (space)
|
||||
fputc(' ', f);
|
||||
fputs(carrier->ifname, f);
|
||||
space = true;
|
||||
}
|
||||
HASHMAP_FOREACH(carrier, link->bound_by_links, i)
|
||||
fputs_with_space(f, carrier->ifname, NULL, &space);
|
||||
|
||||
fputc('\n', f);
|
||||
}
|
||||
|
@ -29,12 +29,14 @@
|
||||
#include "bus-util.h"
|
||||
#include "conf-parser.h"
|
||||
#include "def.h"
|
||||
#include "dns-domain.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "libudev-private.h"
|
||||
#include "local-addresses.h"
|
||||
#include "netlink-util.h"
|
||||
#include "networkd.h"
|
||||
#include "ordered-set.h"
|
||||
#include "path-util.h"
|
||||
#include "set.h"
|
||||
#include "udev-util.h"
|
||||
@ -776,7 +778,7 @@ static int manager_connect_rtnl(Manager *m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_put_in_addr(Set *s, const struct in_addr *address) {
|
||||
static int ordered_set_put_in_addr(OrderedSet *s, const struct in_addr *address) {
|
||||
char *p;
|
||||
int r;
|
||||
|
||||
@ -786,21 +788,21 @@ static int set_put_in_addr(Set *s, const struct in_addr *address) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = set_consume(s, p);
|
||||
r = ordered_set_consume(s, p);
|
||||
if (r == -EEXIST)
|
||||
return 0;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int set_put_in_addrv(Set *s, const struct in_addr *addresses, int n) {
|
||||
static int ordered_set_put_in_addrv(OrderedSet *s, const struct in_addr *addresses, int n) {
|
||||
int r, i, c = 0;
|
||||
|
||||
assert(s);
|
||||
assert(n <= 0 || addresses);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
r = set_put_in_addr(s, addresses+i);
|
||||
r = ordered_set_put_in_addr(s, addresses+i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -810,27 +812,24 @@ static int set_put_in_addrv(Set *s, const struct in_addr *addresses, int n) {
|
||||
return c;
|
||||
}
|
||||
|
||||
static void print_string_set(FILE *f, const char *field, Set *s) {
|
||||
static void print_string_set(FILE *f, const char *field, OrderedSet *s) {
|
||||
bool space = false;
|
||||
Iterator i;
|
||||
char *p;
|
||||
|
||||
if (set_isempty(s))
|
||||
if (ordered_set_isempty(s))
|
||||
return;
|
||||
|
||||
fputs(field, f);
|
||||
|
||||
SET_FOREACH(p, s, i) {
|
||||
if (space)
|
||||
fputc(' ', f);
|
||||
fputs(p, f);
|
||||
space = true;
|
||||
}
|
||||
ORDERED_SET_FOREACH(p, s, i)
|
||||
fputs_with_space(f, p, NULL, &space);
|
||||
|
||||
fputc('\n', f);
|
||||
}
|
||||
|
||||
static int manager_save(Manager *m) {
|
||||
_cleanup_set_free_free_ Set *dns = NULL, *ntp = NULL, *domains = NULL;
|
||||
_cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *search_domains = NULL, *route_domains = NULL;
|
||||
Link *link;
|
||||
Iterator i;
|
||||
_cleanup_free_ char *temp_path = NULL;
|
||||
@ -843,16 +842,20 @@ static int manager_save(Manager *m) {
|
||||
assert(m->state_file);
|
||||
|
||||
/* We add all NTP and DNS server to a set, to filter out duplicates */
|
||||
dns = set_new(&string_hash_ops);
|
||||
dns = ordered_set_new(&string_hash_ops);
|
||||
if (!dns)
|
||||
return -ENOMEM;
|
||||
|
||||
ntp = set_new(&string_hash_ops);
|
||||
ntp = ordered_set_new(&string_hash_ops);
|
||||
if (!ntp)
|
||||
return -ENOMEM;
|
||||
|
||||
domains = set_new(&string_hash_ops);
|
||||
if (!domains)
|
||||
search_domains = ordered_set_new(&dns_name_hash_ops);
|
||||
if (!search_domains)
|
||||
return -ENOMEM;
|
||||
|
||||
route_domains = ordered_set_new(&dns_name_hash_ops);
|
||||
if (!route_domains)
|
||||
return -ENOMEM;
|
||||
|
||||
HASHMAP_FOREACH(link, m->links, i) {
|
||||
@ -866,15 +869,19 @@ static int manager_save(Manager *m) {
|
||||
continue;
|
||||
|
||||
/* First add the static configured entries */
|
||||
r = set_put_strdupv(dns, link->network->dns);
|
||||
r = ordered_set_put_strdupv(dns, link->network->dns);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = set_put_strdupv(ntp, link->network->ntp);
|
||||
r = ordered_set_put_strdupv(ntp, link->network->ntp);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = set_put_strdupv(domains, link->network->domains);
|
||||
r = ordered_set_put_strdupv(search_domains, link->network->search_domains);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = ordered_set_put_strdupv(route_domains, link->network->route_domains);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -882,36 +889,41 @@ static int manager_save(Manager *m) {
|
||||
continue;
|
||||
|
||||
/* Secondly, add the entries acquired via DHCP */
|
||||
if (link->network->dhcp_dns) {
|
||||
if (link->network->dhcp_use_dns) {
|
||||
const struct in_addr *addresses;
|
||||
|
||||
r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses);
|
||||
if (r > 0) {
|
||||
r = set_put_in_addrv(dns, addresses, r);
|
||||
r = ordered_set_put_in_addrv(dns, addresses, r);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (r < 0 && r != -ENODATA)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (link->network->dhcp_ntp) {
|
||||
if (link->network->dhcp_use_ntp) {
|
||||
const struct in_addr *addresses;
|
||||
|
||||
r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses);
|
||||
if (r > 0) {
|
||||
r = set_put_in_addrv(ntp, addresses, r);
|
||||
r = ordered_set_put_in_addrv(ntp, addresses, r);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (r < 0 && r != -ENODATA)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (link->network->dhcp_domains) {
|
||||
if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
|
||||
const char *domainname;
|
||||
|
||||
r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname);
|
||||
if (r >= 0) {
|
||||
r = set_put_strdup(domains, domainname);
|
||||
|
||||
if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES)
|
||||
r = ordered_set_put_strdup(search_domains, domainname);
|
||||
else
|
||||
r = ordered_set_put_strdup(route_domains, domainname);
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (r != -ENODATA)
|
||||
@ -934,7 +946,8 @@ static int manager_save(Manager *m) {
|
||||
|
||||
print_string_set(f, "DNS=", dns);
|
||||
print_string_set(f, "NTP=", ntp);
|
||||
print_string_set(f, "DOMAINS=", domains);
|
||||
print_string_set(f, "DOMAINS=", search_domains);
|
||||
print_string_set(f, "ROUTE_DOMAINS=", route_domains);
|
||||
|
||||
r = fflush_and_check(f);
|
||||
if (r < 0)
|
||||
|
@ -43,7 +43,7 @@ Network.IPv6Token, config_parse_ipv6token,
|
||||
Network.LLDP, config_parse_bool, 0, offsetof(Network, lldp)
|
||||
Network.Address, config_parse_address, 0, 0
|
||||
Network.Gateway, config_parse_gateway, 0, 0
|
||||
Network.Domains, config_parse_domains, 0, offsetof(Network, domains)
|
||||
Network.Domains, config_parse_domains, 0, 0
|
||||
Network.DNS, config_parse_strv, 0, offsetof(Network, dns)
|
||||
Network.LLMNR, config_parse_resolve_support, 0, offsetof(Network, llmnr)
|
||||
Network.MulticastDNS, config_parse_resolve_support, 0, offsetof(Network, mdns)
|
||||
@ -68,19 +68,19 @@ Route.Metric, config_parse_route_priority,
|
||||
Route.Scope, config_parse_route_scope, 0, 0
|
||||
Route.PreferredSource, config_parse_preferred_src, 0, 0
|
||||
DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier)
|
||||
DHCP.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_dns)
|
||||
DHCP.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp_ntp)
|
||||
DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu)
|
||||
DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname)
|
||||
DHCP.UseDomains, config_parse_bool, 0, offsetof(Network, dhcp_domains)
|
||||
DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_routes)
|
||||
DHCP.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_sendhost)
|
||||
DHCP.Hostname, config_parse_hostname, 0, offsetof(Network, hostname)
|
||||
DHCP.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_use_dns)
|
||||
DHCP.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp_use_ntp)
|
||||
DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_use_mtu)
|
||||
DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_use_hostname)
|
||||
DHCP.UseDomains, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains)
|
||||
DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_use_routes)
|
||||
DHCP.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_send_hostname)
|
||||
DHCP.Hostname, config_parse_hostname, 0, offsetof(Network, dhcp_hostname)
|
||||
DHCP.RequestBroadcast, config_parse_bool, 0, offsetof(Network, dhcp_broadcast)
|
||||
DHCP.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical)
|
||||
DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
|
||||
DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric)
|
||||
DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_timezone)
|
||||
DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone)
|
||||
DHCPServer.MaxLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_max_lease_time_usec)
|
||||
DHCPServer.DefaultLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_default_lease_time_usec)
|
||||
DHCPServer.EmitDNS, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_dns)
|
||||
@ -101,9 +101,9 @@ BridgeFDB.MACAddress, config_parse_fdb_hwaddr,
|
||||
BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0
|
||||
/* backwards compatibility: do not add new entries to this section */
|
||||
Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local)
|
||||
DHCPv4.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_dns)
|
||||
DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu)
|
||||
DHCPv4.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname)
|
||||
DHCP.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_domains)
|
||||
DHCPv4.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_domains)
|
||||
DHCPv4.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_use_dns)
|
||||
DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_use_mtu)
|
||||
DHCPv4.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_use_hostname)
|
||||
DHCP.UseDomainName, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains)
|
||||
DHCPv4.UseDomainName, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains)
|
||||
DHCPv4.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical)
|
||||
|
@ -105,11 +105,11 @@ static int network_load_one(Manager *manager, const char *filename) {
|
||||
*d = '\0';
|
||||
|
||||
network->dhcp = ADDRESS_FAMILY_NO;
|
||||
network->dhcp_ntp = true;
|
||||
network->dhcp_dns = true;
|
||||
network->dhcp_hostname = true;
|
||||
network->dhcp_routes = true;
|
||||
network->dhcp_sendhost = true;
|
||||
network->dhcp_use_ntp = true;
|
||||
network->dhcp_use_dns = true;
|
||||
network->dhcp_use_hostname = true;
|
||||
network->dhcp_use_routes = true;
|
||||
network->dhcp_send_hostname = true;
|
||||
network->dhcp_route_metric = DHCP_ROUTE_METRIC;
|
||||
network->dhcp_client_identifier = DHCP_CLIENT_ID_DUID;
|
||||
|
||||
@ -227,13 +227,14 @@ void network_free(Network *network) {
|
||||
|
||||
free(network->description);
|
||||
free(network->dhcp_vendor_class_identifier);
|
||||
free(network->hostname);
|
||||
free(network->dhcp_hostname);
|
||||
|
||||
free(network->mac);
|
||||
|
||||
strv_free(network->ntp);
|
||||
strv_free(network->dns);
|
||||
strv_free(network->domains);
|
||||
strv_free(network->search_domains);
|
||||
strv_free(network->route_domains);
|
||||
strv_free(network->bind_carrier);
|
||||
|
||||
netdev_unref(network->bridge);
|
||||
@ -384,7 +385,10 @@ int network_apply(Manager *manager, Network *network, Link *link) {
|
||||
route->protocol = RTPROT_STATIC;
|
||||
}
|
||||
|
||||
if (network->dns || network->ntp || network->domains) {
|
||||
if (!strv_isempty(network->dns) ||
|
||||
!strv_isempty(network->ntp) ||
|
||||
!strv_isempty(network->search_domains) ||
|
||||
!strv_isempty(network->route_domains)) {
|
||||
manager_dirty(manager);
|
||||
link_dirty(link);
|
||||
}
|
||||
@ -469,7 +473,8 @@ int config_parse_netdev(const char *unit,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_domains(const char *unit,
|
||||
int config_parse_domains(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
@ -479,38 +484,73 @@ int config_parse_domains(const char *unit,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
Network *network = userdata;
|
||||
char ***domains = data;
|
||||
char **domain;
|
||||
|
||||
const char *p;
|
||||
Network *n = data;
|
||||
int r;
|
||||
|
||||
r = config_parse_strv(unit, filename, line, section, section_line,
|
||||
lvalue, ltype, rvalue, domains, userdata);
|
||||
if (r < 0)
|
||||
return r;
|
||||
assert(n);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
strv_uniq(*domains);
|
||||
network->wildcard_domain = !!strv_find(*domains, "*");
|
||||
if (isempty(rvalue)) {
|
||||
n->search_domains = strv_free(n->search_domains);
|
||||
n->route_domains = strv_free(n->route_domains);
|
||||
return 0;
|
||||
}
|
||||
|
||||
STRV_FOREACH(domain, *domains) {
|
||||
if (is_localhost(*domain))
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "'localhost' domain names may not be configured, ignoring assignment: %s", *domain);
|
||||
else {
|
||||
r = dns_name_is_valid(*domain);
|
||||
if (r <= 0 && !streq(*domain, "*")) {
|
||||
if (r < 0)
|
||||
log_error_errno(r, "Failed to validate domain name: %s: %m", *domain);
|
||||
p = rvalue;
|
||||
for (;;) {
|
||||
_cleanup_free_ char *w = NULL, *normalized = NULL;
|
||||
const char *domain;
|
||||
bool is_route;
|
||||
|
||||
r = extract_first_word(&p, &w, NULL, 0);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract search or route domain, ignoring: %s", rvalue);
|
||||
break;
|
||||
}
|
||||
if (r == 0)
|
||||
log_warning("Domain name is not valid, ignoring assignment: %s", *domain);
|
||||
} else
|
||||
break;
|
||||
|
||||
is_route = w[0] == '~';
|
||||
domain = is_route ? w + 1 : w;
|
||||
|
||||
if (dns_name_is_root(domain) || streq(domain, "*")) {
|
||||
/* If the root domain appears as is, or the special token "*" is found, we'll consider this as
|
||||
* routing domain, unconditionally. */
|
||||
is_route = true;
|
||||
domain = "."; /* make sure we don't allow empty strings, thus write the root domain as "." */
|
||||
|
||||
} else {
|
||||
r = dns_name_normalize(domain, &normalized);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "'%s' is not a valid domain name, ignoring.", domain);
|
||||
continue;
|
||||
}
|
||||
|
||||
strv_remove(*domains, *domain);
|
||||
domain = normalized;
|
||||
|
||||
/* We removed one entry, make sure we don't skip the next one */
|
||||
domain--;
|
||||
if (is_localhost(domain)) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "'localhost' domain names may not be configure as search or route domains, ignoring assignment: %s", domain);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_route) {
|
||||
r = strv_extend(&n->route_domains, domain);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
} else {
|
||||
r = strv_extend(&n->search_domains, domain);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
}
|
||||
}
|
||||
|
||||
strv_uniq(n->route_domains);
|
||||
strv_uniq(n->search_domains);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -930,7 +970,7 @@ int config_parse_dnssec_negative_trust_anchors(
|
||||
Network *n = data;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(n);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
@ -965,3 +1005,13 @@ int config_parse_dnssec_negative_trust_anchors(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains, "Failed to parse DHCP use domains setting");
|
||||
|
||||
static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = {
|
||||
[DHCP_USE_DOMAINS_NO] = "no",
|
||||
[DHCP_USE_DOMAINS_ROUTE] = "route",
|
||||
[DHCP_USE_DOMAINS_YES] = "yes",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES);
|
||||
|
@ -52,6 +52,14 @@ typedef enum IPv6PrivacyExtensions {
|
||||
_IPV6_PRIVACY_EXTENSIONS_INVALID = -1,
|
||||
} IPv6PrivacyExtensions;
|
||||
|
||||
typedef enum DHCPUseDomains {
|
||||
DHCP_USE_DOMAINS_NO,
|
||||
DHCP_USE_DOMAINS_YES,
|
||||
DHCP_USE_DOMAINS_ROUTE,
|
||||
_DHCP_USE_DOMAINS_MAX,
|
||||
_DHCP_USE_DOMAINS_INVALID = -1,
|
||||
} DHCPUseDomains;
|
||||
|
||||
struct Network {
|
||||
Manager *manager;
|
||||
|
||||
@ -79,17 +87,17 @@ struct Network {
|
||||
AddressFamilyBoolean dhcp;
|
||||
DCHPClientIdentifier dhcp_client_identifier;
|
||||
char *dhcp_vendor_class_identifier;
|
||||
char *hostname;
|
||||
bool dhcp_dns;
|
||||
bool dhcp_ntp;
|
||||
bool dhcp_mtu;
|
||||
bool dhcp_hostname;
|
||||
bool dhcp_domains;
|
||||
bool dhcp_sendhost;
|
||||
char *dhcp_hostname;
|
||||
bool dhcp_use_dns;
|
||||
bool dhcp_use_ntp;
|
||||
bool dhcp_use_mtu;
|
||||
bool dhcp_use_hostname;
|
||||
DHCPUseDomains dhcp_use_domains;
|
||||
bool dhcp_send_hostname;
|
||||
bool dhcp_broadcast;
|
||||
bool dhcp_critical;
|
||||
bool dhcp_routes;
|
||||
bool dhcp_timezone;
|
||||
bool dhcp_use_routes;
|
||||
bool dhcp_use_timezone;
|
||||
unsigned dhcp_route_metric;
|
||||
|
||||
/* DHCP Server Support */
|
||||
@ -141,8 +149,7 @@ struct Network {
|
||||
Hashmap *routes_by_section;
|
||||
Hashmap *fdb_entries_by_section;
|
||||
|
||||
bool wildcard_domain;
|
||||
char **domains, **dns, **ntp, **bind_carrier;
|
||||
char **search_domains, **route_domains, **dns, **ntp, **bind_carrier;
|
||||
|
||||
ResolveSupport llmnr;
|
||||
ResolveSupport mdns;
|
||||
@ -175,6 +182,7 @@ int config_parse_timezone(const char *unit, const char *filename, unsigned line,
|
||||
int config_parse_dhcp_server_dns(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_dhcp_server_ntp(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_dnssec_negative_trust_anchors(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
int config_parse_dhcp_use_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
|
||||
/* Legacy IPv4LL support */
|
||||
int config_parse_ipv4ll(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||
@ -188,3 +196,6 @@ int network_object_find(sd_bus *bus, const char *path, const char *interface, vo
|
||||
|
||||
const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_;
|
||||
IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_;
|
||||
|
||||
const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_;
|
||||
DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_;
|
||||
|
@ -1217,19 +1217,19 @@ static int bus_property_get_search_domains(
|
||||
assert(reply);
|
||||
assert(m);
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "(is)");
|
||||
r = sd_bus_message_open_container(reply, 'a', "(isb)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
LIST_FOREACH(domains, d, m->search_domains) {
|
||||
r = sd_bus_message_append(reply, "(is)", 0, d->name);
|
||||
r = sd_bus_message_append(reply, "(isb)", 0, d->name, d->route_only);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
HASHMAP_FOREACH(l, m->links, i) {
|
||||
LIST_FOREACH(domains, d, l->search_domains) {
|
||||
r = sd_bus_message_append(reply, "is", l->ifindex, d->name);
|
||||
r = sd_bus_message_append(reply, "(isb)", l->ifindex, d->name, d->route_only);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -1450,7 +1450,7 @@ static const sd_bus_vtable resolve_vtable[] = {
|
||||
SD_BUS_VTABLE_START(0),
|
||||
SD_BUS_PROPERTY("LLMNRHostname", "s", NULL, offsetof(Manager, llmnr_hostname), 0),
|
||||
SD_BUS_PROPERTY("DNS", "a(iiay)", bus_property_get_dns_servers, 0, 0),
|
||||
SD_BUS_PROPERTY("Domains", "a(is)", bus_property_get_search_domains, 0, 0),
|
||||
SD_BUS_PROPERTY("SearchDomains", "a(isb)", bus_property_get_search_domains, 0, 0),
|
||||
SD_BUS_PROPERTY("TransactionStatistics", "(tt)", bus_property_get_transaction_statistics, 0, 0),
|
||||
SD_BUS_PROPERTY("CacheStatistics", "(ttt)", bus_property_get_cache_statistics, 0, 0),
|
||||
SD_BUS_PROPERTY("DNSSECStatistics", "(tttt)", bus_property_get_dnssec_statistics, 0, 0),
|
||||
@ -1463,7 +1463,7 @@ static const sd_bus_vtable resolve_vtable[] = {
|
||||
SD_BUS_METHOD("ResetStatistics", NULL, NULL, bus_method_reset_statistics, 0),
|
||||
SD_BUS_METHOD("GetLink", "i", "o", bus_method_get_link, SD_BUS_VTABLE_UNPRIVILEGED),
|
||||
SD_BUS_METHOD("SetLinkDNS", "ia(iay)", NULL, bus_method_set_link_dns_servers, 0),
|
||||
SD_BUS_METHOD("SetLinkDomains", "ias", NULL, bus_method_set_link_search_domains, 0),
|
||||
SD_BUS_METHOD("SetLinkDomains", "ia(sb)", NULL, bus_method_set_link_search_domains, 0),
|
||||
SD_BUS_METHOD("SetLinkLLMNR", "is", NULL, bus_method_set_link_llmnr, 0),
|
||||
SD_BUS_METHOD("SetLinkMulticastDNS", "is", NULL, bus_method_set_link_mdns, 0),
|
||||
SD_BUS_METHOD("SetLinkDNSSEC", "is", NULL, bus_method_set_link_dnssec, 0),
|
||||
|
@ -80,20 +80,34 @@ int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, con
|
||||
|
||||
int manager_add_search_domain_by_string(Manager *m, const char *domain) {
|
||||
DnsSearchDomain *d;
|
||||
bool route_only;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(domain);
|
||||
|
||||
route_only = *domain == '~';
|
||||
if (route_only)
|
||||
domain++;
|
||||
|
||||
if (dns_name_is_root(domain) || streq(domain, "*")) {
|
||||
route_only = true;
|
||||
domain = ".";
|
||||
}
|
||||
|
||||
r = dns_search_domain_find(m->search_domains, domain, &d);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0) {
|
||||
if (r > 0)
|
||||
dns_search_domain_move_back_and_unmark(d);
|
||||
return 0;
|
||||
else {
|
||||
r = dns_search_domain_new(m, &d, DNS_SEARCH_DOMAIN_SYSTEM, NULL, domain);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return dns_search_domain_new(m, NULL, DNS_SEARCH_DOMAIN_SYSTEM, NULL, domain);
|
||||
d->route_only = route_only;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int manager_parse_search_domains_and_warn(Manager *m, const char *string) {
|
||||
|
@ -28,18 +28,6 @@
|
||||
#include "resolved-dns-packet.h"
|
||||
#include "string-table.h"
|
||||
|
||||
/* Open question:
|
||||
*
|
||||
* How does the DNSSEC canonical form of a hostname with a label
|
||||
* containing a dot look like, the way DNS-SD does it?
|
||||
*
|
||||
* TODO:
|
||||
*
|
||||
* - enable by default
|
||||
* - Allow clients to request DNSSEC even if DNSSEC is off
|
||||
* - make sure when getting an NXDOMAIN response through CNAME, we still process the first CNAMEs in the packet
|
||||
* */
|
||||
|
||||
#define VERIFY_RRS_MAX 256
|
||||
#define MAX_KEY_SIZE (32*1024)
|
||||
|
||||
|
@ -93,17 +93,20 @@ static int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) {
|
||||
|
||||
assert(c);
|
||||
|
||||
if (c->search_domain && c->search_domain->linked) {
|
||||
if (c->search_domain && c->search_domain->linked)
|
||||
next = c->search_domain->domains_next;
|
||||
else
|
||||
next = dns_scope_get_search_domains(c->scope);
|
||||
|
||||
for (;;) {
|
||||
if (!next) /* We hit the end of the list */
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
next = dns_scope_get_search_domains(c->scope);
|
||||
if (!next->route_only)
|
||||
break;
|
||||
|
||||
if (!next) /* OK, there's nothing. */
|
||||
return 0;
|
||||
/* Skip over route-only domains */
|
||||
next = next->domains_next;
|
||||
}
|
||||
|
||||
dns_search_domain_unref(c->search_domain);
|
||||
|
@ -42,9 +42,6 @@ int dns_search_domain_new(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (dns_name_is_root(normalized))
|
||||
return -EINVAL;
|
||||
|
||||
if (l) {
|
||||
if (l->n_search_domains >= LINK_SEARCH_DOMAINS_MAX)
|
||||
return -E2BIG;
|
||||
|
@ -44,6 +44,7 @@ struct DnsSearchDomain {
|
||||
char *name;
|
||||
|
||||
bool marked:1;
|
||||
bool route_only:1;
|
||||
|
||||
bool linked:1;
|
||||
LIST_FIELDS(DnsSearchDomain, domains);
|
||||
|
@ -732,6 +732,55 @@ fail:
|
||||
dns_transaction_complete(t, DNS_TRANSACTION_ERRNO);
|
||||
}
|
||||
|
||||
static int dns_transaction_has_positive_answer(DnsTransaction *t, DnsAnswerFlags *flags) {
|
||||
int r;
|
||||
|
||||
assert(t);
|
||||
|
||||
/* Checks whether the answer is positive, i.e. either a direct
|
||||
* answer to the question, or a CNAME/DNAME for it */
|
||||
|
||||
r = dns_answer_match_key(t->answer, t->key, flags);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = dns_answer_find_cname_or_dname(t->answer, t->key, NULL, flags);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int dns_transaction_fix_rcode(DnsTransaction *t) {
|
||||
int r;
|
||||
|
||||
assert(t);
|
||||
|
||||
/* Fix up the RCODE to SUCCESS if we get at least one matching RR in a response. Note that this contradicts the
|
||||
* DNS RFCs a bit. Specifically, RFC 6604 Section 3 clarifies that the RCODE shall say something about a
|
||||
* CNAME/DNAME chain element coming after the last chain element contained in the message, and not the first
|
||||
* one included. However, it also indicates that not all DNS servers implement this correctly. Moreover, when
|
||||
* using DNSSEC we usually only can prove the first element of a CNAME/DNAME chain anyway, hence let's settle
|
||||
* on always processing the RCODE as referring to the immediate look-up we do, i.e. the first element of a
|
||||
* CNAME/DNAME chain. This way, we uniformly handle CNAME/DNAME chains, regardless if the DNS server
|
||||
* incorrectly implements RCODE, whether DNSSEC is in use, or whether the DNS server only supplied us with an
|
||||
* incomplete CNAME/DNAME chain.
|
||||
*
|
||||
* Or in other words: if we get at least one positive reply in a message we patch NXDOMAIN to become SUCCESS,
|
||||
* and then rely on the CNAME chasing logic to figure out that there's actually a CNAME error with a new
|
||||
* lookup. */
|
||||
|
||||
if (t->answer_rcode != DNS_RCODE_NXDOMAIN)
|
||||
return 0;
|
||||
|
||||
r = dns_transaction_has_positive_answer(t, NULL);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
t->answer_rcode = DNS_RCODE_SUCCESS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
|
||||
usec_t ts;
|
||||
int r;
|
||||
@ -923,6 +972,10 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) {
|
||||
t->answer_dnssec_result = _DNSSEC_RESULT_INVALID;
|
||||
t->answer_authenticated = false;
|
||||
|
||||
r = dns_transaction_fix_rcode(t);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
/* Block GC while starting requests for additional DNSSEC RRs */
|
||||
t->block_gc++;
|
||||
r = dns_transaction_request_dnssec_keys(t);
|
||||
@ -1635,25 +1688,6 @@ static int dns_transaction_request_dnssec_rr(DnsTransaction *t, DnsResourceKey *
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dns_transaction_has_positive_answer(DnsTransaction *t, DnsAnswerFlags *flags) {
|
||||
int r;
|
||||
|
||||
assert(t);
|
||||
|
||||
/* Checks whether the answer is positive, i.e. either a direct
|
||||
* answer to the question, or a CNAME/DNAME for it */
|
||||
|
||||
r = dns_answer_match_key(t->answer, t->key, flags);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = dns_answer_find_cname_or_dname(t->answer, t->key, NULL, flags);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int dns_transaction_negative_trust_anchor_lookup(DnsTransaction *t, const char *name) {
|
||||
int r;
|
||||
|
||||
|
@ -75,12 +75,12 @@ static int property_get_domains(
|
||||
assert(reply);
|
||||
assert(l);
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "s");
|
||||
r = sd_bus_message_open_container(reply, 'a', "(sb)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
LIST_FOREACH(domains, d, l->search_domains) {
|
||||
r = sd_bus_message_append(reply, "s", d->name);
|
||||
r = sd_bus_message_append(reply, "(sb)", d->name, d->route_only);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -242,47 +242,71 @@ clear:
|
||||
}
|
||||
|
||||
int bus_link_method_set_search_domains(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
_cleanup_free_ char **domains = NULL;
|
||||
Link *l = userdata;
|
||||
char **i;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
assert(l);
|
||||
|
||||
r = sd_bus_message_read_strv(message, &domains);
|
||||
r = sd_bus_message_enter_container(message, 'a', "(sb)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
STRV_FOREACH(i, domains) {
|
||||
for (;;) {
|
||||
const char *name;
|
||||
int route_only;
|
||||
|
||||
r = dns_name_is_valid(*i);
|
||||
r = sd_bus_message_read(message, "(sb)", &name, &route_only);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search domain %s", *i);
|
||||
if (dns_name_is_root(*i))
|
||||
break;
|
||||
|
||||
r = dns_name_is_valid(name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid search domain %s", name);
|
||||
if (!route_only && dns_name_is_root(name))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Root domain is not suitable as search domain");
|
||||
}
|
||||
|
||||
dns_search_domain_mark_all(l->search_domains);
|
||||
|
||||
STRV_FOREACH(i, domains) {
|
||||
DnsSearchDomain *d;
|
||||
r = sd_bus_message_rewind(message, false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dns_search_domain_find(l->search_domains, *i, &d);
|
||||
for (;;) {
|
||||
DnsSearchDomain *d;
|
||||
const char *name;
|
||||
int route_only;
|
||||
|
||||
r = sd_bus_message_read(message, "(sb)", &name, &route_only);
|
||||
if (r < 0)
|
||||
goto clear;
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
r = dns_search_domain_find(l->search_domains, name, &d);
|
||||
if (r < 0)
|
||||
goto clear;
|
||||
|
||||
if (r > 0)
|
||||
dns_search_domain_move_back_and_unmark(d);
|
||||
else {
|
||||
r = dns_search_domain_new(l->manager, NULL, DNS_SEARCH_DOMAIN_LINK, l, *i);
|
||||
r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name);
|
||||
if (r < 0)
|
||||
goto clear;
|
||||
}
|
||||
|
||||
d->route_only = route_only;
|
||||
}
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
if (r < 0)
|
||||
goto clear;
|
||||
|
||||
dns_search_domain_unlink_marked(l->search_domains);
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
|
||||
@ -430,7 +454,7 @@ const sd_bus_vtable link_vtable[] = {
|
||||
|
||||
SD_BUS_PROPERTY("ScopesMask", "t", property_get_scopes_mask, 0, 0),
|
||||
SD_BUS_PROPERTY("DNS", "a(iay)", property_get_dns, 0, 0),
|
||||
SD_BUS_PROPERTY("Domains", "as", property_get_domains, 0, 0),
|
||||
SD_BUS_PROPERTY("Domains", "a(sb)", property_get_domains, 0, 0),
|
||||
SD_BUS_PROPERTY("LLMNR", "s", property_get_resolve_support, offsetof(Link, llmnr_support), 0),
|
||||
SD_BUS_PROPERTY("MulticastDNS", "s", property_get_resolve_support, offsetof(Link, mdns_support), 0),
|
||||
SD_BUS_PROPERTY("DNSSEC", "s", property_get_dnssec_mode, offsetof(Link, dnssec_mode), 0),
|
||||
@ -438,7 +462,7 @@ const sd_bus_vtable link_vtable[] = {
|
||||
SD_BUS_PROPERTY("DNSSECSupport", "b", property_get_dnssec_supported, 0, 0),
|
||||
|
||||
SD_BUS_METHOD("SetDNS", "a(iay)", NULL, bus_link_method_set_dns_servers, 0),
|
||||
SD_BUS_METHOD("SetDomains", "as", NULL, bus_link_method_set_search_domains, 0),
|
||||
SD_BUS_METHOD("SetDomains", "a(sb)", NULL, bus_link_method_set_search_domains, 0),
|
||||
SD_BUS_METHOD("SetLLMNR", "s", NULL, bus_link_method_set_llmnr, 0),
|
||||
SD_BUS_METHOD("SetMulticastDNS", "s", NULL, bus_link_method_set_mdns, 0),
|
||||
SD_BUS_METHOD("SetDNSSEC", "s", NULL, bus_link_method_set_dnssec, 0),
|
||||
|
@ -377,38 +377,60 @@ clear:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int link_update_search_domains(Link *l) {
|
||||
_cleanup_strv_free_ char **domains = NULL;
|
||||
char **i;
|
||||
static int link_update_search_domain_one(Link *l, const char *name, bool route_only) {
|
||||
DnsSearchDomain *d;
|
||||
int r;
|
||||
|
||||
r = dns_search_domain_find(l->search_domains, name, &d);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
dns_search_domain_move_back_and_unmark(d);
|
||||
else {
|
||||
r = dns_search_domain_new(l->manager, &d, DNS_SEARCH_DOMAIN_LINK, l, name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
d->route_only = route_only;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_update_search_domains(Link *l) {
|
||||
_cleanup_strv_free_ char **sdomains = NULL, **rdomains = NULL;
|
||||
char **i;
|
||||
int r, q;
|
||||
|
||||
assert(l);
|
||||
|
||||
r = sd_network_link_get_domains(l->ifindex, &domains);
|
||||
if (r == -ENODATA) {
|
||||
r = sd_network_link_get_search_domains(l->ifindex, &sdomains);
|
||||
if (r < 0 && r != -ENODATA)
|
||||
goto clear;
|
||||
|
||||
q = sd_network_link_get_route_domains(l->ifindex, &rdomains);
|
||||
if (q < 0 && q != -ENODATA) {
|
||||
r = q;
|
||||
goto clear;
|
||||
}
|
||||
|
||||
if (r == -ENODATA && q == -ENODATA) {
|
||||
/* networkd knows nothing about this interface, and that's fine. */
|
||||
r = 0;
|
||||
goto clear;
|
||||
}
|
||||
if (r < 0)
|
||||
goto clear;
|
||||
|
||||
dns_search_domain_mark_all(l->search_domains);
|
||||
|
||||
STRV_FOREACH(i, domains) {
|
||||
DnsSearchDomain *d;
|
||||
|
||||
r = dns_search_domain_find(l->search_domains, *i, &d);
|
||||
if (r < 0)
|
||||
goto clear;
|
||||
|
||||
if (r > 0)
|
||||
dns_search_domain_move_back_and_unmark(d);
|
||||
else {
|
||||
r = dns_search_domain_new(l->manager, NULL, DNS_SEARCH_DOMAIN_LINK, l, *i);
|
||||
STRV_FOREACH(i, sdomains) {
|
||||
r = link_update_search_domain_one(l, *i, false);
|
||||
if (r < 0)
|
||||
goto clear;
|
||||
}
|
||||
|
||||
STRV_FOREACH(i, rdomains) {
|
||||
r = link_update_search_domain_one(l, *i, true);
|
||||
if (r < 0)
|
||||
goto clear;
|
||||
}
|
||||
|
||||
dns_search_domain_unlink_marked(l->search_domains);
|
||||
|
@ -206,7 +206,7 @@ static int manager_rtnl_listen(Manager *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_netlink_attach_event(m->rtnl, m->event, 0);
|
||||
r = sd_netlink_attach_event(m->rtnl, m->event, SD_EVENT_PRIORITY_IMPORTANT);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -314,6 +314,10 @@ static int manager_network_monitor_listen(Manager *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_event_source_set_priority(m->network_event_source, SD_EVENT_PRIORITY_IMPORTANT+5);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) sd_event_source_set_description(m->network_event_source, "network-monitor");
|
||||
|
||||
return 0;
|
||||
|
@ -74,6 +74,7 @@ struct Manager {
|
||||
|
||||
LIST_HEAD(DnsSearchDomain, search_domains);
|
||||
unsigned n_search_domains;
|
||||
bool permit_domain_search;
|
||||
|
||||
bool need_builtin_fallbacks:1;
|
||||
|
||||
|
@ -405,11 +405,17 @@ int dns_label_undo_idna(const char *encoded, size_t encoded_size, char *decoded,
|
||||
int dns_name_concat(const char *a, const char *b, char **_ret) {
|
||||
_cleanup_free_ char *ret = NULL;
|
||||
size_t n = 0, allocated = 0;
|
||||
const char *p = a;
|
||||
const char *p;
|
||||
bool first = true;
|
||||
int r;
|
||||
|
||||
assert(a);
|
||||
if (a)
|
||||
p = a;
|
||||
else if (b) {
|
||||
p = b;
|
||||
b = NULL;
|
||||
} else
|
||||
goto finish;
|
||||
|
||||
for (;;) {
|
||||
char label[DNS_LABEL_MAX];
|
||||
@ -457,12 +463,21 @@ int dns_name_concat(const char *a, const char *b, char **_ret) {
|
||||
n += r;
|
||||
}
|
||||
|
||||
finish:
|
||||
if (n > DNS_HOSTNAME_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
if (_ret) {
|
||||
if (n == 0) {
|
||||
/* Nothing appended? If so, generate at least a single dot, to indicate the DNS root domain */
|
||||
if (!GREEDY_REALLOC(ret, allocated, 2))
|
||||
return -ENOMEM;
|
||||
|
||||
ret[n++] = '.';
|
||||
} else {
|
||||
if (!GREEDY_REALLOC(ret, allocated, n + 1))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret[n] = 0;
|
||||
*_ret = ret;
|
||||
|
@ -64,8 +64,11 @@ int sd_network_get_dns(char ***dns);
|
||||
* representations of IP addresses */
|
||||
int sd_network_get_ntp(char ***ntp);
|
||||
|
||||
/* Get the search/routing domains for all links. */
|
||||
int sd_network_get_domains(char ***domains);
|
||||
/* Get the search domains for all links. */
|
||||
int sd_network_get_search_domains(char ***domains);
|
||||
|
||||
/* Get the search domains for all links. */
|
||||
int sd_network_get_route_domains(char ***domains);
|
||||
|
||||
/* Get setup state from ifindex.
|
||||
* Possible states:
|
||||
@ -134,8 +137,11 @@ int sd_network_link_get_dnssec_negative_trust_anchors(int ifindex, char ***nta);
|
||||
|
||||
int sd_network_link_get_lldp(int ifindex, char **lldp);
|
||||
|
||||
/* Get the DNS domain names for a given link. */
|
||||
int sd_network_link_get_domains(int ifindex, char ***domains);
|
||||
/* Get the search DNS domain names for a given link. */
|
||||
int sd_network_link_get_search_domains(int ifindex, char ***domains);
|
||||
|
||||
/* Get the route DNS domain names for a given link. */
|
||||
int sd_network_link_get_route_domains(int ifindex, char ***domains);
|
||||
|
||||
/* Get the CARRIERS to which current link is bound to. */
|
||||
int sd_network_link_get_carrier_bound_to(int ifindex, char ***carriers);
|
||||
@ -146,10 +152,6 @@ int sd_network_link_get_carrier_bound_by(int ifindex, char ***carriers);
|
||||
/* Get the timezone that was learnt on a specific link. */
|
||||
int sd_network_link_get_timezone(int ifindex, char **timezone);
|
||||
|
||||
/* Returns whether or not domains that don't match any link should be resolved
|
||||
* on this link. 1 for yes, 0 for no and negative value for error */
|
||||
int sd_network_link_get_wildcard_domain(int ifindex);
|
||||
|
||||
/* Monitor object */
|
||||
typedef struct sd_network_monitor sd_network_monitor;
|
||||
|
||||
|
@ -186,7 +186,7 @@ static void test_dns_name_normalize_one(const char *what, const char *expect, in
|
||||
}
|
||||
|
||||
static void test_dns_name_normalize(void) {
|
||||
test_dns_name_normalize_one("", "", 0);
|
||||
test_dns_name_normalize_one("", ".", 0);
|
||||
test_dns_name_normalize_one("f", "f", 0);
|
||||
test_dns_name_normalize_one("f.waldi", "f.waldi", 0);
|
||||
test_dns_name_normalize_one("f \\032.waldi", "f\\032\\032.waldi", 0);
|
||||
@ -194,7 +194,7 @@ static void test_dns_name_normalize(void) {
|
||||
test_dns_name_normalize_one("..", NULL, -EINVAL);
|
||||
test_dns_name_normalize_one(".foobar", NULL, -EINVAL);
|
||||
test_dns_name_normalize_one("foobar.", "foobar", 0);
|
||||
test_dns_name_normalize_one(".", "", 0);
|
||||
test_dns_name_normalize_one(".", ".", 0);
|
||||
}
|
||||
|
||||
static void test_dns_name_equal_one(const char *a, const char *b, int ret) {
|
||||
@ -340,10 +340,18 @@ static void test_dns_name_concat_one(const char *a, const char *b, int r, const
|
||||
}
|
||||
|
||||
static void test_dns_name_concat(void) {
|
||||
test_dns_name_concat_one("", "", 0, ".");
|
||||
test_dns_name_concat_one(".", "", 0, ".");
|
||||
test_dns_name_concat_one("", ".", 0, ".");
|
||||
test_dns_name_concat_one(".", ".", 0, ".");
|
||||
test_dns_name_concat_one("foo", "bar", 0, "foo.bar");
|
||||
test_dns_name_concat_one("foo.foo", "bar.bar", 0, "foo.foo.bar.bar");
|
||||
test_dns_name_concat_one("foo", NULL, 0, "foo");
|
||||
test_dns_name_concat_one("foo", ".", 0, "foo");
|
||||
test_dns_name_concat_one("foo.", "bar.", 0, "foo.bar");
|
||||
test_dns_name_concat_one(NULL, NULL, 0, ".");
|
||||
test_dns_name_concat_one(NULL, ".", 0, ".");
|
||||
test_dns_name_concat_one(NULL, "foo", 0, "foo");
|
||||
}
|
||||
|
||||
static void test_dns_name_is_valid_one(const char *s, int ret) {
|
||||
@ -429,7 +437,7 @@ static void test_dns_service_join_one(const char *a, const char *b, const char *
|
||||
assert_se(dns_service_split(t, &x, &y, &z) >= 0);
|
||||
assert_se(streq_ptr(a, x));
|
||||
assert_se(streq_ptr(b, y));
|
||||
assert_se(streq_ptr(c, z));
|
||||
assert_se(dns_name_equal(c, z) > 0);
|
||||
}
|
||||
|
||||
static void test_dns_service_join(void) {
|
||||
@ -460,18 +468,18 @@ static void test_dns_service_split_one(const char *joined, const char *a, const
|
||||
|
||||
if (y) {
|
||||
assert_se(dns_service_join(x, y, z, &t) == 0);
|
||||
assert_se(streq_ptr(joined, t));
|
||||
assert_se(dns_name_equal(joined, t) > 0);
|
||||
} else
|
||||
assert_se(!x && streq_ptr(z, joined));
|
||||
assert_se(!x && dns_name_equal(z, joined) > 0);
|
||||
}
|
||||
|
||||
static void test_dns_service_split(void) {
|
||||
test_dns_service_split_one("", NULL, NULL, "", 0);
|
||||
test_dns_service_split_one("", NULL, NULL, ".", 0);
|
||||
test_dns_service_split_one("foo", NULL, NULL, "foo", 0);
|
||||
test_dns_service_split_one("foo.bar", NULL, NULL, "foo.bar", 0);
|
||||
test_dns_service_split_one("_foo.bar", NULL, NULL, "_foo.bar", 0);
|
||||
test_dns_service_split_one("_foo._bar", NULL, "_foo._bar", "", 0);
|
||||
test_dns_service_split_one("_meh._foo._bar", "_meh", "_foo._bar", "", 0);
|
||||
test_dns_service_split_one("_foo._bar", NULL, "_foo._bar", ".", 0);
|
||||
test_dns_service_split_one("_meh._foo._bar", "_meh", "_foo._bar", ".", 0);
|
||||
test_dns_service_split_one("Wuff\\032Wuff._foo._bar.waldo.com", "Wuff Wuff", "_foo._bar", "waldo.com", 0);
|
||||
}
|
||||
|
||||
@ -490,7 +498,7 @@ static void test_dns_name_change_suffix(void) {
|
||||
test_dns_name_change_suffix_one("foo.bar.waldi.quux", "quux", "piff.paff", 1, "foo.bar.waldi.piff.paff");
|
||||
test_dns_name_change_suffix_one("foo.bar.waldi.quux", "", "piff.paff", 1, "foo.bar.waldi.quux.piff.paff");
|
||||
test_dns_name_change_suffix_one("", "", "piff.paff", 1, "piff.paff");
|
||||
test_dns_name_change_suffix_one("", "", "", 1, "");
|
||||
test_dns_name_change_suffix_one("", "", "", 1, ".");
|
||||
test_dns_name_change_suffix_one("a", "b", "c", 0, NULL);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user