tcp4input.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,546 行 · 第 1/3 页
C
1,546 行
//
// Second step: Check the RST
//
if (TCP_FLG_ON (Seg->Flag, TCP_FLG_RST)) {
TCP4_DEBUG_WARN (("TcpInput: connection reset for TCB %x\n", Tcb));
if (Tcb->State == TCP_SYN_RCVD) {
SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_REFUSED);
//
// This TCB comes from either a LISTEN TCB,
// or active open TCB with simultanous open.
// Do NOT signal user CONNECTION refused
// if it comes from a LISTEN TCB.
//
} else if ((Tcb->State == TCP_ESTABLISHED) ||
(Tcb->State == TCP_FIN_WAIT_1) ||
(Tcb->State == TCP_FIN_WAIT_2) ||
(Tcb->State == TCP_CLOSE_WAIT)
) {
SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_RESET);
} else {
//
// TODO: set socket error to CLOSED
//
}
goto DROP_CONNECTION;
}
//
// Trim the data and flags.
//
TcpTrimInWnd (Tcb, Nbuf);
//
// Third step: Check security and precedence, Ignored
//
//
// Fourth step: Check the SYN bit.
//
if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
TCP4_DEBUG_WARN (("TcpInput: connection reset "
"because received extra SYN for TCB %x\n", Tcb));
SOCK_ERROR (Tcb->Sk, EFI_CONNECTION_RESET);
goto RESET_THEN_DROP;
}
//
// Fifth step: Check the ACK
//
if (!TCP_FLG_ON (Seg->Flag, TCP_FLG_ACK)) {
TCP4_DEBUG_WARN (("TcpInput: segment discard because"
" of no ACK for connected TCB %x\n", Tcb));
goto DISCARD;
}
if (Tcb->State == TCP_SYN_RCVD) {
if (TCP_SEQ_LT (Tcb->SndUna, Seg->Ack) &&
TCP_SEQ_LEQ (Seg->Ack, Tcb->SndNxt)) {
Tcb->SndWnd = Seg->Wnd;
Tcb->SndWndMax = NET_MAX (Tcb->SndWnd, Tcb->SndWndMax);
Tcb->SndWl1 = Seg->Seq;
Tcb->SndWl2 = Seg->Ack;
TcpSetState (Tcb, TCP_ESTABLISHED);
TcpClearTimer (Tcb, TCP_TIMER_CONNECT);
TcpDeliverData (Tcb);
TCP4_DEBUG_TRACE (("TcpInput: connection established "
" for TCB %x in SYN_RCVD\n", Tcb));
//
// Continue the process as ESTABLISHED state
//
} else {
TCP4_DEBUG_WARN (("TcpInput: send reset because of"
" wrong ACK for TCB %x in SYN_RCVD\n", Tcb));
goto SEND_RESET;
}
}
if (TCP_SEQ_LT (Seg->Ack, Tcb->SndUna)) {
TCP4_DEBUG_WARN (("TcpInput: ignore the out-of-data"
" ACK for connected TCB %x\n", Tcb));
goto StepSix;
} else if (TCP_SEQ_GT (Seg->Ack, Tcb->SndNxt)) {
TCP4_DEBUG_WARN (("TcpInput: discard segment for "
"future ACK for connected TCB %x\n", Tcb));
TcpSendAck (Tcb);
goto DISCARD;
}
//
// From now on: SND.UNA <= SEG.ACK <= SND.NXT.
//
if (TCP_FLG_ON (Option.Flag, TCP_OPTION_RCVD_TS)) {
//
// update TsRecent as specified in page 16 RFC1323.
// RcvWl2 equals to the variable "LastAckSent"
// defined there.
//
if (TCP_SEQ_LEQ (Seg->Seq, Tcb->RcvWl2) &&
TCP_SEQ_LT (Tcb->RcvWl2, Seg->End)) {
Tcb->TsRecent = Option.TSVal;
Tcb->TsRecentAge = mTcpTick;
}
TcpComputeRtt (Tcb, TCP_SUB_TIME (mTcpTick, Option.TSEcr));
} else if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) {
ASSERT (Tcb->CongestState == TCP_CONGEST_OPEN);
TcpComputeRtt (Tcb, Tcb->RttMeasure);
TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);
}
if (Seg->Ack == Tcb->SndNxt) {
TcpClearTimer (Tcb, TCP_TIMER_REXMIT);
} else {
TcpSetTimer (Tcb, TCP_TIMER_REXMIT, Tcb->Rto);
}
//
// Count duplicate acks.
//
if ((Seg->Ack == Tcb->SndUna) &&
(Tcb->SndUna != Tcb->SndNxt) &&
(Seg->Wnd == Tcb->SndWnd) &&
(0 == Len)) {
Tcb->DupAck++;
} else {
Tcb->DupAck = 0;
}
//
// Congestion avoidance, fast recovery and fast retransmission.
//
if (((Tcb->CongestState == TCP_CONGEST_OPEN) && (Tcb->DupAck < 3)) ||
(Tcb->CongestState == TCP_CONGEST_LOSS)) {
if (TCP_SEQ_GT (Seg->Ack, Tcb->SndUna)) {
if (Tcb->CWnd < Tcb->Ssthresh) {
Tcb->CWnd += Tcb->SndMss;
} else {
Tcb->CWnd += NET_MAX (Tcb->SndMss * Tcb->SndMss / Tcb->CWnd, 1);
}
Tcb->CWnd = NET_MIN (Tcb->CWnd, TCP_MAX_WIN << Tcb->SndWndScale);
}
if (Tcb->CongestState == TCP_CONGEST_LOSS) {
TcpFastLossRecover (Tcb, Seg);
}
} else {
TcpFastRecover (Tcb, Seg);
}
if (TCP_SEQ_GT (Seg->Ack, Tcb->SndUna)) {
TcpAdjustSndQue (Tcb, Seg->Ack);
Tcb->SndUna = Seg->Ack;
if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_URG) &&
(TCP_SEQ_LT (Tcb->SndUp, Seg->Ack))) {
TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_URG);
}
}
//
// Update window info
//
if (TCP_SEQ_LT (Tcb->SndWl1, Seg->Seq) ||
((Tcb->SndWl1 == Seg->Seq) && TCP_SEQ_LEQ (Tcb->SndWl2, Seg->Ack))) {
Right = Seg->Ack + Seg->Wnd;
if (TCP_SEQ_LT (Right, Tcb->SndWl2 + Tcb->SndWnd)) {
if ((Tcb->SndWl1 == Seg->Seq) &&
(Tcb->SndWl2 == Seg->Ack) &&
(Len == 0)) {
goto NO_UPDATE;
}
TCP4_DEBUG_WARN (("TcpInput: peer shrinks the"
" window for connected TCB %x\n", Tcb));
if ((Tcb->CongestState == TCP_CONGEST_RECOVER) &&
(TCP_SEQ_LT (Right, Tcb->Recover))) {
Tcb->Recover = Right;
}
if ((Tcb->CongestState == TCP_CONGEST_LOSS) &&
(TCP_SEQ_LT (Right, Tcb->LossRecover))) {
Tcb->LossRecover = Right;
}
if (TCP_SEQ_LT (Right, Tcb->SndNxt)) {
Tcb->SndNxt = Right;
if (Right == Tcb->SndUna) {
TcpClearTimer (Tcb, TCP_TIMER_REXMIT);
TcpSetProbeTimer (Tcb);
}
}
}
Tcb->SndWnd = Seg->Wnd;
Tcb->SndWndMax = NET_MAX (Tcb->SndWnd, Tcb->SndWndMax);
Tcb->SndWl1 = Seg->Seq;
Tcb->SndWl2 = Seg->Ack;
}
NO_UPDATE:
if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT) &&
(Tcb->SndUna == Tcb->SndNxt)) {
TCP4_DEBUG_TRACE (("TcpInput: local FIN is ACKed by"
" peer for connected TCB %x\n", Tcb));
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED);
}
//
// Transit the state if proper.
//
switch (Tcb->State) {
case TCP_FIN_WAIT_1:
if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) {
TcpSetState (Tcb, TCP_FIN_WAIT_2);
TcpClearAllTimer (Tcb);
TcpSetTimer (Tcb, TCP_TIMER_FINWAIT2, Tcb->FinWait2Timeout);
}
case TCP_FIN_WAIT_2:
break;
case TCP_CLOSE_WAIT:
break;
case TCP_CLOSING:
if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) {
TcpSetState (Tcb, TCP_TIME_WAIT);
TcpClearAllTimer (Tcb);
if (Tcb->TimeWaitTimeout != 0) {
TcpSetTimer (Tcb, TCP_TIMER_2MSL, Tcb->TimeWaitTimeout);
} else {
TCP4_DEBUG_WARN (("Connection closed immediately "
"because app disables TIME_WAIT timer for %x\n", Tcb));
TcpClose (Tcb);
}
}
break;
case TCP_LAST_ACK:
if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_ACKED)) {
TcpSetState (Tcb, TCP_CLOSED);
}
break;
case TCP_TIME_WAIT:
TcpSendAck (Tcb);
if (Tcb->TimeWaitTimeout != 0) {
TcpSetTimer (Tcb, TCP_TIMER_2MSL, Tcb->TimeWaitTimeout);
} else {
TCP4_DEBUG_WARN (("Connection closed immediately "
"because app disables TIME_WAIT timer for %x\n", Tcb));
TcpClose (Tcb);
}
break;
}
//
// Sixth step: Check the URG bit.update the Urg point
// if in TCP_CAN_RECV, otherwise, leave the RcvUp intact.
//
StepSix:
Tcb->Idle = 0;
TcpSetKeepaliveTimer (Tcb);
if (TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_PROBE)) {
TcpClearTimer (Tcb, TCP_TIMER_PROBE);
}
if (TCP_FLG_ON (Seg->Flag, TCP_FLG_URG) &&
!TCP_FIN_RCVD (Tcb->State)) {
TCP4_DEBUG_TRACE (("TcpInput: received urgent data "
"from peer for connected TCB %x\n", Tcb));
Urg = Seg->Seq + Seg->Urg;
if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_URG) &&
TCP_SEQ_GT (Urg, Tcb->RcvUp)) {
Tcb->RcvUp = Urg;
} else {
Tcb->RcvUp = Urg;
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RCVD_URG);
}
}
//
// Seventh step: Process the segment data
//
if (Seg->End != Seg->Seq) {
if (TCP_FIN_RCVD (Tcb->State)) {
TCP4_DEBUG_WARN (("TcpInput: connection reset because"
" data is lost for connected TCB %x\n", Tcb));
goto RESET_THEN_DROP;
}
if (TCP_LOCAL_CLOSED (Tcb->State) && (Nbuf->TotalSize != 0)) {
TCP4_DEBUG_WARN (("TcpInput: connection reset because"
" data is lost for connected TCB %x\n", Tcb));
goto RESET_THEN_DROP;
}
TcpQueueData (Tcb, Nbuf);
if (TcpDeliverData (Tcb) == -1) {
goto RESET_THEN_DROP;
}
if (!NetListIsEmpty (&Tcb->RcvQue)) {
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);
}
}
//
// Eighth step: check the FIN.
// This step is moved to TcpDeliverData. FIN will be
// processed in sequence there. Check the comments in
// the beginning of the file header for information.
//
//
// Tcb is a new child of the listening Parent,
// commit it.
//
if (Parent) {
Tcb->Parent = Parent;
TcpInsertTcb (Tcb);
}
if ((Tcb->State != TCP_CLOSED) &&
(!TcpToSendData (Tcb, 0)) &&
(TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW) || Nbuf->TotalSize)) {
TcpToSendAck (Tcb);
}
NetbufFree (Nbuf);
return 0;
RESET_THEN_DROP:
TcpSendReset (Tcb, Head, Len, Dst, Src);
DROP_CONNECTION:
ASSERT (Tcb && Tcb->Sk);
NetbufFree (Nbuf);
TcpClose (Tcb);
return -1;
SEND_RESET:
TcpSendReset (Tcb, Head, Len, Dst, Src);
DISCARD:
//
// Tcb is a child of Parent, and it doesn't survive
//
TCP4_DEBUG_WARN (("Tcp4Input: Discard a packet\n"));
NetbufFree (Nbuf);
if (Parent && Tcb) {
ASSERT (Tcb->Sk);
TcpClose (Tcb);
}
return 0;
}
VOID
TcpIcmpInput (
IN NET_BUF *Nbuf,
IN ICMP_ERROR IcmpErr,
IN UINT32 Src,
IN UINT32 Dst
)
/*++
Routine Description:
Process the received ICMP error messages for TCP.
Arguments:
Nbuf - Buffer that contains part of the TCP segment without IP header
truncated from the ICMP error packet.
IcmpErr - The ICMP error code interpreted from ICMP error packet.
Src - Source address of the ICMP error message.
Dst - Destination address of the ICMP error message.
Returns:
None.
--*/
{
TCP_HEAD *Head;
TCP_CB *Tcb;
TCP_SEQNO Seq;
Head = (TCP_HEAD *) NetbufGetByte (Nbuf, 0, NULL);
Tcb = TcpLocateTcb (
Head->DstPort,
Dst,
Head->SrcPort,
Src,
FALSE
);
if (Tcb == NULL || Tcb->State == TCP_CLOSED) {
goto CLEAN_EXIT;
}
//
// Validate the sequence number.
//
Seq = NTOHL (Head->Seq);
if (!(TCP_SEQ_LEQ (Tcb->SndUna, Seq) && TCP_SEQ_LT (Seq, Tcb->SndNxt))) {
goto CLEAN_EXIT;
}
if (mIcmpErrMap[IcmpErr].Notify) {
SOCK_ERROR (Tcb->Sk, mIcmpErrMap[IcmpErr].Error);
}
if (mIcmpErrMap[IcmpErr].IsHard) {
TcpClose (Tcb);
}
CLEAN_EXIT:
NetbufFree (Nbuf);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?