diff options
author | Michael Stapelberg <michael@stapelberg.de> | 2009-07-22 18:36:01 +0200 |
---|---|---|
committer | Michael Stapelberg <michael@stapelberg.de> | 2009-07-22 18:36:01 +0200 |
commit | c9ab465cbba2dc38c5564582531e1b44c8d63ce8 (patch) | |
tree | 21a5d64bab4db13e192142e4e3ac72a084b8503c /src/get_eth_info.c | |
parent | e56213db28c442a7a67e2424d1631a7f1f42a5fc (diff) |
Implement getting the interface speed on FreeBSD, patch by Baptiste Daroussin
Diffstat (limited to 'src/get_eth_info.c')
-rw-r--r-- | src/get_eth_info.c | 74 |
1 files changed, 63 insertions, 11 deletions
diff --git a/src/get_eth_info.c b/src/get_eth_info.c index 5e9ab54..9172abb 100644 --- a/src/get_eth_info.c +++ b/src/get_eth_info.c @@ -4,14 +4,41 @@ #include <stdio.h> #include <sys/ioctl.h> #include <sys/types.h> +#include <sys/socket.h> #include <net/if.h> +#include <netinet/in.h> +#include <arpa/inet.h> -#ifdef LINUX +#include "i3status.h" + +#if defined(LINUX) #include <linux/ethtool.h> #include <linux/sockios.h> +#define PART_ETHSPEED "E: %s (%d Mbit/s)" #endif -#include "i3status.h" +#if defined(__FreeBSD__) +#include <net/if_media.h> +#define IFM_TYPE_MATCH(dt, t) \ + (IFM_TYPE((dt)) == 0 || IFM_TYPE((dt)) == IFM_TYPE((t))) + +#define PART_ETHSPEED "E: %s (%s)" + +struct ifmedia_type_to_subtype { + struct { + struct ifmedia_description *desc; + int alias; + } subtypes[5]; + struct { + struct ifmedia_description *desc; + int alias; + } options[3]; + struct { + struct ifmedia_description *desc; + int alias; + } modes[3]; +}; +#endif /* * Combines ethernet IP addresses and speed (if requested) for displaying @@ -19,11 +46,20 @@ */ const char *get_eth_info() { static char part[512]; +#if defined(LINUX) + int ethspeed=0; +#elif defined(__FreeBSD__) + char *ethspeed; +#endif const char *ip_address = get_ip_addr(eth_interface); - int ethspeed = 0; + + if (ip_address == NULL) { + (void)snprintf(part, sizeof(part), "E: down"); + return part; + } if (get_ethspeed) { -#ifdef LINUX +#if defined(LINUX) /* This code path requires root privileges */ struct ifreq ifr; struct ethtool_cmd ecmd; @@ -35,16 +71,32 @@ const char *get_eth_info() { if (ioctl(general_socket, SIOCETHTOOL, &ifr) == 0) ethspeed = (ecmd.speed == USHRT_MAX ? 0 : ecmd.speed); else get_ethspeed = false; +#elif defined(__FreeBSD__) + struct ifmediareq ifm; + (void)memset(&ifm, 0, sizeof(ifm)); + (void)strncpy(ifm.ifm_name, ifaddr->ifa_name, sizeof(ifm.ifm_name)); + int ret = ioctl(general_socket, SIOCGIFMEDIA, (caddr_t)&ifm); + + /* Get the description of the media type, partially taken from + * FreeBSD's ifconfig */ + const struct ifmedia_description *desc; + struct ifmedia_description ifm_subtype_descriptions[] = + IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; + + for (desc = ifm_subtype_descriptions; + desc->ifmt_string != NULL; + desc++) { + if (IFM_TYPE_MATCH(desc->ifmt_word, ifm.ifm_active) && + IFM_SUBTYPE(desc->ifmt_word) == IFM_SUBTYPE(ifm.ifm_active)) + break; + } + ethspeed = (desc->ifmt_string != NULL ? desc->ifmt_string : "?"); #endif } - if (ip_address == NULL) - (void)snprintf(part, sizeof(part), "E: down"); - else { - if (get_ethspeed) - (void)snprintf(part, sizeof(part), "E: %s (%d Mbit/s)", ip_address, ethspeed); - else (void)snprintf(part, sizeof(part), "E: %s", ip_address); - } + if (get_ethspeed) + (void)snprintf(part, sizeof(part), PART_ETHSPEED, ip_address, ethspeed); + else (void)snprintf(part, sizeof(part), "E: %s", ip_address); return part; } |