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