]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/DnsDxe/DnsImpl.c
NetworkPkg/DnsDxe: Update RetryCount/RetryInterval to comply with UEFI spec.
[mirror_edk2.git] / NetworkPkg / DnsDxe / DnsImpl.c
1 /** @file
2 DnsDxe support functions implementation.
3
4 Copyright (c) 2016 - 2017, 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.IsStarted || Ip6Mode.IsConfigured) {
647 Udp->Configure (Udp, NULL);
648 if (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS) {
649 return TRUE;
650 }
651 }
652 }
653 }
654
655 return FALSE;
656 }
657
658 /**
659 Configure the UDP.
660
661 @param Instance The DNS session
662 @param UdpIo The UDP_IO instance
663
664 @retval EFI_SUCCESS The UDP is successfully configured for the
665 session.
666
667 **/
668 EFI_STATUS
669 Dns4ConfigUdp (
670 IN DNS_INSTANCE *Instance,
671 IN UDP_IO *UdpIo
672 )
673 {
674 EFI_DNS4_CONFIG_DATA *Config;
675 EFI_UDP4_CONFIG_DATA UdpConfig;
676 EFI_STATUS Status;
677
678 Config = &Instance->Dns4CfgData;
679
680 UdpConfig.AcceptBroadcast = FALSE;
681 UdpConfig.AcceptPromiscuous = FALSE;
682 UdpConfig.AcceptAnyPort = FALSE;
683 UdpConfig.AllowDuplicatePort = FALSE;
684 UdpConfig.TypeOfService = 0;
685 UdpConfig.TimeToLive = 128;
686 UdpConfig.DoNotFragment = FALSE;
687 UdpConfig.ReceiveTimeout = 0;
688 UdpConfig.TransmitTimeout = 0;
689 UdpConfig.UseDefaultAddress = Config->UseDefaultSetting;
690 UdpConfig.SubnetMask = Config->SubnetMask;
691 UdpConfig.StationPort = Config->LocalPort;
692 UdpConfig.RemotePort = DNS_SERVER_PORT;
693
694 CopyMem (&UdpConfig.StationAddress, &Config->StationIp, sizeof (EFI_IPv4_ADDRESS));
695 CopyMem (&UdpConfig.RemoteAddress, &Instance->SessionDnsServer.v4, sizeof (EFI_IPv4_ADDRESS));
696
697 Status = UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfig);
698
699 if ((Status == EFI_NO_MAPPING) && Dns4GetMapping (Instance, UdpIo, &UdpConfig)) {
700 return EFI_SUCCESS;
701 }
702
703 return Status;
704 }
705
706 /**
707 Configure the UDP.
708
709 @param Instance The DNS session
710 @param UdpIo The UDP_IO instance
711
712 @retval EFI_SUCCESS The UDP is successfully configured for the
713 session.
714
715 **/
716 EFI_STATUS
717 Dns6ConfigUdp (
718 IN DNS_INSTANCE *Instance,
719 IN UDP_IO *UdpIo
720 )
721 {
722 EFI_DNS6_CONFIG_DATA *Config;
723 EFI_UDP6_CONFIG_DATA UdpConfig;
724 EFI_STATUS Status;
725
726 Config = &Instance->Dns6CfgData;
727
728 UdpConfig.AcceptPromiscuous = FALSE;
729 UdpConfig.AcceptAnyPort = FALSE;
730 UdpConfig.AllowDuplicatePort = FALSE;
731 UdpConfig.TrafficClass = 0;
732 UdpConfig.HopLimit = 128;
733 UdpConfig.ReceiveTimeout = 0;
734 UdpConfig.TransmitTimeout = 0;
735 UdpConfig.StationPort = Config->LocalPort;
736 UdpConfig.RemotePort = DNS_SERVER_PORT;
737 CopyMem (&UdpConfig.StationAddress, &Config->StationIp, sizeof (EFI_IPv6_ADDRESS));
738 CopyMem (&UdpConfig.RemoteAddress, &Instance->SessionDnsServer.v6, sizeof (EFI_IPv6_ADDRESS));
739
740 Status = UdpIo->Protocol.Udp6->Configure (UdpIo->Protocol.Udp6, &UdpConfig);
741
742 if ((Status == EFI_NO_MAPPING) && Dns6GetMapping (Instance, UdpIo, &UdpConfig)) {
743 return EFI_SUCCESS;
744 }
745
746 return Status;
747 }
748
749 /**
750 Update Dns4 cache to shared list of caches of all DNSv4 instances.
751
752 @param Dns4CacheList All Dns4 cache list.
753 @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache.
754 If TRUE, this function will delete matching DNS Cache entry.
755 @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
756 If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
757 @param DnsCacheEntry Entry Pointer to DNS Cache entry.
758
759 @retval EFI_SUCCESS Update Dns4 cache successfully.
760 @retval Others Failed to update Dns4 cache.
761
762 **/
763 EFI_STATUS
764 EFIAPI
765 UpdateDns4Cache (
766 IN LIST_ENTRY *Dns4CacheList,
767 IN BOOLEAN DeleteFlag,
768 IN BOOLEAN Override,
769 IN EFI_DNS4_CACHE_ENTRY DnsCacheEntry
770 )
771 {
772 DNS4_CACHE *NewDnsCache;
773 DNS4_CACHE *Item;
774 LIST_ENTRY *Entry;
775 LIST_ENTRY *Next;
776
777 NewDnsCache = NULL;
778 Item = NULL;
779
780 //
781 // Search the database for the matching EFI_DNS_CACHE_ENTRY
782 //
783 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns4CacheList) {
784 Item = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
785 if (StrCmp (DnsCacheEntry.HostName, Item->DnsCache.HostName) == 0 && \
786 CompareMem (DnsCacheEntry.IpAddress, Item->DnsCache.IpAddress, sizeof (EFI_IPv4_ADDRESS)) == 0) {
787 //
788 // This is the Dns cache entry
789 //
790 if (DeleteFlag) {
791 //
792 // Delete matching DNS Cache entry
793 //
794 RemoveEntryList (&Item->AllCacheLink);
795
796 return EFI_SUCCESS;
797 } else if (Override) {
798 //
799 // Update this one
800 //
801 Item->DnsCache.Timeout = DnsCacheEntry.Timeout;
802
803 return EFI_SUCCESS;
804 }else {
805 return EFI_ACCESS_DENIED;
806 }
807 }
808 }
809
810 //
811 // Add new one
812 //
813 NewDnsCache = AllocatePool (sizeof (DNS4_CACHE));
814 if (NewDnsCache == NULL) {
815 return EFI_OUT_OF_RESOURCES;
816 }
817
818 InitializeListHead (&NewDnsCache->AllCacheLink);
819
820 NewDnsCache->DnsCache.HostName = AllocatePool (StrSize (DnsCacheEntry.HostName));
821 if (NewDnsCache->DnsCache.HostName == NULL) {
822 return EFI_OUT_OF_RESOURCES;
823 }
824
825 CopyMem (NewDnsCache->DnsCache.HostName, DnsCacheEntry.HostName, StrSize (DnsCacheEntry.HostName));
826
827 NewDnsCache->DnsCache.IpAddress = AllocatePool (sizeof (EFI_IPv4_ADDRESS));
828 if (NewDnsCache->DnsCache.IpAddress == NULL) {
829 return EFI_OUT_OF_RESOURCES;
830 }
831
832 CopyMem (NewDnsCache->DnsCache.IpAddress, DnsCacheEntry.IpAddress, sizeof (EFI_IPv4_ADDRESS));
833
834 NewDnsCache->DnsCache.Timeout = DnsCacheEntry.Timeout;
835
836 InsertTailList (Dns4CacheList, &NewDnsCache->AllCacheLink);
837
838 return EFI_SUCCESS;
839 }
840
841 /**
842 Update Dns6 cache to shared list of caches of all DNSv6 instances.
843
844 @param Dns6CacheList All Dns6 cache list.
845 @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache.
846 If TRUE, this function will delete matching DNS Cache entry.
847 @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
848 If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
849 @param DnsCacheEntry Entry Pointer to DNS Cache entry.
850
851 @retval EFI_SUCCESS Update Dns6 cache successfully.
852 @retval Others Failed to update Dns6 cache.
853 **/
854 EFI_STATUS
855 EFIAPI
856 UpdateDns6Cache (
857 IN LIST_ENTRY *Dns6CacheList,
858 IN BOOLEAN DeleteFlag,
859 IN BOOLEAN Override,
860 IN EFI_DNS6_CACHE_ENTRY DnsCacheEntry
861 )
862 {
863 DNS6_CACHE *NewDnsCache;
864 DNS6_CACHE *Item;
865 LIST_ENTRY *Entry;
866 LIST_ENTRY *Next;
867
868 NewDnsCache = NULL;
869 Item = NULL;
870
871 //
872 // Search the database for the matching EFI_DNS_CACHE_ENTRY
873 //
874 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns6CacheList) {
875 Item = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
876 if (StrCmp (DnsCacheEntry.HostName, Item->DnsCache.HostName) == 0 && \
877 CompareMem (DnsCacheEntry.IpAddress, Item->DnsCache.IpAddress, sizeof (EFI_IPv6_ADDRESS)) == 0) {
878 //
879 // This is the Dns cache entry
880 //
881 if (DeleteFlag) {
882 //
883 // Delete matching DNS Cache entry
884 //
885 RemoveEntryList (&Item->AllCacheLink);
886
887 return EFI_SUCCESS;
888 } else if (Override) {
889 //
890 // Update this one
891 //
892 Item->DnsCache.Timeout = DnsCacheEntry.Timeout;
893
894 return EFI_SUCCESS;
895 }else {
896 return EFI_ACCESS_DENIED;
897 }
898 }
899 }
900
901 //
902 // Add new one
903 //
904 NewDnsCache = AllocatePool (sizeof (DNS6_CACHE));
905 if (NewDnsCache == NULL) {
906 return EFI_OUT_OF_RESOURCES;
907 }
908
909 InitializeListHead (&NewDnsCache->AllCacheLink);
910
911 NewDnsCache->DnsCache.HostName = AllocatePool (StrSize (DnsCacheEntry.HostName));
912 if (NewDnsCache->DnsCache.HostName == NULL) {
913 return EFI_OUT_OF_RESOURCES;
914 }
915
916 CopyMem (NewDnsCache->DnsCache.HostName, DnsCacheEntry.HostName, StrSize (DnsCacheEntry.HostName));
917
918 NewDnsCache->DnsCache.IpAddress = AllocatePool (sizeof (EFI_IPv6_ADDRESS));
919 if (NewDnsCache->DnsCache.IpAddress == NULL) {
920 return EFI_OUT_OF_RESOURCES;
921 }
922
923 CopyMem (NewDnsCache->DnsCache.IpAddress, DnsCacheEntry.IpAddress, sizeof (EFI_IPv6_ADDRESS));
924
925 NewDnsCache->DnsCache.Timeout = DnsCacheEntry.Timeout;
926
927 InsertTailList (Dns6CacheList, &NewDnsCache->AllCacheLink);
928
929 return EFI_SUCCESS;
930 }
931
932 /**
933 Add Dns4 ServerIp to common list of addresses of all configured DNSv4 server.
934
935 @param Dns4ServerList Common list of addresses of all configured DNSv4 server.
936 @param ServerIp DNS server Ip.
937
938 @retval EFI_SUCCESS Add Dns4 ServerIp to common list successfully.
939 @retval Others Failed to add Dns4 ServerIp to common list.
940
941 **/
942 EFI_STATUS
943 EFIAPI
944 AddDns4ServerIp (
945 IN LIST_ENTRY *Dns4ServerList,
946 IN EFI_IPv4_ADDRESS ServerIp
947 )
948 {
949 DNS4_SERVER_IP *NewServerIp;
950 DNS4_SERVER_IP *Item;
951 LIST_ENTRY *Entry;
952 LIST_ENTRY *Next;
953
954 NewServerIp = NULL;
955 Item = NULL;
956
957 //
958 // Search the database for the matching ServerIp
959 //
960 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns4ServerList) {
961 Item = NET_LIST_USER_STRUCT (Entry, DNS4_SERVER_IP, AllServerLink);
962 if (CompareMem (&Item->Dns4ServerIp, &ServerIp, sizeof (EFI_IPv4_ADDRESS)) == 0) {
963 //
964 // Already done.
965 //
966 return EFI_SUCCESS;
967 }
968 }
969
970 //
971 // Add new one
972 //
973 NewServerIp = AllocatePool (sizeof (DNS4_SERVER_IP));
974 if (NewServerIp == NULL) {
975 return EFI_OUT_OF_RESOURCES;
976 }
977
978 InitializeListHead (&NewServerIp->AllServerLink);
979
980 CopyMem (&NewServerIp->Dns4ServerIp, &ServerIp, sizeof (EFI_IPv4_ADDRESS));
981
982 InsertTailList (Dns4ServerList, &NewServerIp->AllServerLink);
983
984 return EFI_SUCCESS;
985 }
986
987 /**
988 Add Dns6 ServerIp to common list of addresses of all configured DNSv6 server.
989
990 @param Dns6ServerList Common list of addresses of all configured DNSv6 server.
991 @param ServerIp DNS server Ip.
992
993 @retval EFI_SUCCESS Add Dns6 ServerIp to common list successfully.
994 @retval Others Failed to add Dns6 ServerIp to common list.
995
996 **/
997 EFI_STATUS
998 EFIAPI
999 AddDns6ServerIp (
1000 IN LIST_ENTRY *Dns6ServerList,
1001 IN EFI_IPv6_ADDRESS ServerIp
1002 )
1003 {
1004 DNS6_SERVER_IP *NewServerIp;
1005 DNS6_SERVER_IP *Item;
1006 LIST_ENTRY *Entry;
1007 LIST_ENTRY *Next;
1008
1009 NewServerIp = NULL;
1010 Item = NULL;
1011
1012 //
1013 // Search the database for the matching ServerIp
1014 //
1015 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns6ServerList) {
1016 Item = NET_LIST_USER_STRUCT (Entry, DNS6_SERVER_IP, AllServerLink);
1017 if (CompareMem (&Item->Dns6ServerIp, &ServerIp, sizeof (EFI_IPv6_ADDRESS)) == 0) {
1018 //
1019 // Already done.
1020 //
1021 return EFI_SUCCESS;
1022 }
1023 }
1024
1025 //
1026 // Add new one
1027 //
1028 NewServerIp = AllocatePool (sizeof (DNS6_SERVER_IP));
1029 if (NewServerIp == NULL) {
1030 return EFI_OUT_OF_RESOURCES;
1031 }
1032
1033 InitializeListHead (&NewServerIp->AllServerLink);
1034
1035 CopyMem (&NewServerIp->Dns6ServerIp, &ServerIp, sizeof (EFI_IPv6_ADDRESS));
1036
1037 InsertTailList (Dns6ServerList, &NewServerIp->AllServerLink);
1038
1039 return EFI_SUCCESS;
1040 }
1041
1042 /**
1043 Find out whether the response is valid or invalid.
1044
1045 @param TokensMap All DNS transmittal Tokens entry.
1046 @param Identification Identification for queried packet.
1047 @param Type Type for queried packet.
1048 @param Class Class for queried packet.
1049 @param Item Return corresponding Token entry.
1050
1051 @retval TRUE The response is valid.
1052 @retval FALSE The response is invalid.
1053
1054 **/
1055 BOOLEAN
1056 IsValidDnsResponse (
1057 IN NET_MAP *TokensMap,
1058 IN UINT16 Identification,
1059 IN UINT16 Type,
1060 IN UINT16 Class,
1061 OUT NET_MAP_ITEM **Item
1062 )
1063 {
1064 LIST_ENTRY *Entry;
1065
1066 NET_BUF *Packet;
1067 UINT8 *TxString;
1068 DNS_HEADER *DnsHeader;
1069 CHAR8 *QueryName;
1070 DNS_QUERY_SECTION *QuerySection;
1071
1072 NET_LIST_FOR_EACH (Entry, &TokensMap->Used) {
1073 *Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1074 Packet = (NET_BUF *) ((*Item)->Value);
1075 if (Packet == NULL){
1076
1077 continue;
1078 } else {
1079 TxString = NetbufGetByte (Packet, 0, NULL);
1080 ASSERT (TxString != NULL);
1081 DnsHeader = (DNS_HEADER *) TxString;
1082 QueryName = (CHAR8 *) (TxString + sizeof (*DnsHeader));
1083 QuerySection = (DNS_QUERY_SECTION *) (QueryName + AsciiStrLen (QueryName) + 1);
1084
1085 if (NTOHS (DnsHeader->Identification) == Identification &&
1086 NTOHS (QuerySection->Type) == Type &&
1087 NTOHS (QuerySection->Class) == Class) {
1088 return TRUE;
1089 }
1090 }
1091 }
1092
1093 *Item = NULL;
1094
1095 return FALSE;
1096 }
1097
1098 /**
1099 Parse Dns Response.
1100
1101 @param Instance The DNS instance
1102 @param RxString Received buffer.
1103 @param Completed Flag to indicate that Dns response is valid.
1104
1105 @retval EFI_SUCCESS Parse Dns Response successfully.
1106 @retval Others Failed to parse Dns Response.
1107
1108 **/
1109 EFI_STATUS
1110 ParseDnsResponse (
1111 IN OUT DNS_INSTANCE *Instance,
1112 IN UINT8 *RxString,
1113 OUT BOOLEAN *Completed
1114 )
1115 {
1116 DNS_HEADER *DnsHeader;
1117
1118 CHAR8 *QueryName;
1119 DNS_QUERY_SECTION *QuerySection;
1120
1121 CHAR8 *AnswerName;
1122 DNS_ANSWER_SECTION *AnswerSection;
1123 UINT8 *AnswerData;
1124
1125 NET_MAP_ITEM *Item;
1126 DNS4_TOKEN_ENTRY *Dns4TokenEntry;
1127 DNS6_TOKEN_ENTRY *Dns6TokenEntry;
1128
1129 UINT32 IpCount;
1130 UINT32 RRCount;
1131 UINT32 AnswerSectionNum;
1132 UINT32 CNameTtl;
1133
1134 EFI_IPv4_ADDRESS *HostAddr4;
1135 EFI_IPv6_ADDRESS *HostAddr6;
1136
1137 EFI_DNS4_CACHE_ENTRY *Dns4CacheEntry;
1138 EFI_DNS6_CACHE_ENTRY *Dns6CacheEntry;
1139
1140 DNS_RESOURCE_RECORD *Dns4RR;
1141 DNS6_RESOURCE_RECORD *Dns6RR;
1142
1143 EFI_STATUS Status;
1144
1145 EFI_TPL OldTpl;
1146
1147 Item = NULL;
1148 Dns4TokenEntry = NULL;
1149 Dns6TokenEntry = NULL;
1150
1151 IpCount = 0;
1152 RRCount = 0;
1153 AnswerSectionNum = 0;
1154 CNameTtl = 0;
1155
1156 HostAddr4 = NULL;
1157 HostAddr6 = NULL;
1158
1159 Dns4CacheEntry = NULL;
1160 Dns6CacheEntry = NULL;
1161
1162 Dns4RR = NULL;
1163 Dns6RR = NULL;
1164
1165 *Completed = TRUE;
1166 Status = EFI_SUCCESS;
1167
1168 //
1169 // Get header
1170 //
1171 DnsHeader = (DNS_HEADER *) RxString;
1172
1173 DnsHeader->Identification = NTOHS (DnsHeader->Identification);
1174 DnsHeader->Flags.Uint16 = NTOHS (DnsHeader->Flags.Uint16);
1175 DnsHeader->QuestionsNum = NTOHS (DnsHeader->QuestionsNum);
1176 DnsHeader->AnswersNum = NTOHS (DnsHeader->AnswersNum);
1177 DnsHeader->AuthorityNum = NTOHS (DnsHeader->AuthorityNum);
1178 DnsHeader->AditionalNum = NTOHS (DnsHeader->AditionalNum);
1179
1180 //
1181 // Get Query name
1182 //
1183 QueryName = (CHAR8 *) (RxString + sizeof (*DnsHeader));
1184
1185 //
1186 // Get query section
1187 //
1188 QuerySection = (DNS_QUERY_SECTION *) (QueryName + AsciiStrLen (QueryName) + 1);
1189 QuerySection->Type = NTOHS (QuerySection->Type);
1190 QuerySection->Class = NTOHS (QuerySection->Class);
1191
1192 //
1193 // Get Answer name
1194 //
1195 AnswerName = (CHAR8 *) QuerySection + sizeof (*QuerySection);
1196
1197 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1198
1199 //
1200 // Check DnsResponse Validity, if so, also get a valid NET_MAP_ITEM.
1201 //
1202 if (Instance->Service->IpVersion == IP_VERSION_4) {
1203 if (!IsValidDnsResponse (
1204 &Instance->Dns4TxTokens,
1205 DnsHeader->Identification,
1206 QuerySection->Type,
1207 QuerySection->Class,
1208 &Item
1209 )) {
1210 *Completed = FALSE;
1211 Status = EFI_ABORTED;
1212 goto ON_EXIT;
1213 }
1214 ASSERT (Item != NULL);
1215 Dns4TokenEntry = (DNS4_TOKEN_ENTRY *) (Item->Key);
1216 } else {
1217 if (!IsValidDnsResponse (
1218 &Instance->Dns6TxTokens,
1219 DnsHeader->Identification,
1220 QuerySection->Type,
1221 QuerySection->Class,
1222 &Item
1223 )) {
1224 *Completed = FALSE;
1225 Status = EFI_ABORTED;
1226 goto ON_EXIT;
1227 }
1228 ASSERT (Item != NULL);
1229 Dns6TokenEntry = (DNS6_TOKEN_ENTRY *) (Item->Key);
1230 }
1231
1232 //
1233 // Continue Check Some Errors.
1234 //
1235 if (DnsHeader->Flags.Bits.RCode != DNS_FLAGS_RCODE_NO_ERROR || DnsHeader->AnswersNum < 1 || \
1236 DnsHeader->Flags.Bits.QR != DNS_FLAGS_QR_RESPONSE) {
1237 //
1238 // The domain name referenced in the query does not exist.
1239 //
1240 if (DnsHeader->Flags.Bits.RCode == DNS_FLAGS_RCODE_NAME_ERROR) {
1241 Status = EFI_NOT_FOUND;
1242 } else {
1243 Status = EFI_DEVICE_ERROR;
1244 }
1245
1246 goto ON_COMPLETE;
1247 }
1248
1249 //
1250 // Do some buffer allocations.
1251 //
1252 if (Instance->Service->IpVersion == IP_VERSION_4) {
1253 ASSERT (Dns4TokenEntry != NULL);
1254
1255 if (Dns4TokenEntry->GeneralLookUp) {
1256 //
1257 // It's the GeneralLookUp querying.
1258 //
1259 Dns4TokenEntry->Token->RspData.GLookupData = AllocatePool (sizeof (DNS_RESOURCE_RECORD));
1260 if (Dns4TokenEntry->Token->RspData.GLookupData == NULL) {
1261 Status = EFI_OUT_OF_RESOURCES;
1262 goto ON_EXIT;
1263 }
1264 Dns4TokenEntry->Token->RspData.GLookupData->RRList = AllocatePool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD));
1265 if (Dns4TokenEntry->Token->RspData.GLookupData->RRList == NULL) {
1266 Status = EFI_OUT_OF_RESOURCES;
1267 goto ON_EXIT;
1268 }
1269 } else {
1270 //
1271 // It's not the GeneralLookUp querying. Check the Query type.
1272 //
1273 if (QuerySection->Type == DNS_TYPE_A) {
1274 Dns4TokenEntry->Token->RspData.H2AData = AllocatePool (sizeof (DNS_HOST_TO_ADDR_DATA));
1275 if (Dns4TokenEntry->Token->RspData.H2AData == NULL) {
1276 Status = EFI_OUT_OF_RESOURCES;
1277 goto ON_EXIT;
1278 }
1279 Dns4TokenEntry->Token->RspData.H2AData->IpList = AllocatePool (DnsHeader->AnswersNum * sizeof (EFI_IPv4_ADDRESS));
1280 if (Dns4TokenEntry->Token->RspData.H2AData->IpList == NULL) {
1281 Status = EFI_OUT_OF_RESOURCES;
1282 goto ON_EXIT;
1283 }
1284 } else {
1285 Status = EFI_UNSUPPORTED;
1286 goto ON_EXIT;
1287 }
1288 }
1289 } else {
1290 ASSERT (Dns6TokenEntry != NULL);
1291
1292 if (Dns6TokenEntry->GeneralLookUp) {
1293 //
1294 // It's the GeneralLookUp querying.
1295 //
1296 Dns6TokenEntry->Token->RspData.GLookupData = AllocatePool (sizeof (DNS_RESOURCE_RECORD));
1297 if (Dns6TokenEntry->Token->RspData.GLookupData == NULL) {
1298 Status = EFI_OUT_OF_RESOURCES;
1299 goto ON_EXIT;
1300 }
1301 Dns6TokenEntry->Token->RspData.GLookupData->RRList = AllocatePool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD));
1302 if (Dns6TokenEntry->Token->RspData.GLookupData->RRList == NULL) {
1303 Status = EFI_OUT_OF_RESOURCES;
1304 goto ON_EXIT;
1305 }
1306 } else {
1307 //
1308 // It's not the GeneralLookUp querying. Check the Query type.
1309 //
1310 if (QuerySection->Type == DNS_TYPE_AAAA) {
1311 Dns6TokenEntry->Token->RspData.H2AData = AllocatePool (sizeof (DNS6_HOST_TO_ADDR_DATA));
1312 if (Dns6TokenEntry->Token->RspData.H2AData == NULL) {
1313 Status = EFI_OUT_OF_RESOURCES;
1314 goto ON_EXIT;
1315 }
1316 Dns6TokenEntry->Token->RspData.H2AData->IpList = AllocatePool (DnsHeader->AnswersNum * sizeof (EFI_IPv6_ADDRESS));
1317 if (Dns6TokenEntry->Token->RspData.H2AData->IpList == NULL) {
1318 Status = EFI_OUT_OF_RESOURCES;
1319 goto ON_EXIT;
1320 }
1321 } else {
1322 Status = EFI_UNSUPPORTED;
1323 goto ON_EXIT;
1324 }
1325 }
1326 }
1327
1328 Status = EFI_NOT_FOUND;
1329
1330 //
1331 // Processing AnswerSection.
1332 //
1333 while (AnswerSectionNum < DnsHeader->AnswersNum) {
1334 //
1335 // Answer name should be PTR, else EFI_UNSUPPORTED returned.
1336 //
1337 if ((*(UINT8 *) AnswerName & 0xC0) != 0xC0) {
1338 Status = EFI_UNSUPPORTED;
1339 goto ON_EXIT;
1340 }
1341
1342 //
1343 // Get Answer section.
1344 //
1345 AnswerSection = (DNS_ANSWER_SECTION *) (AnswerName + sizeof (UINT16));
1346 AnswerSection->Type = NTOHS (AnswerSection->Type);
1347 AnswerSection->Class = NTOHS (AnswerSection->Class);
1348 AnswerSection->Ttl = NTOHL (AnswerSection->Ttl);
1349 AnswerSection->DataLength = NTOHS (AnswerSection->DataLength);
1350
1351 //
1352 // Check whether it's the GeneralLookUp querying.
1353 //
1354 if (Instance->Service->IpVersion == IP_VERSION_4 && Dns4TokenEntry->GeneralLookUp) {
1355 Dns4RR = Dns4TokenEntry->Token->RspData.GLookupData->RRList;
1356 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
1357
1358 //
1359 // Fill the ResourceRecord.
1360 //
1361 Dns4RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1);
1362 if (Dns4RR[RRCount].QName == NULL) {
1363 Status = EFI_OUT_OF_RESOURCES;
1364 goto ON_EXIT;
1365 }
1366 CopyMem (Dns4RR[RRCount].QName, QueryName, AsciiStrLen (QueryName));
1367 Dns4RR[RRCount].QType = AnswerSection->Type;
1368 Dns4RR[RRCount].QClass = AnswerSection->Class;
1369 Dns4RR[RRCount].TTL = AnswerSection->Ttl;
1370 Dns4RR[RRCount].DataLength = AnswerSection->DataLength;
1371 Dns4RR[RRCount].RData = AllocateZeroPool (Dns4RR[RRCount].DataLength);
1372 if (Dns4RR[RRCount].RData == NULL) {
1373 Status = EFI_OUT_OF_RESOURCES;
1374 goto ON_EXIT;
1375 }
1376 CopyMem (Dns4RR[RRCount].RData, AnswerData, Dns4RR[RRCount].DataLength);
1377
1378 RRCount ++;
1379 Status = EFI_SUCCESS;
1380 } else if (Instance->Service->IpVersion == IP_VERSION_6 && Dns6TokenEntry->GeneralLookUp) {
1381 Dns6RR = Dns6TokenEntry->Token->RspData.GLookupData->RRList;
1382 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
1383
1384 //
1385 // Fill the ResourceRecord.
1386 //
1387 Dns6RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1);
1388 if (Dns6RR[RRCount].QName == NULL) {
1389 Status = EFI_OUT_OF_RESOURCES;
1390 goto ON_EXIT;
1391 }
1392 CopyMem (Dns6RR[RRCount].QName, QueryName, AsciiStrLen (QueryName));
1393 Dns6RR[RRCount].QType = AnswerSection->Type;
1394 Dns6RR[RRCount].QClass = AnswerSection->Class;
1395 Dns6RR[RRCount].TTL = AnswerSection->Ttl;
1396 Dns6RR[RRCount].DataLength = AnswerSection->DataLength;
1397 Dns6RR[RRCount].RData = AllocateZeroPool (Dns6RR[RRCount].DataLength);
1398 if (Dns6RR[RRCount].RData == NULL) {
1399 Status = EFI_OUT_OF_RESOURCES;
1400 goto ON_EXIT;
1401 }
1402 CopyMem (Dns6RR[RRCount].RData, AnswerData, Dns6RR[RRCount].DataLength);
1403
1404 RRCount ++;
1405 Status = EFI_SUCCESS;
1406 } else {
1407 //
1408 // It's not the GeneralLookUp querying.
1409 // Check the Query type, parse the response packet.
1410 //
1411 switch (AnswerSection->Type) {
1412 case DNS_TYPE_A:
1413 //
1414 // This is address entry, get Data.
1415 //
1416 ASSERT (Dns4TokenEntry != NULL);
1417
1418 if (AnswerSection->DataLength != 4) {
1419 Status = EFI_ABORTED;
1420 goto ON_EXIT;
1421 }
1422
1423 HostAddr4 = Dns4TokenEntry->Token->RspData.H2AData->IpList;
1424 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
1425 CopyMem (&HostAddr4[IpCount], AnswerData, sizeof (EFI_IPv4_ADDRESS));
1426
1427 //
1428 // Allocate new CacheEntry pool to update DNS cache dynamically.
1429 //
1430 Dns4CacheEntry = AllocateZeroPool (sizeof (EFI_DNS4_CACHE_ENTRY));
1431 if (Dns4CacheEntry == NULL) {
1432 Status = EFI_OUT_OF_RESOURCES;
1433 goto ON_EXIT;
1434 }
1435 Dns4CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1));
1436 if (Dns4CacheEntry->HostName == NULL) {
1437 Status = EFI_OUT_OF_RESOURCES;
1438 goto ON_EXIT;
1439 }
1440 CopyMem (Dns4CacheEntry->HostName, Dns4TokenEntry->QueryHostName, 2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1));
1441 Dns4CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv4_ADDRESS));
1442 if (Dns4CacheEntry->IpAddress == NULL) {
1443 Status = EFI_OUT_OF_RESOURCES;
1444 goto ON_EXIT;
1445 }
1446 CopyMem (Dns4CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv4_ADDRESS));
1447
1448 if (CNameTtl != 0 && AnswerSection->Ttl != 0) {
1449 Dns4CacheEntry->Timeout = MIN (CNameTtl, AnswerSection->Ttl);
1450 } else {
1451 Dns4CacheEntry->Timeout = MAX (CNameTtl, AnswerSection->Ttl);
1452 }
1453
1454 UpdateDns4Cache (&mDriverData->Dns4CacheList, FALSE, TRUE, *Dns4CacheEntry);
1455
1456 //
1457 // Free allocated CacheEntry pool.
1458 //
1459 FreePool (Dns4CacheEntry->HostName);
1460 Dns4CacheEntry->HostName = NULL;
1461
1462 FreePool (Dns4CacheEntry->IpAddress);
1463 Dns4CacheEntry->IpAddress = NULL;
1464
1465 FreePool (Dns4CacheEntry);
1466 Dns4CacheEntry = NULL;
1467
1468 IpCount ++;
1469 Status = EFI_SUCCESS;
1470 break;
1471 case DNS_TYPE_AAAA:
1472 //
1473 // This is address entry, get Data.
1474 //
1475 ASSERT (Dns6TokenEntry != NULL);
1476
1477 if (AnswerSection->DataLength != 16) {
1478 Status = EFI_ABORTED;
1479 goto ON_EXIT;
1480 }
1481
1482 HostAddr6 = Dns6TokenEntry->Token->RspData.H2AData->IpList;
1483 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
1484 CopyMem (&HostAddr6[IpCount], AnswerData, sizeof (EFI_IPv6_ADDRESS));
1485
1486 //
1487 // Allocate new CacheEntry pool to update DNS cache dynamically.
1488 //
1489 Dns6CacheEntry = AllocateZeroPool (sizeof (EFI_DNS6_CACHE_ENTRY));
1490 if (Dns6CacheEntry == NULL) {
1491 Status = EFI_OUT_OF_RESOURCES;
1492 goto ON_EXIT;
1493 }
1494 Dns6CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1));
1495 if (Dns6CacheEntry->HostName == NULL) {
1496 Status = EFI_OUT_OF_RESOURCES;
1497 goto ON_EXIT;
1498 }
1499 CopyMem (Dns6CacheEntry->HostName, Dns6TokenEntry->QueryHostName, 2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1));
1500 Dns6CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS));
1501 if (Dns6CacheEntry->IpAddress == NULL) {
1502 Status = EFI_OUT_OF_RESOURCES;
1503 goto ON_EXIT;
1504 }
1505 CopyMem (Dns6CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv6_ADDRESS));
1506
1507 if (CNameTtl != 0 && AnswerSection->Ttl != 0) {
1508 Dns6CacheEntry->Timeout = MIN (CNameTtl, AnswerSection->Ttl);
1509 } else {
1510 Dns6CacheEntry->Timeout = MAX (CNameTtl, AnswerSection->Ttl);
1511 }
1512
1513 UpdateDns6Cache (&mDriverData->Dns6CacheList, FALSE, TRUE, *Dns6CacheEntry);
1514
1515 //
1516 // Free allocated CacheEntry pool.
1517 //
1518 FreePool (Dns6CacheEntry->HostName);
1519 Dns6CacheEntry->HostName = NULL;
1520
1521 FreePool (Dns6CacheEntry->IpAddress);
1522 Dns6CacheEntry->IpAddress = NULL;
1523
1524 FreePool (Dns6CacheEntry);
1525 Dns6CacheEntry = NULL;
1526
1527 IpCount ++;
1528 Status = EFI_SUCCESS;
1529 break;
1530 case DNS_TYPE_CNAME:
1531 //
1532 // According RFC 1034 - 3.6.2, if the query name is an alias, the name server will include the CNAME
1533 // record in the response and restart the query at the domain name specified in the data field of the
1534 // CNAME record. So, just record the TTL value of the CNAME, then skip to parse the next record.
1535 //
1536 CNameTtl = AnswerSection->Ttl;
1537 break;
1538 default:
1539 Status = EFI_UNSUPPORTED;
1540 goto ON_EXIT;
1541 }
1542 }
1543
1544 //
1545 // Find next one
1546 //
1547 AnswerName = (CHAR8 *) AnswerSection + sizeof (*AnswerSection) + AnswerSection->DataLength;
1548 AnswerSectionNum ++;
1549 }
1550
1551 if (Instance->Service->IpVersion == IP_VERSION_4) {
1552 ASSERT (Dns4TokenEntry != NULL);
1553
1554 if (Dns4TokenEntry->GeneralLookUp) {
1555 Dns4TokenEntry->Token->RspData.GLookupData->RRCount = RRCount;
1556 } else {
1557 if (QuerySection->Type == DNS_TYPE_A) {
1558 Dns4TokenEntry->Token->RspData.H2AData->IpCount = IpCount;
1559 } else {
1560 Status = EFI_UNSUPPORTED;
1561 goto ON_EXIT;
1562 }
1563 }
1564 } else {
1565 ASSERT (Dns6TokenEntry != NULL);
1566
1567 if (Dns6TokenEntry->GeneralLookUp) {
1568 Dns6TokenEntry->Token->RspData.GLookupData->RRCount = RRCount;
1569 } else {
1570 if (QuerySection->Type == DNS_TYPE_AAAA) {
1571 Dns6TokenEntry->Token->RspData.H2AData->IpCount = IpCount;
1572 } else {
1573 Status = EFI_UNSUPPORTED;
1574 goto ON_EXIT;
1575 }
1576 }
1577 }
1578
1579 ON_COMPLETE:
1580 //
1581 // Parsing is complete, free the sending packet and signal Event here.
1582 //
1583 if (Item != NULL && Item->Value != NULL) {
1584 NetbufFree ((NET_BUF *) (Item->Value));
1585 }
1586
1587 if (Instance->Service->IpVersion == IP_VERSION_4) {
1588 ASSERT (Dns4TokenEntry != NULL);
1589 Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry);
1590 Dns4TokenEntry->Token->Status = Status;
1591 if (Dns4TokenEntry->Token->Event != NULL) {
1592 gBS->SignalEvent (Dns4TokenEntry->Token->Event);
1593 DispatchDpc ();
1594 }
1595 } else {
1596 ASSERT (Dns6TokenEntry != NULL);
1597 Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry);
1598 Dns6TokenEntry->Token->Status = Status;
1599 if (Dns6TokenEntry->Token->Event != NULL) {
1600 gBS->SignalEvent (Dns6TokenEntry->Token->Event);
1601 DispatchDpc ();
1602 }
1603 }
1604
1605 ON_EXIT:
1606 gBS->RestoreTPL (OldTpl);
1607 return Status;
1608 }
1609
1610 /**
1611 Parse response packet.
1612
1613 @param Packet The packets received.
1614 @param EndPoint The local/remote UDP access point
1615 @param IoStatus The status of the UDP receive
1616 @param Context The opaque parameter to the function.
1617
1618 **/
1619 VOID
1620 EFIAPI
1621 DnsOnPacketReceived (
1622 NET_BUF *Packet,
1623 UDP_END_POINT *EndPoint,
1624 EFI_STATUS IoStatus,
1625 VOID *Context
1626 )
1627 {
1628 DNS_INSTANCE *Instance;
1629
1630 UINT8 *RcvString;
1631
1632 BOOLEAN Completed;
1633
1634 Instance = (DNS_INSTANCE *) Context;
1635 NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE);
1636
1637 RcvString = NULL;
1638 Completed = FALSE;
1639
1640 if (EFI_ERROR (IoStatus)) {
1641 goto ON_EXIT;
1642 }
1643
1644 ASSERT (Packet != NULL);
1645
1646 if (Packet->TotalSize <= sizeof (DNS_HEADER)) {
1647 goto ON_EXIT;
1648 }
1649
1650 RcvString = NetbufGetByte (Packet, 0, NULL);
1651 ASSERT (RcvString != NULL);
1652
1653 //
1654 // Parse Dns Response
1655 //
1656 ParseDnsResponse (Instance, RcvString, &Completed);
1657
1658 ON_EXIT:
1659
1660 if (Packet != NULL) {
1661 NetbufFree (Packet);
1662 }
1663
1664 if (!Completed) {
1665 UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);
1666 }
1667 }
1668
1669 /**
1670 Release the net buffer when packet is sent.
1671
1672 @param Packet The packets received.
1673 @param EndPoint The local/remote UDP access point
1674 @param IoStatus The status of the UDP receive
1675 @param Context The opaque parameter to the function.
1676
1677 **/
1678 VOID
1679 EFIAPI
1680 DnsOnPacketSent (
1681 NET_BUF *Packet,
1682 UDP_END_POINT *EndPoint,
1683 EFI_STATUS IoStatus,
1684 VOID *Context
1685 )
1686 {
1687 DNS_INSTANCE *Instance;
1688 LIST_ENTRY *Entry;
1689 NET_MAP_ITEM *Item;
1690 DNS4_TOKEN_ENTRY *Dns4TokenEntry;
1691 DNS6_TOKEN_ENTRY *Dns6TokenEntry;
1692
1693 Dns4TokenEntry = NULL;
1694 Dns6TokenEntry = NULL;
1695
1696 Instance = (DNS_INSTANCE *) Context;
1697 NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE);
1698
1699 if (Instance->Service->IpVersion == IP_VERSION_4) {
1700 NET_LIST_FOR_EACH (Entry, &Instance->Dns4TxTokens.Used) {
1701 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1702 if (Packet == (NET_BUF *)(Item->Value)) {
1703 Dns4TokenEntry = ((DNS4_TOKEN_ENTRY *)Item->Key);
1704 Dns4TokenEntry->PacketToLive = Dns4TokenEntry->Token->RetryInterval;
1705 break;
1706 }
1707 }
1708 } else {
1709 NET_LIST_FOR_EACH (Entry, &Instance->Dns6TxTokens.Used) {
1710 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1711 if (Packet == (NET_BUF *)(Item->Value)) {
1712 Dns6TokenEntry = ((DNS6_TOKEN_ENTRY *)Item->Key);
1713 Dns6TokenEntry->PacketToLive = Dns6TokenEntry->Token->RetryInterval;
1714 break;
1715 }
1716 }
1717 }
1718
1719 NetbufFree (Packet);
1720 }
1721
1722 /**
1723 Query request information.
1724
1725 @param Instance The DNS instance
1726 @param Packet The packet for querying request information.
1727
1728 @retval EFI_SUCCESS Query request information successfully.
1729 @retval Others Failed to query request information.
1730
1731 **/
1732 EFI_STATUS
1733 DoDnsQuery (
1734 IN DNS_INSTANCE *Instance,
1735 IN NET_BUF *Packet
1736 )
1737 {
1738 EFI_STATUS Status;
1739
1740 //
1741 // Ready to receive the DNS response.
1742 //
1743 if (Instance->UdpIo->RecvRequest == NULL) {
1744 Status = UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);
1745 if (EFI_ERROR (Status)) {
1746 return Status;
1747 }
1748 }
1749
1750 //
1751 // Transmit the DNS packet.
1752 //
1753 NET_GET_REF (Packet);
1754
1755 Status = UdpIoSendDatagram (Instance->UdpIo, Packet, NULL, NULL, DnsOnPacketSent, Instance);
1756
1757 return Status;
1758 }
1759
1760 /**
1761 Construct the Packet according query section.
1762
1763 @param Instance The DNS instance
1764 @param QueryName Queried Name
1765 @param Type Queried Type
1766 @param Class Queried Class
1767 @param Packet The packet for query
1768
1769 @retval EFI_SUCCESS The packet is constructed.
1770 @retval Others Failed to construct the Packet.
1771
1772 **/
1773 EFI_STATUS
1774 ConstructDNSQuery (
1775 IN DNS_INSTANCE *Instance,
1776 IN CHAR8 *QueryName,
1777 IN UINT16 Type,
1778 IN UINT16 Class,
1779 OUT NET_BUF **Packet
1780 )
1781 {
1782 NET_FRAGMENT Frag;
1783 DNS_HEADER *DnsHeader;
1784 DNS_QUERY_SECTION *DnsQuery;
1785
1786 //
1787 // Messages carried by UDP are restricted to 512 bytes (not counting the IP
1788 // or UDP headers).
1789 //
1790 Frag.Bulk = AllocatePool (DNS_MAX_MESSAGE_SIZE * 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->RetryCounting <= Dns4TokenEntry->Token->RetryCount) {
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->RetryCounting <= Dns6TokenEntry->Token->RetryCount) {
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