VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/NetworkPkg/TcpDxe/TcpOption.c@ 87965

Last change on this file since 87965 was 85718, checked in by vboxsync, 5 years ago

Devices/EFI: Merge edk-stable202005 and make it build, bugref:4643

  • Property svn:eol-style set to native
File size: 6.8 KB
Line 
1/** @file
2 Routines to process TCP option.
3
4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8**/
9
10#include "TcpMain.h"
11
12/**
13 Get a UINT16 value from buffer.
14
15 @param[in] Buf Pointer to input buffer.
16
17 @return The UINT16 value obtained from the buffer.
18
19**/
20UINT16
21TcpGetUint16 (
22 IN UINT8 *Buf
23 )
24{
25 UINT16 Value;
26 CopyMem (&Value, Buf, sizeof (UINT16));
27 return NTOHS (Value);
28}
29
30/**
31 Get a UINT32 value from buffer.
32
33 @param[in] Buf Pointer to input buffer.
34
35 @return The UINT32 value obtained from the buffer.
36
37**/
38UINT32
39TcpGetUint32 (
40 IN UINT8 *Buf
41 )
42{
43 UINT32 Value;
44 CopyMem (&Value, Buf, sizeof (UINT32));
45 return NTOHL (Value);
46}
47
48/**
49 Put a UINT32 value in buffer.
50
51 @param[out] Buf Pointer to the buffer.
52 @param[in] Data The UINT32 Date to put in the buffer.
53
54**/
55VOID
56TcpPutUint32 (
57 OUT UINT8 *Buf,
58 IN UINT32 Data
59 )
60{
61 Data = HTONL (Data);
62 CopyMem (Buf, &Data, sizeof (UINT32));
63}
64
65/**
66 Compute the window scale value according to the given buffer size.
67
68 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
69
70 @return The scale value.
71
72**/
73UINT8
74TcpComputeScale (
75 IN TCP_CB *Tcb
76 )
77{
78 UINT8 Scale;
79 UINT32 BufSize;
80
81 ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL));
82
83 BufSize = GET_RCV_BUFFSIZE (Tcb->Sk);
84
85 Scale = 0;
86 while ((Scale < TCP_OPTION_MAX_WS) && ((UINT32) (TCP_OPTION_MAX_WIN << Scale) < BufSize)) {
87
88 Scale++;
89 }
90
91 return Scale;
92}
93
94/**
95 Build the TCP option in three-way handshake.
96
97 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
98 @param[in] Nbuf Pointer to the buffer to store the options.
99
100 @return The total length of the TCP option field.
101
102**/
103UINT16
104TcpSynBuildOption (
105 IN TCP_CB *Tcb,
106 IN NET_BUF *Nbuf
107 )
108{
109 UINT8 *Data;
110 UINT16 Len;
111
112 ASSERT ((Tcb != NULL) && (Nbuf != NULL) && (Nbuf->Tcp == NULL));
113
114 Len = 0;
115
116 //
117 // Add a timestamp option if not disabled by the application
118 // and it is the first SYN segment, or the peer has sent
119 // us its timestamp.
120 //
121 if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS) &&
122 (!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_ACK) ||
123 TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_TS))
124 ) {
125
126 Data = NetbufAllocSpace (
127 Nbuf,
128 TCP_OPTION_TS_ALIGNED_LEN,
129 NET_BUF_HEAD
130 );
131
132 ASSERT (Data != NULL);
133 Len += TCP_OPTION_TS_ALIGNED_LEN;
134
135 TcpPutUint32 (Data, TCP_OPTION_TS_FAST);
136 TcpPutUint32 (Data + 4, mTcpTick);
137 TcpPutUint32 (Data + 8, 0);
138 }
139
140 //
141 // Build window scale option, only when configured
142 // to send WS option, and either we are doing active
143 // open or we have received WS option from peer.
144 //
145 if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS) &&
146 (!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_ACK) ||
147 TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_WS))
148 ) {
149
150 Data = NetbufAllocSpace (
151 Nbuf,
152 TCP_OPTION_WS_ALIGNED_LEN,
153 NET_BUF_HEAD
154 );
155
156 ASSERT (Data != NULL);
157
158 Len += TCP_OPTION_WS_ALIGNED_LEN;
159 TcpPutUint32 (Data, TCP_OPTION_WS_FAST | TcpComputeScale (Tcb));
160 }
161
162 //
163 // Build the MSS option.
164 //
165 Data = NetbufAllocSpace (Nbuf, TCP_OPTION_MSS_LEN, 1);
166 ASSERT (Data != NULL);
167
168 Len += TCP_OPTION_MSS_LEN;
169 TcpPutUint32 (Data, TCP_OPTION_MSS_FAST | Tcb->RcvMss);
170
171 return Len;
172}
173
174/**
175 Build the TCP option in synchronized states.
176
177 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
178 @param[in] Nbuf Pointer to the buffer to store the options.
179
180 @return The total length of the TCP option field.
181
182**/
183UINT16
184TcpBuildOption (
185 IN TCP_CB *Tcb,
186 IN NET_BUF *Nbuf
187 )
188{
189 UINT8 *Data;
190 UINT16 Len;
191
192 ASSERT ((Tcb != NULL) && (Nbuf != NULL) && (Nbuf->Tcp == NULL));
193 Len = 0;
194
195 //
196 // Build the Timestamp option.
197 //
198 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_TS) &&
199 !TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_RST)
200 ) {
201
202 Data = NetbufAllocSpace (
203 Nbuf,
204 TCP_OPTION_TS_ALIGNED_LEN,
205 NET_BUF_HEAD
206 );
207
208 ASSERT (Data != NULL);
209 Len += TCP_OPTION_TS_ALIGNED_LEN;
210
211 TcpPutUint32 (Data, TCP_OPTION_TS_FAST);
212 TcpPutUint32 (Data + 4, mTcpTick);
213 TcpPutUint32 (Data + 8, Tcb->TsRecent);
214 }
215
216 return Len;
217}
218
219/**
220 Parse the supported options.
221
222 @param[in] Tcp Pointer to the TCP_CB of this TCP instance.
223 @param[in, out] Option Pointer to the TCP_OPTION used to store the
224 successfully pasrsed options.
225
226 @retval 0 The options are successfully pasrsed.
227 @retval -1 Illegal option was found.
228
229**/
230INTN
231TcpParseOption (
232 IN TCP_HEAD *Tcp,
233 IN OUT TCP_OPTION *Option
234 )
235{
236 UINT8 *Head;
237 UINT8 TotalLen;
238 UINT8 Cur;
239 UINT8 Type;
240 UINT8 Len;
241
242 ASSERT ((Tcp != NULL) && (Option != NULL));
243
244 Option->Flag = 0;
245
246 TotalLen = (UINT8) ((Tcp->HeadLen << 2) - sizeof (TCP_HEAD));
247 if (TotalLen <= 0) {
248 return 0;
249 }
250
251 Head = (UINT8 *) (Tcp + 1);
252
253 //
254 // Fast process of the timestamp option.
255 //
256 if ((TotalLen == TCP_OPTION_TS_ALIGNED_LEN) && (TcpGetUint32 (Head) == TCP_OPTION_TS_FAST)) {
257
258 Option->TSVal = TcpGetUint32 (Head + 4);
259 Option->TSEcr = TcpGetUint32 (Head + 8);
260 Option->Flag = TCP_OPTION_RCVD_TS;
261
262 return 0;
263 }
264 //
265 // Slow path to process the options.
266 //
267 Cur = 0;
268
269 while (Cur < TotalLen) {
270 Type = Head[Cur];
271
272 switch (Type) {
273 case TCP_OPTION_MSS:
274 Len = Head[Cur + 1];
275
276 if ((Len != TCP_OPTION_MSS_LEN) || (TotalLen - Cur < TCP_OPTION_MSS_LEN)) {
277
278 return -1;
279 }
280
281 Option->Mss = TcpGetUint16 (&Head[Cur + 2]);
282 TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_MSS);
283
284 Cur += TCP_OPTION_MSS_LEN;
285 break;
286
287 case TCP_OPTION_WS:
288 Len = Head[Cur + 1];
289
290 if ((Len != TCP_OPTION_WS_LEN) || (TotalLen - Cur < TCP_OPTION_WS_LEN)) {
291
292 return -1;
293 }
294
295 Option->WndScale = (UINT8) MIN (14, Head[Cur + 2]);
296 TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_WS);
297
298 Cur += TCP_OPTION_WS_LEN;
299 break;
300
301 case TCP_OPTION_TS:
302 Len = Head[Cur + 1];
303
304 if ((Len != TCP_OPTION_TS_LEN) || (TotalLen - Cur < TCP_OPTION_TS_LEN)) {
305
306 return -1;
307 }
308
309 Option->TSVal = TcpGetUint32 (&Head[Cur + 2]);
310 Option->TSEcr = TcpGetUint32 (&Head[Cur + 6]);
311 TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_TS);
312
313 Cur += TCP_OPTION_TS_LEN;
314 break;
315
316 case TCP_OPTION_NOP:
317 Cur++;
318 break;
319
320 case TCP_OPTION_EOP:
321 Cur = TotalLen;
322 break;
323
324 default:
325 Len = Head[Cur + 1];
326
327 if ((TotalLen - Cur) < Len || Len < 2) {
328 return -1;
329 }
330
331 Cur = (UINT8) (Cur + Len);
332 break;
333 }
334
335 }
336
337 return 0;
338}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette