TianoCore EDK2 master
Loading...
Searching...
No Matches
TcpOption.c
Go to the documentation of this file.
1
10#include "TcpMain.h"
11
20UINT16
22 IN UINT8 *Buf
23 )
24{
25 UINT16 Value;
26
27 CopyMem (&Value, Buf, sizeof (UINT16));
28 return NTOHS (Value);
29}
30
39UINT32
41 IN UINT8 *Buf
42 )
43{
44 UINT32 Value;
45
46 CopyMem (&Value, Buf, sizeof (UINT32));
47 return NTOHL (Value);
48}
49
57VOID
59 OUT UINT8 *Buf,
60 IN UINT32 Data
61 )
62{
63 Data = HTONL (Data);
64 CopyMem (Buf, &Data, sizeof (UINT32));
65}
66
75UINT8
77 IN TCP_CB *Tcb
78 )
79{
80 UINT8 Scale;
81 UINT32 BufSize;
82
83 ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL));
84
85 BufSize = GET_RCV_BUFFSIZE (Tcb->Sk);
86
87 Scale = 0;
88 while ((Scale < TCP_OPTION_MAX_WS) && ((UINT32)(TCP_OPTION_MAX_WIN << Scale) < BufSize)) {
89 Scale++;
90 }
91
92 return Scale;
93}
94
104UINT16
106 IN TCP_CB *Tcb,
107 IN NET_BUF *Nbuf
108 )
109{
110 UINT8 *Data;
111 UINT16 Len;
112
113 ASSERT ((Tcb != NULL) && (Nbuf != NULL) && (Nbuf->Tcp == NULL));
114
115 Len = 0;
116
117 //
118 // Add a timestamp option if not disabled by the application
119 // and it is the first SYN segment, or the peer has sent
120 // us its timestamp.
121 //
122 if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS) &&
123 (!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_ACK) ||
124 TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_TS))
125 )
126 {
127 Data = NetbufAllocSpace (
128 Nbuf,
130 NET_BUF_HEAD
131 );
132
133 ASSERT (Data != NULL);
135
136 TcpPutUint32 (Data, TCP_OPTION_TS_FAST);
137 TcpPutUint32 (Data + 4, mTcpTick);
138 TcpPutUint32 (Data + 8, 0);
139 }
140
141 //
142 // Build window scale option, only when configured
143 // to send WS option, and either we are doing active
144 // open or we have received WS option from peer.
145 //
146 if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS) &&
147 (!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_ACK) ||
148 TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_WS))
149 )
150 {
151 Data = NetbufAllocSpace (
152 Nbuf,
154 NET_BUF_HEAD
155 );
156
157 ASSERT (Data != NULL);
158
160 TcpPutUint32 (Data, TCP_OPTION_WS_FAST | TcpComputeScale (Tcb));
161 }
162
163 //
164 // Build the MSS option.
165 //
166 Data = NetbufAllocSpace (Nbuf, TCP_OPTION_MSS_LEN, 1);
167 ASSERT (Data != NULL);
168
169 Len += TCP_OPTION_MSS_LEN;
170 TcpPutUint32 (Data, TCP_OPTION_MSS_FAST | Tcb->RcvMss);
171
172 return Len;
173}
174
184UINT16
186 IN TCP_CB *Tcb,
187 IN NET_BUF *Nbuf
188 )
189{
190 UINT8 *Data;
191 UINT16 Len;
192
193 ASSERT ((Tcb != NULL) && (Nbuf != NULL) && (Nbuf->Tcp == NULL));
194 Len = 0;
195
196 //
197 // Build the Timestamp option.
198 //
199 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_TS) &&
200 !TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_RST)
201 )
202 {
203 Data = NetbufAllocSpace (
204 Nbuf,
206 NET_BUF_HEAD
207 );
208
209 ASSERT (Data != NULL);
211
212 TcpPutUint32 (Data, TCP_OPTION_TS_FAST);
213 TcpPutUint32 (Data + 4, mTcpTick);
214 TcpPutUint32 (Data + 8, Tcb->TsRecent);
215 }
216
217 return Len;
218}
219
231INTN
233 IN TCP_HEAD *Tcp,
234 IN OUT TCP_OPTION *Option
235 )
236{
237 UINT8 *Head;
238 UINT8 TotalLen;
239 UINT8 Cur;
240 UINT8 Type;
241 UINT8 Len;
242
243 ASSERT ((Tcp != NULL) && (Option != NULL));
244
245 Option->Flag = 0;
246
247 TotalLen = (UINT8)((Tcp->HeadLen << 2) - sizeof (TCP_HEAD));
248 if (TotalLen <= 0) {
249 return 0;
250 }
251
252 Head = (UINT8 *)(Tcp + 1);
253
254 //
255 // Fast process of the timestamp option.
256 //
257 if ((TotalLen == TCP_OPTION_TS_ALIGNED_LEN) && (TcpGetUint32 (Head) == TCP_OPTION_TS_FAST)) {
258 Option->TSVal = TcpGetUint32 (Head + 4);
259 Option->TSEcr = TcpGetUint32 (Head + 8);
260 Option->Flag = TCP_OPTION_RCVD_TS;
261
262 return 0;
263 }
264
265 //
266 // Slow path to process the options.
267 //
268 Cur = 0;
269
270 while (Cur < TotalLen) {
271 Type = Head[Cur];
272
273 switch (Type) {
274 case TCP_OPTION_MSS:
275 Len = Head[Cur + 1];
276
277 if ((Len != TCP_OPTION_MSS_LEN) || (TotalLen - Cur < TCP_OPTION_MSS_LEN)) {
278 return -1;
279 }
280
281 Option->Mss = TcpGetUint16 (&Head[Cur + 2]);
282 TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_MSS);
283
284 Cur += TCP_OPTION_MSS_LEN;
285 break;
286
287 case TCP_OPTION_WS:
288 Len = Head[Cur + 1];
289
290 if ((Len != TCP_OPTION_WS_LEN) || (TotalLen - Cur < TCP_OPTION_WS_LEN)) {
291 return -1;
292 }
293
294 Option->WndScale = (UINT8)MIN (14, Head[Cur + 2]);
295 TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_WS);
296
297 Cur += TCP_OPTION_WS_LEN;
298 break;
299
300 case TCP_OPTION_TS:
301 Len = Head[Cur + 1];
302
303 if ((Len != TCP_OPTION_TS_LEN) || (TotalLen - Cur < TCP_OPTION_TS_LEN)) {
304 return -1;
305 }
306
307 Option->TSVal = TcpGetUint32 (&Head[Cur + 2]);
308 Option->TSEcr = TcpGetUint32 (&Head[Cur + 6]);
309 TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_TS);
310
311 Cur += TCP_OPTION_TS_LEN;
312 break;
313
314 case TCP_OPTION_NOP:
315 Cur++;
316 break;
317
318 case TCP_OPTION_EOP:
319 Cur = TotalLen;
320 break;
321
322 default:
323 Len = Head[Cur + 1];
324
325 if (((TotalLen - Cur) < Len) || (Len < 2)) {
326 return -1;
327 }
328
329 Cur = (UINT8)(Cur + Len);
330 break;
331 }
332 }
333
334 return 0;
335}
INT64 INTN
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
#define NULL
Definition: Base.h:319
#define MIN(a, b)
Definition: Base.h:1007
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
UINT8 *EFIAPI NetbufAllocSpace(IN OUT NET_BUF *Nbuf, IN UINT32 Len, IN BOOLEAN FromHead)
Definition: NetBuffer.c:1015
#define GET_RCV_BUFFSIZE(Sock)
Definition: Socket.h:245
UINT16 TcpBuildOption(IN TCP_CB *Tcb, IN NET_BUF *Nbuf)
Definition: TcpOption.c:185
UINT16 TcpSynBuildOption(IN TCP_CB *Tcb, IN NET_BUF *Nbuf)
Definition: TcpOption.c:105
VOID TcpPutUint32(OUT UINT8 *Buf, IN UINT32 Data)
Definition: TcpOption.c:58
UINT32 TcpGetUint32(IN UINT8 *Buf)
Definition: TcpOption.c:40
UINT16 TcpGetUint16(IN UINT8 *Buf)
Definition: TcpOption.c:21
INTN TcpParseOption(IN TCP_HEAD *Tcp, IN OUT TCP_OPTION *Option)
Definition: TcpOption.c:232
UINT8 TcpComputeScale(IN TCP_CB *Tcb)
Definition: TcpOption.c:76
#define TCP_OPTION_TS_LEN
Length of timestamp option.
Definition: TcpOption.h:23
#define TCP_OPTION_TS
Timestamp.
Definition: TcpOption.h:20
#define TCP_OPTION_MAX_WS
Maximum window scale value.
Definition: TcpOption.h:48
#define TCP_OPTION_NOP
No-Option.
Definition: TcpOption.h:17
#define TCP_OPTION_MAX_WIN
Max window size in TCP header.
Definition: TcpOption.h:49
#define TCP_OPTION_WS_ALIGNED_LEN
Length of window scale option, aligned.
Definition: TcpOption.h:24
#define TCP_OPTION_MSS_LEN
Length of MSS option.
Definition: TcpOption.h:21
#define TCP_OPTION_TS_ALIGNED_LEN
Length of timestamp option, aligned.
Definition: TcpOption.h:25
#define TCP_OPTION_EOP
End Of oPtion.
Definition: TcpOption.h:16
#define TCP_OPTION_WS_LEN
Length of window scale option.
Definition: TcpOption.h:22
#define TCP_OPTION_WS
Window scale.
Definition: TcpOption.h:19
#define TCP_OPTION_MSS
Maximum Segment Size.
Definition: TcpOption.h:18
#define TCP_CTRL_RCVD_WS
Received a wnd scale option in syn.
Definition: TcpProto.h:61
#define TCP_CTRL_SND_TS
Send Timestamp option to remote.
Definition: TcpProto.h:64
#define TCP_CTRL_RCVD_TS
Received a Timestamp option in syn.
Definition: TcpProto.h:63
#define TCP_CTRL_NO_WS
Disable window scale option.
Definition: TcpProto.h:60
#define TCP_CTRL_NO_TS
Disable Timestamp option.
Definition: TcpProto.h:62