diff mbox series

[1/5] New function to find hardware address of interface

Message ID b4bd2a6056c576737657b568ae77aa3cbad38980.1587059223.git.weeksd2@rpi.edu
State New
Headers show
Series IB netboot 3/3: IB interface bring up | expand

Commit Message

Daniel M. Weeks April 16, 2020, 6:02 p.m. UTC
Return the hardware address of an interface based on its type. The
address may be truncated if the supplied buffer is too short but the
function will always return the actual length of the address.

Signed-off-by: Daniel M. Weeks <weeksd2@rpi.edu>
---
 discover/network.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 discover/network.h |  2 ++
 2 files changed, 47 insertions(+)
diff mbox series

Patch

diff --git a/discover/network.c b/discover/network.c
index 099ca98..ad7eced 100644
--- a/discover/network.c
+++ b/discover/network.c
@@ -5,7 +5,10 @@ 
 #include <stdlib.h>
 #include <errno.h>
 #include <sys/socket.h>
+#include <ifaddrs.h>
 #include <linux/if.h>
+#include <linux/if_arp.h>
+#include <linux/if_packet.h>
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
 #include <i18n/i18n.h>
@@ -239,6 +242,48 @@  static void remove_interface(struct network *network,
 	talloc_free(interface);
 }
 
+int network_get_hwaddr(const char *ifname, uint8_t *dest, size_t dest_len)
+{
+	struct ifaddrs *ifaddr, *ifa;
+	struct sockaddr_ll *sll;
+	int chomp;
+
+	int ret = -1;
+	size_t len;
+
+	if (getifaddrs(&ifaddr) < 0)
+		return -1;
+
+	for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+		if (strcmp(ifname, ifa->ifa_name) == 0) {
+			sll = (struct sockaddr_ll *) ifa->ifa_addr;
+
+			switch (sll->sll_hatype) {
+			case ARPHRD_ETHER:
+				chomp = 0;
+				break;
+			case ARPHRD_INFINIBAND:
+				chomp = 12;
+				break;
+			default:
+				chomp = -1;
+				break;
+			}
+
+			if (chomp >= 0) {
+				len = sll->sll_halen - chomp;
+				memcpy(dest, sll->sll_addr+chomp, dest_len);
+				ret = len;
+			}
+
+			break;
+		}
+	}
+
+	freeifaddrs(ifaddr);
+	return ret;
+}
+
 void network_register_device(struct network *network,
 		struct discover_device *dev)
 {
diff --git a/discover/network.h b/discover/network.h
index 0cea6f2..d802962 100644
--- a/discover/network.h
+++ b/discover/network.h
@@ -6,6 +6,8 @@  struct device_handler;
 struct discover_device;
 struct waitset;
 
+int network_get_hwaddr(const char *ifname, uint8_t *dest, size_t dest_len);
+
 struct network *network_init(struct device_handler *handler,
 		struct waitset *waitset, bool dry_run);
 int network_shutdown(struct network *network);