Hi,

I'm seeing the behaviour described in $SUBJECT with git head of c-ares
and I'd like to discuss the best way of fixing it.

If you search with ares_gethostbyname() with lookup family set to AF_UNSPEC,
the first family to try would be AF_INET6. The code would jump to
host_callback() on completing the query and try to parse the returned abuf:

188       else if (hquery->sent_family == AF_INET6)
189         {
190           status = ares_parse_aaaa_reply(abuf, alen, &host, NULL, NULL);
191           if ((status == ARES_ENODATA || status == ARES_EBADRESP) &&
192                hquery->want_family == AF_UNSPEC) {
193             /* The query returned something but either there were no AAAA
194                records (e.g. just CNAME) or the response was malformed.  Try
195                looking up A instead. */

But since commit b3afe9cbdee797652d8cfba49aa2e9d42bf781fe parsing a query
that only contains CNAMES returns ARES_SUCCESS and a hostent that contains
the aliases, so the condition on list 191 never matches and AF_INET is
never retried. I don't see a way for ares_parse_aaaa_reply() caller to
see if the data returned contain a real AAAA response or just CNAMEs.

I think ares_parse_aaaa_reply() behaviour is correct now and
I think host_callback() here is buggy, or rather relies on
bug in ares_parse_aaaa_reply(). Since we apparently can't use
ares_parse_aaaa_reply(), I'd like to suggest a new internal function,
something like:

    int ares_peek_aaaa_reply(const unsigned char *abuf, int alen,
                             int *naaaa, int *ncname);

And change the fallback condition to:
    status = ares_peek_aaaa_reply(abuf, alen, &naaaa, &ncname);
    if ((status == ARES_ENODATA || status == ARES_EBADRESP ||
        (status == ARES_SUCCESS && naaaa == 0)) &&
        hquery->want_family == AF_UNSPEC) {
        }

Would that be an acceptable solution? Is there any other/better way?

Thanks for any suggestions.

Reply via email to