network: use destroy callback to clear resolved wireguard endpoints

This commit is contained in:
Yu Watanabe
2018-11-05 13:19:02 +09:00
parent c4397d94c3
commit 8173d1d0ec
2 changed files with 44 additions and 17 deletions
+44 -16
View File
@@ -6,6 +6,8 @@
#include <sys/ioctl.h>
#include <net/if.h>
#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;
}
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;
}
(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);
if (r < 0)
log_netdev_error_errno(netdev, r, "Failed create resolver: %m");
}
}
@@ -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;
}
-1
View File
@@ -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);