2 The implementation of the Udp4 protocol.
4 Copyright (c) 2006 - 2009, 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.
18 UINT16 mUdp4RandomPort
;
21 This function checks and timeouts the I/O datagrams holding by the corresponding
24 @param[in] Event The event this function registered to.
25 @param[in] Context The context data registered during the creation of
37 This function finds the udp instance by the specified <Address, Port> pair.
39 @param[in] InstanceList Pointer to the head of the list linking the udp
41 @param[in] Address Pointer to the specified IPv4 address.
42 @param[in] Port The udp port number.
44 @retval TRUE The specified <Address, Port> pair is found.
45 @retval FALSE Otherwise.
49 Udp4FindInstanceByPort (
50 IN LIST_ENTRY
*InstanceList
,
51 IN EFI_IPv4_ADDRESS
*Address
,
56 This function is the packet transmitting notify function registered to the IpIo
57 interface. It's called to signal the udp TxToken when IpIo layer completes the
58 transmitting of the udp datagram.
60 @param[in] Status The completion status of the output udp datagram.
61 @param[in] Context Pointer to the context data.
62 @param[in] Sender Pointer to the Ip sender of the udp datagram.
63 @param[in] NotifyData Pointer to the notify data.
75 This function processes the received datagram passed up by the IpIo layer.
77 @param[in] Status The status of this udp datagram.
78 @param[in] IcmpError The IcmpError code, only available when Status is
80 @param[in] NetSession Pointer to the EFI_NET_SESSION_DATA.
81 @param[in] Packet Pointer to the NET_BUF containing the received udp
83 @param[in] Context Pointer to the context data.
89 IN ICMP_ERROR IcmpError
,
90 IN EFI_NET_SESSION_DATA
*NetSession
,
96 This function cancels the token specified by Arg in the Map. This is a callback
97 used by Udp4InstanceCancelToken().
99 @param[in] Map Pointer to the NET_MAP.
100 @param[in] Item Pointer to the NET_MAP_ITEM.
101 @param[in] Arg Pointer to the token to be cancelled, if NULL,
102 the token specified by Item is cancelled.
104 @retval EFI_SUCCESS The token is cancelled if Arg is NULL or the token
105 is not the same as that in the Item if Arg is not
107 @retval EFI_ABORTED Arg is not NULL, and the token specified by Arg is
114 IN NET_MAP_ITEM
*Item
,
115 IN VOID
*Arg OPTIONAL
119 This function matches the received udp datagram with the Instance.
121 @param[in] Instance Pointer to the udp instance context data.
122 @param[in] Udp4Session Pointer to the EFI_UDP4_SESSION_DATA abstracted
123 from the received udp datagram.
125 @retval TRUE The udp datagram matches the receiving requirments of the
127 @retval FALSE Otherwise.
132 IN UDP4_INSTANCE_DATA
*Instance
,
133 IN EFI_UDP4_SESSION_DATA
*Udp4Session
137 This function removes the Wrap specified by Context and release relevant resources.
139 @param[in] Event The Event this notify function registered to.
140 @param[in] Context Pointer to the context data.
145 Udp4RecycleRxDataWrap (
151 This function wraps the Packet and the RxData.
153 @param[in] Instance Pointer to the instance context data.
154 @param[in] Packet Pointer to the buffer containing the received
156 @param[in] RxData Pointer to the EFI_UDP4_RECEIVE_DATA of this
159 @return Pointer to the structure wrapping the RxData and the Packet.
164 IN UDP4_INSTANCE_DATA
*Instance
,
166 IN EFI_UDP4_RECEIVE_DATA
*RxData
170 This function enqueues the received datagram into the instances' receiving queues.
172 @param[in] Udp4Service Pointer to the udp service context data.
173 @param[in] Packet Pointer to the buffer containing the received
175 @param[in] RxData Pointer to the EFI_UDP4_RECEIVE_DATA of this
178 @return The times this datagram is enqueued.
183 IN UDP4_SERVICE_DATA
*Udp4Service
,
185 IN EFI_UDP4_RECEIVE_DATA
*RxData
189 This function delivers the datagrams enqueued in the instances.
191 @param[in] Udp4Service Pointer to the udp service context data.
196 IN UDP4_SERVICE_DATA
*Udp4Service
200 This function demultiplexes the received udp datagram to the apropriate instances.
202 @param[in] Udp4Service Pointer to the udp service context data.
203 @param[in] NetSession Pointer to the EFI_NET_SESSION_DATA abstrated from
204 the received datagram.
205 @param[in] Packet Pointer to the buffer containing the received udp
211 IN UDP4_SERVICE_DATA
*Udp4Service
,
212 IN EFI_NET_SESSION_DATA
*NetSession
,
217 This function handles the received Icmp Error message and demultiplexes it to the
220 @param[in] Udp4Service Pointer to the udp service context data.
221 @param[in] IcmpError The icmp error code.
222 @param[in] NetSession Pointer to the EFI_NET_SESSION_DATA abstracted
223 from the received Icmp Error packet.
224 @param[in] Packet Pointer to the Icmp Error packet.
229 IN UDP4_SERVICE_DATA
*Udp4Service
,
230 IN ICMP_ERROR IcmpError
,
231 IN EFI_NET_SESSION_DATA
*NetSession
,
236 This function builds and sends out a icmp port unreachable message.
238 @param[in] IpIo Pointer to the IP_IO instance.
239 @param[in] NetSession Pointer to the EFI_NET_SESSION_DATA of the packet
240 causes this icmp error message.
241 @param[in] Udp4Header Pointer to the udp header of the datagram causes
242 this icmp error message.
246 Udp4SendPortUnreach (
248 IN EFI_NET_SESSION_DATA
*NetSession
,
254 Create the Udp service context data.
256 @param Udp4Service Pointer to the UDP4_SERVICE_DATA.
257 @param ImageHandle The image handle of this udp4 driver.
258 @param ControllerHandle The controller handle this udp4 driver binds on.
260 @retval EFI_SUCCESS The udp4 service context data is created and
262 @retval EFI_OUT_OF_RESOURCES Cannot allocate memory.
263 @retval other Other error occurs.
268 IN OUT UDP4_SERVICE_DATA
*Udp4Service
,
269 IN EFI_HANDLE ImageHandle
,
270 IN EFI_HANDLE ControllerHandle
274 IP_IO_OPEN_DATA OpenData
;
276 ZeroMem (Udp4Service
, sizeof (UDP4_SERVICE_DATA
));
278 Udp4Service
->Signature
= UDP4_SERVICE_DATA_SIGNATURE
;
279 Udp4Service
->ServiceBinding
= mUdp4ServiceBinding
;
280 Udp4Service
->ImageHandle
= ImageHandle
;
281 Udp4Service
->ControllerHandle
= ControllerHandle
;
282 Udp4Service
->ChildrenNumber
= 0;
284 InitializeListHead (&Udp4Service
->ChildrenList
);
287 // Create the IpIo for this service context.
289 Udp4Service
->IpIo
= IpIoCreate (ImageHandle
, ControllerHandle
);
290 if (Udp4Service
->IpIo
== NULL
) {
291 return EFI_OUT_OF_RESOURCES
;
295 // Set the OpenData used to open the IpIo.
297 CopyMem (&OpenData
.IpConfigData
, &mIpIoDefaultIpConfigData
, sizeof (OpenData
.IpConfigData
));
298 OpenData
.IpConfigData
.AcceptBroadcast
= TRUE
;
299 OpenData
.RcvdContext
= (VOID
*) Udp4Service
;
300 OpenData
.SndContext
= NULL
;
301 OpenData
.PktRcvdNotify
= Udp4DgramRcvd
;
302 OpenData
.PktSentNotify
= Udp4DgramSent
;
305 // Configure and start the IpIo.
307 Status
= IpIoOpen (Udp4Service
->IpIo
, &OpenData
);
308 if (EFI_ERROR (Status
)) {
313 // Create the event for Udp timeout checking.
315 Status
= gBS
->CreateEvent (
316 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
320 &Udp4Service
->TimeoutEvent
322 if (EFI_ERROR (Status
)) {
327 // Start the timeout timer event.
329 Status
= gBS
->SetTimer (
330 Udp4Service
->TimeoutEvent
,
332 UDP4_TIMEOUT_INTERVAL
334 if (EFI_ERROR (Status
)) {
342 if (Udp4Service
->TimeoutEvent
!= NULL
) {
343 gBS
->CloseEvent (Udp4Service
->TimeoutEvent
);
346 IpIoDestroy (Udp4Service
->IpIo
);
353 Clean the Udp service context data.
355 @param[in] Udp4Service Pointer to the UDP4_SERVICE_DATA.
360 IN UDP4_SERVICE_DATA
*Udp4Service
364 // Cancel the TimeoutEvent timer.
366 gBS
->SetTimer (Udp4Service
->TimeoutEvent
, TimerCancel
, 0);
369 // Close the TimeoutEvent timer.
371 gBS
->CloseEvent (Udp4Service
->TimeoutEvent
);
376 IpIoDestroy (Udp4Service
->IpIo
);
381 This function checks and timeouts the I/O datagrams holding by the corresponding
384 @param[in] Event The event this function registered to.
385 @param[in] Context The context data registered during the creation of
396 UDP4_SERVICE_DATA
*Udp4Service
;
398 UDP4_INSTANCE_DATA
*Instance
;
399 LIST_ENTRY
*WrapEntry
;
400 LIST_ENTRY
*NextEntry
;
401 UDP4_RXDATA_WRAP
*Wrap
;
403 Udp4Service
= (UDP4_SERVICE_DATA
*) Context
;
404 NET_CHECK_SIGNATURE (Udp4Service
, UDP4_SERVICE_DATA_SIGNATURE
);
406 NET_LIST_FOR_EACH (Entry
, &Udp4Service
->ChildrenList
) {
408 // Iterate all the instances belonging to this service context.
410 Instance
= NET_LIST_USER_STRUCT (Entry
, UDP4_INSTANCE_DATA
, Link
);
411 NET_CHECK_SIGNATURE (Instance
, UDP4_INSTANCE_DATA_SIGNATURE
);
413 if (!Instance
->Configured
|| (Instance
->ConfigData
.ReceiveTimeout
== 0)) {
415 // Skip this instance if it's not configured or no receive timeout.
420 NET_LIST_FOR_EACH_SAFE (WrapEntry
, NextEntry
, &Instance
->RcvdDgramQue
) {
422 // Iterate all the rxdatas belonging to this udp instance.
424 Wrap
= NET_LIST_USER_STRUCT (WrapEntry
, UDP4_RXDATA_WRAP
, Link
);
427 // TimeoutTick unit is microsecond, MNP_TIMEOUT_CHECK_INTERVAL unit is 100ns.
429 if (Wrap
->TimeoutTick
<= (UDP4_TIMEOUT_INTERVAL
/ 10)) {
431 // Remove this RxData if it timeouts.
433 Udp4RecycleRxDataWrap (NULL
, (VOID
*) Wrap
);
435 Wrap
->TimeoutTick
-= (UDP4_TIMEOUT_INTERVAL
/ 10);
443 This function intializes the new created udp instance.
445 @param Udp4Service Pointer to the UDP4_SERVICE_DATA.
446 @param Instance Pointer to the un-initialized UDP4_INSTANCE_DATA.
451 IN UDP4_SERVICE_DATA
*Udp4Service
,
452 IN OUT UDP4_INSTANCE_DATA
*Instance
456 // Set the signature.
458 Instance
->Signature
= UDP4_INSTANCE_DATA_SIGNATURE
;
463 InitializeListHead (&Instance
->Link
);
464 InitializeListHead (&Instance
->RcvdDgramQue
);
465 InitializeListHead (&Instance
->DeliveredDgramQue
);
468 // Init the NET_MAPs.
470 NetMapInit (&Instance
->TxTokens
);
471 NetMapInit (&Instance
->RxTokens
);
472 NetMapInit (&Instance
->McastIps
);
475 // Save the pointer to the UDP4_SERVICE_DATA, and initialize other members.
477 Instance
->Udp4Service
= Udp4Service
;
478 CopyMem (&Instance
->Udp4Proto
, &mUdp4Protocol
, sizeof (Instance
->Udp4Proto
));
479 Instance
->IcmpError
= EFI_SUCCESS
;
480 Instance
->Configured
= FALSE
;
481 Instance
->IsNoMapping
= FALSE
;
482 Instance
->Destroyed
= FALSE
;
487 This function cleans the udp instance.
489 @param[in] Instance Pointer to the UDP4_INSTANCE_DATA to clean.
494 IN UDP4_INSTANCE_DATA
*Instance
497 NetMapClean (&Instance
->McastIps
);
498 NetMapClean (&Instance
->RxTokens
);
499 NetMapClean (&Instance
->TxTokens
);
504 This function finds the udp instance by the specified <Address, Port> pair.
506 @param[in] InstanceList Pointer to the head of the list linking the udp
508 @param[in] Address Pointer to the specified IPv4 address.
509 @param[in] Port The udp port number.
511 @retval TRUE The specified <Address, Port> pair is found.
512 @retval FALSE Otherwise.
516 Udp4FindInstanceByPort (
517 IN LIST_ENTRY
*InstanceList
,
518 IN EFI_IPv4_ADDRESS
*Address
,
523 UDP4_INSTANCE_DATA
*Instance
;
524 EFI_UDP4_CONFIG_DATA
*ConfigData
;
526 NET_LIST_FOR_EACH (Entry
, InstanceList
) {
528 // Iterate all the udp instances.
530 Instance
= NET_LIST_USER_STRUCT (Entry
, UDP4_INSTANCE_DATA
, Link
);
531 ConfigData
= &Instance
->ConfigData
;
533 if (!Instance
->Configured
|| ConfigData
->AcceptAnyPort
) {
535 // If the instance is not configured or the configdata of the instance indicates
536 // this instance accepts any port, skip it.
541 if (EFI_IP4_EQUAL (&ConfigData
->StationAddress
, Address
) &&
542 (ConfigData
->StationPort
== Port
)) {
544 // if both the address and the port are the same, return TRUE.
551 // return FALSE when matching fails.
558 This function tries to bind the udp instance according to the configured port
561 @param InstanceList Pointer to the head of the list linking the udp
563 @param ConfigData Pointer to the ConfigData of the instance to be
564 bound. ConfigData->StationPort will be assigned
565 with an available port value on success.
567 @retval EFI_SUCCESS The bound operation is completed successfully.
568 @retval EFI_ACCESS_DENIED The <Address, Port> specified by the ConfigData is
569 already used by other instance.
570 @retval EFI_OUT_OF_RESOURCES No available port resources.
575 IN LIST_ENTRY
*InstanceList
,
576 IN OUT EFI_UDP4_CONFIG_DATA
*ConfigData
579 EFI_IPv4_ADDRESS
*StationAddress
;
582 if (ConfigData
->AcceptAnyPort
) {
586 StationAddress
= &ConfigData
->StationAddress
;
588 if (ConfigData
->StationPort
!= 0) {
590 if (!ConfigData
->AllowDuplicatePort
&&
591 Udp4FindInstanceByPort (InstanceList
, StationAddress
, ConfigData
->StationPort
)) {
593 // Do not allow duplicate port and the port is already used by other instance.
595 return EFI_ACCESS_DENIED
;
599 // select a random port for this instance;
602 if (ConfigData
->AllowDuplicatePort
) {
604 // Just pick up the random port if the instance allows duplicate port.
606 ConfigData
->StationPort
= mUdp4RandomPort
;
609 StartPort
= mUdp4RandomPort
;
611 while (Udp4FindInstanceByPort(InstanceList
, StationAddress
, mUdp4RandomPort
)) {
614 if (mUdp4RandomPort
== 0) {
615 mUdp4RandomPort
= UDP4_PORT_KNOWN
;
618 if (mUdp4RandomPort
== StartPort
) {
620 // No available port.
622 return EFI_OUT_OF_RESOURCES
;
626 ConfigData
->StationPort
= mUdp4RandomPort
;
630 if (mUdp4RandomPort
== 0) {
631 mUdp4RandomPort
= UDP4_PORT_KNOWN
;
640 This function is used to check whether the NewConfigData has any un-reconfigurable
641 parameters changed compared to the OldConfigData.
643 @param[in] OldConfigData Pointer to the current ConfigData the udp instance
645 @param[in] NewConfigData Pointer to the new ConfigData.
647 @retval TRUE The instance is reconfigurable.
648 @retval FALSE Otherwise.
652 Udp4IsReconfigurable (
653 IN EFI_UDP4_CONFIG_DATA
*OldConfigData
,
654 IN EFI_UDP4_CONFIG_DATA
*NewConfigData
657 if ((NewConfigData
->AcceptAnyPort
!= OldConfigData
->AcceptAnyPort
) ||
658 (NewConfigData
->AcceptBroadcast
!= OldConfigData
->AcceptBroadcast
) ||
659 (NewConfigData
->AcceptPromiscuous
!= OldConfigData
->AcceptPromiscuous
) ||
660 (NewConfigData
->AllowDuplicatePort
!= OldConfigData
->AllowDuplicatePort
)
663 // The receiving filter parameters cannot be changed.
668 if ((!NewConfigData
->AcceptAnyPort
) &&
669 (NewConfigData
->StationPort
!= OldConfigData
->StationPort
)
672 // The port is not changeable.
677 if (!NewConfigData
->AcceptPromiscuous
) {
679 if (NewConfigData
->UseDefaultAddress
!= OldConfigData
->UseDefaultAddress
) {
681 // The NewConfigData differs to the old one on the UseDefaultAddress.
686 if (!NewConfigData
->UseDefaultAddress
&&
687 (!EFI_IP4_EQUAL (&NewConfigData
->StationAddress
, &OldConfigData
->StationAddress
) ||
688 !EFI_IP4_EQUAL (&NewConfigData
->SubnetMask
, &OldConfigData
->SubnetMask
))
691 // If the instance doesn't use the default address, and the new address or
692 // new subnet mask is different from the old values.
698 if (!EFI_IP4_EQUAL (&NewConfigData
->RemoteAddress
, &OldConfigData
->RemoteAddress
)) {
700 // The remoteaddress is not the same.
705 if (!EFI_IP4_EQUAL (&NewConfigData
->RemoteAddress
, &mZeroIp4Addr
) &&
706 NewConfigData
->RemotePort
!= OldConfigData
->RemotePort
709 // The RemotePort differs if it's designated in the configdata.
715 // All checks pass, return TRUE.
722 This function builds the Ip4 configdata from the Udp4ConfigData.
724 @param[in] Udp4ConfigData Pointer to the EFI_UDP4_CONFIG_DATA.
725 @param[in, out] Ip4ConfigData Pointer to the EFI_IP4_CONFIG_DATA.
729 Udp4BuildIp4ConfigData (
730 IN EFI_UDP4_CONFIG_DATA
*Udp4ConfigData
,
731 IN OUT EFI_IP4_CONFIG_DATA
*Ip4ConfigData
734 CopyMem (Ip4ConfigData
, &mIpIoDefaultIpConfigData
, sizeof (*Ip4ConfigData
));
736 Ip4ConfigData
->DefaultProtocol
= EFI_IP_PROTO_UDP
;
737 Ip4ConfigData
->AcceptBroadcast
= Udp4ConfigData
->AcceptBroadcast
;
738 Ip4ConfigData
->AcceptPromiscuous
= Udp4ConfigData
->AcceptPromiscuous
;
739 Ip4ConfigData
->UseDefaultAddress
= Udp4ConfigData
->UseDefaultAddress
;
740 CopyMem (&Ip4ConfigData
->StationAddress
, &Udp4ConfigData
->StationAddress
, sizeof (EFI_IPv4_ADDRESS
));
741 CopyMem (&Ip4ConfigData
->SubnetMask
, &Udp4ConfigData
->SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
744 // use the -1 magic number to disable the receiving process of the ip instance.
746 Ip4ConfigData
->ReceiveTimeout
= (UINT32
) (-1);
751 This function validates the TxToken, it returns the error code according to the spec.
753 @param[in] Instance Pointer to the udp instance context data.
754 @param[in] TxToken Pointer to the token to be checked.
756 @retval EFI_SUCCESS The TxToken is valid.
757 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: This is
758 NULL. Token is NULL. Token.Event is NULL.
759 Token.Packet.TxData is NULL.
760 Token.Packet.TxData.FragmentCount is zero.
761 Token.Packet.TxData.DataLength is not equal to the
762 sum of fragment lengths. One or more of the
763 Token.Packet.TxData.FragmentTable[].
764 FragmentLength fields is zero. One or more of the
765 Token.Packet.TxData.FragmentTable[].
766 FragmentBuffer fields is NULL.
767 Token.Packet.TxData. GatewayAddress is not a
768 unicast IPv4 address if it is not NULL. One or
769 more IPv4 addresses in Token.Packet.TxData.
770 UdpSessionData are not valid unicast IPv4
771 addresses if the UdpSessionData is not NULL.
772 @retval EFI_BAD_BUFFER_SIZE The data length is greater than the maximum UDP
777 Udp4ValidateTxToken (
778 IN UDP4_INSTANCE_DATA
*Instance
,
779 IN EFI_UDP4_COMPLETION_TOKEN
*TxToken
782 EFI_UDP4_TRANSMIT_DATA
*TxData
;
785 EFI_UDP4_CONFIG_DATA
*ConfigData
;
786 EFI_UDP4_SESSION_DATA
*UdpSessionData
;
787 IP4_ADDR SourceAddress
;
788 IP4_ADDR GatewayAddress
;
790 if (TxToken
->Event
== NULL
) {
791 return EFI_INVALID_PARAMETER
;
794 TxData
= TxToken
->Packet
.TxData
;
796 if ((TxData
== NULL
) || (TxData
->FragmentCount
== 0)) {
797 return EFI_INVALID_PARAMETER
;
801 for (Index
= 0; Index
< TxData
->FragmentCount
; Index
++) {
803 if ((TxData
->FragmentTable
[Index
].FragmentBuffer
== NULL
) ||
804 (TxData
->FragmentTable
[Index
].FragmentLength
== 0)) {
806 // if the FragmentBuffer is NULL or the FragmentLeng is zero.
808 return EFI_INVALID_PARAMETER
;
811 TotalLen
+= TxData
->FragmentTable
[Index
].FragmentLength
;
814 if (TotalLen
!= TxData
->DataLength
) {
816 // The TotalLen calculated by adding all the FragmentLeng doesn't equal to the
819 return EFI_INVALID_PARAMETER
;
822 if (TxData
->GatewayAddress
!= NULL
) {
823 CopyMem (&GatewayAddress
, TxData
->GatewayAddress
, sizeof (IP4_ADDR
));
825 if (!Ip4IsUnicast (NTOHL (GatewayAddress
), 0)) {
827 // The specified GatewayAddress is not a unicast IPv4 address while it's not 0.
829 return EFI_INVALID_PARAMETER
;
833 ConfigData
= &Instance
->ConfigData
;
834 UdpSessionData
= TxData
->UdpSessionData
;
836 if (UdpSessionData
!= NULL
) {
838 CopyMem (&SourceAddress
, &UdpSessionData
->SourceAddress
, sizeof (IP4_ADDR
));
840 if ((SourceAddress
!= 0) && !Ip4IsUnicast (HTONL (SourceAddress
), 0)) {
842 // Check whether SourceAddress is a valid IPv4 address in case it's not zero.
843 // The configured station address is used if SourceAddress is zero.
845 return EFI_INVALID_PARAMETER
;
848 if ((UdpSessionData
->DestinationPort
== 0) && (ConfigData
->RemotePort
== 0)) {
850 // Ambiguous, no avalaible DestinationPort for this token.
852 return EFI_INVALID_PARAMETER
;
855 if (EFI_IP4_EQUAL (&UdpSessionData
->DestinationAddress
, &mZeroIp4Addr
)) {
857 // The DestinationAddress specified in the UdpSessionData is 0.
859 return EFI_INVALID_PARAMETER
;
861 } else if (EFI_IP4_EQUAL (&ConfigData
->RemoteAddress
, &mZeroIp4Addr
)) {
863 // the configured RemoteAddress is all zero, and the user doens't override the
864 // destination address.
866 return EFI_INVALID_PARAMETER
;
869 if (TxData
->DataLength
> UDP4_MAX_DATA_SIZE
) {
870 return EFI_BAD_BUFFER_SIZE
;
878 This function checks whether the specified Token duplicates with the one in the Map.
880 @param[in] Map Pointer to the NET_MAP.
881 @param[in] Item Pointer to the NET_MAP_ITEM contain the pointer to
883 @param[in] Context Pointer to the Token to be checked.
885 @retval EFI_SUCCESS The Token specified by Context differs from the
887 @retval EFI_ACCESS_DENIED The Token duplicates with the one in the Item.
893 IN NET_MAP_ITEM
*Item
,
897 EFI_UDP4_COMPLETION_TOKEN
*Token
;
898 EFI_UDP4_COMPLETION_TOKEN
*TokenInItem
;
900 Token
= (EFI_UDP4_COMPLETION_TOKEN
*) Context
;
901 TokenInItem
= (EFI_UDP4_COMPLETION_TOKEN
*) Item
->Key
;
903 if ((Token
== TokenInItem
) || (Token
->Event
== TokenInItem
->Event
)) {
905 // The Token duplicates with the TokenInItem in case either the two pointers are the
906 // same or the Events of these two tokens are the same.
908 return EFI_ACCESS_DENIED
;
916 This function calculates the checksum for the Packet, utilizing the pre-calculated
917 pseudo HeadSum to reduce some overhead.
919 @param[in] Packet Pointer to the NET_BUF contains the udp datagram.
920 @param[in] HeadSum Checksum of the pseudo header execpt the length
923 @retval The 16-bit checksum of this udp datagram.
934 Checksum
= NetbufChecksum (Packet
);
935 Checksum
= NetAddChecksum (Checksum
, HeadSum
);
937 Checksum
= NetAddChecksum (Checksum
, HTONS ((UINT16
) Packet
->TotalSize
));
939 return (UINT16
) ~Checksum
;
944 This function removes the specified Token from the TokenMap.
946 @param TokenMap Pointer to the NET_MAP containing the tokens.
947 @param Token Pointer to the Token to be removed.
949 @retval EFI_SUCCESS The specified Token is removed from the TokenMap.
950 @retval EFI_NOT_FOUND The specified Token is not found in the TokenMap.
955 IN OUT NET_MAP
*TokenMap
,
956 IN EFI_UDP4_COMPLETION_TOKEN
*Token
962 // Find the Token first.
964 Item
= NetMapFindKey (TokenMap
, (VOID
*) Token
);
968 // Remove the token if it's found in the map.
970 NetMapRemoveItem (TokenMap
, Item
, NULL
);
975 return EFI_NOT_FOUND
;
980 This function is the packet transmitting notify function registered to the IpIo
981 interface. It's called to signal the udp TxToken when IpIo layer completes the
982 transmitting of the udp datagram.
984 @param[in] Status The completion status of the output udp datagram.
985 @param[in] Context Pointer to the context data.
986 @param[in] Sender Pointer to the Ip sender of the udp datagram.
987 @param[in] NotifyData Pointer to the notify data.
992 IN EFI_STATUS Status
,
998 UDP4_INSTANCE_DATA
*Instance
;
999 EFI_UDP4_COMPLETION_TOKEN
*Token
;
1001 Instance
= (UDP4_INSTANCE_DATA
*) Context
;
1002 Token
= (EFI_UDP4_COMPLETION_TOKEN
*) NotifyData
;
1004 if (Udp4RemoveToken (&Instance
->TxTokens
, Token
) == EFI_SUCCESS
) {
1006 // The token may be cancelled. Only signal it if the remove operation succeeds.
1008 Token
->Status
= Status
;
1009 gBS
->SignalEvent (Token
->Event
);
1016 This function processes the received datagram passed up by the IpIo layer.
1018 @param[in] Status The status of this udp datagram.
1019 @param[in] IcmpError The IcmpError code, only available when Status is
1021 @param[in] NetSession Pointer to the EFI_NET_SESSION_DATA.
1022 @param[in] Packet Pointer to the NET_BUF containing the received udp
1024 @param[in] Context Pointer to the context data.
1029 IN EFI_STATUS Status
,
1030 IN ICMP_ERROR IcmpError
,
1031 IN EFI_NET_SESSION_DATA
*NetSession
,
1036 NET_CHECK_SIGNATURE (Packet
, NET_BUF_SIGNATURE
);
1039 // IpIo only passes received packets with Status EFI_SUCCESS or EFI_ICMP_ERROR.
1041 if (Status
== EFI_SUCCESS
) {
1043 // Demultiplex the received datagram.
1045 Udp4Demultiplex ((UDP4_SERVICE_DATA
*) Context
, NetSession
, Packet
);
1048 // Handle the ICMP_ERROR packet.
1050 Udp4IcmpHandler ((UDP4_SERVICE_DATA
*) Context
, IcmpError
, NetSession
, Packet
);
1054 // Dispatch the DPC queued by the NotifyFunction of the rx token's events
1055 // which are signaled with received data.
1062 This function removes the multicast group specified by Arg from the Map.
1064 @param Map Pointer to the NET_MAP.
1065 @param Item Pointer to the NET_MAP_ITEM.
1066 @param Arg Pointer to the Arg, it's the pointer to a
1067 multicast IPv4 Address.
1069 @retval EFI_SUCCESS The multicast address is removed.
1070 @retval EFI_ABORTED The specified multicast address is removed and the
1076 IN OUT NET_MAP
*Map
,
1077 IN NET_MAP_ITEM
*Item
,
1078 IN VOID
*Arg OPTIONAL
1081 EFI_IPv4_ADDRESS
*McastIp
;
1085 if ((McastIp
!= NULL
) && (!EFI_IP4_EQUAL (McastIp
, &(Item
->Key
)))) {
1087 // McastIp is not NULL and the multicast address contained in the Item
1088 // is not the same as McastIp.
1094 // Remove this Item.
1096 NetMapRemoveItem (Map
, Item
, NULL
);
1098 if (McastIp
!= NULL
) {
1100 // Return EFI_ABORTED in case McastIp is not NULL to terminate the iteration.
1110 This function cancels the token specified by Arg in the Map. This is a callback
1111 used by Udp4InstanceCancelToken().
1113 @param[in] Map Pointer to the NET_MAP.
1114 @param[in] Item Pointer to the NET_MAP_ITEM.
1115 @param[in] Arg Pointer to the token to be cancelled, if NULL,
1116 the token specified by Item is cancelled.
1118 @retval EFI_SUCCESS The token is cancelled if Arg is NULL or the token
1119 is not the same as that in the Item if Arg is not
1121 @retval EFI_ABORTED Arg is not NULL, and the token specified by Arg is
1128 IN NET_MAP_ITEM
*Item
,
1129 IN VOID
*Arg OPTIONAL
1132 EFI_UDP4_COMPLETION_TOKEN
*TokenToCancel
;
1136 if ((Arg
!= NULL
) && (Item
->Key
!= Arg
)) {
1140 if (Item
->Value
!= NULL
) {
1142 // If the token is a transmit token, the corresponding Packet is recorded in
1143 // Item->Value, invoke IpIo to cancel this packet first. The IpIoCancelTxToken
1144 // will invoke Udp4DgramSent, the token will be signaled and this Item will
1145 // be removed from the Map there.
1147 Packet
= (NET_BUF
*) (Item
->Value
);
1148 IpIo
= (IP_IO
*) (*((UINTN
*) &Packet
->ProtoData
[0]));
1150 IpIoCancelTxToken (IpIo
, Packet
);
1153 // The token is a receive token. Abort it and remove it from the Map.
1155 TokenToCancel
= (EFI_UDP4_COMPLETION_TOKEN
*) Item
->Key
;
1156 NetMapRemoveItem (Map
, Item
, NULL
);
1158 TokenToCancel
->Status
= EFI_ABORTED
;
1159 gBS
->SignalEvent (TokenToCancel
->Event
);
1171 This function removes all the Wrap datas in the RcvdDgramQue.
1173 @param[in] Instance Pointer to the udp instance context data.
1177 Udp4FlushRcvdDgram (
1178 IN UDP4_INSTANCE_DATA
*Instance
1181 UDP4_RXDATA_WRAP
*Wrap
;
1183 while (!IsListEmpty (&Instance
->RcvdDgramQue
)) {
1185 // Iterate all the Wraps in the RcvdDgramQue.
1187 Wrap
= NET_LIST_HEAD (&Instance
->RcvdDgramQue
, UDP4_RXDATA_WRAP
, Link
);
1190 // The Wrap will be removed from the RcvdDgramQue by this function call.
1192 Udp4RecycleRxDataWrap (NULL
, (VOID
*) Wrap
);
1199 Cancel Udp4 tokens from the Udp4 instance.
1201 @param[in] Instance Pointer to the udp instance context data.
1202 @param[in] Token Pointer to the token to be canceled, if NULL, all
1203 tokens in this instance will be cancelled.
1205 @retval EFI_SUCCESS The Token is cancelled.
1206 @retval EFI_NOT_FOUND The Token is not found.
1210 Udp4InstanceCancelToken (
1211 IN UDP4_INSTANCE_DATA
*Instance
,
1212 IN EFI_UDP4_COMPLETION_TOKEN
*Token OPTIONAL
1218 // Cancel this token from the TxTokens map.
1220 Status
= NetMapIterate (&Instance
->TxTokens
, Udp4CancelTokens
, Token
);
1222 if ((Token
!= NULL
) && (Status
== EFI_ABORTED
)) {
1224 // If Token isn't NULL and Status is EFI_ABORTED, the token is cancelled from
1225 // the TxTokens, just return success.
1231 // Try to cancel this token from the RxTokens map in condition either the Token
1232 // is NULL or the specified Token is not in TxTokens.
1234 Status
= NetMapIterate (&Instance
->RxTokens
, Udp4CancelTokens
, Token
);
1236 if ((Token
!= NULL
) && (Status
== EFI_SUCCESS
)) {
1238 // If Token isn't NULL and Status is EFI_SUCCESS, the token is neither in the
1239 // TxTokens nor the RxTokens, or say, it's not found.
1241 return EFI_NOT_FOUND
;
1244 ASSERT ((Token
!= NULL
) || ((0 == NetMapGetCount (&Instance
->TxTokens
))
1245 && (0 == NetMapGetCount (&Instance
->RxTokens
))));
1252 This function matches the received udp datagram with the Instance.
1254 @param[in] Instance Pointer to the udp instance context data.
1255 @param[in] Udp4Session Pointer to the EFI_UDP4_SESSION_DATA abstracted
1256 from the received udp datagram.
1258 @retval TRUE The udp datagram matches the receiving requirments of the
1260 @retval FALSE Otherwise.
1265 IN UDP4_INSTANCE_DATA
*Instance
,
1266 IN EFI_UDP4_SESSION_DATA
*Udp4Session
1269 EFI_UDP4_CONFIG_DATA
*ConfigData
;
1270 IP4_ADDR Destination
;
1272 ConfigData
= &Instance
->ConfigData
;
1274 if (ConfigData
->AcceptPromiscuous
) {
1276 // Always matches if this instance is in the promiscuous state.
1281 if ((!ConfigData
->AcceptAnyPort
&& (Udp4Session
->DestinationPort
!= ConfigData
->StationPort
)) ||
1282 ((ConfigData
->RemotePort
!= 0) && (Udp4Session
->SourcePort
!= ConfigData
->RemotePort
))
1285 // The local port or the remote port doesn't match.
1290 if (!EFI_IP4_EQUAL (&ConfigData
->RemoteAddress
, &mZeroIp4Addr
) &&
1291 !EFI_IP4_EQUAL (&ConfigData
->RemoteAddress
, &Udp4Session
->SourceAddress
)
1294 // This datagram doesn't come from the instance's specified sender.
1299 if (EFI_IP4_EQUAL (&ConfigData
->StationAddress
, &mZeroIp4Addr
) ||
1300 EFI_IP4_EQUAL (&Udp4Session
->DestinationAddress
, &ConfigData
->StationAddress
)
1303 // The instance is configured to receive datagrams destined to any station IP or
1304 // the destination address of this datagram matches the configured station IP.
1309 CopyMem (&Destination
, &Udp4Session
->DestinationAddress
, sizeof (IP4_ADDR
));
1311 if (IP4_IS_LOCAL_BROADCAST (Destination
) && ConfigData
->AcceptBroadcast
) {
1313 // The instance is configured to receive broadcast and this is a broadcast packet.
1318 if (IP4_IS_MULTICAST (NTOHL (Destination
)) &&
1319 NetMapFindKey (&Instance
->McastIps
, (VOID
*) (UINTN
) Destination
) != NULL
1322 // It's a multicast packet and the multicast address is accepted by this instance.
1332 This function removes the Wrap specified by Context and release relevant resources.
1334 @param[in] Event The Event this notify function registered to.
1335 @param[in] Context Pointer to the context data.
1340 Udp4RecycleRxDataWrap (
1345 UDP4_RXDATA_WRAP
*Wrap
;
1347 Wrap
= (UDP4_RXDATA_WRAP
*) Context
;
1350 // Remove the Wrap from the list it belongs to.
1352 RemoveEntryList (&Wrap
->Link
);
1355 // Free the Packet associated with this Wrap.
1357 NetbufFree (Wrap
->Packet
);
1362 gBS
->CloseEvent (Wrap
->RxData
.RecycleSignal
);
1364 gBS
->FreePool (Wrap
);
1369 This function wraps the Packet and the RxData.
1371 @param[in] Instance Pointer to the instance context data.
1372 @param[in] Packet Pointer to the buffer containing the received
1374 @param[in] RxData Pointer to the EFI_UDP4_RECEIVE_DATA of this
1377 @return Pointer to the structure wrapping the RxData and the Packet.
1382 IN UDP4_INSTANCE_DATA
*Instance
,
1384 IN EFI_UDP4_RECEIVE_DATA
*RxData
1388 UDP4_RXDATA_WRAP
*Wrap
;
1391 // Allocate buffer for the Wrap.
1393 Wrap
= AllocatePool (sizeof (UDP4_RXDATA_WRAP
) +
1394 (Packet
->BlockOpNum
- 1) * sizeof (EFI_UDP4_FRAGMENT_DATA
));
1399 InitializeListHead (&Wrap
->Link
);
1401 CopyMem (&Wrap
->RxData
, RxData
, sizeof (Wrap
->RxData
));
1404 // Create the Recycle event.
1406 Status
= gBS
->CreateEvent (
1409 Udp4RecycleRxDataWrap
,
1411 &Wrap
->RxData
.RecycleSignal
1413 if (EFI_ERROR (Status
)) {
1414 gBS
->FreePool (Wrap
);
1418 Wrap
->Packet
= Packet
;
1419 Wrap
->TimeoutTick
= Instance
->ConfigData
.ReceiveTimeout
;
1426 This function enqueues the received datagram into the instances' receiving queues.
1428 @param[in] Udp4Service Pointer to the udp service context data.
1429 @param[in] Packet Pointer to the buffer containing the received
1431 @param[in] RxData Pointer to the EFI_UDP4_RECEIVE_DATA of this
1434 @return The times this datagram is enqueued.
1439 IN UDP4_SERVICE_DATA
*Udp4Service
,
1441 IN EFI_UDP4_RECEIVE_DATA
*RxData
1445 UDP4_INSTANCE_DATA
*Instance
;
1446 UDP4_RXDATA_WRAP
*Wrap
;
1451 NET_LIST_FOR_EACH (Entry
, &Udp4Service
->ChildrenList
) {
1453 // Iterate the instances.
1455 Instance
= NET_LIST_USER_STRUCT (Entry
, UDP4_INSTANCE_DATA
, Link
);
1457 if (!Instance
->Configured
) {
1461 if (Udp4MatchDgram (Instance
, &RxData
->UdpSession
)) {
1463 // Wrap the RxData and put this Wrap into the instances RcvdDgramQue.
1465 Wrap
= Udp4WrapRxData (Instance
, Packet
, RxData
);
1470 NET_GET_REF (Packet
);
1472 InsertTailList (&Instance
->RcvdDgramQue
, &Wrap
->Link
);
1483 This function delivers the received datagrams for the specified instance.
1485 @param[in] Instance Pointer to the instance context data.
1489 Udp4InstanceDeliverDgram (
1490 IN UDP4_INSTANCE_DATA
*Instance
1493 UDP4_RXDATA_WRAP
*Wrap
;
1494 EFI_UDP4_COMPLETION_TOKEN
*Token
;
1496 EFI_UDP4_RECEIVE_DATA
*RxData
;
1499 if (!IsListEmpty (&Instance
->RcvdDgramQue
) &&
1500 !NetMapIsEmpty (&Instance
->RxTokens
)) {
1502 Wrap
= NET_LIST_HEAD (&Instance
->RcvdDgramQue
, UDP4_RXDATA_WRAP
, Link
);
1504 if (NET_BUF_SHARED (Wrap
->Packet
)) {
1506 // Duplicate the Packet if it is shared between instances.
1508 Dup
= NetbufDuplicate (Wrap
->Packet
, NULL
, 0);
1513 NetbufFree (Wrap
->Packet
);
1518 NetListRemoveHead (&Instance
->RcvdDgramQue
);
1520 Token
= (EFI_UDP4_COMPLETION_TOKEN
*) NetMapRemoveHead (&Instance
->RxTokens
, NULL
);
1523 // Build the FragmentTable and set the FragmentCount in RxData.
1525 RxData
= &Wrap
->RxData
;
1526 RxData
->FragmentCount
= Wrap
->Packet
->BlockOpNum
;
1530 (NET_FRAGMENT
*) RxData
->FragmentTable
,
1531 &RxData
->FragmentCount
1534 Token
->Status
= EFI_SUCCESS
;
1535 Token
->Packet
.RxData
= &Wrap
->RxData
;
1537 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1538 InsertTailList (&Instance
->DeliveredDgramQue
, &Wrap
->Link
);
1539 gBS
->RestoreTPL (OldTpl
);
1541 gBS
->SignalEvent (Token
->Event
);
1547 This function delivers the datagrams enqueued in the instances.
1549 @param[in] Udp4Service Pointer to the udp service context data.
1554 IN UDP4_SERVICE_DATA
*Udp4Service
1558 UDP4_INSTANCE_DATA
*Instance
;
1560 NET_LIST_FOR_EACH (Entry
, &Udp4Service
->ChildrenList
) {
1562 // Iterate the instances.
1564 Instance
= NET_LIST_USER_STRUCT (Entry
, UDP4_INSTANCE_DATA
, Link
);
1566 if (!Instance
->Configured
) {
1571 // Deliver the datagrams of this instance.
1573 Udp4InstanceDeliverDgram (Instance
);
1579 This function demultiplexes the received udp datagram to the apropriate instances.
1581 @param[in] Udp4Service Pointer to the udp service context data.
1582 @param[in] NetSession Pointer to the EFI_NET_SESSION_DATA abstrated from
1583 the received datagram.
1584 @param[in] Packet Pointer to the buffer containing the received udp
1590 IN UDP4_SERVICE_DATA
*Udp4Service
,
1591 IN EFI_NET_SESSION_DATA
*NetSession
,
1595 EFI_UDP4_HEADER
*Udp4Header
;
1597 EFI_UDP4_RECEIVE_DATA RxData
;
1598 EFI_UDP4_SESSION_DATA
*Udp4Session
;
1602 // Get the datagram header from the packet buffer.
1604 Udp4Header
= (EFI_UDP4_HEADER
*) NetbufGetByte (Packet
, 0, NULL
);
1606 if (Udp4Header
->Checksum
!= 0) {
1608 // check the checksum.
1610 HeadSum
= NetPseudoHeadChecksum (
1617 if (Udp4Checksum (Packet
, HeadSum
) != 0) {
1625 gRT
->GetTime (&RxData
.TimeStamp
, NULL
);
1627 Udp4Session
= &RxData
.UdpSession
;
1628 Udp4Session
->SourcePort
= NTOHS (Udp4Header
->SrcPort
);
1629 Udp4Session
->DestinationPort
= NTOHS (Udp4Header
->DstPort
);
1631 CopyMem (&Udp4Session
->SourceAddress
, &NetSession
->Source
, sizeof (EFI_IPv4_ADDRESS
));
1632 CopyMem (&Udp4Session
->DestinationAddress
, &NetSession
->Dest
, sizeof (EFI_IPv4_ADDRESS
));
1635 // Trim the UDP header.
1637 NetbufTrim (Packet
, UDP4_HEADER_SIZE
, TRUE
);
1639 RxData
.DataLength
= (UINT32
) Packet
->TotalSize
;
1642 // Try to enqueue this datagram into the instances.
1644 Enqueued
= Udp4EnqueueDgram (Udp4Service
, Packet
, &RxData
);
1646 if (Enqueued
== 0) {
1648 // Send the port unreachable ICMP packet before we free this NET_BUF
1650 Udp4SendPortUnreach (Udp4Service
->IpIo
, NetSession
, Udp4Header
);
1654 // Try to free the packet before deliver it.
1656 NetbufFree (Packet
);
1660 // Deliver the datagram.
1662 Udp4DeliverDgram (Udp4Service
);
1668 This function builds and sends out a icmp port unreachable message.
1670 @param[in] IpIo Pointer to the IP_IO instance.
1671 @param[in] NetSession Pointer to the EFI_NET_SESSION_DATA of the packet
1672 causes this icmp error message.
1673 @param[in] Udp4Header Pointer to the udp header of the datagram causes
1674 this icmp error message.
1678 Udp4SendPortUnreach (
1680 IN EFI_NET_SESSION_DATA
*NetSession
,
1686 IP4_ICMP_ERROR_HEAD
*IcmpErrHdr
;
1687 EFI_IP4_HEADER
*IpHdr
;
1689 IP_IO_OVERRIDE Override
;
1690 IP_IO_IP_INFO
*IpSender
;
1692 IpSender
= IpIoFindSender (&IpIo
, NetSession
->Dest
);
1693 if (IpSender
== NULL
) {
1695 // No apropriate sender, since we cannot send out the ICMP message through
1696 // the default zero station address IP instance, abort.
1701 IpHdr
= NetSession
->IpHdr
;
1704 // Calculate the requried length of the icmp error message.
1706 Len
= sizeof (IP4_ICMP_ERROR_HEAD
) + (EFI_IP4_HEADER_LEN (IpHdr
) -
1707 sizeof (IP4_HEAD
)) + ICMP_ERROR_PACKET_LENGTH
;
1710 // Allocate buffer for the icmp error message.
1712 Packet
= NetbufAlloc (Len
);
1713 if (Packet
== NULL
) {
1718 // Allocate space for the IP4_ICMP_ERROR_HEAD.
1720 IcmpErrHdr
= (IP4_ICMP_ERROR_HEAD
*) NetbufAllocSpace (Packet
, Len
, FALSE
);
1721 ASSERT (IcmpErrHdr
!= NULL
);
1724 // Set the required fields for the icmp port unreachable message.
1726 IcmpErrHdr
->Head
.Type
= ICMP_TYPE_UNREACH
;
1727 IcmpErrHdr
->Head
.Code
= ICMP_CODE_UNREACH_PORT
;
1728 IcmpErrHdr
->Head
.Checksum
= 0;
1729 IcmpErrHdr
->Fourth
= 0;
1732 // Copy the IP header of the datagram tragged the error.
1734 CopyMem (&IcmpErrHdr
->IpHead
, IpHdr
, EFI_IP4_HEADER_LEN (IpHdr
));
1737 // Copy the UDP header.
1739 Ptr
= (UINT8
*) &IcmpErrHdr
->IpHead
+ EFI_IP4_HEADER_LEN (IpHdr
);
1740 CopyMem (Ptr
, Udp4Header
, ICMP_ERROR_PACKET_LENGTH
);
1743 // Calculate the checksum.
1745 IcmpErrHdr
->Head
.Checksum
= (UINT16
) ~(NetbufChecksum (Packet
));
1748 // Fill the override data.
1750 Override
.DoNotFragment
= FALSE
;
1751 Override
.TypeOfService
= 0;
1752 Override
.TimeToLive
= 255;
1753 Override
.Protocol
= EFI_IP_PROTO_ICMP
;
1755 CopyMem (&Override
.SourceAddress
, &NetSession
->Dest
, sizeof (EFI_IPv4_ADDRESS
));
1756 ZeroMem (&Override
.GatewayAddress
, sizeof (EFI_IPv4_ADDRESS
));
1759 // Send out this icmp packet.
1761 IpIoSend (IpIo
, Packet
, IpSender
, NULL
, NULL
, NetSession
->Source
, &Override
);
1763 NetbufFree (Packet
);
1768 This function handles the received Icmp Error message and demultiplexes it to the
1771 @param[in] Udp4Service Pointer to the udp service context data.
1772 @param[in] IcmpError The icmp error code.
1773 @param[in] NetSession Pointer to the EFI_NET_SESSION_DATA abstracted
1774 from the received Icmp Error packet.
1775 @param[in] Packet Pointer to the Icmp Error packet.
1780 IN UDP4_SERVICE_DATA
*Udp4Service
,
1781 IN ICMP_ERROR IcmpError
,
1782 IN EFI_NET_SESSION_DATA
*NetSession
,
1786 EFI_UDP4_HEADER
*Udp4Header
;
1787 EFI_UDP4_SESSION_DATA Udp4Session
;
1789 UDP4_INSTANCE_DATA
*Instance
;
1791 Udp4Header
= (EFI_UDP4_HEADER
*) NetbufGetByte (Packet
, 0, NULL
);
1793 CopyMem (&Udp4Session
.SourceAddress
, &NetSession
->Source
, sizeof (EFI_IPv4_ADDRESS
));
1794 CopyMem (&Udp4Session
.DestinationAddress
, &NetSession
->Dest
, sizeof (EFI_IPv4_ADDRESS
));
1796 Udp4Session
.SourcePort
= NTOHS (Udp4Header
->DstPort
);
1797 Udp4Session
.DestinationPort
= NTOHS (Udp4Header
->SrcPort
);
1799 NET_LIST_FOR_EACH (Entry
, &Udp4Service
->ChildrenList
) {
1801 // Iterate all the instances.
1803 Instance
= NET_LIST_USER_STRUCT (Entry
, UDP4_INSTANCE_DATA
, Link
);
1805 if (!Instance
->Configured
||
1806 Instance
->ConfigData
.AcceptPromiscuous
||
1807 Instance
->ConfigData
.AcceptAnyPort
||
1808 EFI_IP4_EQUAL (&Instance
->ConfigData
.StationAddress
, &mZeroIp4Addr
)
1811 // Don't try to deliver the ICMP error to this instance if it is not configured,
1812 // or it's configured to be promiscuous or accept any port or accept all the
1818 if (Udp4MatchDgram (Instance
, &Udp4Session
)) {
1820 // Translate the Icmp Error code according to the udp spec.
1822 Instance
->IcmpError
= IpIoGetIcmpErrStatus (IcmpError
, NULL
, NULL
);
1824 if (IcmpError
> ICMP_ERR_UNREACH_PORT
) {
1825 Instance
->IcmpError
= EFI_ICMP_ERROR
;
1829 // Notify the instance with the received Icmp Error.
1831 Udp4ReportIcmpError (Instance
);
1837 NetbufFree (Packet
);
1842 This function reports the received ICMP error.
1844 @param[in] Instance Pointer to the udp instance context data.
1848 Udp4ReportIcmpError (
1849 IN UDP4_INSTANCE_DATA
*Instance
1852 EFI_UDP4_COMPLETION_TOKEN
*Token
;
1854 if (NetMapIsEmpty (&Instance
->RxTokens
)) {
1856 // There are no receive tokens to deliver the ICMP error.
1861 if (EFI_ERROR (Instance
->IcmpError
)) {
1863 // Try to get a RxToken from the RxTokens map.
1865 Token
= (EFI_UDP4_COMPLETION_TOKEN
*) NetMapRemoveHead (&Instance
->RxTokens
, NULL
);
1867 if (Token
!= NULL
) {
1869 // Report the error through the Token.
1871 Token
->Status
= Instance
->IcmpError
;
1872 gBS
->SignalEvent (Token
->Event
);
1875 // Clear the IcmpError.
1877 Instance
->IcmpError
= EFI_SUCCESS
;
1884 This function is a dummy ext-free function for the NET_BUF created for the output
1887 @param[in] Context Pointer to the context data.
1891 Udp4NetVectorExtFree (
1899 Set the Udp4 variable data.
1901 @param Udp4Service Udp4 service data.
1903 @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the
1905 @retval EFI_SUCCESS Set variable successfully.
1906 @retval other Set variable failed.
1910 Udp4SetVariableData (
1911 IN UDP4_SERVICE_DATA
*Udp4Service
1914 UINT32 NumConfiguredInstance
;
1916 UINTN VariableDataSize
;
1917 EFI_UDP4_VARIABLE_DATA
*Udp4VariableData
;
1918 EFI_UDP4_SERVICE_POINT
*Udp4ServicePoint
;
1919 UDP4_INSTANCE_DATA
*Udp4Instance
;
1920 CHAR16
*NewMacString
;
1923 NumConfiguredInstance
= 0;
1926 // Go through the children list to count the configured children.
1928 NET_LIST_FOR_EACH (Entry
, &Udp4Service
->ChildrenList
) {
1929 Udp4Instance
= NET_LIST_USER_STRUCT_S (
1933 UDP4_INSTANCE_DATA_SIGNATURE
1936 if (Udp4Instance
->Configured
) {
1937 NumConfiguredInstance
++;
1942 // Calculate the size of the Udp4VariableData. As there may be no Udp4 child,
1943 // we should add extra buffer for the service points only if the number of configured
1944 // children is more than 1.
1946 VariableDataSize
= sizeof (EFI_UDP4_VARIABLE_DATA
);
1948 if (NumConfiguredInstance
> 1) {
1949 VariableDataSize
+= sizeof (EFI_UDP4_SERVICE_POINT
) * (NumConfiguredInstance
- 1);
1952 Udp4VariableData
= AllocatePool (VariableDataSize
);
1953 if (Udp4VariableData
== NULL
) {
1954 return EFI_OUT_OF_RESOURCES
;
1957 Udp4VariableData
->DriverHandle
= Udp4Service
->ImageHandle
;
1958 Udp4VariableData
->ServiceCount
= NumConfiguredInstance
;
1960 Udp4ServicePoint
= &Udp4VariableData
->Services
[0];
1963 // Go through the children list to fill the configured children's address pairs.
1965 NET_LIST_FOR_EACH (Entry
, &Udp4Service
->ChildrenList
) {
1966 Udp4Instance
= NET_LIST_USER_STRUCT_S (
1970 UDP4_INSTANCE_DATA_SIGNATURE
1973 if (Udp4Instance
->Configured
) {
1974 Udp4ServicePoint
->InstanceHandle
= Udp4Instance
->ChildHandle
;
1975 Udp4ServicePoint
->LocalAddress
= Udp4Instance
->ConfigData
.StationAddress
;
1976 Udp4ServicePoint
->LocalPort
= Udp4Instance
->ConfigData
.StationPort
;
1977 Udp4ServicePoint
->RemoteAddress
= Udp4Instance
->ConfigData
.RemoteAddress
;
1978 Udp4ServicePoint
->RemotePort
= Udp4Instance
->ConfigData
.RemotePort
;
1985 // Get the mac string.
1987 Status
= NetLibGetMacString (
1988 Udp4Service
->ControllerHandle
,
1989 Udp4Service
->ImageHandle
,
1992 if (EFI_ERROR (Status
)) {
1996 if (Udp4Service
->MacString
!= NULL
) {
1998 // The variable is set already, we're going to update it.
2000 if (StrCmp (Udp4Service
->MacString
, NewMacString
) != 0) {
2002 // The mac address is changed, delete the previous variable first.
2005 Udp4Service
->MacString
,
2006 &gEfiUdp4ServiceBindingProtocolGuid
,
2007 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
2013 gBS
->FreePool (Udp4Service
->MacString
);
2016 Udp4Service
->MacString
= NewMacString
;
2018 Status
= gRT
->SetVariable (
2019 Udp4Service
->MacString
,
2020 &gEfiUdp4ServiceBindingProtocolGuid
,
2021 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
2023 (VOID
*) Udp4VariableData
2028 gBS
->FreePool (Udp4VariableData
);
2035 Clear the variable and free the resource.
2037 @param[[in] Udp4Service Udp4 service data.
2041 Udp4ClearVariableData (
2042 IN UDP4_SERVICE_DATA
*Udp4Service
2045 ASSERT (Udp4Service
->MacString
!= NULL
);
2048 Udp4Service
->MacString
,
2049 &gEfiUdp4ServiceBindingProtocolGuid
,
2050 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
2055 gBS
->FreePool (Udp4Service
->MacString
);
2056 Udp4Service
->MacString
= NULL
;