aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c40
1 files changed, 37 insertions, 3 deletions
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c
index 6e1dd8cf0..9c2e34f82 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c
@@ -211,9 +211,11 @@ CALLBACK(watch, bool,
return TRUE;
}
-METHOD(netlink_socket_t, netlink_send, status_t,
- private_netlink_socket_t *this, struct nlmsghdr *in, struct nlmsghdr **out,
- size_t *out_len)
+/**
+ * Send a netlink request, try once
+ */
+static status_t send_once(private_netlink_socket_t *this, struct nlmsghdr *in,
+ struct nlmsghdr **out, size_t *out_len)
{
struct nlmsghdr *hdr;
chunk_t result = {};
@@ -277,6 +279,38 @@ METHOD(netlink_socket_t, netlink_send, status_t,
return SUCCESS;
}
+METHOD(netlink_socket_t, netlink_send, status_t,
+ private_netlink_socket_t *this, struct nlmsghdr *in, struct nlmsghdr **out,
+ size_t *out_len)
+{
+ while (TRUE)
+ {
+ struct nlmsghdr *hdr;
+ status_t status;
+ size_t len;
+
+ status = send_once(this, in, &hdr, &len);
+ if (status != SUCCESS)
+ {
+ return status;
+ }
+ if (hdr->nlmsg_type == NLMSG_ERROR)
+ {
+ struct nlmsgerr* err;
+
+ err = NLMSG_DATA(hdr);
+ if (err->error == -EBUSY)
+ {
+ free(hdr);
+ continue;
+ }
+ }
+ *out = hdr;
+ *out_len = len;
+ return SUCCESS;
+ }
+}
+
METHOD(netlink_socket_t, netlink_send_ack, status_t,
private_netlink_socket_t *this, struct nlmsghdr *in)
{