]> git.sur5r.net Git - i3/i3status/blob - src/first_network_device.c
Include sys/select.h on OpenBSD (#198)
[i3/i3status] / src / first_network_device.c
1 // vim:ts=4:sw=4:expandtab
2 #include <sys/socket.h>
3 #include <sys/stat.h>
4 #include <stdlib.h>
5 #include <ifaddrs.h>
6
7 #include "i3status.h"
8
9 static bool sysfs_devtype(char *dest, size_t n, const char *ifnam) {
10     FILE *fp;
11     char buf[1024];
12
13     snprintf(buf, sizeof(buf), "/sys/class/net/%s/uevent", ifnam);
14     if ((fp = fopen(buf, "r")) == NULL)
15         return false;
16
17     dest[0] = '\0';
18
19     while (fgets(buf, sizeof(buf), fp)) {
20         size_t slen;
21         char *s;
22
23         slen = strlen(buf);
24         /* Line is too long to fit in the buffer */
25         if (buf[slen - 1] != '\n' && !feof(fp))
26             break;
27         if ((s = strchr(buf, '='))) {
28             if (strncmp(buf, "DEVTYPE", s - buf))
29                 continue;
30             buf[slen - 1] = '\0';
31             strncpy(dest, ++s, n);
32             break;
33         }
34     }
35     fclose(fp);
36     return true;
37 }
38
39 static net_type_t iface_type(const char *ifname) {
40     char devtype[32];
41
42     if (!sysfs_devtype(devtype, sizeof(devtype), ifname))
43         return NET_TYPE_OTHER;
44
45     if (!devtype[0])
46         return NET_TYPE_ETHERNET;
47
48     if (strcmp(devtype, "wlan") == 0)
49         return NET_TYPE_WIRELESS;
50
51     if (strcmp(devtype, "wwan") == 0)
52         return NET_TYPE_OTHER;
53
54     return NET_TYPE_OTHER;
55 }
56
57 const char *first_eth_interface(const net_type_t type) {
58     static char *interface = NULL;
59     struct ifaddrs *ifaddr, *addrp;
60     net_type_t iftype;
61
62     getifaddrs(&ifaddr);
63
64     if (ifaddr == NULL)
65         return NULL;
66
67     free(interface);
68     interface = NULL;
69     for (addrp = ifaddr;
70          addrp != NULL;
71          addrp = addrp->ifa_next) {
72         if (strncasecmp("lo", addrp->ifa_name, strlen("lo")) == 0)
73             continue;
74         if (addrp->ifa_addr == NULL)
75             continue;
76         // Skip PF_PACKET addresses (MAC addresses), as they are present on any
77         // ethernet interface.
78         if (addrp->ifa_addr->sa_family != AF_INET &&
79             addrp->ifa_addr->sa_family != AF_INET6)
80             continue;
81         // Skip this interface if it is a wireless interface.
82         iftype = iface_type(addrp->ifa_name);
83         if (iftype != type)
84             continue;
85         interface = strdup(addrp->ifa_name);
86         break;
87     }
88
89     freeifaddrs(ifaddr);
90     return interface;
91 }