2 DnsDxe support functions implementation.
4 Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Remove TokenEntry from TokenMap.
20 @param[in] TokenMap All DNSv4 Token entrys.
21 @param[in] TokenEntry TokenEntry need to be removed.
23 @retval EFI_SUCCESS Remove TokenEntry from TokenMap sucessfully.
24 @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap.
28 Dns4RemoveTokenEntry (
30 IN DNS4_TOKEN_ENTRY
*TokenEntry
36 // Find the TokenEntry first.
38 Item
= NetMapFindKey (TokenMap
, (VOID
*) TokenEntry
);
42 // Remove the TokenEntry if it's found in the map.
44 NetMapRemoveItem (TokenMap
, Item
, NULL
);
53 Remove TokenEntry from TokenMap.
55 @param[in] TokenMap All DNSv6 Token entrys.
56 @param[in] TokenEntry TokenEntry need to be removed.
58 @retval EFI_SUCCESS Remove TokenEntry from TokenMap sucessfully.
59 @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap.
63 Dns6RemoveTokenEntry (
65 IN DNS6_TOKEN_ENTRY
*TokenEntry
71 // Find the TokenEntry first.
73 Item
= NetMapFindKey (TokenMap
, (VOID
*) TokenEntry
);
77 // Remove the TokenEntry if it's found in the map.
79 NetMapRemoveItem (TokenMap
, Item
, NULL
);
88 This function cancle the token specified by Arg in the Map.
90 @param[in] Map Pointer to the NET_MAP.
91 @param[in] Item Pointer to the NET_MAP_ITEM.
92 @param[in] Arg Pointer to the token to be cancelled. If NULL, all
93 the tokens in this Map will be cancelled.
94 This parameter is optional and may be NULL.
96 @retval EFI_SUCCESS The token is cancelled if Arg is NULL, or the token
97 is not the same as that in the Item, if Arg is not
99 @retval EFI_ABORTED Arg is not NULL, and the token specified by Arg is
107 IN NET_MAP_ITEM
*Item
,
108 IN VOID
*Arg OPTIONAL
111 DNS4_TOKEN_ENTRY
*TokenEntry
;
115 if ((Arg
!= NULL
) && (Item
->Key
!= Arg
)) {
119 if (Item
->Value
!= NULL
) {
121 // If the TokenEntry is a transmit TokenEntry, the corresponding Packet is recorded in
124 Packet
= (NET_BUF
*) (Item
->Value
);
125 UdpIo
= (UDP_IO
*) (*((UINTN
*) &Packet
->ProtoData
[0]));
127 UdpIoCancelSentDatagram (UdpIo
, Packet
);
131 // Remove TokenEntry from Dns4TxTokens.
133 TokenEntry
= (DNS4_TOKEN_ENTRY
*) Item
->Key
;
134 if (Dns4RemoveTokenEntry (Map
, TokenEntry
) == EFI_SUCCESS
) {
135 TokenEntry
->Token
->Status
= EFI_ABORTED
;
136 gBS
->SignalEvent (TokenEntry
->Token
->Event
);
148 This function cancle the token specified by Arg in the Map.
150 @param[in] Map Pointer to the NET_MAP.
151 @param[in] Item Pointer to the NET_MAP_ITEM.
152 @param[in] Arg Pointer to the token to be cancelled. If NULL, all
153 the tokens in this Map will be cancelled.
154 This parameter is optional and may be NULL.
156 @retval EFI_SUCCESS The token is cancelled if Arg is NULL, or the token
157 is not the same as that in the Item, if Arg is not
159 @retval EFI_ABORTED Arg is not NULL, and the token specified by Arg is
167 IN NET_MAP_ITEM
*Item
,
168 IN VOID
*Arg OPTIONAL
171 DNS6_TOKEN_ENTRY
*TokenEntry
;
175 if ((Arg
!= NULL
) && (Item
->Key
!= Arg
)) {
179 if (Item
->Value
!= NULL
) {
181 // If the TokenEntry is a transmit TokenEntry, the corresponding Packet is recorded in
184 Packet
= (NET_BUF
*) (Item
->Value
);
185 UdpIo
= (UDP_IO
*) (*((UINTN
*) &Packet
->ProtoData
[0]));
187 UdpIoCancelSentDatagram (UdpIo
, Packet
);
191 // Remove TokenEntry from Dns6TxTokens.
193 TokenEntry
= (DNS6_TOKEN_ENTRY
*) Item
->Key
;
194 if (Dns6RemoveTokenEntry (Map
, TokenEntry
) == EFI_SUCCESS
) {
195 TokenEntry
->Token
->Status
= EFI_ABORTED
;
196 gBS
->SignalEvent (TokenEntry
->Token
->Event
);
208 Get the TokenEntry from the TokensMap.
210 @param[in] TokensMap All DNSv4 Token entrys
211 @param[in] Token Pointer to the token to be get.
212 @param[out] TokenEntry Pointer to TokenEntry corresponding Token.
214 @retval EFI_SUCCESS Get the TokenEntry from the TokensMap sucessfully.
215 @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap.
221 IN NET_MAP
*TokensMap
,
222 IN EFI_DNS4_COMPLETION_TOKEN
*Token
,
223 OUT DNS4_TOKEN_ENTRY
**TokenEntry
230 NET_LIST_FOR_EACH (Entry
, &TokensMap
->Used
) {
231 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
232 *TokenEntry
= (DNS4_TOKEN_ENTRY
*) (Item
->Key
);
233 if ((*TokenEntry
)->Token
== Token
) {
240 return EFI_NOT_FOUND
;
244 Get the TokenEntry from the TokensMap.
246 @param[in] TokensMap All DNSv6 Token entrys
247 @param[in] Token Pointer to the token to be get.
248 @param[out] TokenEntry Pointer to TokenEntry corresponding Token.
250 @retval EFI_SUCCESS Get the TokenEntry from the TokensMap sucessfully.
251 @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap.
257 IN NET_MAP
*TokensMap
,
258 IN EFI_DNS6_COMPLETION_TOKEN
*Token
,
259 OUT DNS6_TOKEN_ENTRY
**TokenEntry
266 NET_LIST_FOR_EACH (Entry
, &TokensMap
->Used
) {
267 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
268 *TokenEntry
= (DNS6_TOKEN_ENTRY
*) (Item
->Key
);
269 if ((*TokenEntry
)->Token
== Token
) {
276 return EFI_NOT_FOUND
;
280 Cancel DNS4 tokens from the DNS4 instance.
282 @param[in] Instance Pointer to the DNS instance context data.
283 @param[in] Token Pointer to the token to be canceled. If NULL, all
284 tokens in this instance will be cancelled.
285 This parameter is optional and may be NULL.
287 @retval EFI_SUCCESS The Token is cancelled.
288 @retval EFI_NOT_FOUND The Token is not found.
292 Dns4InstanceCancelToken (
293 IN DNS_INSTANCE
*Instance
,
294 IN EFI_DNS4_COMPLETION_TOKEN
*Token
298 DNS4_TOKEN_ENTRY
*TokenEntry
;
303 Status
= GetDns4TokenEntry (&Instance
->Dns4TxTokens
, Token
, &TokenEntry
);
304 if (EFI_ERROR (Status
)) {
312 // Cancel this TokenEntry from the Dns4TxTokens map.
314 Status
= NetMapIterate (&Instance
->Dns4TxTokens
, Dns4CancelTokens
, TokenEntry
);
316 if ((TokenEntry
!= NULL
) && (Status
== EFI_ABORTED
)) {
318 // If Token isn't NULL and Status is EFI_ABORTED, the token is cancelled from
319 // the Dns4TxTokens and returns success.
321 if (NetMapIsEmpty (&Instance
->Dns4TxTokens
)) {
322 Instance
->UdpIo
->Protocol
.Udp4
->Cancel (Instance
->UdpIo
->Protocol
.Udp4
, &Instance
->UdpIo
->RecvRequest
->Token
.Udp4
);
327 ASSERT ((TokenEntry
!= NULL
) || (0 == NetMapGetCount (&Instance
->Dns4TxTokens
)));
329 if (NetMapIsEmpty (&Instance
->Dns4TxTokens
)) {
330 Instance
->UdpIo
->Protocol
.Udp4
->Cancel (Instance
->UdpIo
->Protocol
.Udp4
, &Instance
->UdpIo
->RecvRequest
->Token
.Udp4
);
337 Cancel DNS6 tokens from the DNS6 instance.
339 @param[in] Instance Pointer to the DNS instance context data.
340 @param[in] Token Pointer to the token to be canceled. If NULL, all
341 tokens in this instance will be cancelled.
342 This parameter is optional and may be NULL.
344 @retval EFI_SUCCESS The Token is cancelled.
345 @retval EFI_NOT_FOUND The Token is not found.
349 Dns6InstanceCancelToken (
350 IN DNS_INSTANCE
*Instance
,
351 IN EFI_DNS6_COMPLETION_TOKEN
*Token
355 DNS6_TOKEN_ENTRY
*TokenEntry
;
360 Status
= GetDns6TokenEntry (&Instance
->Dns6TxTokens
, Token
, &TokenEntry
);
361 if (EFI_ERROR (Status
)) {
369 // Cancel this TokenEntry from the Dns6TxTokens map.
371 Status
= NetMapIterate (&Instance
->Dns6TxTokens
, Dns6CancelTokens
, TokenEntry
);
373 if ((TokenEntry
!= NULL
) && (Status
== EFI_ABORTED
)) {
375 // If Token isn't NULL and Status is EFI_ABORTED, the token is cancelled from
376 // the Dns6TxTokens and returns success.
378 if (NetMapIsEmpty (&Instance
->Dns6TxTokens
)) {
379 Instance
->UdpIo
->Protocol
.Udp6
->Cancel (Instance
->UdpIo
->Protocol
.Udp6
, &Instance
->UdpIo
->RecvRequest
->Token
.Udp6
);
384 ASSERT ((TokenEntry
!= NULL
) || (0 == NetMapGetCount (&Instance
->Dns6TxTokens
)));
386 if (NetMapIsEmpty (&Instance
->Dns6TxTokens
)) {
387 Instance
->UdpIo
->Protocol
.Udp6
->Cancel (Instance
->UdpIo
->Protocol
.Udp6
, &Instance
->UdpIo
->RecvRequest
->Token
.Udp6
);
394 Free the resource related to the configure parameters.
396 @param Config The DNS configure data
401 IN OUT EFI_DNS4_CONFIG_DATA
*Config
404 if (Config
->DnsServerList
!= NULL
) {
405 FreePool (Config
->DnsServerList
);
408 ZeroMem (Config
, sizeof (EFI_DNS4_CONFIG_DATA
));
412 Free the resource related to the configure parameters.
414 @param Config The DNS configure data
419 IN OUT EFI_DNS6_CONFIG_DATA
*Config
422 if (Config
->DnsServerList
!= NULL
) {
423 FreePool (Config
->DnsServerList
);
426 ZeroMem (Config
, sizeof (EFI_DNS6_CONFIG_DATA
));
430 Allocate memory for configure parameter such as timeout value for Dst,
431 then copy the configure parameter from Src to Dst.
433 @param[out] Dst The destination DHCP configure data.
434 @param[in] Src The source DHCP configure data.
436 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
437 @retval EFI_SUCCESS The configure is copied.
442 OUT EFI_DNS4_CONFIG_DATA
*Dst
,
443 IN EFI_DNS4_CONFIG_DATA
*Src
449 CopyMem (Dst
, Src
, sizeof (*Dst
));
450 Dst
->DnsServerList
= NULL
;
453 // Allocate a memory then copy DnsServerList to it
455 if (Src
->DnsServerList
!= NULL
) {
456 Len
= Src
->DnsServerListCount
* sizeof (EFI_IPv4_ADDRESS
);
457 Dst
->DnsServerList
= AllocatePool (Len
);
458 if (Dst
->DnsServerList
== NULL
) {
459 Dns4CleanConfigure (Dst
);
460 return EFI_OUT_OF_RESOURCES
;
463 for (Index
= 0; Index
< Src
->DnsServerListCount
; Index
++) {
464 CopyMem (&Dst
->DnsServerList
[Index
], &Src
->DnsServerList
[Index
], sizeof (EFI_IPv4_ADDRESS
));
472 Allocate memory for configure parameter such as timeout value for Dst,
473 then copy the configure parameter from Src to Dst.
475 @param[out] Dst The destination DHCP configure data.
476 @param[in] Src The source DHCP configure data.
478 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
479 @retval EFI_SUCCESS The configure is copied.
484 OUT EFI_DNS6_CONFIG_DATA
*Dst
,
485 IN EFI_DNS6_CONFIG_DATA
*Src
491 CopyMem (Dst
, Src
, sizeof (*Dst
));
492 Dst
->DnsServerList
= NULL
;
495 // Allocate a memory then copy DnsServerList to it
497 if (Src
->DnsServerList
!= NULL
) {
498 Len
= Src
->DnsServerCount
* sizeof (EFI_IPv6_ADDRESS
);
499 Dst
->DnsServerList
= AllocatePool (Len
);
500 if (Dst
->DnsServerList
== NULL
) {
501 Dns6CleanConfigure (Dst
);
502 return EFI_OUT_OF_RESOURCES
;
505 for (Index
= 0; Index
< Src
->DnsServerCount
; Index
++) {
506 CopyMem (&Dst
->DnsServerList
[Index
], &Src
->DnsServerList
[Index
], sizeof (EFI_IPv6_ADDRESS
));
514 Callback of Dns packet. Does nothing.
516 @param Arg The context.
528 Poll the UDP to get the IP4 default address, which may be retrieved
531 The default time out value is 5 seconds. If IP has retrieved the default address,
532 the UDP is reconfigured.
534 @param Instance The DNS instance
535 @param UdpIo The UDP_IO to poll
536 @param UdpCfgData The UDP configure data to reconfigure the UDP_IO
538 @retval TRUE The default address is retrieved and UDP is reconfigured.
539 @retval FALSE Some error occured.
544 IN DNS_INSTANCE
*Instance
,
546 IN EFI_UDP4_CONFIG_DATA
*UdpCfgData
549 DNS_SERVICE
*Service
;
550 EFI_IP4_MODE_DATA Ip4Mode
;
551 EFI_UDP4_PROTOCOL
*Udp
;
554 ASSERT (Instance
->Dns4CfgData
.UseDefaultSetting
);
556 Service
= Instance
->Service
;
557 Udp
= UdpIo
->Protocol
.Udp4
;
559 Status
= gBS
->SetTimer (
560 Service
->TimerToGetMap
,
562 DNS_TIME_TO_GETMAP
* TICKS_PER_SECOND
564 if (EFI_ERROR (Status
)) {
568 while (EFI_ERROR (gBS
->CheckEvent (Service
->TimerToGetMap
))) {
571 if (!EFI_ERROR (Udp
->GetModeData (Udp
, NULL
, &Ip4Mode
, NULL
, NULL
)) &&
572 Ip4Mode
.IsConfigured
) {
574 Udp
->Configure (Udp
, NULL
);
575 return (BOOLEAN
) (Udp
->Configure (Udp
, UdpCfgData
) == EFI_SUCCESS
);
583 Configure the opened Udp6 instance until the corresponding Ip6 instance
586 @param Instance The DNS instance
587 @param UdpIo The UDP_IO to poll
588 @param UdpCfgData The UDP configure data to reconfigure the UDP_IO
590 @retval TRUE Configure the Udp6 instance successfully.
591 @retval FALSE Some error occured.
596 IN DNS_INSTANCE
*Instance
,
598 IN EFI_UDP6_CONFIG_DATA
*UdpCfgData
601 DNS_SERVICE
*Service
;
602 EFI_IP6_MODE_DATA Ip6Mode
;
603 EFI_UDP6_PROTOCOL
*Udp
;
606 Service
= Instance
->Service
;
607 Udp
= UdpIo
->Protocol
.Udp6
;
609 Status
= gBS
->SetTimer (
610 Service
->TimerToGetMap
,
612 DNS_TIME_TO_GETMAP
* TICKS_PER_SECOND
614 if (EFI_ERROR (Status
)) {
618 while (EFI_ERROR (gBS
->CheckEvent (Service
->TimerToGetMap
))) {
621 if (!EFI_ERROR (Udp
->GetModeData (Udp
, NULL
, &Ip6Mode
, NULL
, NULL
))) {
622 if (Ip6Mode
.AddressList
!= NULL
) {
623 FreePool (Ip6Mode
.AddressList
);
626 if (Ip6Mode
.GroupTable
!= NULL
) {
627 FreePool (Ip6Mode
.GroupTable
);
630 if (Ip6Mode
.RouteTable
!= NULL
) {
631 FreePool (Ip6Mode
.RouteTable
);
634 if (Ip6Mode
.NeighborCache
!= NULL
) {
635 FreePool (Ip6Mode
.NeighborCache
);
638 if (Ip6Mode
.PrefixTable
!= NULL
) {
639 FreePool (Ip6Mode
.PrefixTable
);
642 if (Ip6Mode
.IcmpTypeList
!= NULL
) {
643 FreePool (Ip6Mode
.IcmpTypeList
);
646 if (!Ip6Mode
.IsStarted
|| Ip6Mode
.IsConfigured
) {
647 Udp
->Configure (Udp
, NULL
);
648 if (Udp
->Configure (Udp
, UdpCfgData
) == EFI_SUCCESS
) {
661 @param Instance The DNS session
662 @param UdpIo The UDP_IO instance
664 @retval EFI_SUCCESS The UDP is successfully configured for the
670 IN DNS_INSTANCE
*Instance
,
674 EFI_DNS4_CONFIG_DATA
*Config
;
675 EFI_UDP4_CONFIG_DATA UdpConfig
;
678 Config
= &Instance
->Dns4CfgData
;
680 UdpConfig
.AcceptBroadcast
= FALSE
;
681 UdpConfig
.AcceptPromiscuous
= FALSE
;
682 UdpConfig
.AcceptAnyPort
= FALSE
;
683 UdpConfig
.AllowDuplicatePort
= FALSE
;
684 UdpConfig
.TypeOfService
= 0;
685 UdpConfig
.TimeToLive
= 128;
686 UdpConfig
.DoNotFragment
= FALSE
;
687 UdpConfig
.ReceiveTimeout
= 0;
688 UdpConfig
.TransmitTimeout
= 0;
689 UdpConfig
.UseDefaultAddress
= Config
->UseDefaultSetting
;
690 UdpConfig
.SubnetMask
= Config
->SubnetMask
;
691 UdpConfig
.StationPort
= Config
->LocalPort
;
692 UdpConfig
.RemotePort
= DNS_SERVER_PORT
;
694 CopyMem (&UdpConfig
.StationAddress
, &Config
->StationIp
, sizeof (EFI_IPv4_ADDRESS
));
695 CopyMem (&UdpConfig
.RemoteAddress
, &Instance
->SessionDnsServer
.v4
, sizeof (EFI_IPv4_ADDRESS
));
697 Status
= UdpIo
->Protocol
.Udp4
->Configure (UdpIo
->Protocol
.Udp4
, &UdpConfig
);
699 if ((Status
== EFI_NO_MAPPING
) && Dns4GetMapping (Instance
, UdpIo
, &UdpConfig
)) {
709 @param Instance The DNS session
710 @param UdpIo The UDP_IO instance
712 @retval EFI_SUCCESS The UDP is successfully configured for the
718 IN DNS_INSTANCE
*Instance
,
722 EFI_DNS6_CONFIG_DATA
*Config
;
723 EFI_UDP6_CONFIG_DATA UdpConfig
;
726 Config
= &Instance
->Dns6CfgData
;
728 UdpConfig
.AcceptPromiscuous
= FALSE
;
729 UdpConfig
.AcceptAnyPort
= FALSE
;
730 UdpConfig
.AllowDuplicatePort
= FALSE
;
731 UdpConfig
.TrafficClass
= 0;
732 UdpConfig
.HopLimit
= 128;
733 UdpConfig
.ReceiveTimeout
= 0;
734 UdpConfig
.TransmitTimeout
= 0;
735 UdpConfig
.StationPort
= Config
->LocalPort
;
736 UdpConfig
.RemotePort
= DNS_SERVER_PORT
;
737 CopyMem (&UdpConfig
.StationAddress
, &Config
->StationIp
, sizeof (EFI_IPv6_ADDRESS
));
738 CopyMem (&UdpConfig
.RemoteAddress
, &Instance
->SessionDnsServer
.v6
, sizeof (EFI_IPv6_ADDRESS
));
740 Status
= UdpIo
->Protocol
.Udp6
->Configure (UdpIo
->Protocol
.Udp6
, &UdpConfig
);
742 if ((Status
== EFI_NO_MAPPING
) && Dns6GetMapping (Instance
, UdpIo
, &UdpConfig
)) {
750 Update Dns4 cache to shared list of caches of all DNSv4 instances.
752 @param Dns4CacheList All Dns4 cache list.
753 @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache.
754 If TRUE, this function will delete matching DNS Cache entry.
755 @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
756 If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
757 @param DnsCacheEntry Entry Pointer to DNS Cache entry.
759 @retval EFI_SUCCESS Update Dns4 cache successfully.
760 @retval Others Failed to update Dns4 cache.
766 IN LIST_ENTRY
*Dns4CacheList
,
767 IN BOOLEAN DeleteFlag
,
769 IN EFI_DNS4_CACHE_ENTRY DnsCacheEntry
772 DNS4_CACHE
*NewDnsCache
;
781 // Search the database for the matching EFI_DNS_CACHE_ENTRY
783 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Dns4CacheList
) {
784 Item
= NET_LIST_USER_STRUCT (Entry
, DNS4_CACHE
, AllCacheLink
);
785 if (StrCmp (DnsCacheEntry
.HostName
, Item
->DnsCache
.HostName
) == 0 && \
786 CompareMem (DnsCacheEntry
.IpAddress
, Item
->DnsCache
.IpAddress
, sizeof (EFI_IPv4_ADDRESS
)) == 0) {
788 // This is the Dns cache entry
792 // Delete matching DNS Cache entry
794 RemoveEntryList (&Item
->AllCacheLink
);
796 FreePool (Item
->DnsCache
.HostName
);
797 FreePool (Item
->DnsCache
.IpAddress
);
801 } else if (Override
) {
805 Item
->DnsCache
.Timeout
= DnsCacheEntry
.Timeout
;
809 return EFI_ACCESS_DENIED
;
817 NewDnsCache
= AllocatePool (sizeof (DNS4_CACHE
));
818 if (NewDnsCache
== NULL
) {
819 return EFI_OUT_OF_RESOURCES
;
822 InitializeListHead (&NewDnsCache
->AllCacheLink
);
824 NewDnsCache
->DnsCache
.HostName
= AllocatePool (StrSize (DnsCacheEntry
.HostName
));
825 if (NewDnsCache
->DnsCache
.HostName
== NULL
) {
826 FreePool (NewDnsCache
);
827 return EFI_OUT_OF_RESOURCES
;
830 CopyMem (NewDnsCache
->DnsCache
.HostName
, DnsCacheEntry
.HostName
, StrSize (DnsCacheEntry
.HostName
));
832 NewDnsCache
->DnsCache
.IpAddress
= AllocatePool (sizeof (EFI_IPv4_ADDRESS
));
833 if (NewDnsCache
->DnsCache
.IpAddress
== NULL
) {
834 FreePool (NewDnsCache
->DnsCache
.HostName
);
835 FreePool (NewDnsCache
);
836 return EFI_OUT_OF_RESOURCES
;
839 CopyMem (NewDnsCache
->DnsCache
.IpAddress
, DnsCacheEntry
.IpAddress
, sizeof (EFI_IPv4_ADDRESS
));
841 NewDnsCache
->DnsCache
.Timeout
= DnsCacheEntry
.Timeout
;
843 InsertTailList (Dns4CacheList
, &NewDnsCache
->AllCacheLink
);
849 Update Dns6 cache to shared list of caches of all DNSv6 instances.
851 @param Dns6CacheList All Dns6 cache list.
852 @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache.
853 If TRUE, this function will delete matching DNS Cache entry.
854 @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
855 If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
856 @param DnsCacheEntry Entry Pointer to DNS Cache entry.
858 @retval EFI_SUCCESS Update Dns6 cache successfully.
859 @retval Others Failed to update Dns6 cache.
864 IN LIST_ENTRY
*Dns6CacheList
,
865 IN BOOLEAN DeleteFlag
,
867 IN EFI_DNS6_CACHE_ENTRY DnsCacheEntry
870 DNS6_CACHE
*NewDnsCache
;
879 // Search the database for the matching EFI_DNS_CACHE_ENTRY
881 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Dns6CacheList
) {
882 Item
= NET_LIST_USER_STRUCT (Entry
, DNS6_CACHE
, AllCacheLink
);
883 if (StrCmp (DnsCacheEntry
.HostName
, Item
->DnsCache
.HostName
) == 0 && \
884 CompareMem (DnsCacheEntry
.IpAddress
, Item
->DnsCache
.IpAddress
, sizeof (EFI_IPv6_ADDRESS
)) == 0) {
886 // This is the Dns cache entry
890 // Delete matching DNS Cache entry
892 RemoveEntryList (&Item
->AllCacheLink
);
894 FreePool (Item
->DnsCache
.HostName
);
895 FreePool (Item
->DnsCache
.IpAddress
);
899 } else if (Override
) {
903 Item
->DnsCache
.Timeout
= DnsCacheEntry
.Timeout
;
907 return EFI_ACCESS_DENIED
;
915 NewDnsCache
= AllocatePool (sizeof (DNS6_CACHE
));
916 if (NewDnsCache
== NULL
) {
917 return EFI_OUT_OF_RESOURCES
;
920 InitializeListHead (&NewDnsCache
->AllCacheLink
);
922 NewDnsCache
->DnsCache
.HostName
= AllocatePool (StrSize (DnsCacheEntry
.HostName
));
923 if (NewDnsCache
->DnsCache
.HostName
== NULL
) {
924 FreePool (NewDnsCache
);
925 return EFI_OUT_OF_RESOURCES
;
928 CopyMem (NewDnsCache
->DnsCache
.HostName
, DnsCacheEntry
.HostName
, StrSize (DnsCacheEntry
.HostName
));
930 NewDnsCache
->DnsCache
.IpAddress
= AllocatePool (sizeof (EFI_IPv6_ADDRESS
));
931 if (NewDnsCache
->DnsCache
.IpAddress
== NULL
) {
932 FreePool (NewDnsCache
->DnsCache
.HostName
);
933 FreePool (NewDnsCache
);
934 return EFI_OUT_OF_RESOURCES
;
937 CopyMem (NewDnsCache
->DnsCache
.IpAddress
, DnsCacheEntry
.IpAddress
, sizeof (EFI_IPv6_ADDRESS
));
939 NewDnsCache
->DnsCache
.Timeout
= DnsCacheEntry
.Timeout
;
941 InsertTailList (Dns6CacheList
, &NewDnsCache
->AllCacheLink
);
947 Add Dns4 ServerIp to common list of addresses of all configured DNSv4 server.
949 @param Dns4ServerList Common list of addresses of all configured DNSv4 server.
950 @param ServerIp DNS server Ip.
952 @retval EFI_SUCCESS Add Dns4 ServerIp to common list successfully.
953 @retval Others Failed to add Dns4 ServerIp to common list.
959 IN LIST_ENTRY
*Dns4ServerList
,
960 IN EFI_IPv4_ADDRESS ServerIp
963 DNS4_SERVER_IP
*NewServerIp
;
964 DNS4_SERVER_IP
*Item
;
972 // Search the database for the matching ServerIp
974 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Dns4ServerList
) {
975 Item
= NET_LIST_USER_STRUCT (Entry
, DNS4_SERVER_IP
, AllServerLink
);
976 if (CompareMem (&Item
->Dns4ServerIp
, &ServerIp
, sizeof (EFI_IPv4_ADDRESS
)) == 0) {
987 NewServerIp
= AllocatePool (sizeof (DNS4_SERVER_IP
));
988 if (NewServerIp
== NULL
) {
989 return EFI_OUT_OF_RESOURCES
;
992 InitializeListHead (&NewServerIp
->AllServerLink
);
994 CopyMem (&NewServerIp
->Dns4ServerIp
, &ServerIp
, sizeof (EFI_IPv4_ADDRESS
));
996 InsertTailList (Dns4ServerList
, &NewServerIp
->AllServerLink
);
1002 Add Dns6 ServerIp to common list of addresses of all configured DNSv6 server.
1004 @param Dns6ServerList Common list of addresses of all configured DNSv6 server.
1005 @param ServerIp DNS server Ip.
1007 @retval EFI_SUCCESS Add Dns6 ServerIp to common list successfully.
1008 @retval Others Failed to add Dns6 ServerIp to common list.
1014 IN LIST_ENTRY
*Dns6ServerList
,
1015 IN EFI_IPv6_ADDRESS ServerIp
1018 DNS6_SERVER_IP
*NewServerIp
;
1019 DNS6_SERVER_IP
*Item
;
1027 // Search the database for the matching ServerIp
1029 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Dns6ServerList
) {
1030 Item
= NET_LIST_USER_STRUCT (Entry
, DNS6_SERVER_IP
, AllServerLink
);
1031 if (CompareMem (&Item
->Dns6ServerIp
, &ServerIp
, sizeof (EFI_IPv6_ADDRESS
)) == 0) {
1042 NewServerIp
= AllocatePool (sizeof (DNS6_SERVER_IP
));
1043 if (NewServerIp
== NULL
) {
1044 return EFI_OUT_OF_RESOURCES
;
1047 InitializeListHead (&NewServerIp
->AllServerLink
);
1049 CopyMem (&NewServerIp
->Dns6ServerIp
, &ServerIp
, sizeof (EFI_IPv6_ADDRESS
));
1051 InsertTailList (Dns6ServerList
, &NewServerIp
->AllServerLink
);
1057 Find out whether the response is valid or invalid.
1059 @param TokensMap All DNS transmittal Tokens entry.
1060 @param Identification Identification for queried packet.
1061 @param Type Type for queried packet.
1062 @param Class Class for queried packet.
1063 @param Item Return corresponding Token entry.
1065 @retval TRUE The response is valid.
1066 @retval FALSE The response is invalid.
1070 IsValidDnsResponse (
1071 IN NET_MAP
*TokensMap
,
1072 IN UINT16 Identification
,
1075 OUT NET_MAP_ITEM
**Item
1082 DNS_HEADER
*DnsHeader
;
1084 DNS_QUERY_SECTION
*QuerySection
;
1086 NET_LIST_FOR_EACH (Entry
, &TokensMap
->Used
) {
1087 *Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
1088 Packet
= (NET_BUF
*) ((*Item
)->Value
);
1089 if (Packet
== NULL
){
1093 TxString
= NetbufGetByte (Packet
, 0, NULL
);
1094 ASSERT (TxString
!= NULL
);
1095 DnsHeader
= (DNS_HEADER
*) TxString
;
1096 QueryName
= (CHAR8
*) (TxString
+ sizeof (*DnsHeader
));
1097 QuerySection
= (DNS_QUERY_SECTION
*) (QueryName
+ AsciiStrLen (QueryName
) + 1);
1099 if (NTOHS (DnsHeader
->Identification
) == Identification
&&
1100 NTOHS (QuerySection
->Type
) == Type
&&
1101 NTOHS (QuerySection
->Class
) == Class
) {
1115 @param Instance The DNS instance
1116 @param RxString Received buffer.
1117 @param Completed Flag to indicate that Dns response is valid.
1119 @retval EFI_SUCCESS Parse Dns Response successfully.
1120 @retval Others Failed to parse Dns Response.
1125 IN OUT DNS_INSTANCE
*Instance
,
1127 OUT BOOLEAN
*Completed
1130 DNS_HEADER
*DnsHeader
;
1133 DNS_QUERY_SECTION
*QuerySection
;
1136 DNS_ANSWER_SECTION
*AnswerSection
;
1140 DNS4_TOKEN_ENTRY
*Dns4TokenEntry
;
1141 DNS6_TOKEN_ENTRY
*Dns6TokenEntry
;
1145 UINT32 AnswerSectionNum
;
1148 EFI_IPv4_ADDRESS
*HostAddr4
;
1149 EFI_IPv6_ADDRESS
*HostAddr6
;
1151 EFI_DNS4_CACHE_ENTRY
*Dns4CacheEntry
;
1152 EFI_DNS6_CACHE_ENTRY
*Dns6CacheEntry
;
1154 DNS_RESOURCE_RECORD
*Dns4RR
;
1155 DNS6_RESOURCE_RECORD
*Dns6RR
;
1162 Dns4TokenEntry
= NULL
;
1163 Dns6TokenEntry
= NULL
;
1167 AnswerSectionNum
= 0;
1173 Dns4CacheEntry
= NULL
;
1174 Dns6CacheEntry
= NULL
;
1180 Status
= EFI_SUCCESS
;
1185 DnsHeader
= (DNS_HEADER
*) RxString
;
1187 DnsHeader
->Identification
= NTOHS (DnsHeader
->Identification
);
1188 DnsHeader
->Flags
.Uint16
= NTOHS (DnsHeader
->Flags
.Uint16
);
1189 DnsHeader
->QuestionsNum
= NTOHS (DnsHeader
->QuestionsNum
);
1190 DnsHeader
->AnswersNum
= NTOHS (DnsHeader
->AnswersNum
);
1191 DnsHeader
->AuthorityNum
= NTOHS (DnsHeader
->AuthorityNum
);
1192 DnsHeader
->AditionalNum
= NTOHS (DnsHeader
->AditionalNum
);
1197 QueryName
= (CHAR8
*) (RxString
+ sizeof (*DnsHeader
));
1200 // Get query section
1202 QuerySection
= (DNS_QUERY_SECTION
*) (QueryName
+ AsciiStrLen (QueryName
) + 1);
1203 QuerySection
->Type
= NTOHS (QuerySection
->Type
);
1204 QuerySection
->Class
= NTOHS (QuerySection
->Class
);
1209 AnswerName
= (CHAR8
*) QuerySection
+ sizeof (*QuerySection
);
1211 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1214 // Check DnsResponse Validity, if so, also get a valid NET_MAP_ITEM.
1216 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1217 if (!IsValidDnsResponse (
1218 &Instance
->Dns4TxTokens
,
1219 DnsHeader
->Identification
,
1221 QuerySection
->Class
,
1225 Status
= EFI_ABORTED
;
1228 ASSERT (Item
!= NULL
);
1229 Dns4TokenEntry
= (DNS4_TOKEN_ENTRY
*) (Item
->Key
);
1231 if (!IsValidDnsResponse (
1232 &Instance
->Dns6TxTokens
,
1233 DnsHeader
->Identification
,
1235 QuerySection
->Class
,
1239 Status
= EFI_ABORTED
;
1242 ASSERT (Item
!= NULL
);
1243 Dns6TokenEntry
= (DNS6_TOKEN_ENTRY
*) (Item
->Key
);
1247 // Continue Check Some Errors.
1249 if (DnsHeader
->Flags
.Bits
.RCode
!= DNS_FLAGS_RCODE_NO_ERROR
|| DnsHeader
->AnswersNum
< 1 || \
1250 DnsHeader
->Flags
.Bits
.QR
!= DNS_FLAGS_QR_RESPONSE
) {
1252 // The domain name referenced in the query does not exist.
1254 if (DnsHeader
->Flags
.Bits
.RCode
== DNS_FLAGS_RCODE_NAME_ERROR
) {
1255 Status
= EFI_NOT_FOUND
;
1257 Status
= EFI_DEVICE_ERROR
;
1264 // Do some buffer allocations.
1266 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1267 ASSERT (Dns4TokenEntry
!= NULL
);
1269 if (Dns4TokenEntry
->GeneralLookUp
) {
1271 // It's the GeneralLookUp querying.
1273 Dns4TokenEntry
->Token
->RspData
.GLookupData
= AllocateZeroPool (sizeof (DNS_RESOURCE_RECORD
));
1274 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
== NULL
) {
1275 Status
= EFI_OUT_OF_RESOURCES
;
1278 Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
= AllocateZeroPool (DnsHeader
->AnswersNum
* sizeof (DNS_RESOURCE_RECORD
));
1279 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
== NULL
) {
1280 Status
= EFI_OUT_OF_RESOURCES
;
1285 // It's not the GeneralLookUp querying. Check the Query type.
1287 if (QuerySection
->Type
== DNS_TYPE_A
) {
1288 Dns4TokenEntry
->Token
->RspData
.H2AData
= AllocateZeroPool (sizeof (DNS_HOST_TO_ADDR_DATA
));
1289 if (Dns4TokenEntry
->Token
->RspData
.H2AData
== NULL
) {
1290 Status
= EFI_OUT_OF_RESOURCES
;
1293 Dns4TokenEntry
->Token
->RspData
.H2AData
->IpList
= AllocateZeroPool (DnsHeader
->AnswersNum
* sizeof (EFI_IPv4_ADDRESS
));
1294 if (Dns4TokenEntry
->Token
->RspData
.H2AData
->IpList
== NULL
) {
1295 Status
= EFI_OUT_OF_RESOURCES
;
1299 Status
= EFI_UNSUPPORTED
;
1304 ASSERT (Dns6TokenEntry
!= NULL
);
1306 if (Dns6TokenEntry
->GeneralLookUp
) {
1308 // It's the GeneralLookUp querying.
1310 Dns6TokenEntry
->Token
->RspData
.GLookupData
= AllocateZeroPool (sizeof (DNS_RESOURCE_RECORD
));
1311 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
== NULL
) {
1312 Status
= EFI_OUT_OF_RESOURCES
;
1315 Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
= AllocateZeroPool (DnsHeader
->AnswersNum
* sizeof (DNS_RESOURCE_RECORD
));
1316 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
== NULL
) {
1317 Status
= EFI_OUT_OF_RESOURCES
;
1322 // It's not the GeneralLookUp querying. Check the Query type.
1324 if (QuerySection
->Type
== DNS_TYPE_AAAA
) {
1325 Dns6TokenEntry
->Token
->RspData
.H2AData
= AllocateZeroPool (sizeof (DNS6_HOST_TO_ADDR_DATA
));
1326 if (Dns6TokenEntry
->Token
->RspData
.H2AData
== NULL
) {
1327 Status
= EFI_OUT_OF_RESOURCES
;
1330 Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
= AllocateZeroPool (DnsHeader
->AnswersNum
* sizeof (EFI_IPv6_ADDRESS
));
1331 if (Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
== NULL
) {
1332 Status
= EFI_OUT_OF_RESOURCES
;
1336 Status
= EFI_UNSUPPORTED
;
1342 Status
= EFI_NOT_FOUND
;
1345 // Processing AnswerSection.
1347 while (AnswerSectionNum
< DnsHeader
->AnswersNum
) {
1349 // Answer name should be PTR, else EFI_UNSUPPORTED returned.
1351 if ((*(UINT8
*) AnswerName
& 0xC0) != 0xC0) {
1352 Status
= EFI_UNSUPPORTED
;
1357 // Get Answer section.
1359 AnswerSection
= (DNS_ANSWER_SECTION
*) (AnswerName
+ sizeof (UINT16
));
1360 AnswerSection
->Type
= NTOHS (AnswerSection
->Type
);
1361 AnswerSection
->Class
= NTOHS (AnswerSection
->Class
);
1362 AnswerSection
->Ttl
= NTOHL (AnswerSection
->Ttl
);
1363 AnswerSection
->DataLength
= NTOHS (AnswerSection
->DataLength
);
1366 // Check whether it's the GeneralLookUp querying.
1368 if (Instance
->Service
->IpVersion
== IP_VERSION_4
&& Dns4TokenEntry
->GeneralLookUp
) {
1369 Dns4RR
= Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
;
1370 AnswerData
= (UINT8
*) AnswerSection
+ sizeof (*AnswerSection
);
1373 // Fill the ResourceRecord.
1375 Dns4RR
[RRCount
].QName
= AllocateZeroPool (AsciiStrLen (QueryName
) + 1);
1376 if (Dns4RR
[RRCount
].QName
== NULL
) {
1377 Status
= EFI_OUT_OF_RESOURCES
;
1380 CopyMem (Dns4RR
[RRCount
].QName
, QueryName
, AsciiStrLen (QueryName
));
1381 Dns4RR
[RRCount
].QType
= AnswerSection
->Type
;
1382 Dns4RR
[RRCount
].QClass
= AnswerSection
->Class
;
1383 Dns4RR
[RRCount
].TTL
= AnswerSection
->Ttl
;
1384 Dns4RR
[RRCount
].DataLength
= AnswerSection
->DataLength
;
1385 Dns4RR
[RRCount
].RData
= AllocateZeroPool (Dns4RR
[RRCount
].DataLength
);
1386 if (Dns4RR
[RRCount
].RData
== NULL
) {
1387 Status
= EFI_OUT_OF_RESOURCES
;
1390 CopyMem (Dns4RR
[RRCount
].RData
, AnswerData
, Dns4RR
[RRCount
].DataLength
);
1393 Status
= EFI_SUCCESS
;
1394 } else if (Instance
->Service
->IpVersion
== IP_VERSION_6
&& Dns6TokenEntry
->GeneralLookUp
) {
1395 Dns6RR
= Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
;
1396 AnswerData
= (UINT8
*) AnswerSection
+ sizeof (*AnswerSection
);
1399 // Fill the ResourceRecord.
1401 Dns6RR
[RRCount
].QName
= AllocateZeroPool (AsciiStrLen (QueryName
) + 1);
1402 if (Dns6RR
[RRCount
].QName
== NULL
) {
1403 Status
= EFI_OUT_OF_RESOURCES
;
1406 CopyMem (Dns6RR
[RRCount
].QName
, QueryName
, AsciiStrLen (QueryName
));
1407 Dns6RR
[RRCount
].QType
= AnswerSection
->Type
;
1408 Dns6RR
[RRCount
].QClass
= AnswerSection
->Class
;
1409 Dns6RR
[RRCount
].TTL
= AnswerSection
->Ttl
;
1410 Dns6RR
[RRCount
].DataLength
= AnswerSection
->DataLength
;
1411 Dns6RR
[RRCount
].RData
= AllocateZeroPool (Dns6RR
[RRCount
].DataLength
);
1412 if (Dns6RR
[RRCount
].RData
== NULL
) {
1413 Status
= EFI_OUT_OF_RESOURCES
;
1416 CopyMem (Dns6RR
[RRCount
].RData
, AnswerData
, Dns6RR
[RRCount
].DataLength
);
1419 Status
= EFI_SUCCESS
;
1422 // It's not the GeneralLookUp querying.
1423 // Check the Query type, parse the response packet.
1425 switch (AnswerSection
->Type
) {
1428 // This is address entry, get Data.
1430 ASSERT (Dns4TokenEntry
!= NULL
);
1432 if (AnswerSection
->DataLength
!= 4) {
1433 Status
= EFI_ABORTED
;
1437 HostAddr4
= Dns4TokenEntry
->Token
->RspData
.H2AData
->IpList
;
1438 AnswerData
= (UINT8
*) AnswerSection
+ sizeof (*AnswerSection
);
1439 CopyMem (&HostAddr4
[IpCount
], AnswerData
, sizeof (EFI_IPv4_ADDRESS
));
1442 // Allocate new CacheEntry pool to update DNS cache dynamically.
1444 Dns4CacheEntry
= AllocateZeroPool (sizeof (EFI_DNS4_CACHE_ENTRY
));
1445 if (Dns4CacheEntry
== NULL
) {
1446 Status
= EFI_OUT_OF_RESOURCES
;
1449 Dns4CacheEntry
->HostName
= AllocateZeroPool (2 * (StrLen(Dns4TokenEntry
->QueryHostName
) + 1));
1450 if (Dns4CacheEntry
->HostName
== NULL
) {
1451 Status
= EFI_OUT_OF_RESOURCES
;
1454 CopyMem (Dns4CacheEntry
->HostName
, Dns4TokenEntry
->QueryHostName
, 2 * (StrLen(Dns4TokenEntry
->QueryHostName
) + 1));
1455 Dns4CacheEntry
->IpAddress
= AllocateZeroPool (sizeof (EFI_IPv4_ADDRESS
));
1456 if (Dns4CacheEntry
->IpAddress
== NULL
) {
1457 Status
= EFI_OUT_OF_RESOURCES
;
1460 CopyMem (Dns4CacheEntry
->IpAddress
, AnswerData
, sizeof (EFI_IPv4_ADDRESS
));
1462 if (CNameTtl
!= 0 && AnswerSection
->Ttl
!= 0) {
1463 Dns4CacheEntry
->Timeout
= MIN (CNameTtl
, AnswerSection
->Ttl
);
1465 Dns4CacheEntry
->Timeout
= MAX (CNameTtl
, AnswerSection
->Ttl
);
1468 UpdateDns4Cache (&mDriverData
->Dns4CacheList
, FALSE
, TRUE
, *Dns4CacheEntry
);
1471 // Free allocated CacheEntry pool.
1473 FreePool (Dns4CacheEntry
->HostName
);
1474 Dns4CacheEntry
->HostName
= NULL
;
1476 FreePool (Dns4CacheEntry
->IpAddress
);
1477 Dns4CacheEntry
->IpAddress
= NULL
;
1479 FreePool (Dns4CacheEntry
);
1480 Dns4CacheEntry
= NULL
;
1483 Status
= EFI_SUCCESS
;
1487 // This is address entry, get Data.
1489 ASSERT (Dns6TokenEntry
!= NULL
);
1491 if (AnswerSection
->DataLength
!= 16) {
1492 Status
= EFI_ABORTED
;
1496 HostAddr6
= Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
;
1497 AnswerData
= (UINT8
*) AnswerSection
+ sizeof (*AnswerSection
);
1498 CopyMem (&HostAddr6
[IpCount
], AnswerData
, sizeof (EFI_IPv6_ADDRESS
));
1501 // Allocate new CacheEntry pool to update DNS cache dynamically.
1503 Dns6CacheEntry
= AllocateZeroPool (sizeof (EFI_DNS6_CACHE_ENTRY
));
1504 if (Dns6CacheEntry
== NULL
) {
1505 Status
= EFI_OUT_OF_RESOURCES
;
1508 Dns6CacheEntry
->HostName
= AllocateZeroPool (2 * (StrLen(Dns6TokenEntry
->QueryHostName
) + 1));
1509 if (Dns6CacheEntry
->HostName
== NULL
) {
1510 Status
= EFI_OUT_OF_RESOURCES
;
1513 CopyMem (Dns6CacheEntry
->HostName
, Dns6TokenEntry
->QueryHostName
, 2 * (StrLen(Dns6TokenEntry
->QueryHostName
) + 1));
1514 Dns6CacheEntry
->IpAddress
= AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS
));
1515 if (Dns6CacheEntry
->IpAddress
== NULL
) {
1516 Status
= EFI_OUT_OF_RESOURCES
;
1519 CopyMem (Dns6CacheEntry
->IpAddress
, AnswerData
, sizeof (EFI_IPv6_ADDRESS
));
1521 if (CNameTtl
!= 0 && AnswerSection
->Ttl
!= 0) {
1522 Dns6CacheEntry
->Timeout
= MIN (CNameTtl
, AnswerSection
->Ttl
);
1524 Dns6CacheEntry
->Timeout
= MAX (CNameTtl
, AnswerSection
->Ttl
);
1527 UpdateDns6Cache (&mDriverData
->Dns6CacheList
, FALSE
, TRUE
, *Dns6CacheEntry
);
1530 // Free allocated CacheEntry pool.
1532 FreePool (Dns6CacheEntry
->HostName
);
1533 Dns6CacheEntry
->HostName
= NULL
;
1535 FreePool (Dns6CacheEntry
->IpAddress
);
1536 Dns6CacheEntry
->IpAddress
= NULL
;
1538 FreePool (Dns6CacheEntry
);
1539 Dns6CacheEntry
= NULL
;
1542 Status
= EFI_SUCCESS
;
1544 case DNS_TYPE_CNAME
:
1546 // According RFC 1034 - 3.6.2, if the query name is an alias, the name server will include the CNAME
1547 // record in the response and restart the query at the domain name specified in the data field of the
1548 // CNAME record. So, just record the TTL value of the CNAME, then skip to parse the next record.
1550 CNameTtl
= AnswerSection
->Ttl
;
1553 Status
= EFI_UNSUPPORTED
;
1561 AnswerName
= (CHAR8
*) AnswerSection
+ sizeof (*AnswerSection
) + AnswerSection
->DataLength
;
1562 AnswerSectionNum
++;
1565 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1566 ASSERT (Dns4TokenEntry
!= NULL
);
1568 if (Dns4TokenEntry
->GeneralLookUp
) {
1569 Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRCount
= RRCount
;
1571 if (QuerySection
->Type
== DNS_TYPE_A
) {
1572 Dns4TokenEntry
->Token
->RspData
.H2AData
->IpCount
= IpCount
;
1574 Status
= EFI_UNSUPPORTED
;
1579 ASSERT (Dns6TokenEntry
!= NULL
);
1581 if (Dns6TokenEntry
->GeneralLookUp
) {
1582 Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRCount
= RRCount
;
1584 if (QuerySection
->Type
== DNS_TYPE_AAAA
) {
1585 Dns6TokenEntry
->Token
->RspData
.H2AData
->IpCount
= IpCount
;
1587 Status
= EFI_UNSUPPORTED
;
1595 // Parsing is complete, free the sending packet and signal Event here.
1597 if (Item
!= NULL
&& Item
->Value
!= NULL
) {
1598 NetbufFree ((NET_BUF
*) (Item
->Value
));
1601 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1602 ASSERT (Dns4TokenEntry
!= NULL
);
1603 Dns4RemoveTokenEntry (&Instance
->Dns4TxTokens
, Dns4TokenEntry
);
1604 Dns4TokenEntry
->Token
->Status
= Status
;
1605 if (Dns4TokenEntry
->Token
->Event
!= NULL
) {
1606 gBS
->SignalEvent (Dns4TokenEntry
->Token
->Event
);
1610 ASSERT (Dns6TokenEntry
!= NULL
);
1611 Dns6RemoveTokenEntry (&Instance
->Dns6TxTokens
, Dns6TokenEntry
);
1612 Dns6TokenEntry
->Token
->Status
= Status
;
1613 if (Dns6TokenEntry
->Token
->Event
!= NULL
) {
1614 gBS
->SignalEvent (Dns6TokenEntry
->Token
->Event
);
1621 // Free the allocated buffer if error happen.
1623 if (EFI_ERROR (Status
)) {
1624 if (Dns4TokenEntry
!= NULL
) {
1625 if (Dns4TokenEntry
->GeneralLookUp
) {
1626 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
!= NULL
) {
1627 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
!= NULL
) {
1628 while (RRCount
!= 0) {
1630 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].QName
!= NULL
) {
1631 FreePool (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].QName
);
1634 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].RData
!= NULL
) {
1635 FreePool (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].RData
);
1639 FreePool (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
);
1642 FreePool (Dns4TokenEntry
->Token
->RspData
.GLookupData
);
1645 if (QuerySection
->Type
== DNS_TYPE_A
&& Dns4TokenEntry
->Token
->RspData
.H2AData
!= NULL
) {
1646 if (Dns4TokenEntry
->Token
->RspData
.H2AData
->IpList
!= NULL
) {
1647 FreePool (Dns4TokenEntry
->Token
->RspData
.H2AData
->IpList
);
1650 FreePool (Dns4TokenEntry
->Token
->RspData
.H2AData
);
1655 if (Dns6TokenEntry
!= NULL
) {
1656 if (Dns6TokenEntry
->GeneralLookUp
) {
1657 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
!= NULL
) {
1658 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
!= NULL
) {
1659 while (RRCount
!= 0) {
1661 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].QName
!= NULL
) {
1662 FreePool (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].QName
);
1665 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].RData
!= NULL
) {
1666 FreePool (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
[RRCount
].RData
);
1670 FreePool (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
);
1673 FreePool (Dns6TokenEntry
->Token
->RspData
.GLookupData
);
1676 if (QuerySection
->Type
== DNS_TYPE_AAAA
&& Dns6TokenEntry
->Token
->RspData
.H2AData
!= NULL
) {
1677 if (Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
!= NULL
) {
1678 FreePool (Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
);
1681 FreePool (Dns6TokenEntry
->Token
->RspData
.H2AData
);
1686 if (Dns4CacheEntry
!= NULL
) {
1687 if (Dns4CacheEntry
->HostName
!= NULL
) {
1688 FreePool (Dns4CacheEntry
->HostName
);
1691 if (Dns4CacheEntry
->IpAddress
!= NULL
) {
1692 FreePool (Dns4CacheEntry
->IpAddress
);
1695 FreePool (Dns4CacheEntry
);
1698 if (Dns6CacheEntry
!= NULL
) {
1699 if (Dns6CacheEntry
->HostName
!= NULL
) {
1700 FreePool (Dns6CacheEntry
->HostName
);
1703 if (Dns6CacheEntry
->IpAddress
!= NULL
) {
1704 FreePool (Dns6CacheEntry
->IpAddress
);
1707 FreePool (Dns6CacheEntry
);
1711 gBS
->RestoreTPL (OldTpl
);
1716 Parse response packet.
1718 @param Packet The packets received.
1719 @param EndPoint The local/remote UDP access point
1720 @param IoStatus The status of the UDP receive
1721 @param Context The opaque parameter to the function.
1726 DnsOnPacketReceived (
1728 UDP_END_POINT
*EndPoint
,
1729 EFI_STATUS IoStatus
,
1733 DNS_INSTANCE
*Instance
;
1739 Instance
= (DNS_INSTANCE
*) Context
;
1740 NET_CHECK_SIGNATURE (Instance
, DNS_INSTANCE_SIGNATURE
);
1745 if (EFI_ERROR (IoStatus
)) {
1749 ASSERT (Packet
!= NULL
);
1751 if (Packet
->TotalSize
<= sizeof (DNS_HEADER
)) {
1755 RcvString
= NetbufGetByte (Packet
, 0, NULL
);
1756 ASSERT (RcvString
!= NULL
);
1759 // Parse Dns Response
1761 ParseDnsResponse (Instance
, RcvString
, &Completed
);
1765 if (Packet
!= NULL
) {
1766 NetbufFree (Packet
);
1770 UdpIoRecvDatagram (Instance
->UdpIo
, DnsOnPacketReceived
, Instance
, 0);
1775 Release the net buffer when packet is sent.
1777 @param Packet The packets received.
1778 @param EndPoint The local/remote UDP access point
1779 @param IoStatus The status of the UDP receive
1780 @param Context The opaque parameter to the function.
1787 UDP_END_POINT
*EndPoint
,
1788 EFI_STATUS IoStatus
,
1792 DNS_INSTANCE
*Instance
;
1795 DNS4_TOKEN_ENTRY
*Dns4TokenEntry
;
1796 DNS6_TOKEN_ENTRY
*Dns6TokenEntry
;
1798 Dns4TokenEntry
= NULL
;
1799 Dns6TokenEntry
= NULL
;
1801 Instance
= (DNS_INSTANCE
*) Context
;
1802 NET_CHECK_SIGNATURE (Instance
, DNS_INSTANCE_SIGNATURE
);
1804 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1805 NET_LIST_FOR_EACH (Entry
, &Instance
->Dns4TxTokens
.Used
) {
1806 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
1807 if (Packet
== (NET_BUF
*)(Item
->Value
)) {
1808 Dns4TokenEntry
= ((DNS4_TOKEN_ENTRY
*)Item
->Key
);
1809 Dns4TokenEntry
->PacketToLive
= Dns4TokenEntry
->Token
->RetryInterval
;
1814 NET_LIST_FOR_EACH (Entry
, &Instance
->Dns6TxTokens
.Used
) {
1815 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
1816 if (Packet
== (NET_BUF
*)(Item
->Value
)) {
1817 Dns6TokenEntry
= ((DNS6_TOKEN_ENTRY
*)Item
->Key
);
1818 Dns6TokenEntry
->PacketToLive
= Dns6TokenEntry
->Token
->RetryInterval
;
1824 NetbufFree (Packet
);
1828 Query request information.
1830 @param Instance The DNS instance
1831 @param Packet The packet for querying request information.
1833 @retval EFI_SUCCESS Query request information successfully.
1834 @retval Others Failed to query request information.
1839 IN DNS_INSTANCE
*Instance
,
1846 // Ready to receive the DNS response.
1848 if (Instance
->UdpIo
->RecvRequest
== NULL
) {
1849 Status
= UdpIoRecvDatagram (Instance
->UdpIo
, DnsOnPacketReceived
, Instance
, 0);
1850 if (EFI_ERROR (Status
)) {
1856 // Transmit the DNS packet.
1858 NET_GET_REF (Packet
);
1860 Status
= UdpIoSendDatagram (Instance
->UdpIo
, Packet
, NULL
, NULL
, DnsOnPacketSent
, Instance
);
1866 Construct the Packet according query section.
1868 @param Instance The DNS instance
1869 @param QueryName Queried Name
1870 @param Type Queried Type
1871 @param Class Queried Class
1872 @param Packet The packet for query
1874 @retval EFI_SUCCESS The packet is constructed.
1875 @retval Others Failed to construct the Packet.
1880 IN DNS_INSTANCE
*Instance
,
1881 IN CHAR8
*QueryName
,
1884 OUT NET_BUF
**Packet
1888 DNS_HEADER
*DnsHeader
;
1889 DNS_QUERY_SECTION
*DnsQuery
;
1892 // Messages carried by UDP are restricted to 512 bytes (not counting the IP
1895 Frag
.Bulk
= AllocatePool (DNS_MAX_MESSAGE_SIZE
* sizeof (UINT8
));
1896 if (Frag
.Bulk
== NULL
) {
1897 return EFI_OUT_OF_RESOURCES
;
1903 DnsHeader
= (DNS_HEADER
*) Frag
.Bulk
;
1904 DnsHeader
->Identification
= (UINT16
)NET_RANDOM (NetRandomInitSeed());
1905 DnsHeader
->Flags
.Uint16
= 0x0000;
1906 DnsHeader
->Flags
.Bits
.RD
= 1;
1907 DnsHeader
->Flags
.Bits
.OpCode
= DNS_FLAGS_OPCODE_STANDARD
;
1908 DnsHeader
->Flags
.Bits
.QR
= DNS_FLAGS_QR_QUERY
;
1909 DnsHeader
->QuestionsNum
= 1;
1910 DnsHeader
->AnswersNum
= 0;
1911 DnsHeader
->AuthorityNum
= 0;
1912 DnsHeader
->AditionalNum
= 0;
1914 DnsHeader
->Identification
= HTONS (DnsHeader
->Identification
);
1915 DnsHeader
->Flags
.Uint16
= HTONS (DnsHeader
->Flags
.Uint16
);
1916 DnsHeader
->QuestionsNum
= HTONS (DnsHeader
->QuestionsNum
);
1917 DnsHeader
->AnswersNum
= HTONS (DnsHeader
->AnswersNum
);
1918 DnsHeader
->AuthorityNum
= HTONS (DnsHeader
->AuthorityNum
);
1919 DnsHeader
->AditionalNum
= HTONS (DnsHeader
->AditionalNum
);
1921 Frag
.Len
= sizeof (*DnsHeader
);
1926 CopyMem (Frag
.Bulk
+ Frag
.Len
, QueryName
, AsciiStrLen (QueryName
));
1927 Frag
.Len
= (UINT32
) (Frag
.Len
+ AsciiStrLen (QueryName
));
1928 *(Frag
.Bulk
+ Frag
.Len
) = 0;
1932 // Rest query section
1934 DnsQuery
= (DNS_QUERY_SECTION
*) (Frag
.Bulk
+ Frag
.Len
);
1936 DnsQuery
->Type
= HTONS (Type
);
1937 DnsQuery
->Class
= HTONS (Class
);
1939 Frag
.Len
+= sizeof (*DnsQuery
);
1942 // Wrap the Frag in a net buffer.
1944 *Packet
= NetbufFromExt (&Frag
, 1, 0, 0, DnsDummyExtFree
, NULL
);
1945 if (*Packet
== NULL
) {
1946 FreePool (Frag
.Bulk
);
1947 return EFI_OUT_OF_RESOURCES
;
1951 // Store the UdpIo in ProtoData.
1953 *((UINTN
*) &((*Packet
)->ProtoData
[0])) = (UINTN
) (Instance
->UdpIo
);
1959 Retransmit the packet.
1961 @param Instance The DNS instance
1962 @param Packet Retransmit the packet
1964 @retval EFI_SUCCESS The packet is retransmitted.
1965 @retval Others Failed to retransmit.
1970 IN DNS_INSTANCE
*Instance
,
1978 ASSERT (Packet
!= NULL
);
1981 // Set the requests to the listening port, other packets to the connected port
1983 Buffer
= NetbufGetByte (Packet
, 0, NULL
);
1984 ASSERT (Buffer
!= NULL
);
1986 NET_GET_REF (Packet
);
1988 Status
= UdpIoSendDatagram (
1997 if (EFI_ERROR (Status
)) {
1998 NET_PUT_REF (Packet
);
2005 The timer ticking function for the DNS services.
2007 @param Event The ticking event
2008 @param Context The DNS service instance
2013 DnsOnTimerRetransmit (
2018 DNS_SERVICE
*Service
;
2023 DNS_INSTANCE
*Instance
;
2024 LIST_ENTRY
*EntryNetMap
;
2025 NET_MAP_ITEM
*ItemNetMap
;
2026 DNS4_TOKEN_ENTRY
*Dns4TokenEntry
;
2027 DNS6_TOKEN_ENTRY
*Dns6TokenEntry
;
2029 Dns4TokenEntry
= NULL
;
2030 Dns6TokenEntry
= NULL
;
2032 Service
= (DNS_SERVICE
*) Context
;
2035 if (Service
->IpVersion
== IP_VERSION_4
) {
2037 // Iterate through all the children of the DNS service instance. Time
2038 // out the packet. If maximum retries reached, clean the Token up.
2040 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Service
->Dns4ChildrenList
) {
2041 Instance
= NET_LIST_USER_STRUCT (Entry
, DNS_INSTANCE
, Link
);
2043 EntryNetMap
= Instance
->Dns4TxTokens
.Used
.ForwardLink
;
2044 while (EntryNetMap
!= &Instance
->Dns4TxTokens
.Used
) {
2045 ItemNetMap
= NET_LIST_USER_STRUCT (EntryNetMap
, NET_MAP_ITEM
, Link
);
2046 Dns4TokenEntry
= (DNS4_TOKEN_ENTRY
*)(ItemNetMap
->Key
);
2047 if (Dns4TokenEntry
->PacketToLive
== 0 || (--Dns4TokenEntry
->PacketToLive
> 0)) {
2048 EntryNetMap
= EntryNetMap
->ForwardLink
;
2053 // Retransmit the packet if haven't reach the maxmium retry count,
2054 // otherwise exit the transfer.
2056 if (++Dns4TokenEntry
->RetryCounting
<= Dns4TokenEntry
->Token
->RetryCount
) {
2057 DnsRetransmit (Instance
, (NET_BUF
*)ItemNetMap
->Value
);
2058 EntryNetMap
= EntryNetMap
->ForwardLink
;
2061 // Maximum retries reached, clean the Token up.
2063 Dns4RemoveTokenEntry (&Instance
->Dns4TxTokens
, Dns4TokenEntry
);
2064 Dns4TokenEntry
->Token
->Status
= EFI_TIMEOUT
;
2065 gBS
->SignalEvent (Dns4TokenEntry
->Token
->Event
);
2069 // Free the sending packet.
2071 if (ItemNetMap
->Value
!= NULL
) {
2072 NetbufFree ((NET_BUF
*)(ItemNetMap
->Value
));
2075 EntryNetMap
= Instance
->Dns4TxTokens
.Used
.ForwardLink
;
2081 // Iterate through all the children of the DNS service instance. Time
2082 // out the packet. If maximum retries reached, clean the Token up.
2084 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Service
->Dns6ChildrenList
) {
2085 Instance
= NET_LIST_USER_STRUCT (Entry
, DNS_INSTANCE
, Link
);
2087 EntryNetMap
= Instance
->Dns6TxTokens
.Used
.ForwardLink
;
2088 while (EntryNetMap
!= &Instance
->Dns6TxTokens
.Used
) {
2089 ItemNetMap
= NET_LIST_USER_STRUCT (EntryNetMap
, NET_MAP_ITEM
, Link
);
2090 Dns6TokenEntry
= (DNS6_TOKEN_ENTRY
*) (ItemNetMap
->Key
);
2091 if (Dns6TokenEntry
->PacketToLive
== 0 || (--Dns6TokenEntry
->PacketToLive
> 0)) {
2092 EntryNetMap
= EntryNetMap
->ForwardLink
;
2097 // Retransmit the packet if haven't reach the maxmium retry count,
2098 // otherwise exit the transfer.
2100 if (++Dns6TokenEntry
->RetryCounting
<= Dns6TokenEntry
->Token
->RetryCount
) {
2101 DnsRetransmit (Instance
, (NET_BUF
*) ItemNetMap
->Value
);
2102 EntryNetMap
= EntryNetMap
->ForwardLink
;
2105 // Maximum retries reached, clean the Token up.
2107 Dns6RemoveTokenEntry (&Instance
->Dns6TxTokens
, Dns6TokenEntry
);
2108 Dns6TokenEntry
->Token
->Status
= EFI_TIMEOUT
;
2109 gBS
->SignalEvent (Dns6TokenEntry
->Token
->Event
);
2113 // Free the sending packet.
2115 if (ItemNetMap
->Value
!= NULL
) {
2116 NetbufFree ((NET_BUF
*) (ItemNetMap
->Value
));
2119 EntryNetMap
= Instance
->Dns6TxTokens
.Used
.ForwardLink
;
2127 The timer ticking function for the DNS driver.
2129 @param Event The ticking event
2149 // Iterate through all the DNS4 cache list.
2151 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &mDriverData
->Dns4CacheList
) {
2152 Item4
= NET_LIST_USER_STRUCT (Entry
, DNS4_CACHE
, AllCacheLink
);
2153 Item4
->DnsCache
.Timeout
--;
2156 Entry
= mDriverData
->Dns4CacheList
.ForwardLink
;
2157 while (Entry
!= &mDriverData
->Dns4CacheList
) {
2158 Item4
= NET_LIST_USER_STRUCT (Entry
, DNS4_CACHE
, AllCacheLink
);
2159 if (Item4
->DnsCache
.Timeout
== 0) {
2160 RemoveEntryList (&Item4
->AllCacheLink
);
2161 FreePool (Item4
->DnsCache
.HostName
);
2162 FreePool (Item4
->DnsCache
.IpAddress
);
2164 Entry
= mDriverData
->Dns4CacheList
.ForwardLink
;
2166 Entry
= Entry
->ForwardLink
;
2171 // Iterate through all the DNS6 cache list.
2173 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &mDriverData
->Dns6CacheList
) {
2174 Item6
= NET_LIST_USER_STRUCT (Entry
, DNS6_CACHE
, AllCacheLink
);
2175 Item6
->DnsCache
.Timeout
--;
2178 Entry
= mDriverData
->Dns6CacheList
.ForwardLink
;
2179 while (Entry
!= &mDriverData
->Dns6CacheList
) {
2180 Item6
= NET_LIST_USER_STRUCT (Entry
, DNS6_CACHE
, AllCacheLink
);
2181 if (Item6
->DnsCache
.Timeout
== 0) {
2182 RemoveEntryList (&Item6
->AllCacheLink
);
2183 FreePool (Item6
->DnsCache
.HostName
);
2184 FreePool (Item6
->DnsCache
.IpAddress
);
2186 Entry
= mDriverData
->Dns6CacheList
.ForwardLink
;
2188 Entry
= Entry
->ForwardLink
;