tcp4misc.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,206 行 · 第 1/2 页
C
1,206 行
IN UINT16 HeadSum
)
/*++
Routine Description:
Compute the TCP segment's checksum.
Arguments:
Nbuf - Pointer to the buffer that contains the TCP segment.
HeadSum - The checksum value of the fixed part of pseudo header.
Returns:
The checksum value.
--*/
{
UINT16 Checksum;
Checksum = NetbufChecksum (Nbuf);
Checksum = NetAddChecksum (Checksum, HeadSum);
Checksum = NetAddChecksum (
Checksum,
HTONS ((UINT16) Nbuf->TotalSize)
);
return ~Checksum;
}
TCP_SEG *
TcpFormatNetbuf (
IN TCP_CB *Tcb,
IN NET_BUF *Nbuf
)
/*++
Routine Description:
Translate the information from the head of the received TCP
segment Nbuf contains and fill it into a TCP_SEG structure.
Arguments:
Tcb - Pointer to the TCP_CB of this TCP instance.
Nbuf - Pointer to the buffer contains the TCP segment.
Returns:
Pointer to the TCP_SEG that contains the translated TCP head information.
--*/
{
TCP_SEG *Seg;
TCP_HEAD *Head;
Seg = TCPSEG_NETBUF (Nbuf);
Head = (TCP_HEAD *) NetbufGetByte (Nbuf, 0, NULL);
Nbuf->Tcp = Head;
Seg->Seq = NTOHL (Head->Seq);
Seg->Ack = NTOHL (Head->Ack);
Seg->End = Seg->Seq + (Nbuf->TotalSize - (Head->HeadLen << 2));
Seg->Urg = NTOHS (Head->Urg);
Seg->Wnd = (NTOHS (Head->Wnd) << Tcb->SndWndScale);
Seg->Flag = Head->Flag;
//
// SYN and FIN flag occupy one sequence space each.
//
if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
//
// RFC requires that initial window not be scaled
//
Seg->Wnd = NTOHS (Head->Wnd);
Seg->End++;
}
if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) {
Seg->End++;
}
return Seg;
}
VOID
TcpResetConnection (
IN TCP_CB *Tcb
)
/*++
Routine Description:
Reset the connection related with Tcb.
Arguments:
Tcb - Pointer to the TCP_CB of the connection to be reset.
Returns:
None
--*/
{
NET_BUF *Nbuf;
TCP_HEAD *Nhead;
Nbuf = NetbufAlloc (TCP_MAX_HEAD);
if (Nbuf == NULL) {
return ;
}
Nhead = (TCP_HEAD *) NetbufAllocSpace (
Nbuf,
sizeof (TCP_HEAD),
NET_BUF_TAIL
);
ASSERT (Nhead != NULL);
Nbuf->Tcp = Nhead;
Nhead->Flag = TCP_FLG_RST;
Nhead->Seq = HTONL (Tcb->SndNxt);
Nhead->Ack = HTONL (Tcb->RcvNxt);
Nhead->SrcPort = Tcb->LocalEnd.Port;
Nhead->DstPort = Tcb->RemoteEnd.Port;
Nhead->HeadLen = (sizeof (TCP_HEAD) >> 2);
Nhead->Res = 0;
Nhead->Wnd = HTONS (0xFFFF);
Nhead->Checksum = 0;
Nhead->Urg = 0;
Nhead->Checksum = TcpChecksum (Nbuf, Tcb->HeadSum);
TcpSendIpPacket (Tcb, Nbuf, Tcb->LocalEnd.Ip, Tcb->RemoteEnd.Ip);
NetbufFree (Nbuf);
}
VOID
TcpOnAppConnect (
IN TCP_CB *Tcb
)
/*++
Routine Description:
Initialize an active connection,
Arguments:
Tcb - Pointer to the TCP_CB that wants to initiate
a connection.
Returns:
None
--*/
{
TcpInitTcbLocal (Tcb);
TcpSetState (Tcb, TCP_SYN_SENT);
TcpSetTimer (Tcb, TCP_TIMER_CONNECT, Tcb->ConnectTimeout);
TcpToSendData (Tcb, 1);
}
VOID
TcpOnAppClose (
IN TCP_CB *Tcb
)
/*++
Routine Description:
Initiate the connection close procedure, called when
applications want to close the connection.
Arguments:
Tcb - Pointer to the TCP_CB of this TCP instance.
Returns:
None.
--*/
{
ASSERT (Tcb);
if (!NetListIsEmpty (&Tcb->RcvQue) || GET_RCV_DATASIZE (Tcb->Sk)) {
TCP4_DEBUG_WARN (("TcpOnAppClose: connection reset "
"because data is lost for TCB %x\n", Tcb));
TcpResetConnection (Tcb);
TcpClose (Tcb);
return;
}
switch (Tcb->State) {
case TCP_CLOSED:
case TCP_LISTEN:
case TCP_SYN_SENT:
TcpSetState (Tcb, TCP_CLOSED);
break;
case TCP_SYN_RCVD:
case TCP_ESTABLISHED:
TcpSetState (Tcb, TCP_FIN_WAIT_1);
break;
case TCP_CLOSE_WAIT:
TcpSetState (Tcb, TCP_LAST_ACK);
break;
}
TcpToSendData (Tcb, 1);
}
INTN
TcpOnAppSend (
IN TCP_CB *Tcb
)
/*++
Routine Description:
Check whether the application's newly delivered data
can be sent out.
Arguments:
Tcb - Pointer to the TCP_CB of this TCP instance.
Returns:
0 - Whether the data is sent out or is buffered for
further sending.
-1 - The Tcb is not in a state that data is permitted
to be sent out.
--*/
{
switch (Tcb->State) {
case TCP_CLOSED:
return -1;
break;
case TCP_LISTEN:
return -1;
break;
case TCP_SYN_SENT:
case TCP_SYN_RCVD:
return 0;
break;
case TCP_ESTABLISHED:
case TCP_CLOSE_WAIT:
TcpToSendData (Tcb, 0);
return 0;
break;
case TCP_FIN_WAIT_1:
case TCP_FIN_WAIT_2:
case TCP_CLOSING:
case TCP_LAST_ACK:
case TCP_TIME_WAIT:
return -1;
break;
}
return 0;
}
INTN
TcpOnAppConsume (
IN TCP_CB *Tcb
)
/*++
Routine Description:
Application has consumed some data, check whether
to send a window updata ack or a delayed ack.
Arguments:
Tcb - Pointer to the TCP_CB of this TCP instance.
Returns:
--*/
{
switch (Tcb->State) {
case TCP_CLOSED:
return -1;
break;
case TCP_LISTEN:
return -1;
break;
case TCP_SYN_SENT:
case TCP_SYN_RCVD:
return 0;
break;
case TCP_ESTABLISHED:
if (TcpRcvWinNow (Tcb) > TcpRcvWinOld (Tcb)) {
if (TcpRcvWinOld (Tcb) < Tcb->RcvMss) {
TCP4_DEBUG_TRACE (("TcpOnAppConsume: send a window"
" update for a window closed Tcb(%x)\n", Tcb));
TcpSendAck (Tcb);
} else if (Tcb->DelayedAck == 0) {
TCP4_DEBUG_TRACE (("TcpOnAppConsume: scheduled a delayed"
" ACK to update window for Tcb(%x)\n", Tcb));
Tcb->DelayedAck = 1;
}
}
break;
case TCP_CLOSE_WAIT:
return 0;
break;
case TCP_FIN_WAIT_1:
case TCP_FIN_WAIT_2:
case TCP_CLOSING:
case TCP_LAST_ACK:
case TCP_TIME_WAIT:
return -1;
break;
}
return -1;
}
VOID
TcpOnAppAbort (
IN TCP_CB *Tcb
)
/*++
Routine Description:
Abort the connection by sending a reset segment, called
when the application wants to abort the connection.
Arguments:
Tcb - Pointer to the TCP_CB of the TCP instance.
Returns:
None.
--*/
{
TCP4_DEBUG_WARN (("TcpOnAppAbort: connection reset "
"issued by application for TCB %x\n", Tcb));
switch (Tcb->State) {
case TCP_SYN_RCVD:
case TCP_ESTABLISHED:
case TCP_FIN_WAIT_1:
case TCP_FIN_WAIT_2:
case TCP_CLOSE_WAIT:
TcpResetConnection (Tcb);
break;
}
TcpSetState (Tcb, TCP_CLOSED);
}
EFI_STATUS
TcpSetVariableData (
IN TCP4_SERVICE_DATA *Tcp4Service
)
/*++
Routine Description:
Set the Tdp4 variable data.
Arguments:
Tcp4Service - Tcp4 service data.
Returns:
EFI_OUT_OF_RESOURCES - There are not enough resources to set the variable.
other - Set variable failed.
--*/
{
UINT32 NumConfiguredInstance;
NET_LIST_ENTRY *Entry;
TCP_CB *TcpPcb;
TCP4_PROTO_DATA *TcpProto;
UINTN VariableDataSize;
EFI_TCP4_VARIABLE_DATA *Tcp4VariableData;
EFI_TCP4_SERVICE_POINT *Tcp4ServicePoint;
CHAR16 *NewMacString;
EFI_STATUS Status;
NumConfiguredInstance = 0;
//
// Go through the running queue to count the instances.
//
NET_LIST_FOR_EACH (Entry, &mTcpRunQue) {
TcpPcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
TcpProto = (TCP4_PROTO_DATA *) TcpPcb->Sk->ProtoReserved;
if (TcpProto->TcpService == Tcp4Service) {
//
// This tcp instance belongs to the Tcp4Service.
//
NumConfiguredInstance++;
}
}
//
// Go through the listening queue to count the instances.
//
NET_LIST_FOR_EACH (Entry, &mTcpListenQue) {
TcpPcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
TcpProto = (TCP4_PROTO_DATA *) TcpPcb->Sk->ProtoReserved;
if (TcpProto->TcpService == Tcp4Service) {
//
// This tcp instance belongs to the Tcp4Service.
//
NumConfiguredInstance++;
}
}
//
// Calculate the size of the Tcp4VariableData. As there may be no Tcp4 child,
// we should add extra buffer for the service points only if the number of configured
// children is more than 1.
//
VariableDataSize = sizeof (EFI_TCP4_VARIABLE_DATA);
if (NumConfiguredInstance > 1) {
VariableDataSize += sizeof (EFI_TCP4_SERVICE_POINT) * (NumConfiguredInstance - 1);
}
Tcp4VariableData = NetAllocatePool (VariableDataSize);
if (Tcp4VariableData == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Tcp4VariableData->DriverHandle = Tcp4Service->DriverBindingHandle;
Tcp4VariableData->ServiceCount = NumConfiguredInstance;
Tcp4ServicePoint = &Tcp4VariableData->Services[0];
//
// Go through the running queue to fill the service points.
//
NET_LIST_FOR_EACH (Entry, &mTcpRunQue) {
TcpPcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
TcpProto = (TCP4_PROTO_DATA *) TcpPcb->Sk->ProtoReserved;
if (TcpProto->TcpService == Tcp4Service) {
//
// This tcp instance belongs to the Tcp4Service.
//
Tcp4ServicePoint->InstanceHandle = TcpPcb->Sk->SockHandle;
EFI_IP4 (Tcp4ServicePoint->LocalAddress) = TcpPcb->LocalEnd.Ip;
Tcp4ServicePoint->LocalPort = NTOHS (TcpPcb->LocalEnd.Port);
EFI_IP4 (Tcp4ServicePoint->RemoteAddress) = TcpPcb->RemoteEnd.Ip;
Tcp4ServicePoint->RemotePort = NTOHS (TcpPcb->RemoteEnd.Port);
Tcp4ServicePoint++;
}
}
//
// Go through the listening queue to fill the service points.
//
NET_LIST_FOR_EACH (Entry, &mTcpListenQue) {
TcpPcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
TcpProto = (TCP4_PROTO_DATA *) TcpPcb->Sk->ProtoReserved;
if (TcpProto->TcpService == Tcp4Service) {
//
// This tcp instance belongs to the Tcp4Service.
//
Tcp4ServicePoint->InstanceHandle = TcpPcb->Sk->SockHandle;
EFI_IP4 (Tcp4ServicePoint->LocalAddress) = TcpPcb->LocalEnd.Ip;
Tcp4ServicePoint->LocalPort = NTOHS (TcpPcb->LocalEnd.Port);
EFI_IP4 (Tcp4ServicePoint->RemoteAddress) = TcpPcb->RemoteEnd.Ip;
Tcp4ServicePoint->RemotePort = NTOHS (TcpPcb->RemoteEnd.Port);
Tcp4ServicePoint++;
}
}
//
// Get the mac string.
//
Status = NetLibGetMacString (
Tcp4Service->ControllerHandle,
Tcp4Service->DriverBindingHandle,
&NewMacString
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
if (Tcp4Service->MacString != NULL) {
//
// The variable is set already, we're going to update it.
//
if (EfiStrCmp (Tcp4Service->MacString, NewMacString) != 0) {
//
// The mac address is changed, delete the previous variable first.
//
gRT->SetVariable (
Tcp4Service->MacString,
&gEfiTcp4ServiceBindingProtocolGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS,
0,
NULL
);
}
NetFreePool (Tcp4Service->MacString);
}
Tcp4Service->MacString = NewMacString;
Status = gRT->SetVariable (
Tcp4Service->MacString,
&gEfiTcp4ServiceBindingProtocolGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS,
VariableDataSize,
(VOID *) Tcp4VariableData
);
ON_ERROR:
NetFreePool (Tcp4VariableData);
return Status;
}
VOID
TcpClearVariableData (
IN TCP4_SERVICE_DATA *Tcp4Service
)
/*++
Routine Description:
Clear the variable and free the resource.
Arguments:
Tcp4Service - Tcp4 service data.
Returns:
None.
--*/
{
ASSERT (Tcp4Service->MacString != NULL);
gRT->SetVariable (
Tcp4Service->MacString,
&gEfiTcp4ServiceBindingProtocolGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS,
0,
NULL
);
NetFreePool (Tcp4Service->MacString);
Tcp4Service->MacString = NULL;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?