Import SnpDxe, Tcp4Dxe, Udp4Dxe and MnpDxe.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3416 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
380
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Option.c
Normal file
380
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Option.c
Normal file
@@ -0,0 +1,380 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2005 - 2006, Intel Corporation
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
Tcp4Option.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Routines to process TCP option.
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#include "Tcp4Main.h"
|
||||
|
||||
STATIC
|
||||
UINT16
|
||||
TcpGetUint16 (
|
||||
IN UINT8 *Buf
|
||||
)
|
||||
{
|
||||
UINT16 Value;
|
||||
NetCopyMem (&Value, Buf, sizeof (UINT16));
|
||||
return NTOHS (Value);
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
TcpPutUint16 (
|
||||
IN UINT8 *Buf,
|
||||
IN UINT16 Data
|
||||
)
|
||||
{
|
||||
Data = HTONS (Data);
|
||||
NetCopyMem (Buf, &Data, sizeof (UINT16));
|
||||
}
|
||||
|
||||
STATIC
|
||||
UINT32
|
||||
TcpGetUint32 (
|
||||
IN UINT8 *Buf
|
||||
)
|
||||
{
|
||||
UINT32 Value;
|
||||
NetCopyMem (&Value, Buf, sizeof (UINT32));
|
||||
return NTOHL (Value);
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
TcpPutUint32 (
|
||||
IN UINT8 *Buf,
|
||||
IN UINT32 Data
|
||||
)
|
||||
{
|
||||
Data = HTONL (Data);
|
||||
NetCopyMem (Buf, &Data, sizeof (UINT32));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Compute the window scale value according to the given
|
||||
buffer size.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
|
||||
@retval UINT8 The scale value.
|
||||
|
||||
**/
|
||||
UINT8
|
||||
TcpComputeScale (
|
||||
IN TCP_CB *Tcb
|
||||
)
|
||||
{
|
||||
UINT8 Scale;
|
||||
UINT32 BufSize;
|
||||
|
||||
ASSERT (Tcb && Tcb->Sk);
|
||||
|
||||
BufSize = GET_RCV_BUFFSIZE (Tcb->Sk);
|
||||
|
||||
Scale = 0;
|
||||
while ((Scale < TCP_OPTION_MAX_WS) &&
|
||||
((UINT32) (TCP_OPTION_MAX_WIN << Scale) < BufSize)) {
|
||||
|
||||
Scale++;
|
||||
}
|
||||
|
||||
return Scale;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Build the TCP option in three-way handshake.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param Nbuf Pointer to the buffer to store the options.
|
||||
|
||||
@return The total length of the TCP option field.
|
||||
|
||||
**/
|
||||
UINT16
|
||||
TcpSynBuildOption (
|
||||
IN TCP_CB *Tcb,
|
||||
IN NET_BUF *Nbuf
|
||||
)
|
||||
{
|
||||
char *Data;
|
||||
UINT16 Len;
|
||||
|
||||
ASSERT (Tcb && Nbuf && !Nbuf->Tcp);
|
||||
|
||||
Len = 0;
|
||||
|
||||
//
|
||||
// Add timestamp option if not disabled by application
|
||||
// and it is the first SYN segment or the peer has sent
|
||||
// us its timestamp.
|
||||
//
|
||||
if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS) &&
|
||||
(!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_ACK) ||
|
||||
TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_TS))) {
|
||||
|
||||
Data = NetbufAllocSpace (
|
||||
Nbuf,
|
||||
TCP_OPTION_TS_ALIGNED_LEN,
|
||||
NET_BUF_HEAD
|
||||
);
|
||||
|
||||
ASSERT (Data);
|
||||
Len += TCP_OPTION_TS_ALIGNED_LEN;
|
||||
|
||||
TcpPutUint32 (Data, TCP_OPTION_TS_FAST);
|
||||
TcpPutUint32 (Data + 4, mTcpTick);
|
||||
TcpPutUint32 (Data + 8, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Build window scale option, only when are configured
|
||||
// to send WS option, and either we are doing active
|
||||
// open or we have received WS option from peer.
|
||||
//
|
||||
if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS) &&
|
||||
(!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_ACK) ||
|
||||
TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_WS))) {
|
||||
|
||||
Data = NetbufAllocSpace (
|
||||
Nbuf,
|
||||
TCP_OPTION_WS_ALIGNED_LEN,
|
||||
NET_BUF_HEAD
|
||||
);
|
||||
|
||||
ASSERT (Data);
|
||||
|
||||
Len += TCP_OPTION_WS_ALIGNED_LEN;
|
||||
TcpPutUint32 (Data, TCP_OPTION_WS_FAST | TcpComputeScale (Tcb));
|
||||
}
|
||||
|
||||
//
|
||||
// Build MSS option
|
||||
//
|
||||
Data = NetbufAllocSpace (Nbuf, TCP_OPTION_MSS_LEN, 1);
|
||||
ASSERT (Data);
|
||||
|
||||
Len += TCP_OPTION_MSS_LEN;
|
||||
TcpPutUint32 (Data, TCP_OPTION_MSS_FAST | Tcb->RcvMss);
|
||||
|
||||
return Len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Build the TCP option in synchronized states.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param Nbuf Pointer to the buffer to store the options.
|
||||
|
||||
@return The total length of the TCP option field.
|
||||
|
||||
**/
|
||||
UINT16
|
||||
TcpBuildOption (
|
||||
IN TCP_CB *Tcb,
|
||||
IN NET_BUF *Nbuf
|
||||
)
|
||||
{
|
||||
char *Data;
|
||||
UINT16 Len;
|
||||
|
||||
ASSERT (Tcb && Nbuf && !Nbuf->Tcp);
|
||||
Len = 0;
|
||||
|
||||
//
|
||||
// Build Timestamp option
|
||||
//
|
||||
if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_TS) &&
|
||||
!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_RST)) {
|
||||
|
||||
Data = NetbufAllocSpace (
|
||||
Nbuf,
|
||||
TCP_OPTION_TS_ALIGNED_LEN,
|
||||
NET_BUF_HEAD
|
||||
);
|
||||
|
||||
ASSERT (Data);
|
||||
Len += TCP_OPTION_TS_ALIGNED_LEN;
|
||||
|
||||
TcpPutUint32 (Data, TCP_OPTION_TS_FAST);
|
||||
TcpPutUint32 (Data + 4, mTcpTick);
|
||||
TcpPutUint32 (Data + 8, Tcb->TsRecent);
|
||||
}
|
||||
|
||||
return Len;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Parse the supported options.
|
||||
|
||||
@param Tcp Pointer to the TCP_CB of this TCP instance.
|
||||
@param Option Pointer to the TCP_OPTION used to store the successfully pasrsed
|
||||
options.
|
||||
|
||||
@retval 0 The options are successfully pasrsed.
|
||||
@retval -1 Ilegal option was found.
|
||||
|
||||
**/
|
||||
INTN
|
||||
TcpParseOption (
|
||||
IN TCP_HEAD *Tcp,
|
||||
IN TCP_OPTION *Option
|
||||
)
|
||||
{
|
||||
UINT8 *Head;
|
||||
UINT8 TotalLen;
|
||||
UINT8 Cur;
|
||||
UINT8 Type;
|
||||
UINT8 Len;
|
||||
|
||||
ASSERT (Tcp && Option);
|
||||
|
||||
Option->Flag = 0;
|
||||
|
||||
TotalLen = (Tcp->HeadLen << 2) - sizeof (TCP_HEAD);
|
||||
if (TotalLen <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Head = (UINT8 *) (Tcp + 1);
|
||||
|
||||
//
|
||||
// Fast process of timestamp option
|
||||
//
|
||||
if ((TotalLen == TCP_OPTION_TS_ALIGNED_LEN) &&
|
||||
(TcpGetUint32 (Head) == TCP_OPTION_TS_FAST)) {
|
||||
|
||||
Option->TSVal = TcpGetUint32 (Head + 4);
|
||||
Option->TSEcr = TcpGetUint32 (Head + 8);
|
||||
Option->Flag = TCP_OPTION_RCVD_TS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Slow path to process the options.
|
||||
//
|
||||
Cur = 0;
|
||||
|
||||
while (Cur < TotalLen) {
|
||||
Type = Head[Cur];
|
||||
|
||||
switch (Type) {
|
||||
case TCP_OPTION_MSS:
|
||||
Len = Head[Cur + 1];
|
||||
|
||||
if ((Len != TCP_OPTION_MSS_LEN) ||
|
||||
(TotalLen - Cur < TCP_OPTION_MSS_LEN)) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
Option->Mss = TcpGetUint16 (&Head[Cur + 2]);
|
||||
TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_MSS);
|
||||
|
||||
Cur += TCP_OPTION_MSS_LEN;
|
||||
break;
|
||||
|
||||
case TCP_OPTION_WS:
|
||||
Len = Head[Cur + 1];
|
||||
|
||||
if ((Len != TCP_OPTION_WS_LEN) ||
|
||||
(TotalLen - Cur < TCP_OPTION_WS_LEN)) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
Option->WndScale = NET_MIN (14, Head[Cur + 2]);
|
||||
TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_WS);
|
||||
|
||||
Cur += TCP_OPTION_WS_LEN;
|
||||
break;
|
||||
|
||||
case TCP_OPTION_TS:
|
||||
Len = Head[Cur + 1];
|
||||
|
||||
if ((Len != TCP_OPTION_TS_LEN) ||
|
||||
(TotalLen - Cur < TCP_OPTION_TS_LEN)) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
Option->TSVal = TcpGetUint32 (&Head[Cur + 2]);
|
||||
Option->TSEcr = TcpGetUint32 (&Head[Cur + 6]);
|
||||
TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_TS);
|
||||
|
||||
Cur += TCP_OPTION_TS_LEN;
|
||||
break;
|
||||
|
||||
case TCP_OPTION_NOP:
|
||||
Cur++;
|
||||
break;
|
||||
|
||||
case TCP_OPTION_EOP:
|
||||
Cur = TotalLen;
|
||||
break;
|
||||
|
||||
default:
|
||||
Len = Head[Cur + 1];
|
||||
|
||||
if (TotalLen - Cur < Len || Len < 2) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Cur = Cur + Len;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check the segment against PAWS.
|
||||
|
||||
@param Tcb Pointer to the TCP_CB of this TCP instance.
|
||||
@param TSVal The timestamp value.
|
||||
|
||||
@retval 1 The segment passed the PAWS check.
|
||||
@retval 0 The segment failed to pass the PAWS check.
|
||||
|
||||
**/
|
||||
UINT32
|
||||
TcpPawsOK (
|
||||
IN TCP_CB *Tcb,
|
||||
IN UINT32 TSVal
|
||||
)
|
||||
{
|
||||
//
|
||||
// PAWS as defined in RFC1323, buggy...
|
||||
//
|
||||
if (TCP_TIME_LT (TSVal, Tcb->TsRecent) &&
|
||||
TCP_TIME_LT (Tcb->TsRecentAge + TCP_PAWS_24DAY, mTcpTick)) {
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
Reference in New Issue
Block a user