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