2 Misc support routines for TCP driver.
4 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
13 LIST_ENTRY mTcpRunQue
= {
18 LIST_ENTRY mTcpListenQue
= {
23 TCP_SEQNO mTcpGlobalIss
= TCP_BASE_ISS
;
25 CHAR16
*mTcpStateName
[] = {
41 Initialize the Tcb local related members.
43 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
52 // Compute the checksum of the fixed parts of pseudo header
54 if (Tcb
->Sk
->IpVersion
== IP_VERSION_4
) {
55 Tcb
->HeadSum
= NetPseudoHeadChecksum (
56 Tcb
->LocalEnd
.Ip
.Addr
[0],
57 Tcb
->RemoteEnd
.Ip
.Addr
[0],
62 Tcb
->HeadSum
= NetIp6PseudoHeadChecksum (
64 &Tcb
->RemoteEnd
.Ip
.v6
,
70 Tcb
->Iss
= TcpGetIss ();
71 Tcb
->SndUna
= Tcb
->Iss
;
72 Tcb
->SndNxt
= Tcb
->Iss
;
74 Tcb
->SndWl2
= Tcb
->Iss
;
77 Tcb
->RcvWnd
= GET_RCV_BUFFSIZE (Tcb
->Sk
);
80 // First window size is never scaled
83 Tcb
->RetxmitSeqMax
= 0;
85 Tcb
->ProbeTimerOn
= FALSE
;
89 Initialize the peer related members.
91 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
92 @param[in] Seg Pointer to the segment that contains the peer's intial info.
93 @param[in] Opt Pointer to the options announced by the peer.
105 ASSERT ((Tcb
!= NULL
) && (Seg
!= NULL
) && (Opt
!= NULL
));
106 ASSERT (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_SYN
));
108 Tcb
->SndWnd
= Seg
->Wnd
;
109 Tcb
->SndWndMax
= Tcb
->SndWnd
;
110 Tcb
->SndWl1
= Seg
->Seq
;
112 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_ACK
)) {
113 Tcb
->SndWl2
= Seg
->Ack
;
115 Tcb
->SndWl2
= Tcb
->Iss
+ 1;
118 if (TCP_FLG_ON (Opt
->Flag
, TCP_OPTION_RCVD_MSS
)) {
119 Tcb
->SndMss
= (UINT16
) MAX (64, Opt
->Mss
);
121 RcvMss
= TcpGetRcvMss (Tcb
->Sk
);
122 if (Tcb
->SndMss
> RcvMss
) {
123 Tcb
->SndMss
= RcvMss
;
128 // One end doesn't support MSS option, use default.
133 Tcb
->CWnd
= Tcb
->SndMss
;
136 Tcb
->RcvNxt
= Tcb
->Irs
+ 1;
138 Tcb
->RcvWl2
= Tcb
->RcvNxt
;
140 if (TCP_FLG_ON (Opt
->Flag
, TCP_OPTION_RCVD_WS
) && !TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_WS
)) {
142 Tcb
->SndWndScale
= Opt
->WndScale
;
144 Tcb
->RcvWndScale
= TcpComputeScale (Tcb
);
145 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_RCVD_WS
);
149 // One end doesn't support window scale option. use zero.
151 Tcb
->RcvWndScale
= 0;
154 if (TCP_FLG_ON (Opt
->Flag
, TCP_OPTION_RCVD_TS
) && !TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_TS
)) {
156 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_SND_TS
);
157 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_RCVD_TS
);
159 Tcb
->TsRecent
= Opt
->TSVal
;
162 // Compute the effective SndMss per RFC1122
163 // section 4.2.2.6. If timestamp option is
164 // enabled, it will always occupy 12 bytes.
166 Tcb
->SndMss
-= TCP_OPTION_TS_ALIGNED_LEN
;
171 Check whether one IP address equals the other.
173 @param[in] Ip1 Pointer to IP address to be checked.
174 @param[in] Ip2 Pointer to IP address to be checked.
175 @param[in] Version IP_VERSION_4 indicates the IP address is an IPv4 address,
176 IP_VERSION_6 indicates the IP address is an IPv6 address.
178 @retval TRUE Ip1 equals Ip2.
179 @retval FALSE Ip1 does not equal Ip2.
184 IN EFI_IP_ADDRESS
*Ip1
,
185 IN EFI_IP_ADDRESS
*Ip2
,
189 ASSERT ((Version
== IP_VERSION_4
) || (Version
== IP_VERSION_6
));
191 if (Version
== IP_VERSION_4
) {
192 return (BOOLEAN
) (Ip1
->Addr
[0] == Ip2
->Addr
[0]);
194 return (BOOLEAN
) EFI_IP6_EQUAL (&Ip1
->v6
, &Ip2
->v6
);
199 Check whether one IP address is filled with ZERO.
201 @param[in] Ip Pointer to the IP address to be checked.
202 @param[in] Version IP_VERSION_4 indicates the IP address is an IPv4 address,
203 IP_VERSION_6 indicates the IP address is an IPv6 address.
205 @retval TRUE Ip is all zero address.
206 @retval FALSE Ip is not all zero address.
211 IN EFI_IP_ADDRESS
*Ip
,
215 ASSERT ((Version
== IP_VERSION_4
) || (Version
== IP_VERSION_6
));
217 if (Version
== IP_VERSION_4
) {
218 return (BOOLEAN
) (Ip
->Addr
[0] == 0);
220 return (BOOLEAN
) ((Ip
->Addr
[0] == 0) && (Ip
->Addr
[1] == 0) &&
221 (Ip
->Addr
[2] == 0) && (Ip
->Addr
[3] == 0));
226 Locate a listen TCB that matchs the Local and Remote.
228 @param[in] Local Pointer to the local (IP, Port).
229 @param[in] Remote Pointer to the remote (IP, Port).
230 @param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
231 IP_VERSION_6 indicates TCP is running on IP6 stack.
233 @return Pointer to the TCP_CB with the least number of wildcards,
234 if NULL no match is found.
253 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
254 Node
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
256 if ((Version
!= Node
->Sk
->IpVersion
) ||
257 (Local
->Port
!= Node
->LocalEnd
.Port
) ||
258 !TCP_PEER_MATCH (Remote
, &Node
->RemoteEnd
, Version
) ||
259 !TCP_PEER_MATCH (Local
, &Node
->LocalEnd
, Version
)
266 // Compute the number of wildcard
269 if (TcpIsIpZero (&Node
->RemoteEnd
.Ip
, Version
)) {
273 if (Node
->RemoteEnd
.Port
== 0) {
277 if (TcpIsIpZero (&Node
->LocalEnd
.Ip
, Version
)) {
295 Try to find one Tcb whose <Ip, Port> equals to <IN Addr, IN Port>.
297 @param[in] Addr Pointer to the IP address needs to match.
298 @param[in] Port The port number needs to match.
299 @param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
300 IP_VERSION_6 indicates TCP is running on IP6 stack.
303 @retval TRUE The Tcb which matches the <Addr Port> pair exists.
304 @retval FALSE Otherwise
309 IN EFI_IP_ADDRESS
*Addr
,
314 TCP_PORTNO LocalPort
;
318 ASSERT ((Addr
!= NULL
) && (Port
!= 0));
320 LocalPort
= HTONS (Port
);
322 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
323 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
325 if ((Version
== Tcb
->Sk
->IpVersion
) &&
326 TcpIsIpEqual (Addr
, &Tcb
->LocalEnd
.Ip
, Version
) &&
327 (LocalPort
== Tcb
->LocalEnd
.Port
)
334 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
335 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
337 if ((Version
== Tcb
->Sk
->IpVersion
) &&
338 TcpIsIpEqual (Addr
, &Tcb
->LocalEnd
.Ip
, Version
) &&
339 (LocalPort
== Tcb
->LocalEnd
.Port
)
350 Locate the TCP_CB related to the socket pair.
352 @param[in] LocalPort The local port number.
353 @param[in] LocalIp The local IP address.
354 @param[in] RemotePort The remote port number.
355 @param[in] RemoteIp The remote IP address.
356 @param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
357 IP_VERSION_6 indicates TCP is running on IP6 stack.
358 @param[in] Syn If TRUE, the listen sockets are searched.
360 @return Pointer to the related TCP_CB. If NULL, no match is found.
365 IN TCP_PORTNO LocalPort
,
366 IN EFI_IP_ADDRESS
*LocalIp
,
367 IN TCP_PORTNO RemotePort
,
368 IN EFI_IP_ADDRESS
*RemoteIp
,
378 Local
.Port
= LocalPort
;
379 Remote
.Port
= RemotePort
;
381 CopyMem (&Local
.Ip
, LocalIp
, sizeof (EFI_IP_ADDRESS
));
382 CopyMem (&Remote
.Ip
, RemoteIp
, sizeof (EFI_IP_ADDRESS
));
385 // First check for exact match.
387 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
388 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
390 if ((Version
== Tcb
->Sk
->IpVersion
) &&
391 TCP_PEER_EQUAL (&Remote
, &Tcb
->RemoteEnd
, Version
) &&
392 TCP_PEER_EQUAL (&Local
, &Tcb
->LocalEnd
, Version
)
395 RemoveEntryList (&Tcb
->List
);
396 InsertHeadList (&mTcpRunQue
, &Tcb
->List
);
403 // Only check the listen queue when the SYN flag is on.
406 return TcpLocateListenTcb (&Local
, &Remote
, Version
);
413 Insert a Tcb into the proper queue.
415 @param[in] Tcb Pointer to the TCP_CB to be inserted.
417 @retval 0 The Tcb was inserted successfully.
418 @retval -1 Error condition occurred.
433 (Tcb
->State
== TCP_LISTEN
) ||
434 (Tcb
->State
== TCP_SYN_SENT
) ||
435 (Tcb
->State
== TCP_SYN_RCVD
) ||
436 (Tcb
->State
== TCP_CLOSED
)
440 if (Tcb
->LocalEnd
.Port
== 0) {
446 if (Tcb
->State
== TCP_LISTEN
) {
447 Head
= &mTcpListenQue
;
451 // Check that the Tcb isn't already on the list.
453 NET_LIST_FOR_EACH (Entry
, Head
) {
454 Node
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
456 if (TCP_PEER_EQUAL (&Tcb
->LocalEnd
, &Node
->LocalEnd
, Tcb
->Sk
->IpVersion
) &&
457 TCP_PEER_EQUAL (&Tcb
->RemoteEnd
, &Node
->RemoteEnd
, Tcb
->Sk
->IpVersion
)
464 InsertHeadList (Head
, &Tcb
->List
);
471 Clone a TCP_CB from Tcb.
473 @param[in] Tcb Pointer to the TCP_CB to be cloned.
475 @return Pointer to the new cloned TCP_CB; if NULL, error condition occurred.
485 Clone
= AllocateZeroPool (sizeof (TCP_CB
));
491 CopyMem (Clone
, Tcb
, sizeof (TCP_CB
));
494 // Increase the reference count of the shared IpInfo.
496 NET_GET_REF (Tcb
->IpInfo
);
498 InitializeListHead (&Clone
->List
);
499 InitializeListHead (&Clone
->SndQue
);
500 InitializeListHead (&Clone
->RcvQue
);
502 Clone
->Sk
= SockClone (Tcb
->Sk
);
503 if (Clone
->Sk
== NULL
) {
504 DEBUG ((EFI_D_ERROR
, "TcpCloneTcb: failed to clone a sock\n"));
509 ((TCP_PROTO_DATA
*) (Clone
->Sk
->ProtoReserved
))->TcpPcb
= Clone
;
515 Compute an ISS to be used by a new connection.
517 @return The resulting ISS.
525 mTcpGlobalIss
+= TCP_ISS_INCREMENT_1
;
526 return mTcpGlobalIss
;
532 @param[in] Sock Pointer to the socket to get mss.
534 @return The mss size.
542 EFI_IP4_MODE_DATA Ip4Mode
;
543 EFI_IP6_MODE_DATA Ip6Mode
;
544 EFI_IP4_PROTOCOL
*Ip4
;
545 EFI_IP6_PROTOCOL
*Ip6
;
546 TCP_PROTO_DATA
*TcpProto
;
548 ASSERT (Sock
!= NULL
);
550 ZeroMem (&Ip4Mode
, sizeof (EFI_IP4_MODE_DATA
));
551 ZeroMem (&Ip6Mode
, sizeof (EFI_IP6_MODE_DATA
));
553 TcpProto
= (TCP_PROTO_DATA
*) Sock
->ProtoReserved
;
555 if (Sock
->IpVersion
== IP_VERSION_4
) {
556 Ip4
= TcpProto
->TcpService
->IpIo
->Ip
.Ip4
;
557 ASSERT (Ip4
!= NULL
);
558 Ip4
->GetModeData (Ip4
, &Ip4Mode
, NULL
, NULL
);
560 return (UINT16
) (Ip4Mode
.MaxPacketSize
- sizeof (TCP_HEAD
));
562 Ip6
= TcpProto
->TcpService
->IpIo
->Ip
.Ip6
;
563 ASSERT (Ip6
!= NULL
);
564 if (!EFI_ERROR (Ip6
->GetModeData (Ip6
, &Ip6Mode
, NULL
, NULL
))) {
565 if (Ip6Mode
.AddressList
!= NULL
) {
566 FreePool (Ip6Mode
.AddressList
);
569 if (Ip6Mode
.GroupTable
!= NULL
) {
570 FreePool (Ip6Mode
.GroupTable
);
573 if (Ip6Mode
.RouteTable
!= NULL
) {
574 FreePool (Ip6Mode
.RouteTable
);
577 if (Ip6Mode
.NeighborCache
!= NULL
) {
578 FreePool (Ip6Mode
.NeighborCache
);
581 if (Ip6Mode
.PrefixTable
!= NULL
) {
582 FreePool (Ip6Mode
.PrefixTable
);
585 if (Ip6Mode
.IcmpTypeList
!= NULL
) {
586 FreePool (Ip6Mode
.IcmpTypeList
);
590 return (UINT16
) (Ip6Mode
.MaxPacketSize
- sizeof (TCP_HEAD
));
597 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
598 @param[in] State The state to be set.
607 ASSERT (Tcb
->State
< (sizeof (mTcpStateName
) / sizeof (CHAR16
*)));
608 ASSERT (State
< (sizeof (mTcpStateName
) / sizeof (CHAR16
*)));
612 "Tcb (%p) state %s --> %s\n",
614 mTcpStateName
[Tcb
->State
],
615 mTcpStateName
[State
])
621 case TCP_ESTABLISHED
:
623 SockConnEstablished (Tcb
->Sk
);
625 if (Tcb
->Parent
!= NULL
) {
627 // A new connection is accepted by a listening socket. Install
630 TcpInstallDevicePath (Tcb
->Sk
);
637 SockConnClosed (Tcb
->Sk
);
646 Compute the TCP segment's checksum.
648 @param[in] Nbuf Pointer to the buffer that contains the TCP segment.
649 @param[in] HeadSum The checksum value of the fixed part of pseudo header.
651 @return The checksum value.
662 Checksum
= NetbufChecksum (Nbuf
);
663 Checksum
= NetAddChecksum (Checksum
, HeadSum
);
665 Checksum
= NetAddChecksum (
667 HTONS ((UINT16
) Nbuf
->TotalSize
)
670 return (UINT16
) (~Checksum
);
674 Translate the information from the head of the received TCP
675 segment Nbuf contents and fill it into a TCP_SEG structure.
677 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
678 @param[in, out] Nbuf Pointer to the buffer contains the TCP segment.
680 @return Pointer to the TCP_SEG that contains the translated TCP head information.
692 Seg
= TCPSEG_NETBUF (Nbuf
);
693 Head
= (TCP_HEAD
*) NetbufGetByte (Nbuf
, 0, NULL
);
694 ASSERT (Head
!= NULL
);
698 Seg
->Seq
= NTOHL (Head
->Seq
);
699 Seg
->Ack
= NTOHL (Head
->Ack
);
700 Seg
->End
= Seg
->Seq
+ (Nbuf
->TotalSize
- (Head
->HeadLen
<< 2));
702 Seg
->Urg
= NTOHS (Head
->Urg
);
703 Seg
->Wnd
= (NTOHS (Head
->Wnd
) << Tcb
->SndWndScale
);
704 Seg
->Flag
= Head
->Flag
;
707 // SYN and FIN flag occupy one sequence space each.
709 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_SYN
)) {
711 // RFC requires that the initial window not be scaled.
713 Seg
->Wnd
= NTOHS (Head
->Wnd
);
717 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_FIN
)) {
725 Initialize an active connection.
727 @param[in, out] Tcb Pointer to the TCP_CB that wants to initiate a
736 TcpInitTcbLocal (Tcb
);
737 TcpSetState (Tcb
, TCP_SYN_SENT
);
739 TcpSetTimer (Tcb
, TCP_TIMER_CONNECT
, Tcb
->ConnectTimeout
);
740 TcpToSendData (Tcb
, 1);
744 Initiate the connection close procedure, called when
745 applications want to close the connection.
747 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
755 ASSERT (Tcb
!= NULL
);
757 if (!IsListEmpty (&Tcb
->RcvQue
) || GET_RCV_DATASIZE (Tcb
->Sk
) != 0) {
761 "TcpOnAppClose: connection reset because data is lost for TCB %p\n",
765 TcpResetConnection (Tcb
);
770 switch (Tcb
->State
) {
774 TcpSetState (Tcb
, TCP_CLOSED
);
778 case TCP_ESTABLISHED
:
779 TcpSetState (Tcb
, TCP_FIN_WAIT_1
);
783 TcpSetState (Tcb
, TCP_LAST_ACK
);
789 TcpToSendData (Tcb
, 1);
793 Check whether the application's newly delivered data can be sent out.
795 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
797 @retval 0 The data has been sent out successfully.
798 @retval -1 The Tcb is not in a state that data is permitted to
808 switch (Tcb
->State
) {
819 case TCP_ESTABLISHED
:
821 TcpToSendData (Tcb
, 0);
839 Application has consumed some data. Check whether
840 to send a window update ack or a delayed ack.
842 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
852 switch (Tcb
->State
) {
853 case TCP_ESTABLISHED
:
854 TcpOld
= TcpRcvWinOld (Tcb
);
855 if (TcpRcvWinNow (Tcb
) > TcpOld
) {
857 if (TcpOld
< Tcb
->RcvMss
) {
861 "TcpOnAppConsume: send a window update for a window closed Tcb %p\n",
866 } else if (Tcb
->DelayedAck
== 0) {
870 "TcpOnAppConsume: scheduled a delayed ACK to update window for Tcb %p\n",
886 Abort the connection by sending a reset segment. Called
887 when the application wants to abort the connection.
889 @param[in] Tcb Pointer to the TCP_CB of the TCP instance.
899 "TcpOnAppAbort: connection reset issued by application for TCB %p\n",
903 switch (Tcb
->State
) {
905 case TCP_ESTABLISHED
:
909 TcpResetConnection (Tcb
);
915 TcpSetState (Tcb
, TCP_CLOSED
);
919 Reset the connection related with Tcb.
921 @param[in] Tcb Pointer to the TCP_CB of the connection to be reset.
932 Nbuf
= NetbufAlloc (TCP_MAX_HEAD
);
938 Nhead
= (TCP_HEAD
*) NetbufAllocSpace (
944 ASSERT (Nhead
!= NULL
);
948 Nhead
->Flag
= TCP_FLG_RST
;
949 Nhead
->Seq
= HTONL (Tcb
->SndNxt
);
950 Nhead
->Ack
= HTONL (Tcb
->RcvNxt
);
951 Nhead
->SrcPort
= Tcb
->LocalEnd
.Port
;
952 Nhead
->DstPort
= Tcb
->RemoteEnd
.Port
;
953 Nhead
->HeadLen
= (UINT8
) (sizeof (TCP_HEAD
) >> 2);
955 Nhead
->Wnd
= HTONS (0xFFFF);
958 Nhead
->Checksum
= TcpChecksum (Nbuf
, Tcb
->HeadSum
);
960 TcpSendIpPacket (Tcb
, Nbuf
, &Tcb
->LocalEnd
.Ip
, &Tcb
->RemoteEnd
.Ip
, Tcb
->Sk
->IpVersion
);
966 Install the device path protocol on the TCP instance.
968 @param[in] Sock Pointer to the socket representing the TCP instance.
970 @retval EFI_SUCCESS The device path protocol was installed.
971 @retval other Failed to install the device path protocol.
975 TcpInstallDevicePath (
979 TCP_PROTO_DATA
*TcpProto
;
980 TCP_SERVICE_DATA
*TcpService
;
982 IPv4_DEVICE_PATH Ip4DPathNode
;
983 IPv6_DEVICE_PATH Ip6DPathNode
;
984 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
986 TCP_PORTNO LocalPort
;
987 TCP_PORTNO RemotePort
;
989 TcpProto
= (TCP_PROTO_DATA
*) Sock
->ProtoReserved
;
990 TcpService
= TcpProto
->TcpService
;
991 Tcb
= TcpProto
->TcpPcb
;
993 LocalPort
= NTOHS (Tcb
->LocalEnd
.Port
);
994 RemotePort
= NTOHS (Tcb
->RemoteEnd
.Port
);
995 if (Sock
->IpVersion
== IP_VERSION_4
) {
996 NetLibCreateIPv4DPathNode (
998 TcpService
->ControllerHandle
,
999 Tcb
->LocalEnd
.Ip
.Addr
[0],
1001 Tcb
->RemoteEnd
.Ip
.Addr
[0],
1007 IP4_COPY_ADDRESS (&Ip4DPathNode
.SubnetMask
, &Tcb
->SubnetMask
);
1009 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) &Ip4DPathNode
;
1011 NetLibCreateIPv6DPathNode (
1013 TcpService
->ControllerHandle
,
1014 &Tcb
->LocalEnd
.Ip
.v6
,
1016 &Tcb
->RemoteEnd
.Ip
.v6
,
1021 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) &Ip6DPathNode
;
1024 Sock
->DevicePath
= AppendDevicePathNode (Sock
->ParentDevicePath
, DevicePath
);
1025 if (Sock
->DevicePath
== NULL
) {
1026 return EFI_OUT_OF_RESOURCES
;
1029 Status
= gBS
->InstallProtocolInterface (
1031 &gEfiDevicePathProtocolGuid
,
1032 EFI_NATIVE_INTERFACE
,
1035 if (EFI_ERROR (Status
)) {
1036 FreePool (Sock
->DevicePath
);
1037 Sock
->DevicePath
= NULL
;