]> git.sur5r.net Git - i3/i3status/blobdiff - src/first_network_device.c
Detect interface type on DragonFly BSD
[i3/i3status] / src / first_network_device.c
index 4e680069290b9120f6d493baf78c4d62851a6cef..93626a266c68ec411c48f971caf557b92a18229d 100644 (file)
@@ -3,21 +3,25 @@
 #include <sys/stat.h>
 #include <stdlib.h>
 #include <ifaddrs.h>
-#ifdef __OpenBSD__
+#if defined(__OpenBSD__) || defined(__DragonFly__)
 #include <sys/types.h>
 #include <sys/sockio.h>
 #include <sys/ioctl.h>
 #include <net/if.h>
+#endif
+#if defined(__OpenBSD__)
 #include <net80211/ieee80211.h>
 #include <net80211/ieee80211_ioctl.h>
+#elif defined(__DragonFly__)
+#include <netproto/802_11/ieee80211_ioctl.h>
 #endif
 
 #include "i3status.h"
 
-#ifdef __linux__
-#define LOOPBACK_DEV "lo"
-#else
+#ifdef __OpenBSD__
 #define LOOPBACK_DEV "lo0"
+#else
+#define LOOPBACK_DEV "lo"
 #endif
 
 static bool sysfs_devtype(char *dest, size_t n, const char *ifnam) {
@@ -50,24 +54,24 @@ static bool sysfs_devtype(char *dest, size_t n, const char *ifnam) {
     return true;
 }
 
-static net_type_t iface_type(const char *ifname) {
-#ifdef __linux__
-    char devtype[32];
+static bool is_virtual(const char *ifname) {
+    char path[1024];
+    char *target = NULL;
+    bool is_virtual = false;
 
-    if (!sysfs_devtype(devtype, sizeof(devtype), ifname))
-        return NET_TYPE_OTHER;
-
-    if (!devtype[0])
-        return NET_TYPE_ETHERNET;
-
-    if (strcmp(devtype, "wlan") == 0)
-        return NET_TYPE_WIRELESS;
+    snprintf(path, sizeof(path), "/sys/class/net/%s", ifname);
+    if ((target = realpath(path, NULL))) {
+        if (BEGINS_WITH(target, "/sys/devices/virtual/")) {
+            is_virtual = true;
+        }
+    }
 
-    if (strcmp(devtype, "wwan") == 0)
-        return NET_TYPE_OTHER;
+    free(target);
+    return is_virtual;
+}
 
-    return NET_TYPE_OTHER;
-#elif __OpenBSD__
+static net_type_t iface_type(const char *ifname) {
+#if defined(__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
@@ -78,14 +82,23 @@ static net_type_t iface_type(const char *ifname) {
     struct ifreq ifr;
     struct ieee80211_bssid bssid;
     struct ieee80211_nwid nwid;
+#elif defined(__DragonFly__)
+    struct ieee80211req ifr;
+#endif
+#if defined(__OpenBSD__) || defined(__DragonFly__)
     struct ifmediareq ifmr;
-
-    int s, ibssid, inwid;
-
+    int s;
+#endif
+#if defined(__OpenBSD__)
+    int ibssid, inwid;
+#endif
+#if defined(__OpenBSD__) || defined(__DragonFly__)
     if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
         return NET_TYPE_OTHER;
 
     memset(&ifr, 0, sizeof(ifr));
+#endif
+#if defined(__OpenBSD__)
     ifr.ifr_data = (caddr_t)&nwid;
     (void)strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
     inwid = ioctl(s, SIOCG80211NWID, (caddr_t)&ifr);
@@ -94,21 +107,48 @@ static net_type_t iface_type(const char *ifname) {
     strlcpy(bssid.i_name, ifname, sizeof(bssid.i_name));
     ibssid = ioctl(s, SIOCG80211BSSID, &bssid);
 
-    if (ibssid == 0 || inwid == 0)
+    if (ibssid == 0 || inwid == 0) {
+        close(s);
         return NET_TYPE_WIRELESS;
-
+    }
+#elif defined(__DragonFly__)
+    (void)strlcpy(ifr.i_name, ifname, sizeof(ifr.i_name));
+    ifr.i_type = IEEE80211_IOC_NUMSSIDS;
+    if (ioctl(s, SIOCG80211, &ifr) == 0) {
+        close(s);
+        return NET_TYPE_WIRELESS;
+    }
+#endif
+#if defined(__OpenBSD__) || defined(__DragonFly__)
     (void)memset(&ifmr, 0, sizeof(ifmr));
     (void)strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
 
-    if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
+    if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
+        close(s);
         return NET_TYPE_OTHER;
-    else
+    } else {
+        close(s);
         return NET_TYPE_ETHERNET;
-
-    close(s);
+    }
 #else
-#error Missing implementation to determine interface type.
+    char devtype[32];
+
+    if (!sysfs_devtype(devtype, sizeof(devtype), ifname))
+        return NET_TYPE_OTHER;
+
+    /* Default to Ethernet when no devtype is available */
+    if (!devtype[0])
+        return NET_TYPE_ETHERNET;
+
+    if (strcmp(devtype, "wlan") == 0)
+        return NET_TYPE_WIRELESS;
+
+    if (strcmp(devtype, "wwan") == 0)
+        return NET_TYPE_OTHER;
+
+    return NET_TYPE_OTHER;
 #endif
+    return NET_TYPE_OTHER;
 }
 
 const char *first_eth_interface(const net_type_t type) {
@@ -144,6 +184,8 @@ const char *first_eth_interface(const net_type_t type) {
         iftype = iface_type(addrp->ifa_name);
         if (iftype != type)
             continue;
+        if (is_virtual(addrp->ifa_name))
+            continue;
         interface = strdup(addrp->ifa_name);
         break;
     }