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
[] = {
40 Initialize the Tcb local related members.
42 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
51 // Compute the checksum of the fixed parts of pseudo header
53 if (Tcb
->Sk
->IpVersion
== IP_VERSION_4
) {
54 Tcb
->HeadSum
= NetPseudoHeadChecksum (
55 Tcb
->LocalEnd
.Ip
.Addr
[0],
56 Tcb
->RemoteEnd
.Ip
.Addr
[0],
61 Tcb
->HeadSum
= NetIp6PseudoHeadChecksum (
63 &Tcb
->RemoteEnd
.Ip
.v6
,
69 Tcb
->Iss
= TcpGetIss ();
70 Tcb
->SndUna
= Tcb
->Iss
;
71 Tcb
->SndNxt
= Tcb
->Iss
;
73 Tcb
->SndWl2
= Tcb
->Iss
;
76 Tcb
->RcvWnd
= GET_RCV_BUFFSIZE (Tcb
->Sk
);
79 // First window size is never scaled
82 Tcb
->RetxmitSeqMax
= 0;
84 Tcb
->ProbeTimerOn
= FALSE
;
88 Initialize the peer related members.
90 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
91 @param[in] Seg Pointer to the segment that contains the peer's initial info.
92 @param[in] Opt Pointer to the options announced by the peer.
104 ASSERT ((Tcb
!= NULL
) && (Seg
!= NULL
) && (Opt
!= NULL
));
105 ASSERT (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_SYN
));
107 Tcb
->SndWnd
= Seg
->Wnd
;
108 Tcb
->SndWndMax
= Tcb
->SndWnd
;
109 Tcb
->SndWl1
= Seg
->Seq
;
111 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_ACK
)) {
112 Tcb
->SndWl2
= Seg
->Ack
;
114 Tcb
->SndWl2
= Tcb
->Iss
+ 1;
117 if (TCP_FLG_ON (Opt
->Flag
, TCP_OPTION_RCVD_MSS
)) {
118 Tcb
->SndMss
= (UINT16
)MAX (64, Opt
->Mss
);
120 RcvMss
= TcpGetRcvMss (Tcb
->Sk
);
121 if (Tcb
->SndMss
> RcvMss
) {
122 Tcb
->SndMss
= RcvMss
;
126 // One end doesn't support MSS option, use default.
131 Tcb
->CWnd
= Tcb
->SndMss
;
134 Tcb
->RcvNxt
= Tcb
->Irs
+ 1;
136 Tcb
->RcvWl2
= Tcb
->RcvNxt
;
138 if (TCP_FLG_ON (Opt
->Flag
, TCP_OPTION_RCVD_WS
) && !TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_WS
)) {
139 Tcb
->SndWndScale
= Opt
->WndScale
;
141 Tcb
->RcvWndScale
= TcpComputeScale (Tcb
);
142 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_RCVD_WS
);
145 // One end doesn't support window scale option. use zero.
147 Tcb
->RcvWndScale
= 0;
150 if (TCP_FLG_ON (Opt
->Flag
, TCP_OPTION_RCVD_TS
) && !TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_TS
)) {
151 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_SND_TS
);
152 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_RCVD_TS
);
154 Tcb
->TsRecent
= Opt
->TSVal
;
157 // Compute the effective SndMss per RFC1122
158 // section 4.2.2.6. If timestamp option is
159 // enabled, it will always occupy 12 bytes.
161 Tcb
->SndMss
-= TCP_OPTION_TS_ALIGNED_LEN
;
166 Check whether one IP address equals the other.
168 @param[in] Ip1 Pointer to IP address to be checked.
169 @param[in] Ip2 Pointer to IP address to be checked.
170 @param[in] Version IP_VERSION_4 indicates the IP address is an IPv4 address,
171 IP_VERSION_6 indicates the IP address is an IPv6 address.
173 @retval TRUE Ip1 equals Ip2.
174 @retval FALSE Ip1 does not equal Ip2.
179 IN EFI_IP_ADDRESS
*Ip1
,
180 IN EFI_IP_ADDRESS
*Ip2
,
184 ASSERT ((Version
== IP_VERSION_4
) || (Version
== IP_VERSION_6
));
186 if (Version
== IP_VERSION_4
) {
187 return (BOOLEAN
)(Ip1
->Addr
[0] == Ip2
->Addr
[0]);
189 return (BOOLEAN
)EFI_IP6_EQUAL (&Ip1
->v6
, &Ip2
->v6
);
194 Check whether one IP address is filled with ZERO.
196 @param[in] Ip Pointer to the IP address to be checked.
197 @param[in] Version IP_VERSION_4 indicates the IP address is an IPv4 address,
198 IP_VERSION_6 indicates the IP address is an IPv6 address.
200 @retval TRUE Ip is all zero address.
201 @retval FALSE Ip is not all zero address.
206 IN EFI_IP_ADDRESS
*Ip
,
210 ASSERT ((Version
== IP_VERSION_4
) || (Version
== IP_VERSION_6
));
212 if (Version
== IP_VERSION_4
) {
213 return (BOOLEAN
)(Ip
->Addr
[0] == 0);
215 return (BOOLEAN
)((Ip
->Addr
[0] == 0) && (Ip
->Addr
[1] == 0) &&
216 (Ip
->Addr
[2] == 0) && (Ip
->Addr
[3] == 0));
221 Locate a listen TCB that matchs the Local and Remote.
223 @param[in] Local Pointer to the local (IP, Port).
224 @param[in] Remote Pointer to the remote (IP, Port).
225 @param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
226 IP_VERSION_6 indicates TCP is running on IP6 stack.
228 @return Pointer to the TCP_CB with the least number of wildcards,
229 if NULL no match is found.
248 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
249 Node
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
251 if ((Version
!= Node
->Sk
->IpVersion
) ||
252 (Local
->Port
!= Node
->LocalEnd
.Port
) ||
253 !TCP_PEER_MATCH (Remote
, &Node
->RemoteEnd
, Version
) ||
254 !TCP_PEER_MATCH (Local
, &Node
->LocalEnd
, Version
)
261 // Compute the number of wildcard
264 if (TcpIsIpZero (&Node
->RemoteEnd
.Ip
, Version
)) {
268 if (Node
->RemoteEnd
.Port
== 0) {
272 if (TcpIsIpZero (&Node
->LocalEnd
.Ip
, Version
)) {
290 Try to find one Tcb whose <Ip, Port> equals to <IN Addr, IN Port>.
292 @param[in] Addr Pointer to the IP address needs to match.
293 @param[in] Port The port number needs to match.
294 @param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
295 IP_VERSION_6 indicates TCP is running on IP6 stack.
298 @retval TRUE The Tcb which matches the <Addr Port> pair exists.
299 @retval FALSE Otherwise
304 IN EFI_IP_ADDRESS
*Addr
,
309 TCP_PORTNO LocalPort
;
313 ASSERT ((Addr
!= NULL
) && (Port
!= 0));
315 LocalPort
= HTONS (Port
);
317 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
318 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
320 if ((Version
== Tcb
->Sk
->IpVersion
) &&
321 TcpIsIpEqual (Addr
, &Tcb
->LocalEnd
.Ip
, Version
) &&
322 (LocalPort
== Tcb
->LocalEnd
.Port
)
329 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
330 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
332 if ((Version
== Tcb
->Sk
->IpVersion
) &&
333 TcpIsIpEqual (Addr
, &Tcb
->LocalEnd
.Ip
, Version
) &&
334 (LocalPort
== Tcb
->LocalEnd
.Port
)
345 Locate the TCP_CB related to the socket pair.
347 @param[in] LocalPort The local port number.
348 @param[in] LocalIp The local IP address.
349 @param[in] RemotePort The remote port number.
350 @param[in] RemoteIp The remote IP address.
351 @param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
352 IP_VERSION_6 indicates TCP is running on IP6 stack.
353 @param[in] Syn If TRUE, the listen sockets are searched.
355 @return Pointer to the related TCP_CB. If NULL, no match is found.
360 IN TCP_PORTNO LocalPort
,
361 IN EFI_IP_ADDRESS
*LocalIp
,
362 IN TCP_PORTNO RemotePort
,
363 IN EFI_IP_ADDRESS
*RemoteIp
,
373 Local
.Port
= LocalPort
;
374 Remote
.Port
= RemotePort
;
376 CopyMem (&Local
.Ip
, LocalIp
, sizeof (EFI_IP_ADDRESS
));
377 CopyMem (&Remote
.Ip
, RemoteIp
, sizeof (EFI_IP_ADDRESS
));
380 // First check for exact match.
382 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
383 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
385 if ((Version
== Tcb
->Sk
->IpVersion
) &&
386 TCP_PEER_EQUAL (&Remote
, &Tcb
->RemoteEnd
, Version
) &&
387 TCP_PEER_EQUAL (&Local
, &Tcb
->LocalEnd
, Version
)
390 RemoveEntryList (&Tcb
->List
);
391 InsertHeadList (&mTcpRunQue
, &Tcb
->List
);
398 // Only check the listen queue when the SYN flag is on.
401 return TcpLocateListenTcb (&Local
, &Remote
, Version
);
408 Insert a Tcb into the proper queue.
410 @param[in] Tcb Pointer to the TCP_CB to be inserted.
412 @retval 0 The Tcb was inserted successfully.
413 @retval -1 Error condition occurred.
428 (Tcb
->State
== TCP_LISTEN
) ||
429 (Tcb
->State
== TCP_SYN_SENT
) ||
430 (Tcb
->State
== TCP_SYN_RCVD
) ||
431 (Tcb
->State
== TCP_CLOSED
)
435 if (Tcb
->LocalEnd
.Port
== 0) {
441 if (Tcb
->State
== TCP_LISTEN
) {
442 Head
= &mTcpListenQue
;
446 // Check that the Tcb isn't already on the list.
448 NET_LIST_FOR_EACH (Entry
, Head
) {
449 Node
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
451 if (TCP_PEER_EQUAL (&Tcb
->LocalEnd
, &Node
->LocalEnd
, Tcb
->Sk
->IpVersion
) &&
452 TCP_PEER_EQUAL (&Tcb
->RemoteEnd
, &Node
->RemoteEnd
, Tcb
->Sk
->IpVersion
)
459 InsertHeadList (Head
, &Tcb
->List
);
465 Clone a TCP_CB from Tcb.
467 @param[in] Tcb Pointer to the TCP_CB to be cloned.
469 @return Pointer to the new cloned TCP_CB; if NULL, error condition occurred.
479 Clone
= AllocateZeroPool (sizeof (TCP_CB
));
485 CopyMem (Clone
, Tcb
, sizeof (TCP_CB
));
488 // Increase the reference count of the shared IpInfo.
490 NET_GET_REF (Tcb
->IpInfo
);
492 InitializeListHead (&Clone
->List
);
493 InitializeListHead (&Clone
->SndQue
);
494 InitializeListHead (&Clone
->RcvQue
);
496 Clone
->Sk
= SockClone (Tcb
->Sk
);
497 if (Clone
->Sk
== NULL
) {
498 DEBUG ((DEBUG_ERROR
, "TcpCloneTcb: failed to clone a sock\n"));
503 ((TCP_PROTO_DATA
*)(Clone
->Sk
->ProtoReserved
))->TcpPcb
= Clone
;
509 Compute an ISS to be used by a new connection.
511 @return The resulting ISS.
519 mTcpGlobalIss
+= TCP_ISS_INCREMENT_1
;
520 return mTcpGlobalIss
;
526 @param[in] Sock Pointer to the socket to get mss.
528 @return The mss size.
536 EFI_IP4_MODE_DATA Ip4Mode
;
537 EFI_IP6_MODE_DATA Ip6Mode
;
538 EFI_IP4_PROTOCOL
*Ip4
;
539 EFI_IP6_PROTOCOL
*Ip6
;
540 TCP_PROTO_DATA
*TcpProto
;
542 ASSERT (Sock
!= NULL
);
544 ZeroMem (&Ip4Mode
, sizeof (EFI_IP4_MODE_DATA
));
545 ZeroMem (&Ip6Mode
, sizeof (EFI_IP6_MODE_DATA
));
547 TcpProto
= (TCP_PROTO_DATA
*)Sock
->ProtoReserved
;
549 if (Sock
->IpVersion
== IP_VERSION_4
) {
550 Ip4
= TcpProto
->TcpService
->IpIo
->Ip
.Ip4
;
551 ASSERT (Ip4
!= NULL
);
552 Ip4
->GetModeData (Ip4
, &Ip4Mode
, NULL
, NULL
);
554 return (UINT16
)(Ip4Mode
.MaxPacketSize
- sizeof (TCP_HEAD
));
556 Ip6
= TcpProto
->TcpService
->IpIo
->Ip
.Ip6
;
557 ASSERT (Ip6
!= NULL
);
558 if (!EFI_ERROR (Ip6
->GetModeData (Ip6
, &Ip6Mode
, NULL
, NULL
))) {
559 if (Ip6Mode
.AddressList
!= NULL
) {
560 FreePool (Ip6Mode
.AddressList
);
563 if (Ip6Mode
.GroupTable
!= NULL
) {
564 FreePool (Ip6Mode
.GroupTable
);
567 if (Ip6Mode
.RouteTable
!= NULL
) {
568 FreePool (Ip6Mode
.RouteTable
);
571 if (Ip6Mode
.NeighborCache
!= NULL
) {
572 FreePool (Ip6Mode
.NeighborCache
);
575 if (Ip6Mode
.PrefixTable
!= NULL
) {
576 FreePool (Ip6Mode
.PrefixTable
);
579 if (Ip6Mode
.IcmpTypeList
!= NULL
) {
580 FreePool (Ip6Mode
.IcmpTypeList
);
584 return (UINT16
)(Ip6Mode
.MaxPacketSize
- sizeof (TCP_HEAD
));
591 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
592 @param[in] State The state to be set.
601 ASSERT (Tcb
->State
< (sizeof (mTcpStateName
) / sizeof (CHAR16
*)));
602 ASSERT (State
< (sizeof (mTcpStateName
) / sizeof (CHAR16
*)));
606 "Tcb (%p) state %s --> %s\n",
608 mTcpStateName
[Tcb
->State
],
609 mTcpStateName
[State
])
615 case TCP_ESTABLISHED
:
617 SockConnEstablished (Tcb
->Sk
);
619 if (Tcb
->Parent
!= NULL
) {
621 // A new connection is accepted by a listening socket. Install
624 TcpInstallDevicePath (Tcb
->Sk
);
631 SockConnClosed (Tcb
->Sk
);
640 Compute the TCP segment's checksum.
642 @param[in] Nbuf Pointer to the buffer that contains the TCP segment.
643 @param[in] HeadSum The checksum value of the fixed part of pseudo header.
645 @return The checksum value.
656 Checksum
= NetbufChecksum (Nbuf
);
657 Checksum
= NetAddChecksum (Checksum
, HeadSum
);
659 Checksum
= NetAddChecksum (
661 HTONS ((UINT16
)Nbuf
->TotalSize
)
664 return (UINT16
)(~Checksum
);
668 Translate the information from the head of the received TCP
669 segment Nbuf contents and fill it into a TCP_SEG structure.
671 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
672 @param[in, out] Nbuf Pointer to the buffer contains the TCP segment.
674 @return Pointer to the TCP_SEG that contains the translated TCP head information.
686 Seg
= TCPSEG_NETBUF (Nbuf
);
687 Head
= (TCP_HEAD
*)NetbufGetByte (Nbuf
, 0, NULL
);
688 ASSERT (Head
!= NULL
);
692 Seg
->Seq
= NTOHL (Head
->Seq
);
693 Seg
->Ack
= NTOHL (Head
->Ack
);
694 Seg
->End
= Seg
->Seq
+ (Nbuf
->TotalSize
- (Head
->HeadLen
<< 2));
696 Seg
->Urg
= NTOHS (Head
->Urg
);
697 Seg
->Wnd
= (NTOHS (Head
->Wnd
) << Tcb
->SndWndScale
);
698 Seg
->Flag
= Head
->Flag
;
701 // SYN and FIN flag occupy one sequence space each.
703 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_SYN
)) {
705 // RFC requires that the initial window not be scaled.
707 Seg
->Wnd
= NTOHS (Head
->Wnd
);
711 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_FIN
)) {
719 Initialize an active connection.
721 @param[in, out] Tcb Pointer to the TCP_CB that wants to initiate a
730 TcpInitTcbLocal (Tcb
);
731 TcpSetState (Tcb
, TCP_SYN_SENT
);
733 TcpSetTimer (Tcb
, TCP_TIMER_CONNECT
, Tcb
->ConnectTimeout
);
734 TcpToSendData (Tcb
, 1);
738 Initiate the connection close procedure, called when
739 applications want to close the connection.
741 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
749 ASSERT (Tcb
!= NULL
);
751 if (!IsListEmpty (&Tcb
->RcvQue
) || (GET_RCV_DATASIZE (Tcb
->Sk
) != 0)) {
754 "TcpOnAppClose: connection reset because data is lost for TCB %p\n",
758 TcpResetConnection (Tcb
);
763 switch (Tcb
->State
) {
767 TcpSetState (Tcb
, TCP_CLOSED
);
771 case TCP_ESTABLISHED
:
772 TcpSetState (Tcb
, TCP_FIN_WAIT_1
);
776 TcpSetState (Tcb
, TCP_LAST_ACK
);
782 TcpToSendData (Tcb
, 1);
786 Check whether the application's newly delivered data can be sent out.
788 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
790 @retval 0 The data has been sent out successfully.
791 @retval -1 The Tcb is not in a state that data is permitted to
800 switch (Tcb
->State
) {
811 case TCP_ESTABLISHED
:
813 TcpToSendData (Tcb
, 0);
831 Application has consumed some data. Check whether
832 to send a window update ack or a delayed ack.
834 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
844 switch (Tcb
->State
) {
845 case TCP_ESTABLISHED
:
846 TcpOld
= TcpRcvWinOld (Tcb
);
847 if (TcpRcvWinNow (Tcb
) > TcpOld
) {
848 if (TcpOld
< Tcb
->RcvMss
) {
851 "TcpOnAppConsume: send a window update for a window closed Tcb %p\n",
856 } else if (Tcb
->DelayedAck
== 0) {
859 "TcpOnAppConsume: scheduled a delayed ACK to update window for Tcb %p\n",
875 Abort the connection by sending a reset segment. Called
876 when the application wants to abort the connection.
878 @param[in] Tcb Pointer to the TCP_CB of the TCP instance.
888 "TcpOnAppAbort: connection reset issued by application for TCB %p\n",
892 switch (Tcb
->State
) {
894 case TCP_ESTABLISHED
:
898 TcpResetConnection (Tcb
);
904 TcpSetState (Tcb
, TCP_CLOSED
);
908 Reset the connection related with Tcb.
910 @param[in] Tcb Pointer to the TCP_CB of the connection to be reset.
921 Nbuf
= NetbufAlloc (TCP_MAX_HEAD
);
927 Nhead
= (TCP_HEAD
*)NetbufAllocSpace (
933 ASSERT (Nhead
!= NULL
);
937 Nhead
->Flag
= TCP_FLG_RST
;
938 Nhead
->Seq
= HTONL (Tcb
->SndNxt
);
939 Nhead
->Ack
= HTONL (Tcb
->RcvNxt
);
940 Nhead
->SrcPort
= Tcb
->LocalEnd
.Port
;
941 Nhead
->DstPort
= Tcb
->RemoteEnd
.Port
;
942 Nhead
->HeadLen
= (UINT8
)(sizeof (TCP_HEAD
) >> 2);
944 Nhead
->Wnd
= HTONS (0xFFFF);
947 Nhead
->Checksum
= TcpChecksum (Nbuf
, Tcb
->HeadSum
);
949 TcpSendIpPacket (Tcb
, Nbuf
, &Tcb
->LocalEnd
.Ip
, &Tcb
->RemoteEnd
.Ip
, Tcb
->Sk
->IpVersion
);
955 Install the device path protocol on the TCP instance.
957 @param[in] Sock Pointer to the socket representing the TCP instance.
959 @retval EFI_SUCCESS The device path protocol was installed.
960 @retval other Failed to install the device path protocol.
964 TcpInstallDevicePath (
968 TCP_PROTO_DATA
*TcpProto
;
969 TCP_SERVICE_DATA
*TcpService
;
971 IPv4_DEVICE_PATH Ip4DPathNode
;
972 IPv6_DEVICE_PATH Ip6DPathNode
;
973 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
975 TCP_PORTNO LocalPort
;
976 TCP_PORTNO RemotePort
;
978 TcpProto
= (TCP_PROTO_DATA
*)Sock
->ProtoReserved
;
979 TcpService
= TcpProto
->TcpService
;
980 Tcb
= TcpProto
->TcpPcb
;
982 LocalPort
= NTOHS (Tcb
->LocalEnd
.Port
);
983 RemotePort
= NTOHS (Tcb
->RemoteEnd
.Port
);
984 if (Sock
->IpVersion
== IP_VERSION_4
) {
985 NetLibCreateIPv4DPathNode (
987 TcpService
->ControllerHandle
,
988 Tcb
->LocalEnd
.Ip
.Addr
[0],
990 Tcb
->RemoteEnd
.Ip
.Addr
[0],
996 IP4_COPY_ADDRESS (&Ip4DPathNode
.SubnetMask
, &Tcb
->SubnetMask
);
998 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*)&Ip4DPathNode
;
1000 NetLibCreateIPv6DPathNode (
1002 TcpService
->ControllerHandle
,
1003 &Tcb
->LocalEnd
.Ip
.v6
,
1005 &Tcb
->RemoteEnd
.Ip
.v6
,
1010 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*)&Ip6DPathNode
;
1013 Sock
->DevicePath
= AppendDevicePathNode (Sock
->ParentDevicePath
, DevicePath
);
1014 if (Sock
->DevicePath
== NULL
) {
1015 return EFI_OUT_OF_RESOURCES
;
1018 Status
= gBS
->InstallProtocolInterface (
1020 &gEfiDevicePathProtocolGuid
,
1021 EFI_NATIVE_INTERFACE
,
1024 if (EFI_ERROR (Status
)) {
1025 FreePool (Sock
->DevicePath
);
1026 Sock
->DevicePath
= NULL
;