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