2 Routines to process TCP option.
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Get a UINT16 value from buffer.
21 @param[in] Buf Pointer to input buffer.
23 @return The UINT16 value obtained from the buffer.
32 CopyMem (&Value
, Buf
, sizeof (UINT16
));
37 Get a UINT32 value from buffer.
39 @param[in] Buf Pointer to input buffer.
41 @return The UINT32 value obtained from the buffer.
50 CopyMem (&Value
, Buf
, sizeof (UINT32
));
55 Put a UINT32 value in buffer.
57 @param[out] Buf Pointer to the buffer.
58 @param[in] Data The UINT32 Date to put in the buffer.
68 CopyMem (Buf
, &Data
, sizeof (UINT32
));
72 Compute the window scale value according to the given buffer size.
74 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
76 @return The scale value.
87 ASSERT ((Tcb
!= NULL
) && (Tcb
->Sk
!= NULL
));
89 BufSize
= GET_RCV_BUFFSIZE (Tcb
->Sk
);
92 while ((Scale
< TCP_OPTION_MAX_WS
) && ((UINT32
) (TCP_OPTION_MAX_WIN
<< Scale
) < BufSize
)) {
101 Build the TCP option in three-way handshake.
103 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
104 @param[in] Nbuf Pointer to the buffer to store the options.
106 @return The total length of the TCP option field.
118 ASSERT ((Tcb
!= NULL
) && (Nbuf
!= NULL
) && (Nbuf
->Tcp
== NULL
));
123 // Add a timestamp option if not disabled by the application
124 // and it is the first SYN segment, or the peer has sent
127 if (!TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_TS
) &&
128 (!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf
)->Flag
, TCP_FLG_ACK
) ||
129 TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_RCVD_TS
))
132 Data
= NetbufAllocSpace (
134 TCP_OPTION_TS_ALIGNED_LEN
,
138 ASSERT (Data
!= NULL
);
139 Len
+= TCP_OPTION_TS_ALIGNED_LEN
;
141 TcpPutUint32 (Data
, TCP_OPTION_TS_FAST
);
142 TcpPutUint32 (Data
+ 4, mTcpTick
);
143 TcpPutUint32 (Data
+ 8, 0);
147 // Build window scale option, only when configured
148 // to send WS option, and either we are doing active
149 // open or we have received WS option from peer.
151 if (!TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_WS
) &&
152 (!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf
)->Flag
, TCP_FLG_ACK
) ||
153 TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_RCVD_WS
))
156 Data
= NetbufAllocSpace (
158 TCP_OPTION_WS_ALIGNED_LEN
,
162 ASSERT (Data
!= NULL
);
164 Len
+= TCP_OPTION_WS_ALIGNED_LEN
;
165 TcpPutUint32 (Data
, TCP_OPTION_WS_FAST
| TcpComputeScale (Tcb
));
169 // Build the MSS option.
171 Data
= NetbufAllocSpace (Nbuf
, TCP_OPTION_MSS_LEN
, 1);
172 ASSERT (Data
!= NULL
);
174 Len
+= TCP_OPTION_MSS_LEN
;
175 TcpPutUint32 (Data
, TCP_OPTION_MSS_FAST
| Tcb
->RcvMss
);
181 Build the TCP option in synchronized states.
183 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
184 @param[in] Nbuf Pointer to the buffer to store the options.
186 @return The total length of the TCP option field.
198 ASSERT ((Tcb
!= NULL
) && (Nbuf
!= NULL
) && (Nbuf
->Tcp
== NULL
));
202 // Build the Timestamp option.
204 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_SND_TS
) &&
205 !TCP_FLG_ON (TCPSEG_NETBUF (Nbuf
)->Flag
, TCP_FLG_RST
)
208 Data
= NetbufAllocSpace (
210 TCP_OPTION_TS_ALIGNED_LEN
,
214 ASSERT (Data
!= NULL
);
215 Len
+= TCP_OPTION_TS_ALIGNED_LEN
;
217 TcpPutUint32 (Data
, TCP_OPTION_TS_FAST
);
218 TcpPutUint32 (Data
+ 4, mTcpTick
);
219 TcpPutUint32 (Data
+ 8, Tcb
->TsRecent
);
226 Parse the supported options.
228 @param[in] Tcp Pointer to the TCP_CB of this TCP instance.
229 @param[in, out] Option Pointer to the TCP_OPTION used to store the
230 successfully pasrsed options.
232 @retval 0 The options are successfully pasrsed.
233 @retval -1 Ilegal option was found.
239 IN OUT TCP_OPTION
*Option
248 ASSERT ((Tcp
!= NULL
) && (Option
!= NULL
));
252 TotalLen
= (UINT8
) ((Tcp
->HeadLen
<< 2) - sizeof (TCP_HEAD
));
257 Head
= (UINT8
*) (Tcp
+ 1);
260 // Fast process of the timestamp option.
262 if ((TotalLen
== TCP_OPTION_TS_ALIGNED_LEN
) && (TcpGetUint32 (Head
) == TCP_OPTION_TS_FAST
)) {
264 Option
->TSVal
= TcpGetUint32 (Head
+ 4);
265 Option
->TSEcr
= TcpGetUint32 (Head
+ 8);
266 Option
->Flag
= TCP_OPTION_RCVD_TS
;
271 // Slow path to process the options.
275 while (Cur
< TotalLen
) {
282 if ((Len
!= TCP_OPTION_MSS_LEN
) || (TotalLen
- Cur
< TCP_OPTION_MSS_LEN
)) {
287 Option
->Mss
= TcpGetUint16 (&Head
[Cur
+ 2]);
288 TCP_SET_FLG (Option
->Flag
, TCP_OPTION_RCVD_MSS
);
290 Cur
+= TCP_OPTION_MSS_LEN
;
296 if ((Len
!= TCP_OPTION_WS_LEN
) || (TotalLen
- Cur
< TCP_OPTION_WS_LEN
)) {
301 Option
->WndScale
= (UINT8
) MIN (14, Head
[Cur
+ 2]);
302 TCP_SET_FLG (Option
->Flag
, TCP_OPTION_RCVD_WS
);
304 Cur
+= TCP_OPTION_WS_LEN
;
310 if ((Len
!= TCP_OPTION_TS_LEN
) || (TotalLen
- Cur
< TCP_OPTION_TS_LEN
)) {
315 Option
->TSVal
= TcpGetUint32 (&Head
[Cur
+ 2]);
316 Option
->TSEcr
= TcpGetUint32 (&Head
[Cur
+ 6]);
317 TCP_SET_FLG (Option
->Flag
, TCP_OPTION_RCVD_TS
);
319 Cur
+= TCP_OPTION_TS_LEN
;
333 if ((TotalLen
- Cur
) < Len
|| Len
< 2) {
337 Cur
= (UINT8
) (Cur
+ Len
);
347 Check the segment against PAWS.
349 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
350 @param[in] TSVal The timestamp value.
352 @retval 1 The segment passed the PAWS check.
353 @retval 0 The segment failed to pass the PAWS check.
363 // PAWS as defined in RFC1323, buggy...
365 if (TCP_TIME_LT (TSVal
, Tcb
->TsRecent
) &&
366 TCP_TIME_LT (Tcb
->TsRecentAge
+ TCP_PAWS_24DAY
, mTcpTick
)