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