diff options
| -rw-r--r-- | src/first_network_device.c | 64 | 
1 files changed, 63 insertions, 1 deletions
| 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 <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) | 
