]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/HttpDxe/HttpDns.c
daebc173b5e9a971f115845228936d6d47657540
[mirror_edk2.git] / NetworkPkg / HttpDxe / HttpDns.c
1 /** @file
2 Routines for HttpDxe driver to perform DNS resolution based on UEFI DNS protocols.
3
4 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "HttpDriver.h"
16
17 /**
18 Retrieve the host address using the EFI_DNS4_PROTOCOL.
19
20 @param[in] HttpInstance Pointer to HTTP_PROTOCOL instance.
21 @param[in] HostName Pointer to buffer containing hostname.
22 @param[out] IpAddress On output, pointer to buffer containing IPv4 address.
23
24 @retval EFI_SUCCESS Operation succeeded.
25 @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
26 @retval EFI_DEVICE_ERROR An unexpected network error occurred.
27 @retval Others Other errors as indicated.
28
29 **/
30 EFI_STATUS
31 HttpDns4 (
32 IN HTTP_PROTOCOL *HttpInstance,
33 IN CHAR16 *HostName,
34 OUT EFI_IPv4_ADDRESS *IpAddress
35 )
36 {
37 EFI_STATUS Status;
38 EFI_DNS4_PROTOCOL *Dns4;
39 EFI_DNS4_CONFIG_DATA Dns4CfgData;
40 EFI_DNS4_COMPLETION_TOKEN Token;
41 BOOLEAN IsDone;
42 HTTP_SERVICE *Service;
43 EFI_HANDLE Dns4Handle;
44 EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2;
45 UINTN DnsServerListCount;
46 EFI_IPv4_ADDRESS *DnsServerList;
47 UINTN DataSize;
48
49
50 Service = HttpInstance->Service;
51 ASSERT (Service != NULL);
52
53 DnsServerList = NULL;
54 DnsServerListCount = 0;
55 ZeroMem (&Token, sizeof (EFI_DNS4_COMPLETION_TOKEN));
56
57 //
58 // Get DNS server list from EFI IPv4 Configuration II protocol.
59 //
60 Status = gBS->HandleProtocol (Service->ControllerHandle, &gEfiIp4Config2ProtocolGuid, (VOID **) &Ip4Config2);
61 if (!EFI_ERROR (Status)) {
62 //
63 // Get the required size.
64 //
65 DataSize = 0;
66 Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeDnsServer, &DataSize, NULL);
67 if (Status == EFI_BUFFER_TOO_SMALL) {
68 DnsServerList = AllocatePool (DataSize);
69 if (DnsServerList == NULL) {
70 return EFI_OUT_OF_RESOURCES;
71 }
72
73 Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeDnsServer, &DataSize, DnsServerList);
74 if (EFI_ERROR (Status)) {
75 FreePool (DnsServerList);
76 DnsServerList = NULL;
77 } else {
78 DnsServerListCount = DataSize / sizeof (EFI_IPv4_ADDRESS);
79 }
80 }
81 }
82
83 Dns4Handle = NULL;
84 Dns4 = NULL;
85
86 //
87 // Create a DNS child instance and get the protocol.
88 //
89 Status = NetLibCreateServiceChild (
90 Service->ControllerHandle,
91 Service->ImageHandle,
92 &gEfiDns4ServiceBindingProtocolGuid,
93 &Dns4Handle
94 );
95 if (EFI_ERROR (Status)) {
96 goto Exit;
97 }
98
99 Status = gBS->OpenProtocol (
100 Dns4Handle,
101 &gEfiDns4ProtocolGuid,
102 (VOID **) &Dns4,
103 Service->ImageHandle,
104 Service->ControllerHandle,
105 EFI_OPEN_PROTOCOL_BY_DRIVER
106 );
107 if (EFI_ERROR (Status)) {
108 goto Exit;
109 }
110
111 //
112 // Configure DNS4 instance for the DNS server address and protocol.
113 //
114 ZeroMem (&Dns4CfgData, sizeof (Dns4CfgData));
115 Dns4CfgData.DnsServerListCount = DnsServerListCount;
116 Dns4CfgData.DnsServerList = DnsServerList;
117 Dns4CfgData.UseDefaultSetting = HttpInstance->IPv4Node.UseDefaultAddress;
118 if (!Dns4CfgData.UseDefaultSetting) {
119 IP4_COPY_ADDRESS (&Dns4CfgData.StationIp, &HttpInstance->IPv4Node.LocalAddress);
120 IP4_COPY_ADDRESS (&Dns4CfgData.SubnetMask, &HttpInstance->IPv4Node.LocalSubnet);
121 }
122 Dns4CfgData.EnableDnsCache = TRUE;
123 Dns4CfgData.Protocol = EFI_IP_PROTO_UDP;
124 Status = Dns4->Configure (
125 Dns4,
126 &Dns4CfgData
127 );
128 if (EFI_ERROR (Status)) {
129 goto Exit;
130 }
131
132 //
133 // Create event to set the is done flag when name resolution is finished.
134 //
135 ZeroMem (&Token, sizeof (Token));
136 Status = gBS->CreateEvent (
137 EVT_NOTIFY_SIGNAL,
138 TPL_NOTIFY,
139 HttpCommonNotify,
140 &IsDone,
141 &Token.Event
142 );
143 if (EFI_ERROR (Status)) {
144 goto Exit;
145 }
146
147 //
148 // Start asynchronous name resolution.
149 //
150 Token.Status = EFI_NOT_READY;
151 IsDone = FALSE;
152 Status = Dns4->HostNameToIp (Dns4, HostName, &Token);
153 if (EFI_ERROR (Status)) {
154 goto Exit;
155 }
156
157 while (!IsDone) {
158 Dns4->Poll (Dns4);
159 }
160
161 //
162 // Name resolution is done, check result.
163 //
164 Status = Token.Status;
165 if (!EFI_ERROR (Status)) {
166 if (Token.RspData.H2AData == NULL) {
167 Status = EFI_DEVICE_ERROR;
168 goto Exit;
169 }
170 if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) {
171 Status = EFI_DEVICE_ERROR;
172 goto Exit;
173 }
174 //
175 // We just return the first IP address from DNS protocol.
176 //
177 IP4_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);
178 Status = EFI_SUCCESS;
179 }
180
181 Exit:
182
183 if (Token.Event != NULL) {
184 gBS->CloseEvent (Token.Event);
185 }
186 if (Token.RspData.H2AData != NULL) {
187 if (Token.RspData.H2AData->IpList != NULL) {
188 FreePool (Token.RspData.H2AData->IpList);
189 }
190 FreePool (Token.RspData.H2AData);
191 }
192
193 if (Dns4 != NULL) {
194 Dns4->Configure (Dns4, NULL);
195
196 gBS->CloseProtocol (
197 Dns4Handle,
198 &gEfiDns4ProtocolGuid,
199 Service->ImageHandle,
200 Service->ControllerHandle
201 );
202 }
203
204 if (Dns4Handle != NULL) {
205 NetLibDestroyServiceChild (
206 Service->ControllerHandle,
207 Service->ImageHandle,
208 &gEfiDns4ServiceBindingProtocolGuid,
209 Dns4Handle
210 );
211 }
212
213 if (DnsServerList != NULL) {
214 FreePool (DnsServerList);
215 }
216
217 return Status;
218 }