ttcp.c - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
ttcp.c (3600B) | |
--- | |
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 siz… | |
69 }; | |
70 | |
71 static void | |
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 | |
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->… | |
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 … | |
117 RST = 0x04, /* Reset connection */ | |
118 SYN = 0x02, /* Pkt. is synchronise… | |
119 FIN = 0x01, /* Start close down */ | |
120 }; | |
121 | |
122 static char* | |
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 | |
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 wi… | |
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)", o… | |
195 break; | |
196 case WSOPT: | |
197 m->p = seprint(m->p, m->e, " opt%d=(wscale %ud)"… | |
198 break; | |
199 default: | |
200 m->p = seprint(m->p, m->e, " opt%d=(%ud %.*H)", … | |
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 }; |