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