2 Routines to process TCP option.
4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
13 Get a UINT16 value from buffer.
15 @param[in] Buf Pointer to input buffer.
17 @return The UINT16 value obtained from the buffer.
26 CopyMem (&Value
, Buf
, sizeof (UINT16
));
31 Get a UINT32 value from buffer.
33 @param[in] Buf Pointer to input buffer.
35 @return The UINT32 value obtained from the buffer.
44 CopyMem (&Value
, Buf
, sizeof (UINT32
));
49 Put a UINT32 value in buffer.
51 @param[out] Buf Pointer to the buffer.
52 @param[in] Data The UINT32 Date to put in the buffer.
62 CopyMem (Buf
, &Data
, sizeof (UINT32
));
66 Compute the window scale value according to the given buffer size.
68 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
70 @return The scale value.
81 ASSERT ((Tcb
!= NULL
) && (Tcb
->Sk
!= NULL
));
83 BufSize
= GET_RCV_BUFFSIZE (Tcb
->Sk
);
86 while ((Scale
< TCP_OPTION_MAX_WS
) && ((UINT32
) (TCP_OPTION_MAX_WIN
<< Scale
) < BufSize
)) {
95 Build the TCP option in three-way handshake.
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.
100 @return The total length of the TCP option field.
112 ASSERT ((Tcb
!= NULL
) && (Nbuf
!= NULL
) && (Nbuf
->Tcp
== NULL
));
117 // Add a timestamp option if not disabled by the application
118 // and it is the first SYN segment, or the peer has sent
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
))
126 Data
= NetbufAllocSpace (
128 TCP_OPTION_TS_ALIGNED_LEN
,
132 ASSERT (Data
!= NULL
);
133 Len
+= TCP_OPTION_TS_ALIGNED_LEN
;
135 TcpPutUint32 (Data
, TCP_OPTION_TS_FAST
);
136 TcpPutUint32 (Data
+ 4, mTcpTick
);
137 TcpPutUint32 (Data
+ 8, 0);
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.
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
))
150 Data
= NetbufAllocSpace (
152 TCP_OPTION_WS_ALIGNED_LEN
,
156 ASSERT (Data
!= NULL
);
158 Len
+= TCP_OPTION_WS_ALIGNED_LEN
;
159 TcpPutUint32 (Data
, TCP_OPTION_WS_FAST
| TcpComputeScale (Tcb
));
163 // Build the MSS option.
165 Data
= NetbufAllocSpace (Nbuf
, TCP_OPTION_MSS_LEN
, 1);
166 ASSERT (Data
!= NULL
);
168 Len
+= TCP_OPTION_MSS_LEN
;
169 TcpPutUint32 (Data
, TCP_OPTION_MSS_FAST
| Tcb
->RcvMss
);
175 Build the TCP option in synchronized states.
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.
180 @return The total length of the TCP option field.
192 ASSERT ((Tcb
!= NULL
) && (Nbuf
!= NULL
) && (Nbuf
->Tcp
== NULL
));
196 // Build the Timestamp option.
198 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_SND_TS
) &&
199 !TCP_FLG_ON (TCPSEG_NETBUF (Nbuf
)->Flag
, TCP_FLG_RST
)
202 Data
= NetbufAllocSpace (
204 TCP_OPTION_TS_ALIGNED_LEN
,
208 ASSERT (Data
!= NULL
);
209 Len
+= TCP_OPTION_TS_ALIGNED_LEN
;
211 TcpPutUint32 (Data
, TCP_OPTION_TS_FAST
);
212 TcpPutUint32 (Data
+ 4, mTcpTick
);
213 TcpPutUint32 (Data
+ 8, Tcb
->TsRecent
);
220 Parse the supported options.
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.
226 @retval 0 The options are successfully pasrsed.
227 @retval -1 Ilegal option was found.
233 IN OUT TCP_OPTION
*Option
242 ASSERT ((Tcp
!= NULL
) && (Option
!= NULL
));
246 TotalLen
= (UINT8
) ((Tcp
->HeadLen
<< 2) - sizeof (TCP_HEAD
));
251 Head
= (UINT8
*) (Tcp
+ 1);
254 // Fast process of the timestamp option.
256 if ((TotalLen
== TCP_OPTION_TS_ALIGNED_LEN
) && (TcpGetUint32 (Head
) == TCP_OPTION_TS_FAST
)) {
258 Option
->TSVal
= TcpGetUint32 (Head
+ 4);
259 Option
->TSEcr
= TcpGetUint32 (Head
+ 8);
260 Option
->Flag
= TCP_OPTION_RCVD_TS
;
265 // Slow path to process the options.
269 while (Cur
< TotalLen
) {
276 if ((Len
!= TCP_OPTION_MSS_LEN
) || (TotalLen
- Cur
< TCP_OPTION_MSS_LEN
)) {
281 Option
->Mss
= TcpGetUint16 (&Head
[Cur
+ 2]);
282 TCP_SET_FLG (Option
->Flag
, TCP_OPTION_RCVD_MSS
);
284 Cur
+= TCP_OPTION_MSS_LEN
;
290 if ((Len
!= TCP_OPTION_WS_LEN
) || (TotalLen
- Cur
< TCP_OPTION_WS_LEN
)) {
295 Option
->WndScale
= (UINT8
) MIN (14, Head
[Cur
+ 2]);
296 TCP_SET_FLG (Option
->Flag
, TCP_OPTION_RCVD_WS
);
298 Cur
+= TCP_OPTION_WS_LEN
;
304 if ((Len
!= TCP_OPTION_TS_LEN
) || (TotalLen
- Cur
< TCP_OPTION_TS_LEN
)) {
309 Option
->TSVal
= TcpGetUint32 (&Head
[Cur
+ 2]);
310 Option
->TSEcr
= TcpGetUint32 (&Head
[Cur
+ 6]);
311 TCP_SET_FLG (Option
->Flag
, TCP_OPTION_RCVD_TS
);
313 Cur
+= TCP_OPTION_TS_LEN
;
327 if ((TotalLen
- Cur
) < Len
|| Len
< 2) {
331 Cur
= (UINT8
) (Cur
+ Len
);