/* * rawether - put one ethernet frame on the wire, addressed as told. * * A stack will only ever address a frame to the mac it resolved, so a * frame addressed to somebody else has to be forged. That is the only * way to ask a firewall on a card whether it is looking at frames that * are not for it. * * rawether /net/ether1 * * The payload is an icmp echo request, which is enough to be counted. */ #include #include #include enum { Ehdrlen = 14, Eminlen = 60, Etip4 = 0x0800 }; static ushort csum(uchar *p, int n) { ulong s; int i; s = 0; for(i = 0; i+1 < n; i += 2) s += (p[i]<<8) | p[i+1]; if(i < n) s += p[i]<<8; while(s >> 16) s = (s & 0xFFFF) + (s >> 16); return ~s; } void main(int argc, char **argv) { uchar f[Eminlen], dst[6], src[6], sip[IPaddrlen], dip[IPaddrlen]; char path[128], buf[64]; int cfd, dfd, n, conn; if(argc != 5){ fprint(2, "usage: rawether /net/etherN dstmac srcip dstip\n"); exits("usage"); } if(parseether(dst, argv[2]) < 0) sysfatal("%s: bad ethernet address", argv[2]); if(parseip(sip, argv[3]) == -1 || parseip(dip, argv[4]) == -1) sysfatal("bad ip address"); snprint(path, sizeof path, "%s/clone", argv[1]); if((cfd = open(path, ORDWR)) < 0) sysfatal("open %s: %r", path); if((n = read(cfd, buf, sizeof buf - 1)) <= 0) sysfatal("read %s: %r", path); buf[n] = '\0'; conn = atoi(buf); if(fprint(cfd, "connect -1") < 0) sysfatal("connect -1: %r"); snprint(path, sizeof path, "%s/%d/data", argv[1], conn); if((dfd = open(path, ORDWR)) < 0) sysfatal("open %s: %r", path); snprint(path, sizeof path, "%s/addr", argv[1]); if((n = open(path, OREAD)) < 0) sysfatal("open addr: %r"); if(read(n, buf, 12) != 12) sysfatal("read addr: %r"); close(n); buf[12] = '\0'; if(parseether(src, buf) < 0) sysfatal("unparseable card address %s", buf); memset(f, 0, sizeof f); memmove(f, dst, 6); memmove(f+6, src, 6); f[12] = Etip4 >> 8; f[13] = Etip4; f[14] = 0x45; /* v4, 20 byte header */ hnputs(f+16, 28); /* total length */ f[22] = 64; /* ttl */ f[23] = 1; /* icmp */ memmove(f+26, sip+IPv4off, 4); memmove(f+30, dip+IPv4off, 4); hnputs(f+24, csum(f+14, 20)); f[34] = 8; /* echo request */ hnputs(f+38, 0x1234); /* id */ hnputs(f+40, 1); /* seq */ hnputs(f+36, csum(f+34, 8)); if(write(dfd, f, sizeof f) != sizeof f) sysfatal("write: %r"); fmtinstall('E', eipfmt); print("sent %d bytes to %E\n", (int)sizeof f, dst); exits(nil); }