jpayne@69: /* MIT License jpayne@69: * jpayne@69: * Copyright (c) Massachusetts Institute of Technology jpayne@69: * Copyright (c) Daniel Stenberg jpayne@69: * jpayne@69: * Permission is hereby granted, free of charge, to any person obtaining a copy jpayne@69: * of this software and associated documentation files (the "Software"), to deal jpayne@69: * in the Software without restriction, including without limitation the rights jpayne@69: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell jpayne@69: * copies of the Software, and to permit persons to whom the Software is jpayne@69: * furnished to do so, subject to the following conditions: jpayne@69: * jpayne@69: * The above copyright notice and this permission notice (including the next jpayne@69: * paragraph) shall be included in all copies or substantial portions of the jpayne@69: * Software. jpayne@69: * jpayne@69: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR jpayne@69: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, jpayne@69: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE jpayne@69: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER jpayne@69: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, jpayne@69: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE jpayne@69: * SOFTWARE. jpayne@69: * jpayne@69: * SPDX-License-Identifier: MIT jpayne@69: */ jpayne@69: jpayne@69: #ifndef ARES__H jpayne@69: #define ARES__H jpayne@69: jpayne@69: #include "ares_version.h" /* c-ares version defines */ jpayne@69: #include "ares_build.h" /* c-ares build definitions */ jpayne@69: jpayne@69: #if defined(_WIN32) jpayne@69: # ifndef WIN32_LEAN_AND_MEAN jpayne@69: # define WIN32_LEAN_AND_MEAN jpayne@69: # endif jpayne@69: #endif jpayne@69: jpayne@69: #ifdef CARES_HAVE_SYS_TYPES_H jpayne@69: # include jpayne@69: #endif jpayne@69: jpayne@69: #ifdef CARES_HAVE_SYS_SOCKET_H jpayne@69: # include jpayne@69: #endif jpayne@69: jpayne@69: #ifdef CARES_HAVE_SYS_SELECT_H jpayne@69: # include jpayne@69: #endif jpayne@69: jpayne@69: #ifdef CARES_HAVE_WINSOCK2_H jpayne@69: # include jpayne@69: /* To aid with linking against a static c-ares build, lets tell the microsoft jpayne@69: * compiler to pull in needed dependencies */ jpayne@69: # ifdef _MSC_VER jpayne@69: # pragma comment(lib, "ws2_32") jpayne@69: # pragma comment(lib, "advapi32") jpayne@69: # pragma comment(lib, "iphlpapi") jpayne@69: # endif jpayne@69: #endif jpayne@69: jpayne@69: #ifdef CARES_HAVE_WS2TCPIP_H jpayne@69: # include jpayne@69: #endif jpayne@69: jpayne@69: #ifdef CARES_HAVE_WINDOWS_H jpayne@69: # include jpayne@69: #endif jpayne@69: jpayne@69: /* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish jpayne@69: libc5-based Linux systems. Only include it on system that are known to jpayne@69: require it! */ jpayne@69: #if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ jpayne@69: defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) || \ jpayne@69: defined(ANDROID) || defined(__ANDROID__) || defined(__OpenBSD__) || \ jpayne@69: defined(__QNX__) || defined(__MVS__) || defined(__HAIKU__) jpayne@69: # include jpayne@69: #endif jpayne@69: jpayne@69: #if (defined(NETWARE) && !defined(__NOVELL_LIBC__)) jpayne@69: # include jpayne@69: #endif jpayne@69: jpayne@69: #if !defined(_WIN32) jpayne@69: # include jpayne@69: #endif jpayne@69: jpayne@69: #ifdef WATT32 jpayne@69: # include jpayne@69: #endif jpayne@69: jpayne@69: #if defined(ANDROID) || defined(__ANDROID__) jpayne@69: # include jpayne@69: #endif jpayne@69: jpayne@69: typedef CARES_TYPEOF_ARES_SOCKLEN_T ares_socklen_t; jpayne@69: typedef CARES_TYPEOF_ARES_SSIZE_T ares_ssize_t; jpayne@69: jpayne@69: #ifdef __cplusplus jpayne@69: extern "C" { jpayne@69: #endif jpayne@69: jpayne@69: /* jpayne@69: ** c-ares external API function linkage decorations. jpayne@69: */ jpayne@69: jpayne@69: #if defined(_WIN32) || defined(__CYGWIN__) || defined(__SYMBIAN32__) jpayne@69: # ifdef CARES_STATICLIB jpayne@69: # define CARES_EXTERN jpayne@69: # else jpayne@69: # ifdef CARES_BUILDING_LIBRARY jpayne@69: # define CARES_EXTERN __declspec(dllexport) jpayne@69: # else jpayne@69: # define CARES_EXTERN __declspec(dllimport) jpayne@69: # endif jpayne@69: # endif jpayne@69: #else jpayne@69: # if defined(__GNUC__) && __GNUC__ >= 4 jpayne@69: # define CARES_EXTERN __attribute__((visibility("default"))) jpayne@69: # elif defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 900 jpayne@69: # define CARES_EXTERN __attribute__((visibility("default"))) jpayne@69: # elif defined(__SUNPRO_C) jpayne@69: # define CARES_EXTERN _global jpayne@69: # else jpayne@69: # define CARES_EXTERN jpayne@69: # endif jpayne@69: #endif jpayne@69: jpayne@69: #ifdef __GNUC__ jpayne@69: # define CARES_GCC_VERSION \ jpayne@69: (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) jpayne@69: #else jpayne@69: # define CARES_GCC_VERSION 0 jpayne@69: #endif jpayne@69: jpayne@69: #ifndef __has_attribute jpayne@69: # define __has_attribute(x) 0 jpayne@69: #endif jpayne@69: jpayne@69: #ifdef CARES_NO_DEPRECATED jpayne@69: # define CARES_DEPRECATED jpayne@69: # define CARES_DEPRECATED_FOR(f) jpayne@69: #else jpayne@69: # if CARES_GCC_VERSION >= 30200 || __has_attribute(__deprecated__) jpayne@69: # define CARES_DEPRECATED __attribute__((__deprecated__)) jpayne@69: # else jpayne@69: # define CARES_DEPRECATED jpayne@69: # endif jpayne@69: jpayne@69: # if CARES_GCC_VERSION >= 40500 || defined(__clang__) jpayne@69: # define CARES_DEPRECATED_FOR(f) \ jpayne@69: __attribute__((deprecated("Use " #f " instead"))) jpayne@69: # elif defined(_MSC_VER) jpayne@69: # define CARES_DEPRECATED_FOR(f) __declspec(deprecated("Use " #f " instead")) jpayne@69: # else jpayne@69: # define CARES_DEPRECATED_FOR(f) CARES_DEPRECATED jpayne@69: # endif jpayne@69: #endif jpayne@69: jpayne@69: typedef enum { jpayne@69: ARES_SUCCESS = 0, jpayne@69: jpayne@69: /* Server error codes (ARES_ENODATA indicates no relevant answer) */ jpayne@69: ARES_ENODATA = 1, jpayne@69: ARES_EFORMERR = 2, jpayne@69: ARES_ESERVFAIL = 3, jpayne@69: ARES_ENOTFOUND = 4, jpayne@69: ARES_ENOTIMP = 5, jpayne@69: ARES_EREFUSED = 6, jpayne@69: jpayne@69: /* Locally generated error codes */ jpayne@69: ARES_EBADQUERY = 7, jpayne@69: ARES_EBADNAME = 8, jpayne@69: ARES_EBADFAMILY = 9, jpayne@69: ARES_EBADRESP = 10, jpayne@69: ARES_ECONNREFUSED = 11, jpayne@69: ARES_ETIMEOUT = 12, jpayne@69: ARES_EOF = 13, jpayne@69: ARES_EFILE = 14, jpayne@69: ARES_ENOMEM = 15, jpayne@69: ARES_EDESTRUCTION = 16, jpayne@69: ARES_EBADSTR = 17, jpayne@69: jpayne@69: /* ares_getnameinfo error codes */ jpayne@69: ARES_EBADFLAGS = 18, jpayne@69: jpayne@69: /* ares_getaddrinfo error codes */ jpayne@69: ARES_ENONAME = 19, jpayne@69: ARES_EBADHINTS = 20, jpayne@69: jpayne@69: /* Uninitialized library error code */ jpayne@69: ARES_ENOTINITIALIZED = 21, /* introduced in 1.7.0 */ jpayne@69: jpayne@69: /* ares_library_init error codes */ jpayne@69: ARES_ELOADIPHLPAPI = 22, /* introduced in 1.7.0 */ jpayne@69: ARES_EADDRGETNETWORKPARAMS = 23, /* introduced in 1.7.0 */ jpayne@69: jpayne@69: /* More error codes */ jpayne@69: ARES_ECANCELLED = 24, /* introduced in 1.7.0 */ jpayne@69: jpayne@69: /* More ares_getaddrinfo error codes */ jpayne@69: ARES_ESERVICE = 25, /* ares_getaddrinfo() was passed a text service name that jpayne@69: * is not recognized. introduced in 1.16.0 */ jpayne@69: jpayne@69: ARES_ENOSERVER = 26 /* No DNS servers were configured */ jpayne@69: } ares_status_t; jpayne@69: jpayne@69: typedef enum { jpayne@69: ARES_FALSE = 0, jpayne@69: ARES_TRUE = 1 jpayne@69: } ares_bool_t; jpayne@69: jpayne@69: /*! Values for ARES_OPT_EVENT_THREAD */ jpayne@69: typedef enum { jpayne@69: /*! Default (best choice) event system */ jpayne@69: ARES_EVSYS_DEFAULT = 0, jpayne@69: /*! Win32 IOCP/AFD_POLL event system */ jpayne@69: ARES_EVSYS_WIN32 = 1, jpayne@69: /*! Linux epoll */ jpayne@69: ARES_EVSYS_EPOLL = 2, jpayne@69: /*! BSD/MacOS kqueue */ jpayne@69: ARES_EVSYS_KQUEUE = 3, jpayne@69: /*! POSIX poll() */ jpayne@69: ARES_EVSYS_POLL = 4, jpayne@69: /*! last fallback on Unix-like systems, select() */ jpayne@69: ARES_EVSYS_SELECT = 5 jpayne@69: } ares_evsys_t; jpayne@69: jpayne@69: /* Flag values */ jpayne@69: #define ARES_FLAG_USEVC (1 << 0) jpayne@69: #define ARES_FLAG_PRIMARY (1 << 1) jpayne@69: #define ARES_FLAG_IGNTC (1 << 2) jpayne@69: #define ARES_FLAG_NORECURSE (1 << 3) jpayne@69: #define ARES_FLAG_STAYOPEN (1 << 4) jpayne@69: #define ARES_FLAG_NOSEARCH (1 << 5) jpayne@69: #define ARES_FLAG_NOALIASES (1 << 6) jpayne@69: #define ARES_FLAG_NOCHECKRESP (1 << 7) jpayne@69: #define ARES_FLAG_EDNS (1 << 8) jpayne@69: #define ARES_FLAG_NO_DFLT_SVR (1 << 9) jpayne@69: #define ARES_FLAG_DNS0x20 (1 << 10) jpayne@69: jpayne@69: /* Option mask values */ jpayne@69: #define ARES_OPT_FLAGS (1 << 0) jpayne@69: #define ARES_OPT_TIMEOUT (1 << 1) jpayne@69: #define ARES_OPT_TRIES (1 << 2) jpayne@69: #define ARES_OPT_NDOTS (1 << 3) jpayne@69: #define ARES_OPT_UDP_PORT (1 << 4) jpayne@69: #define ARES_OPT_TCP_PORT (1 << 5) jpayne@69: #define ARES_OPT_SERVERS (1 << 6) jpayne@69: #define ARES_OPT_DOMAINS (1 << 7) jpayne@69: #define ARES_OPT_LOOKUPS (1 << 8) jpayne@69: #define ARES_OPT_SOCK_STATE_CB (1 << 9) jpayne@69: #define ARES_OPT_SORTLIST (1 << 10) jpayne@69: #define ARES_OPT_SOCK_SNDBUF (1 << 11) jpayne@69: #define ARES_OPT_SOCK_RCVBUF (1 << 12) jpayne@69: #define ARES_OPT_TIMEOUTMS (1 << 13) jpayne@69: #define ARES_OPT_ROTATE (1 << 14) jpayne@69: #define ARES_OPT_EDNSPSZ (1 << 15) jpayne@69: #define ARES_OPT_NOROTATE (1 << 16) jpayne@69: #define ARES_OPT_RESOLVCONF (1 << 17) jpayne@69: #define ARES_OPT_HOSTS_FILE (1 << 18) jpayne@69: #define ARES_OPT_UDP_MAX_QUERIES (1 << 19) jpayne@69: #define ARES_OPT_MAXTIMEOUTMS (1 << 20) jpayne@69: #define ARES_OPT_QUERY_CACHE (1 << 21) jpayne@69: #define ARES_OPT_EVENT_THREAD (1 << 22) jpayne@69: #define ARES_OPT_SERVER_FAILOVER (1 << 23) jpayne@69: jpayne@69: /* Nameinfo flag values */ jpayne@69: #define ARES_NI_NOFQDN (1 << 0) jpayne@69: #define ARES_NI_NUMERICHOST (1 << 1) jpayne@69: #define ARES_NI_NAMEREQD (1 << 2) jpayne@69: #define ARES_NI_NUMERICSERV (1 << 3) jpayne@69: #define ARES_NI_DGRAM (1 << 4) jpayne@69: #define ARES_NI_TCP 0 jpayne@69: #define ARES_NI_UDP ARES_NI_DGRAM jpayne@69: #define ARES_NI_SCTP (1 << 5) jpayne@69: #define ARES_NI_DCCP (1 << 6) jpayne@69: #define ARES_NI_NUMERICSCOPE (1 << 7) jpayne@69: #define ARES_NI_LOOKUPHOST (1 << 8) jpayne@69: #define ARES_NI_LOOKUPSERVICE (1 << 9) jpayne@69: /* Reserved for future use */ jpayne@69: #define ARES_NI_IDN (1 << 10) jpayne@69: #define ARES_NI_IDN_ALLOW_UNASSIGNED (1 << 11) jpayne@69: #define ARES_NI_IDN_USE_STD3_ASCII_RULES (1 << 12) jpayne@69: jpayne@69: /* Addrinfo flag values */ jpayne@69: #define ARES_AI_CANONNAME (1 << 0) jpayne@69: #define ARES_AI_NUMERICHOST (1 << 1) jpayne@69: #define ARES_AI_PASSIVE (1 << 2) jpayne@69: #define ARES_AI_NUMERICSERV (1 << 3) jpayne@69: #define ARES_AI_V4MAPPED (1 << 4) jpayne@69: #define ARES_AI_ALL (1 << 5) jpayne@69: #define ARES_AI_ADDRCONFIG (1 << 6) jpayne@69: #define ARES_AI_NOSORT (1 << 7) jpayne@69: #define ARES_AI_ENVHOSTS (1 << 8) jpayne@69: /* Reserved for future use */ jpayne@69: #define ARES_AI_IDN (1 << 10) jpayne@69: #define ARES_AI_IDN_ALLOW_UNASSIGNED (1 << 11) jpayne@69: #define ARES_AI_IDN_USE_STD3_ASCII_RULES (1 << 12) jpayne@69: #define ARES_AI_CANONIDN (1 << 13) jpayne@69: jpayne@69: #define ARES_AI_MASK \ jpayne@69: (ARES_AI_CANONNAME | ARES_AI_NUMERICHOST | ARES_AI_PASSIVE | \ jpayne@69: ARES_AI_NUMERICSERV | ARES_AI_V4MAPPED | ARES_AI_ALL | ARES_AI_ADDRCONFIG) jpayne@69: #define ARES_GETSOCK_MAXNUM \ jpayne@69: 16 /* ares_getsock() can return info about this \ jpayne@69: many sockets */ jpayne@69: #define ARES_GETSOCK_READABLE(bits, num) (bits & (1 << (num))) jpayne@69: #define ARES_GETSOCK_WRITABLE(bits, num) \ jpayne@69: (bits & (1 << ((num) + ARES_GETSOCK_MAXNUM))) jpayne@69: jpayne@69: /* c-ares library initialization flag values */ jpayne@69: #define ARES_LIB_INIT_NONE (0) jpayne@69: #define ARES_LIB_INIT_WIN32 (1 << 0) jpayne@69: #define ARES_LIB_INIT_ALL (ARES_LIB_INIT_WIN32) jpayne@69: jpayne@69: /* Server state callback flag values */ jpayne@69: #define ARES_SERV_STATE_UDP (1 << 0) /* Query used UDP */ jpayne@69: #define ARES_SERV_STATE_TCP (1 << 1) /* Query used TCP */ jpayne@69: jpayne@69: /* jpayne@69: * Typedef our socket type jpayne@69: */ jpayne@69: jpayne@69: #ifndef ares_socket_typedef jpayne@69: # if defined(_WIN32) && !defined(WATT32) jpayne@69: typedef SOCKET ares_socket_t; jpayne@69: # define ARES_SOCKET_BAD INVALID_SOCKET jpayne@69: # else jpayne@69: typedef int ares_socket_t; jpayne@69: # define ARES_SOCKET_BAD -1 jpayne@69: # endif jpayne@69: # define ares_socket_typedef jpayne@69: #endif /* ares_socket_typedef */ jpayne@69: jpayne@69: typedef void (*ares_sock_state_cb)(void *data, ares_socket_t socket_fd, jpayne@69: int readable, int writable); jpayne@69: jpayne@69: struct apattern; jpayne@69: jpayne@69: /* Options controlling server failover behavior. jpayne@69: * The retry chance is the probability (1/N) by which we will retry a failed jpayne@69: * server instead of the best server when selecting a server to send queries jpayne@69: * to. jpayne@69: * The retry delay is the minimum time in milliseconds to wait between doing jpayne@69: * such retries (applied per-server). jpayne@69: */ jpayne@69: struct ares_server_failover_options { jpayne@69: unsigned short retry_chance; jpayne@69: size_t retry_delay; jpayne@69: }; jpayne@69: jpayne@69: /* NOTE about the ares_options struct to users and developers. jpayne@69: jpayne@69: This struct will remain looking like this. It will not be extended nor jpayne@69: shrunk in future releases, but all new options will be set by ares_set_*() jpayne@69: options instead of with the ares_init_options() function. jpayne@69: jpayne@69: Eventually (in a galaxy far far away), all options will be settable by jpayne@69: ares_set_*() options and the ares_init_options() function will become jpayne@69: deprecated. jpayne@69: jpayne@69: When new options are added to c-ares, they are not added to this jpayne@69: struct. And they are not "saved" with the ares_save_options() function but jpayne@69: instead we encourage the use of the ares_dup() function. Needless to say, jpayne@69: if you add config options to c-ares you need to make sure ares_dup() jpayne@69: duplicates this new option. jpayne@69: jpayne@69: */ jpayne@69: struct ares_options { jpayne@69: int flags; jpayne@69: int timeout; /* in seconds or milliseconds, depending on options */ jpayne@69: int tries; jpayne@69: int ndots; jpayne@69: unsigned short udp_port; /* host byte order */ jpayne@69: unsigned short tcp_port; /* host byte order */ jpayne@69: int socket_send_buffer_size; jpayne@69: int socket_receive_buffer_size; jpayne@69: struct in_addr *servers; jpayne@69: int nservers; jpayne@69: char **domains; jpayne@69: int ndomains; jpayne@69: char *lookups; jpayne@69: ares_sock_state_cb sock_state_cb; jpayne@69: void *sock_state_cb_data; jpayne@69: struct apattern *sortlist; jpayne@69: int nsort; jpayne@69: int ednspsz; jpayne@69: char *resolvconf_path; jpayne@69: char *hosts_path; jpayne@69: int udp_max_queries; jpayne@69: int maxtimeout; /* in milliseconds */ jpayne@69: unsigned int qcache_max_ttl; /* Maximum TTL for query cache, 0=disabled */ jpayne@69: ares_evsys_t evsys; jpayne@69: struct ares_server_failover_options server_failover_opts; jpayne@69: }; jpayne@69: jpayne@69: struct hostent; jpayne@69: struct timeval; jpayne@69: struct sockaddr; jpayne@69: struct ares_channeldata; jpayne@69: struct ares_addrinfo; jpayne@69: struct ares_addrinfo_hints; jpayne@69: jpayne@69: /* Legacy typedef, don't use, you can't specify "const" */ jpayne@69: typedef struct ares_channeldata *ares_channel; jpayne@69: jpayne@69: /* Current main channel typedef */ jpayne@69: typedef struct ares_channeldata ares_channel_t; jpayne@69: jpayne@69: /* jpayne@69: * NOTE: before c-ares 1.7.0 we would most often use the system in6_addr jpayne@69: * struct below when ares itself was built, but many apps would use this jpayne@69: * private version since the header checked a HAVE_* define for it. Starting jpayne@69: * with 1.7.0 we always declare and use our own to stop relying on the jpayne@69: * system's one. jpayne@69: */ jpayne@69: struct ares_in6_addr { jpayne@69: union { jpayne@69: unsigned char _S6_u8[16]; jpayne@69: } _S6_un; jpayne@69: }; jpayne@69: jpayne@69: struct ares_addr { jpayne@69: int family; jpayne@69: jpayne@69: union { jpayne@69: struct in_addr addr4; jpayne@69: struct ares_in6_addr addr6; jpayne@69: } addr; jpayne@69: }; jpayne@69: jpayne@69: /* DNS record parser, writer, and helpers */ jpayne@69: #include "ares_dns_record.h" jpayne@69: jpayne@69: typedef void (*ares_callback)(void *arg, int status, int timeouts, jpayne@69: unsigned char *abuf, int alen); jpayne@69: jpayne@69: typedef void (*ares_callback_dnsrec)(void *arg, ares_status_t status, jpayne@69: size_t timeouts, jpayne@69: const ares_dns_record_t *dnsrec); jpayne@69: jpayne@69: typedef void (*ares_host_callback)(void *arg, int status, int timeouts, jpayne@69: struct hostent *hostent); jpayne@69: jpayne@69: typedef void (*ares_nameinfo_callback)(void *arg, int status, int timeouts, jpayne@69: char *node, char *service); jpayne@69: jpayne@69: typedef int (*ares_sock_create_callback)(ares_socket_t socket_fd, int type, jpayne@69: void *data); jpayne@69: jpayne@69: typedef int (*ares_sock_config_callback)(ares_socket_t socket_fd, int type, jpayne@69: void *data); jpayne@69: jpayne@69: typedef void (*ares_addrinfo_callback)(void *arg, int status, int timeouts, jpayne@69: struct ares_addrinfo *res); jpayne@69: jpayne@69: typedef void (*ares_server_state_callback)(const char *server_string, jpayne@69: ares_bool_t success, int flags, jpayne@69: void *data); jpayne@69: jpayne@69: typedef void (*ares_pending_write_cb)(void *data); jpayne@69: jpayne@69: CARES_EXTERN int ares_library_init(int flags); jpayne@69: jpayne@69: CARES_EXTERN int ares_library_init_mem(int flags, void *(*amalloc)(size_t size), jpayne@69: void (*afree)(void *ptr), jpayne@69: void *(*arealloc)(void *ptr, jpayne@69: size_t size)); jpayne@69: jpayne@69: #if defined(ANDROID) || defined(__ANDROID__) jpayne@69: CARES_EXTERN void ares_library_init_jvm(JavaVM *jvm); jpayne@69: CARES_EXTERN int ares_library_init_android(jobject connectivity_manager); jpayne@69: CARES_EXTERN int ares_library_android_initialized(void); jpayne@69: #endif jpayne@69: jpayne@69: #define CARES_HAVE_ARES_LIBRARY_INIT 1 jpayne@69: #define CARES_HAVE_ARES_LIBRARY_CLEANUP 1 jpayne@69: jpayne@69: CARES_EXTERN int ares_library_initialized(void); jpayne@69: jpayne@69: CARES_EXTERN void ares_library_cleanup(void); jpayne@69: jpayne@69: CARES_EXTERN const char *ares_version(int *version); jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_init_options) int ares_init( jpayne@69: ares_channel_t **channelptr); jpayne@69: jpayne@69: CARES_EXTERN int ares_init_options(ares_channel_t **channelptr, jpayne@69: const struct ares_options *options, jpayne@69: int optmask); jpayne@69: jpayne@69: CARES_EXTERN int ares_save_options(const ares_channel_t *channel, jpayne@69: struct ares_options *options, int *optmask); jpayne@69: jpayne@69: CARES_EXTERN void ares_destroy_options(struct ares_options *options); jpayne@69: jpayne@69: CARES_EXTERN int ares_dup(ares_channel_t **dest, const ares_channel_t *src); jpayne@69: jpayne@69: CARES_EXTERN ares_status_t ares_reinit(ares_channel_t *channel); jpayne@69: jpayne@69: CARES_EXTERN void ares_destroy(ares_channel_t *channel); jpayne@69: jpayne@69: CARES_EXTERN void ares_cancel(ares_channel_t *channel); jpayne@69: jpayne@69: /* These next 3 configure local binding for the out-going socket jpayne@69: * connection. Use these to specify source IP and/or network device jpayne@69: * on multi-homed systems. jpayne@69: */ jpayne@69: CARES_EXTERN void ares_set_local_ip4(ares_channel_t *channel, jpayne@69: unsigned int local_ip); jpayne@69: jpayne@69: /* local_ip6 should be 16 bytes in length */ jpayne@69: CARES_EXTERN void ares_set_local_ip6(ares_channel_t *channel, jpayne@69: const unsigned char *local_ip6); jpayne@69: jpayne@69: /* local_dev_name should be null terminated. */ jpayne@69: CARES_EXTERN void ares_set_local_dev(ares_channel_t *channel, jpayne@69: const char *local_dev_name); jpayne@69: jpayne@69: CARES_EXTERN void ares_set_socket_callback(ares_channel_t *channel, jpayne@69: ares_sock_create_callback callback, jpayne@69: void *user_data); jpayne@69: jpayne@69: CARES_EXTERN void ares_set_socket_configure_callback( jpayne@69: ares_channel_t *channel, ares_sock_config_callback callback, void *user_data); jpayne@69: jpayne@69: CARES_EXTERN void jpayne@69: ares_set_server_state_callback(ares_channel_t *channel, jpayne@69: ares_server_state_callback callback, jpayne@69: void *user_data); jpayne@69: jpayne@69: CARES_EXTERN void ares_set_pending_write_cb(ares_channel_t *channel, jpayne@69: ares_pending_write_cb callback, jpayne@69: void *user_data); jpayne@69: jpayne@69: CARES_EXTERN void ares_process_pending_write(ares_channel_t *channel); jpayne@69: jpayne@69: CARES_EXTERN int ares_set_sortlist(ares_channel_t *channel, jpayne@69: const char *sortstr); jpayne@69: jpayne@69: CARES_EXTERN void ares_getaddrinfo(ares_channel_t *channel, const char *node, jpayne@69: const char *service, jpayne@69: const struct ares_addrinfo_hints *hints, jpayne@69: ares_addrinfo_callback callback, void *arg); jpayne@69: jpayne@69: CARES_EXTERN void ares_freeaddrinfo(struct ares_addrinfo *ai); jpayne@69: jpayne@69: /* jpayne@69: * Virtual function set to have user-managed socket IO. jpayne@69: * Note that all functions need to be defined, and when jpayne@69: * set, the library will not do any bind nor set any jpayne@69: * socket options, assuming the client handles these jpayne@69: * through either socket creation or the jpayne@69: * ares_sock_config_callback call. jpayne@69: */ jpayne@69: struct iovec; jpayne@69: jpayne@69: struct ares_socket_functions { jpayne@69: ares_socket_t (*asocket)(int, int, int, void *); jpayne@69: int (*aclose)(ares_socket_t, void *); jpayne@69: int (*aconnect)(ares_socket_t, const struct sockaddr *, ares_socklen_t, jpayne@69: void *); jpayne@69: ares_ssize_t (*arecvfrom)(ares_socket_t, void *, size_t, int, jpayne@69: struct sockaddr *, ares_socklen_t *, void *); jpayne@69: ares_ssize_t (*asendv)(ares_socket_t, const struct iovec *, int, void *); jpayne@69: }; jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR( jpayne@69: ares_set_socket_functions_ex) void ares_set_socket_functions(ares_channel_t jpayne@69: *channel, jpayne@69: const struct jpayne@69: ares_socket_functions jpayne@69: *funcs, jpayne@69: void *user_data); jpayne@69: jpayne@69: /*! Flags defining behavior of socket functions */ jpayne@69: typedef enum { jpayne@69: /*! Strongly recommended to create sockets as non-blocking and set this jpayne@69: * flag */ jpayne@69: ARES_SOCKFUNC_FLAG_NONBLOCKING = 1 << 0 jpayne@69: } ares_sockfunc_flags_t; jpayne@69: jpayne@69: /*! Socket options in request to asetsockopt() in struct jpayne@69: * ares_socket_functions_ex */ jpayne@69: typedef enum { jpayne@69: /*! Set the send buffer size. Value is a pointer to an int. (SO_SNDBUF) */ jpayne@69: ARES_SOCKET_OPT_SENDBUF_SIZE, jpayne@69: /*! Set the recv buffer size. Value is a pointer to an int. (SO_RCVBUF) */ jpayne@69: ARES_SOCKET_OPT_RECVBUF_SIZE, jpayne@69: /*! Set the network interface to use as the source for communication. jpayne@69: * Value is a C string. (SO_BINDTODEVICE) */ jpayne@69: ARES_SOCKET_OPT_BIND_DEVICE, jpayne@69: /*! Enable TCP Fast Open. Value is a pointer to an ares_bool_t. On some jpayne@69: * systems this could be a no-op if it is known it is on by default and jpayne@69: * return success. Other systems may be a no-op if known the system does jpayne@69: * not support the feature and returns failure with errno set to ENOSYS or jpayne@69: * WSASetLastError(WSAEOPNOTSUPP). jpayne@69: */ jpayne@69: ARES_SOCKET_OPT_TCP_FASTOPEN jpayne@69: } ares_socket_opt_t; jpayne@69: jpayne@69: /*! Flags for behavior during connect */ jpayne@69: typedef enum { jpayne@69: /*! Connect using TCP Fast Open */ jpayne@69: ARES_SOCKET_CONN_TCP_FASTOPEN = 1 << 0 jpayne@69: } ares_socket_connect_flags_t; jpayne@69: jpayne@69: /*! Flags for behavior during bind */ jpayne@69: typedef enum { jpayne@69: /*! Bind is for a TCP connection */ jpayne@69: ARES_SOCKET_BIND_TCP = 1 << 0, jpayne@69: /*! Bind is for a client connection, not server */ jpayne@69: ARES_SOCKET_BIND_CLIENT = 1 << 1 jpayne@69: } ares_socket_bind_flags_t; jpayne@69: jpayne@69: /*! Socket functions to call rather than using OS-native functions */ jpayne@69: struct ares_socket_functions_ex { jpayne@69: /*! ABI Version: must be "1" */ jpayne@69: unsigned int version; jpayne@69: jpayne@69: /*! Flags indicating behavior of the subsystem. One or more jpayne@69: * ares_sockfunc_flags_t */ jpayne@69: unsigned int flags; jpayne@69: jpayne@69: /*! REQUIRED. Create a new socket file descriptor. The file descriptor must jpayne@69: * be opened in non-blocking mode (so that reads and writes never block). jpayne@69: * Recommended other options would be to disable signals on write errors jpayne@69: * (SO_NOSIGPIPE), Disable the Nagle algorithm on SOCK_STREAM (TCP_NODELAY), jpayne@69: * and to automatically close file descriptors on exec (FD_CLOEXEC). jpayne@69: * jpayne@69: * \param[in] domain Socket domain. Valid values are AF_INET, AF_INET6. jpayne@69: * \param[in] type Socket type. Valid values are SOCK_STREAM (tcp) and jpayne@69: * SOCK_DGRAM (udp). jpayne@69: * \param[in] protocol In general this should be ignored, may be passed as jpayne@69: * 0 (use as default for type), or may be IPPROTO_UDP jpayne@69: * or IPPROTO_TCP. jpayne@69: * \param[in] user_data Pointer provided to ares_set_socket_functions_ex(). jpayne@69: * \return ARES_SOCKET_BAD on error, or socket file descriptor on success. jpayne@69: * On error, it is expected to set errno (or WSASetLastError()) to an jpayne@69: * appropriate reason code such as EAFNOSUPPORT / WSAAFNOSUPPORT. */ jpayne@69: ares_socket_t (*asocket)(int domain, int type, int protocol, void *user_data); jpayne@69: jpayne@69: /*! REQUIRED. Close a socket file descriptor. jpayne@69: * \param[in] sock Socket file descriptor returned from asocket. jpayne@69: * \param[in] user_data Pointer provided to ares_set_socket_functions_ex(). jpayne@69: * \return 0 on success. On failure, should set errno (or WSASetLastError) jpayne@69: * to an appropriate code such as EBADF / WSAEBADF */ jpayne@69: int (*aclose)(ares_socket_t sock, void *user_data); jpayne@69: jpayne@69: jpayne@69: /*! REQUIRED. Set socket option. This shares a similar syntax to the BSD jpayne@69: * setsockopt() call, however we use our own options. The value is typically jpayne@69: * a pointer to the desired value and each option has its own data type it jpayne@69: * will express in the documentation. jpayne@69: * jpayne@69: * \param[in] sock Socket file descriptor returned from asocket. jpayne@69: * \param[in] opt Option to set. jpayne@69: * \param[in] val Pointer to value for option. jpayne@69: * \param[in] val_size Size of value. jpayne@69: * \param[in] user_data Pointer provided to jpayne@69: * ares_set_socket_functions_ex(). jpayne@69: * \return Return 0 on success, otherwise -1 should be returned with an jpayne@69: * appropriate errno (or WSASetLastError()) set. If error is ENOSYS / jpayne@69: * WSAEOPNOTSUPP an error will not be propagated as it will take it jpayne@69: * to mean it is an intentional decision to not support the feature. jpayne@69: */ jpayne@69: int (*asetsockopt)(ares_socket_t sock, ares_socket_opt_t opt, const void *val, jpayne@69: ares_socklen_t val_size, void *user_data); jpayne@69: jpayne@69: /*! REQUIRED. Connect to the remote using the supplied address. For UDP jpayne@69: * sockets this will bind the file descriptor to only send and receive packets jpayne@69: * from the remote address provided. jpayne@69: * jpayne@69: * \param[in] sock Socket file descriptor returned from asocket. jpayne@69: * \param[in] address Address to connect to jpayne@69: * \param[in] address_len Size of address structure passed jpayne@69: * \param[in] flags One or more ares_socket_connect_flags_t jpayne@69: * \param[in] user_data Pointer provided to jpayne@69: * ares_set_socket_functions_ex(). jpayne@69: * \return Return 0 upon successful establishement, otherwise -1 should be jpayne@69: * returned with an appropriate errno (or WSASetLastError()) set. It jpayne@69: * is generally expected that most TCP connections (not using TCP Fast Open) jpayne@69: * will return -1 with an error of EINPROGRESS / WSAEINPROGRESS due to the jpayne@69: * non-blocking nature of the connection. It is then the responsibility of jpayne@69: * the implementation to notify of writability on the socket to indicate the jpayne@69: * connection has succeeded (or readability on failure to retrieve the jpayne@69: * appropriate error). jpayne@69: */ jpayne@69: int (*aconnect)(ares_socket_t sock, const struct sockaddr *address, jpayne@69: ares_socklen_t address_len, unsigned int flags, jpayne@69: void *user_data); jpayne@69: jpayne@69: /*! REQUIRED. Attempt to read data from the remote. jpayne@69: * jpayne@69: * \param[in] sock Socket file descriptor returned from asocket. jpayne@69: * \param[in,out] buffer Allocated buffer to place data read from jpayne@69: * socket. jpayne@69: * \param[in] length Size of buffer jpayne@69: * \param[in] flags Unused, always 0. jpayne@69: * \param[in,out] address Buffer to hold address data was received from. jpayne@69: * May be NULL if address not desired. jpayne@69: * \param[in,out] address_len Input size of address buffer, output actual jpayne@69: * written size. Must be NULL if address is NULL. jpayne@69: * \param[in] user_data Pointer provided to jpayne@69: * ares_set_socket_functions_ex(). jpayne@69: * \return -1 on error with appropriate errno (or WSASetLastError()) set, jpayne@69: * such as EWOULDBLOCK / EAGAIN / WSAEWOULDBLOCK, or ECONNRESET / jpayne@69: * WSAECONNRESET. jpayne@69: */ jpayne@69: ares_ssize_t (*arecvfrom)(ares_socket_t sock, void *buffer, size_t length, jpayne@69: int flags, struct sockaddr *address, jpayne@69: ares_socklen_t *address_len, void *user_data); jpayne@69: jpayne@69: /*! REQUIRED. Attempt to send data to the remote. Optional address may be jpayne@69: * specified which may be useful on unbound UDP sockets (though currently not jpayne@69: * used), and TCP FastOpen where the connection is delayed until first write. jpayne@69: * jpayne@69: * \param[in] sock Socket file descriptor returned from asocket. jpayne@69: * \param[in] buffer Containing data to place onto wire. jpayne@69: * \param[in] length Size of buffer jpayne@69: * \param[in] flags Flags for writing. Currently only used flag is jpayne@69: * MSG_NOSIGNAL if the host OS has such a flag. In jpayne@69: * general flags can be ignored. jpayne@69: * \param[in] address Buffer containing address to send data to. May jpayne@69: * be NULL. jpayne@69: * \param[in,out] address_len Size of address buffer. Must be 0 if address jpayne@69: * is NULL. jpayne@69: * \param[in] user_data Pointer provided to jpayne@69: * ares_set_socket_functions_ex(). jpayne@69: * \return Number of bytes written. -1 on error with appropriate errno (or jpayne@69: * WSASetLastError()) set. jpayne@69: */ jpayne@69: ares_ssize_t (*asendto)(ares_socket_t sock, const void *buffer, size_t length, jpayne@69: int flags, const struct sockaddr *address, jpayne@69: ares_socklen_t address_len, void *user_data); jpayne@69: jpayne@69: /*! Optional. Retrieve the local address of the socket. jpayne@69: * jpayne@69: * \param[in] sock Socket file descriptor returned from asocket jpayne@69: * \param[in,out] address Buffer to hold address jpayne@69: * \param[in,out] address_len Size of address buffer on input, written size jpayne@69: * on output. jpayne@69: * \param[in] user_data Pointer provided to jpayne@69: * ares_set_socket_functions_ex(). jpayne@69: * \return 0 on success. -1 on error with an appropriate errno (or jpayne@69: * WSASetLastError()) set. jpayne@69: */ jpayne@69: int (*agetsockname)(ares_socket_t sock, struct sockaddr *address, jpayne@69: ares_socklen_t *address_len, void *user_data); jpayne@69: jpayne@69: /*! Optional. Bind the socket to an address. This can be used for client jpayne@69: * connections to bind the source address for packets before connect, or jpayne@69: * for server connections to bind to an address and port before listening. jpayne@69: * Currently c-ares only supports client connections. jpayne@69: * jpayne@69: * \param[in] sock Socket file descriptor returned from asocket jpayne@69: * \param[in] flags ares_socket_bind_flags_t flags. jpayne@69: * \param[in] address Buffer containing address. jpayne@69: * \param[in] address_len Size of address buffer. jpayne@69: * \param[in] user_data Pointer provided to jpayne@69: * ares_set_socket_functions_ex(). jpayne@69: * \return 0 on success. -1 on error with an appropriate errno (or jpayne@69: * WSASetLastError()) set. jpayne@69: */ jpayne@69: int (*abind)(ares_socket_t sock, unsigned int flags, jpayne@69: const struct sockaddr *address, socklen_t address_len, jpayne@69: void *user_data); jpayne@69: jpayne@69: /* Optional. Convert an interface name into the interface index. If this jpayne@69: * callback is not specified, then IPv6 Link-Local DNS servers cannot be used. jpayne@69: * jpayne@69: * \param[in] ifname Interface Name as NULL-terminated string. jpayne@69: * \param[in] user_data Pointer provided to jpayne@69: * ares_set_socket_functions_ex(). jpayne@69: * \return 0 on failure, otherwise interface index. jpayne@69: */ jpayne@69: unsigned int (*aif_nametoindex)(const char *ifname, void *user_data); jpayne@69: jpayne@69: /* Optional. Convert an interface index into the interface name. If this jpayne@69: * callback is not specified, then IPv6 Link-Local DNS servers cannot be used. jpayne@69: * jpayne@69: * \param[in] ifindex Interface index, must be > 0 jpayne@69: * \param[in] ifname_buf Buffer to hold interface name. Must be at least jpayne@69: * IFNAMSIZ in length or 32 bytes if IFNAMSIZ isn't jpayne@69: * defined. jpayne@69: * \param[in] ifname_buf_len Size of ifname_buf for verification. jpayne@69: * \param[in] user_data Pointer provided to jpayne@69: * ares_set_socket_functions_ex(). jpayne@69: * \return NULL on failure, otherwise pointer to provided ifname_buf jpayne@69: */ jpayne@69: const char *(*aif_indextoname)(unsigned int ifindex, char *ifname_buf, jpayne@69: size_t ifname_buf_len, void *user_data); jpayne@69: }; jpayne@69: jpayne@69: /*! Override the native socket functions for the OS with the provided set. jpayne@69: * An optional user data thunk may be specified which will be passed to jpayne@69: * each registered callback. Replaces ares_set_socket_functions(). jpayne@69: * jpayne@69: * \param[in] channel An initialized c-ares channel. jpayne@69: * \param[in] funcs Structure registering the implementations for the jpayne@69: * various functions. See the structure definition. jpayne@69: * This will be duplicated and does not need to exist jpayne@69: * past the life of this call. jpayne@69: * \param[in] user_data User data thunk which will be passed to each call of jpayne@69: * the registered callbacks. jpayne@69: * \return ARES_SUCCESS on success, or another error code such as ARES_EFORMERR jpayne@69: * on misuse. jpayne@69: */ jpayne@69: CARES_EXTERN ares_status_t ares_set_socket_functions_ex( jpayne@69: ares_channel_t *channel, const struct ares_socket_functions_ex *funcs, jpayne@69: void *user_data); jpayne@69: jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_send_dnsrec) void ares_send( jpayne@69: ares_channel_t *channel, const unsigned char *qbuf, int qlen, jpayne@69: ares_callback callback, void *arg); jpayne@69: jpayne@69: /*! Send a DNS query as an ares_dns_record_t with a callback containing the jpayne@69: * parsed DNS record. jpayne@69: * jpayne@69: * \param[in] channel Pointer to channel on which queries will be sent. jpayne@69: * \param[in] dnsrec DNS Record to send jpayne@69: * \param[in] callback Callback function invoked on completion or failure of jpayne@69: * the query sequence. jpayne@69: * \param[in] arg Additional argument passed to the callback function. jpayne@69: * \param[out] qid Query ID jpayne@69: * \return One of the c-ares status codes. jpayne@69: */ jpayne@69: CARES_EXTERN ares_status_t ares_send_dnsrec(ares_channel_t *channel, jpayne@69: const ares_dns_record_t *dnsrec, jpayne@69: ares_callback_dnsrec callback, jpayne@69: void *arg, unsigned short *qid); jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_query_dnsrec) void ares_query( jpayne@69: ares_channel_t *channel, const char *name, int dnsclass, int type, jpayne@69: ares_callback callback, void *arg); jpayne@69: jpayne@69: /*! Perform a DNS query with a callback containing the parsed DNS record. jpayne@69: * jpayne@69: * \param[in] channel Pointer to channel on which queries will be sent. jpayne@69: * \param[in] name Query name jpayne@69: * \param[in] dnsclass DNS Class jpayne@69: * \param[in] type DNS Record Type jpayne@69: * \param[in] callback Callback function invoked on completion or failure of jpayne@69: * the query sequence. jpayne@69: * \param[in] arg Additional argument passed to the callback function. jpayne@69: * \param[out] qid Query ID jpayne@69: * \return One of the c-ares status codes. jpayne@69: */ jpayne@69: CARES_EXTERN ares_status_t ares_query_dnsrec(ares_channel_t *channel, jpayne@69: const char *name, jpayne@69: ares_dns_class_t dnsclass, jpayne@69: ares_dns_rec_type_t type, jpayne@69: ares_callback_dnsrec callback, jpayne@69: void *arg, unsigned short *qid); jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_search_dnsrec) void ares_search( jpayne@69: ares_channel_t *channel, const char *name, int dnsclass, int type, jpayne@69: ares_callback callback, void *arg); jpayne@69: jpayne@69: /*! Search for a complete DNS message. jpayne@69: * jpayne@69: * \param[in] channel Pointer to channel on which queries will be sent. jpayne@69: * \param[in] dnsrec Pointer to initialized and filled DNS record object. jpayne@69: * \param[in] callback Callback function invoked on completion or failure of jpayne@69: * the query sequence. jpayne@69: * \param[in] arg Additional argument passed to the callback function. jpayne@69: * \return One of the c-ares status codes. In all cases, except jpayne@69: * ARES_EFORMERR due to misuse, this error code will also be sent jpayne@69: * to the provided callback. jpayne@69: */ jpayne@69: CARES_EXTERN ares_status_t ares_search_dnsrec(ares_channel_t *channel, jpayne@69: const ares_dns_record_t *dnsrec, jpayne@69: ares_callback_dnsrec callback, jpayne@69: void *arg); jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_getaddrinfo) void ares_gethostbyname( jpayne@69: ares_channel_t *channel, const char *name, int family, jpayne@69: ares_host_callback callback, void *arg); jpayne@69: jpayne@69: CARES_EXTERN int ares_gethostbyname_file(ares_channel_t *channel, jpayne@69: const char *name, int family, jpayne@69: struct hostent **host); jpayne@69: jpayne@69: CARES_EXTERN void ares_gethostbyaddr(ares_channel_t *channel, const void *addr, jpayne@69: int addrlen, int family, jpayne@69: ares_host_callback callback, void *arg); jpayne@69: jpayne@69: CARES_EXTERN void ares_getnameinfo(ares_channel_t *channel, jpayne@69: const struct sockaddr *sa, jpayne@69: ares_socklen_t salen, int flags, jpayne@69: ares_nameinfo_callback callback, void *arg); jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR( jpayne@69: ARES_OPT_EVENT_THREAD or jpayne@69: ARES_OPT_SOCK_STATE_CB) int ares_fds(const ares_channel_t *channel, jpayne@69: fd_set *read_fds, fd_set *write_fds); jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR( jpayne@69: ARES_OPT_EVENT_THREAD or jpayne@69: ARES_OPT_SOCK_STATE_CB) int ares_getsock(const ares_channel_t *channel, jpayne@69: ares_socket_t *socks, int numsocks); jpayne@69: jpayne@69: CARES_EXTERN struct timeval *ares_timeout(const ares_channel_t *channel, jpayne@69: struct timeval *maxtv, jpayne@69: struct timeval *tv); jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_process_fds) void ares_process( jpayne@69: ares_channel_t *channel, fd_set *read_fds, fd_set *write_fds); jpayne@69: jpayne@69: /*! Events used by ares_fd_events_t */ jpayne@69: typedef enum { jpayne@69: ARES_FD_EVENT_NONE = 0, /*!< No events */ jpayne@69: ARES_FD_EVENT_READ = 1 << 0, /*!< Read event (including disconnect/error) */ jpayne@69: ARES_FD_EVENT_WRITE = 1 << 1 /*!< Write event */ jpayne@69: } ares_fd_eventflag_t; jpayne@69: jpayne@69: /*! Type holding a file descriptor and mask of events, used by jpayne@69: * ares_process_fds() */ jpayne@69: typedef struct { jpayne@69: ares_socket_t fd; /*!< File descriptor */ jpayne@69: unsigned int events; /*!< Mask of ares_fd_eventflag_t */ jpayne@69: } ares_fd_events_t; jpayne@69: jpayne@69: /*! Flags used by ares_process_fds() */ jpayne@69: typedef enum { jpayne@69: ARES_PROCESS_FLAG_NONE = 0, /*!< No flag value */ jpayne@69: ARES_PROCESS_FLAG_SKIP_NON_FD = 1 << 0 /*!< skip any processing unrelated to jpayne@69: * the file descriptor events passed jpayne@69: * in */ jpayne@69: } ares_process_flag_t; jpayne@69: jpayne@69: /*! Process events on multiple file descriptors based on the event mask jpayne@69: * associated with each file descriptor. Recommended over calling jpayne@69: * ares_process_fd() multiple times since it would trigger additional logic jpayne@69: * such as timeout processing on each call. jpayne@69: * jpayne@69: * \param[in] channel Initialized ares channel jpayne@69: * \param[in] events Array of file descriptors with events. May be NULL if jpayne@69: * no events, but may have timeouts to process. jpayne@69: * \param[in] nevents Number of elements in the events array. May be 0 if jpayne@69: * no events, but may have timeouts to process. jpayne@69: * \param[in] flags Flags to alter behavior of the process command. jpayne@69: * \return ARES_ENOMEM on out of memory, ARES_EFORMERR on misuse, jpayne@69: * otherwise ARES_SUCCESS jpayne@69: */ jpayne@69: CARES_EXTERN ares_status_t ares_process_fds(ares_channel_t *channel, jpayne@69: const ares_fd_events_t *events, jpayne@69: size_t nevents, unsigned int flags); jpayne@69: jpayne@69: CARES_EXTERN void ares_process_fd(ares_channel_t *channel, jpayne@69: ares_socket_t read_fd, jpayne@69: ares_socket_t write_fd); jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_record_create) int ares_create_query( jpayne@69: const char *name, int dnsclass, int type, unsigned short id, int rd, jpayne@69: unsigned char **buf, int *buflen, int max_udp_size); jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_record_create) int ares_mkquery( jpayne@69: const char *name, int dnsclass, int type, unsigned short id, int rd, jpayne@69: unsigned char **buf, int *buflen); jpayne@69: jpayne@69: CARES_EXTERN int ares_expand_name(const unsigned char *encoded, jpayne@69: const unsigned char *abuf, int alen, char **s, jpayne@69: long *enclen); jpayne@69: jpayne@69: CARES_EXTERN int ares_expand_string(const unsigned char *encoded, jpayne@69: const unsigned char *abuf, int alen, jpayne@69: unsigned char **s, long *enclen); jpayne@69: jpayne@69: struct ares_addrttl { jpayne@69: struct in_addr ipaddr; jpayne@69: int ttl; jpayne@69: }; jpayne@69: jpayne@69: struct ares_addr6ttl { jpayne@69: struct ares_in6_addr ip6addr; jpayne@69: int ttl; jpayne@69: }; jpayne@69: jpayne@69: struct ares_caa_reply { jpayne@69: struct ares_caa_reply *next; jpayne@69: int critical; jpayne@69: unsigned char *property; jpayne@69: size_t plength; /* plength excludes null termination */ jpayne@69: unsigned char *value; jpayne@69: size_t length; /* length excludes null termination */ jpayne@69: }; jpayne@69: jpayne@69: struct ares_srv_reply { jpayne@69: struct ares_srv_reply *next; jpayne@69: char *host; jpayne@69: unsigned short priority; jpayne@69: unsigned short weight; jpayne@69: unsigned short port; jpayne@69: }; jpayne@69: jpayne@69: struct ares_mx_reply { jpayne@69: struct ares_mx_reply *next; jpayne@69: char *host; jpayne@69: unsigned short priority; jpayne@69: }; jpayne@69: jpayne@69: struct ares_txt_reply { jpayne@69: struct ares_txt_reply *next; jpayne@69: unsigned char *txt; jpayne@69: size_t length; /* length excludes null termination */ jpayne@69: }; jpayne@69: jpayne@69: /* NOTE: This structure is a superset of ares_txt_reply jpayne@69: */ jpayne@69: struct ares_txt_ext { jpayne@69: struct ares_txt_ext *next; jpayne@69: unsigned char *txt; jpayne@69: size_t length; jpayne@69: /* 1 - if start of new record jpayne@69: * 0 - if a chunk in the same record */ jpayne@69: unsigned char record_start; jpayne@69: }; jpayne@69: jpayne@69: struct ares_naptr_reply { jpayne@69: struct ares_naptr_reply *next; jpayne@69: unsigned char *flags; jpayne@69: unsigned char *service; jpayne@69: unsigned char *regexp; jpayne@69: char *replacement; jpayne@69: unsigned short order; jpayne@69: unsigned short preference; jpayne@69: }; jpayne@69: jpayne@69: struct ares_soa_reply { jpayne@69: char *nsname; jpayne@69: char *hostmaster; jpayne@69: unsigned int serial; jpayne@69: unsigned int refresh; jpayne@69: unsigned int retry; jpayne@69: unsigned int expire; jpayne@69: unsigned int minttl; jpayne@69: }; jpayne@69: jpayne@69: struct ares_uri_reply { jpayne@69: struct ares_uri_reply *next; jpayne@69: unsigned short priority; jpayne@69: unsigned short weight; jpayne@69: char *uri; jpayne@69: int ttl; jpayne@69: }; jpayne@69: jpayne@69: /* jpayne@69: * Similar to addrinfo, but with extra ttl and missing canonname. jpayne@69: */ jpayne@69: struct ares_addrinfo_node { jpayne@69: int ai_ttl; jpayne@69: int ai_flags; jpayne@69: int ai_family; jpayne@69: int ai_socktype; jpayne@69: int ai_protocol; jpayne@69: ares_socklen_t ai_addrlen; jpayne@69: struct sockaddr *ai_addr; jpayne@69: struct ares_addrinfo_node *ai_next; jpayne@69: }; jpayne@69: jpayne@69: /* jpayne@69: * alias - label of the resource record. jpayne@69: * name - value (canonical name) of the resource record. jpayne@69: * See RFC2181 10.1.1. CNAME terminology. jpayne@69: */ jpayne@69: struct ares_addrinfo_cname { jpayne@69: int ttl; jpayne@69: char *alias; jpayne@69: char *name; jpayne@69: struct ares_addrinfo_cname *next; jpayne@69: }; jpayne@69: jpayne@69: struct ares_addrinfo { jpayne@69: struct ares_addrinfo_cname *cnames; jpayne@69: struct ares_addrinfo_node *nodes; jpayne@69: char *name; jpayne@69: }; jpayne@69: jpayne@69: struct ares_addrinfo_hints { jpayne@69: int ai_flags; jpayne@69: int ai_family; jpayne@69: int ai_socktype; jpayne@69: int ai_protocol; jpayne@69: }; jpayne@69: jpayne@69: /* jpayne@69: ** Parse the buffer, starting at *abuf and of length alen bytes, previously jpayne@69: ** obtained from an ares_search call. Put the results in *host, if nonnull. jpayne@69: ** Also, if addrttls is nonnull, put up to *naddrttls IPv4 addresses along with jpayne@69: ** their TTLs in that array, and set *naddrttls to the number of addresses jpayne@69: ** so written. jpayne@69: */ jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_a_reply( jpayne@69: const unsigned char *abuf, int alen, struct hostent **host, jpayne@69: struct ares_addrttl *addrttls, int *naddrttls); jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_aaaa_reply( jpayne@69: const unsigned char *abuf, int alen, struct hostent **host, jpayne@69: struct ares_addr6ttl *addrttls, int *naddrttls); jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_caa_reply( jpayne@69: const unsigned char *abuf, int alen, struct ares_caa_reply **caa_out); jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_ptr_reply( jpayne@69: const unsigned char *abuf, int alen, const void *addr, int addrlen, jpayne@69: int family, struct hostent **host); jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_ns_reply( jpayne@69: const unsigned char *abuf, int alen, struct hostent **host); jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_srv_reply( jpayne@69: const unsigned char *abuf, int alen, struct ares_srv_reply **srv_out); jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_mx_reply( jpayne@69: const unsigned char *abuf, int alen, struct ares_mx_reply **mx_out); jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_txt_reply( jpayne@69: const unsigned char *abuf, int alen, struct ares_txt_reply **txt_out); jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_txt_reply_ext( jpayne@69: const unsigned char *abuf, int alen, struct ares_txt_ext **txt_out); jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_naptr_reply( jpayne@69: const unsigned char *abuf, int alen, struct ares_naptr_reply **naptr_out); jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_soa_reply( jpayne@69: const unsigned char *abuf, int alen, struct ares_soa_reply **soa_out); jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_dns_parse) int ares_parse_uri_reply( jpayne@69: const unsigned char *abuf, int alen, struct ares_uri_reply **uri_out); jpayne@69: jpayne@69: CARES_EXTERN void ares_free_string(void *str); jpayne@69: jpayne@69: CARES_EXTERN void ares_free_hostent(struct hostent *host); jpayne@69: jpayne@69: CARES_EXTERN void ares_free_data(void *dataptr); jpayne@69: jpayne@69: CARES_EXTERN const char *ares_strerror(int code); jpayne@69: jpayne@69: struct ares_addr_node { jpayne@69: struct ares_addr_node *next; jpayne@69: int family; jpayne@69: jpayne@69: union { jpayne@69: struct in_addr addr4; jpayne@69: struct ares_in6_addr addr6; jpayne@69: } addr; jpayne@69: }; jpayne@69: jpayne@69: struct ares_addr_port_node { jpayne@69: struct ares_addr_port_node *next; jpayne@69: int family; jpayne@69: jpayne@69: union { jpayne@69: struct in_addr addr4; jpayne@69: struct ares_in6_addr addr6; jpayne@69: } addr; jpayne@69: jpayne@69: int udp_port; jpayne@69: int tcp_port; jpayne@69: }; jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_set_servers_csv) int ares_set_servers( jpayne@69: ares_channel_t *channel, const struct ares_addr_node *servers); jpayne@69: jpayne@69: CARES_EXTERN jpayne@69: CARES_DEPRECATED_FOR(ares_set_servers_ports_csv) jpayne@69: int ares_set_servers_ports(ares_channel_t *channel, jpayne@69: const struct ares_addr_port_node *servers); jpayne@69: jpayne@69: /* Incoming string format: host[:port][,host[:port]]... */ jpayne@69: CARES_EXTERN int ares_set_servers_csv(ares_channel_t *channel, jpayne@69: const char *servers); jpayne@69: CARES_EXTERN int ares_set_servers_ports_csv(ares_channel_t *channel, jpayne@69: const char *servers); jpayne@69: CARES_EXTERN char *ares_get_servers_csv(const ares_channel_t *channel); jpayne@69: jpayne@69: CARES_EXTERN CARES_DEPRECATED_FOR(ares_get_servers_csv) int ares_get_servers( jpayne@69: const ares_channel_t *channel, struct ares_addr_node **servers); jpayne@69: jpayne@69: CARES_EXTERN jpayne@69: CARES_DEPRECATED_FOR(ares_get_servers_csv) jpayne@69: int ares_get_servers_ports(const ares_channel_t *channel, jpayne@69: struct ares_addr_port_node **servers); jpayne@69: jpayne@69: CARES_EXTERN const char *ares_inet_ntop(int af, const void *src, char *dst, jpayne@69: ares_socklen_t size); jpayne@69: jpayne@69: CARES_EXTERN int ares_inet_pton(int af, const char *src, void *dst); jpayne@69: jpayne@69: /*! Whether or not the c-ares library was built with threadsafety jpayne@69: * jpayne@69: * \return ARES_TRUE if built with threadsafety, ARES_FALSE if not jpayne@69: */ jpayne@69: CARES_EXTERN ares_bool_t ares_threadsafety(void); jpayne@69: jpayne@69: jpayne@69: /*! Block until notified that there are no longer any queries in queue, or jpayne@69: * the specified timeout has expired. jpayne@69: * jpayne@69: * \param[in] channel Initialized ares channel jpayne@69: * \param[in] timeout_ms Number of milliseconds to wait for the queue to be jpayne@69: * empty. -1 for Infinite. jpayne@69: * \return ARES_ENOTIMP if not built with threading support, ARES_ETIMEOUT jpayne@69: * if requested timeout expires, ARES_SUCCESS when queue is empty. jpayne@69: */ jpayne@69: CARES_EXTERN ares_status_t ares_queue_wait_empty(ares_channel_t *channel, jpayne@69: int timeout_ms); jpayne@69: jpayne@69: jpayne@69: /*! Retrieve the total number of active queries pending answers from servers. jpayne@69: * Some c-ares requests may spawn multiple queries, such as ares_getaddrinfo() jpayne@69: * when using AF_UNSPEC, which will be reflected in this number. jpayne@69: * jpayne@69: * \param[in] channel Initialized ares channel jpayne@69: * \return Number of active queries to servers jpayne@69: */ jpayne@69: CARES_EXTERN size_t ares_queue_active_queries(const ares_channel_t *channel); jpayne@69: jpayne@69: #ifdef __cplusplus jpayne@69: } jpayne@69: #endif jpayne@69: jpayne@69: #endif /* ARES__H */