xref: /plan9/sys/src/cmd/ip/snoopy/ether.c (revision e6dcbf51e935975016093545b6eab69976b6e257)
19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <ip.h>
49a747e4fSDavid du Colombier #include "dat.h"
59a747e4fSDavid du Colombier #include "protos.h"
69a747e4fSDavid du Colombier 
79a747e4fSDavid du Colombier typedef struct Hdr	Hdr;
89a747e4fSDavid du Colombier struct Hdr {
99a747e4fSDavid du Colombier 	uchar	d[6];
109a747e4fSDavid du Colombier 	uchar	s[6];
119a747e4fSDavid du Colombier 	uchar	type[2];
129a747e4fSDavid du Colombier 	char	data[1500];
139a747e4fSDavid du Colombier };
14*e6dcbf51SDavid du Colombier 
159a747e4fSDavid du Colombier #define	ETHERMINTU	60	/* minimum transmit size */
169a747e4fSDavid du Colombier #define	ETHERMAXTU	1514	/* maximum transmit size */
179a747e4fSDavid du Colombier #define ETHERHDRSIZE	14	/* size of an ethernet header */
189a747e4fSDavid du Colombier 
199a747e4fSDavid du Colombier static Mux p_mux[] =
209a747e4fSDavid du Colombier {
219a747e4fSDavid du Colombier 	{"ip",		0x0800,	} ,
229a747e4fSDavid du Colombier 	{"arp",		0x0806,	} ,
239a747e4fSDavid du Colombier 	{"rarp",	0x0806,	} ,
249a747e4fSDavid du Colombier 	{"ip6", 	0x86dd, } ,
25d9306527SDavid du Colombier 	{"pppoe_disc",	0x8863, },
26d9306527SDavid du Colombier 	{"pppoe_sess",	0x8864, },
27ed397113SDavid du Colombier 	{"eapol",	0x888e, },
28*e6dcbf51SDavid du Colombier 	{"aoe",		0x88a2, } ,
29*e6dcbf51SDavid du Colombier 	{"cec",		0xbcbc, } ,
309a747e4fSDavid du Colombier 	{0}
319a747e4fSDavid du Colombier };
329a747e4fSDavid du Colombier 
339a747e4fSDavid du Colombier enum
349a747e4fSDavid du Colombier {
35*e6dcbf51SDavid du Colombier 	Os,	/* source */
36*e6dcbf51SDavid du Colombier 	Od,	/* destination */
37*e6dcbf51SDavid du Colombier 	Oa,	/* source or destination */
38*e6dcbf51SDavid du Colombier 	Ot,	/* type */
399a747e4fSDavid du Colombier };
409a747e4fSDavid du Colombier 
419a747e4fSDavid du Colombier static Field p_fields[] =
429a747e4fSDavid du Colombier {
439a747e4fSDavid du Colombier 	{"s",	Fether,	Os,	"source address",	} ,
449a747e4fSDavid du Colombier 	{"d",	Fether,	Od,	"destination address",	} ,
459a747e4fSDavid du Colombier 	{"a",	Fether,	Oa,	"source|destination address" } ,
46dc5a79c1SDavid du Colombier 	{"sd",	Fether,	Oa,	"source|destination address" } ,
479a747e4fSDavid du Colombier 	{"t",	Fnum,	Ot,	"type" } ,
489a747e4fSDavid du Colombier 	{0}
499a747e4fSDavid du Colombier };
509a747e4fSDavid du Colombier 
519a747e4fSDavid du Colombier static void
p_compile(Filter * f)529a747e4fSDavid du Colombier p_compile(Filter *f)
539a747e4fSDavid du Colombier {
549a747e4fSDavid du Colombier 	Mux *m;
559a747e4fSDavid du Colombier 
569a747e4fSDavid du Colombier 	if(f->op == '='){
579a747e4fSDavid du Colombier 		compile_cmp(ether.name, f, p_fields);
589a747e4fSDavid du Colombier 		return;
599a747e4fSDavid du Colombier 	}
609a747e4fSDavid du Colombier 	for(m = p_mux; m->name != nil; m++)
619a747e4fSDavid du Colombier 		if(strcmp(f->s, m->name) == 0){
629a747e4fSDavid du Colombier 			f->pr = m->pr;
639a747e4fSDavid du Colombier 			f->ulv = m->val;
649a747e4fSDavid du Colombier 			f->subop = Ot;
659a747e4fSDavid du Colombier 			return;
669a747e4fSDavid du Colombier 		}
679a747e4fSDavid du Colombier 	sysfatal("unknown ethernet field or protocol: %s", f->s);
689a747e4fSDavid du Colombier }
699a747e4fSDavid du Colombier 
709a747e4fSDavid du Colombier static int
p_filter(Filter * f,Msg * m)719a747e4fSDavid du Colombier p_filter(Filter *f, Msg *m)
729a747e4fSDavid du Colombier {
739a747e4fSDavid du Colombier 	Hdr *h;
749a747e4fSDavid du Colombier 
759a747e4fSDavid du Colombier 	if(m->pe - m->ps < ETHERHDRSIZE)
769a747e4fSDavid du Colombier 		return 0;
779a747e4fSDavid du Colombier 
789a747e4fSDavid du Colombier 	h = (Hdr*)m->ps;
799a747e4fSDavid du Colombier 	m->ps += ETHERHDRSIZE;
809a747e4fSDavid du Colombier 
819a747e4fSDavid du Colombier 	switch(f->subop){
829a747e4fSDavid du Colombier 	case Os:
83*e6dcbf51SDavid du Colombier 		return memcmp(h->s, f->a, 6) == 0;
849a747e4fSDavid du Colombier 	case Od:
85*e6dcbf51SDavid du Colombier 		return memcmp(h->d, f->a, 6) == 0;
869a747e4fSDavid du Colombier 	case Oa:
879a747e4fSDavid du Colombier 		return memcmp(h->s, f->a, 6) == 0 || memcmp(h->d, f->a, 6) == 0;
889a747e4fSDavid du Colombier 	case Ot:
899a747e4fSDavid du Colombier 		return NetS(h->type) == f->ulv;
909a747e4fSDavid du Colombier 	}
919a747e4fSDavid du Colombier 	return 0;
929a747e4fSDavid du Colombier }
939a747e4fSDavid du Colombier 
949a747e4fSDavid du Colombier static int
p_seprint(Msg * m)959a747e4fSDavid du Colombier p_seprint(Msg *m)
969a747e4fSDavid du Colombier {
979a747e4fSDavid du Colombier 	int len;
98*e6dcbf51SDavid du Colombier 	uint t;
99*e6dcbf51SDavid du Colombier 	Hdr *h;
1009a747e4fSDavid du Colombier 
1019a747e4fSDavid du Colombier 	len = m->pe - m->ps;
1029a747e4fSDavid du Colombier 	if(len < ETHERHDRSIZE)
1039a747e4fSDavid du Colombier 		return -1;
1049a747e4fSDavid du Colombier 
1059a747e4fSDavid du Colombier 	h = (Hdr*)m->ps;
1069a747e4fSDavid du Colombier 	m->ps += ETHERHDRSIZE;
1079a747e4fSDavid du Colombier 
1089a747e4fSDavid du Colombier 	t = NetS(h->type);
1099a747e4fSDavid du Colombier 	demux(p_mux, t, t, m, &dump);
1109a747e4fSDavid du Colombier 
1119a747e4fSDavid du Colombier 	m->p = seprint(m->p, m->e, "s=%E d=%E pr=%4.4ux ln=%d", h->s, h->d,
1129a747e4fSDavid du Colombier 		t, len);
1139a747e4fSDavid du Colombier 	return 0;
1149a747e4fSDavid du Colombier }
1159a747e4fSDavid du Colombier 
1169a747e4fSDavid du Colombier Proto ether =
1179a747e4fSDavid du Colombier {
1189a747e4fSDavid du Colombier 	"ether",
1199a747e4fSDavid du Colombier 	p_compile,
1209a747e4fSDavid du Colombier 	p_filter,
1219a747e4fSDavid du Colombier 	p_seprint,
1229a747e4fSDavid du Colombier 	p_mux,
123ed397113SDavid du Colombier 	"%#.4lux",
1249a747e4fSDavid du Colombier 	p_fields,
1253ff48bf5SDavid du Colombier 	defaultframer
1269a747e4fSDavid du Colombier };
127