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.
205 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
206 Node
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
208 if ((Local
->Port
!= Node
->LocalEnd
.Port
) ||
209 !TCP_PEER_MATCH (Remote
, &Node
->RemoteEnd
) ||
210 !TCP_PEER_MATCH (Local
, &Node
->LocalEnd
)
217 // Compute the number of wildcard
220 if (Node
->RemoteEnd
.Ip
== 0) {
224 if (Node
->RemoteEnd
.Port
== 0) {
228 if (Node
->LocalEnd
.Ip
== 0) {
247 Try to find one Tcb whose <Ip, Port> equals to <IN Addr, IN Port>.
249 @param Addr Pointer to the IP address needs to match.
250 @param Port The port number needs to match.
252 @return The Tcb which matches the <Addr Port> paire exists or not.
257 IN EFI_IPv4_ADDRESS
*Addr
,
261 TCP_PORTNO LocalPort
;
265 ASSERT ((Addr
!= NULL
) && (Port
!= 0));
267 LocalPort
= HTONS (Port
);
269 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
270 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
272 if (EFI_IP4_EQUAL (Addr
, &Tcb
->LocalEnd
.Ip
) &&
273 (LocalPort
== Tcb
->LocalEnd
.Port
)) {
279 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
280 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
282 if (EFI_IP4_EQUAL (Addr
, &Tcb
->LocalEnd
.Ip
) &&
283 (LocalPort
== Tcb
->LocalEnd
.Port
)) {
294 Locate the TCP_CB related to the socket pair.
296 @param LocalPort The local port number.
297 @param LocalIp The local IP address.
298 @param RemotePort The remote port number.
299 @param RemoteIp The remote IP address.
300 @param Syn Whether to search the listen sockets, if TRUE, the
301 listen sockets are searched.
303 @return Pointer to the related TCP_CB, if NULL no match is found.
308 IN TCP_PORTNO LocalPort
,
310 IN TCP_PORTNO RemotePort
,
320 Local
.Port
= LocalPort
;
323 Remote
.Port
= RemotePort
;
324 Remote
.Ip
= RemoteIp
;
327 // First check for exact match.
329 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
330 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
332 if (TCP_PEER_EQUAL (&Remote
, &Tcb
->RemoteEnd
) &&
333 TCP_PEER_EQUAL (&Local
, &Tcb
->LocalEnd
)) {
335 RemoveEntryList (&Tcb
->List
);
336 InsertHeadList (&mTcpRunQue
, &Tcb
->List
);
343 // Only check listen queue when SYN flag is on
346 return TcpLocateListenTcb (&Local
, &Remote
);
354 Insert a Tcb into the proper queue.
356 @param Tcb Pointer to the TCP_CB to be inserted.
358 @retval 0 The Tcb is inserted successfully.
359 @retval -1 Error condition occurred.
370 TCP4_PROTO_DATA
*TcpProto
;
375 (Tcb
->State
== TCP_LISTEN
) ||
376 (Tcb
->State
== TCP_SYN_SENT
) ||
377 (Tcb
->State
== TCP_SYN_RCVD
) ||
378 (Tcb
->State
== TCP_CLOSED
)
382 if (Tcb
->LocalEnd
.Port
== 0) {
388 if (Tcb
->State
== TCP_LISTEN
) {
389 Head
= &mTcpListenQue
;
393 // Check that Tcb isn't already on the list.
395 NET_LIST_FOR_EACH (Entry
, Head
) {
396 Node
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
398 if (TCP_PEER_EQUAL (&Tcb
->LocalEnd
, &Node
->LocalEnd
) &&
399 TCP_PEER_EQUAL (&Tcb
->RemoteEnd
, &Node
->RemoteEnd
)) {
405 InsertHeadList (Head
, &Tcb
->List
);
407 TcpProto
= (TCP4_PROTO_DATA
*) Tcb
->Sk
->ProtoReserved
;
408 TcpSetVariableData (TcpProto
->TcpService
);
415 Clone a TCP_CB from Tcb.
417 @param Tcb Pointer to the TCP_CB to be cloned.
419 @return Pointer to the new cloned TCP_CB, if NULL error condition occurred.
429 Clone
= AllocatePool (sizeof (TCP_CB
));
436 CopyMem (Clone
, Tcb
, sizeof (TCP_CB
));
439 // Increate the reference count of the shared IpInfo.
441 NET_GET_REF (Tcb
->IpInfo
);
443 InitializeListHead (&Clone
->List
);
444 InitializeListHead (&Clone
->SndQue
);
445 InitializeListHead (&Clone
->RcvQue
);
447 Clone
->Sk
= SockClone (Tcb
->Sk
);
448 if (Clone
->Sk
== NULL
) {
449 DEBUG ((EFI_D_ERROR
, "TcpCloneTcb: failed to clone a sock\n"));
450 gBS
->FreePool (Clone
);
454 ((TCP4_PROTO_DATA
*) (Clone
->Sk
->ProtoReserved
))->TcpPcb
= Clone
;
461 Compute an ISS to be used by a new connection.
465 @return The result ISS.
473 mTcpGlobalIss
+= 2048;
474 return mTcpGlobalIss
;
483 @return The mss size.
491 EFI_SIMPLE_NETWORK_MODE SnpMode
;
492 TCP4_PROTO_DATA
*TcpProto
;
493 EFI_IP4_PROTOCOL
*Ip
;
497 TcpProto
= (TCP4_PROTO_DATA
*) Sock
->ProtoReserved
;
498 Ip
= TcpProto
->TcpService
->IpIo
->Ip
;
501 Ip
->GetModeData (Ip
, NULL
, NULL
, &SnpMode
);
503 return (UINT16
) (SnpMode
.MaxPacketSize
- 40);
510 @param Tcb Pointer to the TCP_CB of this TCP instance.
511 @param State The state to be set.
524 "Tcb (%x) state %s --> %s\n",
526 mTcpStateName
[Tcb
->State
],
527 mTcpStateName
[State
])
533 case TCP_ESTABLISHED
:
535 SockConnEstablished (Tcb
->Sk
);
537 if (Tcb
->Parent
!= NULL
) {
539 // A new connection is accepted by a listening socket, install
542 TcpInstallDevicePath (Tcb
->Sk
);
549 SockConnClosed (Tcb
->Sk
);
557 Compute the TCP segment's checksum.
559 @param Nbuf Pointer to the buffer that contains the TCP
561 @param HeadSum The checksum value of the fixed part of pseudo
564 @return The checksum value.
575 Checksum
= NetbufChecksum (Nbuf
);
576 Checksum
= NetAddChecksum (Checksum
, HeadSum
);
578 Checksum
= NetAddChecksum (
580 HTONS ((UINT16
) Nbuf
->TotalSize
)
583 return (UINT16
) ~Checksum
;
588 Translate the information from the head of the received TCP
589 segment Nbuf contains and fill it into a TCP_SEG structure.
591 @param Tcb Pointer to the TCP_CB of this TCP instance.
592 @param Nbuf Pointer to the buffer contains the TCP segment.
594 @return Pointer to the TCP_SEG that contains the translated TCP head information.
606 Seg
= TCPSEG_NETBUF (Nbuf
);
607 Head
= (TCP_HEAD
*) NetbufGetByte (Nbuf
, 0, NULL
);
610 Seg
->Seq
= NTOHL (Head
->Seq
);
611 Seg
->Ack
= NTOHL (Head
->Ack
);
612 Seg
->End
= Seg
->Seq
+ (Nbuf
->TotalSize
- (Head
->HeadLen
<< 2));
614 Seg
->Urg
= NTOHS (Head
->Urg
);
615 Seg
->Wnd
= (NTOHS (Head
->Wnd
) << Tcb
->SndWndScale
);
616 Seg
->Flag
= Head
->Flag
;
619 // SYN and FIN flag occupy one sequence space each.
621 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_SYN
)) {
623 // RFC requires that initial window not be scaled
625 Seg
->Wnd
= NTOHS (Head
->Wnd
);
629 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_FIN
)) {
638 Reset the connection related with Tcb.
640 @param Tcb Pointer to the TCP_CB of the connection to be
654 Nbuf
= NetbufAlloc (TCP_MAX_HEAD
);
660 Nhead
= (TCP_HEAD
*) NetbufAllocSpace (
666 ASSERT (Nhead
!= NULL
);
670 Nhead
->Flag
= TCP_FLG_RST
;
671 Nhead
->Seq
= HTONL (Tcb
->SndNxt
);
672 Nhead
->Ack
= HTONL (Tcb
->RcvNxt
);
673 Nhead
->SrcPort
= Tcb
->LocalEnd
.Port
;
674 Nhead
->DstPort
= Tcb
->RemoteEnd
.Port
;
675 Nhead
->HeadLen
= (sizeof (TCP_HEAD
) >> 2);
677 Nhead
->Wnd
= HTONS (0xFFFF);
680 Nhead
->Checksum
= TcpChecksum (Nbuf
, Tcb
->HeadSum
);
682 TcpSendIpPacket (Tcb
, Nbuf
, Tcb
->LocalEnd
.Ip
, Tcb
->RemoteEnd
.Ip
);
689 Initialize an active connection,
691 @param Tcb Pointer to the TCP_CB that wants to initiate a
702 TcpInitTcbLocal (Tcb
);
703 TcpSetState (Tcb
, TCP_SYN_SENT
);
705 TcpSetTimer (Tcb
, TCP_TIMER_CONNECT
, Tcb
->ConnectTimeout
);
706 TcpToSendData (Tcb
, 1);
711 Initiate the connection close procedure, called when
712 applications want to close the connection.
714 @param Tcb Pointer to the TCP_CB of this TCP instance.
726 if (!IsListEmpty (&Tcb
->RcvQue
) || GET_RCV_DATASIZE (Tcb
->Sk
)) {
728 DEBUG ((EFI_D_WARN
, "TcpOnAppClose: connection reset "
729 "because data is lost for TCB %x\n", Tcb
));
731 TcpResetConnection (Tcb
);
736 switch (Tcb
->State
) {
740 TcpSetState (Tcb
, TCP_CLOSED
);
744 case TCP_ESTABLISHED
:
745 TcpSetState (Tcb
, TCP_FIN_WAIT_1
);
749 TcpSetState (Tcb
, TCP_LAST_ACK
);
753 TcpToSendData (Tcb
, 1);
758 Check whether the application's newly delivered data
761 @param Tcb Pointer to the TCP_CB of this TCP instance.
763 @retval 0 Whether the data is sent out or is buffered for
765 @retval -1 The Tcb is not in a state that data is permitted to
775 switch (Tcb
->State
) {
789 case TCP_ESTABLISHED
:
791 TcpToSendData (Tcb
, 0);
809 Application has consumed some data, check whether
810 to send a window updata ack or a delayed ack.
812 @param Tcb Pointer to the TCP_CB of this TCP instance.
823 switch (Tcb
->State
) {
837 case TCP_ESTABLISHED
:
838 TcpOld
= TcpRcvWinOld (Tcb
);
839 if (TcpRcvWinNow (Tcb
) > TcpOld
) {
841 if (TcpOld
< Tcb
->RcvMss
) {
843 DEBUG ((EFI_D_INFO
, "TcpOnAppConsume: send a window"
844 " update for a window closed Tcb(%x)\n", Tcb
));
847 } else if (Tcb
->DelayedAck
== 0) {
849 DEBUG ((EFI_D_INFO
, "TcpOnAppConsume: scheduled a delayed"
850 " ACK to update window for Tcb(%x)\n", Tcb
));
876 Abort the connection by sending a reset segment, called
877 when the application wants to abort the connection.
879 @param Tcb Pointer to the TCP_CB of the TCP instance.
889 DEBUG ((EFI_D_WARN
, "TcpOnAppAbort: connection reset "
890 "issued by application for TCB %x\n", Tcb
));
892 switch (Tcb
->State
) {
894 case TCP_ESTABLISHED
:
898 TcpResetConnection (Tcb
);
902 TcpSetState (Tcb
, TCP_CLOSED
);
907 Set the Tdp4 variable data.
909 @param Tcp4Service Tcp4 service data.
911 @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the variable.
912 @retval other Set variable failed.
917 IN TCP4_SERVICE_DATA
*Tcp4Service
920 UINT32 NumConfiguredInstance
;
923 TCP4_PROTO_DATA
*TcpProto
;
924 UINTN VariableDataSize
;
925 EFI_TCP4_VARIABLE_DATA
*Tcp4VariableData
;
926 EFI_TCP4_SERVICE_POINT
*Tcp4ServicePoint
;
927 CHAR16
*NewMacString
;
930 NumConfiguredInstance
= 0;
933 // Go through the running queue to count the instances.
935 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
936 TcpPcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
938 TcpProto
= (TCP4_PROTO_DATA
*) TcpPcb
->Sk
->ProtoReserved
;
940 if (TcpProto
->TcpService
== Tcp4Service
) {
942 // This tcp instance belongs to the Tcp4Service.
944 NumConfiguredInstance
++;
949 // Go through the listening queue to count the instances.
951 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
952 TcpPcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
954 TcpProto
= (TCP4_PROTO_DATA
*) TcpPcb
->Sk
->ProtoReserved
;
956 if (TcpProto
->TcpService
== Tcp4Service
) {
958 // This tcp instance belongs to the Tcp4Service.
960 NumConfiguredInstance
++;
965 // Calculate the size of the Tcp4VariableData. As there may be no Tcp4 child,
966 // we should add extra buffer for the service points only if the number of configured
967 // children is more than 1.
969 VariableDataSize
= sizeof (EFI_TCP4_VARIABLE_DATA
);
971 if (NumConfiguredInstance
> 1) {
972 VariableDataSize
+= sizeof (EFI_TCP4_SERVICE_POINT
) * (NumConfiguredInstance
- 1);
975 Tcp4VariableData
= AllocatePool (VariableDataSize
);
976 if (Tcp4VariableData
== NULL
) {
977 return EFI_OUT_OF_RESOURCES
;
980 Tcp4VariableData
->DriverHandle
= Tcp4Service
->DriverBindingHandle
;
981 Tcp4VariableData
->ServiceCount
= NumConfiguredInstance
;
983 Tcp4ServicePoint
= &Tcp4VariableData
->Services
[0];
986 // Go through the running queue to fill the service points.
988 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
989 TcpPcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
991 TcpProto
= (TCP4_PROTO_DATA
*) TcpPcb
->Sk
->ProtoReserved
;
993 if (TcpProto
->TcpService
== Tcp4Service
) {
995 // This tcp instance belongs to the Tcp4Service.
997 Tcp4ServicePoint
->InstanceHandle
= TcpPcb
->Sk
->SockHandle
;
998 CopyMem (&Tcp4ServicePoint
->LocalAddress
, &TcpPcb
->LocalEnd
.Ip
, sizeof (EFI_IPv4_ADDRESS
));
999 Tcp4ServicePoint
->LocalPort
= NTOHS (TcpPcb
->LocalEnd
.Port
);
1000 CopyMem (&Tcp4ServicePoint
->RemoteAddress
, &TcpPcb
->RemoteEnd
.Ip
, sizeof (EFI_IPv4_ADDRESS
));
1001 Tcp4ServicePoint
->RemotePort
= NTOHS (TcpPcb
->RemoteEnd
.Port
);
1008 // Go through the listening queue to fill the service points.
1010 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
1011 TcpPcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
1013 TcpProto
= (TCP4_PROTO_DATA
*) TcpPcb
->Sk
->ProtoReserved
;
1015 if (TcpProto
->TcpService
== Tcp4Service
) {
1017 // This tcp instance belongs to the Tcp4Service.
1019 Tcp4ServicePoint
->InstanceHandle
= TcpPcb
->Sk
->SockHandle
;
1020 CopyMem (&Tcp4ServicePoint
->LocalAddress
, &TcpPcb
->LocalEnd
.Ip
, sizeof (EFI_IPv4_ADDRESS
));
1021 Tcp4ServicePoint
->LocalPort
= NTOHS (TcpPcb
->LocalEnd
.Port
);
1022 CopyMem (&Tcp4ServicePoint
->RemoteAddress
, &TcpPcb
->RemoteEnd
.Ip
, sizeof (EFI_IPv4_ADDRESS
));
1023 Tcp4ServicePoint
->RemotePort
= NTOHS (TcpPcb
->RemoteEnd
.Port
);
1030 // Get the mac string.
1032 Status
= NetLibGetMacString (
1033 Tcp4Service
->ControllerHandle
,
1034 Tcp4Service
->DriverBindingHandle
,
1037 if (EFI_ERROR (Status
)) {
1041 if (Tcp4Service
->MacString
!= NULL
) {
1043 // The variable is set already, we're going to update it.
1045 if (StrCmp (Tcp4Service
->MacString
, NewMacString
) != 0) {
1047 // The mac address is changed, delete the previous variable first.
1050 Tcp4Service
->MacString
,
1051 &gEfiTcp4ServiceBindingProtocolGuid
,
1052 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1058 gBS
->FreePool (Tcp4Service
->MacString
);
1061 Tcp4Service
->MacString
= NewMacString
;
1063 Status
= gRT
->SetVariable (
1064 Tcp4Service
->MacString
,
1065 &gEfiTcp4ServiceBindingProtocolGuid
,
1066 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1068 (VOID
*) Tcp4VariableData
1073 gBS
->FreePool (Tcp4VariableData
);
1080 Clear the variable and free the resource.
1082 @param Tcp4Service Tcp4 service data.
1088 TcpClearVariableData (
1089 IN TCP4_SERVICE_DATA
*Tcp4Service
1092 ASSERT (Tcp4Service
->MacString
!= NULL
);
1095 Tcp4Service
->MacString
,
1096 &gEfiTcp4ServiceBindingProtocolGuid
,
1097 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1102 gBS
->FreePool (Tcp4Service
->MacString
);
1103 Tcp4Service
->MacString
= NULL
;
1107 TcpInstallDevicePath (
1112 Routine Description:
1114 Install the device path protocol on the TCP instance.
1118 Sock - Pointer to the socket representing the TCP instance.
1122 EFI_SUCCESS - The device path protocol is installed.
1123 other - Failed to install the device path protocol.
1127 TCP4_PROTO_DATA
*TcpProto
;
1128 TCP4_SERVICE_DATA
*TcpService
;
1130 IPv4_DEVICE_PATH Ip4DPathNode
;
1133 TcpProto
= (TCP4_PROTO_DATA
*) Sock
->ProtoReserved
;
1134 TcpService
= TcpProto
->TcpService
;
1135 Tcb
= TcpProto
->TcpPcb
;
1137 NetLibCreateIPv4DPathNode (
1139 TcpService
->ControllerHandle
,
1141 NTOHS (Tcb
->LocalEnd
.Port
),
1143 NTOHS (Tcb
->RemoteEnd
.Port
),
1148 Sock
->DevicePath
= AppendDevicePathNode (
1149 Sock
->ParentDevicePath
,
1150 (EFI_DEVICE_PATH_PROTOCOL
*) &Ip4DPathNode
1152 if (Sock
->DevicePath
== NULL
) {
1153 return EFI_OUT_OF_RESOURCES
;
1156 Status
= gBS
->InstallProtocolInterface (
1158 &gEfiDevicePathProtocolGuid
,
1159 EFI_NATIVE_INTERFACE
,
1162 if (EFI_ERROR (Status
)) {
1163 gBS
->FreePool (Sock
->DevicePath
);