2 DnsDxe support functions implementation.
4 Copyright (c) 2016 - 2017, 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
);
797 } else if (Override
) {
801 Item
->DnsCache
.Timeout
= DnsCacheEntry
.Timeout
;
805 return EFI_ACCESS_DENIED
;
813 NewDnsCache
= AllocatePool (sizeof (DNS4_CACHE
));
814 if (NewDnsCache
== NULL
) {
815 return EFI_OUT_OF_RESOURCES
;
818 InitializeListHead (&NewDnsCache
->AllCacheLink
);
820 NewDnsCache
->DnsCache
.HostName
= AllocatePool (StrSize (DnsCacheEntry
.HostName
));
821 if (NewDnsCache
->DnsCache
.HostName
== NULL
) {
822 return EFI_OUT_OF_RESOURCES
;
825 CopyMem (NewDnsCache
->DnsCache
.HostName
, DnsCacheEntry
.HostName
, StrSize (DnsCacheEntry
.HostName
));
827 NewDnsCache
->DnsCache
.IpAddress
= AllocatePool (sizeof (EFI_IPv4_ADDRESS
));
828 if (NewDnsCache
->DnsCache
.IpAddress
== NULL
) {
829 return EFI_OUT_OF_RESOURCES
;
832 CopyMem (NewDnsCache
->DnsCache
.IpAddress
, DnsCacheEntry
.IpAddress
, sizeof (EFI_IPv4_ADDRESS
));
834 NewDnsCache
->DnsCache
.Timeout
= DnsCacheEntry
.Timeout
;
836 InsertTailList (Dns4CacheList
, &NewDnsCache
->AllCacheLink
);
842 Update Dns6 cache to shared list of caches of all DNSv6 instances.
844 @param Dns6CacheList All Dns6 cache list.
845 @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache.
846 If TRUE, this function will delete matching DNS Cache entry.
847 @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
848 If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
849 @param DnsCacheEntry Entry Pointer to DNS Cache entry.
851 @retval EFI_SUCCESS Update Dns6 cache successfully.
852 @retval Others Failed to update Dns6 cache.
857 IN LIST_ENTRY
*Dns6CacheList
,
858 IN BOOLEAN DeleteFlag
,
860 IN EFI_DNS6_CACHE_ENTRY DnsCacheEntry
863 DNS6_CACHE
*NewDnsCache
;
872 // Search the database for the matching EFI_DNS_CACHE_ENTRY
874 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Dns6CacheList
) {
875 Item
= NET_LIST_USER_STRUCT (Entry
, DNS6_CACHE
, AllCacheLink
);
876 if (StrCmp (DnsCacheEntry
.HostName
, Item
->DnsCache
.HostName
) == 0 && \
877 CompareMem (DnsCacheEntry
.IpAddress
, Item
->DnsCache
.IpAddress
, sizeof (EFI_IPv6_ADDRESS
)) == 0) {
879 // This is the Dns cache entry
883 // Delete matching DNS Cache entry
885 RemoveEntryList (&Item
->AllCacheLink
);
888 } else if (Override
) {
892 Item
->DnsCache
.Timeout
= DnsCacheEntry
.Timeout
;
896 return EFI_ACCESS_DENIED
;
904 NewDnsCache
= AllocatePool (sizeof (DNS6_CACHE
));
905 if (NewDnsCache
== NULL
) {
906 return EFI_OUT_OF_RESOURCES
;
909 InitializeListHead (&NewDnsCache
->AllCacheLink
);
911 NewDnsCache
->DnsCache
.HostName
= AllocatePool (StrSize (DnsCacheEntry
.HostName
));
912 if (NewDnsCache
->DnsCache
.HostName
== NULL
) {
913 return EFI_OUT_OF_RESOURCES
;
916 CopyMem (NewDnsCache
->DnsCache
.HostName
, DnsCacheEntry
.HostName
, StrSize (DnsCacheEntry
.HostName
));
918 NewDnsCache
->DnsCache
.IpAddress
= AllocatePool (sizeof (EFI_IPv6_ADDRESS
));
919 if (NewDnsCache
->DnsCache
.IpAddress
== NULL
) {
920 return EFI_OUT_OF_RESOURCES
;
923 CopyMem (NewDnsCache
->DnsCache
.IpAddress
, DnsCacheEntry
.IpAddress
, sizeof (EFI_IPv6_ADDRESS
));
925 NewDnsCache
->DnsCache
.Timeout
= DnsCacheEntry
.Timeout
;
927 InsertTailList (Dns6CacheList
, &NewDnsCache
->AllCacheLink
);
933 Add Dns4 ServerIp to common list of addresses of all configured DNSv4 server.
935 @param Dns4ServerList Common list of addresses of all configured DNSv4 server.
936 @param ServerIp DNS server Ip.
938 @retval EFI_SUCCESS Add Dns4 ServerIp to common list successfully.
939 @retval Others Failed to add Dns4 ServerIp to common list.
945 IN LIST_ENTRY
*Dns4ServerList
,
946 IN EFI_IPv4_ADDRESS ServerIp
949 DNS4_SERVER_IP
*NewServerIp
;
950 DNS4_SERVER_IP
*Item
;
958 // Search the database for the matching ServerIp
960 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Dns4ServerList
) {
961 Item
= NET_LIST_USER_STRUCT (Entry
, DNS4_SERVER_IP
, AllServerLink
);
962 if (CompareMem (&Item
->Dns4ServerIp
, &ServerIp
, sizeof (EFI_IPv4_ADDRESS
)) == 0) {
973 NewServerIp
= AllocatePool (sizeof (DNS4_SERVER_IP
));
974 if (NewServerIp
== NULL
) {
975 return EFI_OUT_OF_RESOURCES
;
978 InitializeListHead (&NewServerIp
->AllServerLink
);
980 CopyMem (&NewServerIp
->Dns4ServerIp
, &ServerIp
, sizeof (EFI_IPv4_ADDRESS
));
982 InsertTailList (Dns4ServerList
, &NewServerIp
->AllServerLink
);
988 Add Dns6 ServerIp to common list of addresses of all configured DNSv6 server.
990 @param Dns6ServerList Common list of addresses of all configured DNSv6 server.
991 @param ServerIp DNS server Ip.
993 @retval EFI_SUCCESS Add Dns6 ServerIp to common list successfully.
994 @retval Others Failed to add Dns6 ServerIp to common list.
1000 IN LIST_ENTRY
*Dns6ServerList
,
1001 IN EFI_IPv6_ADDRESS ServerIp
1004 DNS6_SERVER_IP
*NewServerIp
;
1005 DNS6_SERVER_IP
*Item
;
1013 // Search the database for the matching ServerIp
1015 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Dns6ServerList
) {
1016 Item
= NET_LIST_USER_STRUCT (Entry
, DNS6_SERVER_IP
, AllServerLink
);
1017 if (CompareMem (&Item
->Dns6ServerIp
, &ServerIp
, sizeof (EFI_IPv6_ADDRESS
)) == 0) {
1028 NewServerIp
= AllocatePool (sizeof (DNS6_SERVER_IP
));
1029 if (NewServerIp
== NULL
) {
1030 return EFI_OUT_OF_RESOURCES
;
1033 InitializeListHead (&NewServerIp
->AllServerLink
);
1035 CopyMem (&NewServerIp
->Dns6ServerIp
, &ServerIp
, sizeof (EFI_IPv6_ADDRESS
));
1037 InsertTailList (Dns6ServerList
, &NewServerIp
->AllServerLink
);
1043 Find out whether the response is valid or invalid.
1045 @param TokensMap All DNS transmittal Tokens entry.
1046 @param Identification Identification for queried packet.
1047 @param Type Type for queried packet.
1048 @param Class Class for queried packet.
1049 @param Item Return corresponding Token entry.
1051 @retval TRUE The response is valid.
1052 @retval FALSE The response is invalid.
1056 IsValidDnsResponse (
1057 IN NET_MAP
*TokensMap
,
1058 IN UINT16 Identification
,
1061 OUT NET_MAP_ITEM
**Item
1068 DNS_HEADER
*DnsHeader
;
1070 DNS_QUERY_SECTION
*QuerySection
;
1072 NET_LIST_FOR_EACH (Entry
, &TokensMap
->Used
) {
1073 *Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
1074 Packet
= (NET_BUF
*) ((*Item
)->Value
);
1075 if (Packet
== NULL
){
1079 TxString
= NetbufGetByte (Packet
, 0, NULL
);
1080 ASSERT (TxString
!= NULL
);
1081 DnsHeader
= (DNS_HEADER
*) TxString
;
1082 QueryName
= (CHAR8
*) (TxString
+ sizeof (*DnsHeader
));
1083 QuerySection
= (DNS_QUERY_SECTION
*) (QueryName
+ AsciiStrLen (QueryName
) + 1);
1085 if (NTOHS (DnsHeader
->Identification
) == Identification
&&
1086 NTOHS (QuerySection
->Type
) == Type
&&
1087 NTOHS (QuerySection
->Class
) == Class
) {
1101 @param Instance The DNS instance
1102 @param RxString Received buffer.
1103 @param Completed Flag to indicate that Dns response is valid.
1105 @retval EFI_SUCCESS Parse Dns Response successfully.
1106 @retval Others Failed to parse Dns Response.
1111 IN OUT DNS_INSTANCE
*Instance
,
1113 OUT BOOLEAN
*Completed
1116 DNS_HEADER
*DnsHeader
;
1119 DNS_QUERY_SECTION
*QuerySection
;
1122 DNS_ANSWER_SECTION
*AnswerSection
;
1126 DNS4_TOKEN_ENTRY
*Dns4TokenEntry
;
1127 DNS6_TOKEN_ENTRY
*Dns6TokenEntry
;
1131 UINT32 AnswerSectionNum
;
1134 EFI_IPv4_ADDRESS
*HostAddr4
;
1135 EFI_IPv6_ADDRESS
*HostAddr6
;
1137 EFI_DNS4_CACHE_ENTRY
*Dns4CacheEntry
;
1138 EFI_DNS6_CACHE_ENTRY
*Dns6CacheEntry
;
1140 DNS_RESOURCE_RECORD
*Dns4RR
;
1141 DNS6_RESOURCE_RECORD
*Dns6RR
;
1148 Dns4TokenEntry
= NULL
;
1149 Dns6TokenEntry
= NULL
;
1153 AnswerSectionNum
= 0;
1159 Dns4CacheEntry
= NULL
;
1160 Dns6CacheEntry
= NULL
;
1166 Status
= EFI_SUCCESS
;
1171 DnsHeader
= (DNS_HEADER
*) RxString
;
1173 DnsHeader
->Identification
= NTOHS (DnsHeader
->Identification
);
1174 DnsHeader
->Flags
.Uint16
= NTOHS (DnsHeader
->Flags
.Uint16
);
1175 DnsHeader
->QuestionsNum
= NTOHS (DnsHeader
->QuestionsNum
);
1176 DnsHeader
->AnswersNum
= NTOHS (DnsHeader
->AnswersNum
);
1177 DnsHeader
->AuthorityNum
= NTOHS (DnsHeader
->AuthorityNum
);
1178 DnsHeader
->AditionalNum
= NTOHS (DnsHeader
->AditionalNum
);
1183 QueryName
= (CHAR8
*) (RxString
+ sizeof (*DnsHeader
));
1186 // Get query section
1188 QuerySection
= (DNS_QUERY_SECTION
*) (QueryName
+ AsciiStrLen (QueryName
) + 1);
1189 QuerySection
->Type
= NTOHS (QuerySection
->Type
);
1190 QuerySection
->Class
= NTOHS (QuerySection
->Class
);
1195 AnswerName
= (CHAR8
*) QuerySection
+ sizeof (*QuerySection
);
1197 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1200 // Check DnsResponse Validity, if so, also get a valid NET_MAP_ITEM.
1202 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1203 if (!IsValidDnsResponse (
1204 &Instance
->Dns4TxTokens
,
1205 DnsHeader
->Identification
,
1207 QuerySection
->Class
,
1211 Status
= EFI_ABORTED
;
1214 ASSERT (Item
!= NULL
);
1215 Dns4TokenEntry
= (DNS4_TOKEN_ENTRY
*) (Item
->Key
);
1217 if (!IsValidDnsResponse (
1218 &Instance
->Dns6TxTokens
,
1219 DnsHeader
->Identification
,
1221 QuerySection
->Class
,
1225 Status
= EFI_ABORTED
;
1228 ASSERT (Item
!= NULL
);
1229 Dns6TokenEntry
= (DNS6_TOKEN_ENTRY
*) (Item
->Key
);
1233 // Continue Check Some Errors.
1235 if (DnsHeader
->Flags
.Bits
.RCode
!= DNS_FLAGS_RCODE_NO_ERROR
|| DnsHeader
->AnswersNum
< 1 || \
1236 DnsHeader
->Flags
.Bits
.QR
!= DNS_FLAGS_QR_RESPONSE
) {
1238 // The domain name referenced in the query does not exist.
1240 if (DnsHeader
->Flags
.Bits
.RCode
== DNS_FLAGS_RCODE_NAME_ERROR
) {
1241 Status
= EFI_NOT_FOUND
;
1243 Status
= EFI_DEVICE_ERROR
;
1250 // Do some buffer allocations.
1252 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1253 ASSERT (Dns4TokenEntry
!= NULL
);
1255 if (Dns4TokenEntry
->GeneralLookUp
) {
1257 // It's the GeneralLookUp querying.
1259 Dns4TokenEntry
->Token
->RspData
.GLookupData
= AllocatePool (sizeof (DNS_RESOURCE_RECORD
));
1260 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
== NULL
) {
1261 Status
= EFI_OUT_OF_RESOURCES
;
1264 Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
= AllocatePool (DnsHeader
->AnswersNum
* sizeof (DNS_RESOURCE_RECORD
));
1265 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
== NULL
) {
1266 Status
= EFI_OUT_OF_RESOURCES
;
1271 // It's not the GeneralLookUp querying. Check the Query type.
1273 if (QuerySection
->Type
== DNS_TYPE_A
) {
1274 Dns4TokenEntry
->Token
->RspData
.H2AData
= AllocatePool (sizeof (DNS_HOST_TO_ADDR_DATA
));
1275 if (Dns4TokenEntry
->Token
->RspData
.H2AData
== NULL
) {
1276 Status
= EFI_OUT_OF_RESOURCES
;
1279 Dns4TokenEntry
->Token
->RspData
.H2AData
->IpList
= AllocatePool (DnsHeader
->AnswersNum
* sizeof (EFI_IPv4_ADDRESS
));
1280 if (Dns4TokenEntry
->Token
->RspData
.H2AData
->IpList
== NULL
) {
1281 Status
= EFI_OUT_OF_RESOURCES
;
1285 Status
= EFI_UNSUPPORTED
;
1290 ASSERT (Dns6TokenEntry
!= NULL
);
1292 if (Dns6TokenEntry
->GeneralLookUp
) {
1294 // It's the GeneralLookUp querying.
1296 Dns6TokenEntry
->Token
->RspData
.GLookupData
= AllocatePool (sizeof (DNS_RESOURCE_RECORD
));
1297 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
== NULL
) {
1298 Status
= EFI_OUT_OF_RESOURCES
;
1301 Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
= AllocatePool (DnsHeader
->AnswersNum
* sizeof (DNS_RESOURCE_RECORD
));
1302 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
== NULL
) {
1303 Status
= EFI_OUT_OF_RESOURCES
;
1308 // It's not the GeneralLookUp querying. Check the Query type.
1310 if (QuerySection
->Type
== DNS_TYPE_AAAA
) {
1311 Dns6TokenEntry
->Token
->RspData
.H2AData
= AllocatePool (sizeof (DNS6_HOST_TO_ADDR_DATA
));
1312 if (Dns6TokenEntry
->Token
->RspData
.H2AData
== NULL
) {
1313 Status
= EFI_OUT_OF_RESOURCES
;
1316 Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
= AllocatePool (DnsHeader
->AnswersNum
* sizeof (EFI_IPv6_ADDRESS
));
1317 if (Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
== NULL
) {
1318 Status
= EFI_OUT_OF_RESOURCES
;
1322 Status
= EFI_UNSUPPORTED
;
1328 Status
= EFI_NOT_FOUND
;
1331 // Processing AnswerSection.
1333 while (AnswerSectionNum
< DnsHeader
->AnswersNum
) {
1335 // Answer name should be PTR, else EFI_UNSUPPORTED returned.
1337 if ((*(UINT8
*) AnswerName
& 0xC0) != 0xC0) {
1338 Status
= EFI_UNSUPPORTED
;
1343 // Get Answer section.
1345 AnswerSection
= (DNS_ANSWER_SECTION
*) (AnswerName
+ sizeof (UINT16
));
1346 AnswerSection
->Type
= NTOHS (AnswerSection
->Type
);
1347 AnswerSection
->Class
= NTOHS (AnswerSection
->Class
);
1348 AnswerSection
->Ttl
= NTOHL (AnswerSection
->Ttl
);
1349 AnswerSection
->DataLength
= NTOHS (AnswerSection
->DataLength
);
1352 // Check whether it's the GeneralLookUp querying.
1354 if (Instance
->Service
->IpVersion
== IP_VERSION_4
&& Dns4TokenEntry
->GeneralLookUp
) {
1355 Dns4RR
= Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
;
1356 AnswerData
= (UINT8
*) AnswerSection
+ sizeof (*AnswerSection
);
1359 // Fill the ResourceRecord.
1361 Dns4RR
[RRCount
].QName
= AllocateZeroPool (AsciiStrLen (QueryName
) + 1);
1362 if (Dns4RR
[RRCount
].QName
== NULL
) {
1363 Status
= EFI_OUT_OF_RESOURCES
;
1366 CopyMem (Dns4RR
[RRCount
].QName
, QueryName
, AsciiStrLen (QueryName
));
1367 Dns4RR
[RRCount
].QType
= AnswerSection
->Type
;
1368 Dns4RR
[RRCount
].QClass
= AnswerSection
->Class
;
1369 Dns4RR
[RRCount
].TTL
= AnswerSection
->Ttl
;
1370 Dns4RR
[RRCount
].DataLength
= AnswerSection
->DataLength
;
1371 Dns4RR
[RRCount
].RData
= AllocateZeroPool (Dns4RR
[RRCount
].DataLength
);
1372 if (Dns4RR
[RRCount
].RData
== NULL
) {
1373 Status
= EFI_OUT_OF_RESOURCES
;
1376 CopyMem (Dns4RR
[RRCount
].RData
, AnswerData
, Dns4RR
[RRCount
].DataLength
);
1379 Status
= EFI_SUCCESS
;
1380 } else if (Instance
->Service
->IpVersion
== IP_VERSION_6
&& Dns6TokenEntry
->GeneralLookUp
) {
1381 Dns6RR
= Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
;
1382 AnswerData
= (UINT8
*) AnswerSection
+ sizeof (*AnswerSection
);
1385 // Fill the ResourceRecord.
1387 Dns6RR
[RRCount
].QName
= AllocateZeroPool (AsciiStrLen (QueryName
) + 1);
1388 if (Dns6RR
[RRCount
].QName
== NULL
) {
1389 Status
= EFI_OUT_OF_RESOURCES
;
1392 CopyMem (Dns6RR
[RRCount
].QName
, QueryName
, AsciiStrLen (QueryName
));
1393 Dns6RR
[RRCount
].QType
= AnswerSection
->Type
;
1394 Dns6RR
[RRCount
].QClass
= AnswerSection
->Class
;
1395 Dns6RR
[RRCount
].TTL
= AnswerSection
->Ttl
;
1396 Dns6RR
[RRCount
].DataLength
= AnswerSection
->DataLength
;
1397 Dns6RR
[RRCount
].RData
= AllocateZeroPool (Dns6RR
[RRCount
].DataLength
);
1398 if (Dns6RR
[RRCount
].RData
== NULL
) {
1399 Status
= EFI_OUT_OF_RESOURCES
;
1402 CopyMem (Dns6RR
[RRCount
].RData
, AnswerData
, Dns6RR
[RRCount
].DataLength
);
1405 Status
= EFI_SUCCESS
;
1408 // It's not the GeneralLookUp querying.
1409 // Check the Query type, parse the response packet.
1411 switch (AnswerSection
->Type
) {
1414 // This is address entry, get Data.
1416 ASSERT (Dns4TokenEntry
!= NULL
);
1418 if (AnswerSection
->DataLength
!= 4) {
1419 Status
= EFI_ABORTED
;
1423 HostAddr4
= Dns4TokenEntry
->Token
->RspData
.H2AData
->IpList
;
1424 AnswerData
= (UINT8
*) AnswerSection
+ sizeof (*AnswerSection
);
1425 CopyMem (&HostAddr4
[IpCount
], AnswerData
, sizeof (EFI_IPv4_ADDRESS
));
1428 // Allocate new CacheEntry pool to update DNS cache dynamically.
1430 Dns4CacheEntry
= AllocateZeroPool (sizeof (EFI_DNS4_CACHE_ENTRY
));
1431 if (Dns4CacheEntry
== NULL
) {
1432 Status
= EFI_OUT_OF_RESOURCES
;
1435 Dns4CacheEntry
->HostName
= AllocateZeroPool (2 * (StrLen(Dns4TokenEntry
->QueryHostName
) + 1));
1436 if (Dns4CacheEntry
->HostName
== NULL
) {
1437 Status
= EFI_OUT_OF_RESOURCES
;
1440 CopyMem (Dns4CacheEntry
->HostName
, Dns4TokenEntry
->QueryHostName
, 2 * (StrLen(Dns4TokenEntry
->QueryHostName
) + 1));
1441 Dns4CacheEntry
->IpAddress
= AllocateZeroPool (sizeof (EFI_IPv4_ADDRESS
));
1442 if (Dns4CacheEntry
->IpAddress
== NULL
) {
1443 Status
= EFI_OUT_OF_RESOURCES
;
1446 CopyMem (Dns4CacheEntry
->IpAddress
, AnswerData
, sizeof (EFI_IPv4_ADDRESS
));
1448 if (CNameTtl
!= 0 && AnswerSection
->Ttl
!= 0) {
1449 Dns4CacheEntry
->Timeout
= MIN (CNameTtl
, AnswerSection
->Ttl
);
1451 Dns4CacheEntry
->Timeout
= MAX (CNameTtl
, AnswerSection
->Ttl
);
1454 UpdateDns4Cache (&mDriverData
->Dns4CacheList
, FALSE
, TRUE
, *Dns4CacheEntry
);
1457 // Free allocated CacheEntry pool.
1459 FreePool (Dns4CacheEntry
->HostName
);
1460 Dns4CacheEntry
->HostName
= NULL
;
1462 FreePool (Dns4CacheEntry
->IpAddress
);
1463 Dns4CacheEntry
->IpAddress
= NULL
;
1465 FreePool (Dns4CacheEntry
);
1466 Dns4CacheEntry
= NULL
;
1469 Status
= EFI_SUCCESS
;
1473 // This is address entry, get Data.
1475 ASSERT (Dns6TokenEntry
!= NULL
);
1477 if (AnswerSection
->DataLength
!= 16) {
1478 Status
= EFI_ABORTED
;
1482 HostAddr6
= Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
;
1483 AnswerData
= (UINT8
*) AnswerSection
+ sizeof (*AnswerSection
);
1484 CopyMem (&HostAddr6
[IpCount
], AnswerData
, sizeof (EFI_IPv6_ADDRESS
));
1487 // Allocate new CacheEntry pool to update DNS cache dynamically.
1489 Dns6CacheEntry
= AllocateZeroPool (sizeof (EFI_DNS6_CACHE_ENTRY
));
1490 if (Dns6CacheEntry
== NULL
) {
1491 Status
= EFI_OUT_OF_RESOURCES
;
1494 Dns6CacheEntry
->HostName
= AllocateZeroPool (2 * (StrLen(Dns6TokenEntry
->QueryHostName
) + 1));
1495 if (Dns6CacheEntry
->HostName
== NULL
) {
1496 Status
= EFI_OUT_OF_RESOURCES
;
1499 CopyMem (Dns6CacheEntry
->HostName
, Dns6TokenEntry
->QueryHostName
, 2 * (StrLen(Dns6TokenEntry
->QueryHostName
) + 1));
1500 Dns6CacheEntry
->IpAddress
= AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS
));
1501 if (Dns6CacheEntry
->IpAddress
== NULL
) {
1502 Status
= EFI_OUT_OF_RESOURCES
;
1505 CopyMem (Dns6CacheEntry
->IpAddress
, AnswerData
, sizeof (EFI_IPv6_ADDRESS
));
1507 if (CNameTtl
!= 0 && AnswerSection
->Ttl
!= 0) {
1508 Dns6CacheEntry
->Timeout
= MIN (CNameTtl
, AnswerSection
->Ttl
);
1510 Dns6CacheEntry
->Timeout
= MAX (CNameTtl
, AnswerSection
->Ttl
);
1513 UpdateDns6Cache (&mDriverData
->Dns6CacheList
, FALSE
, TRUE
, *Dns6CacheEntry
);
1516 // Free allocated CacheEntry pool.
1518 FreePool (Dns6CacheEntry
->HostName
);
1519 Dns6CacheEntry
->HostName
= NULL
;
1521 FreePool (Dns6CacheEntry
->IpAddress
);
1522 Dns6CacheEntry
->IpAddress
= NULL
;
1524 FreePool (Dns6CacheEntry
);
1525 Dns6CacheEntry
= NULL
;
1528 Status
= EFI_SUCCESS
;
1530 case DNS_TYPE_CNAME
:
1532 // According RFC 1034 - 3.6.2, if the query name is an alias, the name server will include the CNAME
1533 // record in the response and restart the query at the domain name specified in the data field of the
1534 // CNAME record. So, just record the TTL value of the CNAME, then skip to parse the next record.
1536 CNameTtl
= AnswerSection
->Ttl
;
1539 Status
= EFI_UNSUPPORTED
;
1547 AnswerName
= (CHAR8
*) AnswerSection
+ sizeof (*AnswerSection
) + AnswerSection
->DataLength
;
1548 AnswerSectionNum
++;
1551 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1552 ASSERT (Dns4TokenEntry
!= NULL
);
1554 if (Dns4TokenEntry
->GeneralLookUp
) {
1555 Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRCount
= RRCount
;
1557 if (QuerySection
->Type
== DNS_TYPE_A
) {
1558 Dns4TokenEntry
->Token
->RspData
.H2AData
->IpCount
= IpCount
;
1560 Status
= EFI_UNSUPPORTED
;
1565 ASSERT (Dns6TokenEntry
!= NULL
);
1567 if (Dns6TokenEntry
->GeneralLookUp
) {
1568 Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRCount
= RRCount
;
1570 if (QuerySection
->Type
== DNS_TYPE_AAAA
) {
1571 Dns6TokenEntry
->Token
->RspData
.H2AData
->IpCount
= IpCount
;
1573 Status
= EFI_UNSUPPORTED
;
1581 // Parsing is complete, free the sending packet and signal Event here.
1583 if (Item
!= NULL
&& Item
->Value
!= NULL
) {
1584 NetbufFree ((NET_BUF
*) (Item
->Value
));
1587 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1588 ASSERT (Dns4TokenEntry
!= NULL
);
1589 Dns4RemoveTokenEntry (&Instance
->Dns4TxTokens
, Dns4TokenEntry
);
1590 Dns4TokenEntry
->Token
->Status
= Status
;
1591 if (Dns4TokenEntry
->Token
->Event
!= NULL
) {
1592 gBS
->SignalEvent (Dns4TokenEntry
->Token
->Event
);
1596 ASSERT (Dns6TokenEntry
!= NULL
);
1597 Dns6RemoveTokenEntry (&Instance
->Dns6TxTokens
, Dns6TokenEntry
);
1598 Dns6TokenEntry
->Token
->Status
= Status
;
1599 if (Dns6TokenEntry
->Token
->Event
!= NULL
) {
1600 gBS
->SignalEvent (Dns6TokenEntry
->Token
->Event
);
1606 gBS
->RestoreTPL (OldTpl
);
1611 Parse response packet.
1613 @param Packet The packets received.
1614 @param EndPoint The local/remote UDP access point
1615 @param IoStatus The status of the UDP receive
1616 @param Context The opaque parameter to the function.
1621 DnsOnPacketReceived (
1623 UDP_END_POINT
*EndPoint
,
1624 EFI_STATUS IoStatus
,
1628 DNS_INSTANCE
*Instance
;
1634 Instance
= (DNS_INSTANCE
*) Context
;
1635 NET_CHECK_SIGNATURE (Instance
, DNS_INSTANCE_SIGNATURE
);
1640 if (EFI_ERROR (IoStatus
)) {
1644 ASSERT (Packet
!= NULL
);
1646 if (Packet
->TotalSize
<= sizeof (DNS_HEADER
)) {
1650 RcvString
= NetbufGetByte (Packet
, 0, NULL
);
1651 ASSERT (RcvString
!= NULL
);
1654 // Parse Dns Response
1656 ParseDnsResponse (Instance
, RcvString
, &Completed
);
1660 if (Packet
!= NULL
) {
1661 NetbufFree (Packet
);
1665 UdpIoRecvDatagram (Instance
->UdpIo
, DnsOnPacketReceived
, Instance
, 0);
1670 Release the net buffer when packet is sent.
1672 @param Packet The packets received.
1673 @param EndPoint The local/remote UDP access point
1674 @param IoStatus The status of the UDP receive
1675 @param Context The opaque parameter to the function.
1682 UDP_END_POINT
*EndPoint
,
1683 EFI_STATUS IoStatus
,
1687 DNS_INSTANCE
*Instance
;
1690 DNS4_TOKEN_ENTRY
*Dns4TokenEntry
;
1691 DNS6_TOKEN_ENTRY
*Dns6TokenEntry
;
1693 Dns4TokenEntry
= NULL
;
1694 Dns6TokenEntry
= NULL
;
1696 Instance
= (DNS_INSTANCE
*) Context
;
1697 NET_CHECK_SIGNATURE (Instance
, DNS_INSTANCE_SIGNATURE
);
1699 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1700 NET_LIST_FOR_EACH (Entry
, &Instance
->Dns4TxTokens
.Used
) {
1701 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
1702 if (Packet
== (NET_BUF
*)(Item
->Value
)) {
1703 Dns4TokenEntry
= ((DNS4_TOKEN_ENTRY
*)Item
->Key
);
1704 Dns4TokenEntry
->PacketToLive
= Dns4TokenEntry
->Token
->RetryInterval
;
1709 NET_LIST_FOR_EACH (Entry
, &Instance
->Dns6TxTokens
.Used
) {
1710 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
1711 if (Packet
== (NET_BUF
*)(Item
->Value
)) {
1712 Dns6TokenEntry
= ((DNS6_TOKEN_ENTRY
*)Item
->Key
);
1713 Dns6TokenEntry
->PacketToLive
= Dns6TokenEntry
->Token
->RetryInterval
;
1719 NetbufFree (Packet
);
1723 Query request information.
1725 @param Instance The DNS instance
1726 @param Packet The packet for querying request information.
1728 @retval EFI_SUCCESS Query request information successfully.
1729 @retval Others Failed to query request information.
1734 IN DNS_INSTANCE
*Instance
,
1741 // Ready to receive the DNS response.
1743 if (Instance
->UdpIo
->RecvRequest
== NULL
) {
1744 Status
= UdpIoRecvDatagram (Instance
->UdpIo
, DnsOnPacketReceived
, Instance
, 0);
1745 if (EFI_ERROR (Status
)) {
1751 // Transmit the DNS packet.
1753 NET_GET_REF (Packet
);
1755 Status
= UdpIoSendDatagram (Instance
->UdpIo
, Packet
, NULL
, NULL
, DnsOnPacketSent
, Instance
);
1761 Construct the Packet according query section.
1763 @param Instance The DNS instance
1764 @param QueryName Queried Name
1765 @param Type Queried Type
1766 @param Class Queried Class
1767 @param Packet The packet for query
1769 @retval EFI_SUCCESS The packet is constructed.
1770 @retval Others Failed to construct the Packet.
1775 IN DNS_INSTANCE
*Instance
,
1776 IN CHAR8
*QueryName
,
1779 OUT NET_BUF
**Packet
1783 DNS_HEADER
*DnsHeader
;
1784 DNS_QUERY_SECTION
*DnsQuery
;
1787 // Messages carried by UDP are restricted to 512 bytes (not counting the IP
1790 Frag
.Bulk
= AllocatePool (DNS_MAX_MESSAGE_SIZE
* sizeof (UINT8
));
1791 if (Frag
.Bulk
== NULL
) {
1792 return EFI_OUT_OF_RESOURCES
;
1798 DnsHeader
= (DNS_HEADER
*) Frag
.Bulk
;
1799 DnsHeader
->Identification
= (UINT16
)NET_RANDOM (NetRandomInitSeed());
1800 DnsHeader
->Flags
.Uint16
= 0x0000;
1801 DnsHeader
->Flags
.Bits
.RD
= 1;
1802 DnsHeader
->Flags
.Bits
.OpCode
= DNS_FLAGS_OPCODE_STANDARD
;
1803 DnsHeader
->Flags
.Bits
.QR
= DNS_FLAGS_QR_QUERY
;
1804 DnsHeader
->QuestionsNum
= 1;
1805 DnsHeader
->AnswersNum
= 0;
1806 DnsHeader
->AuthorityNum
= 0;
1807 DnsHeader
->AditionalNum
= 0;
1809 DnsHeader
->Identification
= HTONS (DnsHeader
->Identification
);
1810 DnsHeader
->Flags
.Uint16
= HTONS (DnsHeader
->Flags
.Uint16
);
1811 DnsHeader
->QuestionsNum
= HTONS (DnsHeader
->QuestionsNum
);
1812 DnsHeader
->AnswersNum
= HTONS (DnsHeader
->AnswersNum
);
1813 DnsHeader
->AuthorityNum
= HTONS (DnsHeader
->AuthorityNum
);
1814 DnsHeader
->AditionalNum
= HTONS (DnsHeader
->AditionalNum
);
1816 Frag
.Len
= sizeof (*DnsHeader
);
1821 CopyMem (Frag
.Bulk
+ Frag
.Len
, QueryName
, AsciiStrLen (QueryName
));
1822 Frag
.Len
= (UINT32
) (Frag
.Len
+ AsciiStrLen (QueryName
));
1823 *(Frag
.Bulk
+ Frag
.Len
) = 0;
1827 // Rest query section
1829 DnsQuery
= (DNS_QUERY_SECTION
*) (Frag
.Bulk
+ Frag
.Len
);
1831 DnsQuery
->Type
= HTONS (Type
);
1832 DnsQuery
->Class
= HTONS (Class
);
1834 Frag
.Len
+= sizeof (*DnsQuery
);
1837 // Wrap the Frag in a net buffer.
1839 *Packet
= NetbufFromExt (&Frag
, 1, 0, 0, DnsDummyExtFree
, NULL
);
1840 if (*Packet
== NULL
) {
1841 FreePool (Frag
.Bulk
);
1842 return EFI_OUT_OF_RESOURCES
;
1846 // Store the UdpIo in ProtoData.
1848 *((UINTN
*) &((*Packet
)->ProtoData
[0])) = (UINTN
) (Instance
->UdpIo
);
1854 Retransmit the packet.
1856 @param Instance The DNS instance
1857 @param Packet Retransmit the packet
1859 @retval EFI_SUCCESS The packet is retransmitted.
1860 @retval Others Failed to retransmit.
1865 IN DNS_INSTANCE
*Instance
,
1873 ASSERT (Packet
!= NULL
);
1876 // Set the requests to the listening port, other packets to the connected port
1878 Buffer
= NetbufGetByte (Packet
, 0, NULL
);
1879 ASSERT (Buffer
!= NULL
);
1881 NET_GET_REF (Packet
);
1883 Status
= UdpIoSendDatagram (
1892 if (EFI_ERROR (Status
)) {
1893 NET_PUT_REF (Packet
);
1900 The timer ticking function for the DNS services.
1902 @param Event The ticking event
1903 @param Context The DNS service instance
1908 DnsOnTimerRetransmit (
1913 DNS_SERVICE
*Service
;
1918 DNS_INSTANCE
*Instance
;
1919 LIST_ENTRY
*EntryNetMap
;
1920 NET_MAP_ITEM
*ItemNetMap
;
1921 DNS4_TOKEN_ENTRY
*Dns4TokenEntry
;
1922 DNS6_TOKEN_ENTRY
*Dns6TokenEntry
;
1924 Dns4TokenEntry
= NULL
;
1925 Dns6TokenEntry
= NULL
;
1927 Service
= (DNS_SERVICE
*) Context
;
1930 if (Service
->IpVersion
== IP_VERSION_4
) {
1932 // Iterate through all the children of the DNS service instance. Time
1933 // out the packet. If maximum retries reached, clean the Token up.
1935 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Service
->Dns4ChildrenList
) {
1936 Instance
= NET_LIST_USER_STRUCT (Entry
, DNS_INSTANCE
, Link
);
1938 EntryNetMap
= Instance
->Dns4TxTokens
.Used
.ForwardLink
;
1939 while (EntryNetMap
!= &Instance
->Dns4TxTokens
.Used
) {
1940 ItemNetMap
= NET_LIST_USER_STRUCT (EntryNetMap
, NET_MAP_ITEM
, Link
);
1941 Dns4TokenEntry
= (DNS4_TOKEN_ENTRY
*)(ItemNetMap
->Key
);
1942 if (Dns4TokenEntry
->PacketToLive
== 0 || (--Dns4TokenEntry
->PacketToLive
> 0)) {
1943 EntryNetMap
= EntryNetMap
->ForwardLink
;
1948 // Retransmit the packet if haven't reach the maxmium retry count,
1949 // otherwise exit the transfer.
1951 if (++Dns4TokenEntry
->Token
->RetryCount
< Instance
->MaxRetry
) {
1952 DnsRetransmit (Instance
, (NET_BUF
*)ItemNetMap
->Value
);
1953 EntryNetMap
= EntryNetMap
->ForwardLink
;
1956 // Maximum retries reached, clean the Token up.
1958 Dns4RemoveTokenEntry (&Instance
->Dns4TxTokens
, Dns4TokenEntry
);
1959 Dns4TokenEntry
->Token
->Status
= EFI_TIMEOUT
;
1960 gBS
->SignalEvent (Dns4TokenEntry
->Token
->Event
);
1964 // Free the sending packet.
1966 if (ItemNetMap
->Value
!= NULL
) {
1967 NetbufFree ((NET_BUF
*)(ItemNetMap
->Value
));
1970 EntryNetMap
= Instance
->Dns4TxTokens
.Used
.ForwardLink
;
1976 // Iterate through all the children of the DNS service instance. Time
1977 // out the packet. If maximum retries reached, clean the Token up.
1979 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Service
->Dns6ChildrenList
) {
1980 Instance
= NET_LIST_USER_STRUCT (Entry
, DNS_INSTANCE
, Link
);
1982 EntryNetMap
= Instance
->Dns6TxTokens
.Used
.ForwardLink
;
1983 while (EntryNetMap
!= &Instance
->Dns6TxTokens
.Used
) {
1984 ItemNetMap
= NET_LIST_USER_STRUCT (EntryNetMap
, NET_MAP_ITEM
, Link
);
1985 Dns6TokenEntry
= (DNS6_TOKEN_ENTRY
*) (ItemNetMap
->Key
);
1986 if (Dns6TokenEntry
->PacketToLive
== 0 || (--Dns6TokenEntry
->PacketToLive
> 0)) {
1987 EntryNetMap
= EntryNetMap
->ForwardLink
;
1992 // Retransmit the packet if haven't reach the maxmium retry count,
1993 // otherwise exit the transfer.
1995 if (++Dns6TokenEntry
->Token
->RetryCount
< Instance
->MaxRetry
) {
1996 DnsRetransmit (Instance
, (NET_BUF
*) ItemNetMap
->Value
);
1997 EntryNetMap
= EntryNetMap
->ForwardLink
;
2000 // Maximum retries reached, clean the Token up.
2002 Dns6RemoveTokenEntry (&Instance
->Dns6TxTokens
, Dns6TokenEntry
);
2003 Dns6TokenEntry
->Token
->Status
= EFI_TIMEOUT
;
2004 gBS
->SignalEvent (Dns6TokenEntry
->Token
->Event
);
2008 // Free the sending packet.
2010 if (ItemNetMap
->Value
!= NULL
) {
2011 NetbufFree ((NET_BUF
*) (ItemNetMap
->Value
));
2014 EntryNetMap
= Instance
->Dns6TxTokens
.Used
.ForwardLink
;
2022 The timer ticking function for the DNS driver.
2024 @param Event The ticking event
2044 // Iterate through all the DNS4 cache list.
2046 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &mDriverData
->Dns4CacheList
) {
2047 Item4
= NET_LIST_USER_STRUCT (Entry
, DNS4_CACHE
, AllCacheLink
);
2048 Item4
->DnsCache
.Timeout
--;
2051 Entry
= mDriverData
->Dns4CacheList
.ForwardLink
;
2052 while (Entry
!= &mDriverData
->Dns4CacheList
) {
2053 Item4
= NET_LIST_USER_STRUCT (Entry
, DNS4_CACHE
, AllCacheLink
);
2054 if (Item4
->DnsCache
.Timeout
== 0) {
2055 RemoveEntryList (&Item4
->AllCacheLink
);
2056 Entry
= mDriverData
->Dns4CacheList
.ForwardLink
;
2058 Entry
= Entry
->ForwardLink
;
2063 // Iterate through all the DNS6 cache list.
2065 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &mDriverData
->Dns6CacheList
) {
2066 Item6
= NET_LIST_USER_STRUCT (Entry
, DNS6_CACHE
, AllCacheLink
);
2067 Item6
->DnsCache
.Timeout
--;
2070 Entry
= mDriverData
->Dns6CacheList
.ForwardLink
;
2071 while (Entry
!= &mDriverData
->Dns6CacheList
) {
2072 Item6
= NET_LIST_USER_STRUCT (Entry
, DNS6_CACHE
, AllCacheLink
);
2073 if (Item6
->DnsCache
.Timeout
== 0) {
2074 RemoveEntryList (&Item6
->AllCacheLink
);
2075 Entry
= mDriverData
->Dns6CacheList
.ForwardLink
;
2077 Entry
= Entry
->ForwardLink
;