Compare commits

..

8 Commits

Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek 908dbc70d6
Merge pull request #16044 from ssahani/resolved-interface
systemd-resolved: allow configurable bind address
2020-09-03 19:06:05 +02:00
Lennart Poettering 88fdff4e65
Merge pull request #16945 from poettering/udev-test-selinux
fix udev-test when used with selinux
2020-09-03 18:39:28 +02:00
Lennart Poettering 7d81d85a05 udev-test: don't mix alloca() and regular C stack allocation in one expression 2020-09-03 17:01:17 +02:00
Lennart Poettering 1e7a67ec22 udev-test: use SYNTHETIC_ERRNO() where useful 2020-09-03 17:01:17 +02:00
Lennart Poettering 91e0b0640e udev-test: use mount_verbose() instead of mount(), to make debugging easier 2020-09-03 17:01:17 +02:00
Lennart Poettering 415df097fe udev-test: make sure we run udev tests with selinux assumed off
This is cleaner that way given that we create our own half-virtualizes
device tree, and really shouldn't pull selinux labelling and access
control into that, we can only lose, in particular as our overmounted
/sys/ actually lacks /sys/fs/selinux.

(This fixes udev test woes introduced by #16821 where suddenly the test
would fail because libselinux assumed selinux was on, but selinuxfs
wasn't actually available)
2020-09-03 17:01:11 +02:00
Susant Sahani 1f05101fb6 resolve: allow configurable bind address 2020-09-03 08:27:41 +00:00
Susant Sahani 1f1f3210c9 shared: Introduce socket_addr_port_from_string_auto 2020-09-02 03:25:17 +00:00
14 changed files with 485 additions and 48 deletions

View File

@ -269,6 +269,31 @@
in use.</para></listitem> in use.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>DNSStubListenerExtra=</varname></term>
<listitem><para>Takes an IPv4 or IPv6 address to listen on. The address may optionally be prefixed by <literal>:</literal> and
a protocol name (<literal>udp</literal> or <literal>tcp</literal>). When an IPv6 address is specified with a port number, then the
address must be in the square brackets. This option can be specified multiple times. If an empty string is assigned, then the all
previous assignments are cleared. It may also be optionally suffixed by a numeric port number with separator <literal>:</literal>.
If the protocol is not specified, the service will listen on both <literal>UDP</literal> and <literal>TCP</literal>. If the port is not
specified, then the service takes port as 53. This option may be used multiple times. Note that this is independent of the
primary DNS stub configured with <varname>DNSStubListener=</varname>, and only configures <emphasis>additional</emphasis>
sockets to listen on. Defaults to unset.</para>
<para>If the string in the format <literal>udp</literal>:[<replaceable>x</replaceable>]:<replaceable>y</replaceable>,
it is read as protocol <literal>udp</literal> and IPv6 address x on a port y.</para>
<para>If the string in the format [<replaceable>x</replaceable>]:<replaceable>y</replaceable>, it is read as both protocol
<literal>udp</literal> and <literal>tcp</literal>, IPv6 address x on a port y.</para>
<para>If the string in the format <replaceable>x</replaceable>, it is read as protocol both <literal>udp</literal> and
<literal>tcp</literal>, IPv6/IPv4 address x on a port 53.</para>
<para>If the string in the format <literal>udp</literal>:<replaceable>x</replaceable>:<replaceable>y</replaceable>,
it is read as protocol <literal>udp</literal> and IPv4 address x on a port y.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>ReadEtcHosts=</varname></term> <term><varname>ReadEtcHosts=</varname></term>
<listitem><para>Takes a boolean argument. If <literal>yes</literal> (the default), <listitem><para>Takes a boolean argument. If <literal>yes</literal> (the default),

View File

@ -10,11 +10,13 @@
#include "resolved-dnssd.h" #include "resolved-dnssd.h"
#include "resolved-manager.h" #include "resolved-manager.h"
#include "resolved-dns-search-domain.h" #include "resolved-dns-search-domain.h"
#include "resolved-dns-stub.h"
#include "dns-domain.h" #include "dns-domain.h"
#include "socket-netlink.h" #include "socket-netlink.h"
#include "specifier.h" #include "specifier.h"
#include "string-table.h" #include "string-table.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h"
#include "utf8.h" #include "utf8.h"
DEFINE_CONFIG_PARSE_ENUM(config_parse_dns_stub_listener_mode, dns_stub_listener_mode, DnsStubListenerMode, "Failed to parse DNS stub listener mode setting"); DEFINE_CONFIG_PARSE_ENUM(config_parse_dns_stub_listener_mode, dns_stub_listener_mode, DnsStubListenerMode, "Failed to parse DNS stub listener mode setting");
@ -27,6 +29,51 @@ static const char* const dns_stub_listener_mode_table[_DNS_STUB_LISTENER_MODE_MA
}; };
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dns_stub_listener_mode, DnsStubListenerMode, DNS_STUB_LISTENER_YES); DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dns_stub_listener_mode, DnsStubListenerMode, DNS_STUB_LISTENER_YES);
static void dns_stub_listener_extra_hash_func(const DNSStubListenerExtra *a, struct siphash *state) {
unsigned port;
assert(a);
siphash24_compress(&a->mode, sizeof(a->mode), state);
siphash24_compress(&socket_address_family(&a->address), sizeof(a->address.type), state);
siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(socket_address_family(&a->address)), state);
(void) sockaddr_port(&a->address.sockaddr.sa, &port);
siphash24_compress(&port, sizeof(port), state);
}
static int dns_stub_listener_extra_compare_func(const DNSStubListenerExtra *a, const DNSStubListenerExtra *b) {
unsigned p, q;
int r;
assert(a);
assert(b);
r = CMP(a->mode, b->mode);
if (r != 0)
return r;
r = CMP(socket_address_family(&a->address), socket_address_family(&b->address));
if (r != 0)
return r;
r = memcmp(&a->address, &b->address, FAMILY_ADDRESS_SIZE(socket_address_family(&a->address)));
if (r != 0)
return r;
(void) sockaddr_port(&a->address.sockaddr.sa, &p);
(void) sockaddr_port(&b->address.sockaddr.sa, &q);
return CMP(p, q);
}
DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR(
dns_stub_listener_extra_hash_ops,
DNSStubListenerExtra,
dns_stub_listener_extra_hash_func,
dns_stub_listener_extra_compare_func,
free);
static int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word) { static int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word) {
_cleanup_free_ char *server_name = NULL; _cleanup_free_ char *server_name = NULL;
union in_addr_union address; union in_addr_union address;
@ -385,6 +432,111 @@ int config_parse_dnssd_txt(const char *unit, const char *filename, unsigned line
return 0; return 0;
} }
int config_parse_dns_stub_listener_extra(
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) {
_cleanup_free_ DNSStubListenerExtra *udp = NULL, *tcp = NULL;
_cleanup_free_ char *word = NULL;
Manager *m = userdata;
bool both = false;
const char *p;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
m->dns_extra_stub_listeners = ordered_set_free(m->dns_extra_stub_listeners);
return 0;
}
p = rvalue;
r = extract_first_word(&p, &word, ":", 0);
if (r == -ENOMEM)
return log_oom();
if (r <= 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid DNSStubListenExtra='%s', ignoring assignment", rvalue);
return 0;
}
/* First look for udp/tcp. If not specified then turn both TCP and UDP */
if (!STR_IN_SET(word, "tcp", "udp")) {
both = true;
p = rvalue;
}
if (streq(word, "tcp") || both) {
r = dns_stub_extra_new(&tcp);
if (r < 0)
return log_oom();
tcp->mode = DNS_STUB_LISTENER_TCP;
}
if (streq(word, "udp") || both) {
r = dns_stub_extra_new(&udp);
if (r < 0)
return log_oom();
udp->mode = DNS_STUB_LISTENER_UDP;
}
if (tcp) {
r = socket_addr_port_from_string_auto(p, 53, &tcp->address);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address in DNSStubListenExtra='%s', ignoring", rvalue);
return 0;
}
}
if (udp) {
r = socket_addr_port_from_string_auto(p, 53, &udp->address);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address in DNSStubListenExtra='%s', ignoring", rvalue);
return 0;
}
}
if (tcp) {
r = ordered_set_ensure_put(&m->dns_extra_stub_listeners, &dns_stub_listener_extra_hash_ops, tcp);
if (r < 0) {
if (r == -ENOMEM)
return log_oom();
log_warning_errno(r, "Failed to store TCP DNSStubListenExtra='%s', ignoring assignment: %m", rvalue);
return 0;
}
}
if (udp) {
r = ordered_set_ensure_put(&m->dns_extra_stub_listeners, &dns_stub_listener_extra_hash_ops, udp);
if (r < 0) {
if (r == -ENOMEM)
return log_oom();
log_warning_errno(r, "Failed to store UDP DNSStubListenExtra='%s', ignoring assignment: %m", rvalue);
return 0;
}
}
TAKE_PTR(tcp);
TAKE_PTR(udp);
return 0;
}
int manager_parse_config_file(Manager *m) { int manager_parse_config_file(Manager *m) {
int r; int r;

View File

@ -30,6 +30,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dns_stub_listener_mode);
CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_name); CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_name);
CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_type); CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_service_type);
CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_txt); CONFIG_PARSER_PROTOTYPE(config_parse_dnssd_txt);
CONFIG_PARSER_PROTOTYPE(config_parse_dns_stub_listener_extra);
const char* dns_stub_listener_mode_to_string(DnsStubListenerMode p) _const_; const char* dns_stub_listener_mode_to_string(DnsStubListenerMode p) _const_;
DnsStubListenerMode dns_stub_listener_mode_from_string(const char *s) _pure_; DnsStubListenerMode dns_stub_listener_mode_from_string(const char *s) _pure_;

