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