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