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