HttpDns.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. /** @file
  2. Routines for HttpDxe driver to perform DNS resolution based on UEFI DNS protocols.
  3. Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "HttpDriver.h"
  7. /**
  8. Retrieve the host address using the EFI_DNS4_PROTOCOL.
  9. @param[in] HttpInstance Pointer to HTTP_PROTOCOL instance.
  10. @param[in] HostName Pointer to buffer containing hostname.
  11. @param[out] IpAddress On output, pointer to buffer containing IPv4 address.
  12. @retval EFI_SUCCESS Operation succeeded.
  13. @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
  14. @retval EFI_DEVICE_ERROR An unexpected network error occurred.
  15. @retval Others Other errors as indicated.
  16. **/
  17. EFI_STATUS
  18. HttpDns4 (
  19. IN HTTP_PROTOCOL *HttpInstance,
  20. IN CHAR16 *HostName,
  21. OUT EFI_IPv4_ADDRESS *IpAddress
  22. )
  23. {
  24. EFI_STATUS Status;
  25. EFI_DNS4_PROTOCOL *Dns4;
  26. EFI_DNS4_CONFIG_DATA Dns4CfgData;
  27. EFI_DNS4_COMPLETION_TOKEN Token;
  28. BOOLEAN IsDone;
  29. HTTP_SERVICE *Service;
  30. EFI_HANDLE Dns4Handle;
  31. EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2;
  32. UINTN DnsServerListCount;
  33. EFI_IPv4_ADDRESS *DnsServerList;
  34. UINTN DataSize;
  35. Service = HttpInstance->Service;
  36. ASSERT (Service != NULL);
  37. DnsServerList = NULL;
  38. DnsServerListCount = 0;
  39. ZeroMem (&Token, sizeof (EFI_DNS4_COMPLETION_TOKEN));
  40. //
  41. // Get DNS server list from EFI IPv4 Configuration II protocol.
  42. //
  43. Status = gBS->HandleProtocol (Service->ControllerHandle, &gEfiIp4Config2ProtocolGuid, (VOID **)&Ip4Config2);
  44. if (!EFI_ERROR (Status)) {
  45. //
  46. // Get the required size.
  47. //
  48. DataSize = 0;
  49. Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeDnsServer, &DataSize, NULL);
  50. if (Status == EFI_BUFFER_TOO_SMALL) {
  51. DnsServerList = AllocatePool (DataSize);
  52. if (DnsServerList == NULL) {
  53. return EFI_OUT_OF_RESOURCES;
  54. }
  55. Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeDnsServer, &DataSize, DnsServerList);
  56. if (EFI_ERROR (Status)) {
  57. FreePool (DnsServerList);
  58. DnsServerList = NULL;
  59. } else {
  60. DnsServerListCount = DataSize / sizeof (EFI_IPv4_ADDRESS);
  61. }
  62. }
  63. }
  64. Dns4Handle = NULL;
  65. Dns4 = NULL;
  66. //
  67. // Create a DNS child instance and get the protocol.
  68. //
  69. Status = NetLibCreateServiceChild (
  70. Service->ControllerHandle,
  71. Service->Ip4DriverBindingHandle,
  72. &gEfiDns4ServiceBindingProtocolGuid,
  73. &Dns4Handle
  74. );
  75. if (EFI_ERROR (Status)) {
  76. goto Exit;
  77. }
  78. Status = gBS->OpenProtocol (
  79. Dns4Handle,
  80. &gEfiDns4ProtocolGuid,
  81. (VOID **)&Dns4,
  82. Service->Ip4DriverBindingHandle,
  83. Service->ControllerHandle,
  84. EFI_OPEN_PROTOCOL_BY_DRIVER
  85. );
  86. if (EFI_ERROR (Status)) {
  87. goto Exit;
  88. }
  89. //
  90. // Configure DNS4 instance for the DNS server address and protocol.
  91. //
  92. ZeroMem (&Dns4CfgData, sizeof (Dns4CfgData));
  93. Dns4CfgData.DnsServerListCount = DnsServerListCount;
  94. Dns4CfgData.DnsServerList = DnsServerList;
  95. Dns4CfgData.UseDefaultSetting = HttpInstance->IPv4Node.UseDefaultAddress;
  96. if (!Dns4CfgData.UseDefaultSetting) {
  97. IP4_COPY_ADDRESS (&Dns4CfgData.StationIp, &HttpInstance->IPv4Node.LocalAddress);
  98. IP4_COPY_ADDRESS (&Dns4CfgData.SubnetMask, &HttpInstance->IPv4Node.LocalSubnet);
  99. }
  100. Dns4CfgData.EnableDnsCache = TRUE;
  101. Dns4CfgData.Protocol = EFI_IP_PROTO_UDP;
  102. Status = Dns4->Configure (
  103. Dns4,
  104. &Dns4CfgData
  105. );
  106. if (EFI_ERROR (Status)) {
  107. goto Exit;
  108. }
  109. //
  110. // Create event to set the is done flag when name resolution is finished.
  111. //
  112. ZeroMem (&Token, sizeof (Token));
  113. Status = gBS->CreateEvent (
  114. EVT_NOTIFY_SIGNAL,
  115. TPL_NOTIFY,
  116. HttpCommonNotify,
  117. &IsDone,
  118. &Token.Event
  119. );
  120. if (EFI_ERROR (Status)) {
  121. goto Exit;
  122. }
  123. //
  124. // Start asynchronous name resolution.
  125. //
  126. Token.Status = EFI_NOT_READY;
  127. IsDone = FALSE;
  128. Status = Dns4->HostNameToIp (Dns4, HostName, &Token);
  129. if (EFI_ERROR (Status)) {
  130. goto Exit;
  131. }
  132. while (!IsDone) {
  133. Dns4->Poll (Dns4);
  134. }
  135. //
  136. // Name resolution is done, check result.
  137. //
  138. Status = Token.Status;
  139. if (!EFI_ERROR (Status)) {
  140. if (Token.RspData.H2AData == NULL) {
  141. Status = EFI_DEVICE_ERROR;
  142. goto Exit;
  143. }
  144. if ((Token.RspData.H2AData->IpCount == 0) || (Token.RspData.H2AData->IpList == NULL)) {
  145. Status = EFI_DEVICE_ERROR;
  146. goto Exit;
  147. }
  148. //
  149. // We just return the first IP address from DNS protocol.
  150. //
  151. IP4_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);
  152. Status = EFI_SUCCESS;
  153. }
  154. Exit:
  155. if (Token.Event != NULL) {
  156. gBS->CloseEvent (Token.Event);
  157. }
  158. if (Token.RspData.H2AData != NULL) {
  159. if (Token.RspData.H2AData->IpList != NULL) {
  160. FreePool (Token.RspData.H2AData->IpList);
  161. }
  162. FreePool (Token.RspData.H2AData);
  163. }
  164. if (Dns4 != NULL) {
  165. Dns4->Configure (Dns4, NULL);
  166. gBS->CloseProtocol (
  167. Dns4Handle,
  168. &gEfiDns4ProtocolGuid,
  169. Service->Ip4DriverBindingHandle,
  170. Service->ControllerHandle
  171. );
  172. }
  173. if (Dns4Handle != NULL) {
  174. NetLibDestroyServiceChild (
  175. Service->ControllerHandle,
  176. Service->Ip4DriverBindingHandle,
  177. &gEfiDns4ServiceBindingProtocolGuid,
  178. Dns4Handle
  179. );
  180. }
  181. if (DnsServerList != NULL) {
  182. FreePool (DnsServerList);
  183. }
  184. return Status;
  185. }
  186. /**
  187. Retrieve the host address using the EFI_DNS6_PROTOCOL.
  188. @param[in] HttpInstance Pointer to HTTP_PROTOCOL instance.
  189. @param[in] HostName Pointer to buffer containing hostname.
  190. @param[out] IpAddress On output, pointer to buffer containing IPv6 address.
  191. @retval EFI_SUCCESS Operation succeeded.
  192. @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
  193. @retval EFI_DEVICE_ERROR An unexpected network error occurred.
  194. @retval Others Other errors as indicated.
  195. **/
  196. EFI_STATUS
  197. HttpDns6 (
  198. IN HTTP_PROTOCOL *HttpInstance,
  199. IN CHAR16 *HostName,
  200. OUT EFI_IPv6_ADDRESS *IpAddress
  201. )
  202. {
  203. EFI_STATUS Status;
  204. HTTP_SERVICE *Service;
  205. EFI_DNS6_PROTOCOL *Dns6;
  206. EFI_DNS6_CONFIG_DATA Dns6ConfigData;
  207. EFI_DNS6_COMPLETION_TOKEN Token;
  208. EFI_HANDLE Dns6Handle;
  209. EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
  210. EFI_IPv6_ADDRESS *DnsServerList;
  211. UINTN DnsServerListCount;
  212. UINTN DataSize;
  213. BOOLEAN IsDone;
  214. Service = HttpInstance->Service;
  215. ASSERT (Service != NULL);
  216. DnsServerList = NULL;
  217. DnsServerListCount = 0;
  218. Dns6 = NULL;
  219. Dns6Handle = NULL;
  220. ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN));
  221. //
  222. // Get DNS server list from EFI IPv6 Configuration protocol.
  223. //
  224. Status = gBS->HandleProtocol (Service->ControllerHandle, &gEfiIp6ConfigProtocolGuid, (VOID **)&Ip6Config);
  225. if (!EFI_ERROR (Status)) {
  226. //
  227. // Get the required size.
  228. //
  229. DataSize = 0;
  230. Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, NULL);
  231. if (Status == EFI_BUFFER_TOO_SMALL) {
  232. DnsServerList = AllocatePool (DataSize);
  233. if (DnsServerList == NULL) {
  234. return EFI_OUT_OF_RESOURCES;
  235. }
  236. Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, DnsServerList);
  237. if (EFI_ERROR (Status)) {
  238. FreePool (DnsServerList);
  239. DnsServerList = NULL;
  240. } else {
  241. DnsServerListCount = DataSize / sizeof (EFI_IPv6_ADDRESS);
  242. }
  243. }
  244. }
  245. //
  246. // Create a DNSv6 child instance and get the protocol.
  247. //
  248. Status = NetLibCreateServiceChild (
  249. Service->ControllerHandle,
  250. Service->Ip6DriverBindingHandle,
  251. &gEfiDns6ServiceBindingProtocolGuid,
  252. &Dns6Handle
  253. );
  254. if (EFI_ERROR (Status)) {
  255. goto Exit;
  256. }
  257. Status = gBS->OpenProtocol (
  258. Dns6Handle,
  259. &gEfiDns6ProtocolGuid,
  260. (VOID **)&Dns6,
  261. Service->Ip6DriverBindingHandle,
  262. Service->ControllerHandle,
  263. EFI_OPEN_PROTOCOL_BY_DRIVER
  264. );
  265. if (EFI_ERROR (Status)) {
  266. goto Exit;
  267. }
  268. //
  269. // Configure DNS6 instance for the DNS server address and protocol.
  270. //
  271. ZeroMem (&Dns6ConfigData, sizeof (EFI_DNS6_CONFIG_DATA));
  272. Dns6ConfigData.DnsServerCount = (UINT32)DnsServerListCount;
  273. Dns6ConfigData.DnsServerList = DnsServerList;
  274. Dns6ConfigData.EnableDnsCache = TRUE;
  275. Dns6ConfigData.Protocol = EFI_IP_PROTO_UDP;
  276. IP6_COPY_ADDRESS (&Dns6ConfigData.StationIp, &HttpInstance->Ipv6Node.LocalAddress);
  277. Status = Dns6->Configure (
  278. Dns6,
  279. &Dns6ConfigData
  280. );
  281. if (EFI_ERROR (Status)) {
  282. goto Exit;
  283. }
  284. Token.Status = EFI_NOT_READY;
  285. IsDone = FALSE;
  286. //
  287. // Create event to set the IsDone flag when name resolution is finished.
  288. //
  289. Status = gBS->CreateEvent (
  290. EVT_NOTIFY_SIGNAL,
  291. TPL_NOTIFY,
  292. HttpCommonNotify,
  293. &IsDone,
  294. &Token.Event
  295. );
  296. if (EFI_ERROR (Status)) {
  297. goto Exit;
  298. }
  299. //
  300. // Start asynchronous name resolution.
  301. //
  302. Status = Dns6->HostNameToIp (Dns6, HostName, &Token);
  303. if (EFI_ERROR (Status)) {
  304. goto Exit;
  305. }
  306. while (!IsDone) {
  307. Dns6->Poll (Dns6);
  308. }
  309. //
  310. // Name resolution is done, check result.
  311. //
  312. Status = Token.Status;
  313. if (!EFI_ERROR (Status)) {
  314. if (Token.RspData.H2AData == NULL) {
  315. Status = EFI_DEVICE_ERROR;
  316. goto Exit;
  317. }
  318. if ((Token.RspData.H2AData->IpCount == 0) || (Token.RspData.H2AData->IpList == NULL)) {
  319. Status = EFI_DEVICE_ERROR;
  320. goto Exit;
  321. }
  322. //
  323. // We just return the first IPv6 address from DNS protocol.
  324. //
  325. IP6_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);
  326. Status = EFI_SUCCESS;
  327. }
  328. Exit:
  329. if (Token.Event != NULL) {
  330. gBS->CloseEvent (Token.Event);
  331. }
  332. if (Token.RspData.H2AData != NULL) {
  333. if (Token.RspData.H2AData->IpList != NULL) {
  334. FreePool (Token.RspData.H2AData->IpList);
  335. }
  336. FreePool (Token.RspData.H2AData);
  337. }
  338. if (Dns6 != NULL) {
  339. Dns6->Configure (Dns6, NULL);
  340. gBS->CloseProtocol (
  341. Dns6Handle,
  342. &gEfiDns6ProtocolGuid,
  343. Service->Ip6DriverBindingHandle,
  344. Service->ControllerHandle
  345. );
  346. }
  347. if (Dns6Handle != NULL) {
  348. NetLibDestroyServiceChild (
  349. Service->ControllerHandle,
  350. Service->Ip6DriverBindingHandle,
  351. &gEfiDns6ServiceBindingProtocolGuid,
  352. Dns6Handle
  353. );
  354. }
  355. if (DnsServerList != NULL) {
  356. FreePool (DnsServerList);
  357. }
  358. return Status;
  359. }