Skip to content

Commit

Permalink
work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
alexey-tikhonov committed Sep 11, 2024
1 parent a87dc9d commit ed113e8
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 0 deletions.
129 changes: 129 additions & 0 deletions src/resolv/async_resolv.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,82 @@ resolv_reread_configuration(struct resolv_ctx *ctx)
recreate_ares_channel(ctx);
}

#if (ARES_VERSION_MAJOR > 1) || ((ARES_VERSION_MAJOR == 1) && (ARES_VERSION_MINOR >= 22))
typedef errno_t (*rr_handler)(const ares_dns_rr_t *, void *);

static errno_t rr_counter(const struct ares_dns_rr *, void *p)
{
size_t *c = (size_t *)p;
*c = *c + 1;
return EOK;
}

static errno_t addr_copier(const struct ares_dns_rr *rr, void *p)
{
struct resolv_addr **list = (struct resolv_addr **) p;
while (*list != NULL) ++list; /* array was pre-allocated, find first empty */
struct resolv_addr *addr = *list;

addr = talloc_zero(p, struct resolv_addr);
if (addr == NULL) return ENOMEM;

addr->ttl = (int) ares_dns_rr_get_ttl(rr);

ares_dns_rec_type_t type = ares_dns_rr_get_type(rr);
if (type == ARES_REC_TYPE_A) {
const struct in_addr *in = ares_dns_rr_get_addr(rr, ARES_RR_A_ADDR);
addr->ipaddr = talloc_array(addr, uint8_t, sizeof(struct in_addr));
if (addr->ipaddr == NULL) return ENOMEM;
memcpy(addr->ipaddr, in, sizeof(struct in_addr));
} else if (type == ARES_REC_TYPE_AAAA) {
const struct ares_in6_addr *in6 = ares_dns_rr_get_addr6(rr,ARES_RR_AAAA_ADDR);
addr->ipaddr = talloc_array(addr, uint8_t, sizeof(struct in6_addr));
if (addr->ipaddr == NULL) return ENOMEM;
memcpy(addr->ipaddr, in6, sizeof(struct in6_addr));
} else {
DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected RR type %d\n", type);
}

return EOK;
}

static errno_t iterate_valid_rrs(const ares_dns_record_t *dnsrec, int family, rr_handler func, void *pvt)
{
size_t rr_cnt, i;
const ares_dns_rr_t *rr;
int ret;

rr_cnt = ares_dns_record_rr_cnt(dnsrec, ARES_SECTION_ANSWER);

for (i = 0; i < rr_cnt; ++i) {
#if (ARES_VERSION_MAJOR == 1) && (ARES_VERSION_MINOR < 28)
rr = ares_dns_record_rr_get(dnsrec, ARES_SECTION_ANSWER, i);
#else /* const getter is only available since c-ares-1.28 */
rr = ares_dns_record_rr_get_const(dnsrec, ARES_SECTION_ANSWER, i);
#endif
if (rr == NULL) continue;

if (ares_dns_rr_get_class(rr) != ARES_CLASS_IN) continue;

int ttl = (int) ares_dns_rr_get_ttl(rr);
if (ttl <= 0) continue;

ares_dns_rec_type_t type = ares_dns_rr_get_type(rr);

if (((family == AF_INET) && (type == ARES_REC_TYPE_A)) ||
((family == AF_INET6) && (type == ARES_REC_TYPE_AAAA))) {
ret = func(rr, pvt);
if (ret != EOK) {
return ret;
}
}
}

return EOK;
}

#else

static errno_t
resolv_copy_in_addr(TALLOC_CTX *mem_ctx, struct resolv_addr *ret,

Check warning on line 581 in src/resolv/async_resolv.c

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'resolv_copy_in_addr' is never used.
struct ares_addrttl *attl)
Expand All @@ -526,6 +602,7 @@ resolv_copy_in6_addr(TALLOC_CTX *mem_ctx, struct resolv_addr *ret,

return EOK;
}
#endif

static struct resolv_hostent *
resolv_copy_hostent_common(TALLOC_CTX *mem_ctx, struct hostent *src)
Expand Down Expand Up @@ -614,6 +691,7 @@ resolv_copy_hostent(TALLOC_CTX *mem_ctx, struct hostent *src)
return NULL;
}

