[libvirt] [PATCH v3 0/4] qemu: use arp table of host to get the

introduce VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP to get ip address of VM from the output of /proc/net/arp Chen Hanxiao (4): util: introduce helper to parse /proc/net/arp qemu: introduce qemuARPGetInterfaces to get IP from host's arp table virsh: add --source arp to domifaddr news: qemu: use arp table of host to get the IP address of guests docs/news.xml | 9 ++++ include/libvirt/libvirt-domain.h | 1 + po/POTFILES.in | 1 + src/Makefile.am | 1 + src/libvirt-domain.c | 7 +++ src/libvirt_private.syms | 5 ++ src/qemu/qemu_driver.c | 96 +++++++++++++++++++++++++++++++++ src/util/virarptable.c | 114 +++++++++++++++++++++++++++++++++++++++ src/util/virarptable.h | 48 +++++++++++++++++ tools/virsh-domain-monitor.c | 2 + tools/virsh.pod | 7 +-- 11 files changed, 288 insertions(+), 3 deletions(-) create mode 100644 src/util/virarptable.c create mode 100644 src/util/virarptable.h -- 2.14.3

From: Chen Hanxiao <chenhanxiao@gmail.com> introduce helper to parse /proc/net/arp and store it in struct virArpTable. Signed-off-by: Chen Hanxiao <chenhanxiao@gmail.com> --- v3: s/virGetArpTable/virArpTableGet alloc virArpTable in virArpTableGet return ENOSUPP on none-Linux platform move helpers to virarptable.[ch] po/POTFILES.in | 1 + src/Makefile.am | 1 + src/libvirt_private.syms | 5 +++ src/util/virarptable.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virarptable.h | 48 ++++++++++++++++++++ 5 files changed, 169 insertions(+) create mode 100644 src/util/virarptable.c create mode 100644 src/util/virarptable.h diff --git a/po/POTFILES.in b/po/POTFILES.in index 8382ee633..91a4c5730 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -193,6 +193,7 @@ src/uml/uml_conf.c src/uml/uml_driver.c src/util/iohelper.c src/util/viralloc.c +src/util/virarptable.c src/util/viraudit.c src/util/virauth.c src/util/virauthconfig.c diff --git a/src/Makefile.am b/src/Makefile.am index 289b03747..923eea6fe 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -98,6 +98,7 @@ augeastest_DATA = UTIL_SOURCES = \ util/viralloc.c util/viralloc.h \ util/virarch.h util/virarch.c \ + util/virarptable.h util/virarptable.c \ util/viratomic.h util/viratomic.c \ util/viraudit.c util/viraudit.h \ util/virauth.c util/virauth.h \ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index f2a2c8650..08229797a 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1332,6 +1332,11 @@ virArchGetWordSize; virArchToString; +# util/virarptable.h +virArpTableFree; +virArpTableGet; + + # util/viraudit.h virAuditClose; virAuditEncode; diff --git a/src/util/virarptable.c b/src/util/virarptable.c new file mode 100644 index 000000000..48a38352f --- /dev/null +++ b/src/util/virarptable.c @@ -0,0 +1,114 @@ +/* + * virarptable.c Linux ARP table handling + * + * Copyright (C) 2018 Chen Hanxiao + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Authors: + * Chen Hanxiao <chenhanxiao@gmail.com> + */ + +#include <config.h> + +#include <stdlib.h> +#include <stdio.h> + +#include "viralloc.h" +#include "virarptable.h" +#include "virfile.h" +#include "virstring.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + +#ifdef __linux__ + +virArpTablePtr virArpTableGet(void) +{ + FILE *fp = NULL; + char line[1024]; + int num = 0; + virArpTablePtr table = NULL; + + if (VIR_ALLOC(table) < 0) + return NULL; + + if (!(fp = fopen("/proc/net/arp", "r"))) + goto cleanup; + + while (fgets(line, sizeof(line), fp)) { + char ip[32], mac[32], dev_name[32], hwtype[32], + flags[32], mask[32], nouse[32]; + + if (STRPREFIX(line, "IP address")) + continue; + + if (VIR_REALLOC_N(table->t, num + 1) < 0) + goto cleanup; + + table->n = num + 1; + + /* /proc/net/arp looks like: + * 172.16.17.254 0x1 0x2 e4:68:a3:8d:ed:d3 * enp3s0 + */ + sscanf(line, "%[0-9.]%[ ]%[^ ]%[ ]%[^ ]%[ ]%[^ ]%[ ]%[^ ]%[ ]%[^ \t\n]", + ip, nouse, + hwtype, nouse, + flags, nouse, + mac, nouse, + mask, nouse, + dev_name); + + if (VIR_STRDUP(table->t[num].ipaddr, ip) < 0) + goto cleanup; + + if (VIR_STRDUP(table->t[num].mac, mac) < 0) + goto cleanup; + + if (VIR_STRDUP(table->t[num].dev_name, dev_name) < 0) + goto cleanup; + + num++; + } + + return table; + + cleanup: + VIR_FORCE_FCLOSE(fp); + return NULL; +} + +#else + +virArpTablePtr virArpTableGet(void) +{ + virReportError(VIR_ERR_NO_SUPPORT, "%s", + _("get arp table not implemented on this platform")); + return NULL; +} + +#endif /* __linux__ */ + +void +virArpTableFree(virArpTablePtr table) +{ + size_t i; + for (i = 0; i < table->n; i++) { + VIR_FREE(table->t[i].ipaddr); + VIR_FREE(table->t[i].mac); + VIR_FREE(table->t[i].dev_name); + } + VIR_FREE(table); +} diff --git a/src/util/virarptable.h b/src/util/virarptable.h new file mode 100644 index 000000000..77db4e9f4 --- /dev/null +++ b/src/util/virarptable.h @@ -0,0 +1,48 @@ +/* + * virarptable.h Linux ARP table handling + * + * Copyright (C) 2018 Chen Hanxiao + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Authors: + * Chen Hanxiao <chenhanxiao@gmail.com> + */ + +#ifndef __VIR_ARPTABLE_H__ +# define __VIR_ARPTABLE_H__ + +# include "internal.h" + +typedef struct _virArpTableEntry virArpTableEntry; +typedef virArpTableEntry *virArpTableEntryPtr; +typedef struct _virArpTable virArpTable; +typedef virArpTable *virArpTablePtr; + +struct _virArpTableEntry{ + char *ipaddr; + char *mac; + char *dev_name; +}; + +struct _virArpTable { + int n; + virArpTableEntryPtr t; +}; + +virArpTablePtr virArpTableGet(void); +void virArpTableFree(virArpTablePtr table); + +#endif /* __VIR_ARPTABLE_H__ */ -- 2.14.3

