1 /** @file
2 Implementation of EFI_DNS4_PROTOCOL and EFI_DNS6_PROTOCOL interfaces.
3 
4 Copyright (c) 2015, 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
9 
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.
12 
13 **/
14 
15 #include "DnsImpl.h"
16 
17 EFI_DNS4_PROTOCOL  mDns4Protocol = {
18   Dns4GetModeData,
19   Dns4Configure,
20   Dns4HostNameToIp,
21   Dns4IpToHostName,
22   Dns4GeneralLookUp,
23   Dns4UpdateDnsCache,
24   Dns4Poll,
25   Dns4Cancel
26 };
27 
28 EFI_DNS6_PROTOCOL  mDns6Protocol = {
29   Dns6GetModeData,
30   Dns6Configure,
31   Dns6HostNameToIp,
32   Dns6IpToHostName,
33   Dns6GeneralLookUp,
34   Dns6UpdateDnsCache,
35   Dns6Poll,
36   Dns6Cancel
37 };
38 
39 /**
40   This function is used to retrieve DNS mode data for this DNS instance.
41 
42   @param[in]  This               Pointer to EFI_DNS4_PROTOCOL instance.
43   @param[out] DnsModeData        Pointer to the caller-allocated storage for the EFI_DNS4_MODE_DATA structure.
44 
45   @retval  EFI_SUCCESS           The operation completed successfully.
46   @retval  EFI_NOT_STARTED       When DnsConfigData is queried, no configuration data is
47                                  available because this instance has not been configured.
48   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate needed resources.
49   @retval  EFI_INVALID_PARAMETER This is NULL or DnsModeData is NULL.
50 
51 **/
52 EFI_STATUS
53 EFIAPI
Dns4GetModeData(IN EFI_DNS4_PROTOCOL * This,OUT EFI_DNS4_MODE_DATA * DnsModeData)54 Dns4GetModeData (
55   IN  EFI_DNS4_PROTOCOL          *This,
56   OUT EFI_DNS4_MODE_DATA         *DnsModeData
57   )
58 {
59   DNS_INSTANCE         *Instance;
60 
61   EFI_TPL              OldTpl;
62 
63   UINTN                Index;
64 
65   LIST_ENTRY           *Entry;
66   LIST_ENTRY           *Next;
67 
68   DNS4_SERVER_IP       *ServerItem;
69   EFI_IPv4_ADDRESS     *ServerList;
70   DNS4_CACHE           *CacheItem;
71   EFI_DNS4_CACHE_ENTRY *CacheList;
72   EFI_STATUS           Status;
73 
74   ServerItem = NULL;
75   ServerList = NULL;
76   CacheItem  = NULL;
77   CacheList  = NULL;
78   Status     = EFI_SUCCESS;
79 
80 
81   if ((This == NULL) || (DnsModeData == NULL)) {
82     return EFI_INVALID_PARAMETER;
83   }
84 
85   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
86 
87   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (This);
88   if (Instance->State == DNS_STATE_UNCONFIGED) {
89     gBS->RestoreTPL (OldTpl);
90     return  EFI_NOT_STARTED;
91   }
92 
93   ZeroMem (DnsModeData, sizeof (EFI_DNS4_MODE_DATA));
94 
95   //
96   // Get the current configuration data of this instance.
97   //
98   Status = Dns4CopyConfigure (&DnsModeData->DnsConfigData, &Instance->Dns4CfgData);
99   if (EFI_ERROR (Status)) {
100     gBS->RestoreTPL (OldTpl);
101     return Status;
102   }
103 
104   //
105   // Get the DnsServerCount and DnsServerList
106   //
107   Index = 0;
108   NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4ServerList) {
109     Index++;
110   }
111   DnsModeData->DnsServerCount = (UINT32) Index;
112   ServerList = AllocatePool (sizeof (EFI_IPv4_ADDRESS) * DnsModeData->DnsServerCount);
113   ASSERT (ServerList != NULL);
114   Index = 0;
115   NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4ServerList) {
116     ServerItem = NET_LIST_USER_STRUCT (Entry, DNS4_SERVER_IP, AllServerLink);
117     CopyMem (ServerList + Index, &ServerItem->Dns4ServerIp, sizeof (EFI_IPv4_ADDRESS));
118     Index++;
119   }
120   DnsModeData->DnsServerList = ServerList;
121 
122   //
123   // Get the DnsCacheCount and DnsCacheList
124   //
125   Index =0;
126   NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) {
127     Index++;
128   }
129   DnsModeData->DnsCacheCount = (UINT32) Index;
130   CacheList = AllocatePool (sizeof (EFI_DNS4_CACHE_ENTRY) * DnsModeData->DnsCacheCount);
131   ASSERT (CacheList != NULL);
132   Index =0;
133   NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) {
134     CacheItem = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
135     CopyMem (CacheList + Index, &CacheItem->DnsCache, sizeof (EFI_DNS4_CACHE_ENTRY));
136     Index++;
137   }
138   DnsModeData->DnsCacheList = CacheList;
139 
140   gBS->RestoreTPL (OldTpl);
141 
142   return EFI_SUCCESS;
143 }
144 
145 /**
146   This function is used to configure DNS configuration data for this DNS instance.
147 
148   @param[in]  This               Pointer to EFI_DNS4_PROTOCOL instance.
149   @param[in]  DnsConfigData      Pointer to caller-allocated buffer containing EFI_DNS4_CONFIG_DATA structure.
150                                  If NULL, the driver will reinitialize the protocol instance to the unconfigured state.
151 
152   @retval  EFI_SUCCESS           The operation completed successfully.
153   @retval  EFI_UNSUPPORTED       The designated protocol is not supported.
154   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate needed resources.
155   @retval  EFI_INVALID_PARAMETER This is NULL.
156                                  The StationIp address provided in DnsConfigData is not a valid unicast.
157                                  DnsServerList is NULL while DnsServerListCount is not equal to Zero.
158                                  DnsServerListCount is Zero while DnsServerListCount is not equal to NULL.
159   @retval  EFI_DEVICE_ERROR      An unexpected system or network error occurred. The EFI DNSv4 Protocol instance is not configured.
160 
161 **/
162 EFI_STATUS
163 EFIAPI
Dns4Configure(IN EFI_DNS4_PROTOCOL * This,IN EFI_DNS4_CONFIG_DATA * DnsConfigData)164 Dns4Configure (
165   IN EFI_DNS4_PROTOCOL           *This,
166   IN EFI_DNS4_CONFIG_DATA        *DnsConfigData
167   )
168 {
169   EFI_STATUS                Status;
170   DNS_INSTANCE              *Instance;
171 
172   EFI_TPL                   OldTpl;
173   IP4_ADDR                  Ip;
174   IP4_ADDR                  Netmask;
175 
176   UINT32                    ServerListCount;
177   EFI_IPv4_ADDRESS          *ServerList;
178 
179   Status     = EFI_SUCCESS;
180   ServerList = NULL;
181 
182   if (This == NULL ||
183      (DnsConfigData != NULL && ((DnsConfigData->DnsServerListCount != 0 && DnsConfigData->DnsServerList == NULL) ||
184                                 (DnsConfigData->DnsServerListCount == 0 && DnsConfigData->DnsServerList != NULL)))) {
185     return EFI_INVALID_PARAMETER;
186   }
187 
188   if (DnsConfigData != NULL && DnsConfigData->Protocol != DNS_PROTOCOL_UDP) {
189     return EFI_UNSUPPORTED;
190   }
191 
192   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
193 
194   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (This);
195 
196   if (DnsConfigData == NULL) {
197     ZeroMem (&Instance->SessionDnsServer, sizeof (EFI_IP_ADDRESS));
198 
199     //
200     // Reset the Instance if ConfigData is NULL
201     //
202     if (!NetMapIsEmpty(&Instance->Dns4TxTokens)) {
203       Dns4InstanceCancelToken(Instance, NULL);
204     }
205 
206     Instance->MaxRetry = 0;
207 
208     if (Instance->UdpIo != NULL){
209       UdpIoCleanIo (Instance->UdpIo);
210     }
211 
212     if (Instance->Dns4CfgData.DnsServerList != NULL) {
213       FreePool (Instance->Dns4CfgData.DnsServerList);
214     }
215     ZeroMem (&Instance->Dns4CfgData, sizeof (EFI_DNS4_CONFIG_DATA));
216 
217     Instance->State = DNS_STATE_UNCONFIGED;
218   } else {
219     //
220     // Configure the parameters for new operation.
221     //
222     CopyMem (&Ip, &DnsConfigData->StationIp, sizeof (IP4_ADDR));
223     CopyMem (&Netmask, &DnsConfigData->SubnetMask, sizeof (IP4_ADDR));
224 
225     Ip       = NTOHL (Ip);
226     Netmask  = NTOHL (Netmask);
227 
228     if (!DnsConfigData->UseDefaultSetting &&
229        ((!IP4_IS_VALID_NETMASK (Netmask) || !NetIp4IsUnicast (Ip, Netmask)))) {
230       Status = EFI_INVALID_PARAMETER;
231       goto ON_EXIT;
232     }
233 
234     Status = Dns4CopyConfigure (&Instance->Dns4CfgData, DnsConfigData);
235     if (EFI_ERROR (Status)) {
236       goto ON_EXIT;
237     }
238 
239     if (DnsConfigData->DnsServerListCount == 0 || DnsConfigData->DnsServerList == NULL) {
240       gBS->RestoreTPL (OldTpl);
241 
242       //
243       // The DNS instance will retrieve DNS server from DHCP Server
244       //
245       Status = GetDns4ServerFromDhcp4 (
246                  Instance,
247                  &ServerListCount,
248                  &ServerList
249                  );
250       if (EFI_ERROR (Status)) {
251         return Status;
252       }
253 
254       ASSERT(ServerList != NULL);
255 
256       OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
257 
258       CopyMem (&Instance->SessionDnsServer.v4, &ServerList[0], sizeof (EFI_IPv4_ADDRESS));
259     } else {
260       CopyMem (&Instance->SessionDnsServer.v4, &DnsConfigData->DnsServerList[0], sizeof (EFI_IPv4_ADDRESS));
261     }
262 
263     //
264     // Config UDP
265     //
266     Status = Dns4ConfigUdp (Instance, Instance->UdpIo);
267     if (EFI_ERROR (Status)) {
268       if (Instance->Dns4CfgData.DnsServerList != NULL) {
269         FreePool (Instance->Dns4CfgData.DnsServerList);
270       }
271       goto ON_EXIT;
272     }
273 
274     //
275     // Add configured DNS server used by this instance to ServerList.
276     //
277     Status = AddDns4ServerIp (&mDriverData->Dns4ServerList, Instance->SessionDnsServer.v4);
278     if (EFI_ERROR (Status)) {
279       if (Instance->Dns4CfgData.DnsServerList != NULL) {
280         FreePool (Instance->Dns4CfgData.DnsServerList);
281       }
282       goto ON_EXIT;
283     }
284 
285     Instance->State = DNS_STATE_CONFIGED;
286   }
287 
288 ON_EXIT:
289   gBS->RestoreTPL (OldTpl);
290   return Status;
291 }
292 
293 /**
294   The function is used to translate the host name to host IP address.
295   A type A query is used to get the one or more IP addresses for this host.
296 
297   @param[in]  This               Pointer to EFI_DNS4_PROTOCOL instance.
298   @param[in]  HostName           Pointer to caller-supplied buffer containing Host name to be translated.
299                                  This buffer contains 16 bit characters but these are translated to ASCII for use with
300                                  DNSv4 server and there is no requirement for driver to support non-ASCII Unicode characters.
301   @param[in]  Token              Pointer to the caller-allocated completion token to return at the completion of the process to translate host name to host address.
302 
303   @retval  EFI_SUCCESS           The operation completed successfully.
304   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate needed resources.
305   @retval  EFI_INVALID_PARAMETER This is NULL.
306                                  Token is NULL.
307                                  Token.Event is.NULL
308                                  HostName is NULL
309   @retval  EFI_NO_MAPPING        There's no source address is available for use.
310   @retval  EFI_NOT_STARTED       This instance has not been started.
311 
312 **/
313 EFI_STATUS
314 EFIAPI
Dns4HostNameToIp(IN EFI_DNS4_PROTOCOL * This,IN CHAR16 * HostName,IN EFI_DNS4_COMPLETION_TOKEN * Token)315 Dns4HostNameToIp (
316   IN  EFI_DNS4_PROTOCOL          *This,
317   IN  CHAR16                     *HostName,
318   IN  EFI_DNS4_COMPLETION_TOKEN  *Token
319   )
320 {
321   EFI_STATUS            Status;
322 
323   DNS_INSTANCE          *Instance;
324 
325   EFI_DNS4_CONFIG_DATA  *ConfigData;
326 
327   UINTN                 Index;
328   DNS4_CACHE            *Item;
329   LIST_ENTRY            *Entry;
330   LIST_ENTRY            *Next;
331 
332   CHAR8                 *QueryName;
333 
334   DNS4_TOKEN_ENTRY      *TokenEntry;
335   NET_BUF               *Packet;
336 
337   EFI_TPL               OldTpl;
338 
339   Status     = EFI_SUCCESS;
340   Item       = NULL;
341   QueryName  = NULL;
342   TokenEntry = NULL;
343   Packet     = NULL;
344 
345   //
346   // Validate the parameters
347   //
348   if ((This == NULL) || (HostName == NULL) || Token == NULL) {
349     return EFI_INVALID_PARAMETER;
350   }
351 
352   OldTpl   = gBS->RaiseTPL (TPL_CALLBACK);
353 
354   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (This);
355 
356   ConfigData = &(Instance->Dns4CfgData);
357 
358   Instance->MaxRetry = ConfigData->RetryCount;
359 
360   Token->Status = EFI_NOT_READY;
361   Token->RetryCount = 0;
362   Token->RetryInterval = ConfigData->RetryInterval;
363 
364   if (Instance->State != DNS_STATE_CONFIGED) {
365     Status = EFI_NOT_STARTED;
366     goto ON_EXIT;
367   }
368 
369   //
370   // Check the MaxRetry and RetryInterval values.
371   //
372   if (Instance->MaxRetry == 0) {
373     Instance->MaxRetry = DNS_DEFAULT_RETRY;
374   }
375 
376   if (Token->RetryInterval < DNS_DEFAULT_TIMEOUT) {
377     Token->RetryInterval = DNS_DEFAULT_TIMEOUT;
378   }
379 
380   //
381   // Check cache
382   //
383   if (ConfigData->EnableDnsCache) {
384     Index = 0;
385     NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) {
386       Item = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
387       if (StrCmp (HostName, Item->DnsCache.HostName) == 0) {
388         Index++;
389       }
390     }
391 
392     if (Index != 0) {
393       Token->RspData.H2AData = AllocatePool (sizeof (DNS_HOST_TO_ADDR_DATA));
394       if (Token->RspData.H2AData == NULL) {
395         Status = EFI_OUT_OF_RESOURCES;
396         goto ON_EXIT;
397       }
398 
399       Token->RspData.H2AData->IpCount = (UINT32)Index;
400       Token->RspData.H2AData->IpList = AllocatePool (sizeof (EFI_IPv4_ADDRESS) * Index);
401       if (Token->RspData.H2AData->IpList == NULL) {
402         if (Token->RspData.H2AData != NULL) {
403           FreePool (Token->RspData.H2AData);
404         }
405 
406         Status = EFI_OUT_OF_RESOURCES;
407         goto ON_EXIT;
408       }
409 
410       Index = 0;
411       NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) {
412         Item = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
413         if ((UINT32)Index < Token->RspData.H2AData->IpCount && StrCmp (HostName, Item->DnsCache.HostName) == 0) {
414           CopyMem ((Token->RspData.H2AData->IpList) + Index, Item->DnsCache.IpAddress, sizeof (EFI_IPv4_ADDRESS));
415           Index++;
416         }
417       }
418 
419       Token->Status = EFI_SUCCESS;
420 
421       if (Token->Event != NULL) {
422         gBS->SignalEvent (Token->Event);
423         DispatchDpc ();
424       }
425 
426       Status = Token->Status;
427       goto ON_EXIT;
428     }
429   }
430 
431   //
432   // Construct DNS TokenEntry.
433   //
434   TokenEntry = AllocateZeroPool (sizeof(DNS4_TOKEN_ENTRY));
435   if (TokenEntry == NULL) {
436     Status = EFI_OUT_OF_RESOURCES;
437     goto ON_EXIT;
438   }
439 
440   TokenEntry->PacketToLive = Token->RetryInterval;
441   TokenEntry->QueryHostName = HostName;
442   TokenEntry->Token = Token;
443 
444   //
445   // Construct QName.
446   //
447   QueryName = DnsFillinQNameForQueryIp (TokenEntry->QueryHostName);
448   if (QueryName == NULL) {
449     Status = EFI_OUT_OF_RESOURCES;
450     goto ON_EXIT;
451   }
452 
453   //
454   // Construct DNS Query Packet.
455   //
456   Status = ConstructDNSQuery (Instance, QueryName, DNS_TYPE_A, DNS_CLASS_INET, &Packet);
457   if (EFI_ERROR (Status)) {
458     if (TokenEntry != NULL) {
459       FreePool (TokenEntry);
460     }
461 
462     goto ON_EXIT;
463   }
464 
465   ASSERT (Packet != NULL);
466 
467   //
468   // Save the token into the Dns4TxTokens map.
469   //
470   Status = NetMapInsertTail (&Instance->Dns4TxTokens, TokenEntry, Packet);
471   if (EFI_ERROR (Status)) {
472     if (TokenEntry != NULL) {
473       FreePool (TokenEntry);
474     }
475 
476     NetbufFree (Packet);
477 
478     goto ON_EXIT;
479   }
480 
481   //
482   // Dns Query Ip
483   //
484   Status = DoDnsQuery (Instance, Packet);
485   if (EFI_ERROR (Status)) {
486     if (TokenEntry != NULL) {
487       FreePool (TokenEntry);
488     }
489 
490     NetbufFree (Packet);
491   }
492 
493 ON_EXIT:
494   if (QueryName != NULL) {
495     FreePool (QueryName);
496   }
497 
498   gBS->RestoreTPL (OldTpl);
499   return Status;
500 }
501 
502 /**
503   The function is used to translate the host address to host name.
504   A type PTR query is used to get the primary name of the host.
505 
506   @param[in]  This               Pointer to EFI_DNS4_PROTOCOL instance.
507   @param[in]  IpAddress          IP address.
508   @param[in]  Token              Pointer to the caller-allocated completion used token to translate host address to host name.
509 
510   @retval  EFI_SUCCESS           The operation completed successfully.
511   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate needed resources.
512   @retval  EFI_INVALID_PARAMETER This is NULL.
513                                  Token is NULL.
514                                  Token.Event is NULL.
515                                  IpAddress is not valid IP address.
516   @retval  EFI_NO_MAPPING        There's no source address is available for use.
517   @retval  EFI_NOT_STARTED       This instance has not been started.
518   @retval  EFI_UNSUPPORTED       This function is not supported.
519 
520 **/
521 EFI_STATUS
522 EFIAPI
Dns4IpToHostName(IN EFI_DNS4_PROTOCOL * This,IN EFI_IPv4_ADDRESS IpAddress,IN EFI_DNS4_COMPLETION_TOKEN * Token)523 Dns4IpToHostName (
524   IN  EFI_DNS4_PROTOCOL              *This,
525   IN  EFI_IPv4_ADDRESS               IpAddress,
526   IN  EFI_DNS4_COMPLETION_TOKEN      *Token
527   )
528 {
529   return EFI_UNSUPPORTED;
530 }
531 
532 /**
533   This function retrieves arbitrary information from the DNS.
534   The caller supplies a QNAME, QTYPE, and QCLASS, and all of the matching RRs are returned.
535   All RR content (e.g., Ttl) was returned.
536   The caller need parse the returned RR to get required information. This function is optional.
537 
538   @param[in]  This               Pointer to EFI_DNS4_PROTOCOL instance.
539   @param[in]  QName              Pointer to Query Name.
540   @param[in]  QType              Query Type.
541   @param[in]  QClass             Query Name.
542   @param[in]  Token              Point to the caller-allocated completion token to retrieve arbitrary information.
543 
544   @retval  EFI_SUCCESS           The operation completed successfully.
545   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate needed resources.
546   @retval  EFI_INVALID_PARAMETER This is NULL.
547                                  Token is NULL.
548                                  Token.Event is NULL.
549                                  QName is NULL.
550   @retval  EFI_NO_MAPPING        There's no source address is available for use.
551   @retval  EFI_ALREADY_STARTED   This Token is being used in another DNS session.
552   @retval  EFI_UNSUPPORTED       This function is not supported. Or the requested QType is not supported
553 
554 **/
555 EFI_STATUS
556 EFIAPI
Dns4GeneralLookUp(IN EFI_DNS4_PROTOCOL * This,IN CHAR8 * QName,IN UINT16 QType,IN UINT16 QClass,IN EFI_DNS4_COMPLETION_TOKEN * Token)557 Dns4GeneralLookUp (
558   IN  EFI_DNS4_PROTOCOL                *This,
559   IN  CHAR8                            *QName,
560   IN  UINT16                           QType,
561   IN  UINT16                           QClass,
562   IN  EFI_DNS4_COMPLETION_TOKEN        *Token
563   )
564 {
565   EFI_STATUS            Status;
566 
567   DNS_INSTANCE          *Instance;
568 
569   EFI_DNS4_CONFIG_DATA  *ConfigData;
570 
571   DNS4_TOKEN_ENTRY      *TokenEntry;
572   NET_BUF               *Packet;
573 
574   EFI_TPL               OldTpl;
575 
576   Status     = EFI_SUCCESS;
577   TokenEntry = NULL;
578   Packet     = NULL;
579 
580   //
581   // Validate the parameters
582   //
583   if ((This == NULL) || (QName == NULL) || Token == NULL) {
584     return EFI_INVALID_PARAMETER;
585   }
586 
587   OldTpl   = gBS->RaiseTPL (TPL_CALLBACK);
588 
589   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (This);
590 
591   ConfigData = &(Instance->Dns4CfgData);
592 
593   Instance->MaxRetry = ConfigData->RetryCount;
594 
595   Token->Status = EFI_NOT_READY;
596   Token->RetryCount = 0;
597   Token->RetryInterval = ConfigData->RetryInterval;
598 
599   if (Instance->State != DNS_STATE_CONFIGED) {
600     Status = EFI_NOT_STARTED;
601     goto ON_EXIT;
602   }
603 
604   //
605   // Check the MaxRetry and RetryInterval values.
606   //
607   if (Instance->MaxRetry == 0) {
608     Instance->MaxRetry = DNS_DEFAULT_RETRY;
609   }
610 
611   if (Token->RetryInterval < DNS_DEFAULT_TIMEOUT) {
612     Token->RetryInterval = DNS_DEFAULT_TIMEOUT;
613   }
614 
615   //
616   // Construct DNS TokenEntry.
617   //
618   TokenEntry = AllocateZeroPool (sizeof(DNS4_TOKEN_ENTRY));
619   if (TokenEntry == NULL) {
620     Status = EFI_OUT_OF_RESOURCES;
621     goto ON_EXIT;
622   }
623 
624   TokenEntry->PacketToLive = Token->RetryInterval;
625   TokenEntry->GeneralLookUp = TRUE;
626   TokenEntry->Token = Token;
627 
628   //
629   // Construct DNS Query Packet.
630   //
631   Status = ConstructDNSQuery (Instance, QName, QType, QClass, &Packet);
632   if (EFI_ERROR (Status)) {
633     if (TokenEntry != NULL) {
634       FreePool (TokenEntry);
635     }
636 
637     goto ON_EXIT;
638   }
639 
640   ASSERT (Packet != NULL);
641 
642   //
643   // Save the token into the Dns4TxTokens map.
644   //
645   Status = NetMapInsertTail (&Instance->Dns4TxTokens, TokenEntry, Packet);
646   if (EFI_ERROR (Status)) {
647     if (TokenEntry != NULL) {
648       FreePool (TokenEntry);
649     }
650 
651     NetbufFree (Packet);
652 
653     goto ON_EXIT;
654   }
655 
656   //
657   // Dns Query Ip
658   //
659   Status = DoDnsQuery (Instance, Packet);
660   if (EFI_ERROR (Status)) {
661     if (TokenEntry != NULL) {
662       FreePool (TokenEntry);
663     }
664 
665     NetbufFree (Packet);
666   }
667 
668 ON_EXIT:
669   gBS->RestoreTPL (OldTpl);
670   return Status;
671 }
672 
673 /**
674   This function is used to add/delete/modify DNS cache entry.
675   DNS cache can be normally dynamically updated after the DNS resolve succeeds.
676   This function provided capability to manually add/delete/modify the DNS cache.
677 
678   @param[in]  This               Pointer to EFI_DNS4_PROTOCOL instance.
679   @param[in]  DeleteFlag         If FALSE, this function is to add one entry to the DNS Cache.
680                                  If TRUE, this function will delete matching DNS Cache entry.
681   @param[in]  Override           If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
682                                  If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
683   @param[in]  DnsCacheEntry      Pointer to DNS Cache entry.
684 
685   @retval  EFI_SUCCESS           The operation completed successfully.
686   @retval  EFI_INVALID_PARAMETER This is NULL.
687                                  DnsCacheEntry.HostName is NULL.
688                                  DnsCacheEntry.IpAddress is NULL.
689                                  DnsCacheEntry.Timeout is zero.
690   @retval  EFI_ACCESS_DENIED     The DNS cache entry already exists and Override is not TRUE.
691 
692 **/
693 EFI_STATUS
694 EFIAPI
Dns4UpdateDnsCache(IN EFI_DNS4_PROTOCOL * This,IN BOOLEAN DeleteFlag,IN BOOLEAN Override,IN EFI_DNS4_CACHE_ENTRY DnsCacheEntry)695 Dns4UpdateDnsCache (
696   IN EFI_DNS4_PROTOCOL      *This,
697   IN BOOLEAN                DeleteFlag,
698   IN BOOLEAN                Override,
699   IN EFI_DNS4_CACHE_ENTRY   DnsCacheEntry
700   )
701 {
702   EFI_STATUS    Status;
703   EFI_TPL       OldTpl;
704 
705   Status = EFI_SUCCESS;
706 
707   if (DnsCacheEntry.HostName == NULL || DnsCacheEntry.IpAddress == NULL || DnsCacheEntry.Timeout == 0) {
708     return EFI_INVALID_PARAMETER;
709   }
710 
711   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
712 
713   //
714   // Update Dns4Cache here.
715   //
716   Status = UpdateDns4Cache (&mDriverData->Dns4CacheList, DeleteFlag, Override, DnsCacheEntry);
717 
718   gBS->RestoreTPL (OldTpl);
719 
720   return Status;
721 }
722 
723 /**
724   This function can be used by network drivers and applications to increase the rate that data packets are moved between
725   the communications device and the transmit and receive queues. In some systems, the periodic timer event in the managed
726   network driver may not poll the underlying communications device fast enough to transmit and/or receive all data packets
727   without missing incoming packets or dropping outgoing packets.
728 
729   @param[in]  This               Pointer to EFI_DNS4_PROTOCOL instance.
730 
731   @retval  EFI_SUCCESS           Incoming or outgoing data was processed.
732   @retval  EFI_INVALID_PARAMETER This is NULL.
733   @retval  EFI_NOT_STARTED       This EFI DNS Protocol instance has not been started.
734   @retval  EFI_DEVICE_ERROR      An unexpected system or network error occurred.
735   @retval  EFI_TIMEOUT           Data was dropped out of the transmit and/or receive queue.
736                                  Consider increasing the polling rate.
737 
738 **/
739 EFI_STATUS
740 EFIAPI
Dns4Poll(IN EFI_DNS4_PROTOCOL * This)741 Dns4Poll (
742   IN EFI_DNS4_PROTOCOL    *This
743   )
744 {
745   DNS_INSTANCE           *Instance;
746   EFI_UDP4_PROTOCOL      *Udp;
747 
748   if (This == NULL) {
749     return EFI_INVALID_PARAMETER;
750   }
751 
752   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (This);
753 
754   if (Instance->State == DNS_STATE_UNCONFIGED) {
755     return EFI_NOT_STARTED;
756   } else if (Instance->State == DNS_STATE_DESTROY) {
757     return EFI_DEVICE_ERROR;
758   }
759 
760   Udp = Instance->UdpIo->Protocol.Udp4;
761 
762   return Udp->Poll (Udp);
763 }
764 
765 /**
766   This function is used to abort a pending resolution request.
767   After calling this function, Token.Status will be set to EFI_ABORTED and then Token.
768 
769   @param[in]  This               Pointer to EFI_DNS4_PROTOCOL instance.
770   @param[in]  Token              Pointer to a token that has been issued by EFI_DNS4_PROTOCOL.HostNameToIp(),
771                                  EFI_DNS4_PROTOCOL.IpToHostName() or EFI_DNS4_PROTOCOL.GeneralLookup().
772                                  If NULL, all pending tokens are aborted.
773 
774   @retval  EFI_SUCCESS           Incoming or outgoing data was processed.
775   @retval  EFI_INVALID_PARAMETER This is NULL.
776   @retval  EFI_NOT_STARTED       This EFI DNS Protocol instance has not been started.
777   @retval  EFI_NOT_FOUND         When Token is not NULL, and the asynchronous DNS operation was not found in the transmit queue.
778                                  It was either completed or was not issued by HostNameToIp(), IpToHostName() or GeneralLookup().
779 
780 **/
781 EFI_STATUS
782 EFIAPI
Dns4Cancel(IN EFI_DNS4_PROTOCOL * This,IN EFI_DNS4_COMPLETION_TOKEN * Token)783 Dns4Cancel (
784   IN  EFI_DNS4_PROTOCOL          *This,
785   IN  EFI_DNS4_COMPLETION_TOKEN  *Token
786   )
787 {
788   EFI_STATUS          Status;
789   DNS_INSTANCE        *Instance;
790   EFI_TPL             OldTpl;
791 
792   if (This == NULL) {
793     return EFI_INVALID_PARAMETER;
794   }
795 
796   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (This);
797 
798   if (Instance->State == DNS_STATE_UNCONFIGED) {
799     return EFI_NOT_STARTED;
800   }
801 
802   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
803 
804   //
805   // Cancle the tokens specified by Token for this instance.
806   //
807   Status = Dns4InstanceCancelToken (Instance, Token);
808 
809   //
810   // Dispatch the DPC queued by the NotifyFunction of the canceled token's events.
811   //
812   DispatchDpc ();
813 
814   gBS->RestoreTPL (OldTpl);
815 
816   return Status;
817 }
818 
819 /**
820   This function is used to retrieve DNS mode data for this DNS instance.
821 
822   @param[in]  This               Pointer to EFI_DNS6_PROTOCOL instance.
823   @param[out] DnsModeData        Pointer to the caller-allocated storage for the EFI_DNS6_MODE_DATA structure.
824 
825   @retval  EFI_SUCCESS           The operation completed successfully.
826   @retval  EFI_NOT_STARTED       When DnsConfigData is queried, no configuration data is
827                                  available because this instance has not been configured.
828   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate needed resources.
829   @retval  EFI_INVALID_PARAMETER This is NULL or DnsModeData is NULL.
830 
831 **/
832 EFI_STATUS
833 EFIAPI
Dns6GetModeData(IN EFI_DNS6_PROTOCOL * This,OUT EFI_DNS6_MODE_DATA * DnsModeData)834 Dns6GetModeData (
835   IN  EFI_DNS6_PROTOCOL          *This,
836   OUT EFI_DNS6_MODE_DATA         *DnsModeData
837   )
838 {
839   DNS_INSTANCE         *Instance;
840 
841   EFI_TPL              OldTpl;
842 
843   UINTN                Index;
844 
845   LIST_ENTRY           *Entry;
846   LIST_ENTRY           *Next;
847 
848   DNS6_SERVER_IP       *ServerItem;
849   EFI_IPv6_ADDRESS     *ServerList;
850   DNS6_CACHE           *CacheItem;
851   EFI_DNS6_CACHE_ENTRY *CacheList;
852   EFI_STATUS           Status;
853 
854   ServerItem = NULL;
855   ServerList = NULL;
856   CacheItem  = NULL;
857   CacheList  = NULL;
858   Status     = EFI_SUCCESS;
859 
860   if ((This == NULL) || (DnsModeData == NULL)) {
861     return EFI_INVALID_PARAMETER;
862   }
863 
864   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
865 
866   Instance  = DNS_INSTANCE_FROM_THIS_PROTOCOL6 (This);
867   if (Instance->State == DNS_STATE_UNCONFIGED) {
868     gBS->RestoreTPL (OldTpl);
869     return  EFI_NOT_STARTED;
870   }
871 
872   ZeroMem (DnsModeData, sizeof (EFI_DNS6_MODE_DATA));
873 
874   //
875   // Get the current configuration data of this instance.
876   //
877   Status = Dns6CopyConfigure(&DnsModeData->DnsConfigData, &Instance->Dns6CfgData);
878   if (EFI_ERROR (Status)) {
879     gBS->RestoreTPL (OldTpl);
880     return Status;
881   }
882 
883   //
884   // Get the DnsServerCount and DnsServerList
885   //
886   Index = 0;
887   NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6ServerList) {
888     Index++;
889   }
890   DnsModeData->DnsServerCount = (UINT32) Index;
891   ServerList = AllocatePool (sizeof(EFI_IPv6_ADDRESS) * DnsModeData->DnsServerCount);
892   ASSERT (ServerList != NULL);
893   Index = 0;
894   NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6ServerList) {
895     ServerItem = NET_LIST_USER_STRUCT (Entry, DNS6_SERVER_IP, AllServerLink);
896     CopyMem (ServerList + Index, &ServerItem->Dns6ServerIp, sizeof (EFI_IPv6_ADDRESS));
897     Index++;
898   }
899   DnsModeData->DnsServerList = ServerList;
900 
901   //
902   // Get the DnsCacheCount and DnsCacheList
903   //
904   Index =0;
905   NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6CacheList) {
906     Index++;
907   }
908   DnsModeData->DnsCacheCount = (UINT32) Index;
909   CacheList = AllocatePool (sizeof(EFI_DNS6_CACHE_ENTRY) * DnsModeData->DnsCacheCount);
910   ASSERT (CacheList != NULL);
911   Index =0;
912   NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6CacheList) {
913     CacheItem = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
914     CopyMem (CacheList + Index, &CacheItem->DnsCache, sizeof (EFI_DNS6_CACHE_ENTRY));
915     Index++;
916   }
917   DnsModeData->DnsCacheList = CacheList;
918 
919   gBS->RestoreTPL (OldTpl);
920 
921   return EFI_SUCCESS;
922 }
923 
924 /**
925   The function is used to set and change the configuration data for this EFI DNSv6 Protocol driver instance.
926   Reset the DNS instance if DnsConfigData is NULL.
927 
928   @param[in]  This               Pointer to EFI_DNS6_PROTOCOL instance.
929   @param[in]  DnsConfigData      Pointer to the configuration data structure.
930                                  All associated storage to be allocated and released by caller.
931 
932   @retval  EFI_SUCCESS           The operation completed successfully.
933   @retval  EFI_UNSUPPORTED       The designated protocol is not supported.
934   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate needed resources.
935   @retval  EFI_INVALID_PARAMETER This is NULL.
936                                  The StationIp address provided in DnsConfigData is not a valid unicast.
937                                  DnsServerList is NULL while DnsServerListCount is not equal to Zero.
938                                  DnsServerListCount is Zero while DnsServerList is not equal to NULL.
939   @retval  EFI_DEVICE_ERROR      An unexpected system or network error occurred. The EFI DNSv6 Protocol instance is not configured.
940 
941 **/
942 EFI_STATUS
943 EFIAPI
Dns6Configure(IN EFI_DNS6_PROTOCOL * This,IN EFI_DNS6_CONFIG_DATA * DnsConfigData)944 Dns6Configure (
945   IN EFI_DNS6_PROTOCOL           *This,
946   IN EFI_DNS6_CONFIG_DATA        *DnsConfigData
947   )
948 {
949   EFI_STATUS                Status;
950   DNS_INSTANCE              *Instance;
951 
952   EFI_TPL                   OldTpl;
953 
954   UINT32                    ServerListCount;
955   EFI_IPv6_ADDRESS          *ServerList;
956 
957   Status     = EFI_SUCCESS;
958   ServerList = NULL;
959 
960   if (This == NULL ||
961      (DnsConfigData != NULL && ((DnsConfigData->DnsServerCount != 0 && DnsConfigData->DnsServerList == NULL) ||
962                                 (DnsConfigData->DnsServerCount == 0 && DnsConfigData->DnsServerList != NULL)))) {
963     return EFI_INVALID_PARAMETER;
964   }
965 
966   if (DnsConfigData != NULL && DnsConfigData->Protocol != DNS_PROTOCOL_UDP) {
967     return EFI_UNSUPPORTED;
968   }
969 
970   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
971 
972   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL6 (This);
973 
974   if (DnsConfigData == NULL) {
975     ZeroMem (&Instance->SessionDnsServer, sizeof (EFI_IP_ADDRESS));
976 
977     //
978     // Reset the Instance if ConfigData is NULL
979     //
980     if (!NetMapIsEmpty(&Instance->Dns6TxTokens)) {
981       Dns6InstanceCancelToken(Instance, NULL);
982     }
983 
984     Instance->MaxRetry = 0;
985 
986     if (Instance->UdpIo != NULL){
987       UdpIoCleanIo (Instance->UdpIo);
988     }
989 
990     if (Instance->Dns6CfgData.DnsServerList != NULL) {
991       FreePool (Instance->Dns6CfgData.DnsServerList);
992     }
993     ZeroMem (&Instance->Dns6CfgData, sizeof (EFI_DNS6_CONFIG_DATA));
994 
995     Instance->State = DNS_STATE_UNCONFIGED;
996   } else {
997     //
998     // Configure the parameters for new operation.
999     //
1000     if (!NetIp6IsUnspecifiedAddr (&DnsConfigData->StationIp) && !NetIp6IsValidUnicast (&DnsConfigData->StationIp)) {
1001       Status = EFI_INVALID_PARAMETER;
1002       goto ON_EXIT;
1003     }
1004 
1005     Status = Dns6CopyConfigure (&Instance->Dns6CfgData, DnsConfigData);
1006     if (EFI_ERROR (Status)) {
1007       goto ON_EXIT;
1008     }
1009 
1010     if (DnsConfigData->DnsServerCount == 0 || DnsConfigData->DnsServerList == NULL) {
1011       gBS->RestoreTPL (OldTpl);
1012 
1013       //
1014       //The DNS instance will retrieve DNS server from DHCP Server.
1015       //
1016       Status = GetDns6ServerFromDhcp6 (
1017                  Instance->Service->ImageHandle,
1018                  Instance->Service->ControllerHandle,
1019                  &ServerListCount,
1020                  &ServerList
1021                  );
1022       if (EFI_ERROR (Status)) {
1023         goto ON_EXIT;
1024       }
1025 
1026       ASSERT(ServerList != NULL);
1027 
1028       OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1029 
1030       CopyMem (&Instance->SessionDnsServer.v6, &ServerList[0], sizeof (EFI_IPv6_ADDRESS));
1031     } else {
1032       CopyMem (&Instance->SessionDnsServer.v6, &DnsConfigData->DnsServerList[0], sizeof (EFI_IPv6_ADDRESS));
1033     }
1034 
1035     //
1036     // Config UDP
1037     //
1038     Status = Dns6ConfigUdp (Instance, Instance->UdpIo);
1039     if (EFI_ERROR (Status)) {
1040       if (Instance->Dns6CfgData.DnsServerList != NULL) {
1041         FreePool (Instance->Dns6CfgData.DnsServerList);
1042       }
1043       goto ON_EXIT;
1044     }
1045 
1046     //
1047     // Add configured DNS server used by this instance to ServerList.
1048     //
1049     Status = AddDns6ServerIp (&mDriverData->Dns6ServerList, Instance->SessionDnsServer.v6);
1050     if (EFI_ERROR (Status)) {
1051       if (Instance->Dns6CfgData.DnsServerList != NULL) {
1052         FreePool (Instance->Dns6CfgData.DnsServerList);
1053       }
1054       goto ON_EXIT;
1055     }
1056 
1057     Instance->State = DNS_STATE_CONFIGED;
1058   }
1059 
1060 ON_EXIT:
1061   gBS->RestoreTPL (OldTpl);
1062   return Status;
1063 }
1064 
1065 /**
1066   The function is used to translate the host name to host IP address.
1067   A type AAAA query is used to get the one or more IPv6 addresses for this host.
1068 
1069   @param[in]  This               Pointer to EFI_DNS6_PROTOCOL instance.
1070   @param[in]  HostName           Pointer to caller-supplied buffer containing Host name to be translated.
1071                                  This buffer contains 16 bit characters but these are translated to ASCII for use with
1072                                  DNSv4 server and there is no requirement for driver to support non-ASCII Unicode characters.
1073   @param[in]  Token              Pointer to the caller-allocated completion token to return at the completion of the process to translate host name to host address.
1074 
1075   @retval  EFI_SUCCESS           The operation completed successfully.
1076   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate needed resources.
1077   @retval  EFI_INVALID_PARAMETER This is NULL.
1078                                  Token is NULL.
1079                                  Token.Event is.NULL
1080                                  HostName is NULL
1081   @retval  EFI_NO_MAPPING        There's no source address is available for use.
1082   @retval  EFI_NOT_STARTED       This instance has not been started.
1083 
1084 **/
1085 EFI_STATUS
1086 EFIAPI
Dns6HostNameToIp(IN EFI_DNS6_PROTOCOL * This,IN CHAR16 * HostName,IN EFI_DNS6_COMPLETION_TOKEN * Token)1087 Dns6HostNameToIp (
1088   IN  EFI_DNS6_PROTOCOL          *This,
1089   IN  CHAR16                     *HostName,
1090   IN  EFI_DNS6_COMPLETION_TOKEN  *Token
1091   )
1092 {
1093   EFI_STATUS            Status;
1094 
1095   DNS_INSTANCE          *Instance;
1096 
1097   EFI_DNS6_CONFIG_DATA  *ConfigData;
1098 
1099   UINTN                 Index;
1100   DNS6_CACHE            *Item;
1101   LIST_ENTRY            *Entry;
1102   LIST_ENTRY            *Next;
1103 
1104   CHAR8                 *QueryName;
1105 
1106   DNS6_TOKEN_ENTRY      *TokenEntry;
1107   NET_BUF               *Packet;
1108 
1109   EFI_TPL               OldTpl;
1110 
1111   Status     = EFI_SUCCESS;
1112   Item       = NULL;
1113   QueryName  = NULL;
1114   TokenEntry = NULL;
1115   Packet     = NULL;
1116 
1117   //
1118   // Validate the parameters
1119   //
1120   if ((This == NULL) || (HostName == NULL) || Token == NULL) {
1121     return EFI_INVALID_PARAMETER;
1122   }
1123 
1124   OldTpl   = gBS->RaiseTPL (TPL_CALLBACK);
1125 
1126   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL6 (This);
1127 
1128   ConfigData = &(Instance->Dns6CfgData);
1129 
1130   Instance->MaxRetry = ConfigData->RetryCount;
1131 
1132   Token->Status = EFI_NOT_READY;
1133   Token->RetryCount = 0;
1134   Token->RetryInterval = ConfigData->RetryInterval;
1135 
1136   if (Instance->State != DNS_STATE_CONFIGED) {
1137     Status = EFI_NOT_STARTED;
1138     goto ON_EXIT;
1139   }
1140 
1141   //
1142   // Check the MaxRetry and RetryInterval values.
1143   //
1144   if (Instance->MaxRetry == 0) {
1145     Instance->MaxRetry = DNS_DEFAULT_RETRY;
1146   }
1147 
1148   if (Token->RetryInterval < DNS_DEFAULT_TIMEOUT) {
1149     Token->RetryInterval = DNS_DEFAULT_TIMEOUT;
1150   }
1151 
1152   //
1153   // Check cache
1154   //
1155   if (ConfigData->EnableDnsCache) {
1156     Index = 0;
1157     NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6CacheList) {
1158       Item = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
1159       if (StrCmp (HostName, Item->DnsCache.HostName) == 0) {
1160         Index++;
1161       }
1162     }
1163 
1164     if (Index != 0) {
1165       Token->RspData.H2AData = AllocatePool (sizeof (DNS6_HOST_TO_ADDR_DATA));
1166       if (Token->RspData.H2AData == NULL) {
1167         Status = EFI_OUT_OF_RESOURCES;
1168         goto ON_EXIT;
1169       }
1170 
1171       Token->RspData.H2AData->IpCount = (UINT32)Index;
1172       Token->RspData.H2AData->IpList = AllocatePool (sizeof (EFI_IPv6_ADDRESS) * Index);
1173       if (Token->RspData.H2AData->IpList == NULL) {
1174         if (Token->RspData.H2AData != NULL) {
1175           FreePool (Token->RspData.H2AData);
1176         }
1177 
1178         Status = EFI_OUT_OF_RESOURCES;
1179         goto ON_EXIT;
1180       }
1181 
1182       Index = 0;
1183       NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6CacheList) {
1184         Item = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
1185         if ((UINT32)Index < Token->RspData.H2AData->IpCount && StrCmp (HostName, Item->DnsCache.HostName) == 0) {
1186           CopyMem ((Token->RspData.H2AData->IpList) + Index, Item->DnsCache.IpAddress, sizeof (EFI_IPv6_ADDRESS));
1187           Index++;
1188         }
1189       }
1190 
1191       Token->Status = EFI_SUCCESS;
1192 
1193       if (Token->Event != NULL) {
1194         gBS->SignalEvent (Token->Event);
1195         DispatchDpc ();
1196       }
1197 
1198       Status = Token->Status;
1199       goto ON_EXIT;
1200     }
1201   }
1202 
1203   //
1204   // Construct DNS TokenEntry.
1205   //
1206   TokenEntry = AllocateZeroPool (sizeof (DNS6_TOKEN_ENTRY));
1207   if (TokenEntry == NULL) {
1208     Status = EFI_OUT_OF_RESOURCES;
1209     goto ON_EXIT;
1210   }
1211 
1212   TokenEntry->PacketToLive = Token->RetryInterval;
1213   TokenEntry->QueryHostName = HostName;
1214   TokenEntry->Token = Token;
1215 
1216 
1217   //
1218   // Construct QName.
1219   //
1220   QueryName = DnsFillinQNameForQueryIp (TokenEntry->QueryHostName);
1221   if (QueryName == NULL) {
1222     Status = EFI_OUT_OF_RESOURCES;
1223     goto ON_EXIT;
1224   }
1225 
1226   //
1227   // Construct DNS Query Packet.
1228   //
1229   Status = ConstructDNSQuery (Instance, QueryName, DNS_TYPE_AAAA, DNS_CLASS_INET, &Packet);
1230   if (EFI_ERROR (Status)) {
1231     if (TokenEntry != NULL) {
1232       FreePool (TokenEntry);
1233     }
1234 
1235     goto ON_EXIT;
1236   }
1237 
1238   ASSERT (Packet != NULL);
1239 
1240   //
1241   // Save the token into the Dns6TxTokens map.
1242   //
1243   Status = NetMapInsertTail (&Instance->Dns6TxTokens, TokenEntry, Packet);
1244   if (EFI_ERROR (Status)) {
1245     if (TokenEntry != NULL) {
1246       FreePool (TokenEntry);
1247     }
1248 
1249     NetbufFree (Packet);
1250 
1251     goto ON_EXIT;
1252   }
1253 
1254   //
1255   // Dns Query Ip
1256   //
1257   Status = DoDnsQuery (Instance, Packet);
1258   if (EFI_ERROR (Status)) {
1259     if (TokenEntry != NULL) {
1260       FreePool (TokenEntry);
1261     }
1262 
1263     NetbufFree (Packet);
1264   }
1265 
1266 ON_EXIT:
1267   if (QueryName != NULL) {
1268     FreePool (QueryName);
1269   }
1270 
1271   gBS->RestoreTPL (OldTpl);
1272   return Status;
1273 }
1274 
1275 /**
1276   The function is used to translate the host address to host name.
1277   A type PTR query is used to get the primary name of the host.
1278 
1279   @param[in]  This               Pointer to EFI_DNS6_PROTOCOL instance.
1280   @param[in]  IpAddress          IP address.
1281   @param[in]  Token              Pointer to the caller-allocated completion used token to translate host address to host name.
1282 
1283   @retval  EFI_SUCCESS           The operation completed successfully.
1284   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate needed resources.
1285   @retval  EFI_INVALID_PARAMETER This is NULL.
1286                                  Token is NULL.
1287                                  Token.Event is NULL.
1288                                  IpAddress is not valid IP address.
1289   @retval  EFI_NO_MAPPING        There's no source address is available for use.
1290   @retval  EFI_NOT_STARTED       This instance has not been started.
1291   @retval  EFI_UNSUPPORTED       This function is not supported.
1292 
1293 **/
1294 EFI_STATUS
1295 EFIAPI
Dns6IpToHostName(IN EFI_DNS6_PROTOCOL * This,IN EFI_IPv6_ADDRESS IpAddress,IN EFI_DNS6_COMPLETION_TOKEN * Token)1296 Dns6IpToHostName (
1297   IN  EFI_DNS6_PROTOCOL              *This,
1298   IN  EFI_IPv6_ADDRESS               IpAddress,
1299   IN  EFI_DNS6_COMPLETION_TOKEN      *Token
1300   )
1301 {
1302   return EFI_UNSUPPORTED;
1303 }
1304 
1305 /**
1306   This function retrieves arbitrary information from the DNS.
1307   The caller supplies a QNAME, QTYPE, and QCLASS, and all of the matching RRs are returned.
1308   All RR content (e.g., Ttl) was returned.
1309   The caller need parse the returned RR to get required information. This function is optional.
1310 
1311   @param[in]  This               Pointer to EFI_DNS6_PROTOCOL instance.
1312   @param[in]  QName              Pointer to Query Name.
1313   @param[in]  QType              Query Type.
1314   @param[in]  QClass             Query Name.
1315   @param[in]  Token              Point to the caller-allocated completion token to retrieve arbitrary information.
1316 
1317   @retval  EFI_SUCCESS           The operation completed successfully.
1318   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate needed resources.
1319   @retval  EFI_INVALID_PARAMETER This is NULL.
1320                                  Token is NULL.
1321                                  Token.Event is NULL.
1322                                  QName is NULL.
1323   @retval  EFI_NO_MAPPING        There's no source address is available for use.
1324   @retval  EFI_NOT_STARTED       This instance has not been started.
1325   @retval  EFI_UNSUPPORTED       This function is not supported. Or the requested QType is not supported
1326 
1327 **/
1328 EFI_STATUS
1329 EFIAPI
Dns6GeneralLookUp(IN EFI_DNS6_PROTOCOL * This,IN CHAR8 * QName,IN UINT16 QType,IN UINT16 QClass,IN EFI_DNS6_COMPLETION_TOKEN * Token)1330 Dns6GeneralLookUp (
1331   IN  EFI_DNS6_PROTOCOL                 *This,
1332   IN  CHAR8                             *QName,
1333   IN  UINT16                            QType,
1334   IN  UINT16                            QClass,
1335   IN  EFI_DNS6_COMPLETION_TOKEN         *Token
1336   )
1337 {
1338   EFI_STATUS            Status;
1339 
1340   DNS_INSTANCE          *Instance;
1341 
1342   EFI_DNS6_CONFIG_DATA  *ConfigData;
1343 
1344   DNS6_TOKEN_ENTRY      *TokenEntry;
1345   NET_BUF               *Packet;
1346 
1347   EFI_TPL               OldTpl;
1348 
1349   Status     = EFI_SUCCESS;
1350   TokenEntry = NULL;
1351   Packet     = NULL;
1352 
1353   //
1354   // Validate the parameters
1355   //
1356   if ((This == NULL) || (QName == NULL) || Token == NULL) {
1357     return EFI_INVALID_PARAMETER;
1358   }
1359 
1360   OldTpl   = gBS->RaiseTPL (TPL_CALLBACK);
1361 
1362   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL6 (This);
1363 
1364   ConfigData = &(Instance->Dns6CfgData);
1365 
1366   Instance->MaxRetry = ConfigData->RetryCount;
1367 
1368   Token->Status = EFI_NOT_READY;
1369   Token->RetryCount = 0;
1370   Token->RetryInterval = ConfigData->RetryInterval;
1371 
1372   if (Instance->State != DNS_STATE_CONFIGED) {
1373     Status = EFI_NOT_STARTED;
1374     goto ON_EXIT;
1375   }
1376 
1377   //
1378   // Check the MaxRetry and RetryInterval values.
1379   //
1380   if (Instance->MaxRetry == 0) {
1381     Instance->MaxRetry = DNS_DEFAULT_RETRY;
1382   }
1383 
1384   if (Token->RetryInterval < DNS_DEFAULT_TIMEOUT) {
1385     Token->RetryInterval = DNS_DEFAULT_TIMEOUT;
1386   }
1387 
1388   //
1389   // Construct DNS TokenEntry.
1390   //
1391   TokenEntry = AllocateZeroPool (sizeof(DNS6_TOKEN_ENTRY));
1392   if (TokenEntry == NULL) {
1393     Status = EFI_OUT_OF_RESOURCES;
1394     goto ON_EXIT;
1395   }
1396 
1397   TokenEntry->PacketToLive = Token->RetryInterval;
1398   TokenEntry->GeneralLookUp = TRUE;
1399   TokenEntry->Token = Token;
1400 
1401   //
1402   // Construct DNS Query Packet.
1403   //
1404   Status = ConstructDNSQuery (Instance, QName, QType, QClass, &Packet);
1405   if (EFI_ERROR (Status)) {
1406     if (TokenEntry != NULL) {
1407       FreePool (TokenEntry);
1408     }
1409 
1410     goto ON_EXIT;
1411   }
1412 
1413   ASSERT (Packet != NULL);
1414 
1415   //
1416   // Save the token into the Dns6TxTokens map.
1417   //
1418   Status = NetMapInsertTail (&Instance->Dns6TxTokens, TokenEntry, Packet);
1419   if (EFI_ERROR (Status)) {
1420     if (TokenEntry != NULL) {
1421       FreePool (TokenEntry);
1422     }
1423 
1424     NetbufFree (Packet);
1425 
1426     goto ON_EXIT;
1427   }
1428 
1429   //
1430   // Dns Query Ip
1431   //
1432   Status = DoDnsQuery (Instance, Packet);
1433   if (EFI_ERROR (Status)) {
1434     if (TokenEntry != NULL) {
1435       FreePool (TokenEntry);
1436     }
1437 
1438     NetbufFree (Packet);
1439   }
1440 
1441 ON_EXIT:
1442   gBS->RestoreTPL (OldTpl);
1443   return Status;
1444 }
1445 
1446 /**
1447   This function is used to add/delete/modify DNS cache entry.
1448   DNS cache can be normally dynamically updated after the DNS resolve succeeds.
1449   This function provided capability to manually add/delete/modify the DNS cache.
1450 
1451   @param[in]  This               Pointer to EFI_DNS6_PROTOCOL instance.
1452   @param[in]  DeleteFlag         If FALSE, this function is to add one entry to the DNS Cache.
1453                                  If TRUE, this function will delete matching DNS Cache entry.
1454   @param[in]  Override           If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
1455                                  If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
1456   @param[in]  DnsCacheEntry      Pointer to DNS Cache entry.
1457 
1458   @retval  EFI_SUCCESS           The operation completed successfully.
1459   @retval  EFI_INVALID_PARAMETER This is NULL.
1460                                  DnsCacheEntry.HostName is NULL.
1461                                  DnsCacheEntry.IpAddress is NULL.
1462                                  DnsCacheEntry.Timeout is zero.
1463   @retval  EFI_ACCESS_DENIED     The DNS cache entry already exists and Override is not TRUE.
1464 
1465 **/
1466 EFI_STATUS
1467 EFIAPI
Dns6UpdateDnsCache(IN EFI_DNS6_PROTOCOL * This,IN BOOLEAN DeleteFlag,IN BOOLEAN Override,IN EFI_DNS6_CACHE_ENTRY DnsCacheEntry)1468 Dns6UpdateDnsCache (
1469   IN EFI_DNS6_PROTOCOL      *This,
1470   IN BOOLEAN                DeleteFlag,
1471   IN BOOLEAN                Override,
1472   IN EFI_DNS6_CACHE_ENTRY   DnsCacheEntry
1473   )
1474 {
1475   EFI_STATUS    Status;
1476   EFI_TPL       OldTpl;
1477 
1478   Status = EFI_SUCCESS;
1479 
1480   if (DnsCacheEntry.HostName == NULL || DnsCacheEntry.IpAddress == NULL || DnsCacheEntry.Timeout == 0) {
1481     return EFI_INVALID_PARAMETER;
1482   }
1483 
1484   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1485 
1486   //
1487   // Update Dns6Cache here.
1488   //
1489   Status = UpdateDns6Cache (&mDriverData->Dns6CacheList, DeleteFlag, Override, DnsCacheEntry);
1490 
1491   gBS->RestoreTPL (OldTpl);
1492 
1493   return Status;
1494 }
1495 
1496 /**
1497   This function can be used by network drivers and applications to increase the rate that data packets are moved between
1498   the communications device and the transmit and receive queues. In some systems, the periodic timer event in the managed
1499   network driver may not poll the underlying communications device fast enough to transmit and/or receive all data packets
1500   without missing incoming packets or dropping outgoing packets.
1501 
1502   @param[in]  This               Pointer to EFI_DNS6_PROTOCOL instance.
1503 
1504   @retval  EFI_SUCCESS           Incoming or outgoing data was processed.
1505   @retval  EFI_INVALID_PARAMETER This is NULL.
1506   @retval  EFI_NOT_STARTED       This EFI DNS Protocol instance has not been started.
1507   @retval  EFI_DEVICE_ERROR      An unexpected system or network error occurred.
1508   @retval  EFI_TIMEOUT           Data was dropped out of the transmit and/or receive queue.
1509                                  Consider increasing the polling rate.
1510 
1511 **/
1512 EFI_STATUS
1513 EFIAPI
Dns6Poll(IN EFI_DNS6_PROTOCOL * This)1514 Dns6Poll (
1515   IN EFI_DNS6_PROTOCOL    *This
1516   )
1517 {
1518   DNS_INSTANCE           *Instance;
1519   EFI_UDP6_PROTOCOL      *Udp;
1520 
1521   if (This == NULL) {
1522     return EFI_INVALID_PARAMETER;
1523   }
1524 
1525   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL6 (This);
1526 
1527   if (Instance->State == DNS_STATE_UNCONFIGED) {
1528     return EFI_NOT_STARTED;
1529   } else if (Instance->State == DNS_STATE_DESTROY) {
1530     return EFI_DEVICE_ERROR;
1531   }
1532 
1533   Udp = Instance->UdpIo->Protocol.Udp6;
1534 
1535   return Udp->Poll (Udp);
1536 }
1537 
1538 /**
1539   This function is used to abort a pending resolution request.
1540   After calling this function, Token.Status will be set to EFI_ABORTED and then Token.
1541 
1542   @param[in]  This               Pointer to EFI_DNS6_PROTOCOL instance.
1543   @param[in]  Token              Pointer to a token that has been issued by EFI_DNS6_PROTOCOL.HostNameToIp(),
1544                                  EFI_DNS6_PROTOCOL.IpToHostName() or EFI_DNS6_PROTOCOL.GeneralLookup().
1545                                  If NULL, all pending tokens are aborted.
1546 
1547   @retval  EFI_SUCCESS           Incoming or outgoing data was processed.
1548   @retval  EFI_INVALID_PARAMETER This is NULL.
1549   @retval  EFI_NOT_STARTED       This EFI DNS Protocol instance has not been started.
1550   @retval  EFI_NOT_FOUND         When Token is not NULL, and the asynchronous DNS operation was not found in the transmit queue.
1551                                  It was either completed or was not issued by HostNameToIp(), IpToHostName() or GeneralLookup().
1552 
1553 **/
1554 EFI_STATUS
1555 EFIAPI
Dns6Cancel(IN EFI_DNS6_PROTOCOL * This,IN EFI_DNS6_COMPLETION_TOKEN * Token)1556 Dns6Cancel (
1557   IN  EFI_DNS6_PROTOCOL          *This,
1558   IN  EFI_DNS6_COMPLETION_TOKEN  *Token
1559   )
1560 {
1561   EFI_STATUS          Status;
1562   DNS_INSTANCE        *Instance;
1563   EFI_TPL             OldTpl;
1564 
1565   if (This == NULL) {
1566     return EFI_INVALID_PARAMETER;
1567   }
1568 
1569   Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL6 (This);
1570 
1571   if (Instance->State == DNS_STATE_UNCONFIGED) {
1572     return EFI_NOT_STARTED;
1573   }
1574 
1575   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1576 
1577   //
1578   // Cancle the tokens specified by Token for this instance.
1579   //
1580   Status = Dns6InstanceCancelToken (Instance, Token);
1581 
1582   //
1583   // Dispatch the DPC queued by the NotifyFunction of the canceled token's events.
1584   //
1585   DispatchDpc ();
1586 
1587   gBS->RestoreTPL (OldTpl);
1588 
1589   return Status;
1590 }
1591 
1592