#if (ARES_VERSION_MAJOR == 1) && (ARES_VERSION_MINOR < 22)
struct resolv_hostent *
resolv_copy_hostent_ares(TALLOC_CTX *mem_ctx, struct hostent *src,
int family, void *ares_ttl_data,
Expand Down Expand Up @@ -672,6 +750,7 @@ resolv_copy_hostent_ares(TALLOC_CTX *mem_ctx, struct hostent *src,
talloc_free(ret);
return NULL;
}
#endif

/* =================== Resolve host name in files =========================*/
struct gethostbyname_files_state {
Expand Down Expand Up @@ -946,6 +1025,55 @@ resolv_gethostbyname_dns_query_done(void *arg, int status, int timeouts,
static int
resolv_gethostbyname_dns_parse(struct gethostbyname_dns_state *state,
unsigned char *abuf, int alen)
#if (ARES_VERSION_MAJOR > 1) || ((ARES_VERSION_MAJOR == 1) && (ARES_VERSION_MINOR >= 22))
{
int ret;
ares_dns_record_t *dnsrec = NULL;
size_t answers_cnt = 0;

ares_status_t s = ares_dns_parse(abuf, (size_t) alen, 0, &dnsrec);
if ((s != ARES_SUCCESS) || (dnsrec == NULL)) {
DEBUG(SSSDBG_OP_FAILURE, "Failed to parse reply: %d\n", s);
return EIO;
}

ret = iterate_valid_rrs(dnsrec, state->family, rr_counter, &answers_cnt);
if ((ret != EOK) || (answers_cnt == 0)) {
DEBUG(SSSDBG_MINOR_FAILURE, "No valid answers\n");
ret = ENOENT;
goto done;
}

state->rhostent = talloc_zero(state, struct resolv_hostent);
if (state->rhostent == NULL) {
ret = ENOMEM;
goto done;
}
state->rhostent->family = state->family;
state->rhostent->name = talloc_strdup(state->rhostent, state->name);
if (state->rhostent->name == NULL) {
ret = ENOMEM;
goto done;
}
state->rhostent->addr_list = talloc_zero_array(state->rhostent,
struct resolv_addr *,
answers_cnt + 1);
if (state->rhostent->addr_list == NULL) {
ret = ENOMEM;
goto done;
}

ret = iterate_valid_rrs(dnsrec, state->family,
addr_copier, state->rhostent->addr_list);

done:
ares_dns_record_destroy(dnsrec);
if (ret != EOK) {
talloc_zfree(state->rhostent);
}
return ret;
}
#else /* c-ares < 1.22 */
{
struct hostent *hostent = NULL;
int naddrttls;
Expand Down Expand Up @@ -1018,6 +1146,7 @@ resolv_gethostbyname_dns_parse(struct gethostbyname_dns_state *state,
talloc_free(addr);
return ret;
}
#endif

static int
resolv_gethostbyname_dns_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
Expand Down
4 changes: 4 additions & 0 deletions src/tests/resolv-tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ test_create_rhostent(TALLOC_CTX *mem_ctx,
return NULL;
}

#if (ARES_VERSION_MAJOR == 1) && (ARES_VERSION_MINOR < 22)
START_TEST(test_copy_hostent)
{
void *ctx;
Expand Down Expand Up @@ -230,6 +231,7 @@ START_TEST(test_copy_hostent)
ck_leaks_pop(ctx);
}
END_TEST
#endif

START_TEST(test_address_to_string)
{
Expand Down Expand Up @@ -1047,7 +1049,9 @@ Suite *create_resolv_suite(void)

tcase_add_checked_fixture(tc_resolv, ck_leak_check_setup, ck_leak_check_teardown);
/* Do some testing */
#if (ARES_VERSION_MAJOR == 1) && (ARES_VERSION_MINOR < 22)
tcase_add_test(tc_resolv, test_copy_hostent);
#endif
tcase_add_test(tc_resolv, test_address_to_string);
tcase_add_test(tc_resolv, test_resolv_ip_addr);
tcase_add_test(tc_resolv, test_resolv_unix);
Expand Down

0 comments on commit ed113e8

Please sign in to comment.