SHA256
1
0
forked from pool/libvirt

Accepting request 481947 from home:cbosdonnat:branches:Virtualization

- Fail to start network instead of losing routes if IPv6 forwarding
  is required. bsc#1025252
  Added patches:
    00d28a78b-check-accept_ra-before-enabling-ipv6-forward.patch
    3ee35d7d6-more-uses-of-SYSCTL_PATH.patch
    5dd607059-add-virNetDevGetName.patch
    754515b7d-add-virNetlinkDumpCommand.patch
    d68cb4f55-extract-the-request-sending-code-from-virNetlin.patch

OBS-URL: https://build.opensuse.org/request/show/481947
OBS-URL: https://build.opensuse.org/package/show/Virtualization/libvirt?expand=0&rev=593
This commit is contained in:
Cédric Bosdonnat 2017-03-22 08:50:09 +00:00 committed by Git OBS Bridge
parent 51e9f38d3f
commit 79b3a063e4
7 changed files with 691 additions and 2 deletions

View File

@ -0,0 +1,260 @@
From 00d28a78b5d1f6eaf79f06ac59e31c568af9da37 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com>
Date: Fri, 3 Mar 2017 14:14:51 +0100
Subject: [PATCH 5/5] network: check accept_ra before enabling ipv6 forwarding
When enabling IPv6 on all interfaces, we may get the host Router
Advertisement routes discarded. To avoid this, the user needs to set
accept_ra to 2 for the interfaces with such routes.
See https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt
on this topic.
To avoid user mistakenly losing routes on their hosts, check
accept_ra values before enabling IPv6 forwarding. If a RA route is
detected, but neither the corresponding device nor global accept_ra
is set to 2, the network will fail to start.
---
src/libvirt_private.syms | 1 +
src/network/bridge_driver.c | 16 +++--
src/util/virnetdevip.c | 158 ++++++++++++++++++++++++++++++++++++++++++++
src/util/virnetdevip.h | 1 +
4 files changed, 171 insertions(+), 5 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 3b2cb83c4..57acfdbb1 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2067,6 +2067,7 @@ virNetDevBridgeSetVlanFiltering;
virNetDevIPAddrAdd;
virNetDevIPAddrDel;
virNetDevIPAddrGet;
+virNetDevIPCheckIPv6Forwarding;
virNetDevIPInfoAddToDev;
virNetDevIPInfoClear;
virNetDevIPRouteAdd;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 4d1a44516..a753cd78b 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -61,6 +61,7 @@
#include "virlog.h"
#include "virdnsmasq.h"
#include "configmake.h"
+#include "virnetlink.h"
#include "virnetdev.h"
#include "virnetdevip.h"
#include "virnetdevbridge.h"
@@ -2389,11 +2390,16 @@ networkStartNetworkVirtual(virNetworkDriverStatePtr driver,
}
/* If forward.type != NONE, turn on global IP forwarding */
- if (network->def->forward.type != VIR_NETWORK_FORWARD_NONE &&
- networkEnableIPForwarding(v4present, v6present) < 0) {
- virReportSystemError(errno, "%s",
- _("failed to enable IP forwarding"));
- goto err3;
+ if (network->def->forward.type != VIR_NETWORK_FORWARD_NONE) {
+ if (!virNetDevIPCheckIPv6Forwarding())
+ goto err3; /* Precise error message already provided */
+
+
+ if (networkEnableIPForwarding(v4present, v6present) < 0) {
+ virReportSystemError(errno, "%s",
+ _("failed to enable IP forwarding"));
+ goto err3;
+ }
}
diff --git a/src/util/virnetdevip.c b/src/util/virnetdevip.c
index 42fbba1eb..a4d382427 100644
--- a/src/util/virnetdevip.c
+++ b/src/util/virnetdevip.c
@@ -508,6 +508,158 @@ virNetDevIPWaitDadFinish(virSocketAddrPtr *addrs, size_t count)
return ret;
}
+static int
+virNetDevIPGetAcceptRA(const char *ifname)
+{
+ char *path = NULL;
+ char *buf = NULL;
+ char *suffix;
+ int accept_ra = -1;
+
+ if (virAsprintf(&path, "/proc/sys/net/ipv6/conf/%s/accept_ra",
+ ifname ? ifname : "all") < 0)
+ goto cleanup;
+
+ if ((virFileReadAll(path, 512, &buf) < 0) ||
+ (virStrToLong_i(buf, &suffix, 10, &accept_ra) < 0))
+ goto cleanup;
+
+ cleanup:
+ VIR_FREE(path);
+ VIR_FREE(buf);
+
+ return accept_ra;
+}
+
+struct virNetDevIPCheckIPv6ForwardingData {
+ bool hasRARoutes;
+
+ /* Devices with conflicting accept_ra */
+ char **devices;
+ size_t ndevices;
+};
+
+static int
+virNetDevIPCheckIPv6ForwardingCallback(const struct nlmsghdr *resp,
+ void *opaque)
+{
+ struct rtmsg *rtmsg = NLMSG_DATA(resp);
+ int accept_ra = -1;
+ struct rtattr *rta;
+ char *ifname = NULL;
+ struct virNetDevIPCheckIPv6ForwardingData *data = opaque;
+ int ret = 0;
+ int len = RTM_PAYLOAD(resp);
+ int oif = -1;
+
+ /* Ignore messages other than route ones */
+ if (resp->nlmsg_type != RTM_NEWROUTE)
+ return ret;
+
+ /* Extract a few attributes */
+ for (rta = RTM_RTA(rtmsg); RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
+ switch (rta->rta_type) {
+ case RTA_OIF:
+ oif = *(int *)RTA_DATA(rta);
+
+ if (!(ifname = virNetDevGetName(oif)))
+ goto error;
+ break;
+ }
+ }
+
+ /* No need to do anything else for non RA routes */
+ if (rtmsg->rtm_protocol != RTPROT_RA)
+ goto cleanup;
+
+ data->hasRARoutes = true;
+
+ /* Check the accept_ra value for the interface */
+ accept_ra = virNetDevIPGetAcceptRA(ifname);
+ VIR_DEBUG("Checking route for device %s, accept_ra: %d", ifname, accept_ra);
+
+ if (accept_ra != 2 && VIR_APPEND_ELEMENT(data->devices, data->ndevices, ifname) < 0)
+ goto error;
+
+ cleanup:
+ VIR_FREE(ifname);
+ return ret;
+
+ error:
+ ret = -1;
+ goto cleanup;
+}
+
+bool
+virNetDevIPCheckIPv6Forwarding(void)
+{
+ struct nl_msg *nlmsg = NULL;
+ bool valid = false;
+ struct rtgenmsg genmsg;
+ size_t i;
+ struct virNetDevIPCheckIPv6ForwardingData data = {
+ .hasRARoutes = false,
+ .devices = NULL,
+ .ndevices = 0
+ };
+
+
+ /* Prepare the request message */
+ if (!(nlmsg = nlmsg_alloc_simple(RTM_GETROUTE,
+ NLM_F_REQUEST | NLM_F_DUMP))) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ memset(&genmsg, 0, sizeof(genmsg));
+ genmsg.rtgen_family = AF_INET6;
+
+ if (nlmsg_append(nlmsg, &genmsg, sizeof(genmsg), NLMSG_ALIGNTO) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("allocated netlink buffer is too small"));
+ goto cleanup;
+ }
+
+ /* Send the request and loop over the responses */
+ if (virNetlinkDumpCommand(nlmsg, virNetDevIPCheckIPv6ForwardingCallback,
+ 0, 0, NETLINK_ROUTE, 0, &data) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Failed to loop over IPv6 routes"));
+ goto cleanup;
+ }
+
+ valid = !data.hasRARoutes || data.ndevices == 0;
+
+ /* Check the global accept_ra if at least one isn't set on a
+ per-device basis */
+ if (!valid && data.hasRARoutes) {
+ int accept_ra = virNetDevIPGetAcceptRA(NULL);
+ valid = accept_ra == 2;
+ VIR_DEBUG("Checked global accept_ra: %d", accept_ra);
+ }
+
+ if (!valid) {
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
+ for (i = 0; i < data.ndevices; i++) {
+ virBufferAdd(&buf, data.devices[i], -1);
+ if (i < data.ndevices - 1)
+ virBufferAddLit(&buf, ", ");
+ }
+
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Check the host setup: enabling IPv6 forwarding with "
+ "RA routes without accept_ra set to 2 is likely to cause "
+ "routes loss. Interfaces to look at: %s"),
+ virBufferCurrentContent(&buf));
+ virBufferFreeAndReset(&buf);
+ }
+
+ cleanup:
+ nlmsg_free(nlmsg);
+ for (i = 0; i < data.ndevices; i++)
+ VIR_FREE(data.devices[i]);
+ return valid;
+}
#else /* defined(__linux__) && defined(HAVE_LIBNL) */
@@ -655,6 +807,12 @@ virNetDevIPWaitDadFinish(virSocketAddrPtr *addrs ATTRIBUTE_UNUSED,
return -1;
}
+bool
+virNetDevIPCheckIPv6Forwarding(void)
+{
+ VIR_WARN("built without libnl: unable to check if IPv6 forwarding can be safely enabled");
+ return true;
+}
#endif /* defined(__linux__) && defined(HAVE_LIBNL) */
diff --git a/src/util/virnetdevip.h b/src/util/virnetdevip.h
index b7abdf94d..cc466ca25 100644
--- a/src/util/virnetdevip.h
+++ b/src/util/virnetdevip.h
@@ -83,6 +83,7 @@ int virNetDevIPAddrGet(const char *ifname, virSocketAddrPtr addr)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
int virNetDevIPWaitDadFinish(virSocketAddrPtr *addrs, size_t count)
ATTRIBUTE_NONNULL(1);
+bool virNetDevIPCheckIPv6Forwarding(void);
/* virNetDevIPRoute object */
void virNetDevIPRouteFree(virNetDevIPRoutePtr def);
--
2.12.0

