The solution to bug #120 requires the ability to translate from
an IP address to its corresponding MAC address in cases where
those are present in the ARP/NTP table.
We add this feature here.
Signed-off-by: Jon Maloy
---
netlink.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
netlink.h | 1 +
2 files changed, 59 insertions(+)
diff --git a/netlink.c b/netlink.c
index ee9325a..6c55c4c 100644
--- a/netlink.c
+++ b/netlink.c
@@ -800,6 +800,64 @@ int nl_addr_get(int s, unsigned int ifi, sa_family_t af,
return status;
}
+/**
+ * nl_mac_get() - Get mac address corresponding to given IP address
+ * @s: Netlink socket
+ * @addr: IPv4 or IPv6 address
+ * @mac: Array to place the returned MAC address
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+int nl_mac_get(int s, const union inany_addr *addr, unsigned char *mac)
+{
+ struct nlmsghdr *nlh;
+ char buf[NLBUFSIZ];
+ const void *ip;
+ ssize_t status;
+ uint32_t seq;
+ int alen;
+ struct {
+ struct nlmsghdr nlh;
+ struct ndmsg ndm;
+ } req;
+
+ if (IN6_IS_ADDR_V4MAPPED(&addr->a6)) {
+ ip = &addr->v4mapped.a4;
+ alen = sizeof(struct in_addr);
+ req.ndm.ndm_family = AF_INET;
+ } else {
+ ip = &addr->a6;
+ alen = sizeof(struct in6_addr);
+ req.ndm.ndm_family = AF_INET6;
+ }
+
+ seq = nl_send(s, &req, RTM_GETNEIGH, NLM_F_DUMP, sizeof(req));
+ nl_foreach_oftype(nlh, status, s, buf, seq, RTM_NEWNEIGH) {
+ struct ndmsg *ndm = NLMSG_DATA(nlh);
+ struct rtattr *attr = (struct rtattr *)(ndm + 1);
+ int attrlen = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*ndm));
+ unsigned char *lladdr = NULL;
+ void *neigh_ip = NULL;
+
+ for (; RTA_OK(attr, attrlen); attr = RTA_NEXT(attr, attrlen)) {
+ if (attr->rta_type == NDA_DST)
+ neigh_ip = RTA_DATA(attr);
+ else if (attr->rta_type == NDA_LLADDR)
+ lladdr = RTA_DATA(attr);
+ }
+
+ if (!neigh_ip || !lladdr)
+ continue;
+
+ if (!memcmp(neigh_ip, ip, alen)) {
+ memcpy(mac, lladdr, ETH_ALEN);
+ return 0;
+ }
+ }
+
+ return status;
+}
+
/**
* nl_addr_get_ll() - Get first IPv6 link-local address for a given interface
* @s: Netlink socket
diff --git a/netlink.h b/netlink.h
index b51e99c..2f674d7 100644
--- a/netlink.h
+++ b/netlink.h
@@ -17,6 +17,7 @@ int nl_route_dup(int s_src, unsigned int ifi_src,
int s_dst, unsigned int ifi_dst, sa_family_t af);
int nl_addr_get(int s, unsigned int ifi, sa_family_t af,
void *addr, int *prefix_len, void *addr_l);
+int nl_mac_get(int s, const union inany_addr *addr, unsigned char *mac);
int nl_addr_set(int s, unsigned int ifi, sa_family_t af,
const void *addr, int prefix_len);
int nl_addr_get_ll(int s, unsigned int ifi, struct in6_addr *addr);
--
2.48.1