Parse uevent file to detect network device type (#153)
Currently i3status differentiates wireless and wired devices based on the existence of wireless directory inside the device's sysfs directory. This approach seems to cause 3g modems to be incorrectly identified as the first ethernet device. This commit solves this problem by using DEVTYPE variable from uevent file. Signed-off-by: Cihangir Akturk <cakturk@gmail.com>
This commit is contained in:
parent
ef16acfca5
commit
15de209cba
@ -202,7 +202,8 @@ void set_timezone(const char *tz);
|
|||||||
/* src/first_network_device.c */
|
/* src/first_network_device.c */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NET_TYPE_WIRELESS = 0,
|
NET_TYPE_WIRELESS = 0,
|
||||||
NET_TYPE_ETHERNET = 1
|
NET_TYPE_ETHERNET = 1,
|
||||||
|
NET_TYPE_OTHER = 2
|
||||||
} net_type_t;
|
} net_type_t;
|
||||||
const char *first_eth_interface(const net_type_t type);
|
const char *first_eth_interface(const net_type_t type);
|
||||||
|
|
||||||
|
@ -6,11 +6,58 @@
|
|||||||
|
|
||||||
#include "i3status.h"
|
#include "i3status.h"
|
||||||
|
|
||||||
|
static bool sysfs_devtype(char *dest, size_t n, const char *ifnam) {
|
||||||
|
FILE *fp;
|
||||||
|
char buf[1024];
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "/sys/class/net/%s/uevent", ifnam);
|
||||||
|
if ((fp = fopen(buf, "r")) == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dest[0] = '\0';
|
||||||
|
|
||||||
|
while (fgets(buf, sizeof(buf), fp)) {
|
||||||
|
size_t slen;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
slen = strlen(buf);
|
||||||
|
/* Line is too long to fit in the buffer */
|
||||||
|
if (buf[slen - 1] != '\n' && !feof(fp))
|
||||||
|
break;
|
||||||
|
if ((s = strchr(buf, '='))) {
|
||||||
|
if (strncmp(buf, "DEVTYPE", s - buf))
|
||||||
|
continue;
|
||||||
|
buf[slen - 1] = '\0';
|
||||||
|
strncpy(dest, ++s, n);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static net_type_t iface_type(const char *ifname) {
|
||||||
|
char devtype[32];
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (strcmp(devtype, "wwan") == 0)
|
||||||
|
return NET_TYPE_OTHER;
|
||||||
|
|
||||||
|
return NET_TYPE_OTHER;
|
||||||
|
}
|
||||||
|
|
||||||
const char *first_eth_interface(const net_type_t type) {
|
const char *first_eth_interface(const net_type_t type) {
|
||||||
static char *interface = NULL;
|
static char *interface = NULL;
|
||||||
struct ifaddrs *ifaddr, *addrp;
|
struct ifaddrs *ifaddr, *addrp;
|
||||||
struct stat stbuf;
|
net_type_t iftype;
|
||||||
static char path[1024];
|
|
||||||
|
|
||||||
getifaddrs(&ifaddr);
|
getifaddrs(&ifaddr);
|
||||||
|
|
||||||
@ -32,10 +79,8 @@ const char *first_eth_interface(const net_type_t type) {
|
|||||||
addrp->ifa_addr->sa_family != AF_INET6)
|
addrp->ifa_addr->sa_family != AF_INET6)
|
||||||
continue;
|
continue;
|
||||||
// Skip this interface if it is a wireless interface.
|
// Skip this interface if it is a wireless interface.
|
||||||
snprintf(path, sizeof(path), "/sys/class/net/%s/wireless", addrp->ifa_name);
|
iftype = iface_type(addrp->ifa_name);
|
||||||
const bool is_wireless = (stat(path, &stbuf) == 0);
|
if (iftype != type)
|
||||||
if ((is_wireless && type == NET_TYPE_ETHERNET) ||
|
|
||||||
(!is_wireless && type == NET_TYPE_WIRELESS))
|
|
||||||
continue;
|
continue;
|
||||||
interface = strdup(addrp->ifa_name);
|
interface = strdup(addrp->ifa_name);
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user