View File

@ -4,6 +4,7 @@
#include "fd-util.h" #include "fd-util.h"
#include "missing_network.h" #include "missing_network.h"
#include "resolved-dns-stub.h" #include "resolved-dns-stub.h"
#include "socket-netlink.h"
#include "socket-util.h" #include "socket-util.h"
/* The MTU of the loopback device is 64K on Linux, advertise that as maximum datagram size, but subtract the Ethernet, /* The MTU of the loopback device is 64K on Linux, advertise that as maximum datagram size, but subtract the Ethernet,
@ -13,6 +14,22 @@
static int manager_dns_stub_udp_fd(Manager *m); static int manager_dns_stub_udp_fd(Manager *m);
static int manager_dns_stub_tcp_fd(Manager *m); static int manager_dns_stub_tcp_fd(Manager *m);
int dns_stub_extra_new(DNSStubListenerExtra **ret) {
DNSStubListenerExtra *l;
l = new(DNSStubListenerExtra, 1);
if (!l)
return -ENOMEM;
*l = (DNSStubListenerExtra) {
.fd = -1,
};
*ret = TAKE_PTR(l);
return 0;
}
static int dns_stub_make_reply_packet( static int dns_stub_make_reply_packet(
DnsPacket **p, DnsPacket **p,
size_t max_size, size_t max_size,
@ -386,6 +403,22 @@ static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void
return 0; return 0;
} }
static int set_dns_stub_common_socket_options(int fd) {
int r;
assert(fd >= 0);
r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0)
return r;
r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true);
if (r < 0)
return r;
return setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, true);
}
static int manager_dns_stub_udp_fd(Manager *m) { static int manager_dns_stub_udp_fd(Manager *m) {
union sockaddr_union sa = { union sockaddr_union sa = {
.in.sin_family = AF_INET, .in.sin_family = AF_INET,
@ -402,15 +435,7 @@ static int manager_dns_stub_udp_fd(Manager *m) {
if (fd < 0) if (fd < 0)
return -errno; return -errno;
r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, true); r = set_dns_stub_common_socket_options(fd);
if (r < 0)
return r;
r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true);
if (r < 0)
return r;
r = setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, true);
if (r < 0) if (r < 0)
return r; return r;
@ -431,6 +456,64 @@ static int manager_dns_stub_udp_fd(Manager *m) {
return m->dns_stub_udp_fd = TAKE_FD(fd); return m->dns_stub_udp_fd = TAKE_FD(fd);
} }
static int manager_dns_stub_udp_fd_extra(Manager *m, DNSStubListenerExtra *l) {
_cleanup_free_ char *pretty = NULL;
_cleanup_close_ int fd = -1;
int r;
if (l->fd >= 0)
return 0;
fd = socket(socket_address_family(&l->address), SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (fd < 0) {
r = -errno;
goto fail;
}
r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true);
if (r < 0)
goto fail;
r = set_dns_stub_common_socket_options(fd);
if (r < 0)
goto fail;
if (bind(fd, &l->address.sockaddr.sa, l->address.size) < 0) {
r = -errno;
goto fail;
}
r = sd_event_add_io(m->event, &l->dns_stub_extra_event_source, fd, EPOLLIN, on_dns_stub_packet, m);
if (r < 0)
goto fail;
(void) sd_event_source_set_description(l->dns_stub_extra_event_source, "dns-stub-udp-extra");
l->fd = TAKE_FD(fd);
if (DEBUG_LOGGING) {
(void) sockaddr_pretty(&l->address.sockaddr.sa, FAMILY_ADDRESS_SIZE(l->address.sockaddr.sa.sa_family), true, true, &pretty);
log_debug("Listening on UDP socket %s.", strnull(pretty));
}
return 0;
fail:
(void) sockaddr_pretty(&l->address.sockaddr.sa, FAMILY_ADDRESS_SIZE(l->address.sockaddr.sa.sa_family), true, true, &pretty);
if (r == -EADDRINUSE)
return log_warning_errno(r,
"Another process is already listening on UDP socket %s.\n"
"Turning off local DNS stub extra support.", strnull(pretty));
if (r == -EPERM)
return log_warning_errno(r,
"Failed to listen on UDP socket %s: %m.\n"
"Turning off local DNS stub extra support.", strnull(pretty));
assert(r < 0);
return log_warning_errno(r, "Failed to listen on UDP socket %s, ignoring: %m", strnull(pretty));
}
static int on_dns_stub_stream_packet(DnsStream *s) { static int on_dns_stub_stream_packet(DnsStream *s) {
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
@ -492,22 +575,14 @@ static int manager_dns_stub_tcp_fd(Manager *m) {
if (fd < 0) if (fd < 0)
return -errno; return -errno;
r = set_dns_stub_common_socket_options(fd);
if (r < 0)
return r;
r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, true); r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, true);
if (r < 0) if (r < 0)
return r; return r;
r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, true);
if (r < 0)
return r;
r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true);
if (r < 0)
return r;
r = setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, true);
if (r < 0)
return r;
/* Make sure no traffic from outside the local host can leak to onto this socket */ /* Make sure no traffic from outside the local host can leak to onto this socket */
r = socket_bind_to_ifindex(fd, LOOPBACK_IFINDEX); r = socket_bind_to_ifindex(fd, LOOPBACK_IFINDEX);
if (r < 0) if (r < 0)
@ -528,6 +603,73 @@ static int manager_dns_stub_tcp_fd(Manager *m) {
return m->dns_stub_tcp_fd = TAKE_FD(fd); return m->dns_stub_tcp_fd = TAKE_FD(fd);
} }
static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) {
_cleanup_free_ char *pretty = NULL;
_cleanup_close_ int fd = -1;
int r;
if (l->fd >= 0)
return 0;
fd = socket(socket_address_family(&l->address), SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
if (fd < 0) {
r = -errno;
goto fail;
}
r = set_dns_stub_common_socket_options(fd);
if (r < 0)
goto fail;
r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, true);
if (r < 0)
goto fail;
r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true);
if (r < 0)
goto fail;
if (bind(fd, &l->address.sockaddr.sa, l->address.size) < 0) {
r = -errno;
goto fail;
}
if (listen(fd, SOMAXCONN) < 0) {
r = -errno;
goto fail;
}
r = sd_event_add_io(m->event, &l->dns_stub_extra_event_source, fd, EPOLLIN, on_dns_stub_packet, m);
if (r < 0)
goto fail;
(void) sd_event_source_set_description(l->dns_stub_extra_event_source, "dns-stub-tcp-extra");
l->fd = TAKE_FD(fd);
if (DEBUG_LOGGING) {
(void) sockaddr_pretty(&l->address.sockaddr.sa, FAMILY_ADDRESS_SIZE(l->address.sockaddr.sa.sa_family), true, true, &pretty);
log_debug("Listening on TCP socket %s.", strnull(pretty));
}
return 0;
fail:
(void) sockaddr_pretty(&l->address.sockaddr.sa, FAMILY_ADDRESS_SIZE(l->address.sockaddr.sa.sa_family), true, true, &pretty);
if (r == -EADDRINUSE)
return log_warning_errno(r,
"Another process is already listening on TCP socket %s.\n"
"Turning off local DNS stub extra support.", strnull(pretty));
if (r == -EPERM)
return log_warning_errno(r,
"Failed to listen on TCP socket %s: %m.\n"
"Turning off local DNS stub extra support.", strnull(pretty));
assert(r < 0);
return log_warning_errno(r, "Failed to listen on TCP socket %s, ignoring: %m", strnull(pretty));
}
int manager_dns_stub_start(Manager *m) { int manager_dns_stub_start(Manager *m) {
const char *t = "UDP"; const char *t = "UDP";
int r = 0; int r = 0;
@ -564,6 +706,22 @@ int manager_dns_stub_start(Manager *m) {
} else if (r < 0) } else if (r < 0)
return log_error_errno(r, "Failed to listen on %s socket 127.0.0.53:53: %m", t); return log_error_errno(r, "Failed to listen on %s socket 127.0.0.53:53: %m", t);
if (!ordered_set_isempty(m->dns_extra_stub_listeners)) {
DNSStubListenerExtra *l;
Iterator i;
log_debug("Creating stub listener extra using %s.",
m->dns_stub_listener_mode == DNS_STUB_LISTENER_UDP ? "UDP" :
m->dns_stub_listener_mode == DNS_STUB_LISTENER_TCP ? "TCP" :
"UDP/TCP");
ORDERED_SET_FOREACH(l, m->dns_extra_stub_listeners, i)
if (l->mode == DNS_STUB_LISTENER_UDP)
(void) manager_dns_stub_udp_fd_extra(m, l);
else
(void) manager_dns_stub_tcp_fd_extra(m, l);
}
return 0; return 0;
} }
@ -576,3 +734,15 @@ void manager_dns_stub_stop(Manager *m) {
m->dns_stub_udp_fd = safe_close(m->dns_stub_udp_fd); m->dns_stub_udp_fd = safe_close(m->dns_stub_udp_fd);
m->dns_stub_tcp_fd = safe_close(m->dns_stub_tcp_fd); m->dns_stub_tcp_fd = safe_close(m->dns_stub_tcp_fd);
} }
void manager_dns_stub_stop_extra(Manager *m) {
DNSStubListenerExtra *l;
Iterator i;
assert(m);
ORDERED_SET_FOREACH(l, m->dns_extra_stub_listeners, i) {
l->dns_stub_extra_event_source = sd_event_source_unref(l->dns_stub_extra_event_source);
l->fd = safe_close(l->fd);
}
}

