From 6421194b31bfc1f4b96fdece8c753f045720f48b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 12:58:32 +0900 Subject: [PATCH 01/23] man: update DNSStubListenerExtra= --- man/resolved.conf.xml | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml index 338bee6c38..c3c6b26329 100644 --- a/man/resolved.conf.xml +++ b/man/resolved.conf.xml @@ -271,27 +271,27 @@ DNSStubListenerExtra= - Takes an IPv4 or IPv6 address to listen on. The address may optionally be prefixed by : and - a protocol name (udp or tcp). 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 :. - If the protocol is not specified, the service will listen on both UDP and TCP. 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 DNSStubListener=, and only configures additional - sockets to listen on. Defaults to unset. + Takes an IPv4 or IPv6 address to listen on. The address may be optionally + prefixed with a protocol name (udp or tcp) separated with + :. If the protocol is not specified, the service will listen on both UDP and + TCP. It may be also optionally suffixed by a numeric port number with separator + :. When an IPv6 address is specified with a port number, then the address + must be in the square brackets. If the port is not specified, then the service uses port 53. + Note that this is independent of the primary DNS stub configured with + DNSStubListener=, and only configures additional + sockets to listen on. This option can be specified multiple times. If an empty string is + assigned, then the all previous assignments are cleared. Defaults to unset. - If the string in the format udp:[x]:y, - it is read as protocol udp and IPv6 address x on a port y. - - If the string in the format [x]:y, it is read as both protocol - udp and tcp, IPv6 address x on a port y. - - If the string in the format x, it is read as protocol both udp and - tcp, IPv6/IPv4 address x on a port 53. - - If the string in the format udp:x:y, - it is read as protocol udp and IPv4 address x on a port y. - + Examples: + DNSStubListenerExtra=192.168.10.10 +DNSStubListenerExtra=2001:db8:0:f102::10 +DNSStubListenerExtra=192.168.10.11:9953 +DNSStubListenerExtra=[2001:db8:0:f102::11]:9953 +DNSStubListenerExtra=tcp:192.168.10.12 +DNSStubListenerExtra=udp:2001:db8:0:f102::12 +DNSStubListenerExtra=tcp:192.168.10.13:9953 +DNSStubListenerExtra=udp:[2001:db8:0:f102::13]:9953 + From 8ae07803a03557971729a4115e3df37ea61cfc54 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 13:01:15 +0900 Subject: [PATCH 02/23] resolve: rename dns_stub_extra_event_source -> event_source As the name is too redundant. --- src/resolve/resolved-dns-stub.c | 10 +++++----- src/resolve/resolved-manager.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index d3999ea0a3..f9087a379f 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -483,11 +483,11 @@ static int manager_dns_stub_udp_fd_extra(Manager *m, DNSStubListenerExtra *l) { goto fail; } - r = sd_event_add_io(m->event, &l->dns_stub_extra_event_source, fd, EPOLLIN, on_dns_stub_packet, m); + r = sd_event_add_io(m->event, &l->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"); + (void) sd_event_source_set_description(l->event_source, "dns-stub-udp-extra"); l->fd = TAKE_FD(fd); @@ -639,11 +639,11 @@ static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) { goto fail; } - r = sd_event_add_io(m->event, &l->dns_stub_extra_event_source, fd, EPOLLIN, on_dns_stub_packet, m); + r = sd_event_add_io(m->event, &l->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"); + (void) sd_event_source_set_description(l->event_source, "dns-stub-tcp-extra"); l->fd = TAKE_FD(fd); @@ -742,7 +742,7 @@ void manager_dns_stub_stop_extra(Manager *m) { 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->event_source = sd_event_source_unref(l->event_source); l->fd = safe_close(l->fd); } } diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h index a3a2e08123..f31557a8a3 100644 --- a/src/resolve/resolved-manager.h +++ b/src/resolve/resolved-manager.h @@ -36,7 +36,7 @@ typedef struct DNSStubListenerExtra { DnsStubListenerMode mode; SocketAddress address; - sd_event_source *dns_stub_extra_event_source; + sd_event_source *event_source; } DNSStubListenerExtra; struct Manager { From 88d2cb7c0e3884e5b8e37e20cb9911e7ab210cf7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 13:09:02 +0900 Subject: [PATCH 03/23] resolve: make DnsStubListenerMode bitfield --- src/resolve/resolved-conf.h | 6 +++--- src/resolve/resolved-dns-stub.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/resolve/resolved-conf.h b/src/resolve/resolved-conf.h index f8d16b5a8e..50a0caaf16 100644 --- a/src/resolve/resolved-conf.h +++ b/src/resolve/resolved-conf.h @@ -7,9 +7,9 @@ typedef enum DnsStubListenerMode DnsStubListenerMode; enum DnsStubListenerMode { DNS_STUB_LISTENER_NO, - DNS_STUB_LISTENER_UDP, - DNS_STUB_LISTENER_TCP, - DNS_STUB_LISTENER_YES, + DNS_STUB_LISTENER_UDP = 1 << 0, + DNS_STUB_LISTENER_TCP = 1 << 1, + DNS_STUB_LISTENER_YES = DNS_STUB_LISTENER_UDP | DNS_STUB_LISTENER_TCP, _DNS_STUB_LISTENER_MODE_MAX, _DNS_STUB_LISTENER_MODE_INVALID = -1 }; diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index f9087a379f..de37c9a038 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -684,11 +684,11 @@ int manager_dns_stub_start(Manager *m) { m->dns_stub_listener_mode == DNS_STUB_LISTENER_TCP ? "TCP" : "UDP/TCP"); - if (IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_UDP)) + if (FLAGS_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_UDP)) r = manager_dns_stub_udp_fd(m); if (r >= 0 && - IN_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_YES, DNS_STUB_LISTENER_TCP)) { + FLAGS_SET(m->dns_stub_listener_mode, DNS_STUB_LISTENER_TCP)) { t = "TCP"; r = manager_dns_stub_tcp_fd(m); } From dce65cd40f07ac800ee01cbc8c017b63d87fe593 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 13:21:55 +0900 Subject: [PATCH 04/23] resolve: Manager::dns_stub_listener_mode is not relevant to extra stub listeners --- src/resolve/resolved-dns-stub.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index de37c9a038..5179e86602 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -710,10 +710,7 @@ int manager_dns_stub_start(Manager *m) { 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"); + log_debug("Creating extra stub listeners."); ORDERED_SET_FOREACH(l, m->dns_extra_stub_listeners, i) if (l->mode == DNS_STUB_LISTENER_UDP) From 7314b39746cdc30a9e9bfe96d4b55da650428f27 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 13:23:39 +0900 Subject: [PATCH 05/23] resolve: set DNS_STUB_LISTENER_YES if no protocol is specified in DNSStubListenExtra= --- src/resolve/resolved-conf.c | 97 ++++++++++----------------------- src/resolve/resolved-dns-stub.c | 36 ++++++------ src/resolve/resolved-manager.h | 6 +- 3 files changed, 53 insertions(+), 86 deletions(-) diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c index 3b2b4d2063..1c934b34cf 100644 --- a/src/resolve/resolved-conf.c +++ b/src/resolve/resolved-conf.c @@ -444,10 +444,8 @@ int config_parse_dns_stub_listener_extra( void *data, void *userdata) { - _cleanup_free_ DNSStubListenerExtra *udp = NULL, *tcp = NULL; - _cleanup_free_ char *word = NULL; + _cleanup_free_ DNSStubListenerExtra *stub = NULL; Manager *m = userdata; - bool both = false; const char *p; int r; @@ -461,78 +459,41 @@ int config_parse_dns_stub_listener_extra( return 0; } - p = rvalue; - r = extract_first_word(&p, &word, ":", 0); - if (r == -ENOMEM) + r = dns_stub_extra_new(&stub); + if (r < 0) return log_oom(); - if (r <= 0) { + + p = startswith(rvalue, "udp:"); + if (p) + stub->mode = DNS_STUB_LISTENER_UDP; + else { + p = startswith(rvalue, "tcp:"); + if (p) + stub->mode = DNS_STUB_LISTENER_TCP; + else { + stub->mode = DNS_STUB_LISTENER_YES; + p = rvalue; + } + } + + r = socket_addr_port_from_string_auto(p, 53, &stub->address); + if (r < 0) { log_syntax(unit, LOG_WARNING, filename, line, r, - "Invalid DNSStubListenExtra='%s', ignoring assignment", rvalue); + "Failed to parse address in %s=%s, ignoring assignment: %m", + lvalue, 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; + r = ordered_set_ensure_put(&m->dns_extra_stub_listeners, &dns_stub_listener_extra_hash_ops, stub); + if (r == -ENOMEM) + return log_oom(); + if (r < 0) { + log_syntax(unit, LOG_WARNING, filename, line, r, + "Failed to store %s=%s, ignoring assignment: %m", lvalue, rvalue); + return 0; } - 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); + TAKE_PTR(stub); return 0; } diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index 5179e86602..2a8637d378 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -22,7 +22,8 @@ int dns_stub_extra_new(DNSStubListenerExtra **ret) { return -ENOMEM; *l = (DNSStubListenerExtra) { - .fd = -1, + .udp_fd = -1, + .tcp_fd = -1, }; *ret = TAKE_PTR(l); @@ -461,7 +462,7 @@ static int manager_dns_stub_udp_fd_extra(Manager *m, DNSStubListenerExtra *l) { _cleanup_close_ int fd = -1; int r; - if (l->fd >= 0) + if (l->udp_fd >= 0) return 0; fd = socket(socket_address_family(&l->address), SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); @@ -483,19 +484,19 @@ static int manager_dns_stub_udp_fd_extra(Manager *m, DNSStubListenerExtra *l) { goto fail; } - r = sd_event_add_io(m->event, &l->event_source, fd, EPOLLIN, on_dns_stub_packet, m); + r = sd_event_add_io(m->event, &l->udp_event_source, fd, EPOLLIN, on_dns_stub_packet, m); if (r < 0) goto fail; - (void) sd_event_source_set_description(l->event_source, "dns-stub-udp-extra"); - - l->fd = TAKE_FD(fd); + (void) sd_event_source_set_description(l->udp_event_source, "dns-stub-udp-extra"); 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)); } + l->udp_fd = TAKE_FD(fd); + return 0; fail: @@ -608,7 +609,7 @@ static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) { _cleanup_close_ int fd = -1; int r; - if (l->fd >= 0) + if (l->tcp_fd >= 0) return 0; fd = socket(socket_address_family(&l->address), SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); @@ -639,19 +640,19 @@ static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) { goto fail; } - r = sd_event_add_io(m->event, &l->event_source, fd, EPOLLIN, on_dns_stub_packet, m); + r = sd_event_add_io(m->event, &l->tcp_event_source, fd, EPOLLIN, on_dns_stub_packet, m); if (r < 0) goto fail; - (void) sd_event_source_set_description(l->event_source, "dns-stub-tcp-extra"); - - l->fd = TAKE_FD(fd); + (void) sd_event_source_set_description(l->tcp_event_source, "dns-stub-tcp-extra"); 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)); } + l->tcp_fd = TAKE_FD(fd); + return 0; fail: @@ -712,11 +713,12 @@ int manager_dns_stub_start(Manager *m) { log_debug("Creating extra stub listeners."); - ORDERED_SET_FOREACH(l, m->dns_extra_stub_listeners, i) - if (l->mode == DNS_STUB_LISTENER_UDP) + ORDERED_SET_FOREACH(l, m->dns_extra_stub_listeners, i) { + if (FLAGS_SET(l->mode, DNS_STUB_LISTENER_UDP)) (void) manager_dns_stub_udp_fd_extra(m, l); - else + if (FLAGS_SET(l->mode, DNS_STUB_LISTENER_TCP)) (void) manager_dns_stub_tcp_fd_extra(m, l); + } } return 0; @@ -739,7 +741,9 @@ void manager_dns_stub_stop_extra(Manager *m) { assert(m); ORDERED_SET_FOREACH(l, m->dns_extra_stub_listeners, i) { - l->event_source = sd_event_source_unref(l->event_source); - l->fd = safe_close(l->fd); + l->udp_event_source = sd_event_source_unref(l->udp_event_source); + l->tcp_event_source = sd_event_source_unref(l->tcp_event_source); + l->udp_fd = safe_close(l->udp_fd); + l->tcp_fd = safe_close(l->tcp_fd); } } diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h index f31557a8a3..2c6adfbcbd 100644 --- a/src/resolve/resolved-manager.h +++ b/src/resolve/resolved-manager.h @@ -32,11 +32,13 @@ typedef struct EtcHosts { } EtcHosts; typedef struct DNSStubListenerExtra { - int fd; + int udp_fd; + int tcp_fd; DnsStubListenerMode mode; SocketAddress address; - sd_event_source *event_source; + sd_event_source *udp_event_source; + sd_event_source *tcp_event_source; } DNSStubListenerExtra; struct Manager { From 4650582657aa86770ca3a6b6a8ac14664bd49eac Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 14:29:06 +0900 Subject: [PATCH 06/23] resolve: stop extra stub listners before freeing information about them --- src/resolve/resolved-manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 5c09de0c34..ea26fb0795 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -701,7 +701,6 @@ Manager *manager_free(Manager *m) { hashmap_free(m->links); hashmap_free(m->dns_transactions); - ordered_set_free(m->dns_extra_stub_listeners); sd_event_source_unref(m->network_event_source); sd_network_monitor_unref(m->network_monitor); @@ -715,6 +714,7 @@ Manager *manager_free(Manager *m) { manager_varlink_done(m); manager_dns_stub_stop_extra(m); + ordered_set_free(m->dns_extra_stub_listeners); bus_verify_polkit_async_registry_free(m->polkit_registry); From 355e884dede875bc187802620b7e9ec29bdf7b9d Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 13:40:31 +0900 Subject: [PATCH 07/23] util: introduce in_addr_port_from_string_auto() --- src/shared/socket-netlink.c | 30 ++++++++++++++++++++++++++++++ src/shared/socket-netlink.h | 1 + 2 files changed, 31 insertions(+) diff --git a/src/shared/socket-netlink.c b/src/shared/socket-netlink.c index 32e45985b4..dc1b27f165 100644 --- a/src/shared/socket-netlink.c +++ b/src/shared/socket-netlink.c @@ -482,6 +482,36 @@ int in_addr_port_ifindex_name_from_string_auto( return r; } +int in_addr_port_from_string_auto( + const char *s, + int *ret_family, + union in_addr_union *ret_address, + uint16_t *ret_port) { + + union in_addr_union addr; + int family, ifindex, r; + uint16_t port; + + assert(s); + + r = in_addr_port_ifindex_name_from_string_auto(s, &family, &addr, &port, &ifindex, NULL); + if (r < 0) + return r; + + /* This does not accept interface specified. */ + if (ifindex != 0) + return -EINVAL; + + if (ret_family) + *ret_family = family; + if (ret_address) + *ret_address = addr; + if (ret_port) + *ret_port = port; + + return r; +} + struct in_addr_full *in_addr_full_free(struct in_addr_full *a) { if (!a) return NULL; diff --git a/src/shared/socket-netlink.h b/src/shared/socket-netlink.h index 143fc8d41a..7fa831a880 100644 --- a/src/shared/socket-netlink.h +++ b/src/shared/socket-netlink.h @@ -34,6 +34,7 @@ static inline int in_addr_ifindex_name_from_string_auto(const char *s, int *fami static inline int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex) { return in_addr_ifindex_name_from_string_auto(s, family, ret, ifindex, NULL); } +int in_addr_port_from_string_auto(const char *s, int *ret_family, union in_addr_union *ret_address, uint16_t *ret_port); struct in_addr_full { int family; From c364cefb3a727adeb4934bb6afd5e86185f84d68 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 16:14:14 +0900 Subject: [PATCH 08/23] util: make in_addr_ifindex_to_string() an alias of in_addr_port_ifindex_name_to_string() --- src/basic/in-addr-util.c | 40 ---------------------------------------- src/basic/in-addr-util.h | 4 +++- 2 files changed, 3 insertions(+), 41 deletions(-) diff --git a/src/basic/in-addr-util.c b/src/basic/in-addr-util.c index ea50e26197..f0ce6900ef 100644 --- a/src/basic/in-addr-util.c +++ b/src/basic/in-addr-util.c @@ -402,46 +402,6 @@ int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned return 0; } -int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) { - _cleanup_free_ char *x = NULL; - size_t l; - int r; - - assert(u); - assert(ret); - - /* Much like in_addr_to_string(), but optionally appends the zone interface index to the address, to properly - * handle IPv6 link-local addresses. */ - - if (family != AF_INET6) - goto fallback; - if (ifindex <= 0) - goto fallback; - - r = in_addr_is_link_local(family, u); - if (r < 0) - return r; - if (r == 0) - goto fallback; - - l = INET6_ADDRSTRLEN + 1 + DECIMAL_STR_MAX(ifindex) + 1; - x = new(char, l); - if (!x) - return -ENOMEM; - - errno = 0; - if (!inet_ntop(family, u, x, l)) - return errno_or_else(EINVAL); - - sprintf(strchr(x, 0), "%%%i", ifindex); - - *ret = TAKE_PTR(x); - return 0; - -fallback: - return in_addr_to_string(family, u, ret); -} - int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u, uint16_t port, int ifindex, const char *server_name, char **ret) { _cleanup_free_ char *ip_str = NULL, *x = NULL; int r; diff --git a/src/basic/in-addr-util.h b/src/basic/in-addr-util.h index 03583f2566..e0ef972952 100644 --- a/src/basic/in-addr-util.h +++ b/src/basic/in-addr-util.h @@ -41,8 +41,10 @@ int in_addr_prefix_nth(int family, union in_addr_union *u, unsigned prefixlen, u int in_addr_random_prefix(int family, union in_addr_union *u, unsigned prefixlen_fixed_part, unsigned prefixlen); int in_addr_to_string(int family, const union in_addr_union *u, char **ret); int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned prefixlen, char **ret); -int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret); int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u, uint16_t port, int ifindex, const char *server_name, char **ret); +static inline int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) { + return in_addr_port_ifindex_name_to_string(family, u, 0, ifindex, NULL, ret); +} int in_addr_from_string(int family, const char *s, union in_addr_union *ret); int in_addr_from_string_auto(const char *s, int *ret_family, union in_addr_union *ret); From c4fe658366854b83a2b107fb986ee44d2907a07c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 16:15:29 +0900 Subject: [PATCH 09/23] util: introduce in_addr_port_to_string() --- src/basic/in-addr-util.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/basic/in-addr-util.h b/src/basic/in-addr-util.h index e0ef972952..6ce0bef578 100644 --- a/src/basic/in-addr-util.h +++ b/src/basic/in-addr-util.h @@ -45,6 +45,9 @@ int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u static inline int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) { return in_addr_port_ifindex_name_to_string(family, u, 0, ifindex, NULL, ret); } +static inline int in_addr_port_to_string(int family, const union in_addr_union *u, uint16_t port, char **ret) { + return in_addr_port_ifindex_name_to_string(family, u, port, 0, NULL, ret); +} int in_addr_from_string(int family, const char *s, union in_addr_union *ret); int in_addr_from_string_auto(const char *s, int *ret_family, union in_addr_union *ret); From 23c5aeaac3466321b0855455d469caec2da5159e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 15:53:50 +0900 Subject: [PATCH 10/23] test: move several tests from test-socket-util.c --- src/test/test-in-addr-util.c | 153 +++++++++++++++++++ src/test/test-socket-netlink.c | 108 ++++++++++++++ src/test/test-socket-util.c | 262 --------------------------------- 3 files changed, 261 insertions(+), 262 deletions(-) diff --git a/src/test/test-in-addr-util.c b/src/test/test-in-addr-util.c index 916bd35f0d..63e9800ec8 100644 --- a/src/test/test-in-addr-util.c +++ b/src/test/test-in-addr-util.c @@ -177,10 +177,163 @@ static void test_in_addr_random_prefix(void) { str = mfree(str); } +static void test_in_addr_is_null(void) { + union in_addr_union i = {}; + + log_info("/* %s */", __func__); + + assert_se(in_addr_is_null(AF_INET, &i) == true); + assert_se(in_addr_is_null(AF_INET6, &i) == true); + + i.in.s_addr = 0x1000000; + assert_se(in_addr_is_null(AF_INET, &i) == false); + assert_se(in_addr_is_null(AF_INET6, &i) == false); + + assert_se(in_addr_is_null(-1, &i) == -EAFNOSUPPORT); +} + +static void test_in_addr_prefix_intersect_one(unsigned f, const char *a, unsigned apl, const char *b, unsigned bpl, int result) { + union in_addr_union ua, ub; + + assert_se(in_addr_from_string(f, a, &ua) >= 0); + assert_se(in_addr_from_string(f, b, &ub) >= 0); + + assert_se(in_addr_prefix_intersect(f, &ua, apl, &ub, bpl) == result); +} + +static void test_in_addr_prefix_intersect(void) { + log_info("/* %s */", __func__); + + test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 32, "255.255.255.254", 32, 0); + test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 0, "255.255.255.255", 32, 1); + test_in_addr_prefix_intersect_one(AF_INET, "0.0.0.0", 0, "47.11.8.15", 32, 1); + + test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.1", 24, 1); + test_in_addr_prefix_intersect_one(AF_INET, "2.2.2.2", 24, "1.1.1.1", 24, 0); + + test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 25, 1); + test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 26, 1); + test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.127", 25, 1); + test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.255", 25, 0); + + test_in_addr_prefix_intersect_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe", 128, 0); + test_in_addr_prefix_intersect_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, 1); + test_in_addr_prefix_intersect_one(AF_INET6, "::", 0, "beef:beef:beef:beef:beef:beef:beef:beef", 128, 1); + + test_in_addr_prefix_intersect_one(AF_INET6, "1::2", 64, "1::2", 64, 1); + test_in_addr_prefix_intersect_one(AF_INET6, "2::2", 64, "1::2", 64, 0); + + test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 121, 1); + test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 122, 1); + test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::007f", 121, 1); + test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::00ff", 121, 0); +} + +static void test_in_addr_prefix_next_one(unsigned f, const char *before, unsigned pl, const char *after) { + union in_addr_union ubefore, uafter, t; + + assert_se(in_addr_from_string(f, before, &ubefore) >= 0); + + t = ubefore; + assert_se((in_addr_prefix_next(f, &t, pl) > 0) == !!after); + + if (after) { + assert_se(in_addr_from_string(f, after, &uafter) >= 0); + assert_se(in_addr_equal(f, &t, &uafter) > 0); + } +} + +static void test_in_addr_prefix_next(void) { + log_info("/* %s */", __func__); + + test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 24, "192.168.1.0"); + test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 16, "192.169.0.0"); + test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 20, "192.168.16.0"); + + test_in_addr_prefix_next_one(AF_INET, "0.0.0.0", 32, "0.0.0.1"); + test_in_addr_prefix_next_one(AF_INET, "255.255.255.255", 32, NULL); + test_in_addr_prefix_next_one(AF_INET, "255.255.255.0", 24, NULL); + + test_in_addr_prefix_next_one(AF_INET6, "4400::", 128, "4400::0001"); + test_in_addr_prefix_next_one(AF_INET6, "4400::", 120, "4400::0100"); + test_in_addr_prefix_next_one(AF_INET6, "4400::", 127, "4400::0002"); + test_in_addr_prefix_next_one(AF_INET6, "4400::", 8, "4500::"); + test_in_addr_prefix_next_one(AF_INET6, "4400::", 7, "4600::"); + + test_in_addr_prefix_next_one(AF_INET6, "::", 128, "::1"); + + test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, NULL); + test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00", 120, NULL); +} + +static void test_in_addr_prefix_nth_one(unsigned f, const char *before, unsigned pl, uint64_t nth, const char *after) { + union in_addr_union ubefore, uafter, t; + + assert_se(in_addr_from_string(f, before, &ubefore) >= 0); + + t = ubefore; + assert_se((in_addr_prefix_nth(f, &t, pl, nth) > 0) == !!after); + + if (after) { + assert_se(in_addr_from_string(f, after, &uafter) >= 0); + assert_se(in_addr_equal(f, &t, &uafter) > 0); + } +} + +static void test_in_addr_prefix_nth(void) { + log_info("/* %s */", __func__); + + test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 0, "192.168.0.0"); + test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 1, "192.168.1.0"); + test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 4, "192.168.4.0"); + test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 25, 1, "192.168.0.128"); + test_in_addr_prefix_nth_one(AF_INET, "192.168.255.0", 25, 1, "192.168.255.128"); + test_in_addr_prefix_nth_one(AF_INET, "192.168.255.0", 24, 0, "192.168.255.0"); + test_in_addr_prefix_nth_one(AF_INET, "255.255.255.255", 32, 1, NULL); + test_in_addr_prefix_nth_one(AF_INET, "255.255.255.255", 0, 1, NULL); + + test_in_addr_prefix_nth_one(AF_INET6, "4400::", 8, 1, "4500::"); + test_in_addr_prefix_nth_one(AF_INET6, "4400::", 7, 1, "4600::"); + test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 1, "4400:0:0:1::"); + test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 2, "4400:0:0:2::"); + test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 0xbad, "4400:0:0:0bad::"); + test_in_addr_prefix_nth_one(AF_INET6, "4400:0:0:ffff::", 64, 1, "4400:0:1::"); + test_in_addr_prefix_nth_one(AF_INET6, "4400::", 56, ((uint64_t)1<<48) -1, "44ff:ffff:ffff:ff00::"); + test_in_addr_prefix_nth_one(AF_INET6, "0000::", 8, 255, "ff00::"); + test_in_addr_prefix_nth_one(AF_INET6, "0000::", 8, 256, NULL); + test_in_addr_prefix_nth_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, 1, NULL); + test_in_addr_prefix_nth_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, 1, NULL); +} + +static void test_in_addr_to_string_one(int f, const char *addr) { + union in_addr_union ua; + _cleanup_free_ char *r = NULL; + + assert_se(in_addr_from_string(f, addr, &ua) >= 0); + assert_se(in_addr_to_string(f, &ua, &r) >= 0); + printf("test_in_addr_to_string_one: %s == %s\n", addr, r); + assert_se(streq(addr, r)); +} + +static void test_in_addr_to_string(void) { + log_info("/* %s */", __func__); + + test_in_addr_to_string_one(AF_INET, "192.168.0.1"); + test_in_addr_to_string_one(AF_INET, "10.11.12.13"); + test_in_addr_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); + test_in_addr_to_string_one(AF_INET6, "::1"); + test_in_addr_to_string_one(AF_INET6, "fe80::"); +} + int main(int argc, char *argv[]) { test_in_addr_prefix_from_string(); test_in_addr_random_prefix(); test_in_addr_prefix_to_string(); + test_in_addr_is_null(); + test_in_addr_prefix_intersect(); + test_in_addr_prefix_next(); + test_in_addr_prefix_nth(); + test_in_addr_to_string(); return 0; } diff --git a/src/test/test-socket-netlink.c b/src/test/test-socket-netlink.c index 4335d2eb6c..f33d0fe241 100644 --- a/src/test/test-socket-netlink.c +++ b/src/test/test-socket-netlink.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ #include "alloc-util.h" +#include "missing_network.h" #include "tests.h" #include "socket-netlink.h" #include "string-util.h" @@ -248,6 +249,108 @@ static void test_socket_addr_port_from_string_auto(void) { test_socket_addr_port_from_string_auto_one("[a:b:1]:8888", 53, -EINVAL, 0, NULL); } +static void test_in_addr_ifindex_to_string_one(int f, const char *a, int ifindex, const char *b) { + _cleanup_free_ char *r = NULL; + union in_addr_union ua, uuaa; + int ff, ifindex2; + + assert_se(in_addr_from_string(f, a, &ua) >= 0); + assert_se(in_addr_ifindex_to_string(f, &ua, ifindex, &r) >= 0); + printf("test_in_addr_ifindex_to_string_one: %s == %s\n", b, r); + assert_se(streq(b, r)); + + assert_se(in_addr_ifindex_from_string_auto(b, &ff, &uuaa, &ifindex2) >= 0); + assert_se(ff == f); + assert_se(in_addr_equal(f, &ua, &uuaa)); + assert_se(ifindex2 == ifindex || ifindex2 == 0); +} + +static void test_in_addr_ifindex_to_string(void) { + log_info("/* %s */", __func__); + + test_in_addr_ifindex_to_string_one(AF_INET, "192.168.0.1", 7, "192.168.0.1"); + test_in_addr_ifindex_to_string_one(AF_INET, "10.11.12.13", 9, "10.11.12.13"); + test_in_addr_ifindex_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 10, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); + test_in_addr_ifindex_to_string_one(AF_INET6, "::1", 11, "::1"); + test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 12, "fe80::%12"); + test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 0, "fe80::"); + test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::14", 12, "fe80::14%12"); + test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::15", -7, "fe80::15"); + test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::16", LOOPBACK_IFINDEX, "fe80::16%1"); +} + +static void test_in_addr_ifindex_from_string_auto(void) { + int family, ifindex; + union in_addr_union ua; + + log_info("/* %s */", __func__); + /* Most in_addr_ifindex_from_string_auto() invocations have already been tested above, but let's test some more */ + + assert_se(in_addr_ifindex_from_string_auto("fe80::17", &family, &ua, &ifindex) >= 0); + assert_se(family == AF_INET6); + assert_se(ifindex == 0); + + assert_se(in_addr_ifindex_from_string_auto("fe80::18%19", &family, &ua, &ifindex) >= 0); + assert_se(family == AF_INET6); + assert_se(ifindex == 19); + + assert_se(in_addr_ifindex_from_string_auto("fe80::18%lo", &family, &ua, &ifindex) >= 0); + assert_se(family == AF_INET6); + assert_se(ifindex == LOOPBACK_IFINDEX); + + assert_se(in_addr_ifindex_from_string_auto("fe80::19%thisinterfacecantexist", &family, &ua, &ifindex) == -ENODEV); +} + +static void test_in_addr_ifindex_name_from_string_auto_one(const char *a, const char *expected) { + int family, ifindex; + union in_addr_union ua; + _cleanup_free_ char *server_name = NULL; + + assert_se(in_addr_ifindex_name_from_string_auto(a, &family, &ua, &ifindex, &server_name) >= 0); + assert_se(streq_ptr(server_name, expected)); +} + +static void test_in_addr_ifindex_name_from_string_auto(void) { + log_info("/* %s */", __func__); + + test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1", NULL); + test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1#test.com", "test.com"); + test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19", NULL); + test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19#another.test.com", "another.test.com"); +} + +static void test_in_addr_port_ifindex_name_from_string_auto_one(const char *str, int family, uint16_t port, int ifindex, const char *server_name) { + _cleanup_free_ char *name = NULL, *x = NULL; + union in_addr_union a; + uint16_t p; + int f, i; + + assert_se(in_addr_port_ifindex_name_from_string_auto(str, &f, &a, &p, &i, &name) >= 0); + assert_se(family == f); + assert_se(port == p); + assert_se(ifindex == i); + assert_se(streq_ptr(server_name, name)); + assert_se(in_addr_port_ifindex_name_to_string(f, &a, p, i, name, &x) >= 0); + assert_se(streq(str, x)); +} + +static void test_in_addr_port_ifindex_name_from_string_auto(void) { + log_info("/* %s */", __func__); + + test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1", AF_INET, 0, 0, NULL); + test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1#test.com", AF_INET, 0, 0, "test.com"); + test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1:53", AF_INET, 53, 0, NULL); + test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1:53#example.com", AF_INET, 53, 0, "example.com"); + test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18", AF_INET6, 0, 0, NULL); + test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18#hoge.com", AF_INET6, 0, 0, "hoge.com"); + test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18%19", AF_INET6, 0, 19, NULL); + test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53", AF_INET6, 53, 0, NULL); + test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18%19#hoge.com", AF_INET6, 0, 19, "hoge.com"); + test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53#hoge.com", AF_INET6, 53, 0, "hoge.com"); + test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%19", AF_INET6, 53, 19, NULL); + test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%19#hoge.com", AF_INET6, 53, 19, "hoge.com"); +} + int main(int argc, char *argv[]) { test_setup_logging(LOG_DEBUG); @@ -259,5 +362,10 @@ int main(int argc, char *argv[]) { test_socket_address_is_netlink(); test_socket_addr_port_from_string_auto(); + test_in_addr_ifindex_to_string(); + test_in_addr_ifindex_from_string_auto(); + test_in_addr_ifindex_name_from_string_auto(); + test_in_addr_port_ifindex_name_from_string_auto(); + return 0; } diff --git a/src/test/test-socket-util.c b/src/test/test-socket-util.c index b007dd6276..0bc713cb53 100644 --- a/src/test/test-socket-util.c +++ b/src/test/test-socket-util.c @@ -15,9 +15,7 @@ #include "io-util.h" #include "log.h" #include "macro.h" -#include "missing_network.h" #include "process-util.h" -#include "socket-netlink.h" #include "socket-util.h" #include "string-util.h" #include "tests.h" @@ -84,256 +82,6 @@ static void test_socket_print_unix(void) { test_socket_print_unix_one("\0\a\b\n\255", 6, "@\\a\\b\\n\\255\\000"); } -static void test_in_addr_is_null(void) { - union in_addr_union i = {}; - - log_info("/* %s */", __func__); - - assert_se(in_addr_is_null(AF_INET, &i) == true); - assert_se(in_addr_is_null(AF_INET6, &i) == true); - - i.in.s_addr = 0x1000000; - assert_se(in_addr_is_null(AF_INET, &i) == false); - assert_se(in_addr_is_null(AF_INET6, &i) == false); - - assert_se(in_addr_is_null(-1, &i) == -EAFNOSUPPORT); -} - -static void test_in_addr_prefix_intersect_one(unsigned f, const char *a, unsigned apl, const char *b, unsigned bpl, int result) { - union in_addr_union ua, ub; - - assert_se(in_addr_from_string(f, a, &ua) >= 0); - assert_se(in_addr_from_string(f, b, &ub) >= 0); - - assert_se(in_addr_prefix_intersect(f, &ua, apl, &ub, bpl) == result); -} - -static void test_in_addr_prefix_intersect(void) { - log_info("/* %s */", __func__); - - test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 32, "255.255.255.254", 32, 0); - test_in_addr_prefix_intersect_one(AF_INET, "255.255.255.255", 0, "255.255.255.255", 32, 1); - test_in_addr_prefix_intersect_one(AF_INET, "0.0.0.0", 0, "47.11.8.15", 32, 1); - - test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.1", 24, 1); - test_in_addr_prefix_intersect_one(AF_INET, "2.2.2.2", 24, "1.1.1.1", 24, 0); - - test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 25, 1); - test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 24, "1.1.1.127", 26, 1); - test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.127", 25, 1); - test_in_addr_prefix_intersect_one(AF_INET, "1.1.1.1", 25, "1.1.1.255", 25, 0); - - test_in_addr_prefix_intersect_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe", 128, 0); - test_in_addr_prefix_intersect_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, 1); - test_in_addr_prefix_intersect_one(AF_INET6, "::", 0, "beef:beef:beef:beef:beef:beef:beef:beef", 128, 1); - - test_in_addr_prefix_intersect_one(AF_INET6, "1::2", 64, "1::2", 64, 1); - test_in_addr_prefix_intersect_one(AF_INET6, "2::2", 64, "1::2", 64, 0); - - test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 121, 1); - test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 120, "1::007f", 122, 1); - test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::007f", 121, 1); - test_in_addr_prefix_intersect_one(AF_INET6, "1::1", 121, "1::00ff", 121, 0); -} - -static void test_in_addr_prefix_next_one(unsigned f, const char *before, unsigned pl, const char *after) { - union in_addr_union ubefore, uafter, t; - - assert_se(in_addr_from_string(f, before, &ubefore) >= 0); - - t = ubefore; - assert_se((in_addr_prefix_next(f, &t, pl) > 0) == !!after); - - if (after) { - assert_se(in_addr_from_string(f, after, &uafter) >= 0); - assert_se(in_addr_equal(f, &t, &uafter) > 0); - } -} - -static void test_in_addr_prefix_next(void) { - log_info("/* %s */", __func__); - - test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 24, "192.168.1.0"); - test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 16, "192.169.0.0"); - test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 20, "192.168.16.0"); - - test_in_addr_prefix_next_one(AF_INET, "0.0.0.0", 32, "0.0.0.1"); - test_in_addr_prefix_next_one(AF_INET, "255.255.255.255", 32, NULL); - test_in_addr_prefix_next_one(AF_INET, "255.255.255.0", 24, NULL); - - test_in_addr_prefix_next_one(AF_INET6, "4400::", 128, "4400::0001"); - test_in_addr_prefix_next_one(AF_INET6, "4400::", 120, "4400::0100"); - test_in_addr_prefix_next_one(AF_INET6, "4400::", 127, "4400::0002"); - test_in_addr_prefix_next_one(AF_INET6, "4400::", 8, "4500::"); - test_in_addr_prefix_next_one(AF_INET6, "4400::", 7, "4600::"); - - test_in_addr_prefix_next_one(AF_INET6, "::", 128, "::1"); - - test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, NULL); - test_in_addr_prefix_next_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00", 120, NULL); -} - -static void test_in_addr_prefix_nth_one(unsigned f, const char *before, unsigned pl, uint64_t nth, const char *after) { - union in_addr_union ubefore, uafter, t; - - assert_se(in_addr_from_string(f, before, &ubefore) >= 0); - - t = ubefore; - assert_se((in_addr_prefix_nth(f, &t, pl, nth) > 0) == !!after); - - if (after) { - assert_se(in_addr_from_string(f, after, &uafter) >= 0); - assert_se(in_addr_equal(f, &t, &uafter) > 0); - } -} - -static void test_in_addr_prefix_nth(void) { - log_info("/* %s */", __func__); - - test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 0, "192.168.0.0"); - test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 1, "192.168.1.0"); - test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 4, "192.168.4.0"); - test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 25, 1, "192.168.0.128"); - test_in_addr_prefix_nth_one(AF_INET, "192.168.255.0", 25, 1, "192.168.255.128"); - test_in_addr_prefix_nth_one(AF_INET, "192.168.255.0", 24, 0, "192.168.255.0"); - test_in_addr_prefix_nth_one(AF_INET, "255.255.255.255", 32, 1, NULL); - test_in_addr_prefix_nth_one(AF_INET, "255.255.255.255", 0, 1, NULL); - - test_in_addr_prefix_nth_one(AF_INET6, "4400::", 8, 1, "4500::"); - test_in_addr_prefix_nth_one(AF_INET6, "4400::", 7, 1, "4600::"); - test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 1, "4400:0:0:1::"); - test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 2, "4400:0:0:2::"); - test_in_addr_prefix_nth_one(AF_INET6, "4400::", 64, 0xbad, "4400:0:0:0bad::"); - test_in_addr_prefix_nth_one(AF_INET6, "4400:0:0:ffff::", 64, 1, "4400:0:1::"); - test_in_addr_prefix_nth_one(AF_INET6, "4400::", 56, ((uint64_t)1<<48) -1, "44ff:ffff:ffff:ff00::"); - test_in_addr_prefix_nth_one(AF_INET6, "0000::", 8, 255, "ff00::"); - test_in_addr_prefix_nth_one(AF_INET6, "0000::", 8, 256, NULL); - test_in_addr_prefix_nth_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, 1, NULL); - test_in_addr_prefix_nth_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, 1, NULL); -} - -static void test_in_addr_to_string_one(int f, const char *addr) { - union in_addr_union ua; - _cleanup_free_ char *r = NULL; - - assert_se(in_addr_from_string(f, addr, &ua) >= 0); - assert_se(in_addr_to_string(f, &ua, &r) >= 0); - printf("test_in_addr_to_string_one: %s == %s\n", addr, r); - assert_se(streq(addr, r)); -} - -static void test_in_addr_to_string(void) { - log_info("/* %s */", __func__); - - test_in_addr_to_string_one(AF_INET, "192.168.0.1"); - test_in_addr_to_string_one(AF_INET, "10.11.12.13"); - test_in_addr_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); - test_in_addr_to_string_one(AF_INET6, "::1"); - test_in_addr_to_string_one(AF_INET6, "fe80::"); -} - -static void test_in_addr_ifindex_to_string_one(int f, const char *a, int ifindex, const char *b) { - _cleanup_free_ char *r = NULL; - union in_addr_union ua, uuaa; - int ff, ifindex2; - - assert_se(in_addr_from_string(f, a, &ua) >= 0); - assert_se(in_addr_ifindex_to_string(f, &ua, ifindex, &r) >= 0); - printf("test_in_addr_ifindex_to_string_one: %s == %s\n", b, r); - assert_se(streq(b, r)); - - assert_se(in_addr_ifindex_from_string_auto(b, &ff, &uuaa, &ifindex2) >= 0); - assert_se(ff == f); - assert_se(in_addr_equal(f, &ua, &uuaa)); - assert_se(ifindex2 == ifindex || ifindex2 == 0); -} - -static void test_in_addr_ifindex_to_string(void) { - log_info("/* %s */", __func__); - - test_in_addr_ifindex_to_string_one(AF_INET, "192.168.0.1", 7, "192.168.0.1"); - test_in_addr_ifindex_to_string_one(AF_INET, "10.11.12.13", 9, "10.11.12.13"); - test_in_addr_ifindex_to_string_one(AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 10, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); - test_in_addr_ifindex_to_string_one(AF_INET6, "::1", 11, "::1"); - test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 12, "fe80::%12"); - test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::", 0, "fe80::"); - test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::14", 12, "fe80::14%12"); - test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::15", -7, "fe80::15"); - test_in_addr_ifindex_to_string_one(AF_INET6, "fe80::16", LOOPBACK_IFINDEX, "fe80::16%1"); -} - -static void test_in_addr_ifindex_from_string_auto(void) { - int family, ifindex; - union in_addr_union ua; - - log_info("/* %s */", __func__); - /* Most in_addr_ifindex_from_string_auto() invocations have already been tested above, but let's test some more */ - - assert_se(in_addr_ifindex_from_string_auto("fe80::17", &family, &ua, &ifindex) >= 0); - assert_se(family == AF_INET6); - assert_se(ifindex == 0); - - assert_se(in_addr_ifindex_from_string_auto("fe80::18%19", &family, &ua, &ifindex) >= 0); - assert_se(family == AF_INET6); - assert_se(ifindex == 19); - - assert_se(in_addr_ifindex_from_string_auto("fe80::18%lo", &family, &ua, &ifindex) >= 0); - assert_se(family == AF_INET6); - assert_se(ifindex == LOOPBACK_IFINDEX); - - assert_se(in_addr_ifindex_from_string_auto("fe80::19%thisinterfacecantexist", &family, &ua, &ifindex) == -ENODEV); -} - -static void test_in_addr_ifindex_name_from_string_auto_one(const char *a, const char *expected) { - int family, ifindex; - union in_addr_union ua; - _cleanup_free_ char *server_name = NULL; - - assert_se(in_addr_ifindex_name_from_string_auto(a, &family, &ua, &ifindex, &server_name) >= 0); - assert_se(streq_ptr(server_name, expected)); -} - -static void test_in_addr_ifindex_name_from_string_auto(void) { - log_info("/* %s */", __func__); - - test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1", NULL); - test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1#test.com", "test.com"); - test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19", NULL); - test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19#another.test.com", "another.test.com"); -} - -static void test_in_addr_port_ifindex_name_from_string_auto_one(const char *str, int family, uint16_t port, int ifindex, const char *server_name) { - _cleanup_free_ char *name = NULL, *x = NULL; - union in_addr_union a; - uint16_t p; - int f, i; - - assert_se(in_addr_port_ifindex_name_from_string_auto(str, &f, &a, &p, &i, &name) >= 0); - assert_se(family == f); - assert_se(port == p); - assert_se(ifindex == i); - assert_se(streq_ptr(server_name, name)); - assert_se(in_addr_port_ifindex_name_to_string(f, &a, p, i, name, &x) >= 0); - assert_se(streq(str, x)); -} - -static void test_in_addr_port_ifindex_name_from_string_auto(void) { - log_info("/* %s */", __func__); - - test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1", AF_INET, 0, 0, NULL); - test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1#test.com", AF_INET, 0, 0, "test.com"); - test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1:53", AF_INET, 53, 0, NULL); - test_in_addr_port_ifindex_name_from_string_auto_one("192.168.0.1:53#example.com", AF_INET, 53, 0, "example.com"); - test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18", AF_INET6, 0, 0, NULL); - test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18#hoge.com", AF_INET6, 0, 0, "hoge.com"); - test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18%19", AF_INET6, 0, 19, NULL); - test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53", AF_INET6, 53, 0, NULL); - test_in_addr_port_ifindex_name_from_string_auto_one("fe80::18%19#hoge.com", AF_INET6, 0, 19, "hoge.com"); - test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53#hoge.com", AF_INET6, 53, 0, "hoge.com"); - test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%19", AF_INET6, 53, 19, NULL); - test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%19#hoge.com", AF_INET6, 53, 19, "hoge.com"); -} - static void test_sockaddr_equal(void) { union sockaddr_union a = { .in.sin_family = AF_INET, @@ -759,16 +507,6 @@ int main(int argc, char *argv[]) { test_socket_print_unix(); - test_in_addr_is_null(); - test_in_addr_prefix_intersect(); - test_in_addr_prefix_next(); - test_in_addr_prefix_nth(); - test_in_addr_to_string(); - test_in_addr_ifindex_to_string(); - test_in_addr_ifindex_from_string_auto(); - test_in_addr_ifindex_name_from_string_auto(); - test_in_addr_port_ifindex_name_from_string_auto(); - test_sockaddr_equal(); test_sockaddr_un_len(); From fc6021554be7320e010ac6cf2d739f6c7bec8262 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 15:42:09 +0900 Subject: [PATCH 11/23] test: add tests for in_addr_port_from_string_auto() --- src/test/test-socket-netlink.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/test/test-socket-netlink.c b/src/test/test-socket-netlink.c index f33d0fe241..faebbfd138 100644 --- a/src/test/test-socket-netlink.c +++ b/src/test/test-socket-netlink.c @@ -351,6 +351,36 @@ static void test_in_addr_port_ifindex_name_from_string_auto(void) { test_in_addr_port_ifindex_name_from_string_auto_one("[fe80::18]:53%19#hoge.com", AF_INET6, 53, 19, "hoge.com"); } +static void test_in_addr_port_from_string_auto_one(const char *str, int family, const char *address_string, uint16_t port) { + union in_addr_union a, b; + uint16_t p; + int f; + + assert_se(in_addr_port_from_string_auto(str, &f, &a, &p) >= 0); + assert_se(family == f); + assert_se(port == p); + assert_se(in_addr_from_string(family, address_string, &b) >= 0); + assert_se(in_addr_equal(family, &a, &b) == 1); +} + +static void test_in_addr_port_from_string_auto(void) { + log_info("/* %s */", __func__); + + assert_se(in_addr_port_from_string_auto("192.168.0.1#test.com", NULL, NULL, NULL) < 0); + assert_se(in_addr_port_from_string_auto("192.168.0.1:53#example.com", NULL, NULL, NULL) < 0); + assert_se(in_addr_port_from_string_auto("fe80::18#hoge.com", NULL, NULL, NULL) < 0); + assert_se(in_addr_port_from_string_auto("fe80::18%19", NULL, NULL, NULL) < 0); + assert_se(in_addr_port_from_string_auto("fe80::18%19#hoge.com", NULL, NULL, NULL) < 0); + assert_se(in_addr_port_from_string_auto("[fe80::18]:53#hoge.com", NULL, NULL, NULL) < 0); + assert_se(in_addr_port_from_string_auto("[fe80::18]:53%19", NULL, NULL, NULL) < 0); + assert_se(in_addr_port_from_string_auto("[fe80::18]:53%19#hoge.com", NULL, NULL, NULL) < 0); + + test_in_addr_port_from_string_auto_one("192.168.0.1", AF_INET, "192.168.0.1", 0); + test_in_addr_port_from_string_auto_one("192.168.0.1:53", AF_INET, "192.168.0.1", 53); + test_in_addr_port_from_string_auto_one("fe80::18", AF_INET6, "fe80::18", 0); + test_in_addr_port_from_string_auto_one("[fe80::18]:53", AF_INET6, "fe80::18", 53); +} + int main(int argc, char *argv[]) { test_setup_logging(LOG_DEBUG); @@ -366,6 +396,7 @@ int main(int argc, char *argv[]) { test_in_addr_ifindex_from_string_auto(); test_in_addr_ifindex_name_from_string_auto(); test_in_addr_port_ifindex_name_from_string_auto(); + test_in_addr_port_from_string_auto(); return 0; } From 4e0a46f65ea0188b9d361b59a4eff11d43f99444 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 19:37:50 +0900 Subject: [PATCH 12/23] util: introduce SOCKADDR_LEN() macro --- src/basic/socket-util.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 9e02e39887..5610a99e53 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -205,6 +205,35 @@ struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t leng strnlen(_sa->sun_path, sizeof(_sa->sun_path))+1); \ }) +#define SOCKADDR_LEN(sa) \ + ({ \ + const union sockaddr_union *__sa = &(sa); \ + size_t _len; \ + switch(__sa->sa.sa_family) { \ + case AF_INET: \ + _len = sizeof(struct sockaddr_in); \ + break; \ + case AF_INET6: \ + _len = sizeof(struct sockaddr_in6); \ + break; \ + case AF_UNIX: \ + _len = SOCKADDR_UN_LEN(__sa->un); \ + break; \ + case AF_PACKET: \ + _len = SOCKADDR_LL_LEN(__sa->ll); \ + break; \ + case AF_NETLINK: \ + _len = sizeof(struct sockaddr_nl); \ + break; \ + case AF_VSOCK: \ + _len = sizeof(struct sockaddr_vm); \ + break; \ + default: \ + assert_not_reached("invalid socket family"); \ + } \ + _len; \ + }) + int socket_ioctl_fd(void); int sockaddr_un_set_path(struct sockaddr_un *ret, const char *path); From b4b7ea1b3297d66b1f1c704675b24e9d8b55dbb1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 14:54:03 +0900 Subject: [PATCH 13/23] resolve: fix indentation --- src/resolve/resolved-dns-stub.c | 48 ++++++++++++++++----------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index 2a8637d378..02c60b91d4 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -499,20 +499,20 @@ static int manager_dns_stub_udp_fd_extra(Manager *m, DNSStubListenerExtra *l) { 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)); +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); + assert(r < 0); - return log_warning_errno(r, "Failed to listen on UDP socket %s, ignoring: %m", strnull(pretty)); + 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) { @@ -655,20 +655,20 @@ static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) { 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)); +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); + assert(r < 0); - return log_warning_errno(r, "Failed to listen on TCP socket %s, ignoring: %m", strnull(pretty)); + return log_warning_errno(r, "Failed to listen on TCP socket %s, ignoring: %m", strnull(pretty)); } int manager_dns_stub_start(Manager *m) { From ca8b62b522e0c5944143c0d90428fa88ea0cb434 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 15:01:21 +0900 Subject: [PATCH 14/23] resolve: use in_addr_union to store addresses for extra dns stub listeners --- src/resolve/resolved-conf.c | 22 +++++----------- src/resolve/resolved-dns-stub.c | 46 +++++++++++++++++++++++++++------ src/resolve/resolved-manager.h | 6 ++++- 3 files changed, 50 insertions(+), 24 deletions(-) diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c index 1c934b34cf..57154f8633 100644 --- a/src/resolve/resolved-conf.c +++ b/src/resolve/resolved-conf.c @@ -30,20 +30,15 @@ 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); 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); + siphash24_compress(&a->family, sizeof(a->family), state); + siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(a->family), state); + siphash24_compress(&a->port, sizeof(a->port), state); } static int dns_stub_listener_extra_compare_func(const DNSStubListenerExtra *a, const DNSStubListenerExtra *b) { - unsigned p, q; int r; assert(a); @@ -53,18 +48,15 @@ static int dns_stub_listener_extra_compare_func(const DNSStubListenerExtra *a, c if (r != 0) return r; - r = CMP(socket_address_family(&a->address), socket_address_family(&b->address)); + r = CMP(a->family, b->family); if (r != 0) return r; - r = memcmp(&a->address, &b->address, FAMILY_ADDRESS_SIZE(socket_address_family(&a->address))); + r = memcmp(&a->address, &b->address, FAMILY_ADDRESS_SIZE(a->family)); 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); + return CMP(a->port, b->port); } DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( @@ -476,7 +468,7 @@ int config_parse_dns_stub_listener_extra( } } - r = socket_addr_port_from_string_auto(p, 53, &stub->address); + r = in_addr_port_from_string_auto(p, &stub->family, &stub->address, &stub->port); 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 02c60b91d4..fc169ee0ef 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -1,5 +1,7 @@ /* SPDX-License-Identifier: LGPL-2.1+ */ +#include + #include "errno-util.h" #include "fd-util.h" #include "missing_network.h" @@ -460,12 +462,26 @@ static int manager_dns_stub_udp_fd(Manager *m) { 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; if (l->udp_fd >= 0) return 0; - fd = socket(socket_address_family(&l->address), SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 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; @@ -479,7 +495,7 @@ static int manager_dns_stub_udp_fd_extra(Manager *m, DNSStubListenerExtra *l) { if (r < 0) goto fail; - if (bind(fd, &l->address.sockaddr.sa, l->address.size) < 0) { + if (bind(fd, &sa.sa, SOCKADDR_LEN(sa)) < 0) { r = -errno; goto fail; } @@ -491,7 +507,7 @@ static int manager_dns_stub_udp_fd_extra(Manager *m, DNSStubListenerExtra *l) { (void) sd_event_source_set_description(l->udp_event_source, "dns-stub-udp-extra"); if (DEBUG_LOGGING) { - (void) sockaddr_pretty(&l->address.sockaddr.sa, FAMILY_ADDRESS_SIZE(l->address.sockaddr.sa.sa_family), true, true, &pretty); + (void) in_addr_port_to_string(l->family, &l->address, l->port, &pretty); log_debug("Listening on UDP socket %s.", strnull(pretty)); } @@ -500,7 +516,7 @@ static int manager_dns_stub_udp_fd_extra(Manager *m, DNSStubListenerExtra *l) { return 0; fail: - (void) sockaddr_pretty(&l->address.sockaddr.sa, FAMILY_ADDRESS_SIZE(l->address.sockaddr.sa.sa_family), true, true, &pretty); + (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.\n" @@ -607,12 +623,26 @@ static int manager_dns_stub_tcp_fd(Manager *m) { static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) { _cleanup_free_ char *pretty = NULL; _cleanup_close_ int fd = -1; + union sockaddr_union sa; int r; if (l->tcp_fd >= 0) return 0; - fd = socket(socket_address_family(&l->address), SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 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_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (fd < 0) { r = -errno; goto fail; @@ -630,7 +660,7 @@ static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) { if (r < 0) goto fail; - if (bind(fd, &l->address.sockaddr.sa, l->address.size) < 0) { + if (bind(fd, &sa.sa, SOCKADDR_LEN(sa)) < 0) { r = -errno; goto fail; } @@ -647,7 +677,7 @@ static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) { (void) sd_event_source_set_description(l->tcp_event_source, "dns-stub-tcp-extra"); if (DEBUG_LOGGING) { - (void) sockaddr_pretty(&l->address.sockaddr.sa, FAMILY_ADDRESS_SIZE(l->address.sockaddr.sa.sa_family), true, true, &pretty); + (void) in_addr_port_to_string(l->family, &l->address, l->port, &pretty); log_debug("Listening on TCP socket %s.", strnull(pretty)); } @@ -656,7 +686,7 @@ static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) { return 0; fail: - (void) sockaddr_pretty(&l->address.sockaddr.sa, FAMILY_ADDRESS_SIZE(l->address.sockaddr.sa.sa_family), true, true, &pretty); + (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.\n" diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h index 2c6adfbcbd..9eee30761c 100644 --- a/src/resolve/resolved-manager.h +++ b/src/resolve/resolved-manager.h @@ -36,7 +36,11 @@ typedef struct DNSStubListenerExtra { int tcp_fd; DnsStubListenerMode mode; - SocketAddress address; + + int family; + union in_addr_union address; + uint16_t port; + sd_event_source *udp_event_source; sd_event_source *tcp_event_source; } DNSStubListenerExtra; From fc7676e31397002a56e96387d031f7691da19ac4 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 15:27:53 +0900 Subject: [PATCH 15/23] util: drop unused socket_addr_port_from_string_auto() --- src/shared/socket-netlink.c | 27 ------------------------- src/shared/socket-netlink.h | 1 - src/test/test-socket-netlink.c | 36 ---------------------------------- 3 files changed, 64 deletions(-) diff --git a/src/shared/socket-netlink.c b/src/shared/socket-netlink.c index dc1b27f165..6c121a4c9a 100644 --- a/src/shared/socket-netlink.c +++ b/src/shared/socket-netlink.c @@ -235,33 +235,6 @@ int socket_address_parse_and_warn(SocketAddress *a, const char *s) { 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) { _cleanup_free_ char *word = NULL; unsigned group = 0; diff --git a/src/shared/socket-netlink.h b/src/shared/socket-netlink.h index 7fa831a880..d019bb31c6 100644 --- a/src/shared/socket-netlink.h +++ b/src/shared/socket-netlink.h @@ -16,7 +16,6 @@ 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_and_warn(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_netlink(const SocketAddress *a, const char *s); diff --git a/src/test/test-socket-netlink.c b/src/test/test-socket-netlink.c index faebbfd138..f86f123782 100644 --- a/src/test/test-socket-netlink.c +++ b/src/test/test-socket-netlink.c @@ -214,41 +214,6 @@ static void test_socket_address_is_netlink(void) { 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); -} - static void test_in_addr_ifindex_to_string_one(int f, const char *a, int ifindex, const char *b) { _cleanup_free_ char *r = NULL; union in_addr_union ua, uuaa; @@ -390,7 +355,6 @@ int main(int argc, char *argv[]) { test_socket_address_get_path(); test_socket_address_is(); test_socket_address_is_netlink(); - test_socket_addr_port_from_string_auto(); test_in_addr_ifindex_to_string(); test_in_addr_ifindex_from_string_auto(); From 180c22328bd6c4b30ba147de7439cfaadedb63f1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 23:53:18 +0900 Subject: [PATCH 16/23] missing: add IPV6_FREEBIND --- src/basic/missing_socket.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/basic/missing_socket.h b/src/basic/missing_socket.h index 8c3fec1e35..c4f33449a3 100644 --- a/src/basic/missing_socket.h +++ b/src/basic/missing_socket.h @@ -63,6 +63,10 @@ struct sockaddr_vm { #define IP_TRANSPARENT 19 #endif +#ifndef IPV6_FREEBIND +#define IPV6_FREEBIND 78 +#endif + /* linux/sockios.h */ #ifndef SIOCGSKNS #define SIOCGSKNS 0x894C From d40f00d79819616ad5dc1693ae0c899ede415e6f Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 15:10:48 +0900 Subject: [PATCH 17/23] resolve: do not set IP_TTL for extra DNS stub listeners --- src/resolve/resolved-dns-stub.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index fc169ee0ef..e611624458 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -652,9 +652,8 @@ static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) { if (r < 0) goto fail; - r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, 1); - 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. */ r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true); if (r < 0) From af8b1384220f1d54734762d59d4422556d6d1af0 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 15:22:36 +0900 Subject: [PATCH 18/23] resolve: do not set IPv4 specific options on IPv6 socket --- src/resolve/resolved-dns-stub.c | 47 ++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index e611624458..88a6a0616a 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -5,6 +5,7 @@ #include "errno-util.h" #include "fd-util.h" #include "missing_network.h" +#include "missing_socket.h" #include "resolved-dns-stub.h" #include "socket-netlink.h" #include "socket-util.h" @@ -406,20 +407,35 @@ static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void return 0; } -static int set_dns_stub_common_socket_options(int fd) { +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; - r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true); - if (r < 0) - return r; + if (family == AF_INET) { + r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true); + if (r < 0) + return r; - return setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, true); + 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) { @@ -438,7 +454,7 @@ static int manager_dns_stub_udp_fd(Manager *m) { if (fd < 0) return -errno; - r = set_dns_stub_common_socket_options(fd); + r = set_dns_stub_common_socket_options(fd, AF_INET); if (r < 0) return r; @@ -487,11 +503,13 @@ static int manager_dns_stub_udp_fd_extra(Manager *m, DNSStubListenerExtra *l) { goto fail; } - r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true); - if (r < 0) - 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); + r = set_dns_stub_common_socket_options(fd, l->family); if (r < 0) goto fail; @@ -592,7 +610,7 @@ static int manager_dns_stub_tcp_fd(Manager *m) { if (fd < 0) return -errno; - r = set_dns_stub_common_socket_options(fd); + r = set_dns_stub_common_socket_options(fd, AF_INET); if (r < 0) return r; @@ -648,14 +666,17 @@ static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) { goto fail; } - r = set_dns_stub_common_socket_options(fd); + r = set_dns_stub_common_socket_options(fd, l->family); 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. */ - r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true); + if (l->family == AF_INET) + r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true); + else + r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_FREEBIND, true); if (r < 0) goto fail; From 1c17bcb3ad2b164917f3c0f72a3f067a81b72c13 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 16:26:17 +0900 Subject: [PATCH 19/23] resolve: adjust error messages --- src/resolve/resolved-dns-stub.c | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index 88a6a0616a..a8011d16f3 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -534,19 +534,11 @@ static int manager_dns_stub_udp_fd_extra(Manager *m, DNSStubListenerExtra *l) { return 0; 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.\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)); + 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) { @@ -706,19 +698,11 @@ static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) { return 0; 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.\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)); + 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)); } int manager_dns_stub_start(Manager *m) { From bf22f231cf1788fde3e554b061c081e15ffdaa05 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 16:41:13 +0900 Subject: [PATCH 20/23] resolve: introduce dns_stub_listener_extra_free() and set it as a key destructor --- src/resolve/resolved-conf.c | 4 ++-- src/resolve/resolved-dns-stub.c | 28 +++++++++++++--------------- src/resolve/resolved-dns-stub.h | 4 ++-- src/resolve/resolved-manager.c | 1 - 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c index 57154f8633..639fd34178 100644 --- a/src/resolve/resolved-conf.c +++ b/src/resolve/resolved-conf.c @@ -64,7 +64,7 @@ DEFINE_PRIVATE_HASH_OPS_WITH_KEY_DESTRUCTOR( DNSStubListenerExtra, dns_stub_listener_extra_hash_func, dns_stub_listener_extra_compare_func, - free); + dns_stub_listener_extra_free); static int manager_add_dns_server_by_string(Manager *m, DnsServerType type, const char *word) { _cleanup_free_ char *server_name = NULL; @@ -451,7 +451,7 @@ int config_parse_dns_stub_listener_extra( return 0; } - r = dns_stub_extra_new(&stub); + r = dns_stub_listener_extra_new(&stub); if (r < 0) return log_oom(); diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index a8011d16f3..74e4f261c3 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -17,7 +17,7 @@ static int manager_dns_stub_udp_fd(Manager *m); static int manager_dns_stub_tcp_fd(Manager *m); -int dns_stub_extra_new(DNSStubListenerExtra **ret) { +int dns_stub_listener_extra_new(DNSStubListenerExtra **ret) { DNSStubListenerExtra *l; l = new(DNSStubListenerExtra, 1); @@ -34,6 +34,18 @@ int dns_stub_extra_new(DNSStubListenerExtra **ret) { return 0; } +DNSStubListenerExtra *dns_stub_listener_extra_free(DNSStubListenerExtra *p) { + if (!p) + return NULL; + + p->udp_event_source = sd_event_source_unref(p->udp_event_source); + p->tcp_event_source = sd_event_source_unref(p->tcp_event_source); + p->udp_fd = safe_close(p->udp_fd); + p->tcp_fd = safe_close(p->tcp_fd); + + return mfree(p); +} + static int dns_stub_make_reply_packet( DnsPacket **p, size_t max_size, @@ -767,17 +779,3 @@ void manager_dns_stub_stop(Manager *m) { m->dns_stub_udp_fd = safe_close(m->dns_stub_udp_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->udp_event_source = sd_event_source_unref(l->udp_event_source); - l->tcp_event_source = sd_event_source_unref(l->tcp_event_source); - l->udp_fd = safe_close(l->udp_fd); - l->tcp_fd = safe_close(l->tcp_fd); - } -} diff --git a/src/resolve/resolved-dns-stub.h b/src/resolve/resolved-dns-stub.h index e589df3831..96d65af152 100644 --- a/src/resolve/resolved-dns-stub.h +++ b/src/resolve/resolved-dns-stub.h @@ -3,8 +3,8 @@ #include "resolved-manager.h" -int dns_stub_extra_new(DNSStubListenerExtra **ret); +int dns_stub_listener_extra_new(DNSStubListenerExtra **ret); +DNSStubListenerExtra *dns_stub_listener_extra_free(DNSStubListenerExtra *p); void manager_dns_stub_stop(Manager *m); -void manager_dns_stub_stop_extra(Manager *m); int manager_dns_stub_start(Manager *m); diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index ea26fb0795..50d8b01d9a 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -713,7 +713,6 @@ Manager *manager_free(Manager *m) { manager_dns_stub_stop(m); manager_varlink_done(m); - manager_dns_stub_stop_extra(m); ordered_set_free(m->dns_extra_stub_listeners); bus_verify_polkit_async_registry_free(m->polkit_registry); From 7216a3b5dcde362451a00f63d9e1b7780f19e2ed Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 20:52:46 +0900 Subject: [PATCH 21/23] resolve: use sd_event_source_set_io_fd_own() for stub listners --- src/resolve/resolved-dns-stub.c | 54 +++++++++++++++++---------------- src/resolve/resolved-manager.c | 2 -- src/resolve/resolved-manager.h | 8 +---- 3 files changed, 29 insertions(+), 35 deletions(-) diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index 74e4f261c3..9ef0b0a960 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -20,15 +20,10 @@ static int manager_dns_stub_tcp_fd(Manager *m); int dns_stub_listener_extra_new(DNSStubListenerExtra **ret) { DNSStubListenerExtra *l; - l = new(DNSStubListenerExtra, 1); + l = new0(DNSStubListenerExtra, 1); if (!l) return -ENOMEM; - *l = (DNSStubListenerExtra) { - .udp_fd = -1, - .tcp_fd = -1, - }; - *ret = TAKE_PTR(l); return 0; @@ -40,8 +35,6 @@ DNSStubListenerExtra *dns_stub_listener_extra_free(DNSStubListenerExtra *p) { p->udp_event_source = sd_event_source_unref(p->udp_event_source); p->tcp_event_source = sd_event_source_unref(p->tcp_event_source); - p->udp_fd = safe_close(p->udp_fd); - p->tcp_fd = safe_close(p->tcp_fd); return mfree(p); } @@ -459,8 +452,8 @@ static int manager_dns_stub_udp_fd(Manager *m) { _cleanup_close_ int fd = -1; int r; - if (m->dns_stub_udp_fd >= 0) - return m->dns_stub_udp_fd; + 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) @@ -482,9 +475,13 @@ static int manager_dns_stub_udp_fd(Manager *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 m->dns_stub_udp_fd = TAKE_FD(fd); + return TAKE_FD(fd); } static int manager_dns_stub_udp_fd_extra(Manager *m, DNSStubListenerExtra *l) { @@ -493,7 +490,7 @@ static int manager_dns_stub_udp_fd_extra(Manager *m, DNSStubListenerExtra *l) { union sockaddr_union sa; int r; - if (l->udp_fd >= 0) + if (l->udp_event_source) return 0; if (l->family == AF_INET) @@ -534,6 +531,10 @@ static int manager_dns_stub_udp_fd_extra(Manager *m, DNSStubListenerExtra *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) { @@ -541,9 +542,7 @@ static int manager_dns_stub_udp_fd_extra(Manager *m, DNSStubListenerExtra *l) { log_debug("Listening on UDP socket %s.", strnull(pretty)); } - l->udp_fd = TAKE_FD(fd); - - return 0; + return TAKE_FD(fd); fail: assert(r < 0); @@ -607,8 +606,8 @@ static int manager_dns_stub_tcp_fd(Manager *m) { _cleanup_close_ int fd = -1; int r; - if (m->dns_stub_tcp_fd >= 0) - return m->dns_stub_tcp_fd; + if (m->dns_stub_tcp_event_source) + return sd_event_source_get_io_fd(m->dns_stub_tcp_event_source); fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); if (fd < 0) @@ -637,9 +636,13 @@ static int manager_dns_stub_tcp_fd(Manager *m) { if (r < 0) return r; + r = sd_event_source_set_io_fd_own(m->dns_stub_tcp_event_source, true); + if (r < 0) + return r; + (void) sd_event_source_set_description(m->dns_stub_tcp_event_source, "dns-stub-tcp"); - return m->dns_stub_tcp_fd = TAKE_FD(fd); + return TAKE_FD(fd); } static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) { @@ -648,8 +651,8 @@ static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) { union sockaddr_union sa; int r; - if (l->tcp_fd >= 0) - return 0; + if (l->tcp_event_source) + return sd_event_source_get_io_fd(l->tcp_event_source);; if (l->family == AF_INET) sa = (union sockaddr_union) { @@ -698,6 +701,10 @@ static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) { if (r < 0) goto fail; + r = sd_event_source_set_io_fd_own(l->tcp_event_source, true); + if (r < 0) + goto fail; + (void) sd_event_source_set_description(l->tcp_event_source, "dns-stub-tcp-extra"); if (DEBUG_LOGGING) { @@ -705,9 +712,7 @@ static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) { log_debug("Listening on TCP socket %s.", strnull(pretty)); } - l->tcp_fd = TAKE_FD(fd); - - return 0; + return TAKE_FD(fd); fail: assert(r < 0); @@ -775,7 +780,4 @@ void manager_dns_stub_stop(Manager *m) { m->dns_stub_udp_event_source = sd_event_source_unref(m->dns_stub_udp_event_source); m->dns_stub_tcp_event_source = sd_event_source_unref(m->dns_stub_tcp_event_source); - - m->dns_stub_udp_fd = safe_close(m->dns_stub_udp_fd); - m->dns_stub_tcp_fd = safe_close(m->dns_stub_tcp_fd); } diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 50d8b01d9a..faf1a82155 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -578,8 +578,6 @@ int manager_new(Manager **ret) { .llmnr_ipv6_tcp_fd = -1, .mdns_ipv4_fd = -1, .mdns_ipv6_fd = -1, - .dns_stub_udp_fd = -1, - .dns_stub_tcp_fd = -1, .hostname_fd = -1, .llmnr_support = DEFAULT_LLMNR_MODE, diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h index 9eee30761c..80665876b2 100644 --- a/src/resolve/resolved-manager.h +++ b/src/resolve/resolved-manager.h @@ -32,9 +32,6 @@ typedef struct EtcHosts { } EtcHosts; typedef struct DNSStubListenerExtra { - int udp_fd; - int tcp_fd; - DnsStubListenerMode mode; int family; @@ -147,12 +144,9 @@ struct Manager { dev_t etc_hosts_dev; bool read_etc_hosts; - /* Local DNS stub on 127.0.0.53:53 */ - int dns_stub_udp_fd; - int dns_stub_tcp_fd; - OrderedSet *dns_extra_stub_listeners; + /* Local DNS stub on 127.0.0.53:53 */ sd_event_source *dns_stub_udp_event_source; sd_event_source *dns_stub_tcp_event_source; From d1fb8cdae2565aabfb7d2e6a146ba41cd1ea451b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 21:30:37 +0900 Subject: [PATCH 22/23] resolve: do not check sender and destination for packet received by extra DNS stub listner --- src/resolve/resolved-dns-stub.c | 49 ++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index 9ef0b0a960..72e470533c 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -303,7 +303,7 @@ static int dns_stub_stream_complete(DnsStream *s, int error) { return 0; } -static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p) { +static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p, bool is_extra) { _cleanup_(dns_query_freep) DnsQuery *q = NULL; int r; @@ -311,8 +311,9 @@ static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p) { assert(p); assert(p->protocol == DNS_PROTOCOL_DNS); - if (in_addr_is_localhost(p->family, &p->sender) <= 0 || - in_addr_is_localhost(p->family, &p->destination) <= 0) { + if (!is_extra && + (in_addr_is_localhost(p->family, &p->sender) <= 0 || + in_addr_is_localhost(p->family, &p->destination) <= 0)) { log_error("Got packet on unexpected IP range, refusing."); dns_stub_send_failure(m, s, p, DNS_RCODE_SERVFAIL, false); return; @@ -393,9 +394,8 @@ static void dns_stub_process_query(Manager *m, DnsStream *s, DnsPacket *p) { TAKE_PTR(q); } -static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) { +static int on_dns_stub_packet_internal(sd_event_source *s, int fd, uint32_t revents, Manager *m, bool is_extra) { _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; - Manager *m = userdata; int r; r = manager_recv(m, fd, DNS_PROTOCOL_DNS, &p); @@ -405,13 +405,21 @@ static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void if (dns_packet_validate_query(p) > 0) { log_debug("Got DNS stub UDP query packet for id %u", DNS_PACKET_ID(p)); - dns_stub_process_query(m, NULL, p); + dns_stub_process_query(m, NULL, p, is_extra); } else log_debug("Invalid DNS stub UDP packet, ignoring."); return 0; } +static int on_dns_stub_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + return on_dns_stub_packet_internal(s, fd, revents, userdata, false); +} + +static int on_dns_stub_packet_extra(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + return on_dns_stub_packet_internal(s, fd, revents, userdata, true); +} + static int set_dns_stub_common_socket_options(int fd, int family) { int r; @@ -527,7 +535,7 @@ static int manager_dns_stub_udp_fd_extra(Manager *m, DNSStubListenerExtra *l) { goto fail; } - r = sd_event_add_io(m->event, &l->udp_event_source, fd, EPOLLIN, on_dns_stub_packet, m); + r = sd_event_add_io(m->event, &l->udp_event_source, fd, EPOLLIN, on_dns_stub_packet_extra, m); if (r < 0) goto fail; @@ -552,7 +560,7 @@ fail: return log_warning_errno(r, "Failed to listen on UDP socket %s: %m", strnull(pretty)); } -static int on_dns_stub_stream_packet(DnsStream *s) { +static int on_dns_stub_stream_packet_internal(DnsStream *s, bool is_extra) { _cleanup_(dns_packet_unrefp) DnsPacket *p = NULL; assert(s); @@ -563,16 +571,23 @@ static int on_dns_stub_stream_packet(DnsStream *s) { if (dns_packet_validate_query(p) > 0) { log_debug("Got DNS stub TCP query packet for id %u", DNS_PACKET_ID(p)); - dns_stub_process_query(s->manager, s, p); + dns_stub_process_query(s->manager, s, p, is_extra); } else log_debug("Invalid DNS stub TCP packet, ignoring."); return 0; } -static int on_dns_stub_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) { +static int on_dns_stub_stream_packet(DnsStream *s) { + return on_dns_stub_stream_packet_internal(s, false); +} + +static int on_dns_stub_stream_packet_extra(DnsStream *s) { + return on_dns_stub_stream_packet_internal(s, true); +} + +static int on_dns_stub_stream_internal(sd_event_source *s, int fd, uint32_t revents, Manager *m, bool is_extra) { DnsStream *stream; - Manager *m = userdata; int cfd, r; cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); @@ -589,7 +604,7 @@ static int on_dns_stub_stream(sd_event_source *s, int fd, uint32_t revents, void return r; } - stream->on_packet = on_dns_stub_stream_packet; + stream->on_packet = is_extra ? on_dns_stub_stream_packet_extra : on_dns_stub_stream_packet; stream->complete = dns_stub_stream_complete; /* We let the reference to the stream dangle here, it will be dropped later by the complete callback. */ @@ -597,6 +612,14 @@ static int on_dns_stub_stream(sd_event_source *s, int fd, uint32_t revents, void return 0; } +static int on_dns_stub_stream(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + return on_dns_stub_stream_internal(s, fd, revents, userdata, false); +} + +static int on_dns_stub_stream_extra(sd_event_source *s, int fd, uint32_t revents, void *userdata) { + return on_dns_stub_stream_internal(s, fd, revents, userdata, true); +} + static int manager_dns_stub_tcp_fd(Manager *m) { union sockaddr_union sa = { .in.sin_family = AF_INET, @@ -697,7 +720,7 @@ static int manager_dns_stub_tcp_fd_extra(Manager *m, DNSStubListenerExtra *l) { goto fail; } - r = sd_event_add_io(m->event, &l->tcp_event_source, fd, EPOLLIN, on_dns_stub_packet, m); + r = sd_event_add_io(m->event, &l->tcp_event_source, fd, EPOLLIN, on_dns_stub_stream_extra, m); if (r < 0) goto fail; From 89f7435d0cca90517103f99c95e5d15ef6253258 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 4 Sep 2020 23:08:48 +0900 Subject: [PATCH 23/23] resolve: use correct fd for UDP stub listner --- src/resolve/resolved-dns-packet.h | 1 + src/resolve/resolved-dns-stub.c | 11 +---------- src/resolve/resolved-manager.c | 1 + 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h index 56614c4a07..359cdcfd04 100644 --- a/src/resolve/resolved-dns-packet.h +++ b/src/resolve/resolved-dns-packet.h @@ -66,6 +66,7 @@ struct DnsPacket { DnsResourceRecord *opt; /* Packet reception metadata */ + int fd; /* Used by UDP extra DNS stub listners */ int ifindex; int family, ipproto; union in_addr_union sender, destination; diff --git a/src/resolve/resolved-dns-stub.c b/src/resolve/resolved-dns-stub.c index 72e470533c..132bac8153 100644 --- a/src/resolve/resolved-dns-stub.c +++ b/src/resolve/resolved-dns-stub.c @@ -14,9 +14,6 @@ * IP and UDP header sizes */ #define ADVERTISE_DATAGRAM_SIZE_MAX (65536U-14U-20U-8U) -static int manager_dns_stub_udp_fd(Manager *m); -static int manager_dns_stub_tcp_fd(Manager *m); - int dns_stub_listener_extra_new(DNSStubListenerExtra **ret) { DNSStubListenerExtra *l; @@ -164,17 +161,11 @@ static int dns_stub_send(Manager *m, DnsStream *s, DnsPacket *p, DnsPacket *repl if (s) r = dns_stream_write_packet(s, reply); else { - int fd; - - fd = manager_dns_stub_udp_fd(m); - if (fd < 0) - return log_debug_errno(fd, "Failed to get reply socket: %m"); - /* Note that it is essential here that we explicitly choose the source IP address for this packet. This * 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, fd, LOOPBACK_IFINDEX, p->family, &p->sender, p->sender_port, &p->destination, reply); + r = manager_send(m, p->fd, p->ifindex, p->family, &p->sender, p->sender_port, &p->destination, reply); } if (r < 0) return log_debug_errno(r, "Failed to send reply packet: %m"); diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index faf1a82155..ddd336b489 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -790,6 +790,7 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) { p->size = (size_t) l; + p->fd = fd; p->family = sa.sa.sa_family; p->ipproto = IPPROTO_UDP; if (p->family == AF_INET) {