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