]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/DnsDxe/DnsImpl.c
NetworkPkg: Fix the potential NULL pointer dereferenced issue
[mirror_edk2.git] / NetworkPkg / DnsDxe / DnsImpl.c
1 /** @file
2 DnsDxe support functions implementation.
3
4 Copyright (c) 2015, 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 Ip6Mode.IsConfigured) {
623
624 Udp->Configure (Udp, NULL);
625 return (BOOLEAN) (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS);
626 }
627 }
628
629 return FALSE;
630 }
631
632 /**
633 Configure the UDP.
634
635 @param Instance The DNS session
636 @param UdpIo The UDP_IO instance
637
638 @retval EFI_SUCCESS The UDP is successfully configured for the
639 session.
640
641 **/
642 EFI_STATUS
643 Dns4ConfigUdp (
644 IN DNS_INSTANCE *Instance,
645 IN UDP_IO *UdpIo
646 )
647 {
648 EFI_DNS4_CONFIG_DATA *Config;
649 EFI_UDP4_CONFIG_DATA UdpConfig;
650 EFI_STATUS Status;
651
652 Config = &Instance->Dns4CfgData;
653
654 UdpConfig.AcceptBroadcast = FALSE;
655 UdpConfig.AcceptPromiscuous = FALSE;
656 UdpConfig.AcceptAnyPort = FALSE;
657 UdpConfig.AllowDuplicatePort = FALSE;
658 UdpConfig.TypeOfService = 0;
659 UdpConfig.TimeToLive = 128;
660 UdpConfig.DoNotFragment = FALSE;
661 UdpConfig.ReceiveTimeout = 0;
662 UdpConfig.TransmitTimeout = 0;
663 UdpConfig.UseDefaultAddress = Config->UseDefaultSetting;
664 UdpConfig.SubnetMask = Config->SubnetMask;
665 UdpConfig.StationPort = Config->LocalPort;
666 UdpConfig.RemotePort = DNS_SERVER_PORT;
667
668 CopyMem (&UdpConfig.StationAddress, &Config->StationIp, sizeof (EFI_IPv4_ADDRESS));
669 CopyMem (&UdpConfig.RemoteAddress, &Instance->SessionDnsServer.v4, sizeof (EFI_IPv4_ADDRESS));
670
671 Status = UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfig);
672
673 if ((Status == EFI_NO_MAPPING) && Dns4GetMapping (Instance, UdpIo, &UdpConfig)) {
674 return EFI_SUCCESS;
675 }
676
677 return Status;
678 }
679
680 /**
681 Configure the UDP.
682
683 @param Instance The DNS session
684 @param UdpIo The UDP_IO instance
685
686 @retval EFI_SUCCESS The UDP is successfully configured for the
687 session.
688
689 **/
690 EFI_STATUS
691 Dns6ConfigUdp (
692 IN DNS_INSTANCE *Instance,
693 IN UDP_IO *UdpIo
694 )
695 {
696 EFI_DNS6_CONFIG_DATA *Config;
697 EFI_UDP6_CONFIG_DATA UdpConfig;
698 EFI_STATUS Status;
699
700 Config = &Instance->Dns6CfgData;
701
702 UdpConfig.AcceptPromiscuous = FALSE;
703 UdpConfig.AcceptAnyPort = FALSE;
704 UdpConfig.AllowDuplicatePort = FALSE;
705 UdpConfig.TrafficClass = 0;
706 UdpConfig.HopLimit = 128;
707 UdpConfig.ReceiveTimeout = 0;
708 UdpConfig.TransmitTimeout = 0;
709 UdpConfig.StationPort = Config->LocalPort;
710 UdpConfig.RemotePort = DNS_SERVER_PORT;
711 CopyMem (&UdpConfig.StationAddress, &Config->StationIp, sizeof (EFI_IPv6_ADDRESS));
712 CopyMem (&UdpConfig.RemoteAddress, &Instance->SessionDnsServer.v6, sizeof (EFI_IPv6_ADDRESS));
713
714 Status = UdpIo->Protocol.Udp6->Configure (UdpIo->Protocol.Udp6, &UdpConfig);
715
716 if ((Status == EFI_NO_MAPPING) && Dns6GetMapping (Instance, UdpIo, &UdpConfig)) {
717 return EFI_SUCCESS;
718 }
719
720 return Status;
721 }
722
723 /**
724 Update Dns4 cache to shared list of caches of all DNSv4 instances.
725
726 @param Dns4CacheList All Dns4 cache list.
727 @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache.
728 If TRUE, this function will delete matching DNS Cache entry.
729 @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
730 If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
731 @param DnsCacheEntry Entry Pointer to DNS Cache entry.
732
733 @retval EFI_SUCCESS Update Dns4 cache successfully.
734 @retval Others Failed to update Dns4 cache.
735
736 **/
737 EFI_STATUS
738 EFIAPI
739 UpdateDns4Cache (
740 IN LIST_ENTRY *Dns4CacheList,
741 IN BOOLEAN DeleteFlag,
742 IN BOOLEAN Override,
743 IN EFI_DNS4_CACHE_ENTRY DnsCacheEntry
744 )
745 {
746 DNS4_CACHE *NewDnsCache;
747 DNS4_CACHE *Item;
748 LIST_ENTRY *Entry;
749 LIST_ENTRY *Next;
750
751 NewDnsCache = NULL;
752 Item = NULL;
753
754 //
755 // Search the database for the matching EFI_DNS_CACHE_ENTRY
756 //
757 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns4CacheList) {
758 Item = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
759 if (StrCmp (DnsCacheEntry.HostName, Item->DnsCache.HostName) == 0 && \
760 CompareMem (DnsCacheEntry.IpAddress, Item->DnsCache.IpAddress, sizeof (EFI_IPv4_ADDRESS)) == 0) {
761 //
762 // This is the Dns cache entry
763 //
764 if (DeleteFlag) {
765 //
766 // Delete matching DNS Cache entry
767 //
768 RemoveEntryList (&Item->AllCacheLink);
769
770 return EFI_SUCCESS;
771 } else if (Override) {
772 //
773 // Update this one
774 //
775 Item->DnsCache.Timeout = DnsCacheEntry.Timeout;
776
777 return EFI_SUCCESS;
778 }else {
779 return EFI_ACCESS_DENIED;
780 }
781 }
782 }
783
784 //
785 // Add new one
786 //
787 NewDnsCache = AllocatePool (sizeof (DNS4_CACHE));
788 if (NewDnsCache == NULL) {
789 return EFI_OUT_OF_RESOURCES;
790 }
791
792 InitializeListHead (&NewDnsCache->AllCacheLink);
793
794 NewDnsCache->DnsCache.HostName = AllocatePool (StrSize (DnsCacheEntry.HostName));
795 if (NewDnsCache->DnsCache.HostName == NULL) {
796 return EFI_OUT_OF_RESOURCES;
797 }
798
799 CopyMem (NewDnsCache->DnsCache.HostName, DnsCacheEntry.HostName, StrSize (DnsCacheEntry.HostName));
800
801 NewDnsCache->DnsCache.IpAddress = AllocatePool (sizeof (EFI_IPv4_ADDRESS));
802 if (NewDnsCache->DnsCache.IpAddress == NULL) {
803 return EFI_OUT_OF_RESOURCES;
804 }
805
806 CopyMem (NewDnsCache->DnsCache.IpAddress, DnsCacheEntry.IpAddress, sizeof (EFI_IPv4_ADDRESS));
807
808 NewDnsCache->DnsCache.Timeout = DnsCacheEntry.Timeout;
809
810 InsertTailList (Dns4CacheList, &NewDnsCache->AllCacheLink);
811
812 return EFI_SUCCESS;
813 }
814
815 /**
816 Update Dns6 cache to shared list of caches of all DNSv6 instances.
817
818 @param Dns6CacheList All Dns6 cache list.
819 @param DeleteFlag If FALSE, this function is to add one entry to the DNS Cache.
820 If TRUE, this function will delete matching DNS Cache entry.
821 @param Override If TRUE, the matching DNS cache entry will be overwritten with the supplied parameter.
822 If FALSE, EFI_ACCESS_DENIED will be returned if the entry to be added is already exists.
823 @param DnsCacheEntry Entry Pointer to DNS Cache entry.
824
825 @retval EFI_SUCCESS Update Dns6 cache successfully.
826 @retval Others Failed to update Dns6 cache.
827 **/
828 EFI_STATUS
829 EFIAPI
830 UpdateDns6Cache (
831 IN LIST_ENTRY *Dns6CacheList,
832 IN BOOLEAN DeleteFlag,
833 IN BOOLEAN Override,
834 IN EFI_DNS6_CACHE_ENTRY DnsCacheEntry
835 )
836 {
837 DNS6_CACHE *NewDnsCache;
838 DNS6_CACHE *Item;
839 LIST_ENTRY *Entry;
840 LIST_ENTRY *Next;
841
842 NewDnsCache = NULL;
843 Item = NULL;
844
845 //
846 // Search the database for the matching EFI_DNS_CACHE_ENTRY
847 //
848 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns6CacheList) {
849 Item = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
850 if (StrCmp (DnsCacheEntry.HostName, Item->DnsCache.HostName) == 0 && \
851 CompareMem (DnsCacheEntry.IpAddress, Item->DnsCache.IpAddress, sizeof (EFI_IPv6_ADDRESS)) == 0) {
852 //
853 // This is the Dns cache entry
854 //
855 if (DeleteFlag) {
856 //
857 // Delete matching DNS Cache entry
858 //
859 RemoveEntryList (&Item->AllCacheLink);
860
861 return EFI_SUCCESS;
862 } else if (Override) {
863 //
864 // Update this one
865 //
866 Item->DnsCache.Timeout = DnsCacheEntry.Timeout;
867
868 return EFI_SUCCESS;
869 }else {
870 return EFI_ACCESS_DENIED;
871 }
872 }
873 }
874
875 //
876 // Add new one
877 //
878 NewDnsCache = AllocatePool (sizeof (DNS6_CACHE));
879 if (NewDnsCache == NULL) {
880 return EFI_OUT_OF_RESOURCES;
881 }
882
883 InitializeListHead (&NewDnsCache->AllCacheLink);
884
885 NewDnsCache->DnsCache.HostName = AllocatePool (StrSize (DnsCacheEntry.HostName));
886 if (NewDnsCache->DnsCache.HostName == NULL) {
887 return EFI_OUT_OF_RESOURCES;
888 }
889
890 CopyMem (NewDnsCache->DnsCache.HostName, DnsCacheEntry.HostName, StrSize (DnsCacheEntry.HostName));
891
892 NewDnsCache->DnsCache.IpAddress = AllocatePool (sizeof (EFI_IPv6_ADDRESS));
893 if (NewDnsCache->DnsCache.IpAddress == NULL) {
894 return EFI_OUT_OF_RESOURCES;
895 }
896
897 CopyMem (NewDnsCache->DnsCache.IpAddress, DnsCacheEntry.IpAddress, sizeof (EFI_IPv6_ADDRESS));
898
899 NewDnsCache->DnsCache.Timeout = DnsCacheEntry.Timeout;
900
901 InsertTailList (Dns6CacheList, &NewDnsCache->AllCacheLink);
902
903 return EFI_SUCCESS;
904 }
905
906 /**
907 Add Dns4 ServerIp to common list of addresses of all configured DNSv4 server.
908
909 @param Dns4ServerList Common list of addresses of all configured DNSv4 server.
910 @param ServerIp DNS server Ip.
911
912 @retval EFI_SUCCESS Add Dns4 ServerIp to common list successfully.
913 @retval Others Failed to add Dns4 ServerIp to common list.
914
915 **/
916 EFI_STATUS
917 EFIAPI
918 AddDns4ServerIp (
919 IN LIST_ENTRY *Dns4ServerList,
920 IN EFI_IPv4_ADDRESS ServerIp
921 )
922 {
923 DNS4_SERVER_IP *NewServerIp;
924 DNS4_SERVER_IP *Item;
925 LIST_ENTRY *Entry;
926 LIST_ENTRY *Next;
927
928 NewServerIp = NULL;
929 Item = NULL;
930
931 //
932 // Search the database for the matching ServerIp
933 //
934 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns4ServerList) {
935 Item = NET_LIST_USER_STRUCT (Entry, DNS4_SERVER_IP, AllServerLink);
936 if (CompareMem (&Item->Dns4ServerIp, &ServerIp, sizeof (EFI_IPv4_ADDRESS)) == 0) {
937 //
938 // Already done.
939 //
940 return EFI_SUCCESS;
941 }
942 }
943
944 //
945 // Add new one
946 //
947 NewServerIp = AllocatePool (sizeof (DNS4_SERVER_IP));
948 if (NewServerIp == NULL) {
949 return EFI_OUT_OF_RESOURCES;
950 }
951
952 InitializeListHead (&NewServerIp->AllServerLink);
953
954 CopyMem (&NewServerIp->Dns4ServerIp, &ServerIp, sizeof (EFI_IPv4_ADDRESS));
955
956 InsertTailList (Dns4ServerList, &NewServerIp->AllServerLink);
957
958 return EFI_SUCCESS;
959 }
960
961 /**
962 Add Dns6 ServerIp to common list of addresses of all configured DNSv6 server.
963
964 @param Dns6ServerList Common list of addresses of all configured DNSv6 server.
965 @param ServerIp DNS server Ip.
966
967 @retval EFI_SUCCESS Add Dns6 ServerIp to common list successfully.
968 @retval Others Failed to add Dns6 ServerIp to common list.
969
970 **/
971 EFI_STATUS
972 EFIAPI
973 AddDns6ServerIp (
974 IN LIST_ENTRY *Dns6ServerList,
975 IN EFI_IPv6_ADDRESS ServerIp
976 )
977 {
978 DNS6_SERVER_IP *NewServerIp;
979 DNS6_SERVER_IP *Item;
980 LIST_ENTRY *Entry;
981 LIST_ENTRY *Next;
982
983 NewServerIp = NULL;
984 Item = NULL;
985
986 //
987 // Search the database for the matching ServerIp
988 //
989 NET_LIST_FOR_EACH_SAFE (Entry, Next, Dns6ServerList) {
990 Item = NET_LIST_USER_STRUCT (Entry, DNS6_SERVER_IP, AllServerLink);
991 if (CompareMem (&Item->Dns6ServerIp, &ServerIp, sizeof (EFI_IPv6_ADDRESS)) == 0) {
992 //
993 // Already done.
994 //
995 return EFI_SUCCESS;
996 }
997 }
998
999 //
1000 // Add new one
1001 //
1002 NewServerIp = AllocatePool (sizeof (DNS6_SERVER_IP));
1003 if (NewServerIp == NULL) {
1004 return EFI_OUT_OF_RESOURCES;
1005 }
1006
1007 InitializeListHead (&NewServerIp->AllServerLink);
1008
1009 CopyMem (&NewServerIp->Dns6ServerIp, &ServerIp, sizeof (EFI_IPv6_ADDRESS));
1010
1011 InsertTailList (Dns6ServerList, &NewServerIp->AllServerLink);
1012
1013 return EFI_SUCCESS;
1014 }
1015
1016 /**
1017 Find out whether the response is valid or invalid.
1018
1019 @param TokensMap All DNS transmittal Tokens entry.
1020 @param Identification Identification for queried packet.
1021 @param Type Type for queried packet.
1022 @param Item Return corresponding Token entry.
1023
1024 @retval TRUE The response is valid.
1025 @retval FALSE The response is invalid.
1026
1027 **/
1028 BOOLEAN
1029 IsValidDnsResponse (
1030 IN NET_MAP *TokensMap,
1031 IN UINT16 Identification,
1032 IN UINT16 Type,
1033 OUT NET_MAP_ITEM **Item
1034 )
1035 {
1036 LIST_ENTRY *Entry;
1037
1038 NET_BUF *Packet;
1039 UINT8 *TxString;
1040 DNS_HEADER *DnsHeader;
1041 CHAR8 *QueryName;
1042 DNS_QUERY_SECTION *QuerySection;
1043
1044 NET_LIST_FOR_EACH (Entry, &TokensMap->Used) {
1045 *Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1046 Packet = (NET_BUF *) ((*Item)->Value);
1047 if (Packet == NULL){
1048
1049 continue;
1050 } else {
1051 TxString = NetbufGetByte (Packet, 0, NULL);
1052 ASSERT (TxString != NULL);
1053 DnsHeader = (DNS_HEADER *) TxString;
1054 QueryName = (CHAR8 *) (TxString + sizeof (*DnsHeader));
1055 QuerySection = (DNS_QUERY_SECTION *) (QueryName + AsciiStrLen (QueryName) + 1);
1056
1057 DnsHeader->Identification = NTOHS (DnsHeader->Identification);
1058 QuerySection->Type = NTOHS (QuerySection->Type);
1059
1060 if (DnsHeader->Identification == Identification && QuerySection->Type == Type) {
1061 return TRUE;
1062 }
1063 }
1064 }
1065
1066 *Item =NULL;
1067
1068 return FALSE;
1069 }
1070
1071 /**
1072 Parse Dns Response.
1073
1074 @param Instance The DNS instance
1075 @param RxString Received buffer.
1076 @param Completed Flag to indicate that Dns response is valid.
1077
1078 @retval EFI_SUCCESS Parse Dns Response successfully.
1079 @retval Others Failed to parse Dns Response.
1080
1081 **/
1082 EFI_STATUS
1083 ParseDnsResponse (
1084 IN OUT DNS_INSTANCE *Instance,
1085 IN UINT8 *RxString,
1086 OUT BOOLEAN *Completed
1087 )
1088 {
1089 DNS_HEADER *DnsHeader;
1090
1091 CHAR8 *QueryName;
1092 DNS_QUERY_SECTION *QuerySection;
1093
1094 CHAR8 *AnswerName;
1095 DNS_ANSWER_SECTION *AnswerSection;
1096 UINT8 *AnswerData;
1097
1098 NET_MAP_ITEM *Item;
1099 DNS4_TOKEN_ENTRY *Dns4TokenEntry;
1100 DNS6_TOKEN_ENTRY *Dns6TokenEntry;
1101
1102 UINT32 IpCount;
1103 UINT32 AnswerSectionNum;
1104
1105 EFI_IPv4_ADDRESS *HostAddr4;
1106 EFI_IPv6_ADDRESS *HostAddr6;
1107
1108 EFI_DNS4_CACHE_ENTRY *Dns4CacheEntry;
1109 EFI_DNS6_CACHE_ENTRY *Dns6CacheEntry;
1110
1111 EFI_STATUS Status;
1112
1113 EFI_TPL OldTpl;
1114
1115 Item = NULL;
1116 Dns4TokenEntry = NULL;
1117 Dns6TokenEntry = NULL;
1118
1119 IpCount = 0;
1120 AnswerSectionNum = 0;
1121
1122 HostAddr4 = NULL;
1123 HostAddr6 = NULL;
1124
1125 Dns4CacheEntry = NULL;
1126 Dns6CacheEntry = NULL;
1127
1128 *Completed = TRUE;
1129 Status = EFI_SUCCESS;
1130
1131 //
1132 // Get header
1133 //
1134 DnsHeader = (DNS_HEADER *) RxString;
1135
1136 DnsHeader->Identification = NTOHS (DnsHeader->Identification);
1137 DnsHeader->Flags.Uint16 = NTOHS (DnsHeader->Flags.Uint16);
1138 DnsHeader->QuestionsNum = NTOHS (DnsHeader->QuestionsNum);
1139 DnsHeader->AnswersNum = NTOHS (DnsHeader->AnswersNum);
1140 DnsHeader->AuthorityNum = NTOHS (DnsHeader->AuthorityNum);
1141 DnsHeader->AditionalNum = NTOHS (DnsHeader->AditionalNum);
1142
1143 //
1144 // Get Query name
1145 //
1146 QueryName = (CHAR8 *) (RxString + sizeof (*DnsHeader));
1147
1148 //
1149 // Get query section
1150 //
1151 QuerySection = (DNS_QUERY_SECTION *) (QueryName + AsciiStrLen (QueryName) + 1);
1152 QuerySection->Type = NTOHS (QuerySection->Type);
1153 QuerySection->Class = NTOHS (QuerySection->Class);
1154
1155 //
1156 // Get Answer name
1157 //
1158 AnswerName = (CHAR8 *) QuerySection + sizeof (*QuerySection);
1159
1160 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1161
1162 //
1163 // Check DnsResponse Validity, if so, also get a valid NET_MAP_ITEM.
1164 //
1165 if (Instance->Service->IpVersion == IP_VERSION_4) {
1166 if (!IsValidDnsResponse (&Instance->Dns4TxTokens, DnsHeader->Identification, QuerySection->Type, &Item)) {
1167 *Completed = FALSE;
1168 Status = EFI_ABORTED;
1169 goto ON_EXIT;
1170 }
1171 ASSERT (Item != NULL);
1172 Dns4TokenEntry = (DNS4_TOKEN_ENTRY *) (Item->Key);
1173 } else {
1174 if (!IsValidDnsResponse (&Instance->Dns6TxTokens, DnsHeader->Identification, QuerySection->Type, &Item)) {
1175 *Completed = FALSE;
1176 Status = EFI_ABORTED;
1177 goto ON_EXIT;
1178 }
1179 ASSERT (Item != NULL);
1180 Dns6TokenEntry = (DNS6_TOKEN_ENTRY *) (Item->Key);
1181 }
1182
1183 //
1184 // Continue Check Some Errors.
1185 //
1186 if (DnsHeader->Flags.Bits.RCode != DNS_FLAGS_RCODE_NO_ERROR || DnsHeader->AnswersNum < 1 || \
1187 DnsHeader->Flags.Bits.QR != DNS_FLAGS_QR_RESPONSE || QuerySection->Class != DNS_CLASS_INET) {
1188 Status = EFI_ABORTED;
1189 goto ON_EXIT;
1190 }
1191
1192 //
1193 // Free the sending packet.
1194 //
1195 if (Item->Value != NULL) {
1196 NetbufFree ((NET_BUF *) (Item->Value));
1197 }
1198
1199 //
1200 // Check the Query type, do some buffer allocations.
1201 //
1202 if (Instance->Service->IpVersion == IP_VERSION_4) {
1203 ASSERT (Dns4TokenEntry != NULL);
1204 if (QuerySection->Type == DNS_TYPE_A) {
1205 Dns4TokenEntry->Token->RspData.H2AData = AllocatePool (sizeof (DNS_HOST_TO_ADDR_DATA));
1206 ASSERT (Dns4TokenEntry->Token->RspData.H2AData != NULL);
1207 Dns4TokenEntry->Token->RspData.H2AData->IpList = AllocatePool (DnsHeader->AnswersNum * sizeof (EFI_IPv4_ADDRESS));
1208 ASSERT (Dns4TokenEntry->Token->RspData.H2AData->IpList != NULL);
1209 } else {
1210 Status = EFI_UNSUPPORTED;
1211 goto ON_EXIT;
1212 }
1213 } else {
1214 ASSERT (Dns6TokenEntry != NULL);
1215 if (QuerySection->Type == DNS_TYPE_AAAA) {
1216 Dns6TokenEntry->Token->RspData.H2AData = AllocatePool (sizeof (DNS6_HOST_TO_ADDR_DATA));
1217 ASSERT (Dns6TokenEntry->Token->RspData.H2AData != NULL);
1218 Dns6TokenEntry->Token->RspData.H2AData->IpList = AllocatePool (DnsHeader->AnswersNum * sizeof (EFI_IPv6_ADDRESS));
1219 ASSERT (Dns6TokenEntry->Token->RspData.H2AData->IpList != NULL);
1220 } else {
1221 Status = EFI_UNSUPPORTED;
1222 goto ON_EXIT;
1223 }
1224 }
1225
1226 //
1227 // Processing AnswerSection.
1228 //
1229 while (AnswerSectionNum < DnsHeader->AnswersNum) {
1230 //
1231 // Answer name should be PTR.
1232 //
1233 ASSERT ((*(UINT8 *) AnswerName & 0xC0) == 0xC0);
1234
1235 //
1236 // Get Answer section.
1237 //
1238 AnswerSection = (DNS_ANSWER_SECTION *) (AnswerName + sizeof (UINT16));
1239 AnswerSection->Type = NTOHS (AnswerSection->Type);
1240 AnswerSection->Class = NTOHS (AnswerSection->Class);
1241 AnswerSection->Ttl = NTOHL (AnswerSection->Ttl);
1242 AnswerSection->DataLength = NTOHS (AnswerSection->DataLength);
1243
1244 ASSERT (AnswerSection->Class == DNS_CLASS_INET);
1245
1246 if (AnswerSection->Type == QuerySection->Type) {
1247 switch (AnswerSection->Type) {
1248 case DNS_TYPE_A:
1249 //
1250 // This is address entry, get Data.
1251 //
1252 ASSERT (Dns4TokenEntry != NULL && AnswerSection->DataLength == 4);
1253
1254 HostAddr4 = Dns4TokenEntry->Token->RspData.H2AData->IpList;
1255 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
1256 CopyMem (&HostAddr4[IpCount], AnswerData, sizeof (EFI_IPv4_ADDRESS));
1257
1258 //
1259 // Update DNS cache dynamically.
1260 //
1261 if (Dns4CacheEntry != NULL) {
1262 if (Dns4CacheEntry->HostName != NULL) {
1263 FreePool (Dns4CacheEntry->HostName);
1264 }
1265
1266 if (Dns4CacheEntry->IpAddress != NULL) {
1267 FreePool (Dns4CacheEntry->IpAddress);
1268 }
1269
1270 FreePool (Dns4CacheEntry);
1271 }
1272
1273 //
1274 // Allocate new CacheEntry pool.
1275 //
1276 Dns4CacheEntry = AllocateZeroPool (sizeof (EFI_DNS4_CACHE_ENTRY));
1277 ASSERT (Dns4CacheEntry != NULL);
1278 Dns4CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1));
1279 ASSERT (Dns4CacheEntry->HostName != NULL);
1280 CopyMem (Dns4CacheEntry->HostName, Dns4TokenEntry->QueryHostName, 2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1));
1281 Dns4CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv4_ADDRESS));
1282 ASSERT (Dns4CacheEntry->IpAddress != NULL);
1283 CopyMem (Dns4CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv4_ADDRESS));
1284 Dns4CacheEntry->Timeout = AnswerSection->Ttl;
1285
1286 UpdateDns4Cache (&mDriverData->Dns4CacheList, FALSE, TRUE, *Dns4CacheEntry);
1287
1288 IpCount ++;
1289 break;
1290 case DNS_TYPE_AAAA:
1291 //
1292 // This is address entry, get Data.
1293 //
1294 ASSERT (Dns6TokenEntry != NULL && AnswerSection->DataLength == 16);
1295
1296 HostAddr6 = Dns6TokenEntry->Token->RspData.H2AData->IpList;
1297 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);
1298 CopyMem (&HostAddr6[IpCount], AnswerData, sizeof (EFI_IPv6_ADDRESS));
1299
1300 //
1301 // Update DNS cache dynamically.
1302 //
1303 if (Dns6CacheEntry != NULL) {
1304 if (Dns6CacheEntry->HostName != NULL) {
1305 FreePool (Dns6CacheEntry->HostName);
1306 }
1307
1308 if (Dns6CacheEntry->IpAddress != NULL) {
1309 FreePool (Dns6CacheEntry->IpAddress);
1310 }
1311
1312 FreePool (Dns6CacheEntry);
1313 }
1314
1315 //
1316 // Allocate new CacheEntry pool.
1317 //
1318 Dns6CacheEntry = AllocateZeroPool (sizeof (EFI_DNS6_CACHE_ENTRY));
1319 ASSERT (Dns6CacheEntry != NULL);
1320 Dns6CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1));
1321 ASSERT (Dns6CacheEntry->HostName != NULL);
1322 CopyMem (Dns6CacheEntry->HostName, Dns6TokenEntry->QueryHostName, 2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1));
1323 Dns6CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS));
1324 ASSERT (Dns6CacheEntry->IpAddress != NULL);
1325 CopyMem (Dns6CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv6_ADDRESS));
1326 Dns6CacheEntry->Timeout = AnswerSection->Ttl;
1327
1328 UpdateDns6Cache (&mDriverData->Dns6CacheList, FALSE, TRUE, *Dns6CacheEntry);
1329
1330 IpCount ++;
1331 break;
1332 default:
1333 Status = EFI_UNSUPPORTED;
1334 goto ON_EXIT;
1335 }
1336 }
1337
1338 //
1339 // Find next one
1340 //
1341 AnswerName = (CHAR8 *) AnswerSection + sizeof (*AnswerSection) + AnswerSection->DataLength;
1342 AnswerSectionNum ++;
1343 }
1344
1345 if (Instance->Service->IpVersion == IP_VERSION_4) {
1346 ASSERT (Dns4TokenEntry != NULL);
1347 if (QuerySection->Type == DNS_TYPE_A) {
1348 Dns4TokenEntry->Token->RspData.H2AData->IpCount = IpCount;
1349 } else {
1350 Status = EFI_UNSUPPORTED;
1351 goto ON_EXIT;
1352 }
1353 } else {
1354 ASSERT (Dns6TokenEntry != NULL);
1355 if (QuerySection->Type == DNS_TYPE_AAAA) {
1356 Dns6TokenEntry->Token->RspData.H2AData->IpCount = IpCount;
1357 } else {
1358 Status = EFI_UNSUPPORTED;
1359 goto ON_EXIT;
1360 }
1361 }
1362
1363 //
1364 // Parsing is complete, SignalEvent here.
1365 //
1366 if (Instance->Service->IpVersion == IP_VERSION_4) {
1367 ASSERT (Dns4TokenEntry != NULL);
1368 Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry);
1369 Dns4TokenEntry->Token->Status = EFI_SUCCESS;
1370 if (Dns4TokenEntry->Token->Event != NULL) {
1371 gBS->SignalEvent (Dns4TokenEntry->Token->Event);
1372 DispatchDpc ();
1373 }
1374 } else {
1375 ASSERT (Dns6TokenEntry != NULL);
1376 Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry);
1377 Dns6TokenEntry->Token->Status = EFI_SUCCESS;
1378 if (Dns6TokenEntry->Token->Event != NULL) {
1379 gBS->SignalEvent (Dns6TokenEntry->Token->Event);
1380 DispatchDpc ();
1381 }
1382 }
1383
1384 //
1385 // Free allocated CacheEntry pool.
1386 //
1387 if (Dns4CacheEntry != NULL) {
1388 if (Dns4CacheEntry->HostName != NULL) {
1389 FreePool (Dns4CacheEntry->HostName);
1390 }
1391
1392 if (Dns4CacheEntry->IpAddress != NULL) {
1393 FreePool (Dns4CacheEntry->IpAddress);
1394 }
1395
1396 FreePool (Dns4CacheEntry);
1397 }
1398
1399 if (Dns6CacheEntry != NULL) {
1400 if (Dns6CacheEntry->HostName != NULL) {
1401 FreePool (Dns6CacheEntry->HostName);
1402 }
1403
1404 if (Dns6CacheEntry->IpAddress != NULL) {
1405 FreePool (Dns6CacheEntry->IpAddress);
1406 }
1407
1408 FreePool (Dns6CacheEntry);
1409 }
1410
1411 ON_EXIT:
1412 gBS->RestoreTPL (OldTpl);
1413 return Status;
1414 }
1415
1416 /**
1417 Parse response packet.
1418
1419 @param Packet The packets received.
1420 @param EndPoint The local/remote UDP access point
1421 @param IoStatus The status of the UDP receive
1422 @param Context The opaque parameter to the function.
1423
1424 **/
1425 VOID
1426 EFIAPI
1427 DnsOnPacketReceived (
1428 NET_BUF *Packet,
1429 UDP_END_POINT *EndPoint,
1430 EFI_STATUS IoStatus,
1431 VOID *Context
1432 )
1433 {
1434 DNS_INSTANCE *Instance;
1435
1436 UINT8 *RcvString;
1437
1438 BOOLEAN Completed;
1439
1440 Instance = (DNS_INSTANCE *) Context;
1441 NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE);
1442
1443 RcvString = NULL;
1444 Completed = FALSE;
1445
1446 if (EFI_ERROR (IoStatus)) {
1447 goto ON_EXIT;
1448 }
1449
1450 ASSERT (Packet != NULL);
1451
1452 RcvString = NetbufGetByte (Packet, 0, NULL);
1453 ASSERT (RcvString != NULL);
1454
1455 //
1456 // Parse Dns Response
1457 //
1458 ParseDnsResponse (Instance, RcvString, &Completed);
1459
1460 ON_EXIT:
1461
1462 if (Packet != NULL) {
1463 NetbufFree (Packet);
1464 }
1465
1466 if (!Completed) {
1467 UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);
1468 }
1469 }
1470
1471 /**
1472 Release the net buffer when packet is sent.
1473
1474 @param Packet The packets received.
1475 @param EndPoint The local/remote UDP access point
1476 @param IoStatus The status of the UDP receive
1477 @param Context The opaque parameter to the function.
1478
1479 **/
1480 VOID
1481 EFIAPI
1482 DnsOnPacketSent (
1483 NET_BUF *Packet,
1484 UDP_END_POINT *EndPoint,
1485 EFI_STATUS IoStatus,
1486 VOID *Context
1487 )
1488 {
1489 DNS_INSTANCE *Instance;
1490 LIST_ENTRY *Entry;
1491 NET_MAP_ITEM *Item;
1492 DNS4_TOKEN_ENTRY *Dns4TokenEntry;
1493 DNS6_TOKEN_ENTRY *Dns6TokenEntry;
1494
1495 Dns4TokenEntry = NULL;
1496 Dns6TokenEntry = NULL;
1497
1498 Instance = (DNS_INSTANCE *) Context;
1499 NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE);
1500
1501 if (Instance->Service->IpVersion == IP_VERSION_4) {
1502 NET_LIST_FOR_EACH (Entry, &Instance->Dns4TxTokens.Used) {
1503 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1504 if (Packet == (NET_BUF *)(Item->Value)) {
1505 Dns4TokenEntry = ((DNS4_TOKEN_ENTRY *)Item->Key);
1506 Dns4TokenEntry->PacketToLive = Dns4TokenEntry->Token->RetryInterval;
1507 break;
1508 }
1509 }
1510 } else {
1511 NET_LIST_FOR_EACH (Entry, &Instance->Dns6TxTokens.Used) {
1512 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
1513 if (Packet == (NET_BUF *)(Item->Value)) {
1514 Dns6TokenEntry = ((DNS6_TOKEN_ENTRY *)Item->Key);
1515 Dns6TokenEntry->PacketToLive = Dns6TokenEntry->Token->RetryInterval;
1516 break;
1517 }
1518 }
1519 }
1520
1521 NetbufFree (Packet);
1522 }
1523
1524 /**
1525 Query request information.
1526
1527 @param Instance The DNS instance
1528 @param Packet The packet for querying request information.
1529
1530 @retval EFI_SUCCESS Query request information successfully.
1531 @retval Others Failed to query request information.
1532
1533 **/
1534 EFI_STATUS
1535 DoDnsQuery (
1536 IN DNS_INSTANCE *Instance,
1537 IN NET_BUF *Packet
1538 )
1539 {
1540 EFI_STATUS Status;
1541
1542 //
1543 // Ready to receive the DNS response.
1544 //
1545 if (Instance->UdpIo->RecvRequest == NULL) {
1546 Status = UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);
1547 if (EFI_ERROR (Status)) {
1548 return Status;
1549 }
1550 }
1551
1552 //
1553 // Transmit the DNS packet.
1554 //
1555 NET_GET_REF (Packet);
1556
1557 Status = UdpIoSendDatagram (Instance->UdpIo, Packet, NULL, NULL, DnsOnPacketSent, Instance);
1558
1559 return Status;
1560 }
1561
1562 /**
1563 Construct the Packet to query Ip.
1564
1565 @param Instance The DNS instance
1566 @param HostName Queried HostName
1567 @param Type DNS query Type
1568 @param Packet The packet for querying Ip
1569
1570 @retval EFI_SUCCESS The packet is constructed.
1571 @retval Others Failed to construct the Packet.
1572
1573 **/
1574 EFI_STATUS
1575 ConstructDNSQueryIp (
1576 IN DNS_INSTANCE *Instance,
1577 IN CHAR16 *HostName,
1578 IN UINT16 Type,
1579 OUT NET_BUF **Packet
1580 )
1581 {
1582 NET_FRAGMENT Frag;
1583 DNS_HEADER *DnsHeader;
1584 CHAR8 *QueryName;
1585 DNS_QUERY_SECTION *QuerySection;
1586 CHAR8 *Header;
1587 CHAR8 *Tail;
1588 UINTN Len;
1589 UINTN Index;
1590
1591
1592 Frag.Bulk = AllocatePool (DNS_DEFAULT_BLKSIZE * sizeof (UINT8));
1593 if (Frag.Bulk == NULL) {
1594 return EFI_OUT_OF_RESOURCES;
1595 }
1596
1597 //
1598 // Fill header
1599 //
1600 DnsHeader = (DNS_HEADER *) Frag.Bulk;
1601 DnsHeader->Identification = (UINT16)NET_RANDOM (NetRandomInitSeed());
1602 DnsHeader->Flags.Uint16 = 0x0000;
1603 DnsHeader->Flags.Bits.RD = 1;
1604 DnsHeader->Flags.Bits.OpCode = DNS_FLAGS_OPCODE_STANDARD;
1605 DnsHeader->Flags.Bits.QR = DNS_FLAGS_QR_QUERY;
1606 DnsHeader->QuestionsNum = 1;
1607 DnsHeader->AnswersNum = 0;
1608 DnsHeader->AuthorityNum = 0;
1609 DnsHeader->AditionalNum = 0;
1610
1611 DnsHeader->Identification = HTONS (DnsHeader->Identification);
1612 DnsHeader->Flags.Uint16 = HTONS (DnsHeader->Flags.Uint16);
1613 DnsHeader->QuestionsNum = HTONS (DnsHeader->QuestionsNum);
1614 DnsHeader->AnswersNum = HTONS (DnsHeader->AnswersNum);
1615 DnsHeader->AuthorityNum = HTONS (DnsHeader->AuthorityNum);
1616 DnsHeader->AditionalNum = HTONS (DnsHeader->AditionalNum);
1617
1618 Frag.Len = sizeof (*DnsHeader);
1619
1620 //
1621 // Fill Query name
1622 //
1623 QueryName = (CHAR8 *) (Frag.Bulk + Frag.Len);
1624 Header = QueryName;
1625 Tail = Header + 1;
1626 Len = 0;
1627 for (Index = 0; HostName[Index] != 0; Index++) {
1628 *Tail = (CHAR8) HostName[Index];
1629 if (*Tail == '.') {
1630 *Header = (CHAR8) Len;
1631 Header = Tail;
1632 Tail ++;
1633 Len = 0;
1634 } else {
1635 Tail++;
1636 Len++;
1637 }
1638 }
1639 *Header = (CHAR8) Len;
1640 *Tail = 0;
1641 Frag.Len = (UINT32) (Frag.Len + StrLen (HostName) + 2); /// 1 for header, 1 for tail.
1642
1643 //
1644 // Rest query section
1645 //
1646 QuerySection = (DNS_QUERY_SECTION *) (Frag.Bulk + Frag.Len);
1647 QuerySection->Type = Type;
1648 QuerySection->Class = DNS_CLASS_INET;
1649
1650 QuerySection->Type = HTONS (QuerySection->Type);
1651 QuerySection->Class = HTONS (QuerySection->Class);
1652
1653 Frag.Len += sizeof (*QuerySection);
1654
1655 //
1656 // Wrap the Frag in a net buffer.
1657 //
1658 *Packet = NetbufFromExt (&Frag, 1, 0, 0, DnsDummyExtFree, NULL);
1659 if (*Packet == NULL) {
1660 FreePool (Frag.Bulk);
1661 return EFI_OUT_OF_RESOURCES;
1662 }
1663
1664 //
1665 // Store the UdpIo in ProtoData.
1666 //
1667 *((UINTN *) &((*Packet)->ProtoData[0])) = (UINTN) (Instance->UdpIo);
1668
1669 return EFI_SUCCESS;
1670 }
1671
1672 /**
1673 Retransmit the packet.
1674
1675 @param Instance The DNS instance
1676 @param Packet Retransmit the packet
1677
1678 @retval EFI_SUCCESS The packet is retransmitted.
1679 @retval Others Failed to retransmit.
1680
1681 **/
1682 EFI_STATUS
1683 DnsRetransmit (
1684 IN DNS_INSTANCE *Instance,
1685 IN NET_BUF *Packet
1686 )
1687 {
1688 EFI_STATUS Status;
1689
1690 UINT8 *Buffer;
1691
1692 ASSERT (Packet != NULL);
1693
1694 //
1695 // Set the requests to the listening port, other packets to the connected port
1696 //
1697 Buffer = NetbufGetByte (Packet, 0, NULL);
1698 ASSERT (Buffer != NULL);
1699
1700 NET_GET_REF (Packet);
1701
1702 Status = UdpIoSendDatagram (
1703 Instance->UdpIo,
1704 Packet,
1705 NULL,
1706 NULL,
1707 DnsOnPacketSent,
1708 Instance
1709 );
1710
1711 if (EFI_ERROR (Status)) {
1712 NET_PUT_REF (Packet);
1713 }
1714
1715 return Status;
1716 }
1717
1718 /**
1719 The timer ticking function for the DNS services.
1720
1721 @param Event The ticking event
1722 @param Context The DNS service instance
1723
1724 **/
1725 VOID
1726 EFIAPI
1727 DnsOnTimerRetransmit (
1728 IN EFI_EVENT Event,
1729 IN VOID *Context
1730 )
1731 {
1732 DNS_SERVICE *Service;
1733
1734 LIST_ENTRY *Entry;
1735 LIST_ENTRY *Next;
1736
1737 DNS_INSTANCE *Instance;
1738 LIST_ENTRY *EntryNetMap;
1739 NET_MAP_ITEM *ItemNetMap;
1740 DNS4_TOKEN_ENTRY *Dns4TokenEntry;
1741 DNS6_TOKEN_ENTRY *Dns6TokenEntry;
1742
1743 Dns4TokenEntry = NULL;
1744 Dns6TokenEntry = NULL;
1745
1746 Service = (DNS_SERVICE *) Context;
1747
1748
1749 if (Service->IpVersion == IP_VERSION_4) {
1750 //
1751 // Iterate through all the children of the DNS service instance. Time
1752 // out the packet. If maximum retries reached, clean the Token up.
1753 //
1754 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Service->Dns4ChildrenList) {
1755 Instance = NET_LIST_USER_STRUCT (Entry, DNS_INSTANCE, Link);
1756
1757 EntryNetMap = Instance->Dns4TxTokens.Used.ForwardLink;
1758 while (EntryNetMap != &Instance->Dns4TxTokens.Used) {
1759 ItemNetMap = NET_LIST_USER_STRUCT (EntryNetMap, NET_MAP_ITEM, Link);
1760 Dns4TokenEntry = (DNS4_TOKEN_ENTRY *)(ItemNetMap->Key);
1761 if (Dns4TokenEntry->PacketToLive == 0 || (--Dns4TokenEntry->PacketToLive > 0)) {
1762 EntryNetMap = EntryNetMap->ForwardLink;
1763 continue;
1764 }
1765
1766 //
1767 // Retransmit the packet if haven't reach the maxmium retry count,
1768 // otherwise exit the transfer.
1769 //
1770 if (++Dns4TokenEntry->Token->RetryCount < Instance->MaxRetry) {
1771 DnsRetransmit (Instance, (NET_BUF *)ItemNetMap->Value);
1772 EntryNetMap = EntryNetMap->ForwardLink;
1773 } else {
1774 //
1775 // Maximum retries reached, clean the Token up.
1776 //
1777 Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry);
1778 Dns4TokenEntry->Token->Status = EFI_TIMEOUT;
1779 gBS->SignalEvent (Dns4TokenEntry->Token->Event);
1780 DispatchDpc ();
1781
1782 //
1783 // Free the sending packet.
1784 //
1785 if (ItemNetMap->Value != NULL) {
1786 NetbufFree ((NET_BUF *)(ItemNetMap->Value));
1787 }
1788
1789 EntryNetMap = Instance->Dns4TxTokens.Used.ForwardLink;
1790 }
1791 }
1792 }
1793 }else {
1794 //
1795 // Iterate through all the children of the DNS service instance. Time
1796 // out the packet. If maximum retries reached, clean the Token up.
1797 //
1798 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Service->Dns6ChildrenList) {
1799 Instance = NET_LIST_USER_STRUCT (Entry, DNS_INSTANCE, Link);
1800
1801 EntryNetMap = Instance->Dns6TxTokens.Used.ForwardLink;
1802 while (EntryNetMap != &Instance->Dns6TxTokens.Used) {
1803 ItemNetMap = NET_LIST_USER_STRUCT (EntryNetMap, NET_MAP_ITEM, Link);
1804 Dns6TokenEntry = (DNS6_TOKEN_ENTRY *) (ItemNetMap->Key);
1805 if (Dns6TokenEntry->PacketToLive == 0 || (--Dns6TokenEntry->PacketToLive > 0)) {
1806 EntryNetMap = EntryNetMap->ForwardLink;
1807 continue;
1808 }
1809
1810 //
1811 // Retransmit the packet if haven't reach the maxmium retry count,
1812 // otherwise exit the transfer.
1813 //
1814 if (++Dns6TokenEntry->Token->RetryCount < Instance->MaxRetry) {
1815 DnsRetransmit (Instance, (NET_BUF *) ItemNetMap->Value);
1816 EntryNetMap = EntryNetMap->ForwardLink;
1817 } else {
1818 //
1819 // Maximum retries reached, clean the Token up.
1820 //
1821 Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry);
1822 Dns6TokenEntry->Token->Status = EFI_TIMEOUT;
1823 gBS->SignalEvent (Dns6TokenEntry->Token->Event);
1824 DispatchDpc ();
1825
1826 //
1827 // Free the sending packet.
1828 //
1829 if (ItemNetMap->Value != NULL) {
1830 NetbufFree ((NET_BUF *) (ItemNetMap->Value));
1831 }
1832
1833 EntryNetMap = Instance->Dns6TxTokens.Used.ForwardLink;
1834 }
1835 }
1836 }
1837 }
1838 }
1839
1840 /**
1841 The timer ticking function for the DNS driver.
1842
1843 @param Event The ticking event
1844 @param Context NULL
1845
1846 **/
1847 VOID
1848 EFIAPI
1849 DnsOnTimerUpdate (
1850 IN EFI_EVENT Event,
1851 IN VOID *Context
1852 )
1853 {
1854 LIST_ENTRY *Entry;
1855 LIST_ENTRY *Next;
1856 DNS4_CACHE *Item4;
1857 DNS6_CACHE *Item6;
1858
1859 Item4 = NULL;
1860 Item6 = NULL;
1861
1862 //
1863 // Iterate through all the DNS4 cache list.
1864 //
1865 NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) {
1866 Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
1867 Item4->DnsCache.Timeout--;
1868 }
1869
1870 Entry = mDriverData->Dns4CacheList.ForwardLink;
1871 while (Entry != &mDriverData->Dns4CacheList) {
1872 Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
1873 if (Item4->DnsCache.Timeout<=0) {
1874 RemoveEntryList (&Item4->AllCacheLink);
1875 Entry = mDriverData->Dns4CacheList.ForwardLink;
1876 } else {
1877 Entry = Entry->ForwardLink;
1878 }
1879 }
1880
1881 //
1882 // Iterate through all the DNS6 cache list.
1883 //
1884 NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6CacheList) {
1885 Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
1886 Item6->DnsCache.Timeout--;
1887 }
1888
1889 Entry = mDriverData->Dns6CacheList.ForwardLink;
1890 while (Entry != &mDriverData->Dns6CacheList) {
1891 Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
1892 if (Item6->DnsCache.Timeout<=0) {
1893 RemoveEntryList (&Item6->AllCacheLink);
1894 Entry = mDriverData->Dns6CacheList.ForwardLink;
1895 } else {
1896 Entry = Entry->ForwardLink;
1897 }
1898 }
1899 }
1900