On Mon, Jan 29, 2018 at 16:35:33 +0800, Chen Hanxiao wrote:
From: Chen Hanxiao <chenhanxiao@gmail.com>
introduce helper to parse /proc/net/arp and store it in struct virArpTable.
Signed-off-by: Chen Hanxiao <chenhanxiao@gmail.com> --- v3: s/virGetArpTable/virArpTableGet alloc virArpTable in virArpTableGet return ENOSUPP on none-Linux platform move helpers to virarptable.[ch]
po/POTFILES.in | 1 + src/Makefile.am | 1 + src/libvirt_private.syms | 5 +++ src/util/virarptable.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++ src/util/virarptable.h | 48 ++++++++++++++++++++ 5 files changed, 169 insertions(+) create mode 100644 src/util/virarptable.c create mode 100644 src/util/virarptable.h
diff --git a/po/POTFILES.in b/po/POTFILES.in index 8382ee633..91a4c5730 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -193,6 +193,7 @@ src/uml/uml_conf.c src/uml/uml_driver.c src/util/iohelper.c src/util/viralloc.c +src/util/virarptable.c src/util/viraudit.c src/util/virauth.c src/util/virauthconfig.c diff --git a/src/Makefile.am b/src/Makefile.am index 289b03747..923eea6fe 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -98,6 +98,7 @@ augeastest_DATA = UTIL_SOURCES = \ util/viralloc.c util/viralloc.h \ util/virarch.h util/virarch.c \ + util/virarptable.h util/virarptable.c \ util/viratomic.h util/viratomic.c \ util/viraudit.c util/viraudit.h \ util/virauth.c util/virauth.h \ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index f2a2c8650..08229797a 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1332,6 +1332,11 @@ virArchGetWordSize; virArchToString;
+# util/virarptable.h +virArpTableFree; +virArpTableGet; + + # util/viraudit.h virAuditClose; virAuditEncode; diff --git a/src/util/virarptable.c b/src/util/virarptable.c new file mode 100644 index 000000000..48a38352f --- /dev/null +++ b/src/util/virarptable.c @@ -0,0 +1,114 @@ +/* + * virarptable.c Linux ARP table handling + * + * Copyright (C) 2018 Chen Hanxiao + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + * Authors: + * Chen Hanxiao <chenhanxiao@gmail.com> + */ + +#include <config.h> + +#include <stdlib.h> +#include <stdio.h> + +#include "viralloc.h" +#include "virarptable.h" +#include "virfile.h" +#include "virstring.h" + +#define VIR_FROM_THIS VIR_FROM_NONE + +#ifdef __linux__ + +virArpTablePtr virArpTableGet(void) +{ + FILE *fp = NULL; + char line[1024]; + int num = 0; + virArpTablePtr table = NULL; + + if (VIR_ALLOC(table) < 0) + return NULL; + + if (!(fp = fopen("/proc/net/arp", "r"))) + goto cleanup; + + while (fgets(line, sizeof(line), fp)) { + char ip[32], mac[32], dev_name[32], hwtype[32],
I don't think hardcoding the lenghts ...
+ flags[32], mask[32], nouse[32]; + + if (STRPREFIX(line, "IP address")) + continue; + + if (VIR_REALLOC_N(table->t, num + 1) < 0) + goto cleanup; + + table->n = num + 1; + + /* /proc/net/arp looks like: + * 172.16.17.254 0x1 0x2 e4:68:a3:8d:ed:d3 * enp3s0 + */ + sscanf(line, "%[0-9.]%[ ]%[^ ]%[ ]%[^ ]%[ ]%[^ ]%[ ]%[^ ]%[ ]%[^ \t\n]",
without limiting the size here is a great idea. That is a buffer overflow right here. Also parsing /proc/net/arp is not enough, it will not list IPv6 neighbors. Additionally I'd stay away from parsing this file completely. Not even the obsolete 'arp' utility is using this but rather uses AF_NETLINK socket to discover it. NACK on this approach.

At 2018-01-29 20:01:30, "Peter Krempa" <pkrempa@redhat.com> wrote:
On Mon, Jan 29, 2018 at 16:35:33 +0800, Chen Hanxiao wrote:
From: Chen Hanxiao <chenhanxiao@gmail.com>
introduce helper to parse /proc/net/arp and store it in struct virArpTable.
Signed-off-by: Chen Hanxiao <chenhanxiao@gmail.com> --- v3: [...]
without limiting the size here is a great idea. That is a buffer overflow right here.
Also parsing /proc/net/arp is not enough, it will not list IPv6 neighbors.
Additionally I'd stay away from parsing this file completely. Not even the obsolete 'arp' utility is using this but rather uses AF_NETLINK socket to discover it.
NACK on this approach.
I'll use RTM_GETNEIGH to get these. Thanks for the advice. Regards, - Chen

From: Chen Hanxiao <chenhanxiao@gmail.com> introduce VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP to get ip address of VM from the output of /proc/net/arp Signed-off-by: Chen Hanxiao <chenhanxiao@gmail.com> --- v3: add docs in virDomainInterfaceAddresses remove error label show network interface which did not match the arp table include/libvirt/libvirt-domain.h | 1 + src/libvirt-domain.c | 7 +++ src/qemu/qemu_driver.c | 96 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 4048acf38..38e2d9a3e 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -4665,6 +4665,7 @@ typedef virMemoryParameter *virMemoryParameterPtr; typedef enum { VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE = 0, /* Parse DHCP lease file */ VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT = 1, /* Query qemu guest agent */ + VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP = 2, /* Query ARP tables */ # ifdef VIR_ENUM_SENTINELS VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LAST diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index eaec0979a..1ae83610d 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -11721,6 +11721,13 @@ virDomainFSInfoFree(virDomainFSInfoPtr info) * To match such interface with the one from @dom XML use MAC address or IP * range. * + * If @source is VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP, the /proc/net/arp + * will be check to obtain the interface addresses. + * As the arp cache did not refresh in time, the returned ip address + * may be unreachable. + * As the route config of the guest, the returned mac address + * may be duplicated. + * * @ifaces->name and @ifaces->hwaddr are never NULL. * * The caller *must* free @ifaces when no longer needed. Usual use case diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index a203c9297..d0cb88053 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -70,6 +70,7 @@ #include "virnetdevopenvswitch.h" #include "capabilities.h" #include "viralloc.h" +#include "virarptable.h" #include "viruuid.h" #include "domain_conf.h" #include "domain_audit.h" @@ -160,6 +161,9 @@ static int qemuGetDHCPInterfaces(virDomainPtr dom, virDomainObjPtr vm, virDomainInterfacePtr **ifaces); +static int qemuARPGetInterfaces(virDomainObjPtr vm, + virDomainInterfacePtr **ifaces); + static virQEMUDriverPtr qemu_driver; @@ -20384,6 +20388,10 @@ qemuDomainInterfaceAddresses(virDomainPtr dom, break; + case VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP: + ret = qemuARPGetInterfaces(vm, ifaces); + break; + default: virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, _("Unknown IP address data source %d"), @@ -20494,6 +20502,94 @@ qemuGetDHCPInterfaces(virDomainPtr dom, } +static int +qemuARPGetInterfaces(virDomainObjPtr vm, + virDomainInterfacePtr **ifaces) +{ + size_t i, j; + size_t ifaces_count = 0; + int ret = -1; + char macaddr[VIR_MAC_STRING_BUFLEN]; + virDomainInterfacePtr *ifaces_ret = NULL; + virDomainInterfacePtr iface = NULL; + virArpTablePtr table; + int got_one = 0; + + table = virArpTableGet(); + if (!table) + goto cleanup; + + for (i = 0; i < vm->def->nnets; i++) { + got_one = 0; + if (vm->def->nets[i]->type != VIR_DOMAIN_NET_TYPE_NETWORK) + continue; + + virMacAddrFormat(&(vm->def->nets[i]->mac), macaddr); + virArpTableEntry entry; + for (j = 0; j < table->n; j++) { + entry = table->t[j]; + if (STREQ(entry.mac, macaddr)) { + got_one = 1; + if (VIR_EXPAND_N(ifaces_ret, ifaces_count, 1) < 0) + goto cleanup; + if (VIR_ALLOC(ifaces_ret[ifaces_count - 1]) < 0) + goto cleanup; + + iface = ifaces_ret[ifaces_count - 1]; + iface->naddrs = 1; + if (VIR_ALLOC_N(iface->addrs, iface->naddrs) < 0) + goto cleanup; + + if (VIR_STRDUP(iface->name, vm->def->nets[i]->ifname) < 0) + goto cleanup; + + if (VIR_STRDUP(iface->hwaddr, macaddr) < 0) + goto cleanup; + + if (VIR_STRDUP(iface->addrs->addr, entry.ipaddr) < 0) + goto cleanup; + } + } + + if (got_one == 0) { + if (VIR_EXPAND_N(ifaces_ret, ifaces_count, 1) < 0) + goto cleanup; + if (VIR_ALLOC(ifaces_ret[ifaces_count - 1]) < 0) + goto cleanup; + + iface = ifaces_ret[ifaces_count - 1]; + iface->naddrs = 1; + if (VIR_ALLOC_N(iface->addrs, iface->naddrs) < 0) + goto cleanup; + + if (VIR_STRDUP(iface->name, "") < 0) + goto cleanup; + + if (VIR_STRDUP(iface->hwaddr, macaddr) < 0) + goto cleanup; + + if (VIR_STRDUP(iface->addrs->addr, "") < 0) + goto cleanup; + } + } + + *ifaces = ifaces_ret; + ifaces_ret = NULL; + ret = ifaces_count; + + cleanup: + virArpTableFree(table); + + if (ifaces_ret) { + for (i = 0; i < ifaces_count; i++) + virDomainInterfaceFree(ifaces_ret[i]); + } + VIR_FREE(ifaces_ret); + + return ret; +} + + static int qemuDomainSetUserPassword(virDomainPtr dom, const char *user, -- 2.14.3

On Mon, Jan 29, 2018 at 16:35:34 +0800, Chen Hanxiao wrote:
From: Chen Hanxiao <chenhanxiao@gmail.com>
introduce VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP to get ip address of VM from the output of /proc/net/arp
Signed-off-by: Chen Hanxiao <chenhanxiao@gmail.com> --- v3: add docs in virDomainInterfaceAddresses remove error label show network interface which did not match the arp table
include/libvirt/libvirt-domain.h | 1 + src/libvirt-domain.c | 7 +++ src/qemu/qemu_driver.c | 96 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+)
diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h index 4048acf38..38e2d9a3e 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -4665,6 +4665,7 @@ typedef virMemoryParameter *virMemoryParameterPtr; typedef enum { VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE = 0, /* Parse DHCP lease file */ VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT = 1, /* Query qemu guest agent */ + VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP = 2, /* Query ARP tables */
# ifdef VIR_ENUM_SENTINELS VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LAST diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index eaec0979a..1ae83610d 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -11721,6 +11721,13 @@ virDomainFSInfoFree(virDomainFSInfoPtr info) * To match such interface with the one from @dom XML use MAC address or IP * range. * + * If @source is VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP, the /proc/net/arp + * will be check to obtain the interface addresses. + * As the arp cache did not refresh in time, the returned ip address + * may be unreachable. + * As the route config of the guest, the returned mac address + * may be duplicated. + * * @ifaces->name and @ifaces->hwaddr are never NULL. * * The caller *must* free @ifaces when no longer needed. Usual use case diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index a203c9297..d0cb88053 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -70,6 +70,7 @@ #include "virnetdevopenvswitch.h" #include "capabilities.h" #include "viralloc.h" +#include "virarptable.h" #include "viruuid.h" #include "domain_conf.h" #include "domain_audit.h" @@ -160,6 +161,9 @@ static int qemuGetDHCPInterfaces(virDomainPtr dom, virDomainObjPtr vm, virDomainInterfacePtr **ifaces);
+static int qemuARPGetInterfaces(virDomainObjPtr vm, + virDomainInterfacePtr **ifaces); + static virQEMUDriverPtr qemu_driver;
@@ -20384,6 +20388,10 @@ qemuDomainInterfaceAddresses(virDomainPtr dom,
break;
+ case VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP: + ret = qemuARPGetInterfaces(vm, ifaces); + break; + default: virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, _("Unknown IP address data source %d"), @@ -20494,6 +20502,94 @@ qemuGetDHCPInterfaces(virDomainPtr dom, }
+static int +qemuARPGetInterfaces(virDomainObjPtr vm, + virDomainInterfacePtr **ifaces) +{ + size_t i, j; + size_t ifaces_count = 0; + int ret = -1; + char macaddr[VIR_MAC_STRING_BUFLEN]; + virDomainInterfacePtr *ifaces_ret = NULL; + virDomainInterfacePtr iface = NULL; + virArpTablePtr table; + int got_one = 0;
Isn't this a bool in fact?
+ + table = virArpTableGet(); + if (!table) + goto cleanup; + + for (i = 0; i < vm->def->nnets; i++) { + got_one = 0; + if (vm->def->nets[i]->type != VIR_DOMAIN_NET_TYPE_NETWORK) + continue; + + virMacAddrFormat(&(vm->def->nets[i]->mac), macaddr); + virArpTableEntry entry; + for (j = 0; j < table->n; j++) { + entry = table->t[j]; + if (STREQ(entry.mac, macaddr)) { + got_one = 1; + if (VIR_EXPAND_N(ifaces_ret, ifaces_count, 1) < 0) + goto cleanup; + if (VIR_ALLOC(ifaces_ret[ifaces_count - 1]) < 0) + goto cleanup; +
VIR_APPEND_ELEMENT Looks like you inspired youself in qemuAgentGetInterfaces which isn't probably the right place for nice code.
+ iface = ifaces_ret[ifaces_count - 1]; + iface->naddrs = 1; + if (VIR_ALLOC_N(iface->addrs, iface->naddrs) < 0) + goto cleanup; + + if (VIR_STRDUP(iface->name, vm->def->nets[i]->ifname) < 0) + goto cleanup; + + if (VIR_STRDUP(iface->hwaddr, macaddr) < 0) + goto cleanup; + + if (VIR_STRDUP(iface->addrs->addr, entry.ipaddr) < 0) + goto cleanup; + } + } + + if (got_one == 0) {
Why do you add a dummy entry if given interface does not have one? No other gathering method does this.
+ if (VIR_EXPAND_N(ifaces_ret, ifaces_count, 1) < 0) + goto cleanup; + if (VIR_ALLOC(ifaces_ret[ifaces_count - 1]) < 0) + goto cleanup; + + iface = ifaces_ret[ifaces_count - 1]; + iface->naddrs = 1; + if (VIR_ALLOC_N(iface->addrs, iface->naddrs) < 0) + goto cleanup; + + if (VIR_STRDUP(iface->name, "") < 0) + goto cleanup; + + if (VIR_STRDUP(iface->hwaddr, macaddr) < 0) + goto cleanup; + + if (VIR_STRDUP(iface->addrs->addr, "") < 0) + goto cleanup; + } + } + + *ifaces = ifaces_ret; + ifaces_ret = NULL;
VIR_STEAL_PTR
+ ret = ifaces_count; + + cleanup: + virArpTableFree(table); + + if (ifaces_ret) { + for (i = 0; i < ifaces_count; i++) + virDomainInterfaceFree(ifaces_ret[i]); + } + VIR_FREE(ifaces_ret); + + return ret; +} + + static int qemuDomainSetUserPassword(virDomainPtr dom, const char *user, -- 2.14.3
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

From: Chen Hanxiao <chenhanxiao@gmail.com> We can use: domifaddr f26-cloud --source arp to get the address. Acked-by: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Chen Hanxiao <chenhanxiao@gmail.com> --- tools/virsh-domain-monitor.c | 2 ++ tools/virsh.pod | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/virsh-domain-monitor.c b/tools/virsh-domain-monitor.c index 32a42707e..68da11ed5 100644 --- a/tools/virsh-domain-monitor.c +++ b/tools/virsh-domain-monitor.c @@ -2190,6 +2190,8 @@ cmdDomIfAddr(vshControl *ctl, const vshCmd *cmd) source = VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE; } else if (STREQ(sourcestr, "agent")) { source = VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT; + } else if (STREQ(sourcestr, "arp")) { + source = VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP; } else { vshError(ctl, _("Unknown data source '%s'"), sourcestr); goto cleanup; diff --git a/tools/virsh.pod b/tools/virsh.pod index 69cc42338..1dfe2a9b0 100644 --- a/tools/virsh.pod +++ b/tools/virsh.pod @@ -759,7 +759,7 @@ B<Explanation of fields> (fields appear in the following order): =item B<domifaddr> I<domain> [I<interface>] [I<--full>] - [I<--source lease|agent>] + [I<--source lease|agent|arp>] Get a list of interfaces of a running domain along with their IP and MAC addresses, or limited output just for one interface if I<interface> is @@ -774,8 +774,9 @@ only the interface name and MAC address is displayed for the first name and MAC address with "-" for the others using the same name and MAC address. The I<--source> argument specifies what data source to use for the -addresses, currently one of 'lease' to read DHCP leases, or 'agent' to query -the guest OS via an agent. If unspecified, 'lease' is the default. +addresses, currently 'lease' to read DHCP leases, 'agent' to query +the guest OS via an agent, or 'arp' to get IP from host's arp tables. +If unspecified, 'lease' is the default. =item B<domifstat> I<domain> I<interface-device> -- 2.14.3

From: Chen Hanxiao <chenhanxiao@gmail.com> Signed-off-by: Chen Hanxiao <chenhanxiao@gmail.com> --- v3: more verbose description docs/news.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/news.xml b/docs/news.xml index 2268fdf79..706546e6d 100644 --- a/docs/news.xml +++ b/docs/news.xml @@ -56,6 +56,15 @@ interfaces, NWFilters, and so on). </description> </change> + <change> + <summary> + qemu: use arp table of host to get the IP address of guests + </summary> + <description> + Find IP address of a VM by arp table on hosts. + If someone customizing IP address inside VM, it will be helpful. + </description> + </change> </section> <section title="Bug fixes"> </section> -- 2.14.3
participants (2)
-
Chen Hanxiao
-
Peter Krempa