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