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