3 Copyright (c) 2005 - 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Misc support routines for tcp.
26 #include <Library/DevicePathLib.h>
28 LIST_ENTRY mTcpRunQue
= {
33 LIST_ENTRY mTcpListenQue
= {
38 TCP_SEQNO mTcpGlobalIss
= 0x4d7e980b;
40 CHAR16
*mTcpStateName
[] = {
56 Initialize the Tcb local related members.
58 @param Tcb Pointer to the TCP_CB of this TCP instance.
69 // Compute the checksum of the fixed parts of pseudo header
71 Tcb
->HeadSum
= NetPseudoHeadChecksum (
78 Tcb
->Iss
= TcpGetIss ();
79 Tcb
->SndUna
= Tcb
->Iss
;
80 Tcb
->SndNxt
= Tcb
->Iss
;
82 Tcb
->SndWl2
= Tcb
->Iss
;
85 Tcb
->RcvWnd
= GET_RCV_BUFFSIZE (Tcb
->Sk
);
88 // Fisrt window size is never scaled
95 Initialize the peer related members.
97 @param Tcb Pointer to the TCP_CB of this TCP instance.
98 @param Seg Pointer to the segment that contains the peer's
100 @param Opt Pointer to the options announced by the peer.
114 ASSERT (Tcb
&& Seg
&& Opt
);
115 ASSERT (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_SYN
));
117 Tcb
->SndWnd
= Seg
->Wnd
;
118 Tcb
->SndWndMax
= Tcb
->SndWnd
;
119 Tcb
->SndWl1
= Seg
->Seq
;
121 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_ACK
)) {
122 Tcb
->SndWl2
= Seg
->Ack
;
124 Tcb
->SndWl2
= Tcb
->Iss
+ 1;
127 if (TCP_FLG_ON (Opt
->Flag
, TCP_OPTION_RCVD_MSS
)) {
128 Tcb
->SndMss
= (UINT16
) MAX (64, Opt
->Mss
);
130 RcvMss
= TcpGetRcvMss (Tcb
->Sk
);
131 if (Tcb
->SndMss
> RcvMss
) {
132 Tcb
->SndMss
= RcvMss
;
137 // One end doesn't support MSS option, use default.
142 Tcb
->CWnd
= Tcb
->SndMss
;
145 Tcb
->RcvNxt
= Tcb
->Irs
+ 1;
147 Tcb
->RcvWl2
= Tcb
->RcvNxt
;
149 if (TCP_FLG_ON (Opt
->Flag
, TCP_OPTION_RCVD_WS
) &&
150 !TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_WS
)) {
152 Tcb
->SndWndScale
= Opt
->WndScale
;
154 Tcb
->RcvWndScale
= TcpComputeScale (Tcb
);
155 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_RCVD_WS
);
159 // One end doesn't support window scale option. use zero.
161 Tcb
->RcvWndScale
= 0;
164 if (TCP_FLG_ON (Opt
->Flag
, TCP_OPTION_RCVD_TS
) &&
165 !TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_TS
)) {
167 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_SND_TS
);
168 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_RCVD_TS
);
171 // Compute the effective SndMss per RFC1122
172 // section 4.2.2.6. If timestamp option is
173 // enabled, it will always occupy 12 bytes.
175 Tcb
->SndMss
-= TCP_OPTION_TS_ALIGNED_LEN
;
181 Locate a listen TCB that matchs the Local and Remote.
183 @param Local Pointer to the local (IP, Port).
184 @param Remote Pointer to the remote (IP, Port).
186 @return Pointer to the TCP_CB with the least number of wildcard, if NULL no match is found.
204 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
205 Node
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
207 if ((Local
->Port
!= Node
->LocalEnd
.Port
) ||
208 !TCP_PEER_MATCH (Remote
, &Node
->RemoteEnd
) ||
209 !TCP_PEER_MATCH (Local
, &Node
->LocalEnd
)
216 // Compute the number of wildcard
219 if (Node
->RemoteEnd
.Ip
== 0) {
223 if (Node
->RemoteEnd
.Port
== 0) {
227 if (Node
->LocalEnd
.Ip
== 0) {
246 Try to find one Tcb whose <Ip, Port> equals to <IN Addr, IN Port>.
248 @param Addr Pointer to the IP address needs to match.
249 @param Port The port number needs to match.
251 @return The Tcb which matches the <Addr Port> paire exists or not.
256 IN EFI_IPv4_ADDRESS
*Addr
,
260 TCP_PORTNO LocalPort
;
264 ASSERT ((Addr
!= NULL
) && (Port
!= 0));
266 LocalPort
= HTONS (Port
);
268 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
269 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
271 if (EFI_IP4_EQUAL (Addr
, &Tcb
->LocalEnd
.Ip
) &&
272 (LocalPort
== Tcb
->LocalEnd
.Port
)) {
278 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
279 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
281 if (EFI_IP4_EQUAL (Addr
, &Tcb
->LocalEnd
.Ip
) &&
282 (LocalPort
== Tcb
->LocalEnd
.Port
)) {
293 Locate the TCP_CB related to the socket pair.
295 @param LocalPort The local port number.
296 @param LocalIp The local IP address.
297 @param RemotePort The remote port number.
298 @param RemoteIp The remote IP address.
299 @param Syn Whether to search the listen sockets, if TRUE, the
300 listen sockets are searched.
302 @return Pointer to the related TCP_CB, if NULL no match is found.
307 IN TCP_PORTNO LocalPort
,
309 IN TCP_PORTNO RemotePort
,
319 Local
.Port
= LocalPort
;
322 Remote
.Port
= RemotePort
;
323 Remote
.Ip
= RemoteIp
;
326 // First check for exact match.
328 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
329 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
331 if (TCP_PEER_EQUAL (&Remote
, &Tcb
->RemoteEnd
) &&
332 TCP_PEER_EQUAL (&Local
, &Tcb
->LocalEnd
)) {
334 RemoveEntryList (&Tcb
->List
);
335 InsertHeadList (&mTcpRunQue
, &Tcb
->List
);
342 // Only check listen queue when SYN flag is on
345 return TcpLocateListenTcb (&Local
, &Remote
);
353 Insert a Tcb into the proper queue.
355 @param Tcb Pointer to the TCP_CB to be inserted.
357 @retval 0 The Tcb is inserted successfully.
358 @retval -1 Error condition occurred.
369 TCP4_PROTO_DATA
*TcpProto
;
374 (Tcb
->State
== TCP_LISTEN
) ||
375 (Tcb
->State
== TCP_SYN_SENT
) ||
376 (Tcb
->State
== TCP_SYN_RCVD
) ||
377 (Tcb
->State
== TCP_CLOSED
)
381 if (Tcb
->LocalEnd
.Port
== 0) {
387 if (Tcb
->State
== TCP_LISTEN
) {
388 Head
= &mTcpListenQue
;
392 // Check that Tcb isn't already on the list.
394 NET_LIST_FOR_EACH (Entry
, Head
) {
395 Node
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
397 if (TCP_PEER_EQUAL (&Tcb
->LocalEnd
, &Node
->LocalEnd
) &&
398 TCP_PEER_EQUAL (&Tcb
->RemoteEnd
, &Node
->RemoteEnd
)) {
404 InsertHeadList (Head
, &Tcb
->List
);
406 TcpProto
= (TCP4_PROTO_DATA
*) Tcb
->Sk
->ProtoReserved
;
407 TcpSetVariableData (TcpProto
->TcpService
);
414 Clone a TCP_CB from Tcb.
416 @param Tcb Pointer to the TCP_CB to be cloned.
418 @return Pointer to the new cloned TCP_CB, if NULL error condition occurred.
428 Clone
= AllocatePool (sizeof (TCP_CB
));
435 CopyMem (Clone
, Tcb
, sizeof (TCP_CB
));
438 // Increate the reference count of the shared IpInfo.
440 NET_GET_REF (Tcb
->IpInfo
);
442 InitializeListHead (&Clone
->List
);
443 InitializeListHead (&Clone
->SndQue
);
444 InitializeListHead (&Clone
->RcvQue
);
446 Clone
->Sk
= SockClone (Tcb
->Sk
);
447 if (Clone
->Sk
== NULL
) {
448 DEBUG ((EFI_D_ERROR
, "TcpCloneTcb: failed to clone a sock\n"));
449 gBS
->FreePool (Clone
);
453 ((TCP4_PROTO_DATA
*) (Clone
->Sk
->ProtoReserved
))->TcpPcb
= Clone
;
460 Compute an ISS to be used by a new connection.
464 @return The result ISS.
472 mTcpGlobalIss
+= 2048;
473 return mTcpGlobalIss
;
482 @return The mss size.
490 EFI_SIMPLE_NETWORK_MODE SnpMode
;
491 TCP4_PROTO_DATA
*TcpProto
;
492 EFI_IP4_PROTOCOL
*Ip
;
496 TcpProto
= (TCP4_PROTO_DATA
*) Sock
->ProtoReserved
;
497 Ip
= TcpProto
->TcpService
->IpIo
->Ip
;
500 Ip
->GetModeData (Ip
, NULL
, NULL
, &SnpMode
);
502 return (UINT16
) (SnpMode
.MaxPacketSize
- 40);
509 @param Tcb Pointer to the TCP_CB of this TCP instance.
510 @param State The state to be set.
523 "Tcb (%p) state %s --> %s\n",
525 mTcpStateName
[Tcb
->State
],
526 mTcpStateName
[State
])
532 case TCP_ESTABLISHED
:
534 SockConnEstablished (Tcb
->Sk
);
536 if (Tcb
->Parent
!= NULL
) {
538 // A new connection is accepted by a listening socket, install
541 TcpInstallDevicePath (Tcb
->Sk
);
548 SockConnClosed (Tcb
->Sk
);
556 Compute the TCP segment's checksum.
558 @param Nbuf Pointer to the buffer that contains the TCP
560 @param HeadSum The checksum value of the fixed part of pseudo
563 @return The checksum value.
574 Checksum
= NetbufChecksum (Nbuf
);
575 Checksum
= NetAddChecksum (Checksum
, HeadSum
);
577 Checksum
= NetAddChecksum (
579 HTONS ((UINT16
) Nbuf
->TotalSize
)
582 return (UINT16
) ~Checksum
;
587 Translate the information from the head of the received TCP
588 segment Nbuf contains and fill it into a TCP_SEG structure.
590 @param Tcb Pointer to the TCP_CB of this TCP instance.
591 @param Nbuf Pointer to the buffer contains the TCP segment.
593 @return Pointer to the TCP_SEG that contains the translated TCP head information.
605 Seg
= TCPSEG_NETBUF (Nbuf
);
606 Head
= (TCP_HEAD
*) NetbufGetByte (Nbuf
, 0, NULL
);
609 Seg
->Seq
= NTOHL (Head
->Seq
);
610 Seg
->Ack
= NTOHL (Head
->Ack
);
611 Seg
->End
= Seg
->Seq
+ (Nbuf
->TotalSize
- (Head
->HeadLen
<< 2));
613 Seg
->Urg
= NTOHS (Head
->Urg
);
614 Seg
->Wnd
= (NTOHS (Head
->Wnd
) << Tcb
->SndWndScale
);
615 Seg
->Flag
= Head
->Flag
;
618 // SYN and FIN flag occupy one sequence space each.
620 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_SYN
)) {
622 // RFC requires that initial window not be scaled
624 Seg
->Wnd
= NTOHS (Head
->Wnd
);
628 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_FIN
)) {
637 Reset the connection related with Tcb.
639 @param Tcb Pointer to the TCP_CB of the connection to be
653 Nbuf
= NetbufAlloc (TCP_MAX_HEAD
);
659 Nhead
= (TCP_HEAD
*) NetbufAllocSpace (
665 ASSERT (Nhead
!= NULL
);
669 Nhead
->Flag
= TCP_FLG_RST
;
670 Nhead
->Seq
= HTONL (Tcb
->SndNxt
);
671 Nhead
->Ack
= HTONL (Tcb
->RcvNxt
);
672 Nhead
->SrcPort
= Tcb
->LocalEnd
.Port
;
673 Nhead
->DstPort
= Tcb
->RemoteEnd
.Port
;
674 Nhead
->HeadLen
= (sizeof (TCP_HEAD
) >> 2);
676 Nhead
->Wnd
= HTONS (0xFFFF);
679 Nhead
->Checksum
= TcpChecksum (Nbuf
, Tcb
->HeadSum
);
681 TcpSendIpPacket (Tcb
, Nbuf
, Tcb
->LocalEnd
.Ip
, Tcb
->RemoteEnd
.Ip
);
688 Initialize an active connection,
690 @param Tcb Pointer to the TCP_CB that wants to initiate a
701 TcpInitTcbLocal (Tcb
);
702 TcpSetState (Tcb
, TCP_SYN_SENT
);
704 TcpSetTimer (Tcb
, TCP_TIMER_CONNECT
, Tcb
->ConnectTimeout
);
705 TcpToSendData (Tcb
, 1);
710 Initiate the connection close procedure, called when
711 applications want to close the connection.
713 @param Tcb Pointer to the TCP_CB of this TCP instance.
725 if (!IsListEmpty (&Tcb
->RcvQue
) || GET_RCV_DATASIZE (Tcb
->Sk
)) {
727 DEBUG ((EFI_D_WARN
, "TcpOnAppClose: connection reset "
728 "because data is lost for TCB %p\n", Tcb
));
730 TcpResetConnection (Tcb
);
735 switch (Tcb
->State
) {
739 TcpSetState (Tcb
, TCP_CLOSED
);
743 case TCP_ESTABLISHED
:
744 TcpSetState (Tcb
, TCP_FIN_WAIT_1
);
748 TcpSetState (Tcb
, TCP_LAST_ACK
);
752 TcpToSendData (Tcb
, 1);
757 Check whether the application's newly delivered data
760 @param Tcb Pointer to the TCP_CB of this TCP instance.
762 @retval 0 Whether the data is sent out or is buffered for
764 @retval -1 The Tcb is not in a state that data is permitted to
774 switch (Tcb
->State
) {
788 case TCP_ESTABLISHED
:
790 TcpToSendData (Tcb
, 0);
808 Application has consumed some data, check whether
809 to send a window updata ack or a delayed ack.
811 @param Tcb Pointer to the TCP_CB of this TCP instance.
822 switch (Tcb
->State
) {
836 case TCP_ESTABLISHED
:
837 TcpOld
= TcpRcvWinOld (Tcb
);
838 if (TcpRcvWinNow (Tcb
) > TcpOld
) {
840 if (TcpOld
< Tcb
->RcvMss
) {
842 DEBUG ((EFI_D_INFO
, "TcpOnAppConsume: send a window"
843 " update for a window closed Tcb(%p)\n", Tcb
));
846 } else if (Tcb
->DelayedAck
== 0) {
848 DEBUG ((EFI_D_INFO
, "TcpOnAppConsume: scheduled a delayed"
849 " ACK to update window for Tcb(%p)\n", Tcb
));
875 Abort the connection by sending a reset segment, called
876 when the application wants to abort the connection.
878 @param Tcb Pointer to the TCP_CB of the TCP instance.
888 DEBUG ((EFI_D_WARN
, "TcpOnAppAbort: connection reset "
889 "issued by application for TCB %p\n", Tcb
));
891 switch (Tcb
->State
) {
893 case TCP_ESTABLISHED
:
897 TcpResetConnection (Tcb
);
901 TcpSetState (Tcb
, TCP_CLOSED
);
906 Set the Tdp4 variable data.
908 @param Tcp4Service Tcp4 service data.
910 @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the variable.
911 @retval other Set variable failed.
916 IN TCP4_SERVICE_DATA
*Tcp4Service
919 UINT32 NumConfiguredInstance
;
922 TCP4_PROTO_DATA
*TcpProto
;
923 UINTN VariableDataSize
;
924 EFI_TCP4_VARIABLE_DATA
*Tcp4VariableData
;
925 EFI_TCP4_SERVICE_POINT
*Tcp4ServicePoint
;
926 CHAR16
*NewMacString
;
929 NumConfiguredInstance
= 0;
932 // Go through the running queue to count the instances.
934 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
935 TcpPcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
937 TcpProto
= (TCP4_PROTO_DATA
*) TcpPcb
->Sk
->ProtoReserved
;
939 if (TcpProto
->TcpService
== Tcp4Service
) {
941 // This tcp instance belongs to the Tcp4Service.
943 NumConfiguredInstance
++;
948 // Go through the listening queue to count the instances.
950 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
951 TcpPcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
953 TcpProto
= (TCP4_PROTO_DATA
*) TcpPcb
->Sk
->ProtoReserved
;
955 if (TcpProto
->TcpService
== Tcp4Service
) {
957 // This tcp instance belongs to the Tcp4Service.
959 NumConfiguredInstance
++;
964 // Calculate the size of the Tcp4VariableData. As there may be no Tcp4 child,
965 // we should add extra buffer for the service points only if the number of configured
966 // children is more than 1.
968 VariableDataSize
= sizeof (EFI_TCP4_VARIABLE_DATA
);
970 if (NumConfiguredInstance
> 1) {
971 VariableDataSize
+= sizeof (EFI_TCP4_SERVICE_POINT
) * (NumConfiguredInstance
- 1);
974 Tcp4VariableData
= AllocatePool (VariableDataSize
);
975 if (Tcp4VariableData
== NULL
) {
976 return EFI_OUT_OF_RESOURCES
;
979 Tcp4VariableData
->DriverHandle
= Tcp4Service
->DriverBindingHandle
;
980 Tcp4VariableData
->ServiceCount
= NumConfiguredInstance
;
982 Tcp4ServicePoint
= &Tcp4VariableData
->Services
[0];
985 // Go through the running queue to fill the service points.
987 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
988 TcpPcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
990 TcpProto
= (TCP4_PROTO_DATA
*) TcpPcb
->Sk
->ProtoReserved
;
992 if (TcpProto
->TcpService
== Tcp4Service
) {
994 // This tcp instance belongs to the Tcp4Service.
996 Tcp4ServicePoint
->InstanceHandle
= TcpPcb
->Sk
->SockHandle
;
997 CopyMem (&Tcp4ServicePoint
->LocalAddress
, &TcpPcb
->LocalEnd
.Ip
, sizeof (EFI_IPv4_ADDRESS
));
998 Tcp4ServicePoint
->LocalPort
= NTOHS (TcpPcb
->LocalEnd
.Port
);
999 CopyMem (&Tcp4ServicePoint
->RemoteAddress
, &TcpPcb
->RemoteEnd
.Ip
, sizeof (EFI_IPv4_ADDRESS
));
1000 Tcp4ServicePoint
->RemotePort
= NTOHS (TcpPcb
->RemoteEnd
.Port
);
1007 // Go through the listening queue to fill the service points.
1009 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
1010 TcpPcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
1012 TcpProto
= (TCP4_PROTO_DATA
*) TcpPcb
->Sk
->ProtoReserved
;
1014 if (TcpProto
->TcpService
== Tcp4Service
) {
1016 // This tcp instance belongs to the Tcp4Service.
1018 Tcp4ServicePoint
->InstanceHandle
= TcpPcb
->Sk
->SockHandle
;
1019 CopyMem (&Tcp4ServicePoint
->LocalAddress
, &TcpPcb
->LocalEnd
.Ip
, sizeof (EFI_IPv4_ADDRESS
));
1020 Tcp4ServicePoint
->LocalPort
= NTOHS (TcpPcb
->LocalEnd
.Port
);
1021 CopyMem (&Tcp4ServicePoint
->RemoteAddress
, &TcpPcb
->RemoteEnd
.Ip
, sizeof (EFI_IPv4_ADDRESS
));
1022 Tcp4ServicePoint
->RemotePort
= NTOHS (TcpPcb
->RemoteEnd
.Port
);
1029 // Get the mac string.
1031 Status
= NetLibGetMacString (
1032 Tcp4Service
->ControllerHandle
,
1033 Tcp4Service
->DriverBindingHandle
,
1036 if (EFI_ERROR (Status
)) {
1040 if (Tcp4Service
->MacString
!= NULL
) {
1042 // The variable is set already, we're going to update it.
1044 if (StrCmp (Tcp4Service
->MacString
, NewMacString
) != 0) {
1046 // The mac address is changed, delete the previous variable first.
1049 Tcp4Service
->MacString
,
1050 &gEfiTcp4ServiceBindingProtocolGuid
,
1051 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1057 gBS
->FreePool (Tcp4Service
->MacString
);
1060 Tcp4Service
->MacString
= NewMacString
;
1062 Status
= gRT
->SetVariable (
1063 Tcp4Service
->MacString
,
1064 &gEfiTcp4ServiceBindingProtocolGuid
,
1065 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1067 (VOID
*) Tcp4VariableData
1072 gBS
->FreePool (Tcp4VariableData
);
1079 Clear the variable and free the resource.
1081 @param Tcp4Service Tcp4 service data.
1087 TcpClearVariableData (
1088 IN TCP4_SERVICE_DATA
*Tcp4Service
1091 ASSERT (Tcp4Service
->MacString
!= NULL
);
1094 Tcp4Service
->MacString
,
1095 &gEfiTcp4ServiceBindingProtocolGuid
,
1096 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1101 gBS
->FreePool (Tcp4Service
->MacString
);
1102 Tcp4Service
->MacString
= NULL
;
1106 TcpInstallDevicePath (
1111 Routine Description:
1113 Install the device path protocol on the TCP instance.
1117 Sock - Pointer to the socket representing the TCP instance.
1121 EFI_SUCCESS - The device path protocol is installed.
1122 other - Failed to install the device path protocol.
1126 TCP4_PROTO_DATA
*TcpProto
;
1127 TCP4_SERVICE_DATA
*TcpService
;
1129 IPv4_DEVICE_PATH Ip4DPathNode
;
1132 TcpProto
= (TCP4_PROTO_DATA
*) Sock
->ProtoReserved
;
1133 TcpService
= TcpProto
->TcpService
;
1134 Tcb
= TcpProto
->TcpPcb
;
1136 NetLibCreateIPv4DPathNode (
1138 TcpService
->ControllerHandle
,
1140 NTOHS (Tcb
->LocalEnd
.Port
),
1142 NTOHS (Tcb
->RemoteEnd
.Port
),
1147 Sock
->DevicePath
= AppendDevicePathNode (
1148 Sock
->ParentDevicePath
,
1149 (EFI_DEVICE_PATH_PROTOCOL
*) &Ip4DPathNode
1151 if (Sock
->DevicePath
== NULL
) {
1152 return EFI_OUT_OF_RESOURCES
;
1155 Status
= gBS
->InstallProtocolInterface (
1157 &gEfiDevicePathProtocolGuid
,
1158 EFI_NATIVE_INTERFACE
,
1161 if (EFI_ERROR (Status
)) {
1162 gBS
->FreePool (Sock
->DevicePath
);