summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2018-11-06 19:30:59 +0300
committerGitHub <noreply@github.com>2018-11-06 19:30:59 +0300
commitb992109b3ed639854cfb58a08dab3524e349eeb6 (patch)
tree538f82c590aa8e5bbfee25b2a1e613da17408a9a
parented2e7967befb9074df92d0b8dab3863133e11462 (diff)
parenta7cc45caadec7b113ecc9f8603bfe3387dfefbf8 (diff)
downloadsystemd-b992109b3ed639854cfb58a08dab3524e349eeb6.tar.gz
systemd-b992109b3ed639854cfb58a08dab3524e349eeb6.tar.bz2
systemd-b992109b3ed639854cfb58a08dab3524e349eeb6.zip
Merge pull request #10633 from yuwata/sd-resolve-destroy
Another solution to fix wireguard issues
-rw-r--r--src/libsystemd/libsystemd.sym3
-rw-r--r--src/libsystemd/sd-event/sd-event.c28
-rw-r--r--src/libsystemd/sd-resolve/sd-resolve.c48
-rw-r--r--src/network/netdev/bridge.c2
-rw-r--r--src/network/netdev/geneve.c2
-rw-r--r--src/network/netdev/netdev.c16
-rw-r--r--src/network/netdev/netdev.h2
-rw-r--r--src/network/netdev/wireguard.c130
-rw-r--r--src/network/netdev/wireguard.h7
-rw-r--r--src/network/networkd-link.c20
-rw-r--r--src/network/networkd-manager.c16
-rw-r--r--src/systemd/sd-event.h2
-rw-r--r--src/systemd/sd-resolve.h5
13 files changed, 220 insertions, 61 deletions
diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym
index 8d46081ec4..1f2238ca37 100644
--- a/src/libsystemd/libsystemd.sym
+++ b/src/libsystemd/libsystemd.sym
@@ -663,4 +663,7 @@ global:
sd_device_monitor_filter_add_match_tag;
sd_device_monitor_filter_update;
sd_device_monitor_filter_remove;
+
+ sd_event_source_get_floating;
+ sd_event_source_set_floating;
} LIBSYSTEMD_239;
diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c
index f44e6b4cca..27caa8681c 100644
--- a/src/libsystemd/sd-event/sd-event.c
+++ b/src/libsystemd/sd-event/sd-event.c
@@ -3702,3 +3702,31 @@ _public_ int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_d
return !!s->destroy_callback;
}
+
+_public_ int sd_event_source_get_floating(sd_event_source *s) {
+ assert_return(s, -EINVAL);
+
+ return s->floating;
+}
+
+_public_ int sd_event_source_set_floating(sd_event_source *s, int b) {
+ assert_return(s, -EINVAL);
+
+ if (s->floating == !!b)
+ return 0;
+
+ if (!s->event) /* Already disconnected */
+ return -ESTALE;
+
+ s->floating = b;
+
+ if (b) {
+ sd_event_source_ref(s);
+ sd_event_unref(s->event);
+ } else {
+ sd_event_ref(s->event);
+ sd_event_source_unref(s);
+ }
+
+ return 1;
+}
diff --git a/src/libsystemd/sd-resolve/sd-resolve.c b/src/libsystemd/sd-resolve/sd-resolve.c
index 61876781c0..1fbab9dbf9 100644
--- a/src/libsystemd/sd-resolve/sd-resolve.c
+++ b/src/libsystemd/sd-resolve/sd-resolve.c
@@ -94,6 +94,7 @@ struct sd_resolve_query {
};
void *userdata;
+ sd_resolve_destroy_t destroy_callback;
LIST_FIELDS(sd_resolve_query, queries);
};
@@ -1095,6 +1096,9 @@ static sd_resolve_query *resolve_query_free(sd_resolve_query *q) {
resolve_query_disconnect(q);
+ if (q->destroy_callback)
+ q->destroy_callback(q->userdata);
+
resolve_freeaddrinfo(q->addrinfo);
free(q->host);
free(q->serv);
@@ -1137,6 +1141,50 @@ _public_ sd_resolve *sd_resolve_query_get_resolve(sd_resolve_query *q) {
return q->resolve;
}
+_public_ int sd_resolve_query_get_destroy_callback(sd_resolve_query *q, sd_resolve_destroy_t *destroy_callback) {
+ assert_return(q, -EINVAL);
+
+ if (destroy_callback)
+ *destroy_callback = q->destroy_callback;
+
+ return !!q->destroy_callback;
+}
+
+_public_ int sd_resolve_query_set_destroy_callback(sd_resolve_query *q, sd_resolve_destroy_t destroy_callback) {
+ assert_return(q, -EINVAL);
+
+ q->destroy_callback = destroy_callback;
+ return 0;
+}
+
+_public_ int sd_resolve_query_get_floating(sd_resolve_query *q) {
+ assert_return(q, -EINVAL);
+
+ return q->floating;
+}
+
+_public_ int sd_resolve_query_set_floating(sd_resolve_query *q, int b) {
+ assert_return(q, -EINVAL);
+
+ if (q->floating == !!b)
+ return 0;
+
+ if (!q->resolve) /* Already disconnected */
+ return -ESTALE;
+
+ q->floating = b;
+
+ if (b) {
+ sd_resolve_query_ref(q);
+ sd_resolve_unref(q->resolve);
+ } else {
+ sd_resolve_ref(q->resolve);
+ sd_resolve_query_unref(q);
+ }
+
+ return 1;
+}
+
static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
sd_resolve *resolve = userdata;
int r;
diff --git a/src/network/netdev/bridge.c b/src/network/netdev/bridge.c
index 5a462f8376..cb00780b8a 100644
--- a/src/network/netdev/bridge.c
+++ b/src/network/netdev/bridge.c
@@ -130,7 +130,7 @@ static int netdev_bridge_post_create(NetDev *netdev, Link *link, sd_netlink_mess
return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");
r = sd_netlink_call_async(netdev->manager->rtnl, NULL, req, netdev_bridge_set_handler,
- netdev_netlink_destroy_callback, netdev, 0, __func__);
+ netdev_destroy_callback, netdev, 0, __func__);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m");
diff --git a/src/network/netdev/geneve.c b/src/network/netdev/geneve.c
index e407a8fc5c..1742e399b8 100644
--- a/src/network/netdev/geneve.c
+++ b/src/network/netdev/geneve.c
@@ -137,7 +137,7 @@ static int netdev_geneve_create(NetDev *netdev) {
return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");
r = sd_netlink_call_async(netdev->manager->rtnl, NULL, m, geneve_netdev_create_handler,
- netdev_netlink_destroy_callback, netdev, 0, __func__);
+ netdev_destroy_callback, netdev, 0, __func__);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m");
diff --git a/src/network/netdev/netdev.c b/src/network/netdev/netdev.c
index 6eb63355a4..52b40dd68e 100644
--- a/src/network/netdev/netdev.c
+++ b/src/network/netdev/netdev.c
@@ -112,13 +112,19 @@ static void netdev_callbacks_clear(NetDev *netdev) {
}
}
+static void netdev_detach_from_manager(NetDev *netdev) {
+ if (netdev->ifname && netdev->manager)
+ hashmap_remove(netdev->manager->netdevs, netdev->ifname);
+
+ netdev->manager = NULL;
+}
+
static NetDev *netdev_free(NetDev *netdev) {
assert(netdev);
netdev_callbacks_clear(netdev);
- if (netdev->ifname && netdev->manager)
- hashmap_remove(netdev->manager->netdevs, netdev->ifname);
+ netdev_detach_from_manager(netdev);
free(netdev->filename);
@@ -149,7 +155,7 @@ static NetDev *netdev_free(NetDev *netdev) {
DEFINE_TRIVIAL_REF_UNREF_FUNC(NetDev, netdev, netdev_free);
-void netdev_netlink_destroy_callback(void *userdata) {
+void netdev_destroy_callback(void *userdata) {
NetDev *netdev = userdata;
assert(userdata);
@@ -167,6 +173,8 @@ void netdev_drop(NetDev *netdev) {
netdev_callbacks_clear(netdev);
+ netdev_detach_from_manager(netdev);
+
netdev_unref(netdev);
return;
@@ -542,7 +550,7 @@ static int netdev_create(NetDev *netdev, Link *link,
link_ref(link);
} else {
r = sd_netlink_call_async(netdev->manager->rtnl, NULL, m, netdev_create_handler,
- netdev_netlink_destroy_callback, netdev, 0, __func__);
+ netdev_destroy_callback, netdev, 0, __func__);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m");
diff --git a/src/network/netdev/netdev.h b/src/network/netdev/netdev.h
index 2c1a59f2c4..8c884bb124 100644
--- a/src/network/netdev/netdev.h
+++ b/src/network/netdev/netdev.h
@@ -150,7 +150,7 @@ void netdev_drop(NetDev *netdev);
NetDev *netdev_unref(NetDev *netdev);
NetDev *netdev_ref(NetDev *netdev);
-void netdev_netlink_destroy_callback(void *userdata);
+void netdev_destroy_callback(void *userdata);
DEFINE_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_unref);
int netdev_get(Manager *manager, const char *name, NetDev **ret);
diff --git a/src/network/netdev/wireguard.c b/src/network/netdev/wireguard.c
index 1cab31302e..d5a0a19e9f 100644
--- a/src/network/netdev/wireguard.c
+++ b/src/network/netdev/wireguard.c
@@ -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"
@@ -28,10 +30,13 @@ static WireguardPeer *wireguard_peer_new(Wireguard *w, unsigned section) {
if (w->last_peer_section == section && w->peers)
return w->peers;
- peer = new0(WireguardPeer, 1);
+ peer = new(WireguardPeer, 1);
if (!peer)
return NULL;
- peer->flags = WGPEER_F_REPLACE_ALLOWEDIPS;
+
+ *peer = (WireguardPeer) {
+ .flags = WGPEER_F_REPLACE_ALLOWEDIPS,
+ };
LIST_PREPEND(peers, w->peers, peer);
w->last_peer_section = section;
@@ -195,12 +200,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) {
@@ -211,8 +225,11 @@ static int on_resolve_retry(sd_event_source *s, usec_t usec, void *userdata) {
w = WIREGUARD(netdev);
assert(w);
- w->resolve_retry_event_source = sd_event_source_unref(w->resolve_retry_event_source);
+ if (!netdev->manager)
+ /* The netdev is detached. */
+ return 0;
+ assert(!w->unresolved_endpoints);
w->unresolved_endpoints = TAKE_PTR(w->failed_endpoints);
resolve_endpoints(netdev);
@@ -232,9 +249,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 +263,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);
@@ -264,38 +285,53 @@ static int wireguard_resolve_handler(sd_resolve_query *q,
set_wireguard_interface(netdev);
if (w->failed_endpoints) {
+ _cleanup_(sd_event_source_unrefp) sd_event_source *s = NULL;
+
w->n_retries++;
r = sd_event_add_time(netdev->manager->event,
- &w->resolve_retry_event_source,
+ &s,
CLOCK_MONOTONIC,
now(CLOCK_MONOTONIC) + exponential_backoff_milliseconds(w->n_retries),
0,
on_resolve_retry,
netdev);
- if (r < 0)
+ if (r < 0) {
log_netdev_warning_errno(netdev, r, "Could not arm resolve retry handler: %m");
+ return 0;
+ }
+
+ r = sd_event_source_set_destroy_callback(s, netdev_destroy_callback);
+ if (r < 0) {
+ log_netdev_warning_errno(netdev, r, "Failed to set destroy callback to event source: %m");
+ return 0;
+ }
+
+ (void) sd_event_source_set_floating(s, true);
+ netdev_ref(netdev);
}
return 0;
}
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 +340,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);
}
}
@@ -531,12 +579,15 @@ int config_parse_wireguard_allowed_ips(const char *unit,
return 0;
}
- ipmask = new0(WireguardIPmask, 1);
+ ipmask = new(WireguardIPmask, 1);
if (!ipmask)
return log_oom();
- ipmask->family = family;
- ipmask->ip.in6 = addr.in6;
- ipmask->cidr = prefixlen;
+
+ *ipmask = (WireguardIPmask) {
+ .family = family,
+ .ip.in6 = addr.in6,
+ .cidr = prefixlen,
+ };
LIST_PREPEND(ipmasks, peer->ipmasks, ipmask);
}
@@ -572,10 +623,6 @@ int config_parse_wireguard_endpoint(const char *unit,
if (!peer)
return log_oom();
- endpoint = new0(WireguardEndpoint, 1);
- if (!endpoint)
- return log_oom();
-
if (rvalue[0] == '[') {
begin = &rvalue[1];
end = strchr(rvalue, ']');
@@ -609,12 +656,17 @@ int config_parse_wireguard_endpoint(const char *unit,
if (!port)
return log_oom();
- 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 = new(WireguardEndpoint, 1);
+ if (!endpoint)
+ return log_oom();
+
+ *endpoint = (WireguardEndpoint) {
+ .peer = TAKE_PTR(peer),
+ .host = TAKE_PTR(host),
+ .port = TAKE_PTR(port),
+ .netdev = data,
+ };
+ LIST_PREPEND(endpoints, w->unresolved_endpoints, TAKE_PTR(endpoint));
return 0;
}
@@ -673,11 +725,11 @@ static void wireguard_done(NetDev *netdev) {
Wireguard *w;
WireguardPeer *peer;
WireguardIPmask *mask;
+ WireguardEndpoint *e;
assert(netdev);
w = WIREGUARD(netdev);
- assert(!w->unresolved_endpoints);
- w->resolve_retry_event_source = sd_event_source_unref(w->resolve_retry_event_source);
+ assert(w);
while ((peer = w->peers)) {
LIST_REMOVE(peers, w->peers, peer);
@@ -687,6 +739,16 @@ static void wireguard_done(NetDev *netdev) {
}
free(peer);
}
+
+ while ((e = w->unresolved_endpoints)) {
+ LIST_REMOVE(endpoints, w->unresolved_endpoints, e);
+ wireguard_endpoint_free(e);
+ }
+
+ while ((e = w->failed_endpoints)) {
+ LIST_REMOVE(endpoints, w->failed_endpoints, e);
+ wireguard_endpoint_free(e);
+ }
}
const NetDevVTable wireguard_vtable = {
diff --git a/src/network/netdev/wireguard.h b/src/network/netdev/wireguard.h
index 80a5bf87a0..bd97004519 100644
--- a/src/network/netdev/wireguard.h
+++ b/src/network/netdev/wireguard.h
@@ -2,11 +2,10 @@
typedef struct Wireguard Wireguard;
+#include "in-addr-util.h"
#include "netdev.h"
-#include "sd-resolve.h"
-#include "wireguard-netlink.h"
#include "socket-util.h"
-#include "in-addr-util.h"
+#include "wireguard-netlink.h"
#ifndef IFNAMSIZ
#define IFNAMSIZ 16
@@ -58,12 +57,10 @@ struct Wireguard {
LIST_HEAD(WireguardPeer, peers);
size_t allocation_size;
- sd_event_source *resolve_retry_event_source;
LIST_HEAD(WireguardEndpoint, unresolved_endpoints);
LIST_HEAD(WireguardEndpoint, failed_endpoints);
unsigned n_retries;
- sd_resolve_query *resolve_query;
};
DEFINE_NETDEV_CAST(WIREGUARD, Wireguard);
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 2c0c04985d..1b233507e7 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -503,6 +503,17 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
return 0;
}
+static void link_detach_from_manager(Link *link) {
+ if (!link || !link->manager)
+ return;
+
+ hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
+ set_remove(link->manager->links_requesting_uuid, link);
+ link_clean(link);
+
+ link->manager = NULL;
+}
+
static Link *link_free(Link *link) {
Address *address;
Link *carrier;
@@ -552,11 +563,7 @@ static Link *link_free(Link *link) {
sd_ndisc_unref(link->ndisc);
sd_radv_unref(link->radv);
- if (link->manager) {
- hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
- set_remove(link->manager->links_requesting_uuid, link);
- link_clean(link);
- }
+ link_detach_from_manager(link);
free(link->ifname);
@@ -2265,6 +2272,9 @@ void link_drop(Link *link) {
log_link_debug(link, "Link removed");
(void) unlink(link->state_file);
+
+ link_detach_from_manager(link);
+
link_unref(link);
return;
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index c8a6f81fd8..69861a680e 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -1407,10 +1407,9 @@ int manager_new(Manager **ret) {
}
void manager_free(Manager *m) {
+ AddressPool *pool;
Network *network;
- NetDev *netdev;
Link *link;
- AddressPool *pool;
if (!m)
return;
@@ -1419,6 +1418,7 @@ void manager_free(Manager *m) {
sd_netlink_unref(m->rtnl);
sd_netlink_unref(m->genl);
+ sd_resolve_unref(m->resolve);
while ((network = m->networks))
network_free(network);
@@ -1437,16 +1437,14 @@ void manager_free(Manager *m) {
link_unref(link);
}
- set_free_with_destructor(m->dirty_links, link_unref);
- hashmap_free(m->links);
- set_free(m->links_requesting_uuid);
+ m->dirty_links = set_free_with_destructor(m->dirty_links, link_unref);
+ m->links = hashmap_free(m->links);
+ m->links_requesting_uuid = set_free(m->links_requesting_uuid);
set_free(m->duids_requesting_uuid);
hashmap_free(m->networks_by_name);
- while ((netdev = hashmap_first(m->netdevs)))
- netdev_unref(netdev);
- hashmap_free(m->netdevs);
+ m->netdevs = hashmap_free_with_destructor(m->netdevs, netdev_unref);
while ((pool = m->address_pools))
address_pool_free(pool);
@@ -1459,8 +1457,6 @@ void manager_free(Manager *m) {
sd_event_unref(m->event);
- sd_resolve_unref(m->resolve);
-
sd_device_monitor_unref(m->device_monitor);
sd_bus_unref(m->bus);
diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h
index c38eb84beb..b15cade20a 100644
--- a/src/systemd/sd-event.h
+++ b/src/systemd/sd-event.h
@@ -143,6 +143,8 @@ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid);
int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *ret);
int sd_event_source_set_destroy_callback(sd_event_source *s, sd_event_destroy_t callback);
int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_destroy_t *ret);
+int sd_event_source_get_floating(sd_event_source *s);
+int sd_event_source_set_floating(sd_event_source *s, int b);
/* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref);
diff --git a/src/systemd/sd-resolve.h b/src/systemd/sd-resolve.h
index 5695119b40..089fcdee37 100644
--- a/src/systemd/sd-resolve.h
+++ b/src/systemd/sd-resolve.h
@@ -42,6 +42,7 @@ typedef struct sd_resolve_query sd_resolve_query;
/* A callback on completion */
typedef int (*sd_resolve_getaddrinfo_handler_t)(sd_resolve_query *q, int ret, const struct addrinfo *ai, void *userdata);
typedef int (*sd_resolve_getnameinfo_handler_t)(sd_resolve_query *q, int ret, const char *host, const char *serv, void *userdata);
+typedef void (*sd_resolve_destroy_t)(void *userdata);
enum {
SD_RESOLVE_GET_HOST = 1 << 0,
@@ -108,6 +109,10 @@ int sd_resolve_query_is_done(sd_resolve_query*q);
void *sd_resolve_query_get_userdata(sd_resolve_query *q);
void *sd_resolve_query_set_userdata(sd_resolve_query *q, void *userdata);
+int sd_resolve_query_get_destroy_callback(sd_resolve_query *q, sd_resolve_destroy_t *destroy_callback);
+int sd_resolve_query_set_destroy_callback(sd_resolve_query *q, sd_resolve_destroy_t destroy_callback);
+int sd_resolve_query_get_floating(sd_resolve_query *q);
+int sd_resolve_query_set_floating(sd_resolve_query *q, int b);
sd_resolve *sd_resolve_query_get_resolve(sd_resolve_query *q);