xref: /plan9/sys/src/cmd/ip/snoopy/aoerr.c (revision 43751f27fa93b002d5e921851faf5da5cbdcb417)
1 #include <u.h>
2 #include <libc.h>
3 #include <ip.h>
4 #include "dat.h"
5 #include "protos.h"
6 
7 typedef struct {
8 	uchar	cmd;
9 	uchar	nea;
10 } Hdr;
11 
12 enum {
13 	Ocmd,
14 	Onea,
15 	Oea,
16 
17 	Hsize	= 2,
18 };
19 
20 static Field p_fields[] = {
21 	{"cmd",	Fnum,	Ocmd,	"command",	},
22 	{"nea",	Fnum,	Onea,	"ea count",	},
23 	{"ea",	Fnum,	Onea,	"ethernet addr", },
24 	nil
25 };
26 
27 static void
p_compile(Filter * f)28 p_compile(Filter *f)
29 {
30 	if(f->op == '='){
31 		compile_cmp(aoerr.name, f, p_fields);
32 		return;
33 	}
34 	sysfatal("unknown aoerr field: %s", f->s);
35 }
36 
37 static int
p_filter(Filter * f,Msg * m)38 p_filter(Filter *f, Msg *m)
39 {
40 	uchar buf[6];
41 	int i;
42 	Hdr *h;
43 
44 	if(m->pe - m->ps < Hsize)
45 		return 0;
46 
47 	h = (Hdr*)m->ps;
48 	m->ps += Hsize;
49 
50 	switch(f->subop){
51 	case Ocmd:
52 		return h->cmd == f->ulv;
53 	case Onea:
54 		return h->nea == f->ulv;
55 	case Oea:
56 		if(m->pe - m->ps < 6*h->nea)
57 			return 0;
58 		for(i = 0; i < 6; i++)
59 			buf[i] = f->ulv >> ((5 - i)*8);
60 		for(i = 0; i < h->nea; i++)
61 			if(memcmp(m->ps + 6*i, buf, 6) == 0)
62 				return 1;
63 		return 0;
64 	}
65 	return 0;
66 }
67 
68 static char *ctab[] = {
69 	"read",
70 	"write",
71 	"force",
72 };
73 
74 static int
p_seprint(Msg * m)75 p_seprint(Msg *m)
76 {
77 	char *s;
78 	int i;
79 	Hdr *h;
80 
81 	if(m->pe - m->ps < Hsize)
82 		return 0;
83 
84 	h = (Hdr*)m->ps;
85 	m->ps += Hsize;
86 
87 	/* no next protocol */
88 	m->pr = nil;
89 
90 	s = "unk";
91 	if(h->cmd < nelem(ctab))
92 		s = ctab[h->cmd];
93 	m->p = seprint(m->p, m->e, "cmd=%d %s nea=%d", h->cmd, s, h->nea);
94 	for(i = 0;; i++){
95 		if(h->nea < i)
96 			break;
97 		if(i == 3){
98 			m->p = seprint(m->p, m->e, " ...");
99 			break;
100 		}
101 		if(m->pe - m->ps < 6*i){
102 			m->p = seprint(m->p, m->e, " *short*");
103 			break;
104 		}
105 		m->p = seprint(m->p, m->e, " %E", m->pe + 6*i);
106 	}
107 	m->p = seprint(m->p, m->e, "\n");
108 	return 0;
109 }
110 
111 Proto aoerr = {
112 	"aoerr",
113 	p_compile,
114 	p_filter,
115 	p_seprint,
116 	nil,
117 	nil,
118 	p_fields,
119 	defaultframer,
120 };
121