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