xref: /plan9/sys/src/cmd/ip/snoopy/arp.c (revision ed397113cdcf7aafea372b730bbcd17b05ee3f60)
1 #include <u.h>
2 #include <libc.h>
3 #include <ip.h>
4 #include "dat.h"
5 #include "protos.h"
6 
7 typedef struct Hdr	Hdr;
8 struct Hdr
9 {
10 	uchar	hrd[2];
11 	uchar	pro[2];
12 	uchar	hln;
13 	uchar	pln;
14 	uchar	op[2];
15 	uchar	sha[6];
16 	uchar	spa[4];
17 	uchar	tha[6];
18 	uchar	tpa[4];
19 };
20 
21 enum
22 {
23 	ARPLEN=	28,
24 };
25 
26 enum
27 {
28 	Ospa,
29 	Otpa,
30 	Ostpa,
31 	Osha,
32 	Otha,
33 	Ostha,
34 	Opa,
35 };
36 
37 static Field p_fields[] =
38 {
39 	{"spa",		Fv4ip,	Ospa,	"protocol source",	} ,
40 	{"tpa",		Fv4ip,	Otpa,	"protocol target",	} ,
41 	{"a",		Fv4ip,	Ostpa,	"protocol source/target",	} ,
42 	{"sha",		Fba,	Osha,	"hardware source",	} ,
43 	{"tha",		Fba,	Otha,	"hardware target",	} ,
44 	{"ah",	 	Fba,	Ostha,	"hardware source/target",	} ,
45 	{0}
46 };
47 
48 static void
p_compile(Filter * f)49 p_compile(Filter *f)
50 {
51 	if(f->op == '='){
52 		compile_cmp(arp.name, f, p_fields);
53 		return;
54 	}
55 	sysfatal("unknown arp field: %s", f->s);
56 }
57 
58 static int
p_filter(Filter * f,Msg * m)59 p_filter(Filter *f, Msg *m)
60 {
61 	Hdr *h;
62 
63 	if(m->pe - m->ps < ARPLEN)
64 		return 0;
65 
66 	h = (Hdr*)m->ps;
67 	m->ps += ARPLEN;
68 
69 	switch(f->subop){
70 	case Ospa:
71 		return h->pln == 4 && NetL(h->spa) == f->ulv;
72 	case Otpa:
73 		return h->pln == 4 && NetL(h->tpa) == f->ulv;
74 	case Ostpa:
75 		return h->pln == 4 && (NetL(h->tpa) == f->ulv ||
76 			NetL(h->spa) == f->ulv);
77 	case Osha:
78 		return memcmp(h->sha, f->a, h->hln) == 0;
79 	case Otha:
80 		return memcmp(h->tha, f->a, h->hln) == 0;
81 	case Ostha:
82 		return memcmp(h->sha, f->a, h->hln)==0
83 			||memcmp(h->tha, f->a, h->hln)==0;
84 	}
85 	return 0;
86 }
87 
88 static int
p_seprint(Msg * m)89 p_seprint(Msg *m)
90 {
91 	Hdr *h;
92 
93 	if(m->pe - m->ps < ARPLEN)
94 		return -1;
95 
96 	h = (Hdr*)m->ps;
97 	m->ps += ARPLEN;
98 
99 	/* no next protocol */
100 	m->pr = nil;
101 
102 	m->p = seprint(m->p, m->e, "op=%1d len=%1d/%1d spa=%V sha=%E tpa=%V tha=%E",
103 			NetS(h->op), h->pln, h->hln,
104 			h->spa, h->sha, h->tpa, h->tha);
105 	return 0;
106 }
107 
108 Proto arp =
109 {
110 	"arp",
111 	p_compile,
112 	p_filter,
113 	p_seprint,
114 	nil,
115 	nil,
116 	p_fields,
117 	defaultframer,
118 };
119 
120 Proto rarp =
121 {
122 	"rarp",
123 	p_compile,
124 	p_filter,
125 	p_seprint,
126 	nil,
127 	nil,
128 	p_fields,
129 	defaultframer,
130 };
131