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.
27 CopyMem (&Value
, Buf
, sizeof (UINT16
));
32 Get a UINT32 value from buffer.
34 @param[in] Buf Pointer to input buffer.
36 @return The UINT32 value obtained from the buffer.
46 CopyMem (&Value
, Buf
, sizeof (UINT32
));
51 Put a UINT32 value in buffer.
53 @param[out] Buf Pointer to the buffer.
54 @param[in] Data The UINT32 Date to put in the buffer.
64 CopyMem (Buf
, &Data
, sizeof (UINT32
));
68 Compute the window scale value according to the given buffer size.
70 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
72 @return The scale value.
83 ASSERT ((Tcb
!= NULL
) && (Tcb
->Sk
!= NULL
));
85 BufSize
= GET_RCV_BUFFSIZE (Tcb
->Sk
);
88 while ((Scale
< TCP_OPTION_MAX_WS
) && ((UINT32
)(TCP_OPTION_MAX_WIN
<< Scale
) < BufSize
)) {
96 Build the TCP option in three-way handshake.
98 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
99 @param[in] Nbuf Pointer to the buffer to store the options.
101 @return The total length of the TCP option field.
113 ASSERT ((Tcb
!= NULL
) && (Nbuf
!= NULL
) && (Nbuf
->Tcp
== NULL
));
118 // Add a timestamp option if not disabled by the application
119 // and it is the first SYN segment, or the peer has sent
122 if (!TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_TS
) &&
123 (!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf
)->Flag
, TCP_FLG_ACK
) ||
124 TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_RCVD_TS
))
127 Data
= NetbufAllocSpace (
129 TCP_OPTION_TS_ALIGNED_LEN
,
133 ASSERT (Data
!= NULL
);
134 Len
+= TCP_OPTION_TS_ALIGNED_LEN
;
136 TcpPutUint32 (Data
, TCP_OPTION_TS_FAST
);
137 TcpPutUint32 (Data
+ 4, mTcpTick
);
138 TcpPutUint32 (Data
+ 8, 0);
142 // Build window scale option, only when configured
143 // to send WS option, and either we are doing active
144 // open or we have received WS option from peer.
146 if (!TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_WS
) &&
147 (!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf
)->Flag
, TCP_FLG_ACK
) ||
148 TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_RCVD_WS
))
151 Data
= NetbufAllocSpace (
153 TCP_OPTION_WS_ALIGNED_LEN
,
157 ASSERT (Data
!= NULL
);
159 Len
+= TCP_OPTION_WS_ALIGNED_LEN
;
160 TcpPutUint32 (Data
, TCP_OPTION_WS_FAST
| TcpComputeScale (Tcb
));
164 // Build the MSS option.
166 Data
= NetbufAllocSpace (Nbuf
, TCP_OPTION_MSS_LEN
, 1);
167 ASSERT (Data
!= NULL
);
169 Len
+= TCP_OPTION_MSS_LEN
;
170 TcpPutUint32 (Data
, TCP_OPTION_MSS_FAST
| Tcb
->RcvMss
);
176 Build the TCP option in synchronized states.
178 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
179 @param[in] Nbuf Pointer to the buffer to store the options.
181 @return The total length of the TCP option field.
193 ASSERT ((Tcb
!= NULL
) && (Nbuf
!= NULL
) && (Nbuf
->Tcp
== NULL
));
197 // Build the Timestamp option.
199 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_SND_TS
) &&
200 !TCP_FLG_ON (TCPSEG_NETBUF (Nbuf
)->Flag
, TCP_FLG_RST
)
203 Data
= NetbufAllocSpace (
205 TCP_OPTION_TS_ALIGNED_LEN
,
209 ASSERT (Data
!= NULL
);
210 Len
+= TCP_OPTION_TS_ALIGNED_LEN
;
212 TcpPutUint32 (Data
, TCP_OPTION_TS_FAST
);
213 TcpPutUint32 (Data
+ 4, mTcpTick
);
214 TcpPutUint32 (Data
+ 8, Tcb
->TsRecent
);
221 Parse the supported options.
223 @param[in] Tcp Pointer to the TCP_CB of this TCP instance.
224 @param[in, out] Option Pointer to the TCP_OPTION used to store the
225 successfully pasrsed options.
227 @retval 0 The options are successfully pasrsed.
228 @retval -1 Illegal option was found.
234 IN OUT TCP_OPTION
*Option
243 ASSERT ((Tcp
!= NULL
) && (Option
!= NULL
));
247 TotalLen
= (UINT8
)((Tcp
->HeadLen
<< 2) - sizeof (TCP_HEAD
));
252 Head
= (UINT8
*)(Tcp
+ 1);
255 // Fast process of the timestamp option.
257 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
;
266 // Slow path to process the options.
270 while (Cur
< TotalLen
) {
277 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
)) {
294 Option
->WndScale
= (UINT8
)MIN (14, Head
[Cur
+ 2]);
295 TCP_SET_FLG (Option
->Flag
, TCP_OPTION_RCVD_WS
);
297 Cur
+= TCP_OPTION_WS_LEN
;
303 if ((Len
!= TCP_OPTION_TS_LEN
) || (TotalLen
- Cur
< TCP_OPTION_TS_LEN
)) {
307 Option
->TSVal
= TcpGetUint32 (&Head
[Cur
+ 2]);
308 Option
->TSEcr
= TcpGetUint32 (&Head
[Cur
+ 6]);
309 TCP_SET_FLG (Option
->Flag
, TCP_OPTION_RCVD_TS
);
311 Cur
+= TCP_OPTION_TS_LEN
;
325 if (((TotalLen
- Cur
) < Len
) || (Len
< 2)) {
329 Cur
= (UINT8
)(Cur
+ Len
);