]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Option.c
MdeModulePkg Tcp4Dxe: Remove redundant functions
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Tcp4Dxe / Tcp4Option.c
CommitLineData
8a67d61d 1/** @file\r
dfc1f033 2 Routines to process TCP option.\r
d1102dba
LG
3\r
4Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
8a67d61d 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
dfc1f033 8http://opensource.org/licenses/bsd-license.php<BR>\r
8a67d61d 9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
8a67d61d 13**/\r
14\r
15#include "Tcp4Main.h"\r
16\r
120db52c 17/**\r
18 Get a UINT16 value from buffer.\r
d1102dba 19\r
120db52c 20 @param Buf Pointer to input buffer.\r
d1102dba 21\r
120db52c 22 @return The UINT16 value get from buffer.\r
23\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
120db52c 35/**\r
36 Get a UINT32 value from buffer.\r
d1102dba 37\r
120db52c 38 @param Buf Pointer to input buffer.\r
d1102dba 39\r
120db52c 40 @return The UINT32 value get from buffer.\r
8a67d61d 41\r
120db52c 42**/\r
8a67d61d 43UINT32\r
44TcpGetUint32 (\r
45 IN UINT8 *Buf\r
46 )\r
47{\r
48 UINT32 Value;\r
e48e37fc 49 CopyMem (&Value, Buf, sizeof (UINT32));\r
8a67d61d 50 return NTOHL (Value);\r
51}\r
52\r
120db52c 53/**\r
54 Put a UINT32 value in buffer.\r
d1102dba 55\r
120db52c 56 @param Buf Pointer to the buffer.\r
d1102dba 57 @param Data The UINT32 Date to put in buffer\r
120db52c 58\r
59**/\r
8a67d61d 60VOID\r
61TcpPutUint32 (\r
77f00155 62 OUT UINT8 *Buf,\r
63 IN UINT32 Data\r
8a67d61d 64 )\r
65{\r
66 Data = HTONL (Data);\r
e48e37fc 67 CopyMem (Buf, &Data, sizeof (UINT32));\r
8a67d61d 68}\r
69\r
70\r
71/**\r
120db52c 72 Compute the window scale value according to the given buffer size.\r
8a67d61d 73\r
74 @param Tcb Pointer to the TCP_CB of this TCP instance.\r
75\r
120db52c 76 @return The scale value.\r
8a67d61d 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
120db52c 87 ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL));\r
8a67d61d 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
120db52c 108 @return The total length of the TCP option field.\r
8a67d61d 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
120db52c 120 ASSERT ((Tcb != NULL) && (Nbuf != NULL) && (Nbuf->Tcp == NULL));\r
8a67d61d 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
120db52c 131 TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_TS))) {\r
8a67d61d 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
120db52c 139 ASSERT (Data != NULL);\r
8a67d61d 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
120db52c 154 TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_WS))) {\r
8a67d61d 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
120db52c 162 ASSERT (Data != NULL);\r
8a67d61d 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
120db52c 172 ASSERT (Data != NULL);\r
8a67d61d 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
120db52c 187 @return The total length of the TCP option field.\r
8a67d61d 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
120db52c 199 ASSERT ((Tcb != NULL) && (Nbuf != NULL) && (Nbuf->Tcp == NULL));\r
8a67d61d 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
120db52c 214 ASSERT (Data != NULL);\r
8a67d61d 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
77f00155 239 IN TCP_HEAD *Tcp,\r
240 IN OUT TCP_OPTION *Option\r
8a67d61d 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
120db52c 249 ASSERT ((Tcp != NULL) && (Option != NULL));\r
8a67d61d 250\r
251 Option->Flag = 0;\r
252\r
d074a8e1 253 TotalLen = (UINT8) ((Tcp->HeadLen << 2) - sizeof (TCP_HEAD));\r
8a67d61d 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
36ee91ca 306 Option->WndScale = (UINT8) 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
120db52c 339 if ((TotalLen - Cur) < Len || Len < 2) {\r
8a67d61d 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