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 sucessfully.
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 sucessfully.
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 cancle 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 cancle 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 sucessfully.
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 sucessfully.
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 occured.
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 occured.
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 avaiable 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 avaiable 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 avaiable 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 avaiable 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
);
1707 if (Dns6TokenEntry
!= NULL
) {
1708 if (Dns6TokenEntry
->GeneralLookUp
) {
1709 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
!= NULL
) {
1710 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
!= NULL
) {
1711 while (RRCount
!= 0) {
1713 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].QName
!= NULL
) {
1714 FreePool (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].QName
);
1717 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].RData
!= NULL
) {
1718 FreePool (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].RData
);
1722 FreePool (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
);
1725 FreePool (Dns6TokenEntry
->Token
->RspData
.GLookupData
);
1728 if (QuerySection
->Type
== DNS_TYPE_AAAA
&& Dns6TokenEntry
->Token
->RspData
.H2AData
!= NULL
) {
1729 if (Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
!= NULL
) {
1730 FreePool (Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
);
1733 FreePool (Dns6TokenEntry
->Token
->RspData
.H2AData
);
1738 if (Dns4CacheEntry
!= NULL
) {
1739 if (Dns4CacheEntry
->HostName
!= NULL
) {
1740 FreePool (Dns4CacheEntry
->HostName
);
1743 if (Dns4CacheEntry
->IpAddress
!= NULL
) {
1744 FreePool (Dns4CacheEntry
->IpAddress
);
1747 FreePool (Dns4CacheEntry
);
1750 if (Dns6CacheEntry
!= NULL
) {
1751 if (Dns6CacheEntry
->HostName
!= NULL
) {
1752 FreePool (Dns6CacheEntry
->HostName
);
1755 if (Dns6CacheEntry
->IpAddress
!= NULL
) {
1756 FreePool (Dns6CacheEntry
->IpAddress
);
1759 FreePool (Dns6CacheEntry
);
1763 gBS
->RestoreTPL (OldTpl
);
1768 Parse response packet.
1770 @param Packet The packets received.
1771 @param EndPoint The local/remote UDP access point
1772 @param IoStatus The status of the UDP receive
1773 @param Context The opaque parameter to the function.
1778 DnsOnPacketReceived (
1780 UDP_END_POINT
*EndPoint
,
1781 EFI_STATUS IoStatus
,
1785 DNS_INSTANCE
*Instance
;
1792 Instance
= (DNS_INSTANCE
*) Context
;
1793 NET_CHECK_SIGNATURE (Instance
, DNS_INSTANCE_SIGNATURE
);
1798 if (EFI_ERROR (IoStatus
)) {
1802 ASSERT (Packet
!= NULL
);
1804 Len
= Packet
->TotalSize
;
1806 RcvString
= NetbufGetByte (Packet
, 0, NULL
);
1807 ASSERT (RcvString
!= NULL
);
1810 // Parse Dns Response
1812 ParseDnsResponse (Instance
, RcvString
, Len
, &Completed
);
1816 if (Packet
!= NULL
) {
1817 NetbufFree (Packet
);
1821 UdpIoRecvDatagram (Instance
->UdpIo
, DnsOnPacketReceived
, Instance
, 0);
1826 Release the net buffer when packet is sent.
1828 @param Packet The packets received.
1829 @param EndPoint The local/remote UDP access point
1830 @param IoStatus The status of the UDP receive
1831 @param Context The opaque parameter to the function.
1838 UDP_END_POINT
*EndPoint
,
1839 EFI_STATUS IoStatus
,
1843 DNS_INSTANCE
*Instance
;
1846 DNS4_TOKEN_ENTRY
*Dns4TokenEntry
;
1847 DNS6_TOKEN_ENTRY
*Dns6TokenEntry
;
1849 Dns4TokenEntry
= NULL
;
1850 Dns6TokenEntry
= NULL
;
1852 Instance
= (DNS_INSTANCE
*) Context
;
1853 NET_CHECK_SIGNATURE (Instance
, DNS_INSTANCE_SIGNATURE
);
1855 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1856 NET_LIST_FOR_EACH (Entry
, &Instance
->Dns4TxTokens
.Used
) {
1857 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
1858 if (Packet
== (NET_BUF
*)(Item
->Value
)) {
1859 Dns4TokenEntry
= ((DNS4_TOKEN_ENTRY
*)Item
->Key
);
1860 Dns4TokenEntry
->PacketToLive
= Dns4TokenEntry
->Token
->RetryInterval
;
1865 NET_LIST_FOR_EACH (Entry
, &Instance
->Dns6TxTokens
.Used
) {
1866 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
1867 if (Packet
== (NET_BUF
*)(Item
->Value
)) {
1868 Dns6TokenEntry
= ((DNS6_TOKEN_ENTRY
*)Item
->Key
);
1869 Dns6TokenEntry
->PacketToLive
= Dns6TokenEntry
->Token
->RetryInterval
;
1875 NetbufFree (Packet
);
1879 Query request information.
1881 @param Instance The DNS instance
1882 @param Packet The packet for querying request information.
1884 @retval EFI_SUCCESS Query request information successfully.
1885 @retval Others Failed to query request information.
1890 IN DNS_INSTANCE
*Instance
,
1897 // Ready to receive the DNS response.
1899 if (Instance
->UdpIo
->RecvRequest
== NULL
) {
1900 Status
= UdpIoRecvDatagram (Instance
->UdpIo
, DnsOnPacketReceived
, Instance
, 0);
1901 if (EFI_ERROR (Status
)) {
1907 // Transmit the DNS packet.
1909 NET_GET_REF (Packet
);
1911 Status
= UdpIoSendDatagram (Instance
->UdpIo
, Packet
, NULL
, NULL
, DnsOnPacketSent
, Instance
);
1917 Construct the Packet according query section.
1919 @param Instance The DNS instance
1920 @param QueryName Queried Name
1921 @param Type Queried Type
1922 @param Class Queried Class
1923 @param Packet The packet for query
1925 @retval EFI_SUCCESS The packet is constructed.
1926 @retval Others Failed to construct the Packet.
1931 IN DNS_INSTANCE
*Instance
,
1932 IN CHAR8
*QueryName
,
1935 OUT NET_BUF
**Packet
1939 DNS_HEADER
*DnsHeader
;
1940 DNS_QUERY_SECTION
*DnsQuery
;
1943 // Messages carried by UDP are restricted to 512 bytes (not counting the IP
1946 Frag
.Bulk
= AllocatePool (DNS_MAX_MESSAGE_SIZE
* sizeof (UINT8
));
1947 if (Frag
.Bulk
== NULL
) {
1948 return EFI_OUT_OF_RESOURCES
;
1954 DnsHeader
= (DNS_HEADER
*) Frag
.Bulk
;
1955 DnsHeader
->Identification
= (UINT16
)NET_RANDOM (NetRandomInitSeed());
1956 DnsHeader
->Flags
.Uint16
= 0x0000;
1957 DnsHeader
->Flags
.Bits
.RD
= 1;
1958 DnsHeader
->Flags
.Bits
.OpCode
= DNS_FLAGS_OPCODE_STANDARD
;
1959 DnsHeader
->Flags
.Bits
.QR
= DNS_FLAGS_QR_QUERY
;
1960 DnsHeader
->QuestionsNum
= 1;
1961 DnsHeader
->AnswersNum
= 0;
1962 DnsHeader
->AuthorityNum
= 0;
1963 DnsHeader
->AditionalNum
= 0;
1965 DnsHeader
->Identification
= HTONS (DnsHeader
->Identification
);
1966 DnsHeader
->Flags
.Uint16
= HTONS (DnsHeader
->Flags
.Uint16
);
1967 DnsHeader
->QuestionsNum
= HTONS (DnsHeader
->QuestionsNum
);
1968 DnsHeader
->AnswersNum
= HTONS (DnsHeader
->AnswersNum
);
1969 DnsHeader
->AuthorityNum
= HTONS (DnsHeader
->AuthorityNum
);
1970 DnsHeader
->AditionalNum
= HTONS (DnsHeader
->AditionalNum
);
1972 Frag
.Len
= sizeof (*DnsHeader
);
1977 CopyMem (Frag
.Bulk
+ Frag
.Len
, QueryName
, AsciiStrLen (QueryName
));
1978 Frag
.Len
= (UINT32
) (Frag
.Len
+ AsciiStrLen (QueryName
));
1979 *(Frag
.Bulk
+ Frag
.Len
) = 0;
1983 // Rest query section
1985 DnsQuery
= (DNS_QUERY_SECTION
*) (Frag
.Bulk
+ Frag
.Len
);
1987 DnsQuery
->Type
= HTONS (Type
);
1988 DnsQuery
->Class
= HTONS (Class
);
1990 Frag
.Len
+= sizeof (*DnsQuery
);
1993 // Wrap the Frag in a net buffer.
1995 *Packet
= NetbufFromExt (&Frag
, 1, 0, 0, DnsDummyExtFree
, NULL
);
1996 if (*Packet
== NULL
) {
1997 FreePool (Frag
.Bulk
);
1998 return EFI_OUT_OF_RESOURCES
;
2002 // Store the UdpIo in ProtoData.
2004 *((UINTN
*) &((*Packet
)->ProtoData
[0])) = (UINTN
) (Instance
->UdpIo
);
2010 Retransmit the packet.
2012 @param Instance The DNS instance
2013 @param Packet Retransmit the packet
2015 @retval EFI_SUCCESS The packet is retransmitted.
2016 @retval Others Failed to retransmit.
2021 IN DNS_INSTANCE
*Instance
,
2029 ASSERT (Packet
!= NULL
);
2032 // Set the requests to the listening port, other packets to the connected port
2034 Buffer
= NetbufGetByte (Packet
, 0, NULL
);
2035 ASSERT (Buffer
!= NULL
);
2037 NET_GET_REF (Packet
);
2039 Status
= UdpIoSendDatagram (
2048 if (EFI_ERROR (Status
)) {
2049 NET_PUT_REF (Packet
);
2056 The timer ticking function for the DNS services.
2058 @param Event The ticking event
2059 @param Context The DNS service instance
2064 DnsOnTimerRetransmit (
2069 DNS_SERVICE
*Service
;
2074 DNS_INSTANCE
*Instance
;
2075 LIST_ENTRY
*EntryNetMap
;
2076 NET_MAP_ITEM
*ItemNetMap
;
2077 DNS4_TOKEN_ENTRY
*Dns4TokenEntry
;
2078 DNS6_TOKEN_ENTRY
*Dns6TokenEntry
;
2080 Dns4TokenEntry
= NULL
;
2081 Dns6TokenEntry
= NULL
;
2083 Service
= (DNS_SERVICE
*) Context
;
2086 if (Service
->IpVersion
== IP_VERSION_4
) {
2088 // Iterate through all the children of the DNS service instance. Time
2089 // out the packet. If maximum retries reached, clean the Token up.
2091 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Service
->Dns4ChildrenList
) {
2092 Instance
= NET_LIST_USER_STRUCT (Entry
, DNS_INSTANCE
, Link
);
2094 EntryNetMap
= Instance
->Dns4TxTokens
.Used
.ForwardLink
;
2095 while (EntryNetMap
!= &Instance
->Dns4TxTokens
.Used
) {
2096 ItemNetMap
= NET_LIST_USER_STRUCT (EntryNetMap
, NET_MAP_ITEM
, Link
);
2097 Dns4TokenEntry
= (DNS4_TOKEN_ENTRY
*)(ItemNetMap
->Key
);
2098 if (Dns4TokenEntry
->PacketToLive
== 0 || (--Dns4TokenEntry
->PacketToLive
> 0)) {
2099 EntryNetMap
= EntryNetMap
->ForwardLink
;
2104 // Retransmit the packet if haven't reach the maxmium retry count,
2105 // otherwise exit the transfer.
2107 if (++Dns4TokenEntry
->RetryCounting
<= Dns4TokenEntry
->Token
->RetryCount
) {
2108 DnsRetransmit (Instance
, (NET_BUF
*)ItemNetMap
->Value
);
2109 EntryNetMap
= EntryNetMap
->ForwardLink
;
2112 // Maximum retries reached, clean the Token up.
2114 Dns4RemoveTokenEntry (&Instance
->Dns4TxTokens
, Dns4TokenEntry
);
2115 Dns4TokenEntry
->Token
->Status
= EFI_TIMEOUT
;
2116 gBS
->SignalEvent (Dns4TokenEntry
->Token
->Event
);
2120 // Free the sending packet.
2122 if (ItemNetMap
->Value
!= NULL
) {
2123 NetbufFree ((NET_BUF
*)(ItemNetMap
->Value
));
2126 EntryNetMap
= Instance
->Dns4TxTokens
.Used
.ForwardLink
;
2132 // Iterate through all the children of the DNS service instance. Time
2133 // out the packet. If maximum retries reached, clean the Token up.
2135 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Service
->Dns6ChildrenList
) {
2136 Instance
= NET_LIST_USER_STRUCT (Entry
, DNS_INSTANCE
, Link
);
2138 EntryNetMap
= Instance
->Dns6TxTokens
.Used
.ForwardLink
;
2139 while (EntryNetMap
!= &Instance
->Dns6TxTokens
.Used
) {
2140 ItemNetMap
= NET_LIST_USER_STRUCT (EntryNetMap
, NET_MAP_ITEM
, Link
);
2141 Dns6TokenEntry
= (DNS6_TOKEN_ENTRY
*) (ItemNetMap
->Key
);
2142 if (Dns6TokenEntry
->PacketToLive
== 0 || (--Dns6TokenEntry
->PacketToLive
> 0)) {
2143 EntryNetMap
= EntryNetMap
->ForwardLink
;
2148 // Retransmit the packet if haven't reach the maxmium retry count,
2149 // otherwise exit the transfer.
2151 if (++Dns6TokenEntry
->RetryCounting
<= Dns6TokenEntry
->Token
->RetryCount
) {
2152 DnsRetransmit (Instance
, (NET_BUF
*) ItemNetMap
->Value
);
2153 EntryNetMap
= EntryNetMap
->ForwardLink
;
2156 // Maximum retries reached, clean the Token up.
2158 Dns6RemoveTokenEntry (&Instance
->Dns6TxTokens
, Dns6TokenEntry
);
2159 Dns6TokenEntry
->Token
->Status
= EFI_TIMEOUT
;
2160 gBS
->SignalEvent (Dns6TokenEntry
->Token
->Event
);
2164 // Free the sending packet.
2166 if (ItemNetMap
->Value
!= NULL
) {
2167 NetbufFree ((NET_BUF
*) (ItemNetMap
->Value
));
2170 EntryNetMap
= Instance
->Dns6TxTokens
.Used
.ForwardLink
;
2178 The timer ticking function for the DNS driver.
2180 @param Event The ticking event
2200 // Iterate through all the DNS4 cache list.
2202 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &mDriverData
->Dns4CacheList
) {
2203 Item4
= NET_LIST_USER_STRUCT (Entry
, DNS4_CACHE
, AllCacheLink
);
2204 Item4
->DnsCache
.Timeout
--;
2207 Entry
= mDriverData
->Dns4CacheList
.ForwardLink
;
2208 while (Entry
!= &mDriverData
->Dns4CacheList
) {
2209 Item4
= NET_LIST_USER_STRUCT (Entry
, DNS4_CACHE
, AllCacheLink
);
2210 if (Item4
->DnsCache
.Timeout
== 0) {
2211 RemoveEntryList (&Item4
->AllCacheLink
);
2212 FreePool (Item4
->DnsCache
.HostName
);
2213 FreePool (Item4
->DnsCache
.IpAddress
);
2215 Entry
= mDriverData
->Dns4CacheList
.ForwardLink
;
2217 Entry
= Entry
->ForwardLink
;
2222 // Iterate through all the DNS6 cache list.
2224 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &mDriverData
->Dns6CacheList
) {
2225 Item6
= NET_LIST_USER_STRUCT (Entry
, DNS6_CACHE
, AllCacheLink
);
2226 Item6
->DnsCache
.Timeout
--;
2229 Entry
= mDriverData
->Dns6CacheList
.ForwardLink
;
2230 while (Entry
!= &mDriverData
->Dns6CacheList
) {
2231 Item6
= NET_LIST_USER_STRUCT (Entry
, DNS6_CACHE
, AllCacheLink
);
2232 if (Item6
->DnsCache
.Timeout
== 0) {
2233 RemoveEntryList (&Item6
->AllCacheLink
);
2234 FreePool (Item6
->DnsCache
.HostName
);
2235 FreePool (Item6
->DnsCache
.IpAddress
);
2237 Entry
= mDriverData
->Dns6CacheList
.ForwardLink
;
2239 Entry
= Entry
->ForwardLink
;