From: Yu Watanabe Date: Sun, 4 Nov 2018 11:42:14 +0000 (+0900) Subject: network: use destroy callback to clear resolved wireguard endpoints X-Git-Tag: v240~404^2~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8173d1d0ecbb219a7dde64ba45900216f2b771da;p=thirdparty%2Fsystemd.git network: use destroy callback to clear resolved wireguard endpoints --- diff --git a/src/network/netdev/wireguard.c b/src/network/netdev/wireguard.c index 1cab31302e8..de685157efd 100644 --- a/src/network/netdev/wireguard.c +++ b/src/network/netdev/wireguard.c @@ -6,6 +6,8 @@ #include #include +#include "sd-resolve.h" + #include "alloc-util.h" #include "parse-util.h" #include "fd-util.h" @@ -195,12 +197,21 @@ static int set_wireguard_interface(NetDev *netdev) { static WireguardEndpoint* wireguard_endpoint_free(WireguardEndpoint *e) { if (!e) return NULL; - netdev_unref(e->netdev); e->host = mfree(e->host); e->port = mfree(e->port); return mfree(e); } +static void wireguard_endpoint_destroy_callback(void *userdata) { + WireguardEndpoint *e = userdata; + + assert(e); + assert(e->netdev); + + netdev_unref(e->netdev); + wireguard_endpoint_free(e); +} + DEFINE_TRIVIAL_CLEANUP_FUNC(WireguardEndpoint*, wireguard_endpoint_free); static int on_resolve_retry(sd_event_source *s, usec_t usec, void *userdata) { @@ -232,9 +243,10 @@ static int wireguard_resolve_handler(sd_resolve_query *q, int ret, const struct addrinfo *ai, void *userdata) { - NetDev *netdev; + _cleanup_(netdev_unrefp) NetDev *netdev_will_unrefed = NULL; + NetDev *netdev = NULL; + WireguardEndpoint *e; Wireguard *w; - _cleanup_(wireguard_endpoint_freep) WireguardEndpoint *e; int r; assert(userdata); @@ -245,14 +257,17 @@ static int wireguard_resolve_handler(sd_resolve_query *q, w = WIREGUARD(netdev); assert(w); - w->resolve_query = sd_resolve_query_unref(w->resolve_query); + if (!netdev->manager) + /* The netdev is detached. */ + return 0; if (ret != 0) { log_netdev_error(netdev, "Failed to resolve host '%s:%s': %s", e->host, e->port, gai_strerror(ret)); LIST_PREPEND(endpoints, w->failed_endpoints, e); - e = NULL; + (void) sd_resolve_query_set_destroy_callback(q, NULL); /* Avoid freeing endpoint by destroy callback. */ + netdev_will_unrefed = netdev; /* But netdev needs to be unrefed. */ } else if ((ai->ai_family == AF_INET && ai->ai_addrlen == sizeof(struct sockaddr_in)) || - (ai->ai_family == AF_INET6 && ai->ai_addrlen == sizeof(struct sockaddr_in6))) + (ai->ai_family == AF_INET6 && ai->ai_addrlen == sizeof(struct sockaddr_in6))) memcpy(&e->peer->endpoint, ai->ai_addr, ai->ai_addrlen); else log_netdev_error(netdev, "Neither IPv4 nor IPv6 address found for peer endpoint: %s:%s", e->host, e->port); @@ -280,22 +295,24 @@ static int wireguard_resolve_handler(sd_resolve_query *q, } static void resolve_endpoints(NetDev *netdev) { - int r = 0; - Wireguard *w; - WireguardEndpoint *endpoint; static const struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_DGRAM, .ai_protocol = IPPROTO_UDP }; + WireguardEndpoint *endpoint; + Wireguard *w; + int r = 0; assert(netdev); w = WIREGUARD(netdev); assert(w); LIST_FOREACH(endpoints, endpoint, w->unresolved_endpoints) { + _cleanup_(sd_resolve_query_unrefp) sd_resolve_query *q = NULL; + r = sd_resolve_getaddrinfo(netdev->manager->resolve, - &w->resolve_query, + &q, endpoint->host, endpoint->port, &hints, @@ -304,11 +321,23 @@ static void resolve_endpoints(NetDev *netdev) { if (r == -ENOBUFS) break; + if (r < 0) { + log_netdev_error_errno(netdev, r, "Failed to create resolver: %m"); + continue; + } - LIST_REMOVE(endpoints, w->unresolved_endpoints, endpoint); + r = sd_resolve_query_set_destroy_callback(q, wireguard_endpoint_destroy_callback); + if (r < 0) { + log_netdev_error_errno(netdev, r, "Failed to set destroy callback to resolving query: %m"); + continue; + } - if (r < 0) - log_netdev_error_errno(netdev, r, "Failed create resolver: %m"); + (void) sd_resolve_query_set_floating(q, true); + + /* Avoid freeing netdev. It will be unrefed by the destroy callback. */ + netdev_ref(netdev); + + LIST_REMOVE(endpoints, w->unresolved_endpoints, endpoint); } } @@ -612,9 +641,8 @@ int config_parse_wireguard_endpoint(const char *unit, endpoint->peer = TAKE_PTR(peer); endpoint->host = TAKE_PTR(host); endpoint->port = TAKE_PTR(port); - endpoint->netdev = netdev_ref(data); - LIST_PREPEND(endpoints, w->unresolved_endpoints, endpoint); - endpoint = NULL; + endpoint->netdev = data; + LIST_PREPEND(endpoints, w->unresolved_endpoints, TAKE_PTR(endpoint)); return 0; } diff --git a/src/network/netdev/wireguard.h b/src/network/netdev/wireguard.h index 80a5bf87a0a..7e6feb298b1 100644 --- a/src/network/netdev/wireguard.h +++ b/src/network/netdev/wireguard.h @@ -63,7 +63,6 @@ struct Wireguard { LIST_HEAD(WireguardEndpoint, unresolved_endpoints); LIST_HEAD(WireguardEndpoint, failed_endpoints); unsigned n_retries; - sd_resolve_query *resolve_query; }; DEFINE_NETDEV_CAST(WIREGUARD, Wireguard);