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 ICMP_ERROR_INFO mIcmpErrMap
[10] = {
76 IpIoTransmitHandlerDpc (
89 This function create an IP child, open the IP protocol and return the opened
90 IP protocol as Interface.
92 @param ControllerHandle The controller handle.
93 @param ImageHandle The image handle.
94 @param ChildHandle Pointer to the buffer to save the IP child handle.
95 @param 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 Other 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 ControllerHandle The controller handle.
156 @param ImageHandle the image handle.
157 @param ChildHandle The child handle of the IP child.
159 @retval EFI_SUCCESS The IP protocol is closed and the relevant IP child
161 @retval Other 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 IpIo Pointer to the IP_IO instance.
201 @param Pkt Pointer to the ICMP packet.
202 @param 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
;
280 case ICMP_TYPE_TIMXCEED
:
285 IcmpErr
= (ICMP_ERROR
) (Code
+ ICMP_ERR_TIMXCEED_INTRANS
);
289 case ICMP_TYPE_PARAMPROB
:
294 IcmpErr
= ICMP_ERR_PARAMPROB
;
298 case ICMP_TYPE_SOURCEQUENCH
:
303 IcmpErr
= ICMP_ERR_QUENCH
;
314 // Notify user the ICMP pkt only containing payload except
315 // IP and ICMP header
317 PayLoadHdr
= (UINT8
*) ((UINT8
*) IpHdr
+ EFI_IP4_HEADER_LEN (IpHdr
));
318 TrimBytes
= (UINT32
) (PayLoadHdr
- (UINT8
*) IcmpHdr
);
320 NetbufTrim (Pkt
, TrimBytes
, TRUE
);
322 IpIo
->PktRcvdNotify (EFI_ICMP_ERROR
, IcmpErr
, Session
, Pkt
, IpIo
->RcvdContext
);
329 Free function for receive token of IP_IO. It is used to
330 signal the recycle event to notify IP to recycle the
333 @param Event The event to be signaled.
341 gBS
->SignalEvent ((EFI_EVENT
) Event
);
346 Create a send entry to wrap a packet before sending
349 @param IpIo Pointer to the IP_IO instance.
350 @param Pkt Pointer to the packet.
351 @param Sender Pointer to the IP sender.
352 @param NotifyData Pointer to the notify data.
353 @param Dest Pointer to the destination IP address.
354 @param Override Pointer to the overriden IP_IO data.
356 @return Pointer to the data structure created to wrap the packet. If NULL,
357 resource limit occurred.
364 IN EFI_IP4_PROTOCOL
*Sender
,
365 IN VOID
*Context OPTIONAL
,
366 IN VOID
*NotifyData OPTIONAL
,
368 IN IP_IO_OVERRIDE
*Override
371 IP_IO_SEND_ENTRY
*SndEntry
;
372 EFI_IP4_COMPLETION_TOKEN
*SndToken
;
373 EFI_IP4_TRANSMIT_DATA
*TxData
;
375 EFI_IP4_OVERRIDE_DATA
*OverrideData
;
376 volatile UINT32 Index
;
379 // Allocate resource for SndEntry
381 SndEntry
= AllocatePool (sizeof (IP_IO_SEND_ENTRY
));
382 if (NULL
== SndEntry
) {
387 // Allocate resource for SndToken
389 SndToken
= AllocatePool (sizeof (EFI_IP4_COMPLETION_TOKEN
));
390 if (NULL
== SndToken
) {
391 goto ReleaseSndEntry
;
394 Status
= gBS
->CreateEvent (
401 if (EFI_ERROR (Status
)) {
402 goto ReleaseSndToken
;
406 // Allocate resource for TxData
408 TxData
= AllocatePool (
409 sizeof (EFI_IP4_TRANSMIT_DATA
) +
410 sizeof (EFI_IP4_FRAGMENT_DATA
) * (Pkt
->BlockOpNum
- 1)
413 if (NULL
== TxData
) {
418 // Allocate resource for OverrideData if needed
421 if (NULL
!= Override
) {
423 OverrideData
= AllocatePool (sizeof (EFI_IP4_OVERRIDE_DATA
));
424 if (NULL
== OverrideData
) {
425 goto ReleaseResource
;
428 // Set the fields of OverrideData
430 CopyMem (OverrideData
, Override
, sizeof (*OverrideData
));
434 // Set the fields of TxData
436 CopyMem (&TxData
->DestinationAddress
, &Dest
, sizeof (EFI_IPv4_ADDRESS
));
437 TxData
->OverrideData
= OverrideData
;
438 TxData
->OptionsLength
= 0;
439 TxData
->OptionsBuffer
= NULL
;
440 TxData
->TotalDataLength
= Pkt
->TotalSize
;
441 TxData
->FragmentCount
= Pkt
->BlockOpNum
;
444 for (Index
= 0; Index
< Pkt
->BlockOpNum
; Index
++) {
445 TxData
->FragmentTable
[Index
].FragmentBuffer
= Pkt
->BlockOp
[Index
].Head
;
446 TxData
->FragmentTable
[Index
].FragmentLength
= Pkt
->BlockOp
[Index
].Size
;
450 // Set the fields of SndToken
452 SndToken
->Packet
.TxData
= TxData
;
455 // Set the fields of SndEntry
457 SndEntry
->IpIo
= IpIo
;
458 SndEntry
->Ip
= Sender
;
459 SndEntry
->Context
= Context
;
460 SndEntry
->NotifyData
= NotifyData
;
465 SndEntry
->SndToken
= SndToken
;
467 InsertTailList (&IpIo
->PendingSndList
, &SndEntry
->Entry
);
472 gBS
->FreePool (TxData
);
475 gBS
->CloseEvent (SndToken
->Event
);
478 gBS
->FreePool (SndToken
);
481 gBS
->FreePool (SndEntry
);
488 Destroy the SndEntry.
490 This function pairs with IpIoCreateSndEntry().
492 @param SndEntry Pointer to the send entry to be destroyed.
496 IpIoDestroySndEntry (
497 IN IP_IO_SEND_ENTRY
*SndEntry
500 EFI_IP4_TRANSMIT_DATA
*TxData
;
502 TxData
= SndEntry
->SndToken
->Packet
.TxData
;
504 if (NULL
!= TxData
->OverrideData
) {
505 gBS
->FreePool (TxData
->OverrideData
);
508 gBS
->FreePool (TxData
);
509 NetbufFree (SndEntry
->Pkt
);
510 gBS
->CloseEvent (SndEntry
->SndToken
->Event
);
512 gBS
->FreePool (SndEntry
->SndToken
);
513 RemoveEntryList (&SndEntry
->Entry
);
515 gBS
->FreePool (SndEntry
);
520 Notify function for IP transmit token.
522 @param Context The context passed in by the event notifier.
527 IpIoTransmitHandlerDpc (
532 IP_IO_SEND_ENTRY
*SndEntry
;
534 SndEntry
= (IP_IO_SEND_ENTRY
*) Context
;
536 IpIo
= SndEntry
->IpIo
;
538 if (IpIo
->PktSentNotify
&& SndEntry
->NotifyData
) {
539 IpIo
->PktSentNotify (
540 SndEntry
->SndToken
->Status
,
547 IpIoDestroySndEntry (SndEntry
);
551 Notify function for IP transmit token.
553 @param Event The event signaled.
554 @param Context The context passed in by the event notifier.
560 IpIoTransmitHandler (
566 // Request IpIoTransmitHandlerDpc as a DPC at TPL_CALLBACK
568 NetLibQueueDpc (TPL_CALLBACK
, IpIoTransmitHandlerDpc
, Context
);
573 The dummy handler for the dummy IP receive token.
575 @param Context The context passed in by the event notifier.
580 IpIoDummyHandlerDpc (
584 IP_IO_IP_INFO
*IpInfo
;
585 EFI_IP4_COMPLETION_TOKEN
*DummyToken
;
587 IpInfo
= (IP_IO_IP_INFO
*) Context
;
588 DummyToken
= &(IpInfo
->DummyRcvToken
);
590 if (EFI_ABORTED
== DummyToken
->Status
) {
592 // The reception is actively aborted by the consumer, directly return.
595 } else if (EFI_SUCCESS
== DummyToken
->Status
) {
596 ASSERT (DummyToken
->Packet
.RxData
);
598 gBS
->SignalEvent (DummyToken
->Packet
.RxData
->RecycleSignal
);
601 IpInfo
->Ip
->Receive (IpInfo
->Ip
, DummyToken
);
606 Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK.
608 @param Event The event signaled.
609 @param Context The context passed in by the event notifier.
620 // Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK
622 NetLibQueueDpc (TPL_CALLBACK
, IpIoDummyHandlerDpc
, Context
);
627 Notify function for the IP receive token, used to process
628 the received IP packets.
630 @param Context The context passed in by the event notifier.
635 IpIoListenHandlerDpc (
641 EFI_IP4_RECEIVE_DATA
*RxData
;
642 EFI_IP4_PROTOCOL
*Ip
;
643 EFI_NET_SESSION_DATA Session
;
646 IpIo
= (IP_IO
*) Context
;
649 Status
= IpIo
->RcvToken
.Status
;
650 RxData
= IpIo
->RcvToken
.Packet
.RxData
;
652 if (EFI_ABORTED
== Status
) {
654 // The reception is actively aborted by the consumer, directly return.
659 if (((EFI_SUCCESS
!= Status
) && (EFI_ICMP_ERROR
!= Status
)) || (NULL
== RxData
)) {
661 // Only process the normal packets and the icmp error packets, if RxData is NULL
662 // with Status == EFI_SUCCESS or EFI_ICMP_ERROR, just resume the receive although
663 // this should be a bug of the low layer (IP).
668 if (NULL
== IpIo
->PktRcvdNotify
) {
672 if ((EFI_IP4 (RxData
->Header
->SourceAddress
) != 0) &&
673 !Ip4IsUnicast (EFI_NTOHL (RxData
->Header
->SourceAddress
), 0)) {
675 // The source address is not zero and it's not a unicast IP address, discard it.
681 // Create a netbuffer representing packet
683 Pkt
= NetbufFromExt (
684 (NET_FRAGMENT
*) RxData
->FragmentTable
,
685 RxData
->FragmentCount
,
689 RxData
->RecycleSignal
696 // Create a net session
698 Session
.Source
= EFI_IP4 (RxData
->Header
->SourceAddress
);
699 Session
.Dest
= EFI_IP4 (RxData
->Header
->DestinationAddress
);
700 Session
.IpHdr
= RxData
->Header
;
702 if (EFI_SUCCESS
== Status
) {
704 IpIo
->PktRcvdNotify (EFI_SUCCESS
, (ICMP_ERROR
) 0, &Session
, Pkt
, IpIo
->RcvdContext
);
707 // Status is EFI_ICMP_ERROR
709 Status
= IpIoIcmpHandler (IpIo
, Pkt
, &Session
);
710 if (EFI_ERROR (Status
)) {
718 gBS
->SignalEvent (RxData
->RecycleSignal
);
721 Ip
->Receive (Ip
, &(IpIo
->RcvToken
));
726 Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK
728 @param Event The event signaled.
729 @param Context The context passed in by the event notifier.
742 // Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK
744 NetLibQueueDpc (TPL_CALLBACK
, IpIoListenHandlerDpc
, Context
);
749 Create a new IP_IO instance.
751 This function uses IP4 service binding protocol in Controller to create an IP4
752 child (aka IP4 instance).
754 @param Image The image handle of the driver or application that
756 @param Controller The controller handle that has IP4 service binding
759 @return Pointer to a newly created IP_IO instance, or NULL if failed.
766 IN EFI_HANDLE Controller
772 IpIo
= AllocateZeroPool (sizeof (IP_IO
));
777 InitializeListHead (&(IpIo
->PendingSndList
));
778 InitializeListHead (&(IpIo
->IpList
));
779 IpIo
->Controller
= Controller
;
782 Status
= gBS
->CreateEvent (
787 &(IpIo
->RcvToken
.Event
)
789 if (EFI_ERROR (Status
)) {
794 // Create an IP child and open IP protocol
796 Status
= IpIoCreateIpChildOpenProtocol (
802 if (EFI_ERROR (Status
)) {
810 if (NULL
!= IpIo
->RcvToken
.Event
) {
811 gBS
->CloseEvent (IpIo
->RcvToken
.Event
);
814 gBS
->FreePool (IpIo
);
821 Open an IP_IO instance for use.
823 This function is called after IpIoCreate(). It is used for configuring the IP
824 instance and register the callbacks and their context data for sending and
825 receiving IP packets.
827 @param IpIo Pointer to an IP_IO instance that needs to open.
828 @param OpenData The configuration data and callbacks for the IP_IO
831 @retval EFI_SUCCESS The IP_IO instance opened with OpenData
833 @retval Other Error condition occurred.
840 IN IP_IO_OPEN_DATA
*OpenData
844 EFI_IP4_PROTOCOL
*Ip
;
846 if (IpIo
->IsConfigured
) {
847 return EFI_ACCESS_DENIED
;
855 Status
= Ip
->Configure (Ip
, &OpenData
->IpConfigData
);
856 if (EFI_ERROR (Status
)) {
861 // bugbug: to delete the default route entry in this Ip, if it is:
862 // (0.0.0.0, 0.0.0.0, 0.0.0.0). Delete this statement if Ip modified
865 Status
= Ip
->Routes (Ip
, TRUE
, &mZeroIp4Addr
, &mZeroIp4Addr
, &mZeroIp4Addr
);
867 if (EFI_ERROR (Status
) && (EFI_NOT_FOUND
!= Status
)) {
871 IpIo
->PktRcvdNotify
= OpenData
->PktRcvdNotify
;
872 IpIo
->PktSentNotify
= OpenData
->PktSentNotify
;
874 IpIo
->RcvdContext
= OpenData
->RcvdContext
;
875 IpIo
->SndContext
= OpenData
->SndContext
;
877 IpIo
->Protocol
= OpenData
->IpConfigData
.DefaultProtocol
;
880 // start to listen incoming packet
882 Status
= Ip
->Receive (Ip
, &(IpIo
->RcvToken
));
883 if (EFI_ERROR (Status
)) {
884 Ip
->Configure (Ip
, NULL
);
888 IpIo
->IsConfigured
= TRUE
;
889 InsertTailList (&mActiveIpIoList
, &IpIo
->Entry
);
898 Stop an IP_IO instance.
900 This function is paired with IpIoOpen(). The IP_IO will be unconfigured and all
901 the pending send/receive tokens will be canceled.
903 @param IpIo Pointer to the IP_IO instance that needs to stop.
905 @retval EFI_SUCCESS The IP_IO instance stopped successfully.
906 @retval Other Error condition occurred.
916 EFI_IP4_PROTOCOL
*Ip
;
917 IP_IO_IP_INFO
*IpInfo
;
919 if (!IpIo
->IsConfigured
) {
924 // Remove the IpIo from the active IpIo list.
926 RemoveEntryList (&IpIo
->Entry
);
933 Status
= Ip
->Configure (Ip
, NULL
);
934 if (EFI_ERROR (Status
)) {
938 IpIo
->IsConfigured
= FALSE
;
941 // Detroy the Ip List used by IpIo
944 while (!IsListEmpty (&(IpIo
->IpList
))) {
945 IpInfo
= NET_LIST_HEAD (&(IpIo
->IpList
), IP_IO_IP_INFO
, Entry
);
947 IpIoRemoveIp (IpIo
, IpInfo
);
951 // All pending snd tokens should be flushed by reseting the IP instances.
953 ASSERT (IsListEmpty (&IpIo
->PendingSndList
));
956 // Close the receive event.
958 gBS
->CloseEvent (IpIo
->RcvToken
.Event
);
965 Destroy an IP_IO instance.
967 This function is paired with IpIoCreate(). The IP_IO will be closed first.
968 Resource will be freed afterwards. See IpIoClose().
970 @param IpIo Pointer to the IP_IO instance that needs to be
973 @retval EFI_SUCCESS The IP_IO instance destroyed successfully.
974 @retval Other Error condition occurred.
989 // Close the IP protocol and destroy the child.
991 IpIoCloseProtocolDestroyIpChild (IpIo
->Controller
, IpIo
->Image
, IpIo
->ChildHandle
);
993 gBS
->FreePool (IpIo
);
1000 Send out an IP packet.
1002 This function is called after IpIoOpen(). The data to be sent are wrapped in
1003 Pkt. The IP instance wrapped in IpIo is used for sending by default but can be
1004 overriden by Sender. Other sending configs, like source address and gateway
1005 address etc., are specified in OverrideData.
1007 @param IpIo Pointer to an IP_IO instance used for sending IP
1009 @param Pkt Pointer to the IP packet to be sent.
1010 @param Sender The IP protocol instance used for sending.
1011 @param Context Optional context data
1012 @param NotifyData Optional notify data
1013 @param Dest The destination IP address to send this packet to.
1014 @param OverrideData The data to override some configuration of the IP
1015 instance used for sending.
1017 @retval EFI_SUCCESS The operation is completed successfully.
1018 @retval EFI_NOT_STARTED The IpIo is not configured.
1019 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
1027 IN IP_IO_IP_INFO
*Sender OPTIONAL
,
1028 IN VOID
*Context OPTIONAL
,
1029 IN VOID
*NotifyData OPTIONAL
,
1031 IN IP_IO_OVERRIDE
*OverrideData OPTIONAL
1035 EFI_IP4_PROTOCOL
*Ip
;
1036 IP_IO_SEND_ENTRY
*SndEntry
;
1038 if (!IpIo
->IsConfigured
) {
1039 return EFI_NOT_STARTED
;
1042 Ip
= (NULL
== Sender
) ? IpIo
->Ip
: Sender
->Ip
;
1045 // create a new SndEntry
1047 SndEntry
= IpIoCreateSndEntry (IpIo
, Pkt
, Ip
, Context
, NotifyData
, Dest
, OverrideData
);
1048 if (NULL
== SndEntry
) {
1049 return EFI_OUT_OF_RESOURCES
;
1055 Status
= Ip
->Transmit (Ip
, SndEntry
->SndToken
);
1056 if (EFI_ERROR (Status
)) {
1057 IpIoDestroySndEntry (SndEntry
);
1065 Cancel the IP transmit token which wraps this Packet.
1067 @param IpIo Pointer to the IP_IO instance.
1068 @param Packet Pointer to the packet of NET_BUF to cancel.
1079 IP_IO_SEND_ENTRY
*SndEntry
;
1080 EFI_IP4_PROTOCOL
*Ip
;
1082 ASSERT (IpIo
&& Packet
);
1084 NET_LIST_FOR_EACH (Node
, &IpIo
->PendingSndList
) {
1086 SndEntry
= NET_LIST_USER_STRUCT (Node
, IP_IO_SEND_ENTRY
, Entry
);
1088 if (SndEntry
->Pkt
== Packet
) {
1091 Ip
->Cancel (Ip
, SndEntry
->SndToken
);
1101 Add a new IP instance for sending data.
1103 The function is used to add the IP_IO to the IP_IO sending list. The caller
1104 can later use IpIoFindSender() to get the IP_IO and call IpIoSend() to send
1107 @param IpIo Pointer to a IP_IO instance to add a new IP
1108 instance for sending purpose.
1110 @return Pointer to the created IP_IO_IP_INFO structure, NULL if failed.
1120 IP_IO_IP_INFO
*IpInfo
;
1124 IpInfo
= AllocatePool (sizeof (IP_IO_IP_INFO
));
1125 if (IpInfo
== NULL
) {
1130 // Init this IpInfo, set the Addr and SubnetMask to 0 before we configure the IP
1133 InitializeListHead (&IpInfo
->Entry
);
1134 IpInfo
->ChildHandle
= NULL
;
1136 IpInfo
->SubnetMask
= 0;
1140 // Create the IP instance and open the Ip4 protocol.
1142 Status
= IpIoCreateIpChildOpenProtocol (
1145 &IpInfo
->ChildHandle
,
1146 (VOID
**) &IpInfo
->Ip
1148 if (EFI_ERROR (Status
)) {
1153 // Create the event for the DummyRcvToken.
1155 Status
= gBS
->CreateEvent (
1160 &IpInfo
->DummyRcvToken
.Event
1162 if (EFI_ERROR (Status
)) {
1163 goto ReleaseIpChild
;
1167 // Link this IpInfo into the IpIo.
1169 InsertTailList (&IpIo
->IpList
, &IpInfo
->Entry
);
1175 IpIoCloseProtocolDestroyIpChild (
1183 gBS
->FreePool (IpInfo
);
1190 Configure the IP instance of this IpInfo and start the receiving if Ip4ConfigData
1193 @param IpInfo Pointer to the IP_IO_IP_INFO instance.
1194 @param Ip4ConfigData The IP4 configure data used to configure the IP
1195 instance, if NULL the IP instance is reset. If
1196 UseDefaultAddress is set to TRUE, and the configure
1197 operation succeeds, the default address information
1198 is written back in this Ip4ConfigData.
1200 @retval EFI_STATUS The status returned by IP4->Configure or
1202 @retval Other Configuration fails.
1208 IN IP_IO_IP_INFO
*IpInfo
,
1209 IN OUT EFI_IP4_CONFIG_DATA
*Ip4ConfigData OPTIONAL
1213 EFI_IP4_PROTOCOL
*Ip
;
1214 EFI_IP4_MODE_DATA Ip4ModeData
;
1218 if (IpInfo
->RefCnt
> 1) {
1220 // This IP instance is shared, don't reconfigure it until it has only one
1221 // consumer. Currently, only the tcp children cloned from their passive parent
1222 // will share the same IP. So this cases only happens while Ip4ConfigData is NULL,
1223 // let the last consumer clean the IP instance.
1230 Status
= Ip
->Configure (Ip
, Ip4ConfigData
);
1231 if (EFI_ERROR (Status
)) {
1235 if (Ip4ConfigData
!= NULL
) {
1237 if (Ip4ConfigData
->UseDefaultAddress
) {
1238 Ip
->GetModeData (Ip
, &Ip4ModeData
, NULL
, NULL
);
1240 Ip4ConfigData
->StationAddress
= Ip4ModeData
.ConfigData
.StationAddress
;
1241 Ip4ConfigData
->SubnetMask
= Ip4ModeData
.ConfigData
.SubnetMask
;
1244 CopyMem (&IpInfo
->Addr
, &Ip4ConfigData
->StationAddress
, sizeof (IP4_ADDR
));
1245 CopyMem (&IpInfo
->SubnetMask
, &Ip4ConfigData
->SubnetMask
, sizeof (IP4_ADDR
));
1247 Status
= Ip
->Receive (Ip
, &IpInfo
->DummyRcvToken
);
1248 if (EFI_ERROR (Status
)) {
1249 Ip
->Configure (Ip
, NULL
);
1254 // The IP instance is reseted, set the stored Addr and SubnetMask to zero.
1257 IpInfo
->SubnetMask
=0;
1267 Destroy an IP instance maintained in IpIo->IpList for
1270 This function pairs with IpIoAddIp(). The IpInfo is previously created by
1271 IpIoAddIp(). The IP_IO_IP_INFO::RefCnt is decremented and the IP instance
1272 will be dstroyed if the RefCnt is zero.
1274 @param IpIo Pointer to the IP_IO instance.
1275 @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 This function is called when the caller needs the IpIo to send data to the
1311 specified Src. The IpIo was added previously by IpIoAddIp().
1313 @param IpIo Pointer to the pointer of the IP_IO instance.
1314 @param Src The local IP address.
1316 @return Pointer to the IP protocol can be used for sending purpose and its local
1317 address is the same with Src.
1323 IN OUT IP_IO
**IpIo
,
1327 LIST_ENTRY
*IpIoEntry
;
1329 LIST_ENTRY
*IpInfoEntry
;
1330 IP_IO_IP_INFO
*IpInfo
;
1332 NET_LIST_FOR_EACH (IpIoEntry
, &mActiveIpIoList
) {
1333 IpIoPtr
= NET_LIST_USER_STRUCT (IpIoEntry
, IP_IO
, Entry
);
1335 if ((*IpIo
!= NULL
) && (*IpIo
!= IpIoPtr
)) {
1339 NET_LIST_FOR_EACH (IpInfoEntry
, &IpIoPtr
->IpList
) {
1340 IpInfo
= NET_LIST_USER_STRUCT (IpInfoEntry
, IP_IO_IP_INFO
, Entry
);
1342 if (IpInfo
->Addr
== Src
) {
1357 Get the ICMP error map information.
1359 The ErrorStatus will be returned. The IsHard and Notify are optional. If they
1360 are not NULL, this routine will fill them.
1362 @param IcmpError IcmpError Type
1363 @param IsHard Whether it is a hard error
1364 @param Notify Whether it need to notify SockError
1366 @return ICMP Error Status
1371 IpIoGetIcmpErrStatus (
1372 IN ICMP_ERROR IcmpError
,
1373 OUT BOOLEAN
*IsHard OPTIONAL
,
1374 OUT BOOLEAN
*Notify OPTIONAL
1377 ASSERT ((IcmpError
>= ICMP_ERR_UNREACH_NET
) && (IcmpError
<= ICMP_ERR_PARAMPROB
));
1379 if (IsHard
!= NULL
) {
1380 *IsHard
= mIcmpErrMap
[IcmpError
].IsHard
;
1383 if (Notify
!= NULL
) {
1384 *Notify
= mIcmpErrMap
[IcmpError
].Notify
;
1387 switch (IcmpError
) {
1388 case ICMP_ERR_UNREACH_NET
:
1389 return EFI_NETWORK_UNREACHABLE
;
1391 case ICMP_ERR_TIMXCEED_INTRANS
:
1392 case ICMP_ERR_TIMXCEED_REASS
:
1393 case ICMP_ERR_UNREACH_HOST
:
1394 return EFI_HOST_UNREACHABLE
;
1396 case ICMP_ERR_UNREACH_PROTOCOL
:
1397 return EFI_PROTOCOL_UNREACHABLE
;
1399 case ICMP_ERR_UNREACH_PORT
:
1400 return EFI_PORT_UNREACHABLE
;
1402 case ICMP_ERR_MSGSIZE
:
1403 case ICMP_ERR_UNREACH_SRCFAIL
:
1404 case ICMP_ERR_QUENCH
:
1405 case ICMP_ERR_PARAMPROB
:
1406 return EFI_ICMP_ERROR
;
1410 // will never run here!
1413 return EFI_UNSUPPORTED
;