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