4 Copyright (c) 2005 - 2007, Intel Corporation.<BR>
5 All rights reserved. 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
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.
16 #include <Protocol/Udp4.h>
18 #include <Library/IpIoLib.h>
19 #include <Library/BaseLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
24 LIST_ENTRY mActiveIpIoList
= {
29 EFI_IP4_CONFIG_DATA mIpIoDefaultIpConfigData
= {
46 ICMP_ERROR_INFO mIcmpErrMap
[10] = {
61 Notify function for IP transmit token.
63 @param[in] Context The context passed in by the event notifier.
68 IpIoTransmitHandlerDpc (
74 Notify function for IP transmit token.
76 @param[in] Event The event signaled.
77 @param[in] Context The context passed in by the event notifier.
89 This function create an IP child ,open the IP protocol, and return the opened
90 IP protocol as Interface.
92 @param[in] ControllerHandle The controller handle.
93 @param[in] ImageHandle The image handle.
94 @param[in] ChildHandle Pointer to the buffer to save the IP child handle.
95 @param[out] Interface Pointer used to get the IP protocol interface.
97 @retval EFI_SUCCESS The IP child is created and the IP protocol
98 interface is retrieved.
99 @retval Others The required operation failed.
103 IpIoCreateIpChildOpenProtocol (
104 IN EFI_HANDLE ControllerHandle
,
105 IN EFI_HANDLE ImageHandle
,
106 IN EFI_HANDLE
*ChildHandle
,
113 // Create an IP child.
115 Status
= NetLibCreateServiceChild (
118 &gEfiIp4ServiceBindingProtocolGuid
,
121 if (EFI_ERROR (Status
)) {
126 // Open the IP protocol installed on the *ChildHandle.
128 Status
= gBS
->OpenProtocol (
130 &gEfiIp4ProtocolGuid
,
134 EFI_OPEN_PROTOCOL_BY_DRIVER
136 if (EFI_ERROR (Status
)) {
138 // On failure, destroy the IP child.
140 NetLibDestroyServiceChild (
143 &gEfiIp4ServiceBindingProtocolGuid
,
153 This function close the previously openned IP protocol and destroy the IP child.
155 @param[in] ControllerHandle The controller handle.
156 @param[in] ImageHandle The image handle.
157 @param[in] ChildHandle The child handle of the IP child.
159 @retval EFI_SUCCESS The IP protocol is closed and the relevant IP child
161 @retval Others The required operation failed.
165 IpIoCloseProtocolDestroyIpChild (
166 IN EFI_HANDLE ControllerHandle
,
167 IN EFI_HANDLE ImageHandle
,
168 IN EFI_HANDLE ChildHandle
174 // Close the previously openned IP protocol.
178 &gEfiIp4ProtocolGuid
,
184 // Destroy the IP child.
186 Status
= NetLibDestroyServiceChild (
189 &gEfiIp4ServiceBindingProtocolGuid
,
198 This function handles ICMP packets.
200 @param[in] IpIo Pointer to the IP_IO instance.
201 @param[in, out] Pkt Pointer to the ICMP packet.
202 @param[in] Session Pointer to the net session of this ICMP packet.
204 @retval EFI_SUCCESS The ICMP packet is handled successfully.
205 @retval EFI_ABORTED This type of ICMP packet is not supported.
212 IN EFI_NET_SESSION_DATA
*Session
215 IP4_ICMP_ERROR_HEAD
*IcmpHdr
;
216 EFI_IP4_HEADER
*IpHdr
;
223 IcmpHdr
= NET_PROTO_HDR (Pkt
, IP4_ICMP_ERROR_HEAD
);
224 IpHdr
= (EFI_IP4_HEADER
*) (&IcmpHdr
->IpHead
);
227 // Check the ICMP packet length.
229 if (Pkt
->TotalSize
< ICMP_ERRLEN (IpHdr
)) {
234 Type
= IcmpHdr
->Head
.Type
;
235 Code
= IcmpHdr
->Head
.Code
;
238 // Analyze the ICMP Error in this ICMP pkt
241 case ICMP_TYPE_UNREACH
:
243 case ICMP_CODE_UNREACH_NET
:
244 case ICMP_CODE_UNREACH_HOST
:
245 case ICMP_CODE_UNREACH_PROTOCOL
:
246 case ICMP_CODE_UNREACH_PORT
:
247 case ICMP_CODE_UNREACH_SRCFAIL
:
248 IcmpErr
= (ICMP_ERROR
) (ICMP_ERR_UNREACH_NET
+ Code
);
252 case ICMP_CODE_UNREACH_NEEDFRAG
:
253 IcmpErr
= ICMP_ERR_MSGSIZE
;
257 case ICMP_CODE_UNREACH_NET_UNKNOWN
:
258 case ICMP_CODE_UNREACH_NET_PROHIB
:
259 case ICMP_CODE_UNREACH_TOSNET
:
260 IcmpErr
= ICMP_ERR_UNREACH_NET
;
264 case ICMP_CODE_UNREACH_HOST_UNKNOWN
:
265 case ICMP_CODE_UNREACH_ISOLATED
:
266 case ICMP_CODE_UNREACH_HOST_PROHIB
:
267 case ICMP_CODE_UNREACH_TOSHOST
:
268 IcmpErr
= ICMP_ERR_UNREACH_HOST
;
278 case ICMP_TYPE_TIMXCEED
:
283 IcmpErr
= (ICMP_ERROR
) (Code
+ ICMP_ERR_TIMXCEED_INTRANS
);
287 case ICMP_TYPE_PARAMPROB
:
292 IcmpErr
= ICMP_ERR_PARAMPROB
;
296 case ICMP_TYPE_SOURCEQUENCH
:
301 IcmpErr
= ICMP_ERR_QUENCH
;
310 // Notify user the ICMP pkt only containing payload except
311 // IP and ICMP header
313 PayLoadHdr
= (UINT8
*) ((UINT8
*) IpHdr
+ EFI_IP4_HEADER_LEN (IpHdr
));
314 TrimBytes
= (UINT32
) (PayLoadHdr
- (UINT8
*) IcmpHdr
);
316 NetbufTrim (Pkt
, TrimBytes
, TRUE
);
318 IpIo
->PktRcvdNotify (EFI_ICMP_ERROR
, IcmpErr
, Session
, Pkt
, IpIo
->RcvdContext
);
325 Free function for receive token of IP_IO. It is used to
326 signal the recycle event to notify IP to recycle the
329 @param[in] Event The event to be signaled.
337 gBS
->SignalEvent ((EFI_EVENT
) Event
);
342 Create a send entry to wrap a packet before sending
345 @param[in, out] IpIo Pointer to the IP_IO instance.
346 @param[in, out] Pkt Pointer to the packet.
347 @param[in] Sender Pointer to the IP sender.
348 @param[in] Context Pointer to the context.
349 @param[in] NotifyData Pointer to the notify data.
350 @param[in] Dest Pointer to the destination IP address.
351 @param[in] Override Pointer to the overriden IP_IO data.
353 @return Pointer to the data structure created to wrap the packet. If NULL,
354 @return resource limit occurred.
361 IN EFI_IP4_PROTOCOL
*Sender
,
362 IN VOID
*Context OPTIONAL
,
363 IN VOID
*NotifyData OPTIONAL
,
365 IN IP_IO_OVERRIDE
*Override
368 IP_IO_SEND_ENTRY
*SndEntry
;
369 EFI_IP4_COMPLETION_TOKEN
*SndToken
;
370 EFI_IP4_TRANSMIT_DATA
*TxData
;
372 EFI_IP4_OVERRIDE_DATA
*OverrideData
;
373 volatile UINT32 Index
;
376 // Allocate resource for SndEntry
378 SndEntry
= AllocatePool (sizeof (IP_IO_SEND_ENTRY
));
379 if (NULL
== SndEntry
) {
384 // Allocate resource for SndToken
386 SndToken
= AllocatePool (sizeof (EFI_IP4_COMPLETION_TOKEN
));
387 if (NULL
== SndToken
) {
388 goto ReleaseSndEntry
;
391 Status
= gBS
->CreateEvent (
398 if (EFI_ERROR (Status
)) {
399 goto ReleaseSndToken
;
403 // Allocate resource for TxData
405 TxData
= AllocatePool (
406 sizeof (EFI_IP4_TRANSMIT_DATA
) +
407 sizeof (EFI_IP4_FRAGMENT_DATA
) * (Pkt
->BlockOpNum
- 1)
410 if (NULL
== TxData
) {
415 // Allocate resource for OverrideData if needed
418 if (NULL
!= Override
) {
420 OverrideData
= AllocatePool (sizeof (EFI_IP4_OVERRIDE_DATA
));
421 if (NULL
== OverrideData
) {
422 goto ReleaseResource
;
425 // Set the fields of OverrideData
427 CopyMem (OverrideData
, Override
, sizeof (*OverrideData
));
431 // Set the fields of TxData
433 CopyMem (&TxData
->DestinationAddress
, &Dest
, sizeof (EFI_IPv4_ADDRESS
));
434 TxData
->OverrideData
= OverrideData
;
435 TxData
->OptionsLength
= 0;
436 TxData
->OptionsBuffer
= NULL
;
437 TxData
->TotalDataLength
= Pkt
->TotalSize
;
438 TxData
->FragmentCount
= Pkt
->BlockOpNum
;
441 for (Index
= 0; Index
< Pkt
->BlockOpNum
; Index
++) {
442 TxData
->FragmentTable
[Index
].FragmentBuffer
= Pkt
->BlockOp
[Index
].Head
;
443 TxData
->FragmentTable
[Index
].FragmentLength
= Pkt
->BlockOp
[Index
].Size
;
447 // Set the fields of SndToken
449 SndToken
->Packet
.TxData
= TxData
;
452 // Set the fields of SndEntry
454 SndEntry
->IpIo
= IpIo
;
455 SndEntry
->Ip
= Sender
;
456 SndEntry
->Context
= Context
;
457 SndEntry
->NotifyData
= NotifyData
;
462 SndEntry
->SndToken
= SndToken
;
464 InsertTailList (&IpIo
->PendingSndList
, &SndEntry
->Entry
);
469 gBS
->FreePool (TxData
);
472 gBS
->CloseEvent (SndToken
->Event
);
475 gBS
->FreePool (SndToken
);
478 gBS
->FreePool (SndEntry
);
485 Destroy the SndEntry.
487 This function pairs with IpIoCreateSndEntry().
489 @param[in] SndEntry Pointer to the send entry to be destroyed.
493 IpIoDestroySndEntry (
494 IN IP_IO_SEND_ENTRY
*SndEntry
497 EFI_IP4_TRANSMIT_DATA
*TxData
;
499 TxData
= SndEntry
->SndToken
->Packet
.TxData
;
501 if (NULL
!= TxData
->OverrideData
) {
502 gBS
->FreePool (TxData
->OverrideData
);
505 gBS
->FreePool (TxData
);
506 NetbufFree (SndEntry
->Pkt
);
507 gBS
->CloseEvent (SndEntry
->SndToken
->Event
);
509 gBS
->FreePool (SndEntry
->SndToken
);
510 RemoveEntryList (&SndEntry
->Entry
);
512 gBS
->FreePool (SndEntry
);
517 Notify function for IP transmit token.
519 @param[in] Context The context passed in by the event notifier.
524 IpIoTransmitHandlerDpc (
529 IP_IO_SEND_ENTRY
*SndEntry
;
531 SndEntry
= (IP_IO_SEND_ENTRY
*) Context
;
533 IpIo
= SndEntry
->IpIo
;
535 if ((IpIo
->PktSentNotify
!= NULL
) && (SndEntry
->NotifyData
!= NULL
)) {
536 IpIo
->PktSentNotify (
537 SndEntry
->SndToken
->Status
,
544 IpIoDestroySndEntry (SndEntry
);
549 Notify function for IP transmit token.
551 @param[in] Event The event signaled.
552 @param[in] Context The context passed in by the event notifier.
557 IpIoTransmitHandler (
563 // Request IpIoTransmitHandlerDpc as a DPC at TPL_CALLBACK
565 NetLibQueueDpc (TPL_CALLBACK
, IpIoTransmitHandlerDpc
, Context
);
570 The dummy handler for the dummy IP receive token.
572 @param[in] Context The context passed in by the event notifier.
577 IpIoDummyHandlerDpc (
581 IP_IO_IP_INFO
*IpInfo
;
582 EFI_IP4_COMPLETION_TOKEN
*DummyToken
;
584 IpInfo
= (IP_IO_IP_INFO
*) Context
;
585 DummyToken
= &(IpInfo
->DummyRcvToken
);
587 if (EFI_ABORTED
== DummyToken
->Status
) {
589 // The reception is actively aborted by the consumer, directly return.
592 } else if (EFI_SUCCESS
== DummyToken
->Status
) {
593 ASSERT ((DummyToken
->Packet
.RxData
)!= NULL
);
595 gBS
->SignalEvent (DummyToken
->Packet
.RxData
->RecycleSignal
);
598 IpInfo
->Ip
->Receive (IpInfo
->Ip
, DummyToken
);
603 This function add IpIoDummyHandlerDpc to the end of the DPC queue.
605 @param[in] Event The event signaled.
606 @param[in] Context The context passed in by the event notifier.
617 // Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK
619 NetLibQueueDpc (TPL_CALLBACK
, IpIoDummyHandlerDpc
, Context
);
624 Notify function for the IP receive token, used to process
625 the received IP packets.
627 @param[in] Context The context passed in by the event notifier.
632 IpIoListenHandlerDpc (
638 EFI_IP4_RECEIVE_DATA
*RxData
;
639 EFI_IP4_PROTOCOL
*Ip
;
640 EFI_NET_SESSION_DATA Session
;
643 IpIo
= (IP_IO
*) Context
;
646 Status
= IpIo
->RcvToken
.Status
;
647 RxData
= IpIo
->RcvToken
.Packet
.RxData
;
649 if (EFI_ABORTED
== Status
) {
651 // The reception is actively aborted by the consumer, directly return.
656 if (((EFI_SUCCESS
!= Status
) && (EFI_ICMP_ERROR
!= Status
)) || (NULL
== RxData
)) {
658 // @bug Only process the normal packets and the icmp error packets, if RxData is NULL
659 // @bug with Status == EFI_SUCCESS or EFI_ICMP_ERROR, just resume the receive although
660 // @bug this should be a bug of the low layer (IP).
665 if (NULL
== IpIo
->PktRcvdNotify
) {
669 if ((EFI_IP4 (RxData
->Header
->SourceAddress
) != 0) &&
670 !Ip4IsUnicast (EFI_NTOHL (RxData
->Header
->SourceAddress
), 0)) {
672 // The source address is not zero and it's not a unicast IP address, discard it.
678 // Create a netbuffer representing packet
680 Pkt
= NetbufFromExt (
681 (NET_FRAGMENT
*) RxData
->FragmentTable
,
682 RxData
->FragmentCount
,
686 RxData
->RecycleSignal
693 // Create a net session
695 Session
.Source
= EFI_IP4 (RxData
->Header
->SourceAddress
);
696 Session
.Dest
= EFI_IP4 (RxData
->Header
->DestinationAddress
);
697 Session
.IpHdr
= RxData
->Header
;
699 if (EFI_SUCCESS
== Status
) {
701 IpIo
->PktRcvdNotify (EFI_SUCCESS
, (ICMP_ERROR
) 0, &Session
, Pkt
, IpIo
->RcvdContext
);
704 // Status is EFI_ICMP_ERROR
706 Status
= IpIoIcmpHandler (IpIo
, Pkt
, &Session
);
707 if (EFI_ERROR (Status
)) {
715 gBS
->SignalEvent (RxData
->RecycleSignal
);
718 Ip
->Receive (Ip
, &(IpIo
->RcvToken
));
723 This function add IpIoListenHandlerDpc to the end of the DPC queue.
725 @param[in] Event The event signaled.
726 @param[in] Context The context passed in by the event notifier.
737 // Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK
739 NetLibQueueDpc (TPL_CALLBACK
, IpIoListenHandlerDpc
, Context
);
744 Create a new IP_IO instance.
746 This function uses IP4 service binding protocol in Controller to create an IP4
747 child (aka IP4 instance).
749 @param[in] Image The image handle of the driver or application that
751 @param[in] Controller The controller handle that has IP4 service binding
754 @return Pointer to a newly created IP_IO instance, or NULL if failed.
761 IN EFI_HANDLE Controller
767 IpIo
= AllocateZeroPool (sizeof (IP_IO
));
772 InitializeListHead (&(IpIo
->PendingSndList
));
773 InitializeListHead (&(IpIo
->IpList
));
774 IpIo
->Controller
= Controller
;
777 Status
= gBS
->CreateEvent (
782 &(IpIo
->RcvToken
.Event
)
784 if (EFI_ERROR (Status
)) {
789 // Create an IP child and open IP protocol
791 Status
= IpIoCreateIpChildOpenProtocol (
797 if (EFI_ERROR (Status
)) {
805 if (NULL
!= IpIo
->RcvToken
.Event
) {
806 gBS
->CloseEvent (IpIo
->RcvToken
.Event
);
809 gBS
->FreePool (IpIo
);
816 Open an IP_IO instance for use.
818 This function is called after IpIoCreate(). It is used for configuring the IP
819 instance and register the callbacks and their context data for sending and
820 receiving IP packets.
822 @param[in, out] IpIo Pointer to an IP_IO instance that needs
824 @param[in] OpenData The configuration data and callbacks for
827 @retval EFI_SUCCESS The IP_IO instance opened with OpenData
829 @retval EFI_ACCESS_DENIED The IP_IO instance is configured, avoid to
831 @retval Others Error condition occurred.
838 IN IP_IO_OPEN_DATA
*OpenData
842 EFI_IP4_PROTOCOL
*Ip
;
844 if (IpIo
->IsConfigured
) {
845 return EFI_ACCESS_DENIED
;
853 Status
= Ip
->Configure (Ip
, &OpenData
->IpConfigData
);
854 if (EFI_ERROR (Status
)) {
859 // @bug To delete the default route entry in this Ip, if it is:
860 // @bug (0.0.0.0, 0.0.0.0, 0.0.0.0). Delete this statement if Ip modified
863 Status
= Ip
->Routes (Ip
, TRUE
, &mZeroIp4Addr
, &mZeroIp4Addr
, &mZeroIp4Addr
);
865 if (EFI_ERROR (Status
) && (EFI_NOT_FOUND
!= Status
)) {
869 IpIo
->PktRcvdNotify
= OpenData
->PktRcvdNotify
;
870 IpIo
->PktSentNotify
= OpenData
->PktSentNotify
;
872 IpIo
->RcvdContext
= OpenData
->RcvdContext
;
873 IpIo
->SndContext
= OpenData
->SndContext
;
875 IpIo
->Protocol
= OpenData
->IpConfigData
.DefaultProtocol
;
878 // start to listen incoming packet
880 Status
= Ip
->Receive (Ip
, &(IpIo
->RcvToken
));
881 if (EFI_ERROR (Status
)) {
882 Ip
->Configure (Ip
, NULL
);
886 IpIo
->IsConfigured
= TRUE
;
887 InsertTailList (&mActiveIpIoList
, &IpIo
->Entry
);
896 Stop an IP_IO instance.
898 This function is paired with IpIoOpen(). The IP_IO will be unconfigured and all
899 the pending send/receive tokens will be canceled.
901 @param[in, out] IpIo Pointer to the IP_IO instance that needs to stop.
903 @retval EFI_SUCCESS The IP_IO instance stopped successfully.
904 @retval Others Error condition occurred.
914 EFI_IP4_PROTOCOL
*Ip
;
915 IP_IO_IP_INFO
*IpInfo
;
917 if (!IpIo
->IsConfigured
) {
922 // Remove the IpIo from the active IpIo list.
924 RemoveEntryList (&IpIo
->Entry
);
931 Status
= Ip
->Configure (Ip
, NULL
);
932 if (EFI_ERROR (Status
)) {
936 IpIo
->IsConfigured
= FALSE
;
939 // Detroy the Ip List used by IpIo
942 while (!IsListEmpty (&(IpIo
->IpList
))) {
943 IpInfo
= NET_LIST_HEAD (&(IpIo
->IpList
), IP_IO_IP_INFO
, Entry
);
945 IpIoRemoveIp (IpIo
, IpInfo
);
949 // All pending send tokens should be flushed by reseting the IP instances.
951 ASSERT (IsListEmpty (&IpIo
->PendingSndList
));
954 // Close the receive event.
956 gBS
->CloseEvent (IpIo
->RcvToken
.Event
);
963 Destroy an IP_IO instance.
965 This function is paired with IpIoCreate(). The IP_IO will be closed first.
966 Resource will be freed afterwards. See IpIoCloseProtocolDestroyIpChild().
968 @param[in, out] IpIo Pointer to the IP_IO instance that needs to be
971 @retval EFI_SUCCESS The IP_IO instance destroyed successfully.
972 @retval Others Error condition occurred.
987 // Close the IP protocol and destroy the child.
989 IpIoCloseProtocolDestroyIpChild (IpIo
->Controller
, IpIo
->Image
, IpIo
->ChildHandle
);
991 gBS
->FreePool (IpIo
);
998 Send out an IP packet.
1000 This function is called after IpIoOpen(). The data to be sent are wrapped in
1001 Pkt. The IP instance wrapped in IpIo is used for sending by default but can be
1002 overriden by Sender. Other sending configs, like source address and gateway
1003 address etc., are specified in OverrideData.
1005 @param[in, out] IpIo Pointer to an IP_IO instance used for sending IP
1007 @param[in, out] Pkt Pointer to the IP packet to be sent.
1008 @param[in] Sender The IP protocol instance used for sending.
1009 @param[in] Context Optional context data.
1010 @param[in] NotifyData Optional notify data.
1011 @param[in] Dest The destination IP address to send this packet to.
1012 @param[in] OverrideData The data to override some configuration of the IP
1013 instance used for sending.
1015 @retval EFI_SUCCESS The operation is completed successfully.
1016 @retval EFI_NOT_STARTED The IpIo is not configured.
1017 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
1024 IN OUT NET_BUF
*Pkt
,
1025 IN IP_IO_IP_INFO
*Sender OPTIONAL
,
1026 IN VOID
*Context OPTIONAL
,
1027 IN VOID
*NotifyData OPTIONAL
,
1029 IN IP_IO_OVERRIDE
*OverrideData OPTIONAL
1033 EFI_IP4_PROTOCOL
*Ip
;
1034 IP_IO_SEND_ENTRY
*SndEntry
;
1036 if (!IpIo
->IsConfigured
) {
1037 return EFI_NOT_STARTED
;
1040 Ip
= (NULL
== Sender
) ? IpIo
->Ip
: Sender
->Ip
;
1043 // create a new SndEntry
1045 SndEntry
= IpIoCreateSndEntry (IpIo
, Pkt
, Ip
, Context
, NotifyData
, Dest
, OverrideData
);
1046 if (NULL
== SndEntry
) {
1047 return EFI_OUT_OF_RESOURCES
;
1053 Status
= Ip
->Transmit (Ip
, SndEntry
->SndToken
);
1054 if (EFI_ERROR (Status
)) {
1055 IpIoDestroySndEntry (SndEntry
);
1063 Cancel the IP transmit token which wraps this Packet.
1065 @param[in] IpIo Pointer to the IP_IO instance.
1066 @param[in] Packet Pointer to the packet of NET_BUF to cancel.
1077 IP_IO_SEND_ENTRY
*SndEntry
;
1078 EFI_IP4_PROTOCOL
*Ip
;
1080 ASSERT ((IpIo
)!= NULL
&& (Packet
)!= NULL
);
1082 NET_LIST_FOR_EACH (Node
, &IpIo
->PendingSndList
) {
1084 SndEntry
= NET_LIST_USER_STRUCT (Node
, IP_IO_SEND_ENTRY
, Entry
);
1086 if (SndEntry
->Pkt
== Packet
) {
1089 Ip
->Cancel (Ip
, SndEntry
->SndToken
);
1099 Add a new IP instance for sending data.
1101 The function is used to add the IP_IO to the IP_IO sending list. The caller
1102 can later use IpIoFindSender() to get the IP_IO and call IpIoSend() to send
1105 @param[in, out] IpIo Pointer to a IP_IO instance to add a new IP
1106 instance for sending purpose.
1108 @return Pointer to the created IP_IO_IP_INFO structure, NULL if failed.
1118 IP_IO_IP_INFO
*IpInfo
;
1120 ASSERT (IpIo
!= NULL
);
1122 IpInfo
= AllocatePool (sizeof (IP_IO_IP_INFO
));
1123 if (IpInfo
== NULL
) {
1128 // Init this IpInfo, set the Addr and SubnetMask to 0 before we configure the IP
1131 InitializeListHead (&IpInfo
->Entry
);
1132 IpInfo
->ChildHandle
= NULL
;
1134 IpInfo
->SubnetMask
= 0;
1138 // Create the IP instance and open the Ip4 protocol.
1140 Status
= IpIoCreateIpChildOpenProtocol (
1143 &IpInfo
->ChildHandle
,
1144 (VOID
**) &IpInfo
->Ip
1146 if (EFI_ERROR (Status
)) {
1151 // Create the event for the DummyRcvToken.
1153 Status
= gBS
->CreateEvent (
1158 &IpInfo
->DummyRcvToken
.Event
1160 if (EFI_ERROR (Status
)) {
1161 goto ReleaseIpChild
;
1165 // Link this IpInfo into the IpIo.
1167 InsertTailList (&IpIo
->IpList
, &IpInfo
->Entry
);
1173 IpIoCloseProtocolDestroyIpChild (
1181 gBS
->FreePool (IpInfo
);
1188 Configure the IP instance of this IpInfo and start the receiving if Ip4ConfigData
1191 @param[in, out] IpInfo Pointer to the IP_IO_IP_INFO instance.
1192 @param[in, out] Ip4ConfigData The IP4 configure data used to configure the IP
1193 instance, if NULL the IP instance is reset. If
1194 UseDefaultAddress is set to TRUE, and the configure
1195 operation succeeds, the default address information
1196 is written back in this Ip4ConfigData.
1198 @retval EFI_SUCCESS The IP instance of this IpInfo is configured successfully
1199 or no need to reconfigure it.
1200 @retval Others Configuration fails.
1206 IN OUT IP_IO_IP_INFO
*IpInfo
,
1207 IN OUT EFI_IP4_CONFIG_DATA
*Ip4ConfigData OPTIONAL
1211 EFI_IP4_PROTOCOL
*Ip
;
1212 EFI_IP4_MODE_DATA Ip4ModeData
;
1214 ASSERT (IpInfo
!= NULL
);
1216 if (IpInfo
->RefCnt
> 1) {
1218 // This IP instance is shared, don't reconfigure it until it has only one
1219 // consumer. Currently, only the tcp children cloned from their passive parent
1220 // will share the same IP. So this cases only happens while Ip4ConfigData is NULL,
1221 // let the last consumer clean the IP instance.
1228 Status
= Ip
->Configure (Ip
, Ip4ConfigData
);
1229 if (EFI_ERROR (Status
)) {
1233 if (Ip4ConfigData
!= NULL
) {
1235 if (Ip4ConfigData
->UseDefaultAddress
) {
1236 Ip
->GetModeData (Ip
, &Ip4ModeData
, NULL
, NULL
);
1238 Ip4ConfigData
->StationAddress
= Ip4ModeData
.ConfigData
.StationAddress
;
1239 Ip4ConfigData
->SubnetMask
= Ip4ModeData
.ConfigData
.SubnetMask
;
1242 CopyMem (&IpInfo
->Addr
, &Ip4ConfigData
->StationAddress
, sizeof (IP4_ADDR
));
1243 CopyMem (&IpInfo
->SubnetMask
, &Ip4ConfigData
->SubnetMask
, sizeof (IP4_ADDR
));
1245 Status
= Ip
->Receive (Ip
, &IpInfo
->DummyRcvToken
);
1246 if (EFI_ERROR (Status
)) {
1247 Ip
->Configure (Ip
, NULL
);
1252 // The IP instance is reseted, set the stored Addr and SubnetMask to zero.
1255 IpInfo
->SubnetMask
=0;
1265 Destroy an IP instance maintained in IpIo->IpList for
1268 This function pairs with IpIoAddIp(). The IpInfo is previously created by
1269 IpIoAddIp(). The IP_IO_IP_INFO::RefCnt is decremented and the IP instance
1270 will be dstroyed if the RefCnt is zero.
1272 @param[in] IpIo Pointer to the IP_IO instance.
1273 @param[in] IpInfo Pointer to the IpInfo to be removed.
1280 IN IP_IO_IP_INFO
*IpInfo
1283 ASSERT (IpInfo
->RefCnt
> 0);
1285 NET_PUT_REF (IpInfo
);
1287 if (IpInfo
->RefCnt
> 0) {
1292 RemoveEntryList (&IpInfo
->Entry
);
1294 IpInfo
->Ip
->Configure (IpInfo
->Ip
, NULL
);
1296 IpIoCloseProtocolDestroyIpChild (IpIo
->Controller
, IpIo
->Image
, IpInfo
->ChildHandle
);
1298 gBS
->CloseEvent (IpInfo
->DummyRcvToken
.Event
);
1300 gBS
->FreePool (IpInfo
);
1305 Find the first IP protocol maintained in IpIo whose local
1306 address is the same with Src.
1308 This function is called when the caller needs the IpIo to send data to the
1309 specified Src. The IpIo was added previously by IpIoAddIp().
1311 @param[in, out] IpIo Pointer to the pointer of the IP_IO instance.
1312 @param[in] Src The local IP address.
1314 @return Pointer to the IP protocol can be used for sending purpose and its local
1315 @return address is the same with Src.
1321 IN OUT IP_IO
**IpIo
,
1325 LIST_ENTRY
*IpIoEntry
;
1327 LIST_ENTRY
*IpInfoEntry
;
1328 IP_IO_IP_INFO
*IpInfo
;
1330 NET_LIST_FOR_EACH (IpIoEntry
, &mActiveIpIoList
) {
1331 IpIoPtr
= NET_LIST_USER_STRUCT (IpIoEntry
, IP_IO
, Entry
);
1333 if ((*IpIo
!= NULL
) && (*IpIo
!= IpIoPtr
)) {
1337 NET_LIST_FOR_EACH (IpInfoEntry
, &IpIoPtr
->IpList
) {
1338 IpInfo
= NET_LIST_USER_STRUCT (IpInfoEntry
, IP_IO_IP_INFO
, Entry
);
1340 if (IpInfo
->Addr
== Src
) {
1355 Get the ICMP error map information.
1357 The ErrorStatus will be returned. The IsHard and Notify are optional. If they
1358 are not NULL, this routine will fill them.
1360 @param[in] IcmpError IcmpError Type.
1361 @param[out] IsHard Whether it is a hard error.
1362 @param[out] Notify Whether it need to notify SockError.
1364 @return ICMP Error Status, such as EFI_NETWORK_UNREACHABLE.
1369 IpIoGetIcmpErrStatus (
1370 IN ICMP_ERROR IcmpError
,
1371 OUT BOOLEAN
*IsHard OPTIONAL
,
1372 OUT BOOLEAN
*Notify OPTIONAL
1375 ASSERT ((IcmpError
>= ICMP_ERR_UNREACH_NET
) && (IcmpError
<= ICMP_ERR_PARAMPROB
));
1377 if (IsHard
!= NULL
) {
1378 *IsHard
= mIcmpErrMap
[IcmpError
].IsHard
;
1381 if (Notify
!= NULL
) {
1382 *Notify
= mIcmpErrMap
[IcmpError
].Notify
;
1385 switch (IcmpError
) {
1386 case ICMP_ERR_UNREACH_NET
:
1387 return EFI_NETWORK_UNREACHABLE
;
1389 case ICMP_ERR_TIMXCEED_INTRANS
:
1390 case ICMP_ERR_TIMXCEED_REASS
:
1391 case ICMP_ERR_UNREACH_HOST
:
1392 return EFI_HOST_UNREACHABLE
;
1394 case ICMP_ERR_UNREACH_PROTOCOL
:
1395 return EFI_PROTOCOL_UNREACHABLE
;
1397 case ICMP_ERR_UNREACH_PORT
:
1398 return EFI_PORT_UNREACHABLE
;
1400 case ICMP_ERR_MSGSIZE
:
1401 case ICMP_ERR_UNREACH_SRCFAIL
:
1402 case ICMP_ERR_QUENCH
:
1403 case ICMP_ERR_PARAMPROB
:
1404 return EFI_ICMP_ERROR
;
1408 // will never run here!
1411 return EFI_UNSUPPORTED
;