2 Routines to process TCP option.
4 Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php<BR>
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Get a UINT16 value from buffer.
20 @param Buf Pointer to input buffer.
22 @return The UINT16 value get from buffer.
31 CopyMem (&Value
, Buf
, sizeof (UINT16
));
36 Get a UINT32 value from buffer.
38 @param Buf Pointer to input buffer.
40 @return The UINT32 value get from buffer.
49 CopyMem (&Value
, Buf
, sizeof (UINT32
));
54 Put a UINT32 value in buffer.
56 @param Buf Pointer to the buffer.
57 @param Data The UINT32 Date to put in buffer
67 CopyMem (Buf
, &Data
, sizeof (UINT32
));
72 Compute the window scale value according to the given buffer size.
74 @param 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
) &&
93 ((UINT32
) (TCP_OPTION_MAX_WIN
<< Scale
) < BufSize
)) {
103 Build the TCP option in three-way handshake.
105 @param Tcb Pointer to the TCP_CB of this TCP instance.
106 @param Nbuf Pointer to the buffer to store the options.
108 @return The total length of the TCP option field.
120 ASSERT ((Tcb
!= NULL
) && (Nbuf
!= NULL
) && (Nbuf
->Tcp
== NULL
));
125 // Add timestamp option if not disabled by application
126 // and it is the first SYN segment or the peer has sent
129 if (!TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_TS
) &&
130 (!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf
)->Flag
, TCP_FLG_ACK
) ||
131 TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_RCVD_TS
))) {
133 Data
= NetbufAllocSpace (
135 TCP_OPTION_TS_ALIGNED_LEN
,
139 ASSERT (Data
!= NULL
);
140 Len
+= TCP_OPTION_TS_ALIGNED_LEN
;
142 TcpPutUint32 (Data
, TCP_OPTION_TS_FAST
);
143 TcpPutUint32 (Data
+ 4, mTcpTick
);
144 TcpPutUint32 (Data
+ 8, 0);
148 // Build window scale option, only when are configured
149 // to send WS option, and either we are doing active
150 // open or we have received WS option from peer.
152 if (!TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_WS
) &&
153 (!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf
)->Flag
, TCP_FLG_ACK
) ||
154 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
));
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
);
182 Build the TCP option in synchronized states.
184 @param Tcb Pointer to the TCP_CB of this TCP instance.
185 @param Nbuf Pointer to the buffer to store the options.
187 @return The total length of the TCP option field.
199 ASSERT ((Tcb
!= NULL
) && (Nbuf
!= NULL
) && (Nbuf
->Tcp
== NULL
));
203 // Build Timestamp option
205 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_SND_TS
) &&
206 !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
);
227 Parse the supported options.
229 @param Tcp Pointer to the TCP_CB of this TCP instance.
230 @param Option Pointer to the TCP_OPTION used to store the successfully pasrsed
233 @retval 0 The options are successfully pasrsed.
234 @retval -1 Ilegal option was found.
240 IN OUT TCP_OPTION
*Option
249 ASSERT ((Tcp
!= NULL
) && (Option
!= NULL
));
253 TotalLen
= (UINT8
) ((Tcp
->HeadLen
<< 2) - sizeof (TCP_HEAD
));
258 Head
= (UINT8
*) (Tcp
+ 1);
261 // Fast process of timestamp option
263 if ((TotalLen
== TCP_OPTION_TS_ALIGNED_LEN
) &&
264 (TcpGetUint32 (Head
) == TCP_OPTION_TS_FAST
)) {
266 Option
->TSVal
= TcpGetUint32 (Head
+ 4);
267 Option
->TSEcr
= TcpGetUint32 (Head
+ 8);
268 Option
->Flag
= TCP_OPTION_RCVD_TS
;
274 // Slow path to process the options.
278 while (Cur
< TotalLen
) {
285 if ((Len
!= TCP_OPTION_MSS_LEN
) ||
286 (TotalLen
- Cur
< TCP_OPTION_MSS_LEN
)) {
291 Option
->Mss
= TcpGetUint16 (&Head
[Cur
+ 2]);
292 TCP_SET_FLG (Option
->Flag
, TCP_OPTION_RCVD_MSS
);
294 Cur
+= TCP_OPTION_MSS_LEN
;
300 if ((Len
!= TCP_OPTION_WS_LEN
) ||
301 (TotalLen
- Cur
< TCP_OPTION_WS_LEN
)) {
306 Option
->WndScale
= (UINT8
) MIN (14, Head
[Cur
+ 2]);
307 TCP_SET_FLG (Option
->Flag
, TCP_OPTION_RCVD_WS
);
309 Cur
+= TCP_OPTION_WS_LEN
;
315 if ((Len
!= TCP_OPTION_TS_LEN
) ||
316 (TotalLen
- Cur
< TCP_OPTION_TS_LEN
)) {
321 Option
->TSVal
= TcpGetUint32 (&Head
[Cur
+ 2]);
322 Option
->TSEcr
= TcpGetUint32 (&Head
[Cur
+ 6]);
323 TCP_SET_FLG (Option
->Flag
, TCP_OPTION_RCVD_TS
);
325 Cur
+= TCP_OPTION_TS_LEN
;
339 if ((TotalLen
- Cur
) < Len
|| Len
< 2) {
343 Cur
= (UINT8
) (Cur
+ Len
);
354 Check the segment against PAWS.
356 @param Tcb Pointer to the TCP_CB of this TCP instance.
357 @param TSVal The timestamp value.
359 @retval 1 The segment passed the PAWS check.
360 @retval 0 The segment failed to pass the PAWS check.
370 // PAWS as defined in RFC1323, buggy...
372 if (TCP_TIME_LT (TSVal
, Tcb
->TsRecent
) &&
373 TCP_TIME_LT (Tcb
->TsRecentAge
+ TCP_PAWS_24DAY
, mTcpTick
)) {