]> git.sur5r.net Git - i3/i3status/commitdiff
Make first_eth_interface() work on OpenBSD: (#197)
authorJasper Lievisse Adriaanse <jasper@humppa.nl>
Wed, 1 Feb 2017 07:28:38 +0000 (08:28 +0100)
committerMichael Stapelberg <stapelberg@users.noreply.github.com>
Wed, 1 Feb 2017 07:28:38 +0000 (23:28 -0800)
- use a define for loopback interface device
- use an approach similar to ifconfig(8) for determining device type

src/first_network_device.c

index 541aabb4d69daa2cf032b07d7445efb00a71aa3b..4e680069290b9120f6d493baf78c4d62851a6cef 100644 (file)
@@ -3,9 +3,23 @@
 #include <sys/stat.h>
 #include <stdlib.h>
 #include <ifaddrs.h>
+#ifdef __OpenBSD__
+#include <sys/types.h>
+#include <sys/sockio.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <net80211/ieee80211.h>
+#include <net80211/ieee80211_ioctl.h>
+#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)