summaryrefslogtreecommitdiff
path: root/sys/src/cmd/ip/snoopy/cec.c
blob: 9cbb27dd1298e4c47f22e6c93e849f41a5cf502d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <u.h>
#include <libc.h>
#include <ip.h>
#include "dat.h"
#include "protos.h"

typedef struct{
	uchar	type;
	uchar	conn;
	uchar	seq;
	uchar	len;
}Hdr;

enum{
	Hsize	= 4,
};

enum{
	Otype,
	Oconn,
	Oseq,
	Olen,
};

static Field p_fields[] =
{
	{"type",	Fnum,	Otype,		"type",	},
	{"conn",	Fnum,	Oconn,		"conn",	},
	{"seq",		Fnum,	Oseq,		"seq",	},
	{"len",		Fnum,	Olen,		"len",	},
	{0}
};

static void
p_compile(Filter *f)
{
	if(f->op == '='){
		compile_cmp(aoe.name, f, p_fields);
		return;
	}
	sysfatal("unknown aoe field: %s", f->s);
}

static int
p_filter(Filter *f, Msg *m)
{
	Hdr *h;

	if(m->pe - m->ps < Hsize)
		return 0;

	h = (Hdr*)m->ps;
	m->ps += Hsize;

	switch(f->subop){
	case Otype:
		return h->type == f->ulv;
	case Oconn:
		return h->conn = f->ulv;
	case Oseq:
		return h->seq = f->ulv;
	case Olen:
		return h->len = f->ulv;
	}
	return 0;
}

static char* ttab[] = {
	"Tinita",
	"Tinitb",
	"Tinitc",
	"Tdata",
	"Tack",
	"Tdiscover",
	"Toffer",
	"Treset",
};

static int
p_seprint(Msg *m)
{
	char *s, *p, buf[4];
	Hdr *h;

	if(m->pe - m->ps < Hsize)
		return 0;

	h = (Hdr*)m->ps;
	m->ps += Hsize;

	m->pr = nil;

	if(h->type < nelem(ttab))
		s = ttab[h->type];
	else{
		snprint(buf, sizeof buf, "%d", h->type);
		s = buf;
	}

	p = (char*)m->ps;
	m->p = seprint(m->p, m->e, "type=%s conn=%d seq=%d len=%d %.*s",
		s, h->conn, h->seq, h->len,
		(int)utfnlen(p, h->len), p);
	return 0;
}

Proto cec =
{
	"cec",
	p_compile,
	p_filter,
	p_seprint,
	nil,
	nil,
	p_fields,
	defaultframer,
};