mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-12 22:51:29 +00:00
util: introduce helper to parse message from RTM_GETNEIGH query
introduce helper to parse RTM_GETNEIGH query message and store it in struct virArpTable. Signed-off-by: Chen Hanxiao <chenhanxiao@gmail.com> Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
414e61109c
commit
a176d67cdf
@ -192,6 +192,7 @@ src/uml/uml_conf.c
|
|||||||
src/uml/uml_driver.c
|
src/uml/uml_driver.c
|
||||||
src/util/iohelper.c
|
src/util/iohelper.c
|
||||||
src/util/viralloc.c
|
src/util/viralloc.c
|
||||||
|
src/util/virarptable.c
|
||||||
src/util/viraudit.c
|
src/util/viraudit.c
|
||||||
src/util/virauth.c
|
src/util/virauth.c
|
||||||
src/util/virauthconfig.c
|
src/util/virauthconfig.c
|
||||||
|
@ -672,6 +672,7 @@ noinst_LTLIBRARIES += libvirt-setuid-rpc-client.la
|
|||||||
libvirt_setuid_rpc_client_la_SOURCES = \
|
libvirt_setuid_rpc_client_la_SOURCES = \
|
||||||
util/viralloc.c \
|
util/viralloc.c \
|
||||||
util/virarch.c \
|
util/virarch.c \
|
||||||
|
util/virarptable.c \
|
||||||
util/viratomic.c \
|
util/viratomic.c \
|
||||||
util/viratomic.h \
|
util/viratomic.h \
|
||||||
util/virbitmap.c \
|
util/virbitmap.c \
|
||||||
|
@ -1366,6 +1366,11 @@ virArchGetWordSize;
|
|||||||
virArchToString;
|
virArchToString;
|
||||||
|
|
||||||
|
|
||||||
|
# util/virarptable.h
|
||||||
|
virArpTableFree;
|
||||||
|
virArpTableGet;
|
||||||
|
|
||||||
|
|
||||||
# util/viraudit.h
|
# util/viraudit.h
|
||||||
virAuditClose;
|
virAuditClose;
|
||||||
virAuditEncode;
|
virAuditEncode;
|
||||||
|
@ -5,6 +5,8 @@ UTIL_SOURCES = \
|
|||||||
util/viralloc.h \
|
util/viralloc.h \
|
||||||
util/virarch.c \
|
util/virarch.c \
|
||||||
util/virarch.h \
|
util/virarch.h \
|
||||||
|
util/virarptable.c \
|
||||||
|
util/virarptable.h \
|
||||||
util/viratomic.c \
|
util/viratomic.c \
|
||||||
util/viratomic.h \
|
util/viratomic.h \
|
||||||
util/viraudit.c \
|
util/viraudit.c \
|
||||||
|
182
src/util/virarptable.c
Normal file
182
src/util/virarptable.c
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
/*
|
||||||
|
* 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->t);
|
||||||
|
VIR_FREE(table);
|
||||||
|
}
|
48
src/util/virarptable.h
Normal file
48
src/util/virarptable.h
Normal file
@ -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__ */
|
Loading…
x
Reference in New Issue
Block a user