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