
// nload.c - v.1.0
//
// prints network load
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <poll.h>
#include <limits.h>
#include <err.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>

#include <kvm.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>


int main(int argc, char **argv) {

	kvm_t *kd;
	static char buf[_POSIX2_LINE_MAX]; /* 2048 */
	struct nlist nl[] = { { "_ifnet" }, { "" } };
	paddr_t addr;
	struct ifnet_head ih;
	struct ifnet in;
	unsigned int ibps, ipps, obps, opps;
	int interval = 5;
	int e;

	if (argc < 2) {
		fprintf(stderr, "usage: %s <if name> [interval]\n",argv[0]);
		return 1;
	}

	if (argc > 2) {
		interval = atoi(argv[2]);
		if (interval<1) {
			fprintf(stderr,"invalid interval!");
			return 1;
		}
	}

	kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, buf);
	if (kd == NULL) {
		fprintf(stderr,"Could not open kvm: %s\n", buf);
	     	return -2;
	}

	/* get ifs */

	if (kvm_nlist(kd, nl) == -1)
	{
	     fprintf(stderr,"Could not kvm_nlist\n");
	     return -3;
	}

	/* loop through ifs */

	kvm_read(kd, nl[0].n_value, &ih, sizeof(ih));
	addr = (paddr_t)ih.tqh_first;
     	do
     	{
     		kvm_read(kd, addr, &in, sizeof(in));

		if ( !strcmp(in.if_xname,argv[1]) ) {
			
			while (1) {

     				kvm_read(kd, addr, &in, sizeof(in));
				ipps = in.if_data.ifi_ipackets;
				ibps = in.if_data.ifi_ibytes;
				opps = in.if_data.ifi_opackets;
				obps = in.if_data.ifi_obytes;

				sleep(interval);

     				kvm_read(kd, addr, &in, sizeof(in));
				ipps = (in.if_data.ifi_ipackets - ipps) / interval;
				ibps = (in.if_data.ifi_ibytes - ibps) * 8 / 1000 / interval;
				opps = (in.if_data.ifi_opackets - opps) / interval;
				obps = (in.if_data.ifi_obytes - obps) * 8 / 1000 / interval;

				fprintf(stdout, "%s:  in: %i kbps (%i pps)  out: %i kbps (%i pps)\n", in.if_xname, ibps, ipps, obps, opps);
				fflush(stdout);
			}
		}

	        if (!(addr = (u_long)in.if_list.tqe_next))
			break;

	} while (1);

	fprintf(stderr, "No such interface found!\n");

	return 0;
}
