From 705d4d4b5f1c59d0d2f6a24d4d584e21738521df Mon Sep 17 00:00:00 2001
From: "Joseph C. Lehner" <joseph.c.lehner@gmail.com>
Date: Sat, 28 Jan 2017 10:44:33 +0100
Subject: [PATCH] Improve BSD bridge detection portability

---
 ethsock.c | 49 +++++++++++--------------------------------------
 1 file changed, 11 insertions(+), 38 deletions(-)

diff --git a/ethsock.c b/ethsock.c
index 4e58830..90fd71f 100644
--- a/ethsock.c
+++ b/ethsock.c
@@ -41,16 +41,10 @@
 #else
 #define NMRPFLASH_AF_PACKET AF_LINK
 #include <net/if_types.h>
+#include <net/if_media.h>
 #endif
 #endif
 
-#ifdef NMRPFLASH_BSD
-#include <sys/ioctl.h>
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
-#include <net/if_bridgevar.h>
-#endif
-
 struct ethsock
 {
 	const char *intf;
@@ -162,36 +156,9 @@ static bool set_stp_enabled(const char *intf, bool enabled)
 
 	return ret;
 }
-#else
-static bool is_bridge(const char *intf)
-{
-#ifdef NMRPFLASH_BSD
-	struct ifdrv ifd;
-	struct ifbropreq ifbop;
-	int err, fd = socket(AF_INET, SOCK_DGRAM, 0);
-	if (fd < 0) {
-		return false;
-	}
-
-	strncpy(ifd.ifd_name, intf, sizeof(ifd.ifd_name));
-	ifd.ifd_cmd = BRDGPARAM;
-	ifd.ifd_data = &ifbop;
-	ifd.ifd_len = sizeof(ifbop);
-
-	err = ioctl(fd, SIOCGDRVSPEC, &ifd);
-	if (err && verbosity) {
-		xperror("ioctl(SIOCGDRVSPEC)");
-	}
-
-	close(fd);
-	return !err;
-#else
-	return false;
-#endif
-}
 #endif
 
-static bool get_intf_info(const char *intf, uint8_t *hwaddr, void *dummy)
+static bool get_intf_info(const char *intf, uint8_t *hwaddr, bool *bridge)
 {
 	struct ifaddrs *ifas, *ifa;
 	bool found;
@@ -202,10 +169,14 @@ static bool get_intf_info(const char *intf, uint8_t *hwaddr, void *dummy)
 	}
 
 	found = false;
+	*bridge = false;
 
 	for (ifa = ifas; ifa; ifa = ifa->ifa_next) {
 		if (!strcmp(ifa->ifa_name, intf)) {
 			if (sockaddr_get_hwaddr(ifa->ifa_addr, hwaddr)) {
+#ifdef NMRPFLASH_BSD
+				*bridge = ((struct if_data*) ifa->ifa_data)->ifi_type == IFT_BRIDGE;
+#endif
 				found = true;
 				break;
 			}
@@ -371,6 +342,7 @@ struct ethsock *ethsock_create(const char *intf, uint16_t protocol)
 	char buf[PCAP_ERRBUF_SIZE];
 	struct bpf_program fp;
 	struct ethsock *sock;
+	bool is_bridge;
 	int err;
 
 #ifdef NMRPFLASH_WINDOWS
@@ -406,7 +378,7 @@ struct ethsock *ethsock_create(const char *intf, uint16_t protocol)
 	}
 
 #ifndef NMRPFLASH_WINDOWS
-	err = !get_intf_info(intf, sock->hwaddr, NULL);
+	err = !get_intf_info(intf, sock->hwaddr, &is_bridge);
 #else
 	err = !get_intf_info(intf, sock->hwaddr, &sock->index);
 #endif
@@ -460,7 +432,7 @@ struct ethsock *ethsock_create(const char *intf, uint16_t protocol)
 		}
 	}
 #else
-	if (is_bridge(intf)) {
+	if (is_bridge) {
 		fprintf(stderr, "Warning: bridge interfaces are not fully "
 				"supported on this platform.\n");
 	}
@@ -647,6 +619,7 @@ int ethsock_arp_del(struct ethsock *sock, struct ethsock_arp_undo **undo)
 
 static bool get_hwaddr_from_pcap(const pcap_if_t *dev, uint8_t *hwaddr)
 {
+	bool is_bridge;
 #ifndef NMRPFLASH_WINDOWS
 	pcap_addr_t *addr;
 	int i;
@@ -667,7 +640,7 @@ static bool get_hwaddr_from_pcap(const pcap_if_t *dev, uint8_t *hwaddr)
 	}
 #endif
 
-	return get_intf_info(dev->name, hwaddr, NULL);
+	return get_intf_info(dev->name, hwaddr, &is_bridge);
 }
 
 int ethsock_list_all(void)
-- 
2.25.1