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