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 {"ninep", 17007, }, /* exportfs */
54 {"ninep", 564, }, /* 9fs */
55 {"ninep", 17005, }, /* ocpu */
56 {"ninep", 17010, }, /* ncpu */
57 {"ninep", 17013, }, /* cpu */
58 {0}
59 };
60
61 enum
62 {
63 EOLOPT = 0,
64 NOOPOPT = 1,
65 MSSOPT = 2,
66 MSS_LENGTH = 4, /* Mean segment size */
67 WSOPT = 3,
68 WS_LENGTH = 3, /* Bits to scale window size by */
69 };
70
71 static void
p_compile(Filter * f)72 p_compile(Filter *f)
73 {
74 Mux *m;
75
76 if(f->op == '='){
77 compile_cmp(udp.name, f, p_fields);
78 return;
79 }
80 for(m = p_mux; m->name != nil; m++)
81 if(strcmp(f->s, m->name) == 0){
82 f->pr = m->pr;
83 f->ulv = m->val;
84 f->subop = Osd;
85 return;
86 }
87 sysfatal("unknown tcp field or protocol: %s", f->s);
88 }
89
90 static int
p_filter(Filter * f,Msg * m)91 p_filter(Filter *f, Msg *m)
92 {
93 Hdr *h;
94
95 if(m->pe - m->ps < TCPLEN)
96 return 0;
97
98 h = (Hdr*)m->ps;
99 m->ps += ((NetS(h->flag)>>10)&0x3f);
100
101 switch(f->subop){
102 case Os:
103 return NetS(h->sport) == f->ulv;
104 case Od:
105 return NetS(h->dport) == f->ulv;
106 case Osd:
107 return NetS(h->sport) == f->ulv || NetS(h->dport) == f->ulv;
108 }
109 return 0;
110 }
111
112 enum
113 {
114 URG = 0x20, /* Data marked urgent */
115 ACK = 0x10, /* Aknowledge is valid */
116 PSH = 0x08, /* Whole data pipe is pushed */
117 RST = 0x04, /* Reset connection */
118 SYN = 0x02, /* Pkt. is synchronise */
119 FIN = 0x01, /* Start close down */
120 };
121
122 static char*
flags(int f)123 flags(int f)
124 {
125 static char fl[20];
126 char *p;
127
128 p = fl;
129 if(f & URG)
130 *p++ = 'U';
131 if(f & ACK)
132 *p++ = 'A';
133 if(f & PSH)
134 *p++ = 'P';
135 if(f & RST)
136 *p++ = 'R';
137 if(f & SYN)
138 *p++ = 'S';
139 if(f & FIN)
140 *p++ = 'F';
141 *p = 0;
142 return fl;
143 }
144
145
146 static int
p_seprint(Msg * m)147 p_seprint(Msg *m)
148 {
149 Hdr *h;
150 int dport, sport;
151 int len, flag, optlen;
152 uchar *optr;
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)", optlen, nhgets(optr+2));
195 break;
196 case WSOPT:
197 m->p = seprint(m->p, m->e, " opt%d=(wscale %ud)", optlen, *(optr+2));
198 break;
199 default:
200 m->p = seprint(m->p, m->e, " opt%d=(%ud %.*H)", optlen, *optr, optlen-2,optr+2);
201 }
202 len -= optlen;
203 optr += optlen;
204 }
205
206 if(Cflag){
207 /* editing in progress by ehg */
208 }
209 return 0;
210 }
211
212 Proto tcp =
213 {
214 "tcp",
215 p_compile,
216 p_filter,
217 p_seprint,
218 p_mux,
219 "%lud",
220 p_fields,
221 defaultframer
222 };
223