diff options
author | Daniel Borkmann <dborkman@redhat.com> | 2013-06-04 11:32:19 +0200 |
---|---|---|
committer | Daniel Borkmann <dborkman@redhat.com> | 2013-06-04 11:32:19 +0200 |
commit | ab9d73629872a474d9194177fa4c9c8cdabe9a44 (patch) | |
tree | be238632f09ab058370c086dfb6feee32006b7ff /link.c | |
parent | a66fe185ab6a3eb7a483fd9888b54ee43328836e (diff) |
link: add link management functions
Same here as usual, break out link functions from xutils.
Signed-off-by: Daniel Borkmann <dborkman@redhat.com>
Diffstat (limited to 'link.c')
-rw-r--r-- | link.c | 166 |
1 files changed, 166 insertions, 0 deletions
@@ -0,0 +1,166 @@ +#include <sys/ioctl.h> +#include <linux/sockios.h> +#include <unistd.h> +#include <errno.h> + +#include "link.h" +#include "sock.h" +#include "str.h" + +u32 wireless_bitrate(const char *ifname) +{ + int sock, ret, rate_in_mbit; + struct iwreq iwr; + + sock = af_socket(AF_INET); + + memset(&iwr, 0, sizeof(iwr)); + strlcpy(iwr.ifr_name, ifname, IFNAMSIZ); + + ret = ioctl(sock, SIOCGIWRATE, &iwr); + if (!ret) + rate_in_mbit = iwr.u.bitrate.value / 1000000; + else + rate_in_mbit = 0; + + close(sock); + + return rate_in_mbit; +} + +int wireless_sigqual(const char *ifname, struct iw_statistics *stats) +{ + int ret, sock; + struct iwreq iwr; + + sock = af_socket(AF_INET); + + memset(&iwr, 0, sizeof(iwr)); + strlcpy(iwr.ifr_name, ifname, IFNAMSIZ); + + iwr.u.data.pointer = (caddr_t) stats; + iwr.u.data.length = sizeof(*stats); + iwr.u.data.flags = 1; + + ret = ioctl(sock, SIOCGIWSTATS, &iwr); + + close(sock); + + return ret; +} + +int wireless_rangemax_sigqual(const char *ifname) +{ + int ret, sock, sigqual; + struct iwreq iwr; + struct iw_range iwrange; + + sock = af_socket(AF_INET); + + memset(&iwrange, 0, sizeof(iwrange)); + + memset(&iwr, 0, sizeof(iwr)); + strlcpy(iwr.ifr_name, ifname, IFNAMSIZ); + + iwr.u.data.pointer = (caddr_t) &iwrange; + iwr.u.data.length = sizeof(iwrange); + iwr.u.data.flags = 0; + + ret = ioctl(sock, SIOCGIWRANGE, &iwr); + if (!ret) + sigqual = iwrange.max_qual.qual; + else + sigqual = 0; + + close(sock); + + return sigqual; +} + +u32 ethtool_bitrate(const char *ifname) +{ + int ret, sock, bitrate; + struct ifreq ifr; + struct ethtool_cmd ecmd; + + sock = af_socket(AF_INET); + + memset(&ecmd, 0, sizeof(ecmd)); + + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); + + ecmd.cmd = ETHTOOL_GSET; + ifr.ifr_data = (char *) &ecmd; + + ret = ioctl(sock, SIOCETHTOOL, &ifr); + if (ret) { + bitrate = 0; + goto out; + } + + switch (ecmd.speed) { + case SPEED_10: + case SPEED_100: + case SPEED_1000: + case SPEED_2500: + case SPEED_10000: + bitrate = ecmd.speed; + break; + default: + bitrate = 0; + break; + }; +out: + close(sock); + + return bitrate; +} + +int ethtool_link(const char *ifname) +{ + int ret, sock; + struct ifreq ifr; + struct ethtool_value ecmd; + + sock = af_socket(AF_INET); + + memset(&ecmd, 0, sizeof(ecmd)); + + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); + + ecmd.cmd = ETHTOOL_GLINK; + ifr.ifr_data = (char *) &ecmd; + + ret = ioctl(sock, SIOCETHTOOL, &ifr); + if (ret) + ret = -EINVAL; + else + ret = !!ecmd.data; + + close(sock); + return ret; +} + +int ethtool_drvinf(const char *ifname, struct ethtool_drvinfo *drvinf) +{ + int ret, sock; + struct ifreq ifr; + + sock = af_socket(AF_INET); + + memset(drvinf, 0, sizeof(*drvinf)); + + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, ifname, IFNAMSIZ); + + drvinf->cmd = ETHTOOL_GDRVINFO; + ifr.ifr_data = (char *) drvinf; + + ret = ioctl(sock, SIOCETHTOOL, &ifr); + + close(sock); + + return ret; +} |