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