Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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	sport[2];
11
	uchar	dport[2];
12
	uchar	seq[4];
13
	uchar	ack[4];
14
	uchar	flag[2];
15
	uchar	win[2];
16
	uchar	cksum[2];
17
	uchar	urg[2];
18
	uchar	opt[1];
19
};
20
 
21
typedef struct PseudoHdr{
22
	uchar	src[4];
23
	uchar	dst[4];
24
	uchar	zero;
25
	uchar	proto;
26
	uchar	length[2];
27
	uchar	hdrdata[1580];
28
} PseudoHdr;
29
 
30
enum
31
{
32
	TCPLEN= 20,
33
};
34
 
35
enum
36
{
37
	Os,
38
	Od,
39
	Osd,
40
};
41
 
42
static Field p_fields[] =
43
{
44
	{"s",		Fnum,	Os,	"source port",	} ,
45
	{"d",		Fnum,	Od,	"dest port",	} ,
46
	{"a",		Fnum,	Osd,	"source/dest port",	} ,
47
	{"sd",		Fnum,	Osd,	"source/dest port",	} ,
48
	{0}
49
};
50
 
51
static Mux p_mux[] =
52
{
53
	{"dns",		53, },
54
	{"ninep",	17007, },	/* exportfs */
55
	{"ninep",	564, },		/* 9fs */
56
	{"ninep",	17005, },	/* ocpu */
57
	{"ninep",	17010, },	/* ncpu */
58
	{"ninep",	17013, },	/* cpu */
59
	{0},
60
};
61
 
62
enum
63
{
64
	EOLOPT		= 0,
65
	NOOPOPT		= 1,
66
	MSSOPT		= 2,
67
	MSS_LENGTH	= 4,		/* Mean segment size */
68
	WSOPT		= 3,
69
	WS_LENGTH	= 3,		/* Bits to scale window size by */
70
};
71
 
72
static void
73
p_compile(Filter *f)
74
{
75
	Mux *m;
76
 
77
	if(f->op == '='){
78
		compile_cmp(tcp.name, f, p_fields);
79
		return;
80
	}
81
	for(m = p_mux; m->name != nil; m++)
82
		if(strcmp(f->s, m->name) == 0){
83
			f->pr = m->pr;
84
			f->ulv = m->val;
85
			f->subop = Osd;
86
			return;
87
		}
88
	sysfatal("unknown tcp field or protocol: %s", f->s);
89
}
90
 
91
static int
92
p_filter(Filter *f, Msg *m)
93
{
94
	Hdr *h;
95
 
96
	if(m->pe - m->ps < TCPLEN)
97
		return 0;
98
 
99
	h = (Hdr*)m->ps;
100
	m->ps += (NetS(h->flag)>>10) & 0x3f;
101
 
102
	switch(f->subop){
103
	case Os:
104
		return NetS(h->sport) == f->ulv;
105
	case Od:
106
		return NetS(h->dport) == f->ulv;
107
	case Osd:
108
		return NetS(h->sport) == f->ulv || NetS(h->dport) == f->ulv;
109
	}
110
	return 0;
111
}
112
 
113
enum
114
{
115
	URG		= 0x20,		/* Data marked urgent */
116
	ACK		= 0x10,		/* Aknowledge is valid */
117
	PSH		= 0x08,		/* Whole data pipe is pushed */
118
	RST		= 0x04,		/* Reset connection */
119
	SYN		= 0x02,		/* Pkt. is synchronise */
120
	FIN		= 0x01,		/* Start close down */
121
};
122
 
123
static char*
124
flags(int f)
125
{
126
	static char fl[20];
127
	char *p;
128
 
129
	p = fl;
130
	if(f & URG)
131
		*p++ = 'U';
132
	if(f & ACK)
133
		*p++ = 'A';
134
	if(f & PSH)
135
		*p++ = 'P';
136
	if(f & RST)
137
		*p++ = 'R';
138
	if(f & SYN)
139
		*p++ = 'S';
140
	if(f & FIN)
141
		*p++ = 'F';
142
	*p = 0;
143
	return fl;
144
}
145
 
146
 
147
static int
148
p_seprint(Msg *m)
149
{
150
	int dport, sport, len, flag, optlen;
151
	uchar *optr;
152
	Hdr *h;
153
 
154
	if(m->pe - m->ps < TCPLEN)
155
		return -1;
156
	h = (Hdr*)m->ps;
157
 
158
	/* get tcp header length */
159
	flag = NetS(h->flag);
160
	len = (flag>>10) & ~3;
161
	flag &= 0x3ff;
162
	m->ps += len;
163
 
164
	/* next protocol */
165
	dport = NetS(h->dport);
166
	sport = NetS(h->sport);
167
	demux(p_mux, sport, dport, m, &dump);
168
 
169
	m->p = seprint(m->p, m->e, "s=%d d=%d seq=%lud ack=%lud fl=%s win=%d ck=%4.4ux",
170
			NetS(h->sport), dport,
171
			(ulong)NetL(h->seq), (ulong)NetL(h->ack),
172
			flags(flag), NetS(h->win),
173
			NetS(h->cksum));
174
 
175
	/* tcp options */
176
	len -= TCPLEN;
177
	optr = h->opt;
178
	while(len > 0) {
179
		if(*optr == EOLOPT){
180
			m->p = seprint(m->p, m->e, " opt=EOL");
181
			break;
182
		}
183
		if(*optr == NOOPOPT) {
184
			m->p = seprint(m->p, m->e, " opt=NOOP");
185
			len--;
186
			optr++;
187
			continue;
188
		}
189
		optlen = optr[1];
190
		if(optlen < 2 || optlen > len)
191
			break;
192
		switch(*optr) {
193
		case MSSOPT:
194
			m->p = seprint(m->p, m->e, " opt%d=(mss %ud)",
195
				optlen, nhgets(optr+2));
196
			break;
197
		case WSOPT:
198
			m->p = seprint(m->p, m->e, " opt%d=(wscale %ud)",
199
				optlen, *(optr+2));
200
			break;
201
		default:
202
			m->p = seprint(m->p, m->e, " opt%d=(%ud %.*H)",
203
				optlen, *optr, optlen-2, optr+2);
204
		}
205
		len -= optlen;
206
		optr += optlen;
207
	}
208
	return 0;
209
}
210
 
211
Proto tcp =
212
{
213
	"tcp",
214
	p_compile,
215
	p_filter,
216
	p_seprint,
217
	p_mux,
218
	"%lud",
219
	p_fields,
220
	defaultframer,
221
};