IScsiDns.c 11 KB

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