]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/TcpDxe/TcpOption.c
SecurityPkg: Add TPM PTP support in TCG2 SMM.
[mirror_edk2.git] / NetworkPkg / TcpDxe / TcpOption.c
CommitLineData
a3bcde70
HT
1/** @file\r
2 Routines to process TCP option.\r
3\r
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
5\r
6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php.\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "TcpMain.h"\r
17\r
18/**\r
19 Get a UINT16 value from buffer.\r
20\r
21 @param[in] Buf Pointer to input buffer.\r
22\r
23 @return The UINT16 value obtained from the buffer.\r
24\r
25**/\r
26UINT16\r
27TcpGetUint16 (\r
28 IN UINT8 *Buf\r
29 )\r
30{\r
31 UINT16 Value;\r
32 CopyMem (&Value, Buf, sizeof (UINT16));\r
33 return NTOHS (Value);\r
34}\r
35\r
36/**\r
37 Get a UINT32 value from buffer.\r
38\r
39 @param[in] Buf Pointer to input buffer.\r
40\r
41 @return The UINT32 value obtained from the buffer.\r
42\r
43**/\r
44UINT32\r
45TcpGetUint32 (\r
46 IN UINT8 *Buf\r
47 )\r
48{\r
49 UINT32 Value;\r
50 CopyMem (&Value, Buf, sizeof (UINT32));\r
51 return NTOHL (Value);\r
52}\r
53\r
54/**\r
55 Put a UINT32 value in buffer.\r
56\r
57 @param[out] Buf Pointer to the buffer.\r
58 @param[in] Data The UINT32 Date to put in the buffer.\r
59\r
60**/\r
61VOID\r
62TcpPutUint32 (\r
63 OUT UINT8 *Buf,\r
64 IN UINT32 Data\r
65 )\r
66{\r
67 Data = HTONL (Data);\r
68 CopyMem (Buf, &Data, sizeof (UINT32));\r
69}\r
70\r
71/**\r
72 Compute the window scale value according to the given buffer size.\r
73\r
74 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.\r
75\r
76 @return The scale value.\r
77\r
78**/\r
79UINT8\r
80TcpComputeScale (\r
81 IN TCP_CB *Tcb\r
82 )\r
83{\r
84 UINT8 Scale;\r
85 UINT32 BufSize;\r
86\r
87 ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL));\r
88\r
89 BufSize = GET_RCV_BUFFSIZE (Tcb->Sk);\r
90\r
91 Scale = 0;\r
92 while ((Scale < TCP_OPTION_MAX_WS) && ((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 Build the TCP option in three-way handshake.\r
102\r
103 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.\r
104 @param[in] Nbuf Pointer to the buffer to store the options.\r
105\r
106 @return The total length of the TCP option field.\r
107\r
108**/\r
109UINT16\r
110TcpSynBuildOption (\r
111 IN TCP_CB *Tcb,\r
112 IN NET_BUF *Nbuf\r
113 )\r
114{\r
115 UINT8 *Data;\r
116 UINT16 Len;\r
117\r
118 ASSERT ((Tcb != NULL) && (Nbuf != NULL) && (Nbuf->Tcp == NULL));\r
119\r
120 Len = 0;\r
121\r
122 //\r
123 // Add a timestamp option if not disabled by the application\r
124 // and it is the first SYN segment, or the peer has sent\r
125 // us its timestamp.\r
126 //\r
127 if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS) &&\r
128 (!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_ACK) ||\r
129 TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_TS))\r
130 ) {\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 != NULL);\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 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\r
156 Data = NetbufAllocSpace (\r
157 Nbuf,\r
158 TCP_OPTION_WS_ALIGNED_LEN,\r
159 NET_BUF_HEAD\r
160 );\r
161\r
162 ASSERT (Data != NULL);\r
163\r
164 Len += TCP_OPTION_WS_ALIGNED_LEN;\r
165 TcpPutUint32 (Data, TCP_OPTION_WS_FAST | TcpComputeScale (Tcb));\r
166 }\r
167\r
168 //\r
169 // Build the MSS option.\r
170 //\r
171 Data = NetbufAllocSpace (Nbuf, TCP_OPTION_MSS_LEN, 1);\r
172 ASSERT (Data != NULL);\r
173\r
174 Len += TCP_OPTION_MSS_LEN;\r
175 TcpPutUint32 (Data, TCP_OPTION_MSS_FAST | Tcb->RcvMss);\r
176\r
177 return Len;\r
178}\r
179\r
180/**\r
181 Build the TCP option in synchronized states.\r
182\r
183 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.\r
184 @param[in] 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
195 UINT8 *Data;\r
196 UINT16 Len;\r
197\r
198 ASSERT ((Tcb != NULL) && (Nbuf != NULL) && (Nbuf->Tcp == NULL));\r
199 Len = 0;\r
200\r
201 //\r
202 // Build the 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\r
208 Data = NetbufAllocSpace (\r
209 Nbuf,\r
210 TCP_OPTION_TS_ALIGNED_LEN,\r
211 NET_BUF_HEAD\r
212 );\r
213\r
214 ASSERT (Data != NULL);\r
215 Len += TCP_OPTION_TS_ALIGNED_LEN;\r
216\r
217 TcpPutUint32 (Data, TCP_OPTION_TS_FAST);\r
218 TcpPutUint32 (Data + 4, mTcpTick);\r
219 TcpPutUint32 (Data + 8, Tcb->TsRecent);\r
220 }\r
221\r
222 return Len;\r
223}\r
224\r
225/**\r
226 Parse the supported options.\r
227\r
228 @param[in] Tcp Pointer to the TCP_CB of this TCP instance.\r
229 @param[in, out] Option Pointer to the TCP_OPTION used to store the\r
230 successfully pasrsed 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 OUT 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 != NULL) && (Option != NULL));\r
249\r
250 Option->Flag = 0;\r
251\r
252 TotalLen = (UINT8) ((Tcp->HeadLen << 2) - sizeof (TCP_HEAD));\r
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 the timestamp option.\r
261 //\r
262 if ((TotalLen == TCP_OPTION_TS_ALIGNED_LEN) && (TcpGetUint32 (Head) == TCP_OPTION_TS_FAST)) {\r
263\r
264 Option->TSVal = TcpGetUint32 (Head + 4);\r
265 Option->TSEcr = TcpGetUint32 (Head + 8);\r
266 Option->Flag = TCP_OPTION_RCVD_TS;\r
267\r
268 return 0;\r
269 }\r
270 //\r
271 // Slow path to process the options.\r
272 //\r
273 Cur = 0;\r
274\r
275 while (Cur < TotalLen) {\r
276 Type = Head[Cur];\r
277\r
278 switch (Type) {\r
279 case TCP_OPTION_MSS:\r
280 Len = Head[Cur + 1];\r
281\r
282 if ((Len != TCP_OPTION_MSS_LEN) || (TotalLen - Cur < TCP_OPTION_MSS_LEN)) {\r
283\r
284 return -1;\r
285 }\r
286\r
287 Option->Mss = TcpGetUint16 (&Head[Cur + 2]);\r
288 TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_MSS);\r
289\r
290 Cur += TCP_OPTION_MSS_LEN;\r
291 break;\r
292\r
293 case TCP_OPTION_WS:\r
294 Len = Head[Cur + 1];\r
295\r
296 if ((Len != TCP_OPTION_WS_LEN) || (TotalLen - Cur < TCP_OPTION_WS_LEN)) {\r
297\r
298 return -1;\r
299 }\r
300\r
301 Option->WndScale = (UINT8) MIN (14, Head[Cur + 2]);\r
302 TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_WS);\r
303\r
304 Cur += TCP_OPTION_WS_LEN;\r
305 break;\r
306\r
307 case TCP_OPTION_TS:\r
308 Len = Head[Cur + 1];\r
309\r
310 if ((Len != TCP_OPTION_TS_LEN) || (TotalLen - Cur < TCP_OPTION_TS_LEN)) {\r
311\r
312 return -1;\r
313 }\r
314\r
315 Option->TSVal = TcpGetUint32 (&Head[Cur + 2]);\r
316 Option->TSEcr = TcpGetUint32 (&Head[Cur + 6]);\r
317 TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_TS);\r
318\r
319 Cur += TCP_OPTION_TS_LEN;\r
320 break;\r
321\r
322 case TCP_OPTION_NOP:\r
323 Cur++;\r
324 break;\r
325\r
326 case TCP_OPTION_EOP:\r
327 Cur = TotalLen;\r
328 break;\r
329\r
330 default:\r
331 Len = Head[Cur + 1];\r
332\r
333 if ((TotalLen - Cur) < Len || Len < 2) {\r
334 return -1;\r
335 }\r
336\r
337 Cur = (UINT8) (Cur + Len);\r
338 break;\r
339 }\r
340\r
341 }\r
342\r
343 return 0;\r
344}\r
345\r
346/**\r
347 Check the segment against PAWS.\r
348\r
349 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.\r
350 @param[in] TSVal The timestamp value.\r
351\r
352 @retval 1 The segment passed the PAWS check.\r
353 @retval 0 The segment failed to pass the PAWS check.\r
354\r
355**/\r
356UINT32\r
357TcpPawsOK (\r
358 IN TCP_CB *Tcb,\r
359 IN UINT32 TSVal\r
360 )\r
361{\r
362 //\r
363 // PAWS as defined in RFC1323, buggy...\r
364 //\r
365 if (TCP_TIME_LT (TSVal, Tcb->TsRecent) &&\r
366 TCP_TIME_LT (Tcb->TsRecentAge + TCP_PAWS_24DAY, mTcpTick)\r
367 ) {\r
368\r
369 return 0;\r
370\r
371 }\r
372\r
373 return 1;\r
374}\r