10

I'm looking for a way to get hold of network stats in C on Linux and MacOSX. Specifically, I need to monitor the number of bytes uploaded and downloaded from each network adapter on the system - I don't need to do packet inspection, or differentiate between protocols, just a 'total bytes' counter which I can poll at intervals would be fine. In Windows I can do this using the iphlpapi.dll library via GetIfTable (to list the network adapters) and GetIfEntry (to read the stats), but I can't find the Linux/OSX equivalents. My knowledge of C is fairly basic so I would appreciate a solution that isn't too involved. Any help would be much appreciated!

  • From what I have found thus far, you aren't going to be able to use common code on both platforms. It appears Linux uses the file system to retain this information, and the normal method of query the systems is to read the files. On OSX the information is held in memory and obscure files. – Armand Jun 28 '13 at 16:27

3 Answers3

25

The Darwin netstat source code uses sysctl. Here's some code that prints the number of bytes in and out on OSX:

#import <Foundation/Foundation.h>
#include <sys/sysctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <net/route.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    int mib[] = {
        CTL_NET,
        PF_ROUTE,
        0,
        0,
        NET_RT_IFLIST2,
        0
    };
    size_t len;
    if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
        fprintf(stderr, "sysctl: %s\n", strerror(errno));
        exit(1);
    }
    char *buf = (char *)malloc(len);
    if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
        fprintf(stderr, "sysctl: %s\n", strerror(errno));
        exit(1);
    }
    char *lim = buf + len;
    char *next = NULL;
    u_int64_t totalibytes = 0;
    u_int64_t totalobytes = 0;
    for (next = buf; next < lim; ) {
        struct if_msghdr *ifm = (struct if_msghdr *)next;
        next += ifm->ifm_msglen;
        if (ifm->ifm_type == RTM_IFINFO2) {
            struct if_msghdr2 *if2m = (struct if_msghdr2 *)ifm;
            totalibytes += if2m->ifm_data.ifi_ibytes;
            totalobytes += if2m->ifm_data.ifi_obytes;
        }
    }
    printf("total ibytes %qu\tobytes %qu\n", totalibytes, totalobytes);
    [pool drain];
    return 0;
}
Stefan
  • 1,248
  • 11
  • 14
1

on Linux:

  • low level: check /sys/class/net/eth0/statistics/
  • slightly higher level: ip -s link show eth0
  • graphical: iftop
  • interactive: iptraf
Javier
  • 60,510
  • 8
  • 78
  • 126
  • 5
    Title of question is OSX. First two do not work on OSX. Bottom two are not suited to question either, being graphical and interactive. – Purrell Jul 23 '13 at 21:07
  • 2
    both the tile and the body of the question mention Linux and OSX. this is about the Linux part – Javier Nov 22 '13 at 06:34
1

I can't speak to OSX but on linux take a look at /proc/net/dev.

If you do 'cat /proc/net/dev' you should see statistics including 'bytes' - the total number of bytes of data transmitted or received by the interface. You can read the file within your own program.

EDIT:

I didn't read your whole question. This article should help you get started with /proc and has a section on /proc/net/dev.

Also, to list the interfaces you can call ioctl with the SIOCGIFCONF option. You can Google for a decent code example on how to loop through the returned data. Or you can simply pull it out of the /proc.net/dev data mentioned above, which should be easier.

Duck
  • 26,924
  • 5
  • 64
  • 92
  • Or, as per Javier's answer, look at the files under `/sys/class/net/{your network interface}/statistics`, where `{your network interface}` is the name of the network interface you want to look at, e.g. `eth0` for the first Ethernet interface. sysfs (on `/sys`) is newer than procfs (on `/proc`). –  May 21 '12 at 17:28