summaryrefslogtreecommitdiff
path: root/netspeed/src/backend.c
diff options
context:
space:
mode:
Diffstat (limited to 'netspeed/src/backend.c')
-rw-r--r--netspeed/src/backend.c380
1 files changed, 259 insertions, 121 deletions
diff --git a/netspeed/src/backend.c b/netspeed/src/backend.c
index afbdea2e..e1321497 100644
--- a/netspeed/src/backend.c
+++ b/netspeed/src/backend.c
@@ -27,6 +27,12 @@
#include <sys/sockio.h>
#endif
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <ifaddrs.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
#include <glib.h>
#include <glib/gi18n.h>
#include <glibtop/netlist.h>
@@ -59,91 +65,217 @@ struct nl80211_state {
#endif /* HAVE_NL */
gboolean
-is_dummy_device(const char* device)
+is_dummy_device (const char* device)
{
- glibtop_netload netload;
- glibtop_get_netload(&netload, device);
-
- if (netload.if_flags & (1 << GLIBTOP_IF_FLAGS_LOOPBACK))
- return TRUE;
-
- /* Skip interfaces without any IPv4/IPv6 address (or
- those with only a LINK ipv6 addr) However we need to
- be able to exclude these while still keeping the
- value so when they get online (with NetworkManager
- for example) we don't get a suddent peak. Once we're
- able to get this, ignoring down interfaces will be
- possible too. */
- if (!(netload.flags & (1 << GLIBTOP_NETLOAD_ADDRESS6)
- && netload.scope6 != GLIBTOP_IF_IN6_SCOPE_LINK)
- && !(netload.flags & (1 << GLIBTOP_NETLOAD_ADDRESS)))
- return TRUE;
-
- return FALSE;
-}
+ glibtop_netload netload;
+ glibtop_get_netload (&netload, device);
+ if (netload.if_flags & (1 << GLIBTOP_IF_FLAGS_LOOPBACK))
+ return TRUE;
+
+ /* Skip interfaces without any IPv4/IPv6 address (or
+ those with only a LINK ipv6 addr) However we need to
+ be able to exclude these while still keeping the
+ value so when they get online (with NetworkManager
+ for example) we don't get a suddent peak. Once we're
+ able to get this, ignoring down interfaces will be
+ possible too. */
+ if (!(netload.flags & (1 << GLIBTOP_NETLOAD_ADDRESS6)
+ && netload.scope6 != GLIBTOP_IF_IN6_SCOPE_LINK)
+ && !(netload.flags & (1 << GLIBTOP_NETLOAD_ADDRESS)))
+ return TRUE;
+
+ return FALSE;
+}
/* Check for all available devices. This really should be
* portable for at least all plattforms using the gnu c lib
* TODO: drop it, use glibtop_get_netlist directly / gchar**
*/
GList*
-get_available_devices(void)
+get_available_devices (void)
{
- glibtop_netlist buf;
- char **devices, **dev;
- GList *device_glist = NULL;
+ glibtop_netlist buf;
+ char **devices, **dev;
+ GList *device_glist = NULL;
+
+ devices = glibtop_get_netlist (&buf);
- devices = glibtop_get_netlist(&buf);
+ for (dev = devices; *dev; ++dev) {
+ device_glist = g_list_prepend (device_glist, g_strdup (*dev));
+ }
+ device_glist = g_list_sort (device_glist, (GCompareFunc) g_strcmp0);
- for(dev = devices; *dev; ++dev) {
- device_glist = g_list_prepend(device_glist, g_strdup(*dev));
- }
+ g_strfreev (devices);
- g_strfreev(devices);
+ return device_glist;
+}
- return device_glist;
+GSList*
+get_ip_address_list (const char *iface_name,
+ gboolean ipv4)
+{
+ GSList *list = NULL;
+ struct ifaddrs *ifaces;
+
+ if (getifaddrs (&ifaces) != -1) {
+ int family;
+ char ip[INET6_ADDRSTRLEN];
+
+ family = ipv4 ? AF_INET : AF_INET6;
+ for (struct ifaddrs *iface = ifaces; iface != NULL; iface = iface->ifa_next) {
+ if (iface->ifa_addr == NULL)
+ continue;
+
+ if ((iface->ifa_addr->sa_family == family) &&
+ !g_strcmp0 (iface->ifa_name, iface_name))
+ {
+ unsigned int netmask = 0;
+ void *sinx_addr = NULL;
+
+ if (iface->ifa_addr->sa_family == AF_INET6) {
+ struct sockaddr_in6 ip6_addr;
+ struct sockaddr_in6 ip6_network;
+ uint32_t ip6_netmask = 0;
+ const char *scope;
+ int i;
+
+ memcpy (&ip6_addr, iface->ifa_addr, sizeof (struct sockaddr_in6));
+ memcpy (&ip6_network, iface->ifa_netmask, sizeof (struct sockaddr_in6));
+
+ /* get network scope */
+ if (IN6_IS_ADDR_LINKLOCAL (&ip6_addr.sin6_addr)) {
+ scope = _("link-local");
+ } else if (IN6_IS_ADDR_SITELOCAL (&ip6_addr.sin6_addr)) {
+ scope = _("site-local");
+ } else if (IN6_IS_ADDR_V4MAPPED (&ip6_addr.sin6_addr)) {
+ scope = _("v4mapped");
+ } else if (IN6_IS_ADDR_V4COMPAT (&ip6_addr.sin6_addr)) {
+ scope = _("v4compat");
+ } else if (IN6_IS_ADDR_LOOPBACK (&ip6_addr.sin6_addr)) {
+ scope = _("host");
+ } else if (IN6_IS_ADDR_UNSPECIFIED (&ip6_addr.sin6_addr)) {
+ scope = _("unspecified");
+ } else {
+ scope = _("global");
+ }
+
+ /* get network ip */
+ sinx_addr = &ip6_addr.sin6_addr;
+ inet_ntop (iface->ifa_addr->sa_family, sinx_addr, ip, sizeof (ip));
+
+ /* get network mask length */
+ for (i = 0; i < 4; i++) {
+ ip6_netmask = ntohl (((uint32_t*)(&ip6_network.sin6_addr))[i]);
+ while (ip6_netmask) {
+ netmask++;
+ ip6_netmask <<= 1;
+ }
+ }
+
+ list = g_slist_prepend (list,
+ g_strdup_printf ("%s/%u (%s)",
+ ip, netmask, scope));
+ } else {
+ struct sockaddr_in ip4_addr;
+ struct sockaddr_in ip4_network;
+ in_addr_t ip4_netmask = 0;
+
+ memcpy (&ip4_addr, iface->ifa_addr, sizeof (struct sockaddr_in));
+ memcpy (&ip4_network, iface->ifa_netmask, sizeof (struct sockaddr_in));
+
+ /* get network ip */
+ sinx_addr = &ip4_addr.sin_addr;
+ inet_ntop (iface->ifa_addr->sa_family, sinx_addr, ip, sizeof (ip));
+
+ /* get network mask length */
+ ip4_netmask = ntohl (ip4_network.sin_addr.s_addr);
+ while (ip4_netmask) {
+ netmask++;
+ ip4_netmask <<= 1;
+ }
+
+ list = g_slist_prepend (list,
+ g_strdup_printf ("%s/%u", ip, netmask));
+ }
+ }
+ }
+ if (list != NULL)
+ list = g_slist_sort (list, (GCompareFunc) g_strcmp0);
+ freeifaddrs (ifaces);
+ }
+ return list;
}
-const gchar*
-get_default_route(void)
+GSList*
+get_ip6_address_list (const char *iface_name)
{
- FILE *fp;
- static char device[50];
+ GSList *list = NULL;
+ struct ifaddrs *ifaces;
- fp = fopen("/proc/net/route", "r");
+ if (getifaddrs (&ifaces) != -1) {
+ char ip6[INET6_ADDRSTRLEN];
- if (fp == NULL) return NULL;
+ for (struct ifaddrs *iface = ifaces; iface != NULL; iface = iface->ifa_next) {
+ if ((iface->ifa_addr == NULL) || (iface->ifa_addr->sa_family != AF_INET6))
+ continue;
- while (!feof(fp)) {
- char buffer[1024];
- unsigned int ip, gw, flags, ref, use, metric, mask, mtu, window, irtt;
- int retval;
- char *rv;
+ if (!g_strcmp0 (iface->ifa_name, iface_name)) {
+ void *sinx_addr = NULL;
- rv = fgets(buffer, 1024, fp);
- if (!rv) {
- break;
- }
+ struct sockaddr_in6 ip6_addr;
- retval = sscanf(buffer, "%49s %x %x %x %u %u %u %x %u %u %u",
- device, &ip, &gw, &flags, &ref, &use, &metric, &mask, &mtu, &window, &irtt);
+ memcpy (&ip6_addr, iface->ifa_addr, sizeof (struct sockaddr_in6));
- if (retval != 11) continue;
+ /* get network ip */
+ sinx_addr = &ip6_addr.sin6_addr;
+ inet_ntop (iface->ifa_addr->sa_family, sinx_addr, ip6, sizeof (ip6));
- if (ip == 0 && !is_dummy_device(device)) {
- fclose(fp);
- return device;
- }
- }
- fclose(fp);
- return NULL;
+ list = g_slist_prepend (list, g_strdup (ip6));
+ }
+ }
+
+ if (list != NULL)
+ list = g_slist_sort (list, (GCompareFunc) g_strcmp0);
+ freeifaddrs (ifaces);
+ }
+ return list;
}
-void
-free_devices_list(GList *list)
+const gchar*
+get_default_route (void)
{
- g_list_free_full (list, g_free);
+ FILE *fp;
+ static char device[50];
+
+ fp = fopen ("/proc/net/route", "r");
+
+ if (fp == NULL) return NULL;
+
+ while (!feof (fp)) {
+ char buffer[1024];
+ unsigned int ip, gw, flags, ref, use, metric, mask, mtu, window, irtt;
+ int retval;
+ char *rv;
+
+ rv = fgets (buffer, 1024, fp);
+ if (!rv) {
+ break;
+ }
+
+ retval = sscanf (buffer, "%49s %x %x %x %u %u %u %x %u %u %u",
+ device, &ip, &gw, &flags, &ref, &use, &metric,
+ &mask, &mtu, &window, &irtt);
+
+ if (retval != 11) continue;
+
+ if (ip == 0 && !is_dummy_device (device)) {
+ fclose (fp);
+ return device;
+ }
+ }
+ fclose (fp);
+ return NULL;
}
/* Frees a DevInfo struct and all the stuff it contains
@@ -175,13 +307,13 @@ get_ptp_info (DevInfo *devinfo)
if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
return;
- if (ioctl(fd, SIOCGIFDSTADDR, &request) >= 0) {
+ if (ioctl (fd, SIOCGIFDSTADDR, &request) >= 0) {
struct sockaddr_in* addr;
addr = (struct sockaddr_in*)&request.ifr_dstaddr;
devinfo->ptpip = addr->sin_addr.s_addr;
}
- close(fd);
+ close (fd);
}
void
@@ -192,7 +324,7 @@ get_device_info (const char *device,
glibtop_netload netload;
gboolean ptp = FALSE;
- g_assert(device);
+ g_assert (device);
*info = g_new0 (DevInfo, 1);
devinfo = *info;
@@ -211,11 +343,11 @@ get_device_info (const char *device,
else if (netload.if_flags & (1L << GLIBTOP_IF_FLAGS_WIRELESS)) {
devinfo->type = DEV_WIRELESS;
}
- else if(netload.if_flags & (1L << GLIBTOP_IF_FLAGS_POINTOPOINT)) {
- if (g_str_has_prefix(device, "plip")) {
+ else if (netload.if_flags & (1L << GLIBTOP_IF_FLAGS_POINTOPOINT)) {
+ if (g_str_has_prefix (device, "plip")) {
devinfo->type = DEV_PLIP;
}
- else if (g_str_has_prefix(device, "sl")) {
+ else if (g_str_has_prefix (device, "sl")) {
devinfo->type = DEV_SLIP;
}
else {
@@ -247,7 +379,6 @@ get_device_info (const char *device,
if (devinfo->running) {
devinfo->ip = netload.address;
devinfo->netmask = netload.subnet;
- memcpy (devinfo->ipv6, netload.address6, 16);
#if defined (HAVE_NL)
if (devinfo->type != DEV_WIRELESS) {
devinfo->tx = netload.bytes_out;
@@ -261,70 +392,74 @@ get_device_info (const char *device,
if (ptp)
get_ptp_info (devinfo);
#endif /* HAVE_NL */
- }
+ }
}
gboolean
compare_device_info (const DevInfo *a,
const DevInfo *b)
{
- g_assert(a && b);
- g_assert(a->name && b->name);
-
- if (!g_str_equal(a->name, b->name)) return TRUE;
- if (a->ip != b->ip) return TRUE;
- /* Ignore hwaddr, ptpip and netmask... I think this is ok */
- if (a->up != b->up) return TRUE;
- if (a->running != b->running) return TRUE;
-
- return FALSE;
+ g_assert (a && b);
+ g_assert (a->name && b->name);
+
+ if (!g_str_equal (a->name, b->name))
+ return TRUE;
+ if (a->ip != b->ip)
+ return TRUE;
+ /* Ignore hwaddr, ptpip and netmask... I think this is ok */
+ if (a->up != b->up)
+ return TRUE;
+ if (a->running != b->running)
+ return TRUE;
+
+ return FALSE;
}
#ifdef HAVE_IW
void
get_wireless_info (DevInfo *devinfo)
{
- int fd;
- int newqual;
- wireless_info info = {0};
+ int fd;
+ int newqual;
+ wireless_info info = {0};
- fd = iw_sockets_open ();
+ fd = iw_sockets_open ();
- if (fd < 0)
- return;
+ if (fd < 0)
+ return;
- if (iw_get_basic_config (fd, devinfo->name, &info.b) < 0)
- goto out;
+ if (iw_get_basic_config (fd, devinfo->name, &info.b) < 0)
+ goto out;
- if (info.b.has_essid) {
- if ((!devinfo->essid) || (strcmp (devinfo->essid, info.b.essid) != 0)) {
- devinfo->essid = g_strdup (info.b.essid);
- }
- } else {
- devinfo->essid = NULL;
- }
+ if (info.b.has_essid) {
+ if ((!devinfo->essid) || (strcmp (devinfo->essid, info.b.essid) != 0)) {
+ devinfo->essid = g_strdup (info.b.essid);
+ }
+ } else {
+ devinfo->essid = NULL;
+ }
- if (iw_get_stats (fd, devinfo->name, &info.stats, &info.range, info.has_range) >= 0)
- info.has_stats = 1;
+ if (iw_get_stats (fd, devinfo->name, &info.stats, &info.range, info.has_range) >= 0)
+ info.has_stats = 1;
- if (info.has_stats) {
- if ((iw_get_range_info(fd, devinfo->name, &info.range) >= 0) && (info.range.max_qual.qual > 0)) {
- newqual = 0.5f + (100.0f * info.stats.qual.qual) / (1.0f * info.range.max_qual.qual);
- } else {
- newqual = info.stats.qual.qual;
- }
+ if (info.has_stats) {
+ if ((iw_get_range_info (fd, devinfo->name, &info.range) >= 0) && (info.range.max_qual.qual > 0)) {
+ newqual = 0.5f + (100.0f * info.stats.qual.qual) / (1.0f * info.range.max_qual.qual);
+ } else {
+ newqual = info.stats.qual.qual;
+ }
- newqual = CLAMP(newqual, 0, 100);
- if (devinfo->qual != newqual)
- devinfo->qual = newqual;
+ newqual = CLAMP (newqual, 0, 100);
+ if (devinfo->qual != newqual)
+ devinfo->qual = newqual;
- } else {
- devinfo->qual = 0;
- }
+ } else {
+ devinfo->qual = 0;
+ }
- goto out;
+ goto out;
out:
- if (fd != -1)
- close (fd);
+ if (fd != -1)
+ close (fd);
}
#endif /* HAVE_IW */
@@ -369,7 +504,6 @@ out_handle_destroy:
return err;
}
-
static void
nl80211_cleanup (struct nl80211_state *state)
{
@@ -408,10 +542,14 @@ scan_cb (struct nl_msg *msg,
g_warning ("failed to parse nested attributes!");
return NL_SKIP;
}
- if (!bss[NL80211_BSS_BSSID]) return NL_SKIP;
- if (!bss[NL80211_BSS_STATUS]) return NL_SKIP;
+ if (!bss[NL80211_BSS_BSSID])
+ return NL_SKIP;
+ if (!bss[NL80211_BSS_STATUS])
+ return NL_SKIP;
+
+ if (nla_get_u32 (bss[NL80211_BSS_STATUS]) != NL80211_BSS_STATUS_ASSOCIATED)
+ return NL_SKIP;
- if (nla_get_u32 (bss[NL80211_BSS_STATUS]) != NL80211_BSS_STATUS_ASSOCIATED) return NL_SKIP;
memcpy (devinfo->station_mac_addr, nla_data (bss[NL80211_BSS_BSSID]), ETH_ALEN);
return NL_SKIP;
@@ -472,10 +610,10 @@ parse_bitrate (struct nlattr *bitrate_attr,
pos += snprintf (pos, buflen - (pos - buf),
_(" HE-MCS %d"), nla_get_u8 (rinfo[NL80211_RATE_INFO_HE_MCS]));
if (rinfo[NL80211_RATE_INFO_HE_NSS])
- pos += snprintf(pos, buflen - (pos - buf),
+ pos += snprintf (pos, buflen - (pos - buf),
_(" HE-NSS %d"), nla_get_u8 (rinfo[NL80211_RATE_INFO_HE_NSS]));
if (rinfo[NL80211_RATE_INFO_HE_GI])
- pos += snprintf(pos, buflen - (pos - buf),
+ pos += snprintf (pos, buflen - (pos - buf),
_(" HE-GI %d"), nla_get_u8 (rinfo[NL80211_RATE_INFO_HE_GI]));
if (rinfo[NL80211_RATE_INFO_HE_DCM])
snprintf (pos, buflen - (pos - buf),
@@ -512,8 +650,8 @@ station_cb (struct nl_msg *msg,
return NL_SKIP;
}
if (nla_parse_nested (sinfo, NL80211_STA_INFO_MAX,
- tb[NL80211_ATTR_STA_INFO],
- stats_policy)) {
+ tb[NL80211_ATTR_STA_INFO],
+ stats_policy)) {
g_warning ("failed to parse nested attributes!\n");
return NL_SKIP;
}
@@ -610,7 +748,7 @@ iface_cb (struct nl_msg *msg,
struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
nla_parse (tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata (gnlh, 0),
- genlmsg_attrlen(gnlh, 0), NULL);
+ genlmsg_attrlen (gnlh, 0), NULL);
if (tb_msg[NL80211_ATTR_MAC]) {
memcpy (devinfo->hwaddr, nla_data (tb_msg[NL80211_ATTR_MAC]), ETH_ALEN);
@@ -677,7 +815,7 @@ get_wireless_info (DevInfo *devinfo)
ret = nl_recvmsgs_default (nlstate.sock);
nlmsg_free (msg);
if (ret < 0) {
- g_warning ("failed to recive netlink message");
+ g_warning ("failed to receive netlink message");
}
if (!devinfo->running)
@@ -701,7 +839,7 @@ get_wireless_info (DevInfo *devinfo)
ret = nl_recvmsgs_default (nlstate.sock);
nlmsg_free (msg);
if (ret < 0) {
- g_warning ("failed to recive netlink message");
+ g_warning ("failed to receive netlink message");
goto cleanup;
}
@@ -727,7 +865,7 @@ get_wireless_info (DevInfo *devinfo)
ret = nl_recvmsgs_default (nlstate.sock);
nlmsg_free (msg);
if (ret < 0) {
- g_warning ("failed to recive netlink message");
+ g_warning ("failed to receive netlink message");
}
cleanup: