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