4 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Protocol/Udp4.h>
19 #include <Library/IpIoLib.h>
20 #include <Library/BaseLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/BaseMemoryLib.h>
23 #include <Library/UefiBootServicesTableLib.h>
24 #include <Library/MemoryAllocationLib.h>
25 #include <Library/DpcLib.h>
28 GLOBAL_REMOVE_IF_UNREFERENCED LIST_ENTRY mActiveIpIoList
= {
33 GLOBAL_REMOVE_IF_UNREFERENCED EFI_IP4_CONFIG_DATA mIp4IoDefaultIpConfigData
= {
50 GLOBAL_REMOVE_IF_UNREFERENCED EFI_IP6_CONFIG_DATA mIp6IoDefaultIpConfigData
= {
55 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
56 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
64 GLOBAL_REMOVE_IF_UNREFERENCED ICMP_ERROR_INFO mIcmpErrMap
[10] = {
65 {FALSE
, TRUE
}, // ICMP_ERR_UNREACH_NET
66 {FALSE
, TRUE
}, // ICMP_ERR_UNREACH_HOST
67 {TRUE
, TRUE
}, // ICMP_ERR_UNREACH_PROTOCOL
68 {TRUE
, TRUE
}, // ICMP_ERR_UNREACH_PORT
69 {TRUE
, TRUE
}, // ICMP_ERR_MSGSIZE
70 {FALSE
, TRUE
}, // ICMP_ERR_UNREACH_SRCFAIL
71 {FALSE
, TRUE
}, // ICMP_ERR_TIMXCEED_INTRANS
72 {FALSE
, TRUE
}, // ICMP_ERR_TIMEXCEED_REASS
73 {FALSE
, FALSE
}, // ICMP_ERR_QUENCH
74 {FALSE
, TRUE
} // ICMP_ERR_PARAMPROB
77 GLOBAL_REMOVE_IF_UNREFERENCED ICMP_ERROR_INFO mIcmp6ErrMap
[10] = {
78 {FALSE
, TRUE
}, // ICMP6_ERR_UNREACH_NET
79 {FALSE
, TRUE
}, // ICMP6_ERR_UNREACH_HOST
80 {TRUE
, TRUE
}, // ICMP6_ERR_UNREACH_PROTOCOL
81 {TRUE
, TRUE
}, // ICMP6_ERR_UNREACH_PORT
82 {TRUE
, TRUE
}, // ICMP6_ERR_PACKAGE_TOOBIG
83 {FALSE
, TRUE
}, // ICMP6_ERR_TIMXCEED_HOPLIMIT
84 {FALSE
, TRUE
}, // ICMP6_ERR_TIMXCEED_REASS
85 {FALSE
, TRUE
}, // ICMP6_ERR_PARAMPROB_HEADER
86 {FALSE
, TRUE
}, // ICMP6_ERR_PARAMPROB_NEXHEADER
87 {FALSE
, TRUE
} // ICMP6_ERR_PARAMPROB_IPV6OPTION
92 Notify function for IP transmit token.
94 @param[in] Context The context passed in by the event notifier.
99 IpIoTransmitHandlerDpc (
105 Notify function for IP transmit token.
107 @param[in] Event The event signaled.
108 @param[in] Context The context passed in by the event notifier.
113 IpIoTransmitHandler (
120 This function create an IP child ,open the IP protocol, and return the opened
121 IP protocol as Interface.
123 @param[in] ControllerHandle The controller handle.
124 @param[in] ImageHandle The image handle.
125 @param[in] ChildHandle Pointer to the buffer to save the IP child handle.
126 @param[in] IpVersion The version of the IP protocol to use, either
128 @param[out] Interface Pointer used to get the IP protocol interface.
130 @retval EFI_SUCCESS The IP child is created and the IP protocol
131 interface is retrieved.
132 @retval Others The required operation failed.
136 IpIoCreateIpChildOpenProtocol (
137 IN EFI_HANDLE ControllerHandle
,
138 IN EFI_HANDLE ImageHandle
,
139 IN EFI_HANDLE
*ChildHandle
,
145 EFI_GUID
*ServiceBindingGuid
;
146 EFI_GUID
*IpProtocolGuid
;
148 if (IpVersion
== IP_VERSION_4
) {
149 ServiceBindingGuid
= &gEfiIp4ServiceBindingProtocolGuid
;
150 IpProtocolGuid
= &gEfiIp4ProtocolGuid
;
151 } else if (IpVersion
== IP_VERSION_6
){
152 ServiceBindingGuid
= &gEfiIp6ServiceBindingProtocolGuid
;
153 IpProtocolGuid
= &gEfiIp6ProtocolGuid
;
155 return EFI_UNSUPPORTED
;
159 // Create an IP child.
161 Status
= NetLibCreateServiceChild (
167 if (EFI_ERROR (Status
)) {
172 // Open the IP protocol installed on the *ChildHandle.
174 Status
= gBS
->OpenProtocol (
180 EFI_OPEN_PROTOCOL_BY_DRIVER
182 if (EFI_ERROR (Status
)) {
184 // On failure, destroy the IP child.
186 NetLibDestroyServiceChild (
199 This function close the previously openned IP protocol and destroy the IP child.
201 @param[in] ControllerHandle The controller handle.
202 @param[in] ImageHandle The image handle.
203 @param[in] ChildHandle The child handle of the IP child.
204 @param[in] IpVersion The version of the IP protocol to use, either
207 @retval EFI_SUCCESS The IP protocol is closed and the relevant IP child
209 @retval Others The required operation failed.
213 IpIoCloseProtocolDestroyIpChild (
214 IN EFI_HANDLE ControllerHandle
,
215 IN EFI_HANDLE ImageHandle
,
216 IN EFI_HANDLE ChildHandle
,
221 EFI_GUID
*ServiceBindingGuid
;
222 EFI_GUID
*IpProtocolGuid
;
224 if (IpVersion
== IP_VERSION_4
) {
225 ServiceBindingGuid
= &gEfiIp4ServiceBindingProtocolGuid
;
226 IpProtocolGuid
= &gEfiIp4ProtocolGuid
;
227 } else if (IpVersion
== IP_VERSION_6
) {
228 ServiceBindingGuid
= &gEfiIp6ServiceBindingProtocolGuid
;
229 IpProtocolGuid
= &gEfiIp6ProtocolGuid
;
231 return EFI_UNSUPPORTED
;
235 // Close the previously openned IP protocol.
245 // Destroy the IP child.
247 Status
= NetLibDestroyServiceChild (
258 This function handles ICMPv4 packets. It is the worker function of
261 @param[in] IpIo Pointer to the IP_IO instance.
262 @param[in, out] Pkt Pointer to the ICMPv4 packet.
263 @param[in] Session Pointer to the net session of this ICMPv4 packet.
265 @retval EFI_SUCCESS The ICMPv4 packet is handled successfully.
266 @retval EFI_ABORTED This type of ICMPv4 packet is not supported.
273 IN EFI_NET_SESSION_DATA
*Session
276 IP4_ICMP_ERROR_HEAD
*IcmpHdr
;
277 EFI_IP4_HEADER
*IpHdr
;
284 ASSERT (IpIo
->IpVersion
== IP_VERSION_4
);
286 IcmpHdr
= NET_PROTO_HDR (Pkt
, IP4_ICMP_ERROR_HEAD
);
287 IpHdr
= (EFI_IP4_HEADER
*) (&IcmpHdr
->IpHead
);
290 // Check the ICMP packet length.
292 if (Pkt
->TotalSize
< ICMP_ERRLEN (IpHdr
)) {
297 Type
= IcmpHdr
->Head
.Type
;
298 Code
= IcmpHdr
->Head
.Code
;
301 // Analyze the ICMP Error in this ICMP pkt
304 case ICMP_TYPE_UNREACH
:
306 case ICMP_CODE_UNREACH_NET
:
307 case ICMP_CODE_UNREACH_HOST
:
308 case ICMP_CODE_UNREACH_PROTOCOL
:
309 case ICMP_CODE_UNREACH_PORT
:
310 case ICMP_CODE_UNREACH_SRCFAIL
:
311 IcmpErr
= (UINT8
) (ICMP_ERR_UNREACH_NET
+ Code
);
315 case ICMP_CODE_UNREACH_NEEDFRAG
:
316 IcmpErr
= ICMP_ERR_MSGSIZE
;
320 case ICMP_CODE_UNREACH_NET_UNKNOWN
:
321 case ICMP_CODE_UNREACH_NET_PROHIB
:
322 case ICMP_CODE_UNREACH_TOSNET
:
323 IcmpErr
= ICMP_ERR_UNREACH_NET
;
327 case ICMP_CODE_UNREACH_HOST_UNKNOWN
:
328 case ICMP_CODE_UNREACH_ISOLATED
:
329 case ICMP_CODE_UNREACH_HOST_PROHIB
:
330 case ICMP_CODE_UNREACH_TOSHOST
:
331 IcmpErr
= ICMP_ERR_UNREACH_HOST
;
341 case ICMP_TYPE_TIMXCEED
:
346 IcmpErr
= (UINT8
) (Code
+ ICMP_ERR_TIMXCEED_INTRANS
);
350 case ICMP_TYPE_PARAMPROB
:
355 IcmpErr
= ICMP_ERR_PARAMPROB
;
359 case ICMP_TYPE_SOURCEQUENCH
:
364 IcmpErr
= ICMP_ERR_QUENCH
;
373 // Notify user the ICMP pkt only containing payload except
374 // IP and ICMP header
376 PayLoadHdr
= (UINT8
*) ((UINT8
*) IpHdr
+ EFI_IP4_HEADER_LEN (IpHdr
));
377 TrimBytes
= (UINT32
) (PayLoadHdr
- (UINT8
*) IcmpHdr
);
379 NetbufTrim (Pkt
, TrimBytes
, TRUE
);
381 IpIo
->PktRcvdNotify (EFI_ICMP_ERROR
, IcmpErr
, Session
, Pkt
, IpIo
->RcvdContext
);
387 This function handles ICMPv6 packets. It is the worker function of
390 @param[in] IpIo Pointer to the IP_IO instance.
391 @param[in, out] Pkt Pointer to the ICMPv6 packet.
392 @param[in] Session Pointer to the net session of this ICMPv6 packet.
394 @retval EFI_SUCCESS The ICMPv6 packet is handled successfully.
395 @retval EFI_ABORTED This type of ICMPv6 packet is not supported.
402 IN EFI_NET_SESSION_DATA
*Session
405 IP6_ICMP_ERROR_HEAD
*IcmpHdr
;
406 EFI_IP6_HEADER
*IpHdr
;
415 ASSERT (IpIo
->IpVersion
== IP_VERSION_6
);
418 // Check the ICMPv6 packet length.
420 if (Pkt
->TotalSize
< sizeof (IP6_ICMP_ERROR_HEAD
)) {
425 IcmpHdr
= NET_PROTO_HDR (Pkt
, IP6_ICMP_ERROR_HEAD
);
426 Type
= IcmpHdr
->Head
.Type
;
427 Code
= IcmpHdr
->Head
.Code
;
430 // Analyze the ICMPv6 Error in this ICMPv6 packet
433 case ICMP_V6_DEST_UNREACHABLE
:
435 case ICMP_V6_NO_ROUTE_TO_DEST
:
436 case ICMP_V6_BEYOND_SCOPE
:
437 case ICMP_V6_ROUTE_REJECTED
:
438 IcmpErr
= ICMP6_ERR_UNREACH_NET
;
442 case ICMP_V6_COMM_PROHIBITED
:
443 case ICMP_V6_ADDR_UNREACHABLE
:
444 case ICMP_V6_SOURCE_ADDR_FAILED
:
445 IcmpErr
= ICMP6_ERR_UNREACH_HOST
;
449 case ICMP_V6_PORT_UNREACHABLE
:
450 IcmpErr
= ICMP6_ERR_UNREACH_PORT
;
460 case ICMP_V6_PACKET_TOO_BIG
:
465 IcmpErr
= ICMP6_ERR_PACKAGE_TOOBIG
;
469 case ICMP_V6_TIME_EXCEEDED
:
474 IcmpErr
= (UINT8
) (ICMP6_ERR_TIMXCEED_HOPLIMIT
+ Code
);
478 case ICMP_V6_PARAMETER_PROBLEM
:
483 IcmpErr
= (UINT8
) (ICMP6_ERR_PARAMPROB_HEADER
+ Code
);
493 // Notify user the ICMPv6 packet only containing payload except
494 // IPv6 basic header, extension header and ICMP header
497 IpHdr
= (EFI_IP6_HEADER
*) (&IcmpHdr
->IpHead
);
498 NextHeader
= IpHdr
->NextHeader
;
499 PayLoadHdr
= (UINT8
*) ((UINT8
*) IcmpHdr
+ sizeof (IP6_ICMP_ERROR_HEAD
));
503 switch (NextHeader
) {
504 case EFI_IP_PROTO_UDP
:
505 case EFI_IP_PROTO_TCP
:
506 case EFI_IP_PROTO_ICMP
:
507 case IP6_NO_NEXT_HEADER
:
513 case IP6_DESTINATION
:
515 // The Hdr Ext Len is 8-bit unsigned integer in 8-octet units, not including
516 // the first 8 octets.
518 NextHeader
= *(PayLoadHdr
);
519 PayLoadHdr
= (UINT8
*) (PayLoadHdr
+ (*(PayLoadHdr
+ 1) + 1) * 8);
525 // The Fragment Header Length is 8 octets.
527 NextHeader
= *(PayLoadHdr
);
528 PayLoadHdr
= (UINT8
*) (PayLoadHdr
+ 8);
538 TrimBytes
= (UINT32
) (PayLoadHdr
- (UINT8
*) IcmpHdr
);
540 NetbufTrim (Pkt
, TrimBytes
, TRUE
);
542 IpIo
->PktRcvdNotify (EFI_ICMP_ERROR
, IcmpErr
, Session
, Pkt
, IpIo
->RcvdContext
);
548 This function handles ICMP packets.
550 @param[in] IpIo Pointer to the IP_IO instance.
551 @param[in, out] Pkt Pointer to the ICMP packet.
552 @param[in] Session Pointer to the net session of this ICMP packet.
554 @retval EFI_SUCCESS The ICMP packet is handled successfully.
555 @retval EFI_ABORTED This type of ICMP packet is not supported.
556 @retval EFI_UNSUPPORTED The IP protocol version in IP_IO is not supported.
563 IN EFI_NET_SESSION_DATA
*Session
567 if (IpIo
->IpVersion
== IP_VERSION_4
) {
569 return IpIoIcmpv4Handler (IpIo
, Pkt
, Session
);
571 } else if (IpIo
->IpVersion
== IP_VERSION_6
) {
573 return IpIoIcmpv6Handler (IpIo
, Pkt
, Session
);
577 return EFI_UNSUPPORTED
;
583 Free function for receive token of IP_IO. It is used to
584 signal the recycle event to notify IP to recycle the
587 @param[in] Event The event to be signaled.
596 gBS
->SignalEvent ((EFI_EVENT
) Event
);
601 Create a send entry to wrap a packet before sending
604 @param[in, out] IpIo Pointer to the IP_IO instance.
605 @param[in, out] Pkt Pointer to the packet.
606 @param[in] Sender Pointer to the IP sender.
607 @param[in] Context Pointer to the context.
608 @param[in] NotifyData Pointer to the notify data.
609 @param[in] Dest Pointer to the destination IP address.
610 @param[in] Override Pointer to the overriden IP_IO data.
612 @return Pointer to the data structure created to wrap the packet. If NULL,
613 @return resource limit occurred.
620 IN IP_IO_IP_PROTOCOL Sender
,
621 IN VOID
*Context OPTIONAL
,
622 IN VOID
*NotifyData OPTIONAL
,
623 IN EFI_IP_ADDRESS
*Dest OPTIONAL
,
624 IN IP_IO_OVERRIDE
*Override
627 IP_IO_SEND_ENTRY
*SndEntry
;
630 NET_FRAGMENT
*ExtFragment
;
631 UINT32 FragmentCount
;
632 IP_IO_OVERRIDE
*OverrideData
;
633 IP_IO_IP_TX_DATA
*TxData
;
634 EFI_IP4_TRANSMIT_DATA
*Ip4TxData
;
635 EFI_IP6_TRANSMIT_DATA
*Ip6TxData
;
637 if ((IpIo
->IpVersion
!= IP_VERSION_4
) && (IpIo
->IpVersion
!= IP_VERSION_6
)) {
646 // Allocate resource for SndEntry
648 SndEntry
= AllocatePool (sizeof (IP_IO_SEND_ENTRY
));
649 if (NULL
== SndEntry
) {
653 Status
= gBS
->CreateEvent (
660 if (EFI_ERROR (Status
)) {
664 FragmentCount
= Pkt
->BlockOpNum
;
667 // Allocate resource for TxData
669 TxData
= (IP_IO_IP_TX_DATA
*) AllocatePool (
670 sizeof (IP_IO_IP_TX_DATA
) + sizeof (NET_FRAGMENT
) * (FragmentCount
- 1)
673 if (NULL
== TxData
) {
678 // Build a fragment table to contain the fragments in the packet.
680 if (IpIo
->IpVersion
== IP_VERSION_4
) {
681 ExtFragment
= (NET_FRAGMENT
*) TxData
->Ip4TxData
.FragmentTable
;
683 ExtFragment
= (NET_FRAGMENT
*) TxData
->Ip6TxData
.FragmentTable
;
686 NetbufBuildExt (Pkt
, ExtFragment
, &FragmentCount
);
690 // Allocate resource for OverrideData if needed
692 if (NULL
!= Override
) {
694 OverrideData
= AllocateCopyPool (sizeof (IP_IO_OVERRIDE
), Override
);
695 if (NULL
== OverrideData
) {
701 // Set other fields of TxData except the fragment table
703 if (IpIo
->IpVersion
== IP_VERSION_4
) {
705 Ip4TxData
= &TxData
->Ip4TxData
;
707 IP4_COPY_ADDRESS (&Ip4TxData
->DestinationAddress
, Dest
);
709 Ip4TxData
->OverrideData
= &OverrideData
->Ip4OverrideData
;
710 Ip4TxData
->OptionsLength
= 0;
711 Ip4TxData
->OptionsBuffer
= NULL
;
712 Ip4TxData
->TotalDataLength
= Pkt
->TotalSize
;
713 Ip4TxData
->FragmentCount
= FragmentCount
;
716 // Set the fields of SndToken
718 SndEntry
->SndToken
.Ip4Token
.Event
= Event
;
719 SndEntry
->SndToken
.Ip4Token
.Packet
.TxData
= Ip4TxData
;
722 Ip6TxData
= &TxData
->Ip6TxData
;
725 CopyMem (&Ip6TxData
->DestinationAddress
, Dest
, sizeof (EFI_IPv6_ADDRESS
));
727 ZeroMem (&Ip6TxData
->DestinationAddress
, sizeof (EFI_IPv6_ADDRESS
));
730 Ip6TxData
->OverrideData
= &OverrideData
->Ip6OverrideData
;
731 Ip6TxData
->DataLength
= Pkt
->TotalSize
;
732 Ip6TxData
->FragmentCount
= FragmentCount
;
733 Ip6TxData
->ExtHdrsLength
= 0;
734 Ip6TxData
->ExtHdrs
= NULL
;
737 // Set the fields of SndToken
739 SndEntry
->SndToken
.Ip6Token
.Event
= Event
;
740 SndEntry
->SndToken
.Ip6Token
.Packet
.TxData
= Ip6TxData
;
744 // Set the fields of SndEntry
746 SndEntry
->IpIo
= IpIo
;
747 SndEntry
->Ip
= Sender
;
748 SndEntry
->Context
= Context
;
749 SndEntry
->NotifyData
= NotifyData
;
754 InsertTailList (&IpIo
->PendingSndList
, &SndEntry
->Entry
);
760 if (OverrideData
!= NULL
) {
761 FreePool (OverrideData
);
764 if (TxData
!= NULL
) {
768 if (SndEntry
!= NULL
) {
773 gBS
->CloseEvent (Event
);
781 Destroy the SndEntry.
783 This function pairs with IpIoCreateSndEntry().
785 @param[in] SndEntry Pointer to the send entry to be destroyed.
789 IpIoDestroySndEntry (
790 IN IP_IO_SEND_ENTRY
*SndEntry
794 IP_IO_IP_TX_DATA
*TxData
;
795 IP_IO_OVERRIDE
*Override
;
797 if (SndEntry
->IpIo
->IpVersion
== IP_VERSION_4
) {
798 Event
= SndEntry
->SndToken
.Ip4Token
.Event
;
799 TxData
= (IP_IO_IP_TX_DATA
*) SndEntry
->SndToken
.Ip4Token
.Packet
.TxData
;
800 Override
= (IP_IO_OVERRIDE
*) TxData
->Ip4TxData
.OverrideData
;
801 } else if (SndEntry
->IpIo
->IpVersion
== IP_VERSION_6
) {
802 Event
= SndEntry
->SndToken
.Ip6Token
.Event
;
803 TxData
= (IP_IO_IP_TX_DATA
*) SndEntry
->SndToken
.Ip6Token
.Packet
.TxData
;
804 Override
= (IP_IO_OVERRIDE
*) TxData
->Ip6TxData
.OverrideData
;
809 gBS
->CloseEvent (Event
);
813 if (NULL
!= Override
) {
817 NetbufFree (SndEntry
->Pkt
);
819 RemoveEntryList (&SndEntry
->Entry
);
826 Notify function for IP transmit token.
828 @param[in] Context The context passed in by the event notifier.
833 IpIoTransmitHandlerDpc (
838 IP_IO_SEND_ENTRY
*SndEntry
;
841 SndEntry
= (IP_IO_SEND_ENTRY
*) Context
;
843 IpIo
= SndEntry
->IpIo
;
845 if (IpIo
->IpVersion
== IP_VERSION_4
) {
846 Status
= SndEntry
->SndToken
.Ip4Token
.Status
;
847 } else if (IpIo
->IpVersion
== IP_VERSION_6
){
848 Status
= SndEntry
->SndToken
.Ip6Token
.Status
;
853 if ((IpIo
->PktSentNotify
!= NULL
) && (SndEntry
->NotifyData
!= NULL
)) {
854 IpIo
->PktSentNotify (
862 IpIoDestroySndEntry (SndEntry
);
867 Notify function for IP transmit token.
869 @param[in] Event The event signaled.
870 @param[in] Context The context passed in by the event notifier.
875 IpIoTransmitHandler (
881 // Request IpIoTransmitHandlerDpc as a DPC at TPL_CALLBACK
883 QueueDpc (TPL_CALLBACK
, IpIoTransmitHandlerDpc
, Context
);
888 The dummy handler for the dummy IP receive token.
890 @param[in] Context The context passed in by the event notifier.
895 IpIoDummyHandlerDpc (
899 IP_IO_IP_INFO
*IpInfo
;
901 EFI_EVENT RecycleEvent
;
903 IpInfo
= (IP_IO_IP_INFO
*) Context
;
905 if ((IpInfo
->IpVersion
!= IP_VERSION_4
) && (IpInfo
->IpVersion
!= IP_VERSION_6
)) {
911 if (IpInfo
->IpVersion
== IP_VERSION_4
) {
912 Status
= IpInfo
->DummyRcvToken
.Ip4Token
.Status
;
914 if (IpInfo
->DummyRcvToken
.Ip4Token
.Packet
.RxData
!= NULL
) {
915 RecycleEvent
= IpInfo
->DummyRcvToken
.Ip4Token
.Packet
.RxData
->RecycleSignal
;
918 Status
= IpInfo
->DummyRcvToken
.Ip6Token
.Status
;
920 if (IpInfo
->DummyRcvToken
.Ip6Token
.Packet
.RxData
!= NULL
) {
921 RecycleEvent
= IpInfo
->DummyRcvToken
.Ip6Token
.Packet
.RxData
->RecycleSignal
;
927 if (EFI_ABORTED
== Status
) {
929 // The reception is actively aborted by the consumer, directly return.
932 } else if (EFI_SUCCESS
== Status
) {
934 // Recycle the RxData.
936 ASSERT (RecycleEvent
!= NULL
);
938 gBS
->SignalEvent (RecycleEvent
);
942 // Continue the receive.
944 if (IpInfo
->IpVersion
== IP_VERSION_4
) {
945 IpInfo
->Ip
.Ip4
->Receive (
947 &IpInfo
->DummyRcvToken
.Ip4Token
950 IpInfo
->Ip
.Ip6
->Receive (
952 &IpInfo
->DummyRcvToken
.Ip6Token
959 This function add IpIoDummyHandlerDpc to the end of the DPC queue.
961 @param[in] Event The event signaled.
962 @param[in] Context The context passed in by the event notifier.
973 // Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK
975 QueueDpc (TPL_CALLBACK
, IpIoDummyHandlerDpc
, Context
);
980 Notify function for the IP receive token, used to process
981 the received IP packets.
983 @param[in] Context The context passed in by the event notifier.
988 IpIoListenHandlerDpc (
994 IP_IO_IP_RX_DATA
*RxData
;
995 EFI_NET_SESSION_DATA Session
;
998 IpIo
= (IP_IO
*) Context
;
1000 if (IpIo
->IpVersion
== IP_VERSION_4
) {
1001 Status
= IpIo
->RcvToken
.Ip4Token
.Status
;
1002 RxData
= (IP_IO_IP_RX_DATA
*) IpIo
->RcvToken
.Ip4Token
.Packet
.RxData
;
1003 } else if (IpIo
->IpVersion
== IP_VERSION_6
) {
1004 Status
= IpIo
->RcvToken
.Ip6Token
.Status
;
1005 RxData
= (IP_IO_IP_RX_DATA
*) IpIo
->RcvToken
.Ip6Token
.Packet
.RxData
;
1010 if (EFI_ABORTED
== Status
) {
1012 // The reception is actively aborted by the consumer, directly return.
1017 if (((EFI_SUCCESS
!= Status
) && (EFI_ICMP_ERROR
!= Status
)) || (NULL
== RxData
)) {
1019 // @bug Only process the normal packets and the icmp error packets, if RxData is NULL
1020 // @bug with Status == EFI_SUCCESS or EFI_ICMP_ERROR, just resume the receive although
1021 // @bug this should be a bug of the low layer (IP).
1026 if (NULL
== IpIo
->PktRcvdNotify
) {
1030 if (IpIo
->IpVersion
== IP_VERSION_4
) {
1031 if ((EFI_IP4 (RxData
->Ip4RxData
.Header
->SourceAddress
) != 0) &&
1032 (IpIo
->SubnetMask
!= 0) &&
1033 IP4_NET_EQUAL (IpIo
->StationIp
, EFI_NTOHL (((EFI_IP4_RECEIVE_DATA
*) RxData
)->Header
->SourceAddress
), IpIo
->SubnetMask
) &&
1034 !NetIp4IsUnicast (EFI_NTOHL (((EFI_IP4_RECEIVE_DATA
*) RxData
)->Header
->SourceAddress
), IpIo
->SubnetMask
)) {
1036 // The source address is not zero and it's not a unicast IP address, discard it.
1041 if (RxData
->Ip4RxData
.DataLength
== 0) {
1043 // Discard zero length data payload packet.
1049 // Create a netbuffer representing IPv4 packet
1051 Pkt
= NetbufFromExt (
1052 (NET_FRAGMENT
*) RxData
->Ip4RxData
.FragmentTable
,
1053 RxData
->Ip4RxData
.FragmentCount
,
1057 RxData
->Ip4RxData
.RecycleSignal
1064 // Create a net session
1066 Session
.Source
.Addr
[0] = EFI_IP4 (RxData
->Ip4RxData
.Header
->SourceAddress
);
1067 Session
.Dest
.Addr
[0] = EFI_IP4 (RxData
->Ip4RxData
.Header
->DestinationAddress
);
1068 Session
.IpHdr
.Ip4Hdr
= RxData
->Ip4RxData
.Header
;
1069 Session
.IpHdrLen
= RxData
->Ip4RxData
.HeaderLength
;
1070 Session
.IpVersion
= IP_VERSION_4
;
1073 if (!NetIp6IsValidUnicast(&RxData
->Ip6RxData
.Header
->SourceAddress
)) {
1077 if (RxData
->Ip6RxData
.DataLength
== 0) {
1079 // Discard zero length data payload packet.
1085 // Create a netbuffer representing IPv6 packet
1087 Pkt
= NetbufFromExt (
1088 (NET_FRAGMENT
*) RxData
->Ip6RxData
.FragmentTable
,
1089 RxData
->Ip6RxData
.FragmentCount
,
1093 RxData
->Ip6RxData
.RecycleSignal
1100 // Create a net session
1104 &RxData
->Ip6RxData
.Header
->SourceAddress
,
1105 sizeof(EFI_IPv6_ADDRESS
)
1109 &RxData
->Ip6RxData
.Header
->DestinationAddress
,
1110 sizeof(EFI_IPv6_ADDRESS
)
1112 Session
.IpHdr
.Ip6Hdr
= RxData
->Ip6RxData
.Header
;
1113 Session
.IpHdrLen
= RxData
->Ip6RxData
.HeaderLength
;
1114 Session
.IpVersion
= IP_VERSION_6
;
1117 if (EFI_SUCCESS
== Status
) {
1119 IpIo
->PktRcvdNotify (EFI_SUCCESS
, 0, &Session
, Pkt
, IpIo
->RcvdContext
);
1122 // Status is EFI_ICMP_ERROR
1124 Status
= IpIoIcmpHandler (IpIo
, Pkt
, &Session
);
1125 if (EFI_ERROR (Status
)) {
1134 if (IpIo
->IpVersion
== IP_VERSION_4
){
1135 gBS
->SignalEvent (RxData
->Ip4RxData
.RecycleSignal
);
1137 gBS
->SignalEvent (RxData
->Ip6RxData
.RecycleSignal
);
1142 if (IpIo
->IpVersion
== IP_VERSION_4
){
1143 IpIo
->Ip
.Ip4
->Receive (IpIo
->Ip
.Ip4
, &(IpIo
->RcvToken
.Ip4Token
));
1145 IpIo
->Ip
.Ip6
->Receive (IpIo
->Ip
.Ip6
, &(IpIo
->RcvToken
.Ip6Token
));
1150 This function add IpIoListenHandlerDpc to the end of the DPC queue.
1152 @param[in] Event The event signaled.
1153 @param[in] Context The context passed in by the event notifier.
1164 // Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK
1166 QueueDpc (TPL_CALLBACK
, IpIoListenHandlerDpc
, Context
);
1171 Create a new IP_IO instance.
1173 This function uses IP4/IP6 service binding protocol in Controller to create
1174 an IP4/IP6 child (aka IP4/IP6 instance).
1176 @param[in] Image The image handle of the driver or application that
1178 @param[in] Controller The controller handle that has IP4 or IP6 service
1179 binding protocol installed.
1180 @param[in] IpVersion The version of the IP protocol to use, either
1183 @return Pointer to a newly created IP_IO instance, or NULL if failed.
1189 IN EFI_HANDLE Image
,
1190 IN EFI_HANDLE Controller
,
1198 ASSERT ((IpVersion
== IP_VERSION_4
) || (IpVersion
== IP_VERSION_6
));
1200 IpIo
= AllocateZeroPool (sizeof (IP_IO
));
1205 InitializeListHead (&(IpIo
->PendingSndList
));
1206 InitializeListHead (&(IpIo
->IpList
));
1207 IpIo
->Controller
= Controller
;
1208 IpIo
->Image
= Image
;
1209 IpIo
->IpVersion
= IpVersion
;
1212 Status
= gBS
->CreateEvent (
1219 if (EFI_ERROR (Status
)) {
1223 if (IpVersion
== IP_VERSION_4
) {
1224 IpIo
->RcvToken
.Ip4Token
.Event
= Event
;
1226 IpIo
->RcvToken
.Ip6Token
.Event
= Event
;
1230 // Create an IP child and open IP protocol
1232 Status
= IpIoCreateIpChildOpenProtocol (
1237 (VOID
**)&(IpIo
->Ip
)
1239 if (EFI_ERROR (Status
)) {
1247 if (Event
!= NULL
) {
1248 gBS
->CloseEvent (Event
);
1251 gBS
->FreePool (IpIo
);
1258 Open an IP_IO instance for use.
1260 This function is called after IpIoCreate(). It is used for configuring the IP
1261 instance and register the callbacks and their context data for sending and
1262 receiving IP packets.
1264 @param[in, out] IpIo Pointer to an IP_IO instance that needs
1266 @param[in] OpenData The configuration data and callbacks for
1269 @retval EFI_SUCCESS The IP_IO instance opened with OpenData
1271 @retval EFI_ACCESS_DENIED The IP_IO instance is configured, avoid to
1273 @retval Others Error condition occurred.
1280 IN IP_IO_OPEN_DATA
*OpenData
1286 if (IpIo
->IsConfigured
) {
1287 return EFI_ACCESS_DENIED
;
1290 IpVersion
= IpIo
->IpVersion
;
1292 ASSERT ((IpVersion
== IP_VERSION_4
) || (IpVersion
== IP_VERSION_6
));
1297 if (IpVersion
== IP_VERSION_4
){
1299 // RawData mode is no supported.
1301 ASSERT (!OpenData
->IpConfigData
.Ip4CfgData
.RawData
);
1302 if (OpenData
->IpConfigData
.Ip4CfgData
.RawData
) {
1303 return EFI_UNSUPPORTED
;
1306 if (!OpenData
->IpConfigData
.Ip4CfgData
.UseDefaultAddress
) {
1307 IpIo
->StationIp
= EFI_NTOHL (OpenData
->IpConfigData
.Ip4CfgData
.StationAddress
);
1308 IpIo
->SubnetMask
= EFI_NTOHL (OpenData
->IpConfigData
.Ip4CfgData
.SubnetMask
);
1311 Status
= IpIo
->Ip
.Ip4
->Configure (
1313 &OpenData
->IpConfigData
.Ip4CfgData
1317 Status
= IpIo
->Ip
.Ip6
->Configure (
1319 &OpenData
->IpConfigData
.Ip6CfgData
1323 if (EFI_ERROR (Status
)) {
1328 // @bug To delete the default route entry in this Ip, if it is:
1329 // @bug (0.0.0.0, 0.0.0.0, 0.0.0.0). Delete this statement if Ip modified
1332 if (IpVersion
== IP_VERSION_4
){
1333 Status
= IpIo
->Ip
.Ip4
->Routes (
1341 if (EFI_ERROR (Status
) && (EFI_NOT_FOUND
!= Status
)) {
1346 IpIo
->PktRcvdNotify
= OpenData
->PktRcvdNotify
;
1347 IpIo
->PktSentNotify
= OpenData
->PktSentNotify
;
1349 IpIo
->RcvdContext
= OpenData
->RcvdContext
;
1350 IpIo
->SndContext
= OpenData
->SndContext
;
1352 if (IpVersion
== IP_VERSION_4
){
1353 IpIo
->Protocol
= OpenData
->IpConfigData
.Ip4CfgData
.DefaultProtocol
;
1356 // start to listen incoming packet
1358 Status
= IpIo
->Ip
.Ip4
->Receive (
1360 &(IpIo
->RcvToken
.Ip4Token
)
1362 if (EFI_ERROR (Status
)) {
1363 IpIo
->Ip
.Ip4
->Configure (IpIo
->Ip
.Ip4
, NULL
);
1369 IpIo
->Protocol
= OpenData
->IpConfigData
.Ip6CfgData
.DefaultProtocol
;
1370 Status
= IpIo
->Ip
.Ip6
->Receive (
1372 &(IpIo
->RcvToken
.Ip6Token
)
1374 if (EFI_ERROR (Status
)) {
1375 IpIo
->Ip
.Ip6
->Configure (IpIo
->Ip
.Ip6
, NULL
);
1380 IpIo
->IsConfigured
= TRUE
;
1381 InsertTailList (&mActiveIpIoList
, &IpIo
->Entry
);
1390 Stop an IP_IO instance.
1392 This function is paired with IpIoOpen(). The IP_IO will be unconfigured and all
1393 the pending send/receive tokens will be canceled.
1395 @param[in, out] IpIo Pointer to the IP_IO instance that needs to stop.
1397 @retval EFI_SUCCESS The IP_IO instance stopped successfully.
1398 @retval Others Error condition occurred.
1408 IP_IO_IP_INFO
*IpInfo
;
1411 if (!IpIo
->IsConfigured
) {
1415 IpVersion
= IpIo
->IpVersion
;
1417 ASSERT ((IpVersion
== IP_VERSION_4
) || (IpVersion
== IP_VERSION_6
));
1420 // Remove the IpIo from the active IpIo list.
1422 RemoveEntryList (&IpIo
->Entry
);
1425 // Configure NULL Ip
1427 if (IpVersion
== IP_VERSION_4
) {
1428 Status
= IpIo
->Ip
.Ip4
->Configure (IpIo
->Ip
.Ip4
, NULL
);
1430 Status
= IpIo
->Ip
.Ip6
->Configure (IpIo
->Ip
.Ip6
, NULL
);
1432 if (EFI_ERROR (Status
)) {
1436 IpIo
->IsConfigured
= FALSE
;
1439 // Detroy the Ip List used by IpIo
1442 while (!IsListEmpty (&(IpIo
->IpList
))) {
1443 IpInfo
= NET_LIST_HEAD (&(IpIo
->IpList
), IP_IO_IP_INFO
, Entry
);
1445 IpIoRemoveIp (IpIo
, IpInfo
);
1449 // All pending send tokens should be flushed by resetting the IP instances.
1451 ASSERT (IsListEmpty (&IpIo
->PendingSndList
));
1454 // Close the receive event.
1456 if (IpVersion
== IP_VERSION_4
){
1457 gBS
->CloseEvent (IpIo
->RcvToken
.Ip4Token
.Event
);
1459 gBS
->CloseEvent (IpIo
->RcvToken
.Ip6Token
.Event
);
1467 Destroy an IP_IO instance.
1469 This function is paired with IpIoCreate(). The IP_IO will be closed first.
1470 Resource will be freed afterwards. See IpIoCloseProtocolDestroyIpChild().
1472 @param[in, out] IpIo Pointer to the IP_IO instance that needs to be
1475 @retval EFI_SUCCESS The IP_IO instance destroyed successfully.
1476 @retval Others Error condition occurred.
1491 // Close the IP protocol and destroy the child.
1493 IpIoCloseProtocolDestroyIpChild (
1500 gBS
->FreePool (IpIo
);
1507 Send out an IP packet.
1509 This function is called after IpIoOpen(). The data to be sent are wrapped in
1510 Pkt. The IP instance wrapped in IpIo is used for sending by default but can be
1511 overriden by Sender. Other sending configs, like source address and gateway
1512 address etc., are specified in OverrideData.
1514 @param[in, out] IpIo Pointer to an IP_IO instance used for sending IP
1516 @param[in, out] Pkt Pointer to the IP packet to be sent.
1517 @param[in] Sender The IP protocol instance used for sending.
1518 @param[in] Context Optional context data.
1519 @param[in] NotifyData Optional notify data.
1520 @param[in] Dest The destination IP address to send this packet to.
1521 @param[in] OverrideData The data to override some configuration of the IP
1522 instance used for sending.
1524 @retval EFI_SUCCESS The operation is completed successfully.
1525 @retval EFI_NOT_STARTED The IpIo is not configured.
1526 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
1533 IN OUT NET_BUF
*Pkt
,
1534 IN IP_IO_IP_INFO
*Sender OPTIONAL
,
1535 IN VOID
*Context OPTIONAL
,
1536 IN VOID
*NotifyData OPTIONAL
,
1537 IN EFI_IP_ADDRESS
*Dest
,
1538 IN IP_IO_OVERRIDE
*OverrideData OPTIONAL
1542 IP_IO_IP_PROTOCOL Ip
;
1543 IP_IO_SEND_ENTRY
*SndEntry
;
1545 ASSERT ((IpIo
->IpVersion
!= IP_VERSION_4
) || (Dest
!= NULL
));
1547 if (!IpIo
->IsConfigured
) {
1548 return EFI_NOT_STARTED
;
1551 Ip
= (NULL
== Sender
) ? IpIo
->Ip
: Sender
->Ip
;
1554 // create a new SndEntry
1556 SndEntry
= IpIoCreateSndEntry (IpIo
, Pkt
, Ip
, Context
, NotifyData
, Dest
, OverrideData
);
1557 if (NULL
== SndEntry
) {
1558 return EFI_OUT_OF_RESOURCES
;
1564 if (IpIo
->IpVersion
== IP_VERSION_4
){
1565 Status
= Ip
.Ip4
->Transmit (
1567 &SndEntry
->SndToken
.Ip4Token
1570 Status
= Ip
.Ip6
->Transmit (
1572 &SndEntry
->SndToken
.Ip6Token
1576 if (EFI_ERROR (Status
)) {
1577 IpIoDestroySndEntry (SndEntry
);
1585 Cancel the IP transmit token which wraps this Packet.
1587 @param[in] IpIo Pointer to the IP_IO instance.
1588 @param[in] Packet Pointer to the packet of NET_BUF to cancel.
1599 IP_IO_SEND_ENTRY
*SndEntry
;
1600 IP_IO_IP_PROTOCOL Ip
;
1602 ASSERT ((IpIo
!= NULL
) && (Packet
!= NULL
));
1604 NET_LIST_FOR_EACH (Node
, &IpIo
->PendingSndList
) {
1606 SndEntry
= NET_LIST_USER_STRUCT (Node
, IP_IO_SEND_ENTRY
, Entry
);
1608 if (SndEntry
->Pkt
== Packet
) {
1612 if (IpIo
->IpVersion
== IP_VERSION_4
) {
1615 &SndEntry
->SndToken
.Ip4Token
1620 &SndEntry
->SndToken
.Ip6Token
1632 Add a new IP instance for sending data.
1634 The function is used to add the IP_IO to the IP_IO sending list. The caller
1635 can later use IpIoFindSender() to get the IP_IO and call IpIoSend() to send
1638 @param[in, out] IpIo Pointer to a IP_IO instance to add a new IP
1639 instance for sending purpose.
1641 @return Pointer to the created IP_IO_IP_INFO structure, NULL if failed.
1651 IP_IO_IP_INFO
*IpInfo
;
1654 ASSERT (IpIo
!= NULL
);
1656 IpInfo
= AllocatePool (sizeof (IP_IO_IP_INFO
));
1657 if (IpInfo
== NULL
) {
1662 // Init this IpInfo, set the Addr and SubnetMask to 0 before we configure the IP
1665 InitializeListHead (&IpInfo
->Entry
);
1666 IpInfo
->ChildHandle
= NULL
;
1667 ZeroMem (&IpInfo
->Addr
, sizeof (IpInfo
->Addr
));
1668 ZeroMem (&IpInfo
->PreMask
, sizeof (IpInfo
->PreMask
));
1671 IpInfo
->IpVersion
= IpIo
->IpVersion
;
1674 // Create the IP instance and open the IP protocol.
1676 Status
= IpIoCreateIpChildOpenProtocol (
1679 &IpInfo
->ChildHandle
,
1681 (VOID
**) &IpInfo
->Ip
1683 if (EFI_ERROR (Status
)) {
1688 // Create the event for the DummyRcvToken.
1690 Status
= gBS
->CreateEvent (
1697 if (EFI_ERROR (Status
)) {
1698 goto ReleaseIpChild
;
1701 if (IpInfo
->IpVersion
== IP_VERSION_4
) {
1702 IpInfo
->DummyRcvToken
.Ip4Token
.Event
= Event
;
1704 IpInfo
->DummyRcvToken
.Ip6Token
.Event
= Event
;
1708 // Link this IpInfo into the IpIo.
1710 InsertTailList (&IpIo
->IpList
, &IpInfo
->Entry
);
1716 IpIoCloseProtocolDestroyIpChild (
1719 IpInfo
->ChildHandle
,
1725 gBS
->FreePool (IpInfo
);
1732 Configure the IP instance of this IpInfo and start the receiving if IpConfigData
1735 @param[in, out] IpInfo Pointer to the IP_IO_IP_INFO instance.
1736 @param[in, out] IpConfigData The IP configure data used to configure the IP
1737 instance, if NULL the IP instance is reset. If
1738 UseDefaultAddress is set to TRUE, and the configure
1739 operation succeeds, the default address information
1740 is written back in this IpConfigData.
1742 @retval EFI_SUCCESS The IP instance of this IpInfo is configured successfully
1743 or no need to reconfigure it.
1744 @retval Others Configuration fails.
1750 IN OUT IP_IO_IP_INFO
*IpInfo
,
1751 IN OUT VOID
*IpConfigData OPTIONAL
1755 IP_IO_IP_PROTOCOL Ip
;
1757 EFI_IP4_MODE_DATA Ip4ModeData
;
1758 EFI_IP6_MODE_DATA Ip6ModeData
;
1760 ASSERT (IpInfo
!= NULL
);
1762 if (IpInfo
->RefCnt
> 1) {
1764 // This IP instance is shared, don't reconfigure it until it has only one
1765 // consumer. Currently, only the tcp children cloned from their passive parent
1766 // will share the same IP. So this cases only happens while IpConfigData is NULL,
1767 // let the last consumer clean the IP instance.
1772 IpVersion
= IpInfo
->IpVersion
;
1773 ASSERT ((IpVersion
== IP_VERSION_4
) || (IpVersion
== IP_VERSION_6
));
1777 if (IpInfo
->IpVersion
== IP_VERSION_4
) {
1778 Status
= Ip
.Ip4
->Configure (Ip
.Ip4
, IpConfigData
);
1780 Status
= Ip
.Ip6
->Configure (Ip
.Ip6
, IpConfigData
);
1783 if (EFI_ERROR (Status
)) {
1787 if (IpConfigData
!= NULL
) {
1788 if (IpInfo
->IpVersion
== IP_VERSION_4
){
1790 if (((EFI_IP4_CONFIG_DATA
*) IpConfigData
)->UseDefaultAddress
) {
1791 Ip
.Ip4
->GetModeData (
1798 IP4_COPY_ADDRESS (&((EFI_IP4_CONFIG_DATA
*) IpConfigData
)->StationAddress
, &Ip4ModeData
.ConfigData
.StationAddress
);
1799 IP4_COPY_ADDRESS (&((EFI_IP4_CONFIG_DATA
*) IpConfigData
)->SubnetMask
, &Ip4ModeData
.ConfigData
.SubnetMask
);
1804 &((EFI_IP4_CONFIG_DATA
*) IpConfigData
)->StationAddress
,
1808 &IpInfo
->PreMask
.SubnetMask
,
1809 &((EFI_IP4_CONFIG_DATA
*) IpConfigData
)->SubnetMask
,
1813 Status
= Ip
.Ip4
->Receive (
1815 &IpInfo
->DummyRcvToken
.Ip4Token
1817 if (EFI_ERROR (Status
)) {
1818 Ip
.Ip4
->Configure (Ip
.Ip4
, NULL
);
1821 Ip
.Ip6
->GetModeData (
1828 if (Ip6ModeData
.IsConfigured
) {
1830 &((EFI_IP6_CONFIG_DATA
*) IpConfigData
)->StationAddress
,
1831 &Ip6ModeData
.ConfigData
.StationAddress
,
1832 sizeof (EFI_IPv6_ADDRESS
)
1835 if (Ip6ModeData
.AddressList
!= NULL
) {
1836 FreePool (Ip6ModeData
.AddressList
);
1839 if (Ip6ModeData
.GroupTable
!= NULL
) {
1840 FreePool (Ip6ModeData
.GroupTable
);
1843 if (Ip6ModeData
.RouteTable
!= NULL
) {
1844 FreePool (Ip6ModeData
.RouteTable
);
1847 if (Ip6ModeData
.NeighborCache
!= NULL
) {
1848 FreePool (Ip6ModeData
.NeighborCache
);
1851 if (Ip6ModeData
.PrefixTable
!= NULL
) {
1852 FreePool (Ip6ModeData
.PrefixTable
);
1855 if (Ip6ModeData
.IcmpTypeList
!= NULL
) {
1856 FreePool (Ip6ModeData
.IcmpTypeList
);
1860 Status
= EFI_NO_MAPPING
;
1866 &Ip6ModeData
.ConfigData
.StationAddress
,
1867 sizeof (EFI_IPv6_ADDRESS
)
1870 Status
= Ip
.Ip6
->Receive (
1872 &IpInfo
->DummyRcvToken
.Ip6Token
1874 if (EFI_ERROR (Status
)) {
1875 Ip
.Ip6
->Configure (Ip
.Ip6
, NULL
);
1880 // The IP instance is reset, set the stored Addr and SubnetMask to zero.
1882 ZeroMem (&IpInfo
->Addr
, sizeof (IpInfo
->Addr
));
1883 ZeroMem (&IpInfo
->PreMask
, sizeof (IpInfo
->PreMask
));
1893 Destroy an IP instance maintained in IpIo->IpList for
1896 This function pairs with IpIoAddIp(). The IpInfo is previously created by
1897 IpIoAddIp(). The IP_IO_IP_INFO::RefCnt is decremented and the IP instance
1898 will be dstroyed if the RefCnt is zero.
1900 @param[in] IpIo Pointer to the IP_IO instance.
1901 @param[in] IpInfo Pointer to the IpInfo to be removed.
1908 IN IP_IO_IP_INFO
*IpInfo
1914 ASSERT (IpInfo
->RefCnt
> 0);
1916 NET_PUT_REF (IpInfo
);
1918 if (IpInfo
->RefCnt
> 0) {
1923 IpVersion
= IpIo
->IpVersion
;
1925 ASSERT ((IpVersion
== IP_VERSION_4
) || (IpVersion
== IP_VERSION_6
));
1927 RemoveEntryList (&IpInfo
->Entry
);
1929 if (IpVersion
== IP_VERSION_4
){
1930 IpInfo
->Ip
.Ip4
->Configure (
1934 IpIoCloseProtocolDestroyIpChild (
1937 IpInfo
->ChildHandle
,
1941 gBS
->CloseEvent (IpInfo
->DummyRcvToken
.Ip4Token
.Event
);
1945 IpInfo
->Ip
.Ip6
->Configure (
1950 IpIoCloseProtocolDestroyIpChild (
1953 IpInfo
->ChildHandle
,
1957 gBS
->CloseEvent (IpInfo
->DummyRcvToken
.Ip6Token
.Event
);
1965 Find the first IP protocol maintained in IpIo whose local
1966 address is the same as Src.
1968 This function is called when the caller needs the IpIo to send data to the
1969 specified Src. The IpIo was added previously by IpIoAddIp().
1971 @param[in, out] IpIo Pointer to the pointer of the IP_IO instance.
1972 @param[in] IpVersion The version of the IP protocol to use, either
1974 @param[in] Src The local IP address.
1976 @return Pointer to the IP protocol can be used for sending purpose and its local
1977 address is the same with Src.
1983 IN OUT IP_IO
**IpIo
,
1985 IN EFI_IP_ADDRESS
*Src
1988 LIST_ENTRY
*IpIoEntry
;
1990 LIST_ENTRY
*IpInfoEntry
;
1991 IP_IO_IP_INFO
*IpInfo
;
1993 ASSERT ((IpVersion
== IP_VERSION_4
) || (IpVersion
== IP_VERSION_6
));
1995 NET_LIST_FOR_EACH (IpIoEntry
, &mActiveIpIoList
) {
1996 IpIoPtr
= NET_LIST_USER_STRUCT (IpIoEntry
, IP_IO
, Entry
);
1998 if (((*IpIo
!= NULL
) && (*IpIo
!= IpIoPtr
)) || (IpIoPtr
->IpVersion
!= IpVersion
)) {
2002 NET_LIST_FOR_EACH (IpInfoEntry
, &IpIoPtr
->IpList
) {
2003 IpInfo
= NET_LIST_USER_STRUCT (IpInfoEntry
, IP_IO_IP_INFO
, Entry
);
2004 if (IpInfo
->IpVersion
== IP_VERSION_4
){
2006 if (EFI_IP4_EQUAL (&IpInfo
->Addr
.v4
, &Src
->v4
)) {
2013 if (EFI_IP6_EQUAL (&IpInfo
->Addr
.v6
, &Src
->v6
)) {
2030 Get the ICMP error map information.
2032 The ErrorStatus will be returned. The IsHard and Notify are optional. If they
2033 are not NULL, this routine will fill them.
2035 @param[in] IcmpError IcmpError Type.
2036 @param[in] IpVersion The version of the IP protocol to use,
2037 either IPv4 or IPv6.
2038 @param[out] IsHard If TRUE, indicates that it is a hard error.
2039 @param[out] Notify If TRUE, SockError needs to be notified.
2041 @return ICMP Error Status, such as EFI_NETWORK_UNREACHABLE.
2046 IpIoGetIcmpErrStatus (
2049 OUT BOOLEAN
*IsHard OPTIONAL
,
2050 OUT BOOLEAN
*Notify OPTIONAL
2053 if (IpVersion
== IP_VERSION_4
) {
2054 ASSERT (IcmpError
<= ICMP_ERR_PARAMPROB
);
2056 if (IsHard
!= NULL
) {
2057 *IsHard
= mIcmpErrMap
[IcmpError
].IsHard
;
2060 if (Notify
!= NULL
) {
2061 *Notify
= mIcmpErrMap
[IcmpError
].Notify
;
2064 switch (IcmpError
) {
2065 case ICMP_ERR_UNREACH_NET
:
2066 return EFI_NETWORK_UNREACHABLE
;
2068 case ICMP_ERR_TIMXCEED_INTRANS
:
2069 case ICMP_ERR_TIMXCEED_REASS
:
2070 case ICMP_ERR_UNREACH_HOST
:
2071 return EFI_HOST_UNREACHABLE
;
2073 case ICMP_ERR_UNREACH_PROTOCOL
:
2074 return EFI_PROTOCOL_UNREACHABLE
;
2076 case ICMP_ERR_UNREACH_PORT
:
2077 return EFI_PORT_UNREACHABLE
;
2079 case ICMP_ERR_MSGSIZE
:
2080 case ICMP_ERR_UNREACH_SRCFAIL
:
2081 case ICMP_ERR_QUENCH
:
2082 case ICMP_ERR_PARAMPROB
:
2083 return EFI_ICMP_ERROR
;
2087 return EFI_UNSUPPORTED
;
2090 } else if (IpVersion
== IP_VERSION_6
) {
2092 ASSERT (IcmpError
<= ICMP6_ERR_PARAMPROB_IPV6OPTION
);
2094 if (IsHard
!= NULL
) {
2095 *IsHard
= mIcmp6ErrMap
[IcmpError
].IsHard
;
2098 if (Notify
!= NULL
) {
2099 *Notify
= mIcmp6ErrMap
[IcmpError
].Notify
;
2102 switch (IcmpError
) {
2103 case ICMP6_ERR_UNREACH_NET
:
2104 return EFI_NETWORK_UNREACHABLE
;
2106 case ICMP6_ERR_UNREACH_HOST
:
2107 case ICMP6_ERR_TIMXCEED_HOPLIMIT
:
2108 case ICMP6_ERR_TIMXCEED_REASS
:
2109 return EFI_HOST_UNREACHABLE
;
2111 case ICMP6_ERR_UNREACH_PROTOCOL
:
2112 return EFI_PROTOCOL_UNREACHABLE
;
2114 case ICMP6_ERR_UNREACH_PORT
:
2115 return EFI_PORT_UNREACHABLE
;
2117 case ICMP6_ERR_PACKAGE_TOOBIG
:
2118 case ICMP6_ERR_PARAMPROB_HEADER
:
2119 case ICMP6_ERR_PARAMPROB_NEXHEADER
:
2120 case ICMP6_ERR_PARAMPROB_IPV6OPTION
:
2121 return EFI_ICMP_ERROR
;
2125 return EFI_UNSUPPORTED
;
2130 // Should never be here
2133 return EFI_UNSUPPORTED
;
2139 Refresh the remote peer's Neighbor Cache entries.
2141 This function is called when the caller needs the IpIo to refresh the existing
2142 IPv6 neighbor cache entries since the neighbor is considered reachable by the
2143 node has recently received a confirmation that packets sent recently to the
2144 neighbor were received by its IP layer.
2146 @param[in] IpIo Pointer to an IP_IO instance
2147 @param[in] Neighbor The IP address of the neighbor
2148 @param[in] Timeout Time in 100-ns units that this entry will
2149 remain in the neighbor cache. A value of
2150 zero means that the entry is permanent.
2151 A value of non-zero means that the entry is
2152 dynamic and will be deleted after Timeout.
2154 @retval EFI_SUCCESS The operation is completed successfully.
2155 @retval EFI_NOT_STARTED The IpIo is not configured.
2156 @retval EFI_INVALID_PARAMETER Neighbor Address is invalid.
2157 @retval EFI_NOT_FOUND The neighbor cache entry is not in the
2159 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
2163 IpIoRefreshNeighbor (
2165 IN EFI_IP_ADDRESS
*Neighbor
,
2169 EFI_IP6_PROTOCOL
*Ip
;
2171 if (!IpIo
->IsConfigured
|| IpIo
->IpVersion
!= IP_VERSION_6
) {
2172 return EFI_NOT_STARTED
;
2177 return Ip
->Neighbors (Ip
, FALSE
, &Neighbor
->v6
, NULL
, Timeout
, TRUE
);