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:
parent
51e9f38d3f
commit
79b3a063e4
260
00d28a78b-check-accept_ra-before-enabling-ipv6-forward.patch
Normal file
260
00d28a78b-check-accept_ra-before-enabling-ipv6-forward.patch
Normal 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
|
||||
|
46
3ee35d7d6-more-uses-of-SYSCTL_PATH.patch
Normal file
46
3ee35d7d6-more-uses-of-SYSCTL_PATH.patch
Normal 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
|
||||
|
70
5dd607059-add-virNetDevGetName.patch
Normal file
70
5dd607059-add-virNetDevGetName.patch
Normal 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
|
||||
|
125
754515b7d-add-virNetlinkDumpCommand.patch
Normal file
125
754515b7d-add-virNetlinkDumpCommand.patch
Normal 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
|
||||
|
165
d68cb4f55-extract-the-request-sending-code-from-virNetlin.patch
Normal file
165
d68cb4f55-extract-the-request-sending-code-from-virNetlin.patch
Normal 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
|
||||
|
@ -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
|
||||
|
||||
|
14
libvirt.spec
14
libvirt.spec
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user