2 Misc support routines for tcp.
4 Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php<BR>
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include <Library/DevicePathLib.h>
20 LIST_ENTRY mTcpRunQue
= {
25 LIST_ENTRY mTcpListenQue
= {
30 TCP_SEQNO mTcpGlobalIss
= 0x4d7e980b;
32 CHAR16
*mTcpStateName
[] = {
48 Initialize the Tcb local related members.
50 @param Tcb Pointer to the TCP_CB of this TCP instance.
59 // Compute the checksum of the fixed parts of pseudo header
61 Tcb
->HeadSum
= NetPseudoHeadChecksum (
68 Tcb
->Iss
= TcpGetIss ();
69 Tcb
->SndUna
= Tcb
->Iss
;
70 Tcb
->SndNxt
= Tcb
->Iss
;
72 Tcb
->SndWl2
= Tcb
->Iss
;
75 Tcb
->RcvWnd
= GET_RCV_BUFFSIZE (Tcb
->Sk
);
78 // First window size is never scaled
82 Tcb
->ProbeTimerOn
= FALSE
;
87 Initialize the peer related members.
89 @param Tcb Pointer to the TCP_CB of this TCP instance.
90 @param Seg Pointer to the segment that contains the peer's
92 @param 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
;
127 // One end doesn't support MSS option, use default.
132 Tcb
->CWnd
= Tcb
->SndMss
;
135 Tcb
->RcvNxt
= Tcb
->Irs
+ 1;
137 Tcb
->RcvWl2
= Tcb
->RcvNxt
;
139 if (TCP_FLG_ON (Opt
->Flag
, TCP_OPTION_RCVD_WS
) &&
140 !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
) &&
155 !TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_TS
)) {
157 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_SND_TS
);
158 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_RCVD_TS
);
161 // Compute the effective SndMss per RFC1122
162 // section 4.2.2.6. If timestamp option is
163 // enabled, it will always occupy 12 bytes.
165 Tcb
->SndMss
-= TCP_OPTION_TS_ALIGNED_LEN
;
171 Locate a listen TCB that matchs the Local and Remote.
173 @param Local Pointer to the local (IP, Port).
174 @param Remote Pointer to the remote (IP, Port).
176 @return Pointer to the TCP_CB with the least number of wildcard,
177 if NULL no match is found.
195 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
196 Node
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
198 if ((Local
->Port
!= Node
->LocalEnd
.Port
) ||
199 !TCP_PEER_MATCH (Remote
, &Node
->RemoteEnd
) ||
200 !TCP_PEER_MATCH (Local
, &Node
->LocalEnd
)) {
206 // Compute the number of wildcard
209 if (Node
->RemoteEnd
.Ip
== 0) {
213 if (Node
->RemoteEnd
.Port
== 0) {
217 if (Node
->LocalEnd
.Ip
== 0) {
236 Try to find one Tcb whose <Ip, Port> equals to <IN Addr, IN Port>.
238 @param Addr Pointer to the IP address needs to match.
239 @param Port The port number needs to match.
241 @return The Tcb which matches the <Addr Port> paire exists or not.
246 IN EFI_IPv4_ADDRESS
*Addr
,
250 TCP_PORTNO LocalPort
;
254 ASSERT ((Addr
!= NULL
) && (Port
!= 0));
256 LocalPort
= HTONS (Port
);
258 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
259 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
261 if (EFI_IP4_EQUAL (Addr
, &Tcb
->LocalEnd
.Ip
) &&
262 (LocalPort
== Tcb
->LocalEnd
.Port
)) {
268 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
269 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
271 if (EFI_IP4_EQUAL (Addr
, &Tcb
->LocalEnd
.Ip
) &&
272 (LocalPort
== Tcb
->LocalEnd
.Port
)) {
283 Locate the TCP_CB related to the socket pair.
285 @param LocalPort The local port number.
286 @param LocalIp The local IP address.
287 @param RemotePort The remote port number.
288 @param RemoteIp The remote IP address.
289 @param Syn Whether to search the listen sockets, if TRUE, the
290 listen sockets are searched.
292 @return Pointer to the related TCP_CB, if NULL no match is found.
297 IN TCP_PORTNO LocalPort
,
299 IN TCP_PORTNO RemotePort
,
309 Local
.Port
= LocalPort
;
312 Remote
.Port
= RemotePort
;
313 Remote
.Ip
= RemoteIp
;
316 // First check for exact match.
318 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
319 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
321 if (TCP_PEER_EQUAL (&Remote
, &Tcb
->RemoteEnd
) &&
322 TCP_PEER_EQUAL (&Local
, &Tcb
->LocalEnd
)) {
324 RemoveEntryList (&Tcb
->List
);
325 InsertHeadList (&mTcpRunQue
, &Tcb
->List
);
332 // Only check listen queue when SYN flag is on
335 return TcpLocateListenTcb (&Local
, &Remote
);
343 Insert a Tcb into the proper queue.
345 @param Tcb Pointer to the TCP_CB to be inserted.
347 @retval 0 The Tcb is inserted successfully.
348 @retval -1 Error condition occurred.
359 TCP4_PROTO_DATA
*TcpProto
;
363 ((Tcb
->State
== TCP_LISTEN
) ||
364 (Tcb
->State
== TCP_SYN_SENT
) ||
365 (Tcb
->State
== TCP_SYN_RCVD
) ||
366 (Tcb
->State
== TCP_CLOSED
))
369 if (Tcb
->LocalEnd
.Port
== 0) {
375 if (Tcb
->State
== TCP_LISTEN
) {
376 Head
= &mTcpListenQue
;
380 // Check that Tcb isn't already on the list.
382 NET_LIST_FOR_EACH (Entry
, Head
) {
383 Node
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
385 if (TCP_PEER_EQUAL (&Tcb
->LocalEnd
, &Node
->LocalEnd
) &&
386 TCP_PEER_EQUAL (&Tcb
->RemoteEnd
, &Node
->RemoteEnd
)) {
392 InsertHeadList (Head
, &Tcb
->List
);
394 TcpProto
= (TCP4_PROTO_DATA
*) Tcb
->Sk
->ProtoReserved
;
395 TcpSetVariableData (TcpProto
->TcpService
);
402 Clone a TCB_CB from Tcb.
404 @param Tcb Pointer to the TCP_CB to be cloned.
406 @return Pointer to the new cloned TCP_CB, if NULL error condition occurred.
416 Clone
= AllocatePool (sizeof (TCP_CB
));
423 CopyMem (Clone
, Tcb
, sizeof (TCP_CB
));
426 // Increate the reference count of the shared IpInfo.
428 NET_GET_REF (Tcb
->IpInfo
);
430 InitializeListHead (&Clone
->List
);
431 InitializeListHead (&Clone
->SndQue
);
432 InitializeListHead (&Clone
->RcvQue
);
434 Clone
->Sk
= SockClone (Tcb
->Sk
);
435 if (Clone
->Sk
== NULL
) {
436 DEBUG ((EFI_D_ERROR
, "TcpCloneTcb: failed to clone a sock\n"));
441 ((TCP4_PROTO_DATA
*) (Clone
->Sk
->ProtoReserved
))->TcpPcb
= Clone
;
448 Compute an ISS to be used by a new connection.
450 @return The result ISS.
458 mTcpGlobalIss
+= 2048;
459 return mTcpGlobalIss
;
466 @param Sock Pointer to the socket to get mss
468 @return The mss size.
476 EFI_IP4_MODE_DATA Ip4Mode
;
477 TCP4_PROTO_DATA
*TcpProto
;
478 EFI_IP4_PROTOCOL
*Ip
;
480 ASSERT (Sock
!= NULL
);
482 TcpProto
= (TCP4_PROTO_DATA
*) Sock
->ProtoReserved
;
483 Ip
= TcpProto
->TcpService
->IpIo
->Ip
.Ip4
;
486 Ip
->GetModeData (Ip
, &Ip4Mode
, NULL
, NULL
);
488 return (UINT16
) (Ip4Mode
.MaxPacketSize
- sizeof (TCP_HEAD
));
495 @param Tcb Pointer to the TCP_CB of this TCP instance.
496 @param State The state to be set.
505 ASSERT (Tcb
->State
< (sizeof (mTcpStateName
) / sizeof (CHAR16
*)));
506 ASSERT (State
< (sizeof (mTcpStateName
) / sizeof (CHAR16
*)));
510 "Tcb (%p) state %s --> %s\n",
512 mTcpStateName
[Tcb
->State
],
513 mTcpStateName
[State
])
519 case TCP_ESTABLISHED
:
521 SockConnEstablished (Tcb
->Sk
);
523 if (Tcb
->Parent
!= NULL
) {
525 // A new connection is accepted by a listening socket, install
528 TcpInstallDevicePath (Tcb
->Sk
);
535 SockConnClosed (Tcb
->Sk
);
545 Compute the TCP segment's checksum.
547 @param Nbuf Pointer to the buffer that contains the TCP
549 @param HeadSum The checksum value of the fixed part of pseudo
552 @return The checksum value.
563 Checksum
= NetbufChecksum (Nbuf
);
564 Checksum
= NetAddChecksum (Checksum
, HeadSum
);
566 Checksum
= NetAddChecksum (
568 HTONS ((UINT16
) Nbuf
->TotalSize
)
571 return (UINT16
) ~Checksum
;
575 Translate the information from the head of the received TCP
576 segment Nbuf contains and fill it into a TCP_SEG structure.
578 @param Tcb Pointer to the TCP_CB of this TCP instance.
579 @param Nbuf Pointer to the buffer contains the TCP segment.
581 @return Pointer to the TCP_SEG that contains the translated TCP head information.
593 Seg
= TCPSEG_NETBUF (Nbuf
);
594 Head
= (TCP_HEAD
*) NetbufGetByte (Nbuf
, 0, NULL
);
595 ASSERT (Head
!= NULL
);
598 Seg
->Seq
= NTOHL (Head
->Seq
);
599 Seg
->Ack
= NTOHL (Head
->Ack
);
600 Seg
->End
= Seg
->Seq
+ (Nbuf
->TotalSize
- (Head
->HeadLen
<< 2));
602 Seg
->Urg
= NTOHS (Head
->Urg
);
603 Seg
->Wnd
= (NTOHS (Head
->Wnd
) << Tcb
->SndWndScale
);
604 Seg
->Flag
= Head
->Flag
;
607 // SYN and FIN flag occupy one sequence space each.
609 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_SYN
)) {
611 // RFC requires that initial window not be scaled
613 Seg
->Wnd
= NTOHS (Head
->Wnd
);
617 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_FIN
)) {
626 Reset the connection related with Tcb.
628 @param Tcb Pointer to the TCP_CB of the connection to be
640 Nbuf
= NetbufAlloc (TCP_MAX_HEAD
);
646 Nhead
= (TCP_HEAD
*) NetbufAllocSpace (
652 ASSERT (Nhead
!= NULL
);
656 Nhead
->Flag
= TCP_FLG_RST
;
657 Nhead
->Seq
= HTONL (Tcb
->SndNxt
);
658 Nhead
->Ack
= HTONL (Tcb
->RcvNxt
);
659 Nhead
->SrcPort
= Tcb
->LocalEnd
.Port
;
660 Nhead
->DstPort
= Tcb
->RemoteEnd
.Port
;
661 Nhead
->HeadLen
= (UINT8
) (sizeof (TCP_HEAD
) >> 2);
663 Nhead
->Wnd
= HTONS (0xFFFF);
666 Nhead
->Checksum
= TcpChecksum (Nbuf
, Tcb
->HeadSum
);
668 TcpSendIpPacket (Tcb
, Nbuf
, Tcb
->LocalEnd
.Ip
, Tcb
->RemoteEnd
.Ip
);
675 Initialize an active connection.
677 @param Tcb Pointer to the TCP_CB that wants to initiate a
686 TcpInitTcbLocal (Tcb
);
687 TcpSetState (Tcb
, TCP_SYN_SENT
);
689 TcpSetTimer (Tcb
, TCP_TIMER_CONNECT
, Tcb
->ConnectTimeout
);
690 TcpToSendData (Tcb
, 1);
695 Initiate the connection close procedure, called when
696 applications want to close the connection.
698 @param Tcb Pointer to the TCP_CB of this TCP instance.
706 ASSERT (Tcb
!= NULL
);
708 if (!IsListEmpty (&Tcb
->RcvQue
) || GET_RCV_DATASIZE (Tcb
->Sk
) != 0) {
710 DEBUG ((EFI_D_WARN
, "TcpOnAppClose: connection reset "
711 "because data is lost for TCB %p\n", Tcb
));
713 TcpResetConnection (Tcb
);
718 switch (Tcb
->State
) {
722 TcpSetState (Tcb
, TCP_CLOSED
);
726 case TCP_ESTABLISHED
:
727 TcpSetState (Tcb
, TCP_FIN_WAIT_1
);
731 TcpSetState (Tcb
, TCP_LAST_ACK
);
737 TcpToSendData (Tcb
, 1);
742 Check whether the application's newly delivered data can be sent out.
744 @param Tcb Pointer to the TCP_CB of this TCP instance.
746 @retval 0 Whether the data is sent out or is buffered for
748 @retval -1 The Tcb is not in a state that data is permitted to
758 switch (Tcb
->State
) {
769 case TCP_ESTABLISHED
:
771 TcpToSendData (Tcb
, 0);
790 Application has consumed some data, check whether
791 to send a window updata ack or a delayed ack.
793 @param Tcb Pointer to the TCP_CB of this TCP instance.
803 switch (Tcb
->State
) {
814 case TCP_ESTABLISHED
:
815 TcpOld
= TcpRcvWinOld (Tcb
);
816 if (TcpRcvWinNow (Tcb
) > TcpOld
) {
818 if (TcpOld
< Tcb
->RcvMss
) {
820 DEBUG ((EFI_D_INFO
, "TcpOnAppConsume: send a window"
821 " update for a window closed Tcb %p\n", Tcb
));
824 } else if (Tcb
->DelayedAck
== 0) {
826 DEBUG ((EFI_D_INFO
, "TcpOnAppConsume: scheduled a delayed"
827 " ACK to update window for Tcb %p\n", Tcb
));
852 Abort the connection by sending a reset segment, called
853 when the application wants to abort the connection.
855 @param Tcb Pointer to the TCP_CB of the TCP instance.
863 DEBUG ((EFI_D_WARN
, "TcpOnAppAbort: connection reset "
864 "issued by application for TCB %p\n", Tcb
));
866 switch (Tcb
->State
) {
868 case TCP_ESTABLISHED
:
872 TcpResetConnection (Tcb
);
878 TcpSetState (Tcb
, TCP_CLOSED
);
883 Set the Tdp4 variable data.
885 @param Tcp4Service Pointer to Tcp4 service data.
887 @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the variable.
888 @retval other Set variable failed.
893 IN TCP4_SERVICE_DATA
*Tcp4Service
896 UINT32 NumConfiguredInstance
;
899 TCP4_PROTO_DATA
*TcpProto
;
900 UINTN VariableDataSize
;
901 EFI_TCP4_VARIABLE_DATA
*Tcp4VariableData
;
902 EFI_TCP4_SERVICE_POINT
*Tcp4ServicePoint
;
903 CHAR16
*NewMacString
;
906 NumConfiguredInstance
= 0;
909 // Go through the running queue to count the instances.
911 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
912 TcpPcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
914 TcpProto
= (TCP4_PROTO_DATA
*) TcpPcb
->Sk
->ProtoReserved
;
916 if (TcpProto
->TcpService
== Tcp4Service
) {
918 // This tcp instance belongs to the Tcp4Service.
920 NumConfiguredInstance
++;
925 // Go through the listening queue to count the instances.
927 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
928 TcpPcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
930 TcpProto
= (TCP4_PROTO_DATA
*) TcpPcb
->Sk
->ProtoReserved
;
932 if (TcpProto
->TcpService
== Tcp4Service
) {
934 // This tcp instance belongs to the Tcp4Service.
936 NumConfiguredInstance
++;
941 // Calculate the size of the Tcp4VariableData. As there may be no Tcp4 child,
942 // we should add extra buffer for the service points only if the number of configured
943 // children is more than 1.
945 VariableDataSize
= sizeof (EFI_TCP4_VARIABLE_DATA
);
947 if (NumConfiguredInstance
> 1) {
948 VariableDataSize
+= sizeof (EFI_TCP4_SERVICE_POINT
) * (NumConfiguredInstance
- 1);
951 Tcp4VariableData
= AllocatePool (VariableDataSize
);
952 if (Tcp4VariableData
== NULL
) {
953 return EFI_OUT_OF_RESOURCES
;
956 Tcp4VariableData
->DriverHandle
= Tcp4Service
->DriverBindingHandle
;
957 Tcp4VariableData
->ServiceCount
= NumConfiguredInstance
;
959 Tcp4ServicePoint
= &Tcp4VariableData
->Services
[0];
962 // Go through the running queue to fill the service points.
964 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
965 TcpPcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
967 TcpProto
= (TCP4_PROTO_DATA
*) TcpPcb
->Sk
->ProtoReserved
;
969 if (TcpProto
->TcpService
== Tcp4Service
) {
971 // This tcp instance belongs to the Tcp4Service.
973 Tcp4ServicePoint
->InstanceHandle
= TcpPcb
->Sk
->SockHandle
;
974 CopyMem (&Tcp4ServicePoint
->LocalAddress
, &TcpPcb
->LocalEnd
.Ip
, sizeof (EFI_IPv4_ADDRESS
));
975 Tcp4ServicePoint
->LocalPort
= NTOHS (TcpPcb
->LocalEnd
.Port
);
976 CopyMem (&Tcp4ServicePoint
->RemoteAddress
, &TcpPcb
->RemoteEnd
.Ip
, sizeof (EFI_IPv4_ADDRESS
));
977 Tcp4ServicePoint
->RemotePort
= NTOHS (TcpPcb
->RemoteEnd
.Port
);
984 // Go through the listening queue to fill the service points.
986 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
987 TcpPcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
989 TcpProto
= (TCP4_PROTO_DATA
*) TcpPcb
->Sk
->ProtoReserved
;
991 if (TcpProto
->TcpService
== Tcp4Service
) {
993 // This tcp instance belongs to the Tcp4Service.
995 Tcp4ServicePoint
->InstanceHandle
= TcpPcb
->Sk
->SockHandle
;
996 CopyMem (&Tcp4ServicePoint
->LocalAddress
, &TcpPcb
->LocalEnd
.Ip
, sizeof (EFI_IPv4_ADDRESS
));
997 Tcp4ServicePoint
->LocalPort
= NTOHS (TcpPcb
->LocalEnd
.Port
);
998 CopyMem (&Tcp4ServicePoint
->RemoteAddress
, &TcpPcb
->RemoteEnd
.Ip
, sizeof (EFI_IPv4_ADDRESS
));
999 Tcp4ServicePoint
->RemotePort
= NTOHS (TcpPcb
->RemoteEnd
.Port
);
1006 // Get the mac string.
1008 Status
= NetLibGetMacString (
1009 Tcp4Service
->ControllerHandle
,
1010 Tcp4Service
->DriverBindingHandle
,
1013 if (EFI_ERROR (Status
)) {
1017 if (Tcp4Service
->MacString
!= NULL
) {
1019 // The variable is set already, we're going to update it.
1021 if (StrCmp (Tcp4Service
->MacString
, NewMacString
) != 0) {
1023 // The mac address is changed, delete the previous variable first.
1026 Tcp4Service
->MacString
,
1027 &gEfiTcp4ServiceBindingProtocolGuid
,
1028 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1034 FreePool (Tcp4Service
->MacString
);
1037 Tcp4Service
->MacString
= NewMacString
;
1039 Status
= gRT
->SetVariable (
1040 Tcp4Service
->MacString
,
1041 &gEfiTcp4ServiceBindingProtocolGuid
,
1042 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1044 (VOID
*) Tcp4VariableData
1049 FreePool (Tcp4VariableData
);
1056 Clear the variable and free the resource.
1058 @param Tcp4Service Pointer to Tcp4 service data.
1062 TcpClearVariableData (
1063 IN TCP4_SERVICE_DATA
*Tcp4Service
1066 ASSERT (Tcp4Service
->MacString
!= NULL
);
1069 Tcp4Service
->MacString
,
1070 &gEfiTcp4ServiceBindingProtocolGuid
,
1071 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1076 FreePool (Tcp4Service
->MacString
);
1077 Tcp4Service
->MacString
= NULL
;
1081 Install the device path protocol on the TCP instance.
1083 @param Sock Pointer to the socket representing the TCP instance.
1085 @retval EFI_SUCCESS The device path protocol is installed.
1086 @retval other Failed to install the device path protocol.
1090 TcpInstallDevicePath (
1094 TCP4_PROTO_DATA
*TcpProto
;
1095 TCP4_SERVICE_DATA
*TcpService
;
1097 IPv4_DEVICE_PATH Ip4DPathNode
;
1099 TCP_PORTNO LocalPort
;
1100 TCP_PORTNO RemotePort
;
1102 TcpProto
= (TCP4_PROTO_DATA
*) Sock
->ProtoReserved
;
1103 TcpService
= TcpProto
->TcpService
;
1104 Tcb
= TcpProto
->TcpPcb
;
1106 LocalPort
= NTOHS (Tcb
->LocalEnd
.Port
);
1107 RemotePort
= NTOHS (Tcb
->RemoteEnd
.Port
);
1108 NetLibCreateIPv4DPathNode (
1110 TcpService
->ControllerHandle
,
1119 IP4_COPY_ADDRESS (&Ip4DPathNode
.SubnetMask
, &Tcb
->SubnetMask
);
1121 Sock
->DevicePath
= AppendDevicePathNode (
1122 Sock
->ParentDevicePath
,
1123 (EFI_DEVICE_PATH_PROTOCOL
*) &Ip4DPathNode
1125 if (Sock
->DevicePath
== NULL
) {
1126 return EFI_OUT_OF_RESOURCES
;
1129 Status
= gBS
->InstallProtocolInterface (
1131 &gEfiDevicePathProtocolGuid
,
1132 EFI_NATIVE_INTERFACE
,
1135 if (EFI_ERROR (Status
)) {
1136 FreePool (Sock
->DevicePath
);