summaryrefslogtreecommitdiff
path: root/link.c
diff options
context:
space:
mode:
Diffstat (limited to 'link.c')
-rw-r--r--link.c166
1 files changed, 166 insertions, 0 deletions
diff --git a/link.c b/link.c
new file mode 100644
index 0000000..95f0816
--- /dev/null
+++ b/link.c
@@ -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;
+}