diff options
author | rsc <devnull@localhost> | 2005-12-26 04:48:52 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2005-12-26 04:48:52 +0000 |
commit | 87a52e0485d3281ebea6bf4b725aa8023690e96f (patch) | |
tree | 0abc2d2ddb875196177231639d3cb4519e814b9d /src/cmd/ip/snoopy/ether.c | |
parent | 35d26aa32167e84326cdb745c0e906393b8de71d (diff) | |
download | plan9port-87a52e0485d3281ebea6bf4b725aa8023690e96f.tar.gz plan9port-87a52e0485d3281ebea6bf4b725aa8023690e96f.tar.bz2 plan9port-87a52e0485d3281ebea6bf4b725aa8023690e96f.zip |
new goodies
Diffstat (limited to 'src/cmd/ip/snoopy/ether.c')
-rwxr-xr-x | src/cmd/ip/snoopy/ether.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/cmd/ip/snoopy/ether.c b/src/cmd/ip/snoopy/ether.c new file mode 100755 index 00000000..62ec485d --- /dev/null +++ b/src/cmd/ip/snoopy/ether.c @@ -0,0 +1,121 @@ +#include <u.h> +#include <libc.h> +#include <ip.h> +#include "dat.h" +#include "protos.h" + +typedef struct Hdr Hdr; +struct Hdr { + 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 */ + +static Mux p_mux[] = +{ + {"ip", 0x0800, } , + {"arp", 0x0806, } , + {"rarp", 0x0806, } , + {"ip6", 0x86dd, } , + {"pppoe_disc", 0x8863, }, + {"pppoe_sess", 0x8864, }, + {0} +}; + +enum +{ + Os, // source + Od, // destination + Oa, // source or destination + Ot, // type +}; + +static Field p_fields[] = +{ + {"s", Fether, Os, "source address", } , + {"d", Fether, Od, "destination address", } , + {"a", Fether, Oa, "source|destination address" } , + {"sd", Fether, Oa, "source|destination address" } , + {"t", Fnum, Ot, "type" } , + {0} +}; + +static void +p_compile(Filter *f) +{ + Mux *m; + + if(f->op == '='){ + compile_cmp(ether.name, f, p_fields); + return; + } + for(m = p_mux; m->name != nil; m++) + if(strcmp(f->s, m->name) == 0){ + f->pr = m->pr; + f->ulv = m->val; + f->subop = Ot; + return; + } + sysfatal("unknown ethernet field or protocol: %s", f->s); +} + +static int +p_filter(Filter *f, Msg *m) +{ + Hdr *h; + + if(m->pe - m->ps < ETHERHDRSIZE) + return 0; + + h = (Hdr*)m->ps; + m->ps += ETHERHDRSIZE; + + switch(f->subop){ + case Os: + return !memcmp(h->s, f->a, 6); + case Od: + return !memcmp(h->d, f->a, 6); + case Oa: + return memcmp(h->s, f->a, 6) == 0 || memcmp(h->d, f->a, 6) == 0; + case Ot: + return NetS(h->type) == f->ulv; + } + return 0; +} + +static int +p_seprint(Msg *m) +{ + Hdr *h; + uint t; + int len; + + len = m->pe - m->ps; + if(len < ETHERHDRSIZE) + return -1; + + h = (Hdr*)m->ps; + m->ps += ETHERHDRSIZE; + + t = NetS(h->type); + demux(p_mux, t, t, m, &dump); + + m->p = seprint(m->p, m->e, "s=%E d=%E pr=%4.4ux ln=%d", h->s, h->d, + t, len); + return 0; +} + +Proto ether = +{ + "ether", + p_compile, + p_filter, + p_seprint, + p_mux, + p_fields, + defaultframer +}; |