From: Chen Hanxiao <chenhanxiao@gmail.com>
introduce helper to parse RTM_GETNEIGH query message and
store it in struct virArpTable.
Signed-off-by: Chen Hanxiao <chenhanxiao@gmail.com>
---
v4-rebase:
fit split Makefile.am
fit new virMacAddr fields
v4:
use netlink query instead of parsing /proc/net/arp
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/Makefile.inc.am | 2 +
src/util/virarptable.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++
src/util/virarptable.h | 48 +++++++++++++
6 files changed, 238 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 cfdd4ebdd..71c61dec9 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -192,6 +192,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 8b1e4c8a4..82c5d5cde 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -672,6 +672,7 @@ noinst_LTLIBRARIES += libvirt-setuid-rpc-client.la
libvirt_setuid_rpc_client_la_SOURCES = \
util/viralloc.c \
util/virarch.c \
+ util/virarptable.c \
util/viratomic.c \
util/viratomic.h \
util/virbitmap.c \
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 11b9f4937..05b0c5b0e 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1365,6 +1365,11 @@ virArchGetWordSize;
virArchToString;
+# util/virarptable.h
+virArpTableFree;
+virArpTableGet;
+
+
# util/viraudit.h
virAuditClose;
virAuditEncode;
diff --git a/src/util/Makefile.inc.am b/src/util/Makefile.inc.am
index a91b30dca..02d9c42cc 100644
--- a/src/util/Makefile.inc.am
+++ b/src/util/Makefile.inc.am
@@ -5,6 +5,8 @@ UTIL_SOURCES = \
util/viralloc.h \
util/virarch.c \
util/virarch.h \
+ util/virarptable.c \
+ util/virarptable.h \
util/viratomic.c \
util/viratomic.h \
util/viraudit.c \
diff --git a/src/util/virarptable.c b/src/util/virarptable.c
new file mode 100644
index 000000000..cb56338eb
--- /dev/null
+++ b/src/util/virarptable.c
@@ -0,0 +1,181 @@
+/*
+ * 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 <arpa/inet.h>
+
+#include "viralloc.h"
+#include "virarptable.h"
+#include "virfile.h"
+#include "virlog.h"
+#include "virnetlink.h"
+#include "virsocketaddr.h"
+#include "virstring.h"
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+VIR_LOG_INIT("util.arptable");
+
+#ifdef __linux__
+
+# define NDA_RTA(r) \
+ ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
+
+static int
+parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
+{
+ memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
+ while (RTA_OK(rta, len)) {
+ if ((rta->rta_type <= max) && (!tb[rta->rta_type]))
+ tb[rta->rta_type] = rta;
+ rta = RTA_NEXT(rta, len);
+ }
+
+ if (len)
+ VIR_WARN("malformed netlink message: Deficit %d, rta_len=%d",
+ len, rta->rta_len);
+ return 0;
+}
+
+virArpTablePtr virArpTableGet(void)
+{
+ int num = 0;
+ int msglen;
+ void *nlData = NULL;
+ virArpTablePtr table = NULL;
+ char *ipstr = NULL;
+ struct nlmsghdr* nh;
+ struct rtattr * tb[NDA_MAX+1];
+
+ msglen = virNetlinkGetNeighbor(&nlData, 0, 0);
+ if (msglen < 0)
+ return NULL;
+
+ if (VIR_ALLOC(table) < 0)
+ return NULL;
+
+ nh = (struct nlmsghdr*)nlData;
+
+ while (NLMSG_OK(nh, msglen)) {
+ struct ndmsg *r = NLMSG_DATA(nh);
+ int len = nh->nlmsg_len;
+ void *addr;
+
+ if ((len -= NLMSG_LENGTH(sizeof(*nh))) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("wrong nlmsg len"));
+ goto cleanup;
+ }
+
+ if (r->ndm_family && (r->ndm_family != AF_INET))
+ goto next_nlmsg;
+
+ /* catch stale and reachalbe arp entry only */
+ if (r->ndm_state &&
+ (!(r->ndm_state == NUD_STALE || r->ndm_state == NUD_REACHABLE))) {
+ nh = NLMSG_NEXT(nh, msglen);
+ continue;
+ }
+
+ if (nh->nlmsg_type == NLMSG_DONE)
+ goto end_of_netlink_messages;
+
+ parse_rtattr(tb, NDA_MAX, NDA_RTA(r),
+ nh->nlmsg_len - NLMSG_LENGTH(sizeof(*r)));
+
+ if (tb[NDA_DST] == NULL || tb[NDA_LLADDR] == NULL)
+ goto next_nlmsg;
+
+ if (tb[NDA_DST]) {
+ virSocketAddr virAddr;
+ if (VIR_REALLOC_N(table->t, num + 1) < 0)
+ goto cleanup;
+
+ table->n = num + 1;
+
+ addr = RTA_DATA(tb[NDA_DST]);
+ bzero(&virAddr, sizeof(virAddr));
+ virAddr.len = sizeof(virAddr.data.inet4);
+ virAddr.data.inet4.sin_family = AF_INET;
+ virAddr.data.inet4.sin_addr = *(struct in_addr *)addr;
+ ipstr = virSocketAddrFormat(&virAddr);
+
+ if (VIR_STRDUP(table->t[num].ipaddr, ipstr) < 0)
+ goto cleanup;
+
+ VIR_FREE(ipstr);
+ }
+
+ if (tb[NDA_LLADDR]) {
+ virMacAddr macaddr;
+ char ifmac[VIR_MAC_STRING_BUFLEN];
+
+ addr = RTA_DATA(tb[NDA_LLADDR]);
+ memcpy(macaddr.addr, addr, VIR_MAC_BUFLEN);
+
+ virMacAddrFormat(&macaddr, ifmac);
+
+ if (VIR_STRDUP(table->t[num].mac, ifmac) < 0)
+ goto cleanup;
+
+ num++;
+ }
+
+ next_nlmsg:
+ nh = NLMSG_NEXT(nh, msglen);
+ }
+
+ end_of_netlink_messages:
+ VIR_FREE(nlData);
+ return table;
+
+ cleanup:
+ VIR_FREE(ipstr);
+ VIR_FREE(nlData);
+ 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);
+}
diff --git a/src/util/virarptable.h b/src/util/virarptable.h
new file mode 100644
index 000000000..404d8eb86
--- /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"
+# include <linux/rtnetlink.h>
+
+typedef struct _virArpTableEntry virArpTableEntry;
+typedef virArpTableEntry *virArpTableEntryPtr;
+typedef struct _virArpTable virArpTable;
+typedef virArpTable *virArpTablePtr;
+
+struct _virArpTableEntry{
+ char *ipaddr;
+ char *mac;
+};
+
+struct _virArpTable {
+ int n;
+ virArpTableEntryPtr t;
+};
+
+virArpTablePtr virArpTableGet(void);
+void virArpTableFree(virArpTablePtr table);
+
+#endif /* __VIR_ARPTABLE_H__ */
--
2.14.3
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
On 03/08/2018 02:11 AM, Chen Hanxiao wrote: > From: Chen Hanxiao <chenhanxiao@gmail.com> > > introduce helper to parse RTM_GETNEIGH query message and > store it in struct virArpTable. > > Signed-off-by: Chen Hanxiao <chenhanxiao@gmail.com> > --- > v4-rebase: > fit split Makefile.am > fit new virMacAddr fields > > v4: > use netlink query instead of parsing /proc/net/arp > > 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/Makefile.inc.am | 2 + > src/util/virarptable.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++ > src/util/virarptable.h | 48 +++++++++++++ > 6 files changed, 238 insertions(+) > create mode 100644 src/util/virarptable.c > create mode 100644 src/util/virarptable.h > Couple of Coverity issues.... [...] > diff --git a/src/util/virarptable.c b/src/util/virarptable.c > new file mode 100644 > index 000000000..cb56338eb > --- /dev/null > +++ b/src/util/virarptable.c [...] > +# define NDA_RTA(r) \ > + ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg)))) > + > +static int > +parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) > +{ > + memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); > + while (RTA_OK(rta, len)) { > + if ((rta->rta_type <= max) && (!tb[rta->rta_type])) > + tb[rta->rta_type] = rta; > + rta = RTA_NEXT(rta, len); > + } > + > + if (len) > + VIR_WARN("malformed netlink message: Deficit %d, rta_len=%d", > + len, rta->rta_len); > + return 0; > +} > + > +virArpTablePtr virArpTableGet(void) As an aside - this format is non standard, should be virArpTablePtr virArpTableGet(void) and there should be 2 blank lines between functions. > +{ > + int num = 0; > + int msglen; > + void *nlData = NULL; > + virArpTablePtr table = NULL; > + char *ipstr = NULL; > + struct nlmsghdr* nh; > + struct rtattr * tb[NDA_MAX+1]; > + > + msglen = virNetlinkGetNeighbor(&nlData, 0, 0); > + if (msglen < 0) > + return NULL; > + > + if (VIR_ALLOC(table) < 0) > + return NULL; > + > + nh = (struct nlmsghdr*)nlData; > + > + while (NLMSG_OK(nh, msglen)) { > + struct ndmsg *r = NLMSG_DATA(nh); > + int len = nh->nlmsg_len; > + void *addr; > + > + if ((len -= NLMSG_LENGTH(sizeof(*nh))) < 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("wrong nlmsg len")); > + goto cleanup; > + } > + > + if (r->ndm_family && (r->ndm_family != AF_INET)) > + goto next_nlmsg; > + > + /* catch stale and reachalbe arp entry only */ > + if (r->ndm_state && > + (!(r->ndm_state == NUD_STALE || r->ndm_state == NUD_REACHABLE))) { > + nh = NLMSG_NEXT(nh, msglen); > + continue; > + } > + > + if (nh->nlmsg_type == NLMSG_DONE) > + goto end_of_netlink_messages; > + > + parse_rtattr(tb, NDA_MAX, NDA_RTA(r), > + nh->nlmsg_len - NLMSG_LENGTH(sizeof(*r))); > + > + if (tb[NDA_DST] == NULL || tb[NDA_LLADDR] == NULL) > + goto next_nlmsg; > + > + if (tb[NDA_DST]) { > + virSocketAddr virAddr; > + if (VIR_REALLOC_N(table->t, num + 1) < 0) > + goto cleanup; > + > + table->n = num + 1; > + > + addr = RTA_DATA(tb[NDA_DST]); > + bzero(&virAddr, sizeof(virAddr)); > + virAddr.len = sizeof(virAddr.data.inet4); > + virAddr.data.inet4.sin_family = AF_INET; > + virAddr.data.inet4.sin_addr = *(struct in_addr *)addr; > + ipstr = virSocketAddrFormat(&virAddr); > + > + if (VIR_STRDUP(table->t[num].ipaddr, ipstr) < 0) > + goto cleanup; > + > + VIR_FREE(ipstr); > + } > + > + if (tb[NDA_LLADDR]) { > + virMacAddr macaddr; > + char ifmac[VIR_MAC_STRING_BUFLEN]; > + > + addr = RTA_DATA(tb[NDA_LLADDR]); > + memcpy(macaddr.addr, addr, VIR_MAC_BUFLEN); > + > + virMacAddrFormat(&macaddr, ifmac); > + > + if (VIR_STRDUP(table->t[num].mac, ifmac) < 0) > + goto cleanup; > + > + num++; > + } > + > + next_nlmsg: > + nh = NLMSG_NEXT(nh, msglen); > + } > + > + end_of_netlink_messages: > + VIR_FREE(nlData); > + return table; > + > + cleanup: If we end up here, then @table (and anything that's allocated into it) is leaked > + VIR_FREE(ipstr); > + VIR_FREE(nlData); > + return NULL; > +} > + > +#else > + > +virArpTablePtr virArpTableGet(void) Similar comment here about the format... > +{ > + 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; This can be called by qemuARPGetInterfaces when @table == NULL, so it would be good to put in a "if (!table) return;" right here > + for (i = 0; i < table->n; i++) { > + VIR_FREE(table->t[i].ipaddr); > + VIR_FREE(table->t[i].mac); > + } > + VIR_FREE(table); > +} John [...] -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
At 2018-03-16 18:53:58, "John Ferlan" <jferlan@redhat.com> wrote: > > >On 03/08/2018 02:11 AM, Chen Hanxiao wrote: >> From: Chen Hanxiao <chenhanxiao@gmail.com> >> >> introduce helper to parse RTM_GETNEIGH query message and >> store it in struct virArpTable. >> >> Signed-off-by: Chen Hanxiao <chenhanxiao@gmail.com> >> --- >> v4-rebase: >> fit split Makefile.am >> fit new virMacAddr fields >> >> v4: >> use netlink query instead of parsing /proc/net/arp >> >> 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/Makefile.inc.am | 2 + >> src/util/virarptable.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++ >> src/util/virarptable.h | 48 +++++++++++++ >> 6 files changed, 238 insertions(+) >> create mode 100644 src/util/virarptable.c >> create mode 100644 src/util/virarptable.h >> > >Couple of Coverity issues.... > Thanks, will be fixed soon. Regards, - Chen -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
On 03/08/2018 08:11 AM, Chen Hanxiao wrote: > From: Chen Hanxiao <chenhanxiao@gmail.com> > > introduce helper to parse RTM_GETNEIGH query message and > store it in struct virArpTable. > > Signed-off-by: Chen Hanxiao <chenhanxiao@gmail.com> > --- > v4-rebase: > fit split Makefile.am > fit new virMacAddr fields > > v4: > use netlink query instead of parsing /proc/net/arp > > 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/Makefile.inc.am | 2 + > src/util/virarptable.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++ > src/util/virarptable.h | 48 +++++++++++++ > 6 files changed, 238 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 cfdd4ebdd..71c61dec9 100644 > --- a/po/POTFILES.in > +++ b/po/POTFILES.in > @@ -192,6 +192,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 8b1e4c8a4..82c5d5cde 100644 > --- a/src/Makefile.am > +++ b/src/Makefile.am > @@ -672,6 +672,7 @@ noinst_LTLIBRARIES += libvirt-setuid-rpc-client.la > libvirt_setuid_rpc_client_la_SOURCES = \ > util/viralloc.c \ > util/virarch.c \ > + util/virarptable.c \ > util/viratomic.c \ > util/viratomic.h \ > util/virbitmap.c \ > diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms > index 11b9f4937..05b0c5b0e 100644 > --- a/src/libvirt_private.syms > +++ b/src/libvirt_private.syms > @@ -1365,6 +1365,11 @@ virArchGetWordSize; > virArchToString; > > > +# util/virarptable.h > +virArpTableFree; > +virArpTableGet; > + > + > # util/viraudit.h > virAuditClose; > virAuditEncode; > diff --git a/src/util/Makefile.inc.am b/src/util/Makefile.inc.am > index a91b30dca..02d9c42cc 100644 > --- a/src/util/Makefile.inc.am > +++ b/src/util/Makefile.inc.am > @@ -5,6 +5,8 @@ UTIL_SOURCES = \ > util/viralloc.h \ > util/virarch.c \ > util/virarch.h \ > + util/virarptable.c \ > + util/virarptable.h \ > util/viratomic.c \ > util/viratomic.h \ > util/viraudit.c \ > diff --git a/src/util/virarptable.c b/src/util/virarptable.c > new file mode 100644 > index 000000000..cb56338eb > --- /dev/null > +++ b/src/util/virarptable.c > @@ -0,0 +1,181 @@ > +/* > + * 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 <arpa/inet.h> > + > +#include "viralloc.h" > +#include "virarptable.h" > +#include "virfile.h" > +#include "virlog.h" > +#include "virnetlink.h" > +#include "virsocketaddr.h" > +#include "virstring.h" > + > +#define VIR_FROM_THIS VIR_FROM_NONE > + > +VIR_LOG_INIT("util.arptable"); > + > +#ifdef __linux__ > + > +# define NDA_RTA(r) \ > + ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg)))) > + > +static int > +parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len) > +{ > + memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); > + while (RTA_OK(rta, len)) { > + if ((rta->rta_type <= max) && (!tb[rta->rta_type])) > + tb[rta->rta_type] = rta; > + rta = RTA_NEXT(rta, len); > + } > + > + if (len) > + VIR_WARN("malformed netlink message: Deficit %d, rta_len=%d", > + len, rta->rta_len); > + return 0; > +} > + > +virArpTablePtr virArpTableGet(void) > +{ > + int num = 0; > + int msglen; > + void *nlData = NULL; > + virArpTablePtr table = NULL; > + char *ipstr = NULL; > + struct nlmsghdr* nh; > + struct rtattr * tb[NDA_MAX+1]; > + > + msglen = virNetlinkGetNeighbor(&nlData, 0, 0); > + if (msglen < 0) > + return NULL; > + > + if (VIR_ALLOC(table) < 0) > + return NULL; > + > + nh = (struct nlmsghdr*)nlData; > + > + while (NLMSG_OK(nh, msglen)) { > + struct ndmsg *r = NLMSG_DATA(nh); > + int len = nh->nlmsg_len; > + void *addr; > + > + if ((len -= NLMSG_LENGTH(sizeof(*nh))) < 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("wrong nlmsg len")); > + goto cleanup; > + } > + > + if (r->ndm_family && (r->ndm_family != AF_INET)) > + goto next_nlmsg; > + > + /* catch stale and reachalbe arp entry only */ > + if (r->ndm_state && > + (!(r->ndm_state == NUD_STALE || r->ndm_state == NUD_REACHABLE))) { > + nh = NLMSG_NEXT(nh, msglen); > + continue; > + } > + > + if (nh->nlmsg_type == NLMSG_DONE) > + goto end_of_netlink_messages; > + > + parse_rtattr(tb, NDA_MAX, NDA_RTA(r), > + nh->nlmsg_len - NLMSG_LENGTH(sizeof(*r))); > + > + if (tb[NDA_DST] == NULL || tb[NDA_LLADDR] == NULL) > + goto next_nlmsg; > + > + if (tb[NDA_DST]) { > + virSocketAddr virAddr; > + if (VIR_REALLOC_N(table->t, num + 1) < 0) > + goto cleanup; > + > + table->n = num + 1; > + > + addr = RTA_DATA(tb[NDA_DST]); > + bzero(&virAddr, sizeof(virAddr)); > + virAddr.len = sizeof(virAddr.data.inet4); > + virAddr.data.inet4.sin_family = AF_INET; > + virAddr.data.inet4.sin_addr = *(struct in_addr *)addr; > + ipstr = virSocketAddrFormat(&virAddr); > + > + if (VIR_STRDUP(table->t[num].ipaddr, ipstr) < 0) > + goto cleanup; > + > + VIR_FREE(ipstr); > + } > + > + if (tb[NDA_LLADDR]) { > + virMacAddr macaddr; > + char ifmac[VIR_MAC_STRING_BUFLEN]; > + > + addr = RTA_DATA(tb[NDA_LLADDR]); > + memcpy(macaddr.addr, addr, VIR_MAC_BUFLEN); > + > + virMacAddrFormat(&macaddr, ifmac); > + > + if (VIR_STRDUP(table->t[num].mac, ifmac) < 0) > + goto cleanup; > + > + num++; > + } > + > + next_nlmsg: > + nh = NLMSG_NEXT(nh, msglen); > + } > + > + end_of_netlink_messages: > + VIR_FREE(nlData); > + return table; > + > + cleanup: > + VIR_FREE(ipstr); > + VIR_FREE(nlData); > + 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); > + } You need to free table->t too. > + VIR_FREE(table); > +} Michal -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
© 2016 - 2025 Red Hat, Inc.