View File

@ -0,0 +1,46 @@
From 3ee35d7d6caf0ffa722d60251eabec43c094fb12 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com>
Date: Fri, 3 Mar 2017 14:13:49 +0100
Subject: [PATCH 3/5] bridge_driver.c: more uses of SYSCTL_PATH
Replace a few occurences of /proc/sys by the corresponding macro
defined a few lines after: SYSCTL_PATH
---
src/network/bridge_driver.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index 32c5ab7a7..4d1a44516 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -85,6 +85,8 @@
*/
#define VIR_NETWORK_DHCP_LEASE_FILE_SIZE_MAX (32 * 1024 * 1024)
+#define SYSCTL_PATH "/proc/sys"
+
VIR_LOG_INIT("network.bridge_driver");
static virNetworkDriverStatePtr network_driver;
@@ -2092,15 +2094,14 @@ networkEnableIPForwarding(bool enableIPv4, bool enableIPv6)
&enabled, sizeof(enabled));
#else
if (enableIPv4)
- ret = virFileWriteStr("/proc/sys/net/ipv4/ip_forward", "1\n", 0);
+ ret = virFileWriteStr(SYSCTL_PATH "/net/ipv4/ip_forward", "1\n", 0);
if (enableIPv6 && ret == 0)
- ret = virFileWriteStr("/proc/sys/net/ipv6/conf/all/forwarding", "1\n", 0);
+ ret = virFileWriteStr(SYSCTL_PATH "/net/ipv6/conf/all/forwarding", "1\n", 0);
+
#endif
return ret;
}
-#define SYSCTL_PATH "/proc/sys"
-
static int
networkSetIPv6Sysctls(virNetworkObjPtr network)
{
--
2.12.0

View File

@ -0,0 +1,70 @@
From 5dd607059d8a98e04024305ae4afbd038aadbdcd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com>
Date: Wed, 15 Mar 2017 14:46:56 +0100
Subject: [PATCH 4/5] util: add virNetDevGetName() function
Add a function getting the name of a network interface out of its index.
---
src/libvirt_private.syms | 1 +
src/util/virnetdev.c | 19 +++++++++++++++++++
src/util/virnetdev.h | 2 ++
3 files changed, 22 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index f03925bc1..3b2cb83c4 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1995,6 +1995,7 @@ virNetDevGetIndex;
virNetDevGetLinkInfo;
virNetDevGetMAC;
virNetDevGetMTU;
+virNetDevGetName;
virNetDevGetOnline;
virNetDevGetPhysicalFunction;
virNetDevGetPromiscuous;
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index d12324878..91a5274aa 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -899,6 +899,25 @@ virNetDevGetRcvAllMulti(const char *ifname,
return virNetDevGetIFFlag(ifname, VIR_IFF_ALLMULTI, receive);
}
+char *virNetDevGetName(int ifindex)
+{
+ char name[IFNAMSIZ];
+ char *ifname = NULL;
+
+ memset(&name, 0, sizeof(name));
+
+ if (!if_indextoname(ifindex, name)) {
+ virReportSystemError(errno,
+ _("Failed to convert interface index %d to a name"),
+ ifindex);
+ goto cleanup;
+ }
+
+ ignore_value(VIR_STRDUP(ifname, name));
+
+ cleanup:
+ return ifname;
+}
/**
* virNetDevGetIndex:
diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h
index 236cf83ef..01e9c5b95 100644
--- a/src/util/virnetdev.h
+++ b/src/util/virnetdev.h
@@ -157,6 +157,8 @@ int virNetDevSetNamespace(const char *ifname, pid_t pidInNs)
int virNetDevSetName(const char *ifname, const char *newifname)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+char *virNetDevGetName(int ifindex)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
int virNetDevGetIndex(const char *ifname, int *ifindex)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
--
2.12.0

View File

@ -0,0 +1,125 @@
From 754515b7db6258ab592265b743128353be0cb32b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com>
Date: Fri, 3 Mar 2017 12:22:50 +0100
Subject: [PATCH 2/5] util: add virNetlinkDumpCommand()
virNetlinkCommand() processes only one response message, while some
netlink commands, like route dumping, need to process several.
Add virNetlinkDumpCommand() as a virNetlinkCommand() sister.
---
src/libvirt_private.syms | 1 +
src/util/virnetlink.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++
src/util/virnetlink.h | 9 ++++++++
3 files changed, 68 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index b46e85f63..f03925bc1 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2138,6 +2138,7 @@ virNetDevVPortProfileOpTypeToString;
# util/virnetlink.h
virNetlinkCommand;
virNetlinkDelLink;
+virNetlinkDumpCommand;
virNetlinkDumpLink;
virNetlinkEventAddClient;
virNetlinkEventRemoveClient;
diff --git a/src/util/virnetlink.c b/src/util/virnetlink.c
index be00351db..9bc1f0f2b 100644
--- a/src/util/virnetlink.c
+++ b/src/util/virnetlink.c
@@ -335,6 +335,52 @@ int virNetlinkCommand(struct nl_msg *nl_msg,
return ret;
}
+int
+virNetlinkDumpCommand(struct nl_msg *nl_msg,
+ virNetlinkDumpCallback callback,
+ uint32_t src_pid, uint32_t dst_pid,
+ unsigned int protocol, unsigned int groups,
+ void *opaque)
+{
+ int ret = -1;
+ bool end = false;
+ int len = 0;
+ struct nlmsghdr *resp = NULL;
+ struct nlmsghdr *msg = NULL;
+
+ struct sockaddr_nl nladdr = {
+ .nl_family = AF_NETLINK,
+ .nl_pid = dst_pid,
+ .nl_groups = 0,
+ };
+ virNetlinkHandle *nlhandle = NULL;
+
+ if (!(nlhandle = virNetlinkSendRequest(nl_msg, src_pid, nladdr,
+ protocol, groups)))
+ goto cleanup;
+
+ while (!end) {
+ len = nl_recv(nlhandle, &nladdr, (unsigned char **)&resp, NULL);
+
+ for (msg = resp; NLMSG_OK(msg, len); msg = NLMSG_NEXT(msg, len)) {
+ if (msg->nlmsg_type == NLMSG_DONE)
+ end = true;
+
+ if (virNetlinkGetErrorCode(msg, len) < 0)
+ goto cleanup;
+
+ if (callback(msg, opaque) < 0)
+ goto cleanup;
+ }
+ }
+
+ ret = 0;
+
+ cleanup:
+ virNetlinkFree(nlhandle);
+ return ret;
+}
+
/**
* virNetlinkDumpLink:
*
@@ -1061,6 +1107,18 @@ int virNetlinkCommand(struct nl_msg *nl_msg ATTRIBUTE_UNUSED,
return -1;
}
+int
+virNetlinkDumpCommand(struct nl_msg *nl_msg ATTRIBUTE_UNUSED,
+ virNetlinkDumpCallback callback ATTRIBUTE_UNUSED,
+ uint32_t src_pid ATTRIBUTE_UNUSED,
+ uint32_t dst_pid ATTRIBUTE_UNUSED,
+ unsigned int protocol ATTRIBUTE_UNUSED,
+ unsigned int groups ATTRIBUTE_UNUSED,
+ void *opaque ATTRIBUTE_UNUSED)
+{
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(unsupported));
+ return -1;
+}
int
virNetlinkDumpLink(const char *ifname ATTRIBUTE_UNUSED,
diff --git a/src/util/virnetlink.h b/src/util/virnetlink.h
index 11e817c82..088b01343 100644
--- a/src/util/virnetlink.h
+++ b/src/util/virnetlink.h
@@ -52,6 +52,15 @@ int virNetlinkCommand(struct nl_msg *nl_msg,
uint32_t src_pid, uint32_t dst_pid,
unsigned int protocol, unsigned int groups);
+typedef int (*virNetlinkDumpCallback)(const struct nlmsghdr *resp,
+ void *data);
+
+int virNetlinkDumpCommand(struct nl_msg *nl_msg,
+ virNetlinkDumpCallback callback,
+ uint32_t src_pid, uint32_t dst_pid,
+ unsigned int protocol, unsigned int groups,
+ void *opaque);
+
typedef int (*virNetlinkDelLinkFallback)(const char *ifname);
int virNetlinkDelLink(const char *ifname, virNetlinkDelLinkFallback fallback);
--
2.12.0

View File

@ -0,0 +1,165 @@
From d68cb4f554d16c2af79f64749e18d7d6cd9dd5b9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com>
Date: Fri, 3 Mar 2017 12:16:32 +0100
Subject: [PATCH 1/5] util: extract the request sending code from
virNetlinkCommand()
Allow to reuse as much as possible from virNetlinkCommand(). This
comment prepares for the introduction of virNetlinkDumpCommand()
only differing by how it handles the responses.
---
src/util/virnetlink.c | 89 +++++++++++++++++++++++++++++++--------------------
1 file changed, 54 insertions(+), 35 deletions(-)
diff --git a/src/util/virnetlink.c b/src/util/virnetlink.c
index a5d10fa8e..be00351db 100644
--- a/src/util/virnetlink.c
+++ b/src/util/virnetlink.c
@@ -209,61 +209,38 @@ virNetlinkCreateSocket(int protocol)
goto cleanup;
}
-
-/**
- * virNetlinkCommand:
- * @nlmsg: pointer to netlink message
- * @respbuf: pointer to pointer where response buffer will be allocated
- * @respbuflen: pointer to integer holding the size of the response buffer
- * on return of the function.
- * @src_pid: the pid of the process to send a message
- * @dst_pid: the pid of the process to talk to, i.e., pid = 0 for kernel
- * @protocol: netlink protocol
- * @groups: the group identifier
- *
- * Send the given message to the netlink layer and receive response.
- * Returns 0 on success, -1 on error. In case of error, no response
- * buffer will be returned.
- */
-int virNetlinkCommand(struct nl_msg *nl_msg,
- struct nlmsghdr **resp, unsigned int *respbuflen,
- uint32_t src_pid, uint32_t dst_pid,
+static virNetlinkHandle *
+virNetlinkSendRequest(struct nl_msg *nl_msg, uint32_t src_pid,
+ struct sockaddr_nl nladdr,
unsigned int protocol, unsigned int groups)
{
- int ret = -1;
- struct sockaddr_nl nladdr = {
- .nl_family = AF_NETLINK,
- .nl_pid = dst_pid,
- .nl_groups = 0,
- };
ssize_t nbytes;
- struct pollfd fds[1];
int fd;
int n;
- struct nlmsghdr *nlmsg = nlmsg_hdr(nl_msg);
virNetlinkHandle *nlhandle = NULL;
- int len = 0;
+ struct pollfd fds[1];
+ struct nlmsghdr *nlmsg = nlmsg_hdr(nl_msg);
if (protocol >= MAX_LINKS) {
virReportSystemError(EINVAL,
_("invalid protocol argument: %d"), protocol);
- goto cleanup;
+ goto error;
}
if (!(nlhandle = virNetlinkCreateSocket(protocol)))
- goto cleanup;
+ goto error;
fd = nl_socket_get_fd(nlhandle);
if (fd < 0) {
virReportSystemError(errno,
"%s", _("cannot get netlink socket fd"));
- goto cleanup;
+ goto error;
}
if (groups && nl_socket_add_membership(nlhandle, groups) < 0) {
virReportSystemError(errno,
"%s", _("cannot add netlink membership"));
- goto cleanup;
+ goto error;
}
nlmsg_set_dst(nl_msg, &nladdr);
@@ -274,10 +251,11 @@ int virNetlinkCommand(struct nl_msg *nl_msg,
if (nbytes < 0) {
virReportSystemError(errno,
"%s", _("cannot send to netlink socket"));
- goto cleanup;
+ goto error;
}
memset(fds, 0, sizeof(fds));
+
fds[0].fd = fd;
fds[0].events = POLLIN;
@@ -289,9 +267,51 @@ int virNetlinkCommand(struct nl_msg *nl_msg,
if (n == 0)
virReportSystemError(ETIMEDOUT, "%s",
_("no valid netlink response was received"));
- goto cleanup;
}
+ return nlhandle;
+
+ error:
+ virNetlinkFree(nlhandle);
+ return NULL;
+}
+
+/**
+ * virNetlinkCommand:
+ * @nlmsg: pointer to netlink message
+ * @respbuf: pointer to pointer where response buffer will be allocated
+ * @respbuflen: pointer to integer holding the size of the response buffer
+ * on return of the function.
+ * @src_pid: the pid of the process to send a message
+ * @dst_pid: the pid of the process to talk to, i.e., pid = 0 for kernel
+ * @protocol: netlink protocol
+ * @groups: the group identifier
+ *
+ * Send the given message to the netlink layer and receive response.
+ * Returns 0 on success, -1 on error. In case of error, no response
+ * buffer will be returned.
+ */
+int virNetlinkCommand(struct nl_msg *nl_msg,
+ struct nlmsghdr **resp, unsigned int *respbuflen,
+ uint32_t src_pid, uint32_t dst_pid,
+ unsigned int protocol, unsigned int groups)
+{
+ int ret = -1;
+ struct sockaddr_nl nladdr = {
+ .nl_family = AF_NETLINK,
+ .nl_pid = dst_pid,
+ .nl_groups = 0,
+ };
+ struct pollfd fds[1];
+ virNetlinkHandle *nlhandle = NULL;
+ int len = 0;
+
+ memset(fds, 0, sizeof(fds));
+
+ if (!(nlhandle = virNetlinkSendRequest(nl_msg, src_pid, nladdr,
+ protocol, groups)))
+ goto cleanup;
+
len = nl_recv(nlhandle, &nladdr, (unsigned char **)resp, NULL);
if (len == 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -315,7 +335,6 @@ int virNetlinkCommand(struct nl_msg *nl_msg,
return ret;
}
-
/**
* virNetlinkDumpLink:
*
--
2.12.0

View File

@ -1,3 +1,16 @@
-------------------------------------------------------------------
Wed Mar 22 08:30:55 UTC 2017 - cbosdonnat@suse.com
- Fail to start network instead of losing routes if IPv6 forwarding
is required. bsc#1025252
Added patches:
00d28a78b-check-accept_ra-before-enabling-ipv6-forward.patch
3ee35d7d6-more-uses-of-SYSCTL_PATH.patch
5dd607059-add-virNetDevGetName.patch
754515b7d-add-virNetlinkDumpCommand.patch
d68cb4f55-extract-the-request-sending-code-from-virNetlin.patch
-------------------------------------------------------------------
Thu Mar 16 14:23:16 UTC 2017 - jfehlig@suse.com

View File

@ -1,7 +1,7 @@
#
# spec file for package libvirt
#
# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
# Copyright (c) 2017 SUSE LINUX Products GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@ -319,6 +319,11 @@ Source100: %{name}-rpmlintrc
# Upstream patches
Patch0: 67dcb797-virTimeBackOffWait-sleepcap.patch
Patch1: 85af0b80-qemu-adaptive-montimeout.patch
Patch2: d68cb4f55-extract-the-request-sending-code-from-virNetlin.patch
Patch3: 754515b7d-add-virNetlinkDumpCommand.patch
Patch4: 3ee35d7d6-more-uses-of-SYSCTL_PATH.patch
Patch5: 5dd607059-add-virNetDevGetName.patch
Patch6: 00d28a78b-check-accept_ra-before-enabling-ipv6-forward.patch
# Patches pending upstream review
Patch100: libxl-dom-reset.patch
Patch101: network-don-t-use-dhcp-authoritative-on-static-netwo.patch
@ -818,9 +823,9 @@ capabilities of recent versions of Linux (and other OSes).
%package libs
Summary: Client side libraries for libvirt
Group: Development/Libraries/C and C++
# So remote clients can access libvirt over SSH tunnel
# (client invokes 'nc' against the UNIX socket on the server)
Group: Development/Libraries/C and C++
Requires: netcat-openbsd
# Not technically required, but makes 'out-of-box' config
# work correctly & doesn't have onerous dependencies
@ -888,6 +893,11 @@ libvirt plugin for NSS for translating domain names into IP addresses.
%setup -q
%patch0 -p1
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch100 -p1
%patch101 -p1
%patch150 -p1