3 Copyright (c) 2005 - 2007, 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 The implementation of the IpIo layer.
25 #include <Protocol/Udp4.h>
27 #include <Library/IpIoLib.h>
28 #include <Library/BaseLib.h>
29 #include <Library/DebugLib.h>
30 #include <Library/UefiBootServicesTableLib.h>
31 #include <Library/MemoryAllocationLib.h>
32 #include <Library/BaseMemoryLib.h>
35 #define NET_PROTO_HDR(Buf, Type) ((Type *) ((Buf)->BlockOp[0].Head))
36 #define ICMP_ERRLEN(IpHdr) \
37 (sizeof(IP4_ICMP_HEAD) + EFI_IP4_HEADER_LEN(IpHdr) + 8)
39 LIST_ENTRY mActiveIpIoList
= {
44 EFI_IP4_CONFIG_DATA mIpIoDefaultIpConfigData
= {
61 STATIC ICMP_ERROR_INFO mIcmpErrMap
[10] = {
77 IpIoTransmitHandlerDpc (
91 This function create an ip child ,open the IP protocol, return the opened
92 Ip protocol to Interface.
94 @param ControllerHandle The controller handle.
95 @param ImageHandle The image handle.
96 @param ChildHandle Pointer to the buffer to save the ip child handle.
97 @param Interface Pointer used to get the ip protocol interface.
99 @retval EFI_SUCCESS The ip child is created and the ip protocol
100 interface is retrieved.
101 @retval other The required operation failed.
106 IpIoCreateIpChildOpenProtocol (
107 IN EFI_HANDLE ControllerHandle
,
108 IN EFI_HANDLE ImageHandle
,
109 IN EFI_HANDLE
*ChildHandle
,
116 // Create an ip child.
118 Status
= NetLibCreateServiceChild (
121 &gEfiIp4ServiceBindingProtocolGuid
,
124 if (EFI_ERROR (Status
)) {
129 // Open the ip protocol installed on the *ChildHandle.
131 Status
= gBS
->OpenProtocol (
133 &gEfiIp4ProtocolGuid
,
137 EFI_OPEN_PROTOCOL_BY_DRIVER
139 if (EFI_ERROR (Status
)) {
141 // On failure, destroy the ip child.
143 NetLibDestroyServiceChild (
146 &gEfiIp4ServiceBindingProtocolGuid
,
156 This function close the previously openned ip protocol and destroy the ip child.
158 @param ControllerHandle The controller handle.
159 @param ImageHandle the image handle.
160 @param ChildHandle The child handle of the ip child.
162 @retval EFI_SUCCESS The ip protocol is closed and the relevant ip child
164 @retval other The required operation failed.
169 IpIoCloseProtocolDestroyIpChild (
170 IN EFI_HANDLE ControllerHandle
,
171 IN EFI_HANDLE ImageHandle
,
172 IN EFI_HANDLE ChildHandle
178 // Close the previously openned ip protocol.
182 &gEfiIp4ProtocolGuid
,
188 // Destroy the ip child.
190 Status
= NetLibDestroyServiceChild (
193 &gEfiIp4ServiceBindingProtocolGuid
,
204 @param IpIo Pointer to the IP_IO instance.
205 @param Pkt Pointer to the ICMP packet.
206 @param Session Pointer to the net session of this ICMP packet.
208 @retval EFI_SUCCESS The ICMP packet is handled successfully.
209 @retval EFI_ABORTED This type of ICMP packet is not supported.
217 IN EFI_NET_SESSION_DATA
*Session
220 IP4_ICMP_ERROR_HEAD
*IcmpHdr
;
221 EFI_IP4_HEADER
*IpHdr
;
228 IcmpHdr
= NET_PROTO_HDR (Pkt
, IP4_ICMP_ERROR_HEAD
);
229 IpHdr
= (EFI_IP4_HEADER
*) (&IcmpHdr
->IpHead
);
232 // Check the ICMP packet length.
234 if (Pkt
->TotalSize
< ICMP_ERRLEN (IpHdr
)) {
239 Type
= IcmpHdr
->Head
.Type
;
240 Code
= IcmpHdr
->Head
.Code
;
243 // Analyze the ICMP Error in this ICMP pkt
246 case ICMP_TYPE_UNREACH
:
248 case ICMP_CODE_UNREACH_NET
:
249 case ICMP_CODE_UNREACH_HOST
:
250 case ICMP_CODE_UNREACH_PROTOCOL
:
251 case ICMP_CODE_UNREACH_PORT
:
252 case ICMP_CODE_UNREACH_SRCFAIL
:
253 IcmpErr
= (ICMP_ERROR
) (ICMP_ERR_UNREACH_NET
+ Code
);
257 case ICMP_CODE_UNREACH_NEEDFRAG
:
258 IcmpErr
= ICMP_ERR_MSGSIZE
;
262 case ICMP_CODE_UNREACH_NET_UNKNOWN
:
263 case ICMP_CODE_UNREACH_NET_PROHIB
:
264 case ICMP_CODE_UNREACH_TOSNET
:
265 IcmpErr
= ICMP_ERR_UNREACH_NET
;
269 case ICMP_CODE_UNREACH_HOST_UNKNOWN
:
270 case ICMP_CODE_UNREACH_ISOLATED
:
271 case ICMP_CODE_UNREACH_HOST_PROHIB
:
272 case ICMP_CODE_UNREACH_TOSHOST
:
273 IcmpErr
= ICMP_ERR_UNREACH_HOST
;
285 case ICMP_TYPE_TIMXCEED
:
290 IcmpErr
= (ICMP_ERROR
) (Code
+ ICMP_ERR_TIMXCEED_INTRANS
);
294 case ICMP_TYPE_PARAMPROB
:
299 IcmpErr
= ICMP_ERR_PARAMPROB
;
303 case ICMP_TYPE_SOURCEQUENCH
:
308 IcmpErr
= ICMP_ERR_QUENCH
;
319 // Notify user the ICMP pkt only containing payload except
320 // IP and ICMP header
322 PayLoadHdr
= (UINT8
*) ((UINT8
*) IpHdr
+ EFI_IP4_HEADER_LEN (IpHdr
));
323 TrimBytes
= (UINT32
) (PayLoadHdr
- (UINT8
*) IcmpHdr
);
325 NetbufTrim (Pkt
, TrimBytes
, TRUE
);
327 IpIo
->PktRcvdNotify (EFI_ICMP_ERROR
, IcmpErr
, Session
, Pkt
, IpIo
->RcvdContext
);
334 Ext free function for net buffer. This function is
335 called when the net buffer is freed. It is used to
336 signal the recycle event to notify IP to recycle the
339 @param Event The event to be signaled.
350 gBS
->SignalEvent ((EFI_EVENT
) Event
);
355 Create a send entry to wrap a packet before sending
358 @param IpIo Pointer to the IP_IO instance.
359 @param Pkt Pointer to the packet.
360 @param Sender Pointer to the IP sender.
361 @param NotifyData Pointer to the notify data.
362 @param Dest Pointer to the destination IP address.
363 @param Override Pointer to the overriden IP_IO data.
365 @return Pointer to the data structure created to wrap the packet. If NULL,
366 @return resource limit occurred.
374 IN EFI_IP4_PROTOCOL
*Sender
,
375 IN VOID
*Context OPTIONAL
,
376 IN VOID
*NotifyData OPTIONAL
,
378 IN IP_IO_OVERRIDE
*Override
381 IP_IO_SEND_ENTRY
*SndEntry
;
382 EFI_IP4_COMPLETION_TOKEN
*SndToken
;
383 EFI_IP4_TRANSMIT_DATA
*TxData
;
385 EFI_IP4_OVERRIDE_DATA
*OverrideData
;
386 volatile UINT32 Index
;
389 // Allocate resource for SndEntry
391 SndEntry
= AllocatePool (sizeof (IP_IO_SEND_ENTRY
));
392 if (NULL
== SndEntry
) {
397 // Allocate resource for SndToken
399 SndToken
= AllocatePool (sizeof (EFI_IP4_COMPLETION_TOKEN
));
400 if (NULL
== SndToken
) {
401 goto ReleaseSndEntry
;
404 Status
= gBS
->CreateEvent (
411 if (EFI_ERROR (Status
)) {
412 goto ReleaseSndToken
;
416 // Allocate resource for TxData
418 TxData
= AllocatePool (
419 sizeof (EFI_IP4_TRANSMIT_DATA
) +
420 sizeof (EFI_IP4_FRAGMENT_DATA
) * (Pkt
->BlockOpNum
- 1)
423 if (NULL
== TxData
) {
428 // Allocate resource for OverrideData if needed
431 if (NULL
!= Override
) {
433 OverrideData
= AllocatePool (sizeof (EFI_IP4_OVERRIDE_DATA
));
434 if (NULL
== OverrideData
) {
435 goto ReleaseResource
;
438 // Set the fields of OverrideData
440 CopyMem (OverrideData
, Override
, sizeof (*OverrideData
));
444 // Set the fields of TxData
446 CopyMem (&TxData
->DestinationAddress
, &Dest
, sizeof (EFI_IPv4_ADDRESS
));
447 TxData
->OverrideData
= OverrideData
;
448 TxData
->OptionsLength
= 0;
449 TxData
->OptionsBuffer
= NULL
;
450 TxData
->TotalDataLength
= Pkt
->TotalSize
;
451 TxData
->FragmentCount
= Pkt
->BlockOpNum
;
454 for (Index
= 0; Index
< Pkt
->BlockOpNum
; Index
++) {
455 TxData
->FragmentTable
[Index
].FragmentBuffer
= Pkt
->BlockOp
[Index
].Head
;
456 TxData
->FragmentTable
[Index
].FragmentLength
= Pkt
->BlockOp
[Index
].Size
;
460 // Set the fields of SndToken
462 SndToken
->Packet
.TxData
= TxData
;
465 // Set the fields of SndEntry
467 SndEntry
->IpIo
= IpIo
;
468 SndEntry
->Ip
= Sender
;
469 SndEntry
->Context
= Context
;
470 SndEntry
->NotifyData
= NotifyData
;
475 SndEntry
->SndToken
= SndToken
;
477 InsertTailList (&IpIo
->PendingSndList
, &SndEntry
->Entry
);
482 gBS
->FreePool (TxData
);
485 gBS
->CloseEvent (SndToken
->Event
);
488 gBS
->FreePool (SndToken
);
491 gBS
->FreePool (SndEntry
);
498 Destroy the SndEntry.
500 @param SndEntry Pointer to the send entry to be destroyed.
507 IpIoDestroySndEntry (
508 IN IP_IO_SEND_ENTRY
*SndEntry
511 EFI_IP4_TRANSMIT_DATA
*TxData
;
513 TxData
= SndEntry
->SndToken
->Packet
.TxData
;
515 if (NULL
!= TxData
->OverrideData
) {
516 gBS
->FreePool (TxData
->OverrideData
);
519 gBS
->FreePool (TxData
);
520 NetbufFree (SndEntry
->Pkt
);
521 gBS
->CloseEvent (SndEntry
->SndToken
->Event
);
523 gBS
->FreePool (SndEntry
->SndToken
);
524 RemoveEntryList (&SndEntry
->Entry
);
526 gBS
->FreePool (SndEntry
);
531 Notify function for IP transmit token.
533 @param Context The context passed in by the event notifier.
541 IpIoTransmitHandlerDpc (
546 IP_IO_SEND_ENTRY
*SndEntry
;
548 SndEntry
= (IP_IO_SEND_ENTRY
*) Context
;
550 IpIo
= SndEntry
->IpIo
;
552 if (IpIo
->PktSentNotify
&& SndEntry
->NotifyData
) {
553 IpIo
->PktSentNotify (
554 SndEntry
->SndToken
->Status
,
561 IpIoDestroySndEntry (SndEntry
);
565 Notify function for IP transmit token.
567 @param Event The event signaled.
568 @param Context The context passed in by the event notifier.
577 IpIoTransmitHandler (
583 // Request IpIoTransmitHandlerDpc as a DPC at TPL_CALLBACK
585 NetLibQueueDpc (TPL_CALLBACK
, IpIoTransmitHandlerDpc
, Context
);
590 The dummy handler for the dummy IP receive token.
592 @param Context The context passed in by the event notifier.
600 IpIoDummyHandlerDpc (
604 IP_IO_IP_INFO
*IpInfo
;
605 EFI_IP4_COMPLETION_TOKEN
*DummyToken
;
607 IpInfo
= (IP_IO_IP_INFO
*) Context
;
608 DummyToken
= &(IpInfo
->DummyRcvToken
);
610 if (EFI_ABORTED
== DummyToken
->Status
) {
612 // The reception is actively aborted by the consumer, directly return.
615 } else if (EFI_SUCCESS
== DummyToken
->Status
) {
616 ASSERT (DummyToken
->Packet
.RxData
);
618 gBS
->SignalEvent (DummyToken
->Packet
.RxData
->RecycleSignal
);
621 IpInfo
->Ip
->Receive (IpInfo
->Ip
, DummyToken
);
626 Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK.
628 @param Event The event signaled.
629 @param Context The context passed in by the event notifier.
643 // Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK
645 NetLibQueueDpc (TPL_CALLBACK
, IpIoDummyHandlerDpc
, Context
);
650 Notify function for the IP receive token, used to process
651 the received IP packets.
653 @param Context The context passed in by the event notifier.
661 IpIoListenHandlerDpc (
667 EFI_IP4_RECEIVE_DATA
*RxData
;
668 EFI_IP4_PROTOCOL
*Ip
;
669 EFI_NET_SESSION_DATA Session
;
672 IpIo
= (IP_IO
*) Context
;
675 Status
= IpIo
->RcvToken
.Status
;
676 RxData
= IpIo
->RcvToken
.Packet
.RxData
;
678 if (EFI_ABORTED
== Status
) {
680 // The reception is actively aborted by the consumer, directly return.
685 if (((EFI_SUCCESS
!= Status
) && (EFI_ICMP_ERROR
!= Status
)) || (NULL
== RxData
)) {
687 // Only process the normal packets and the icmp error packets, if RxData is NULL
688 // with Status == EFI_SUCCESS or EFI_ICMP_ERROR, just resume the receive although
689 // this should be a bug of the low layer (IP).
694 if (NULL
== IpIo
->PktRcvdNotify
) {
698 if ((EFI_IP4 (RxData
->Header
->SourceAddress
) != 0) &&
699 !Ip4IsUnicast (EFI_NTOHL (RxData
->Header
->SourceAddress
), 0)) {
701 // The source address is not zero and it's not a unicast IP address, discard it.
707 // Create a netbuffer representing packet
709 Pkt
= NetbufFromExt (
710 (NET_FRAGMENT
*) RxData
->FragmentTable
,
711 RxData
->FragmentCount
,
715 RxData
->RecycleSignal
722 // Create a net session
724 Session
.Source
= EFI_IP4 (RxData
->Header
->SourceAddress
);
725 Session
.Dest
= EFI_IP4 (RxData
->Header
->DestinationAddress
);
726 Session
.IpHdr
= RxData
->Header
;
728 if (EFI_SUCCESS
== Status
) {
730 IpIo
->PktRcvdNotify (EFI_SUCCESS
, (ICMP_ERROR
) 0, &Session
, Pkt
, IpIo
->RcvdContext
);
733 // Status is EFI_ICMP_ERROR
735 Status
= IpIoIcmpHandler (IpIo
, Pkt
, &Session
);
736 if (EFI_ERROR (Status
)) {
744 gBS
->SignalEvent (RxData
->RecycleSignal
);
747 Ip
->Receive (Ip
, &(IpIo
->RcvToken
));
752 Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK
754 @param Event The event signaled.
755 @param Context The context passed in by the event notifier.
769 // Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK
771 NetLibQueueDpc (TPL_CALLBACK
, IpIoListenHandlerDpc
, Context
);
776 Create a new IP_IO instance.
778 @param Image The image handle of an IP_IO consumer protocol.
779 @param Controller The controller handle of an IP_IO consumer protocol
782 @return Pointer to a newly created IP_IO instance.
789 IN EFI_HANDLE Controller
795 IpIo
= AllocateZeroPool (sizeof (IP_IO
));
800 InitializeListHead (&(IpIo
->PendingSndList
));
801 InitializeListHead (&(IpIo
->IpList
));
802 IpIo
->Controller
= Controller
;
805 Status
= gBS
->CreateEvent (
810 &(IpIo
->RcvToken
.Event
)
812 if (EFI_ERROR (Status
)) {
817 // Create an IP child and open IP protocol
819 Status
= IpIoCreateIpChildOpenProtocol (
825 if (EFI_ERROR (Status
)) {
833 if (NULL
!= IpIo
->RcvToken
.Event
) {
834 gBS
->CloseEvent (IpIo
->RcvToken
.Event
);
837 gBS
->FreePool (IpIo
);
844 Open an IP_IO instance for use.
846 @param IpIo Pointer to an IP_IO instance that needs to open.
847 @param OpenData The configuration data for the IP_IO instance.
849 @retval EFI_SUCCESS The IP_IO instance opened with OpenData
851 @retval other Error condition occurred.
858 IN IP_IO_OPEN_DATA
*OpenData
862 EFI_IP4_PROTOCOL
*Ip
;
864 if (IpIo
->IsConfigured
) {
865 return EFI_ACCESS_DENIED
;
873 Status
= Ip
->Configure (Ip
, &OpenData
->IpConfigData
);
874 if (EFI_ERROR (Status
)) {
879 // bugbug: to delete the default route entry in this Ip, if it is:
880 // (0.0.0.0, 0.0.0.0, 0.0.0.0). Delete this statement if Ip modified
883 Status
= Ip
->Routes (Ip
, TRUE
, &mZeroIp4Addr
, &mZeroIp4Addr
, &mZeroIp4Addr
);
885 if (EFI_ERROR (Status
) && (EFI_NOT_FOUND
!= Status
)) {
889 IpIo
->PktRcvdNotify
= OpenData
->PktRcvdNotify
;
890 IpIo
->PktSentNotify
= OpenData
->PktSentNotify
;
892 IpIo
->RcvdContext
= OpenData
->RcvdContext
;
893 IpIo
->SndContext
= OpenData
->SndContext
;
895 IpIo
->Protocol
= OpenData
->IpConfigData
.DefaultProtocol
;
898 // start to listen incoming packet
900 Status
= Ip
->Receive (Ip
, &(IpIo
->RcvToken
));
901 if (EFI_ERROR (Status
)) {
902 Ip
->Configure (Ip
, NULL
);
906 IpIo
->IsConfigured
= TRUE
;
907 InsertTailList (&mActiveIpIoList
, &IpIo
->Entry
);
916 Stop an IP_IO instance.
918 @param IpIo Pointer to the IP_IO instance that needs to stop.
920 @retval EFI_SUCCESS The IP_IO instance stopped successfully.
921 @retval other Error condition occurred.
930 EFI_IP4_PROTOCOL
*Ip
;
931 IP_IO_IP_INFO
*IpInfo
;
933 if (!IpIo
->IsConfigured
) {
938 // Remove the IpIo from the active IpIo list.
940 RemoveEntryList (&IpIo
->Entry
);
947 Status
= Ip
->Configure (Ip
, NULL
);
948 if (EFI_ERROR (Status
)) {
952 IpIo
->IsConfigured
= FALSE
;
955 // Detroy the Ip List used by IpIo
958 while (!IsListEmpty (&(IpIo
->IpList
))) {
959 IpInfo
= NET_LIST_HEAD (&(IpIo
->IpList
), IP_IO_IP_INFO
, Entry
);
961 IpIoRemoveIp (IpIo
, IpInfo
);
965 // All pending snd tokens should be flushed by reseting the IP instances.
967 ASSERT (IsListEmpty (&IpIo
->PendingSndList
));
970 // Close the receive event.
972 gBS
->CloseEvent (IpIo
->RcvToken
.Event
);
979 Destroy an IP_IO instance.
981 @param IpIo Pointer to the IP_IO instance that needs to
984 @retval EFI_SUCCESS The IP_IO instance destroyed successfully.
985 @retval other Error condition occurred.
1000 // Close the IP protocol and destroy the child.
1002 IpIoCloseProtocolDestroyIpChild (IpIo
->Controller
, IpIo
->Image
, IpIo
->ChildHandle
);
1004 gBS
->FreePool (IpIo
);
1011 Send out an IP packet.
1013 @param IpIo Pointer to an IP_IO instance used for sending IP
1015 @param Pkt Pointer to the IP packet to be sent.
1016 @param Sender The IP protocol instance used for sending.
1018 @param Dest The destination IP address to send this packet to.
1019 @param OverrideData The data to override some configuration of the IP
1020 instance used for sending.
1022 @retval EFI_SUCCESS The operation is completed successfully.
1023 @retval EFI_NOT_STARTED The IpIo is not configured.
1024 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
1032 IN IP_IO_IP_INFO
*Sender
,
1033 IN VOID
*Context OPTIONAL
,
1034 IN VOID
*NotifyData OPTIONAL
,
1036 IN IP_IO_OVERRIDE
*OverrideData
1040 EFI_IP4_PROTOCOL
*Ip
;
1041 IP_IO_SEND_ENTRY
*SndEntry
;
1043 if (!IpIo
->IsConfigured
) {
1044 return EFI_NOT_STARTED
;
1047 Ip
= (NULL
== Sender
) ? IpIo
->Ip
: Sender
->Ip
;
1050 // create a new SndEntry
1052 SndEntry
= IpIoCreateSndEntry (IpIo
, Pkt
, Ip
, Context
, NotifyData
, Dest
, OverrideData
);
1053 if (NULL
== SndEntry
) {
1054 return EFI_OUT_OF_RESOURCES
;
1060 Status
= Ip
->Transmit (Ip
, SndEntry
->SndToken
);
1061 if (EFI_ERROR (Status
)) {
1062 IpIoDestroySndEntry (SndEntry
);
1070 Cancel the IP transmit token which wraps this Packet.
1072 @param IpIo Pointer to the IP_IO instance.
1073 @param Packet Pointer to the packet to cancel.
1086 IP_IO_SEND_ENTRY
*SndEntry
;
1087 EFI_IP4_PROTOCOL
*Ip
;
1089 ASSERT (IpIo
&& Packet
);
1091 NET_LIST_FOR_EACH (Node
, &IpIo
->PendingSndList
) {
1093 SndEntry
= NET_LIST_USER_STRUCT (Node
, IP_IO_SEND_ENTRY
, Entry
);
1095 if (SndEntry
->Pkt
== Packet
) {
1098 Ip
->Cancel (Ip
, SndEntry
->SndToken
);
1108 Add a new IP instance for sending data.
1110 @param IpIo Pointer to a IP_IO instance to add a new IP
1111 instance for sending purpose.
1113 @return Pointer to the created IP_IO_IP_INFO structure, NULL is failed.
1123 IP_IO_IP_INFO
*IpInfo
;
1127 IpInfo
= AllocatePool (sizeof (IP_IO_IP_INFO
));
1128 if (IpInfo
== NULL
) {
1133 // Init this IpInfo, set the Addr and SubnetMask to 0 before we configure the IP
1136 InitializeListHead (&IpInfo
->Entry
);
1137 IpInfo
->ChildHandle
= NULL
;
1139 IpInfo
->SubnetMask
= 0;
1143 // Create the IP instance and open the Ip4 protocol.
1145 Status
= IpIoCreateIpChildOpenProtocol (
1148 &IpInfo
->ChildHandle
,
1149 (VOID
**) &IpInfo
->Ip
1151 if (EFI_ERROR (Status
)) {
1156 // Create the event for the DummyRcvToken.
1158 Status
= gBS
->CreateEvent (
1163 &IpInfo
->DummyRcvToken
.Event
1165 if (EFI_ERROR (Status
)) {
1166 goto ReleaseIpChild
;
1170 // Link this IpInfo into the IpIo.
1172 InsertTailList (&IpIo
->IpList
, &IpInfo
->Entry
);
1178 IpIoCloseProtocolDestroyIpChild (
1186 gBS
->FreePool (IpInfo
);
1193 Configure the IP instance of this IpInfo and start the receiving if Ip4ConfigData
1196 @param IpInfo Pointer to the IP_IO_IP_INFO instance.
1197 @param Ip4ConfigData The IP4 configure data used to configure the ip
1198 instance, if NULL the ip instance is reseted. If
1199 UseDefaultAddress is set to TRUE, and the configure
1200 operation succeeds, the default address information
1201 is written back in this Ip4ConfigData.
1203 @retval EFI_STATUS The status returned by IP4->Configure or
1210 IN IP_IO_IP_INFO
*IpInfo
,
1211 IN OUT EFI_IP4_CONFIG_DATA
*Ip4ConfigData OPTIONAL
1215 EFI_IP4_PROTOCOL
*Ip
;
1216 EFI_IP4_MODE_DATA Ip4ModeData
;
1220 if (IpInfo
->RefCnt
> 1) {
1222 // This IP instance is shared, don't reconfigure it until it has only one
1223 // consumer. Currently, only the tcp children cloned from their passive parent
1224 // will share the same IP. So this cases only happens while Ip4ConfigData is NULL,
1225 // let the last consumer clean the IP instance.
1232 Status
= Ip
->Configure (Ip
, Ip4ConfigData
);
1233 if (EFI_ERROR (Status
)) {
1237 if (Ip4ConfigData
!= NULL
) {
1239 if (Ip4ConfigData
->UseDefaultAddress
) {
1240 Ip
->GetModeData (Ip
, &Ip4ModeData
, NULL
, NULL
);
1242 Ip4ConfigData
->StationAddress
= Ip4ModeData
.ConfigData
.StationAddress
;
1243 Ip4ConfigData
->SubnetMask
= Ip4ModeData
.ConfigData
.SubnetMask
;
1246 CopyMem (&IpInfo
->Addr
, &Ip4ConfigData
->StationAddress
, sizeof (IP4_ADDR
));
1247 CopyMem (&IpInfo
->SubnetMask
, &Ip4ConfigData
->SubnetMask
, sizeof (IP4_ADDR
));
1249 Status
= Ip
->Receive (Ip
, &IpInfo
->DummyRcvToken
);
1250 if (EFI_ERROR (Status
)) {
1251 Ip
->Configure (Ip
, NULL
);
1256 // The IP instance is reseted, set the stored Addr and SubnetMask to zero.
1259 IpInfo
->SubnetMask
=0;
1269 Destroy an IP instance maintained in IpIo->IpList for
1272 @param IpIo Pointer to the IP_IO instance.
1273 @param IpInfo Pointer to the IpInfo to be removed.
1282 IN IP_IO_IP_INFO
*IpInfo
1285 ASSERT (IpInfo
->RefCnt
> 0);
1287 NET_PUT_REF (IpInfo
);
1289 if (IpInfo
->RefCnt
> 0) {
1294 RemoveEntryList (&IpInfo
->Entry
);
1296 IpInfo
->Ip
->Configure (IpInfo
->Ip
, NULL
);
1298 IpIoCloseProtocolDestroyIpChild (IpIo
->Controller
, IpIo
->Image
, IpInfo
->ChildHandle
);
1300 gBS
->CloseEvent (IpInfo
->DummyRcvToken
.Event
);
1302 gBS
->FreePool (IpInfo
);
1307 Find the first IP protocol maintained in IpIo whose local
1308 address is the same with Src.
1310 @param IpIo Pointer to the pointer of the IP_IO instance.
1311 @param Src The local IP address.
1313 @return Pointer to the IP protocol can be used for sending purpose and its local
1314 @return address is the same with Src.
1320 IN OUT IP_IO
**IpIo
,
1324 LIST_ENTRY
*IpIoEntry
;
1326 LIST_ENTRY
*IpInfoEntry
;
1327 IP_IO_IP_INFO
*IpInfo
;
1329 NET_LIST_FOR_EACH (IpIoEntry
, &mActiveIpIoList
) {
1330 IpIoPtr
= NET_LIST_USER_STRUCT (IpIoEntry
, IP_IO
, Entry
);
1332 if ((*IpIo
!= NULL
) && (*IpIo
!= IpIoPtr
)) {
1336 NET_LIST_FOR_EACH (IpInfoEntry
, &IpIoPtr
->IpList
) {
1337 IpInfo
= NET_LIST_USER_STRUCT (IpInfoEntry
, IP_IO_IP_INFO
, Entry
);
1339 if (IpInfo
->Addr
== Src
) {
1354 Get the ICMP error map information, the ErrorStatus will be returned.
1355 The IsHard and Notify are optional. If they are not NULL, this rouine will
1357 We move IcmpErrMap[] to local variable to enable EBC build.
1359 @param IcmpError IcmpError Type
1360 @param IsHard Whether it is a hard error
1361 @param Notify Whether it need to notify SockError
1363 @return ICMP Error Status
1368 IpIoGetIcmpErrStatus (
1369 IN ICMP_ERROR IcmpError
,
1370 OUT BOOLEAN
*IsHard
, OPTIONAL
1371 OUT BOOLEAN
*Notify OPTIONAL
1374 ASSERT ((IcmpError
>= ICMP_ERR_UNREACH_NET
) && (IcmpError
<= ICMP_ERR_PARAMPROB
));
1376 if (IsHard
!= NULL
) {
1377 *IsHard
= mIcmpErrMap
[IcmpError
].IsHard
;
1380 if (Notify
!= NULL
) {
1381 *Notify
= mIcmpErrMap
[IcmpError
].Notify
;
1384 switch (IcmpError
) {
1385 case ICMP_ERR_UNREACH_NET
:
1386 return EFI_NETWORK_UNREACHABLE
;
1388 case ICMP_ERR_TIMXCEED_INTRANS
:
1389 case ICMP_ERR_TIMXCEED_REASS
:
1390 case ICMP_ERR_UNREACH_HOST
:
1391 return EFI_HOST_UNREACHABLE
;
1393 case ICMP_ERR_UNREACH_PROTOCOL
:
1394 return EFI_PROTOCOL_UNREACHABLE
;
1396 case ICMP_ERR_UNREACH_PORT
:
1397 return EFI_PORT_UNREACHABLE
;
1399 case ICMP_ERR_MSGSIZE
:
1400 case ICMP_ERR_UNREACH_SRCFAIL
:
1401 case ICMP_ERR_QUENCH
:
1402 case ICMP_ERR_PARAMPROB
:
1403 return EFI_ICMP_ERROR
;
1407 // will never run here!
1410 return EFI_UNSUPPORTED
;