summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/first_network_device.c64
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)