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