Blame sysdeps/freebsd/netload.c

Packit d37888
/* Copyright (C) 1998-99 Martin Baulig
Packit d37888
   Copyright (C) 2014 Gleb Smirnoff
Packit d37888
   This file is part of LibGTop 1.0.
Packit d37888
Packit d37888
   Contributed by Martin Baulig <martin@home-of-linux.org>, October 1998.
Packit d37888
   Contributed by Gleb Smirnoff <glebius@FreeBSD.org>, September 2014
Packit d37888
Packit d37888
   LibGTop is free software; you can redistribute it and/or modify it
Packit d37888
   under the terms of the GNU General Public License as published by
Packit d37888
   the Free Software Foundation; either version 2 of the License,
Packit d37888
   or (at your option) any later version.
Packit d37888
Packit d37888
   LibGTop is distributed in the hope that it will be useful, but WITHOUT
Packit d37888
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
Packit d37888
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
Packit d37888
   for more details.
Packit d37888
Packit d37888
   You should have received a copy of the GNU General Public License
Packit d37888
   along with LibGTop; see the file COPYING. If not, write to the
Packit d37888
   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Packit d37888
   Boston, MA 02110-1301, USA.
Packit d37888
*/
Packit d37888
Packit d37888
#include <config.h>
Packit d37888
#include <glibtop.h>
Packit d37888
#include <glibtop/error.h>
Packit d37888
#include <glibtop/netload.h>
Packit d37888
Packit d37888
#include <glibtop_suid.h>
Packit d37888
Packit d37888
#include <sys/ioctl.h>
Packit d37888
#include <sys/sockio.h>
Packit d37888
#include <netinet/in.h>
Packit d37888
#include <net/if.h>
Packit d37888
#include <net/if_dl.h>
Packit d37888
#include <net/if_media.h>
Packit d37888
#include <ifaddrs.h>
Packit d37888
Packit d37888
static const unsigned long _glibtop_sysdeps_netload =
Packit d37888
(1L << GLIBTOP_NETLOAD_IF_FLAGS) +
Packit d37888
(1L << GLIBTOP_NETLOAD_MTU) +
Packit d37888
(1L << GLIBTOP_NETLOAD_PACKETS_IN) +
Packit d37888
(1L << GLIBTOP_NETLOAD_PACKETS_OUT) +
Packit d37888
(1L << GLIBTOP_NETLOAD_PACKETS_TOTAL) +
Packit d37888
(1L << GLIBTOP_NETLOAD_BYTES_IN) +
Packit d37888
(1L << GLIBTOP_NETLOAD_BYTES_OUT) +
Packit d37888
(1L << GLIBTOP_NETLOAD_BYTES_TOTAL) +
Packit d37888
(1L << GLIBTOP_NETLOAD_ERRORS_IN) +
Packit d37888
(1L << GLIBTOP_NETLOAD_ERRORS_OUT) +
Packit d37888
(1L << GLIBTOP_NETLOAD_ERRORS_TOTAL) +
Packit d37888
(1L << GLIBTOP_NETLOAD_COLLISIONS) +
Packit d37888
(1L << GLIBTOP_NETLOAD_HWADDRESS);
Packit d37888
Packit d37888
static const unsigned long _glibtop_sysdeps_netload_data =
Packit d37888
(1L << GLIBTOP_NETLOAD_SUBNET) +
Packit d37888
(1L << GLIBTOP_NETLOAD_ADDRESS);
Packit d37888
Packit d37888
static const unsigned long _glibtop_sysdeps_netload6 =
Packit d37888
(1L << GLIBTOP_NETLOAD_ADDRESS6) +
Packit d37888
(1L << GLIBTOP_NETLOAD_PREFIX6) +
Packit d37888
(1L << GLIBTOP_NETLOAD_SCOPE6);
Packit d37888
Packit d37888
/* Init function. */
Packit d37888
Packit d37888
void
Packit d37888
_glibtop_init_netload_p (glibtop *server)
Packit d37888
{
Packit d37888
        server->sysdeps.netload = _glibtop_sysdeps_netload;
Packit d37888
}
Packit d37888
Packit d37888
/* Provides Network statistics. */
Packit d37888
Packit d37888
void
Packit d37888
glibtop_get_netload_p (glibtop *server, glibtop_netload *buf,
Packit d37888
                       const char *interface)
