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