1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030 |
- /** @file
- Misc support routines for TCP driver.
- (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
- Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "TcpMain.h"
- LIST_ENTRY mTcpRunQue = {
- &mTcpRunQue,
- &mTcpRunQue
- };
- LIST_ENTRY mTcpListenQue = {
- &mTcpListenQue,
- &mTcpListenQue
- };
- TCP_SEQNO mTcpGlobalIss = TCP_BASE_ISS;
- 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"
- };
- /**
- Initialize the Tcb local related members.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- **/
- VOID
- TcpInitTcbLocal (
- IN OUT TCP_CB *Tcb
- )
- {
- //
- // Compute the checksum of the fixed parts of pseudo header
- //
- if (Tcb->Sk->IpVersion == IP_VERSION_4) {
- Tcb->HeadSum = NetPseudoHeadChecksum (
- Tcb->LocalEnd.Ip.Addr[0],
- Tcb->RemoteEnd.Ip.Addr[0],
- 0x06,
- 0
- );
- } else {
- Tcb->HeadSum = NetIp6PseudoHeadChecksum (
- &Tcb->LocalEnd.Ip.v6,
- &Tcb->RemoteEnd.Ip.v6,
- 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);
- //
- // First window size is never scaled
- //
- Tcb->RcvWndScale = 0;
- Tcb->RetxmitSeqMax = 0;
- Tcb->ProbeTimerOn = FALSE;
- }
- /**
- Initialize the peer related members.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- @param[in] Seg Pointer to the segment that contains the peer's initial info.
- @param[in] Opt Pointer to the options announced by the peer.
- **/
- VOID
- TcpInitTcbPeer (
- IN OUT TCP_CB *Tcb,
- IN TCP_SEG *Seg,
- IN TCP_OPTION *Opt
- )
- {
- UINT16 RcvMss;
- ASSERT ((Tcb != NULL) && (Seg != NULL) && (Opt != NULL));
- 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 = (UINT16)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);
- Tcb->TsRecent = Opt->TSVal;
- //
- // 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;
- }
- }
- /**
- Check whether one IP address equals the other.
- @param[in] Ip1 Pointer to IP address to be checked.
- @param[in] Ip2 Pointer to IP address to be checked.
- @param[in] Version IP_VERSION_4 indicates the IP address is an IPv4 address,
- IP_VERSION_6 indicates the IP address is an IPv6 address.
- @retval TRUE Ip1 equals Ip2.
- @retval FALSE Ip1 does not equal Ip2.
- **/
- BOOLEAN
- TcpIsIpEqual (
- IN EFI_IP_ADDRESS *Ip1,
- IN EFI_IP_ADDRESS *Ip2,
- IN UINT8 Version
- )
- {
- ASSERT ((Version == IP_VERSION_4) || (Version == IP_VERSION_6));
- if (Version == IP_VERSION_4) {
- return (BOOLEAN)(Ip1->Addr[0] == Ip2->Addr[0]);
- } else {
- return (BOOLEAN)EFI_IP6_EQUAL (&Ip1->v6, &Ip2->v6);
- }
- }
- /**
- Check whether one IP address is filled with ZERO.
- @param[in] Ip Pointer to the IP address to be checked.
- @param[in] Version IP_VERSION_4 indicates the IP address is an IPv4 address,
- IP_VERSION_6 indicates the IP address is an IPv6 address.
- @retval TRUE Ip is all zero address.
- @retval FALSE Ip is not all zero address.
- **/
- BOOLEAN
- TcpIsIpZero (
- IN EFI_IP_ADDRESS *Ip,
- IN UINT8 Version
- )
- {
- ASSERT ((Version == IP_VERSION_4) || (Version == IP_VERSION_6));
- if (Version == IP_VERSION_4) {
- return (BOOLEAN)(Ip->Addr[0] == 0);
- } else {
- return (BOOLEAN)((Ip->Addr[0] == 0) && (Ip->Addr[1] == 0) &&
- (Ip->Addr[2] == 0) && (Ip->Addr[3] == 0));
- }
- }
- /**
- Locate a listen TCB that matchs the Local and Remote.
- @param[in] Local Pointer to the local (IP, Port).
- @param[in] Remote Pointer to the remote (IP, Port).
- @param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
- IP_VERSION_6 indicates TCP is running on IP6 stack.
- @return Pointer to the TCP_CB with the least number of wildcards,
- if NULL no match is found.
- **/
- TCP_CB *
- TcpLocateListenTcb (
- IN TCP_PEER *Local,
- IN TCP_PEER *Remote,
- IN UINT8 Version
- )
- {
- 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 ((Version != Node->Sk->IpVersion) ||
- (Local->Port != Node->LocalEnd.Port) ||
- !TCP_PEER_MATCH (Remote, &Node->RemoteEnd, Version) ||
- !TCP_PEER_MATCH (Local, &Node->LocalEnd, Version)
- )
- {
- continue;
- }
- //
- // Compute the number of wildcard
- //
- Cur = 0;
- if (TcpIsIpZero (&Node->RemoteEnd.Ip, Version)) {
- Cur++;
- }
- if (Node->RemoteEnd.Port == 0) {
- Cur++;
- }
- if (TcpIsIpZero (&Node->LocalEnd.Ip, Version)) {
- Cur++;
- }
- if (Cur < Last) {
- if (Cur == 0) {
- return Node;
- }
- Last = Cur;
- Match = Node;
- }
- }
- return Match;
- }
- /**
- Try to find one Tcb whose <Ip, Port> equals to <IN Addr, IN Port>.
- @param[in] Addr Pointer to the IP address needs to match.
- @param[in] Port The port number needs to match.
- @param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
- IP_VERSION_6 indicates TCP is running on IP6 stack.
- @retval TRUE The Tcb which matches the <Addr Port> pair exists.
- @retval FALSE Otherwise
- **/
- BOOLEAN
- TcpFindTcbByPeer (
- IN EFI_IP_ADDRESS *Addr,
- IN TCP_PORTNO Port,
- IN UINT8 Version
- )
- {
- TCP_PORTNO LocalPort;
- 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 ((Version == Tcb->Sk->IpVersion) &&
- TcpIsIpEqual (Addr, &Tcb->LocalEnd.Ip, Version) &&
- (LocalPort == Tcb->LocalEnd.Port)
- )
- {
- return TRUE;
- }
- }
- NET_LIST_FOR_EACH (Entry, &mTcpRunQue) {
- Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
- if ((Version == Tcb->Sk->IpVersion) &&
- TcpIsIpEqual (Addr, &Tcb->LocalEnd.Ip, Version) &&
- (LocalPort == Tcb->LocalEnd.Port)
- )
- {
- return TRUE;
- }
- }
- return FALSE;
- }
- /**
- Locate the TCP_CB related to the socket pair.
- @param[in] LocalPort The local port number.
- @param[in] LocalIp The local IP address.
- @param[in] RemotePort The remote port number.
- @param[in] RemoteIp The remote IP address.
- @param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
- IP_VERSION_6 indicates TCP is running on IP6 stack.
- @param[in] Syn If TRUE, the listen sockets are searched.
- @return Pointer to the related TCP_CB. If NULL, no match is found.
- **/
- TCP_CB *
- TcpLocateTcb (
- IN TCP_PORTNO LocalPort,
- IN EFI_IP_ADDRESS *LocalIp,
- IN TCP_PORTNO RemotePort,
- IN EFI_IP_ADDRESS *RemoteIp,
- IN UINT8 Version,
- IN BOOLEAN Syn
- )
- {
- TCP_PEER Local;
- TCP_PEER Remote;
- LIST_ENTRY *Entry;
- TCP_CB *Tcb;
- Local.Port = LocalPort;
- Remote.Port = RemotePort;
- CopyMem (&Local.Ip, LocalIp, sizeof (EFI_IP_ADDRESS));
- CopyMem (&Remote.Ip, RemoteIp, sizeof (EFI_IP_ADDRESS));
- //
- // First check for exact match.
- //
- NET_LIST_FOR_EACH (Entry, &mTcpRunQue) {
- Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
- if ((Version == Tcb->Sk->IpVersion) &&
- TCP_PEER_EQUAL (&Remote, &Tcb->RemoteEnd, Version) &&
- TCP_PEER_EQUAL (&Local, &Tcb->LocalEnd, Version)
- )
- {
- RemoveEntryList (&Tcb->List);
- InsertHeadList (&mTcpRunQue, &Tcb->List);
- return Tcb;
- }
- }
- //
- // Only check the listen queue when the SYN flag is on.
- //
- if (Syn) {
- return TcpLocateListenTcb (&Local, &Remote, Version);
- }
- return NULL;
- }
- /**
- Insert a Tcb into the proper queue.
- @param[in] Tcb Pointer to the TCP_CB to be inserted.
- @retval 0 The Tcb was inserted successfully.
- @retval -1 Error condition occurred.
- **/
- INTN
- TcpInsertTcb (
- IN TCP_CB *Tcb
- )
- {
- LIST_ENTRY *Entry;
- LIST_ENTRY *Head;
- TCP_CB *Node;
- ASSERT (
- (Tcb != NULL) &&
- (
- (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 the 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, Tcb->Sk->IpVersion) &&
- TCP_PEER_EQUAL (&Tcb->RemoteEnd, &Node->RemoteEnd, Tcb->Sk->IpVersion)
- )
- {
- return -1;
- }
- }
- InsertHeadList (Head, &Tcb->List);
- return 0;
- }
- /**
- Clone a TCP_CB from Tcb.
- @param[in] Tcb Pointer to the TCP_CB to be cloned.
- @return Pointer to the new cloned TCP_CB; if NULL, error condition occurred.
- **/
- TCP_CB *
- TcpCloneTcb (
- IN TCP_CB *Tcb
- )
- {
- TCP_CB *Clone;
- Clone = AllocateZeroPool (sizeof (TCP_CB));
- if (Clone == NULL) {
- return NULL;
- }
- CopyMem (Clone, Tcb, sizeof (TCP_CB));
- //
- // Increase the reference count of the shared IpInfo.
- //
- NET_GET_REF (Tcb->IpInfo);
- InitializeListHead (&Clone->List);
- InitializeListHead (&Clone->SndQue);
- InitializeListHead (&Clone->RcvQue);
- Clone->Sk = SockClone (Tcb->Sk);
- if (Clone->Sk == NULL) {
- DEBUG ((DEBUG_ERROR, "TcpCloneTcb: failed to clone a sock\n"));
- FreePool (Clone);
- return NULL;
- }
- ((TCP_PROTO_DATA *)(Clone->Sk->ProtoReserved))->TcpPcb = Clone;
- return Clone;
- }
- /**
- Compute an ISS to be used by a new connection.
- @return The resulting ISS.
- **/
- TCP_SEQNO
- TcpGetIss (
- VOID
- )
- {
- mTcpGlobalIss += TCP_ISS_INCREMENT_1;
- return mTcpGlobalIss;
- }
- /**
- Get the local mss.
- @param[in] Sock Pointer to the socket to get mss.
- @return The mss size.
- **/
- UINT16
- TcpGetRcvMss (
- IN SOCKET *Sock
- )
- {
- EFI_IP4_MODE_DATA Ip4Mode;
- EFI_IP6_MODE_DATA Ip6Mode;
- EFI_IP4_PROTOCOL *Ip4;
- EFI_IP6_PROTOCOL *Ip6;
- TCP_PROTO_DATA *TcpProto;
- ASSERT (Sock != NULL);
- ZeroMem (&Ip4Mode, sizeof (EFI_IP4_MODE_DATA));
- ZeroMem (&Ip6Mode, sizeof (EFI_IP6_MODE_DATA));
- TcpProto = (TCP_PROTO_DATA *)Sock->ProtoReserved;
- if (Sock->IpVersion == IP_VERSION_4) {
- Ip4 = TcpProto->TcpService->IpIo->Ip.Ip4;
- ASSERT (Ip4 != NULL);
- Ip4->GetModeData (Ip4, &Ip4Mode, NULL, NULL);
- return (UINT16)(Ip4Mode.MaxPacketSize - sizeof (TCP_HEAD));
- } else {
- Ip6 = TcpProto->TcpService->IpIo->Ip.Ip6;
- ASSERT (Ip6 != NULL);
- if (!EFI_ERROR (Ip6->GetModeData (Ip6, &Ip6Mode, NULL, NULL))) {
- if (Ip6Mode.AddressList != NULL) {
- FreePool (Ip6Mode.AddressList);
- }
- if (Ip6Mode.GroupTable != NULL) {
- FreePool (Ip6Mode.GroupTable);
- }
- if (Ip6Mode.RouteTable != NULL) {
- FreePool (Ip6Mode.RouteTable);
- }
- if (Ip6Mode.NeighborCache != NULL) {
- FreePool (Ip6Mode.NeighborCache);
- }
- if (Ip6Mode.PrefixTable != NULL) {
- FreePool (Ip6Mode.PrefixTable);
- }
- if (Ip6Mode.IcmpTypeList != NULL) {
- FreePool (Ip6Mode.IcmpTypeList);
- }
- }
- return (UINT16)(Ip6Mode.MaxPacketSize - sizeof (TCP_HEAD));
- }
- }
- /**
- Set the Tcb's state.
- @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
- @param[in] State The state to be set.
- **/
- VOID
- TcpSetState (
- IN TCP_CB *Tcb,
- IN UINT8 State
- )
- {
- ASSERT (Tcb->State < (sizeof (mTcpStateName) / sizeof (CHAR16 *)));
- ASSERT (State < (sizeof (mTcpStateName) / sizeof (CHAR16 *)));
- DEBUG (
- (DEBUG_NET,
- "Tcb (%p) state %s --> %s\n",
- Tcb,
- mTcpStateName[Tcb->State],
- mTcpStateName[State])
- );
- Tcb->State = State;
- switch (State) {
- case TCP_ESTABLISHED:
- SockConnEstablished (Tcb->Sk);
- if (Tcb->Parent != NULL) {
- //
- // A new connection is accepted by a listening socket. Install
- // the device path.
- //
- TcpInstallDevicePath (Tcb->Sk);
- }
- break;
- case TCP_CLOSED:
- SockConnClosed (Tcb->Sk);
- break;
- default:
- break;
- }
- }
- /**
- Compute the TCP segment's checksum.
- @param[in] Nbuf Pointer to the buffer that contains the TCP segment.
- @param[in] HeadSum The checksum value of the fixed part of pseudo header.
- @return The checksum value.
- **/
- UINT16
- TcpChecksum (
- IN NET_BUF *Nbuf,
- IN UINT16 HeadSum
- )
- {
- UINT16 Checksum;
- Checksum = NetbufChecksum (Nbuf);
- Checksum = NetAddChecksum (Checksum, HeadSum);
- Checksum = NetAddChecksum (
- Checksum,
- HTONS ((UINT16)Nbuf->TotalSize)
- );
- return (UINT16)(~Checksum);
- }
- /**
- Translate the information from the head of the received TCP
- segment Nbuf contents and fill it into a TCP_SEG structure.
- @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
- @param[in, out] Nbuf Pointer to the buffer contains the TCP segment.
- @return Pointer to the TCP_SEG that contains the translated TCP head information.
- **/
- TCP_SEG *
- TcpFormatNetbuf (
- IN TCP_CB *Tcb,
- IN OUT NET_BUF *Nbuf
- )
- {
- TCP_SEG *Seg;
- TCP_HEAD *Head;
- Seg = TCPSEG_NETBUF (Nbuf);
- Head = (TCP_HEAD *)NetbufGetByte (Nbuf, 0, NULL);
- ASSERT (Head != 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 the 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;
- }
- /**
- Initialize an active connection.
- @param[in, out] Tcb Pointer to the TCP_CB that wants to initiate a
- connection.
- **/
- VOID
- TcpOnAppConnect (
- IN OUT TCP_CB *Tcb
- )
- {
- TcpInitTcbLocal (Tcb);
- TcpSetState (Tcb, TCP_SYN_SENT);
- TcpSetTimer (Tcb, TCP_TIMER_CONNECT, Tcb->ConnectTimeout);
- TcpToSendData (Tcb, 1);
- }
- /**
- Initiate the connection close procedure, called when
- applications want to close the connection.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- **/
- VOID
- TcpOnAppClose (
- IN OUT TCP_CB *Tcb
- )
- {
- ASSERT (Tcb != NULL);
- if (!IsListEmpty (&Tcb->RcvQue) || (GET_RCV_DATASIZE (Tcb->Sk) != 0)) {
- DEBUG (
- (DEBUG_WARN,
- "TcpOnAppClose: connection reset because data is lost for TCB %p\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;
- default:
- break;
- }
- TcpToSendData (Tcb, 1);
- }
- /**
- Check whether the application's newly delivered data can be sent out.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- @retval 0 The data has been sent out successfully.
- @retval -1 The Tcb is not in a state that data is permitted to
- be sent out.
- **/
- INTN
- TcpOnAppSend (
- IN OUT TCP_CB *Tcb
- )
- {
- switch (Tcb->State) {
- case TCP_CLOSED:
- return -1;
- case TCP_LISTEN:
- return -1;
- case TCP_SYN_SENT:
- case TCP_SYN_RCVD:
- return 0;
- case TCP_ESTABLISHED:
- case TCP_CLOSE_WAIT:
- TcpToSendData (Tcb, 0);
- return 0;
- case TCP_FIN_WAIT_1:
- case TCP_FIN_WAIT_2:
- case TCP_CLOSING:
- case TCP_LAST_ACK:
- case TCP_TIME_WAIT:
- return -1;
- default:
- break;
- }
- return 0;
- }
- /**
- Application has consumed some data. Check whether
- to send a window update ack or a delayed ack.
- @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
- **/
- VOID
- TcpOnAppConsume (
- IN TCP_CB *Tcb
- )
- {
- UINT32 TcpOld;
- switch (Tcb->State) {
- case TCP_ESTABLISHED:
- TcpOld = TcpRcvWinOld (Tcb);
- if (TcpRcvWinNow (Tcb) > TcpOld) {
- if (TcpOld < Tcb->RcvMss) {
- DEBUG (
- (DEBUG_NET,
- "TcpOnAppConsume: send a window update for a window closed Tcb %p\n",
- Tcb)
- );
- TcpSendAck (Tcb);
- } else if (Tcb->DelayedAck == 0) {
- DEBUG (
- (DEBUG_NET,
- "TcpOnAppConsume: scheduled a delayed ACK to update window for Tcb %p\n",
- Tcb)
- );
- Tcb->DelayedAck = 1;
- }
- }
- break;
- default:
- break;
- }
- }
- /**
- Abort the connection by sending a reset segment. Called
- when the application wants to abort the connection.
- @param[in] Tcb Pointer to the TCP_CB of the TCP instance.
- **/
- VOID
- TcpOnAppAbort (
- IN TCP_CB *Tcb
- )
- {
- DEBUG (
- (DEBUG_WARN,
- "TcpOnAppAbort: connection reset issued by application for TCB %p\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;
- default:
- break;
- }
- TcpSetState (Tcb, TCP_CLOSED);
- }
- /**
- Reset the connection related with Tcb.
- @param[in] Tcb Pointer to the TCP_CB of the connection to be reset.
- **/
- VOID
- TcpResetConnection (
- IN TCP_CB *Tcb
- )
- {
- 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 = (UINT8)(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, Tcb->Sk->IpVersion);
- NetbufFree (Nbuf);
- }
- /**
- Install the device path protocol on the TCP instance.
- @param[in] Sock Pointer to the socket representing the TCP instance.
- @retval EFI_SUCCESS The device path protocol was installed.
- @retval other Failed to install the device path protocol.
- **/
- EFI_STATUS
- TcpInstallDevicePath (
- IN SOCKET *Sock
- )
- {
- TCP_PROTO_DATA *TcpProto;
- TCP_SERVICE_DATA *TcpService;
- TCP_CB *Tcb;
- IPv4_DEVICE_PATH Ip4DPathNode;
- IPv6_DEVICE_PATH Ip6DPathNode;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_STATUS Status;
- TCP_PORTNO LocalPort;
- TCP_PORTNO RemotePort;
- TcpProto = (TCP_PROTO_DATA *)Sock->ProtoReserved;
- TcpService = TcpProto->TcpService;
- Tcb = TcpProto->TcpPcb;
- LocalPort = NTOHS (Tcb->LocalEnd.Port);
- RemotePort = NTOHS (Tcb->RemoteEnd.Port);
- if (Sock->IpVersion == IP_VERSION_4) {
- NetLibCreateIPv4DPathNode (
- &Ip4DPathNode,
- TcpService->ControllerHandle,
- Tcb->LocalEnd.Ip.Addr[0],
- LocalPort,
- Tcb->RemoteEnd.Ip.Addr[0],
- RemotePort,
- EFI_IP_PROTO_TCP,
- Tcb->UseDefaultAddr
- );
- IP4_COPY_ADDRESS (&Ip4DPathNode.SubnetMask, &Tcb->SubnetMask);
- DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&Ip4DPathNode;
- } else {
- NetLibCreateIPv6DPathNode (
- &Ip6DPathNode,
- TcpService->ControllerHandle,
- &Tcb->LocalEnd.Ip.v6,
- LocalPort,
- &Tcb->RemoteEnd.Ip.v6,
- RemotePort,
- EFI_IP_PROTO_TCP
- );
- DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&Ip6DPathNode;
- }
- Sock->DevicePath = AppendDevicePathNode (Sock->ParentDevicePath, DevicePath);
- if (Sock->DevicePath == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- Status = gBS->InstallProtocolInterface (
- &Sock->SockHandle,
- &gEfiDevicePathProtocolGuid,
- EFI_NATIVE_INTERFACE,
- Sock->DevicePath
- );
- if (EFI_ERROR (Status)) {
- FreePool (Sock->DevicePath);
- Sock->DevicePath = NULL;
- }
- return Status;
- }
|