Packit d37888
{
Packit d37888
        struct ifaddrs *ifap, *ifa;
Packit d37888
Packit d37888
        memset (buf, 0, sizeof (glibtop_netload));
Packit d37888
Packit d37888
        if (server->sysdeps.netload == 0)
Packit d37888
                return;
Packit d37888
Packit d37888
        if (getifaddrs(&ifap) != 0) {
Packit d37888
                glibtop_warn_io_r (server, "getifaddrs");
Packit d37888
                return;
Packit d37888
        }
Packit d37888
Packit d37888
#define IFA_STAT(s)     (((struct if_data *)ifa->ifa_data)->ifi_ ## s)
Packit d37888
Packit d37888
        for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
Packit d37888
                if (strcmp (ifa->ifa_name, interface) != 0)
Packit d37888
                        continue;
Packit d37888
Packit d37888
                switch (ifa->ifa_addr->sa_family) {
Packit d37888
                case AF_LINK: {
Packit d37888
                        struct sockaddr_dl *sdl;
Packit d37888
                        struct ifmediareq ifmr;
Packit d37888
                        struct ifreq ifr;
Packit d37888
                        int s, flags;
Packit d37888
Packit d37888
                        s = socket(AF_INET, SOCK_DGRAM, 0);
Packit d37888
                        if (s < 0) {
Packit d37888
                                glibtop_warn_io_r(server, "socket(AF_INET)");
Packit d37888
                                break;
Packit d37888
                        }
Packit d37888
Packit d37888
                        memset(&ifmr, 0, sizeof(ifmr));
Packit d37888
                        (void)strlcpy(ifmr.ifm_name, ifa->ifa_name,
Packit d37888
                                sizeof(ifmr.ifm_name));
Packit d37888
                        if (ioctl(s, SIOCGIFXMEDIA, (caddr_t)&ifmr) < 0 &&
Packit d37888
                            ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
Packit d37888
                                glibtop_warn_io_r(server, "ioctl(SIOCGIFMEDIA)");
Packit d37888
                        } else {
Packit d37888
                                if (IFM_TYPE (ifmr.ifm_current) & IFM_IEEE80211)
Packit d37888
                                    buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_WIRELESS);
Packit d37888
                                if (IFM_TYPE (ifmr.ifm_active) & IFM_IEEE80211)
Packit d37888
                                    buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_WIRELESS);
Packit d37888
                        }
Packit d37888
Packit d37888
                        memset(&ifr, 0, sizeof(ifr));
Packit d37888
                        (void)strlcpy(ifr.ifr_name, ifa->ifa_name,
Packit d37888
                                sizeof(ifr.ifr_name));
Packit d37888
                        if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
Packit d37888
                                glibtop_warn_io_r(server, "ioctl(SIOCGIFFLAGS)");
Packit d37888
                                close(s);
Packit d37888
                                break;
Packit d37888
                        }
Packit d37888
Packit d37888
                        close(s);
Packit d37888
Packit d37888
                        flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);
Packit d37888
Packit d37888
                        if (flags & IFF_UP)
Packit d37888
                                buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_UP);
Packit d37888
                        if (flags & IFF_BROADCAST)
Packit d37888
                                buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_BROADCAST);
Packit d37888
                        if (flags & IFF_DEBUG)
Packit d37888
                                buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_DEBUG);
Packit d37888
                        if (flags & IFF_LOOPBACK)
Packit d37888
                                buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_LOOPBACK);
Packit d37888
                        if (flags & IFF_POINTOPOINT)
Packit d37888
                                buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_POINTOPOINT);
Packit d37888
                        if (flags & IFF_RUNNING)
Packit d37888
                                buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_RUNNING);
Packit d37888
                        if (flags & IFF_NOARP)
Packit d37888
                                buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_NOARP);
