tcp4misc.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,206 行 · 第 1/2 页
C
1,206 行
/*++
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:
Tcp4Misc.c
Abstract:
Misc support routines for tcp.
--*/
#include "Tcp4Main.h"
NET_LIST_ENTRY mTcpRunQue = {
&mTcpRunQue,
&mTcpRunQue
};
NET_LIST_ENTRY mTcpListenQue = {
&mTcpListenQue,
&mTcpListenQue
};
TCP_SEQNO mTcpGlobalIss = 0x4d7e980b;
STATIC CHAR16 *mTcpStateName[] = {
L"TCP_CLOSED",
L"TCP_LISTEN",
L"TCP_SYN_SENT",
L"TCP_SYN_RCVD",
L"TCP_ESTABLISHED",
L"TCP_FIN_WAIT_1",
L"TCP_FIN_WAIT_2",
L"TCP_CLOSING",
L"TCP_TIME_WAIT",
L"TCP_CLOSE_WAIT",
L"TCP_LAST_ACK"
};
VOID
TcpInitTcbLocal (
IN TCP_CB *Tcb
)
/*++
Routine Description:
Initialize the Tcb local related members.
Arguments:
Tcb - Pointer to the TCP_CB of this TCP instance.
Returns:
None
--*/
{
//
// Compute the checksum of the fixed parts of pseudo header
//
Tcb->HeadSum = NetPseudoHeadChecksum (
Tcb->LocalEnd.Ip,
Tcb->RemoteEnd.Ip,
0x06,
0
);
Tcb->Iss = TcpGetIss ();
Tcb->SndUna = Tcb->Iss;
Tcb->SndNxt = Tcb->Iss;
Tcb->SndWl2 = Tcb->Iss;
Tcb->SndWnd = 536;
Tcb->RcvWnd = GET_RCV_BUFFSIZE (Tcb->Sk);
//
// Fisrt window size is never scaled
//
Tcb->RcvWndScale = 0;
}
VOID
TcpInitTcbPeer (
IN TCP_CB *Tcb,
IN TCP_SEG *Seg,
IN TCP_OPTION *Opt
)
/*++
Routine Description:
Initialize the peer related members.
Arguments:
Tcb - Pointer to the TCP_CB of this TCP instance.
Seg - Pointer to the segment that contains the peer's intial info.
Opt - Pointer to the options announced by the peer.
Returns:
None
--*/
{
UINT16 RcvMss;
ASSERT (Tcb && Seg && Opt);
ASSERT (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN));
Tcb->SndWnd = Seg->Wnd;
Tcb->SndWndMax = Tcb->SndWnd;
Tcb->SndWl1 = Seg->Seq;
if (TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {
Tcb->SndWl2 = Seg->Ack;
} else {
Tcb->SndWl2 = Tcb->Iss + 1;
}
if (TCP_FLG_ON (Opt->Flag, TCP_OPTION_RCVD_MSS)) {
Tcb->SndMss = NET_MAX (64, Opt->Mss);
RcvMss = TcpGetRcvMss (Tcb->Sk);
if (Tcb->SndMss > RcvMss) {
Tcb->SndMss = RcvMss;
}
} else {
//
// One end doesn't support MSS option, use default.
//
Tcb->RcvMss = 536;
}
Tcb->CWnd = Tcb->SndMss;
Tcb->Irs = Seg->Seq;
Tcb->RcvNxt = Tcb->Irs + 1;
Tcb->RcvWl2 = Tcb->RcvNxt;
if (TCP_FLG_ON (Opt->Flag, TCP_OPTION_RCVD_WS) &&
!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS)) {
Tcb->SndWndScale = Opt->WndScale;
Tcb->RcvWndScale = TcpComputeScale (Tcb);
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RCVD_WS);
} else {
//
// One end doesn't support window scale option. use zero.
//
Tcb->RcvWndScale = 0;
}
if (TCP_FLG_ON (Opt->Flag, TCP_OPTION_RCVD_TS) &&
!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS)) {
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_TS);
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RCVD_TS);
//
// Compute the effective SndMss per RFC1122
// section 4.2.2.6. If timestamp option is
// enabled, it will always occupy 12 bytes.
//
Tcb->SndMss -= TCP_OPTION_TS_ALIGNED_LEN;
}
}
STATIC
TCP_CB *
TcpLocateListenTcb (
IN TCP_PEER *Local,
IN TCP_PEER *Remote
)
/*++
Routine Description:
Locate a listen TCB that matchs the Local and Remote.
Arguments:
Local - Pointer to the local (IP, Port).
Remote - Pointer to the remote (IP, Port).
Returns:
Pointer to the TCP_CB with the least number of wildcard, if NULL no match is found.
--*/
{
NET_LIST_ENTRY *Entry;
TCP_CB *Node;
TCP_CB *Match;
INTN Last;
INTN Cur;
Last = 4;
Match = NULL;
NET_LIST_FOR_EACH (Entry, &mTcpListenQue) {
Node = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
if ((Local->Port != Node->LocalEnd.Port) ||
!TCP_PEER_MATCH (Remote, &Node->RemoteEnd) ||
!TCP_PEER_MATCH (Local, &Node->LocalEnd)
) {
continue;
}
//
// Compute the number of wildcard
//
Cur = 0;
if (Node->RemoteEnd.Ip == 0) {
Cur++;
}
if (Node->RemoteEnd.Port == 0) {
Cur++;
}
if (Node->LocalEnd.Ip == 0) {
Cur++;
}
if (Cur < Last) {
if (Cur == 0) {
return Node;
}
Last = Cur;
Match = Node;
}
}
return Match;
}
BOOLEAN
TcpFindTcbByPeer (
IN EFI_IPv4_ADDRESS *Addr,
IN TCP_PORTNO Port
)
/*++
Routine Description:
Try to find one Tcb whose <Ip, Port> equals to <IN Addr, IN Port>.
Arguments:
Addr - Pointer to the IP address needs to match.
Port - The port number needs to match.
Returns:
The Tcb which matches the <Addr Port> paire exists or not.
--*/
{
TCP_PORTNO LocalPort;
NET_LIST_ENTRY *Entry;
TCP_CB *Tcb;
ASSERT ((Addr != NULL) && (Port != 0));
LocalPort = HTONS (Port);
NET_LIST_FOR_EACH (Entry, &mTcpListenQue) {
Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
if ((EFI_IP4 (*Addr) == Tcb->LocalEnd.Ip) &&
(LocalPort == Tcb->LocalEnd.Port)) {
return TRUE;
}
}
NET_LIST_FOR_EACH (Entry, &mTcpRunQue) {
Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
if (((EFI_IP4 (*Addr) == Tcb->LocalEnd.Ip)) &&
(LocalPort == Tcb->LocalEnd.Port)) {
return TRUE;
}
}
return FALSE;
}
TCP_CB *
TcpLocateTcb (
IN TCP_PORTNO LocalPort,
IN UINT32 LocalIp,
IN TCP_PORTNO RemotePort,
IN UINT32 RemoteIp,
IN BOOLEAN Syn
)
/*++
Routine Description:
Locate the TCP_CB related to the socket pair.
Arguments:
LocalPort - The local port number.
LocalIp - The local IP address.
RemotePort - The remote port number.
RemoteIp - The remote IP address.
Syn - Whether to search the listen sockets,
if TRUE, the listen sockets are searched.
Returns:
Pointer to the related TCP_CB, if NULL no match is found.
--*/
{
TCP_PEER Local;
TCP_PEER Remote;
NET_LIST_ENTRY *Entry;
TCP_CB *Tcb;
Local.Port = LocalPort;
Local.Ip = LocalIp;
Remote.Port = RemotePort;
Remote.Ip = RemoteIp;
//
// First check for exact match.
//
NET_LIST_FOR_EACH (Entry, &mTcpRunQue) {
Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
if (TCP_PEER_EQUAL (&Remote, &Tcb->RemoteEnd) &&
TCP_PEER_EQUAL (&Local, &Tcb->LocalEnd)) {
NetListRemoveEntry (&Tcb->List);
NetListInsertHead (&mTcpRunQue, &Tcb->List);
return Tcb;
}
}
//
// Only check listen queue when SYN flag is on
//
if (Syn) {
return TcpLocateListenTcb (&Local, &Remote);
}
return NULL;
}
INTN
TcpInsertTcb (
IN TCP_CB *Tcb
)
/*++
Routine Description:
Insert a Tcb into the proper queue.
Arguments:
Tcb - Pointer to the TCP_CB to be inserted.
Returns:
0 - The Tcb is inserted successfully.
-1 - Error condition occurred.
--*/
{
NET_LIST_ENTRY *Entry;
NET_LIST_ENTRY *Head;
TCP_CB *Node;
TCP4_PROTO_DATA *TcpProto;
ASSERT (
Tcb &&
(
(Tcb->State == TCP_LISTEN) ||
(Tcb->State == TCP_SYN_SENT) ||
(Tcb->State == TCP_SYN_RCVD) ||
(Tcb->State == TCP_CLOSED)
)
);
if (Tcb->LocalEnd.Port == 0) {
return -1;
}
Head = &mTcpRunQue;
if (Tcb->State == TCP_LISTEN) {
Head = &mTcpListenQue;
}
//
// Check that Tcb isn't already on the list.
//
NET_LIST_FOR_EACH (Entry, Head) {
Node = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
if (TCP_PEER_EQUAL (&Tcb->LocalEnd, &Node->LocalEnd) &&
TCP_PEER_EQUAL (&Tcb->RemoteEnd, &Node->RemoteEnd)) {
return -1;
}
}
NetListInsertHead (Head, &Tcb->List);
TcpProto = (TCP4_PROTO_DATA *) Tcb->Sk->ProtoReserved;
TcpSetVariableData (TcpProto->TcpService);
return 0;
}
TCP_CB *
TcpCloneTcb (
IN TCP_CB *Tcb
)
/*++
Routine Description:
Clone a TCP_CB from Tcb.
Arguments:
Tcb - Pointer to the TCP_CB to be cloned.
Returns:
Pointer to the new cloned TCP_CB, if NULL error condition occurred.
--*/
{
TCP_CB *Clone;
Clone = NetAllocatePool (sizeof (TCP_CB));
if (Clone == NULL) {
return NULL;
}
NetCopyMem (Clone, Tcb, sizeof (TCP_CB));
//
// Increate the reference count of the shared IpInfo.
//
NET_GET_REF (Tcb->IpInfo);
NetListInit (&Clone->List);
NetListInit (&Clone->SndQue);
NetListInit (&Clone->RcvQue);
Clone->Sk = SockClone (Tcb->Sk);
if (Clone->Sk == NULL) {
TCP4_DEBUG_ERROR (("TcpCloneTcb: failed to clone a sock\n"));
NetFreePool (Clone);
return NULL;
}
((TCP4_PROTO_DATA *) (Clone->Sk->ProtoReserved))->TcpPcb = Clone;
return Clone;
}
TCP_SEQNO
TcpGetIss (
VOID
)
/*++
Routine Description:
Compute an ISS to be used by a new connection.
Arguments:
None
Returns:
The result ISS.
--*/
{
mTcpGlobalIss += 2048;
return mTcpGlobalIss;
}
UINT16
TcpGetRcvMss (
IN SOCKET *Sock
)
/*++
Routine Description:
Get the local mss.
Arguments:
None
Returns:
The mss size.
--*/
{
EFI_SIMPLE_NETWORK_MODE SnpMode;
TCP4_PROTO_DATA *TcpProto;
EFI_IP4_PROTOCOL *Ip;
ASSERT (Sock);
TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
Ip = TcpProto->TcpService->IpIo->Ip;
ASSERT (Ip);
Ip->GetModeData (Ip, NULL, NULL, &SnpMode);
return (UINT16) (SnpMode.MaxPacketSize - 40);
}
VOID
TcpSetState (
IN TCP_CB *Tcb,
IN UINT8 State
)
/*++
Routine Description:
Set the Tcb's state.
Arguments:
Tcb - Pointer to the TCP_CB of this TCP instance.
State - The state to be set.
Returns:
None
--*/
{
TCP4_DEBUG_TRACE (
("Tcb (%x) state %s --> %s\n",
Tcb,
mTcpStateName[Tcb->State],
mTcpStateName[State])
);
Tcb->State = State;
switch (State) {
case TCP_ESTABLISHED:
SockConnEstablished (Tcb->Sk);
break;
case TCP_CLOSED:
SockConnClosed (Tcb->Sk);
break;
}
}
UINT16
TcpChecksum (
IN NET_BUF *Nbuf,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?