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