]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/DnsDxe/DnsImpl.c
MdeModulePkg: Fix the wrong Timer event check
[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
1040/**\r
1041 Find out whether the response is valid or invalid.\r
1042\r
1043 @param TokensMap All DNS transmittal Tokens entry. \r
1044 @param Identification Identification for queried packet. \r
1045 @param Type Type for queried packet.\r
3900a743 1046 @param Class Class for queried packet.\r
99c048ef 1047 @param Item Return corresponding Token entry.\r
1048\r
1049 @retval TRUE The response is valid.\r
1050 @retval FALSE The response is invalid.\r
1051 \r
1052**/ \r
1053BOOLEAN\r
1054IsValidDnsResponse (\r
1055 IN NET_MAP *TokensMap,\r
1056 IN UINT16 Identification,\r
1057 IN UINT16 Type,\r
3900a743 1058 IN UINT16 Class,\r
99c048ef 1059 OUT NET_MAP_ITEM **Item\r
1060 )\r
1061{\r
1062 LIST_ENTRY *Entry;\r
1063\r
1064 NET_BUF *Packet;\r
1065 UINT8 *TxString;\r
1066 DNS_HEADER *DnsHeader;\r
1067 CHAR8 *QueryName;\r
1068 DNS_QUERY_SECTION *QuerySection;\r
1069\r
1070 NET_LIST_FOR_EACH (Entry, &TokensMap->Used) {\r
1071 *Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);\r
1072 Packet = (NET_BUF *) ((*Item)->Value);\r
1073 if (Packet == NULL){\r
1074 \r
1075 continue;\r
1076 } else {\r
1077 TxString = NetbufGetByte (Packet, 0, NULL);\r
3fd7bd08 1078 ASSERT (TxString != NULL);\r
99c048ef 1079 DnsHeader = (DNS_HEADER *) TxString;\r
1080 QueryName = (CHAR8 *) (TxString + sizeof (*DnsHeader));\r
1081 QuerySection = (DNS_QUERY_SECTION *) (QueryName + AsciiStrLen (QueryName) + 1);\r
99c048ef 1082 \r
3900a743
JW
1083 if (NTOHS (DnsHeader->Identification) == Identification &&\r
1084 NTOHS (QuerySection->Type) == Type && \r
1085 NTOHS (QuerySection->Class) == Class) {\r
99c048ef 1086 return TRUE;\r
1087 }\r
1088 } \r
1089 }\r
1090 \r
3900a743 1091 *Item = NULL;\r
99c048ef 1092 \r
1093 return FALSE;\r
1094}\r
1095\r
1096/**\r
1097 Parse Dns Response.\r
1098\r
1099 @param Instance The DNS instance\r
1100 @param RxString Received buffer.\r
1101 @param Completed Flag to indicate that Dns response is valid. \r
1102 \r
1103 @retval EFI_SUCCESS Parse Dns Response successfully.\r
1104 @retval Others Failed to parse Dns Response.\r
1105 \r
1106**/ \r
1107EFI_STATUS\r
1108ParseDnsResponse (\r
1109 IN OUT DNS_INSTANCE *Instance,\r
1110 IN UINT8 *RxString,\r
1111 OUT BOOLEAN *Completed\r
1112 )\r
1113{\r
1114 DNS_HEADER *DnsHeader;\r
1115 \r
1116 CHAR8 *QueryName;\r
1117 DNS_QUERY_SECTION *QuerySection;\r
1118 \r
1119 CHAR8 *AnswerName;\r
1120 DNS_ANSWER_SECTION *AnswerSection;\r
1121 UINT8 *AnswerData;\r
1122\r
1123 NET_MAP_ITEM *Item;\r
1124 DNS4_TOKEN_ENTRY *Dns4TokenEntry;\r
1125 DNS6_TOKEN_ENTRY *Dns6TokenEntry;\r
1126 \r
1127 UINT32 IpCount;\r
fcae1a99 1128 UINT32 RRCount;\r
99c048ef 1129 UINT32 AnswerSectionNum;\r
3093f45c 1130 UINT32 CNameTtl;\r
99c048ef 1131 \r
1132 EFI_IPv4_ADDRESS *HostAddr4;\r
1133 EFI_IPv6_ADDRESS *HostAddr6;\r
1134\r
1135 EFI_DNS4_CACHE_ENTRY *Dns4CacheEntry;\r
1136 EFI_DNS6_CACHE_ENTRY *Dns6CacheEntry;\r
1137\r
fcae1a99
JW
1138 DNS_RESOURCE_RECORD *Dns4RR;\r
1139 DNS6_RESOURCE_RECORD *Dns6RR;\r
1140\r
99c048ef 1141 EFI_STATUS Status;\r
1142\r
1143 EFI_TPL OldTpl;\r
1144 \r
1145 Item = NULL;\r
1146 Dns4TokenEntry = NULL;\r
1147 Dns6TokenEntry = NULL;\r
1148 \r
1149 IpCount = 0;\r
fcae1a99 1150 RRCount = 0;\r
99c048ef 1151 AnswerSectionNum = 0;\r
3093f45c 1152 CNameTtl = 0;\r
99c048ef 1153 \r
1154 HostAddr4 = NULL;\r
1155 HostAddr6 = NULL;\r
1156 \r
1157 Dns4CacheEntry = NULL;\r
1158 Dns6CacheEntry = NULL;\r
fcae1a99
JW
1159 \r
1160 Dns4RR = NULL;\r
1161 Dns6RR = NULL;\r
99c048ef 1162\r
1163 *Completed = TRUE;\r
1164 Status = EFI_SUCCESS;\r
1165 \r
1166 //\r
1167 // Get header\r
1168 //\r
1169 DnsHeader = (DNS_HEADER *) RxString;\r
1170 \r
1171 DnsHeader->Identification = NTOHS (DnsHeader->Identification);\r
1172 DnsHeader->Flags.Uint16 = NTOHS (DnsHeader->Flags.Uint16);\r
1173 DnsHeader->QuestionsNum = NTOHS (DnsHeader->QuestionsNum);\r
1174 DnsHeader->AnswersNum = NTOHS (DnsHeader->AnswersNum);\r
1175 DnsHeader->AuthorityNum = NTOHS (DnsHeader->AuthorityNum);\r
1176 DnsHeader->AditionalNum = NTOHS (DnsHeader->AditionalNum);\r
1177\r
1178 //\r
1179 // Get Query name\r
1180 //\r
1181 QueryName = (CHAR8 *) (RxString + sizeof (*DnsHeader));\r
1182\r
1183 //\r
1184 // Get query section\r
1185 //\r
1186 QuerySection = (DNS_QUERY_SECTION *) (QueryName + AsciiStrLen (QueryName) + 1);\r
1187 QuerySection->Type = NTOHS (QuerySection->Type);\r
1188 QuerySection->Class = NTOHS (QuerySection->Class);\r
1189\r
1190 //\r
1191 // Get Answer name\r
1192 //\r
1193 AnswerName = (CHAR8 *) QuerySection + sizeof (*QuerySection);\r
1194\r
1195 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1196\r
1197 //\r
1198 // Check DnsResponse Validity, if so, also get a valid NET_MAP_ITEM.\r
1199 //\r
1200 if (Instance->Service->IpVersion == IP_VERSION_4) {\r
3900a743
JW
1201 if (!IsValidDnsResponse (\r
1202 &Instance->Dns4TxTokens, \r
1203 DnsHeader->Identification, \r
1204 QuerySection->Type,\r
1205 QuerySection->Class,\r
1206 &Item\r
1207 )) {\r
99c048ef 1208 *Completed = FALSE;\r
1209 Status = EFI_ABORTED;\r
1210 goto ON_EXIT;\r
1211 }\r
1212 ASSERT (Item != NULL);\r
1213 Dns4TokenEntry = (DNS4_TOKEN_ENTRY *) (Item->Key);\r
1214 } else {\r
3900a743
JW
1215 if (!IsValidDnsResponse (\r
1216 &Instance->Dns6TxTokens, \r
1217 DnsHeader->Identification, \r
1218 QuerySection->Type,\r
1219 QuerySection->Class,\r
1220 &Item\r
1221 )) {\r
99c048ef 1222 *Completed = FALSE;\r
1223 Status = EFI_ABORTED;\r
1224 goto ON_EXIT;\r
1225 }\r
1226 ASSERT (Item != NULL);\r
1227 Dns6TokenEntry = (DNS6_TOKEN_ENTRY *) (Item->Key);\r
1228 }\r
1229 \r
1230 //\r
1231 // Continue Check Some Errors.\r
1232 //\r
1233 if (DnsHeader->Flags.Bits.RCode != DNS_FLAGS_RCODE_NO_ERROR || DnsHeader->AnswersNum < 1 || \\r
3900a743 1234 DnsHeader->Flags.Bits.QR != DNS_FLAGS_QR_RESPONSE) {\r
0a92ac88
JW
1235 //\r
1236 // The domain name referenced in the query does not exist.\r
1237 //\r
1238 if (DnsHeader->Flags.Bits.RCode == DNS_FLAGS_RCODE_NAME_ERROR) {\r
1239 Status = EFI_NOT_FOUND; \r
1240 } else {\r
1241 Status = EFI_DEVICE_ERROR;\r
1242 }\r
1243 \r
1244 goto ON_COMPLETE;\r
99c048ef 1245 }\r
99c048ef 1246 \r
1247 //\r
fcae1a99 1248 // Do some buffer allocations.\r
99c048ef 1249 //\r
00c0c3f2
JW
1250 if (Instance->Service->IpVersion == IP_VERSION_4) {\r
1251 ASSERT (Dns4TokenEntry != NULL);\r
fcae1a99
JW
1252\r
1253 if (Dns4TokenEntry->GeneralLookUp) {\r
1254 //\r
1255 // It's the GeneralLookUp querying.\r
1256 //\r
1257 Dns4TokenEntry->Token->RspData.GLookupData = AllocatePool (sizeof (DNS_RESOURCE_RECORD));\r
1258 if (Dns4TokenEntry->Token->RspData.GLookupData == NULL) {\r
1259 Status = EFI_OUT_OF_RESOURCES;\r
1260 goto ON_EXIT;\r
1261 }\r
1262 Dns4TokenEntry->Token->RspData.GLookupData->RRList = AllocatePool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD));\r
1263 if (Dns4TokenEntry->Token->RspData.GLookupData->RRList == NULL) {\r
1264 Status = EFI_OUT_OF_RESOURCES;\r
1265 goto ON_EXIT;\r
1266 }\r
00c0c3f2 1267 } else {\r
fcae1a99
JW
1268 //\r
1269 // It's not the GeneralLookUp querying. Check the Query type.\r
1270 //\r
1271 if (QuerySection->Type == DNS_TYPE_A) {\r
1272 Dns4TokenEntry->Token->RspData.H2AData = AllocatePool (sizeof (DNS_HOST_TO_ADDR_DATA));\r
1273 if (Dns4TokenEntry->Token->RspData.H2AData == NULL) {\r
1274 Status = EFI_OUT_OF_RESOURCES;\r
1275 goto ON_EXIT;\r
1276 }\r
1277 Dns4TokenEntry->Token->RspData.H2AData->IpList = AllocatePool (DnsHeader->AnswersNum * sizeof (EFI_IPv4_ADDRESS));\r
1278 if (Dns4TokenEntry->Token->RspData.H2AData->IpList == NULL) {\r
1279 Status = EFI_OUT_OF_RESOURCES;\r
1280 goto ON_EXIT;\r
1281 }\r
1282 } else {\r
1283 Status = EFI_UNSUPPORTED;\r
1284 goto ON_EXIT;\r
1285 }\r
00c0c3f2 1286 }\r
99c048ef 1287 } else {\r
00c0c3f2 1288 ASSERT (Dns6TokenEntry != NULL);\r
fcae1a99
JW
1289\r
1290 if (Dns6TokenEntry->GeneralLookUp) {\r
1291 //\r
1292 // It's the GeneralLookUp querying.\r
1293 //\r
1294 Dns6TokenEntry->Token->RspData.GLookupData = AllocatePool (sizeof (DNS_RESOURCE_RECORD));\r
1295 if (Dns6TokenEntry->Token->RspData.GLookupData == NULL) {\r
3093f45c 1296 Status = EFI_OUT_OF_RESOURCES;\r
fcae1a99
JW
1297 goto ON_EXIT;\r
1298 }\r
1299 Dns6TokenEntry->Token->RspData.GLookupData->RRList = AllocatePool (DnsHeader->AnswersNum * sizeof (DNS_RESOURCE_RECORD));\r
1300 if (Dns6TokenEntry->Token->RspData.GLookupData->RRList == NULL) {\r
3093f45c 1301 Status = EFI_OUT_OF_RESOURCES;\r
fcae1a99
JW
1302 goto ON_EXIT;\r
1303 }\r
00c0c3f2 1304 } else {\r
fcae1a99
JW
1305 //\r
1306 // It's not the GeneralLookUp querying. Check the Query type.\r
1307 //\r
1308 if (QuerySection->Type == DNS_TYPE_AAAA) {\r
1309 Dns6TokenEntry->Token->RspData.H2AData = AllocatePool (sizeof (DNS6_HOST_TO_ADDR_DATA));\r
1310 if (Dns6TokenEntry->Token->RspData.H2AData == NULL) {\r
3093f45c 1311 Status = EFI_OUT_OF_RESOURCES;\r
fcae1a99
JW
1312 goto ON_EXIT;\r
1313 }\r
1314 Dns6TokenEntry->Token->RspData.H2AData->IpList = AllocatePool (DnsHeader->AnswersNum * sizeof (EFI_IPv6_ADDRESS));\r
1315 if (Dns6TokenEntry->Token->RspData.H2AData->IpList == NULL) {\r
3093f45c 1316 Status = EFI_OUT_OF_RESOURCES;\r
fcae1a99
JW
1317 goto ON_EXIT;\r
1318 }\r
1319 } else {\r
1320 Status = EFI_UNSUPPORTED;\r
1321 goto ON_EXIT;\r
1322 }\r
00c0c3f2 1323 }\r
99c048ef 1324 }\r
1325\r
3093f45c
JW
1326 Status = EFI_NOT_FOUND;\r
1327\r
99c048ef 1328 //\r
1329 // Processing AnswerSection.\r
1330 //\r
1331 while (AnswerSectionNum < DnsHeader->AnswersNum) {\r
1332 //\r
1333 // Answer name should be PTR.\r
1334 //\r
1335 ASSERT ((*(UINT8 *) AnswerName & 0xC0) == 0xC0);\r
1336 \r
1337 //\r
1338 // Get Answer section.\r
1339 //\r
1340 AnswerSection = (DNS_ANSWER_SECTION *) (AnswerName + sizeof (UINT16));\r
1341 AnswerSection->Type = NTOHS (AnswerSection->Type);\r
1342 AnswerSection->Class = NTOHS (AnswerSection->Class);\r
1343 AnswerSection->Ttl = NTOHL (AnswerSection->Ttl);\r
1344 AnswerSection->DataLength = NTOHS (AnswerSection->DataLength);\r
1345\r
fcae1a99
JW
1346 //\r
1347 // Check whether it's the GeneralLookUp querying.\r
1348 //\r
1349 if (Instance->Service->IpVersion == IP_VERSION_4 && Dns4TokenEntry->GeneralLookUp) {\r
fcae1a99
JW
1350 Dns4RR = Dns4TokenEntry->Token->RspData.GLookupData->RRList;\r
1351 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);\r
1352\r
1353 //\r
1354 // Fill the ResourceRecord.\r
1355 //\r
1356 Dns4RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1);\r
1357 if (Dns4RR[RRCount].QName == NULL) {\r
3093f45c 1358 Status = EFI_OUT_OF_RESOURCES;\r
fcae1a99
JW
1359 goto ON_EXIT;\r
1360 }\r
1361 CopyMem (Dns4RR[RRCount].QName, QueryName, AsciiStrLen (QueryName));\r
1362 Dns4RR[RRCount].QType = AnswerSection->Type;\r
1363 Dns4RR[RRCount].QClass = AnswerSection->Class;\r
1364 Dns4RR[RRCount].TTL = AnswerSection->Ttl;\r
1365 Dns4RR[RRCount].DataLength = AnswerSection->DataLength;\r
1366 Dns4RR[RRCount].RData = AllocateZeroPool (Dns4RR[RRCount].DataLength);\r
1367 if (Dns4RR[RRCount].RData == NULL) {\r
3093f45c 1368 Status = EFI_OUT_OF_RESOURCES;\r
fcae1a99
JW
1369 goto ON_EXIT;\r
1370 }\r
1371 CopyMem (Dns4RR[RRCount].RData, AnswerData, Dns4RR[RRCount].DataLength);\r
1372 \r
1373 RRCount ++;\r
3093f45c 1374 Status = EFI_SUCCESS;\r
fcae1a99 1375 } else if (Instance->Service->IpVersion == IP_VERSION_6 && Dns6TokenEntry->GeneralLookUp) {\r
fcae1a99
JW
1376 Dns6RR = Dns6TokenEntry->Token->RspData.GLookupData->RRList;\r
1377 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);\r
99c048ef 1378\r
fcae1a99
JW
1379 //\r
1380 // Fill the ResourceRecord.\r
1381 //\r
1382 Dns6RR[RRCount].QName = AllocateZeroPool (AsciiStrLen (QueryName) + 1);\r
1383 if (Dns6RR[RRCount].QName == NULL) {\r
3093f45c 1384 Status = EFI_OUT_OF_RESOURCES;\r
fcae1a99
JW
1385 goto ON_EXIT;\r
1386 }\r
1387 CopyMem (Dns6RR[RRCount].QName, QueryName, AsciiStrLen (QueryName));\r
1388 Dns6RR[RRCount].QType = AnswerSection->Type;\r
1389 Dns6RR[RRCount].QClass = AnswerSection->Class;\r
1390 Dns6RR[RRCount].TTL = AnswerSection->Ttl;\r
1391 Dns6RR[RRCount].DataLength = AnswerSection->DataLength;\r
1392 Dns6RR[RRCount].RData = AllocateZeroPool (Dns6RR[RRCount].DataLength);\r
1393 if (Dns6RR[RRCount].RData == NULL) {\r
3093f45c 1394 Status = EFI_OUT_OF_RESOURCES;\r
fcae1a99
JW
1395 goto ON_EXIT;\r
1396 }\r
1397 CopyMem (Dns6RR[RRCount].RData, AnswerData, Dns6RR[RRCount].DataLength);\r
1398 \r
1399 RRCount ++;\r
3093f45c 1400 Status = EFI_SUCCESS;\r
fcae1a99
JW
1401 } else {\r
1402 //\r
1403 // It's not the GeneralLookUp querying. \r
1404 // Check the Query type, parse the response packet.\r
1405 //\r
99c048ef 1406 switch (AnswerSection->Type) {\r
1407 case DNS_TYPE_A:\r
1408 //\r
1409 // This is address entry, get Data.\r
1410 //\r
00c0c3f2 1411 ASSERT (Dns4TokenEntry != NULL && AnswerSection->DataLength == 4);\r
99c048ef 1412 \r
1413 HostAddr4 = Dns4TokenEntry->Token->RspData.H2AData->IpList;\r
1414 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);\r
1415 CopyMem (&HostAddr4[IpCount], AnswerData, sizeof (EFI_IPv4_ADDRESS));\r
1416\r
99c048ef 1417 // \r
0a92ac88 1418 // Allocate new CacheEntry pool to update DNS cache dynamically.\r
99c048ef 1419 //\r
1420 Dns4CacheEntry = AllocateZeroPool (sizeof (EFI_DNS4_CACHE_ENTRY));\r
fcae1a99 1421 if (Dns4CacheEntry == NULL) {\r
3093f45c 1422 Status = EFI_OUT_OF_RESOURCES;\r
fcae1a99
JW
1423 goto ON_EXIT;\r
1424 }\r
99c048ef 1425 Dns4CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1));\r
fcae1a99 1426 if (Dns4CacheEntry->HostName == NULL) {\r
3093f45c 1427 Status = EFI_OUT_OF_RESOURCES;\r
fcae1a99
JW
1428 goto ON_EXIT;\r
1429 }\r
99c048ef 1430 CopyMem (Dns4CacheEntry->HostName, Dns4TokenEntry->QueryHostName, 2 * (StrLen(Dns4TokenEntry->QueryHostName) + 1));\r
1431 Dns4CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv4_ADDRESS));\r
fcae1a99 1432 if (Dns4CacheEntry->IpAddress == NULL) {\r
3093f45c 1433 Status = EFI_OUT_OF_RESOURCES;\r
fcae1a99
JW
1434 goto ON_EXIT;\r
1435 }\r
99c048ef 1436 CopyMem (Dns4CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv4_ADDRESS));\r
3093f45c
JW
1437\r
1438 if (CNameTtl != 0 && AnswerSection->Ttl != 0) {\r
1439 Dns4CacheEntry->Timeout = MIN (CNameTtl, AnswerSection->Ttl);\r
1440 } else {\r
1441 Dns4CacheEntry->Timeout = MAX (CNameTtl, AnswerSection->Ttl);\r
1442 }\r
99c048ef 1443 \r
0a92ac88
JW
1444 UpdateDns4Cache (&mDriverData->Dns4CacheList, FALSE, TRUE, *Dns4CacheEntry);\r
1445\r
1446 // \r
1447 // Free allocated CacheEntry pool.\r
1448 //\r
1449 FreePool (Dns4CacheEntry->HostName);\r
1450 Dns4CacheEntry->HostName = NULL;\r
1451 \r
1452 FreePool (Dns4CacheEntry->IpAddress);\r
1453 Dns4CacheEntry->IpAddress = NULL;\r
1454\r
1455 FreePool (Dns4CacheEntry);\r
1456 Dns4CacheEntry = NULL;\r
99c048ef 1457\r
3093f45c
JW
1458 IpCount ++;\r
1459 Status = EFI_SUCCESS;\r
99c048ef 1460 break;\r
1461 case DNS_TYPE_AAAA:\r
1462 //\r
1463 // This is address entry, get Data.\r
1464 //\r
00c0c3f2 1465 ASSERT (Dns6TokenEntry != NULL && AnswerSection->DataLength == 16);\r
99c048ef 1466 \r
1467 HostAddr6 = Dns6TokenEntry->Token->RspData.H2AData->IpList;\r
1468 AnswerData = (UINT8 *) AnswerSection + sizeof (*AnswerSection);\r
1469 CopyMem (&HostAddr6[IpCount], AnswerData, sizeof (EFI_IPv6_ADDRESS));\r
1470\r
99c048ef 1471 // \r
0a92ac88 1472 // Allocate new CacheEntry pool to update DNS cache dynamically.\r
99c048ef 1473 //\r
1474 Dns6CacheEntry = AllocateZeroPool (sizeof (EFI_DNS6_CACHE_ENTRY));\r
fcae1a99 1475 if (Dns6CacheEntry == NULL) {\r
3093f45c 1476 Status = EFI_OUT_OF_RESOURCES;\r
fcae1a99
JW
1477 goto ON_EXIT;\r
1478 }\r
99c048ef 1479 Dns6CacheEntry->HostName = AllocateZeroPool (2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1));\r
fcae1a99 1480 if (Dns6CacheEntry->HostName == NULL) {\r
3093f45c 1481 Status = EFI_OUT_OF_RESOURCES;\r
fcae1a99
JW
1482 goto ON_EXIT;\r
1483 }\r
99c048ef 1484 CopyMem (Dns6CacheEntry->HostName, Dns6TokenEntry->QueryHostName, 2 * (StrLen(Dns6TokenEntry->QueryHostName) + 1));\r
1485 Dns6CacheEntry->IpAddress = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS));\r
fcae1a99 1486 if (Dns6CacheEntry->IpAddress == NULL) {\r
3093f45c 1487 Status = EFI_OUT_OF_RESOURCES;\r
fcae1a99
JW
1488 goto ON_EXIT;\r
1489 }\r
99c048ef 1490 CopyMem (Dns6CacheEntry->IpAddress, AnswerData, sizeof (EFI_IPv6_ADDRESS));\r
3093f45c
JW
1491\r
1492 if (CNameTtl != 0 && AnswerSection->Ttl != 0) {\r
1493 Dns6CacheEntry->Timeout = MIN (CNameTtl, AnswerSection->Ttl);\r
1494 } else {\r
1495 Dns6CacheEntry->Timeout = MAX (CNameTtl, AnswerSection->Ttl);\r
1496 }\r
99c048ef 1497 \r
0a92ac88
JW
1498 UpdateDns6Cache (&mDriverData->Dns6CacheList, FALSE, TRUE, *Dns6CacheEntry);\r
1499\r
1500 // \r
1501 // Free allocated CacheEntry pool.\r
1502 //\r
1503 FreePool (Dns6CacheEntry->HostName);\r
1504 Dns6CacheEntry->HostName = NULL;\r
1505 \r
1506 FreePool (Dns6CacheEntry->IpAddress);\r
1507 Dns6CacheEntry->IpAddress = NULL;\r
1508\r
1509 FreePool (Dns6CacheEntry);\r
1510 Dns6CacheEntry = NULL;\r
99c048ef 1511 \r
1512 IpCount ++;\r
3093f45c
JW
1513 Status = EFI_SUCCESS;\r
1514 break;\r
1515 case DNS_TYPE_CNAME:\r
1516 //\r
1517 // According RFC 1034 - 3.6.2, if the query name is an alias, the name server will include the CNAME \r
1518 // record in the response and restart the query at the domain name specified in the data field of the \r
1519 // CNAME record. So, just record the TTL value of the CNAME, then skip to parse the next record.\r
1520 //\r
1521 CNameTtl = AnswerSection->Ttl;\r
99c048ef 1522 break;\r
1523 default:\r
1524 Status = EFI_UNSUPPORTED;\r
1525 goto ON_EXIT;\r
1526 }\r
1527 }\r
1528 \r
1529 //\r
1530 // Find next one\r
1531 //\r
1532 AnswerName = (CHAR8 *) AnswerSection + sizeof (*AnswerSection) + AnswerSection->DataLength;\r
1533 AnswerSectionNum ++;\r
1534 }\r
1535\r
00c0c3f2
JW
1536 if (Instance->Service->IpVersion == IP_VERSION_4) {\r
1537 ASSERT (Dns4TokenEntry != NULL);\r
fcae1a99
JW
1538 \r
1539 if (Dns4TokenEntry->GeneralLookUp) {\r
1540 Dns4TokenEntry->Token->RspData.GLookupData->RRCount = RRCount;\r
00c0c3f2 1541 } else {\r
fcae1a99
JW
1542 if (QuerySection->Type == DNS_TYPE_A) {\r
1543 Dns4TokenEntry->Token->RspData.H2AData->IpCount = IpCount;\r
1544 } else {\r
1545 Status = EFI_UNSUPPORTED;\r
1546 goto ON_EXIT;\r
1547 }\r
00c0c3f2
JW
1548 }\r
1549 } else {\r
1550 ASSERT (Dns6TokenEntry != NULL);\r
fcae1a99
JW
1551\r
1552 if (Dns6TokenEntry->GeneralLookUp) {\r
1553 Dns6TokenEntry->Token->RspData.GLookupData->RRCount = RRCount;\r
00c0c3f2 1554 } else {\r
fcae1a99
JW
1555 if (QuerySection->Type == DNS_TYPE_AAAA) {\r
1556 Dns6TokenEntry->Token->RspData.H2AData->IpCount = IpCount;\r
1557 } else {\r
1558 Status = EFI_UNSUPPORTED;\r
1559 goto ON_EXIT;\r
1560 }\r
00c0c3f2 1561 }\r
99c048ef 1562 }\r
0a92ac88
JW
1563 \r
1564ON_COMPLETE:\r
99c048ef 1565 //\r
3093f45c 1566 // Parsing is complete, free the sending packet and signal Event here.\r
99c048ef 1567 //\r
3093f45c
JW
1568 if (Item != NULL && Item->Value != NULL) {\r
1569 NetbufFree ((NET_BUF *) (Item->Value));\r
1570 }\r
1571 \r
99c048ef 1572 if (Instance->Service->IpVersion == IP_VERSION_4) {\r
00c0c3f2 1573 ASSERT (Dns4TokenEntry != NULL);\r
99c048ef 1574 Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry);\r
3093f45c 1575 Dns4TokenEntry->Token->Status = Status;\r
99c048ef 1576 if (Dns4TokenEntry->Token->Event != NULL) {\r
1577 gBS->SignalEvent (Dns4TokenEntry->Token->Event);\r
1578 DispatchDpc ();\r
1579 }\r
1580 } else {\r
00c0c3f2 1581 ASSERT (Dns6TokenEntry != NULL);\r
99c048ef 1582 Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry);\r
3093f45c 1583 Dns6TokenEntry->Token->Status = Status;\r
99c048ef 1584 if (Dns6TokenEntry->Token->Event != NULL) {\r
1585 gBS->SignalEvent (Dns6TokenEntry->Token->Event);\r
1586 DispatchDpc ();\r
1587 }\r
1588 }\r
1589\r
99c048ef 1590ON_EXIT:\r
1591 gBS->RestoreTPL (OldTpl);\r
1592 return Status;\r
1593}\r
1594\r
1595/**\r
1596 Parse response packet.\r
1597\r
1598 @param Packet The packets received.\r
1599 @param EndPoint The local/remote UDP access point\r
1600 @param IoStatus The status of the UDP receive\r
1601 @param Context The opaque parameter to the function.\r
1602\r
1603**/ \r
1604VOID\r
1605EFIAPI\r
1606DnsOnPacketReceived (\r
1607 NET_BUF *Packet,\r
1608 UDP_END_POINT *EndPoint,\r
1609 EFI_STATUS IoStatus,\r
1610 VOID *Context\r
1611 )\r
1612{\r
1613 DNS_INSTANCE *Instance;\r
1614\r
1615 UINT8 *RcvString;\r
1616\r
1617 BOOLEAN Completed;\r
1618 \r
1619 Instance = (DNS_INSTANCE *) Context;\r
1620 NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE);\r
1621\r
1622 RcvString = NULL;\r
1623 Completed = FALSE;\r
1624\r
1625 if (EFI_ERROR (IoStatus)) {\r
1626 goto ON_EXIT;\r
1627 }\r
1628\r
1629 ASSERT (Packet != NULL);\r
37b68011
FS
1630\r
1631 if (Packet->TotalSize <= sizeof (DNS_HEADER)) {\r
1632 goto ON_EXIT;\r
1633 }\r
99c048ef 1634 \r
1635 RcvString = NetbufGetByte (Packet, 0, NULL);\r
3fd7bd08 1636 ASSERT (RcvString != NULL);\r
1637 \r
99c048ef 1638 //\r
1639 // Parse Dns Response\r
1640 //\r
1641 ParseDnsResponse (Instance, RcvString, &Completed);\r
1642\r
37b68011 1643ON_EXIT:\r
99c048ef 1644\r
37b68011
FS
1645 if (Packet != NULL) {\r
1646 NetbufFree (Packet);\r
1647 }\r
99c048ef 1648\r
37b68011
FS
1649 if (!Completed) {\r
1650 UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);\r
1651 }\r
99c048ef 1652}\r
1653\r
1654/**\r
1655 Release the net buffer when packet is sent.\r
1656\r
1657 @param Packet The packets received.\r
1658 @param EndPoint The local/remote UDP access point\r
1659 @param IoStatus The status of the UDP receive\r
1660 @param Context The opaque parameter to the function.\r
1661\r
1662**/\r
1663VOID\r
1664EFIAPI\r
1665DnsOnPacketSent (\r
1666 NET_BUF *Packet,\r
1667 UDP_END_POINT *EndPoint,\r
1668 EFI_STATUS IoStatus,\r
1669 VOID *Context\r
1670 )\r
1671{\r
1672 DNS_INSTANCE *Instance;\r
1673 LIST_ENTRY *Entry;\r
1674 NET_MAP_ITEM *Item;\r
1675 DNS4_TOKEN_ENTRY *Dns4TokenEntry;\r
1676 DNS6_TOKEN_ENTRY *Dns6TokenEntry;\r
1677\r
1678 Dns4TokenEntry = NULL;\r
1679 Dns6TokenEntry = NULL;\r
1680\r
1681 Instance = (DNS_INSTANCE *) Context;\r
1682 NET_CHECK_SIGNATURE (Instance, DNS_INSTANCE_SIGNATURE);\r
1683\r
1684 if (Instance->Service->IpVersion == IP_VERSION_4) {\r
1685 NET_LIST_FOR_EACH (Entry, &Instance->Dns4TxTokens.Used) {\r
1686 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);\r
1687 if (Packet == (NET_BUF *)(Item->Value)) {\r
1688 Dns4TokenEntry = ((DNS4_TOKEN_ENTRY *)Item->Key);\r
1689 Dns4TokenEntry->PacketToLive = Dns4TokenEntry->Token->RetryInterval;\r
1690 break;\r
1691 }\r
1692 }\r
1693 } else {\r
1694 NET_LIST_FOR_EACH (Entry, &Instance->Dns6TxTokens.Used) {\r
1695 Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);\r
1696 if (Packet == (NET_BUF *)(Item->Value)) {\r
1697 Dns6TokenEntry = ((DNS6_TOKEN_ENTRY *)Item->Key);\r
1698 Dns6TokenEntry->PacketToLive = Dns6TokenEntry->Token->RetryInterval;\r
1699 break;\r
1700 }\r
1701 }\r
1702 }\r
1703 \r
1704 NetbufFree (Packet);\r
1705}\r
1706\r
1707/**\r
1708 Query request information.\r
1709\r
1710 @param Instance The DNS instance\r
1711 @param Packet The packet for querying request information.\r
1712\r
1713 @retval EFI_SUCCESS Query request information successfully.\r
1714 @retval Others Failed to query request information.\r
1715\r
1716**/\r
1717EFI_STATUS\r
1718DoDnsQuery (\r
1719 IN DNS_INSTANCE *Instance,\r
1720 IN NET_BUF *Packet\r
1721 )\r
1722{\r
1723 EFI_STATUS Status;\r
1724\r
1725 //\r
1726 // Ready to receive the DNS response.\r
1727 //\r
1728 if (Instance->UdpIo->RecvRequest == NULL) {\r
1729 Status = UdpIoRecvDatagram (Instance->UdpIo, DnsOnPacketReceived, Instance, 0);\r
1730 if (EFI_ERROR (Status)) {\r
1731 return Status;\r
1732 }\r
1733 }\r
1734 \r
1735 //\r
1736 // Transmit the DNS packet.\r
1737 //\r
1738 NET_GET_REF (Packet);\r
1739\r
1740 Status = UdpIoSendDatagram (Instance->UdpIo, Packet, NULL, NULL, DnsOnPacketSent, Instance);\r
1741 \r
1742 return Status;\r
1743}\r
1744\r
1745/**\r
fcae1a99 1746 Construct the Packet according query section.\r
99c048ef 1747\r
1748 @param Instance The DNS instance\r
fcae1a99
JW
1749 @param QueryName Queried Name \r
1750 @param Type Queried Type \r
1751 @param Class Queried Class \r
1752 @param Packet The packet for query\r
99c048ef 1753\r
1754 @retval EFI_SUCCESS The packet is constructed.\r
1755 @retval Others Failed to construct the Packet.\r
1756\r
1757**/\r
1758EFI_STATUS\r
fcae1a99 1759ConstructDNSQuery (\r
99c048ef 1760 IN DNS_INSTANCE *Instance,\r
fcae1a99 1761 IN CHAR8 *QueryName,\r
99c048ef 1762 IN UINT16 Type,\r
fcae1a99 1763 IN UINT16 Class,\r
99c048ef 1764 OUT NET_BUF **Packet\r
1765 )\r
1766{\r
1767 NET_FRAGMENT Frag;\r
1768 DNS_HEADER *DnsHeader;\r
fcae1a99 1769 DNS_QUERY_SECTION *DnsQuery;\r
3700da73
JW
1770\r
1771 //\r
1772 // Messages carried by UDP are restricted to 512 bytes (not counting the IP\r
1773 // or UDP headers).\r
1774 //\r
1775 Frag.Bulk = AllocatePool (DNS_MAX_MESSAGE_SIZE * sizeof (UINT8));\r
99c048ef 1776 if (Frag.Bulk == NULL) {\r
1777 return EFI_OUT_OF_RESOURCES;\r
1778 }\r
1779\r
1780 //\r
1781 // Fill header\r
1782 //\r
5e0cdec1
ZL
1783 DnsHeader = (DNS_HEADER *) Frag.Bulk; \r
1784 DnsHeader->Identification = (UINT16)NET_RANDOM (NetRandomInitSeed());\r
99c048ef 1785 DnsHeader->Flags.Uint16 = 0x0000;\r
1786 DnsHeader->Flags.Bits.RD = 1;\r
1787 DnsHeader->Flags.Bits.OpCode = DNS_FLAGS_OPCODE_STANDARD;\r
1788 DnsHeader->Flags.Bits.QR = DNS_FLAGS_QR_QUERY;\r
1789 DnsHeader->QuestionsNum = 1;\r
1790 DnsHeader->AnswersNum = 0;\r
1791 DnsHeader->AuthorityNum = 0;\r
1792 DnsHeader->AditionalNum = 0;\r
1793\r
5e0cdec1
ZL
1794 DnsHeader->Identification = HTONS (DnsHeader->Identification);\r
1795 DnsHeader->Flags.Uint16 = HTONS (DnsHeader->Flags.Uint16);\r
1796 DnsHeader->QuestionsNum = HTONS (DnsHeader->QuestionsNum);\r
1797 DnsHeader->AnswersNum = HTONS (DnsHeader->AnswersNum);\r
1798 DnsHeader->AuthorityNum = HTONS (DnsHeader->AuthorityNum);\r
1799 DnsHeader->AditionalNum = HTONS (DnsHeader->AditionalNum);\r
99c048ef 1800\r
1801 Frag.Len = sizeof (*DnsHeader);\r
1802\r
1803 //\r
1804 // Fill Query name\r
1805 //\r
fcae1a99
JW
1806 CopyMem (Frag.Bulk + Frag.Len, QueryName, AsciiStrLen (QueryName));\r
1807 Frag.Len = (UINT32) (Frag.Len + AsciiStrLen (QueryName));\r
1808 *(Frag.Bulk + Frag.Len) = 0;\r
1809 Frag.Len ++;\r
1810 \r
99c048ef 1811 //\r
1812 // Rest query section\r
1813 //\r
fcae1a99 1814 DnsQuery = (DNS_QUERY_SECTION *) (Frag.Bulk + Frag.Len);\r
99c048ef 1815\r
fcae1a99
JW
1816 DnsQuery->Type = HTONS (Type);\r
1817 DnsQuery->Class = HTONS (Class);\r
99c048ef 1818\r
fcae1a99 1819 Frag.Len += sizeof (*DnsQuery);\r
99c048ef 1820\r
1821 //\r
1822 // Wrap the Frag in a net buffer.\r
1823 //\r
1824 *Packet = NetbufFromExt (&Frag, 1, 0, 0, DnsDummyExtFree, NULL);\r
1825 if (*Packet == NULL) {\r
1826 FreePool (Frag.Bulk);\r
1827 return EFI_OUT_OF_RESOURCES;\r
1828 }\r
1829 \r
1830 //\r
1831 // Store the UdpIo in ProtoData.\r
1832 //\r
1833 *((UINTN *) &((*Packet)->ProtoData[0])) = (UINTN) (Instance->UdpIo);\r
1834\r
1835 return EFI_SUCCESS;\r
1836}\r
1837\r
1838/**\r
1839 Retransmit the packet.\r
1840\r
1841 @param Instance The DNS instance\r
1842 @param Packet Retransmit the packet \r
1843\r
1844 @retval EFI_SUCCESS The packet is retransmitted.\r
1845 @retval Others Failed to retransmit.\r
1846\r
1847**/\r
1848EFI_STATUS\r
1849DnsRetransmit (\r
1850 IN DNS_INSTANCE *Instance,\r
1851 IN NET_BUF *Packet\r
1852 )\r
1853{\r
1854 EFI_STATUS Status;\r
1855 \r
1856 UINT8 *Buffer;\r
1857\r
1858 ASSERT (Packet != NULL);\r
1859\r
1860 //\r
1861 // Set the requests to the listening port, other packets to the connected port\r
1862 //\r
1863 Buffer = NetbufGetByte (Packet, 0, NULL);\r
1864 ASSERT (Buffer != NULL);\r
1865\r
1866 NET_GET_REF (Packet);\r
1867\r
1868 Status = UdpIoSendDatagram (\r
1869 Instance->UdpIo,\r
1870 Packet,\r
1871 NULL,\r
1872 NULL,\r
1873 DnsOnPacketSent,\r
1874 Instance\r
1875 );\r
1876\r
1877 if (EFI_ERROR (Status)) {\r
1878 NET_PUT_REF (Packet);\r
1879 }\r
1880\r
1881 return Status;\r
1882}\r
1883\r
1884/**\r
1885 The timer ticking function for the DNS services.\r
1886\r
1887 @param Event The ticking event\r
1888 @param Context The DNS service instance\r
1889\r
1890**/\r
1891VOID\r
1892EFIAPI\r
1893DnsOnTimerRetransmit (\r
1894 IN EFI_EVENT Event,\r
1895 IN VOID *Context\r
1896 )\r
1897{\r
1898 DNS_SERVICE *Service;\r
1899\r
1900 LIST_ENTRY *Entry;\r
1901 LIST_ENTRY *Next;\r
1902\r
1903 DNS_INSTANCE *Instance;\r
1904 LIST_ENTRY *EntryNetMap;\r
1905 NET_MAP_ITEM *ItemNetMap;\r
1906 DNS4_TOKEN_ENTRY *Dns4TokenEntry;\r
1907 DNS6_TOKEN_ENTRY *Dns6TokenEntry;\r
1908\r
1909 Dns4TokenEntry = NULL;\r
1910 Dns6TokenEntry = NULL;\r
1911\r
1912 Service = (DNS_SERVICE *) Context;\r
1913\r
1914\r
1915 if (Service->IpVersion == IP_VERSION_4) {\r
1916 //\r
1917 // Iterate through all the children of the DNS service instance. Time\r
1918 // out the packet. If maximum retries reached, clean the Token up.\r
1919 //\r
1920 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Service->Dns4ChildrenList) {\r
1921 Instance = NET_LIST_USER_STRUCT (Entry, DNS_INSTANCE, Link);\r
1922\r
1923 EntryNetMap = Instance->Dns4TxTokens.Used.ForwardLink;\r
1924 while (EntryNetMap != &Instance->Dns4TxTokens.Used) {\r
1925 ItemNetMap = NET_LIST_USER_STRUCT (EntryNetMap, NET_MAP_ITEM, Link);\r
1926 Dns4TokenEntry = (DNS4_TOKEN_ENTRY *)(ItemNetMap->Key);\r
1927 if (Dns4TokenEntry->PacketToLive == 0 || (--Dns4TokenEntry->PacketToLive > 0)) {\r
1928 EntryNetMap = EntryNetMap->ForwardLink;\r
1929 continue;\r
1930 }\r
1931\r
1932 //\r
1933 // Retransmit the packet if haven't reach the maxmium retry count,\r
1934 // otherwise exit the transfer.\r
1935 //\r
1936 if (++Dns4TokenEntry->Token->RetryCount < Instance->MaxRetry) {\r
1937 DnsRetransmit (Instance, (NET_BUF *)ItemNetMap->Value);\r
1938 EntryNetMap = EntryNetMap->ForwardLink;\r
1939 } else {\r
1940 //\r
1941 // Maximum retries reached, clean the Token up.\r
1942 //\r
1943 Dns4RemoveTokenEntry (&Instance->Dns4TxTokens, Dns4TokenEntry);\r
1944 Dns4TokenEntry->Token->Status = EFI_TIMEOUT;\r
1945 gBS->SignalEvent (Dns4TokenEntry->Token->Event);\r
1946 DispatchDpc ();\r
1947 \r
1948 //\r
1949 // Free the sending packet.\r
1950 //\r
1951 if (ItemNetMap->Value != NULL) {\r
1952 NetbufFree ((NET_BUF *)(ItemNetMap->Value));\r
1953 }\r
1954\r
1955 EntryNetMap = Instance->Dns4TxTokens.Used.ForwardLink;\r
1956 }\r
1957 }\r
1958 } \r
1959 }else {\r
1960 //\r
1961 // Iterate through all the children of the DNS service instance. Time\r
1962 // out the packet. If maximum retries reached, clean the Token up.\r
1963 //\r
1964 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Service->Dns6ChildrenList) {\r
1965 Instance = NET_LIST_USER_STRUCT (Entry, DNS_INSTANCE, Link);\r
1966 \r
1967 EntryNetMap = Instance->Dns6TxTokens.Used.ForwardLink;\r
1968 while (EntryNetMap != &Instance->Dns6TxTokens.Used) {\r
1969 ItemNetMap = NET_LIST_USER_STRUCT (EntryNetMap, NET_MAP_ITEM, Link);\r
1970 Dns6TokenEntry = (DNS6_TOKEN_ENTRY *) (ItemNetMap->Key);\r
1971 if (Dns6TokenEntry->PacketToLive == 0 || (--Dns6TokenEntry->PacketToLive > 0)) {\r
1972 EntryNetMap = EntryNetMap->ForwardLink;\r
1973 continue;\r
1974 }\r
1975\r
1976 //\r
1977 // Retransmit the packet if haven't reach the maxmium retry count,\r
1978 // otherwise exit the transfer.\r
1979 //\r
1980 if (++Dns6TokenEntry->Token->RetryCount < Instance->MaxRetry) {\r
1981 DnsRetransmit (Instance, (NET_BUF *) ItemNetMap->Value);\r
1982 EntryNetMap = EntryNetMap->ForwardLink;\r
1983 } else {\r
1984 //\r
1985 // Maximum retries reached, clean the Token up.\r
1986 //\r
1987 Dns6RemoveTokenEntry (&Instance->Dns6TxTokens, Dns6TokenEntry);\r
1988 Dns6TokenEntry->Token->Status = EFI_TIMEOUT;\r
1989 gBS->SignalEvent (Dns6TokenEntry->Token->Event);\r
1990 DispatchDpc ();\r
1991 \r
1992 //\r
1993 // Free the sending packet.\r
1994 //\r
1995 if (ItemNetMap->Value != NULL) {\r
1996 NetbufFree ((NET_BUF *) (ItemNetMap->Value));\r
1997 }\r
1998\r
1999 EntryNetMap = Instance->Dns6TxTokens.Used.ForwardLink;\r
2000 } \r
2001 }\r
2002 }\r
2003 } \r
2004}\r
2005\r
2006/**\r
2007 The timer ticking function for the DNS driver.\r
2008\r
2009 @param Event The ticking event\r
2010 @param Context NULL\r
2011\r
2012**/\r
2013VOID\r
2014EFIAPI\r
2015DnsOnTimerUpdate (\r
2016 IN EFI_EVENT Event,\r
2017 IN VOID *Context\r
2018 )\r
2019{\r
2020 LIST_ENTRY *Entry;\r
2021 LIST_ENTRY *Next;\r
2022 DNS4_CACHE *Item4;\r
2023 DNS6_CACHE *Item6;\r
2024\r
2025 Item4 = NULL;\r
2026 Item6 = NULL;\r
2027\r
2028 //\r
2029 // Iterate through all the DNS4 cache list.\r
2030 //\r
2031 NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns4CacheList) {\r
2032 Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);\r
2033 Item4->DnsCache.Timeout--;\r
2034 }\r
2035 \r
2036 Entry = mDriverData->Dns4CacheList.ForwardLink;\r
2037 while (Entry != &mDriverData->Dns4CacheList) {\r
2038 Item4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);\r
3093f45c 2039 if (Item4->DnsCache.Timeout == 0) {\r
99c048ef 2040 RemoveEntryList (&Item4->AllCacheLink);\r
2041 Entry = mDriverData->Dns4CacheList.ForwardLink;\r
2042 } else {\r
2043 Entry = Entry->ForwardLink;\r
2044 }\r
2045 }\r
2046 \r
2047 //\r
2048 // Iterate through all the DNS6 cache list.\r
2049 //\r
2050 NET_LIST_FOR_EACH_SAFE (Entry, Next, &mDriverData->Dns6CacheList) {\r
2051 Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);\r
2052 Item6->DnsCache.Timeout--;\r
2053 }\r
2054 \r
2055 Entry = mDriverData->Dns6CacheList.ForwardLink;\r
2056 while (Entry != &mDriverData->Dns6CacheList) {\r
2057 Item6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);\r
3093f45c 2058 if (Item6->DnsCache.Timeout == 0) {\r
99c048ef 2059 RemoveEntryList (&Item6->AllCacheLink);\r
2060 Entry = mDriverData->Dns6CacheList.ForwardLink;\r
2061 } else {\r
2062 Entry = Entry->ForwardLink;\r
2063 }\r
2064 }\r
2065}\r
2066\r