2 Misc support routines for tcp.
4 Copyright (c) 2005 - 2009, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php<BR>
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include <Library/DevicePathLib.h>
20 LIST_ENTRY mTcpRunQue
= {
25 LIST_ENTRY mTcpListenQue
= {
30 TCP_SEQNO mTcpGlobalIss
= 0x4d7e980b;
32 CHAR16
*mTcpStateName
[] = {
48 Initialize the Tcb local related members.
50 @param Tcb Pointer to the TCP_CB of this TCP instance.
59 // Compute the checksum of the fixed parts of pseudo header
61 Tcb
->HeadSum
= NetPseudoHeadChecksum (
68 Tcb
->Iss
= TcpGetIss ();
69 Tcb
->SndUna
= Tcb
->Iss
;
70 Tcb
->SndNxt
= Tcb
->Iss
;
72 Tcb
->SndWl2
= Tcb
->Iss
;
75 Tcb
->RcvWnd
= GET_RCV_BUFFSIZE (Tcb
->Sk
);
78 // First window size is never scaled
85 Initialize the peer related members.
87 @param Tcb Pointer to the TCP_CB of this TCP instance.
88 @param Seg Pointer to the segment that contains the peer's
90 @param Opt Pointer to the options announced by the peer.
102 ASSERT ((Tcb
!= NULL
) && (Seg
!= NULL
) && (Opt
!= NULL
));
103 ASSERT (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_SYN
));
105 Tcb
->SndWnd
= Seg
->Wnd
;
106 Tcb
->SndWndMax
= Tcb
->SndWnd
;
107 Tcb
->SndWl1
= Seg
->Seq
;
109 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_ACK
)) {
110 Tcb
->SndWl2
= Seg
->Ack
;
112 Tcb
->SndWl2
= Tcb
->Iss
+ 1;
115 if (TCP_FLG_ON (Opt
->Flag
, TCP_OPTION_RCVD_MSS
)) {
116 Tcb
->SndMss
= (UINT16
) MAX (64, Opt
->Mss
);
118 RcvMss
= TcpGetRcvMss (Tcb
->Sk
);
119 if (Tcb
->SndMss
> RcvMss
) {
120 Tcb
->SndMss
= RcvMss
;
125 // One end doesn't support MSS option, use default.
130 Tcb
->CWnd
= Tcb
->SndMss
;
133 Tcb
->RcvNxt
= Tcb
->Irs
+ 1;
135 Tcb
->RcvWl2
= Tcb
->RcvNxt
;
137 if (TCP_FLG_ON (Opt
->Flag
, TCP_OPTION_RCVD_WS
) &&
138 !TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_WS
)) {
140 Tcb
->SndWndScale
= Opt
->WndScale
;
142 Tcb
->RcvWndScale
= TcpComputeScale (Tcb
);
143 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_RCVD_WS
);
147 // One end doesn't support window scale option. use zero.
149 Tcb
->RcvWndScale
= 0;
152 if (TCP_FLG_ON (Opt
->Flag
, TCP_OPTION_RCVD_TS
) &&
153 !TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_TS
)) {
155 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_SND_TS
);
156 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_RCVD_TS
);
159 // Compute the effective SndMss per RFC1122
160 // section 4.2.2.6. If timestamp option is
161 // enabled, it will always occupy 12 bytes.
163 Tcb
->SndMss
-= TCP_OPTION_TS_ALIGNED_LEN
;
169 Locate a listen TCB that matchs the Local and Remote.
171 @param Local Pointer to the local (IP, Port).
172 @param Remote Pointer to the remote (IP, Port).
174 @return Pointer to the TCP_CB with the least number of wildcard,
175 if NULL no match is found.
193 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
194 Node
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
196 if ((Local
->Port
!= Node
->LocalEnd
.Port
) ||
197 !TCP_PEER_MATCH (Remote
, &Node
->RemoteEnd
) ||
198 !TCP_PEER_MATCH (Local
, &Node
->LocalEnd
)) {
204 // Compute the number of wildcard
207 if (Node
->RemoteEnd
.Ip
== 0) {
211 if (Node
->RemoteEnd
.Port
== 0) {
215 if (Node
->LocalEnd
.Ip
== 0) {
234 Try to find one Tcb whose <Ip, Port> equals to <IN Addr, IN Port>.
236 @param Addr Pointer to the IP address needs to match.
237 @param Port The port number needs to match.
239 @return The Tcb which matches the <Addr Port> paire exists or not.
244 IN EFI_IPv4_ADDRESS
*Addr
,
248 TCP_PORTNO LocalPort
;
252 ASSERT ((Addr
!= NULL
) && (Port
!= 0));
254 LocalPort
= HTONS (Port
);
256 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
257 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
259 if (EFI_IP4_EQUAL (Addr
, &Tcb
->LocalEnd
.Ip
) &&
260 (LocalPort
== Tcb
->LocalEnd
.Port
)) {
266 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
267 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
269 if (EFI_IP4_EQUAL (Addr
, &Tcb
->LocalEnd
.Ip
) &&
270 (LocalPort
== Tcb
->LocalEnd
.Port
)) {
281 Locate the TCP_CB related to the socket pair.
283 @param LocalPort The local port number.
284 @param LocalIp The local IP address.
285 @param RemotePort The remote port number.
286 @param RemoteIp The remote IP address.
287 @param Syn Whether to search the listen sockets, if TRUE, the
288 listen sockets are searched.
290 @return Pointer to the related TCP_CB, if NULL no match is found.
295 IN TCP_PORTNO LocalPort
,
297 IN TCP_PORTNO RemotePort
,
307 Local
.Port
= LocalPort
;
310 Remote
.Port
= RemotePort
;
311 Remote
.Ip
= RemoteIp
;
314 // First check for exact match.
316 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
317 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
319 if (TCP_PEER_EQUAL (&Remote
, &Tcb
->RemoteEnd
) &&
320 TCP_PEER_EQUAL (&Local
, &Tcb
->LocalEnd
)) {
322 RemoveEntryList (&Tcb
->List
);
323 InsertHeadList (&mTcpRunQue
, &Tcb
->List
);
330 // Only check listen queue when SYN flag is on
333 return TcpLocateListenTcb (&Local
, &Remote
);
341 Insert a Tcb into the proper queue.
343 @param Tcb Pointer to the TCP_CB to be inserted.
345 @retval 0 The Tcb is inserted successfully.
346 @retval -1 Error condition occurred.
357 TCP4_PROTO_DATA
*TcpProto
;
361 ((Tcb
->State
== TCP_LISTEN
) ||
362 (Tcb
->State
== TCP_SYN_SENT
) ||
363 (Tcb
->State
== TCP_SYN_RCVD
) ||
364 (Tcb
->State
== TCP_CLOSED
))
367 if (Tcb
->LocalEnd
.Port
== 0) {
373 if (Tcb
->State
== TCP_LISTEN
) {
374 Head
= &mTcpListenQue
;
378 // Check that Tcb isn't already on the list.
380 NET_LIST_FOR_EACH (Entry
, Head
) {
381 Node
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
383 if (TCP_PEER_EQUAL (&Tcb
->LocalEnd
, &Node
->LocalEnd
) &&
384 TCP_PEER_EQUAL (&Tcb
->RemoteEnd
, &Node
->RemoteEnd
)) {
390 InsertHeadList (Head
, &Tcb
->List
);
392 TcpProto
= (TCP4_PROTO_DATA
*) Tcb
->Sk
->ProtoReserved
;
393 TcpSetVariableData (TcpProto
->TcpService
);
400 Clone a TCB_CB from Tcb.
402 @param Tcb Pointer to the TCP_CB to be cloned.
404 @return Pointer to the new cloned TCP_CB, if NULL error condition occurred.
414 Clone
= AllocatePool (sizeof (TCP_CB
));
421 CopyMem (Clone
, Tcb
, sizeof (TCP_CB
));
424 // Increate the reference count of the shared IpInfo.
426 NET_GET_REF (Tcb
->IpInfo
);
428 InitializeListHead (&Clone
->List
);
429 InitializeListHead (&Clone
->SndQue
);
430 InitializeListHead (&Clone
->RcvQue
);
432 Clone
->Sk
= SockClone (Tcb
->Sk
);
433 if (Clone
->Sk
== NULL
) {
434 DEBUG ((EFI_D_ERROR
, "TcpCloneTcb: failed to clone a sock\n"));
439 ((TCP4_PROTO_DATA
*) (Clone
->Sk
->ProtoReserved
))->TcpPcb
= Clone
;
446 Compute an ISS to be used by a new connection.
448 @return The result ISS.
456 mTcpGlobalIss
+= 2048;
457 return mTcpGlobalIss
;
464 @param Sock Pointer to the socket to get mss
466 @return The mss size.
474 EFI_IP4_MODE_DATA Ip4Mode
;
475 TCP4_PROTO_DATA
*TcpProto
;
476 EFI_IP4_PROTOCOL
*Ip
;
478 ASSERT (Sock
!= NULL
);
480 TcpProto
= (TCP4_PROTO_DATA
*) Sock
->ProtoReserved
;
481 Ip
= (EFI_IP4_PROTOCOL
*) (TcpProto
->TcpService
->IpIo
->Ip
);
484 Ip
->GetModeData (Ip
, &Ip4Mode
, NULL
, NULL
);
486 return (UINT16
) (Ip4Mode
.MaxPacketSize
- sizeof (TCP_HEAD
));
493 @param Tcb Pointer to the TCP_CB of this TCP instance.
494 @param State The state to be set.
505 "Tcb (%p) state %s --> %s\n",
507 mTcpStateName
[Tcb
->State
],
508 mTcpStateName
[State
])
514 case TCP_ESTABLISHED
:
516 SockConnEstablished (Tcb
->Sk
);
518 if (Tcb
->Parent
!= NULL
) {
520 // A new connection is accepted by a listening socket, install
523 TcpInstallDevicePath (Tcb
->Sk
);
530 SockConnClosed (Tcb
->Sk
);
540 Compute the TCP segment's checksum.
542 @param Nbuf Pointer to the buffer that contains the TCP
544 @param HeadSum The checksum value of the fixed part of pseudo
547 @return The checksum value.
558 Checksum
= NetbufChecksum (Nbuf
);
559 Checksum
= NetAddChecksum (Checksum
, HeadSum
);
561 Checksum
= NetAddChecksum (
563 HTONS ((UINT16
) Nbuf
->TotalSize
)
566 return (UINT16
) ~Checksum
;
570 Translate the information from the head of the received TCP
571 segment Nbuf contains and fill it into a TCP_SEG structure.
573 @param Tcb Pointer to the TCP_CB of this TCP instance.
574 @param Nbuf Pointer to the buffer contains the TCP segment.
576 @return Pointer to the TCP_SEG that contains the translated TCP head information.
588 Seg
= TCPSEG_NETBUF (Nbuf
);
589 Head
= (TCP_HEAD
*) NetbufGetByte (Nbuf
, 0, NULL
);
592 Seg
->Seq
= NTOHL (Head
->Seq
);
593 Seg
->Ack
= NTOHL (Head
->Ack
);
594 Seg
->End
= Seg
->Seq
+ (Nbuf
->TotalSize
- (Head
->HeadLen
<< 2));
596 Seg
->Urg
= NTOHS (Head
->Urg
);
597 Seg
->Wnd
= (NTOHS (Head
->Wnd
) << Tcb
->SndWndScale
);
598 Seg
->Flag
= Head
->Flag
;
601 // SYN and FIN flag occupy one sequence space each.
603 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_SYN
)) {
605 // RFC requires that initial window not be scaled
607 Seg
->Wnd
= NTOHS (Head
->Wnd
);
611 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_FIN
)) {
620 Reset the connection related with Tcb.
622 @param Tcb Pointer to the TCP_CB of the connection to be
634 Nbuf
= NetbufAlloc (TCP_MAX_HEAD
);
640 Nhead
= (TCP_HEAD
*) NetbufAllocSpace (
646 ASSERT (Nhead
!= NULL
);
650 Nhead
->Flag
= TCP_FLG_RST
;
651 Nhead
->Seq
= HTONL (Tcb
->SndNxt
);
652 Nhead
->Ack
= HTONL (Tcb
->RcvNxt
);
653 Nhead
->SrcPort
= Tcb
->LocalEnd
.Port
;
654 Nhead
->DstPort
= Tcb
->RemoteEnd
.Port
;
655 Nhead
->HeadLen
= (sizeof (TCP_HEAD
) >> 2);
657 Nhead
->Wnd
= HTONS (0xFFFF);
660 Nhead
->Checksum
= TcpChecksum (Nbuf
, Tcb
->HeadSum
);
662 TcpSendIpPacket (Tcb
, Nbuf
, Tcb
->LocalEnd
.Ip
, Tcb
->RemoteEnd
.Ip
);
669 Initialize an active connection.
671 @param Tcb Pointer to the TCP_CB that wants to initiate a
680 TcpInitTcbLocal (Tcb
);
681 TcpSetState (Tcb
, TCP_SYN_SENT
);
683 TcpSetTimer (Tcb
, TCP_TIMER_CONNECT
, Tcb
->ConnectTimeout
);
684 TcpToSendData (Tcb
, 1);
689 Initiate the connection close procedure, called when
690 applications want to close the connection.
692 @param Tcb Pointer to the TCP_CB of this TCP instance.
700 ASSERT (Tcb
!= NULL
);
702 if (!IsListEmpty (&Tcb
->RcvQue
) || GET_RCV_DATASIZE (Tcb
->Sk
) != 0) {
704 DEBUG ((EFI_D_WARN
, "TcpOnAppClose: connection reset "
705 "because data is lost for TCB %p\n", Tcb
));
707 TcpResetConnection (Tcb
);
712 switch (Tcb
->State
) {
716 TcpSetState (Tcb
, TCP_CLOSED
);
720 case TCP_ESTABLISHED
:
721 TcpSetState (Tcb
, TCP_FIN_WAIT_1
);
725 TcpSetState (Tcb
, TCP_LAST_ACK
);
731 TcpToSendData (Tcb
, 1);
736 Check whether the application's newly delivered data can be sent out.
738 @param Tcb Pointer to the TCP_CB of this TCP instance.
740 @retval 0 Whether the data is sent out or is buffered for
742 @retval -1 The Tcb is not in a state that data is permitted to
752 switch (Tcb
->State
) {
763 case TCP_ESTABLISHED
:
765 TcpToSendData (Tcb
, 0);
784 Application has consumed some data, check whether
785 to send a window updata ack or a delayed ack.
787 @param Tcb Pointer to the TCP_CB of this TCP instance.
797 switch (Tcb
->State
) {
808 case TCP_ESTABLISHED
:
809 TcpOld
= TcpRcvWinOld (Tcb
);
810 if (TcpRcvWinNow (Tcb
) > TcpOld
) {
812 if (TcpOld
< Tcb
->RcvMss
) {
814 DEBUG ((EFI_D_INFO
, "TcpOnAppConsume: send a window"
815 " update for a window closed Tcb %p\n", Tcb
));
818 } else if (Tcb
->DelayedAck
== 0) {
820 DEBUG ((EFI_D_INFO
, "TcpOnAppConsume: scheduled a delayed"
821 " ACK to update window for Tcb %p\n", Tcb
));
846 Abort the connection by sending a reset segment, called
847 when the application wants to abort the connection.
849 @param Tcb Pointer to the TCP_CB of the TCP instance.
857 DEBUG ((EFI_D_WARN
, "TcpOnAppAbort: connection reset "
858 "issued by application for TCB %p\n", Tcb
));
860 switch (Tcb
->State
) {
862 case TCP_ESTABLISHED
:
866 TcpResetConnection (Tcb
);
872 TcpSetState (Tcb
, TCP_CLOSED
);
877 Set the Tdp4 variable data.
879 @param Tcp4Service Pointer to Tcp4 service data.
881 @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the variable.
882 @retval other Set variable failed.
887 IN TCP4_SERVICE_DATA
*Tcp4Service
890 UINT32 NumConfiguredInstance
;
893 TCP4_PROTO_DATA
*TcpProto
;
894 UINTN VariableDataSize
;
895 EFI_TCP4_VARIABLE_DATA
*Tcp4VariableData
;
896 EFI_TCP4_SERVICE_POINT
*Tcp4ServicePoint
;
897 CHAR16
*NewMacString
;
900 NumConfiguredInstance
= 0;
903 // Go through the running queue to count the instances.
905 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
906 TcpPcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
908 TcpProto
= (TCP4_PROTO_DATA
*) TcpPcb
->Sk
->ProtoReserved
;
910 if (TcpProto
->TcpService
== Tcp4Service
) {
912 // This tcp instance belongs to the Tcp4Service.
914 NumConfiguredInstance
++;
919 // Go through the listening queue to count the instances.
921 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
922 TcpPcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
924 TcpProto
= (TCP4_PROTO_DATA
*) TcpPcb
->Sk
->ProtoReserved
;
926 if (TcpProto
->TcpService
== Tcp4Service
) {
928 // This tcp instance belongs to the Tcp4Service.
930 NumConfiguredInstance
++;
935 // Calculate the size of the Tcp4VariableData. As there may be no Tcp4 child,
936 // we should add extra buffer for the service points only if the number of configured
937 // children is more than 1.
939 VariableDataSize
= sizeof (EFI_TCP4_VARIABLE_DATA
);
941 if (NumConfiguredInstance
> 1) {
942 VariableDataSize
+= sizeof (EFI_TCP4_SERVICE_POINT
) * (NumConfiguredInstance
- 1);
945 Tcp4VariableData
= AllocatePool (VariableDataSize
);
946 if (Tcp4VariableData
== NULL
) {
947 return EFI_OUT_OF_RESOURCES
;
950 Tcp4VariableData
->DriverHandle
= Tcp4Service
->DriverBindingHandle
;
951 Tcp4VariableData
->ServiceCount
= NumConfiguredInstance
;
953 Tcp4ServicePoint
= &Tcp4VariableData
->Services
[0];
956 // Go through the running queue to fill the service points.
958 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
959 TcpPcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
961 TcpProto
= (TCP4_PROTO_DATA
*) TcpPcb
->Sk
->ProtoReserved
;
963 if (TcpProto
->TcpService
== Tcp4Service
) {
965 // This tcp instance belongs to the Tcp4Service.
967 Tcp4ServicePoint
->InstanceHandle
= TcpPcb
->Sk
->SockHandle
;
968 CopyMem (&Tcp4ServicePoint
->LocalAddress
, &TcpPcb
->LocalEnd
.Ip
, sizeof (EFI_IPv4_ADDRESS
));
969 Tcp4ServicePoint
->LocalPort
= NTOHS (TcpPcb
->LocalEnd
.Port
);
970 CopyMem (&Tcp4ServicePoint
->RemoteAddress
, &TcpPcb
->RemoteEnd
.Ip
, sizeof (EFI_IPv4_ADDRESS
));
971 Tcp4ServicePoint
->RemotePort
= NTOHS (TcpPcb
->RemoteEnd
.Port
);
978 // Go through the listening queue to fill the service points.
980 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
981 TcpPcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
983 TcpProto
= (TCP4_PROTO_DATA
*) TcpPcb
->Sk
->ProtoReserved
;
985 if (TcpProto
->TcpService
== Tcp4Service
) {
987 // This tcp instance belongs to the Tcp4Service.
989 Tcp4ServicePoint
->InstanceHandle
= TcpPcb
->Sk
->SockHandle
;
990 CopyMem (&Tcp4ServicePoint
->LocalAddress
, &TcpPcb
->LocalEnd
.Ip
, sizeof (EFI_IPv4_ADDRESS
));
991 Tcp4ServicePoint
->LocalPort
= NTOHS (TcpPcb
->LocalEnd
.Port
);
992 CopyMem (&Tcp4ServicePoint
->RemoteAddress
, &TcpPcb
->RemoteEnd
.Ip
, sizeof (EFI_IPv4_ADDRESS
));
993 Tcp4ServicePoint
->RemotePort
= NTOHS (TcpPcb
->RemoteEnd
.Port
);
1000 // Get the mac string.
1002 Status
= NetLibGetMacString (
1003 Tcp4Service
->ControllerHandle
,
1004 Tcp4Service
->DriverBindingHandle
,
1007 if (EFI_ERROR (Status
)) {
1011 if (Tcp4Service
->MacString
!= NULL
) {
1013 // The variable is set already, we're going to update it.
1015 if (StrCmp (Tcp4Service
->MacString
, NewMacString
) != 0) {
1017 // The mac address is changed, delete the previous variable first.
1020 Tcp4Service
->MacString
,
1021 &gEfiTcp4ServiceBindingProtocolGuid
,
1022 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1028 FreePool (Tcp4Service
->MacString
);
1031 Tcp4Service
->MacString
= NewMacString
;
1033 Status
= gRT
->SetVariable (
1034 Tcp4Service
->MacString
,
1035 &gEfiTcp4ServiceBindingProtocolGuid
,
1036 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1038 (VOID
*) Tcp4VariableData
1043 FreePool (Tcp4VariableData
);
1050 Clear the variable and free the resource.
1052 @param Tcp4Service Pointer to Tcp4 service data.
1056 TcpClearVariableData (
1057 IN TCP4_SERVICE_DATA
*Tcp4Service
1060 ASSERT (Tcp4Service
->MacString
!= NULL
);
1063 Tcp4Service
->MacString
,
1064 &gEfiTcp4ServiceBindingProtocolGuid
,
1065 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1070 FreePool (Tcp4Service
->MacString
);
1071 Tcp4Service
->MacString
= NULL
;
1075 Install the device path protocol on the TCP instance.
1077 @param Sock Pointer to the socket representing the TCP instance.
1079 @retval EFI_SUCCESS The device path protocol is installed.
1080 @retval other Failed to install the device path protocol.
1084 TcpInstallDevicePath (
1088 TCP4_PROTO_DATA
*TcpProto
;
1089 TCP4_SERVICE_DATA
*TcpService
;
1091 IPv4_DEVICE_PATH Ip4DPathNode
;
1093 TCP_PORTNO LocalPort
;
1094 TCP_PORTNO RemotePort
;
1096 TcpProto
= (TCP4_PROTO_DATA
*) Sock
->ProtoReserved
;
1097 TcpService
= TcpProto
->TcpService
;
1098 Tcb
= TcpProto
->TcpPcb
;
1100 LocalPort
= NTOHS (Tcb
->LocalEnd
.Port
);
1101 RemotePort
= NTOHS (Tcb
->RemoteEnd
.Port
);
1102 NetLibCreateIPv4DPathNode (
1104 TcpService
->ControllerHandle
,
1113 Sock
->DevicePath
= AppendDevicePathNode (
1114 Sock
->ParentDevicePath
,
1115 (EFI_DEVICE_PATH_PROTOCOL
*) &Ip4DPathNode
1117 if (Sock
->DevicePath
== NULL
) {
1118 return EFI_OUT_OF_RESOURCES
;
1121 Status
= gBS
->InstallProtocolInterface (
1123 &gEfiDevicePathProtocolGuid
,
1124 EFI_NATIVE_INTERFACE
,
1127 if (EFI_ERROR (Status
)) {
1128 FreePool (Sock
->DevicePath
);