2 DnsDxe support functions implementation.
4 Copyright (c) 2016, 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
.IsConfigured
) {
647 Udp
->Configure (Udp
, NULL
);
648 return (BOOLEAN
) (Udp
->Configure (Udp
, UdpCfgData
) == EFI_SUCCESS
);
659 @param Instance The DNS session
660 @param UdpIo The UDP_IO instance
662 @retval EFI_SUCCESS The UDP is successfully configured for the
668 IN DNS_INSTANCE
*Instance
,
672 EFI_DNS4_CONFIG_DATA
*Config
;
673 EFI_UDP4_CONFIG_DATA UdpConfig
;
676 Config
= &Instance
->Dns4CfgData
;
678 UdpConfig
.AcceptBroadcast
= FALSE
;
679 UdpConfig
.AcceptPromiscuous
= FALSE
;
680 UdpConfig
.AcceptAnyPort
= FALSE
;
681 UdpConfig
.AllowDuplicatePort
= FALSE
;
682 UdpConfig
.TypeOfService
= 0;
683 UdpConfig
.TimeToLive
= 128;
684 UdpConfig
.DoNotFragment
= FALSE
;
685 UdpConfig
.ReceiveTimeout
= 0;
686 UdpConfig
.TransmitTimeout
= 0;
687 UdpConfig
.UseDefaultAddress
= Config
->UseDefaultSetting
;
688 UdpConfig
.SubnetMask
= Config
->SubnetMask
;
689 UdpConfig
.StationPort
= Config
->LocalPort
;
690 UdpConfig
.RemotePort
= DNS_SERVER_PORT
;
692 CopyMem (&UdpConfig
.StationAddress
, &Config
->StationIp
, sizeof (EFI_IPv4_ADDRESS
));
693 CopyMem (&UdpConfig
.RemoteAddress
, &Instance
->SessionDnsServer
.v4
, sizeof (EFI_IPv4_ADDRESS
));
695 Status
= UdpIo
->Protocol
.Udp4
->Configure (UdpIo
->Protocol
.Udp4
, &UdpConfig
);
697 if ((Status
== EFI_NO_MAPPING
) && Dns4GetMapping (Instance
, UdpIo
, &UdpConfig
)) {
707 @param Instance The DNS session
708 @param UdpIo The UDP_IO instance
710 @retval EFI_SUCCESS The UDP is successfully configured for the
716 IN DNS_INSTANCE
*Instance
,
720 EFI_DNS6_CONFIG_DATA
*Config
;
721 EFI_UDP6_CONFIG_DATA UdpConfig
;
724 Config
= &Instance
->Dns6CfgData
;
726 UdpConfig
.AcceptPromiscuous
= FALSE
;
727 UdpConfig
.AcceptAnyPort
= FALSE
;
728 UdpConfig
.AllowDuplicatePort
= FALSE
;
729 UdpConfig
.TrafficClass
= 0;
730 UdpConfig
.HopLimit
= 128;
731 UdpConfig
.ReceiveTimeout
= 0;
732 UdpConfig
.TransmitTimeout
= 0;
733 UdpConfig
.StationPort
= Config
->LocalPort
;
734 UdpConfig
.RemotePort
= DNS_SERVER_PORT
;
735 CopyMem (&UdpConfig
.StationAddress
, &Config
->StationIp
, sizeof (EFI_IPv6_ADDRESS
));
736 CopyMem (&UdpConfig
.RemoteAddress
, &Instance
->SessionDnsServer
.v6
, sizeof (EFI_IPv6_ADDRESS
));
738 Status
= UdpIo
->Protocol
.Udp6
->Configure (UdpIo
->Protocol
.Udp6
, &UdpConfig
);
740 if ((Status
== EFI_NO_MAPPING
) && Dns6GetMapping (Instance
, UdpIo
, &UdpConfig
)) {
748 Update Dns4 cache to shared list of caches of all DNSv4 instances.
750 @param Dns4CacheList All Dns4 cache list.
751 @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache.
752 If TRUE, this function will delete matching DNS Cache entry.
753 @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
754 If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
755 @param DnsCacheEntry Entry Pointer to DNS Cache entry.
757 @retval EFI_SUCCESS Update Dns4 cache successfully.
758 @retval Others Failed to update Dns4 cache.
764 IN LIST_ENTRY
*Dns4CacheList
,
765 IN BOOLEAN DeleteFlag
,
767 IN EFI_DNS4_CACHE_ENTRY DnsCacheEntry
770 DNS4_CACHE
*NewDnsCache
;
779 // Search the database for the matching EFI_DNS_CACHE_ENTRY
781 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Dns4CacheList
) {
782 Item
= NET_LIST_USER_STRUCT (Entry
, DNS4_CACHE
, AllCacheLink
);
783 if (StrCmp (DnsCacheEntry
.HostName
, Item
->DnsCache
.HostName
) == 0 && \
784 CompareMem (DnsCacheEntry
.IpAddress
, Item
->DnsCache
.IpAddress
, sizeof (EFI_IPv4_ADDRESS
)) == 0) {
786 // This is the Dns cache entry
790 // Delete matching DNS Cache entry
792 RemoveEntryList (&Item
->AllCacheLink
);
795 } else if (Override
) {
799 Item
->DnsCache
.Timeout
= DnsCacheEntry
.Timeout
;
803 return EFI_ACCESS_DENIED
;
811 NewDnsCache
= AllocatePool (sizeof (DNS4_CACHE
));
812 if (NewDnsCache
== NULL
) {
813 return EFI_OUT_OF_RESOURCES
;
816 InitializeListHead (&NewDnsCache
->AllCacheLink
);
818 NewDnsCache
->DnsCache
.HostName
= AllocatePool (StrSize (DnsCacheEntry
.HostName
));
819 if (NewDnsCache
->DnsCache
.HostName
== NULL
) {
820 return EFI_OUT_OF_RESOURCES
;
823 CopyMem (NewDnsCache
->DnsCache
.HostName
, DnsCacheEntry
.HostName
, StrSize (DnsCacheEntry
.HostName
));
825 NewDnsCache
->DnsCache
.IpAddress
= AllocatePool (sizeof (EFI_IPv4_ADDRESS
));
826 if (NewDnsCache
->DnsCache
.IpAddress
== NULL
) {
827 return EFI_OUT_OF_RESOURCES
;
830 CopyMem (NewDnsCache
->DnsCache
.IpAddress
, DnsCacheEntry
.IpAddress
, sizeof (EFI_IPv4_ADDRESS
));
832 NewDnsCache
->DnsCache
.Timeout
= DnsCacheEntry
.Timeout
;
834 InsertTailList (Dns4CacheList
, &NewDnsCache
->AllCacheLink
);
840 Update Dns6 cache to shared list of caches of all DNSv6 instances.
842 @param Dns6CacheList All Dns6 cache list.
843 @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache.
844 If TRUE, this function will delete matching DNS Cache entry.
845 @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
846 If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
847 @param DnsCacheEntry Entry Pointer to DNS Cache entry.
849 @retval EFI_SUCCESS Update Dns6 cache successfully.
850 @retval Others Failed to update Dns6 cache.
855 IN LIST_ENTRY
*Dns6CacheList
,
856 IN BOOLEAN DeleteFlag
,
858 IN EFI_DNS6_CACHE_ENTRY DnsCacheEntry
861 DNS6_CACHE
*NewDnsCache
;
870 // Search the database for the matching EFI_DNS_CACHE_ENTRY
872 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Dns6CacheList
) {
873 Item
= NET_LIST_USER_STRUCT (Entry
, DNS6_CACHE
, AllCacheLink
);
874 if (StrCmp (DnsCacheEntry
.HostName
, Item
->DnsCache
.HostName
) == 0 && \
875 CompareMem (DnsCacheEntry
.IpAddress
, Item
->DnsCache
.IpAddress
, sizeof (EFI_IPv6_ADDRESS
)) == 0) {
877 // This is the Dns cache entry
881 // Delete matching DNS Cache entry
883 RemoveEntryList (&Item
->AllCacheLink
);
886 } else if (Override
) {
890 Item
->DnsCache
.Timeout
= DnsCacheEntry
.Timeout
;
894 return EFI_ACCESS_DENIED
;
902 NewDnsCache
= AllocatePool (sizeof (DNS6_CACHE
));
903 if (NewDnsCache
== NULL
) {
904 return EFI_OUT_OF_RESOURCES
;
907 InitializeListHead (&NewDnsCache
->AllCacheLink
);
909 NewDnsCache
->DnsCache
.HostName
= AllocatePool (StrSize (DnsCacheEntry
.HostName
));
910 if (NewDnsCache
->DnsCache
.HostName
== NULL
) {
911 return EFI_OUT_OF_RESOURCES
;
914 CopyMem (NewDnsCache
->DnsCache
.HostName
, DnsCacheEntry
.HostName
, StrSize (DnsCacheEntry
.HostName
));
916 NewDnsCache
->DnsCache
.IpAddress
= AllocatePool (sizeof (EFI_IPv6_ADDRESS
));
917 if (NewDnsCache
->DnsCache
.IpAddress
== NULL
) {
918 return EFI_OUT_OF_RESOURCES
;
921 CopyMem (NewDnsCache
->DnsCache
.IpAddress
, DnsCacheEntry
.IpAddress
, sizeof (EFI_IPv6_ADDRESS
));
923 NewDnsCache
->DnsCache
.Timeout
= DnsCacheEntry
.Timeout
;
925 InsertTailList (Dns6CacheList
, &NewDnsCache
->AllCacheLink
);
931 Add Dns4 ServerIp to common list of addresses of all configured DNSv4 server.
933 @param Dns4ServerList Common list of addresses of all configured DNSv4 server.
934 @param ServerIp DNS server Ip.
936 @retval EFI_SUCCESS Add Dns4 ServerIp to common list successfully.
937 @retval Others Failed to add Dns4 ServerIp to common list.
943 IN LIST_ENTRY
*Dns4ServerList
,
944 IN EFI_IPv4_ADDRESS ServerIp
947 DNS4_SERVER_IP
*NewServerIp
;
948 DNS4_SERVER_IP
*Item
;
956 // Search the database for the matching ServerIp
958 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Dns4ServerList
) {
959 Item
= NET_LIST_USER_STRUCT (Entry
, DNS4_SERVER_IP
, AllServerLink
);
960 if (CompareMem (&Item
->Dns4ServerIp
, &ServerIp
, sizeof (EFI_IPv4_ADDRESS
)) == 0) {
971 NewServerIp
= AllocatePool (sizeof (DNS4_SERVER_IP
));
972 if (NewServerIp
== NULL
) {
973 return EFI_OUT_OF_RESOURCES
;
976 InitializeListHead (&NewServerIp
->AllServerLink
);
978 CopyMem (&NewServerIp
->Dns4ServerIp
, &ServerIp
, sizeof (EFI_IPv4_ADDRESS
));
980 InsertTailList (Dns4ServerList
, &NewServerIp
->AllServerLink
);
986 Add Dns6 ServerIp to common list of addresses of all configured DNSv6 server.
988 @param Dns6ServerList Common list of addresses of all configured DNSv6 server.
989 @param ServerIp DNS server Ip.
991 @retval EFI_SUCCESS Add Dns6 ServerIp to common list successfully.
992 @retval Others Failed to add Dns6 ServerIp to common list.
998 IN LIST_ENTRY
*Dns6ServerList
,
999 IN EFI_IPv6_ADDRESS ServerIp
1002 DNS6_SERVER_IP
*NewServerIp
;
1003 DNS6_SERVER_IP
*Item
;
1011 // Search the database for the matching ServerIp
1013 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Dns6ServerList
) {
1014 Item
= NET_LIST_USER_STRUCT (Entry
, DNS6_SERVER_IP
, AllServerLink
);
1015 if (CompareMem (&Item
->Dns6ServerIp
, &ServerIp
, sizeof (EFI_IPv6_ADDRESS
)) == 0) {
1026 NewServerIp
= AllocatePool (sizeof (DNS6_SERVER_IP
));
1027 if (NewServerIp
== NULL
) {
1028 return EFI_OUT_OF_RESOURCES
;
1031 InitializeListHead (&NewServerIp
->AllServerLink
);
1033 CopyMem (&NewServerIp
->Dns6ServerIp
, &ServerIp
, sizeof (EFI_IPv6_ADDRESS
));
1035 InsertTailList (Dns6ServerList
, &NewServerIp
->AllServerLink
);
1041 Find out whether the response is valid or invalid.
1043 @param TokensMap All DNS transmittal Tokens entry.
1044 @param Identification Identification for queried packet.
1045 @param Type Type for queried packet.
1046 @param Class Class for queried packet.
1047 @param Item Return corresponding Token entry.
1049 @retval TRUE The response is valid.
1050 @retval FALSE The response is invalid.
1054 IsValidDnsResponse (
1055 IN NET_MAP
*TokensMap
,
1056 IN UINT16 Identification
,
1059 OUT NET_MAP_ITEM
**Item
1066 DNS_HEADER
*DnsHeader
;
1068 DNS_QUERY_SECTION
*QuerySection
;
1070 NET_LIST_FOR_EACH (Entry
, &TokensMap
->Used
) {
1071 *Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
1072 Packet
= (NET_BUF
*) ((*Item
)->Value
);
1073 if (Packet
== NULL
){
1077 TxString
= NetbufGetByte (Packet
, 0, NULL
);
1078 ASSERT (TxString
!= NULL
);
1079 DnsHeader
= (DNS_HEADER
*) TxString
;
1080 QueryName
= (CHAR8
*) (TxString
+ sizeof (*DnsHeader
));
1081 QuerySection
= (DNS_QUERY_SECTION
*) (QueryName
+ AsciiStrLen (QueryName
) + 1);
1083 if (NTOHS (DnsHeader
->Identification
) == Identification
&&
1084 NTOHS (QuerySection
->Type
) == Type
&&
1085 NTOHS (QuerySection
->Class
) == Class
) {
1099 @param Instance The DNS instance
1100 @param RxString Received buffer.
1101 @param Completed Flag to indicate that Dns response is valid.
1103 @retval EFI_SUCCESS Parse Dns Response successfully.
1104 @retval Others Failed to parse Dns Response.
1109 IN OUT DNS_INSTANCE
*Instance
,
1111 OUT BOOLEAN
*Completed
1114 DNS_HEADER
*DnsHeader
;
1117 DNS_QUERY_SECTION
*QuerySection
;
1120 DNS_ANSWER_SECTION
*AnswerSection
;
1124 DNS4_TOKEN_ENTRY
*Dns4TokenEntry
;
1125 DNS6_TOKEN_ENTRY
*Dns6TokenEntry
;
1129 UINT32 AnswerSectionNum
;
1132 EFI_IPv4_ADDRESS
*HostAddr4
;
1133 EFI_IPv6_ADDRESS
*HostAddr6
;
1135 EFI_DNS4_CACHE_ENTRY
*Dns4CacheEntry
;
1136 EFI_DNS6_CACHE_ENTRY
*Dns6CacheEntry
;
1138 DNS_RESOURCE_RECORD
*Dns4RR
;
1139 DNS6_RESOURCE_RECORD
*Dns6RR
;
1146 Dns4TokenEntry
= NULL
;
1147 Dns6TokenEntry
= NULL
;
1151 AnswerSectionNum
= 0;
1157 Dns4CacheEntry
= NULL
;
1158 Dns6CacheEntry
= NULL
;
1164 Status
= EFI_SUCCESS
;
1169 DnsHeader
= (DNS_HEADER
*) RxString
;
1171 DnsHeader
->Identification
= NTOHS (DnsHeader
->Identification
);
1172 DnsHeader
->Flags
.Uint16
= NTOHS (DnsHeader
->Flags
.Uint16
);
1173 DnsHeader
->QuestionsNum
= NTOHS (DnsHeader
->QuestionsNum
);
1174 DnsHeader
->AnswersNum
= NTOHS (DnsHeader
->AnswersNum
);
1175 DnsHeader
->AuthorityNum
= NTOHS (DnsHeader
->AuthorityNum
);
1176 DnsHeader
->AditionalNum
= NTOHS (DnsHeader
->AditionalNum
);
1181 QueryName
= (CHAR8
*) (RxString
+ sizeof (*DnsHeader
));
1184 // Get query section
1186 QuerySection
= (DNS_QUERY_SECTION
*) (QueryName
+ AsciiStrLen (QueryName
) + 1);
1187 QuerySection
->Type
= NTOHS (QuerySection
->Type
);
1188 QuerySection
->Class
= NTOHS (QuerySection
->Class
);
1193 AnswerName
= (CHAR8
*) QuerySection
+ sizeof (*QuerySection
);
1195 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1198 // Check DnsResponse Validity, if so, also get a valid NET_MAP_ITEM.
1200 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1201 if (!IsValidDnsResponse (
1202 &Instance
->Dns4TxTokens
,
1203 DnsHeader
->Identification
,
1205 QuerySection
->Class
,
1209 Status
= EFI_ABORTED
;
1212 ASSERT (Item
!= NULL
);
1213 Dns4TokenEntry
= (DNS4_TOKEN_ENTRY
*) (Item
->Key
);
1215 if (!IsValidDnsResponse (
1216 &Instance
->Dns6TxTokens
,
1217 DnsHeader
->Identification
,
1219 QuerySection
->Class
,
1223 Status
= EFI_ABORTED
;
1226 ASSERT (Item
!= NULL
);
1227 Dns6TokenEntry
= (DNS6_TOKEN_ENTRY
*) (Item
->Key
);
1231 // Continue Check Some Errors.
1233 if (DnsHeader
->Flags
.Bits
.RCode
!= DNS_FLAGS_RCODE_NO_ERROR
|| DnsHeader
->AnswersNum
< 1 || \
1234 DnsHeader
->Flags
.Bits
.QR
!= DNS_FLAGS_QR_RESPONSE
) {
1235 Status
= EFI_ABORTED
;
1240 // Do some buffer allocations.
1242 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1243 ASSERT (Dns4TokenEntry
!= NULL
);
1245 if (Dns4TokenEntry
->GeneralLookUp
) {
1247 // It's the GeneralLookUp querying.
1249 Dns4TokenEntry
->Token
->RspData
.GLookupData
= AllocatePool (sizeof (DNS_RESOURCE_RECORD
));
1250 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
== NULL
) {
1251 Status
= EFI_OUT_OF_RESOURCES
;
1254 Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
= AllocatePool (DnsHeader
->AnswersNum
* sizeof (DNS_RESOURCE_RECORD
));
1255 if (Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
== NULL
) {
1256 Status
= EFI_OUT_OF_RESOURCES
;
1261 // It's not the GeneralLookUp querying. Check the Query type.
1263 if (QuerySection
->Type
== DNS_TYPE_A
) {
1264 Dns4TokenEntry
->Token
->RspData
.H2AData
= AllocatePool (sizeof (DNS_HOST_TO_ADDR_DATA
));
1265 if (Dns4TokenEntry
->Token
->RspData
.H2AData
== NULL
) {
1266 Status
= EFI_OUT_OF_RESOURCES
;
1269 Dns4TokenEntry
->Token
->RspData
.H2AData
->IpList
= AllocatePool (DnsHeader
->AnswersNum
* sizeof (EFI_IPv4_ADDRESS
));
1270 if (Dns4TokenEntry
->Token
->RspData
.H2AData
->IpList
== NULL
) {
1271 Status
= EFI_OUT_OF_RESOURCES
;
1275 Status
= EFI_UNSUPPORTED
;
1280 ASSERT (Dns6TokenEntry
!= NULL
);
1282 if (Dns6TokenEntry
->GeneralLookUp
) {
1284 // It's the GeneralLookUp querying.
1286 Dns6TokenEntry
->Token
->RspData
.GLookupData
= AllocatePool (sizeof (DNS_RESOURCE_RECORD
));
1287 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
== NULL
) {
1288 Status
= EFI_OUT_OF_RESOURCES
;
1291 Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
= AllocatePool (DnsHeader
->AnswersNum
* sizeof (DNS_RESOURCE_RECORD
));
1292 if (Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
== NULL
) {
1293 Status
= EFI_OUT_OF_RESOURCES
;
1298 // It's not the GeneralLookUp querying. Check the Query type.
1300 if (QuerySection
->Type
== DNS_TYPE_AAAA
) {
1301 Dns6TokenEntry
->Token
->RspData
.H2AData
= AllocatePool (sizeof (DNS6_HOST_TO_ADDR_DATA
));
1302 if (Dns6TokenEntry
->Token
->RspData
.H2AData
== NULL
) {
1303 Status
= EFI_OUT_OF_RESOURCES
;
1306 Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
= AllocatePool (DnsHeader
->AnswersNum
* sizeof (EFI_IPv6_ADDRESS
));
1307 if (Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
== NULL
) {
1308 Status
= EFI_OUT_OF_RESOURCES
;
1312 Status
= EFI_UNSUPPORTED
;
1318 Status
= EFI_NOT_FOUND
;
1321 // Processing AnswerSection.
1323 while (AnswerSectionNum
< DnsHeader
->AnswersNum
) {
1325 // Answer name should be PTR.
1327 ASSERT ((*(UINT8
*) AnswerName
& 0xC0) == 0xC0);
1330 // Get Answer section.
1332 AnswerSection
= (DNS_ANSWER_SECTION
*) (AnswerName
+ sizeof (UINT16
));
1333 AnswerSection
->Type
= NTOHS (AnswerSection
->Type
);
1334 AnswerSection
->Class
= NTOHS (AnswerSection
->Class
);
1335 AnswerSection
->Ttl
= NTOHL (AnswerSection
->Ttl
);
1336 AnswerSection
->DataLength
= NTOHS (AnswerSection
->DataLength
);
1339 // Check whether it's the GeneralLookUp querying.
1341 if (Instance
->Service
->IpVersion
== IP_VERSION_4
&& Dns4TokenEntry
->GeneralLookUp
) {
1342 Dns4RR
= Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRList
;
1343 AnswerData
= (UINT8
*) AnswerSection
+ sizeof (*AnswerSection
);
1346 // Fill the ResourceRecord.
1348 Dns4RR
[RRCount
].QName
= AllocateZeroPool (AsciiStrLen (QueryName
) + 1);
1349 if (Dns4RR
[RRCount
].QName
== NULL
) {
1350 Status
= EFI_OUT_OF_RESOURCES
;
1353 CopyMem (Dns4RR
[RRCount
].QName
, QueryName
, AsciiStrLen (QueryName
));
1354 Dns4RR
[RRCount
].QType
= AnswerSection
->Type
;
1355 Dns4RR
[RRCount
].QClass
= AnswerSection
->Class
;
1356 Dns4RR
[RRCount
].TTL
= AnswerSection
->Ttl
;
1357 Dns4RR
[RRCount
].DataLength
= AnswerSection
->DataLength
;
1358 Dns4RR
[RRCount
].RData
= AllocateZeroPool (Dns4RR
[RRCount
].DataLength
);
1359 if (Dns4RR
[RRCount
].RData
== NULL
) {
1360 Status
= EFI_OUT_OF_RESOURCES
;
1363 CopyMem (Dns4RR
[RRCount
].RData
, AnswerData
, Dns4RR
[RRCount
].DataLength
);
1366 Status
= EFI_SUCCESS
;
1367 } else if (Instance
->Service
->IpVersion
== IP_VERSION_6
&& Dns6TokenEntry
->GeneralLookUp
) {
1368 Dns6RR
= Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRList
;
1369 AnswerData
= (UINT8
*) AnswerSection
+ sizeof (*AnswerSection
);
1372 // Fill the ResourceRecord.
1374 Dns6RR
[RRCount
].QName
= AllocateZeroPool (AsciiStrLen (QueryName
) + 1);
1375 if (Dns6RR
[RRCount
].QName
== NULL
) {
1376 Status
= EFI_OUT_OF_RESOURCES
;
1379 CopyMem (Dns6RR
[RRCount
].QName
, QueryName
, AsciiStrLen (QueryName
));
1380 Dns6RR
[RRCount
].QType
= AnswerSection
->Type
;
1381 Dns6RR
[RRCount
].QClass
= AnswerSection
->Class
;
1382 Dns6RR
[RRCount
].TTL
= AnswerSection
->Ttl
;
1383 Dns6RR
[RRCount
].DataLength
= AnswerSection
->DataLength
;
1384 Dns6RR
[RRCount
].RData
= AllocateZeroPool (Dns6RR
[RRCount
].DataLength
);
1385 if (Dns6RR
[RRCount
].RData
== NULL
) {
1386 Status
= EFI_OUT_OF_RESOURCES
;
1389 CopyMem (Dns6RR
[RRCount
].RData
, AnswerData
, Dns6RR
[RRCount
].DataLength
);
1392 Status
= EFI_SUCCESS
;
1395 // It's not the GeneralLookUp querying.
1396 // Check the Query type, parse the response packet.
1398 switch (AnswerSection
->Type
) {
1401 // This is address entry, get Data.
1403 ASSERT (Dns4TokenEntry
!= NULL
&& AnswerSection
->DataLength
== 4);
1405 HostAddr4
= Dns4TokenEntry
->Token
->RspData
.H2AData
->IpList
;
1406 AnswerData
= (UINT8
*) AnswerSection
+ sizeof (*AnswerSection
);
1407 CopyMem (&HostAddr4
[IpCount
], AnswerData
, sizeof (EFI_IPv4_ADDRESS
));
1410 // Update DNS cache dynamically.
1412 if (Dns4CacheEntry
!= NULL
) {
1413 if (Dns4CacheEntry
->HostName
!= NULL
) {
1414 FreePool (Dns4CacheEntry
->HostName
);
1417 if (Dns4CacheEntry
->IpAddress
!= NULL
) {
1418 FreePool (Dns4CacheEntry
->IpAddress
);
1421 FreePool (Dns4CacheEntry
);
1425 // Allocate new CacheEntry pool.
1427 Dns4CacheEntry
= AllocateZeroPool (sizeof (EFI_DNS4_CACHE_ENTRY
));
1428 if (Dns4CacheEntry
== NULL
) {
1429 Status
= EFI_OUT_OF_RESOURCES
;
1432 Dns4CacheEntry
->HostName
= AllocateZeroPool (2 * (StrLen(Dns4TokenEntry
->QueryHostName
) + 1));
1433 if (Dns4CacheEntry
->HostName
== NULL
) {
1434 Status
= EFI_OUT_OF_RESOURCES
;
1437 CopyMem (Dns4CacheEntry
->HostName
, Dns4TokenEntry
->QueryHostName
, 2 * (StrLen(Dns4TokenEntry
->QueryHostName
) + 1));
1438 Dns4CacheEntry
->IpAddress
= AllocateZeroPool (sizeof (EFI_IPv4_ADDRESS
));
1439 if (Dns4CacheEntry
->IpAddress
== NULL
) {
1440 Status
= EFI_OUT_OF_RESOURCES
;
1443 CopyMem (Dns4CacheEntry
->IpAddress
, AnswerData
, sizeof (EFI_IPv4_ADDRESS
));
1445 if (CNameTtl
!= 0 && AnswerSection
->Ttl
!= 0) {
1446 Dns4CacheEntry
->Timeout
= MIN (CNameTtl
, AnswerSection
->Ttl
);
1448 Dns4CacheEntry
->Timeout
= MAX (CNameTtl
, AnswerSection
->Ttl
);
1451 UpdateDns4Cache (&mDriverData
->Dns4CacheList
, FALSE
, TRUE
, *Dns4CacheEntry
);
1454 Status
= EFI_SUCCESS
;
1458 // This is address entry, get Data.
1460 ASSERT (Dns6TokenEntry
!= NULL
&& AnswerSection
->DataLength
== 16);
1462 HostAddr6
= Dns6TokenEntry
->Token
->RspData
.H2AData
->IpList
;
1463 AnswerData
= (UINT8
*) AnswerSection
+ sizeof (*AnswerSection
);
1464 CopyMem (&HostAddr6
[IpCount
], AnswerData
, sizeof (EFI_IPv6_ADDRESS
));
1467 // Update DNS cache dynamically.
1469 if (Dns6CacheEntry
!= NULL
) {
1470 if (Dns6CacheEntry
->HostName
!= NULL
) {
1471 FreePool (Dns6CacheEntry
->HostName
);
1474 if (Dns6CacheEntry
->IpAddress
!= NULL
) {
1475 FreePool (Dns6CacheEntry
->IpAddress
);
1478 FreePool (Dns6CacheEntry
);
1482 // Allocate new CacheEntry pool.
1484 Dns6CacheEntry
= AllocateZeroPool (sizeof (EFI_DNS6_CACHE_ENTRY
));
1485 if (Dns6CacheEntry
== NULL
) {
1486 Status
= EFI_OUT_OF_RESOURCES
;
1489 Dns6CacheEntry
->HostName
= AllocateZeroPool (2 * (StrLen(Dns6TokenEntry
->QueryHostName
) + 1));
1490 if (Dns6CacheEntry
->HostName
== NULL
) {
1491 Status
= EFI_OUT_OF_RESOURCES
;
1494 CopyMem (Dns6CacheEntry
->HostName
, Dns6TokenEntry
->QueryHostName
, 2 * (StrLen(Dns6TokenEntry
->QueryHostName
) + 1));
1495 Dns6CacheEntry
->IpAddress
= AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS
));
1496 if (Dns6CacheEntry
->IpAddress
== NULL
) {
1497 Status
= EFI_OUT_OF_RESOURCES
;
1500 CopyMem (Dns6CacheEntry
->IpAddress
, AnswerData
, sizeof (EFI_IPv6_ADDRESS
));
1502 if (CNameTtl
!= 0 && AnswerSection
->Ttl
!= 0) {
1503 Dns6CacheEntry
->Timeout
= MIN (CNameTtl
, AnswerSection
->Ttl
);
1505 Dns6CacheEntry
->Timeout
= MAX (CNameTtl
, AnswerSection
->Ttl
);
1508 UpdateDns6Cache (&mDriverData
->Dns6CacheList
, FALSE
, TRUE
, *Dns6CacheEntry
);
1511 Status
= EFI_SUCCESS
;
1513 case DNS_TYPE_CNAME
:
1515 // According RFC 1034 - 3.6.2, if the query name is an alias, the name server will include the CNAME
1516 // record in the response and restart the query at the domain name specified in the data field of the
1517 // CNAME record. So, just record the TTL value of the CNAME, then skip to parse the next record.
1519 CNameTtl
= AnswerSection
->Ttl
;
1522 Status
= EFI_UNSUPPORTED
;
1530 AnswerName
= (CHAR8
*) AnswerSection
+ sizeof (*AnswerSection
) + AnswerSection
->DataLength
;
1531 AnswerSectionNum
++;
1534 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1535 ASSERT (Dns4TokenEntry
!= NULL
);
1537 if (Dns4TokenEntry
->GeneralLookUp
) {
1538 Dns4TokenEntry
->Token
->RspData
.GLookupData
->RRCount
= RRCount
;
1540 if (QuerySection
->Type
== DNS_TYPE_A
) {
1541 Dns4TokenEntry
->Token
->RspData
.H2AData
->IpCount
= IpCount
;
1543 Status
= EFI_UNSUPPORTED
;
1548 ASSERT (Dns6TokenEntry
!= NULL
);
1550 if (Dns6TokenEntry
->GeneralLookUp
) {
1551 Dns6TokenEntry
->Token
->RspData
.GLookupData
->RRCount
= RRCount
;
1553 if (QuerySection
->Type
== DNS_TYPE_AAAA
) {
1554 Dns6TokenEntry
->Token
->RspData
.H2AData
->IpCount
= IpCount
;
1556 Status
= EFI_UNSUPPORTED
;
1563 // Parsing is complete, free the sending packet and signal Event here.
1565 if (Item
!= NULL
&& Item
->Value
!= NULL
) {
1566 NetbufFree ((NET_BUF
*) (Item
->Value
));
1569 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1570 ASSERT (Dns4TokenEntry
!= NULL
);
1571 Dns4RemoveTokenEntry (&Instance
->Dns4TxTokens
, Dns4TokenEntry
);
1572 Dns4TokenEntry
->Token
->Status
= Status
;
1573 if (Dns4TokenEntry
->Token
->Event
!= NULL
) {
1574 gBS
->SignalEvent (Dns4TokenEntry
->Token
->Event
);
1578 ASSERT (Dns6TokenEntry
!= NULL
);
1579 Dns6RemoveTokenEntry (&Instance
->Dns6TxTokens
, Dns6TokenEntry
);
1580 Dns6TokenEntry
->Token
->Status
= Status
;
1581 if (Dns6TokenEntry
->Token
->Event
!= NULL
) {
1582 gBS
->SignalEvent (Dns6TokenEntry
->Token
->Event
);
1588 // Free allocated CacheEntry pool.
1590 if (Dns4CacheEntry
!= NULL
) {
1591 if (Dns4CacheEntry
->HostName
!= NULL
) {
1592 FreePool (Dns4CacheEntry
->HostName
);
1595 if (Dns4CacheEntry
->IpAddress
!= NULL
) {
1596 FreePool (Dns4CacheEntry
->IpAddress
);
1599 FreePool (Dns4CacheEntry
);
1602 if (Dns6CacheEntry
!= NULL
) {
1603 if (Dns6CacheEntry
->HostName
!= NULL
) {
1604 FreePool (Dns6CacheEntry
->HostName
);
1607 if (Dns6CacheEntry
->IpAddress
!= NULL
) {
1608 FreePool (Dns6CacheEntry
->IpAddress
);
1611 FreePool (Dns6CacheEntry
);
1615 gBS
->RestoreTPL (OldTpl
);
1620 Parse response packet.
1622 @param Packet The packets received.
1623 @param EndPoint The local/remote UDP access point
1624 @param IoStatus The status of the UDP receive
1625 @param Context The opaque parameter to the function.
1630 DnsOnPacketReceived (
1632 UDP_END_POINT
*EndPoint
,
1633 EFI_STATUS IoStatus
,
1637 DNS_INSTANCE
*Instance
;
1643 Instance
= (DNS_INSTANCE
*) Context
;
1644 NET_CHECK_SIGNATURE (Instance
, DNS_INSTANCE_SIGNATURE
);
1649 if (EFI_ERROR (IoStatus
)) {
1653 ASSERT (Packet
!= NULL
);
1655 if (Packet
->TotalSize
<= sizeof (DNS_HEADER
)) {
1659 RcvString
= NetbufGetByte (Packet
, 0, NULL
);
1660 ASSERT (RcvString
!= NULL
);
1663 // Parse Dns Response
1665 ParseDnsResponse (Instance
, RcvString
, &Completed
);
1669 if (Packet
!= NULL
) {
1670 NetbufFree (Packet
);
1674 UdpIoRecvDatagram (Instance
->UdpIo
, DnsOnPacketReceived
, Instance
, 0);
1679 Release the net buffer when packet is sent.
1681 @param Packet The packets received.
1682 @param EndPoint The local/remote UDP access point
1683 @param IoStatus The status of the UDP receive
1684 @param Context The opaque parameter to the function.
1691 UDP_END_POINT
*EndPoint
,
1692 EFI_STATUS IoStatus
,
1696 DNS_INSTANCE
*Instance
;
1699 DNS4_TOKEN_ENTRY
*Dns4TokenEntry
;
1700 DNS6_TOKEN_ENTRY
*Dns6TokenEntry
;
1702 Dns4TokenEntry
= NULL
;
1703 Dns6TokenEntry
= NULL
;
1705 Instance
= (DNS_INSTANCE
*) Context
;
1706 NET_CHECK_SIGNATURE (Instance
, DNS_INSTANCE_SIGNATURE
);
1708 if (Instance
->Service
->IpVersion
== IP_VERSION_4
) {
1709 NET_LIST_FOR_EACH (Entry
, &Instance
->Dns4TxTokens
.Used
) {
1710 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
1711 if (Packet
== (NET_BUF
*)(Item
->Value
)) {
1712 Dns4TokenEntry
= ((DNS4_TOKEN_ENTRY
*)Item
->Key
);
1713 Dns4TokenEntry
->PacketToLive
= Dns4TokenEntry
->Token
->RetryInterval
;
1718 NET_LIST_FOR_EACH (Entry
, &Instance
->Dns6TxTokens
.Used
) {
1719 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
1720 if (Packet
== (NET_BUF
*)(Item
->Value
)) {
1721 Dns6TokenEntry
= ((DNS6_TOKEN_ENTRY
*)Item
->Key
);
1722 Dns6TokenEntry
->PacketToLive
= Dns6TokenEntry
->Token
->RetryInterval
;
1728 NetbufFree (Packet
);
1732 Query request information.
1734 @param Instance The DNS instance
1735 @param Packet The packet for querying request information.
1737 @retval EFI_SUCCESS Query request information successfully.
1738 @retval Others Failed to query request information.
1743 IN DNS_INSTANCE
*Instance
,
1750 // Ready to receive the DNS response.
1752 if (Instance
->UdpIo
->RecvRequest
== NULL
) {
1753 Status
= UdpIoRecvDatagram (Instance
->UdpIo
, DnsOnPacketReceived
, Instance
, 0);
1754 if (EFI_ERROR (Status
)) {
1760 // Transmit the DNS packet.
1762 NET_GET_REF (Packet
);
1764 Status
= UdpIoSendDatagram (Instance
->UdpIo
, Packet
, NULL
, NULL
, DnsOnPacketSent
, Instance
);
1770 Construct the Packet according query section.
1772 @param Instance The DNS instance
1773 @param QueryName Queried Name
1774 @param Type Queried Type
1775 @param Class Queried Class
1776 @param Packet The packet for query
1778 @retval EFI_SUCCESS The packet is constructed.
1779 @retval Others Failed to construct the Packet.
1784 IN DNS_INSTANCE
*Instance
,
1785 IN CHAR8
*QueryName
,
1788 OUT NET_BUF
**Packet
1792 DNS_HEADER
*DnsHeader
;
1793 DNS_QUERY_SECTION
*DnsQuery
;
1796 // Messages carried by UDP are restricted to 512 bytes (not counting the IP
1799 Frag
.Bulk
= AllocatePool (DNS_MAX_MESSAGE_SIZE
* sizeof (UINT8
));
1800 if (Frag
.Bulk
== NULL
) {
1801 return EFI_OUT_OF_RESOURCES
;
1807 DnsHeader
= (DNS_HEADER
*) Frag
.Bulk
;
1808 DnsHeader
->Identification
= (UINT16
)NET_RANDOM (NetRandomInitSeed());
1809 DnsHeader
->Flags
.Uint16
= 0x0000;
1810 DnsHeader
->Flags
.Bits
.RD
= 1;
1811 DnsHeader
->Flags
.Bits
.OpCode
= DNS_FLAGS_OPCODE_STANDARD
;
1812 DnsHeader
->Flags
.Bits
.QR
= DNS_FLAGS_QR_QUERY
;
1813 DnsHeader
->QuestionsNum
= 1;
1814 DnsHeader
->AnswersNum
= 0;
1815 DnsHeader
->AuthorityNum
= 0;
1816 DnsHeader
->AditionalNum
= 0;
1818 DnsHeader
->Identification
= HTONS (DnsHeader
->Identification
);
1819 DnsHeader
->Flags
.Uint16
= HTONS (DnsHeader
->Flags
.Uint16
);
1820 DnsHeader
->QuestionsNum
= HTONS (DnsHeader
->QuestionsNum
);
1821 DnsHeader
->AnswersNum
= HTONS (DnsHeader
->AnswersNum
);
1822 DnsHeader
->AuthorityNum
= HTONS (DnsHeader
->AuthorityNum
);
1823 DnsHeader
->AditionalNum
= HTONS (DnsHeader
->AditionalNum
);
1825 Frag
.Len
= sizeof (*DnsHeader
);
1830 CopyMem (Frag
.Bulk
+ Frag
.Len
, QueryName
, AsciiStrLen (QueryName
));
1831 Frag
.Len
= (UINT32
) (Frag
.Len
+ AsciiStrLen (QueryName
));
1832 *(Frag
.Bulk
+ Frag
.Len
) = 0;
1836 // Rest query section
1838 DnsQuery
= (DNS_QUERY_SECTION
*) (Frag
.Bulk
+ Frag
.Len
);
1840 DnsQuery
->Type
= HTONS (Type
);
1841 DnsQuery
->Class
= HTONS (Class
);
1843 Frag
.Len
+= sizeof (*DnsQuery
);
1846 // Wrap the Frag in a net buffer.
1848 *Packet
= NetbufFromExt (&Frag
, 1, 0, 0, DnsDummyExtFree
, NULL
);
1849 if (*Packet
== NULL
) {
1850 FreePool (Frag
.Bulk
);
1851 return EFI_OUT_OF_RESOURCES
;
1855 // Store the UdpIo in ProtoData.
1857 *((UINTN
*) &((*Packet
)->ProtoData
[0])) = (UINTN
) (Instance
->UdpIo
);
1863 Retransmit the packet.
1865 @param Instance The DNS instance
1866 @param Packet Retransmit the packet
1868 @retval EFI_SUCCESS The packet is retransmitted.
1869 @retval Others Failed to retransmit.
1874 IN DNS_INSTANCE
*Instance
,
1882 ASSERT (Packet
!= NULL
);
1885 // Set the requests to the listening port, other packets to the connected port
1887 Buffer
= NetbufGetByte (Packet
, 0, NULL
);
1888 ASSERT (Buffer
!= NULL
);
1890 NET_GET_REF (Packet
);
1892 Status
= UdpIoSendDatagram (
1901 if (EFI_ERROR (Status
)) {
1902 NET_PUT_REF (Packet
);
1909 The timer ticking function for the DNS services.
1911 @param Event The ticking event
1912 @param Context The DNS service instance
1917 DnsOnTimerRetransmit (
1922 DNS_SERVICE
*Service
;
1927 DNS_INSTANCE
*Instance
;
1928 LIST_ENTRY
*EntryNetMap
;
1929 NET_MAP_ITEM
*ItemNetMap
;
1930 DNS4_TOKEN_ENTRY
*Dns4TokenEntry
;
1931 DNS6_TOKEN_ENTRY
*Dns6TokenEntry
;
1933 Dns4TokenEntry
= NULL
;
1934 Dns6TokenEntry
= NULL
;
1936 Service
= (DNS_SERVICE
*) Context
;
1939 if (Service
->IpVersion
== IP_VERSION_4
) {
1941 // Iterate through all the children of the DNS service instance. Time
1942 // out the packet. If maximum retries reached, clean the Token up.
1944 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Service
->Dns4ChildrenList
) {
1945 Instance
= NET_LIST_USER_STRUCT (Entry
, DNS_INSTANCE
, Link
);
1947 EntryNetMap
= Instance
->Dns4TxTokens
.Used
.ForwardLink
;
1948 while (EntryNetMap
!= &Instance
->Dns4TxTokens
.Used
) {
1949 ItemNetMap
= NET_LIST_USER_STRUCT (EntryNetMap
, NET_MAP_ITEM
, Link
);
1950 Dns4TokenEntry
= (DNS4_TOKEN_ENTRY
*)(ItemNetMap
->Key
);
1951 if (Dns4TokenEntry
->PacketToLive
== 0 || (--Dns4TokenEntry
->PacketToLive
> 0)) {
1952 EntryNetMap
= EntryNetMap
->ForwardLink
;
1957 // Retransmit the packet if haven't reach the maxmium retry count,
1958 // otherwise exit the transfer.
1960 if (++Dns4TokenEntry
->Token
->RetryCount
< Instance
->MaxRetry
) {
1961 DnsRetransmit (Instance
, (NET_BUF
*)ItemNetMap
->Value
);
1962 EntryNetMap
= EntryNetMap
->ForwardLink
;
1965 // Maximum retries reached, clean the Token up.
1967 Dns4RemoveTokenEntry (&Instance
->Dns4TxTokens
, Dns4TokenEntry
);
1968 Dns4TokenEntry
->Token
->Status
= EFI_TIMEOUT
;
1969 gBS
->SignalEvent (Dns4TokenEntry
->Token
->Event
);
1973 // Free the sending packet.
1975 if (ItemNetMap
->Value
!= NULL
) {
1976 NetbufFree ((NET_BUF
*)(ItemNetMap
->Value
));
1979 EntryNetMap
= Instance
->Dns4TxTokens
.Used
.ForwardLink
;
1985 // Iterate through all the children of the DNS service instance. Time
1986 // out the packet. If maximum retries reached, clean the Token up.
1988 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Service
->Dns6ChildrenList
) {
1989 Instance
= NET_LIST_USER_STRUCT (Entry
, DNS_INSTANCE
, Link
);
1991 EntryNetMap
= Instance
->Dns6TxTokens
.Used
.ForwardLink
;
1992 while (EntryNetMap
!= &Instance
->Dns6TxTokens
.Used
) {
1993 ItemNetMap
= NET_LIST_USER_STRUCT (EntryNetMap
, NET_MAP_ITEM
, Link
);
1994 Dns6TokenEntry
= (DNS6_TOKEN_ENTRY
*) (ItemNetMap
->Key
);
1995 if (Dns6TokenEntry
->PacketToLive
== 0 || (--Dns6TokenEntry
->PacketToLive
> 0)) {
1996 EntryNetMap
= EntryNetMap
->ForwardLink
;
2001 // Retransmit the packet if haven't reach the maxmium retry count,
2002 // otherwise exit the transfer.
2004 if (++Dns6TokenEntry
->Token
->RetryCount
< Instance
->MaxRetry
) {
2005 DnsRetransmit (Instance
, (NET_BUF
*) ItemNetMap
->Value
);
2006 EntryNetMap
= EntryNetMap
->ForwardLink
;
2009 // Maximum retries reached, clean the Token up.
2011 Dns6RemoveTokenEntry (&Instance
->Dns6TxTokens
, Dns6TokenEntry
);
2012 Dns6TokenEntry
->Token
->Status
= EFI_TIMEOUT
;
2013 gBS
->SignalEvent (Dns6TokenEntry
->Token
->Event
);
2017 // Free the sending packet.
2019 if (ItemNetMap
->Value
!= NULL
) {
2020 NetbufFree ((NET_BUF
*) (ItemNetMap
->Value
));
2023 EntryNetMap
= Instance
->Dns6TxTokens
.Used
.ForwardLink
;
2031 The timer ticking function for the DNS driver.
2033 @param Event The ticking event
2053 // Iterate through all the DNS4 cache list.
2055 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &mDriverData
->Dns4CacheList
) {
2056 Item4
= NET_LIST_USER_STRUCT (Entry
, DNS4_CACHE
, AllCacheLink
);
2057 Item4
->DnsCache
.Timeout
--;
2060 Entry
= mDriverData
->Dns4CacheList
.ForwardLink
;
2061 while (Entry
!= &mDriverData
->Dns4CacheList
) {
2062 Item4
= NET_LIST_USER_STRUCT (Entry
, DNS4_CACHE
, AllCacheLink
);
2063 if (Item4
->DnsCache
.Timeout
== 0) {
2064 RemoveEntryList (&Item4
->AllCacheLink
);
2065 Entry
= mDriverData
->Dns4CacheList
.ForwardLink
;
2067 Entry
= Entry
->ForwardLink
;
2072 // Iterate through all the DNS6 cache list.
2074 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &mDriverData
->Dns6CacheList
) {
2075 Item6
= NET_LIST_USER_STRUCT (Entry
, DNS6_CACHE
, AllCacheLink
);
2076 Item6
->DnsCache
.Timeout
--;
2079 Entry
= mDriverData
->Dns6CacheList
.ForwardLink
;
2080 while (Entry
!= &mDriverData
->Dns6CacheList
) {
2081 Item6
= NET_LIST_USER_STRUCT (Entry
, DNS6_CACHE
, AllCacheLink
);
2082 if (Item6
->DnsCache
.Timeout
== 0) {
2083 RemoveEntryList (&Item6
->AllCacheLink
);
2084 Entry
= mDriverData
->Dns6CacheList
.ForwardLink
;
2086 Entry
= Entry
->ForwardLink
;