From c9ab465cbba2dc38c5564582531e1b44c8d63ce8 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 22 Jul 2009 18:36:01 +0200 Subject: Implement getting the interface speed on FreeBSD, patch by Baptiste Daroussin --- src/get_eth_info.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file 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 #include #include +#include #include +#include +#include -#ifdef LINUX +#include "i3status.h" + +#if defined(LINUX) #include #include +#define PART_ETHSPEED "E: %s (%d Mbit/s)" #endif -#include "i3status.h" +#if defined(__FreeBSD__) +#include +#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; } -- cgit v1.2.3