summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stapelberg <michael@stapelberg.de>2009-07-22 18:36:01 +0200
committerMichael Stapelberg <michael@stapelberg.de>2009-07-22 18:36:01 +0200
commitc9ab465cbba2dc38c5564582531e1b44c8d63ce8 (patch)
tree21a5d64bab4db13e192142e4e3ac72a084b8503c
parente56213db28c442a7a67e2424d1631a7f1f42a5fc (diff)
Implement getting the interface speed on FreeBSD, patch by Baptiste Daroussin
-rw-r--r--src/get_eth_info.c74
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;
}