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