]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/DnsDxe/DnsImpl.c
NetworkPkg: Support DNS4/6 GeneralLookUp feature
[mirror_edk2.git] / NetworkPkg / DnsDxe / DnsImpl.c
1 /** @file
2 DnsDxe support functions implementation.
3
4 Copyright (c) 2015, 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 Ip6Mode.IsConfigured) {
623
624 Udp->Configure (Udp, NULL);
625 return (BOOLEAN) (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS);
626 }
627 }
628
629 return FALSE;
630 }
631
632 /**
633 Configure the UDP.
634
635 @param Instance The DNS session
636 @param UdpIo The UDP_IO instance
637
638 @retval EFI_SUCCESS The UDP is successfully configured for the
639 session.
640
641 **/
642 EFI_STATUS
643 Dns4ConfigUdp (
644 IN DNS_INSTANCE *Instance,
645 IN UDP_IO *UdpIo
646 )
647 {
648 EFI_DNS4_CONFIG_DATA *Config;
649 EFI_UDP4_CONFIG_DATA UdpConfig;
650 EFI_STATUS Status;
651
652 Config = &Instance->Dns4CfgData;
653
654 UdpConfig.AcceptBroadcast = FALSE;
655 UdpConfig.AcceptPromiscuous = FALSE;
656 UdpConfig.AcceptAnyPort = FALSE;
657 UdpConfig.AllowDuplicatePort = FALSE;
658 UdpConfig.TypeOfService = 0;
659 UdpConfig.TimeToLive = 128;
660 UdpConfig.DoNotFragment = FALSE;
661 UdpConfig.ReceiveTimeout = 0;
662 UdpConfig.TransmitTimeout = 0;
663 UdpConfig.UseDefaultAddress = Config->UseDefaultSetting;
664 UdpConfig.SubnetMask = Config->SubnetMask;
665 UdpConfig.StationPort = Config->LocalPort;
666 UdpConfig.RemotePort = DNS_SERVER_PORT;
667
668 CopyMem (&UdpConfig.StationAddress, &Config->StationIp, sizeof (EFI_IPv4_ADDRESS));
669 CopyMem (&UdpConfig.RemoteAddress, &Instance->SessionDnsServer.v4, sizeof (EFI_IPv4_ADDRESS));
670
671 Status = UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfig);
672
673 if ((Status == EFI_NO_MAPPING) && Dns4GetMapping (Instance, UdpIo, &UdpConfig)) {
674 return EFI_SUCCESS;
675 }
676
677 return Status;
678 }
679
680 /**
681 Configure the UDP.
682
683 @param Instance The DNS session
684 @param UdpIo The UDP_IO instance
685
686 @retval EFI_SUCCESS The UDP is successfully configured for the
687 session.
688
689 **/
690 EFI_STATUS
691 Dns6ConfigUdp (
692 IN DNS_INSTANCE *Instance,
693 IN UDP_IO *UdpIo
694 )
695 {
696 EFI_DNS6_CONFIG_DATA *Config;
697 EFI_UDP6_CONFIG_DATA UdpConfig;
698 EFI_STATUS Status;
699
700 Config = &Instance->Dns6CfgData;
701
702 UdpConfig.AcceptPromiscuous = FALSE;
703 UdpConfig.AcceptAnyPort = FALSE;
704 UdpConfig.AllowDuplicatePort = FALSE;
705 UdpConfig.TrafficClass = 0;
706 UdpConfig.HopLimit = 128;
707 UdpConfig.ReceiveTimeout = 0;
708 UdpConfig.TransmitTimeout = 0;
709 UdpConfig.StationPort = Config->LocalPort;
710 UdpConfig.RemotePort = DNS_SERVER_PORT;
711 CopyMem (&UdpConfig.StationAddress, &Config->StationIp, sizeof (EFI_IPv6_ADDRESS));
712 CopyMem (&UdpConfig.RemoteAddress, &Instance->SessionDnsServer.v6, sizeof (EFI_IPv6_ADDRESS));
713
714 Status = UdpIo->Protocol.Udp6->Configure (UdpIo->Protocol.Udp6, &UdpConfig);
715
716 if ((Status == EFI_NO_MAPPING) && Dns6GetMapping (Instance, UdpIo, &UdpConfig)) {
717 return EFI_SUCCESS;
718 }
719
720 return Status;
721 }
722
723 /**
724 Update Dns4 cache to shared list of caches of all DNSv4 instances.
725
726 @param Dns4CacheList All Dns4 cache list.
727 @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache.
728 If TRUE, this function will delete matching DNS Cache entry.
729 @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
730 If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
731 @param DnsCacheEntry Entry Pointer to DNS Cache entry.
732
733 @retval EFI_SUCCESS Update Dns4 cache successfully.
734 @retval Others Failed to update Dns4 cache.
735
736 **/
737 EFI_STATUS
738 EFIAPI
739 UpdateDns4Cache (
740 IN LIST_ENTRY *Dns4CacheList,
741 IN BOOLEAN DeleteFlag,
742 IN BOOLEAN Override,
743 IN EFI_DNS4_CACHE_ENTRY DnsCacheEntry
744 )
745 {
746 DNS4_CACHE *NewDnsCache;
747 DNS4_CACHE *Item;
748 LIST_ENTRY *Entry;
749 LIST_ENTRY *Next;
750
751 NewDnsCache = NULL;
752 Item = NULL;
753
754 //
755 // Search the database for the matching EFI_DNS_CACHE_ENTRY
756 //
757 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns4CacheList) {
758 Item = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
759 if (StrCmp (DnsCacheEntry.HostName, Item->DnsCache.HostName) == 0 && \
760 CompareMem (DnsCacheEntry.IpAddress, Item->DnsCache.IpAddress, sizeof (EFI_IPv4_ADDRESS)) == 0) {
761 //
762 // This is the Dns cache entry
763 //
764 if (DeleteFlag) {
765 //
766 // Delete matching DNS Cache entry
767 //
768 RemoveEntryList (&Item->AllCacheLink);
769
770 return EFI_SUCCESS;
771 } else if (Override) {
772 //
773 // Update this one
774 //
775 Item->DnsCache.Timeout = DnsCacheEntry.Timeout;
776
777 return EFI_SUCCESS;
778 }else {
779 return EFI_ACCESS_DENIED;
780 }
781 }
782 }
783
784 //
785 // Add new one
786 //
787 NewDnsCache = AllocatePool (sizeof (DNS4_CACHE));
788 if (NewDnsCache == NULL) {
789 return EFI_OUT_OF_RESOURCES;
790 }
791
792 InitializeListHead (&NewDnsCache->AllCacheLink);
793
794 NewDnsCache->DnsCache.HostName = AllocatePool (StrSize (DnsCacheEntry.HostName));
795 if (NewDnsCache->DnsCache.HostName == NULL) {
796 return EFI_OUT_OF_RESOURCES;
797 }
798
799 CopyMem (NewDnsCache->DnsCache.HostName, DnsCacheEntry.HostName, StrSize (DnsCacheEntry.HostName));
800
801 NewDnsCache->DnsCache.IpAddress = AllocatePool (sizeof (EFI_IPv4_ADDRESS));
802 if (NewDnsCache->DnsCache.IpAddress == NULL) {
803 return EFI_OUT_OF_RESOURCES;
804 }
805
806 CopyMem (NewDnsCache->DnsCache.IpAddress, DnsCacheEntry.IpAddress, sizeof (EFI_IPv4_ADDRESS));
807
808 NewDnsCache->DnsCache.Timeout = DnsCacheEntry.Timeout;
809
810 InsertTailList (Dns4CacheList, &NewDnsCache->AllCacheLink);
811
812 return EFI_SUCCESS;
813 }
814
815 /**
816 Update Dns6 cache to shared list of caches of all DNSv6 instances.
817
818 @param Dns6CacheList All Dns6 cache list.
819 @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache.
820 If TRUE, this function will delete matching DNS Cache entry.
821 @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
822 If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
823 @param DnsCacheEntry Entry Pointer to DNS Cache entry.
824
825 @retval EFI_SUCCESS Update Dns6 cache successfully.
826 @retval Others Failed to update Dns6 cache.
827 **/
828 EFI_STATUS
829 EFIAPI
830 UpdateDns6Cache (
831 IN LIST_ENTRY *Dns6CacheList,
832 IN BOOLEAN DeleteFlag,
833 IN BOOLEAN Override,
834 IN EFI_DNS6_CACHE_ENTRY DnsCacheEntry
835 )
836 {
837 DNS6_CACHE *NewDnsCache;
838 DNS6_CACHE *Item;
839 LIST_ENTRY *Entry;
840 LIST_ENTRY *Next;
841
842 NewDnsCache = NULL;
843 Item = NULL;
844
845 //
846 // Search the database for the matching EFI_DNS_CACHE_ENTRY
847 //
848 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns6CacheList) {
849 Item = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
850 if (StrCmp (DnsCacheEntry.HostName, Item->DnsCache.HostName) == 0 && \
851 CompareMem (DnsCacheEntry.IpAddress, Item->DnsCache.IpAddress, sizeof (EFI_IPv6_ADDRESS)) == 0) {
852 //
853 // This is the Dns cache entry
854 //
855 if (DeleteFlag) {
856 //
857 // Delete matching DNS Cache entry
858 //
859 RemoveEntryList (&Item->AllCacheLink);
860
861 return EFI_SUCCESS;
862 } else if (Override) {
863 //
864 // Update this one
865 //
866 Item->DnsCache.Timeout = DnsCacheEntry.Timeout;
867
868 return EFI_SUCCESS;
869 }else {
870 return EFI_ACCESS_DENIED;
871 }
872 }
873 }
874
875 //
876 // Add new one
877 //
878 NewDnsCache = AllocatePool (sizeof (DNS6_CACHE));
879 if (NewDnsCache == NULL) {
880 return EFI_OUT_OF_RESOURCES;
881 }
882
883 InitializeListHead (&NewDnsCache->AllCacheLink);
884
885 NewDnsCache->DnsCache.HostName = AllocatePool (StrSize (DnsCacheEntry.HostName));
886 if (NewDnsCache->DnsCache.HostName == NULL) {
887 return EFI_OUT_OF_RESOURCES;
888 }
889
890 CopyMem (NewDnsCache->DnsCache.HostName, DnsCacheEntry.HostName, StrSize (DnsCacheEntry.HostName));
891
892 NewDnsCache->DnsCache.IpAddress = AllocatePool (sizeof (EFI_IPv6_ADDRESS));
893 if (NewDnsCache->DnsCache.IpAddress == NULL) {
894 return EFI_OUT_OF_RESOURCES;
895 }
896
897 CopyMem (NewDnsCache->DnsCache.IpAddress, DnsCacheEntry.IpAddress, sizeof (EFI_IPv6_ADDRESS));
898
899 NewDnsCache->DnsCache.Timeout = DnsCacheEntry.Timeout;
900
901 InsertTailList (Dns6CacheList, &NewDnsCache->AllCacheLink);
902
903 return EFI_SUCCESS;
904 }
905
906 /**
907 Add Dns4 ServerIp to common list of addresses of all configured DNSv4 server.
908
909 @param Dns4ServerList Common list of addresses of all configured DNSv4 server.
910 @param ServerIp DNS server Ip.
911
912 @retval EFI_SUCCESS Add Dns4 ServerIp to common list successfully.
913 @retval Others Failed to add Dns4 ServerIp to common list.
914
915 **/
916 EFI_STATUS
917 EFIAPI
918 AddDns4ServerIp (
919 IN LIST_ENTRY *Dns4ServerList,
920 IN EFI_IPv4_ADDRESS ServerIp
921 )
922 {
923 DNS4_SERVER_IP *NewServerIp;
924 DNS4_SERVER_IP *Item;
925 LIST_ENTRY *Entry;
926 LIST_ENTRY *Next;
927
928 NewServerIp = NULL;
929 Item = NULL;
930
931 //
932 // Search the database for the matching ServerIp
933 //
934 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns4ServerList) {
935 Item = NET_LIST_USER_STRUCT (Entry, DNS4_SERVER_IP, AllServerLink);
936 if (CompareMem (&Item->Dns4ServerIp, &ServerIp, sizeof (EFI_IPv4_ADDRESS)) == 0) {
937 //
938 // Already done.
939 //
940 return EFI_SUCCESS;
941 }
942 }
943
944 //
945 // Add new one
946 //
947 NewServerIp = AllocatePool (sizeof (DNS4_SERVER_IP));
948 if (NewServerIp == NULL) {
949 return EFI_OUT_OF_RESOURCES;
950 }
951
952 InitializeListHead (&NewServerIp->AllServerLink);
953
954 CopyMem (&NewServerIp->Dns4ServerIp, &ServerIp, sizeof (EFI_IPv4_ADDRESS));
955
956 InsertTailList (Dns4ServerList, &NewServerIp->AllServerLink);
957
958 return EFI_SUCCESS;
959 }
960
961 /**
962 Add Dns6 ServerIp to common list of addresses of all configured DNSv6 server.
963
964 @param Dns6ServerList Common list of addresses of all configured DNSv6 server.
965 @param ServerIp DNS server Ip.
966
967 @retval EFI_SUCCESS Add Dns6 ServerIp to common list successfully.
968 @retval Others Failed to add Dns6 ServerIp to common list.
969
970 **/
971 EFI_STATUS
972 EFIAPI
973 AddDns6ServerIp (
974 IN LIST_ENTRY *Dns6ServerList,
975 IN EFI_IPv6_ADDRESS ServerIp
976 )
977 {
978 DNS6_SERVER_IP *NewServerIp;
979 DNS6_SERVER_IP *Item;
980 LIST_ENTRY *Entry;
981 LIST_ENTRY *Next;
982
983 NewServerIp = NULL;
984 Item = NULL;
985
986 //
987 // Search the database for the matching ServerIp
988 //
989 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns6ServerList) {
990 Item = NET_LIST_USER_STRUCT (Entry, DNS6_SERVER_IP, AllServerLink);
991 if (CompareMem (&Item->Dns6ServerIp, &ServerIp, sizeof (EFI_IPv6_ADDRESS)) == 0) {
992 //
993 // Already done.
994 //
995 return EFI_SUCCESS;
996 }
997 }
998
999 //
1000 // Add new one
1001 //
1002 NewServerIp = AllocatePool (sizeof (DNS6_SERVER_IP));
1003 if (NewServerIp == NULL) {
1004 return EFI_OUT_OF_RESOURCES;
1005 }
1006
1007 InitializeListHead (&NewServerIp->AllServerLink);
1008
1009 CopyMem (&NewServerIp->Dns6ServerIp, &ServerIp, sizeof (EFI_IPv6_ADDRESS));
1010
1011 InsertTailList (Dns6ServerList, &NewServerIp->AllServerLink);
1012
1013 return EFI_SUCCESS;
1014 }
1015
1016 /**
1017 Fill QName for IP querying. QName is a domain name represented as
1018 a sequence of labels, where each label consists of a length octet
1019 followed by that number of octets. The domain name terminates with
1020 the zero length octet for the null label of the root. Caller should
1021 take responsibility to the buffer in QName.
1022
1023 @param HostName Queried HostName
1024
1025 @retval NULL Failed to fill QName.
1026 @return QName filled successfully.
1027
1028 **/
1029 UINT8 *
1030 EFIAPI
1031 DnsFillinQNameForQueryIp (
1032 IN CHAR16 *HostName
1033 )
1034 {
1035 CHAR8 *QueryName;
1036 CHAR8 *Header;
1037 CHAR8 *Tail;
1038 UINTN Len;
1039 UINTN Index;
1040
1041 QueryName = NULL;
1042 Header = NULL;
1043 Tail = NULL;
1044
1045 QueryName = AllocateZeroPool (DNS_DEFAULT_BLKSIZE);
1046 if (QueryName == NULL) {
1047 return NULL;
1048 }
1049
1050 Header = QueryName;
1051 Tail = Header + 1;
1052 Len = 0;
1053 for (Index = 0; HostName[Index] != 0; Index++) {
1054 *Tail = (CHAR8) HostName[Index];
1055 if (*Tail == '.') {
1056 *Header = (CHAR8) Len;
1057 Header = Tail;
1058 Tail ++;
1059 Len = 0;
1060 } else {
1061 Tail++;
1062 Len++;
1063 }
1064 }
1065 *Header = (CHAR8) Len;
1066 *Tail = 0;
1067
1068 return QueryName;
1069 }
1070
1071 /**
1072 Find out whether the response is valid or invalid.
1073
1074 @param TokensMap All DNS transmittal Tokens entry.
1075 @param Identification Identification for queried packet.
1076 @param Type Type for queried packet.
1077 @param Item Return corresponding Token entry.
1078
1079 @retval TRUE The response is valid.
1080 @retval FALSE The response is invalid.
1081
1082 **/
1083 BOOLEAN
1084 IsValidDnsResponse (
1085 IN NET_MAP *TokensMap,
1086 IN UINT16 Identification,
1087 IN UINT16 Type,
1088 OUT NET_MAP_ITEM **Item
1089 )
1090 {
1091 LIST_ENTRY *Entry;
1092
1093 NET_BUF *Packet;
1094 UINT8 *TxString;
1095 DNS_HEADER *DnsHeader;
1096 CHAR8 *QueryName;
1097 DNS_QUERY_SECTION *QuerySection;
1098
1099 NET_LIST_FOR_EACH (Entry, &TokensMap->Used) {
1100 *Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1101 Packet = (NET_BUF *) ((*Item)->Value);
1102 if (Packet == NULL){
1103
1104 continue;
1105 } else {
1106 TxString = NetbufGetByte (Packet, 0, NULL);
1107 ASSERT (TxString != NULL);
1108 DnsHeader = (DNS_HEADER *) TxString;
1109 QueryName = (CHAR8 *) (TxString + sizeof (*DnsHeader));
1110 QuerySection = (DNS_QUERY_SECTION *) (QueryName + AsciiStrLen (QueryName) + 1);
1111
1112 DnsHeader->Identification = NTOHS (DnsHeader->Identification);
1113 QuerySection->Type = NTOHS (QuerySection->Type);
1114
1115 if (DnsHeader->Identification == Identification && QuerySection->Type == Type) {
1116 return TRUE;
1117 }
1118 }
1119 }
1120
1121 *Item =NULL;
1122
1123 return FALSE;
1124 }
1125
1126 /**
1127 Parse Dns Response.
1128
1129 @param Instance The DNS instance
1130 @param RxString Received buffer.
1131 @param Completed Flag to indicate that Dns response is valid.
1132
1133 @retval EFI_SUCCESS Parse Dns Response successfully.
1134 @retval Others Failed to parse Dns Response.
1135
1136 **/
1137 EFI_STATUS
1138 ParseDnsResponse (
1139 IN OUT DNS_INSTANCE *Instance,
1140 IN UINT8 *RxString,
1141 OUT BOOLEAN *Completed
1142 )
1143 {
1144 DNS_HEADER *DnsHeader;
1145
1146 CHAR8 *QueryName;
1147 DNS_QUERY_SECTION *QuerySection;
1148
1149 CHAR8 *AnswerName;
1150 DNS_ANSWER_SECTION *AnswerSection;
1151 UINT8 *AnswerData;
1152
1153 NET_MAP_ITEM *Item;
1154 DNS4_TOKEN_ENTRY *Dns4TokenEntry;
1155 DNS6_TOKEN_ENTRY *Dns6TokenEntry;
1156
1157 UINT32 IpCount;
1158 UINT32 RRCount;
1159 UINT32 AnswerSectionNum;
1160
1161 EFI_IPv4_ADDRESS *HostAddr4;
1162 EFI_IPv6_ADDRESS *HostAddr6;
1163
1164 EFI_DNS4_CACHE_ENTRY *Dns4CacheEntry;
1165 EFI_DNS6_CACHE_ENTRY *Dns6CacheEntry;
1166
1167 DNS_RESOURCE_RECORD *Dns4RR;
1168 DNS6_RESOURCE_RECORD *Dns6RR;
1169
1170 EFI_STATUS Status;
1171
1172 EFI_TPL OldTpl;
1173
1174 Item = NULL;
1175 Dns4TokenEntry = NULL;
1176 Dns6TokenEntry = NULL;
1177
1178 IpCount = 0;
1179 RRCount = 0;
1180 AnswerSectionNum = 0;
1181
1182 HostAddr4 = NULL;
1183 HostAddr6 = NULL;
1184
1185 Dns4CacheEntry = NULL;
1186 Dns6CacheEntry = NULL;
1187
1188 Dns4RR = NULL;
1189 Dns6RR = NULL;
1190
1191 *Completed = TRUE;
1192 Status = EFI_SUCCESS;
1193
1194 //
1195 // Get header
1196 //
1197 DnsHeader = (DNS_HEADER *) RxString;
1198
1199 DnsHeader->Identification = NTOHS (DnsHeader->Identification);
1200 DnsHeader->Flags.Uint16 = NTOHS (DnsHeader->Flags.Uint16);
1201 DnsHeader->QuestionsNum = NTOHS (DnsHeader->QuestionsNum);
1202 DnsHeader->AnswersNum = NTOHS (DnsHeader->AnswersNum);
1203 DnsHeader->AuthorityNum = NTOHS (DnsHeader->AuthorityNum);
1204 DnsHeader->AditionalNum = NTOHS (DnsHeader->AditionalNum);
1205
1206 //
1207 // Get Query name
1208 //
1209 QueryName = (CHAR8 *) (RxString + sizeof (*DnsHeader));
1210
1211 //
1212 // Get query section
1213 //
1214 QuerySection = (DNS_QUERY_SECTION *) (QueryName + AsciiStrLen (QueryName) + 1);
1215 QuerySection->Type = NTOHS (QuerySection->Type);
1216 QuerySection->Class = NTOHS (QuerySection->Class);
1217
1218 //
1219 // Get Answer name
1220 //
1221 AnswerName = (CHAR8 *) QuerySection + sizeof (*QuerySection);
1222
1223 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1224
1225 //
1226 // Check DnsResponse Validity, if so, also get a valid NET_MAP_ITEM.
1227 //
1228 if (Instance->Service->IpVersion == IP_VERSION_4) {
1229 if (!IsValidDnsResponse (&Instance->Dns4TxTokens, DnsHeader->Identification, QuerySection->Type, &Item)) {
1230 *Completed = FALSE;
1231 Status = EFI_ABORTED;
1232 goto ON_EXIT;
1233 }
1234 ASSERT (Item != NULL);
1235 Dns4TokenEntry = (DNS4_TOKEN_ENTRY *) (Item->Key);
1236 } else {
1237 if (!IsValidDnsResponse (&Instance->Dns6TxTokens, DnsHeader->Identification, QuerySection->Type, &Item)) {
1238 *Completed = FALSE;
1239 Status = EFI_ABORTED;
1240 goto ON_EXIT;
1241 }
1242 ASSERT (Item != NULL);
1243 Dns6TokenEntry = (DNS6_TOKEN_ENTRY *) (Item->Key);
1244 }
1245
1246 //
1247 // Continue Check Some Errors.
1248 //
1249 if (DnsHeader->Flags.Bits.RCode != DNS_FLAGS_RCODE_NO_ERROR || DnsHeader->AnswersNum < 1 || \
1250 DnsHeader->Flags.Bits.QR != DNS_FLAGS_QR_RESPONSE || QuerySection->Class != DNS_CLASS_INET) {
1251 Status = EFI_ABORTED;
1252 goto ON_EXIT;
1253 }
1254
1255 //
1256 // Free the sending packet.
1257 //
1258 if (Item->Value != NULL) {
1259 NetbufFree ((NET_BUF *) (Item->Value));
1260 }
1261
1262 //
1263 // Do some buffer allocations.
1264 //
1265 if (Instance->Service->IpVersion == IP_VERSION_4) {
1266 ASSERT (Dns4TokenEntry != NULL);
1267
1268 if (Dns4TokenEntry->GeneralLookUp) {
1269 //
1270 // It's the GeneralLookUp querying.
1271 //
1272 Dns4TokenEntry->Token->RspData.GLookupData = AllocatePool (sizeof (DNS_RESOURCE_RECORD));
1273 if (Dns4TokenEntry->Token->RspData.GLookupData == NULL) {
1274 Status = EFI_OUT_OF_RESOURCES;
1275 goto ON_EXIT;
1276 }
1277 Dns4TokenEntry->Token->RspData.GLookupData->RRList = AllocatePool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD));
1278 if (Dns4TokenEntry->Token->RspData.GLookupData->RRList == NULL) {
1279 Status = EFI_OUT_OF_RESOURCES;
1280 goto ON_EXIT;
1281 }
1282 } else {
1283 //
1284 // It's not the GeneralLookUp querying. Check the Query type.
1285 //
1286 if (QuerySection->Type == DNS_TYPE_A) {
1287 Dns4TokenEntry->Token->RspData.H2AData = AllocatePool (sizeof (DNS_HOST_TO_ADDR_DATA));
1288 if (Dns4TokenEntry->Token->RspData.H2AData == NULL) {
1289 Status = EFI_OUT_OF_RESOURCES;
1290 goto ON_EXIT;
1291 }
1292 Dns4TokenEntry->Token->RspData.H2AData->IpList = AllocatePool (DnsHeader->AnswersNum * sizeof (EFI_IPv4_ADDRESS));
1293 if (Dns4TokenEntry->Token->RspData.H2AData->IpList == NULL) {
1294 Status = EFI_OUT_OF_RESOURCES;
1295 goto ON_EXIT;
1296 }
1297 } else {
1298 Status = EFI_UNSUPPORTED;
1299 goto ON_EXIT;
1300 }
1301 }
1302 } else {
1303 ASSERT (Dns6TokenEntry != NULL);
1304
1305 if (Dns6TokenEntry->GeneralLookUp) {
1306 //
1307 // It's the GeneralLookUp querying.
1308 //
1309 Dns6TokenEntry->Token->RspData.GLookupData = AllocatePool (sizeof (DNS_RESOURCE_RECORD));
1310 if (Dns6TokenEntry->Token->RspData.GLookupData == NULL) {
1311 Status = EFI_UNSUPPORTED;
1312 goto ON_EXIT;
1313 }
1314 Dns6TokenEntry->Token->RspData.GLookupData->RRList = AllocatePool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD));
1315 if (Dns6TokenEntry->Token->RspData.GLookupData->RRList == NULL) {
1316 Status = EFI_UNSUPPORTED;
1317 goto ON_EXIT;
1318 }
1319 } else {
1320 //
1321 // It's not the GeneralLookUp querying. Check the Query type.
1322 //
1323 if (QuerySection->Type == DNS_TYPE_AAAA) {
1324 Dns6TokenEntry->Token->RspData.H2AData = AllocatePool (sizeof (DNS6_HOST_TO_ADDR_DATA));
1325 if (Dns6TokenEntry->Token->RspData.H2AData == NULL) {
1326 Status = EFI_UNSUPPORTED;
1327 goto ON_EXIT;
1328 }
1329 Dns6TokenEntry->Token->RspData.H2AData->IpList = AllocatePool (DnsHeader->AnswersNum * sizeof (EFI_IPv6_ADDRESS));
1330 if (Dns6TokenEntry->Token->RspData.H2AData->IpList == NULL) {
1331 Status = EFI_UNSUPPORTED;
1332 goto ON_EXIT;
1333 }
1334 } else {
1335 Status = EFI_UNSUPPORTED;
1336 goto ON_EXIT;
1337 }
1338 }
1339 }
1340
1341 //
1342 // Processing AnswerSection.
1343 //
1344 while (AnswerSectionNum < DnsHeader->AnswersNum) {
1345 //
1346 // Answer name should be PTR.
1347 //
1348 ASSERT ((*(UINT8 *) AnswerName & 0xC0) == 0xC0);
1349
1350 //
1351 // Get Answer section.
1352 //
1353 AnswerSection = (DNS_ANSWER_SECTION *) (AnswerName + sizeof (UINT16));
1354 AnswerSection->Type = NTOHS (AnswerSection->Type);
1355 AnswerSection->Class = NTOHS (AnswerSection->Class);
1356 AnswerSection->Ttl = NTOHL (AnswerSection->Ttl);
1357 AnswerSection->DataLength = NTOHS (AnswerSection->DataLength);
1358
1359 //
1360 // Check whether it's the GeneralLookUp querying.
1361 //
1362 if (Instance->Service->IpVersion == IP_VERSION_4 && Dns4TokenEntry->GeneralLookUp) {
1363 ASSERT (Dns4TokenEntry != NULL);
1364
1365 Dns4RR = Dns4TokenEntry->Token->RspData.GLookupData->RRList;
1366 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
1367
1368 //
1369 // Fill the ResourceRecord.
1370 //
1371 Dns4RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1);
1372 if (Dns4RR[RRCount].QName == NULL) {
1373 Status = EFI_UNSUPPORTED;
1374 goto ON_EXIT;
1375 }
1376 CopyMem (Dns4RR[RRCount].QName, QueryName, AsciiStrLen (QueryName));
1377 Dns4RR[RRCount].QType = AnswerSection->Type;
1378 Dns4RR[RRCount].QClass = AnswerSection->Class;
1379 Dns4RR[RRCount].TTL = AnswerSection->Ttl;
1380 Dns4RR[RRCount].DataLength = AnswerSection->DataLength;
1381 Dns4RR[RRCount].RData = AllocateZeroPool (Dns4RR[RRCount].DataLength);
1382 if (Dns4RR[RRCount].RData == NULL) {
1383 Status = EFI_UNSUPPORTED;
1384 goto ON_EXIT;
1385 }
1386 CopyMem (Dns4RR[RRCount].RData, AnswerData, Dns4RR[RRCount].DataLength);
1387
1388 RRCount ++;
1389 } else if (Instance->Service->IpVersion == IP_VERSION_6 && Dns6TokenEntry->GeneralLookUp) {
1390 ASSERT (Dns6TokenEntry != NULL);
1391
1392 Dns6RR = Dns6TokenEntry->Token->RspData.GLookupData->RRList;
1393 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
1394
1395 //
1396 // Fill the ResourceRecord.
1397 //
1398 Dns6RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1);
1399 if (Dns6RR[RRCount].QName == NULL) {
1400 Status = EFI_UNSUPPORTED;
1401 goto ON_EXIT;
1402 }
1403 CopyMem (Dns6RR[RRCount].QName, QueryName, AsciiStrLen (QueryName));
1404 Dns6RR[RRCount].QType = AnswerSection->Type;
1405 Dns6RR[RRCount].QClass = AnswerSection->Class;
1406 Dns6RR[RRCount].TTL = AnswerSection->Ttl;
1407 Dns6RR[RRCount].DataLength = AnswerSection->DataLength;
1408 Dns6RR[RRCount].RData = AllocateZeroPool (Dns6RR[RRCount].DataLength);
1409 if (Dns6RR[RRCount].RData == NULL) {
1410 Status = EFI_UNSUPPORTED;
1411 goto ON_EXIT;
1412 }
1413 CopyMem (Dns6RR[RRCount].RData, AnswerData, Dns6RR[RRCount].DataLength);
1414
1415 RRCount ++;
1416 } else {
1417 //
1418 // It's not the GeneralLookUp querying.
1419 // Check the Query type, parse the response packet.
1420 //
1421 switch (AnswerSection->Type) {
1422 case DNS_TYPE_A:
1423 //
1424 // This is address entry, get Data.
1425 //
1426 ASSERT (Dns4TokenEntry != NULL && AnswerSection->DataLength == 4);
1427
1428 HostAddr4 = Dns4TokenEntry->Token->RspData.H2AData->IpList;
1429 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
1430 CopyMem (&HostAddr4[IpCount], AnswerData, sizeof (EFI_IPv4_ADDRESS));
1431
1432 //
1433 // Update DNS cache dynamically.
1434 //
1435 if (Dns4CacheEntry != NULL) {
1436 if (Dns4CacheEntry->HostName != NULL) {
1437 FreePool (Dns4CacheEntry->HostName);
1438 }
1439
1440 if (Dns4CacheEntry->IpAddress != NULL) {
1441 FreePool (Dns4CacheEntry->IpAddress);
1442 }
1443
1444 FreePool (Dns4CacheEntry);
1445 }
1446
1447 //
1448 // Allocate new CacheEntry pool.
1449 //
1450 Dns4CacheEntry = AllocateZeroPool (sizeof (EFI_DNS4_CACHE_ENTRY));
1451 if (Dns4CacheEntry == NULL) {
1452 Status = EFI_UNSUPPORTED;
1453 goto ON_EXIT;
1454 }
1455 Dns4CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1));
1456 if (Dns4CacheEntry->HostName == NULL) {
1457 Status = EFI_UNSUPPORTED;
1458 goto ON_EXIT;
1459 }
1460 CopyMem (Dns4CacheEntry->HostName, Dns4TokenEntry->QueryHostName, 2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1));
1461 Dns4CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv4_ADDRESS));
1462 if (Dns4CacheEntry->IpAddress == NULL) {
1463 Status = EFI_UNSUPPORTED;
1464 goto ON_EXIT;
1465 }
1466 CopyMem (Dns4CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv4_ADDRESS));
1467 Dns4CacheEntry->Timeout = AnswerSection->Ttl;
1468
1469 UpdateDns4Cache (&mDriverData->Dns4CacheList, FALSE, TRUE, *Dns4CacheEntry);
1470
1471 IpCount ++;
1472 break;
1473 case DNS_TYPE_AAAA:
1474 //
1475 // This is address entry, get Data.
1476 //
1477 ASSERT (Dns6TokenEntry != NULL && AnswerSection->DataLength == 16);
1478
1479 HostAddr6 = Dns6TokenEntry->Token->RspData.H2AData->IpList;
1480 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
1481 CopyMem (&HostAddr6[IpCount], AnswerData, sizeof (EFI_IPv6_ADDRESS));
1482
1483 //
1484 // Update DNS cache dynamically.
1485 //
1486 if (Dns6CacheEntry != NULL) {
1487 if (Dns6CacheEntry->HostName != NULL) {
1488 FreePool (Dns6CacheEntry->HostName);
1489 }
1490
1491 if (Dns6CacheEntry->IpAddress != NULL) {
1492 FreePool (Dns6CacheEntry->IpAddress);
1493 }
1494
1495 FreePool (Dns6CacheEntry);
1496 }
1497
1498 //
1499 // Allocate new CacheEntry pool.
1500 //
1501 Dns6CacheEntry = AllocateZeroPool (sizeof (EFI_DNS6_CACHE_ENTRY));
1502 if (Dns6CacheEntry == NULL) {
1503 Status = EFI_UNSUPPORTED;
1504 goto ON_EXIT;
1505 }
1506 Dns6CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1));
1507 if (Dns6CacheEntry->HostName == NULL) {
1508 Status = EFI_UNSUPPORTED;
1509 goto ON_EXIT;
1510 }
1511 CopyMem (Dns6CacheEntry->HostName, Dns6TokenEntry->QueryHostName, 2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1));
1512 Dns6CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS));
1513 if (Dns6CacheEntry->IpAddress == NULL) {
1514 Status = EFI_UNSUPPORTED;
1515 goto ON_EXIT;
1516 }
1517 CopyMem (Dns6CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv6_ADDRESS));
1518 Dns6CacheEntry->Timeout = AnswerSection->Ttl;
1519
1520 UpdateDns6Cache (&mDriverData->Dns6CacheList, FALSE, TRUE, *Dns6CacheEntry);
1521
1522 IpCount ++;
1523 break;
1524 default:
1525 Status = EFI_UNSUPPORTED;
1526 goto ON_EXIT;
1527 }
1528 }
1529
1530 //
1531 // Find next one
1532 //
1533 AnswerName = (CHAR8 *) AnswerSection + sizeof (*AnswerSection) + AnswerSection->DataLength;
1534 AnswerSectionNum ++;
1535 }
1536
1537 if (Instance->Service->IpVersion == IP_VERSION_4) {
1538 ASSERT (Dns4TokenEntry != NULL);
1539
1540 if (Dns4TokenEntry->GeneralLookUp) {
1541 Dns4TokenEntry->Token->RspData.GLookupData->RRCount = RRCount;
1542 } else {
1543 if (QuerySection->Type == DNS_TYPE_A) {
1544 Dns4TokenEntry->Token->RspData.H2AData->IpCount = IpCount;
1545 } else {
1546 Status = EFI_UNSUPPORTED;
1547 goto ON_EXIT;
1548 }
1549 }
1550 } else {
1551 ASSERT (Dns6TokenEntry != NULL);
1552
1553 if (Dns6TokenEntry->GeneralLookUp) {
1554 Dns6TokenEntry->Token->RspData.GLookupData->RRCount = RRCount;
1555 } else {
1556 if (QuerySection->Type == DNS_TYPE_AAAA) {
1557 Dns6TokenEntry->Token->RspData.H2AData->IpCount = IpCount;
1558 } else {
1559 Status = EFI_UNSUPPORTED;
1560 goto ON_EXIT;
1561 }
1562 }
1563 }
1564
1565 //
1566 // Parsing is complete, SignalEvent here.
1567 //
1568 if (Instance->Service->IpVersion == IP_VERSION_4) {
1569 ASSERT (Dns4TokenEntry != NULL);
1570 Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry);
1571 Dns4TokenEntry->Token->Status = EFI_SUCCESS;
1572 if (Dns4TokenEntry->Token->Event != NULL) {
1573 gBS->SignalEvent (Dns4TokenEntry->Token->Event);
1574 DispatchDpc ();
1575 }
1576 } else {
1577 ASSERT (Dns6TokenEntry != NULL);
1578 Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry);
1579 Dns6TokenEntry->Token->Status = EFI_SUCCESS;
1580 if (Dns6TokenEntry->Token->Event != NULL) {
1581 gBS->SignalEvent (Dns6TokenEntry->Token->Event);
1582 DispatchDpc ();
1583 }
1584 }
1585
1586 //
1587 // Free allocated CacheEntry pool.
1588 //
1589 if (Dns4CacheEntry != NULL) {
1590 if (Dns4CacheEntry->HostName != NULL) {
1591 FreePool (Dns4CacheEntry->HostName);
1592 }
1593
1594 if (Dns4CacheEntry->IpAddress != NULL) {
1595 FreePool (Dns4CacheEntry->IpAddress);
1596 }
1597
1598 FreePool (Dns4CacheEntry);
1599 }
1600
1601 if (Dns6CacheEntry != NULL) {
1602 if (Dns6CacheEntry->HostName != NULL) {
1603 FreePool (Dns6CacheEntry->HostName);
1604 }
1605
1606 if (Dns6CacheEntry->IpAddress != NULL) {
1607 FreePool (Dns6CacheEntry->IpAddress);
1608 }
1609
1610 FreePool (Dns6CacheEntry);
1611 }
1612
1613 ON_EXIT:
1614 gBS->RestoreTPL (OldTpl);
1615 return Status;
1616 }
1617
1618 /**
1619 Parse response packet.
1620
1621 @param Packet The packets received.
1622 @param EndPoint The local/remote UDP access point
1623 @param IoStatus The status of the UDP receive
1624 @param Context The opaque parameter to the function.
1625
1626 **/
1627 VOID
1628 EFIAPI
1629 DnsOnPacketReceived (
1630 NET_BUF *Packet,
1631 UDP_END_POINT *EndPoint,
1632 EFI_STATUS IoStatus,
1633 VOID *Context
1634 )
1635 {
1636 DNS_INSTANCE *Instance;
1637
1638 UINT8 *RcvString;
1639
1640 BOOLEAN Completed;
1641
1642 Instance = (DNS_INSTANCE *) Context;
1643 NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE);
1644
1645 RcvString = NULL;
1646 Completed = FALSE;
1647
1648 if (EFI_ERROR (IoStatus)) {
1649 goto ON_EXIT;
1650 }
1651
1652 ASSERT (Packet != NULL);
1653
1654 RcvString = NetbufGetByte (Packet, 0, NULL);
1655 ASSERT (RcvString != NULL);
1656
1657 //
1658 // Parse Dns Response
1659 //
1660 ParseDnsResponse (Instance, RcvString, &Completed);
1661
1662 ON_EXIT:
1663
1664 if (Packet != NULL) {
1665 NetbufFree (Packet);
1666 }
1667
1668 if (!Completed) {
1669 UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);
1670 }
1671 }
1672
1673 /**
1674 Release the net buffer when packet is sent.
1675
1676 @param Packet The packets received.
1677 @param EndPoint The local/remote UDP access point
1678 @param IoStatus The status of the UDP receive
1679 @param Context The opaque parameter to the function.
1680
1681 **/
1682 VOID
1683 EFIAPI
1684 DnsOnPacketSent (
1685 NET_BUF *Packet,
1686 UDP_END_POINT *EndPoint,
1687 EFI_STATUS IoStatus,
1688 VOID *Context
1689 )
1690 {
1691 DNS_INSTANCE *Instance;
1692 LIST_ENTRY *Entry;
1693 NET_MAP_ITEM *Item;
1694 DNS4_TOKEN_ENTRY *Dns4TokenEntry;
1695 DNS6_TOKEN_ENTRY *Dns6TokenEntry;
1696
1697 Dns4TokenEntry = NULL;
1698 Dns6TokenEntry = NULL;
1699
1700 Instance = (DNS_INSTANCE *) Context;
1701 NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE);
1702
1703 if (Instance->Service->IpVersion == IP_VERSION_4) {
1704 NET_LIST_FOR_EACH (Entry, &Instance->Dns4TxTokens.Used) {
1705 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1706 if (Packet == (NET_BUF *)(Item->Value)) {
1707 Dns4TokenEntry = ((DNS4_TOKEN_ENTRY *)Item->Key);
1708 Dns4TokenEntry->PacketToLive = Dns4TokenEntry->Token->RetryInterval;
1709 break;
1710 }
1711 }
1712 } else {
1713 NET_LIST_FOR_EACH (Entry, &Instance->Dns6TxTokens.Used) {
1714 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1715 if (Packet == (NET_BUF *)(Item->Value)) {
1716 Dns6TokenEntry = ((DNS6_TOKEN_ENTRY *)Item->Key);
1717 Dns6TokenEntry->PacketToLive = Dns6TokenEntry->Token->RetryInterval;
1718 break;
1719 }
1720 }
1721 }
1722
1723 NetbufFree (Packet);
1724 }
1725
1726 /**
1727 Query request information.
1728
1729 @param Instance The DNS instance
1730 @param Packet The packet for querying request information.
1731
1732 @retval EFI_SUCCESS Query request information successfully.
1733 @retval Others Failed to query request information.
1734
1735 **/
1736 EFI_STATUS
1737 DoDnsQuery (
1738 IN DNS_INSTANCE *Instance,
1739 IN NET_BUF *Packet
1740 )
1741 {
1742 EFI_STATUS Status;
1743
1744 //
1745 // Ready to receive the DNS response.
1746 //
1747 if (Instance->UdpIo->RecvRequest == NULL) {
1748 Status = UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);
1749 if (EFI_ERROR (Status)) {
1750 return Status;
1751 }
1752 }
1753
1754 //
1755 // Transmit the DNS packet.
1756 //
1757 NET_GET_REF (Packet);
1758
1759 Status = UdpIoSendDatagram (Instance->UdpIo, Packet, NULL, NULL, DnsOnPacketSent, Instance);
1760
1761 return Status;
1762 }
1763
1764 /**
1765 Construct the Packet according query section.
1766
1767 @param Instance The DNS instance
1768 @param QueryName Queried Name
1769 @param Type Queried Type
1770 @param Class Queried Class
1771 @param Packet The packet for query
1772
1773 @retval EFI_SUCCESS The packet is constructed.
1774 @retval Others Failed to construct the Packet.
1775
1776 **/
1777 EFI_STATUS
1778 ConstructDNSQuery (
1779 IN DNS_INSTANCE *Instance,
1780 IN CHAR8 *QueryName,
1781 IN UINT16 Type,
1782 IN UINT16 Class,
1783 OUT NET_BUF **Packet
1784 )
1785 {
1786 NET_FRAGMENT Frag;
1787 DNS_HEADER *DnsHeader;
1788 DNS_QUERY_SECTION *DnsQuery;
1789
1790 Frag.Bulk = AllocatePool (DNS_DEFAULT_BLKSIZE * sizeof (UINT8));
1791 if (Frag.Bulk == NULL) {
1792 return EFI_OUT_OF_RESOURCES;
1793 }
1794
1795 //
1796 // Fill header
1797 //
1798 DnsHeader = (DNS_HEADER *) Frag.Bulk;
1799 DnsHeader->Identification = (UINT16)NET_RANDOM (NetRandomInitSeed());
1800 DnsHeader->Flags.Uint16 = 0x0000;
1801 DnsHeader->Flags.Bits.RD = 1;
1802 DnsHeader->Flags.Bits.OpCode = DNS_FLAGS_OPCODE_STANDARD;
1803 DnsHeader->Flags.Bits.QR = DNS_FLAGS_QR_QUERY;
1804 DnsHeader->QuestionsNum = 1;
1805 DnsHeader->AnswersNum = 0;
1806 DnsHeader->AuthorityNum = 0;
1807 DnsHeader->AditionalNum = 0;
1808
1809 DnsHeader->Identification = HTONS (DnsHeader->Identification);
1810 DnsHeader->Flags.Uint16 = HTONS (DnsHeader->Flags.Uint16);
1811 DnsHeader->QuestionsNum = HTONS (DnsHeader->QuestionsNum);
1812 DnsHeader->AnswersNum = HTONS (DnsHeader->AnswersNum);
1813 DnsHeader->AuthorityNum = HTONS (DnsHeader->AuthorityNum);
1814 DnsHeader->AditionalNum = HTONS (DnsHeader->AditionalNum);
1815
1816 Frag.Len = sizeof (*DnsHeader);
1817
1818 //
1819 // Fill Query name
1820 //
1821 CopyMem (Frag.Bulk + Frag.Len, QueryName, AsciiStrLen (QueryName));
1822 Frag.Len = (UINT32) (Frag.Len + AsciiStrLen (QueryName));
1823 *(Frag.Bulk + Frag.Len) = 0;
1824 Frag.Len ++;
1825
1826 //
1827 // Rest query section
1828 //
1829 DnsQuery = (DNS_QUERY_SECTION *) (Frag.Bulk + Frag.Len);
1830
1831 DnsQuery->Type = HTONS (Type);
1832 DnsQuery->Class = HTONS (Class);
1833
1834 Frag.Len += sizeof (*DnsQuery);
1835
1836 //
1837 // Wrap the Frag in a net buffer.
1838 //
1839 *Packet = NetbufFromExt (&Frag, 1, 0, 0, DnsDummyExtFree, NULL);
1840 if (*Packet == NULL) {
1841 FreePool (Frag.Bulk);
1842 return EFI_OUT_OF_RESOURCES;
1843 }
1844
1845 //
1846 // Store the UdpIo in ProtoData.
1847 //
1848 *((UINTN *) &((*Packet)->ProtoData[0])) = (UINTN) (Instance->UdpIo);
1849
1850 return EFI_SUCCESS;
1851 }
1852
1853 /**
1854 Retransmit the packet.
1855
1856 @param Instance The DNS instance
1857 @param Packet Retransmit the packet
1858
1859 @retval EFI_SUCCESS The packet is retransmitted.
1860 @retval Others Failed to retransmit.
1861
1862 **/
1863 EFI_STATUS
1864 DnsRetransmit (
1865 IN DNS_INSTANCE *Instance,
1866 IN NET_BUF *Packet
1867 )
1868 {
1869 EFI_STATUS Status;
1870
1871 UINT8 *Buffer;
1872
1873 ASSERT (Packet != NULL);
1874
1875 //
1876 // Set the requests to the listening port, other packets to the connected port
1877 //
1878 Buffer = NetbufGetByte (Packet, 0, NULL);
1879 ASSERT (Buffer != NULL);
1880
1881 NET_GET_REF (Packet);
1882
1883 Status = UdpIoSendDatagram (
1884 Instance->UdpIo,
1885 Packet,
1886 NULL,
1887 NULL,
1888 DnsOnPacketSent,
1889 Instance
1890 );
1891
1892 if (EFI_ERROR (Status)) {
1893 NET_PUT_REF (Packet);
1894 }
1895
1896 return Status;
1897 }
1898
1899 /**
1900 The timer ticking function for the DNS services.
1901
1902 @param Event The ticking event
1903 @param Context The DNS service instance
1904
1905 **/
1906 VOID
1907 EFIAPI
1908 DnsOnTimerRetransmit (
1909 IN EFI_EVENT Event,
1910 IN VOID *Context
1911 )
1912 {
1913 DNS_SERVICE *Service;
1914
1915 LIST_ENTRY *Entry;
1916 LIST_ENTRY *Next;
1917
1918 DNS_INSTANCE *Instance;
1919 LIST_ENTRY *EntryNetMap;
1920 NET_MAP_ITEM *ItemNetMap;
1921 DNS4_TOKEN_ENTRY *Dns4TokenEntry;
1922 DNS6_TOKEN_ENTRY *Dns6TokenEntry;
1923
1924 Dns4TokenEntry = NULL;
1925 Dns6TokenEntry = NULL;
1926
1927 Service = (DNS_SERVICE *) Context;
1928
1929
1930 if (Service->IpVersion == IP_VERSION_4) {
1931 //
1932 // Iterate through all the children of the DNS service instance. Time
1933 // out the packet. If maximum retries reached, clean the Token up.
1934 //
1935 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Service->Dns4ChildrenList) {
1936 Instance = NET_LIST_USER_STRUCT (Entry, DNS_INSTANCE, Link);
1937
1938 EntryNetMap = Instance->Dns4TxTokens.Used.ForwardLink;
1939 while (EntryNetMap != &Instance->Dns4TxTokens.Used) {
1940 ItemNetMap = NET_LIST_USER_STRUCT (EntryNetMap, NET_MAP_ITEM, Link);
1941 Dns4TokenEntry = (DNS4_TOKEN_ENTRY *)(ItemNetMap->Key);
1942 if (Dns4TokenEntry->PacketToLive == 0 || (--Dns4TokenEntry->PacketToLive > 0)) {
1943 EntryNetMap = EntryNetMap->ForwardLink;
1944 continue;
1945 }
1946
1947 //
1948 // Retransmit the packet if haven't reach the maxmium retry count,
1949 // otherwise exit the transfer.
1950 //
1951 if (++Dns4TokenEntry->Token->RetryCount < Instance->MaxRetry) {
1952 DnsRetransmit (Instance, (NET_BUF *)ItemNetMap->Value);
1953 EntryNetMap = EntryNetMap->ForwardLink;
1954 } else {
1955 //
1956 // Maximum retries reached, clean the Token up.
1957 //
1958 Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry);
1959 Dns4TokenEntry->Token->Status = EFI_TIMEOUT;
1960 gBS->SignalEvent (Dns4TokenEntry->Token->Event);
1961 DispatchDpc ();
1962
1963 //
1964 // Free the sending packet.
1965 //
1966 if (ItemNetMap->Value != NULL) {
1967 NetbufFree ((NET_BUF *)(ItemNetMap->Value));
1968 }
1969
1970 EntryNetMap = Instance->Dns4TxTokens.Used.ForwardLink;
1971 }
1972 }
1973 }
1974 }else {
1975 //
1976 // Iterate through all the children of the DNS service instance. Time
1977 // out the packet. If maximum retries reached, clean the Token up.
1978 //
1979 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Service->Dns6ChildrenList) {
1980 Instance = NET_LIST_USER_STRUCT (Entry, DNS_INSTANCE, Link);
1981
1982 EntryNetMap = Instance->Dns6TxTokens.Used.ForwardLink;
1983 while (EntryNetMap != &Instance->Dns6TxTokens.Used) {
1984 ItemNetMap = NET_LIST_USER_STRUCT (EntryNetMap, NET_MAP_ITEM, Link);
1985 Dns6TokenEntry = (DNS6_TOKEN_ENTRY *) (ItemNetMap->Key);
1986 if (Dns6TokenEntry->PacketToLive == 0 || (--Dns6TokenEntry->PacketToLive > 0)) {
1987 EntryNetMap = EntryNetMap->ForwardLink;
1988 continue;
1989 }
1990
1991 //
1992 // Retransmit the packet if haven't reach the maxmium retry count,
1993 // otherwise exit the transfer.
1994 //
1995 if (++Dns6TokenEntry->Token->RetryCount < Instance->MaxRetry) {
1996 DnsRetransmit (Instance, (NET_BUF *) ItemNetMap->Value);
1997 EntryNetMap = EntryNetMap->ForwardLink;
1998 } else {
1999 //
2000 // Maximum retries reached, clean the Token up.
2001 //
2002 Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry);
2003 Dns6TokenEntry->Token->Status = EFI_TIMEOUT;
2004 gBS->SignalEvent (Dns6TokenEntry->Token->Event);
2005 DispatchDpc ();
2006
2007 //
2008 // Free the sending packet.
2009 //
2010 if (ItemNetMap->Value != NULL) {
2011 NetbufFree ((NET_BUF *) (ItemNetMap->Value));
2012 }
2013
2014 EntryNetMap = Instance->Dns6TxTokens.Used.ForwardLink;
2015 }
2016 }
2017 }
2018 }
2019 }
2020
2021 /**
2022 The timer ticking function for the DNS driver.
2023
2024 @param Event The ticking event
2025 @param Context NULL
2026
2027 **/
2028 VOID
2029 EFIAPI
2030 DnsOnTimerUpdate (
2031 IN EFI_EVENT Event,
2032 IN VOID *Context
2033 )
2034 {
2035 LIST_ENTRY *Entry;
2036 LIST_ENTRY *Next;
2037 DNS4_CACHE *Item4;
2038 DNS6_CACHE *Item6;
2039
2040 Item4 = NULL;
2041 Item6 = NULL;
2042
2043 //
2044 // Iterate through all the DNS4 cache list.
2045 //
2046 NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) {
2047 Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
2048 Item4->DnsCache.Timeout--;
2049 }
2050
2051 Entry = mDriverData->Dns4CacheList.ForwardLink;
2052 while (Entry != &mDriverData->Dns4CacheList) {
2053 Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
2054 if (Item4->DnsCache.Timeout<=0) {
2055 RemoveEntryList (&Item4->AllCacheLink);
2056 Entry = mDriverData->Dns4CacheList.ForwardLink;
2057 } else {
2058 Entry = Entry->ForwardLink;
2059 }
2060 }
2061
2062 //
2063 // Iterate through all the DNS6 cache list.
2064 //
2065 NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6CacheList) {
2066 Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
2067 Item6->DnsCache.Timeout--;
2068 }
2069
2070 Entry = mDriverData->Dns6CacheList.ForwardLink;
2071 while (Entry != &mDriverData->Dns6CacheList) {
2072 Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
2073 if (Item6->DnsCache.Timeout<=0) {
2074 RemoveEntryList (&Item6->AllCacheLink);
2075 Entry = mDriverData->Dns6CacheList.ForwardLink;
2076 } else {
2077 Entry = Entry->ForwardLink;
2078 }
2079 }
2080 }
2081