VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsImpl.c

最後變更 在這個檔案是 105670,由 vboxsync 提交於 7 月 前

Devices/EFI/FirmwareNew: Merge edk2-stable-202405 and make it build on aarch64, bugref:4643

  • 屬性 svn:eol-style 設為 native
檔案大小: 62.5 KB
 
1/** @file
2DnsDxe support functions implementation.
3
4Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
5Copyright (c) Microsoft Corporation
6SPDX-License-Identifier: BSD-2-Clause-Patent
7
8**/
9
10#include "DnsImpl.h"
11
12/**
13 Remove TokenEntry from TokenMap.
14
15 @param[in] TokenMap All DNSv4 Token entrys.
16 @param[in] TokenEntry TokenEntry need to be removed.
17
18 @retval EFI_SUCCESS Remove TokenEntry from TokenMap successfully.
19 @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap.
20
21**/
22EFI_STATUS
23Dns4RemoveTokenEntry (
24 IN NET_MAP *TokenMap,
25 IN DNS4_TOKEN_ENTRY *TokenEntry
26 )
27{
28 NET_MAP_ITEM *Item;
29
30 //
31 // Find the TokenEntry first.
32 //
33 Item = NetMapFindKey (TokenMap, (VOID *)TokenEntry);
34
35 if (Item != NULL) {
36 //
37 // Remove the TokenEntry if it's found in the map.
38 //
39 NetMapRemoveItem (TokenMap, Item, NULL);
40
41 return EFI_SUCCESS;
42 }
43
44 return EFI_NOT_FOUND;
45}
46
47/**
48 Remove TokenEntry from TokenMap.
49
50 @param[in] TokenMap All DNSv6 Token entrys.
51 @param[in] TokenEntry TokenEntry need to be removed.
52
53 @retval EFI_SUCCESS Remove TokenEntry from TokenMap successfully.
54 @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap.
55
56**/
57EFI_STATUS
58Dns6RemoveTokenEntry (
59 IN NET_MAP *TokenMap,
60 IN DNS6_TOKEN_ENTRY *TokenEntry
61 )
62{
63 NET_MAP_ITEM *Item;
64
65 //
66 // Find the TokenEntry first.
67 //
68 Item = NetMapFindKey (TokenMap, (VOID *)TokenEntry);
69
70 if (Item != NULL) {
71 //
72 // Remove the TokenEntry if it's found in the map.
73 //
74 NetMapRemoveItem (TokenMap, Item, NULL);
75
76 return EFI_SUCCESS;
77 }
78
79 return EFI_NOT_FOUND;
80}
81
82/**
83 This function cancel the token specified by Arg in the Map.
84
85 @param[in] Map Pointer to the NET_MAP.
86 @param[in] Item Pointer to the NET_MAP_ITEM.
87 @param[in] Arg Pointer to the token to be cancelled. If NULL, all
88 the tokens in this Map will be cancelled.
89 This parameter is optional and may be NULL.
90
91 @retval EFI_SUCCESS The token is cancelled if Arg is NULL, or the token
92 is not the same as that in the Item, if Arg is not
93 NULL.
94 @retval EFI_ABORTED Arg is not NULL, and the token specified by Arg is
95 cancelled.
96
97**/
98EFI_STATUS
99EFIAPI
100Dns4CancelTokens (
101 IN NET_MAP *Map,
102 IN NET_MAP_ITEM *Item,
103 IN VOID *Arg OPTIONAL
104 )
105{
106 DNS4_TOKEN_ENTRY *TokenEntry;
107 NET_BUF *Packet;
108 UDP_IO *UdpIo;
109
110 if ((Arg != NULL) && (Item->Key != Arg)) {
111 return EFI_SUCCESS;
112 }
113
114 if (Item->Value != NULL) {
115 //
116 // If the TokenEntry is a transmit TokenEntry, the corresponding Packet is recorded in
117 // Item->Value.
118 //
119 Packet = (NET_BUF *)(Item->Value);
120 UdpIo = (UDP_IO *)(*((UINTN *)&Packet->ProtoData[0]));
121
122 UdpIoCancelSentDatagram (UdpIo, Packet);
123 }
124
125 //
126 // Remove TokenEntry from Dns4TxTokens.
127 //
128 TokenEntry = (DNS4_TOKEN_ENTRY *)Item->Key;
129 if (Dns4RemoveTokenEntry (Map, TokenEntry) == EFI_SUCCESS) {
130 TokenEntry->Token->Status = EFI_ABORTED;
131 gBS->SignalEvent (TokenEntry->Token->Event);
132 DispatchDpc ();
133 }
134
135 if (Arg != NULL) {
136 return EFI_ABORTED;
137 }
138
139 return EFI_SUCCESS;
140}
141
142/**
143 This function cancel the token specified by Arg in the Map.
144
145 @param[in] Map Pointer to the NET_MAP.
146 @param[in] Item Pointer to the NET_MAP_ITEM.
147 @param[in] Arg Pointer to the token to be cancelled. If NULL, all
148 the tokens in this Map will be cancelled.
149 This parameter is optional and may be NULL.
150
151 @retval EFI_SUCCESS The token is cancelled if Arg is NULL, or the token
152 is not the same as that in the Item, if Arg is not
153 NULL.
154 @retval EFI_ABORTED Arg is not NULL, and the token specified by Arg is
155 cancelled.
156
157**/
158EFI_STATUS
159EFIAPI
160Dns6CancelTokens (
161 IN NET_MAP *Map,
162 IN NET_MAP_ITEM *Item,
163 IN VOID *Arg OPTIONAL
164 )
165{
166 DNS6_TOKEN_ENTRY *TokenEntry;
167 NET_BUF *Packet;
168 UDP_IO *UdpIo;
169
170 if ((Arg != NULL) && (Item->Key != Arg)) {
171 return EFI_SUCCESS;
172 }
173
174 if (Item->Value != NULL) {
175 //
176 // If the TokenEntry is a transmit TokenEntry, the corresponding Packet is recorded in
177 // Item->Value.
178 //
179 Packet = (NET_BUF *)(Item->Value);
180 UdpIo = (UDP_IO *)(*((UINTN *)&Packet->ProtoData[0]));
181
182 UdpIoCancelSentDatagram (UdpIo, Packet);
183 }
184
185 //
186 // Remove TokenEntry from Dns6TxTokens.
187 //
188 TokenEntry = (DNS6_TOKEN_ENTRY *)Item->Key;
189 if (Dns6RemoveTokenEntry (Map, TokenEntry) == EFI_SUCCESS) {
190 TokenEntry->Token->Status = EFI_ABORTED;
191 gBS->SignalEvent (TokenEntry->Token->Event);
192 DispatchDpc ();
193 }
194
195 if (Arg != NULL) {
196 return EFI_ABORTED;
197 }
198
199 return EFI_SUCCESS;
200}
201
202/**
203 Get the TokenEntry from the TokensMap.
204
205 @param[in] TokensMap All DNSv4 Token entrys
206 @param[in] Token Pointer to the token to be get.
207 @param[out] TokenEntry Pointer to TokenEntry corresponding Token.
208
209 @retval EFI_SUCCESS Get the TokenEntry from the TokensMap successfully.
210 @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap.
211
212**/
213EFI_STATUS
214EFIAPI
215GetDns4TokenEntry (
216 IN NET_MAP *TokensMap,
217 IN EFI_DNS4_COMPLETION_TOKEN *Token,
218 OUT DNS4_TOKEN_ENTRY **TokenEntry
219 )
220{
221 LIST_ENTRY *Entry;
222
223 NET_MAP_ITEM *Item;
224
225 NET_LIST_FOR_EACH (Entry, &TokensMap->Used) {
226 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
227 *TokenEntry = (DNS4_TOKEN_ENTRY *)(Item->Key);
228 if ((*TokenEntry)->Token == Token) {
229 return EFI_SUCCESS;
230 }
231 }
232
233 *TokenEntry = NULL;
234
235 return EFI_NOT_FOUND;
236}
237
238/**
239 Get the TokenEntry from the TokensMap.
240
241 @param[in] TokensMap All DNSv6 Token entrys
242 @param[in] Token Pointer to the token to be get.
243 @param[out] TokenEntry Pointer to TokenEntry corresponding Token.
244
245 @retval EFI_SUCCESS Get the TokenEntry from the TokensMap successfully.
246 @retval EFI_NOT_FOUND TokenEntry is not found in TokenMap.
247
248**/
249EFI_STATUS
250EFIAPI
251GetDns6TokenEntry (
252 IN NET_MAP *TokensMap,
253 IN EFI_DNS6_COMPLETION_TOKEN *Token,
254 OUT DNS6_TOKEN_ENTRY **TokenEntry
255 )
256{
257 LIST_ENTRY *Entry;
258
259 NET_MAP_ITEM *Item;
260
261 NET_LIST_FOR_EACH (Entry, &TokensMap->Used) {
262 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
263 *TokenEntry = (DNS6_TOKEN_ENTRY *)(Item->Key);
264 if ((*TokenEntry)->Token == Token) {
265 return EFI_SUCCESS;
266 }
267 }
268
269 *TokenEntry = NULL;
270
271 return EFI_NOT_FOUND;
272}
273
274/**
275 Cancel DNS4 tokens from the DNS4 instance.
276
277 @param[in] Instance Pointer to the DNS instance context data.
278 @param[in] Token Pointer to the token to be canceled. If NULL, all
279 tokens in this instance will be cancelled.
280 This parameter is optional and may be NULL.
281
282 @retval EFI_SUCCESS The Token is cancelled.
283 @retval EFI_NOT_FOUND The Token is not found.
284
285**/
286EFI_STATUS
287Dns4InstanceCancelToken (
288 IN DNS_INSTANCE *Instance,
289 IN EFI_DNS4_COMPLETION_TOKEN *Token
290 )
291{
292 EFI_STATUS Status;
293 DNS4_TOKEN_ENTRY *TokenEntry;
294
295 TokenEntry = NULL;
296
297 if (Token != NULL ) {
298 Status = GetDns4TokenEntry (&Instance->Dns4TxTokens, Token, &TokenEntry);
299 if (EFI_ERROR (Status)) {
300 return Status;
301 }
302 } else {
303 TokenEntry = NULL;
304 }
305
306 //
307 // Cancel this TokenEntry from the Dns4TxTokens map.
308 //
309 Status = NetMapIterate (&Instance->Dns4TxTokens, Dns4CancelTokens, TokenEntry);
310
311 if ((TokenEntry != NULL) && (Status == EFI_ABORTED)) {
312 //
313 // If Token isn't NULL and Status is EFI_ABORTED, the token is cancelled from
314 // the Dns4TxTokens and returns success.
315 //
316 if (NetMapIsEmpty (&Instance->Dns4TxTokens)) {
317 Instance->UdpIo->Protocol.Udp4->Cancel (Instance->UdpIo->Protocol.Udp4, &Instance->UdpIo->RecvRequest->Token.Udp4);
318 }
319
320 return EFI_SUCCESS;
321 }
322
323 ASSERT ((TokenEntry != NULL) || (0 == NetMapGetCount (&Instance->Dns4TxTokens)));
324
325 if (NetMapIsEmpty (&Instance->Dns4TxTokens)) {
326 Instance->UdpIo->Protocol.Udp4->Cancel (Instance->UdpIo->Protocol.Udp4, &Instance->UdpIo->RecvRequest->Token.Udp4);
327 }
328
329 return EFI_SUCCESS;
330}
331
332/**
333 Cancel DNS6 tokens from the DNS6 instance.
334
335 @param[in] Instance Pointer to the DNS instance context data.
336 @param[in] Token Pointer to the token to be canceled. If NULL, all
337 tokens in this instance will be cancelled.
338 This parameter is optional and may be NULL.
339
340 @retval EFI_SUCCESS The Token is cancelled.
341 @retval EFI_NOT_FOUND The Token is not found.
342
343**/
344EFI_STATUS
345Dns6InstanceCancelToken (
346 IN DNS_INSTANCE *Instance,
347 IN EFI_DNS6_COMPLETION_TOKEN *Token
348 )
349{
350 EFI_STATUS Status;
351 DNS6_TOKEN_ENTRY *TokenEntry;
352
353 TokenEntry = NULL;
354
355 if (Token != NULL ) {
356 Status = GetDns6TokenEntry (&Instance->Dns6TxTokens, Token, &TokenEntry);
357 if (EFI_ERROR (Status)) {
358 return Status;
359 }
360 } else {
361 TokenEntry = NULL;
362 }
363
364 //
365 // Cancel this TokenEntry from the Dns6TxTokens map.
366 //
367 Status = NetMapIterate (&Instance->Dns6TxTokens, Dns6CancelTokens, TokenEntry);
368
369 if ((TokenEntry != NULL) && (Status == EFI_ABORTED)) {
370 //
371 // If Token isn't NULL and Status is EFI_ABORTED, the token is cancelled from
372 // the Dns6TxTokens and returns success.
373 //
374 if (NetMapIsEmpty (&Instance->Dns6TxTokens)) {
375 Instance->UdpIo->Protocol.Udp6->Cancel (Instance->UdpIo->Protocol.Udp6, &Instance->UdpIo->RecvRequest->Token.Udp6);
376 }
377
378 return EFI_SUCCESS;
379 }
380
381 ASSERT ((TokenEntry != NULL) || (0 == NetMapGetCount (&Instance->Dns6TxTokens)));
382
383 if (NetMapIsEmpty (&Instance->Dns6TxTokens)) {
384 Instance->UdpIo->Protocol.Udp6->Cancel (Instance->UdpIo->Protocol.Udp6, &Instance->UdpIo->RecvRequest->Token.Udp6);
385 }
386
387 return EFI_SUCCESS;
388}
389
390/**
391 Free the resource related to the configure parameters.
392
393 @param Config The DNS configure data
394
395**/
396VOID
397Dns4CleanConfigure (
398 IN OUT EFI_DNS4_CONFIG_DATA *Config
399 )
400{
401 if (Config->DnsServerList != NULL) {
402 FreePool (Config->DnsServerList);
403 }
404
405 ZeroMem (Config, sizeof (EFI_DNS4_CONFIG_DATA));
406}
407
408/**
409 Free the resource related to the configure parameters.
410
411 @param Config The DNS configure data
412
413**/
414VOID
415Dns6CleanConfigure (
416 IN OUT EFI_DNS6_CONFIG_DATA *Config
417 )
418{
419 if (Config->DnsServerList != NULL) {
420 FreePool (Config->DnsServerList);
421 }
422
423 ZeroMem (Config, sizeof (EFI_DNS6_CONFIG_DATA));
424}
425
426/**
427 Allocate memory for configure parameter such as timeout value for Dst,
428 then copy the configure parameter from Src to Dst.
429
430 @param[out] Dst The destination DHCP configure data.
431 @param[in] Src The source DHCP configure data.
432
433 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
434 @retval EFI_SUCCESS The configure is copied.
435
436**/
437EFI_STATUS
438Dns4CopyConfigure (
439 OUT EFI_DNS4_CONFIG_DATA *Dst,
440 IN EFI_DNS4_CONFIG_DATA *Src
441 )
442{
443 UINTN Len;
444 UINT32 Index;
445
446 CopyMem (Dst, Src, sizeof (*Dst));
447 Dst->DnsServerList = NULL;
448
449 //
450 // Allocate a memory then copy DnsServerList to it
451 //
452 if (Src->DnsServerList != NULL) {
453 Len = Src->DnsServerListCount * sizeof (EFI_IPv4_ADDRESS);
454 Dst->DnsServerList = AllocatePool (Len);
455 if (Dst->DnsServerList == NULL) {
456 Dns4CleanConfigure (Dst);
457 return EFI_OUT_OF_RESOURCES;
458 }
459
460 for (Index = 0; Index < Src->DnsServerListCount; Index++) {
461 CopyMem (&Dst->DnsServerList[Index], &Src->DnsServerList[Index], sizeof (EFI_IPv4_ADDRESS));
462 }
463 }
464
465 return EFI_SUCCESS;
466}
467
468/**
469 Allocate memory for configure parameter such as timeout value for Dst,
470 then copy the configure parameter from Src to Dst.
471
472 @param[out] Dst The destination DHCP configure data.
473 @param[in] Src The source DHCP configure data.
474
475 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
476 @retval EFI_SUCCESS The configure is copied.
477
478**/
479EFI_STATUS
480Dns6CopyConfigure (
481 OUT EFI_DNS6_CONFIG_DATA *Dst,
482 IN EFI_DNS6_CONFIG_DATA *Src
483 )
484{
485 UINTN Len;
486 UINT32 Index;
487
488 CopyMem (Dst, Src, sizeof (*Dst));
489 Dst->DnsServerList = NULL;
490
491 //
492 // Allocate a memory then copy DnsServerList to it
493 //
494 if (Src->DnsServerList != NULL) {
495 Len = Src->DnsServerCount * sizeof (EFI_IPv6_ADDRESS);
496 Dst->DnsServerList = AllocatePool (Len);
497 if (Dst->DnsServerList == NULL) {
498 Dns6CleanConfigure (Dst);
499 return EFI_OUT_OF_RESOURCES;
500 }
501
502 for (Index = 0; Index < Src->DnsServerCount; Index++) {
503 CopyMem (&Dst->DnsServerList[Index], &Src->DnsServerList[Index], sizeof (EFI_IPv6_ADDRESS));
504 }
505 }
506
507 return EFI_SUCCESS;
508}
509
510/**
511 Callback of Dns packet. Does nothing.
512
513 @param Arg The context.
514
515**/
516VOID
517EFIAPI
518DnsDummyExtFree (
519 IN VOID *Arg
520 )
521{
522}
523
524/**
525 Poll the UDP to get the IP4 default address, which may be retrieved
526 by DHCP.
527
528 The default time out value is 5 seconds. If IP has retrieved the default address,
529 the UDP is reconfigured.
530
531 @param Instance The DNS instance
532 @param UdpIo The UDP_IO to poll
533 @param UdpCfgData The UDP configure data to reconfigure the UDP_IO
534
535 @retval TRUE The default address is retrieved and UDP is reconfigured.
536 @retval FALSE Some error occurred.
537
538**/
539BOOLEAN
540Dns4GetMapping (
541 IN DNS_INSTANCE *Instance,
542 IN UDP_IO *UdpIo,
543 IN EFI_UDP4_CONFIG_DATA *UdpCfgData
544 )
545{
546 DNS_SERVICE *Service;
547 EFI_IP4_MODE_DATA Ip4Mode;
548 EFI_UDP4_PROTOCOL *Udp;
549 EFI_STATUS Status;
550
551 ASSERT (Instance->Dns4CfgData.UseDefaultSetting);
552
553 Service = Instance->Service;
554 Udp = UdpIo->Protocol.Udp4;
555
556 Status = gBS->SetTimer (
557 Service->TimerToGetMap,
558 TimerRelative,
559 DNS_TIME_TO_GETMAP * TICKS_PER_SECOND
560 );
561 if (EFI_ERROR (Status)) {
562 return FALSE;
563 }
564
565 while (EFI_ERROR (gBS->CheckEvent (Service->TimerToGetMap))) {
566 Udp->Poll (Udp);
567
568 if (!EFI_ERROR (Udp->GetModeData (Udp, NULL, &Ip4Mode, NULL, NULL)) &&
569 Ip4Mode.IsConfigured)
570 {
571 Udp->Configure (Udp, NULL);
572 return (BOOLEAN)(Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS);
573 }
574 }
575
576 return FALSE;
577}
578
579/**
580 Configure the opened Udp6 instance until the corresponding Ip6 instance
581 has been configured.
582
583 @param Instance The DNS instance
584 @param UdpIo The UDP_IO to poll
585 @param UdpCfgData The UDP configure data to reconfigure the UDP_IO
586
587 @retval TRUE Configure the Udp6 instance successfully.
588 @retval FALSE Some error occurred.
589
590**/
591BOOLEAN
592Dns6GetMapping (
593 IN DNS_INSTANCE *Instance,
594 IN UDP_IO *UdpIo,
595 IN EFI_UDP6_CONFIG_DATA *UdpCfgData
596 )
597{
598 DNS_SERVICE *Service;
599 EFI_IP6_MODE_DATA Ip6Mode;
600 EFI_UDP6_PROTOCOL *Udp;
601 EFI_STATUS Status;
602
603 Service = Instance->Service;
604 Udp = UdpIo->Protocol.Udp6;
605
606 Status = gBS->SetTimer (
607 Service->TimerToGetMap,
608 TimerRelative,
609 DNS_TIME_TO_GETMAP * TICKS_PER_SECOND
610 );
611 if (EFI_ERROR (Status)) {
612 return FALSE;
613 }
614
615 while (EFI_ERROR (gBS->CheckEvent (Service->TimerToGetMap))) {
616 Udp->Poll (Udp);
617
618 if (!EFI_ERROR (Udp->GetModeData (Udp, NULL, &Ip6Mode, NULL, NULL))) {
619 if (Ip6Mode.AddressList != NULL) {
620 FreePool (Ip6Mode.AddressList);
621 }
622
623 if (Ip6Mode.GroupTable != NULL) {
624 FreePool (Ip6Mode.GroupTable);
625 }
626
627 if (Ip6Mode.RouteTable != NULL) {
628 FreePool (Ip6Mode.RouteTable);
629 }
630
631 if (Ip6Mode.NeighborCache != NULL) {
632 FreePool (Ip6Mode.NeighborCache);
633 }
634
635 if (Ip6Mode.PrefixTable != NULL) {
636 FreePool (Ip6Mode.PrefixTable);
637 }
638
639 if (Ip6Mode.IcmpTypeList != NULL) {
640 FreePool (Ip6Mode.IcmpTypeList);
641 }
642
643 if (!Ip6Mode.IsStarted || Ip6Mode.IsConfigured) {
644 Udp->Configure (Udp, NULL);
645 if (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS) {
646 return TRUE;
647 }
648 }
649 }
650 }
651
652 return FALSE;
653}
654
655/**
656 Configure the UDP.
657
658 @param Instance The DNS session
659 @param UdpIo The UDP_IO instance
660
661 @retval EFI_SUCCESS The UDP is successfully configured for the
662 session.
663
664**/
665EFI_STATUS
666Dns4ConfigUdp (
667 IN DNS_INSTANCE *Instance,
668 IN UDP_IO *UdpIo
669 )
670{
671 EFI_DNS4_CONFIG_DATA *Config;
672 EFI_UDP4_CONFIG_DATA UdpConfig;
673 EFI_STATUS Status;
674
675 Config = &Instance->Dns4CfgData;
676
677 UdpConfig.AcceptBroadcast = FALSE;
678 UdpConfig.AcceptPromiscuous = FALSE;
679 UdpConfig.AcceptAnyPort = FALSE;
680 UdpConfig.AllowDuplicatePort = FALSE;
681 UdpConfig.TypeOfService = 0;
682 UdpConfig.TimeToLive = 128;
683 UdpConfig.DoNotFragment = FALSE;
684 UdpConfig.ReceiveTimeout = 0;
685 UdpConfig.TransmitTimeout = 0;
686 UdpConfig.UseDefaultAddress = Config->UseDefaultSetting;
687 UdpConfig.SubnetMask = Config->SubnetMask;
688 UdpConfig.StationPort = Config->LocalPort;
689 UdpConfig.RemotePort = DNS_SERVER_PORT;
690
691 CopyMem (&UdpConfig.StationAddress, &Config->StationIp, sizeof (EFI_IPv4_ADDRESS));
692 CopyMem (&UdpConfig.RemoteAddress, &Instance->SessionDnsServer.v4, sizeof (EFI_IPv4_ADDRESS));
693
694 Status = UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfig);
695
696 if ((Status == EFI_NO_MAPPING) && Dns4GetMapping (Instance, UdpIo, &UdpConfig)) {
697 return EFI_SUCCESS;
698 }
699
700 return Status;
701}
702
703/**
704 Configure the UDP.
705
706 @param Instance The DNS session
707 @param UdpIo The UDP_IO instance
708
709 @retval EFI_SUCCESS The UDP is successfully configured for the
710 session.
711
712**/
713EFI_STATUS
714Dns6ConfigUdp (
715 IN DNS_INSTANCE *Instance,
716 IN UDP_IO *UdpIo
717 )
718{
719 EFI_DNS6_CONFIG_DATA *Config;
720 EFI_UDP6_CONFIG_DATA UdpConfig;
721 EFI_STATUS Status;
722
723 Config = &Instance->Dns6CfgData;
724
725 UdpConfig.AcceptPromiscuous = FALSE;
726 UdpConfig.AcceptAnyPort = FALSE;
727 UdpConfig.AllowDuplicatePort = FALSE;
728 UdpConfig.TrafficClass = 0;
729 UdpConfig.HopLimit = 128;
730 UdpConfig.ReceiveTimeout = 0;
731 UdpConfig.TransmitTimeout = 0;
732 UdpConfig.StationPort = Config->LocalPort;
733 UdpConfig.RemotePort = DNS_SERVER_PORT;
734 CopyMem (&UdpConfig.StationAddress, &Config->StationIp, sizeof (EFI_IPv6_ADDRESS));
735 CopyMem (&UdpConfig.RemoteAddress, &Instance->SessionDnsServer.v6, sizeof (EFI_IPv6_ADDRESS));
736
737 Status = UdpIo->Protocol.Udp6->Configure (UdpIo->Protocol.Udp6, &UdpConfig);
738
739 if ((Status == EFI_NO_MAPPING) && Dns6GetMapping (Instance, UdpIo, &UdpConfig)) {
740 return EFI_SUCCESS;
741 }
742
743 return Status;
744}
745
746/**
747 Update Dns4 cache to shared list of caches of all DNSv4 instances.
748
749 @param Dns4CacheList All Dns4 cache list.
750 @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache.
751 If TRUE, this function will delete matching DNS Cache entry.
752 @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
753 If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
754 @param DnsCacheEntry Entry Pointer to DNS Cache entry.
755
756 @retval EFI_SUCCESS Update Dns4 cache successfully.
757 @retval Others Failed to update Dns4 cache.
758
759**/
760EFI_STATUS
761EFIAPI
762UpdateDns4Cache (
763 IN LIST_ENTRY *Dns4CacheList,
764 IN BOOLEAN DeleteFlag,
765 IN BOOLEAN Override,
766 IN EFI_DNS4_CACHE_ENTRY DnsCacheEntry
767 )
768{
769 DNS4_CACHE *NewDnsCache;
770 DNS4_CACHE *Item;
771 LIST_ENTRY *Entry;
772 LIST_ENTRY *Next;
773
774 NewDnsCache = NULL;
775 Item = NULL;
776
777 //
778 // Search the database for the matching EFI_DNS_CACHE_ENTRY
779 //
780 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns4CacheList) {
781 Item = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
782 if ((StrCmp (DnsCacheEntry.HostName, Item->DnsCache.HostName) == 0) && \
783 (CompareMem (DnsCacheEntry.IpAddress, Item->DnsCache.IpAddress, sizeof (EFI_IPv4_ADDRESS)) == 0))
784 {
785 //
786 // This is the Dns cache entry
787 //
788 if (DeleteFlag) {
789 //
790 // Delete matching DNS Cache entry
791 //
792 RemoveEntryList (&Item->AllCacheLink);
793
794 FreePool (Item->DnsCache.HostName);
795 FreePool (Item->DnsCache.IpAddress);
796 FreePool (Item);
797
798 return EFI_SUCCESS;
799 } else if (Override) {
800 //
801 // Update this one
802 //
803 Item->DnsCache.Timeout = DnsCacheEntry.Timeout;
804
805 return EFI_SUCCESS;
806 } else {
807 return EFI_ACCESS_DENIED;
808 }
809 }
810 }
811
812 //
813 // Add new one
814 //
815 NewDnsCache = AllocatePool (sizeof (DNS4_CACHE));
816 if (NewDnsCache == NULL) {
817 return EFI_OUT_OF_RESOURCES;
818 }
819
820 InitializeListHead (&NewDnsCache->AllCacheLink);
821
822 NewDnsCache->DnsCache.HostName = AllocatePool (StrSize (DnsCacheEntry.HostName));
823 if (NewDnsCache->DnsCache.HostName == NULL) {
824 FreePool (NewDnsCache);
825 return EFI_OUT_OF_RESOURCES;
826 }
827
828 CopyMem (NewDnsCache->DnsCache.HostName, DnsCacheEntry.HostName, StrSize (DnsCacheEntry.HostName));
829
830 NewDnsCache->DnsCache.IpAddress = AllocatePool (sizeof (EFI_IPv4_ADDRESS));
831 if (NewDnsCache->DnsCache.IpAddress == NULL) {
832 FreePool (NewDnsCache->DnsCache.HostName);
833 FreePool (NewDnsCache);
834 return EFI_OUT_OF_RESOURCES;
835 }
836
837 CopyMem (NewDnsCache->DnsCache.IpAddress, DnsCacheEntry.IpAddress, sizeof (EFI_IPv4_ADDRESS));
838
839 NewDnsCache->DnsCache.Timeout = DnsCacheEntry.Timeout;
840
841 InsertTailList (Dns4CacheList, &NewDnsCache->AllCacheLink);
842
843 return EFI_SUCCESS;
844}
845
846/**
847 Update Dns6 cache to shared list of caches of all DNSv6 instances.
848
849 @param Dns6CacheList All Dns6 cache list.
850 @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache.
851 If TRUE, this function will delete matching DNS Cache entry.
852 @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
853 If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
854 @param DnsCacheEntry Entry Pointer to DNS Cache entry.
855
856 @retval EFI_SUCCESS Update Dns6 cache successfully.
857 @retval Others Failed to update Dns6 cache.
858**/
859EFI_STATUS
860EFIAPI
861UpdateDns6Cache (
862 IN LIST_ENTRY *Dns6CacheList,
863 IN BOOLEAN DeleteFlag,
864 IN BOOLEAN Override,
865 IN EFI_DNS6_CACHE_ENTRY DnsCacheEntry
866 )
867{
868 DNS6_CACHE *NewDnsCache;
869 DNS6_CACHE *Item;
870 LIST_ENTRY *Entry;
871 LIST_ENTRY *Next;
872
873 NewDnsCache = NULL;
874 Item = NULL;
875
876 //
877 // Search the database for the matching EFI_DNS_CACHE_ENTRY
878 //
879 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns6CacheList) {
880 Item = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
881 if ((StrCmp (DnsCacheEntry.HostName, Item->DnsCache.HostName) == 0) && \
882 (CompareMem (DnsCacheEntry.IpAddress, Item->DnsCache.IpAddress, sizeof (EFI_IPv6_ADDRESS)) == 0))
883 {
884 //
885 // This is the Dns cache entry
886 //
887 if (DeleteFlag) {
888 //
889 // Delete matching DNS Cache entry
890 //
891 RemoveEntryList (&Item->AllCacheLink);
892
893 FreePool (Item->DnsCache.HostName);
894 FreePool (Item->DnsCache.IpAddress);
895 FreePool (Item);
896
897 return EFI_SUCCESS;
898 } else if (Override) {
899 //
900 // Update this one
901 //
902 Item->DnsCache.Timeout = DnsCacheEntry.Timeout;
903
904 return EFI_SUCCESS;
905 } else {
906 return EFI_ACCESS_DENIED;
907 }
908 }
909 }
910
911 //
912 // Add new one
913 //
914 NewDnsCache = AllocatePool (sizeof (DNS6_CACHE));
915 if (NewDnsCache == NULL) {
916 return EFI_OUT_OF_RESOURCES;
917 }
918
919 InitializeListHead (&NewDnsCache->AllCacheLink);
920
921 NewDnsCache->DnsCache.HostName = AllocatePool (StrSize (DnsCacheEntry.HostName));
922 if (NewDnsCache->DnsCache.HostName == NULL) {
923 FreePool (NewDnsCache);
924 return EFI_OUT_OF_RESOURCES;
925 }
926
927 CopyMem (NewDnsCache->DnsCache.HostName, DnsCacheEntry.HostName, StrSize (DnsCacheEntry.HostName));
928
929 NewDnsCache->DnsCache.IpAddress = AllocatePool (sizeof (EFI_IPv6_ADDRESS));
930 if (NewDnsCache->DnsCache.IpAddress == NULL) {
931 FreePool (NewDnsCache->DnsCache.HostName);
932 FreePool (NewDnsCache);
933 return EFI_OUT_OF_RESOURCES;
934 }
935
936 CopyMem (NewDnsCache->DnsCache.IpAddress, DnsCacheEntry.IpAddress, sizeof (EFI_IPv6_ADDRESS));
937
938 NewDnsCache->DnsCache.Timeout = DnsCacheEntry.Timeout;
939
940 InsertTailList (Dns6CacheList, &NewDnsCache->AllCacheLink);
941
942 return EFI_SUCCESS;
943}
944
945/**
946 Add Dns4 ServerIp to common list of addresses of all configured DNSv4 server.
947
948 @param Dns4ServerList Common list of addresses of all configured DNSv4 server.
949 @param ServerIp DNS server Ip.
950
951 @retval EFI_SUCCESS Add Dns4 ServerIp to common list successfully.
952 @retval Others Failed to add Dns4 ServerIp to common list.
953
954**/
955EFI_STATUS
956EFIAPI
957AddDns4ServerIp (
958 IN LIST_ENTRY *Dns4ServerList,
959 IN EFI_IPv4_ADDRESS ServerIp
960 )
961{
962 DNS4_SERVER_IP *NewServerIp;
963 DNS4_SERVER_IP *Item;
964 LIST_ENTRY *Entry;
965 LIST_ENTRY *Next;
966
967 NewServerIp = NULL;
968 Item = NULL;
969
970 //
971 // Search the database for the matching ServerIp
972 //
973 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns4ServerList) {
974 Item = NET_LIST_USER_STRUCT (Entry, DNS4_SERVER_IP, AllServerLink);
975 if (CompareMem (&Item->Dns4ServerIp, &ServerIp, sizeof (EFI_IPv4_ADDRESS)) == 0) {
976 //
977 // Already done.
978 //
979 return EFI_SUCCESS;
980 }
981 }
982
983 //
984 // Add new one
985 //
986 NewServerIp = AllocatePool (sizeof (DNS4_SERVER_IP));
987 if (NewServerIp == NULL) {
988 return EFI_OUT_OF_RESOURCES;
989 }
990
991 InitializeListHead (&NewServerIp->AllServerLink);
992
993 CopyMem (&NewServerIp->Dns4ServerIp, &ServerIp, sizeof (EFI_IPv4_ADDRESS));
994
995 InsertTailList (Dns4ServerList, &NewServerIp->AllServerLink);
996
997 return EFI_SUCCESS;
998}
999
1000/**
1001 Add Dns6 ServerIp to common list of addresses of all configured DNSv6 server.
1002
1003 @param Dns6ServerList Common list of addresses of all configured DNSv6 server.
1004 @param ServerIp DNS server Ip.
1005
1006 @retval EFI_SUCCESS Add Dns6 ServerIp to common list successfully.
1007 @retval Others Failed to add Dns6 ServerIp to common list.
1008
1009**/
1010EFI_STATUS
1011EFIAPI
1012AddDns6ServerIp (
1013 IN LIST_ENTRY *Dns6ServerList,
1014 IN EFI_IPv6_ADDRESS ServerIp
1015 )
1016{
1017 DNS6_SERVER_IP *NewServerIp;
1018 DNS6_SERVER_IP *Item;
1019 LIST_ENTRY *Entry;
1020 LIST_ENTRY *Next;
1021
1022 NewServerIp = NULL;
1023 Item = NULL;
1024
1025 //
1026 // Search the database for the matching ServerIp
1027 //
1028 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns6ServerList) {
1029 Item = NET_LIST_USER_STRUCT (Entry, DNS6_SERVER_IP, AllServerLink);
1030 if (CompareMem (&Item->Dns6ServerIp, &ServerIp, sizeof (EFI_IPv6_ADDRESS)) == 0) {
1031 //
1032 // Already done.
1033 //
1034 return EFI_SUCCESS;
1035 }
1036 }
1037
1038 //
1039 // Add new one
1040 //
1041 NewServerIp = AllocatePool (sizeof (DNS6_SERVER_IP));
1042 if (NewServerIp == NULL) {
1043 return EFI_OUT_OF_RESOURCES;
1044 }
1045
1046 InitializeListHead (&NewServerIp->AllServerLink);
1047
1048 CopyMem (&NewServerIp->Dns6ServerIp, &ServerIp, sizeof (EFI_IPv6_ADDRESS));
1049
1050 InsertTailList (Dns6ServerList, &NewServerIp->AllServerLink);
1051
1052 return EFI_SUCCESS;
1053}
1054
1055/**
1056 Find out whether the response is valid or invalid.
1057
1058 @param TokensMap All DNS transmittal Tokens entry.
1059 @param Identification Identification for queried packet.
1060 @param Type Type for queried packet.
1061 @param Class Class for queried packet.
1062 @param Item Return corresponding Token entry.
1063
1064 @retval TRUE The response is valid.
1065 @retval FALSE The response is invalid.
1066
1067**/
1068BOOLEAN
1069IsValidDnsResponse (
1070 IN NET_MAP *TokensMap,
1071 IN UINT16 Identification,
1072 IN UINT16 Type,
1073 IN UINT16 Class,
1074 OUT NET_MAP_ITEM **Item
1075 )
1076{
1077 LIST_ENTRY *Entry;
1078
1079 NET_BUF *Packet;
1080 UINT8 *TxString;
1081 DNS_HEADER *DnsHeader;
1082 CHAR8 *QueryName;
1083 DNS_QUERY_SECTION *QuerySection;
1084
1085 NET_LIST_FOR_EACH (Entry, &TokensMap->Used) {
1086 *Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1087 Packet = (NET_BUF *)((*Item)->Value);
1088 if (Packet == NULL) {
1089 continue;
1090 } else {
1091 TxString = NetbufGetByte (Packet, 0, NULL);
1092 ASSERT (TxString != NULL);
1093 DnsHeader = (DNS_HEADER *)TxString;
1094 QueryName = (CHAR8 *)(TxString + sizeof (*DnsHeader));
1095 QuerySection = (DNS_QUERY_SECTION *)(QueryName + AsciiStrLen (QueryName) + 1);
1096
1097 if ((NTOHS (DnsHeader->Identification) == Identification) &&
1098 (NTOHS (QuerySection->Type) == Type) &&
1099 (NTOHS (QuerySection->Class) == Class))
1100 {
1101 return TRUE;
1102 }
1103 }
1104 }
1105
1106 *Item = NULL;
1107
1108 return FALSE;
1109}
1110
1111/**
1112 Parse Dns Response.
1113
1114 @param Instance The DNS instance
1115 @param RxString Received buffer.
1116 @param Length Received buffer length.
1117 @param Completed Flag to indicate that Dns response is valid.
1118
1119 @retval EFI_SUCCESS Parse Dns Response successfully.
1120 @retval Others Failed to parse Dns Response.
1121
1122**/
1123EFI_STATUS
1124ParseDnsResponse (
1125 IN OUT DNS_INSTANCE *Instance,
1126 IN UINT8 *RxString,
1127 IN UINT32 Length,
1128 OUT BOOLEAN *Completed
1129 )
1130{
1131 DNS_HEADER *DnsHeader;
1132
1133 CHAR8 *QueryName;
1134 UINT32 QueryNameLen;
1135 DNS_QUERY_SECTION *QuerySection;
1136
1137 CHAR8 *AnswerName;
1138 DNS_ANSWER_SECTION *AnswerSection;
1139 UINT8 *AnswerData;
1140
1141 NET_MAP_ITEM *Item;
1142 DNS4_TOKEN_ENTRY *Dns4TokenEntry;
1143 DNS6_TOKEN_ENTRY *Dns6TokenEntry;
1144
1145 UINT32 IpCount;
1146 UINT32 RRCount;
1147 UINT32 AnswerSectionNum;
1148 UINT32 CNameTtl;
1149
1150 EFI_IPv4_ADDRESS *HostAddr4;
1151 EFI_IPv6_ADDRESS *HostAddr6;
1152
1153 EFI_DNS4_CACHE_ENTRY *Dns4CacheEntry;
1154 EFI_DNS6_CACHE_ENTRY *Dns6CacheEntry;
1155
1156 DNS_RESOURCE_RECORD *Dns4RR;
1157 DNS6_RESOURCE_RECORD *Dns6RR;
1158
1159 EFI_STATUS Status;
1160 UINT32 RemainingLength;
1161
1162 EFI_TPL OldTpl;
1163
1164 Item = NULL;
1165 Dns4TokenEntry = NULL;
1166 Dns6TokenEntry = NULL;
1167
1168 IpCount = 0;
1169 RRCount = 0;
1170 AnswerSectionNum = 0;
1171 CNameTtl = 0;
1172
1173 HostAddr4 = NULL;
1174 HostAddr6 = NULL;
1175
1176 Dns4CacheEntry = NULL;
1177 Dns6CacheEntry = NULL;
1178
1179 Dns4RR = NULL;
1180 Dns6RR = NULL;
1181
1182 *Completed = TRUE;
1183 Status = EFI_SUCCESS;
1184 RemainingLength = Length;
1185
1186 //
1187 // Check whether the remaining packet length is available or not.
1188 //
1189 if (RemainingLength <= sizeof (DNS_HEADER)) {
1190 *Completed = FALSE;
1191 return EFI_ABORTED;
1192 } else {
1193 RemainingLength -= sizeof (DNS_HEADER);
1194 }
1195
1196 //
1197 // Get header
1198 //
1199 DnsHeader = (DNS_HEADER *)RxString;
1200
1201 DnsHeader->Identification = NTOHS (DnsHeader->Identification);
1202 DnsHeader->Flags.Uint16 = NTOHS (DnsHeader->Flags.Uint16);
1203 DnsHeader->QuestionsNum = NTOHS (DnsHeader->QuestionsNum);
1204 DnsHeader->AnswersNum = NTOHS (DnsHeader->AnswersNum);
1205 DnsHeader->AuthorityNum = NTOHS (DnsHeader->AuthorityNum);
1206 DnsHeader->AditionalNum = NTOHS (DnsHeader->AditionalNum);
1207
1208 //
1209 // There is always one QuestionsNum in DNS message. The capability to handle more
1210 // than one requires to redesign the message format. Currently, it's not supported.
1211 //
1212 if (DnsHeader->QuestionsNum > 1) {
1213 *Completed = FALSE;
1214 return EFI_UNSUPPORTED;
1215 }
1216
1217 //
1218 // Get Query name
1219 //
1220 QueryName = (CHAR8 *)(RxString + sizeof (*DnsHeader));
1221
1222 QueryNameLen = (UINT32)AsciiStrLen (QueryName) + 1;
1223
1224 //
1225 // Check whether the remaining packet length is available or not.
1226 //
1227 if (RemainingLength <= QueryNameLen + sizeof (DNS_QUERY_SECTION)) {
1228 *Completed = FALSE;
1229 return EFI_ABORTED;
1230 } else {
1231 RemainingLength -= (QueryNameLen + sizeof (DNS_QUERY_SECTION));
1232 }
1233
1234 //
1235 // Get query section
1236 //
1237 QuerySection = (DNS_QUERY_SECTION *)(QueryName + QueryNameLen);
1238 QuerySection->Type = NTOHS (QuerySection->Type);
1239 QuerySection->Class = NTOHS (QuerySection->Class);
1240
1241 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1242
1243 //
1244 // Check DnsResponse Validity, if so, also get a valid NET_MAP_ITEM.
1245 //
1246 if (Instance->Service->IpVersion == IP_VERSION_4) {
1247 if (!IsValidDnsResponse (
1248 &Instance->Dns4TxTokens,
1249 DnsHeader->Identification,
1250 QuerySection->Type,
1251 QuerySection->Class,
1252 &Item
1253 ))
1254 {
1255 *Completed = FALSE;
1256 Status = EFI_ABORTED;
1257 goto ON_EXIT;
1258 }
1259
1260 ASSERT (Item != NULL);
1261 Dns4TokenEntry = (DNS4_TOKEN_ENTRY *)(Item->Key);
1262 } else {
1263 if (!IsValidDnsResponse (
1264 &Instance->Dns6TxTokens,
1265 DnsHeader->Identification,
1266 QuerySection->Type,
1267 QuerySection->Class,
1268 &Item
1269 ))
1270 {
1271 *Completed = FALSE;
1272 Status = EFI_ABORTED;
1273 goto ON_EXIT;
1274 }
1275
1276 ASSERT (Item != NULL);
1277 Dns6TokenEntry = (DNS6_TOKEN_ENTRY *)(Item->Key);
1278 }
1279
1280 //
1281 // Continue Check Some Errors.
1282 //
1283 if ((DnsHeader->Flags.Bits.RCode != DNS_FLAGS_RCODE_NO_ERROR) || (DnsHeader->AnswersNum < 1) || \
1284 (DnsHeader->Flags.Bits.QR != DNS_FLAGS_QR_RESPONSE))
1285 {
1286 //
1287 // The domain name referenced in the query does not exist.
1288 //
1289 if (DnsHeader->Flags.Bits.RCode == DNS_FLAGS_RCODE_NAME_ERROR) {
1290 Status = EFI_NOT_FOUND;
1291 } else {
1292 Status = EFI_DEVICE_ERROR;
1293 }
1294
1295 goto ON_COMPLETE;
1296 }
1297
1298 //
1299 // Do some buffer allocations.
1300 //
1301 if (Instance->Service->IpVersion == IP_VERSION_4) {
1302 ASSERT (Dns4TokenEntry != NULL);
1303
1304 if (Dns4TokenEntry->GeneralLookUp) {
1305 //
1306 // It's the GeneralLookUp querying.
1307 //
1308 Dns4TokenEntry->Token->RspData.GLookupData = AllocateZeroPool (sizeof (DNS_RESOURCE_RECORD));
1309 if (Dns4TokenEntry->Token->RspData.GLookupData == NULL) {
1310 Status = EFI_OUT_OF_RESOURCES;
1311 goto ON_EXIT;
1312 }
1313
1314 Dns4TokenEntry->Token->RspData.GLookupData->RRList = AllocateZeroPool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD));
1315 if (Dns4TokenEntry->Token->RspData.GLookupData->RRList == NULL) {
1316 Status = EFI_OUT_OF_RESOURCES;
1317 goto ON_EXIT;
1318 }
1319 } else {
1320 //
1321 // It's not the GeneralLookUp querying. Check the Query type.
1322 //
1323 if (QuerySection->Type == DNS_TYPE_A) {
1324 Dns4TokenEntry->Token->RspData.H2AData = AllocateZeroPool (sizeof (DNS_HOST_TO_ADDR_DATA));
1325 if (Dns4TokenEntry->Token->RspData.H2AData == NULL) {
1326 Status = EFI_OUT_OF_RESOURCES;
1327 goto ON_EXIT;
1328 }
1329
1330 Dns4TokenEntry->Token->RspData.H2AData->IpList = AllocateZeroPool (DnsHeader->AnswersNum * sizeof (EFI_IPv4_ADDRESS));
1331 if (Dns4TokenEntry->Token->RspData.H2AData->IpList == NULL) {
1332 Status = EFI_OUT_OF_RESOURCES;
1333 goto ON_EXIT;
1334 }
1335 } else {
1336 Status = EFI_UNSUPPORTED;
1337 goto ON_EXIT;
1338 }
1339 }
1340 } else {
1341 ASSERT (Dns6TokenEntry != NULL);
1342
1343 if (Dns6TokenEntry->GeneralLookUp) {
1344 //
1345 // It's the GeneralLookUp querying.
1346 //
1347 Dns6TokenEntry->Token->RspData.GLookupData = AllocateZeroPool (sizeof (DNS_RESOURCE_RECORD));
1348 if (Dns6TokenEntry->Token->RspData.GLookupData == NULL) {
1349 Status = EFI_OUT_OF_RESOURCES;
1350 goto ON_EXIT;
1351 }
1352
1353 Dns6TokenEntry->Token->RspData.GLookupData->RRList = AllocateZeroPool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD));
1354 if (Dns6TokenEntry->Token->RspData.GLookupData->RRList == NULL) {
1355 Status = EFI_OUT_OF_RESOURCES;
1356 goto ON_EXIT;
1357 }
1358 } else {
1359 //
1360 // It's not the GeneralLookUp querying. Check the Query type.
1361 //
1362 if (QuerySection->Type == DNS_TYPE_AAAA) {
1363 Dns6TokenEntry->Token->RspData.H2AData = AllocateZeroPool (sizeof (DNS6_HOST_TO_ADDR_DATA));
1364 if (Dns6TokenEntry->Token->RspData.H2AData == NULL) {
1365 Status = EFI_OUT_OF_RESOURCES;
1366 goto ON_EXIT;
1367 }
1368
1369 Dns6TokenEntry->Token->RspData.H2AData->IpList = AllocateZeroPool (DnsHeader->AnswersNum * sizeof (EFI_IPv6_ADDRESS));
1370 if (Dns6TokenEntry->Token->RspData.H2AData->IpList == NULL) {
1371 Status = EFI_OUT_OF_RESOURCES;
1372 goto ON_EXIT;
1373 }
1374 } else {
1375 Status = EFI_UNSUPPORTED;
1376 goto ON_EXIT;
1377 }
1378 }
1379 }
1380
1381 Status = EFI_NOT_FOUND;
1382
1383 //
1384 // Get Answer name
1385 //
1386 AnswerName = (CHAR8 *)QuerySection + sizeof (*QuerySection);
1387
1388 //
1389 // Processing AnswerSection.
1390 //
1391 while (AnswerSectionNum < DnsHeader->AnswersNum) {
1392 //
1393 // Check whether the remaining packet length is available or not.
1394 //
1395 if (RemainingLength <= sizeof (UINT16) + sizeof (DNS_ANSWER_SECTION)) {
1396 *Completed = FALSE;
1397 Status = EFI_ABORTED;
1398 goto ON_EXIT;
1399 } else {
1400 RemainingLength -= (sizeof (UINT16) + sizeof (DNS_ANSWER_SECTION));
1401 }
1402
1403 //
1404 // Answer name should be PTR, else EFI_UNSUPPORTED returned.
1405 //
1406 if ((*(UINT8 *)AnswerName & 0xC0) != 0xC0) {
1407 Status = EFI_UNSUPPORTED;
1408 goto ON_EXIT;
1409 }
1410
1411 //
1412 // Get Answer section.
1413 //
1414 AnswerSection = (DNS_ANSWER_SECTION *)(AnswerName + sizeof (UINT16));
1415 AnswerSection->Type = NTOHS (AnswerSection->Type);
1416 AnswerSection->Class = NTOHS (AnswerSection->Class);
1417 AnswerSection->Ttl = NTOHL (AnswerSection->Ttl);
1418 AnswerSection->DataLength = NTOHS (AnswerSection->DataLength);
1419
1420 //
1421 // Check whether the remaining packet length is available or not.
1422 //
1423 if (RemainingLength < AnswerSection->DataLength) {
1424 *Completed = FALSE;
1425 Status = EFI_ABORTED;
1426 goto ON_EXIT;
1427 } else {
1428 RemainingLength -= AnswerSection->DataLength;
1429 }
1430
1431 //
1432 // Check whether it's the GeneralLookUp querying.
1433 //
1434 if ((Instance->Service->IpVersion == IP_VERSION_4) && Dns4TokenEntry->GeneralLookUp) {
1435 Dns4RR = Dns4TokenEntry->Token->RspData.GLookupData->RRList;
1436 AnswerData = (UINT8 *)AnswerSection + sizeof (*AnswerSection);
1437
1438 //
1439 // Fill the ResourceRecord.
1440 //
1441 Dns4RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1);
1442 if (Dns4RR[RRCount].QName == NULL) {
1443 Status = EFI_OUT_OF_RESOURCES;
1444 goto ON_EXIT;
1445 }
1446
1447 CopyMem (Dns4RR[RRCount].QName, QueryName, AsciiStrLen (QueryName));
1448 Dns4RR[RRCount].QType = AnswerSection->Type;
1449 Dns4RR[RRCount].QClass = AnswerSection->Class;
1450 Dns4RR[RRCount].TTL = AnswerSection->Ttl;
1451 Dns4RR[RRCount].DataLength = AnswerSection->DataLength;
1452 Dns4RR[RRCount].RData = AllocateZeroPool (Dns4RR[RRCount].DataLength);
1453 if (Dns4RR[RRCount].RData == NULL) {
1454 Status = EFI_OUT_OF_RESOURCES;
1455 goto ON_EXIT;
1456 }
1457
1458 CopyMem (Dns4RR[RRCount].RData, AnswerData, Dns4RR[RRCount].DataLength);
1459
1460 RRCount++;
1461 Status = EFI_SUCCESS;
1462 } else if ((Instance->Service->IpVersion == IP_VERSION_6) && Dns6TokenEntry->GeneralLookUp) {
1463 Dns6RR = Dns6TokenEntry->Token->RspData.GLookupData->RRList;
1464 AnswerData = (UINT8 *)AnswerSection + sizeof (*AnswerSection);
1465
1466 //
1467 // Fill the ResourceRecord.
1468 //
1469 Dns6RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1);
1470 if (Dns6RR[RRCount].QName == NULL) {
1471 Status = EFI_OUT_OF_RESOURCES;
1472 goto ON_EXIT;
1473 }
1474
1475 CopyMem (Dns6RR[RRCount].QName, QueryName, AsciiStrLen (QueryName));
1476 Dns6RR[RRCount].QType = AnswerSection->Type;
1477 Dns6RR[RRCount].QClass = AnswerSection->Class;
1478 Dns6RR[RRCount].TTL = AnswerSection->Ttl;
1479 Dns6RR[RRCount].DataLength = AnswerSection->DataLength;
1480 Dns6RR[RRCount].RData = AllocateZeroPool (Dns6RR[RRCount].DataLength);
1481 if (Dns6RR[RRCount].RData == NULL) {
1482 Status = EFI_OUT_OF_RESOURCES;
1483 goto ON_EXIT;
1484 }
1485
1486 CopyMem (Dns6RR[RRCount].RData, AnswerData, Dns6RR[RRCount].DataLength);
1487
1488 RRCount++;
1489 Status = EFI_SUCCESS;
1490 } else {
1491 //
1492 // It's not the GeneralLookUp querying.
1493 // Check the Query type, parse the response packet.
1494 //
1495 switch (AnswerSection->Type) {
1496 case DNS_TYPE_A:
1497 //
1498 // This is address entry, get Data.
1499 //
1500 ASSERT (Dns4TokenEntry != NULL);
1501
1502 if (AnswerSection->DataLength != 4) {
1503 Status = EFI_ABORTED;
1504 goto ON_EXIT;
1505 }
1506
1507 HostAddr4 = Dns4TokenEntry->Token->RspData.H2AData->IpList;
1508 AnswerData = (UINT8 *)AnswerSection + sizeof (*AnswerSection);
1509 CopyMem (&HostAddr4[IpCount], AnswerData, sizeof (EFI_IPv4_ADDRESS));
1510
1511 //
1512 // Allocate new CacheEntry pool to update DNS cache dynamically.
1513 //
1514 Dns4CacheEntry = AllocateZeroPool (sizeof (EFI_DNS4_CACHE_ENTRY));
1515 if (Dns4CacheEntry == NULL) {
1516 Status = EFI_OUT_OF_RESOURCES;
1517 goto ON_EXIT;
1518 }
1519
1520 Dns4CacheEntry->HostName = AllocateZeroPool (2 * (StrLen (Dns4TokenEntry->QueryHostName) + 1));
1521 if (Dns4CacheEntry->HostName == NULL) {
1522 Status = EFI_OUT_OF_RESOURCES;
1523 goto ON_EXIT;
1524 }
1525
1526 CopyMem (Dns4CacheEntry->HostName, Dns4TokenEntry->QueryHostName, 2 * (StrLen (Dns4TokenEntry->QueryHostName) + 1));
1527 Dns4CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv4_ADDRESS));
1528 if (Dns4CacheEntry->IpAddress == NULL) {
1529 Status = EFI_OUT_OF_RESOURCES;
1530 goto ON_EXIT;
1531 }
1532
1533 CopyMem (Dns4CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv4_ADDRESS));
1534
1535 if ((CNameTtl != 0) && (AnswerSection->Ttl != 0)) {
1536 Dns4CacheEntry->Timeout = MIN (CNameTtl, AnswerSection->Ttl);
1537 } else {
1538 Dns4CacheEntry->Timeout = MAX (CNameTtl, AnswerSection->Ttl);
1539 }
1540
1541 UpdateDns4Cache (&mDriverData->Dns4CacheList, FALSE, TRUE, *Dns4CacheEntry);
1542
1543 //
1544 // Free allocated CacheEntry pool.
1545 //
1546 FreePool (Dns4CacheEntry->HostName);
1547 Dns4CacheEntry->HostName = NULL;
1548
1549 FreePool (Dns4CacheEntry->IpAddress);
1550 Dns4CacheEntry->IpAddress = NULL;
1551
1552 FreePool (Dns4CacheEntry);
1553 Dns4CacheEntry = NULL;
1554
1555 IpCount++;
1556 Status = EFI_SUCCESS;
1557 break;
1558 case DNS_TYPE_AAAA:
1559 //
1560 // This is address entry, get Data.
1561 //
1562 ASSERT (Dns6TokenEntry != NULL);
1563
1564 if (AnswerSection->DataLength != 16) {
1565 Status = EFI_ABORTED;
1566 goto ON_EXIT;
1567 }
1568
1569 HostAddr6 = Dns6TokenEntry->Token->RspData.H2AData->IpList;
1570 AnswerData = (UINT8 *)AnswerSection + sizeof (*AnswerSection);
1571 CopyMem (&HostAddr6[IpCount], AnswerData, sizeof (EFI_IPv6_ADDRESS));
1572
1573 //
1574 // Allocate new CacheEntry pool to update DNS cache dynamically.
1575 //
1576 Dns6CacheEntry = AllocateZeroPool (sizeof (EFI_DNS6_CACHE_ENTRY));
1577 if (Dns6CacheEntry == NULL) {
1578 Status = EFI_OUT_OF_RESOURCES;
1579 goto ON_EXIT;
1580 }
1581
1582 Dns6CacheEntry->HostName = AllocateZeroPool (2 * (StrLen (Dns6TokenEntry->QueryHostName) + 1));
1583 if (Dns6CacheEntry->HostName == NULL) {
1584 Status = EFI_OUT_OF_RESOURCES;
1585 goto ON_EXIT;
1586 }
1587
1588 CopyMem (Dns6CacheEntry->HostName, Dns6TokenEntry->QueryHostName, 2 * (StrLen (Dns6TokenEntry->QueryHostName) + 1));
1589 Dns6CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS));
1590 if (Dns6CacheEntry->IpAddress == NULL) {
1591 Status = EFI_OUT_OF_RESOURCES;
1592 goto ON_EXIT;
1593 }
1594
1595 CopyMem (Dns6CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv6_ADDRESS));
1596
1597 if ((CNameTtl != 0) && (AnswerSection->Ttl != 0)) {
1598 Dns6CacheEntry->Timeout = MIN (CNameTtl, AnswerSection->Ttl);
1599 } else {
1600 Dns6CacheEntry->Timeout = MAX (CNameTtl, AnswerSection->Ttl);
1601 }
1602
1603 UpdateDns6Cache (&mDriverData->Dns6CacheList, FALSE, TRUE, *Dns6CacheEntry);
1604
1605 //
1606 // Free allocated CacheEntry pool.
1607 //
1608 FreePool (Dns6CacheEntry->HostName);
1609 Dns6CacheEntry->HostName = NULL;
1610
1611 FreePool (Dns6CacheEntry->IpAddress);
1612 Dns6CacheEntry->IpAddress = NULL;
1613
1614 FreePool (Dns6CacheEntry);
1615 Dns6CacheEntry = NULL;
1616
1617 IpCount++;
1618 Status = EFI_SUCCESS;
1619 break;
1620 case DNS_TYPE_CNAME:
1621 //
1622 // According RFC 1034 - 3.6.2, if the query name is an alias, the name server will include the CNAME
1623 // record in the response and restart the query at the domain name specified in the data field of the
1624 // CNAME record. So, just record the TTL value of the CNAME, then skip to parse the next record.
1625 //
1626 CNameTtl = AnswerSection->Ttl;
1627 break;
1628 default:
1629 Status = EFI_UNSUPPORTED;
1630 goto ON_EXIT;
1631 }
1632 }
1633
1634 //
1635 // Find next one
1636 //
1637 AnswerName = (CHAR8 *)AnswerSection + sizeof (*AnswerSection) + AnswerSection->DataLength;
1638 AnswerSectionNum++;
1639 }
1640
1641 if (Instance->Service->IpVersion == IP_VERSION_4) {
1642 ASSERT (Dns4TokenEntry != NULL);
1643
1644 if (Dns4TokenEntry->GeneralLookUp) {
1645 Dns4TokenEntry->Token->RspData.GLookupData->RRCount = RRCount;
1646 } else {
1647 if (QuerySection->Type == DNS_TYPE_A) {
1648 Dns4TokenEntry->Token->RspData.H2AData->IpCount = IpCount;
1649 } else {
1650 Status = EFI_UNSUPPORTED;
1651 goto ON_EXIT;
1652 }
1653 }
1654 } else {
1655 ASSERT (Dns6TokenEntry != NULL);
1656
1657 if (Dns6TokenEntry->GeneralLookUp) {
1658 Dns6TokenEntry->Token->RspData.GLookupData->RRCount = RRCount;
1659 } else {
1660 if (QuerySection->Type == DNS_TYPE_AAAA) {
1661 Dns6TokenEntry->Token->RspData.H2AData->IpCount = IpCount;
1662 } else {
1663 Status = EFI_UNSUPPORTED;
1664 goto ON_EXIT;
1665 }
1666 }
1667 }
1668
1669ON_COMPLETE:
1670 //
1671 // Parsing is complete, free the sending packet and signal Event here.
1672 //
1673 if ((Item != NULL) && (Item->Value != NULL)) {
1674 NetbufFree ((NET_BUF *)(Item->Value));
1675 }
1676
1677 if (Instance->Service->IpVersion == IP_VERSION_4) {
1678 ASSERT (Dns4TokenEntry != NULL);
1679 Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry);
1680 Dns4TokenEntry->Token->Status = Status;
1681 if (Dns4TokenEntry->Token->Event != NULL) {
1682 gBS->SignalEvent (Dns4TokenEntry->Token->Event);
1683 DispatchDpc ();
1684 }
1685 } else {
1686 ASSERT (Dns6TokenEntry != NULL);
1687 Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry);
1688 Dns6TokenEntry->Token->Status = Status;
1689 if (Dns6TokenEntry->Token->Event != NULL) {
1690 gBS->SignalEvent (Dns6TokenEntry->Token->Event);
1691 DispatchDpc ();
1692 }
1693 }
1694
1695ON_EXIT:
1696 //
1697 // Free the allocated buffer if error happen.
1698 //
1699 if (EFI_ERROR (Status)) {
1700 if (Dns4TokenEntry != NULL) {
1701 if (Dns4TokenEntry->GeneralLookUp) {
1702 if (Dns4TokenEntry->Token->RspData.GLookupData != NULL) {
1703 if (Dns4TokenEntry->Token->RspData.GLookupData->RRList != NULL) {
1704 while (RRCount != 0) {
1705 RRCount--;
1706 if (Dns4TokenEntry->Token->RspData.GLookupData->RRList[RRCount].QName != NULL) {
1707 FreePool (Dns4TokenEntry->Token->RspData.GLookupData->RRList[RRCount].QName);
1708 }
1709
1710 if (Dns4TokenEntry->Token->RspData.GLookupData->RRList[RRCount].RData != NULL) {
1711 FreePool (Dns4TokenEntry->Token->RspData.GLookupData->RRList[RRCount].RData);
1712 }
1713 }
1714
1715 FreePool (Dns4TokenEntry->Token->RspData.GLookupData->RRList);
1716 }
1717
1718 FreePool (Dns4TokenEntry->Token->RspData.GLookupData);
1719 }
1720 } else {
1721 if ((QuerySection->Type == DNS_TYPE_A) && (Dns4TokenEntry->Token->RspData.H2AData != NULL)) {
1722 if (Dns4TokenEntry->Token->RspData.H2AData->IpList != NULL) {
1723 FreePool (Dns4TokenEntry->Token->RspData.H2AData->IpList);
1724 }
1725
1726 FreePool (Dns4TokenEntry->Token->RspData.H2AData);
1727 Dns4TokenEntry->Token->RspData.H2AData = NULL;
1728 }
1729 }
1730 }
1731
1732 if (Dns6TokenEntry != NULL) {
1733 if (Dns6TokenEntry->GeneralLookUp) {
1734 if (Dns6TokenEntry->Token->RspData.GLookupData != NULL) {
1735 if (Dns6TokenEntry->Token->RspData.GLookupData->RRList != NULL) {
1736 while (RRCount != 0) {
1737 RRCount--;
1738 if (Dns6TokenEntry->Token->RspData.GLookupData->RRList[RRCount].QName != NULL) {
1739 FreePool (Dns6TokenEntry->Token->RspData.GLookupData->RRList[RRCount].QName);
1740 }
1741
1742 if (Dns6TokenEntry->Token->RspData.GLookupData->RRList[RRCount].RData != NULL) {
1743 FreePool (Dns6TokenEntry->Token->RspData.GLookupData->RRList[RRCount].RData);
1744 }
1745 }
1746
1747 FreePool (Dns6TokenEntry->Token->RspData.GLookupData->RRList);
1748 }
1749
1750 FreePool (Dns6TokenEntry->Token->RspData.GLookupData);
1751 }
1752 } else {
1753 if ((QuerySection->Type == DNS_TYPE_AAAA) && (Dns6TokenEntry->Token->RspData.H2AData != NULL)) {
1754 if (Dns6TokenEntry->Token->RspData.H2AData->IpList != NULL) {
1755 FreePool (Dns6TokenEntry->Token->RspData.H2AData->IpList);
1756 }
1757
1758 FreePool (Dns6TokenEntry->Token->RspData.H2AData);
1759 Dns6TokenEntry->Token->RspData.H2AData = NULL;
1760 }
1761 }
1762 }
1763
1764 if (Dns4CacheEntry != NULL) {
1765 if (Dns4CacheEntry->HostName != NULL) {
1766 FreePool (Dns4CacheEntry->HostName);
1767 }
1768
1769 if (Dns4CacheEntry->IpAddress != NULL) {
1770 FreePool (Dns4CacheEntry->IpAddress);
1771 }
1772
1773 FreePool (Dns4CacheEntry);
1774 }
1775
1776 if (Dns6CacheEntry != NULL) {
1777 if (Dns6CacheEntry->HostName != NULL) {
1778 FreePool (Dns6CacheEntry->HostName);
1779 }
1780
1781 if (Dns6CacheEntry->IpAddress != NULL) {
1782 FreePool (Dns6CacheEntry->IpAddress);
1783 }
1784
1785 FreePool (Dns6CacheEntry);
1786 }
1787 }
1788
1789 gBS->RestoreTPL (OldTpl);
1790 return Status;
1791}
1792
1793/**
1794 Parse response packet.
1795
1796 @param Packet The packets received.
1797 @param EndPoint The local/remote UDP access point
1798 @param IoStatus The status of the UDP receive
1799 @param Context The opaque parameter to the function.
1800
1801**/
1802VOID
1803EFIAPI
1804DnsOnPacketReceived (
1805 NET_BUF *Packet,
1806 UDP_END_POINT *EndPoint,
1807 EFI_STATUS IoStatus,
1808 VOID *Context
1809 )
1810{
1811 DNS_INSTANCE *Instance;
1812
1813 UINT8 *RcvString;
1814 UINT32 Len;
1815
1816 BOOLEAN Completed;
1817
1818 Instance = (DNS_INSTANCE *)Context;
1819 NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE);
1820
1821 RcvString = NULL;
1822 Completed = FALSE;
1823
1824 if (EFI_ERROR (IoStatus)) {
1825 goto ON_EXIT;
1826 }
1827
1828 ASSERT (Packet != NULL);
1829
1830 Len = Packet->TotalSize;
1831
1832 RcvString = NetbufGetByte (Packet, 0, NULL);
1833 ASSERT (RcvString != NULL);
1834
1835 //
1836 // Parse Dns Response
1837 //
1838 ParseDnsResponse (Instance, RcvString, Len, &Completed);
1839
1840ON_EXIT:
1841
1842 if (Packet != NULL) {
1843 NetbufFree (Packet);
1844 }
1845
1846 if (!Completed) {
1847 UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);
1848 }
1849}
1850
1851/**
1852 Release the net buffer when packet is sent.
1853
1854 @param Packet The packets received.
1855 @param EndPoint The local/remote UDP access point
1856 @param IoStatus The status of the UDP receive
1857 @param Context The opaque parameter to the function.
1858
1859**/
1860VOID
1861EFIAPI
1862DnsOnPacketSent (
1863 NET_BUF *Packet,
1864 UDP_END_POINT *EndPoint,
1865 EFI_STATUS IoStatus,
1866 VOID *Context
1867 )
1868{
1869 DNS_INSTANCE *Instance;
1870 LIST_ENTRY *Entry;
1871 NET_MAP_ITEM *Item;
1872 DNS4_TOKEN_ENTRY *Dns4TokenEntry;
1873 DNS6_TOKEN_ENTRY *Dns6TokenEntry;
1874
1875 Dns4TokenEntry = NULL;
1876 Dns6TokenEntry = NULL;
1877
1878 Instance = (DNS_INSTANCE *)Context;
1879 NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE);
1880
1881 if (Instance->Service->IpVersion == IP_VERSION_4) {
1882 NET_LIST_FOR_EACH (Entry, &Instance->Dns4TxTokens.Used) {
1883 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1884 if (Packet == (NET_BUF *)(Item->Value)) {
1885 Dns4TokenEntry = ((DNS4_TOKEN_ENTRY *)Item->Key);
1886 Dns4TokenEntry->PacketToLive = Dns4TokenEntry->Token->RetryInterval;
1887 break;
1888 }
1889 }
1890 } else {
1891 NET_LIST_FOR_EACH (Entry, &Instance->Dns6TxTokens.Used) {
1892 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1893 if (Packet == (NET_BUF *)(Item->Value)) {
1894 Dns6TokenEntry = ((DNS6_TOKEN_ENTRY *)Item->Key);
1895 Dns6TokenEntry->PacketToLive = Dns6TokenEntry->Token->RetryInterval;
1896 break;
1897 }
1898 }
1899 }
1900
1901 NetbufFree (Packet);
1902}
1903
1904/**
1905 Query request information.
1906
1907 @param Instance The DNS instance
1908 @param Packet The packet for querying request information.
1909
1910 @retval EFI_SUCCESS Query request information successfully.
1911 @retval Others Failed to query request information.
1912
1913**/
1914EFI_STATUS
1915DoDnsQuery (
1916 IN DNS_INSTANCE *Instance,
1917 IN NET_BUF *Packet
1918 )
1919{
1920 EFI_STATUS Status;
1921
1922 //
1923 // Ready to receive the DNS response.
1924 //
1925 if (Instance->UdpIo->RecvRequest == NULL) {
1926 Status = UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);
1927 if (EFI_ERROR (Status)) {
1928 return Status;
1929 }
1930 }
1931
1932 //
1933 // Transmit the DNS packet.
1934 //
1935 NET_GET_REF (Packet);
1936
1937 Status = UdpIoSendDatagram (Instance->UdpIo, Packet, NULL, NULL, DnsOnPacketSent, Instance);
1938
1939 return Status;
1940}
1941
1942/**
1943 Construct the Packet according query section.
1944
1945 @param Instance The DNS instance
1946 @param QueryName Queried Name
1947 @param Type Queried Type
1948 @param Class Queried Class
1949 @param Packet The packet for query
1950
1951 @retval EFI_SUCCESS The packet is constructed.
1952 @retval Others Failed to construct the Packet.
1953
1954**/
1955EFI_STATUS
1956ConstructDNSQuery (
1957 IN DNS_INSTANCE *Instance,
1958 IN CHAR8 *QueryName,
1959 IN UINT16 Type,
1960 IN UINT16 Class,
1961 OUT NET_BUF **Packet
1962 )
1963{
1964 NET_FRAGMENT Frag;
1965 DNS_HEADER *DnsHeader;
1966 DNS_QUERY_SECTION *DnsQuery;
1967 EFI_STATUS Status;
1968 UINT32 Random;
1969
1970 Status = PseudoRandomU32 (&Random);
1971 if (EFI_ERROR (Status)) {
1972 DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
1973 return Status;
1974 }
1975
1976 //
1977 // Messages carried by UDP are restricted to 512 bytes (not counting the IP
1978 // or UDP headers).
1979 //
1980 Frag.Bulk = AllocatePool (DNS_MAX_MESSAGE_SIZE * sizeof (UINT8));
1981 if (Frag.Bulk == NULL) {
1982 return EFI_OUT_OF_RESOURCES;
1983 }
1984
1985 //
1986 // Fill header
1987 //
1988 DnsHeader = (DNS_HEADER *)Frag.Bulk;
1989 DnsHeader->Identification = (UINT16)Random;
1990 DnsHeader->Flags.Uint16 = 0x0000;
1991 DnsHeader->Flags.Bits.RD = 1;
1992 DnsHeader->Flags.Bits.OpCode = DNS_FLAGS_OPCODE_STANDARD;
1993 DnsHeader->Flags.Bits.QR = DNS_FLAGS_QR_QUERY;
1994 DnsHeader->QuestionsNum = 1;
1995 DnsHeader->AnswersNum = 0;
1996 DnsHeader->AuthorityNum = 0;
1997 DnsHeader->AditionalNum = 0;
1998
1999 DnsHeader->Identification = HTONS (DnsHeader->Identification);
2000 DnsHeader->Flags.Uint16 = HTONS (DnsHeader->Flags.Uint16);
2001 DnsHeader->QuestionsNum = HTONS (DnsHeader->QuestionsNum);
2002 DnsHeader->AnswersNum = HTONS (DnsHeader->AnswersNum);
2003 DnsHeader->AuthorityNum = HTONS (DnsHeader->AuthorityNum);
2004 DnsHeader->AditionalNum = HTONS (DnsHeader->AditionalNum);
2005
2006 Frag.Len = sizeof (*DnsHeader);
2007
2008 //
2009 // Fill Query name
2010 //
2011 CopyMem (Frag.Bulk + Frag.Len, QueryName, AsciiStrLen (QueryName));
2012 Frag.Len = (UINT32)(Frag.Len + AsciiStrLen (QueryName));
2013 *(Frag.Bulk + Frag.Len) = 0;
2014 Frag.Len++;
2015
2016 //
2017 // Rest query section
2018 //
2019 DnsQuery = (DNS_QUERY_SECTION *)(Frag.Bulk + Frag.Len);
2020
2021 DnsQuery->Type = HTONS (Type);
2022 DnsQuery->Class = HTONS (Class);
2023
2024 Frag.Len += sizeof (*DnsQuery);
2025
2026 //
2027 // Wrap the Frag in a net buffer.
2028 //
2029 *Packet = NetbufFromExt (&Frag, 1, 0, 0, DnsDummyExtFree, NULL);
2030 if (*Packet == NULL) {
2031 FreePool (Frag.Bulk);
2032 return EFI_OUT_OF_RESOURCES;
2033 }
2034
2035 //
2036 // Store the UdpIo in ProtoData.
2037 //
2038 *((UINTN *)&((*Packet)->ProtoData[0])) = (UINTN)(Instance->UdpIo);
2039
2040 return EFI_SUCCESS;
2041}
2042
2043/**
2044 Retransmit the packet.
2045
2046 @param Instance The DNS instance
2047 @param Packet Retransmit the packet
2048
2049 @retval EFI_SUCCESS The packet is retransmitted.
2050 @retval Others Failed to retransmit.
2051
2052**/
2053EFI_STATUS
2054DnsRetransmit (
2055 IN DNS_INSTANCE *Instance,
2056 IN NET_BUF *Packet
2057 )
2058{
2059 EFI_STATUS Status;
2060
2061 UINT8 *Buffer;
2062
2063 ASSERT (Packet != NULL);
2064
2065 //
2066 // Set the requests to the listening port, other packets to the connected port
2067 //
2068 Buffer = NetbufGetByte (Packet, 0, NULL);
2069 ASSERT (Buffer != NULL);
2070
2071 NET_GET_REF (Packet);
2072
2073 Status = UdpIoSendDatagram (
2074 Instance->UdpIo,
2075 Packet,
2076 NULL,
2077 NULL,
2078 DnsOnPacketSent,
2079 Instance
2080 );
2081
2082 if (EFI_ERROR (Status)) {
2083 NET_PUT_REF (Packet);
2084 }
2085
2086 return Status;
2087}
2088
2089/**
2090 The timer ticking function for the DNS services.
2091
2092 @param Event The ticking event
2093 @param Context The DNS service instance
2094
2095**/
2096VOID
2097EFIAPI
2098DnsOnTimerRetransmit (
2099 IN EFI_EVENT Event,
2100 IN VOID *Context
2101 )
2102{
2103 DNS_SERVICE *Service;
2104
2105 LIST_ENTRY *Entry;
2106 LIST_ENTRY *Next;
2107
2108 DNS_INSTANCE *Instance;
2109 LIST_ENTRY *EntryNetMap;
2110 NET_MAP_ITEM *ItemNetMap;
2111 DNS4_TOKEN_ENTRY *Dns4TokenEntry;
2112 DNS6_TOKEN_ENTRY *Dns6TokenEntry;
2113
2114 Dns4TokenEntry = NULL;
2115 Dns6TokenEntry = NULL;
2116
2117 Service = (DNS_SERVICE *)Context;
2118
2119 if (Service->IpVersion == IP_VERSION_4) {
2120 //
2121 // Iterate through all the children of the DNS service instance. Time
2122 // out the packet. If maximum retries reached, clean the Token up.
2123 //
2124 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Service->Dns4ChildrenList) {
2125 Instance = NET_LIST_USER_STRUCT (Entry, DNS_INSTANCE, Link);
2126
2127 EntryNetMap = Instance->Dns4TxTokens.Used.ForwardLink;
2128 while (EntryNetMap != &Instance->Dns4TxTokens.Used) {
2129 ItemNetMap = NET_LIST_USER_STRUCT (EntryNetMap, NET_MAP_ITEM, Link);
2130 Dns4TokenEntry = (DNS4_TOKEN_ENTRY *)(ItemNetMap->Key);
2131 if ((Dns4TokenEntry->PacketToLive == 0) || (--Dns4TokenEntry->PacketToLive > 0)) {
2132 EntryNetMap = EntryNetMap->ForwardLink;
2133 continue;
2134 }
2135
2136 //
2137 // Retransmit the packet if haven't reach the maximum retry count,
2138 // otherwise exit the transfer.
2139 //
2140 if (++Dns4TokenEntry->RetryCounting <= Dns4TokenEntry->Token->RetryCount) {
2141 DnsRetransmit (Instance, (NET_BUF *)ItemNetMap->Value);
2142 EntryNetMap = EntryNetMap->ForwardLink;
2143 } else {
2144 //
2145 // Maximum retries reached, clean the Token up.
2146 //
2147 Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry);
2148 Dns4TokenEntry->Token->Status = EFI_TIMEOUT;
2149 gBS->SignalEvent (Dns4TokenEntry->Token->Event);
2150 DispatchDpc ();
2151
2152 //
2153 // Free the sending packet.
2154 //
2155 if (ItemNetMap->Value != NULL) {
2156 NetbufFree ((NET_BUF *)(ItemNetMap->Value));
2157 }
2158
2159 EntryNetMap = Instance->Dns4TxTokens.Used.ForwardLink;
2160 }
2161 }
2162 }
2163 } else {
2164 //
2165 // Iterate through all the children of the DNS service instance. Time
2166 // out the packet. If maximum retries reached, clean the Token up.
2167 //
2168 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Service->Dns6ChildrenList) {
2169 Instance = NET_LIST_USER_STRUCT (Entry, DNS_INSTANCE, Link);
2170
2171 EntryNetMap = Instance->Dns6TxTokens.Used.ForwardLink;
2172 while (EntryNetMap != &Instance->Dns6TxTokens.Used) {
2173 ItemNetMap = NET_LIST_USER_STRUCT (EntryNetMap, NET_MAP_ITEM, Link);
2174 Dns6TokenEntry = (DNS6_TOKEN_ENTRY *)(ItemNetMap->Key);
2175 if ((Dns6TokenEntry->PacketToLive == 0) || (--Dns6TokenEntry->PacketToLive > 0)) {
2176 EntryNetMap = EntryNetMap->ForwardLink;
2177 continue;
2178 }
2179
2180 //
2181 // Retransmit the packet if haven't reach the maximum retry count,
2182 // otherwise exit the transfer.
2183 //
2184 if (++Dns6TokenEntry->RetryCounting <= Dns6TokenEntry->Token->RetryCount) {
2185 DnsRetransmit (Instance, (NET_BUF *)ItemNetMap->Value);
2186 EntryNetMap = EntryNetMap->ForwardLink;
2187 } else {
2188 //
2189 // Maximum retries reached, clean the Token up.
2190 //
2191 Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry);
2192 Dns6TokenEntry->Token->Status = EFI_TIMEOUT;
2193 gBS->SignalEvent (Dns6TokenEntry->Token->Event);
2194 DispatchDpc ();
2195
2196 //
2197 // Free the sending packet.
2198 //
2199 if (ItemNetMap->Value != NULL) {
2200 NetbufFree ((NET_BUF *)(ItemNetMap->Value));
2201 }
2202
2203 EntryNetMap = Instance->Dns6TxTokens.Used.ForwardLink;
2204 }
2205 }
2206 }
2207 }
2208}
2209
2210/**
2211 The timer ticking function for the DNS driver.
2212
2213 @param Event The ticking event
2214 @param Context NULL
2215
2216**/
2217VOID
2218EFIAPI
2219DnsOnTimerUpdate (
2220 IN EFI_EVENT Event,
2221 IN VOID *Context
2222 )
2223{
2224 LIST_ENTRY *Entry;
2225 LIST_ENTRY *Next;
2226 DNS4_CACHE *Item4;
2227 DNS6_CACHE *Item6;
2228
2229 Item4 = NULL;
2230 Item6 = NULL;
2231
2232 //
2233 // Iterate through all the DNS4 cache list.
2234 //
2235 NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) {
2236 Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
2237 Item4->DnsCache.Timeout--;
2238 }
2239
2240 Entry = mDriverData->Dns4CacheList.ForwardLink;
2241 while (Entry != &mDriverData->Dns4CacheList) {
2242 Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
2243 if (Item4->DnsCache.Timeout == 0) {
2244 RemoveEntryList (&Item4->AllCacheLink);
2245 FreePool (Item4->DnsCache.HostName);
2246 FreePool (Item4->DnsCache.IpAddress);
2247 FreePool (Item4);
2248 Entry = mDriverData->Dns4CacheList.ForwardLink;
2249 } else {
2250 Entry = Entry->ForwardLink;
2251 }
2252 }
2253
2254 //
2255 // Iterate through all the DNS6 cache list.
2256 //
2257 NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6CacheList) {
2258 Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
2259 Item6->DnsCache.Timeout--;
2260 }
2261
2262 Entry = mDriverData->Dns6CacheList.ForwardLink;
2263 while (Entry != &mDriverData->Dns6CacheList) {
2264 Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
2265 if (Item6->DnsCache.Timeout == 0) {
2266 RemoveEntryList (&Item6->AllCacheLink);
2267 FreePool (Item6->DnsCache.HostName);
2268 FreePool (Item6->DnsCache.IpAddress);
2269 FreePool (Item6);
2270 Entry = mDriverData->Dns6CacheList.ForwardLink;
2271 } else {
2272 Entry = Entry->ForwardLink;
2273 }
2274 }
2275}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette