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