diff options
| -rw-r--r-- | status.c | 163 |
1 files changed, 118 insertions, 45 deletions
@@ -6,8 +6,8 @@ #include <linux/wireless.h> #include <netinet/in.h> #include <stdbool.h> -#include <stdio.h> #include <stdint.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> @@ -47,6 +47,18 @@ struct battery_status { float charge; }; +#define ADDRSTRLEN \ + (INET_ADDRSTRLEN > INET6_ADDRSTRLEN) ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN +struct interface_status { + enum { loopback, ethernet, wifi, wan } type; + struct { + char ip4[INET_ADDRSTRLEN]; + char ip6[INET6_ADDRSTRLEN]; + } address; + char ssid[IW_ESSID_MAX_SIZE + 1]; + char* name; +}; + /* Prototypes */ void date(char* buf); struct battery_status get_battery_status(const char* buf); @@ -72,11 +84,11 @@ static char* battery_level_icon[] = { static struct element statusbar[] = { /* Add status elements here */ + /*{element_function, {seconds, microseconds}, {0}, {0}},*/ {get_net_link_status, {5, 0}, {0}, {0}}, { get_all_bat_status, {60, 0}, {0}, {0}}, { date, {2, 500000}, {0}, {0}}, - }; /* Functions */ @@ -176,73 +188,134 @@ get_all_bat_status(char* buf) { } void +get_essid(char* if_name, char* dst) { + /* Get the SSID */ + size_t l = strlen(if_name); + int sock = socket(AF_INET, SOCK_DGRAM, 0); + struct iwreq wreq; + memset(&wreq, 0, sizeof(struct iwreq)); + + setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, if_name, l); + + strncpy(wreq.ifr_name, if_name, l); + + wreq.u.essid.pointer = dst; + wreq.u.essid.length = IW_ESSID_MAX_SIZE; + if (ioctl(sock, SIOCGIWESSID, &wreq) == -1) { + dst[0] = '\0'; + } +} + +struct interface_status status[8]; // surely noone has more than 8 interfaces. + +void get_net_link_status(char* buf) { struct ifaddrs* if_addr; size_t n = 0; + size_t c = 0; + struct interface_status status[8]; // surely noone has more than 8 interfaces. + memset(status, 0, sizeof(struct interface_status[8])); getifaddrs(&if_addr); for (struct ifaddrs* ifa = if_addr; ifa != NULL; ifa = ifa->ifa_next) { + + /* We're not interested in interfaces that are not "up" */ + if (!(ifa->ifa_flags & IFF_UP)) + continue; + /* Ignore loopback interface flag */ if (ifa->ifa_flags & IFF_LOOPBACK) continue; - /* Ignore interfaces without an address */ - if (ifa->ifa_addr == NULL) - continue; + ///* Ignore interfaces without an address */ + // if (ifa->ifa_addr == NULL) + // continue; - /* Ignore everythings not an IPv4 link */ - /* (AF_PACKET might be usefull if you want to display tx) */ - if (ifa->ifa_addr->sa_family != AF_INET) - continue; + ///* Ignore everythings not an IPv4 link */ + ///* (AF_PACKET might be usefull if you want to display tx) */ + // if (ifa->ifa_addr->sa_family != AF_INET) + // continue; + + /* Find the interface in status, if it exists */ + struct interface_status* s = &status[c]; + const char* name = ifa->ifa_name; + + int i = 0; + for (int i = 0; i < c; i++) { + if (!strcmp(name, status[i].name)) { + s = &status[i]; + } + } + if (i == c) + c++; + + s->name = ifa->ifa_name; + + if (ifa->ifa_addr != NULL) { + const int family = ifa->ifa_addr->sa_family; - if (ifa->ifa_flags & IFF_UP) { + size_t strsize = 0; + char* dst = NULL; - size_t l = strlen(ifa->ifa_name); - struct iwreq wreq; - int sock; - const size_t ipv6_charlen = 8 * 4 + 7; - char address[ipv6_charlen + 1]; // in case of ipv6, plus null-byte - char id[IW_ESSID_MAX_SIZE + 1]; + if (family == AF_INET) { + strsize = INET_ADDRSTRLEN; + dst = s->address.ip4; + } else if (family == AF_INET6) { + strsize = INET6_ADDRSTRLEN; + dst = s->address.ip6; + } else if (family == AF_PACKET) { + continue; + } else + /* In this case, there's probably something horribly wrong */ + continue; /* Get the IP address */ - memset(address, 0, ipv6_charlen + 1); - /* Use sa_family instead of hardcoding AF_INET, just in case - * we get ip6'ed */ - /* Does inet_ntop add a null-byte? */ - inet_ntop(ifa->ifa_addr->sa_family, - (void*)&((struct sockaddr_in*)ifa->ifa_addr)->sin_addr, address, - ipv6_charlen); + inet_ntop(family, (void*)&((struct sockaddr_in*)ifa->ifa_addr)->sin_addr, + dst, strsize); + } - /* Get the SSID */ - memset(id, 0, IW_ESSID_MAX_SIZE + 1); - memset(&wreq, 0, sizeof(struct iwreq)); - sock = socket(AF_INET, SOCK_DGRAM, 0); - setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, ifa->ifa_name, l); + // Get the ESSID + get_essid(s->name, s->ssid); + } + freeifaddrs(if_addr); - strncpy(wreq.ifr_name, ifa->ifa_name, l); + for (int i = 0; i < c; i++) { + // int i = 0; { + struct interface_status* s = &status[i]; + // Write the status string to the output buffer + const size_t namelen = strlen(s->name); + strncat(buf + n, s->name, namelen); + n += namelen; - wreq.u.essid.pointer = id; - wreq.u.essid.length = IW_ESSID_MAX_SIZE; - ioctl(sock, SIOCGIWESSID, &wreq); + size_t ssid_len = strlen(s->ssid); + if (ssid_len > 0) { + buf[n++] = ' '; + buf[n++] = '('; + strncpy(buf + n, s->ssid, ssid_len); + n += ssid_len; - strncpy(buf + n, ifa->ifa_name, l); + buf[n++] = ')'; + } - size_t ssid_len = strlen(id); - if (ssid_len > 0) { - buf[n + l] = ' '; - buf[n + l + 1] = '('; - strncpy(buf + n + l + 2, id, ssid_len); - l += ssid_len; - buf[n + l + 2] = ')'; + { // Add the addresses + const size_t addr4_len = strlen(s->address.ip4); + if (addr4_len > 0) { + buf[n++] = ' '; + strncat(buf + n, s->address.ip4, addr4_len); + n += addr4_len; } - n += l; - - strcat(buf + n, address); - n += strlen(address); - strcat(buf + n, " "); + const size_t addr6_len = strlen(s->address.ip6); + if (addr6_len > 0) { + buf[n++] = ' '; + strncat(buf + n, s->address.ip6, addr6_len); + n += addr6_len; + } + } + if (i != c - 1) { + strncat(buf + n, " ", 3); n += 2; } } |
