diff options
author | Lennart Poettering <lennart@poettering.net> | 2020-09-10 16:47:37 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-09-10 16:47:37 +0200 |
commit | 6ae05c9b141e2051d001668089dfe8aaf268bd29 (patch) | |
tree | 935d9dc69d1a4e7848a434062acf9ab5960d5e85 /src/resolve | |
parent | Merge pull request #17003 from yuwata/conf-parser-downgrade-log-level (diff) | |
parent | Minor simplification in sockaddr_un_set_path() (diff) | |
download | systemd-6ae05c9b141e2051d001668089dfe8aaf268bd29.tar.xz systemd-6ae05c9b141e2051d001668089dfe8aaf268bd29.zip |
Merge pull request #16947 from keszybz/socket-parsing-rework
Socket parsing rework
Diffstat (limited to 'src/resolve')
-rw-r--r-- | src/resolve/resolved-conf.c | 13 | ||||
-rw-r--r-- | src/resolve/resolved-dns-stub.c | 274 |
2 files changed, 93 insertions, 194 deletions
diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c index 00cea964b4..0b7c5c8fc9 100644 --- a/src/resolve/resolved-conf.c +++ b/src/resolve/resolved-conf.c @@ -35,9 +35,6 @@ static int manager_add_dns_server_by_string(Manager *m, DnsServerType type, cons if (r < 0) return r; - if (IN_SET(port, 53, 853)) - port = 0; - /* Silently filter out 0.0.0.0 and 127.0.0.53 (our own stub DNS listener) */ if (!dns_server_address_valid(family, &address)) return 0; @@ -50,12 +47,8 @@ static int manager_add_dns_server_by_string(Manager *m, DnsServerType type, cons /* Filter out duplicates */ s = dns_server_find(manager_get_first_dns_server(m, type), family, &address, port, ifindex, server_name); if (s) { - /* - * Drop the marker. This is used to find the servers - * that ceased to exist, see - * manager_mark_dns_servers() and - * manager_flush_marked_dns_servers(). - */ + /* Drop the marker. This is used to find the servers that ceased to exist, see + * manager_mark_dns_servers() and manager_flush_marked_dns_servers(). */ dns_server_move_back_and_unmark(s); return 0; } @@ -447,7 +440,7 @@ int config_parse_dns_stub_listener_extra( } } - r = in_addr_port_from_string_auto(p, &stub->family, &stub->address, &stub->port); + r = in_addr_port_ifindex_name_from_string_auto(p, &stub->family, &stub->address, &stub->port, NULL, NULL); if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse address in %s=%s, ignoring assignment: %m", diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index 59ced33847..572be26c2d 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -15,7 +15,7 @@ * IP and UDP header sizes */ #define ADVERTISE_DATAGRAM_SIZE_MAX (65536U-14U-20U-8U) -static int manager_dns_stub_udp_fd_extra(Manager *m, DnsStubListenerExtra *l); +static int manager_dns_stub_fd_extra(Manager *m, DnsStubListenerExtra *l, int type); static void dns_stub_listener_extra_hash_func(const DnsStubListenerExtra *a, struct siphash *state) { assert(a); @@ -217,7 +217,7 @@ static int dns_stub_send( * is because otherwise the kernel will choose it automatically based on the routing table and will * thus pick 127.0.0.1 rather than 127.0.0.53. */ r = manager_send(m, - manager_dns_stub_udp_fd_extra(m, l), + manager_dns_stub_fd_extra(m, l, SOCK_DGRAM), l ? p->ifindex : LOOPBACK_IFINDEX, /* force loopback iface if this is the main listener stub */ p->family, &p->sender, p->sender_port, &p->destination, reply); @@ -477,151 +477,6 @@ static int on_dns_stub_packet_extra(sd_event_source *s, int fd, uint32_t revents return on_dns_stub_packet_internal(s, fd, revents, l->manager, l); } -static int set_dns_stub_common_socket_options(int fd, int family) { - int r; - - assert(fd >= 0); - assert(IN_SET(family, AF_INET, AF_INET6)); - - r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, true); - if (r < 0) - return r; - - if (family == AF_INET) { - 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; - } else { - r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, true); - if (r < 0) - return r; - - r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, true); - if (r < 0) - return r; - } - - return 0; -} - -static int manager_dns_stub_udp_fd(Manager *m) { - union sockaddr_union sa = { - .in.sin_family = AF_INET, - .in.sin_port = htobe16(53), - .in.sin_addr.s_addr = htobe32(INADDR_DNS_STUB), - }; - _cleanup_close_ int fd = -1; - int r; - - if (m->dns_stub_udp_event_source) - return sd_event_source_get_io_fd(m->dns_stub_udp_event_source); - - fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); - if (fd < 0) - return -errno; - - r = set_dns_stub_common_socket_options(fd, AF_INET); - if (r < 0) - return r; - - /* Make sure no traffic from outside the local host can leak to onto this socket */ - r = socket_bind_to_ifindex(fd, LOOPBACK_IFINDEX); - if (r < 0) - return r; - - if (bind(fd, &sa.sa, sizeof(sa.in)) < 0) - return -errno; - - r = sd_event_add_io(m->event, &m->dns_stub_udp_event_source, fd, EPOLLIN, on_dns_stub_packet, m); - if (r < 0) - return r; - - r = sd_event_source_set_io_fd_own(m->dns_stub_udp_event_source, true); - if (r < 0) - return r; - - (void) sd_event_source_set_description(m->dns_stub_udp_event_source, "dns-stub-udp"); - - return 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; - union sockaddr_union sa; - int r; - - assert(m); - - if (!l) - return manager_dns_stub_udp_fd(m); - - if (l->udp_event_source) - return 0; - - if (l->family == AF_INET) - sa = (union sockaddr_union) { - .in.sin_family = l->family, - .in.sin_port = htobe16(l->port != 0 ? l->port : 53U), - .in.sin_addr = l->address.in, - }; - else - sa = (union sockaddr_union) { - .in6.sin6_family = l->family, - .in6.sin6_port = htobe16(l->port != 0 ? l->port : 53U), - .in6.sin6_addr = l->address.in6, - }; - - fd = socket(l->family, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); - if (fd < 0) { - r = -errno; - goto fail; - } - - if (l->family == AF_INET) { - r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true); - if (r < 0) - goto fail; - } - - r = set_dns_stub_common_socket_options(fd, l->family); - if (r < 0) - goto fail; - - if (bind(fd, &sa.sa, SOCKADDR_LEN(sa)) < 0) { - r = -errno; - goto fail; - } - - r = sd_event_add_io(m->event, &l->udp_event_source, fd, EPOLLIN, on_dns_stub_packet_extra, l); - if (r < 0) - goto fail; - - r = sd_event_source_set_io_fd_own(l->udp_event_source, true); - if (r < 0) - goto fail; - - (void) sd_event_source_set_description(l->udp_event_source, "dns-stub-udp-extra"); - - if (DEBUG_LOGGING) { - (void) in_addr_port_to_string(l->family, &l->address, l->port, &pretty); - log_debug("Listening on UDP socket %s.", strnull(pretty)); - } - - return TAKE_FD(fd); - -fail: - assert(r < 0); - (void) in_addr_port_to_string(l->family, &l->address, l->port, &pretty); - if (r == -EADDRINUSE) - return log_warning_errno(r, "Another process is already listening on UDP socket %s: %m", strnull(pretty)); - return log_warning_errno(r, "Failed to listen on UDP socket %s: %m", strnull(pretty)); -} - static int on_dns_stub_stream_packet(DnsStream *s) { _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; @@ -678,7 +533,38 @@ static int on_dns_stub_stream_extra(sd_event_source *s, int fd, uint32_t revents return on_dns_stub_stream_internal(s, fd, revents, l->manager, l); } -static int manager_dns_stub_tcp_fd(Manager *m) { +static int set_dns_stub_common_socket_options(int fd, int family) { + int r; + + assert(fd >= 0); + assert(IN_SET(family, AF_INET, AF_INET6)); + + r = setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, true); + if (r < 0) + return r; + + if (family == AF_INET) { + 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; + } else { + r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, true); + if (r < 0) + return r; + + r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, true); + if (r < 0) + return r; + } + + return 0; +} + +static int manager_dns_stub_fd(Manager *m, int type) { union sockaddr_union sa = { .in.sin_family = AF_INET, .in.sin_addr.s_addr = htobe32(INADDR_DNS_STUB), @@ -687,10 +573,13 @@ static int manager_dns_stub_tcp_fd(Manager *m) { _cleanup_close_ int fd = -1; int r; - if (m->dns_stub_tcp_event_source) - return sd_event_source_get_io_fd(m->dns_stub_tcp_event_source); + assert(IN_SET(type, SOCK_DGRAM, SOCK_STREAM)); + + sd_event_source **event_source = type == SOCK_DGRAM ? &m->dns_stub_udp_event_source : &m->dns_stub_tcp_event_source; + if (*event_source) + return sd_event_source_get_io_fd(*event_source); - fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + fd = socket(AF_INET, type | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); if (fd < 0) return -errno; @@ -698,42 +587,53 @@ static int manager_dns_stub_tcp_fd(Manager *m) { if (r < 0) return r; - r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, 1); + /* Make sure no traffic from outside the local host can leak to onto this socket */ + r = socket_bind_to_ifindex(fd, LOOPBACK_IFINDEX); if (r < 0) return r; - /* Make sure no traffic from outside the local host can leak to onto this socket */ - r = socket_bind_to_ifindex(fd, LOOPBACK_IFINDEX); + r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, 1); if (r < 0) return r; if (bind(fd, &sa.sa, sizeof(sa.in)) < 0) return -errno; - if (listen(fd, SOMAXCONN) < 0) + if (type == SOCK_STREAM && + listen(fd, SOMAXCONN) < 0) return -errno; - r = sd_event_add_io(m->event, &m->dns_stub_tcp_event_source, fd, EPOLLIN, on_dns_stub_stream, m); + r = sd_event_add_io(m->event, event_source, fd, EPOLLIN, + type == SOCK_DGRAM ? on_dns_stub_packet : on_dns_stub_stream, + m); if (r < 0) return r; - r = sd_event_source_set_io_fd_own(m->dns_stub_tcp_event_source, true); + r = sd_event_source_set_io_fd_own(*event_source, true); if (r < 0) return r; - (void) sd_event_source_set_description(m->dns_stub_tcp_event_source, "dns-stub-tcp"); + (void) sd_event_source_set_description(*event_source, + type == SOCK_DGRAM ? "dns-stub-udp" : "dns-stub-tcp"); return TAKE_FD(fd); } -static int manager_dns_stub_tcp_fd_extra(Manager *m, DnsStubListenerExtra *l) { +static int manager_dns_stub_fd_extra(Manager *m, DnsStubListenerExtra *l, int type) { _cleanup_free_ char *pretty = NULL; _cleanup_close_ int fd = -1; union sockaddr_union sa; int r; - if (l->tcp_event_source) - return sd_event_source_get_io_fd(l->tcp_event_source);; + assert(m); + assert(IN_SET(type, SOCK_DGRAM, SOCK_STREAM)); + + if (!l) + return manager_dns_stub_fd(m, type); + + sd_event_source **event_source = type == SOCK_DGRAM ? &l->udp_event_source : &l->tcp_event_source; + if (*event_source) + return sd_event_source_get_io_fd(*event_source); if (l->family == AF_INET) sa = (union sockaddr_union) { @@ -748,7 +648,7 @@ static int manager_dns_stub_tcp_fd_extra(Manager *m, DnsStubListenerExtra *l) { .in6.sin6_addr = l->address.in6, }; - fd = socket(l->family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); + fd = socket(l->family, type | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); if (fd < 0) { r = -errno; goto fail; @@ -758,8 +658,8 @@ static int manager_dns_stub_tcp_fd_extra(Manager *m, DnsStubListenerExtra *l) { if (r < 0) goto fail; - /* Do not set IP_TTL for extra DNS stub listners, as the address may not be local and in that - * case people may want ttl > 1. */ + /* Do not set IP_TTL for extra DNS stub listners, as the address may not be local and in that case + * people may want ttl > 1. */ if (l->family == AF_INET) r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true); @@ -773,24 +673,30 @@ static int manager_dns_stub_tcp_fd_extra(Manager *m, DnsStubListenerExtra *l) { goto fail; } - if (listen(fd, SOMAXCONN) < 0) { + if (type == SOCK_STREAM && + listen(fd, SOMAXCONN) < 0) { r = -errno; goto fail; } - r = sd_event_add_io(m->event, &l->tcp_event_source, fd, EPOLLIN, on_dns_stub_stream_extra, l); + r = sd_event_add_io(m->event, event_source, fd, EPOLLIN, + type == SOCK_DGRAM ? on_dns_stub_packet_extra : on_dns_stub_stream_extra, + l); if (r < 0) goto fail; - r = sd_event_source_set_io_fd_own(l->tcp_event_source, true); + r = sd_event_source_set_io_fd_own(*event_source, true); if (r < 0) goto fail; - (void) sd_event_source_set_description(l->tcp_event_source, "dns-stub-tcp-extra"); + (void) sd_event_source_set_description(*event_source, + type == SOCK_DGRAM ? "dns-stub-udp-extra" : "dns-stub-tcp-extra"); if (DEBUG_LOGGING) { (void) in_addr_port_to_string(l->family, &l->address, l->port, &pretty); - log_debug("Listening on TCP socket %s.", strnull(pretty)); + log_debug("Listening on %s socket %s.", + type == SOCK_DGRAM ? "UDP" : "TCP", + strnull(pretty)); } return TAKE_FD(fd); @@ -798,9 +704,11 @@ static int manager_dns_stub_tcp_fd_extra(Manager *m, DnsStubListenerExtra *l) { fail: assert(r < 0); (void) in_addr_port_to_string(l->family, &l->address, l->port, &pretty); - if (r == -EADDRINUSE) - return log_warning_errno(r, "Another process is already listening on TCP socket %s: %m", strnull(pretty)); - return log_warning_errno(r, "Failed to listen on TCP socket %s: %m", strnull(pretty)); + return log_warning_errno(r, + r == -EADDRINUSE ? "Another process is already listening on %s socket %s: %m" : + "Failed to listen on %s socket %s: %m", + type == SOCK_DGRAM ? "UDP" : "TCP", + strnull(pretty)); } int manager_dns_stub_start(Manager *m) { @@ -818,23 +726,21 @@ int manager_dns_stub_start(Manager *m) { "UDP/TCP"); if (FLAGS_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_UDP)) - r = manager_dns_stub_udp_fd(m); + r = manager_dns_stub_fd(m, SOCK_DGRAM); if (r >= 0 && FLAGS_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_TCP)) { t = "TCP"; - r = manager_dns_stub_tcp_fd(m); + r = manager_dns_stub_fd(m, SOCK_STREAM); } if (IN_SET(r, -EADDRINUSE, -EPERM)) { - if (r == -EADDRINUSE) - log_warning_errno(r, - "Another process is already listening on %s socket 127.0.0.53:53.\n" - "Turning off local DNS stub support.", t); - else - log_warning_errno(r, - "Failed to listen on %s socket 127.0.0.53:53: %m.\n" - "Turning off local DNS stub support.", t); + log_warning_errno(r, + r == -EADDRINUSE ? "Another process is already listening on %s socket 127.0.0.53:53.\n" + "Turning off local DNS stub support." : + "Failed to listen on %s socket 127.0.0.53:53: %m.\n" + "Turning off local DNS stub support.", + t); manager_dns_stub_stop(m); } else if (r < 0) return log_error_errno(r, "Failed to listen on %s socket 127.0.0.53:53: %m", t); @@ -846,9 +752,9 @@ int manager_dns_stub_start(Manager *m) { ORDERED_SET_FOREACH(l, m->dns_extra_stub_listeners) { if (FLAGS_SET(l->mode, DNS_STUB_LISTENER_UDP)) - (void) manager_dns_stub_udp_fd_extra(m, l); + (void) manager_dns_stub_fd_extra(m, l, SOCK_DGRAM); if (FLAGS_SET(l->mode, DNS_STUB_LISTENER_TCP)) - (void) manager_dns_stub_tcp_fd_extra(m, l); + (void) manager_dns_stub_fd_extra(m, l, SOCK_STREAM); } } |