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