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