View File

@ -3,5 +3,8 @@
#include "resolved-manager.h" #include "resolved-manager.h"
int dns_stub_extra_new(DNSStubListenerExtra **ret);
void manager_dns_stub_stop(Manager *m); void manager_dns_stub_stop(Manager *m);
void manager_dns_stub_stop_extra(Manager *m);
int manager_dns_stub_start(Manager *m); int manager_dns_stub_start(Manager *m);

View File

@ -18,14 +18,15 @@ struct ConfigPerfItem;
%struct-type %struct-type
%includes %includes
%% %%
Resolve.DNS, config_parse_dns_servers, DNS_SERVER_SYSTEM, 0 Resolve.DNS, config_parse_dns_servers, DNS_SERVER_SYSTEM, 0
Resolve.FallbackDNS, config_parse_dns_servers, DNS_SERVER_FALLBACK, 0 Resolve.FallbackDNS, config_parse_dns_servers, DNS_SERVER_FALLBACK, 0
Resolve.Domains, config_parse_search_domains, 0, 0 Resolve.Domains, config_parse_search_domains, 0, 0
Resolve.LLMNR, config_parse_resolve_support, 0, offsetof(Manager, llmnr_support) Resolve.LLMNR, config_parse_resolve_support, 0, offsetof(Manager, llmnr_support)
Resolve.MulticastDNS, config_parse_resolve_support, 0, offsetof(Manager, mdns_support) Resolve.MulticastDNS, config_parse_resolve_support, 0, offsetof(Manager, mdns_support)
Resolve.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Manager, dnssec_mode) Resolve.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Manager, dnssec_mode)
Resolve.DNSOverTLS, config_parse_dns_over_tls_mode, 0, offsetof(Manager, dns_over_tls_mode) Resolve.DNSOverTLS, config_parse_dns_over_tls_mode, 0, offsetof(Manager, dns_over_tls_mode)
Resolve.Cache, config_parse_dns_cache_mode, DNS_CACHE_MODE_YES, offsetof(Manager, enable_cache) Resolve.Cache, config_parse_dns_cache_mode, DNS_CACHE_MODE_YES, offsetof(Manager, enable_cache)
Resolve.DNSStubListener, config_parse_dns_stub_listener_mode, 0, offsetof(Manager, dns_stub_listener_mode) Resolve.DNSStubListener, config_parse_dns_stub_listener_mode, 0, offsetof(Manager, dns_stub_listener_mode)
Resolve.ReadEtcHosts, config_parse_bool, 0, offsetof(Manager, read_etc_hosts) Resolve.ReadEtcHosts, config_parse_bool, 0, offsetof(Manager, read_etc_hosts)
Resolve.ResolveUnicastSingleLabel, config_parse_bool, 0, offsetof(Manager, resolve_unicast_single_label) Resolve.ResolveUnicastSingleLabel, config_parse_bool, 0, offsetof(Manager, resolve_unicast_single_label)
Resolve.DNSStubListenerExtra, config_parse_dns_stub_listener_extra, 0, offsetof(Manager, dns_extra_stub_listeners)

