]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/DnsDxe/DnsImpl.c
26a718987cc00451a782898ee2c9fae2b7661aeb
[mirror_edk2.git] / NetworkPkg / DnsDxe / DnsImpl.c
1 /** @file
2 DnsDxe support functions implementation.
3
4 Copyright (c) 2016 - 2018, 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 Length Received buffer length.
1118 @param Completed Flag to indicate that Dns response is valid.
1119
1120 @retval EFI_SUCCESS Parse Dns Response successfully.
1121 @retval Others Failed to parse Dns Response.
1122
1123 **/
1124 EFI_STATUS
1125 ParseDnsResponse (
1126 IN OUT DNS_INSTANCE *Instance,
1127 IN UINT8 *RxString,
1128 IN UINT32 Length,
1129 OUT BOOLEAN *Completed
1130 )
1131 {
1132 DNS_HEADER *DnsHeader;
1133
1134 CHAR8 *QueryName;
1135 UINT32 QueryNameLen;
1136 DNS_QUERY_SECTION *QuerySection;
1137
1138 CHAR8 *AnswerName;
1139 DNS_ANSWER_SECTION *AnswerSection;
1140 UINT8 *AnswerData;
1141
1142 NET_MAP_ITEM *Item;
1143 DNS4_TOKEN_ENTRY *Dns4TokenEntry;
1144 DNS6_TOKEN_ENTRY *Dns6TokenEntry;
1145
1146 UINT32 IpCount;
1147 UINT32 RRCount;
1148 UINT32 AnswerSectionNum;
1149 UINT32 CNameTtl;
1150
1151 EFI_IPv4_ADDRESS *HostAddr4;
1152 EFI_IPv6_ADDRESS *HostAddr6;
1153
1154 EFI_DNS4_CACHE_ENTRY *Dns4CacheEntry;
1155 EFI_DNS6_CACHE_ENTRY *Dns6CacheEntry;
1156
1157 DNS_RESOURCE_RECORD *Dns4RR;
1158 DNS6_RESOURCE_RECORD *Dns6RR;
1159
1160 EFI_STATUS Status;
1161 UINT32 RemainingLength;
1162
1163 EFI_TPL OldTpl;
1164
1165 Item = NULL;
1166 Dns4TokenEntry = NULL;
1167 Dns6TokenEntry = NULL;
1168
1169 IpCount = 0;
1170 RRCount = 0;
1171 AnswerSectionNum = 0;
1172 CNameTtl = 0;
1173
1174 HostAddr4 = NULL;
1175 HostAddr6 = NULL;
1176
1177 Dns4CacheEntry = NULL;
1178 Dns6CacheEntry = NULL;
1179
1180 Dns4RR = NULL;
1181 Dns6RR = NULL;
1182
1183 *Completed = TRUE;
1184 Status = EFI_SUCCESS;
1185 RemainingLength = Length;
1186
1187 //
1188 // Check whether the remaining packet length is avaiable or not.
1189 //
1190 if (RemainingLength <= sizeof (DNS_HEADER)) {
1191 *Completed = FALSE;
1192 return EFI_ABORTED;
1193 } else {
1194 RemainingLength -= sizeof (DNS_HEADER);
1195 }
1196
1197 //
1198 // Get header
1199 //
1200 DnsHeader = (DNS_HEADER *) RxString;
1201
1202 DnsHeader->Identification = NTOHS (DnsHeader->Identification);
1203 DnsHeader->Flags.Uint16 = NTOHS (DnsHeader->Flags.Uint16);
1204 DnsHeader->QuestionsNum = NTOHS (DnsHeader->QuestionsNum);
1205 DnsHeader->AnswersNum = NTOHS (DnsHeader->AnswersNum);
1206 DnsHeader->AuthorityNum = NTOHS (DnsHeader->AuthorityNum);
1207 DnsHeader->AditionalNum = NTOHS (DnsHeader->AditionalNum);
1208
1209 //
1210 // There is always one QuestionsNum in DNS message. The capability to handle more
1211 // than one requires to redesign the message format. Currently, it's not supported.
1212 //
1213 if (DnsHeader->QuestionsNum > 1) {
1214 *Completed = FALSE;
1215 return EFI_UNSUPPORTED;
1216 }
1217
1218 //
1219 // Get Query name
1220 //
1221 QueryName = (CHAR8 *) (RxString + sizeof (*DnsHeader));
1222
1223 QueryNameLen = (UINT32) AsciiStrLen (QueryName) + 1;
1224
1225 //
1226 // Check whether the remaining packet length is avaiable or not.
1227 //
1228 if (RemainingLength <= QueryNameLen + sizeof (DNS_QUERY_SECTION)) {
1229 *Completed = FALSE;
1230 return EFI_ABORTED;
1231 } else {
1232 RemainingLength -= (QueryNameLen + sizeof (DNS_QUERY_SECTION));
1233 }
1234
1235 //
1236 // Get query section
1237 //
1238 QuerySection = (DNS_QUERY_SECTION *) (QueryName + QueryNameLen);
1239 QuerySection->Type = NTOHS (QuerySection->Type);
1240 QuerySection->Class = NTOHS (QuerySection->Class);
1241
1242 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1243
1244 //
1245 // Check DnsResponse Validity, if so, also get a valid NET_MAP_ITEM.
1246 //
1247 if (Instance->Service->IpVersion == IP_VERSION_4) {
1248 if (!IsValidDnsResponse (
1249 &Instance->Dns4TxTokens,
1250 DnsHeader->Identification,
1251 QuerySection->Type,
1252 QuerySection->Class,
1253 &Item
1254 )) {
1255 *Completed = FALSE;
1256 Status = EFI_ABORTED;
1257 goto ON_EXIT;
1258 }
1259 ASSERT (Item != NULL);
1260 Dns4TokenEntry = (DNS4_TOKEN_ENTRY *) (Item->Key);
1261 } else {
1262 if (!IsValidDnsResponse (
1263 &Instance->Dns6TxTokens,
1264 DnsHeader->Identification,
1265 QuerySection->Type,
1266 QuerySection->Class,
1267 &Item
1268 )) {
1269 *Completed = FALSE;
1270 Status = EFI_ABORTED;
1271 goto ON_EXIT;
1272 }
1273 ASSERT (Item != NULL);
1274 Dns6TokenEntry = (DNS6_TOKEN_ENTRY *) (Item->Key);
1275 }
1276
1277 //
1278 // Continue Check Some Errors.
1279 //
1280 if (DnsHeader->Flags.Bits.RCode != DNS_FLAGS_RCODE_NO_ERROR || DnsHeader->AnswersNum < 1 || \
1281 DnsHeader->Flags.Bits.QR != DNS_FLAGS_QR_RESPONSE) {
1282 //
1283 // The domain name referenced in the query does not exist.
1284 //
1285 if (DnsHeader->Flags.Bits.RCode == DNS_FLAGS_RCODE_NAME_ERROR) {
1286 Status = EFI_NOT_FOUND;
1287 } else {
1288 Status = EFI_DEVICE_ERROR;
1289 }
1290
1291 goto ON_COMPLETE;
1292 }
1293
1294 //
1295 // Do some buffer allocations.
1296 //
1297 if (Instance->Service->IpVersion == IP_VERSION_4) {
1298 ASSERT (Dns4TokenEntry != NULL);
1299
1300 if (Dns4TokenEntry->GeneralLookUp) {
1301 //
1302 // It's the GeneralLookUp querying.
1303 //
1304 Dns4TokenEntry->Token->RspData.GLookupData = AllocateZeroPool (sizeof (DNS_RESOURCE_RECORD));
1305 if (Dns4TokenEntry->Token->RspData.GLookupData == NULL) {
1306 Status = EFI_OUT_OF_RESOURCES;
1307 goto ON_EXIT;
1308 }
1309 Dns4TokenEntry->Token->RspData.GLookupData->RRList = AllocateZeroPool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD));
1310 if (Dns4TokenEntry->Token->RspData.GLookupData->RRList == NULL) {
1311 Status = EFI_OUT_OF_RESOURCES;
1312 goto ON_EXIT;
1313 }
1314 } else {
1315 //
1316 // It's not the GeneralLookUp querying. Check the Query type.
1317 //
1318 if (QuerySection->Type == DNS_TYPE_A) {
1319 Dns4TokenEntry->Token->RspData.H2AData = AllocateZeroPool (sizeof (DNS_HOST_TO_ADDR_DATA));
1320 if (Dns4TokenEntry->Token->RspData.H2AData == NULL) {
1321 Status = EFI_OUT_OF_RESOURCES;
1322 goto ON_EXIT;
1323 }
1324 Dns4TokenEntry->Token->RspData.H2AData->IpList = AllocateZeroPool (DnsHeader->AnswersNum * sizeof (EFI_IPv4_ADDRESS));
1325 if (Dns4TokenEntry->Token->RspData.H2AData->IpList == NULL) {
1326 Status = EFI_OUT_OF_RESOURCES;
1327 goto ON_EXIT;
1328 }
1329 } else {
1330 Status = EFI_UNSUPPORTED;
1331 goto ON_EXIT;
1332 }
1333 }
1334 } else {
1335 ASSERT (Dns6TokenEntry != NULL);
1336
1337 if (Dns6TokenEntry->GeneralLookUp) {
1338 //
1339 // It's the GeneralLookUp querying.
1340 //
1341 Dns6TokenEntry->Token->RspData.GLookupData = AllocateZeroPool (sizeof (DNS_RESOURCE_RECORD));
1342 if (Dns6TokenEntry->Token->RspData.GLookupData == NULL) {
1343 Status = EFI_OUT_OF_RESOURCES;
1344 goto ON_EXIT;
1345 }
1346 Dns6TokenEntry->Token->RspData.GLookupData->RRList = AllocateZeroPool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD));
1347 if (Dns6TokenEntry->Token->RspData.GLookupData->RRList == NULL) {
1348 Status = EFI_OUT_OF_RESOURCES;
1349 goto ON_EXIT;
1350 }
1351 } else {
1352 //
1353 // It's not the GeneralLookUp querying. Check the Query type.
1354 //
1355 if (QuerySection->Type == DNS_TYPE_AAAA) {
1356 Dns6TokenEntry->Token->RspData.H2AData = AllocateZeroPool (sizeof (DNS6_HOST_TO_ADDR_DATA));
1357 if (Dns6TokenEntry->Token->RspData.H2AData == NULL) {
1358 Status = EFI_OUT_OF_RESOURCES;
1359 goto ON_EXIT;
1360 }
1361 Dns6TokenEntry->Token->RspData.H2AData->IpList = AllocateZeroPool (DnsHeader->AnswersNum * sizeof (EFI_IPv6_ADDRESS));
1362 if (Dns6TokenEntry->Token->RspData.H2AData->IpList == NULL) {
1363 Status = EFI_OUT_OF_RESOURCES;
1364 goto ON_EXIT;
1365 }
1366 } else {
1367 Status = EFI_UNSUPPORTED;
1368 goto ON_EXIT;
1369 }
1370 }
1371 }
1372
1373 Status = EFI_NOT_FOUND;
1374
1375 //
1376 // Get Answer name
1377 //
1378 AnswerName = (CHAR8 *) QuerySection + sizeof (*QuerySection);
1379
1380 //
1381 // Processing AnswerSection.
1382 //
1383 while (AnswerSectionNum < DnsHeader->AnswersNum) {
1384 //
1385 // Check whether the remaining packet length is avaiable or not.
1386 //
1387 if (RemainingLength <= sizeof (UINT16) + sizeof (DNS_ANSWER_SECTION)) {
1388 *Completed = FALSE;
1389 Status = EFI_ABORTED;
1390 goto ON_EXIT;
1391 } else {
1392 RemainingLength -= (sizeof (UINT16) + sizeof (DNS_ANSWER_SECTION));
1393 }
1394
1395 //
1396 // Answer name should be PTR, else EFI_UNSUPPORTED returned.
1397 //
1398 if ((*(UINT8 *) AnswerName & 0xC0) != 0xC0) {
1399 Status = EFI_UNSUPPORTED;
1400 goto ON_EXIT;
1401 }
1402
1403 //
1404 // Get Answer section.
1405 //
1406 AnswerSection = (DNS_ANSWER_SECTION *) (AnswerName + sizeof (UINT16));
1407 AnswerSection->Type = NTOHS (AnswerSection->Type);
1408 AnswerSection->Class = NTOHS (AnswerSection->Class);
1409 AnswerSection->Ttl = NTOHL (AnswerSection->Ttl);
1410 AnswerSection->DataLength = NTOHS (AnswerSection->DataLength);
1411
1412 //
1413 // Check whether the remaining packet length is avaiable or not.
1414 //
1415 if (RemainingLength < AnswerSection->DataLength) {
1416 *Completed = FALSE;
1417 Status = EFI_ABORTED;
1418 goto ON_EXIT;
1419 } else {
1420 RemainingLength -= AnswerSection->DataLength;
1421 }
1422
1423 //
1424 // Check whether it's the GeneralLookUp querying.
1425 //
1426 if (Instance->Service->IpVersion == IP_VERSION_4 && Dns4TokenEntry->GeneralLookUp) {
1427 Dns4RR = Dns4TokenEntry->Token->RspData.GLookupData->RRList;
1428 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
1429
1430 //
1431 // Fill the ResourceRecord.
1432 //
1433 Dns4RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1);
1434 if (Dns4RR[RRCount].QName == NULL) {
1435 Status = EFI_OUT_OF_RESOURCES;
1436 goto ON_EXIT;
1437 }
1438 CopyMem (Dns4RR[RRCount].QName, QueryName, AsciiStrLen (QueryName));
1439 Dns4RR[RRCount].QType = AnswerSection->Type;
1440 Dns4RR[RRCount].QClass = AnswerSection->Class;
1441 Dns4RR[RRCount].TTL = AnswerSection->Ttl;
1442 Dns4RR[RRCount].DataLength = AnswerSection->DataLength;
1443 Dns4RR[RRCount].RData = AllocateZeroPool (Dns4RR[RRCount].DataLength);
1444 if (Dns4RR[RRCount].RData == NULL) {
1445 Status = EFI_OUT_OF_RESOURCES;
1446 goto ON_EXIT;
1447 }
1448 CopyMem (Dns4RR[RRCount].RData, AnswerData, Dns4RR[RRCount].DataLength);
1449
1450 RRCount ++;
1451 Status = EFI_SUCCESS;
1452 } else if (Instance->Service->IpVersion == IP_VERSION_6 && Dns6TokenEntry->GeneralLookUp) {
1453 Dns6RR = Dns6TokenEntry->Token->RspData.GLookupData->RRList;
1454 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
1455
1456 //
1457 // Fill the ResourceRecord.
1458 //
1459 Dns6RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1);
1460 if (Dns6RR[RRCount].QName == NULL) {
1461 Status = EFI_OUT_OF_RESOURCES;
1462 goto ON_EXIT;
1463 }
1464 CopyMem (Dns6RR[RRCount].QName, QueryName, AsciiStrLen (QueryName));
1465 Dns6RR[RRCount].QType = AnswerSection->Type;
1466 Dns6RR[RRCount].QClass = AnswerSection->Class;
1467 Dns6RR[RRCount].TTL = AnswerSection->Ttl;
1468 Dns6RR[RRCount].DataLength = AnswerSection->DataLength;
1469 Dns6RR[RRCount].RData = AllocateZeroPool (Dns6RR[RRCount].DataLength);
1470 if (Dns6RR[RRCount].RData == NULL) {
1471 Status = EFI_OUT_OF_RESOURCES;
1472 goto ON_EXIT;
1473 }
1474 CopyMem (Dns6RR[RRCount].RData, AnswerData, Dns6RR[RRCount].DataLength);
1475
1476 RRCount ++;
1477 Status = EFI_SUCCESS;
1478 } else {
1479 //
1480 // It's not the GeneralLookUp querying.
1481 // Check the Query type, parse the response packet.
1482 //
1483 switch (AnswerSection->Type) {
1484 case DNS_TYPE_A:
1485 //
1486 // This is address entry, get Data.
1487 //
1488 ASSERT (Dns4TokenEntry != NULL);
1489
1490 if (AnswerSection->DataLength != 4) {
1491 Status = EFI_ABORTED;
1492 goto ON_EXIT;
1493 }
1494
1495 HostAddr4 = Dns4TokenEntry->Token->RspData.H2AData->IpList;
1496 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
1497 CopyMem (&HostAddr4[IpCount], AnswerData, sizeof (EFI_IPv4_ADDRESS));
1498
1499 //
1500 // Allocate new CacheEntry pool to update DNS cache dynamically.
1501 //
1502 Dns4CacheEntry = AllocateZeroPool (sizeof (EFI_DNS4_CACHE_ENTRY));
1503 if (Dns4CacheEntry == NULL) {
1504 Status = EFI_OUT_OF_RESOURCES;
1505 goto ON_EXIT;
1506 }
1507 Dns4CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1));
1508 if (Dns4CacheEntry->HostName == NULL) {
1509 Status = EFI_OUT_OF_RESOURCES;
1510 goto ON_EXIT;
1511 }
1512 CopyMem (Dns4CacheEntry->HostName, Dns4TokenEntry->QueryHostName, 2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1));
1513 Dns4CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv4_ADDRESS));
1514 if (Dns4CacheEntry->IpAddress == NULL) {
1515 Status = EFI_OUT_OF_RESOURCES;
1516 goto ON_EXIT;
1517 }
1518 CopyMem (Dns4CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv4_ADDRESS));
1519
1520 if (CNameTtl != 0 && AnswerSection->Ttl != 0) {
1521 Dns4CacheEntry->Timeout = MIN (CNameTtl, AnswerSection->Ttl);
1522 } else {
1523 Dns4CacheEntry->Timeout = MAX (CNameTtl, AnswerSection->Ttl);
1524 }
1525
1526 UpdateDns4Cache (&mDriverData->Dns4CacheList, FALSE, TRUE, *Dns4CacheEntry);
1527
1528 //
1529 // Free allocated CacheEntry pool.
1530 //
1531 FreePool (Dns4CacheEntry->HostName);
1532 Dns4CacheEntry->HostName = NULL;
1533
1534 FreePool (Dns4CacheEntry->IpAddress);
1535 Dns4CacheEntry->IpAddress = NULL;
1536
1537 FreePool (Dns4CacheEntry);
1538 Dns4CacheEntry = NULL;
1539
1540 IpCount ++;
1541 Status = EFI_SUCCESS;
1542 break;
1543 case DNS_TYPE_AAAA:
1544 //
1545 // This is address entry, get Data.
1546 //
1547 ASSERT (Dns6TokenEntry != NULL);
1548
1549 if (AnswerSection->DataLength != 16) {
1550 Status = EFI_ABORTED;
1551 goto ON_EXIT;
1552 }
1553
1554 HostAddr6 = Dns6TokenEntry->Token->RspData.H2AData->IpList;
1555 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
1556 CopyMem (&HostAddr6[IpCount], AnswerData, sizeof (EFI_IPv6_ADDRESS));
1557
1558 //
1559 // Allocate new CacheEntry pool to update DNS cache dynamically.
1560 //
1561 Dns6CacheEntry = AllocateZeroPool (sizeof (EFI_DNS6_CACHE_ENTRY));
1562 if (Dns6CacheEntry == NULL) {
1563 Status = EFI_OUT_OF_RESOURCES;
1564 goto ON_EXIT;
1565 }
1566 Dns6CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1));
1567 if (Dns6CacheEntry->HostName == NULL) {
1568 Status = EFI_OUT_OF_RESOURCES;
1569 goto ON_EXIT;
1570 }
1571 CopyMem (Dns6CacheEntry->HostName, Dns6TokenEntry->QueryHostName, 2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1));
1572 Dns6CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS));
1573 if (Dns6CacheEntry->IpAddress == NULL) {
1574 Status = EFI_OUT_OF_RESOURCES;
1575 goto ON_EXIT;
1576 }
1577 CopyMem (Dns6CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv6_ADDRESS));
1578
1579 if (CNameTtl != 0 && AnswerSection->Ttl != 0) {
1580 Dns6CacheEntry->Timeout = MIN (CNameTtl, AnswerSection->Ttl);
1581 } else {
1582 Dns6CacheEntry->Timeout = MAX (CNameTtl, AnswerSection->Ttl);
1583 }
1584
1585 UpdateDns6Cache (&mDriverData->Dns6CacheList, FALSE, TRUE, *Dns6CacheEntry);
1586
1587 //
1588 // Free allocated CacheEntry pool.
1589 //
1590 FreePool (Dns6CacheEntry->HostName);
1591 Dns6CacheEntry->HostName = NULL;
1592
1593 FreePool (Dns6CacheEntry->IpAddress);
1594 Dns6CacheEntry->IpAddress = NULL;
1595
1596 FreePool (Dns6CacheEntry);
1597 Dns6CacheEntry = NULL;
1598
1599 IpCount ++;
1600 Status = EFI_SUCCESS;
1601 break;
1602 case DNS_TYPE_CNAME:
1603 //
1604 // According RFC 1034 - 3.6.2, if the query name is an alias, the name server will include the CNAME
1605 // record in the response and restart the query at the domain name specified in the data field of the
1606 // CNAME record. So, just record the TTL value of the CNAME, then skip to parse the next record.
1607 //
1608 CNameTtl = AnswerSection->Ttl;
1609 break;
1610 default:
1611 Status = EFI_UNSUPPORTED;
1612 goto ON_EXIT;
1613 }
1614 }
1615
1616 //
1617 // Find next one
1618 //
1619 AnswerName = (CHAR8 *) AnswerSection + sizeof (*AnswerSection) + AnswerSection->DataLength;
1620 AnswerSectionNum ++;
1621 }
1622
1623 if (Instance->Service->IpVersion == IP_VERSION_4) {
1624 ASSERT (Dns4TokenEntry != NULL);
1625
1626 if (Dns4TokenEntry->GeneralLookUp) {
1627 Dns4TokenEntry->Token->RspData.GLookupData->RRCount = RRCount;
1628 } else {
1629 if (QuerySection->Type == DNS_TYPE_A) {
1630 Dns4TokenEntry->Token->RspData.H2AData->IpCount = IpCount;
1631 } else {
1632 Status = EFI_UNSUPPORTED;
1633 goto ON_EXIT;
1634 }
1635 }
1636 } else {
1637 ASSERT (Dns6TokenEntry != NULL);
1638
1639 if (Dns6TokenEntry->GeneralLookUp) {
1640 Dns6TokenEntry->Token->RspData.GLookupData->RRCount = RRCount;
1641 } else {
1642 if (QuerySection->Type == DNS_TYPE_AAAA) {
1643 Dns6TokenEntry->Token->RspData.H2AData->IpCount = IpCount;
1644 } else {
1645 Status = EFI_UNSUPPORTED;
1646 goto ON_EXIT;
1647 }
1648 }
1649 }
1650
1651 ON_COMPLETE:
1652 //
1653 // Parsing is complete, free the sending packet and signal Event here.
1654 //
1655 if (Item != NULL && Item->Value != NULL) {
1656 NetbufFree ((NET_BUF *) (Item->Value));
1657 }
1658
1659 if (Instance->Service->IpVersion == IP_VERSION_4) {
1660 ASSERT (Dns4TokenEntry != NULL);
1661 Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry);
1662 Dns4TokenEntry->Token->Status = Status;
1663 if (Dns4TokenEntry->Token->Event != NULL) {
1664 gBS->SignalEvent (Dns4TokenEntry->Token->Event);
1665 DispatchDpc ();
1666 }
1667 } else {
1668 ASSERT (Dns6TokenEntry != NULL);
1669 Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry);
1670 Dns6TokenEntry->Token->Status = Status;
1671 if (Dns6TokenEntry->Token->Event != NULL) {
1672 gBS->SignalEvent (Dns6TokenEntry->Token->Event);
1673 DispatchDpc ();
1674 }
1675 }
1676
1677 ON_EXIT:
1678 //
1679 // Free the allocated buffer if error happen.
1680 //
1681 if (EFI_ERROR (Status)) {
1682 if (Dns4TokenEntry != NULL) {
1683 if (Dns4TokenEntry->GeneralLookUp) {
1684 if (Dns4TokenEntry->Token->RspData.GLookupData != NULL) {
1685 if (Dns4TokenEntry->Token->RspData.GLookupData->RRList != NULL) {
1686 while (RRCount != 0) {
1687 RRCount --;
1688 if (Dns4TokenEntry->Token->RspData.GLookupData->RRList[RRCount].QName != NULL) {
1689 FreePool (Dns4TokenEntry->Token->RspData.GLookupData->RRList[RRCount].QName);
1690 }
1691
1692 if (Dns4TokenEntry->Token->RspData.GLookupData->RRList[RRCount].RData != NULL) {
1693 FreePool (Dns4TokenEntry->Token->RspData.GLookupData->RRList[RRCount].RData);
1694 }
1695 }
1696
1697 FreePool (Dns4TokenEntry->Token->RspData.GLookupData->RRList);
1698 }
1699
1700 FreePool (Dns4TokenEntry->Token->RspData.GLookupData);
1701 }
1702 } else {
1703 if (QuerySection->Type == DNS_TYPE_A && Dns4TokenEntry->Token->RspData.H2AData != NULL) {
1704 if (Dns4TokenEntry->Token->RspData.H2AData->IpList != NULL) {
1705 FreePool (Dns4TokenEntry->Token->RspData.H2AData->IpList);
1706 }
1707
1708 FreePool (Dns4TokenEntry->Token->RspData.H2AData);
1709 }
1710 }
1711 }
1712
1713 if (Dns6TokenEntry != NULL) {
1714 if (Dns6TokenEntry->GeneralLookUp) {
1715 if (Dns6TokenEntry->Token->RspData.GLookupData != NULL) {
1716 if (Dns6TokenEntry->Token->RspData.GLookupData->RRList != NULL) {
1717 while (RRCount != 0) {
1718 RRCount --;
1719 if (Dns6TokenEntry->Token->RspData.GLookupData->RRList[RRCount].QName != NULL) {
1720 FreePool (Dns6TokenEntry->Token->RspData.GLookupData->RRList[RRCount].QName);
1721 }
1722
1723 if (Dns6TokenEntry->Token->RspData.GLookupData->RRList[RRCount].RData != NULL) {
1724 FreePool (Dns6TokenEntry->Token->RspData.GLookupData->RRList[RRCount].RData);
1725 }
1726 }
1727
1728 FreePool (Dns6TokenEntry->Token->RspData.GLookupData->RRList);
1729 }
1730
1731 FreePool (Dns6TokenEntry->Token->RspData.GLookupData);
1732 }
1733 } else {
1734 if (QuerySection->Type == DNS_TYPE_AAAA && Dns6TokenEntry->Token->RspData.H2AData != NULL) {
1735 if (Dns6TokenEntry->Token->RspData.H2AData->IpList != NULL) {
1736 FreePool (Dns6TokenEntry->Token->RspData.H2AData->IpList);
1737 }
1738
1739 FreePool (Dns6TokenEntry->Token->RspData.H2AData);
1740 }
1741 }
1742 }
1743
1744 if (Dns4CacheEntry != NULL) {
1745 if (Dns4CacheEntry->HostName != NULL) {
1746 FreePool (Dns4CacheEntry->HostName);
1747 }
1748
1749 if (Dns4CacheEntry->IpAddress != NULL) {
1750 FreePool (Dns4CacheEntry->IpAddress);
1751 }
1752
1753 FreePool (Dns4CacheEntry);
1754 }
1755
1756 if (Dns6CacheEntry != NULL) {
1757 if (Dns6CacheEntry->HostName != NULL) {
1758 FreePool (Dns6CacheEntry->HostName);
1759 }
1760
1761 if (Dns6CacheEntry->IpAddress != NULL) {
1762 FreePool (Dns6CacheEntry->IpAddress);
1763 }
1764
1765 FreePool (Dns6CacheEntry);
1766 }
1767 }
1768
1769 gBS->RestoreTPL (OldTpl);
1770 return Status;
1771 }
1772
1773 /**
1774 Parse response packet.
1775
1776 @param Packet The packets received.
1777 @param EndPoint The local/remote UDP access point
1778 @param IoStatus The status of the UDP receive
1779 @param Context The opaque parameter to the function.
1780
1781 **/
1782 VOID
1783 EFIAPI
1784 DnsOnPacketReceived (
1785 NET_BUF *Packet,
1786 UDP_END_POINT *EndPoint,
1787 EFI_STATUS IoStatus,
1788 VOID *Context
1789 )
1790 {
1791 DNS_INSTANCE *Instance;
1792
1793 UINT8 *RcvString;
1794 UINT32 Len;
1795
1796 BOOLEAN Completed;
1797
1798 Instance = (DNS_INSTANCE *) Context;
1799 NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE);
1800
1801 RcvString = NULL;
1802 Completed = FALSE;
1803
1804 if (EFI_ERROR (IoStatus)) {
1805 goto ON_EXIT;
1806 }
1807
1808 ASSERT (Packet != NULL);
1809
1810 Len = Packet->TotalSize;
1811
1812 RcvString = NetbufGetByte (Packet, 0, NULL);
1813 ASSERT (RcvString != NULL);
1814
1815 //
1816 // Parse Dns Response
1817 //
1818 ParseDnsResponse (Instance, RcvString, Len, &Completed);
1819
1820 ON_EXIT:
1821
1822 if (Packet != NULL) {
1823 NetbufFree (Packet);
1824 }
1825
1826 if (!Completed) {
1827 UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);
1828 }
1829 }
1830
1831 /**
1832 Release the net buffer when packet is sent.
1833
1834 @param Packet The packets received.
1835 @param EndPoint The local/remote UDP access point
1836 @param IoStatus The status of the UDP receive
1837 @param Context The opaque parameter to the function.
1838
1839 **/
1840 VOID
1841 EFIAPI
1842 DnsOnPacketSent (
1843 NET_BUF *Packet,
1844 UDP_END_POINT *EndPoint,
1845 EFI_STATUS IoStatus,
1846 VOID *Context
1847 )
1848 {
1849 DNS_INSTANCE *Instance;
1850 LIST_ENTRY *Entry;
1851 NET_MAP_ITEM *Item;
1852 DNS4_TOKEN_ENTRY *Dns4TokenEntry;
1853 DNS6_TOKEN_ENTRY *Dns6TokenEntry;
1854
1855 Dns4TokenEntry = NULL;
1856 Dns6TokenEntry = NULL;
1857
1858 Instance = (DNS_INSTANCE *) Context;
1859 NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE);
1860
1861 if (Instance->Service->IpVersion == IP_VERSION_4) {
1862 NET_LIST_FOR_EACH (Entry, &Instance->Dns4TxTokens.Used) {
1863 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1864 if (Packet == (NET_BUF *)(Item->Value)) {
1865 Dns4TokenEntry = ((DNS4_TOKEN_ENTRY *)Item->Key);
1866 Dns4TokenEntry->PacketToLive = Dns4TokenEntry->Token->RetryInterval;
1867 break;
1868 }
1869 }
1870 } else {
1871 NET_LIST_FOR_EACH (Entry, &Instance->Dns6TxTokens.Used) {
1872 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1873 if (Packet == (NET_BUF *)(Item->Value)) {
1874 Dns6TokenEntry = ((DNS6_TOKEN_ENTRY *)Item->Key);
1875 Dns6TokenEntry->PacketToLive = Dns6TokenEntry->Token->RetryInterval;
1876 break;
1877 }
1878 }
1879 }
1880
1881 NetbufFree (Packet);
1882 }
1883
1884 /**
1885 Query request information.
1886
1887 @param Instance The DNS instance
1888 @param Packet The packet for querying request information.
1889
1890 @retval EFI_SUCCESS Query request information successfully.
1891 @retval Others Failed to query request information.
1892
1893 **/
1894 EFI_STATUS
1895 DoDnsQuery (
1896 IN DNS_INSTANCE *Instance,
1897 IN NET_BUF *Packet
1898 )
1899 {
1900 EFI_STATUS Status;
1901
1902 //
1903 // Ready to receive the DNS response.
1904 //
1905 if (Instance->UdpIo->RecvRequest == NULL) {
1906 Status = UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);
1907 if (EFI_ERROR (Status)) {
1908 return Status;
1909 }
1910 }
1911
1912 //
1913 // Transmit the DNS packet.
1914 //
1915 NET_GET_REF (Packet);
1916
1917 Status = UdpIoSendDatagram (Instance->UdpIo, Packet, NULL, NULL, DnsOnPacketSent, Instance);
1918
1919 return Status;
1920 }
1921
1922 /**
1923 Construct the Packet according query section.
1924
1925 @param Instance The DNS instance
1926 @param QueryName Queried Name
1927 @param Type Queried Type
1928 @param Class Queried Class
1929 @param Packet The packet for query
1930
1931 @retval EFI_SUCCESS The packet is constructed.
1932 @retval Others Failed to construct the Packet.
1933
1934 **/
1935 EFI_STATUS
1936 ConstructDNSQuery (
1937 IN DNS_INSTANCE *Instance,
1938 IN CHAR8 *QueryName,
1939 IN UINT16 Type,
1940 IN UINT16 Class,
1941 OUT NET_BUF **Packet
1942 )
1943 {
1944 NET_FRAGMENT Frag;
1945 DNS_HEADER *DnsHeader;
1946 DNS_QUERY_SECTION *DnsQuery;
1947
1948 //
1949 // Messages carried by UDP are restricted to 512 bytes (not counting the IP
1950 // or UDP headers).
1951 //
1952 Frag.Bulk = AllocatePool (DNS_MAX_MESSAGE_SIZE * sizeof (UINT8));
1953 if (Frag.Bulk == NULL) {
1954 return EFI_OUT_OF_RESOURCES;
1955 }
1956
1957 //
1958 // Fill header
1959 //
1960 DnsHeader = (DNS_HEADER *) Frag.Bulk;
1961 DnsHeader->Identification = (UINT16)NET_RANDOM (NetRandomInitSeed());
1962 DnsHeader->Flags.Uint16 = 0x0000;
1963 DnsHeader->Flags.Bits.RD = 1;
1964 DnsHeader->Flags.Bits.OpCode = DNS_FLAGS_OPCODE_STANDARD;
1965 DnsHeader->Flags.Bits.QR = DNS_FLAGS_QR_QUERY;
1966 DnsHeader->QuestionsNum = 1;
1967 DnsHeader->AnswersNum = 0;
1968 DnsHeader->AuthorityNum = 0;
1969 DnsHeader->AditionalNum = 0;
1970
1971 DnsHeader->Identification = HTONS (DnsHeader->Identification);
1972 DnsHeader->Flags.Uint16 = HTONS (DnsHeader->Flags.Uint16);
1973 DnsHeader->QuestionsNum = HTONS (DnsHeader->QuestionsNum);
1974 DnsHeader->AnswersNum = HTONS (DnsHeader->AnswersNum);
1975 DnsHeader->AuthorityNum = HTONS (DnsHeader->AuthorityNum);
1976 DnsHeader->AditionalNum = HTONS (DnsHeader->AditionalNum);
1977
1978 Frag.Len = sizeof (*DnsHeader);
1979
1980 //
1981 // Fill Query name
1982 //
1983 CopyMem (Frag.Bulk + Frag.Len, QueryName, AsciiStrLen (QueryName));
1984 Frag.Len = (UINT32) (Frag.Len + AsciiStrLen (QueryName));
1985 *(Frag.Bulk + Frag.Len) = 0;
1986 Frag.Len ++;
1987
1988 //
1989 // Rest query section
1990 //
1991 DnsQuery = (DNS_QUERY_SECTION *) (Frag.Bulk + Frag.Len);
1992
1993 DnsQuery->Type = HTONS (Type);
1994 DnsQuery->Class = HTONS (Class);
1995
1996 Frag.Len += sizeof (*DnsQuery);
1997
1998 //
1999 // Wrap the Frag in a net buffer.
2000 //
2001 *Packet = NetbufFromExt (&Frag, 1, 0, 0, DnsDummyExtFree, NULL);
2002 if (*Packet == NULL) {
2003 FreePool (Frag.Bulk);
2004 return EFI_OUT_OF_RESOURCES;
2005 }
2006
2007 //
2008 // Store the UdpIo in ProtoData.
2009 //
2010 *((UINTN *) &((*Packet)->ProtoData[0])) = (UINTN) (Instance->UdpIo);
2011
2012 return EFI_SUCCESS;
2013 }
2014
2015 /**
2016 Retransmit the packet.
2017
2018 @param Instance The DNS instance
2019 @param Packet Retransmit the packet
2020
2021 @retval EFI_SUCCESS The packet is retransmitted.
2022 @retval Others Failed to retransmit.
2023
2024 **/
2025 EFI_STATUS
2026 DnsRetransmit (
2027 IN DNS_INSTANCE *Instance,
2028 IN NET_BUF *Packet
2029 )
2030 {
2031 EFI_STATUS Status;
2032
2033 UINT8 *Buffer;
2034
2035 ASSERT (Packet != NULL);
2036
2037 //
2038 // Set the requests to the listening port, other packets to the connected port
2039 //
2040 Buffer = NetbufGetByte (Packet, 0, NULL);
2041 ASSERT (Buffer != NULL);
2042
2043 NET_GET_REF (Packet);
2044
2045 Status = UdpIoSendDatagram (
2046 Instance->UdpIo,
2047 Packet,
2048 NULL,
2049 NULL,
2050 DnsOnPacketSent,
2051 Instance
2052 );
2053
2054 if (EFI_ERROR (Status)) {
2055 NET_PUT_REF (Packet);
2056 }
2057
2058 return Status;
2059 }
2060
2061 /**
2062 The timer ticking function for the DNS services.
2063
2064 @param Event The ticking event
2065 @param Context The DNS service instance
2066
2067 **/
2068 VOID
2069 EFIAPI
2070 DnsOnTimerRetransmit (
2071 IN EFI_EVENT Event,
2072 IN VOID *Context
2073 )
2074 {
2075 DNS_SERVICE *Service;
2076
2077 LIST_ENTRY *Entry;
2078 LIST_ENTRY *Next;
2079
2080 DNS_INSTANCE *Instance;
2081 LIST_ENTRY *EntryNetMap;
2082 NET_MAP_ITEM *ItemNetMap;
2083 DNS4_TOKEN_ENTRY *Dns4TokenEntry;
2084 DNS6_TOKEN_ENTRY *Dns6TokenEntry;
2085
2086 Dns4TokenEntry = NULL;
2087 Dns6TokenEntry = NULL;
2088
2089 Service = (DNS_SERVICE *) Context;
2090
2091
2092 if (Service->IpVersion == IP_VERSION_4) {
2093 //
2094 // Iterate through all the children of the DNS service instance. Time
2095 // out the packet. If maximum retries reached, clean the Token up.
2096 //
2097 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Service->Dns4ChildrenList) {
2098 Instance = NET_LIST_USER_STRUCT (Entry, DNS_INSTANCE, Link);
2099
2100 EntryNetMap = Instance->Dns4TxTokens.Used.ForwardLink;
2101 while (EntryNetMap != &Instance->Dns4TxTokens.Used) {
2102 ItemNetMap = NET_LIST_USER_STRUCT (EntryNetMap, NET_MAP_ITEM, Link);
2103 Dns4TokenEntry = (DNS4_TOKEN_ENTRY *)(ItemNetMap->Key);
2104 if (Dns4TokenEntry->PacketToLive == 0 || (--Dns4TokenEntry->PacketToLive > 0)) {
2105 EntryNetMap = EntryNetMap->ForwardLink;
2106 continue;
2107 }
2108
2109 //
2110 // Retransmit the packet if haven't reach the maxmium retry count,
2111 // otherwise exit the transfer.
2112 //
2113 if (++Dns4TokenEntry->RetryCounting <= Dns4TokenEntry->Token->RetryCount) {
2114 DnsRetransmit (Instance, (NET_BUF *)ItemNetMap->Value);
2115 EntryNetMap = EntryNetMap->ForwardLink;
2116 } else {
2117 //
2118 // Maximum retries reached, clean the Token up.
2119 //
2120 Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry);
2121 Dns4TokenEntry->Token->Status = EFI_TIMEOUT;
2122 gBS->SignalEvent (Dns4TokenEntry->Token->Event);
2123 DispatchDpc ();
2124
2125 //
2126 // Free the sending packet.
2127 //
2128 if (ItemNetMap->Value != NULL) {
2129 NetbufFree ((NET_BUF *)(ItemNetMap->Value));
2130 }
2131
2132 EntryNetMap = Instance->Dns4TxTokens.Used.ForwardLink;
2133 }
2134 }
2135 }
2136 }else {
2137 //
2138 // Iterate through all the children of the DNS service instance. Time
2139 // out the packet. If maximum retries reached, clean the Token up.
2140 //
2141 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Service->Dns6ChildrenList) {
2142 Instance = NET_LIST_USER_STRUCT (Entry, DNS_INSTANCE, Link);
2143
2144 EntryNetMap = Instance->Dns6TxTokens.Used.ForwardLink;
2145 while (EntryNetMap != &Instance->Dns6TxTokens.Used) {
2146 ItemNetMap = NET_LIST_USER_STRUCT (EntryNetMap, NET_MAP_ITEM, Link);
2147 Dns6TokenEntry = (DNS6_TOKEN_ENTRY *) (ItemNetMap->Key);
2148 if (Dns6TokenEntry->PacketToLive == 0 || (--Dns6TokenEntry->PacketToLive > 0)) {
2149 EntryNetMap = EntryNetMap->ForwardLink;
2150 continue;
2151 }
2152
2153 //
2154 // Retransmit the packet if haven't reach the maxmium retry count,
2155 // otherwise exit the transfer.
2156 //
2157 if (++Dns6TokenEntry->RetryCounting <= Dns6TokenEntry->Token->RetryCount) {
2158 DnsRetransmit (Instance, (NET_BUF *) ItemNetMap->Value);
2159 EntryNetMap = EntryNetMap->ForwardLink;
2160 } else {
2161 //
2162 // Maximum retries reached, clean the Token up.
2163 //
2164 Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry);
2165 Dns6TokenEntry->Token->Status = EFI_TIMEOUT;
2166 gBS->SignalEvent (Dns6TokenEntry->Token->Event);
2167 DispatchDpc ();
2168
2169 //
2170 // Free the sending packet.
2171 //
2172 if (ItemNetMap->Value != NULL) {
2173 NetbufFree ((NET_BUF *) (ItemNetMap->Value));
2174 }
2175
2176 EntryNetMap = Instance->Dns6TxTokens.Used.ForwardLink;
2177 }
2178 }
2179 }
2180 }
2181 }
2182
2183 /**
2184 The timer ticking function for the DNS driver.
2185
2186 @param Event The ticking event
2187 @param Context NULL
2188
2189 **/
2190 VOID
2191 EFIAPI
2192 DnsOnTimerUpdate (
2193 IN EFI_EVENT Event,
2194 IN VOID *Context
2195 )
2196 {
2197 LIST_ENTRY *Entry;
2198 LIST_ENTRY *Next;
2199 DNS4_CACHE *Item4;
2200 DNS6_CACHE *Item6;
2201
2202 Item4 = NULL;
2203 Item6 = NULL;
2204
2205 //
2206 // Iterate through all the DNS4 cache list.
2207 //
2208 NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) {
2209 Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
2210 Item4->DnsCache.Timeout--;
2211 }
2212
2213 Entry = mDriverData->Dns4CacheList.ForwardLink;
2214 while (Entry != &mDriverData->Dns4CacheList) {
2215 Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
2216 if (Item4->DnsCache.Timeout == 0) {
2217 RemoveEntryList (&Item4->AllCacheLink);
2218 FreePool (Item4->DnsCache.HostName);
2219 FreePool (Item4->DnsCache.IpAddress);
2220 FreePool (Item4);
2221 Entry = mDriverData->Dns4CacheList.ForwardLink;
2222 } else {
2223 Entry = Entry->ForwardLink;
2224 }
2225 }
2226
2227 //
2228 // Iterate through all the DNS6 cache list.
2229 //
2230 NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6CacheList) {
2231 Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
2232 Item6->DnsCache.Timeout--;
2233 }
2234
2235 Entry = mDriverData->Dns6CacheList.ForwardLink;
2236 while (Entry != &mDriverData->Dns6CacheList) {
2237 Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
2238 if (Item6->DnsCache.Timeout == 0) {
2239 RemoveEntryList (&Item6->AllCacheLink);
2240 FreePool (Item6->DnsCache.HostName);
2241 FreePool (Item6->DnsCache.IpAddress);
2242 FreePool (Item6);
2243 Entry = mDriverData->Dns6CacheList.ForwardLink;
2244 } else {
2245 Entry = Entry->ForwardLink;
2246 }
2247 }
2248 }
2249