host_resolver.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /**
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. * SPDX-License-Identifier: Apache-2.0.
  4. */
  5. #include <aws/io/host_resolver.h>
  6. #include <aws/io/logging.h>
  7. #include <aws/common/string.h>
  8. #include <arpa/inet.h>
  9. #include <netdb.h>
  10. #include <sys/socket.h>
  11. #include <sys/types.h>
  12. int aws_default_dns_resolve(
  13. struct aws_allocator *allocator,
  14. const struct aws_string *host_name,
  15. struct aws_array_list *output_addresses,
  16. void *user_data) {
  17. (void)user_data;
  18. struct addrinfo *result = NULL;
  19. struct addrinfo *iter = NULL;
  20. /* max string length for ipv6. */
  21. socklen_t max_len = INET6_ADDRSTRLEN;
  22. char address_buffer[max_len];
  23. const char *hostname_cstr = aws_string_c_str(host_name);
  24. AWS_LOGF_DEBUG(AWS_LS_IO_DNS, "static: resolving host %s", hostname_cstr);
  25. /* Android would prefer NO HINTS IF YOU DON'T MIND, SIR */
  26. #if defined(ANDROID)
  27. int err_code = getaddrinfo(hostname_cstr, NULL, NULL, &result);
  28. #else
  29. struct addrinfo hints;
  30. AWS_ZERO_STRUCT(hints);
  31. hints.ai_family = AF_UNSPEC;
  32. hints.ai_socktype = SOCK_STREAM;
  33. # if !defined(__OpenBSD__)
  34. hints.ai_flags = AI_ALL | AI_V4MAPPED;
  35. # endif /* __OpenBSD__ */
  36. int err_code = getaddrinfo(hostname_cstr, NULL, &hints, &result);
  37. #endif
  38. if (err_code) {
  39. AWS_LOGF_ERROR(
  40. AWS_LS_IO_DNS, "static: getaddrinfo failed with error_code %d: %s", err_code, gai_strerror(err_code));
  41. goto clean_up;
  42. }
  43. for (iter = result; iter != NULL; iter = iter->ai_next) {
  44. struct aws_host_address host_address;
  45. AWS_ZERO_ARRAY(address_buffer);
  46. if (iter->ai_family == AF_INET6) {
  47. host_address.record_type = AWS_ADDRESS_RECORD_TYPE_AAAA;
  48. inet_ntop(iter->ai_family, &((struct sockaddr_in6 *)iter->ai_addr)->sin6_addr, address_buffer, max_len);
  49. } else {
  50. host_address.record_type = AWS_ADDRESS_RECORD_TYPE_A;
  51. inet_ntop(iter->ai_family, &((struct sockaddr_in *)iter->ai_addr)->sin_addr, address_buffer, max_len);
  52. }
  53. size_t address_len = strlen(address_buffer);
  54. const struct aws_string *address =
  55. aws_string_new_from_array(allocator, (const uint8_t *)address_buffer, address_len);
  56. if (!address) {
  57. goto clean_up;
  58. }
  59. const struct aws_string *host_cpy = aws_string_new_from_string(allocator, host_name);
  60. if (!host_cpy) {
  61. aws_string_destroy((void *)address);
  62. goto clean_up;
  63. }
  64. AWS_LOGF_DEBUG(AWS_LS_IO_DNS, "static: resolved record: %s", address_buffer);
  65. host_address.address = address;
  66. host_address.weight = 0;
  67. host_address.allocator = allocator;
  68. host_address.use_count = 0;
  69. host_address.connection_failure_count = 0;
  70. host_address.host = host_cpy;
  71. if (aws_array_list_push_back(output_addresses, &host_address)) {
  72. aws_host_address_clean_up(&host_address);
  73. goto clean_up;
  74. }
  75. }
  76. freeaddrinfo(result);
  77. return AWS_OP_SUCCESS;
  78. clean_up:
  79. if (result) {
  80. freeaddrinfo(result);
  81. }
  82. if (err_code) {
  83. switch (err_code) {
  84. case EAI_FAIL:
  85. case EAI_AGAIN:
  86. return aws_raise_error(AWS_IO_DNS_QUERY_FAILED);
  87. case EAI_MEMORY:
  88. return aws_raise_error(AWS_ERROR_OOM);
  89. case EAI_NONAME:
  90. case EAI_SERVICE:
  91. return aws_raise_error(AWS_IO_DNS_INVALID_NAME);
  92. default:
  93. return aws_raise_error(AWS_ERROR_SYS_CALL_FAILURE);
  94. }
  95. }
  96. return AWS_OP_ERR;
  97. }