View File

@ -701,6 +701,7 @@ Manager *manager_free(Manager *m) {
hashmap_free(m->links); hashmap_free(m->links);
hashmap_free(m->dns_transactions); hashmap_free(m->dns_transactions);
ordered_set_free(m->dns_extra_stub_listeners);
sd_event_source_unref(m->network_event_source); sd_event_source_unref(m->network_event_source);
sd_network_monitor_unref(m->network_monitor); sd_network_monitor_unref(m->network_monitor);
@ -713,6 +714,8 @@ Manager *manager_free(Manager *m) {
manager_dns_stub_stop(m); manager_dns_stub_stop(m);
manager_varlink_done(m); manager_varlink_done(m);
manager_dns_stub_stop_extra(m);
bus_verify_polkit_async_registry_free(m->polkit_registry); bus_verify_polkit_async_registry_free(m->polkit_registry);
sd_bus_flush_close_unref(m->bus); sd_bus_flush_close_unref(m->bus);

View File

@ -31,6 +31,14 @@ typedef struct EtcHosts {
Set *no_address; Set *no_address;
} EtcHosts; } EtcHosts;
typedef struct DNSStubListenerExtra {
int fd;
DnsStubListenerMode mode;
SocketAddress address;
sd_event_source *dns_stub_extra_event_source;
} DNSStubListenerExtra;
struct Manager { struct Manager {
sd_event *event; sd_event *event;
@ -137,6 +145,8 @@ struct Manager {
int dns_stub_udp_fd; int dns_stub_udp_fd;
int dns_stub_tcp_fd; int dns_stub_tcp_fd;
OrderedSet *dns_extra_stub_listeners;
sd_event_source *dns_stub_udp_event_source; sd_event_source *dns_stub_udp_event_source;
sd_event_source *dns_stub_tcp_event_source; sd_event_source *dns_stub_tcp_event_source;

View File

@ -235,6 +235,33 @@ int socket_address_parse_and_warn(SocketAddress *a, const char *s) {
return 0; return 0;
} }
int socket_addr_port_from_string_auto(const char *s, uint16_t default_port, SocketAddress *a) {
union in_addr_union address;
uint16_t port = 0;
int family, r;
assert(a);
assert(s);
r = in_addr_port_ifindex_name_from_string_auto(s, &family, &address, &port, NULL, NULL);
if (r < 0)
return r;
if (family == AF_INET) {
memcpy(&a->sockaddr.in.sin_addr, &address.in.s_addr, sizeof(a->sockaddr.in.sin_addr));
a->sockaddr.in.sin_family = AF_INET;
a->size = sizeof(struct sockaddr_in);
a->sockaddr.in.sin_port = port ? htobe16(port) : htobe16(default_port);
} else {
memcpy(&a->sockaddr.in6.sin6_addr, &address.in6, sizeof(a->sockaddr.in6.sin6_addr));
a->sockaddr.in6.sin6_family = AF_INET6;
a->sockaddr.in6.sin6_port = port ? htobe16(port) : htobe16(default_port);
a->size = sizeof(struct sockaddr_in6);
}
return 0;
}
int socket_address_parse_netlink(SocketAddress *a, const char *s) { int socket_address_parse_netlink(SocketAddress *a, const char *s) {
_cleanup_free_ char *word = NULL; _cleanup_free_ char *word = NULL;
unsigned group = 0; unsigned group = 0;

View File

@ -16,6 +16,7 @@ int make_socket_fd(int log_level, const char* address, int type, int flags);
int socket_address_parse(SocketAddress *a, const char *s); int socket_address_parse(SocketAddress *a, const char *s);
int socket_address_parse_and_warn(SocketAddress *a, const char *s); int socket_address_parse_and_warn(SocketAddress *a, const char *s);
int socket_address_parse_netlink(SocketAddress *a, const char *s); int socket_address_parse_netlink(SocketAddress *a, const char *s);
int socket_addr_port_from_string_auto(const char *s, uint16_t default_port, SocketAddress *a);
bool socket_address_is(const SocketAddress *a, const char *s, int type); bool socket_address_is(const SocketAddress *a, const char *s, int type);
bool socket_address_is_netlink(const SocketAddress *a, const char *s); bool socket_address_is_netlink(const SocketAddress *a, const char *s);

View File

@ -757,7 +757,8 @@ tests += [
librt, librt,
libblkid, libblkid,
libkmod, libkmod,
libacl], libacl,
libselinux],
'', 'manual', '-DLOG_REALM=LOG_REALM_UDEV'], '', 'manual', '-DLOG_REALM=LOG_REALM_UDEV'],
[['src/test/test-id128.c'], [['src/test/test-id128.c'],

View File

@ -213,6 +213,41 @@ static void test_socket_address_is_netlink(void) {
assert_se(!socket_address_is_netlink(&a, "route 1")); assert_se(!socket_address_is_netlink(&a, "route 1"));
} }
static void test_socket_addr_port_from_string_auto_one(const char *in, uint16_t port, int ret, int family, const char *expected) {
_cleanup_free_ char *out = NULL;
SocketAddress a;
int r;
r = socket_addr_port_from_string_auto(in, port, &a);
if (r >= 0)
assert_se(sockaddr_pretty(&a.sockaddr.sa, a.size, false, true, &out) >= 0);
log_info("\"%s\" → %s → \"%s\" (expect \"%s\")", in,
r >= 0 ? "" : "", empty_to_dash(out), r >= 0 ? expected ?: in : "-");
assert_se(r == ret);
if (r >= 0) {
assert_se(a.sockaddr.sa.sa_family == family);
assert_se(streq(out, expected ?: in));
}
}
static void test_socket_addr_port_from_string_auto(void) {
log_info("/* %s */", __func__);
test_socket_addr_port_from_string_auto_one("junk", 51, -EINVAL, 0, NULL);
test_socket_addr_port_from_string_auto_one("192.168.1.1", 53, 0, AF_INET, "192.168.1.1:53");
test_socket_addr_port_from_string_auto_one(".168.1.1", 53, -EINVAL, 0, NULL);
test_socket_addr_port_from_string_auto_one("989.168.1.1", 53, -EINVAL, 0, NULL);
test_socket_addr_port_from_string_auto_one("[::1]", 53, -EINVAL, 0, NULL);
test_socket_addr_port_from_string_auto_one("[::1]8888", 53, -EINVAL, 0, NULL);
test_socket_addr_port_from_string_auto_one("2001:db8:3c4d:15::1a2f:1a2b", 53, 0, AF_INET6, "[2001:db8:3c4d:15::1a2f:1a2b]:53");
test_socket_addr_port_from_string_auto_one("[2001:db8:3c4d:15::1a2f:1a2b]:2001", 53, 0, AF_INET6, "[2001:db8:3c4d:15::1a2f:1a2b]:2001");
test_socket_addr_port_from_string_auto_one("[::1]:0", 53, -EINVAL, 0, NULL);
test_socket_addr_port_from_string_auto_one("[::1]:65536", 53, -ERANGE, 0, NULL);
test_socket_addr_port_from_string_auto_one("[a:b:1]:8888", 53, -EINVAL, 0, NULL);
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG); test_setup_logging(LOG_DEBUG);
@ -222,6 +257,7 @@ int main(int argc, char *argv[]) {
test_socket_address_get_path(); test_socket_address_get_path();
test_socket_address_is(); test_socket_address_is();
test_socket_address_is_netlink(); test_socket_address_is_netlink();
test_socket_addr_port_from_string_auto();
return 0; return 0;
} }

View File

@ -17,6 +17,7 @@
#include "log.h" #include "log.h"
#include "main-func.h" #include "main-func.h"
#include "mkdir.h" #include "mkdir.h"
#include "mount-util.h"
#include "namespace-util.h" #include "namespace-util.h"
#include "selinux-util.h" #include "selinux-util.h"
#include "signal-util.h" #include "signal-util.h"
@ -43,12 +44,12 @@ static int fake_filesystems(void) {
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to detach mount namespace: %m"); return log_error_errno(r, "Failed to detach mount namespace: %m");
for (size_t i = 0; i < ELEMENTSOF(fakefss); i++) for (size_t i = 0; i < ELEMENTSOF(fakefss); i++) {
if (mount(fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL) < 0) { r = mount_verbose(fakefss[i].ignore_mount_error ? LOG_NOTICE : LOG_ERR,
log_full_errno(fakefss[i].ignore_mount_error ? LOG_DEBUG : LOG_ERR, errno, "%s: %m", fakefss[i].error); fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL);
if (!fakefss[i].ignore_mount_error) if (r < 0 && !fakefss[i].ignore_mount_error)
return -errno; return r;
} }
return 0; return 0;
} }
@ -62,20 +63,24 @@ static int run(int argc, char *argv[]) {
test_setup_logging(LOG_INFO); test_setup_logging(LOG_INFO);
if (!IN_SET(argc, 2, 3)) { if (!IN_SET(argc, 2, 3))
log_error("This program needs one or two arguments, %d given", argc - 1); return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
return -EINVAL; "This program needs one or two arguments, %d given", argc - 1);
}
r = fake_filesystems(); r = fake_filesystems();
if (r < 0) if (r < 0)
return r; return r;
/* Let's make sure the test runs with selinux assumed disabled. */
#if HAVE_SELINUX
fini_selinuxmnt();
#endif
mac_selinux_retest();
if (argc == 2) { if (argc == 2) {
if (!streq(argv[1], "check")) { if (!streq(argv[1], "check"))
log_error("Unknown argument: %s", argv[1]); return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
return -EINVAL; "Unknown argument: %s", argv[1]);
}
return 0; return 0;
} }
@ -91,7 +96,8 @@ static int run(int argc, char *argv[]) {
assert_se(udev_rules_load(&rules, RESOLVE_NAME_EARLY) == 0); assert_se(udev_rules_load(&rules, RESOLVE_NAME_EARLY) == 0);
const char *syspath = strjoina("/sys", devpath); const char *syspath;
syspath = strjoina("/sys", devpath);
r = device_new_from_synthetic_event(&dev, syspath, action); r = device_new_from_synthetic_event(&dev, syspath, action);
if (r < 0) if (r < 0)
return log_debug_errno(r, "Failed to open device '%s'", devpath); return log_debug_errno(r, "Failed to open device '%s'", devpath);

View File

@ -385,6 +385,7 @@ DNSLifetimeSec=
DNSSEC= DNSSEC=
DNSSECNegativeTrustAnchors= DNSSECNegativeTrustAnchors=
DNSStubListener= DNSStubListener=
DNSStubListenerExtra=
DUIDRawData= DUIDRawData=
DUIDType= DUIDType=
DefaultLeaseTimeSec= DefaultLeaseTimeSec=