From e09186fa19c82f2899d4f1559970ea3421c7618d Mon Sep 17 00:00:00 2001 From: Jasper Lievisse Adriaanse Date: Wed, 1 Feb 2017 08:28:38 +0100 Subject: Make first_eth_interface() work on OpenBSD: (#197) - use a define for loopback interface device - use an approach similar to ifconfig(8) for determining device type --- src/first_network_device.c | 64 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/first_network_device.c b/src/first_network_device.c index 541aabb..4e68006 100644 --- a/src/first_network_device.c +++ b/src/first_network_device.c @@ -3,9 +3,23 @@ #include #include #include +#ifdef __OpenBSD__ +#include +#include +#include +#include +#include +#include +#endif #include "i3status.h" +#ifdef __linux__ +#define LOOPBACK_DEV "lo" +#else +#define LOOPBACK_DEV "lo0" +#endif + static bool sysfs_devtype(char *dest, size_t n, const char *ifnam) { FILE *fp; char buf[1024]; @@ -37,6 +51,7 @@ static bool sysfs_devtype(char *dest, size_t n, const char *ifnam) { } static net_type_t iface_type(const char *ifname) { +#ifdef __linux__ char devtype[32]; if (!sysfs_devtype(devtype, sizeof(devtype), ifname)) @@ -52,6 +67,48 @@ static net_type_t iface_type(const char *ifname) { return NET_TYPE_OTHER; return NET_TYPE_OTHER; +#elif __OpenBSD__ + /* + *First determine if the device is a wireless device by trying two ioctl(2) + * commands against it. If either succeeds we can be sure it's a wireless + * device. + * Otherwise we try another ioctl(2) to determine the interface media. If that + * fails it's not an ethernet device eiter. + */ + struct ifreq ifr; + struct ieee80211_bssid bssid; + struct ieee80211_nwid nwid; + struct ifmediareq ifmr; + + int s, ibssid, inwid; + + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) + return NET_TYPE_OTHER; + + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_data = (caddr_t)&nwid; + (void)strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + inwid = ioctl(s, SIOCG80211NWID, (caddr_t)&ifr); + + memset(&bssid, 0, sizeof(bssid)); + strlcpy(bssid.i_name, ifname, sizeof(bssid.i_name)); + ibssid = ioctl(s, SIOCG80211BSSID, &bssid); + + if (ibssid == 0 || inwid == 0) + return NET_TYPE_WIRELESS; + + (void)memset(&ifmr, 0, sizeof(ifmr)); + (void)strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name)); + + if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) + return NET_TYPE_OTHER; + else + return NET_TYPE_ETHERNET; + + close(s); +#else +#error Missing implementation to determine interface type. +#endif } const char *first_eth_interface(const net_type_t type) { @@ -69,15 +126,20 @@ const char *first_eth_interface(const net_type_t type) { for (addrp = ifaddr; addrp != NULL; addrp = addrp->ifa_next) { - if (strncasecmp("lo", addrp->ifa_name, strlen("lo")) == 0) + if (strncasecmp(LOOPBACK_DEV, addrp->ifa_name, strlen(LOOPBACK_DEV)) == 0) continue; if (addrp->ifa_addr == NULL) continue; +#ifdef __OpenBSD__ + if (addrp->ifa_addr->sa_family != AF_LINK) + continue; +#else // Skip PF_PACKET addresses (MAC addresses), as they are present on any // ethernet interface. if (addrp->ifa_addr->sa_family != AF_INET && addrp->ifa_addr->sa_family != AF_INET6) continue; +#endif /* !__OpenBSD__ */ // Skip this interface if it is a wireless interface. iftype = iface_type(addrp->ifa_name); if (iftype != type) -- cgit v1.2.3