2 DnsDxe support functions implementation.
4 Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 Remove TokenEntry from TokenMap.
14 @param[in] TokenMap All DNSv4 Token entrys.
15 @param[in] TokenEntry TokenEntry need to be removed.
17 @retval EFI_SUCCESS Remove TokenEntry from TokenMap successfully.
18 @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap.
22 Dns4RemoveTokenEntry (
24 IN DNS4_TOKEN_ENTRY
*TokenEntry
30 // Find the TokenEntry first.
32 Item
= NetMapFindKey (TokenMap
, (VOID
*)TokenEntry
);
36 // Remove the TokenEntry if it's found in the map.
38 NetMapRemoveItem (TokenMap
, Item
, NULL
);
47 Remove TokenEntry from TokenMap.
49 @param[in] TokenMap All DNSv6 Token entrys.
50 @param[in] TokenEntry TokenEntry need to be removed.
52 @retval EFI_SUCCESS Remove TokenEntry from TokenMap successfully.
53 @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap.
57 Dns6RemoveTokenEntry (
59 IN DNS6_TOKEN_ENTRY
*TokenEntry
65 // Find the TokenEntry first.
67 Item
= NetMapFindKey (TokenMap
, (VOID
*)TokenEntry
);
71 // Remove the TokenEntry if it's found in the map.
73 NetMapRemoveItem (TokenMap
, Item
, NULL
);
82 This function cancel the token specified by Arg in the Map.
84 @param[in] Map Pointer to the NET_MAP.
85 @param[in] Item Pointer to the NET_MAP_ITEM.
86 @param[in] Arg Pointer to the token to be cancelled. If NULL, all
87 the tokens in this Map will be cancelled.
88 This parameter is optional and may be NULL.
90 @retval EFI_SUCCESS The token is cancelled if Arg is NULL, or the token
91 is not the same as that in the Item, if Arg is not
93 @retval EFI_ABORTED Arg is not NULL, and the token specified by Arg is
101 IN NET_MAP_ITEM
*Item
,
102 IN VOID
*Arg OPTIONAL
105 DNS4_TOKEN_ENTRY
*TokenEntry
;
109 if ((Arg
!= NULL
) && (Item
->Key
!= Arg
)) {
113 if (Item
->Value
!= NULL
) {
115 // If the TokenEntry is a transmit TokenEntry, the corresponding Packet is recorded in
118 Packet
= (NET_BUF
*)(Item
->Value
);
119 UdpIo
= (UDP_IO
*)(*((UINTN
*)&Packet
->ProtoData
[0]));
121 UdpIoCancelSentDatagram (UdpIo
, Packet
);
125 // Remove TokenEntry from Dns4TxTokens.
127 TokenEntry
= (DNS4_TOKEN_ENTRY
*)Item
->Key
;
128 if (Dns4RemoveTokenEntry (Map
, TokenEntry
) == EFI_SUCCESS
) {
129 TokenEntry
->Token
->Status
= EFI_ABORTED
;
130 gBS
->SignalEvent (TokenEntry
->Token
->Event
);
142 This function cancel the token specified by Arg in the Map.
144 @param[in] Map Pointer to the NET_MAP.
145 @param[in] Item Pointer to the NET_MAP_ITEM.
146 @param[in] Arg Pointer to the token to be cancelled. If NULL, all
147 the tokens in this Map will be cancelled.
148 This parameter is optional and may be NULL.
150 @retval EFI_SUCCESS The token is cancelled if Arg is NULL, or the token
151 is not the same as that in the Item, if Arg is not
153 @retval EFI_ABORTED Arg is not NULL, and the token specified by Arg is
161 IN NET_MAP_ITEM
*Item
,
162 IN VOID
*Arg OPTIONAL
165 DNS6_TOKEN_ENTRY
*TokenEntry
;
169 if ((Arg
!= NULL
) && (Item
->Key
!= Arg
)) {
173 if (Item
->Value
!= NULL
) {
175 // If the TokenEntry is a transmit TokenEntry, the corresponding Packet is recorded in
178 Packet
= (NET_BUF
*)(Item
->Value
);
179 UdpIo
= (UDP_IO
*)(*((UINTN
*)&Packet
->ProtoData
[0]));
181 UdpIoCancelSentDatagram (UdpIo
, Packet
);
185 // Remove TokenEntry from Dns6TxTokens.
187 TokenEntry
= (DNS6_TOKEN_ENTRY
*)Item
->Key
;
188 if (Dns6RemoveTokenEntry (Map
, TokenEntry
) == EFI_SUCCESS
) {
189 TokenEntry
->Token
->Status
= EFI_ABORTED
;
190 gBS
->SignalEvent (TokenEntry
->Token
->Event
);
202 Get the TokenEntry from the TokensMap.
204 @param[in] TokensMap All DNSv4 Token entrys
205 @param[in] Token Pointer to the token to be get.
206 @param[out] TokenEntry Pointer to TokenEntry corresponding Token.
208 @retval EFI_SUCCESS Get the TokenEntry from the TokensMap successfully.
209 @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap.
215 IN NET_MAP
*TokensMap
,
216 IN EFI_DNS4_COMPLETION_TOKEN
*Token
,
217 OUT DNS4_TOKEN_ENTRY
**TokenEntry
224 NET_LIST_FOR_EACH (Entry
, &TokensMap
->Used
) {
225 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
226 *TokenEntry
= (DNS4_TOKEN_ENTRY
*)(Item
->Key
);
227 if ((*TokenEntry
)->Token
== Token
) {
234 return EFI_NOT_FOUND
;
238 Get the TokenEntry from the TokensMap.
240 @param[in] TokensMap All DNSv6 Token entrys
241 @param[in] Token Pointer to the token to be get.
242 @param[out] TokenEntry Pointer to TokenEntry corresponding Token.
244 @retval EFI_SUCCESS Get the TokenEntry from the TokensMap successfully.
245 @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap.
251 IN NET_MAP
*TokensMap
,
252 IN EFI_DNS6_COMPLETION_TOKEN
*Token
,
253 OUT DNS6_TOKEN_ENTRY
**TokenEntry
260 NET_LIST_FOR_EACH (Entry
, &TokensMap
->Used
) {
261 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
262 *TokenEntry
= (DNS6_TOKEN_ENTRY
*)(Item
->Key
);
263 if ((*TokenEntry
)->Token
== Token
) {
270 return EFI_NOT_FOUND
;
274 Cancel DNS4 tokens from the DNS4 instance.
276 @param[in] Instance Pointer to the DNS instance context data.
277 @param[in] Token Pointer to the token to be canceled. If NULL, all
278 tokens in this instance will be cancelled.
279 This parameter is optional and may be NULL.
281 @retval EFI_SUCCESS The Token is cancelled.
282 @retval EFI_NOT_FOUND The Token is not found.
286 Dns4InstanceCancelToken (
287 IN DNS_INSTANCE
*Instance
,
288 IN EFI_DNS4_COMPLETION_TOKEN
*Token
292 DNS4_TOKEN_ENTRY
*TokenEntry
;
296 if (Token
!= NULL
) {
297 Status
= GetDns4TokenEntry (&Instance
->Dns4TxTokens
, Token
, &TokenEntry
);
298 if (EFI_ERROR (Status
)) {
306 // Cancel this TokenEntry from the Dns4TxTokens map.
308 Status
= NetMapIterate (&Instance
->Dns4TxTokens
, Dns4CancelTokens
, TokenEntry
);
310 if ((TokenEntry
!= NULL
) && (Status
== EFI_ABORTED
)) {
312 // If Token isn't NULL and Status is EFI_ABORTED, the token is cancelled from
313 // the Dns4TxTokens and returns success.
315 if (NetMapIsEmpty (&Instance
->Dns4TxTokens
)) {
316 Instance
->UdpIo
->Protocol
.Udp4
->Cancel (Instance
->UdpIo
->Protocol
.Udp4
, &Instance
->UdpIo
->RecvRequest
->Token
.Udp4
);
322 ASSERT ((TokenEntry
!= NULL
) || (0 == NetMapGetCount (&Instance
->Dns4TxTokens
)));
324 if (NetMapIsEmpty (&Instance
->Dns4TxTokens
)) {
325 Instance
->UdpIo
->Protocol
.Udp4
->Cancel (Instance
->UdpIo
->Protocol
.Udp4
, &Instance
->UdpIo
->RecvRequest
->Token
.Udp4
);
332 Cancel DNS6 tokens from the DNS6 instance.
334 @param[in] Instance Pointer to the DNS instance context data.
335 @param[in] Token Pointer to the token to be canceled. If NULL, all
336 tokens in this instance will be cancelled.
337 This parameter is optional and may be NULL.
339 @retval EFI_SUCCESS The Token is cancelled.
340 @retval EFI_NOT_FOUND The Token is not found.
344 Dns6InstanceCancelToken (
345 IN DNS_INSTANCE
*Instance
,
346 IN EFI_DNS6_COMPLETION_TOKEN
*Token
350 DNS6_TOKEN_ENTRY
*TokenEntry
;
354 if (Token
!= NULL
) {
355 Status
= GetDns6TokenEntry (&Instance
->Dns6TxTokens
, Token
, &TokenEntry
);
356 if (EFI_ERROR (Status
)) {
364 // Cancel this TokenEntry from the Dns6TxTokens map.
366 Status
= NetMapIterate (&Instance
->Dns6TxTokens
, Dns6CancelTokens
, TokenEntry
);
368 if ((TokenEntry
!= NULL
) && (Status
== EFI_ABORTED
)) {
370 // If Token isn't NULL and Status is EFI_ABORTED, the token is cancelled from
371 // the Dns6TxTokens and returns success.
373 if (NetMapIsEmpty (&Instance
->Dns6TxTokens
)) {
374 Instance
->UdpIo
->Protocol
.Udp6
->Cancel (Instance
->UdpIo
->Protocol
.Udp6
, &Instance
->UdpIo
->RecvRequest
->Token
.Udp6
);
380 ASSERT ((TokenEntry
!= NULL
) || (0 == NetMapGetCount (&Instance
->Dns6TxTokens
)));
382 if (NetMapIsEmpty (&Instance
->Dns6TxTokens
)) {
383 Instance
->UdpIo
->Protocol
.Udp6
->Cancel (Instance
->UdpIo
->Protocol
.Udp6
, &Instance
->UdpIo
->RecvRequest
->Token
.Udp6
);
390 Free the resource related to the configure parameters.
392 @param Config The DNS configure data
397 IN OUT EFI_DNS4_CONFIG_DATA
*Config
400 if (Config
->DnsServerList
!= NULL
) {
401 FreePool (Config
->DnsServerList
);
404 ZeroMem (Config
, sizeof (EFI_DNS4_CONFIG_DATA
));
408 Free the resource related to the configure parameters.
410 @param Config The DNS configure data
415 IN OUT EFI_DNS6_CONFIG_DATA
*Config
418 if (Config
->DnsServerList
!= NULL
) {
419 FreePool (Config
->DnsServerList
);
422 ZeroMem (Config
, sizeof (EFI_DNS6_CONFIG_DATA
));
426 Allocate memory for configure parameter such as timeout value for Dst,
427 then copy the configure parameter from Src to Dst.
429 @param[out] Dst The destination DHCP configure data.
430 @param[in] Src The source DHCP configure data.
432 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
433 @retval EFI_SUCCESS The configure is copied.
438 OUT EFI_DNS4_CONFIG_DATA
*Dst
,
439 IN EFI_DNS4_CONFIG_DATA
*Src
445 CopyMem (Dst
, Src
, sizeof (*Dst
));
446 Dst
->DnsServerList
= NULL
;
449 // Allocate a memory then copy DnsServerList to it
451 if (Src
->DnsServerList
!= NULL
) {
452 Len
= Src
->DnsServerListCount
* sizeof (EFI_IPv4_ADDRESS
);
453 Dst
->DnsServerList
= AllocatePool (Len
);
454 if (Dst
->DnsServerList
== NULL
) {
455 Dns4CleanConfigure (Dst
);
456 return EFI_OUT_OF_RESOURCES
;
459 for (Index
= 0; Index
< Src
->DnsServerListCount
; Index
++) {
460 CopyMem (&Dst
->DnsServerList
[Index
], &Src
->DnsServerList
[Index
], sizeof (EFI_IPv4_ADDRESS
));
468 Allocate memory for configure parameter such as timeout value for Dst,
469 then copy the configure parameter from Src to Dst.
471 @param[out] Dst The destination DHCP configure data.
472 @param[in] Src The source DHCP configure data.
474 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
475 @retval EFI_SUCCESS The configure is copied.
480 OUT EFI_DNS6_CONFIG_DATA
*Dst
,
481 IN EFI_DNS6_CONFIG_DATA
*Src
487 CopyMem (Dst
, Src
, sizeof (*Dst
));
488 Dst
->DnsServerList
= NULL
;
491 // Allocate a memory then copy DnsServerList to it
493 if (Src
->DnsServerList
!= NULL
) {
494 Len
= Src
->DnsServerCount
* sizeof (EFI_IPv6_ADDRESS
);
495 Dst
->DnsServerList
= AllocatePool (Len
);
496 if (Dst
->DnsServerList
== NULL
) {
497 Dns6CleanConfigure (Dst
);
498 return EFI_OUT_OF_RESOURCES
;
501 for (Index
= 0; Index
< Src
->DnsServerCount
; Index
++) {
502 CopyMem (&Dst
->DnsServerList
[Index
], &Src
->DnsServerList
[Index
], sizeof (EFI_IPv6_ADDRESS
));
510 Callback of Dns packet. Does nothing.
512 @param Arg The context.
524 Poll the UDP to get the IP4 default address, which may be retrieved
527 The default time out value is 5 seconds. If IP has retrieved the default address,
528 the UDP is reconfigured.
530 @param Instance The DNS instance
531 @param UdpIo The UDP_IO to poll
532 @param UdpCfgData The UDP configure data to reconfigure the UDP_IO
534 @retval TRUE The default address is retrieved and UDP is reconfigured.
535 @retval FALSE Some error occurred.
540 IN DNS_INSTANCE
*Instance
,
542 IN EFI_UDP4_CONFIG_DATA
*UdpCfgData
545 DNS_SERVICE
*Service
;
546 EFI_IP4_MODE_DATA Ip4Mode
;
547 EFI_UDP4_PROTOCOL
*Udp
;
550 ASSERT (Instance
->Dns4CfgData
.UseDefaultSetting
);
552 Service
= Instance
->Service
;
553 Udp
= UdpIo
->Protocol
.Udp4
;
555 Status
= gBS
->SetTimer (
556 Service
->TimerToGetMap
,
558 DNS_TIME_TO_GETMAP
* TICKS_PER_SECOND
560 if (EFI_ERROR (Status
)) {
564 while (EFI_ERROR (gBS
->CheckEvent (Service
->TimerToGetMap
))) {
567 if (!EFI_ERROR (Udp
->GetModeData (Udp
, NULL
, &Ip4Mode
, NULL
, NULL
)) &&
568 Ip4Mode
.IsConfigured
)
570 Udp
->Configure (Udp
, NULL
);
571 return (BOOLEAN
)(Udp
->Configure (Udp
, UdpCfgData
) == EFI_SUCCESS
);
579 Configure the opened Udp6 instance until the corresponding Ip6 instance
582 @param Instance The DNS instance
583 @param UdpIo The UDP_IO to poll
584 @param UdpCfgData The UDP configure data to reconfigure the UDP_IO
586 @retval TRUE Configure the Udp6 instance successfully.
587 @retval FALSE Some error occurred.
592 IN DNS_INSTANCE
*Instance
,
594 IN EFI_UDP6_CONFIG_DATA
*UdpCfgData
597 DNS_SERVICE
*Service
;
598 EFI_IP6_MODE_DATA Ip6Mode
;
599 EFI_UDP6_PROTOCOL
*Udp
;
602 Service
= Instance
->Service
;
603 Udp
= UdpIo
->Protocol
.Udp6
;
605 Status
= gBS
->SetTimer (
606 Service
->TimerToGetMap
,
608 DNS_TIME_TO_GETMAP
* TICKS_PER_SECOND
610 if (EFI_ERROR (Status
)) {
614 while (EFI_ERROR (gBS
->CheckEvent (Service
->TimerToGetMap
))) {
617 if (!EFI_ERROR (Udp
->GetModeData (Udp
, NULL
, &Ip6Mode
, NULL
, NULL
))) {
618 if (Ip6Mode
.AddressList
!= NULL
) {
619 FreePool (Ip6Mode
.AddressList
);
622 if (Ip6Mode
.GroupTable
!= NULL
) {
623 FreePool (Ip6Mode
.GroupTable
);
626 if (Ip6Mode
.RouteTable
!= NULL
) {
627 FreePool (Ip6Mode
.RouteTable
);
630 if (Ip6Mode
.NeighborCache
!= NULL
) {
631 FreePool (Ip6Mode
.NeighborCache
);
634 if (Ip6Mode
.PrefixTable
!= NULL
) {
635 FreePool (Ip6Mode
.PrefixTable
);
638 if (Ip6Mode
.IcmpTypeList
!= NULL
) {
639 FreePool (Ip6Mode
.IcmpTypeList
);
642 if (!Ip6Mode
.IsStarted
|| Ip6Mode
.IsConfigured
) {
643 Udp
->Configure (Udp
, NULL
);
644 if (Udp
->Configure (Udp
, UdpCfgData
) == EFI_SUCCESS
) {
657 @param Instance The DNS session
658 @param UdpIo The UDP_IO instance
660 @retval EFI_SUCCESS The UDP is successfully configured for the
666 IN DNS_INSTANCE
*Instance
,
670 EFI_DNS4_CONFIG_DATA
*Config
;
671 EFI_UDP4_CONFIG_DATA UdpConfig
;
674 Config
= &Instance
->Dns4CfgData
;
676 UdpConfig
.AcceptBroadcast
= FALSE
;
677 UdpConfig
.AcceptPromiscuous
= FALSE
;
678 UdpConfig
.AcceptAnyPort
= FALSE
;
679 UdpConfig
.AllowDuplicatePort
= FALSE
;
680 UdpConfig
.TypeOfService
= 0;
681 UdpConfig
.TimeToLive
= 128;
682 UdpConfig
.DoNotFragment
= FALSE
;
683 UdpConfig
.ReceiveTimeout
= 0;
684 UdpConfig
.TransmitTimeout
= 0;
685 UdpConfig
.UseDefaultAddress
= Config
->UseDefaultSetting
;
686 UdpConfig
.SubnetMask
= Config
->SubnetMask
;
687 UdpConfig
.StationPort
= Config
->LocalPort
;
688 UdpConfig
.RemotePort
= DNS_SERVER_PORT
;
690 CopyMem (&UdpConfig
.StationAddress
, &Config
->StationIp
, sizeof (EFI_IPv4_ADDRESS
));
691 CopyMem (&UdpConfig
.RemoteAddress
, &Instance
->SessionDnsServer
.v4
, sizeof (EFI_IPv4_ADDRESS
));
693 Status
= UdpIo
->Protocol
.Udp4
->Configure (UdpIo
->Protocol
.Udp4
, &UdpConfig
);
695 if ((Status
== EFI_NO_MAPPING
) && Dns4GetMapping (Instance
, UdpIo
, &UdpConfig
)) {
705 @param Instance The DNS session
706 @param UdpIo The UDP_IO instance
708 @retval EFI_SUCCESS The UDP is successfully configured for the
714 IN DNS_INSTANCE
*Instance
,
718 EFI_DNS6_CONFIG_DATA
*Config
;
719 EFI_UDP6_CONFIG_DATA UdpConfig
;
722 Config
= &Instance
->Dns6CfgData
;
724 UdpConfig
.AcceptPromiscuous
= FALSE
;
725 UdpConfig
.AcceptAnyPort
= FALSE
;
726 UdpConfig
.AllowDuplicatePort
= FALSE
;
727 UdpConfig
.TrafficClass
= 0;
728 UdpConfig
.HopLimit
= 128;
729 UdpConfig
.ReceiveTimeout
= 0;
730 UdpConfig
.TransmitTimeout
= 0;
731 UdpConfig
.StationPort
= Config
->LocalPort
;
732 UdpConfig
.RemotePort
= DNS_SERVER_PORT
;
733 CopyMem (&UdpConfig
.StationAddress
, &Config
->StationIp
, sizeof (EFI_IPv6_ADDRESS
));
734 CopyMem (&UdpConfig
.RemoteAddress
, &Instance
->SessionDnsServer
.v6
, sizeof (EFI_IPv6_ADDRESS
));
736 Status
= UdpIo
->Protocol
.Udp6
->Configure (UdpIo
->Protocol
.Udp6
, &UdpConfig
);
738 if ((Status
== EFI_NO_MAPPING
) && Dns6GetMapping (Instance
, UdpIo
, &UdpConfig
)) {
746 Update Dns4 cache to shared list of caches of all DNSv4 instances.
748 @param Dns4CacheList All Dns4 cache list.
749 @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache.
750 If TRUE, this function will delete matching DNS Cache entry.
751 @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
752 If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
753 @param DnsCacheEntry Entry Pointer to DNS Cache entry.
755 @retval EFI_SUCCESS Update Dns4 cache successfully.
756 @retval Others Failed to update Dns4 cache.
762 IN LIST_ENTRY
*Dns4CacheList
,
763 IN BOOLEAN DeleteFlag
,
765 IN EFI_DNS4_CACHE_ENTRY DnsCacheEntry
768 DNS4_CACHE
*NewDnsCache
;
777 // Search the database for the matching EFI_DNS_CACHE_ENTRY
779 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Dns4CacheList
) {
780 Item
= NET_LIST_USER_STRUCT (Entry
, DNS4_CACHE
, AllCacheLink
);
781 if ((StrCmp (DnsCacheEntry
.HostName
, Item
->DnsCache
.HostName
) == 0) && \
782 (CompareMem (DnsCacheEntry
.IpAddress
, Item
->DnsCache
.IpAddress
, sizeof (EFI_IPv4_ADDRESS
)) == 0))
785 // This is the Dns cache entry
789 // Delete matching DNS Cache entry
791 RemoveEntryList (&Item
->AllCacheLink
);
793 FreePool (Item
->DnsCache
.HostName
);
794 FreePool (Item
->DnsCache
.IpAddress
);
798 } else if (Override
) {
802 Item
->DnsCache
.Timeout
= DnsCacheEntry
.Timeout
;
806 return EFI_ACCESS_DENIED
;
814 NewDnsCache
= AllocatePool (sizeof (DNS4_CACHE
));
815 if (NewDnsCache
== NULL
) {
816 return EFI_OUT_OF_RESOURCES
;
819 InitializeListHead (&NewDnsCache
->AllCacheLink
);
821 NewDnsCache
->DnsCache
.HostName
= AllocatePool (StrSize (DnsCacheEntry
.HostName
));
822 if (NewDnsCache
->DnsCache
.HostName
== NULL
) {
823 FreePool (NewDnsCache
);
824 return EFI_OUT_OF_RESOURCES
;
827 CopyMem (NewDnsCache
->DnsCache
.HostName
, DnsCacheEntry
.HostName
, StrSize (DnsCacheEntry
.HostName
));
829 NewDnsCache
->DnsCache
.IpAddress
= AllocatePool (sizeof (EFI_IPv4_ADDRESS
));
830 if (NewDnsCache
->DnsCache
.IpAddress
== NULL
) {
831 FreePool (NewDnsCache
->DnsCache
.HostName
);
832 FreePool (NewDnsCache
);
833 return EFI_OUT_OF_RESOURCES
;
836 CopyMem (NewDnsCache
->DnsCache
.IpAddress
, DnsCacheEntry
.IpAddress
, sizeof (EFI_IPv4_ADDRESS
));
838 NewDnsCache
->DnsCache
.Timeout
= DnsCacheEntry
.Timeout
;
840 InsertTailList (Dns4CacheList
, &NewDnsCache
->AllCacheLink
);
846 Update Dns6 cache to shared list of caches of all DNSv6 instances.
848 @param Dns6CacheList All Dns6 cache list.
849 @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache.
850 If TRUE, this function will delete matching DNS Cache entry.
851 @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
852 If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
853 @param DnsCacheEntry Entry Pointer to DNS Cache entry.
855 @retval EFI_SUCCESS Update Dns6 cache successfully.
856 @retval Others Failed to update Dns6 cache.
861 IN LIST_ENTRY
*Dns6CacheList
,
862 IN BOOLEAN DeleteFlag
,
864 IN EFI_DNS6_CACHE_ENTRY DnsCacheEntry
867 DNS6_CACHE
*NewDnsCache
;
876 // Search the database for the matching EFI_DNS_CACHE_ENTRY
878 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Dns6CacheList
) {
879 Item
= NET_LIST_USER_STRUCT (Entry
, DNS6_CACHE
, AllCacheLink
);
880 if ((StrCmp (DnsCacheEntry
.HostName
, Item
->DnsCache
.HostName
) == 0) && \
881 (CompareMem (DnsCacheEntry
.IpAddress
, Item
->DnsCache
.IpAddress
, sizeof (EFI_IPv6_ADDRESS
)) == 0))
884 // This is the Dns cache entry
888 // Delete matching DNS Cache entry
890 RemoveEntryList (&Item
->AllCacheLink
);
892 FreePool (Item
->DnsCache
.HostName
);
893 FreePool (Item
->DnsCache
.IpAddress
);
897 } else if (Override
) {
901 Item
->DnsCache
.Timeout
= DnsCacheEntry
.Timeout
;
905 return EFI_ACCESS_DENIED
;
913 NewDnsCache
= AllocatePool (sizeof (DNS6_CACHE
));
914 if (NewDnsCache
== NULL
) {
915 return EFI_OUT_OF_RESOURCES
;
918 InitializeListHead (&NewDnsCache
->AllCacheLink
);
920 NewDnsCache
->DnsCache
.HostName
= AllocatePool (StrSize (DnsCacheEntry
.HostName
));
921 if (NewDnsCache
->DnsCache
.HostName
== NULL
) {
922 FreePool (NewDnsCache
);
923 return EFI_OUT_OF_RESOURCES
;
926 CopyMem (NewDnsCache
->DnsCache
.HostName
, DnsCacheEntry
.HostName
, StrSize (DnsCacheEntry
.HostName
));
928 NewDnsCache
->DnsCache
.IpAddress
= AllocatePool (sizeof (EFI_IPv6_ADDRESS
));
929 if (NewDnsCache
->DnsCache
.IpAddress
== NULL
) {
930 FreePool (NewDnsCache
->DnsCache
.HostName
);
931 FreePool (NewDnsCache
);
932 return EFI_OUT_OF_RESOURCES
;
935 CopyMem (NewDnsCache
->DnsCache
.IpAddress
, DnsCacheEntry
.IpAddress
, sizeof (EFI_IPv6_ADDRESS
));
937 NewDnsCache
->DnsCache
.Timeout
= DnsCacheEntry
.Timeout
;
939 InsertTailList (Dns6CacheList
, &NewDnsCache
->AllCacheLink
);
945 Add Dns4 ServerIp to common list of addresses of all configured DNSv4 server.
947 @param Dns4ServerList Common list of addresses of all configured DNSv4 server.
948 @param ServerIp DNS server Ip.
950 @retval EFI_SUCCESS Add Dns4 ServerIp to common list successfully.
951 @retval Others Failed to add Dns4 ServerIp to common list.
957 IN LIST_ENTRY
*Dns4ServerList
,
958 IN EFI_IPv4_ADDRESS ServerIp
961 DNS4_SERVER_IP
*NewServerIp
;
962 DNS4_SERVER_IP
*Item
;
970 // Search the database for the matching ServerIp
972 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Dns4ServerList
) {
973 Item
= NET_LIST_USER_STRUCT (Entry
, DNS4_SERVER_IP
, AllServerLink
);
974 if (CompareMem (&Item
->Dns4ServerIp
, &ServerIp
, sizeof (EFI_IPv4_ADDRESS
)) == 0) {
985 NewServerIp
= AllocatePool (sizeof (DNS4_SERVER_IP
));
986 if (NewServerIp
== NULL
) {
987 return EFI_OUT_OF_RESOURCES
;
990 InitializeListHead (&NewServerIp
->AllServerLink
);
992 CopyMem (&NewServerIp
->Dns4ServerIp
, &ServerIp
, sizeof (EFI_IPv4_ADDRESS
));
994 InsertTailList (Dns4ServerList
, &NewServerIp
->AllServerLink
);
1000 Add Dns6 ServerIp to common list of addresses of all configured DNSv6 server.
1002 @param Dns6ServerList Common list of addresses of all configured DNSv6 server.
1003 @param ServerIp DNS server Ip.
1005 @retval EFI_SUCCESS Add Dns6 ServerIp to common list successfully.
1006 @retval Others Failed to add Dns6 ServerIp to common list.
1012 IN LIST_ENTRY
*Dns6ServerList
,
1013 IN EFI_IPv6_ADDRESS ServerIp
1016 DNS6_SERVER_IP
*NewServerIp
;
1017 DNS6_SERVER_IP
*Item
;
1025 // Search the database for the matching ServerIp
1027 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Dns6ServerList
) {
1028 Item
= NET_LIST_USER_STRUCT (Entry
, DNS6_SERVER_IP
, AllServerLink
);
1029 if (CompareMem (&Item
->Dns6ServerIp
, &ServerIp
, sizeof (EFI_IPv6_ADDRESS
)) == 0) {
1040 NewServerIp
= AllocatePool (sizeof (DNS6_SERVER_IP
));
1041 if (NewServerIp
== NULL
) {
1042 return EFI_OUT_OF_RESOURCES
;
1045 InitializeListHead (&NewServerIp
->AllServerLink
);
1047 CopyMem (&NewServerIp
->Dns6ServerIp
, &ServerIp
, sizeof (EFI_IPv6_ADDRESS
));
1049 InsertTailList (Dns6ServerList
, &NewServerIp
->AllServerLink
);
1055 Find out whether the response is valid or invalid.
1057 @param TokensMap All DNS transmittal Tokens entry.
1058 @param Identification Identification for queried packet.
1059 @param Type Type for queried packet.
1060 @param Class Class for queried packet.
1061 @param Item Return corresponding Token entry.
1063 @retval TRUE The response is valid.
1064 @retval FALSE The response is invalid.
1068 IsValidDnsResponse (
1069 IN NET_MAP
*TokensMap
,
1070 IN UINT16 Identification
,
1073 OUT NET_MAP_ITEM
**Item
1080 DNS_HEADER
*DnsHeader
;
1082 DNS_QUERY_SECTION
*QuerySection
;
1084 NET_LIST_FOR_EACH (Entry
, &TokensMap
->Used
) {
1085 *Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
1086 Packet
= (NET_BUF
*)((*Item
)->Value
);
1087 if (Packet
== NULL
) {
1090 TxString
= NetbufGetByte (Packet
, 0, NULL
);
1091 ASSERT (TxString
!= NULL
);
1092 DnsHeader
= (DNS_HEADER
*)TxString
;
1093 QueryName
= (CHAR8
*)(TxString
+ sizeof (*DnsHeader
));
1094 QuerySection
= (DNS_QUERY_SECTION
*)(QueryName
+ AsciiStrLen (QueryName
) + 1);
1096 if ((NTOHS (DnsHeader
->Identification
) == Identification
) &&
1097 (NTOHS (QuerySection
->Type
) == Type
) &&
1098 (NTOHS (QuerySection
->Class
) == Class
))
1113 @param Instance The DNS instance
1114 @param RxString Received buffer.
1115 @param Length Received buffer length.
1116 @param Completed Flag to indicate that Dns response is valid.
1118 @retval EFI_SUCCESS Parse Dns Response successfully.
1119 @retval Others Failed to parse Dns Response.
1124 IN OUT DNS_INSTANCE
*Instance
,
1127 OUT BOOLEAN
*Completed
1130 DNS_HEADER
*DnsHeader
;
1133 UINT32 QueryNameLen
;
1134 DNS_QUERY_SECTION
*QuerySection
;
1137 DNS_ANSWER_SECTION
*AnswerSection
;
1141 DNS4_TOKEN_ENTRY
*Dns4TokenEntry
;
1142 DNS6_TOKEN_ENTRY
*Dns6TokenEntry
;
1146 UINT32 AnswerSectionNum
;
1149 EFI_IPv4_ADDRESS
*HostAddr4
;
1150 EFI_IPv6_ADDRESS
*HostAddr6
;
1152 EFI_DNS4_CACHE_ENTRY
*Dns4CacheEntry
;
1153 EFI_DNS6_CACHE_ENTRY
*Dns6CacheEntry
;
1155 DNS_RESOURCE_RECORD
*Dns4RR
;
1156 DNS6_RESOURCE_RECORD
*Dns6RR
;
1159 UINT32 RemainingLength
;
1164 Dns4TokenEntry
= NULL
;
1165 Dns6TokenEntry
= NULL
;
1169 AnswerSectionNum
= 0;
1175 Dns4CacheEntry
= NULL
;
1176 Dns6CacheEntry
= NULL
;
1182 Status
= EFI_SUCCESS
;
1183 RemainingLength
= Length
;
1186 // Check whether the remaining packet length is available or not.
1188 if (RemainingLength
<= sizeof (DNS_HEADER
)) {
1192 RemainingLength
-= sizeof (DNS_HEADER
);
1198 DnsHeader
= (DNS_HEADER
*)RxString
;
1200 DnsHeader
->Identification
= NTOHS (DnsHeader
->Identification
);
1201 DnsHeader
->Flags
.Uint16
= NTOHS (DnsHeader
->Flags
.Uint16
);
1202 DnsHeader
->QuestionsNum
= NTOHS (DnsHeader
->QuestionsNum
);
1203 DnsHeader
->AnswersNum
= NTOHS (DnsHeader
->AnswersNum
);
1204 DnsHeader
->AuthorityNum
= NTOHS (DnsHeader
->AuthorityNum
);
1205 DnsHeader
->AditionalNum
= NTOHS (DnsHeader
->AditionalNum
);
1208 // There is always one QuestionsNum in DNS message. The capability to handle more
1209 // than one requires to redesign the message format. Currently, it's not supported.
1211 if (DnsHeader
->QuestionsNum
> 1) {
1213 return EFI_UNSUPPORTED
;
1219 QueryName
= (CHAR8
*)(RxString
+ sizeof (*DnsHeader
));
1221 QueryNameLen
= (UINT32
)AsciiStrLen (QueryName
) + 1;
1224 // Check whether the remaining packet length is available or not.
1226 if (RemainingLength
<= QueryNameLen
+ sizeof (DNS_QUERY_SECTION
)) {
1230 RemainingLength
-= (QueryNameLen
+ sizeof (DNS_QUERY_SECTION
));
1234 // Get query section
1236 QuerySection
= (DNS_QUERY_SECTION
*)(QueryName
+ QueryNameLen
);
1237 QuerySection
->Type
= NTOHS (QuerySection
->Type
);
1238 QuerySection
->Class
= NTOHS (QuerySection
->Class
);
1240 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1243 // Check DnsResponse Validity, if so, also get a valid NET_MAP_ITEM.
1245 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1246 if (!IsValidDnsResponse (
1247 &Instance
->Dns4TxTokens
,
1248 DnsHeader
->Identification
,
1250 QuerySection
->Class
,
1255 Status
= EFI_ABORTED
;
1259 ASSERT (Item
!= NULL
);
1260 Dns4TokenEntry
= (DNS4_TOKEN_ENTRY
*)(Item
->Key
);
1262 if (!IsValidDnsResponse (
1263 &Instance
->Dns6TxTokens
,
1264 DnsHeader
->Identification
,
1266 QuerySection
->Class
,
1271 Status
= EFI_ABORTED
;
1275 ASSERT (Item
!= NULL
);
1276 Dns6TokenEntry
= (DNS6_TOKEN_ENTRY
*)(Item
->Key
);
1280 // Continue Check Some Errors.
1282 if ((DnsHeader
->Flags
.Bits
.RCode
!= DNS_FLAGS_RCODE_NO_ERROR
) || (DnsHeader
->AnswersNum
< 1) || \
1283 (DnsHeader
->Flags
.Bits
.QR
!= DNS_FLAGS_QR_RESPONSE
))
1286 // The domain name referenced in the query does not exist.
1288 if (DnsHeader
->Flags
.Bits
.RCode
== DNS_FLAGS_RCODE_NAME_ERROR
) {
1289 Status
= EFI_NOT_FOUND
;
1291 Status
= EFI_DEVICE_ERROR
;
1298 // Do some buffer allocations.
1300 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1301 ASSERT (Dns4TokenEntry
!= NULL
);
1303 if (Dns4TokenEntry
->GeneralLookUp
) {
1305 // It's the GeneralLookUp querying.
1307 Dns4TokenEntry
->Token
->RspData
.GLookupData
= AllocateZeroPool (sizeof (DNS_RESOURCE_RECORD
));
1308 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
== NULL
) {
1309 Status
= EFI_OUT_OF_RESOURCES
;
1313 Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
= AllocateZeroPool (DnsHeader
->AnswersNum
* sizeof (DNS_RESOURCE_RECORD
));
1314 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
== NULL
) {
1315 Status
= EFI_OUT_OF_RESOURCES
;
1320 // It's not the GeneralLookUp querying. Check the Query type.
1322 if (QuerySection
->Type
== DNS_TYPE_A
) {
1323 Dns4TokenEntry
->Token
->RspData
.H2AData
= AllocateZeroPool (sizeof (DNS_HOST_TO_ADDR_DATA
));
1324 if (Dns4TokenEntry
->Token
->RspData
.H2AData
== NULL
) {
1325 Status
= EFI_OUT_OF_RESOURCES
;
1329 Dns4TokenEntry
->Token
->RspData
.H2AData
->IpList
= AllocateZeroPool (DnsHeader
->AnswersNum
* sizeof (EFI_IPv4_ADDRESS
));
1330 if (Dns4TokenEntry
->Token
->RspData
.H2AData
->IpList
== NULL
) {
1331 Status
= EFI_OUT_OF_RESOURCES
;
1335 Status
= EFI_UNSUPPORTED
;
1340 ASSERT (Dns6TokenEntry
!= NULL
);
1342 if (Dns6TokenEntry
->GeneralLookUp
) {
1344 // It's the GeneralLookUp querying.
1346 Dns6TokenEntry
->Token
->RspData
.GLookupData
= AllocateZeroPool (sizeof (DNS_RESOURCE_RECORD
));
1347 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
== NULL
) {
1348 Status
= EFI_OUT_OF_RESOURCES
;
1352 Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
= AllocateZeroPool (DnsHeader
->AnswersNum
* sizeof (DNS_RESOURCE_RECORD
));
1353 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
== NULL
) {
1354 Status
= EFI_OUT_OF_RESOURCES
;
1359 // It's not the GeneralLookUp querying. Check the Query type.
1361 if (QuerySection
->Type
== DNS_TYPE_AAAA
) {
1362 Dns6TokenEntry
->Token
->RspData
.H2AData
= AllocateZeroPool (sizeof (DNS6_HOST_TO_ADDR_DATA
));
1363 if (Dns6TokenEntry
->Token
->RspData
.H2AData
== NULL
) {
1364 Status
= EFI_OUT_OF_RESOURCES
;
1368 Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
= AllocateZeroPool (DnsHeader
->AnswersNum
* sizeof (EFI_IPv6_ADDRESS
));
1369 if (Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
== NULL
) {
1370 Status
= EFI_OUT_OF_RESOURCES
;
1374 Status
= EFI_UNSUPPORTED
;
1380 Status
= EFI_NOT_FOUND
;
1385 AnswerName
= (CHAR8
*)QuerySection
+ sizeof (*QuerySection
);
1388 // Processing AnswerSection.
1390 while (AnswerSectionNum
< DnsHeader
->AnswersNum
) {
1392 // Check whether the remaining packet length is available or not.
1394 if (RemainingLength
<= sizeof (UINT16
) + sizeof (DNS_ANSWER_SECTION
)) {
1396 Status
= EFI_ABORTED
;
1399 RemainingLength
-= (sizeof (UINT16
) + sizeof (DNS_ANSWER_SECTION
));
1403 // Answer name should be PTR, else EFI_UNSUPPORTED returned.
1405 if ((*(UINT8
*)AnswerName
& 0xC0) != 0xC0) {
1406 Status
= EFI_UNSUPPORTED
;
1411 // Get Answer section.
1413 AnswerSection
= (DNS_ANSWER_SECTION
*)(AnswerName
+ sizeof (UINT16
));
1414 AnswerSection
->Type
= NTOHS (AnswerSection
->Type
);
1415 AnswerSection
->Class
= NTOHS (AnswerSection
->Class
);
1416 AnswerSection
->Ttl
= NTOHL (AnswerSection
->Ttl
);
1417 AnswerSection
->DataLength
= NTOHS (AnswerSection
->DataLength
);
1420 // Check whether the remaining packet length is available or not.
1422 if (RemainingLength
< AnswerSection
->DataLength
) {
1424 Status
= EFI_ABORTED
;
1427 RemainingLength
-= AnswerSection
->DataLength
;
1431 // Check whether it's the GeneralLookUp querying.
1433 if ((Instance
->Service
->IpVersion
== IP_VERSION_4
) && Dns4TokenEntry
->GeneralLookUp
) {
1434 Dns4RR
= Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
;
1435 AnswerData
= (UINT8
*)AnswerSection
+ sizeof (*AnswerSection
);
1438 // Fill the ResourceRecord.
1440 Dns4RR
[RRCount
].QName
= AllocateZeroPool (AsciiStrLen (QueryName
) + 1);
1441 if (Dns4RR
[RRCount
].QName
== NULL
) {
1442 Status
= EFI_OUT_OF_RESOURCES
;
1446 CopyMem (Dns4RR
[RRCount
].QName
, QueryName
, AsciiStrLen (QueryName
));
1447 Dns4RR
[RRCount
].QType
= AnswerSection
->Type
;
1448 Dns4RR
[RRCount
].QClass
= AnswerSection
->Class
;
1449 Dns4RR
[RRCount
].TTL
= AnswerSection
->Ttl
;
1450 Dns4RR
[RRCount
].DataLength
= AnswerSection
->DataLength
;
1451 Dns4RR
[RRCount
].RData
= AllocateZeroPool (Dns4RR
[RRCount
].DataLength
);
1452 if (Dns4RR
[RRCount
].RData
== NULL
) {
1453 Status
= EFI_OUT_OF_RESOURCES
;
1457 CopyMem (Dns4RR
[RRCount
].RData
, AnswerData
, Dns4RR
[RRCount
].DataLength
);
1460 Status
= EFI_SUCCESS
;
1461 } else if ((Instance
->Service
->IpVersion
== IP_VERSION_6
) && Dns6TokenEntry
->GeneralLookUp
) {
1462 Dns6RR
= Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
;
1463 AnswerData
= (UINT8
*)AnswerSection
+ sizeof (*AnswerSection
);
1466 // Fill the ResourceRecord.
1468 Dns6RR
[RRCount
].QName
= AllocateZeroPool (AsciiStrLen (QueryName
) + 1);
1469 if (Dns6RR
[RRCount
].QName
== NULL
) {
1470 Status
= EFI_OUT_OF_RESOURCES
;
1474 CopyMem (Dns6RR
[RRCount
].QName
, QueryName
, AsciiStrLen (QueryName
));
1475 Dns6RR
[RRCount
].QType
= AnswerSection
->Type
;
1476 Dns6RR
[RRCount
].QClass
= AnswerSection
->Class
;
1477 Dns6RR
[RRCount
].TTL
= AnswerSection
->Ttl
;
1478 Dns6RR
[RRCount
].DataLength
= AnswerSection
->DataLength
;
1479 Dns6RR
[RRCount
].RData
= AllocateZeroPool (Dns6RR
[RRCount
].DataLength
);
1480 if (Dns6RR
[RRCount
].RData
== NULL
) {
1481 Status
= EFI_OUT_OF_RESOURCES
;
1485 CopyMem (Dns6RR
[RRCount
].RData
, AnswerData
, Dns6RR
[RRCount
].DataLength
);
1488 Status
= EFI_SUCCESS
;
1491 // It's not the GeneralLookUp querying.
1492 // Check the Query type, parse the response packet.
1494 switch (AnswerSection
->Type
) {
1497 // This is address entry, get Data.
1499 ASSERT (Dns4TokenEntry
!= NULL
);
1501 if (AnswerSection
->DataLength
!= 4) {
1502 Status
= EFI_ABORTED
;
1506 HostAddr4
= Dns4TokenEntry
->Token
->RspData
.H2AData
->IpList
;
1507 AnswerData
= (UINT8
*)AnswerSection
+ sizeof (*AnswerSection
);
1508 CopyMem (&HostAddr4
[IpCount
], AnswerData
, sizeof (EFI_IPv4_ADDRESS
));
1511 // Allocate new CacheEntry pool to update DNS cache dynamically.
1513 Dns4CacheEntry
= AllocateZeroPool (sizeof (EFI_DNS4_CACHE_ENTRY
));
1514 if (Dns4CacheEntry
== NULL
) {
1515 Status
= EFI_OUT_OF_RESOURCES
;
1519 Dns4CacheEntry
->HostName
= AllocateZeroPool (2 * (StrLen (Dns4TokenEntry
->QueryHostName
) + 1));
1520 if (Dns4CacheEntry
->HostName
== NULL
) {
1521 Status
= EFI_OUT_OF_RESOURCES
;
1525 CopyMem (Dns4CacheEntry
->HostName
, Dns4TokenEntry
->QueryHostName
, 2 * (StrLen (Dns4TokenEntry
->QueryHostName
) + 1));
1526 Dns4CacheEntry
->IpAddress
= AllocateZeroPool (sizeof (EFI_IPv4_ADDRESS
));
1527 if (Dns4CacheEntry
->IpAddress
== NULL
) {
1528 Status
= EFI_OUT_OF_RESOURCES
;
1532 CopyMem (Dns4CacheEntry
->IpAddress
, AnswerData
, sizeof (EFI_IPv4_ADDRESS
));
1534 if ((CNameTtl
!= 0) && (AnswerSection
->Ttl
!= 0)) {
1535 Dns4CacheEntry
->Timeout
= MIN (CNameTtl
, AnswerSection
->Ttl
);
1537 Dns4CacheEntry
->Timeout
= MAX (CNameTtl
, AnswerSection
->Ttl
);
1540 UpdateDns4Cache (&mDriverData
->Dns4CacheList
, FALSE
, TRUE
, *Dns4CacheEntry
);
1543 // Free allocated CacheEntry pool.
1545 FreePool (Dns4CacheEntry
->HostName
);
1546 Dns4CacheEntry
->HostName
= NULL
;
1548 FreePool (Dns4CacheEntry
->IpAddress
);
1549 Dns4CacheEntry
->IpAddress
= NULL
;
1551 FreePool (Dns4CacheEntry
);
1552 Dns4CacheEntry
= NULL
;
1555 Status
= EFI_SUCCESS
;
1559 // This is address entry, get Data.
1561 ASSERT (Dns6TokenEntry
!= NULL
);
1563 if (AnswerSection
->DataLength
!= 16) {
1564 Status
= EFI_ABORTED
;
1568 HostAddr6
= Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
;
1569 AnswerData
= (UINT8
*)AnswerSection
+ sizeof (*AnswerSection
);
1570 CopyMem (&HostAddr6
[IpCount
], AnswerData
, sizeof (EFI_IPv6_ADDRESS
));
1573 // Allocate new CacheEntry pool to update DNS cache dynamically.
1575 Dns6CacheEntry
= AllocateZeroPool (sizeof (EFI_DNS6_CACHE_ENTRY
));
1576 if (Dns6CacheEntry
== NULL
) {
1577 Status
= EFI_OUT_OF_RESOURCES
;
1581 Dns6CacheEntry
->HostName
= AllocateZeroPool (2 * (StrLen (Dns6TokenEntry
->QueryHostName
) + 1));
1582 if (Dns6CacheEntry
->HostName
== NULL
) {
1583 Status
= EFI_OUT_OF_RESOURCES
;
1587 CopyMem (Dns6CacheEntry
->HostName
, Dns6TokenEntry
->QueryHostName
, 2 * (StrLen (Dns6TokenEntry
->QueryHostName
) + 1));
1588 Dns6CacheEntry
->IpAddress
= AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS
));
1589 if (Dns6CacheEntry
->IpAddress
== NULL
) {
1590 Status
= EFI_OUT_OF_RESOURCES
;
1594 CopyMem (Dns6CacheEntry
->IpAddress
, AnswerData
, sizeof (EFI_IPv6_ADDRESS
));
1596 if ((CNameTtl
!= 0) && (AnswerSection
->Ttl
!= 0)) {
1597 Dns6CacheEntry
->Timeout
= MIN (CNameTtl
, AnswerSection
->Ttl
);
1599 Dns6CacheEntry
->Timeout
= MAX (CNameTtl
, AnswerSection
->Ttl
);
1602 UpdateDns6Cache (&mDriverData
->Dns6CacheList
, FALSE
, TRUE
, *Dns6CacheEntry
);
1605 // Free allocated CacheEntry pool.
1607 FreePool (Dns6CacheEntry
->HostName
);
1608 Dns6CacheEntry
->HostName
= NULL
;
1610 FreePool (Dns6CacheEntry
->IpAddress
);
1611 Dns6CacheEntry
->IpAddress
= NULL
;
1613 FreePool (Dns6CacheEntry
);
1614 Dns6CacheEntry
= NULL
;
1617 Status
= EFI_SUCCESS
;
1619 case DNS_TYPE_CNAME
:
1621 // According RFC 1034 - 3.6.2, if the query name is an alias, the name server will include the CNAME
1622 // record in the response and restart the query at the domain name specified in the data field of the
1623 // CNAME record. So, just record the TTL value of the CNAME, then skip to parse the next record.
1625 CNameTtl
= AnswerSection
->Ttl
;
1628 Status
= EFI_UNSUPPORTED
;
1636 AnswerName
= (CHAR8
*)AnswerSection
+ sizeof (*AnswerSection
) + AnswerSection
->DataLength
;
1640 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1641 ASSERT (Dns4TokenEntry
!= NULL
);
1643 if (Dns4TokenEntry
->GeneralLookUp
) {
1644 Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRCount
= RRCount
;
1646 if (QuerySection
->Type
== DNS_TYPE_A
) {
1647 Dns4TokenEntry
->Token
->RspData
.H2AData
->IpCount
= IpCount
;
1649 Status
= EFI_UNSUPPORTED
;
1654 ASSERT (Dns6TokenEntry
!= NULL
);
1656 if (Dns6TokenEntry
->GeneralLookUp
) {
1657 Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRCount
= RRCount
;
1659 if (QuerySection
->Type
== DNS_TYPE_AAAA
) {
1660 Dns6TokenEntry
->Token
->RspData
.H2AData
->IpCount
= IpCount
;
1662 Status
= EFI_UNSUPPORTED
;
1670 // Parsing is complete, free the sending packet and signal Event here.
1672 if ((Item
!= NULL
) && (Item
->Value
!= NULL
)) {
1673 NetbufFree ((NET_BUF
*)(Item
->Value
));
1676 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1677 ASSERT (Dns4TokenEntry
!= NULL
);
1678 Dns4RemoveTokenEntry (&Instance
->Dns4TxTokens
, Dns4TokenEntry
);
1679 Dns4TokenEntry
->Token
->Status
= Status
;
1680 if (Dns4TokenEntry
->Token
->Event
!= NULL
) {
1681 gBS
->SignalEvent (Dns4TokenEntry
->Token
->Event
);
1685 ASSERT (Dns6TokenEntry
!= NULL
);
1686 Dns6RemoveTokenEntry (&Instance
->Dns6TxTokens
, Dns6TokenEntry
);
1687 Dns6TokenEntry
->Token
->Status
= Status
;
1688 if (Dns6TokenEntry
->Token
->Event
!= NULL
) {
1689 gBS
->SignalEvent (Dns6TokenEntry
->Token
->Event
);
1696 // Free the allocated buffer if error happen.
1698 if (EFI_ERROR (Status
)) {
1699 if (Dns4TokenEntry
!= NULL
) {
1700 if (Dns4TokenEntry
->GeneralLookUp
) {
1701 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
!= NULL
) {
1702 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
!= NULL
) {
1703 while (RRCount
!= 0) {
1705 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].QName
!= NULL
) {
1706 FreePool (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].QName
);
1709 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].RData
!= NULL
) {
1710 FreePool (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].RData
);
1714 FreePool (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
);
1717 FreePool (Dns4TokenEntry
->Token
->RspData
.GLookupData
);
1720 if ((QuerySection
->Type
== DNS_TYPE_A
) && (Dns4TokenEntry
->Token
->RspData
.H2AData
!= NULL
)) {
1721 if (Dns4TokenEntry
->Token
->RspData
.H2AData
->IpList
!= NULL
) {
1722 FreePool (Dns4TokenEntry
->Token
->RspData
.H2AData
->IpList
);
1725 FreePool (Dns4TokenEntry
->Token
->RspData
.H2AData
);
1726 Dns4TokenEntry
->Token
->RspData
.H2AData
= NULL
;
1731 if (Dns6TokenEntry
!= NULL
) {
1732 if (Dns6TokenEntry
->GeneralLookUp
) {
1733 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
!= NULL
) {
1734 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
!= NULL
) {
1735 while (RRCount
!= 0) {
1737 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].QName
!= NULL
) {
1738 FreePool (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].QName
);
1741 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].RData
!= NULL
) {
1742 FreePool (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].RData
);
1746 FreePool (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
);
1749 FreePool (Dns6TokenEntry
->Token
->RspData
.GLookupData
);
1752 if ((QuerySection
->Type
== DNS_TYPE_AAAA
) && (Dns6TokenEntry
->Token
->RspData
.H2AData
!= NULL
)) {
1753 if (Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
!= NULL
) {
1754 FreePool (Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
);
1757 FreePool (Dns6TokenEntry
->Token
->RspData
.H2AData
);
1758 Dns6TokenEntry
->Token
->RspData
.H2AData
= NULL
;
1763 if (Dns4CacheEntry
!= NULL
) {
1764 if (Dns4CacheEntry
->HostName
!= NULL
) {
1765 FreePool (Dns4CacheEntry
->HostName
);
1768 if (Dns4CacheEntry
->IpAddress
!= NULL
) {
1769 FreePool (Dns4CacheEntry
->IpAddress
);
1772 FreePool (Dns4CacheEntry
);
1775 if (Dns6CacheEntry
!= NULL
) {
1776 if (Dns6CacheEntry
->HostName
!= NULL
) {
1777 FreePool (Dns6CacheEntry
->HostName
);
1780 if (Dns6CacheEntry
->IpAddress
!= NULL
) {
1781 FreePool (Dns6CacheEntry
->IpAddress
);
1784 FreePool (Dns6CacheEntry
);
1788 gBS
->RestoreTPL (OldTpl
);
1793 Parse response packet.
1795 @param Packet The packets received.
1796 @param EndPoint The local/remote UDP access point
1797 @param IoStatus The status of the UDP receive
1798 @param Context The opaque parameter to the function.
1803 DnsOnPacketReceived (
1805 UDP_END_POINT
*EndPoint
,
1806 EFI_STATUS IoStatus
,
1810 DNS_INSTANCE
*Instance
;
1817 Instance
= (DNS_INSTANCE
*)Context
;
1818 NET_CHECK_SIGNATURE (Instance
, DNS_INSTANCE_SIGNATURE
);
1823 if (EFI_ERROR (IoStatus
)) {
1827 ASSERT (Packet
!= NULL
);
1829 Len
= Packet
->TotalSize
;
1831 RcvString
= NetbufGetByte (Packet
, 0, NULL
);
1832 ASSERT (RcvString
!= NULL
);
1835 // Parse Dns Response
1837 ParseDnsResponse (Instance
, RcvString
, Len
, &Completed
);
1841 if (Packet
!= NULL
) {
1842 NetbufFree (Packet
);
1846 UdpIoRecvDatagram (Instance
->UdpIo
, DnsOnPacketReceived
, Instance
, 0);
1851 Release the net buffer when packet is sent.
1853 @param Packet The packets received.
1854 @param EndPoint The local/remote UDP access point
1855 @param IoStatus The status of the UDP receive
1856 @param Context The opaque parameter to the function.
1863 UDP_END_POINT
*EndPoint
,
1864 EFI_STATUS IoStatus
,
1868 DNS_INSTANCE
*Instance
;
1871 DNS4_TOKEN_ENTRY
*Dns4TokenEntry
;
1872 DNS6_TOKEN_ENTRY
*Dns6TokenEntry
;
1874 Dns4TokenEntry
= NULL
;
1875 Dns6TokenEntry
= NULL
;
1877 Instance
= (DNS_INSTANCE
*)Context
;
1878 NET_CHECK_SIGNATURE (Instance
, DNS_INSTANCE_SIGNATURE
);
1880 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1881 NET_LIST_FOR_EACH (Entry
, &Instance
->Dns4TxTokens
.Used
) {
1882 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
1883 if (Packet
== (NET_BUF
*)(Item
->Value
)) {
1884 Dns4TokenEntry
= ((DNS4_TOKEN_ENTRY
*)Item
->Key
);
1885 Dns4TokenEntry
->PacketToLive
= Dns4TokenEntry
->Token
->RetryInterval
;
1890 NET_LIST_FOR_EACH (Entry
, &Instance
->Dns6TxTokens
.Used
) {
1891 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
1892 if (Packet
== (NET_BUF
*)(Item
->Value
)) {
1893 Dns6TokenEntry
= ((DNS6_TOKEN_ENTRY
*)Item
->Key
);
1894 Dns6TokenEntry
->PacketToLive
= Dns6TokenEntry
->Token
->RetryInterval
;
1900 NetbufFree (Packet
);
1904 Query request information.
1906 @param Instance The DNS instance
1907 @param Packet The packet for querying request information.
1909 @retval EFI_SUCCESS Query request information successfully.
1910 @retval Others Failed to query request information.
1915 IN DNS_INSTANCE
*Instance
,
1922 // Ready to receive the DNS response.
1924 if (Instance
->UdpIo
->RecvRequest
== NULL
) {
1925 Status
= UdpIoRecvDatagram (Instance
->UdpIo
, DnsOnPacketReceived
, Instance
, 0);
1926 if (EFI_ERROR (Status
)) {
1932 // Transmit the DNS packet.
1934 NET_GET_REF (Packet
);
1936 Status
= UdpIoSendDatagram (Instance
->UdpIo
, Packet
, NULL
, NULL
, DnsOnPacketSent
, Instance
);
1942 Construct the Packet according query section.
1944 @param Instance The DNS instance
1945 @param QueryName Queried Name
1946 @param Type Queried Type
1947 @param Class Queried Class
1948 @param Packet The packet for query
1950 @retval EFI_SUCCESS The packet is constructed.
1951 @retval Others Failed to construct the Packet.
1956 IN DNS_INSTANCE
*Instance
,
1957 IN CHAR8
*QueryName
,
1960 OUT NET_BUF
**Packet
1964 DNS_HEADER
*DnsHeader
;
1965 DNS_QUERY_SECTION
*DnsQuery
;
1968 // Messages carried by UDP are restricted to 512 bytes (not counting the IP
1971 Frag
.Bulk
= AllocatePool (DNS_MAX_MESSAGE_SIZE
* sizeof (UINT8
));
1972 if (Frag
.Bulk
== NULL
) {
1973 return EFI_OUT_OF_RESOURCES
;
1979 DnsHeader
= (DNS_HEADER
*)Frag
.Bulk
;
1980 DnsHeader
->Identification
= (UINT16
)NET_RANDOM (NetRandomInitSeed ());
1981 DnsHeader
->Flags
.Uint16
= 0x0000;
1982 DnsHeader
->Flags
.Bits
.RD
= 1;
1983 DnsHeader
->Flags
.Bits
.OpCode
= DNS_FLAGS_OPCODE_STANDARD
;
1984 DnsHeader
->Flags
.Bits
.QR
= DNS_FLAGS_QR_QUERY
;
1985 DnsHeader
->QuestionsNum
= 1;
1986 DnsHeader
->AnswersNum
= 0;
1987 DnsHeader
->AuthorityNum
= 0;
1988 DnsHeader
->AditionalNum
= 0;
1990 DnsHeader
->Identification
= HTONS (DnsHeader
->Identification
);
1991 DnsHeader
->Flags
.Uint16
= HTONS (DnsHeader
->Flags
.Uint16
);
1992 DnsHeader
->QuestionsNum
= HTONS (DnsHeader
->QuestionsNum
);
1993 DnsHeader
->AnswersNum
= HTONS (DnsHeader
->AnswersNum
);
1994 DnsHeader
->AuthorityNum
= HTONS (DnsHeader
->AuthorityNum
);
1995 DnsHeader
->AditionalNum
= HTONS (DnsHeader
->AditionalNum
);
1997 Frag
.Len
= sizeof (*DnsHeader
);
2002 CopyMem (Frag
.Bulk
+ Frag
.Len
, QueryName
, AsciiStrLen (QueryName
));
2003 Frag
.Len
= (UINT32
)(Frag
.Len
+ AsciiStrLen (QueryName
));
2004 *(Frag
.Bulk
+ Frag
.Len
) = 0;
2008 // Rest query section
2010 DnsQuery
= (DNS_QUERY_SECTION
*)(Frag
.Bulk
+ Frag
.Len
);
2012 DnsQuery
->Type
= HTONS (Type
);
2013 DnsQuery
->Class
= HTONS (Class
);
2015 Frag
.Len
+= sizeof (*DnsQuery
);
2018 // Wrap the Frag in a net buffer.
2020 *Packet
= NetbufFromExt (&Frag
, 1, 0, 0, DnsDummyExtFree
, NULL
);
2021 if (*Packet
== NULL
) {
2022 FreePool (Frag
.Bulk
);
2023 return EFI_OUT_OF_RESOURCES
;
2027 // Store the UdpIo in ProtoData.
2029 *((UINTN
*)&((*Packet
)->ProtoData
[0])) = (UINTN
)(Instance
->UdpIo
);
2035 Retransmit the packet.
2037 @param Instance The DNS instance
2038 @param Packet Retransmit the packet
2040 @retval EFI_SUCCESS The packet is retransmitted.
2041 @retval Others Failed to retransmit.
2046 IN DNS_INSTANCE
*Instance
,
2054 ASSERT (Packet
!= NULL
);
2057 // Set the requests to the listening port, other packets to the connected port
2059 Buffer
= NetbufGetByte (Packet
, 0, NULL
);
2060 ASSERT (Buffer
!= NULL
);
2062 NET_GET_REF (Packet
);
2064 Status
= UdpIoSendDatagram (
2073 if (EFI_ERROR (Status
)) {
2074 NET_PUT_REF (Packet
);
2081 The timer ticking function for the DNS services.
2083 @param Event The ticking event
2084 @param Context The DNS service instance
2089 DnsOnTimerRetransmit (
2094 DNS_SERVICE
*Service
;
2099 DNS_INSTANCE
*Instance
;
2100 LIST_ENTRY
*EntryNetMap
;
2101 NET_MAP_ITEM
*ItemNetMap
;
2102 DNS4_TOKEN_ENTRY
*Dns4TokenEntry
;
2103 DNS6_TOKEN_ENTRY
*Dns6TokenEntry
;
2105 Dns4TokenEntry
= NULL
;
2106 Dns6TokenEntry
= NULL
;
2108 Service
= (DNS_SERVICE
*)Context
;
2110 if (Service
->IpVersion
== IP_VERSION_4
) {
2112 // Iterate through all the children of the DNS service instance. Time
2113 // out the packet. If maximum retries reached, clean the Token up.
2115 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Service
->Dns4ChildrenList
) {
2116 Instance
= NET_LIST_USER_STRUCT (Entry
, DNS_INSTANCE
, Link
);
2118 EntryNetMap
= Instance
->Dns4TxTokens
.Used
.ForwardLink
;
2119 while (EntryNetMap
!= &Instance
->Dns4TxTokens
.Used
) {
2120 ItemNetMap
= NET_LIST_USER_STRUCT (EntryNetMap
, NET_MAP_ITEM
, Link
);
2121 Dns4TokenEntry
= (DNS4_TOKEN_ENTRY
*)(ItemNetMap
->Key
);
2122 if ((Dns4TokenEntry
->PacketToLive
== 0) || (--Dns4TokenEntry
->PacketToLive
> 0)) {
2123 EntryNetMap
= EntryNetMap
->ForwardLink
;
2128 // Retransmit the packet if haven't reach the maximum retry count,
2129 // otherwise exit the transfer.
2131 if (++Dns4TokenEntry
->RetryCounting
<= Dns4TokenEntry
->Token
->RetryCount
) {
2132 DnsRetransmit (Instance
, (NET_BUF
*)ItemNetMap
->Value
);
2133 EntryNetMap
= EntryNetMap
->ForwardLink
;
2136 // Maximum retries reached, clean the Token up.
2138 Dns4RemoveTokenEntry (&Instance
->Dns4TxTokens
, Dns4TokenEntry
);
2139 Dns4TokenEntry
->Token
->Status
= EFI_TIMEOUT
;
2140 gBS
->SignalEvent (Dns4TokenEntry
->Token
->Event
);
2144 // Free the sending packet.
2146 if (ItemNetMap
->Value
!= NULL
) {
2147 NetbufFree ((NET_BUF
*)(ItemNetMap
->Value
));
2150 EntryNetMap
= Instance
->Dns4TxTokens
.Used
.ForwardLink
;
2156 // Iterate through all the children of the DNS service instance. Time
2157 // out the packet. If maximum retries reached, clean the Token up.
2159 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Service
->Dns6ChildrenList
) {
2160 Instance
= NET_LIST_USER_STRUCT (Entry
, DNS_INSTANCE
, Link
);
2162 EntryNetMap
= Instance
->Dns6TxTokens
.Used
.ForwardLink
;
2163 while (EntryNetMap
!= &Instance
->Dns6TxTokens
.Used
) {
2164 ItemNetMap
= NET_LIST_USER_STRUCT (EntryNetMap
, NET_MAP_ITEM
, Link
);
2165 Dns6TokenEntry
= (DNS6_TOKEN_ENTRY
*)(ItemNetMap
->Key
);
2166 if ((Dns6TokenEntry
->PacketToLive
== 0) || (--Dns6TokenEntry
->PacketToLive
> 0)) {
2167 EntryNetMap
= EntryNetMap
->ForwardLink
;
2172 // Retransmit the packet if haven't reach the maximum retry count,
2173 // otherwise exit the transfer.
2175 if (++Dns6TokenEntry
->RetryCounting
<= Dns6TokenEntry
->Token
->RetryCount
) {
2176 DnsRetransmit (Instance
, (NET_BUF
*)ItemNetMap
->Value
);
2177 EntryNetMap
= EntryNetMap
->ForwardLink
;
2180 // Maximum retries reached, clean the Token up.
2182 Dns6RemoveTokenEntry (&Instance
->Dns6TxTokens
, Dns6TokenEntry
);
2183 Dns6TokenEntry
->Token
->Status
= EFI_TIMEOUT
;
2184 gBS
->SignalEvent (Dns6TokenEntry
->Token
->Event
);
2188 // Free the sending packet.
2190 if (ItemNetMap
->Value
!= NULL
) {
2191 NetbufFree ((NET_BUF
*)(ItemNetMap
->Value
));
2194 EntryNetMap
= Instance
->Dns6TxTokens
.Used
.ForwardLink
;
2202 The timer ticking function for the DNS driver.
2204 @param Event The ticking event
2224 // Iterate through all the DNS4 cache list.
2226 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &mDriverData
->Dns4CacheList
) {
2227 Item4
= NET_LIST_USER_STRUCT (Entry
, DNS4_CACHE
, AllCacheLink
);
2228 Item4
->DnsCache
.Timeout
--;
2231 Entry
= mDriverData
->Dns4CacheList
.ForwardLink
;
2232 while (Entry
!= &mDriverData
->Dns4CacheList
) {
2233 Item4
= NET_LIST_USER_STRUCT (Entry
, DNS4_CACHE
, AllCacheLink
);
2234 if (Item4
->DnsCache
.Timeout
== 0) {
2235 RemoveEntryList (&Item4
->AllCacheLink
);
2236 FreePool (Item4
->DnsCache
.HostName
);
2237 FreePool (Item4
->DnsCache
.IpAddress
);
2239 Entry
= mDriverData
->Dns4CacheList
.ForwardLink
;
2241 Entry
= Entry
->ForwardLink
;
2246 // Iterate through all the DNS6 cache list.
2248 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &mDriverData
->Dns6CacheList
) {
2249 Item6
= NET_LIST_USER_STRUCT (Entry
, DNS6_CACHE
, AllCacheLink
);
2250 Item6
->DnsCache
.Timeout
--;
2253 Entry
= mDriverData
->Dns6CacheList
.ForwardLink
;
2254 while (Entry
!= &mDriverData
->Dns6CacheList
) {
2255 Item6
= NET_LIST_USER_STRUCT (Entry
, DNS6_CACHE
, AllCacheLink
);
2256 if (Item6
->DnsCache
.Timeout
== 0) {
2257 RemoveEntryList (&Item6
->AllCacheLink
);
2258 FreePool (Item6
->DnsCache
.HostName
);
2259 FreePool (Item6
->DnsCache
.IpAddress
);
2261 Entry
= mDriverData
->Dns6CacheList
.ForwardLink
;
2263 Entry
= Entry
->ForwardLink
;