]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/DnsDxe/DnsImpl.c
617e623286d86f448b77e224735c62cae6afc4d9
[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 Fill QName for IP querying. QName is a domain name represented as
1042 a sequence of labels, where each label consists of a length octet
1043 followed by that number of octets. The domain name terminates with
1044 the zero length octet for the null label of the root. Caller should
1045 take responsibility to the buffer in QName.
1046
1047 @param HostName Queried HostName
1048
1049 @retval NULL Failed to fill QName.
1050 @return QName filled successfully.
1051
1052 **/
1053 CHAR8 *
1054 EFIAPI
1055 DnsFillinQNameForQueryIp (
1056 IN CHAR16 *HostName
1057 )
1058 {
1059 CHAR8 *QueryName;
1060 CHAR8 *Header;
1061 CHAR8 *Tail;
1062 UINTN Len;
1063 UINTN Index;
1064
1065 QueryName = NULL;
1066 Header = NULL;
1067 Tail = NULL;
1068
1069 QueryName = AllocateZeroPool (DNS_DEFAULT_BLKSIZE);
1070 if (QueryName == NULL) {
1071 return NULL;
1072 }
1073
1074 Header = QueryName;
1075 Tail = Header + 1;
1076 Len = 0;
1077 for (Index = 0; HostName[Index] != 0; Index++) {
1078 *Tail = (CHAR8) HostName[Index];
1079 if (*Tail == '.') {
1080 *Header = (CHAR8) Len;
1081 Header = Tail;
1082 Tail ++;
1083 Len = 0;
1084 } else {
1085 Tail++;
1086 Len++;
1087 }
1088 }
1089 *Header = (CHAR8) Len;
1090 *Tail = 0;
1091
1092 return QueryName;
1093 }
1094
1095 /**
1096 Find out whether the response is valid or invalid.
1097
1098 @param TokensMap All DNS transmittal Tokens entry.
1099 @param Identification Identification for queried packet.
1100 @param Type Type for queried packet.
1101 @param Item Return corresponding Token entry.
1102
1103 @retval TRUE The response is valid.
1104 @retval FALSE The response is invalid.
1105
1106 **/
1107 BOOLEAN
1108 IsValidDnsResponse (
1109 IN NET_MAP *TokensMap,
1110 IN UINT16 Identification,
1111 IN UINT16 Type,
1112 OUT NET_MAP_ITEM **Item
1113 )
1114 {
1115 LIST_ENTRY *Entry;
1116
1117 NET_BUF *Packet;
1118 UINT8 *TxString;
1119 DNS_HEADER *DnsHeader;
1120 CHAR8 *QueryName;
1121 DNS_QUERY_SECTION *QuerySection;
1122
1123 NET_LIST_FOR_EACH (Entry, &TokensMap->Used) {
1124 *Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1125 Packet = (NET_BUF *) ((*Item)->Value);
1126 if (Packet == NULL){
1127
1128 continue;
1129 } else {
1130 TxString = NetbufGetByte (Packet, 0, NULL);
1131 ASSERT (TxString != NULL);
1132 DnsHeader = (DNS_HEADER *) TxString;
1133 QueryName = (CHAR8 *) (TxString + sizeof (*DnsHeader));
1134 QuerySection = (DNS_QUERY_SECTION *) (QueryName + AsciiStrLen (QueryName) + 1);
1135
1136 DnsHeader->Identification = NTOHS (DnsHeader->Identification);
1137 QuerySection->Type = NTOHS (QuerySection->Type);
1138
1139 if (DnsHeader->Identification == Identification && QuerySection->Type == Type) {
1140 return TRUE;
1141 }
1142 }
1143 }
1144
1145 *Item =NULL;
1146
1147 return FALSE;
1148 }
1149
1150 /**
1151 Parse Dns Response.
1152
1153 @param Instance The DNS instance
1154 @param RxString Received buffer.
1155 @param Completed Flag to indicate that Dns response is valid.
1156
1157 @retval EFI_SUCCESS Parse Dns Response successfully.
1158 @retval Others Failed to parse Dns Response.
1159
1160 **/
1161 EFI_STATUS
1162 ParseDnsResponse (
1163 IN OUT DNS_INSTANCE *Instance,
1164 IN UINT8 *RxString,
1165 OUT BOOLEAN *Completed
1166 )
1167 {
1168 DNS_HEADER *DnsHeader;
1169
1170 CHAR8 *QueryName;
1171 DNS_QUERY_SECTION *QuerySection;
1172
1173 CHAR8 *AnswerName;
1174 DNS_ANSWER_SECTION *AnswerSection;
1175 UINT8 *AnswerData;
1176
1177 NET_MAP_ITEM *Item;
1178 DNS4_TOKEN_ENTRY *Dns4TokenEntry;
1179 DNS6_TOKEN_ENTRY *Dns6TokenEntry;
1180
1181 UINT32 IpCount;
1182 UINT32 RRCount;
1183 UINT32 AnswerSectionNum;
1184
1185 EFI_IPv4_ADDRESS *HostAddr4;
1186 EFI_IPv6_ADDRESS *HostAddr6;
1187
1188 EFI_DNS4_CACHE_ENTRY *Dns4CacheEntry;
1189 EFI_DNS6_CACHE_ENTRY *Dns6CacheEntry;
1190
1191 DNS_RESOURCE_RECORD *Dns4RR;
1192 DNS6_RESOURCE_RECORD *Dns6RR;
1193
1194 EFI_STATUS Status;
1195
1196 EFI_TPL OldTpl;
1197
1198 Item = NULL;
1199 Dns4TokenEntry = NULL;
1200 Dns6TokenEntry = NULL;
1201
1202 IpCount = 0;
1203 RRCount = 0;
1204 AnswerSectionNum = 0;
1205
1206 HostAddr4 = NULL;
1207 HostAddr6 = NULL;
1208
1209 Dns4CacheEntry = NULL;
1210 Dns6CacheEntry = NULL;
1211
1212 Dns4RR = NULL;
1213 Dns6RR = NULL;
1214
1215 *Completed = TRUE;
1216 Status = EFI_SUCCESS;
1217
1218 //
1219 // Get header
1220 //
1221 DnsHeader = (DNS_HEADER *) RxString;
1222
1223 DnsHeader->Identification = NTOHS (DnsHeader->Identification);
1224 DnsHeader->Flags.Uint16 = NTOHS (DnsHeader->Flags.Uint16);
1225 DnsHeader->QuestionsNum = NTOHS (DnsHeader->QuestionsNum);
1226 DnsHeader->AnswersNum = NTOHS (DnsHeader->AnswersNum);
1227 DnsHeader->AuthorityNum = NTOHS (DnsHeader->AuthorityNum);
1228 DnsHeader->AditionalNum = NTOHS (DnsHeader->AditionalNum);
1229
1230 //
1231 // Get Query name
1232 //
1233 QueryName = (CHAR8 *) (RxString + sizeof (*DnsHeader));
1234
1235 //
1236 // Get query section
1237 //
1238 QuerySection = (DNS_QUERY_SECTION *) (QueryName + AsciiStrLen (QueryName) + 1);
1239 QuerySection->Type = NTOHS (QuerySection->Type);
1240 QuerySection->Class = NTOHS (QuerySection->Class);
1241
1242 //
1243 // Get Answer name
1244 //
1245 AnswerName = (CHAR8 *) QuerySection + sizeof (*QuerySection);
1246
1247 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1248
1249 //
1250 // Check DnsResponse Validity, if so, also get a valid NET_MAP_ITEM.
1251 //
1252 if (Instance->Service->IpVersion == IP_VERSION_4) {
1253 if (!IsValidDnsResponse (&Instance->Dns4TxTokens, DnsHeader->Identification, QuerySection->Type, &Item)) {
1254 *Completed = FALSE;
1255 Status = EFI_ABORTED;
1256 goto ON_EXIT;
1257 }
1258 ASSERT (Item != NULL);
1259 Dns4TokenEntry = (DNS4_TOKEN_ENTRY *) (Item->Key);
1260 } else {
1261 if (!IsValidDnsResponse (&Instance->Dns6TxTokens, DnsHeader->Identification, QuerySection->Type, &Item)) {
1262 *Completed = FALSE;
1263 Status = EFI_ABORTED;
1264 goto ON_EXIT;
1265 }
1266 ASSERT (Item != NULL);
1267 Dns6TokenEntry = (DNS6_TOKEN_ENTRY *) (Item->Key);
1268 }
1269
1270 //
1271 // Continue Check Some Errors.
1272 //
1273 if (DnsHeader->Flags.Bits.RCode != DNS_FLAGS_RCODE_NO_ERROR || DnsHeader->AnswersNum < 1 || \
1274 DnsHeader->Flags.Bits.QR != DNS_FLAGS_QR_RESPONSE || QuerySection->Class != DNS_CLASS_INET) {
1275 Status = EFI_ABORTED;
1276 goto ON_EXIT;
1277 }
1278
1279 //
1280 // Free the sending packet.
1281 //
1282 if (Item->Value != NULL) {
1283 NetbufFree ((NET_BUF *) (Item->Value));
1284 }
1285
1286 //
1287 // Do some buffer allocations.
1288 //
1289 if (Instance->Service->IpVersion == IP_VERSION_4) {
1290 ASSERT (Dns4TokenEntry != NULL);
1291
1292 if (Dns4TokenEntry->GeneralLookUp) {
1293 //
1294 // It's the GeneralLookUp querying.
1295 //
1296 Dns4TokenEntry->Token->RspData.GLookupData = AllocatePool (sizeof (DNS_RESOURCE_RECORD));
1297 if (Dns4TokenEntry->Token->RspData.GLookupData == NULL) {
1298 Status = EFI_OUT_OF_RESOURCES;
1299 goto ON_EXIT;
1300 }
1301 Dns4TokenEntry->Token->RspData.GLookupData->RRList = AllocatePool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD));
1302 if (Dns4TokenEntry->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_A) {
1311 Dns4TokenEntry->Token->RspData.H2AData = AllocatePool (sizeof (DNS_HOST_TO_ADDR_DATA));
1312 if (Dns4TokenEntry->Token->RspData.H2AData == NULL) {
1313 Status = EFI_OUT_OF_RESOURCES;
1314 goto ON_EXIT;
1315 }
1316 Dns4TokenEntry->Token->RspData.H2AData->IpList = AllocatePool (DnsHeader->AnswersNum * sizeof (EFI_IPv4_ADDRESS));
1317 if (Dns4TokenEntry->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 } else {
1327 ASSERT (Dns6TokenEntry != NULL);
1328
1329 if (Dns6TokenEntry->GeneralLookUp) {
1330 //
1331 // It's the GeneralLookUp querying.
1332 //
1333 Dns6TokenEntry->Token->RspData.GLookupData = AllocatePool (sizeof (DNS_RESOURCE_RECORD));
1334 if (Dns6TokenEntry->Token->RspData.GLookupData == NULL) {
1335 Status = EFI_UNSUPPORTED;
1336 goto ON_EXIT;
1337 }
1338 Dns6TokenEntry->Token->RspData.GLookupData->RRList = AllocatePool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD));
1339 if (Dns6TokenEntry->Token->RspData.GLookupData->RRList == NULL) {
1340 Status = EFI_UNSUPPORTED;
1341 goto ON_EXIT;
1342 }
1343 } else {
1344 //
1345 // It's not the GeneralLookUp querying. Check the Query type.
1346 //
1347 if (QuerySection->Type == DNS_TYPE_AAAA) {
1348 Dns6TokenEntry->Token->RspData.H2AData = AllocatePool (sizeof (DNS6_HOST_TO_ADDR_DATA));
1349 if (Dns6TokenEntry->Token->RspData.H2AData == NULL) {
1350 Status = EFI_UNSUPPORTED;
1351 goto ON_EXIT;
1352 }
1353 Dns6TokenEntry->Token->RspData.H2AData->IpList = AllocatePool (DnsHeader->AnswersNum * sizeof (EFI_IPv6_ADDRESS));
1354 if (Dns6TokenEntry->Token->RspData.H2AData->IpList == NULL) {
1355 Status = EFI_UNSUPPORTED;
1356 goto ON_EXIT;
1357 }
1358 } else {
1359 Status = EFI_UNSUPPORTED;
1360 goto ON_EXIT;
1361 }
1362 }
1363 }
1364
1365 //
1366 // Processing AnswerSection.
1367 //
1368 while (AnswerSectionNum < DnsHeader->AnswersNum) {
1369 //
1370 // Answer name should be PTR.
1371 //
1372 ASSERT ((*(UINT8 *) AnswerName & 0xC0) == 0xC0);
1373
1374 //
1375 // Get Answer section.
1376 //
1377 AnswerSection = (DNS_ANSWER_SECTION *) (AnswerName + sizeof (UINT16));
1378 AnswerSection->Type = NTOHS (AnswerSection->Type);
1379 AnswerSection->Class = NTOHS (AnswerSection->Class);
1380 AnswerSection->Ttl = NTOHL (AnswerSection->Ttl);
1381 AnswerSection->DataLength = NTOHS (AnswerSection->DataLength);
1382
1383 //
1384 // Check whether it's the GeneralLookUp querying.
1385 //
1386 if (Instance->Service->IpVersion == IP_VERSION_4 && Dns4TokenEntry->GeneralLookUp) {
1387 Dns4RR = Dns4TokenEntry->Token->RspData.GLookupData->RRList;
1388 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
1389
1390 //
1391 // Fill the ResourceRecord.
1392 //
1393 Dns4RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1);
1394 if (Dns4RR[RRCount].QName == NULL) {
1395 Status = EFI_UNSUPPORTED;
1396 goto ON_EXIT;
1397 }
1398 CopyMem (Dns4RR[RRCount].QName, QueryName, AsciiStrLen (QueryName));
1399 Dns4RR[RRCount].QType = AnswerSection->Type;
1400 Dns4RR[RRCount].QClass = AnswerSection->Class;
1401 Dns4RR[RRCount].TTL = AnswerSection->Ttl;
1402 Dns4RR[RRCount].DataLength = AnswerSection->DataLength;
1403 Dns4RR[RRCount].RData = AllocateZeroPool (Dns4RR[RRCount].DataLength);
1404 if (Dns4RR[RRCount].RData == NULL) {
1405 Status = EFI_UNSUPPORTED;
1406 goto ON_EXIT;
1407 }
1408 CopyMem (Dns4RR[RRCount].RData, AnswerData, Dns4RR[RRCount].DataLength);
1409
1410 RRCount ++;
1411 } else if (Instance->Service->IpVersion == IP_VERSION_6 && Dns6TokenEntry->GeneralLookUp) {
1412 Dns6RR = Dns6TokenEntry->Token->RspData.GLookupData->RRList;
1413 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
1414
1415 //
1416 // Fill the ResourceRecord.
1417 //
1418 Dns6RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1);
1419 if (Dns6RR[RRCount].QName == NULL) {
1420 Status = EFI_UNSUPPORTED;
1421 goto ON_EXIT;
1422 }
1423 CopyMem (Dns6RR[RRCount].QName, QueryName, AsciiStrLen (QueryName));
1424 Dns6RR[RRCount].QType = AnswerSection->Type;
1425 Dns6RR[RRCount].QClass = AnswerSection->Class;
1426 Dns6RR[RRCount].TTL = AnswerSection->Ttl;
1427 Dns6RR[RRCount].DataLength = AnswerSection->DataLength;
1428 Dns6RR[RRCount].RData = AllocateZeroPool (Dns6RR[RRCount].DataLength);
1429 if (Dns6RR[RRCount].RData == NULL) {
1430 Status = EFI_UNSUPPORTED;
1431 goto ON_EXIT;
1432 }
1433 CopyMem (Dns6RR[RRCount].RData, AnswerData, Dns6RR[RRCount].DataLength);
1434
1435 RRCount ++;
1436 } else {
1437 //
1438 // It's not the GeneralLookUp querying.
1439 // Check the Query type, parse the response packet.
1440 //
1441 switch (AnswerSection->Type) {
1442 case DNS_TYPE_A:
1443 //
1444 // This is address entry, get Data.
1445 //
1446 ASSERT (Dns4TokenEntry != NULL && AnswerSection->DataLength == 4);
1447
1448 HostAddr4 = Dns4TokenEntry->Token->RspData.H2AData->IpList;
1449 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
1450 CopyMem (&HostAddr4[IpCount], AnswerData, sizeof (EFI_IPv4_ADDRESS));
1451
1452 //
1453 // Update DNS cache dynamically.
1454 //
1455 if (Dns4CacheEntry != NULL) {
1456 if (Dns4CacheEntry->HostName != NULL) {
1457 FreePool (Dns4CacheEntry->HostName);
1458 }
1459
1460 if (Dns4CacheEntry->IpAddress != NULL) {
1461 FreePool (Dns4CacheEntry->IpAddress);
1462 }
1463
1464 FreePool (Dns4CacheEntry);
1465 }
1466
1467 //
1468 // Allocate new CacheEntry pool.
1469 //
1470 Dns4CacheEntry = AllocateZeroPool (sizeof (EFI_DNS4_CACHE_ENTRY));
1471 if (Dns4CacheEntry == NULL) {
1472 Status = EFI_UNSUPPORTED;
1473 goto ON_EXIT;
1474 }
1475 Dns4CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1));
1476 if (Dns4CacheEntry->HostName == NULL) {
1477 Status = EFI_UNSUPPORTED;
1478 goto ON_EXIT;
1479 }
1480 CopyMem (Dns4CacheEntry->HostName, Dns4TokenEntry->QueryHostName, 2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1));
1481 Dns4CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv4_ADDRESS));
1482 if (Dns4CacheEntry->IpAddress == NULL) {
1483 Status = EFI_UNSUPPORTED;
1484 goto ON_EXIT;
1485 }
1486 CopyMem (Dns4CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv4_ADDRESS));
1487 Dns4CacheEntry->Timeout = AnswerSection->Ttl;
1488
1489 UpdateDns4Cache (&mDriverData->Dns4CacheList, FALSE, TRUE, *Dns4CacheEntry);
1490
1491 IpCount ++;
1492 break;
1493 case DNS_TYPE_AAAA:
1494 //
1495 // This is address entry, get Data.
1496 //
1497 ASSERT (Dns6TokenEntry != NULL && AnswerSection->DataLength == 16);
1498
1499 HostAddr6 = Dns6TokenEntry->Token->RspData.H2AData->IpList;
1500 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
1501 CopyMem (&HostAddr6[IpCount], AnswerData, sizeof (EFI_IPv6_ADDRESS));
1502
1503 //
1504 // Update DNS cache dynamically.
1505 //
1506 if (Dns6CacheEntry != NULL) {
1507 if (Dns6CacheEntry->HostName != NULL) {
1508 FreePool (Dns6CacheEntry->HostName);
1509 }
1510
1511 if (Dns6CacheEntry->IpAddress != NULL) {
1512 FreePool (Dns6CacheEntry->IpAddress);
1513 }
1514
1515 FreePool (Dns6CacheEntry);
1516 }
1517
1518 //
1519 // Allocate new CacheEntry pool.
1520 //
1521 Dns6CacheEntry = AllocateZeroPool (sizeof (EFI_DNS6_CACHE_ENTRY));
1522 if (Dns6CacheEntry == NULL) {
1523 Status = EFI_UNSUPPORTED;
1524 goto ON_EXIT;
1525 }
1526 Dns6CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1));
1527 if (Dns6CacheEntry->HostName == NULL) {
1528 Status = EFI_UNSUPPORTED;
1529 goto ON_EXIT;
1530 }
1531 CopyMem (Dns6CacheEntry->HostName, Dns6TokenEntry->QueryHostName, 2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1));
1532 Dns6CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS));
1533 if (Dns6CacheEntry->IpAddress == NULL) {
1534 Status = EFI_UNSUPPORTED;
1535 goto ON_EXIT;
1536 }
1537 CopyMem (Dns6CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv6_ADDRESS));
1538 Dns6CacheEntry->Timeout = AnswerSection->Ttl;
1539
1540 UpdateDns6Cache (&mDriverData->Dns6CacheList, FALSE, TRUE, *Dns6CacheEntry);
1541
1542 IpCount ++;
1543 break;
1544 default:
1545 Status = EFI_UNSUPPORTED;
1546 goto ON_EXIT;
1547 }
1548 }
1549
1550 //
1551 // Find next one
1552 //
1553 AnswerName = (CHAR8 *) AnswerSection + sizeof (*AnswerSection) + AnswerSection->DataLength;
1554 AnswerSectionNum ++;
1555 }
1556
1557 if (Instance->Service->IpVersion == IP_VERSION_4) {
1558 ASSERT (Dns4TokenEntry != NULL);
1559
1560 if (Dns4TokenEntry->GeneralLookUp) {
1561 Dns4TokenEntry->Token->RspData.GLookupData->RRCount = RRCount;
1562 } else {
1563 if (QuerySection->Type == DNS_TYPE_A) {
1564 Dns4TokenEntry->Token->RspData.H2AData->IpCount = IpCount;
1565 } else {
1566 Status = EFI_UNSUPPORTED;
1567 goto ON_EXIT;
1568 }
1569 }
1570 } else {
1571 ASSERT (Dns6TokenEntry != NULL);
1572
1573 if (Dns6TokenEntry->GeneralLookUp) {
1574 Dns6TokenEntry->Token->RspData.GLookupData->RRCount = RRCount;
1575 } else {
1576 if (QuerySection->Type == DNS_TYPE_AAAA) {
1577 Dns6TokenEntry->Token->RspData.H2AData->IpCount = IpCount;
1578 } else {
1579 Status = EFI_UNSUPPORTED;
1580 goto ON_EXIT;
1581 }
1582 }
1583 }
1584
1585 //
1586 // Parsing is complete, SignalEvent here.
1587 //
1588 if (Instance->Service->IpVersion == IP_VERSION_4) {
1589 ASSERT (Dns4TokenEntry != NULL);
1590 Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry);
1591 Dns4TokenEntry->Token->Status = EFI_SUCCESS;
1592 if (Dns4TokenEntry->Token->Event != NULL) {
1593 gBS->SignalEvent (Dns4TokenEntry->Token->Event);
1594 DispatchDpc ();
1595 }
1596 } else {
1597 ASSERT (Dns6TokenEntry != NULL);
1598 Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry);
1599 Dns6TokenEntry->Token->Status = EFI_SUCCESS;
1600 if (Dns6TokenEntry->Token->Event != NULL) {
1601 gBS->SignalEvent (Dns6TokenEntry->Token->Event);
1602 DispatchDpc ();
1603 }
1604 }
1605
1606 //
1607 // Free allocated CacheEntry pool.
1608 //
1609 if (Dns4CacheEntry != NULL) {
1610 if (Dns4CacheEntry->HostName != NULL) {
1611 FreePool (Dns4CacheEntry->HostName);
1612 }
1613
1614 if (Dns4CacheEntry->IpAddress != NULL) {
1615 FreePool (Dns4CacheEntry->IpAddress);
1616 }
1617
1618 FreePool (Dns4CacheEntry);
1619 }
1620
1621 if (Dns6CacheEntry != NULL) {
1622 if (Dns6CacheEntry->HostName != NULL) {
1623 FreePool (Dns6CacheEntry->HostName);
1624 }
1625
1626 if (Dns6CacheEntry->IpAddress != NULL) {
1627 FreePool (Dns6CacheEntry->IpAddress);
1628 }
1629
1630 FreePool (Dns6CacheEntry);
1631 }
1632
1633 ON_EXIT:
1634 gBS->RestoreTPL (OldTpl);
1635 return Status;
1636 }
1637
1638 /**
1639 Parse response packet.
1640
1641 @param Packet The packets received.
1642 @param EndPoint The local/remote UDP access point
1643 @param IoStatus The status of the UDP receive
1644 @param Context The opaque parameter to the function.
1645
1646 **/
1647 VOID
1648 EFIAPI
1649 DnsOnPacketReceived (
1650 NET_BUF *Packet,
1651 UDP_END_POINT *EndPoint,
1652 EFI_STATUS IoStatus,
1653 VOID *Context
1654 )
1655 {
1656 DNS_INSTANCE *Instance;
1657
1658 UINT8 *RcvString;
1659
1660 BOOLEAN Completed;
1661
1662 Instance = (DNS_INSTANCE *) Context;
1663 NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE);
1664
1665 RcvString = NULL;
1666 Completed = FALSE;
1667
1668 if (EFI_ERROR (IoStatus)) {
1669 goto ON_EXIT;
1670 }
1671
1672 ASSERT (Packet != NULL);
1673
1674 RcvString = NetbufGetByte (Packet, 0, NULL);
1675 ASSERT (RcvString != NULL);
1676
1677 //
1678 // Parse Dns Response
1679 //
1680 ParseDnsResponse (Instance, RcvString, &Completed);
1681
1682 ON_EXIT:
1683
1684 if (Packet != NULL) {
1685 NetbufFree (Packet);
1686 }
1687
1688 if (!Completed) {
1689 UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);
1690 }
1691 }
1692
1693 /**
1694 Release the net buffer when packet is sent.
1695
1696 @param Packet The packets received.
1697 @param EndPoint The local/remote UDP access point
1698 @param IoStatus The status of the UDP receive
1699 @param Context The opaque parameter to the function.
1700
1701 **/
1702 VOID
1703 EFIAPI
1704 DnsOnPacketSent (
1705 NET_BUF *Packet,
1706 UDP_END_POINT *EndPoint,
1707 EFI_STATUS IoStatus,
1708 VOID *Context
1709 )
1710 {
1711 DNS_INSTANCE *Instance;
1712 LIST_ENTRY *Entry;
1713 NET_MAP_ITEM *Item;
1714 DNS4_TOKEN_ENTRY *Dns4TokenEntry;
1715 DNS6_TOKEN_ENTRY *Dns6TokenEntry;
1716
1717 Dns4TokenEntry = NULL;
1718 Dns6TokenEntry = NULL;
1719
1720 Instance = (DNS_INSTANCE *) Context;
1721 NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE);
1722
1723 if (Instance->Service->IpVersion == IP_VERSION_4) {
1724 NET_LIST_FOR_EACH (Entry, &Instance->Dns4TxTokens.Used) {
1725 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1726 if (Packet == (NET_BUF *)(Item->Value)) {
1727 Dns4TokenEntry = ((DNS4_TOKEN_ENTRY *)Item->Key);
1728 Dns4TokenEntry->PacketToLive = Dns4TokenEntry->Token->RetryInterval;
1729 break;
1730 }
1731 }
1732 } else {
1733 NET_LIST_FOR_EACH (Entry, &Instance->Dns6TxTokens.Used) {
1734 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1735 if (Packet == (NET_BUF *)(Item->Value)) {
1736 Dns6TokenEntry = ((DNS6_TOKEN_ENTRY *)Item->Key);
1737 Dns6TokenEntry->PacketToLive = Dns6TokenEntry->Token->RetryInterval;
1738 break;
1739 }
1740 }
1741 }
1742
1743 NetbufFree (Packet);
1744 }
1745
1746 /**
1747 Query request information.
1748
1749 @param Instance The DNS instance
1750 @param Packet The packet for querying request information.
1751
1752 @retval EFI_SUCCESS Query request information successfully.
1753 @retval Others Failed to query request information.
1754
1755 **/
1756 EFI_STATUS
1757 DoDnsQuery (
1758 IN DNS_INSTANCE *Instance,
1759 IN NET_BUF *Packet
1760 )
1761 {
1762 EFI_STATUS Status;
1763
1764 //
1765 // Ready to receive the DNS response.
1766 //
1767 if (Instance->UdpIo->RecvRequest == NULL) {
1768 Status = UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);
1769 if (EFI_ERROR (Status)) {
1770 return Status;
1771 }
1772 }
1773
1774 //
1775 // Transmit the DNS packet.
1776 //
1777 NET_GET_REF (Packet);
1778
1779 Status = UdpIoSendDatagram (Instance->UdpIo, Packet, NULL, NULL, DnsOnPacketSent, Instance);
1780
1781 return Status;
1782 }
1783
1784 /**
1785 Construct the Packet according query section.
1786
1787 @param Instance The DNS instance
1788 @param QueryName Queried Name
1789 @param Type Queried Type
1790 @param Class Queried Class
1791 @param Packet The packet for query
1792
1793 @retval EFI_SUCCESS The packet is constructed.
1794 @retval Others Failed to construct the Packet.
1795
1796 **/
1797 EFI_STATUS
1798 ConstructDNSQuery (
1799 IN DNS_INSTANCE *Instance,
1800 IN CHAR8 *QueryName,
1801 IN UINT16 Type,
1802 IN UINT16 Class,
1803 OUT NET_BUF **Packet
1804 )
1805 {
1806 NET_FRAGMENT Frag;
1807 DNS_HEADER *DnsHeader;
1808 DNS_QUERY_SECTION *DnsQuery;
1809
1810 Frag.Bulk = AllocatePool (DNS_DEFAULT_BLKSIZE * sizeof (UINT8));
1811 if (Frag.Bulk == NULL) {
1812 return EFI_OUT_OF_RESOURCES;
1813 }
1814
1815 //
1816 // Fill header
1817 //
1818 DnsHeader = (DNS_HEADER *) Frag.Bulk;
1819 DnsHeader->Identification = (UINT16)NET_RANDOM (NetRandomInitSeed());
1820 DnsHeader->Flags.Uint16 = 0x0000;
1821 DnsHeader->Flags.Bits.RD = 1;
1822 DnsHeader->Flags.Bits.OpCode = DNS_FLAGS_OPCODE_STANDARD;
1823 DnsHeader->Flags.Bits.QR = DNS_FLAGS_QR_QUERY;
1824 DnsHeader->QuestionsNum = 1;
1825 DnsHeader->AnswersNum = 0;
1826 DnsHeader->AuthorityNum = 0;
1827 DnsHeader->AditionalNum = 0;
1828
1829 DnsHeader->Identification = HTONS (DnsHeader->Identification);
1830 DnsHeader->Flags.Uint16 = HTONS (DnsHeader->Flags.Uint16);
1831 DnsHeader->QuestionsNum = HTONS (DnsHeader->QuestionsNum);
1832 DnsHeader->AnswersNum = HTONS (DnsHeader->AnswersNum);
1833 DnsHeader->AuthorityNum = HTONS (DnsHeader->AuthorityNum);
1834 DnsHeader->AditionalNum = HTONS (DnsHeader->AditionalNum);
1835
1836 Frag.Len = sizeof (*DnsHeader);
1837
1838 //
1839 // Fill Query name
1840 //
1841 CopyMem (Frag.Bulk + Frag.Len, QueryName, AsciiStrLen (QueryName));
1842 Frag.Len = (UINT32) (Frag.Len + AsciiStrLen (QueryName));
1843 *(Frag.Bulk + Frag.Len) = 0;
1844 Frag.Len ++;
1845
1846 //
1847 // Rest query section
1848 //
1849 DnsQuery = (DNS_QUERY_SECTION *) (Frag.Bulk + Frag.Len);
1850
1851 DnsQuery->Type = HTONS (Type);
1852 DnsQuery->Class = HTONS (Class);
1853
1854 Frag.Len += sizeof (*DnsQuery);
1855
1856 //
1857 // Wrap the Frag in a net buffer.
1858 //
1859 *Packet = NetbufFromExt (&Frag, 1, 0, 0, DnsDummyExtFree, NULL);
1860 if (*Packet == NULL) {
1861 FreePool (Frag.Bulk);
1862 return EFI_OUT_OF_RESOURCES;
1863 }
1864
1865 //
1866 // Store the UdpIo in ProtoData.
1867 //
1868 *((UINTN *) &((*Packet)->ProtoData[0])) = (UINTN) (Instance->UdpIo);
1869
1870 return EFI_SUCCESS;
1871 }
1872
1873 /**
1874 Retransmit the packet.
1875
1876 @param Instance The DNS instance
1877 @param Packet Retransmit the packet
1878
1879 @retval EFI_SUCCESS The packet is retransmitted.
1880 @retval Others Failed to retransmit.
1881
1882 **/
1883 EFI_STATUS
1884 DnsRetransmit (
1885 IN DNS_INSTANCE *Instance,
1886 IN NET_BUF *Packet
1887 )
1888 {
1889 EFI_STATUS Status;
1890
1891 UINT8 *Buffer;
1892
1893 ASSERT (Packet != NULL);
1894
1895 //
1896 // Set the requests to the listening port, other packets to the connected port
1897 //
1898 Buffer = NetbufGetByte (Packet, 0, NULL);
1899 ASSERT (Buffer != NULL);
1900
1901 NET_GET_REF (Packet);
1902
1903 Status = UdpIoSendDatagram (
1904 Instance->UdpIo,
1905 Packet,
1906 NULL,
1907 NULL,
1908 DnsOnPacketSent,
1909 Instance
1910 );
1911
1912 if (EFI_ERROR (Status)) {
1913 NET_PUT_REF (Packet);
1914 }
1915
1916 return Status;
1917 }
1918
1919 /**
1920 The timer ticking function for the DNS services.
1921
1922 @param Event The ticking event
1923 @param Context The DNS service instance
1924
1925 **/
1926 VOID
1927 EFIAPI
1928 DnsOnTimerRetransmit (
1929 IN EFI_EVENT Event,
1930 IN VOID *Context
1931 )
1932 {
1933 DNS_SERVICE *Service;
1934
1935 LIST_ENTRY *Entry;
1936 LIST_ENTRY *Next;
1937
1938 DNS_INSTANCE *Instance;
1939 LIST_ENTRY *EntryNetMap;
1940 NET_MAP_ITEM *ItemNetMap;
1941 DNS4_TOKEN_ENTRY *Dns4TokenEntry;
1942 DNS6_TOKEN_ENTRY *Dns6TokenEntry;
1943
1944 Dns4TokenEntry = NULL;
1945 Dns6TokenEntry = NULL;
1946
1947 Service = (DNS_SERVICE *) Context;
1948
1949
1950 if (Service->IpVersion == IP_VERSION_4) {
1951 //
1952 // Iterate through all the children of the DNS service instance. Time
1953 // out the packet. If maximum retries reached, clean the Token up.
1954 //
1955 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Service->Dns4ChildrenList) {
1956 Instance = NET_LIST_USER_STRUCT (Entry, DNS_INSTANCE, Link);
1957
1958 EntryNetMap = Instance->Dns4TxTokens.Used.ForwardLink;
1959 while (EntryNetMap != &Instance->Dns4TxTokens.Used) {
1960 ItemNetMap = NET_LIST_USER_STRUCT (EntryNetMap, NET_MAP_ITEM, Link);
1961 Dns4TokenEntry = (DNS4_TOKEN_ENTRY *)(ItemNetMap->Key);
1962 if (Dns4TokenEntry->PacketToLive == 0 || (--Dns4TokenEntry->PacketToLive > 0)) {
1963 EntryNetMap = EntryNetMap->ForwardLink;
1964 continue;
1965 }
1966
1967 //
1968 // Retransmit the packet if haven't reach the maxmium retry count,
1969 // otherwise exit the transfer.
1970 //
1971 if (++Dns4TokenEntry->Token->RetryCount < Instance->MaxRetry) {
1972 DnsRetransmit (Instance, (NET_BUF *)ItemNetMap->Value);
1973 EntryNetMap = EntryNetMap->ForwardLink;
1974 } else {
1975 //
1976 // Maximum retries reached, clean the Token up.
1977 //
1978 Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry);
1979 Dns4TokenEntry->Token->Status = EFI_TIMEOUT;
1980 gBS->SignalEvent (Dns4TokenEntry->Token->Event);
1981 DispatchDpc ();
1982
1983 //
1984 // Free the sending packet.
1985 //
1986 if (ItemNetMap->Value != NULL) {
1987 NetbufFree ((NET_BUF *)(ItemNetMap->Value));
1988 }
1989
1990 EntryNetMap = Instance->Dns4TxTokens.Used.ForwardLink;
1991 }
1992 }
1993 }
1994 }else {
1995 //
1996 // Iterate through all the children of the DNS service instance. Time
1997 // out the packet. If maximum retries reached, clean the Token up.
1998 //
1999 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Service->Dns6ChildrenList) {
2000 Instance = NET_LIST_USER_STRUCT (Entry, DNS_INSTANCE, Link);
2001
2002 EntryNetMap = Instance->Dns6TxTokens.Used.ForwardLink;
2003 while (EntryNetMap != &Instance->Dns6TxTokens.Used) {
2004 ItemNetMap = NET_LIST_USER_STRUCT (EntryNetMap, NET_MAP_ITEM, Link);
2005 Dns6TokenEntry = (DNS6_TOKEN_ENTRY *) (ItemNetMap->Key);
2006 if (Dns6TokenEntry->PacketToLive == 0 || (--Dns6TokenEntry->PacketToLive > 0)) {
2007 EntryNetMap = EntryNetMap->ForwardLink;
2008 continue;
2009 }
2010
2011 //
2012 // Retransmit the packet if haven't reach the maxmium retry count,
2013 // otherwise exit the transfer.
2014 //
2015 if (++Dns6TokenEntry->Token->RetryCount < Instance->MaxRetry) {
2016 DnsRetransmit (Instance, (NET_BUF *) ItemNetMap->Value);
2017 EntryNetMap = EntryNetMap->ForwardLink;
2018 } else {
2019 //
2020 // Maximum retries reached, clean the Token up.
2021 //
2022 Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry);
2023 Dns6TokenEntry->Token->Status = EFI_TIMEOUT;
2024 gBS->SignalEvent (Dns6TokenEntry->Token->Event);
2025 DispatchDpc ();
2026
2027 //
2028 // Free the sending packet.
2029 //
2030 if (ItemNetMap->Value != NULL) {
2031 NetbufFree ((NET_BUF *) (ItemNetMap->Value));
2032 }
2033
2034 EntryNetMap = Instance->Dns6TxTokens.Used.ForwardLink;
2035 }
2036 }
2037 }
2038 }
2039 }
2040
2041 /**
2042 The timer ticking function for the DNS driver.
2043
2044 @param Event The ticking event
2045 @param Context NULL
2046
2047 **/
2048 VOID
2049 EFIAPI
2050 DnsOnTimerUpdate (
2051 IN EFI_EVENT Event,
2052 IN VOID *Context
2053 )
2054 {
2055 LIST_ENTRY *Entry;
2056 LIST_ENTRY *Next;
2057 DNS4_CACHE *Item4;
2058 DNS6_CACHE *Item6;
2059
2060 Item4 = NULL;
2061 Item6 = NULL;
2062
2063 //
2064 // Iterate through all the DNS4 cache list.
2065 //
2066 NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) {
2067 Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
2068 Item4->DnsCache.Timeout--;
2069 }
2070
2071 Entry = mDriverData->Dns4CacheList.ForwardLink;
2072 while (Entry != &mDriverData->Dns4CacheList) {
2073 Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
2074 if (Item4->DnsCache.Timeout<=0) {
2075 RemoveEntryList (&Item4->AllCacheLink);
2076 Entry = mDriverData->Dns4CacheList.ForwardLink;
2077 } else {
2078 Entry = Entry->ForwardLink;
2079 }
2080 }
2081
2082 //
2083 // Iterate through all the DNS6 cache list.
2084 //
2085 NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6CacheList) {
2086 Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
2087 Item6->DnsCache.Timeout--;
2088 }
2089
2090 Entry = mDriverData->Dns6CacheList.ForwardLink;
2091 while (Entry != &mDriverData->Dns6CacheList) {
2092 Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
2093 if (Item6->DnsCache.Timeout<=0) {
2094 RemoveEntryList (&Item6->AllCacheLink);
2095 Entry = mDriverData->Dns6CacheList.ForwardLink;
2096 } else {
2097 Entry = Entry->ForwardLink;
2098 }
2099 }
2100 }
2101