plan9fox/sys/src/cmd/ip/measure.c
2011-03-30 19:35:09 +03:00

197 lines
3.7 KiB
C

#include <u.h>
#include <libc.h>
#include <bio.h>
#include <ip.h>
/*
* ether packet
*/
typedef struct Etherpkt Etherpkt;
struct Etherpkt {
uchar d[6];
uchar s[6];
uchar type[2];
char data[1500];
};
#define ETHERMINTU 60 /* minimum transmit size */
#define ETHERMAXTU 1514 /* maximum transmit size */
#define ETHERHDRSIZE 14 /* size of an ethernet header */
/*
* ip packets
*/
typedef struct Ippkt Ippkt;
struct Ippkt
{
uchar vihl; /* Version and header length */
uchar tos; /* Type of service */
uchar length[2]; /* packet length */
uchar id[2]; /* Identification */
uchar frag[2]; /* Fragment information */
uchar ttl; /* Time to live */
uchar proto; /* Protocol */
uchar cksum[2]; /* Header checksum */
uchar src[4]; /* Ip source */
uchar dst[4]; /* Ip destination */
char data[1];
};
#define IP_HDRSIZE 20
#define IP_UDPPROTO 17
#define IP_MBONEPROTO 4
#define IP_TCPPROTO 6
#define IP_ILPROTO 40
#define IP_ICMPPROTO 1
#define IP_DF 0x4000
#define IP_MF 0x2000
#define NetS(x) (((x)[0]<<8) | (x)[1])
#define NetL(x) (((x)[0]<<24) | ((x)[1]<<16) | ((x)[2]<<8) | (x)[3])
/*
* run flags
*/
int debug;
int mbone;
ulong protoin[256];
ulong protoout[256];
ulong protopin[256];
ulong protopout[256];
void
error(char *s)
{
char buf[ERRMAX];
errstr(buf, sizeof buf);
fprint(2, "snoopy: %s %s\n", buf, s);
exits("death");
}
void
warning(char *s)
{
char buf[ERRMAX];
errstr(buf, sizeof buf);
fprint(2, "snoopy: %s %s\n", buf, s);
}
void
printproto(int p)
{
print("\t%d(%ld %ld %ld %ld)", p, protoin[p], protopin[p], protoout[p], protopout[p]);
}
void
main(int argc, char *argv[])
{
Etherpkt e;
Ippkt *ip;
long n;
int fd, cfd;
int ts, len, t;
long start;
int delta;
uchar target[6];
char buf[256];
ulong samples;
samples = -1;
ARGBEGIN{
case 'd':
debug++;
break;
case 's':
samples = atoi(ARGF());
break;
}ARGEND;
if(argc < 2){
fprint(2, "usage: %s device ip-addr [minutes-per-sample]\n", argv0);
exits("usage");
}
if(argc > 2)
delta = atoi(argv[2])*60*1000;
else
delta = 5*60*1000;
parseether(target, argv[1]);
fmtinstall('E', eipfmt);
fmtinstall('I', eipfmt);
snprint(buf, sizeof(buf), "%s!-2", argv[0]);
fd = dial(buf, 0, 0, &cfd);
if(fd < 0)
error("opening ether data");
if(write(cfd, "promiscuous", sizeof("promiscuous")-1) <= 0)
error("connecting");
start = 0;
fd = -1;
for(;;){
if(fd < 0){
fd = dial(buf, 0, 0, &cfd);
if(fd < 0)
error("opening ether data");
if(write(cfd, "promiscuous", sizeof("promiscuous")-1) <= 0)
error("connecting");
close(cfd);
}
n = read(fd, &e, sizeof(e));
if(n <= 0)
break;
ts = NetL(&e.d[60]);
n = NetS(&e.d[58]) - ETHERHDRSIZE;
if(n < 0)
continue;
if(start == 0)
start = ts;
t = NetS(e.type);
if(t == 0x0800 || (t&0xFF00) == 0x1000){
ip = (Ippkt*)e.data;
len = NetS(ip->length);
if(len > n)
len = n;
if(debug)
fprint(2, "%I -> %I %d\n", ip->src, ip->dst, len);
if(memcmp(e.s, target, 6) == 0){
protopin[0]++;
protoin[0] += len;
if(ip->proto){
protopin[ip->proto]++;
protoin[ip->proto] += len;
}
}
if(memcmp(e.d, target, 6) == 0){
protopout[0]++;
protoout[0] += len;
if(ip->proto){
protopout[ip->proto]++;
protoout[ip->proto] += len;
}
}
}
if(ts - start >= delta){
print("%8.8ld %ld", time(0), ts - start);
printproto(0);
printproto(IP_MBONEPROTO);
printproto(IP_UDPPROTO);
printproto(IP_TCPPROTO);
print("\n");
start = 0;
memset(protoin, 0, sizeof(protoin));
memset(protoout, 0, sizeof(protoout));
memset(protopin, 0, sizeof(protopin));
memset(protopout, 0, sizeof(protopout));
close(fd);
fd = -1;
if(--samples == 0)
break;
}
}
exits(0);
}