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