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