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