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