From: Chen Hanxiao <chenhanxiao@xxxxxxxxx> use RTM_GETNEIGH to query arp table entry by netlink socket Signed-off-by: Chen Hanxiao <chenhanxiao@xxxxxxxxx> --- v4: use netlink to get arp table entry src/libvirt_private.syms | 1 + src/util/virnetlink.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++ src/util/virnetlink.h | 2 ++ 3 files changed, 85 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 3766e20d3..11b9f4937 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2386,6 +2386,7 @@ virNetlinkEventServiceStart; virNetlinkEventServiceStop; virNetlinkEventServiceStopAll; virNetlinkGetErrorCode; +virNetlinkGetNeighbor; virNetlinkShutdown; virNetlinkStartup; diff --git a/src/util/virnetlink.c b/src/util/virnetlink.c index e61bbb96d..f0a92db23 100644 --- a/src/util/virnetlink.c +++ b/src/util/virnetlink.c @@ -590,6 +590,88 @@ virNetlinkDelLink(const char *ifname, virNetlinkDelLinkFallback fallback) goto cleanup; } +/** + * virNetlinkGetNeighbor: + * + * @nlData: Gets a pointer to the raw data from netlink. + MUST BE FREED BY CALLER! + * @src_pid: pid used for nl_pid of the local end of the netlink message + * (0 == "use getpid()") + * @dst_pid: pid of destination nl_pid if the kernel + * is not the target of the netlink message but it is to be + * sent to another process (0 if sending to the kernel) + * + * Get neighbor table entry from netlink. + * + * Returns 0 on success, -1 on fatal error. + */ +int +virNetlinkGetNeighbor(void **nlData, uint32_t src_pid, uint32_t dst_pid) +{ + int rc = -1; + struct nlmsghdr *resp = NULL; + struct nlmsgerr *err; + struct ndmsg ndinfo = { + .ndm_family = AF_UNSPEC, + }; + unsigned int recvbuflen; + struct nl_msg *nl_msg; + + nl_msg = nlmsg_alloc_simple(RTM_GETNEIGH, NLM_F_DUMP | NLM_F_REQUEST); + if (!nl_msg) { + virReportOOMError(); + return -1; + } + + if (nlmsg_append(nl_msg, &ndinfo, sizeof(ndinfo), NLMSG_ALIGNTO) < 0) + goto buffer_too_small; + + + if (virNetlinkCommand(nl_msg, &resp, &recvbuflen, + src_pid, dst_pid, NETLINK_ROUTE, 0) < 0) + goto cleanup; + + if (recvbuflen < NLMSG_LENGTH(0) || resp == NULL) + goto malformed_resp; + + switch (resp->nlmsg_type) { + case NLMSG_ERROR: + err = (struct nlmsgerr *)NLMSG_DATA(resp); + if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err))) + goto malformed_resp; + + if (err->error) { + virReportSystemError(-err->error, + "%s", _("error dumping")); + goto cleanup; + } + break; + + case RTM_NEWNEIGH: + break; + + default: + goto malformed_resp; + } + rc = recvbuflen; + + cleanup: + nlmsg_free(nl_msg); + if (rc < 0) + VIR_FREE(resp); + *nlData = resp; + return rc; + + malformed_resp: + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("malformed netlink response message")); + goto cleanup; + + buffer_too_small: + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("allocated netlink buffer is too small")); + goto cleanup; +} int virNetlinkGetErrorCode(struct nlmsghdr *resp, unsigned int recvbuflen) diff --git a/src/util/virnetlink.h b/src/util/virnetlink.h index 088b01343..2a9de0a57 100644 --- a/src/util/virnetlink.h +++ b/src/util/virnetlink.h @@ -71,6 +71,8 @@ int virNetlinkDumpLink(const char *ifname, int ifindex, void **nlData, struct nlattr **tb, uint32_t src_pid, uint32_t dst_pid) ATTRIBUTE_RETURN_CHECK; +int +virNetlinkGetNeighbor(void **nlData, uint32_t src_pid, uint32_t dst_pid); typedef void (*virNetlinkEventHandleCallback)(struct nlmsghdr *, unsigned int length, -- 2.14.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list