2 Misc support routines for TCP driver.
4 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php.
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 LIST_ENTRY mTcpRunQue
= {
24 LIST_ENTRY mTcpListenQue
= {
29 TCP_SEQNO mTcpGlobalIss
= TCP_BASE_ISS
;
31 CHAR16
*mTcpStateName
[] = {
47 Initialize the Tcb local related members.
49 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
58 // Compute the checksum of the fixed parts of pseudo header
60 if (Tcb
->Sk
->IpVersion
== IP_VERSION_4
) {
61 Tcb
->HeadSum
= NetPseudoHeadChecksum (
62 Tcb
->LocalEnd
.Ip
.Addr
[0],
63 Tcb
->RemoteEnd
.Ip
.Addr
[0],
68 Tcb
->HeadSum
= NetIp6PseudoHeadChecksum (
70 &Tcb
->RemoteEnd
.Ip
.v6
,
76 Tcb
->Iss
= TcpGetIss ();
77 Tcb
->SndUna
= Tcb
->Iss
;
78 Tcb
->SndNxt
= Tcb
->Iss
;
80 Tcb
->SndWl2
= Tcb
->Iss
;
83 Tcb
->RcvWnd
= GET_RCV_BUFFSIZE (Tcb
->Sk
);
86 // First window size is never scaled
90 Tcb
->ProbeTimerOn
= FALSE
;
94 Initialize the peer related members.
96 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
97 @param[in] Seg Pointer to the segment that contains the peer's intial info.
98 @param[in] Opt Pointer to the options announced by the peer.
110 ASSERT ((Tcb
!= NULL
) && (Seg
!= NULL
) && (Opt
!= NULL
));
111 ASSERT (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_SYN
));
113 Tcb
->SndWnd
= Seg
->Wnd
;
114 Tcb
->SndWndMax
= Tcb
->SndWnd
;
115 Tcb
->SndWl1
= Seg
->Seq
;
117 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_ACK
)) {
118 Tcb
->SndWl2
= Seg
->Ack
;
120 Tcb
->SndWl2
= Tcb
->Iss
+ 1;
123 if (TCP_FLG_ON (Opt
->Flag
, TCP_OPTION_RCVD_MSS
)) {
124 Tcb
->SndMss
= (UINT16
) MAX (64, Opt
->Mss
);
126 RcvMss
= TcpGetRcvMss (Tcb
->Sk
);
127 if (Tcb
->SndMss
> RcvMss
) {
128 Tcb
->SndMss
= RcvMss
;
133 // One end doesn't support MSS option, use default.
138 Tcb
->CWnd
= Tcb
->SndMss
;
141 Tcb
->RcvNxt
= Tcb
->Irs
+ 1;
143 Tcb
->RcvWl2
= Tcb
->RcvNxt
;
145 if (TCP_FLG_ON (Opt
->Flag
, TCP_OPTION_RCVD_WS
) && !TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_WS
)) {
147 Tcb
->SndWndScale
= Opt
->WndScale
;
149 Tcb
->RcvWndScale
= TcpComputeScale (Tcb
);
150 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_RCVD_WS
);
154 // One end doesn't support window scale option. use zero.
156 Tcb
->RcvWndScale
= 0;
159 if (TCP_FLG_ON (Opt
->Flag
, TCP_OPTION_RCVD_TS
) && !TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_TS
)) {
161 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_SND_TS
);
162 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_RCVD_TS
);
164 Tcb
->TsRecent
= Opt
->TSVal
;
167 // Compute the effective SndMss per RFC1122
168 // section 4.2.2.6. If timestamp option is
169 // enabled, it will always occupy 12 bytes.
171 Tcb
->SndMss
-= TCP_OPTION_TS_ALIGNED_LEN
;
176 Check whether one IP address equals the other.
178 @param[in] Ip1 Pointer to IP address to be checked.
179 @param[in] Ip2 Pointer to IP address to be checked.
180 @param[in] Version IP_VERSION_4 indicates the IP address is an IPv4 address,
181 IP_VERSION_6 indicates the IP address is an IPv6 address.
183 @retval TRUE Ip1 equals Ip2.
184 @retval FALSE Ip1 does not equal Ip2.
189 IN EFI_IP_ADDRESS
*Ip1
,
190 IN EFI_IP_ADDRESS
*Ip2
,
194 ASSERT ((Version
== IP_VERSION_4
) || (Version
== IP_VERSION_6
));
196 if (Version
== IP_VERSION_4
) {
197 return (BOOLEAN
) (Ip1
->Addr
[0] == Ip2
->Addr
[0]);
199 return (BOOLEAN
) EFI_IP6_EQUAL (&Ip1
->v6
, &Ip2
->v6
);
204 Check whether one IP address is filled with ZERO.
206 @param[in] Ip Pointer to the IP address to be checked.
207 @param[in] Version IP_VERSION_4 indicates the IP address is an IPv4 address,
208 IP_VERSION_6 indicates the IP address is an IPv6 address.
210 @retval TRUE Ip is all zero address.
211 @retval FALSE Ip is not all zero address.
216 IN EFI_IP_ADDRESS
*Ip
,
220 ASSERT ((Version
== IP_VERSION_4
) || (Version
== IP_VERSION_6
));
222 if (Version
== IP_VERSION_4
) {
223 return (BOOLEAN
) (Ip
->Addr
[0] == 0);
225 return (BOOLEAN
) ((Ip
->Addr
[0] == 0) && (Ip
->Addr
[1] == 0) &&
226 (Ip
->Addr
[2] == 0) && (Ip
->Addr
[3] == 0));
231 Locate a listen TCB that matchs the Local and Remote.
233 @param[in] Local Pointer to the local (IP, Port).
234 @param[in] Remote Pointer to the remote (IP, Port).
235 @param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
236 IP_VERSION_6 indicates TCP is running on IP6 stack.
238 @return Pointer to the TCP_CB with the least number of wildcards,
239 if NULL no match is found.
258 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
259 Node
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
261 if ((Version
!= Node
->Sk
->IpVersion
) ||
262 (Local
->Port
!= Node
->LocalEnd
.Port
) ||
263 !TCP_PEER_MATCH (Remote
, &Node
->RemoteEnd
, Version
) ||
264 !TCP_PEER_MATCH (Local
, &Node
->LocalEnd
, Version
)
271 // Compute the number of wildcard
274 if (TcpIsIpZero (&Node
->RemoteEnd
.Ip
, Version
)) {
278 if (Node
->RemoteEnd
.Port
== 0) {
282 if (TcpIsIpZero (&Node
->LocalEnd
.Ip
, Version
)) {
300 Try to find one Tcb whose <Ip, Port> equals to <IN Addr, IN Port>.
302 @param[in] Addr Pointer to the IP address needs to match.
303 @param[in] Port The port number needs to match.
304 @param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
305 IP_VERSION_6 indicates TCP is running on IP6 stack.
308 @retval TRUE The Tcb which matches the <Addr Port> pair exists.
309 @retval FALSE Otherwise
314 IN EFI_IP_ADDRESS
*Addr
,
319 TCP_PORTNO LocalPort
;
323 ASSERT ((Addr
!= NULL
) && (Port
!= 0));
325 LocalPort
= HTONS (Port
);
327 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
328 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
330 if ((Version
== Tcb
->Sk
->IpVersion
) &&
331 TcpIsIpEqual (Addr
, &Tcb
->LocalEnd
.Ip
, Version
) &&
332 (LocalPort
== Tcb
->LocalEnd
.Port
)
339 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
340 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
342 if ((Version
== Tcb
->Sk
->IpVersion
) &&
343 TcpIsIpEqual (Addr
, &Tcb
->LocalEnd
.Ip
, Version
) &&
344 (LocalPort
== Tcb
->LocalEnd
.Port
)
355 Locate the TCP_CB related to the socket pair.
357 @param[in] LocalPort The local port number.
358 @param[in] LocalIp The local IP address.
359 @param[in] RemotePort The remote port number.
360 @param[in] RemoteIp The remote IP address.
361 @param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
362 IP_VERSION_6 indicates TCP is running on IP6 stack.
363 @param[in] Syn If TRUE, the listen sockets are searched.
365 @return Pointer to the related TCP_CB. If NULL, no match is found.
370 IN TCP_PORTNO LocalPort
,
371 IN EFI_IP_ADDRESS
*LocalIp
,
372 IN TCP_PORTNO RemotePort
,
373 IN EFI_IP_ADDRESS
*RemoteIp
,
383 Local
.Port
= LocalPort
;
384 Remote
.Port
= RemotePort
;
386 CopyMem (&Local
.Ip
, LocalIp
, sizeof (EFI_IP_ADDRESS
));
387 CopyMem (&Remote
.Ip
, RemoteIp
, sizeof (EFI_IP_ADDRESS
));
390 // First check for exact match.
392 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
393 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
395 if ((Version
== Tcb
->Sk
->IpVersion
) &&
396 TCP_PEER_EQUAL (&Remote
, &Tcb
->RemoteEnd
, Version
) &&
397 TCP_PEER_EQUAL (&Local
, &Tcb
->LocalEnd
, Version
)
400 RemoveEntryList (&Tcb
->List
);
401 InsertHeadList (&mTcpRunQue
, &Tcb
->List
);
408 // Only check the listen queue when the SYN flag is on.
411 return TcpLocateListenTcb (&Local
, &Remote
, Version
);
418 Insert a Tcb into the proper queue.
420 @param[in] Tcb Pointer to the TCP_CB to be inserted.
422 @retval 0 The Tcb was inserted successfully.
423 @retval -1 Error condition occurred.
438 (Tcb
->State
== TCP_LISTEN
) ||
439 (Tcb
->State
== TCP_SYN_SENT
) ||
440 (Tcb
->State
== TCP_SYN_RCVD
) ||
441 (Tcb
->State
== TCP_CLOSED
)
445 if (Tcb
->LocalEnd
.Port
== 0) {
451 if (Tcb
->State
== TCP_LISTEN
) {
452 Head
= &mTcpListenQue
;
456 // Check that the Tcb isn't already on the list.
458 NET_LIST_FOR_EACH (Entry
, Head
) {
459 Node
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
461 if (TCP_PEER_EQUAL (&Tcb
->LocalEnd
, &Node
->LocalEnd
, Tcb
->Sk
->IpVersion
) &&
462 TCP_PEER_EQUAL (&Tcb
->RemoteEnd
, &Node
->RemoteEnd
, Tcb
->Sk
->IpVersion
)
469 InsertHeadList (Head
, &Tcb
->List
);
476 Clone a TCP_CB from Tcb.
478 @param[in] Tcb Pointer to the TCP_CB to be cloned.
480 @return Pointer to the new cloned TCP_CB; if NULL, error condition occurred.
490 Clone
= AllocateZeroPool (sizeof (TCP_CB
));
496 CopyMem (Clone
, Tcb
, sizeof (TCP_CB
));
499 // Increase the reference count of the shared IpInfo.
501 NET_GET_REF (Tcb
->IpInfo
);
503 InitializeListHead (&Clone
->List
);
504 InitializeListHead (&Clone
->SndQue
);
505 InitializeListHead (&Clone
->RcvQue
);
507 Clone
->Sk
= SockClone (Tcb
->Sk
);
508 if (Clone
->Sk
== NULL
) {
509 DEBUG ((EFI_D_ERROR
, "TcpCloneTcb: failed to clone a sock\n"));
514 ((TCP_PROTO_DATA
*) (Clone
->Sk
->ProtoReserved
))->TcpPcb
= Clone
;
520 Compute an ISS to be used by a new connection.
522 @return The resulting ISS.
530 mTcpGlobalIss
+= TCP_ISS_INCREMENT_1
;
531 return mTcpGlobalIss
;
537 @param[in] Sock Pointer to the socket to get mss.
539 @return The mss size.
547 EFI_IP4_MODE_DATA Ip4Mode
;
548 EFI_IP6_MODE_DATA Ip6Mode
;
549 EFI_IP4_PROTOCOL
*Ip4
;
550 EFI_IP6_PROTOCOL
*Ip6
;
551 TCP_PROTO_DATA
*TcpProto
;
553 ASSERT (Sock
!= NULL
);
555 ZeroMem (&Ip4Mode
, sizeof (EFI_IP4_MODE_DATA
));
556 ZeroMem (&Ip6Mode
, sizeof (EFI_IP6_MODE_DATA
));
558 TcpProto
= (TCP_PROTO_DATA
*) Sock
->ProtoReserved
;
560 if (Sock
->IpVersion
== IP_VERSION_4
) {
561 Ip4
= TcpProto
->TcpService
->IpIo
->Ip
.Ip4
;
562 ASSERT (Ip4
!= NULL
);
563 Ip4
->GetModeData (Ip4
, &Ip4Mode
, NULL
, NULL
);
565 return (UINT16
) (Ip4Mode
.MaxPacketSize
- sizeof (TCP_HEAD
));
567 Ip6
= TcpProto
->TcpService
->IpIo
->Ip
.Ip6
;
568 ASSERT (Ip6
!= NULL
);
569 if (!EFI_ERROR (Ip6
->GetModeData (Ip6
, &Ip6Mode
, NULL
, NULL
))) {
570 if (Ip6Mode
.AddressList
!= NULL
) {
571 FreePool (Ip6Mode
.AddressList
);
574 if (Ip6Mode
.GroupTable
!= NULL
) {
575 FreePool (Ip6Mode
.GroupTable
);
578 if (Ip6Mode
.RouteTable
!= NULL
) {
579 FreePool (Ip6Mode
.RouteTable
);
582 if (Ip6Mode
.NeighborCache
!= NULL
) {
583 FreePool (Ip6Mode
.NeighborCache
);
586 if (Ip6Mode
.PrefixTable
!= NULL
) {
587 FreePool (Ip6Mode
.PrefixTable
);
590 if (Ip6Mode
.IcmpTypeList
!= NULL
) {
591 FreePool (Ip6Mode
.IcmpTypeList
);
595 return (UINT16
) (Ip6Mode
.MaxPacketSize
- sizeof (TCP_HEAD
));
602 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
603 @param[in] State The state to be set.
612 ASSERT (Tcb
->State
< (sizeof (mTcpStateName
) / sizeof (CHAR16
*)));
613 ASSERT (State
< (sizeof (mTcpStateName
) / sizeof (CHAR16
*)));
617 "Tcb (%p) state %s --> %s\n",
619 mTcpStateName
[Tcb
->State
],
620 mTcpStateName
[State
])
626 case TCP_ESTABLISHED
:
628 SockConnEstablished (Tcb
->Sk
);
630 if (Tcb
->Parent
!= NULL
) {
632 // A new connection is accepted by a listening socket. Install
635 TcpInstallDevicePath (Tcb
->Sk
);
642 SockConnClosed (Tcb
->Sk
);
651 Compute the TCP segment's checksum.
653 @param[in] Nbuf Pointer to the buffer that contains the TCP segment.
654 @param[in] HeadSum The checksum value of the fixed part of pseudo header.
656 @return The checksum value.
667 Checksum
= NetbufChecksum (Nbuf
);
668 Checksum
= NetAddChecksum (Checksum
, HeadSum
);
670 Checksum
= NetAddChecksum (
672 HTONS ((UINT16
) Nbuf
->TotalSize
)
675 return (UINT16
) (~Checksum
);
679 Translate the information from the head of the received TCP
680 segment Nbuf contents and fill it into a TCP_SEG structure.
682 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
683 @param[in, out] Nbuf Pointer to the buffer contains the TCP segment.
685 @return Pointer to the TCP_SEG that contains the translated TCP head information.
697 Seg
= TCPSEG_NETBUF (Nbuf
);
698 Head
= (TCP_HEAD
*) NetbufGetByte (Nbuf
, 0, NULL
);
699 ASSERT (Head
!= NULL
);
703 Seg
->Seq
= NTOHL (Head
->Seq
);
704 Seg
->Ack
= NTOHL (Head
->Ack
);
705 Seg
->End
= Seg
->Seq
+ (Nbuf
->TotalSize
- (Head
->HeadLen
<< 2));
707 Seg
->Urg
= NTOHS (Head
->Urg
);
708 Seg
->Wnd
= (NTOHS (Head
->Wnd
) << Tcb
->SndWndScale
);
709 Seg
->Flag
= Head
->Flag
;
712 // SYN and FIN flag occupy one sequence space each.
714 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_SYN
)) {
716 // RFC requires that the initial window not be scaled.
718 Seg
->Wnd
= NTOHS (Head
->Wnd
);
722 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_FIN
)) {
730 Initialize an active connection.
732 @param[in, out] Tcb Pointer to the TCP_CB that wants to initiate a
741 TcpInitTcbLocal (Tcb
);
742 TcpSetState (Tcb
, TCP_SYN_SENT
);
744 TcpSetTimer (Tcb
, TCP_TIMER_CONNECT
, Tcb
->ConnectTimeout
);
745 TcpToSendData (Tcb
, 1);
749 Initiate the connection close procedure, called when
750 applications want to close the connection.
752 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
760 ASSERT (Tcb
!= NULL
);
762 if (!IsListEmpty (&Tcb
->RcvQue
) || GET_RCV_DATASIZE (Tcb
->Sk
) != 0) {
766 "TcpOnAppClose: connection reset because data is lost for TCB %p\n",
770 TcpResetConnection (Tcb
);
775 switch (Tcb
->State
) {
779 TcpSetState (Tcb
, TCP_CLOSED
);
783 case TCP_ESTABLISHED
:
784 TcpSetState (Tcb
, TCP_FIN_WAIT_1
);
788 TcpSetState (Tcb
, TCP_LAST_ACK
);
794 TcpToSendData (Tcb
, 1);
798 Check whether the application's newly delivered data can be sent out.
800 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
802 @retval 0 The data has been sent out successfully.
803 @retval -1 The Tcb is not in a state that data is permitted to
813 switch (Tcb
->State
) {
824 case TCP_ESTABLISHED
:
826 TcpToSendData (Tcb
, 0);
844 Application has consumed some data. Check whether
845 to send a window update ack or a delayed ack.
847 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
857 switch (Tcb
->State
) {
858 case TCP_ESTABLISHED
:
859 TcpOld
= TcpRcvWinOld (Tcb
);
860 if (TcpRcvWinNow (Tcb
) > TcpOld
) {
862 if (TcpOld
< Tcb
->RcvMss
) {
866 "TcpOnAppConsume: send a window update for a window closed Tcb %p\n",
871 } else if (Tcb
->DelayedAck
== 0) {
875 "TcpOnAppConsume: scheduled a delayed ACK to update window for Tcb %p\n",
891 Abort the connection by sending a reset segment. Called
892 when the application wants to abort the connection.
894 @param[in] Tcb Pointer to the TCP_CB of the TCP instance.
904 "TcpOnAppAbort: connection reset issued by application for TCB %p\n",
908 switch (Tcb
->State
) {
910 case TCP_ESTABLISHED
:
914 TcpResetConnection (Tcb
);
920 TcpSetState (Tcb
, TCP_CLOSED
);
924 Reset the connection related with Tcb.
926 @param[in] Tcb Pointer to the TCP_CB of the connection to be reset.
937 Nbuf
= NetbufAlloc (TCP_MAX_HEAD
);
943 Nhead
= (TCP_HEAD
*) NetbufAllocSpace (
949 ASSERT (Nhead
!= NULL
);
953 Nhead
->Flag
= TCP_FLG_RST
;
954 Nhead
->Seq
= HTONL (Tcb
->SndNxt
);
955 Nhead
->Ack
= HTONL (Tcb
->RcvNxt
);
956 Nhead
->SrcPort
= Tcb
->LocalEnd
.Port
;
957 Nhead
->DstPort
= Tcb
->RemoteEnd
.Port
;
958 Nhead
->HeadLen
= (UINT8
) (sizeof (TCP_HEAD
) >> 2);
960 Nhead
->Wnd
= HTONS (0xFFFF);
963 Nhead
->Checksum
= TcpChecksum (Nbuf
, Tcb
->HeadSum
);
965 TcpSendIpPacket (Tcb
, Nbuf
, &Tcb
->LocalEnd
.Ip
, &Tcb
->RemoteEnd
.Ip
, Tcb
->Sk
->IpVersion
);
971 Install the device path protocol on the TCP instance.
973 @param[in] Sock Pointer to the socket representing the TCP instance.
975 @retval EFI_SUCCESS The device path protocol was installed.
976 @retval other Failed to install the device path protocol.
980 TcpInstallDevicePath (
984 TCP_PROTO_DATA
*TcpProto
;
985 TCP_SERVICE_DATA
*TcpService
;
987 IPv4_DEVICE_PATH Ip4DPathNode
;
988 IPv6_DEVICE_PATH Ip6DPathNode
;
989 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
991 TCP_PORTNO LocalPort
;
992 TCP_PORTNO RemotePort
;
994 TcpProto
= (TCP_PROTO_DATA
*) Sock
->ProtoReserved
;
995 TcpService
= TcpProto
->TcpService
;
996 Tcb
= TcpProto
->TcpPcb
;
998 LocalPort
= NTOHS (Tcb
->LocalEnd
.Port
);
999 RemotePort
= NTOHS (Tcb
->RemoteEnd
.Port
);
1000 if (Sock
->IpVersion
== IP_VERSION_4
) {
1001 NetLibCreateIPv4DPathNode (
1003 TcpService
->ControllerHandle
,
1004 Tcb
->LocalEnd
.Ip
.Addr
[0],
1006 Tcb
->RemoteEnd
.Ip
.Addr
[0],
1012 IP4_COPY_ADDRESS (&Ip4DPathNode
.SubnetMask
, &Tcb
->SubnetMask
);
1014 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) &Ip4DPathNode
;
1016 NetLibCreateIPv6DPathNode (
1018 TcpService
->ControllerHandle
,
1019 &Tcb
->LocalEnd
.Ip
.v6
,
1021 &Tcb
->RemoteEnd
.Ip
.v6
,
1026 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) &Ip6DPathNode
;
1029 Sock
->DevicePath
= AppendDevicePathNode (Sock
->ParentDevicePath
, DevicePath
);
1030 if (Sock
->DevicePath
== NULL
) {
1031 return EFI_OUT_OF_RESOURCES
;
1034 Status
= gBS
->InstallProtocolInterface (
1036 &gEfiDevicePathProtocolGuid
,
1037 EFI_NATIVE_INTERFACE
,
1040 if (EFI_ERROR (Status
)) {
1041 FreePool (Sock
->DevicePath
);
1042 Sock
->DevicePath
= NULL
;