|  | #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, }, | 
|  | {"eapol",	0x888e, }, | 
|  | {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, | 
|  | "%#.4lux", | 
|  | p_fields, | 
|  | defaultframer | 
|  | }; |