|
|
|
.\"
|
|
|
|
.\" Copyright 1998 by the Massachusetts Institute of Technology.
|
|
|
|
.\" SPDX-License-Identifier: MIT
|
|
|
|
.\"
|
|
|
|
.TH ARES_GETADDRINFO 3 "4 November 2018"
|
|
|
|
.SH NAME
|
|
|
|
ares_getaddrinfo \- Initiate a host query by name and service
|
|
|
|
.SH SYNOPSIS
|
|
|
|
.nf
|
|
|
|
#include <ares.h>
|
|
|
|
|
|
|
|
typedef void (*ares_addrinfo_callback)(void *\fIarg\fP, int \fIstatus\fP,
|
|
|
|
int \fItimeouts\fP,
|
|
|
|
struct ares_addrinfo *\fIresult\fP)
|
|
|
|
|
`ares_channel` -> `ares_channel_t *`: don't bury the pointer (#595)
`ares_channel` is defined as `typedef struct ares_channeldata *ares_channel;`. The problem with this, is it embeds the pointer into the typedef, which means an `ares_channel` can never be declared as `const` as if you write `const ares_channel channel`, that expands to `struct ares_channeldata * const ares_channel` and not `const struct ares_channeldata *channel`.
We will now typedef `ares_channel_t` as `typedef struct ares_channeldata ares_channel_t;`, so if you write `const ares_channel_t *channel`, it properly expands to `const struct ares_channeldata *channel`.
We are maintaining the old typedef for API compatibility with existing integrations, and due to typedef expansion this should not even cause any compiler warnings for existing code. There are no ABI implications with this change. I could be convinced to keep existing public functions as `ares_channel` if a sufficient argument exists, but internally we really need make this change for modern best practices.
This change will allow us to internally use `const ares_channel_t *` where appropriate. Whether or not we decide to change any public interfaces to use `const` may require further discussion on if there might be ABI implications (I don't think so, but I'm also not 100% sure what a compiler internally does with `const` when emitting machine code ... I think more likely ABI implications would occur going the opposite direction).
FYI, This PR was done via a combination of sed and clang-format, the only manual code change was the addition of the new typedef, and a couple doc fixes :)
Fix By: Brad House (@bradh352)
1 year ago
|
|
|
void ares_getaddrinfo(ares_channel_t *\fIchannel\fP, const char *\fIname\fP,
|
|
|
|
const char* \fIservice\fP,
|
|
|
|
const struct ares_addrinfo_hints *\fIhints\fP,
|
|
|
|
ares_addrinfo_callback \fIcallback\fP, void *\fIarg\fP)
|
|
|
|
.fi
|
|
|
|
.SH DESCRIPTION
|
|
|
|
The \fBares_getaddrinfo(3)\fP function initiates a host query by name on the
|
|
|
|
name service channel identified by
|
|
|
|
.IR channel .
|
|
|
|
The
|
|
|
|
.I name
|
|
|
|
and
|
|
|
|
.I service
|
|
|
|
parameters give the hostname and service as NULL-terminated C strings.
|
|
|
|
The
|
|
|
|
.I hints
|
|
|
|
parameter is an
|
|
|
|
.BR ares_addrinfo_hints
|
|
|
|
structure:
|
|
|
|
.PP
|
|
|
|
.RS
|
|
|
|
.EX
|
|
|
|
struct ares_addrinfo_hints {
|
|
|
|
int ai_flags;
|
|
|
|
int ai_family;
|
|
|
|
int ai_socktype;
|
|
|
|
int ai_protocol;
|
|
|
|
};
|
|
|
|
.EE
|
|
|
|
.RE
|
|
|
|
.TP
|
|
|
|
.I ai_family
|
|
|
|
Specifies desired address family. AF_UNSPEC means return both AF_INET and AF_INET6.
|
|
|
|
.TP
|
|
|
|
.I ai_socktype
|
|
|
|
Specifies desired socket type, for example SOCK_STREAM or SOCK_DGRAM.
|
|
|
|
Setting this to 0 means any type.
|
|
|
|
.TP
|
|
|
|
.I ai_protocol
|
|
|
|
Setting this to 0 means any protocol.
|
|
|
|
.TP
|
|
|
|
.I ai_flags
|
|
|
|
Specifies additional options, see below.
|
|
|
|
.PP
|
|
|
|
.TP 19
|
|
|
|
.B ARES_AI_NUMERICSERV
|
|
|
|
If this option is set
|
|
|
|
.I service
|
|
|
|
field will be treated as a numeric value.
|
|
|
|
.TP 19
|
|
|
|
.B ARES_AI_CANONNAME
|
|
|
|
The ares_addrinfo structure will return a canonical names list.
|
|
|
|
.TP 19
|
|
|
|
.B ARES_AI_NOSORT
|
|
|
|
Result addresses will not be sorted and no connections to resolved addresses will be attempted.
|
|
|
|
.TP 19
|
|
|
|
.B ARES_AI_ENVHOSTS
|
|
|
|
Read hosts file path from the environment variable
|
|
|
|
.I CARES_HOSTS .
|
|
|
|
.PP
|
|
|
|
When the query is complete or has failed, the ares library will invoke \fIcallback\fP.
|
|
|
|
Completion or failure of the query may happen immediately, or may happen
|
|
|
|
during a later call to \fIares_process(3)\fP, \fIares_destroy(3)\fP or
|
|
|
|
\fIares_cancel(3)\fP.
|
|
|
|
.PP
|
|
|
|
When the associated callback is called, it is called with a channel lock so care
|
|
|
|
must be taken to ensure any processing is minimal to prevent DNS channel stalls.
|
|
|
|
|
|
|
|
The callback may be triggered from a different thread than the one which
|
|
|
|
called \fIares_getaddrinfo(3)\fP.
|
|
|
|
|
|
|
|
For integrators running their own event loops and not using \fBARES_OPT_EVENT_THREAD\fP,
|
|
|
|
care needs to be taken to ensure any file descriptor lists are updated immediately
|
|
|
|
within the eventloop when notified.
|
|
|
|
.PP
|
|
|
|
The callback argument
|
|
|
|
.I arg
|
|
|
|
is copied from the \fBares_getaddrinfo(3)\fP argument
|
|
|
|
.IR arg .
|
|
|
|
The callback argument
|
|
|
|
.I status
|
|
|
|
indicates whether the query succeeded and, if not, how it failed. It
|
|
|
|
may have any of the following values:
|
|
|
|
.TP 19
|
|
|
|
.B ARES_SUCCESS
|
|
|
|
The host lookup completed successfully.
|
|
|
|
.TP 19
|
|
|
|
.B ARES_ENOTIMP
|
|
|
|
The ares library does not know how to find addresses of type
|
|
|
|
.IR family .
|
|
|
|
.TP 19
|
|
|
|
.B ARES_ENOTFOUND
|
|
|
|
The
|
|
|
|
.I name
|
|
|
|
was not found.
|
|
|
|
.TP 19
|
|
|
|
.B ARES_ENOMEM
|
|
|
|
Memory was exhausted.
|
|
|
|
.TP 19
|
|
|
|
.B ARES_ESERVICE
|
|
|
|
The textual service name provided could not be dereferenced into a port.
|
|
|
|
.TP 19
|
|
|
|
.B ARES_ECANCELLED
|
|
|
|
The query was cancelled.
|
|
|
|
.TP 19
|
|
|
|
.B ARES_EDESTRUCTION
|
|
|
|
The name service channel
|
|
|
|
.I channel
|
|
|
|
is being destroyed; the query will not be completed.
|
|
|
|
.PP
|
|
|
|
On successful completion of the query, the callback argument
|
|
|
|
.I result
|
|
|
|
points to a
|
|
|
|
.B struct ares_addrinfo
|
Reimplement ares_gethostbyname() by wrapping ares_getaddrinfo() (#428)
ares_gethostbyname() and ares_getaddrinfo() do a lot of similar things, however ares_getaddrinfo() has some desirable behaviors that should be imported into ares_gethostbyname(). For one, it sorts the address lists for the most likely to succeed based on the current system routes. Next, when AF_UNSPEC is specified, it properly handles search lists instead of first searching all of AF_INET6 then AF_INET, since ares_gethostbyname() searches in parallel. Therefore, this PR should also resolve the issues attempted in #94.
A few things this PR does:
1. ares_parse_a_reply() and ares_parse_aaaa_reply() had very similar code to translate struct ares_addrinfo into a struct hostent as well as into struct ares_addrttl/ares_addr6ttl this has been split out into helper functions of ares__addrinfo2hostent() and ares__addrinfo2addrttl() to prevent this duplicative code.
2. ares_getaddrinfo() was apparently never honoring HOSTALIASES, and this was discovered once ares_gethostbyname() was turned into a wrapper, the affected test cases started failing.
3. A slight API modification to save the query hostname into struct ares_addrinfo as the last element of name. Since this is the last element, and all user-level instances of struct ares_addrinfo are allocated internally by c-ares, this is not an ABI-breaking change nor would it impact any API compatibility. This was needed since struct hostent has an h_name element.
4. Test Framework: MockServer tests via TCP would fail if more than 1 request was received at a time which is common when ares_getaddrinfo() queries for both A and AAAA records simultaneously. Infact, this was a long standing issue in which the ares_getaddrinfo() test were bypassing TCP alltogether. This has been corrected, the message is now processed in a loop.
5. Some tests had to be updated for overall correctness as they were invalid but somehow passing prior to this change.
Change By: Brad House (@bradh352)
3 years ago
|
|
|
which contains two linked lists, one with resolved addresses and another with canonical names.
|
|
|
|
Also included is the official name of the host (analogous to gethostbyname() h_name).
|
|
|
|
.PP
|
|
|
|
.RS
|
|
|
|
.EX
|
|
|
|
struct ares_addrinfo {
|
|
|
|
struct ares_addrinfo_cname *cnames;
|
|
|
|
struct ares_addrinfo_node *nodes;
|
Reimplement ares_gethostbyname() by wrapping ares_getaddrinfo() (#428)
ares_gethostbyname() and ares_getaddrinfo() do a lot of similar things, however ares_getaddrinfo() has some desirable behaviors that should be imported into ares_gethostbyname(). For one, it sorts the address lists for the most likely to succeed based on the current system routes. Next, when AF_UNSPEC is specified, it properly handles search lists instead of first searching all of AF_INET6 then AF_INET, since ares_gethostbyname() searches in parallel. Therefore, this PR should also resolve the issues attempted in #94.
A few things this PR does:
1. ares_parse_a_reply() and ares_parse_aaaa_reply() had very similar code to translate struct ares_addrinfo into a struct hostent as well as into struct ares_addrttl/ares_addr6ttl this has been split out into helper functions of ares__addrinfo2hostent() and ares__addrinfo2addrttl() to prevent this duplicative code.
2. ares_getaddrinfo() was apparently never honoring HOSTALIASES, and this was discovered once ares_gethostbyname() was turned into a wrapper, the affected test cases started failing.
3. A slight API modification to save the query hostname into struct ares_addrinfo as the last element of name. Since this is the last element, and all user-level instances of struct ares_addrinfo are allocated internally by c-ares, this is not an ABI-breaking change nor would it impact any API compatibility. This was needed since struct hostent has an h_name element.
4. Test Framework: MockServer tests via TCP would fail if more than 1 request was received at a time which is common when ares_getaddrinfo() queries for both A and AAAA records simultaneously. Infact, this was a long standing issue in which the ares_getaddrinfo() test were bypassing TCP alltogether. This has been corrected, the message is now processed in a loop.
5. Some tests had to be updated for overall correctness as they were invalid but somehow passing prior to this change.
Change By: Brad House (@bradh352)
3 years ago
|
|
|
char *name;
|
|
|
|
};
|
|
|
|
.EE
|
|
|
|
.RE
|
|
|
|
.PP
|
|
|
|
.I ares_addrinfo_node
|
|
|
|
structure is similar to RFC3493 addrinfo, but without canonname and with extra ttl field.
|
|
|
|
.RS
|
|
|
|
.PP
|
|
|
|
.EX
|
|
|
|
struct ares_addrinfo_node {
|
|
|
|
int ai_ttl;
|
|
|
|
int ai_flags;
|
|
|
|
int ai_family;
|
|
|
|
int ai_socktype;
|
|
|
|
int ai_protocol;
|
|
|
|
ares_socklen_t ai_addrlen;
|
|
|
|
struct sockaddr *ai_addr;
|
|
|
|
struct ares_addrinfo_node *ai_next;
|
|
|
|
};
|
|
|
|
.EE
|
|
|
|
.RE
|
|
|
|
.PP
|
|
|
|
.I ares_addrinfo_cname
|
|
|
|
structure is a linked list of CNAME records where
|
|
|
|
.I ttl
|
|
|
|
is a time to live
|
|
|
|
.I alias
|
|
|
|
is a label of the resource record and
|
|
|
|
.I name
|
|
|
|
is a value (canonical name) of the resource record.
|
|
|
|
See RFC2181 10.1.1. CNAME terminology.
|
|
|
|
.RS
|
|
|
|
.PP
|
|
|
|
.EX
|
|
|
|
struct ares_addrinfo_cname {
|
|
|
|
int ttl;
|
|
|
|
char *alias;
|
|
|
|
char *name;
|
|
|
|
struct ares_addrinfo_cname *next;
|
|
|
|
};
|
|
|
|
.EE
|
|
|
|
.RE
|
|
|
|
.PP
|
|
|
|
The reserved memory has to be deleted by \fBares_freeaddrinfo(3)\fP.
|
|
|
|
|
|
|
|
The result is sorted according to RFC6724 except:
|
|
|
|
- Rule 3 (Avoid deprecated addresses)
|
|
|
|
- Rule 4 (Prefer home addresses)
|
|
|
|
- Rule 7 (Prefer native transport)
|
|
|
|
|
|
|
|
Please note that the function will attempt a connection
|
|
|
|
on each of the resolved addresses as per RFC6724.
|
|
|
|
.SH AVAILABILITY
|
|
|
|
This function was added in c-ares 1.16.0, released in March 2020.
|
|
|
|
.SH SEE ALSO
|
|
|
|
.BR ares_freeaddrinfo (3)
|