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
;
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
);
321 ASSERT ((TokenEntry
!= NULL
) || (0 == NetMapGetCount (&Instance
->Dns4TxTokens
)));
323 if (NetMapIsEmpty (&Instance
->Dns4TxTokens
)) {
324 Instance
->UdpIo
->Protocol
.Udp4
->Cancel (Instance
->UdpIo
->Protocol
.Udp4
, &Instance
->UdpIo
->RecvRequest
->Token
.Udp4
);
331 Cancel DNS6 tokens from the DNS6 instance.
333 @param[in] Instance Pointer to the DNS instance context data.
334 @param[in] Token Pointer to the token to be canceled. If NULL, all
335 tokens in this instance will be cancelled.
336 This parameter is optional and may be NULL.
338 @retval EFI_SUCCESS The Token is cancelled.
339 @retval EFI_NOT_FOUND The Token is not found.
343 Dns6InstanceCancelToken (
344 IN DNS_INSTANCE
*Instance
,
345 IN EFI_DNS6_COMPLETION_TOKEN
*Token
349 DNS6_TOKEN_ENTRY
*TokenEntry
;
354 Status
= GetDns6TokenEntry (&Instance
->Dns6TxTokens
, Token
, &TokenEntry
);
355 if (EFI_ERROR (Status
)) {
363 // Cancel this TokenEntry from the Dns6TxTokens map.
365 Status
= NetMapIterate (&Instance
->Dns6TxTokens
, Dns6CancelTokens
, TokenEntry
);
367 if ((TokenEntry
!= NULL
) && (Status
== EFI_ABORTED
)) {
369 // If Token isn't NULL and Status is EFI_ABORTED, the token is cancelled from
370 // the Dns6TxTokens and returns success.
372 if (NetMapIsEmpty (&Instance
->Dns6TxTokens
)) {
373 Instance
->UdpIo
->Protocol
.Udp6
->Cancel (Instance
->UdpIo
->Protocol
.Udp6
, &Instance
->UdpIo
->RecvRequest
->Token
.Udp6
);
378 ASSERT ((TokenEntry
!= NULL
) || (0 == NetMapGetCount (&Instance
->Dns6TxTokens
)));
380 if (NetMapIsEmpty (&Instance
->Dns6TxTokens
)) {
381 Instance
->UdpIo
->Protocol
.Udp6
->Cancel (Instance
->UdpIo
->Protocol
.Udp6
, &Instance
->UdpIo
->RecvRequest
->Token
.Udp6
);
388 Free the resource related to the configure parameters.
390 @param Config The DNS configure data
395 IN OUT EFI_DNS4_CONFIG_DATA
*Config
398 if (Config
->DnsServerList
!= NULL
) {
399 FreePool (Config
->DnsServerList
);
402 ZeroMem (Config
, sizeof (EFI_DNS4_CONFIG_DATA
));
406 Free the resource related to the configure parameters.
408 @param Config The DNS configure data
413 IN OUT EFI_DNS6_CONFIG_DATA
*Config
416 if (Config
->DnsServerList
!= NULL
) {
417 FreePool (Config
->DnsServerList
);
420 ZeroMem (Config
, sizeof (EFI_DNS6_CONFIG_DATA
));
424 Allocate memory for configure parameter such as timeout value for Dst,
425 then copy the configure parameter from Src to Dst.
427 @param[out] Dst The destination DHCP configure data.
428 @param[in] Src The source DHCP configure data.
430 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
431 @retval EFI_SUCCESS The configure is copied.
436 OUT EFI_DNS4_CONFIG_DATA
*Dst
,
437 IN EFI_DNS4_CONFIG_DATA
*Src
443 CopyMem (Dst
, Src
, sizeof (*Dst
));
444 Dst
->DnsServerList
= NULL
;
447 // Allocate a memory then copy DnsServerList to it
449 if (Src
->DnsServerList
!= NULL
) {
450 Len
= Src
->DnsServerListCount
* sizeof (EFI_IPv4_ADDRESS
);
451 Dst
->DnsServerList
= AllocatePool (Len
);
452 if (Dst
->DnsServerList
== NULL
) {
453 Dns4CleanConfigure (Dst
);
454 return EFI_OUT_OF_RESOURCES
;
457 for (Index
= 0; Index
< Src
->DnsServerListCount
; Index
++) {
458 CopyMem (&Dst
->DnsServerList
[Index
], &Src
->DnsServerList
[Index
], sizeof (EFI_IPv4_ADDRESS
));
466 Allocate memory for configure parameter such as timeout value for Dst,
467 then copy the configure parameter from Src to Dst.
469 @param[out] Dst The destination DHCP configure data.
470 @param[in] Src The source DHCP configure data.
472 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
473 @retval EFI_SUCCESS The configure is copied.
478 OUT EFI_DNS6_CONFIG_DATA
*Dst
,
479 IN EFI_DNS6_CONFIG_DATA
*Src
485 CopyMem (Dst
, Src
, sizeof (*Dst
));
486 Dst
->DnsServerList
= NULL
;
489 // Allocate a memory then copy DnsServerList to it
491 if (Src
->DnsServerList
!= NULL
) {
492 Len
= Src
->DnsServerCount
* sizeof (EFI_IPv6_ADDRESS
);
493 Dst
->DnsServerList
= AllocatePool (Len
);
494 if (Dst
->DnsServerList
== NULL
) {
495 Dns6CleanConfigure (Dst
);
496 return EFI_OUT_OF_RESOURCES
;
499 for (Index
= 0; Index
< Src
->DnsServerCount
; Index
++) {
500 CopyMem (&Dst
->DnsServerList
[Index
], &Src
->DnsServerList
[Index
], sizeof (EFI_IPv6_ADDRESS
));
508 Callback of Dns packet. Does nothing.
510 @param Arg The context.
522 Poll the UDP to get the IP4 default address, which may be retrieved
525 The default time out value is 5 seconds. If IP has retrieved the default address,
526 the UDP is reconfigured.
528 @param Instance The DNS instance
529 @param UdpIo The UDP_IO to poll
530 @param UdpCfgData The UDP configure data to reconfigure the UDP_IO
532 @retval TRUE The default address is retrieved and UDP is reconfigured.
533 @retval FALSE Some error occurred.
538 IN DNS_INSTANCE
*Instance
,
540 IN EFI_UDP4_CONFIG_DATA
*UdpCfgData
543 DNS_SERVICE
*Service
;
544 EFI_IP4_MODE_DATA Ip4Mode
;
545 EFI_UDP4_PROTOCOL
*Udp
;
548 ASSERT (Instance
->Dns4CfgData
.UseDefaultSetting
);
550 Service
= Instance
->Service
;
551 Udp
= UdpIo
->Protocol
.Udp4
;
553 Status
= gBS
->SetTimer (
554 Service
->TimerToGetMap
,
556 DNS_TIME_TO_GETMAP
* TICKS_PER_SECOND
558 if (EFI_ERROR (Status
)) {
562 while (EFI_ERROR (gBS
->CheckEvent (Service
->TimerToGetMap
))) {
565 if (!EFI_ERROR (Udp
->GetModeData (Udp
, NULL
, &Ip4Mode
, NULL
, NULL
)) &&
566 Ip4Mode
.IsConfigured
) {
568 Udp
->Configure (Udp
, NULL
);
569 return (BOOLEAN
) (Udp
->Configure (Udp
, UdpCfgData
) == EFI_SUCCESS
);
577 Configure the opened Udp6 instance until the corresponding Ip6 instance
580 @param Instance The DNS instance
581 @param UdpIo The UDP_IO to poll
582 @param UdpCfgData The UDP configure data to reconfigure the UDP_IO
584 @retval TRUE Configure the Udp6 instance successfully.
585 @retval FALSE Some error occurred.
590 IN DNS_INSTANCE
*Instance
,
592 IN EFI_UDP6_CONFIG_DATA
*UdpCfgData
595 DNS_SERVICE
*Service
;
596 EFI_IP6_MODE_DATA Ip6Mode
;
597 EFI_UDP6_PROTOCOL
*Udp
;
600 Service
= Instance
->Service
;
601 Udp
= UdpIo
->Protocol
.Udp6
;
603 Status
= gBS
->SetTimer (
604 Service
->TimerToGetMap
,
606 DNS_TIME_TO_GETMAP
* TICKS_PER_SECOND
608 if (EFI_ERROR (Status
)) {
612 while (EFI_ERROR (gBS
->CheckEvent (Service
->TimerToGetMap
))) {
615 if (!EFI_ERROR (Udp
->GetModeData (Udp
, NULL
, &Ip6Mode
, NULL
, NULL
))) {
616 if (Ip6Mode
.AddressList
!= NULL
) {
617 FreePool (Ip6Mode
.AddressList
);
620 if (Ip6Mode
.GroupTable
!= NULL
) {
621 FreePool (Ip6Mode
.GroupTable
);
624 if (Ip6Mode
.RouteTable
!= NULL
) {
625 FreePool (Ip6Mode
.RouteTable
);
628 if (Ip6Mode
.NeighborCache
!= NULL
) {
629 FreePool (Ip6Mode
.NeighborCache
);
632 if (Ip6Mode
.PrefixTable
!= NULL
) {
633 FreePool (Ip6Mode
.PrefixTable
);
636 if (Ip6Mode
.IcmpTypeList
!= NULL
) {
637 FreePool (Ip6Mode
.IcmpTypeList
);
640 if (!Ip6Mode
.IsStarted
|| Ip6Mode
.IsConfigured
) {
641 Udp
->Configure (Udp
, NULL
);
642 if (Udp
->Configure (Udp
, UdpCfgData
) == EFI_SUCCESS
) {
655 @param Instance The DNS session
656 @param UdpIo The UDP_IO instance
658 @retval EFI_SUCCESS The UDP is successfully configured for the
664 IN DNS_INSTANCE
*Instance
,
668 EFI_DNS4_CONFIG_DATA
*Config
;
669 EFI_UDP4_CONFIG_DATA UdpConfig
;
672 Config
= &Instance
->Dns4CfgData
;
674 UdpConfig
.AcceptBroadcast
= FALSE
;
675 UdpConfig
.AcceptPromiscuous
= FALSE
;
676 UdpConfig
.AcceptAnyPort
= FALSE
;
677 UdpConfig
.AllowDuplicatePort
= FALSE
;
678 UdpConfig
.TypeOfService
= 0;
679 UdpConfig
.TimeToLive
= 128;
680 UdpConfig
.DoNotFragment
= FALSE
;
681 UdpConfig
.ReceiveTimeout
= 0;
682 UdpConfig
.TransmitTimeout
= 0;
683 UdpConfig
.UseDefaultAddress
= Config
->UseDefaultSetting
;
684 UdpConfig
.SubnetMask
= Config
->SubnetMask
;
685 UdpConfig
.StationPort
= Config
->LocalPort
;
686 UdpConfig
.RemotePort
= DNS_SERVER_PORT
;
688 CopyMem (&UdpConfig
.StationAddress
, &Config
->StationIp
, sizeof (EFI_IPv4_ADDRESS
));
689 CopyMem (&UdpConfig
.RemoteAddress
, &Instance
->SessionDnsServer
.v4
, sizeof (EFI_IPv4_ADDRESS
));
691 Status
= UdpIo
->Protocol
.Udp4
->Configure (UdpIo
->Protocol
.Udp4
, &UdpConfig
);
693 if ((Status
== EFI_NO_MAPPING
) && Dns4GetMapping (Instance
, UdpIo
, &UdpConfig
)) {
703 @param Instance The DNS session
704 @param UdpIo The UDP_IO instance
706 @retval EFI_SUCCESS The UDP is successfully configured for the
712 IN DNS_INSTANCE
*Instance
,
716 EFI_DNS6_CONFIG_DATA
*Config
;
717 EFI_UDP6_CONFIG_DATA UdpConfig
;
720 Config
= &Instance
->Dns6CfgData
;
722 UdpConfig
.AcceptPromiscuous
= FALSE
;
723 UdpConfig
.AcceptAnyPort
= FALSE
;
724 UdpConfig
.AllowDuplicatePort
= FALSE
;
725 UdpConfig
.TrafficClass
= 0;
726 UdpConfig
.HopLimit
= 128;
727 UdpConfig
.ReceiveTimeout
= 0;
728 UdpConfig
.TransmitTimeout
= 0;
729 UdpConfig
.StationPort
= Config
->LocalPort
;
730 UdpConfig
.RemotePort
= DNS_SERVER_PORT
;
731 CopyMem (&UdpConfig
.StationAddress
, &Config
->StationIp
, sizeof (EFI_IPv6_ADDRESS
));
732 CopyMem (&UdpConfig
.RemoteAddress
, &Instance
->SessionDnsServer
.v6
, sizeof (EFI_IPv6_ADDRESS
));
734 Status
= UdpIo
->Protocol
.Udp6
->Configure (UdpIo
->Protocol
.Udp6
, &UdpConfig
);
736 if ((Status
== EFI_NO_MAPPING
) && Dns6GetMapping (Instance
, UdpIo
, &UdpConfig
)) {
744 Update Dns4 cache to shared list of caches of all DNSv4 instances.
746 @param Dns4CacheList All Dns4 cache list.
747 @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache.
748 If TRUE, this function will delete matching DNS Cache entry.
749 @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
750 If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
751 @param DnsCacheEntry Entry Pointer to DNS Cache entry.
753 @retval EFI_SUCCESS Update Dns4 cache successfully.
754 @retval Others Failed to update Dns4 cache.
760 IN LIST_ENTRY
*Dns4CacheList
,
761 IN BOOLEAN DeleteFlag
,
763 IN EFI_DNS4_CACHE_ENTRY DnsCacheEntry
766 DNS4_CACHE
*NewDnsCache
;
775 // Search the database for the matching EFI_DNS_CACHE_ENTRY
777 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Dns4CacheList
) {
778 Item
= NET_LIST_USER_STRUCT (Entry
, DNS4_CACHE
, AllCacheLink
);
779 if (StrCmp (DnsCacheEntry
.HostName
, Item
->DnsCache
.HostName
) == 0 && \
780 CompareMem (DnsCacheEntry
.IpAddress
, Item
->DnsCache
.IpAddress
, sizeof (EFI_IPv4_ADDRESS
)) == 0) {
782 // This is the Dns cache entry
786 // Delete matching DNS Cache entry
788 RemoveEntryList (&Item
->AllCacheLink
);
790 FreePool (Item
->DnsCache
.HostName
);
791 FreePool (Item
->DnsCache
.IpAddress
);
795 } else if (Override
) {
799 Item
->DnsCache
.Timeout
= DnsCacheEntry
.Timeout
;
803 return EFI_ACCESS_DENIED
;
811 NewDnsCache
= AllocatePool (sizeof (DNS4_CACHE
));
812 if (NewDnsCache
== NULL
) {
813 return EFI_OUT_OF_RESOURCES
;
816 InitializeListHead (&NewDnsCache
->AllCacheLink
);
818 NewDnsCache
->DnsCache
.HostName
= AllocatePool (StrSize (DnsCacheEntry
.HostName
));
819 if (NewDnsCache
->DnsCache
.HostName
== NULL
) {
820 FreePool (NewDnsCache
);
821 return EFI_OUT_OF_RESOURCES
;
824 CopyMem (NewDnsCache
->DnsCache
.HostName
, DnsCacheEntry
.HostName
, StrSize (DnsCacheEntry
.HostName
));
826 NewDnsCache
->DnsCache
.IpAddress
= AllocatePool (sizeof (EFI_IPv4_ADDRESS
));
827 if (NewDnsCache
->DnsCache
.IpAddress
== NULL
) {
828 FreePool (NewDnsCache
->DnsCache
.HostName
);
829 FreePool (NewDnsCache
);
830 return EFI_OUT_OF_RESOURCES
;
833 CopyMem (NewDnsCache
->DnsCache
.IpAddress
, DnsCacheEntry
.IpAddress
, sizeof (EFI_IPv4_ADDRESS
));
835 NewDnsCache
->DnsCache
.Timeout
= DnsCacheEntry
.Timeout
;
837 InsertTailList (Dns4CacheList
, &NewDnsCache
->AllCacheLink
);
843 Update Dns6 cache to shared list of caches of all DNSv6 instances.
845 @param Dns6CacheList All Dns6 cache list.
846 @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache.
847 If TRUE, this function will delete matching DNS Cache entry.
848 @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
849 If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
850 @param DnsCacheEntry Entry Pointer to DNS Cache entry.
852 @retval EFI_SUCCESS Update Dns6 cache successfully.
853 @retval Others Failed to update Dns6 cache.
858 IN LIST_ENTRY
*Dns6CacheList
,
859 IN BOOLEAN DeleteFlag
,
861 IN EFI_DNS6_CACHE_ENTRY DnsCacheEntry
864 DNS6_CACHE
*NewDnsCache
;
873 // Search the database for the matching EFI_DNS_CACHE_ENTRY
875 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Dns6CacheList
) {
876 Item
= NET_LIST_USER_STRUCT (Entry
, DNS6_CACHE
, AllCacheLink
);
877 if (StrCmp (DnsCacheEntry
.HostName
, Item
->DnsCache
.HostName
) == 0 && \
878 CompareMem (DnsCacheEntry
.IpAddress
, Item
->DnsCache
.IpAddress
, sizeof (EFI_IPv6_ADDRESS
)) == 0) {
880 // This is the Dns cache entry
884 // Delete matching DNS Cache entry
886 RemoveEntryList (&Item
->AllCacheLink
);
888 FreePool (Item
->DnsCache
.HostName
);
889 FreePool (Item
->DnsCache
.IpAddress
);
893 } else if (Override
) {
897 Item
->DnsCache
.Timeout
= DnsCacheEntry
.Timeout
;
901 return EFI_ACCESS_DENIED
;
909 NewDnsCache
= AllocatePool (sizeof (DNS6_CACHE
));
910 if (NewDnsCache
== NULL
) {
911 return EFI_OUT_OF_RESOURCES
;
914 InitializeListHead (&NewDnsCache
->AllCacheLink
);
916 NewDnsCache
->DnsCache
.HostName
= AllocatePool (StrSize (DnsCacheEntry
.HostName
));
917 if (NewDnsCache
->DnsCache
.HostName
== NULL
) {
918 FreePool (NewDnsCache
);
919 return EFI_OUT_OF_RESOURCES
;
922 CopyMem (NewDnsCache
->DnsCache
.HostName
, DnsCacheEntry
.HostName
, StrSize (DnsCacheEntry
.HostName
));
924 NewDnsCache
->DnsCache
.IpAddress
= AllocatePool (sizeof (EFI_IPv6_ADDRESS
));
925 if (NewDnsCache
->DnsCache
.IpAddress
== NULL
) {
926 FreePool (NewDnsCache
->DnsCache
.HostName
);
927 FreePool (NewDnsCache
);
928 return EFI_OUT_OF_RESOURCES
;
931 CopyMem (NewDnsCache
->DnsCache
.IpAddress
, DnsCacheEntry
.IpAddress
, sizeof (EFI_IPv6_ADDRESS
));
933 NewDnsCache
->DnsCache
.Timeout
= DnsCacheEntry
.Timeout
;
935 InsertTailList (Dns6CacheList
, &NewDnsCache
->AllCacheLink
);
941 Add Dns4 ServerIp to common list of addresses of all configured DNSv4 server.
943 @param Dns4ServerList Common list of addresses of all configured DNSv4 server.
944 @param ServerIp DNS server Ip.
946 @retval EFI_SUCCESS Add Dns4 ServerIp to common list successfully.
947 @retval Others Failed to add Dns4 ServerIp to common list.
953 IN LIST_ENTRY
*Dns4ServerList
,
954 IN EFI_IPv4_ADDRESS ServerIp
957 DNS4_SERVER_IP
*NewServerIp
;
958 DNS4_SERVER_IP
*Item
;
966 // Search the database for the matching ServerIp
968 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Dns4ServerList
) {
969 Item
= NET_LIST_USER_STRUCT (Entry
, DNS4_SERVER_IP
, AllServerLink
);
970 if (CompareMem (&Item
->Dns4ServerIp
, &ServerIp
, sizeof (EFI_IPv4_ADDRESS
)) == 0) {
981 NewServerIp
= AllocatePool (sizeof (DNS4_SERVER_IP
));
982 if (NewServerIp
== NULL
) {
983 return EFI_OUT_OF_RESOURCES
;
986 InitializeListHead (&NewServerIp
->AllServerLink
);
988 CopyMem (&NewServerIp
->Dns4ServerIp
, &ServerIp
, sizeof (EFI_IPv4_ADDRESS
));
990 InsertTailList (Dns4ServerList
, &NewServerIp
->AllServerLink
);
996 Add Dns6 ServerIp to common list of addresses of all configured DNSv6 server.
998 @param Dns6ServerList Common list of addresses of all configured DNSv6 server.
999 @param ServerIp DNS server Ip.
1001 @retval EFI_SUCCESS Add Dns6 ServerIp to common list successfully.
1002 @retval Others Failed to add Dns6 ServerIp to common list.
1008 IN LIST_ENTRY
*Dns6ServerList
,
1009 IN EFI_IPv6_ADDRESS ServerIp
1012 DNS6_SERVER_IP
*NewServerIp
;
1013 DNS6_SERVER_IP
*Item
;
1021 // Search the database for the matching ServerIp
1023 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Dns6ServerList
) {
1024 Item
= NET_LIST_USER_STRUCT (Entry
, DNS6_SERVER_IP
, AllServerLink
);
1025 if (CompareMem (&Item
->Dns6ServerIp
, &ServerIp
, sizeof (EFI_IPv6_ADDRESS
)) == 0) {
1036 NewServerIp
= AllocatePool (sizeof (DNS6_SERVER_IP
));
1037 if (NewServerIp
== NULL
) {
1038 return EFI_OUT_OF_RESOURCES
;
1041 InitializeListHead (&NewServerIp
->AllServerLink
);
1043 CopyMem (&NewServerIp
->Dns6ServerIp
, &ServerIp
, sizeof (EFI_IPv6_ADDRESS
));
1045 InsertTailList (Dns6ServerList
, &NewServerIp
->AllServerLink
);
1051 Find out whether the response is valid or invalid.
1053 @param TokensMap All DNS transmittal Tokens entry.
1054 @param Identification Identification for queried packet.
1055 @param Type Type for queried packet.
1056 @param Class Class for queried packet.
1057 @param Item Return corresponding Token entry.
1059 @retval TRUE The response is valid.
1060 @retval FALSE The response is invalid.
1064 IsValidDnsResponse (
1065 IN NET_MAP
*TokensMap
,
1066 IN UINT16 Identification
,
1069 OUT NET_MAP_ITEM
**Item
1076 DNS_HEADER
*DnsHeader
;
1078 DNS_QUERY_SECTION
*QuerySection
;
1080 NET_LIST_FOR_EACH (Entry
, &TokensMap
->Used
) {
1081 *Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
1082 Packet
= (NET_BUF
*) ((*Item
)->Value
);
1083 if (Packet
== NULL
) {
1087 TxString
= NetbufGetByte (Packet
, 0, NULL
);
1088 ASSERT (TxString
!= NULL
);
1089 DnsHeader
= (DNS_HEADER
*) TxString
;
1090 QueryName
= (CHAR8
*) (TxString
+ sizeof (*DnsHeader
));
1091 QuerySection
= (DNS_QUERY_SECTION
*) (QueryName
+ AsciiStrLen (QueryName
) + 1);
1093 if (NTOHS (DnsHeader
->Identification
) == Identification
&&
1094 NTOHS (QuerySection
->Type
) == Type
&&
1095 NTOHS (QuerySection
->Class
) == Class
) {
1109 @param Instance The DNS instance
1110 @param RxString Received buffer.
1111 @param Length Received buffer length.
1112 @param Completed Flag to indicate that Dns response is valid.
1114 @retval EFI_SUCCESS Parse Dns Response successfully.
1115 @retval Others Failed to parse Dns Response.
1120 IN OUT DNS_INSTANCE
*Instance
,
1123 OUT BOOLEAN
*Completed
1126 DNS_HEADER
*DnsHeader
;
1129 UINT32 QueryNameLen
;
1130 DNS_QUERY_SECTION
*QuerySection
;
1133 DNS_ANSWER_SECTION
*AnswerSection
;
1137 DNS4_TOKEN_ENTRY
*Dns4TokenEntry
;
1138 DNS6_TOKEN_ENTRY
*Dns6TokenEntry
;
1142 UINT32 AnswerSectionNum
;
1145 EFI_IPv4_ADDRESS
*HostAddr4
;
1146 EFI_IPv6_ADDRESS
*HostAddr6
;
1148 EFI_DNS4_CACHE_ENTRY
*Dns4CacheEntry
;
1149 EFI_DNS6_CACHE_ENTRY
*Dns6CacheEntry
;
1151 DNS_RESOURCE_RECORD
*Dns4RR
;
1152 DNS6_RESOURCE_RECORD
*Dns6RR
;
1155 UINT32 RemainingLength
;
1160 Dns4TokenEntry
= NULL
;
1161 Dns6TokenEntry
= NULL
;
1165 AnswerSectionNum
= 0;
1171 Dns4CacheEntry
= NULL
;
1172 Dns6CacheEntry
= NULL
;
1178 Status
= EFI_SUCCESS
;
1179 RemainingLength
= Length
;
1182 // Check whether the remaining packet length is available or not.
1184 if (RemainingLength
<= sizeof (DNS_HEADER
)) {
1188 RemainingLength
-= sizeof (DNS_HEADER
);
1194 DnsHeader
= (DNS_HEADER
*) RxString
;
1196 DnsHeader
->Identification
= NTOHS (DnsHeader
->Identification
);
1197 DnsHeader
->Flags
.Uint16
= NTOHS (DnsHeader
->Flags
.Uint16
);
1198 DnsHeader
->QuestionsNum
= NTOHS (DnsHeader
->QuestionsNum
);
1199 DnsHeader
->AnswersNum
= NTOHS (DnsHeader
->AnswersNum
);
1200 DnsHeader
->AuthorityNum
= NTOHS (DnsHeader
->AuthorityNum
);
1201 DnsHeader
->AditionalNum
= NTOHS (DnsHeader
->AditionalNum
);
1204 // There is always one QuestionsNum in DNS message. The capability to handle more
1205 // than one requires to redesign the message format. Currently, it's not supported.
1207 if (DnsHeader
->QuestionsNum
> 1) {
1209 return EFI_UNSUPPORTED
;
1215 QueryName
= (CHAR8
*) (RxString
+ sizeof (*DnsHeader
));
1217 QueryNameLen
= (UINT32
) AsciiStrLen (QueryName
) + 1;
1220 // Check whether the remaining packet length is available or not.
1222 if (RemainingLength
<= QueryNameLen
+ sizeof (DNS_QUERY_SECTION
)) {
1226 RemainingLength
-= (QueryNameLen
+ sizeof (DNS_QUERY_SECTION
));
1230 // Get query section
1232 QuerySection
= (DNS_QUERY_SECTION
*) (QueryName
+ QueryNameLen
);
1233 QuerySection
->Type
= NTOHS (QuerySection
->Type
);
1234 QuerySection
->Class
= NTOHS (QuerySection
->Class
);
1236 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1239 // Check DnsResponse Validity, if so, also get a valid NET_MAP_ITEM.
1241 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1242 if (!IsValidDnsResponse (
1243 &Instance
->Dns4TxTokens
,
1244 DnsHeader
->Identification
,
1246 QuerySection
->Class
,
1250 Status
= EFI_ABORTED
;
1253 ASSERT (Item
!= NULL
);
1254 Dns4TokenEntry
= (DNS4_TOKEN_ENTRY
*) (Item
->Key
);
1256 if (!IsValidDnsResponse (
1257 &Instance
->Dns6TxTokens
,
1258 DnsHeader
->Identification
,
1260 QuerySection
->Class
,
1264 Status
= EFI_ABORTED
;
1267 ASSERT (Item
!= NULL
);
1268 Dns6TokenEntry
= (DNS6_TOKEN_ENTRY
*) (Item
->Key
);
1272 // Continue Check Some Errors.
1274 if (DnsHeader
->Flags
.Bits
.RCode
!= DNS_FLAGS_RCODE_NO_ERROR
|| DnsHeader
->AnswersNum
< 1 || \
1275 DnsHeader
->Flags
.Bits
.QR
!= DNS_FLAGS_QR_RESPONSE
) {
1277 // The domain name referenced in the query does not exist.
1279 if (DnsHeader
->Flags
.Bits
.RCode
== DNS_FLAGS_RCODE_NAME_ERROR
) {
1280 Status
= EFI_NOT_FOUND
;
1282 Status
= EFI_DEVICE_ERROR
;
1289 // Do some buffer allocations.
1291 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1292 ASSERT (Dns4TokenEntry
!= NULL
);
1294 if (Dns4TokenEntry
->GeneralLookUp
) {
1296 // It's the GeneralLookUp querying.
1298 Dns4TokenEntry
->Token
->RspData
.GLookupData
= AllocateZeroPool (sizeof (DNS_RESOURCE_RECORD
));
1299 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
== NULL
) {
1300 Status
= EFI_OUT_OF_RESOURCES
;
1303 Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
= AllocateZeroPool (DnsHeader
->AnswersNum
* sizeof (DNS_RESOURCE_RECORD
));
1304 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
== NULL
) {
1305 Status
= EFI_OUT_OF_RESOURCES
;
1310 // It's not the GeneralLookUp querying. Check the Query type.
1312 if (QuerySection
->Type
== DNS_TYPE_A
) {
1313 Dns4TokenEntry
->Token
->RspData
.H2AData
= AllocateZeroPool (sizeof (DNS_HOST_TO_ADDR_DATA
));
1314 if (Dns4TokenEntry
->Token
->RspData
.H2AData
== NULL
) {
1315 Status
= EFI_OUT_OF_RESOURCES
;
1318 Dns4TokenEntry
->Token
->RspData
.H2AData
->IpList
= AllocateZeroPool (DnsHeader
->AnswersNum
* sizeof (EFI_IPv4_ADDRESS
));
1319 if (Dns4TokenEntry
->Token
->RspData
.H2AData
->IpList
== NULL
) {
1320 Status
= EFI_OUT_OF_RESOURCES
;
1324 Status
= EFI_UNSUPPORTED
;
1329 ASSERT (Dns6TokenEntry
!= NULL
);
1331 if (Dns6TokenEntry
->GeneralLookUp
) {
1333 // It's the GeneralLookUp querying.
1335 Dns6TokenEntry
->Token
->RspData
.GLookupData
= AllocateZeroPool (sizeof (DNS_RESOURCE_RECORD
));
1336 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
== NULL
) {
1337 Status
= EFI_OUT_OF_RESOURCES
;
1340 Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
= AllocateZeroPool (DnsHeader
->AnswersNum
* sizeof (DNS_RESOURCE_RECORD
));
1341 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
== NULL
) {
1342 Status
= EFI_OUT_OF_RESOURCES
;
1347 // It's not the GeneralLookUp querying. Check the Query type.
1349 if (QuerySection
->Type
== DNS_TYPE_AAAA
) {
1350 Dns6TokenEntry
->Token
->RspData
.H2AData
= AllocateZeroPool (sizeof (DNS6_HOST_TO_ADDR_DATA
));
1351 if (Dns6TokenEntry
->Token
->RspData
.H2AData
== NULL
) {
1352 Status
= EFI_OUT_OF_RESOURCES
;
1355 Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
= AllocateZeroPool (DnsHeader
->AnswersNum
* sizeof (EFI_IPv6_ADDRESS
));
1356 if (Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
== NULL
) {
1357 Status
= EFI_OUT_OF_RESOURCES
;
1361 Status
= EFI_UNSUPPORTED
;
1367 Status
= EFI_NOT_FOUND
;
1372 AnswerName
= (CHAR8
*) QuerySection
+ sizeof (*QuerySection
);
1375 // Processing AnswerSection.
1377 while (AnswerSectionNum
< DnsHeader
->AnswersNum
) {
1379 // Check whether the remaining packet length is available or not.
1381 if (RemainingLength
<= sizeof (UINT16
) + sizeof (DNS_ANSWER_SECTION
)) {
1383 Status
= EFI_ABORTED
;
1386 RemainingLength
-= (sizeof (UINT16
) + sizeof (DNS_ANSWER_SECTION
));
1390 // Answer name should be PTR, else EFI_UNSUPPORTED returned.
1392 if ((*(UINT8
*) AnswerName
& 0xC0) != 0xC0) {
1393 Status
= EFI_UNSUPPORTED
;
1398 // Get Answer section.
1400 AnswerSection
= (DNS_ANSWER_SECTION
*) (AnswerName
+ sizeof (UINT16
));
1401 AnswerSection
->Type
= NTOHS (AnswerSection
->Type
);
1402 AnswerSection
->Class
= NTOHS (AnswerSection
->Class
);
1403 AnswerSection
->Ttl
= NTOHL (AnswerSection
->Ttl
);
1404 AnswerSection
->DataLength
= NTOHS (AnswerSection
->DataLength
);
1407 // Check whether the remaining packet length is available or not.
1409 if (RemainingLength
< AnswerSection
->DataLength
) {
1411 Status
= EFI_ABORTED
;
1414 RemainingLength
-= AnswerSection
->DataLength
;
1418 // Check whether it's the GeneralLookUp querying.
1420 if (Instance
->Service
->IpVersion
== IP_VERSION_4
&& Dns4TokenEntry
->GeneralLookUp
) {
1421 Dns4RR
= Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
;
1422 AnswerData
= (UINT8
*) AnswerSection
+ sizeof (*AnswerSection
);
1425 // Fill the ResourceRecord.
1427 Dns4RR
[RRCount
].QName
= AllocateZeroPool (AsciiStrLen (QueryName
) + 1);
1428 if (Dns4RR
[RRCount
].QName
== NULL
) {
1429 Status
= EFI_OUT_OF_RESOURCES
;
1432 CopyMem (Dns4RR
[RRCount
].QName
, QueryName
, AsciiStrLen (QueryName
));
1433 Dns4RR
[RRCount
].QType
= AnswerSection
->Type
;
1434 Dns4RR
[RRCount
].QClass
= AnswerSection
->Class
;
1435 Dns4RR
[RRCount
].TTL
= AnswerSection
->Ttl
;
1436 Dns4RR
[RRCount
].DataLength
= AnswerSection
->DataLength
;
1437 Dns4RR
[RRCount
].RData
= AllocateZeroPool (Dns4RR
[RRCount
].DataLength
);
1438 if (Dns4RR
[RRCount
].RData
== NULL
) {
1439 Status
= EFI_OUT_OF_RESOURCES
;
1442 CopyMem (Dns4RR
[RRCount
].RData
, AnswerData
, Dns4RR
[RRCount
].DataLength
);
1445 Status
= EFI_SUCCESS
;
1446 } else if (Instance
->Service
->IpVersion
== IP_VERSION_6
&& Dns6TokenEntry
->GeneralLookUp
) {
1447 Dns6RR
= Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
;
1448 AnswerData
= (UINT8
*) AnswerSection
+ sizeof (*AnswerSection
);
1451 // Fill the ResourceRecord.
1453 Dns6RR
[RRCount
].QName
= AllocateZeroPool (AsciiStrLen (QueryName
) + 1);
1454 if (Dns6RR
[RRCount
].QName
== NULL
) {
1455 Status
= EFI_OUT_OF_RESOURCES
;
1458 CopyMem (Dns6RR
[RRCount
].QName
, QueryName
, AsciiStrLen (QueryName
));
1459 Dns6RR
[RRCount
].QType
= AnswerSection
->Type
;
1460 Dns6RR
[RRCount
].QClass
= AnswerSection
->Class
;
1461 Dns6RR
[RRCount
].TTL
= AnswerSection
->Ttl
;
1462 Dns6RR
[RRCount
].DataLength
= AnswerSection
->DataLength
;
1463 Dns6RR
[RRCount
].RData
= AllocateZeroPool (Dns6RR
[RRCount
].DataLength
);
1464 if (Dns6RR
[RRCount
].RData
== NULL
) {
1465 Status
= EFI_OUT_OF_RESOURCES
;
1468 CopyMem (Dns6RR
[RRCount
].RData
, AnswerData
, Dns6RR
[RRCount
].DataLength
);
1471 Status
= EFI_SUCCESS
;
1474 // It's not the GeneralLookUp querying.
1475 // Check the Query type, parse the response packet.
1477 switch (AnswerSection
->Type
) {
1480 // This is address entry, get Data.
1482 ASSERT (Dns4TokenEntry
!= NULL
);
1484 if (AnswerSection
->DataLength
!= 4) {
1485 Status
= EFI_ABORTED
;
1489 HostAddr4
= Dns4TokenEntry
->Token
->RspData
.H2AData
->IpList
;
1490 AnswerData
= (UINT8
*) AnswerSection
+ sizeof (*AnswerSection
);
1491 CopyMem (&HostAddr4
[IpCount
], AnswerData
, sizeof (EFI_IPv4_ADDRESS
));
1494 // Allocate new CacheEntry pool to update DNS cache dynamically.
1496 Dns4CacheEntry
= AllocateZeroPool (sizeof (EFI_DNS4_CACHE_ENTRY
));
1497 if (Dns4CacheEntry
== NULL
) {
1498 Status
= EFI_OUT_OF_RESOURCES
;
1501 Dns4CacheEntry
->HostName
= AllocateZeroPool (2 * (StrLen(Dns4TokenEntry
->QueryHostName
) + 1));
1502 if (Dns4CacheEntry
->HostName
== NULL
) {
1503 Status
= EFI_OUT_OF_RESOURCES
;
1506 CopyMem (Dns4CacheEntry
->HostName
, Dns4TokenEntry
->QueryHostName
, 2 * (StrLen(Dns4TokenEntry
->QueryHostName
) + 1));
1507 Dns4CacheEntry
->IpAddress
= AllocateZeroPool (sizeof (EFI_IPv4_ADDRESS
));
1508 if (Dns4CacheEntry
->IpAddress
== NULL
) {
1509 Status
= EFI_OUT_OF_RESOURCES
;
1512 CopyMem (Dns4CacheEntry
->IpAddress
, AnswerData
, sizeof (EFI_IPv4_ADDRESS
));
1514 if (CNameTtl
!= 0 && AnswerSection
->Ttl
!= 0) {
1515 Dns4CacheEntry
->Timeout
= MIN (CNameTtl
, AnswerSection
->Ttl
);
1517 Dns4CacheEntry
->Timeout
= MAX (CNameTtl
, AnswerSection
->Ttl
);
1520 UpdateDns4Cache (&mDriverData
->Dns4CacheList
, FALSE
, TRUE
, *Dns4CacheEntry
);
1523 // Free allocated CacheEntry pool.
1525 FreePool (Dns4CacheEntry
->HostName
);
1526 Dns4CacheEntry
->HostName
= NULL
;
1528 FreePool (Dns4CacheEntry
->IpAddress
);
1529 Dns4CacheEntry
->IpAddress
= NULL
;
1531 FreePool (Dns4CacheEntry
);
1532 Dns4CacheEntry
= NULL
;
1535 Status
= EFI_SUCCESS
;
1539 // This is address entry, get Data.
1541 ASSERT (Dns6TokenEntry
!= NULL
);
1543 if (AnswerSection
->DataLength
!= 16) {
1544 Status
= EFI_ABORTED
;
1548 HostAddr6
= Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
;
1549 AnswerData
= (UINT8
*) AnswerSection
+ sizeof (*AnswerSection
);
1550 CopyMem (&HostAddr6
[IpCount
], AnswerData
, sizeof (EFI_IPv6_ADDRESS
));
1553 // Allocate new CacheEntry pool to update DNS cache dynamically.
1555 Dns6CacheEntry
= AllocateZeroPool (sizeof (EFI_DNS6_CACHE_ENTRY
));
1556 if (Dns6CacheEntry
== NULL
) {
1557 Status
= EFI_OUT_OF_RESOURCES
;
1560 Dns6CacheEntry
->HostName
= AllocateZeroPool (2 * (StrLen(Dns6TokenEntry
->QueryHostName
) + 1));
1561 if (Dns6CacheEntry
->HostName
== NULL
) {
1562 Status
= EFI_OUT_OF_RESOURCES
;
1565 CopyMem (Dns6CacheEntry
->HostName
, Dns6TokenEntry
->QueryHostName
, 2 * (StrLen(Dns6TokenEntry
->QueryHostName
) + 1));
1566 Dns6CacheEntry
->IpAddress
= AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS
));
1567 if (Dns6CacheEntry
->IpAddress
== NULL
) {
1568 Status
= EFI_OUT_OF_RESOURCES
;
1571 CopyMem (Dns6CacheEntry
->IpAddress
, AnswerData
, sizeof (EFI_IPv6_ADDRESS
));
1573 if (CNameTtl
!= 0 && AnswerSection
->Ttl
!= 0) {
1574 Dns6CacheEntry
->Timeout
= MIN (CNameTtl
, AnswerSection
->Ttl
);
1576 Dns6CacheEntry
->Timeout
= MAX (CNameTtl
, AnswerSection
->Ttl
);
1579 UpdateDns6Cache (&mDriverData
->Dns6CacheList
, FALSE
, TRUE
, *Dns6CacheEntry
);
1582 // Free allocated CacheEntry pool.
1584 FreePool (Dns6CacheEntry
->HostName
);
1585 Dns6CacheEntry
->HostName
= NULL
;
1587 FreePool (Dns6CacheEntry
->IpAddress
);
1588 Dns6CacheEntry
->IpAddress
= NULL
;
1590 FreePool (Dns6CacheEntry
);
1591 Dns6CacheEntry
= NULL
;
1594 Status
= EFI_SUCCESS
;
1596 case DNS_TYPE_CNAME
:
1598 // According RFC 1034 - 3.6.2, if the query name is an alias, the name server will include the CNAME
1599 // record in the response and restart the query at the domain name specified in the data field of the
1600 // CNAME record. So, just record the TTL value of the CNAME, then skip to parse the next record.
1602 CNameTtl
= AnswerSection
->Ttl
;
1605 Status
= EFI_UNSUPPORTED
;
1613 AnswerName
= (CHAR8
*) AnswerSection
+ sizeof (*AnswerSection
) + AnswerSection
->DataLength
;
1614 AnswerSectionNum
++;
1617 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1618 ASSERT (Dns4TokenEntry
!= NULL
);
1620 if (Dns4TokenEntry
->GeneralLookUp
) {
1621 Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRCount
= RRCount
;
1623 if (QuerySection
->Type
== DNS_TYPE_A
) {
1624 Dns4TokenEntry
->Token
->RspData
.H2AData
->IpCount
= IpCount
;
1626 Status
= EFI_UNSUPPORTED
;
1631 ASSERT (Dns6TokenEntry
!= NULL
);
1633 if (Dns6TokenEntry
->GeneralLookUp
) {
1634 Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRCount
= RRCount
;
1636 if (QuerySection
->Type
== DNS_TYPE_AAAA
) {
1637 Dns6TokenEntry
->Token
->RspData
.H2AData
->IpCount
= IpCount
;
1639 Status
= EFI_UNSUPPORTED
;
1647 // Parsing is complete, free the sending packet and signal Event here.
1649 if (Item
!= NULL
&& Item
->Value
!= NULL
) {
1650 NetbufFree ((NET_BUF
*) (Item
->Value
));
1653 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1654 ASSERT (Dns4TokenEntry
!= NULL
);
1655 Dns4RemoveTokenEntry (&Instance
->Dns4TxTokens
, Dns4TokenEntry
);
1656 Dns4TokenEntry
->Token
->Status
= Status
;
1657 if (Dns4TokenEntry
->Token
->Event
!= NULL
) {
1658 gBS
->SignalEvent (Dns4TokenEntry
->Token
->Event
);
1662 ASSERT (Dns6TokenEntry
!= NULL
);
1663 Dns6RemoveTokenEntry (&Instance
->Dns6TxTokens
, Dns6TokenEntry
);
1664 Dns6TokenEntry
->Token
->Status
= Status
;
1665 if (Dns6TokenEntry
->Token
->Event
!= NULL
) {
1666 gBS
->SignalEvent (Dns6TokenEntry
->Token
->Event
);
1673 // Free the allocated buffer if error happen.
1675 if (EFI_ERROR (Status
)) {
1676 if (Dns4TokenEntry
!= NULL
) {
1677 if (Dns4TokenEntry
->GeneralLookUp
) {
1678 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
!= NULL
) {
1679 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
!= NULL
) {
1680 while (RRCount
!= 0) {
1682 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].QName
!= NULL
) {
1683 FreePool (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].QName
);
1686 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].RData
!= NULL
) {
1687 FreePool (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].RData
);
1691 FreePool (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
);
1694 FreePool (Dns4TokenEntry
->Token
->RspData
.GLookupData
);
1697 if (QuerySection
->Type
== DNS_TYPE_A
&& Dns4TokenEntry
->Token
->RspData
.H2AData
!= NULL
) {
1698 if (Dns4TokenEntry
->Token
->RspData
.H2AData
->IpList
!= NULL
) {
1699 FreePool (Dns4TokenEntry
->Token
->RspData
.H2AData
->IpList
);
1702 FreePool (Dns4TokenEntry
->Token
->RspData
.H2AData
);
1703 Dns4TokenEntry
->Token
->RspData
.H2AData
= NULL
;
1708 if (Dns6TokenEntry
!= NULL
) {
1709 if (Dns6TokenEntry
->GeneralLookUp
) {
1710 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
!= NULL
) {
1711 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
!= NULL
) {
1712 while (RRCount
!= 0) {
1714 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].QName
!= NULL
) {
1715 FreePool (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].QName
);
1718 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].RData
!= NULL
) {
1719 FreePool (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].RData
);
1723 FreePool (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
);
1726 FreePool (Dns6TokenEntry
->Token
->RspData
.GLookupData
);
1729 if (QuerySection
->Type
== DNS_TYPE_AAAA
&& Dns6TokenEntry
->Token
->RspData
.H2AData
!= NULL
) {
1730 if (Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
!= NULL
) {
1731 FreePool (Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
);
1734 FreePool (Dns6TokenEntry
->Token
->RspData
.H2AData
);
1735 Dns6TokenEntry
->Token
->RspData
.H2AData
= NULL
;
1740 if (Dns4CacheEntry
!= NULL
) {
1741 if (Dns4CacheEntry
->HostName
!= NULL
) {
1742 FreePool (Dns4CacheEntry
->HostName
);
1745 if (Dns4CacheEntry
->IpAddress
!= NULL
) {
1746 FreePool (Dns4CacheEntry
->IpAddress
);
1749 FreePool (Dns4CacheEntry
);
1752 if (Dns6CacheEntry
!= NULL
) {
1753 if (Dns6CacheEntry
->HostName
!= NULL
) {
1754 FreePool (Dns6CacheEntry
->HostName
);
1757 if (Dns6CacheEntry
->IpAddress
!= NULL
) {
1758 FreePool (Dns6CacheEntry
->IpAddress
);
1761 FreePool (Dns6CacheEntry
);
1765 gBS
->RestoreTPL (OldTpl
);
1770 Parse response packet.
1772 @param Packet The packets received.
1773 @param EndPoint The local/remote UDP access point
1774 @param IoStatus The status of the UDP receive
1775 @param Context The opaque parameter to the function.
1780 DnsOnPacketReceived (
1782 UDP_END_POINT
*EndPoint
,
1783 EFI_STATUS IoStatus
,
1787 DNS_INSTANCE
*Instance
;
1794 Instance
= (DNS_INSTANCE
*) Context
;
1795 NET_CHECK_SIGNATURE (Instance
, DNS_INSTANCE_SIGNATURE
);
1800 if (EFI_ERROR (IoStatus
)) {
1804 ASSERT (Packet
!= NULL
);
1806 Len
= Packet
->TotalSize
;
1808 RcvString
= NetbufGetByte (Packet
, 0, NULL
);
1809 ASSERT (RcvString
!= NULL
);
1812 // Parse Dns Response
1814 ParseDnsResponse (Instance
, RcvString
, Len
, &Completed
);
1818 if (Packet
!= NULL
) {
1819 NetbufFree (Packet
);
1823 UdpIoRecvDatagram (Instance
->UdpIo
, DnsOnPacketReceived
, Instance
, 0);
1828 Release the net buffer when packet is sent.
1830 @param Packet The packets received.
1831 @param EndPoint The local/remote UDP access point
1832 @param IoStatus The status of the UDP receive
1833 @param Context The opaque parameter to the function.
1840 UDP_END_POINT
*EndPoint
,
1841 EFI_STATUS IoStatus
,
1845 DNS_INSTANCE
*Instance
;
1848 DNS4_TOKEN_ENTRY
*Dns4TokenEntry
;
1849 DNS6_TOKEN_ENTRY
*Dns6TokenEntry
;
1851 Dns4TokenEntry
= NULL
;
1852 Dns6TokenEntry
= NULL
;
1854 Instance
= (DNS_INSTANCE
*) Context
;
1855 NET_CHECK_SIGNATURE (Instance
, DNS_INSTANCE_SIGNATURE
);
1857 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1858 NET_LIST_FOR_EACH (Entry
, &Instance
->Dns4TxTokens
.Used
) {
1859 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
1860 if (Packet
== (NET_BUF
*)(Item
->Value
)) {
1861 Dns4TokenEntry
= ((DNS4_TOKEN_ENTRY
*)Item
->Key
);
1862 Dns4TokenEntry
->PacketToLive
= Dns4TokenEntry
->Token
->RetryInterval
;
1867 NET_LIST_FOR_EACH (Entry
, &Instance
->Dns6TxTokens
.Used
) {
1868 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
1869 if (Packet
== (NET_BUF
*)(Item
->Value
)) {
1870 Dns6TokenEntry
= ((DNS6_TOKEN_ENTRY
*)Item
->Key
);
1871 Dns6TokenEntry
->PacketToLive
= Dns6TokenEntry
->Token
->RetryInterval
;
1877 NetbufFree (Packet
);
1881 Query request information.
1883 @param Instance The DNS instance
1884 @param Packet The packet for querying request information.
1886 @retval EFI_SUCCESS Query request information successfully.
1887 @retval Others Failed to query request information.
1892 IN DNS_INSTANCE
*Instance
,
1899 // Ready to receive the DNS response.
1901 if (Instance
->UdpIo
->RecvRequest
== NULL
) {
1902 Status
= UdpIoRecvDatagram (Instance
->UdpIo
, DnsOnPacketReceived
, Instance
, 0);
1903 if (EFI_ERROR (Status
)) {
1909 // Transmit the DNS packet.
1911 NET_GET_REF (Packet
);
1913 Status
= UdpIoSendDatagram (Instance
->UdpIo
, Packet
, NULL
, NULL
, DnsOnPacketSent
, Instance
);
1919 Construct the Packet according query section.
1921 @param Instance The DNS instance
1922 @param QueryName Queried Name
1923 @param Type Queried Type
1924 @param Class Queried Class
1925 @param Packet The packet for query
1927 @retval EFI_SUCCESS The packet is constructed.
1928 @retval Others Failed to construct the Packet.
1933 IN DNS_INSTANCE
*Instance
,
1934 IN CHAR8
*QueryName
,
1937 OUT NET_BUF
**Packet
1941 DNS_HEADER
*DnsHeader
;
1942 DNS_QUERY_SECTION
*DnsQuery
;
1945 // Messages carried by UDP are restricted to 512 bytes (not counting the IP
1948 Frag
.Bulk
= AllocatePool (DNS_MAX_MESSAGE_SIZE
* sizeof (UINT8
));
1949 if (Frag
.Bulk
== NULL
) {
1950 return EFI_OUT_OF_RESOURCES
;
1956 DnsHeader
= (DNS_HEADER
*) Frag
.Bulk
;
1957 DnsHeader
->Identification
= (UINT16
)NET_RANDOM (NetRandomInitSeed());
1958 DnsHeader
->Flags
.Uint16
= 0x0000;
1959 DnsHeader
->Flags
.Bits
.RD
= 1;
1960 DnsHeader
->Flags
.Bits
.OpCode
= DNS_FLAGS_OPCODE_STANDARD
;
1961 DnsHeader
->Flags
.Bits
.QR
= DNS_FLAGS_QR_QUERY
;
1962 DnsHeader
->QuestionsNum
= 1;
1963 DnsHeader
->AnswersNum
= 0;
1964 DnsHeader
->AuthorityNum
= 0;
1965 DnsHeader
->AditionalNum
= 0;
1967 DnsHeader
->Identification
= HTONS (DnsHeader
->Identification
);
1968 DnsHeader
->Flags
.Uint16
= HTONS (DnsHeader
->Flags
.Uint16
);
1969 DnsHeader
->QuestionsNum
= HTONS (DnsHeader
->QuestionsNum
);
1970 DnsHeader
->AnswersNum
= HTONS (DnsHeader
->AnswersNum
);
1971 DnsHeader
->AuthorityNum
= HTONS (DnsHeader
->AuthorityNum
);
1972 DnsHeader
->AditionalNum
= HTONS (DnsHeader
->AditionalNum
);
1974 Frag
.Len
= sizeof (*DnsHeader
);
1979 CopyMem (Frag
.Bulk
+ Frag
.Len
, QueryName
, AsciiStrLen (QueryName
));
1980 Frag
.Len
= (UINT32
) (Frag
.Len
+ AsciiStrLen (QueryName
));
1981 *(Frag
.Bulk
+ Frag
.Len
) = 0;
1985 // Rest query section
1987 DnsQuery
= (DNS_QUERY_SECTION
*) (Frag
.Bulk
+ Frag
.Len
);
1989 DnsQuery
->Type
= HTONS (Type
);
1990 DnsQuery
->Class
= HTONS (Class
);
1992 Frag
.Len
+= sizeof (*DnsQuery
);
1995 // Wrap the Frag in a net buffer.
1997 *Packet
= NetbufFromExt (&Frag
, 1, 0, 0, DnsDummyExtFree
, NULL
);
1998 if (*Packet
== NULL
) {
1999 FreePool (Frag
.Bulk
);
2000 return EFI_OUT_OF_RESOURCES
;
2004 // Store the UdpIo in ProtoData.
2006 *((UINTN
*) &((*Packet
)->ProtoData
[0])) = (UINTN
) (Instance
->UdpIo
);
2012 Retransmit the packet.
2014 @param Instance The DNS instance
2015 @param Packet Retransmit the packet
2017 @retval EFI_SUCCESS The packet is retransmitted.
2018 @retval Others Failed to retransmit.
2023 IN DNS_INSTANCE
*Instance
,
2031 ASSERT (Packet
!= NULL
);
2034 // Set the requests to the listening port, other packets to the connected port
2036 Buffer
= NetbufGetByte (Packet
, 0, NULL
);
2037 ASSERT (Buffer
!= NULL
);
2039 NET_GET_REF (Packet
);
2041 Status
= UdpIoSendDatagram (
2050 if (EFI_ERROR (Status
)) {
2051 NET_PUT_REF (Packet
);
2058 The timer ticking function for the DNS services.
2060 @param Event The ticking event
2061 @param Context The DNS service instance
2066 DnsOnTimerRetransmit (
2071 DNS_SERVICE
*Service
;
2076 DNS_INSTANCE
*Instance
;
2077 LIST_ENTRY
*EntryNetMap
;
2078 NET_MAP_ITEM
*ItemNetMap
;
2079 DNS4_TOKEN_ENTRY
*Dns4TokenEntry
;
2080 DNS6_TOKEN_ENTRY
*Dns6TokenEntry
;
2082 Dns4TokenEntry
= NULL
;
2083 Dns6TokenEntry
= NULL
;
2085 Service
= (DNS_SERVICE
*) Context
;
2088 if (Service
->IpVersion
== IP_VERSION_4
) {
2090 // Iterate through all the children of the DNS service instance. Time
2091 // out the packet. If maximum retries reached, clean the Token up.
2093 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Service
->Dns4ChildrenList
) {
2094 Instance
= NET_LIST_USER_STRUCT (Entry
, DNS_INSTANCE
, Link
);
2096 EntryNetMap
= Instance
->Dns4TxTokens
.Used
.ForwardLink
;
2097 while (EntryNetMap
!= &Instance
->Dns4TxTokens
.Used
) {
2098 ItemNetMap
= NET_LIST_USER_STRUCT (EntryNetMap
, NET_MAP_ITEM
, Link
);
2099 Dns4TokenEntry
= (DNS4_TOKEN_ENTRY
*)(ItemNetMap
->Key
);
2100 if (Dns4TokenEntry
->PacketToLive
== 0 || (--Dns4TokenEntry
->PacketToLive
> 0)) {
2101 EntryNetMap
= EntryNetMap
->ForwardLink
;
2106 // Retransmit the packet if haven't reach the maximum retry count,
2107 // otherwise exit the transfer.
2109 if (++Dns4TokenEntry
->RetryCounting
<= Dns4TokenEntry
->Token
->RetryCount
) {
2110 DnsRetransmit (Instance
, (NET_BUF
*)ItemNetMap
->Value
);
2111 EntryNetMap
= EntryNetMap
->ForwardLink
;
2114 // Maximum retries reached, clean the Token up.
2116 Dns4RemoveTokenEntry (&Instance
->Dns4TxTokens
, Dns4TokenEntry
);
2117 Dns4TokenEntry
->Token
->Status
= EFI_TIMEOUT
;
2118 gBS
->SignalEvent (Dns4TokenEntry
->Token
->Event
);
2122 // Free the sending packet.
2124 if (ItemNetMap
->Value
!= NULL
) {
2125 NetbufFree ((NET_BUF
*)(ItemNetMap
->Value
));
2128 EntryNetMap
= Instance
->Dns4TxTokens
.Used
.ForwardLink
;
2134 // Iterate through all the children of the DNS service instance. Time
2135 // out the packet. If maximum retries reached, clean the Token up.
2137 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Service
->Dns6ChildrenList
) {
2138 Instance
= NET_LIST_USER_STRUCT (Entry
, DNS_INSTANCE
, Link
);
2140 EntryNetMap
= Instance
->Dns6TxTokens
.Used
.ForwardLink
;
2141 while (EntryNetMap
!= &Instance
->Dns6TxTokens
.Used
) {
2142 ItemNetMap
= NET_LIST_USER_STRUCT (EntryNetMap
, NET_MAP_ITEM
, Link
);
2143 Dns6TokenEntry
= (DNS6_TOKEN_ENTRY
*) (ItemNetMap
->Key
);
2144 if (Dns6TokenEntry
->PacketToLive
== 0 || (--Dns6TokenEntry
->PacketToLive
> 0)) {
2145 EntryNetMap
= EntryNetMap
->ForwardLink
;
2150 // Retransmit the packet if haven't reach the maximum retry count,
2151 // otherwise exit the transfer.
2153 if (++Dns6TokenEntry
->RetryCounting
<= Dns6TokenEntry
->Token
->RetryCount
) {
2154 DnsRetransmit (Instance
, (NET_BUF
*) ItemNetMap
->Value
);
2155 EntryNetMap
= EntryNetMap
->ForwardLink
;
2158 // Maximum retries reached, clean the Token up.
2160 Dns6RemoveTokenEntry (&Instance
->Dns6TxTokens
, Dns6TokenEntry
);
2161 Dns6TokenEntry
->Token
->Status
= EFI_TIMEOUT
;
2162 gBS
->SignalEvent (Dns6TokenEntry
->Token
->Event
);
2166 // Free the sending packet.
2168 if (ItemNetMap
->Value
!= NULL
) {
2169 NetbufFree ((NET_BUF
*) (ItemNetMap
->Value
));
2172 EntryNetMap
= Instance
->Dns6TxTokens
.Used
.ForwardLink
;
2180 The timer ticking function for the DNS driver.
2182 @param Event The ticking event
2202 // Iterate through all the DNS4 cache list.
2204 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &mDriverData
->Dns4CacheList
) {
2205 Item4
= NET_LIST_USER_STRUCT (Entry
, DNS4_CACHE
, AllCacheLink
);
2206 Item4
->DnsCache
.Timeout
--;
2209 Entry
= mDriverData
->Dns4CacheList
.ForwardLink
;
2210 while (Entry
!= &mDriverData
->Dns4CacheList
) {
2211 Item4
= NET_LIST_USER_STRUCT (Entry
, DNS4_CACHE
, AllCacheLink
);
2212 if (Item4
->DnsCache
.Timeout
== 0) {
2213 RemoveEntryList (&Item4
->AllCacheLink
);
2214 FreePool (Item4
->DnsCache
.HostName
);
2215 FreePool (Item4
->DnsCache
.IpAddress
);
2217 Entry
= mDriverData
->Dns4CacheList
.ForwardLink
;
2219 Entry
= Entry
->ForwardLink
;
2224 // Iterate through all the DNS6 cache list.
2226 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &mDriverData
->Dns6CacheList
) {
2227 Item6
= NET_LIST_USER_STRUCT (Entry
, DNS6_CACHE
, AllCacheLink
);
2228 Item6
->DnsCache
.Timeout
--;
2231 Entry
= mDriverData
->Dns6CacheList
.ForwardLink
;
2232 while (Entry
!= &mDriverData
->Dns6CacheList
) {
2233 Item6
= NET_LIST_USER_STRUCT (Entry
, DNS6_CACHE
, AllCacheLink
);
2234 if (Item6
->DnsCache
.Timeout
== 0) {
2235 RemoveEntryList (&Item6
->AllCacheLink
);
2236 FreePool (Item6
->DnsCache
.HostName
);
2237 FreePool (Item6
->DnsCache
.IpAddress
);
2239 Entry
= mDriverData
->Dns6CacheList
.ForwardLink
;
2241 Entry
= Entry
->ForwardLink
;