Packit d37888
                        if (flags & IFF_PROMISC)
Packit d37888
                                buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_PROMISC);
Packit d37888
                        if (flags & IFF_ALLMULTI)
Packit d37888
                                buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_ALLMULTI);
Packit d37888
                        if (flags & IFF_OACTIVE)
Packit d37888
                                buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_OACTIVE);
Packit d37888
                        if (flags & IFF_SIMPLEX)
Packit d37888
                                buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_SIMPLEX);
Packit d37888
                        if (flags & IFF_LINK0)
Packit d37888
                                buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_LINK0);
Packit d37888
                        if (flags & IFF_LINK1)
Packit d37888
                                buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_LINK1);
Packit d37888
                        if (flags & IFF_LINK2)
Packit d37888
                                buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_LINK2);
Packit d37888
                        if (flags & IFF_ALTPHYS)
Packit d37888
                                buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_ALTPHYS);
Packit d37888
                        if (flags & IFF_MULTICAST)
Packit d37888
                                buf->if_flags |= (1L << GLIBTOP_IF_FLAGS_MULTICAST);
Packit d37888
Packit d37888
                        buf->packets_in = IFA_STAT(ipackets);
Packit d37888
                        buf->packets_out = IFA_STAT(opackets);
Packit d37888
                        buf->packets_total = buf->packets_in + buf->packets_out;
Packit d37888
Packit d37888
                        buf->bytes_in = IFA_STAT(ibytes);
Packit d37888
                        buf->bytes_out = IFA_STAT(obytes);
Packit d37888
                        buf->bytes_total = buf->bytes_in + buf->bytes_out;
Packit d37888
Packit d37888
                        buf->errors_in = IFA_STAT(ierrors);
Packit d37888
                        buf->errors_out = IFA_STAT(oerrors);
Packit d37888
                        buf->errors_total = buf->errors_in + buf->errors_out;
Packit d37888
Packit d37888
                        buf->collisions = IFA_STAT(collisions);
Packit d37888
Packit d37888
                        sdl = (struct sockaddr_dl *)(void *)ifa->ifa_addr;
Packit d37888
                        memcpy(buf->hwaddress, LLADDR(sdl),
Packit d37888
                                sizeof(buf->hwaddress));
Packit d37888
                        buf->mtu = IFA_STAT(mtu);
Packit d37888
                        buf->flags |= _glibtop_sysdeps_netload;
Packit d37888
                        break;
Packit d37888
                }
Packit d37888
                case AF_INET: {
Packit d37888
                        struct sockaddr_in *sin;
Packit d37888
Packit d37888
                        sin = (struct sockaddr_in *)(void *)ifa->ifa_addr;
Packit d37888
                        buf->address = sin->sin_addr.s_addr;
Packit d37888
                        sin = (struct sockaddr_in *)(void *)ifa->ifa_netmask;
Packit d37888
                        buf->subnet = sin->sin_addr.s_addr & buf->address;
Packit d37888
                        buf->flags |= _glibtop_sysdeps_netload_data;
Packit d37888
                        break;
Packit d37888
                }
Packit d37888
                case AF_INET6: {
Packit d37888
                        struct sockaddr_in6 *sin6;
Packit d37888
Packit d37888
                        sin6 = (struct sockaddr_in6 *)(void *)ifa->ifa_addr;
Packit d37888
                        memcpy(buf->address6, &sin6->sin6_addr,
Packit d37888
                                sizeof(buf->address6));
Packit d37888
                        buf->scope6 = (guint8 )sin6->sin6_scope_id;
Packit d37888
                        sin6 = (struct sockaddr_in6 *)(void *)ifa->ifa_netmask;
Packit d37888
                        memcpy(buf->prefix6, &sin6->sin6_addr,
Packit d37888
                                sizeof(buf->prefix6));
Packit d37888
                        buf->flags |= _glibtop_sysdeps_netload6;
Packit d37888
                        break;
Packit d37888
                }
Packit d37888
                } // switch() end
Packit d37888
        }
Packit d37888
        freeifaddrs(ifap);
Packit d37888
}