]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Option.c
Patch to remove STATIC modifier. This is on longer recommended by EFI Framework codin...
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Tcp4Dxe / Tcp4Option.c
1 /** @file
2
3 Copyright (c) 2005 - 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 Tcp4Option.c
15
16 Abstract:
17
18 Routines to process TCP option.
19
20
21 **/
22
23 #include "Tcp4Main.h"
24
25 UINT16
26 TcpGetUint16 (
27 IN UINT8 *Buf
28 )
29 {
30 UINT16 Value;
31 CopyMem (&Value, Buf, sizeof (UINT16));
32 return NTOHS (Value);
33 }
34
35 // STATIC
36 // VOID
37 // TcpPutUint16 (
38 // IN UINT8 *Buf,
39 // IN UINT16 Data
40 // )
41 // {
42 // Data = HTONS (Data);
43 // CopyMem (Buf, &Data, sizeof (UINT16));
44 // }
45
46 UINT32
47 TcpGetUint32 (
48 IN UINT8 *Buf
49 )
50 {
51 UINT32 Value;
52 CopyMem (&Value, Buf, sizeof (UINT32));
53 return NTOHL (Value);
54 }
55
56 VOID
57 TcpPutUint32 (
58 IN UINT8 *Buf,
59 IN UINT32 Data
60 )
61 {
62 Data = HTONL (Data);
63 CopyMem (Buf, &Data, sizeof (UINT32));
64 }
65
66
67 /**
68 Compute the window scale value according to the given
69 buffer size.
70
71 @param Tcb Pointer to the TCP_CB of this TCP instance.
72
73 @retval UINT8 The scale value.
74
75 **/
76 UINT8
77 TcpComputeScale (
78 IN TCP_CB *Tcb
79 )
80 {
81 UINT8 Scale;
82 UINT32 BufSize;
83
84 ASSERT (Tcb && Tcb->Sk);
85
86 BufSize = GET_RCV_BUFFSIZE (Tcb->Sk);
87
88 Scale = 0;
89 while ((Scale < TCP_OPTION_MAX_WS) &&
90 ((UINT32) (TCP_OPTION_MAX_WIN << Scale) < BufSize)) {
91
92 Scale++;
93 }
94
95 return Scale;
96 }
97
98
99 /**
100 Build the TCP option in three-way handshake.
101
102 @param Tcb Pointer to the TCP_CB of this TCP instance.
103 @param Nbuf Pointer to the buffer to store the options.
104
105 @return The total length of the TCP option field.
106
107 **/
108 UINT16
109 TcpSynBuildOption (
110 IN TCP_CB *Tcb,
111 IN NET_BUF *Nbuf
112 )
113 {
114 UINT8 *Data;
115 UINT16 Len;
116
117 ASSERT (Tcb && Nbuf && !Nbuf->Tcp);
118
119 Len = 0;
120
121 //
122 // Add timestamp option if not disabled by application
123 // and it is the first SYN segment or the peer has sent
124 // us its timestamp.
125 //
126 if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS) &&
127 (!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_ACK) ||
128 TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_TS))) {
129
130 Data = NetbufAllocSpace (
131 Nbuf,
132 TCP_OPTION_TS_ALIGNED_LEN,
133 NET_BUF_HEAD
134 );
135
136 ASSERT (Data);
137 Len += TCP_OPTION_TS_ALIGNED_LEN;
138
139 TcpPutUint32 (Data, TCP_OPTION_TS_FAST);
140 TcpPutUint32 (Data + 4, mTcpTick);
141 TcpPutUint32 (Data + 8, 0);
142 }
143
144 //
145 // Build window scale option, only when are configured
146 // to send WS option, and either we are doing active
147 // open or we have received WS option from peer.
148 //
149 if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS) &&
150 (!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_ACK) ||
151 TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_WS))) {
152
153 Data = NetbufAllocSpace (
154 Nbuf,
155 TCP_OPTION_WS_ALIGNED_LEN,
156 NET_BUF_HEAD
157 );
158
159 ASSERT (Data);
160
161 Len += TCP_OPTION_WS_ALIGNED_LEN;
162 TcpPutUint32 (Data, TCP_OPTION_WS_FAST | TcpComputeScale (Tcb));
163 }
164
165 //
166 // Build MSS option
167 //
168 Data = NetbufAllocSpace (Nbuf, TCP_OPTION_MSS_LEN, 1);
169 ASSERT (Data);
170
171 Len += TCP_OPTION_MSS_LEN;
172 TcpPutUint32 (Data, TCP_OPTION_MSS_FAST | Tcb->RcvMss);
173
174 return Len;
175 }
176
177
178 /**
179 Build the TCP option in synchronized states.
180
181 @param Tcb Pointer to the TCP_CB of this TCP instance.
182 @param Nbuf Pointer to the buffer to store the options.
183
184 @return The total length of the TCP option field.
185
186 **/
187 UINT16
188 TcpBuildOption (
189 IN TCP_CB *Tcb,
190 IN NET_BUF *Nbuf
191 )
192 {
193 UINT8 *Data;
194 UINT16 Len;
195
196 ASSERT (Tcb && Nbuf && !Nbuf->Tcp);
197 Len = 0;
198
199 //
200 // Build Timestamp option
201 //
202 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_TS) &&
203 !TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_RST)) {
204
205 Data = NetbufAllocSpace (
206 Nbuf,
207 TCP_OPTION_TS_ALIGNED_LEN,
208 NET_BUF_HEAD
209 );
210
211 ASSERT (Data);
212 Len += TCP_OPTION_TS_ALIGNED_LEN;
213
214 TcpPutUint32 (Data, TCP_OPTION_TS_FAST);
215 TcpPutUint32 (Data + 4, mTcpTick);
216 TcpPutUint32 (Data + 8, Tcb->TsRecent);
217 }
218
219 return Len;
220 }
221
222
223 /**
224 Parse the supported options.
225
226 @param Tcp Pointer to the TCP_CB of this TCP instance.
227 @param Option Pointer to the TCP_OPTION used to store the successfully pasrsed
228 options.
229
230 @retval 0 The options are successfully pasrsed.
231 @retval -1 Ilegal option was found.
232
233 **/
234 INTN
235 TcpParseOption (
236 IN TCP_HEAD *Tcp,
237 IN TCP_OPTION *Option
238 )
239 {
240 UINT8 *Head;
241 UINT8 TotalLen;
242 UINT8 Cur;
243 UINT8 Type;
244 UINT8 Len;
245
246 ASSERT (Tcp && Option);
247
248 Option->Flag = 0;
249
250 TotalLen = (UINT8) ((Tcp->HeadLen << 2) - sizeof (TCP_HEAD));
251 if (TotalLen <= 0) {
252 return 0;
253 }
254
255 Head = (UINT8 *) (Tcp + 1);
256
257 //
258 // Fast process of timestamp option
259 //
260 if ((TotalLen == TCP_OPTION_TS_ALIGNED_LEN) &&
261 (TcpGetUint32 (Head) == TCP_OPTION_TS_FAST)) {
262
263 Option->TSVal = TcpGetUint32 (Head + 4);
264 Option->TSEcr = TcpGetUint32 (Head + 8);
265 Option->Flag = TCP_OPTION_RCVD_TS;
266
267 return 0;
268 }
269
270 //
271 // Slow path to process the options.
272 //
273 Cur = 0;
274
275 while (Cur < TotalLen) {
276 Type = Head[Cur];
277
278 switch (Type) {
279 case TCP_OPTION_MSS:
280 Len = Head[Cur + 1];
281
282 if ((Len != TCP_OPTION_MSS_LEN) ||
283 (TotalLen - Cur < TCP_OPTION_MSS_LEN)) {
284
285 return -1;
286 }
287
288 Option->Mss = TcpGetUint16 (&Head[Cur + 2]);
289 TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_MSS);
290
291 Cur += TCP_OPTION_MSS_LEN;
292 break;
293
294 case TCP_OPTION_WS:
295 Len = Head[Cur + 1];
296
297 if ((Len != TCP_OPTION_WS_LEN) ||
298 (TotalLen - Cur < TCP_OPTION_WS_LEN)) {
299
300 return -1;
301 }
302
303 Option->WndScale = (UINT8) MIN (14, Head[Cur + 2]);
304 TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_WS);
305
306 Cur += TCP_OPTION_WS_LEN;
307 break;
308
309 case TCP_OPTION_TS:
310 Len = Head[Cur + 1];
311
312 if ((Len != TCP_OPTION_TS_LEN) ||
313 (TotalLen - Cur < TCP_OPTION_TS_LEN)) {
314
315 return -1;
316 }
317
318 Option->TSVal = TcpGetUint32 (&Head[Cur + 2]);
319 Option->TSEcr = TcpGetUint32 (&Head[Cur + 6]);
320 TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_TS);
321
322 Cur += TCP_OPTION_TS_LEN;
323 break;
324
325 case TCP_OPTION_NOP:
326 Cur++;
327 break;
328
329 case TCP_OPTION_EOP:
330 Cur = TotalLen;
331 break;
332
333 default:
334 Len = Head[Cur + 1];
335
336 if (TotalLen - Cur < Len || Len < 2) {
337 return -1;
338 }
339
340 Cur = (UINT8) (Cur + Len);
341 break;
342 }
343
344 }
345
346 return 0;
347 }
348
349
350 /**
351 Check the segment against PAWS.
352
353 @param Tcb Pointer to the TCP_CB of this TCP instance.
354 @param TSVal The timestamp value.
355
356 @retval 1 The segment passed the PAWS check.
357 @retval 0 The segment failed to pass the PAWS check.
358
359 **/
360 UINT32
361 TcpPawsOK (
362 IN TCP_CB *Tcb,
363 IN UINT32 TSVal
364 )
365 {
366 //
367 // PAWS as defined in RFC1323, buggy...
368 //
369 if (TCP_TIME_LT (TSVal, Tcb->TsRecent) &&
370 TCP_TIME_LT (Tcb->TsRecentAge + TCP_PAWS_24DAY, mTcpTick)) {
371
372 return 0;
373
374 }
375
376 return 1;
377 }