diff options
| author | Remko Tronçon <git@el-tramo.be> | 2009-12-03 20:06:33 (GMT) | 
|---|---|---|
| committer | Remko Tronçon <git@el-tramo.be> | 2009-12-03 20:06:33 (GMT) | 
| commit | 5df50c35e1baeee517a0895a2c8a2cc2052b087f (patch) | |
| tree | b9d90fd123ec251ebb930cfcfaa2ffc805433812 | |
| parent | 9b3edba27b8683f1a87ad66ee05802dd93bbbdfc (diff) | |
| download | swift-5df50c35e1baeee517a0895a2c8a2cc2052b087f.zip swift-5df50c35e1baeee517a0895a2c8a2cc2052b087f.tar.bz2  | |
Added C-Ares.
65 files changed, 12359 insertions, 0 deletions
diff --git a/3rdParty/CAres/SConscript b/3rdParty/CAres/SConscript new file mode 100644 index 0000000..f422867 --- /dev/null +++ b/3rdParty/CAres/SConscript @@ -0,0 +1,49 @@ +Import("env") + +myenv = env.Clone() +myenv.Append(CPPPATH = ["src"]) +if myenv["PLATFORM"] != "win32" : +  myenv.Append(CPPDEFINES = ["HAVE_CONFIG_H"]) + +myenv.StaticLibrary("CAres", [ +    "src/ares__close_sockets.c", +    "src/ares__get_hostent.c", +    "src/ares__read_line.c", +    "src/ares__timeval.c", +    "src/ares_cancel.c", +    "src/ares_data.c", +    "src/ares_destroy.c", +    "src/ares_expand_name.c", +    "src/ares_expand_string.c", +    "src/ares_fds.c", +    "src/ares_free_hostent.c", +    "src/ares_free_string.c", +    "src/ares_gethostbyaddr.c", +    "src/ares_gethostbyname.c", +    "src/ares_getnameinfo.c", +    "src/ares_getsock.c", +    "src/ares_init.c", +    "src/ares_library_init.c", +    "src/ares_llist.c", +    "src/ares_mkquery.c", +    "src/ares_parse_a_reply.c", +    "src/ares_parse_aaaa_reply.c", +    "src/ares_parse_ns_reply.c", +    "src/ares_parse_ptr_reply.c", +    "src/ares_parse_srv_reply.c", +    "src/ares_parse_txt_reply.c", +    "src/ares_process.c", +    "src/ares_query.c", +    "src/ares_search.c", +    "src/ares_send.c", +    "src/ares_strcasecmp.c", +    "src/ares_strdup.c", +    "src/ares_strerror.c", +    "src/ares_timeout.c", +    "src/ares_version.c", +    "src/ares_writev.c", +    "src/bitncmp.c", +    "src/inet_net_pton.c", +    "src/inet_ntop.c", +    "src/windows_port.c", +  ]) diff --git a/3rdParty/CAres/src/ares.h b/3rdParty/CAres/src/ares.h new file mode 100644 index 0000000..b1c2c22 --- /dev/null +++ b/3rdParty/CAres/src/ares.h @@ -0,0 +1,494 @@ +/* $Id: ares.h,v 1.72 2009-11-23 12:03:32 yangtse Exp $ */ + +/* Copyright 1998, 2009 by the Massachusetts Institute of Technology. + * Copyright (C) 2007-2009 by Daniel Stenberg + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#ifndef ARES__H +#define ARES__H + +#include "ares_version.h"  /* c-ares version defines   */ +#include "ares_build.h"    /* c-ares build definitions */ +#include "ares_rules.h"    /* c-ares rules enforcement */ + +/* + * Define WIN32 when build target is Win32 API + */ + +#if (defined(_WIN32) || defined(__WIN32__)) && \ +   !defined(WIN32) && !defined(__SYMBIAN32__) +#  define WIN32 +#endif + +#include <sys/types.h> + +/* HP-UX systems version 9, 10 and 11 lack sys/select.h and so does oldish +   libc5-based Linux systems. Only include it on system that are known to +   require it! */ +#if defined(_AIX) || defined(__NOVELL_LIBC__) || defined(__NetBSD__) || \ +    defined(__minix) || defined(__SYMBIAN32__) || defined(__INTEGRITY) +#include <sys/select.h> +#endif +#if (defined(NETWARE) && !defined(__NOVELL_LIBC__)) +#include <sys/bsdskt.h> +#endif + +#if defined(WATT32) +#  include <netinet/in.h> +#  include <sys/socket.h> +#  include <tcp.h> +#elif defined(WIN32) +#  ifndef WIN32_LEAN_AND_MEAN +#    define WIN32_LEAN_AND_MEAN +#  endif +#  include <windows.h> +#  include <winsock2.h> +#  include <ws2tcpip.h> +#else +#  include <sys/socket.h> +#  include <netinet/in.h> +#endif + +#ifdef  __cplusplus +extern "C" { +#endif + +/* +** c-ares external API function linkage decorations. +*/ + +#if !defined(CARES_STATICLIB) && \ +   (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__)) +   /* __declspec function decoration for Win32 and Symbian DLL's */ +#  if defined(CARES_BUILDING_LIBRARY) +#    define CARES_EXTERN  __declspec(dllexport) +#  else +#    define CARES_EXTERN  __declspec(dllimport) +#  endif +#else +   /* visibility function decoration for other cases */ +#  if !defined(CARES_SYMBOL_HIDING) || \ +     defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__) +#    define CARES_EXTERN +#  else +#    define CARES_EXTERN CARES_SYMBOL_SCOPE_EXTERN +#  endif +#endif + + +#define ARES_SUCCESS            0 + +/* Server error codes (ARES_ENODATA indicates no relevant answer) */ +#define ARES_ENODATA            1 +#define ARES_EFORMERR           2 +#define ARES_ESERVFAIL          3 +#define ARES_ENOTFOUND          4 +#define ARES_ENOTIMP            5 +#define ARES_EREFUSED           6 + +/* Locally generated error codes */ +#define ARES_EBADQUERY          7 +#define ARES_EBADNAME           8 +#define ARES_EBADFAMILY         9 +#define ARES_EBADRESP           10 +#define ARES_ECONNREFUSED       11 +#define ARES_ETIMEOUT           12 +#define ARES_EOF                13 +#define ARES_EFILE              14 +#define ARES_ENOMEM             15 +#define ARES_EDESTRUCTION       16 +#define ARES_EBADSTR            17 + +/* ares_getnameinfo error codes */ +#define ARES_EBADFLAGS          18 + +/* ares_getaddrinfo error codes */ +#define ARES_ENONAME            19 +#define ARES_EBADHINTS          20 + +/* Uninitialized library error code */ +#define ARES_ENOTINITIALIZED    21          /* introduced in 1.7.0 */ + +/* ares_library_init error codes */ +#define ARES_ELOADIPHLPAPI           22     /* introduced in 1.7.0 */ +#define ARES_EADDRGETNETWORKPARAMS   23     /* introduced in 1.7.0 */ + +/* More error codes */ +#define ARES_ECANCELLED         24          /* introduced in 1.7.0 */ + +/* Flag values */ +#define ARES_FLAG_USEVC         (1 << 0) +#define ARES_FLAG_PRIMARY       (1 << 1) +#define ARES_FLAG_IGNTC         (1 << 2) +#define ARES_FLAG_NORECURSE     (1 << 3) +#define ARES_FLAG_STAYOPEN      (1 << 4) +#define ARES_FLAG_NOSEARCH      (1 << 5) +#define ARES_FLAG_NOALIASES     (1 << 6) +#define ARES_FLAG_NOCHECKRESP   (1 << 7) + +/* Option mask values */ +#define ARES_OPT_FLAGS          (1 << 0) +#define ARES_OPT_TIMEOUT        (1 << 1) +#define ARES_OPT_TRIES          (1 << 2) +#define ARES_OPT_NDOTS          (1 << 3) +#define ARES_OPT_UDP_PORT       (1 << 4) +#define ARES_OPT_TCP_PORT       (1 << 5) +#define ARES_OPT_SERVERS        (1 << 6) +#define ARES_OPT_DOMAINS        (1 << 7) +#define ARES_OPT_LOOKUPS        (1 << 8) +#define ARES_OPT_SOCK_STATE_CB  (1 << 9) +#define ARES_OPT_SORTLIST       (1 << 10) +#define ARES_OPT_SOCK_SNDBUF    (1 << 11) +#define ARES_OPT_SOCK_RCVBUF    (1 << 12) +#define ARES_OPT_TIMEOUTMS      (1 << 13) +#define ARES_OPT_ROTATE         (1 << 14) + +/* Nameinfo flag values */ +#define ARES_NI_NOFQDN                  (1 << 0) +#define ARES_NI_NUMERICHOST             (1 << 1) +#define ARES_NI_NAMEREQD                (1 << 2) +#define ARES_NI_NUMERICSERV             (1 << 3) +#define ARES_NI_DGRAM                   (1 << 4) +#define ARES_NI_TCP                     0 +#define ARES_NI_UDP                     ARES_NI_DGRAM +#define ARES_NI_SCTP                    (1 << 5) +#define ARES_NI_DCCP                    (1 << 6) +#define ARES_NI_NUMERICSCOPE            (1 << 7) +#define ARES_NI_LOOKUPHOST              (1 << 8) +#define ARES_NI_LOOKUPSERVICE           (1 << 9) +/* Reserved for future use */ +#define ARES_NI_IDN                     (1 << 10) +#define ARES_NI_IDN_ALLOW_UNASSIGNED    (1 << 11) +#define ARES_NI_IDN_USE_STD3_ASCII_RULES (1 << 12) + +/* Addrinfo flag values */ +#define ARES_AI_CANONNAME               (1 << 0) +#define ARES_AI_NUMERICHOST             (1 << 1) +#define ARES_AI_PASSIVE                 (1 << 2) +#define ARES_AI_NUMERICSERV             (1 << 3) +#define ARES_AI_V4MAPPED                (1 << 4) +#define ARES_AI_ALL                     (1 << 5) +#define ARES_AI_ADDRCONFIG              (1 << 6) +/* Reserved for future use */ +#define ARES_AI_IDN                     (1 << 10) +#define ARES_AI_IDN_ALLOW_UNASSIGNED    (1 << 11) +#define ARES_AI_IDN_USE_STD3_ASCII_RULES (1 << 12) +#define ARES_AI_CANONIDN                (1 << 13) + +#define ARES_AI_MASK (ARES_AI_CANONNAME|ARES_AI_NUMERICHOST|ARES_AI_PASSIVE| \ +                      ARES_AI_NUMERICSERV|ARES_AI_V4MAPPED|ARES_AI_ALL| \ +                      ARES_AI_ADDRCONFIG) +#define ARES_GETSOCK_MAXNUM 16 /* ares_getsock() can return info about this +                                  many sockets */ +#define ARES_GETSOCK_READABLE(bits,num) (bits & (1<< (num))) +#define ARES_GETSOCK_WRITABLE(bits,num) (bits & (1 << ((num) + \ +                                         ARES_GETSOCK_MAXNUM))) + +/* c-ares library initialization flag values */ +#define ARES_LIB_INIT_NONE   (0) +#define ARES_LIB_INIT_WIN32  (1 << 0) +#define ARES_LIB_INIT_ALL    (ARES_LIB_INIT_WIN32) + + +/* + * Typedef our socket type + */ + +#ifndef ares_socket_typedef +#ifdef WIN32 +typedef SOCKET ares_socket_t; +#define ARES_SOCKET_BAD INVALID_SOCKET +#else +typedef int ares_socket_t; +#define ARES_SOCKET_BAD -1 +#endif +#define ares_socket_typedef +#endif /* ares_socket_typedef */ + +typedef void (*ares_sock_state_cb)(void *data, +                                   ares_socket_t socket_fd, +                                   int readable, +                                   int writable); + +struct apattern; + +/* NOTE about the ares_options struct to users and developers. + +   This struct will remain looking like this. It will not be extended nor +   shrunk in future releases, but all new options will be set by ares_set_*() +   options instead of with the ares_init_options() function. + +   Eventually (in a galaxy far far away), all options will be settable by +   ares_set_*() options and the ares_init_options() function will become +   deprecated. + +   When new options are added to c-ares, they are not added to this +   struct. And they are not "saved" with the ares_save_options() function but +   instead we encourage the use of the ares_dup() function. Needless to say, +   if you add config options to c-ares you need to make sure ares_dup() +   duplicates this new option. + + */ +struct ares_options { +  int flags; +  int timeout; /* in seconds or milliseconds, depending on options */ +  int tries; +  int ndots; +  unsigned short udp_port; +  unsigned short tcp_port; +  int socket_send_buffer_size; +  int socket_receive_buffer_size; +  struct in_addr *servers; +  int nservers; +  char **domains; +  int ndomains; +  char *lookups; +  ares_sock_state_cb sock_state_cb; +  void *sock_state_cb_data; +  struct apattern *sortlist; +  int nsort; +}; + +struct hostent; +struct timeval; +struct sockaddr; +struct ares_channeldata; + +typedef struct ares_channeldata *ares_channel; + +typedef void (*ares_callback)(void *arg, +                              int status, +                              int timeouts, +                              unsigned char *abuf, +                              int alen); + +typedef void (*ares_host_callback)(void *arg, +                                   int status, +                                   int timeouts, +                                   struct hostent *hostent); + +typedef void (*ares_nameinfo_callback)(void *arg, +                                       int status, +                                       int timeouts, +                                       char *node, +                                       char *service); + +typedef int  (*ares_sock_create_callback)(ares_socket_t socket_fd, +                                          int type, +                                          void *data); + +CARES_EXTERN int ares_library_init(int flags); + +CARES_EXTERN void ares_library_cleanup(void); + +CARES_EXTERN const char *ares_version(int *version); + +CARES_EXTERN int ares_init(ares_channel *channelptr); + +CARES_EXTERN int ares_init_options(ares_channel *channelptr, +                                   struct ares_options *options, +                                   int optmask); + +CARES_EXTERN int ares_save_options(ares_channel channel, +                                   struct ares_options *options, +                                   int *optmask); + +CARES_EXTERN void ares_destroy_options(struct ares_options *options); + +CARES_EXTERN int ares_dup(ares_channel *dest, +                          ares_channel src); + +CARES_EXTERN void ares_destroy(ares_channel channel); + +CARES_EXTERN void ares_cancel(ares_channel channel); + +CARES_EXTERN void ares_set_socket_callback(ares_channel channel, +                                           ares_sock_create_callback callback, +                                           void *user_data); + +CARES_EXTERN void ares_send(ares_channel channel, +                            const unsigned char *qbuf, +                            int qlen, +                            ares_callback callback, +                            void *arg); + +CARES_EXTERN void ares_query(ares_channel channel, +                             const char *name, +                             int dnsclass, +                             int type, +                             ares_callback callback, +                             void *arg); + +CARES_EXTERN void ares_search(ares_channel channel, +                              const char *name, +                              int dnsclass, +                              int type, +                              ares_callback callback, +                              void *arg); + +CARES_EXTERN void ares_gethostbyname(ares_channel channel, +                                     const char *name, +                                     int family, +                                     ares_host_callback callback, +                                     void *arg); + +CARES_EXTERN int ares_gethostbyname_file(ares_channel channel, +                                         const char *name, +                                         int family, +                                         struct hostent **host); + +CARES_EXTERN void ares_gethostbyaddr(ares_channel channel, +                                     const void *addr, +                                     int addrlen, +                                     int family, +                                     ares_host_callback callback, +                                     void *arg); + +CARES_EXTERN void ares_getnameinfo(ares_channel channel, +                                   const struct sockaddr *sa, +                                   ares_socklen_t salen, +                                   int flags, +                                   ares_nameinfo_callback callback, +                                   void *arg); + +CARES_EXTERN int ares_fds(ares_channel channel, +                          fd_set *read_fds, +                          fd_set *write_fds); + +CARES_EXTERN int ares_getsock(ares_channel channel, +                              int *socks, +                              int numsocks); + +CARES_EXTERN struct timeval *ares_timeout(ares_channel channel, +                                          struct timeval *maxtv, +                                          struct timeval *tv); + +CARES_EXTERN void ares_process(ares_channel channel, +                               fd_set *read_fds, +                               fd_set *write_fds); + +CARES_EXTERN void ares_process_fd(ares_channel channel, +                                  ares_socket_t read_fd, +                                  ares_socket_t write_fd); + +CARES_EXTERN int ares_mkquery(const char *name, +                              int dnsclass, +                              int type, +                              unsigned short id, +                              int rd, +                              unsigned char **buf, +                              int *buflen); + +CARES_EXTERN int ares_expand_name(const unsigned char *encoded, +                                  const unsigned char *abuf, +                                  int alen, +                                  char **s, +                                  long *enclen); + +CARES_EXTERN int ares_expand_string(const unsigned char *encoded, +                                    const unsigned char *abuf, +                                    int alen, +                                    unsigned char **s, +                                    long *enclen); + +/* + * NOTE: before c-ares 1.7.0 we would most often use the system in6_addr + * struct below when ares itself was built, but many apps would use this + * private version since the header checked a HAVE_* define for it. Starting + * with 1.7.0 we always declare and use our own to stop relying on the + * system's one. + */ +struct ares_in6_addr { +  union { +    unsigned char _S6_u8[16]; +  } _S6_un; +}; + +struct ares_addrttl { +  struct in_addr ipaddr; +  int            ttl; +}; + +struct ares_addr6ttl { +  struct ares_in6_addr ip6addr; +  int             ttl; +}; + +struct ares_srv_reply { +  struct ares_srv_reply  *next; +  char                   *host; +  unsigned short          priority; +  unsigned short          weight; +  unsigned short          port; +}; + +struct ares_txt_reply { +  struct ares_txt_reply  *next; +  unsigned char          *txt; +  size_t                  length;  /* length excludes null termination */ +}; + +/* +** Parse the buffer, starting at *abuf and of length alen bytes, previously +** obtained from an ares_search call.  Put the results in *host, if nonnull. +** Also, if addrttls is nonnull, put up to *naddrttls IPv4 addresses along with +** their TTLs in that array, and set *naddrttls to the number of addresses +** so written. +*/ + +CARES_EXTERN int ares_parse_a_reply(const unsigned char *abuf, +                                    int alen, +                                    struct hostent **host, +                                    struct ares_addrttl *addrttls, +                                    int *naddrttls); + +CARES_EXTERN int ares_parse_aaaa_reply(const unsigned char *abuf, +                                       int alen, +                                       struct hostent **host, +                                       struct ares_addr6ttl *addrttls, +                                       int *naddrttls); + +CARES_EXTERN int ares_parse_ptr_reply(const unsigned char *abuf, +                                      int alen, +                                      const void *addr, +                                      int addrlen, +                                      int family, +                                      struct hostent **host); + +CARES_EXTERN int ares_parse_ns_reply(const unsigned char *abuf, +                                     int alen, +                                     struct hostent **host); + +CARES_EXTERN int ares_parse_srv_reply(const unsigned char* abuf, +                                      int alen, +                                      struct ares_srv_reply** srv_out); + +CARES_EXTERN int ares_parse_txt_reply(const unsigned char* abuf, +                                      int alen, +                                      struct ares_txt_reply** txt_out); + +CARES_EXTERN void ares_free_string(void *str); + +CARES_EXTERN void ares_free_hostent(struct hostent *host); + +CARES_EXTERN void ares_free_data(void *dataptr); + +CARES_EXTERN const char *ares_strerror(int code); + +#ifdef  __cplusplus +} +#endif + +#endif /* ARES__H */ diff --git a/3rdParty/CAres/src/ares__close_sockets.c b/3rdParty/CAres/src/ares__close_sockets.c new file mode 100644 index 0000000..ef8910d --- /dev/null +++ b/3rdParty/CAres/src/ares__close_sockets.c @@ -0,0 +1,67 @@ +/* $Id: ares__close_sockets.c,v 1.10 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#include <stdlib.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include "ares.h" +#include "ares_private.h" + +void ares__close_sockets(ares_channel channel, struct server_state *server) +{ +  struct send_request *sendreq; + +  /* Free all pending output buffers. */ +  while (server->qhead) +    { +      /* Advance server->qhead; pull out query as we go. */ +      sendreq = server->qhead; +      server->qhead = sendreq->next; +      if (sendreq->data_storage != NULL) +        free(sendreq->data_storage); +      free(sendreq); +    } +  server->qtail = NULL; + +  /* Reset any existing input buffer. */ +  if (server->tcp_buffer) +    free(server->tcp_buffer); +  server->tcp_buffer = NULL; +  server->tcp_lenbuf_pos = 0; + +  /* Reset brokenness */ +  server->is_broken = 0; + +  /* Close the TCP and UDP sockets. */ +  if (server->tcp_socket != ARES_SOCKET_BAD) +    { +      SOCK_STATE_CALLBACK(channel, server->tcp_socket, 0, 0); +      sclose(server->tcp_socket); +      server->tcp_socket = ARES_SOCKET_BAD; +      server->tcp_connection_generation = ++channel->tcp_connection_generation; +    } +  if (server->udp_socket != ARES_SOCKET_BAD) +    { +      SOCK_STATE_CALLBACK(channel, server->udp_socket, 0, 0); +      sclose(server->udp_socket); +      server->udp_socket = ARES_SOCKET_BAD; +    } +} diff --git a/3rdParty/CAres/src/ares__get_hostent.c b/3rdParty/CAres/src/ares__get_hostent.c new file mode 100644 index 0000000..335f763 --- /dev/null +++ b/3rdParty/CAres/src/ares__get_hostent.c @@ -0,0 +1,264 @@ +/* $Id: ares__get_hostent.c,v 1.24 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998, 2009 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_SYS_SOCKET_H +#  include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#  include <netinet/in.h> +#endif +#ifdef HAVE_NETDB_H +#  include <netdb.h> +#endif +#ifdef HAVE_ARPA_INET_H +#  include <arpa/inet.h> +#endif + +#include "ares.h" +#include "inet_net_pton.h" +#include "ares_private.h" + +int ares__get_hostent(FILE *fp, int family, struct hostent **host) +{ +  char *line = NULL, *p, *q, **alias; +  char *txtaddr, *txthost, *txtalias; +  int status; +  size_t addrlen, linesize, naliases; +  struct ares_addr addr; +  struct hostent *hostent = NULL; + +  *host = NULL; /* Assume failure */ + +  /* Validate family */ +  switch (family) { +    case AF_INET: +    case AF_INET6: +    case AF_UNSPEC: +      break; +    default: +      return ARES_EBADFAMILY; +  } + +  while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) +    { + +      /* Trim line comment. */ +      p = line; +      while (*p && (*p != '#')) +        p++; +      *p = '\0'; + +      /* Trim trailing whitespace. */ +      q = p - 1; +      while ((q >= line) && ISSPACE(*q)) +        q--; +      *++q = '\0'; + +      /* Skip leading whitespace. */ +      p = line; +      while (*p && ISSPACE(*p)) +        p++; +      if (!*p) +        /* Ignore line if empty. */ +        continue; + +      /* Pointer to start of IPv4 or IPv6 address part. */ +      txtaddr = p; + +      /* Advance past address part. */ +      while (*p && !ISSPACE(*p)) +        p++; +      if (!*p) +        /* Ignore line if reached end of line. */ +        continue; + +      /* Null terminate address part. */ +      *p = '\0'; + +      /* Advance to host name */ +      p++; +      while (*p && ISSPACE(*p)) +        p++; +      if (!*p) +        /* Ignore line if reached end of line. */ +        continue; + +      /* Pointer to start of host name. */ +      txthost = p; + +      /* Advance past host name. */ +      while (*p && !ISSPACE(*p)) +        p++; + +      /* Pointer to start of first alias. */ +      txtalias = NULL; +      if (*p) +        { +          q = p + 1; +          while (*q && ISSPACE(*q)) +            q++; +          if (*q) +            txtalias = q; +        } + +      /* Null terminate host name. */ +      *p = '\0'; + +      /* find out number of aliases. */ +      naliases = 0; +      if (txtalias) +        { +          p = txtalias; +          while (*p) +            { +              while (*p && !ISSPACE(*p)) +                p++; +              while (*p && ISSPACE(*p)) +                p++; +              naliases++; +            } +        } + +      /* Convert address string to network address for the requested family. */ +      addrlen = 0; +      addr.family = AF_UNSPEC; +      addr.addrV4.s_addr = INADDR_NONE; +      if ((family == AF_INET) || (family == AF_UNSPEC)) +        { +          addr.addrV4.s_addr = inet_addr(txtaddr); +          if (addr.addrV4.s_addr != INADDR_NONE) +            { +              /* Actual network address family and length. */ +              addr.family = AF_INET; +              addrlen = sizeof(struct in_addr); +            } +        } +      if ((family == AF_INET6) || ((family == AF_UNSPEC) && (!addrlen))) +        { +          if (ares_inet_pton(AF_INET6, txtaddr, &addr.addrV6) > 0) +            { +              /* Actual network address family and length. */ +              addr.family = AF_INET6; +              addrlen = sizeof(struct in6_addr); +            } +        } +      if (!addrlen) +        /* Ignore line if invalid address string for the requested family. */ +        continue; + +      /* +      ** Actual address family possible values are AF_INET and AF_INET6 only. +      */ + +      /* Allocate memory for the hostent structure. */ +      hostent = malloc(sizeof(struct hostent)); +      if (!hostent) +        break; + +      /* Initialize fields for out of memory condition. */ +      hostent->h_aliases = NULL; +      hostent->h_addr_list = NULL; + +      /* Copy official host name. */ +      hostent->h_name = strdup(txthost); +      if (!hostent->h_name) +        break; + +      /* Copy network address. */ +      hostent->h_addr_list = malloc(2 * sizeof(char *)); +      if (!hostent->h_addr_list) +        break; +      hostent->h_addr_list[1] = NULL; +      hostent->h_addr_list[0] = malloc(addrlen); +      if (!hostent->h_addr_list[0]) +        break; +      if (addr.family == AF_INET) +        memcpy(hostent->h_addr_list[0], &addr.addrV4, sizeof(struct in_addr)); +      else +        memcpy(hostent->h_addr_list[0], &addr.addrV6, sizeof(struct in6_addr)); + +      /* Copy aliases. */ +      hostent->h_aliases = malloc((naliases + 1) * sizeof(char *)); +      if (!hostent->h_aliases) +        break; +      alias = hostent->h_aliases; +      while (naliases) +        *(alias + naliases--) = NULL; +      *alias = NULL; +      while (txtalias) +        { +          p = txtalias; +          while (*p && !ISSPACE(*p)) +            p++; +          q = p; +          while (*q && ISSPACE(*q)) +            q++; +          *p = '\0'; +          if ((*alias = strdup(txtalias)) == NULL) +            break; +          alias++; +          txtalias = *q ? q : NULL; +        } +      if (txtalias) +        /* Alias memory allocation failure. */ +        break; + +      /* Copy actual network address family and length. */ +      hostent->h_addrtype = addr.family; +      hostent->h_length = (int)addrlen; + +      /* Free line buffer. */ +      free(line); + +      /* Return hostent successfully */ +      *host = hostent; +      return ARES_SUCCESS; + +    } + +  /* If allocated, free line buffer. */ +  if (line) +    free(line); + +  if (status == ARES_SUCCESS) +    { +      /* Memory allocation failure; clean up. */ +      if (hostent) +        { +          if (hostent->h_name) +            free((char *) hostent->h_name); +          if (hostent->h_aliases) +            { +              for (alias = hostent->h_aliases; *alias; alias++) +                free(*alias); +              free(hostent->h_aliases); +            } +          if (hostent->h_addr_list) +            { +              if (hostent->h_addr_list[0]) +                free(hostent->h_addr_list[0]); +              free(hostent->h_addr_list); +            } +          free(hostent); +        } +      return ARES_ENOMEM; +    } + +  return status; +} diff --git a/3rdParty/CAres/src/ares__read_line.c b/3rdParty/CAres/src/ares__read_line.c new file mode 100644 index 0000000..270e0e3 --- /dev/null +++ b/3rdParty/CAres/src/ares__read_line.c @@ -0,0 +1,67 @@ +/* $Id: ares__read_line.c,v 1.14 2009-11-10 18:41:03 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "ares.h" +#include "ares_private.h" + +/* This is an internal function.  Its contract is to read a line from + * a file into a dynamically allocated buffer, zeroing the trailing + * newline if there is one.  The calling routine may call + * ares__read_line multiple times with the same buf and bufsize + * pointers; *buf will be reallocated and *bufsize adjusted as + * appropriate.  The initial value of *buf should be NULL.  After the + * calling routine is done reading lines, it should free *buf. + */ +int ares__read_line(FILE *fp, char **buf, size_t *bufsize) +{ +  char *newbuf; +  size_t offset = 0; +  size_t len; + +  if (*buf == NULL) +    { +      *buf = malloc(128); +      if (!*buf) +        return ARES_ENOMEM; +      *bufsize = 128; +    } + +  for (;;) +    { +      if (!fgets(*buf + offset, (int)(*bufsize - offset), fp)) +        return (offset != 0) ? 0 : (ferror(fp)) ? ARES_EFILE : ARES_EOF; +      len = offset + strlen(*buf + offset); +      if ((*buf)[len - 1] == '\n') +        { +          (*buf)[len - 1] = 0; +          break; +        } +      offset = len; + +      /* Allocate more space. */ +      newbuf = realloc(*buf, *bufsize * 2); +      if (!newbuf) +        return ARES_ENOMEM; +      *buf = newbuf; +      *bufsize *= 2; +    } +  return ARES_SUCCESS; +} diff --git a/3rdParty/CAres/src/ares__timeval.c b/3rdParty/CAres/src/ares__timeval.c new file mode 100644 index 0000000..2957350 --- /dev/null +++ b/3rdParty/CAres/src/ares__timeval.c @@ -0,0 +1,112 @@ +/* $Id: ares__timeval.c,v 1.6 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright (C) 2008 by Daniel Stenberg et al + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission.  M.I.T. makes no representations about the + * suitability of this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" +#include "ares.h" +#include "ares_private.h" + +#if defined(WIN32) && !defined(MSDOS) + +struct timeval ares__tvnow(void) +{ +  /* +  ** GetTickCount() is available on _all_ Windows versions from W95 up +  ** to nowadays. Returns milliseconds elapsed since last system boot, +  ** increases monotonically and wraps once 49.7 days have elapsed. +  */ +  struct timeval now; +  DWORD milliseconds = GetTickCount(); +  now.tv_sec = milliseconds / 1000; +  now.tv_usec = (milliseconds % 1000) * 1000; +  return now; +} + +#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC) + +struct timeval ares__tvnow(void) +{ +  /* +  ** clock_gettime() is granted to be increased monotonically when the +  ** monotonic clock is queried. Time starting point is unspecified, it +  ** could be the system start-up time, the Epoch, or something else, +  ** in any case the time starting point does not change once that the +  ** system has started up. +  */ +  struct timeval now; +  struct timespec tsnow; +  if(0 == clock_gettime(CLOCK_MONOTONIC, &tsnow)) { +    now.tv_sec = tsnow.tv_sec; +    now.tv_usec = tsnow.tv_nsec / 1000; +  } +  /* +  ** Even when the configure process has truly detected monotonic clock +  ** availability, it might happen that it is not actually available at +  ** run-time. When this occurs simply fallback to other time source. +  */ +#ifdef HAVE_GETTIMEOFDAY +  else +    (void)gettimeofday(&now, NULL); +#else +  else { +    now.tv_sec = (long)time(NULL); +    now.tv_usec = 0; +  } +#endif +  return now; +} + +#elif defined(HAVE_GETTIMEOFDAY) + +struct timeval ares__tvnow(void) +{ +  /* +  ** gettimeofday() is not granted to be increased monotonically, due to +  ** clock drifting and external source time synchronization it can jump +  ** forward or backward in time. +  */ +  struct timeval now; +  (void)gettimeofday(&now, NULL); +  return now; +} + +#else + +struct timeval ares__tvnow(void) +{ +  /* +  ** time() returns the value of time in seconds since the Epoch. +  */ +  struct timeval now; +  now.tv_sec = (long)time(NULL); +  now.tv_usec = 0; +  return now; +} + +#endif + +#if 0 /* Not used */ +/* + * Make sure that the first argument is the more recent time, as otherwise + * we'll get a weird negative time-diff back... + * + * Returns: the time difference in number of milliseconds. + */ +long ares__tvdiff(struct timeval newer, struct timeval older) +{ +  return (newer.tv_sec-older.tv_sec)*1000+ +    (newer.tv_usec-older.tv_usec)/1000; +} +#endif + diff --git a/3rdParty/CAres/src/ares_build.h b/3rdParty/CAres/src/ares_build.h new file mode 100644 index 0000000..bbbef1b --- /dev/null +++ b/3rdParty/CAres/src/ares_build.h @@ -0,0 +1,253 @@ +#ifndef __CARES_BUILD_H +#define __CARES_BUILD_H + +/* $Id: ares_build.h.dist,v 1.9 2009-05-12 01:57:53 yangtse Exp $ */ + +/* Copyright (C) 2009 by Daniel Stenberg et al + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission.  M.I.T. makes no representations about the + * suitability of this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +/* ================================================================ */ +/*               NOTES FOR CONFIGURE CAPABLE SYSTEMS                */ +/* ================================================================ */ + +/* + * NOTE 1: + * ------- + * + * See file ares_build.h.in, run configure, and forget that this file + * exists it is only used for non-configure systems. + * But you can keep reading if you want ;-) + * + */ + +/* ================================================================ */ +/*                 NOTES FOR NON-CONFIGURE SYSTEMS                  */ +/* ================================================================ */ + +/* + * NOTE 1: + * ------- + * + * Nothing in this file is intended to be modified or adjusted by the + * c-ares library user nor by the c-ares library builder. + * + * If you think that something actually needs to be changed, adjusted + * or fixed in this file, then, report it on the c-ares development + * mailing list: http://cool.haxx.se/mailman/listinfo/c-ares/ + * + * Try to keep one section per platform, compiler and architecture, + * otherwise, if an existing section is reused for a different one and + * later on the original is adjusted, probably the piggybacking one can + * be adversely changed. + * + * In order to differentiate between platforms/compilers/architectures + * use only compiler built in predefined preprocessor symbols. + * + * This header file shall only export symbols which are 'cares' or 'CARES' + * prefixed, otherwise public name space would be polluted. + * + * NOTE 2: + * ------- + * + * Right now you might be staring at file ares_build.h.dist or ares_build.h, + * this is due to the following reason: file ares_build.h.dist is renamed + * to ares_build.h when the c-ares source code distribution archive file is + * created. + * + * File ares_build.h.dist is not included in the distribution archive. + * File ares_build.h is not present in the CVS tree. + * + * The distributed ares_build.h file is only intended to be used on systems + * which can not run the also distributed configure script. + * + * On systems capable of running the configure script, the configure process + * will overwrite the distributed ares_build.h file with one that is suitable + * and specific to the library being configured and built, which is generated + * from the ares_build.h.in template file. + * + * If you check out from CVS on a non-configure platform, you must run the + * appropriate buildconf* script to set up ares_build.h and other local files. + * + */ + +/* ================================================================ */ +/*  DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE  */ +/* ================================================================ */ + +#ifdef CARES_SIZEOF_LONG +#  error "CARES_SIZEOF_LONG shall not be defined except in ares_build.h" +   Error Compilation_aborted_CARES_SIZEOF_LONG_already_defined +#endif + +#ifdef CARES_TYPEOF_ARES_SOCKLEN_T +#  error "CARES_TYPEOF_ARES_SOCKLEN_T shall not be defined except in ares_build.h" +   Error Compilation_aborted_CARES_TYPEOF_ARES_SOCKLEN_T_already_defined +#endif + +#ifdef CARES_SIZEOF_ARES_SOCKLEN_T +#  error "CARES_SIZEOF_ARES_SOCKLEN_T shall not be defined except in ares_build.h" +   Error Compilation_aborted_CARES_SIZEOF_ARES_SOCKLEN_T_already_defined +#endif + +/* ================================================================ */ +/*    EXTERNAL INTERFACE SETTINGS FOR NON-CONFIGURE SYSTEMS ONLY    */ +/* ================================================================ */ + +#if defined(__DJGPP__) || defined(__GO32__) +#  define CARES_SIZEOF_LONG           4 +#  define CARES_TYPEOF_ARES_SOCKLEN_T int +#  define CARES_SIZEOF_ARES_SOCKLEN_T 4 + +#elif defined(__SALFORDC__) +#  define CARES_SIZEOF_LONG           4 +#  define CARES_TYPEOF_ARES_SOCKLEN_T int +#  define CARES_SIZEOF_ARES_SOCKLEN_T 4 + +#elif defined(__BORLANDC__) +#  define CARES_SIZEOF_LONG           4 +#  define CARES_TYPEOF_ARES_SOCKLEN_T int +#  define CARES_SIZEOF_ARES_SOCKLEN_T 4 + +#elif defined(__TURBOC__) +#  define CARES_SIZEOF_LONG           4 +#  define CARES_TYPEOF_ARES_SOCKLEN_T int +#  define CARES_SIZEOF_ARES_SOCKLEN_T 4 + +#elif defined(__WATCOMC__) +#  define CARES_SIZEOF_LONG           4 +#  define CARES_TYPEOF_ARES_SOCKLEN_T int +#  define CARES_SIZEOF_ARES_SOCKLEN_T 4 + +#elif defined(__POCC__) +#  define CARES_SIZEOF_LONG           4 +#  define CARES_TYPEOF_ARES_SOCKLEN_T int +#  define CARES_SIZEOF_ARES_SOCKLEN_T 4 + +#elif defined(__LCC__) +#  define CARES_SIZEOF_LONG           4 +#  define CARES_TYPEOF_ARES_SOCKLEN_T int +#  define CARES_SIZEOF_ARES_SOCKLEN_T 4 + +#elif defined(__SYMBIAN32__) +#  define CARES_SIZEOF_LONG           4 +#  define CARES_TYPEOF_ARES_SOCKLEN_T unsigned int +#  define CARES_SIZEOF_ARES_SOCKLEN_T 4 + +#elif defined(__MWERKS__) +#  define CARES_SIZEOF_LONG           4 +#  define CARES_TYPEOF_ARES_SOCKLEN_T int +#  define CARES_SIZEOF_ARES_SOCKLEN_T 4 + +#elif defined(_WIN32_WCE) +#  define CARES_SIZEOF_LONG           4 +#  define CARES_TYPEOF_ARES_SOCKLEN_T int +#  define CARES_SIZEOF_ARES_SOCKLEN_T 4 + +#elif defined(__MINGW32__) +#  define CARES_SIZEOF_LONG           4 +#  define CARES_TYPEOF_ARES_SOCKLEN_T int +#  define CARES_SIZEOF_ARES_SOCKLEN_T 4 + +#elif defined(__VMS) +#  define CARES_SIZEOF_LONG           4 +#  define CARES_TYPEOF_ARES_SOCKLEN_T unsigned int +#  define CARES_SIZEOF_ARES_SOCKLEN_T 4 + +#elif defined(__OS400__) +#  if defined(__ILEC400__) +#    define CARES_SIZEOF_LONG           4 +#    define CARES_TYPEOF_ARES_SOCKLEN_T socklen_t +#    define CARES_SIZEOF_ARES_SOCKLEN_T 4 +#    define CARES_PULL_SYS_TYPES_H      1 +#    define CARES_PULL_SYS_SOCKET_H     1 +#  endif + +#elif defined(__MVS__) +#  if defined(__IBMC__) || defined(__IBMCPP__) +#    if defined(_ILP32) +#      define CARES_SIZEOF_LONG           4 +#    elif defined(_LP64) +#      define CARES_SIZEOF_LONG           8 +#    endif +#    define CARES_TYPEOF_ARES_SOCKLEN_T socklen_t +#    define CARES_SIZEOF_ARES_SOCKLEN_T 4 +#    define CARES_PULL_SYS_TYPES_H      1 +#    define CARES_PULL_SYS_SOCKET_H     1 +#  endif + +#elif defined(__370__) +#  if defined(__IBMC__) || defined(__IBMCPP__) +#    if defined(_ILP32) +#      define CARES_SIZEOF_LONG           4 +#    elif defined(_LP64) +#      define CARES_SIZEOF_LONG           8 +#    endif +#    define CARES_TYPEOF_ARES_SOCKLEN_T socklen_t +#    define CARES_SIZEOF_ARES_SOCKLEN_T 4 +#    define CARES_PULL_SYS_TYPES_H      1 +#    define CARES_PULL_SYS_SOCKET_H     1 +#  endif + +#elif defined(TPF) +#  define CARES_SIZEOF_LONG           8 +#  define CARES_TYPEOF_ARES_SOCKLEN_T int +#  define CARES_SIZEOF_ARES_SOCKLEN_T 4 + +/* ===================================== */ +/*    KEEP MSVC THE PENULTIMATE ENTRY    */ +/* ===================================== */ + +#elif defined(_MSC_VER) +#  define CARES_SIZEOF_LONG           4 +#  define CARES_TYPEOF_ARES_SOCKLEN_T int +#  define CARES_SIZEOF_ARES_SOCKLEN_T 4 + +/* ===================================== */ +/*    KEEP GENERIC GCC THE LAST ENTRY    */ +/* ===================================== */ + +#elif defined(__GNUC__) +#  if defined(__i386__) || defined(__ppc__) +#    define CARES_SIZEOF_LONG           4 +#  elif defined(__x86_64__) || defined(__ppc64__) +#    define CARES_SIZEOF_LONG           8 +#  endif +#  define CARES_TYPEOF_ARES_SOCKLEN_T socklen_t +#  define CARES_SIZEOF_ARES_SOCKLEN_T 4 +#  define CARES_PULL_SYS_TYPES_H      1 +#  define CARES_PULL_SYS_SOCKET_H     1 + +#else +#  error "Unknown non-configure build target!" +   Error Compilation_aborted_Unknown_non_configure_build_target +#endif + +/* CARES_PULL_SYS_TYPES_H is defined above when inclusion of header file  */ +/* sys/types.h is required here to properly make type definitions below.  */ +#ifdef CARES_PULL_SYS_TYPES_H +#  include <sys/types.h> +#endif + +/* CARES_PULL_SYS_SOCKET_H is defined above when inclusion of header file  */ +/* sys/socket.h is required here to properly make type definitions below.  */ +#ifdef CARES_PULL_SYS_SOCKET_H +#  include <sys/socket.h> +#endif + +/* Data type definition of ares_socklen_t. */ + +#ifdef CARES_TYPEOF_ARES_SOCKLEN_T +  typedef CARES_TYPEOF_ARES_SOCKLEN_T ares_socklen_t; +#endif + +#endif /* __CARES_BUILD_H */ diff --git a/3rdParty/CAres/src/ares_cancel.c b/3rdParty/CAres/src/ares_cancel.c new file mode 100644 index 0000000..9478085 --- /dev/null +++ b/3rdParty/CAres/src/ares_cancel.c @@ -0,0 +1,64 @@ +/* $Id: ares_cancel.c,v 1.12 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright (C) 2004 by Daniel Stenberg et al + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission.  M.I.T. makes no representations about the + * suitability of this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" +#include <assert.h> +#include <stdlib.h> +#include "ares.h" +#include "ares_private.h" + +/* + * ares_cancel() cancels all ongoing requests/resolves that might be going on + * on the given channel. It does NOT kill the channel, use ares_destroy() for + * that. + */ +void ares_cancel(ares_channel channel) +{ +  struct query *query; +  struct list_node* list_head; +  struct list_node* list_node; +  int i; + +  list_head = &(channel->all_queries); +  for (list_node = list_head->next; list_node != list_head; ) +  { +    query = list_node->data; +    list_node = list_node->next;  /* since we're deleting the query */ +    query->callback(query->arg, ARES_ECANCELLED, 0, NULL, 0); +    ares__free_query(query); +  } +#ifndef NDEBUG +  /* Freeing the query should remove it from all the lists in which it sits, +   * so all query lists should be empty now. +   */ +  assert(ares__is_list_empty(&(channel->all_queries))); +  for (i = 0; i < ARES_QID_TABLE_SIZE; i++) +    { +      assert(ares__is_list_empty(&(channel->queries_by_qid[i]))); +    } +  for (i = 0; i < ARES_TIMEOUT_TABLE_SIZE; i++) +    { +      assert(ares__is_list_empty(&(channel->queries_by_timeout[i]))); +    } +#endif +  if (!(channel->flags & ARES_FLAG_STAYOPEN)) +  { +    if (channel->servers) +    { +      for (i = 0; i < channel->nservers; i++) +        ares__close_sockets(channel, &channel->servers[i]); +    } +  } +} diff --git a/3rdParty/CAres/src/ares_config.h b/3rdParty/CAres/src/ares_config.h new file mode 100644 index 0000000..2561090 --- /dev/null +++ b/3rdParty/CAres/src/ares_config.h @@ -0,0 +1,513 @@ +/* ares_config.h.  Generated from ares_config.h.in by configure.  */ +/* ares_config.h.in.  Generated from configure.ac by autoheader.  */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* define this if ares is built for a big endian system */ +/* #undef ARES_BIG_ENDIAN */ + +/* when building as static part of libcurl */ +/* #undef BUILDING_LIBCURL */ + +/* when building c-ares library */ +/* #undef CARES_BUILDING_LIBRARY */ + +/* when not building a shared library */ +/* #undef CARES_STATICLIB */ + +/* Define to 1 to enable hiding of library internal symbols. */ +#define CARES_SYMBOL_HIDING 1 + +/* Definition to make a library symbol externally visible. */ +#define CARES_SYMBOL_SCOPE_EXTERN __attribute__ ((visibility ("default"))) + +/* if a /etc/inet dir is being used */ +/* #undef ETC_INET */ + +/* Define to the type qualifier of arg 1 for getnameinfo. */ +#define GETNAMEINFO_QUAL_ARG1 const + +/* Define to the type of arg 1 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG1 struct sockaddr * + +/* Define to the type of arg 2 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG2 socklen_t + +/* Define to the type of args 4 and 6 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG46 size_t + +/* Define to the type of arg 7 for getnameinfo. */ +#define GETNAMEINFO_TYPE_ARG7 unsigned int + +/* Specifies the number of arguments to getservbyport_r */ +#define GETSERVBYPORT_R_ARGS 6 + +/* Specifies the size of the buffer to pass to getservbyport_r */ +#define GETSERVBYPORT_R_BUFSIZE 4096 + +/* Define to 1 if you have AF_INET6. */ +#define HAVE_AF_INET6 1 + +/* Define to 1 if you have the <arpa/inet.h> header file. */ +#define HAVE_ARPA_INET_H 1 + +/* Define to 1 if you have the <arpa/nameser_compat.h> header file. */ +#define HAVE_ARPA_NAMESER_COMPAT_H 1 + +/* Define to 1 if you have the <arpa/nameser.h> header file. */ +#define HAVE_ARPA_NAMESER_H 1 + +/* Define to 1 if you have the <assert.h> header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `bitncmp' function. */ +/* #undef HAVE_BITNCMP */ + +/* Define to 1 if bool is an available type. */ +#define HAVE_BOOL_T 1 + +/* Define to 1 if you have the clock_gettime function and monotonic timer. */ +#define HAVE_CLOCK_GETTIME_MONOTONIC 1 + +/* Define to 1 if you have the closesocket function. */ +/* #undef HAVE_CLOSESOCKET */ + +/* Define to 1 if you have the CloseSocket camel case function. */ +/* #undef HAVE_CLOSESOCKET_CAMEL */ + +/* Define to 1 if you have the connect function. */ +#define HAVE_CONNECT 1 + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the <errno.h> header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if you have the fcntl function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have the <fcntl.h> header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have a working fcntl O_NONBLOCK function. */ +#define HAVE_FCNTL_O_NONBLOCK 1 + +/* Define to 1 if you have the freeaddrinfo function. */ +#define HAVE_FREEADDRINFO 1 + +/* Define to 1 if you have a working getaddrinfo function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if the getaddrinfo function is threadsafe. */ +#define HAVE_GETADDRINFO_THREADSAFE 1 + +/* Define to 1 if you have the gethostbyaddr function. */ +#define HAVE_GETHOSTBYADDR 1 + +/* Define to 1 if you have the gethostbyname function. */ +#define HAVE_GETHOSTBYNAME 1 + +/* Define to 1 if you have the gethostname function. */ +#define HAVE_GETHOSTNAME 1 + +/* Define to 1 if you have the getnameinfo function. */ +#define HAVE_GETNAMEINFO 1 + +/* Define to 1 if you have the getservbyport_r function. */ +#define HAVE_GETSERVBYPORT_R 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the `if_indextoname' function. */ +#define HAVE_IF_INDEXTONAME 1 + +/* Define to 1 if you have the `inet_net_pton' function. */ +/* #undef HAVE_INET_NET_PTON */ + +/* Define to 1 if inet_net_pton supports IPv6. */ +/* #undef HAVE_INET_NET_PTON_IPV6 */ + +/* Define to 1 if you have a IPv6 capable working inet_ntop function. */ +#define HAVE_INET_NTOP 1 + +/* Define to 1 if you have a IPv6 capable working inet_pton function. */ +#define HAVE_INET_PTON 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the ioctl function. */ +#define HAVE_IOCTL 1 + +/* Define to 1 if you have the ioctlsocket function. */ +/* #undef HAVE_IOCTLSOCKET */ + +/* Define to 1 if you have the IoctlSocket camel case function. */ +/* #undef HAVE_IOCTLSOCKET_CAMEL */ + +/* Define to 1 if you have a working IoctlSocket camel case FIONBIO function. +   */ +/* #undef HAVE_IOCTLSOCKET_CAMEL_FIONBIO */ + +/* Define to 1 if you have a working ioctlsocket FIONBIO function. */ +/* #undef HAVE_IOCTLSOCKET_FIONBIO */ + +/* Define to 1 if you have a working ioctl FIONBIO function. */ +#define HAVE_IOCTL_FIONBIO 1 + +/* Define to 1 if you have a working ioctl SIOCGIFADDR function. */ +#define HAVE_IOCTL_SIOCGIFADDR 1 + +/* Define to 1 if you have the `resolve' library (-lresolve). */ +/* #undef HAVE_LIBRESOLVE */ + +/* Define to 1 if you have the <limits.h> header file. */ +#define HAVE_LIMITS_H 1 + +/* if your compiler supports LL */ +#define HAVE_LL 1 + +/* Define to 1 if the compiler supports the 'long long' data type. */ +#define HAVE_LONGLONG 1 + +/* Define to 1 if you have the malloc.h header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the memory.h header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the MSG_NOSIGNAL flag. */ +#define HAVE_MSG_NOSIGNAL 1 + +/* Define to 1 if you have the <netdb.h> header file. */ +#define HAVE_NETDB_H 1 + +/* Define to 1 if you have the <netinet/in.h> header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the <netinet/tcp.h> header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define to 1 if you have the <net/if.h> header file. */ +#define HAVE_NET_IF_H 1 + +/* Define to 1 if you have PF_INET6. */ +#define HAVE_PF_INET6 1 + +/* Define to 1 if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to 1 if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to 1 if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to 1 if you have the setsockopt function. */ +#define HAVE_SETSOCKOPT 1 + +/* Define to 1 if you have a working setsockopt SO_NONBLOCK function. */ +/* #undef HAVE_SETSOCKOPT_SO_NONBLOCK */ + +/* Define to 1 if you have the <signal.h> header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if sig_atomic_t is already defined as volatile. */ +/* #undef HAVE_SIG_ATOMIC_T_VOLATILE */ + +/* Define to 1 if your struct sockaddr_in6 has sin6_scope_id. */ +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 + +/* Define to 1 if you have the socket function. */ +#define HAVE_SOCKET 1 + +/* Define to 1 if you have the <socket.h> header file. */ +/* #undef HAVE_SOCKET_H */ + +/* Define to 1 if you have the <stdbool.h> header file. */ +#define HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the strcasecmp function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the strcmpi function. */ +/* #undef HAVE_STRCMPI */ + +/* Define to 1 if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the stricmp function. */ +/* #undef HAVE_STRICMP */ + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the strncasecmp function. */ +#define HAVE_STRNCASECMP 1 + +/* Define to 1 if you have the strncmpi function. */ +/* #undef HAVE_STRNCMPI */ + +/* Define to 1 if you have the strnicmp function. */ +/* #undef HAVE_STRNICMP */ + +/* Define to 1 if you have the <stropts.h> header file. */ +#define HAVE_STROPTS_H 1 + +/* Define to 1 if you have struct addrinfo. */ +#define HAVE_STRUCT_ADDRINFO 1 + +/* Define to 1 if you have struct in6_addr. */ +#define HAVE_STRUCT_IN6_ADDR 1 + +/* Define to 1 if you have struct sockaddr_in6. */ +#define HAVE_STRUCT_SOCKADDR_IN6 1 + +/* if struct sockaddr_storage is defined */ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if you have the timeval struct. */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* Define to 1 if you have the <sys/ioctl.h> header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the <sys/param.h> header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the <sys/select.h> header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the <sys/socket.h> header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/time.h> header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the <sys/uio.h> header file. */ +#define HAVE_SYS_UIO_H 1 + +/* Define to 1 if you have the <time.h> header file. */ +#define HAVE_TIME_H 1 + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the windows.h header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* Define to 1 if you have the winsock2.h header file. */ +/* #undef HAVE_WINSOCK2_H */ + +/* Define to 1 if you have the winsock.h header file. */ +/* #undef HAVE_WINSOCK_H */ + +/* Define to 1 if you have the writev function. */ +#define HAVE_WRITEV 1 + +/* Define to 1 if you have the ws2tcpip.h header file. */ +/* #undef HAVE_WS2TCPIP_H */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. +   */ +#define LT_OBJDIR ".libs/" + +/* Define to 1 if you are building a native Windows target. */ +/* #undef NATIVE_WINDOWS */ + +/* Define to 1 if you need the malloc.h header file even with stdlib.h */ +/* #undef NEED_MALLOC_H */ + +/* Define to 1 if you need the memory.h header file even with stdlib.h */ +/* #undef NEED_MEMORY_H */ + +/* Define to 1 if _REENTRANT preprocessor symbol must be defined. */ +/* #undef NEED_REENTRANT */ + +/* Define to 1 if _THREAD_SAFE preprocessor symbol must be defined. */ +/* #undef NEED_THREAD_SAFE */ + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +/* #undef NO_MINUS_C_MINUS_O */ + +/* cpu-machine-OS */ +#define OS "i686-pc-linux-gnu" + +/* Name of package */ +#define PACKAGE "c-ares" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "c-ares mailing list => http://cool.haxx.se/mailman/listinfo/c-ares" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "c-ares" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "c-ares 1.7.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "c-ares" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.7.0" + +/* a suitable file/device to read random data from */ +#define RANDOM_FILE "/dev/urandom" + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 int + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 void + +/* Define to 1 if the type pointed by arg 2 for recvfrom is void. */ +#define RECVFROM_TYPE_ARG2_IS_VOID 1 + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to 1 if the type pointed by arg 5 for recvfrom is void. */ +/* #undef RECVFROM_TYPE_ARG5_IS_VOID */ + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 socklen_t + +/* Define to 1 if the type pointed by arg 6 for recvfrom is void. */ +/* #undef RECVFROM_TYPE_ARG6_IS_VOID */ + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV int + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 int + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 void * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 int + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 void * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 size_t + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +/* The size of `int', as computed by sizeof. */ +#define SIZEOF_INT 4 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 4 + +/* The size of `struct in6_addr', as computed by sizeof. */ +#define SIZEOF_STRUCT_IN6_ADDR 16 + +/* The size of `struct in_addr', as computed by sizeof. */ +#define SIZEOF_STRUCT_IN_ADDR 4 + +/* The size of `time_t', as computed by sizeof. */ +#define SIZEOF_TIME_T 4 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to disable non-blocking sockets. */ +/* #undef USE_BLOCKING_SOCKETS */ + +/* Version number of package */ +#define VERSION "1.7.0" + +/* Define to avoid automatic inclusion of winsock.h */ +/* #undef WIN32_LEAN_AND_MEAN */ + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most +   significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +#  define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* #  undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Define to 1 if OS is AIX. */ +#ifndef _ALL_SOURCE +/* #  undef _ALL_SOURCE */ +#endif + +/* Number of bits in a file offset, on hosts where this is settable. */ +#define _FILE_OFFSET_BITS 64 + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Type to use in place of in_addr_t when system does not provide it. */ +/* #undef in_addr_t */ + +/* Define to `unsigned int' if <sys/types.h> does not define. */ +/* #undef size_t */ + +/* the signed version of size_t */ +/* #undef ssize_t */ diff --git a/3rdParty/CAres/src/ares_data.c b/3rdParty/CAres/src/ares_data.c new file mode 100644 index 0000000..1ad66a6 --- /dev/null +++ b/3rdParty/CAres/src/ares_data.c @@ -0,0 +1,143 @@ +/* $Id: ares_data.c,v 1.2 2009-11-20 09:06:33 yangtse Exp $ */ + +/* Copyright (C) 2009 by Daniel Stenberg + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + + +#include "ares_setup.h" + +#include <stddef.h> + +#include "ares.h" +#include "ares_data.h" +#include "ares_private.h" + + +/* +** ares_free_data() - c-ares external API function. +** +** This function must be used by the application to free data memory that +** has been internally allocated by some c-ares function and for which a +** pointer has already been returned to the calling application. The list +** of c-ares functions returning pointers that must be free'ed using this +** function is: +** +**   ares_parse_srv_reply() +**   ares_parse_txt_reply() +*/ + +void ares_free_data(void *dataptr) +{ +  struct ares_data *ptr; + +  if (!dataptr) +    return; + +  ptr = (void *)((char *)dataptr - offsetof(struct ares_data, data)); + +  if (ptr->mark != ARES_DATATYPE_MARK) +    return; + +  switch (ptr->type) +    { +      case ARES_DATATYPE_SRV_REPLY: + +        if (ptr->data.srv_reply.next) +          ares_free_data(ptr->data.srv_reply.next); +        if (ptr->data.srv_reply.host) +          free(ptr->data.srv_reply.host); +        break; + +      case ARES_DATATYPE_TXT_REPLY: + +        if (ptr->data.txt_reply.next) +          ares_free_data(ptr->data.txt_reply.next); +        if (ptr->data.txt_reply.txt) +          free(ptr->data.txt_reply.txt); +        break; + +      default: +        return; +    } + +  free(ptr); +} + + +/* +** ares_malloc_data() - c-ares internal helper function. +** +** This function allocates memory for a c-ares private ares_data struct +** for the specified ares_datatype, initializes c-ares private fields +** and zero initializes those which later might be used from the public +** API. It returns an interior pointer which can be passed by c-ares +** functions to the calling application, and that must be free'ed using +** c-ares external API function ares_free_data(). +*/ + +void *ares_malloc_data(ares_datatype type) +{ +  struct ares_data *ptr; + +  ptr = malloc(sizeof(struct ares_data)); +  if (!ptr) +    return NULL; + +  switch (type) +    { +      case ARES_DATATYPE_SRV_REPLY: +        ptr->data.srv_reply.next = NULL; +        ptr->data.srv_reply.host = NULL; +        ptr->data.srv_reply.priority = 0; +        ptr->data.srv_reply.weight = 0; +        ptr->data.srv_reply.port = 0; +        break; + +      case ARES_DATATYPE_TXT_REPLY: +        ptr->data.txt_reply.next = NULL; +        ptr->data.txt_reply.txt = NULL; +        ptr->data.txt_reply.length  = 0; +        break; + +      default: +        free(ptr); +        return NULL; +    } + +  ptr->mark = ARES_DATATYPE_MARK; +  ptr->type = type; + +  return &ptr->data; +} + + +/* +** ares_get_datatype() - c-ares internal helper function. +** +** This function returns the ares_datatype of the data stored in a +** private ares_data struct when given the public API pointer. +*/ + +ares_datatype ares_get_datatype(void * dataptr) +{ +  struct ares_data *ptr; + +  ptr = (void *)((char *)dataptr - offsetof(struct ares_data, data)); + +  if (ptr->mark == ARES_DATATYPE_MARK) +    return ptr->type; + +  return ARES_DATATYPE_UNKNOWN; +} diff --git a/3rdParty/CAres/src/ares_data.h b/3rdParty/CAres/src/ares_data.h new file mode 100644 index 0000000..18794e3 --- /dev/null +++ b/3rdParty/CAres/src/ares_data.h @@ -0,0 +1,62 @@ +/* $Id: ares_data.h,v 1.2 2009-11-23 12:03:33 yangtse Exp $ */ + +/* Copyright (C) 2009 by Daniel Stenberg + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +typedef enum { +  ARES_DATATYPE_UNKNOWN = 1,  /* unknown data type     - introduced in 1.7.0 */ +  ARES_DATATYPE_SRV_REPLY,    /* struct ares_srv_reply - introduced in 1.7.0 */ +  ARES_DATATYPE_TXT_REPLY,    /* struct ares_txt_reply - introduced in 1.7.0 */ +#if 0 +  ARES_DATATYPE_ADDR6TTL,     /* struct ares_addrttl   */ +  ARES_DATATYPE_ADDRTTL,      /* struct ares_addr6ttl  */ +  ARES_DATATYPE_HOSTENT,      /* struct hostent        */ +  ARES_DATATYPE_OPTIONS,      /* struct ares_options   */ +#endif +  ARES_DATATYPE_LAST          /* not used              - introduced in 1.7.0 */ +} ares_datatype; + +#define ARES_DATATYPE_MARK 0xbead + +/* + * ares_data struct definition is internal to c-ares and shall not + * be exposed by the public API in order to allow future changes + * and extensions to it without breaking ABI.  This will be used + * internally by c-ares as the container of multiple types of data + * dynamically allocated for which a reference will be returned + * to the calling application. + * + * c-ares API functions returning a pointer to c-ares internally + * allocated data will actually be returning an interior pointer + * into this ares_data struct. + * + * All this is 'invisible' to the calling application, the only + * requirement is that this kind of data must be free'ed by the + * calling application using ares_free_data() with the pointer + * it has received from a previous c-ares function call. + */ + +struct ares_data { +  ares_datatype type;  /* Actual data type identifier. */ +  unsigned int  mark;  /* Private ares_data signature. */ +  union { +    struct ares_txt_reply txt_reply; +    struct ares_srv_reply srv_reply; +  } data; +}; + +void *ares_malloc_data(ares_datatype type); + +ares_datatype ares_get_datatype(void * dataptr); diff --git a/3rdParty/CAres/src/ares_destroy.c b/3rdParty/CAres/src/ares_destroy.c new file mode 100644 index 0000000..0044a71 --- /dev/null +++ b/3rdParty/CAres/src/ares_destroy.c @@ -0,0 +1,93 @@ +/* $Id: ares_destroy.c,v 1.14 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" +#include <assert.h> +#include <stdlib.h> +#include "ares.h" +#include "ares_private.h" + +void ares_destroy_options(struct ares_options *options) +{ +  int i; + +  free(options->servers); +  for (i = 0; i < options->ndomains; i++) +    free(options->domains[i]); +  free(options->domains); +  if(options->sortlist) +    free(options->sortlist); +  free(options->lookups); +} + +void ares_destroy(ares_channel channel) +{ +  int i; +  struct query *query; +  struct list_node* list_head; +  struct list_node* list_node; +   +  if (!channel) +    return; + +  list_head = &(channel->all_queries); +  for (list_node = list_head->next; list_node != list_head; ) +    { +      query = list_node->data; +      list_node = list_node->next;  /* since we're deleting the query */ +      query->callback(query->arg, ARES_EDESTRUCTION, 0, NULL, 0); +      ares__free_query(query); +    } +#ifndef NDEBUG +  /* Freeing the query should remove it from all the lists in which it sits, +   * so all query lists should be empty now. +   */ +  assert(ares__is_list_empty(&(channel->all_queries))); +  for (i = 0; i < ARES_QID_TABLE_SIZE; i++) +    { +      assert(ares__is_list_empty(&(channel->queries_by_qid[i]))); +    } +  for (i = 0; i < ARES_TIMEOUT_TABLE_SIZE; i++) +    { +      assert(ares__is_list_empty(&(channel->queries_by_timeout[i]))); +    } +#endif + +  if (channel->servers) { +    for (i = 0; i < channel->nservers; i++) +      { +        struct server_state *server = &channel->servers[i]; +        ares__close_sockets(channel, server); +        assert(ares__is_list_empty(&(server->queries_to_server))); +      } +    free(channel->servers); +  } + +  if (channel->domains) { +    for (i = 0; i < channel->ndomains; i++) +      free(channel->domains[i]); +    free(channel->domains); +  } + +  if(channel->sortlist) +    free(channel->sortlist); + +  if (channel->lookups) +    free(channel->lookups); + +  free(channel); +} diff --git a/3rdParty/CAres/src/ares_dns.h b/3rdParty/CAres/src/ares_dns.h new file mode 100644 index 0000000..c0a9dda --- /dev/null +++ b/3rdParty/CAres/src/ares_dns.h @@ -0,0 +1,91 @@ +/* $Id: ares_dns.h,v 1.8 2007-02-16 14:22:08 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#ifndef ARES__DNS_H +#define ARES__DNS_H + +#define DNS__16BIT(p)                   (((p)[0] << 8) | (p)[1]) +#define DNS__32BIT(p)                   (((p)[0] << 24) | ((p)[1] << 16) | \ +                                         ((p)[2] << 8) | (p)[3]) + +#define DNS__SET16BIT(p, v)  (((p)[0] = (unsigned char)(((v) >> 8) & 0xff)), \ +                              ((p)[1] = (unsigned char)((v) & 0xff))) +#define DNS__SET32BIT(p, v)  (((p)[0] = (unsigned char)(((v) >> 24) & 0xff)), \ +                              ((p)[1] = (unsigned char)(((v) >> 16) & 0xff)), \ +                              ((p)[2] = (unsigned char)(((v) >> 8) & 0xff)), \ +                              ((p)[3] = (unsigned char)((v) & 0xff))) + +#if 0 +/* we cannot use this approach on systems where we can't access 16/32 bit +   data on un-aligned addresses */ +#define DNS__16BIT(p)                   ntohs(*(unsigned short*)(p)) +#define DNS__32BIT(p)                   ntohl(*(unsigned long*)(p)) +#define DNS__SET16BIT(p, v)             *(unsigned short*)(p) = htons(v) +#define DNS__SET32BIT(p, v)             *(unsigned long*)(p) = htonl(v) +#endif + +/* Macros for parsing a DNS header */ +#define DNS_HEADER_QID(h)               DNS__16BIT(h) +#define DNS_HEADER_QR(h)                (((h)[2] >> 7) & 0x1) +#define DNS_HEADER_OPCODE(h)            (((h)[2] >> 3) & 0xf) +#define DNS_HEADER_AA(h)                (((h)[2] >> 2) & 0x1) +#define DNS_HEADER_TC(h)                (((h)[2] >> 1) & 0x1) +#define DNS_HEADER_RD(h)                ((h)[2] & 0x1) +#define DNS_HEADER_RA(h)                (((h)[3] >> 7) & 0x1) +#define DNS_HEADER_Z(h)                 (((h)[3] >> 4) & 0x7) +#define DNS_HEADER_RCODE(h)             ((h)[3] & 0xf) +#define DNS_HEADER_QDCOUNT(h)           DNS__16BIT((h) + 4) +#define DNS_HEADER_ANCOUNT(h)           DNS__16BIT((h) + 6) +#define DNS_HEADER_NSCOUNT(h)           DNS__16BIT((h) + 8) +#define DNS_HEADER_ARCOUNT(h)           DNS__16BIT((h) + 10) + +/* Macros for constructing a DNS header */ +#define DNS_HEADER_SET_QID(h, v)      DNS__SET16BIT(h, v) +#define DNS_HEADER_SET_QR(h, v)       ((h)[2] |= (unsigned char)(((v) & 0x1) << 7)) +#define DNS_HEADER_SET_OPCODE(h, v)   ((h)[2] |= (unsigned char)(((v) & 0xf) << 3)) +#define DNS_HEADER_SET_AA(h, v)       ((h)[2] |= (unsigned char)(((v) & 0x1) << 2)) +#define DNS_HEADER_SET_TC(h, v)       ((h)[2] |= (unsigned char)(((v) & 0x1) << 1)) +#define DNS_HEADER_SET_RD(h, v)       ((h)[2] |= (unsigned char)((v) & 0x1)) +#define DNS_HEADER_SET_RA(h, v)       ((h)[3] |= (unsigned char)(((v) & 0x1) << 7)) +#define DNS_HEADER_SET_Z(h, v)        ((h)[3] |= (unsigned char)(((v) & 0x7) << 4)) +#define DNS_HEADER_SET_RCODE(h, v)    ((h)[3] |= (unsigned char)((v) & 0xf)) +#define DNS_HEADER_SET_QDCOUNT(h, v)  DNS__SET16BIT((h) + 4, v) +#define DNS_HEADER_SET_ANCOUNT(h, v)  DNS__SET16BIT((h) + 6, v) +#define DNS_HEADER_SET_NSCOUNT(h, v)  DNS__SET16BIT((h) + 8, v) +#define DNS_HEADER_SET_ARCOUNT(h, v)  DNS__SET16BIT((h) + 10, v) + +/* Macros for parsing the fixed part of a DNS question */ +#define DNS_QUESTION_TYPE(q)            DNS__16BIT(q) +#define DNS_QUESTION_CLASS(q)           DNS__16BIT((q) + 2) + +/* Macros for constructing the fixed part of a DNS question */ +#define DNS_QUESTION_SET_TYPE(q, v)     DNS__SET16BIT(q, v) +#define DNS_QUESTION_SET_CLASS(q, v)    DNS__SET16BIT((q) + 2, v) + +/* Macros for parsing the fixed part of a DNS resource record */ +#define DNS_RR_TYPE(r)                  DNS__16BIT(r) +#define DNS_RR_CLASS(r)                 DNS__16BIT((r) + 2) +#define DNS_RR_TTL(r)                   DNS__32BIT((r) + 4) +#define DNS_RR_LEN(r)                   DNS__16BIT((r) + 8) + +/* Macros for constructing the fixed part of a DNS resource record */ +#define DNS_RR_SET_TYPE(r)              DNS__SET16BIT(r, v) +#define DNS_RR_SET_CLASS(r)             DNS__SET16BIT((r) + 2, v) +#define DNS_RR_SET_TTL(r)               DNS__SET32BIT((r) + 4, v) +#define DNS_RR_SET_LEN(r)               DNS__SET16BIT((r) + 8, v) + +#endif /* ARES__DNS_H */ diff --git a/3rdParty/CAres/src/ares_expand_name.c b/3rdParty/CAres/src/ares_expand_name.c new file mode 100644 index 0000000..75e88e8 --- /dev/null +++ b/3rdParty/CAres/src/ares_expand_name.c @@ -0,0 +1,190 @@ +/* $Id: ares_expand_name.c,v 1.20 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_SYS_SOCKET_H +#  include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#  include <netinet/in.h> +#endif +#ifdef HAVE_ARPA_NAMESER_H +#  include <arpa/nameser.h> +#else +#  include "nameser.h" +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +#  include <arpa/nameser_compat.h> +#endif + +#include <stdlib.h> +#include "ares.h" +#include "ares_private.h" /* for the memdebug */ + +static int name_length(const unsigned char *encoded, const unsigned char *abuf, +                       int alen); + +/* Expand an RFC1035-encoded domain name given by encoded.  The + * containing message is given by abuf and alen.  The result given by + * *s, which is set to a NUL-terminated allocated buffer.  *enclen is + * set to the length of the encoded name (not the length of the + * expanded name; the goal is to tell the caller how many bytes to + * move forward to get past the encoded name). + * + * In the simple case, an encoded name is a series of labels, each + * composed of a one-byte length (limited to values between 0 and 63 + * inclusive) followed by the label contents.  The name is terminated + * by a zero-length label. + * + * In the more complicated case, a label may be terminated by an + * indirection pointer, specified by two bytes with the high bits of + * the first byte (corresponding to INDIR_MASK) set to 11.  With the + * two high bits of the first byte stripped off, the indirection + * pointer gives an offset from the beginning of the containing + * message with more labels to decode.  Indirection can happen an + * arbitrary number of times, so we have to detect loops. + * + * Since the expanded name uses '.' as a label separator, we use + * backslashes to escape periods or backslashes in the expanded name. + */ + +int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf, +                     int alen, char **s, long *enclen) +{ +  int len, indir = 0; +  char *q; +  const unsigned char *p; + +  len = name_length(encoded, abuf, alen); +  if (len < 0) +    return ARES_EBADNAME; + +  *s = malloc(((size_t)len) + 1); +  if (!*s) +    return ARES_ENOMEM; +  q = *s; + +  if (len == 0) { +    /* RFC2181 says this should be ".": the root of the DNS tree. +     * Since this function strips trailing dots though, it becomes "" +     */ +    q[0] = '\0'; +    *enclen = 1;  /* the caller should move one byte to get past this */ +    return ARES_SUCCESS; +  } + +  /* No error-checking necessary; it was all done by name_length(). */ +  p = encoded; +  while (*p) +    { +      if ((*p & INDIR_MASK) == INDIR_MASK) +        { +          if (!indir) +            { +              *enclen = p + 2 - encoded; +              indir = 1; +            } +          p = abuf + ((*p & ~INDIR_MASK) << 8 | *(p + 1)); +        } +      else +        { +          len = *p; +          p++; +          while (len--) +            { +              if (*p == '.' || *p == '\\') +                *q++ = '\\'; +              *q++ = *p; +              p++; +            } +          *q++ = '.'; +        } +    } +  if (!indir) +    *enclen = p + 1 - encoded; + +  /* Nuke the trailing period if we wrote one. */ +  if (q > *s) +    *(q - 1) = 0; +  else +    *q = 0; /* zero terminate */ + +  return ARES_SUCCESS; +} + +/* Return the length of the expansion of an encoded domain name, or + * -1 if the encoding is invalid. + */ +static int name_length(const unsigned char *encoded, const unsigned char *abuf, +                       int alen) +{ +  int n = 0, offset, indir = 0; + +  /* Allow the caller to pass us abuf + alen and have us check for it. */ +  if (encoded == abuf + alen) +    return -1; + +  while (*encoded) +    { +      if ((*encoded & INDIR_MASK) == INDIR_MASK) +        { +          /* Check the offset and go there. */ +          if (encoded + 1 >= abuf + alen) +            return -1; +          offset = (*encoded & ~INDIR_MASK) << 8 | *(encoded + 1); +          if (offset >= alen) +            return -1; +          encoded = abuf + offset; + +          /* If we've seen more indirects than the message length, +           * then there's a loop. +           */ +          if (++indir > alen) +            return -1; +        } +      else +        { +          offset = *encoded; +          if (encoded + offset + 1 >= abuf + alen) +            return -1; +          encoded++; +          while (offset--) +            { +              n += (*encoded == '.' || *encoded == '\\') ? 2 : 1; +              encoded++; +            } +          n++; +        } +    } + +  /* If there were any labels at all, then the number of dots is one +   * less than the number of labels, so subtract one. +   */ +  return (n) ? n - 1 : n; +} + +/* Like ares_expand_name but returns EBADRESP in case of invalid input. */ +int ares__expand_name_for_response(const unsigned char *encoded, +                                   const unsigned char *abuf, int alen, +                                   char **s, long *enclen) +{ +  int status = ares_expand_name(encoded, abuf, alen, s, enclen); +  if (status == ARES_EBADNAME) +    status = ARES_EBADRESP; +  return status; +} diff --git a/3rdParty/CAres/src/ares_expand_string.c b/3rdParty/CAres/src/ares_expand_string.c new file mode 100644 index 0000000..c72bb62 --- /dev/null +++ b/3rdParty/CAres/src/ares_expand_string.c @@ -0,0 +1,72 @@ +/* $Id: ares_expand_string.c,v 1.10 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_SYS_SOCKET_H +#  include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#  include <netinet/in.h> +#endif +#ifdef HAVE_ARPA_NAMESER_H +#  include <arpa/nameser.h> +#else +#  include "nameser.h" +#endif + +#include <string.h> +#include <stdlib.h> +#include "ares.h" +#include "ares_private.h" /* for the memdebug */ + +/* Simply decodes a length-encoded character string. The first byte of the + * input is the length of the string to be returned and the bytes thereafter + * are the characters of the string. The returned result will be NULL + * terminated. + */ +int ares_expand_string(const unsigned char *encoded, +                       const unsigned char *abuf, +                       int alen, +                       unsigned char **s, +                       long *enclen) +{ +  unsigned char *q; +  long len; +  if (encoded == abuf+alen) +    return ARES_EBADSTR; + +  len = *encoded; +  if (encoded+len+1 > abuf+alen) +    return ARES_EBADSTR; + +  encoded++; + +  *s = malloc(len+1); +  if (*s == NULL) +    return ARES_ENOMEM; +  q = *s; +  strncpy((char *)q, (char *)encoded, len); +  q[len] = '\0'; + +  *s = q; + +  *enclen = len+1; + +  return ARES_SUCCESS; +} + diff --git a/3rdParty/CAres/src/ares_fds.c b/3rdParty/CAres/src/ares_fds.c new file mode 100644 index 0000000..6ffe9c7 --- /dev/null +++ b/3rdParty/CAres/src/ares_fds.c @@ -0,0 +1,63 @@ +/* $Id: ares_fds.c,v 1.12 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +#include "ares.h" +#include "ares_private.h" + +int ares_fds(ares_channel channel, fd_set *read_fds, fd_set *write_fds) +{ +  struct server_state *server; +  ares_socket_t nfds; +  int i; + +  /* Are there any active queries? */ +  int active_queries = !ares__is_list_empty(&(channel->all_queries)); + +  nfds = 0; +  for (i = 0; i < channel->nservers; i++) +    { +      server = &channel->servers[i]; +      /* We only need to register interest in UDP sockets if we have +       * outstanding queries. +       */ +      if (active_queries && server->udp_socket != ARES_SOCKET_BAD) +        { +          FD_SET(server->udp_socket, read_fds); +          if (server->udp_socket >= nfds) +            nfds = server->udp_socket + 1; +        } +      /* We always register for TCP events, because we want to know +       * when the other side closes the connection, so we don't waste +       * time trying to use a broken connection. +       */ +      if (server->tcp_socket != ARES_SOCKET_BAD) +       { +         FD_SET(server->tcp_socket, read_fds); +         if (server->qhead) +           FD_SET(server->tcp_socket, write_fds); +         if (server->tcp_socket >= nfds) +           nfds = server->tcp_socket + 1; +	} +    } +  return (int)nfds; +} diff --git a/3rdParty/CAres/src/ares_free_hostent.c b/3rdParty/CAres/src/ares_free_hostent.c new file mode 100644 index 0000000..c0794ee --- /dev/null +++ b/3rdParty/CAres/src/ares_free_hostent.c @@ -0,0 +1,40 @@ +/* $Id: ares_free_hostent.c,v 1.12 2009-11-09 12:56:50 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" +#include <stdlib.h> + +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif + +#include "ares.h" +#include "ares_private.h" /* for memdebug */ + +void ares_free_hostent(struct hostent *host) +{ +  char **p; + +  free((char *)(host->h_name)); +  for (p = host->h_aliases; *p; p++) +    free(*p); +  free(host->h_aliases); +  free(host->h_addr_list[0]); /* no matter if there is one or many entries, +                                 there is only one malloc for all of them */ +  free(host->h_addr_list); +  free(host); +} diff --git a/3rdParty/CAres/src/ares_free_string.c b/3rdParty/CAres/src/ares_free_string.c new file mode 100644 index 0000000..38f98f9 --- /dev/null +++ b/3rdParty/CAres/src/ares_free_string.c @@ -0,0 +1,26 @@ +/* $Id: ares_free_string.c,v 1.7 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 2000 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" +#include <stdlib.h> +#include "ares.h" +#include "ares_private.h" + +void ares_free_string(void *str) +{ +  free(str); +} diff --git a/3rdParty/CAres/src/ares_gethostbyaddr.c b/3rdParty/CAres/src/ares_gethostbyaddr.c new file mode 100644 index 0000000..732a031 --- /dev/null +++ b/3rdParty/CAres/src/ares_gethostbyaddr.c @@ -0,0 +1,291 @@ +/* $Id: ares_gethostbyaddr.c,v 1.35 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ +#include "ares_setup.h" + +#ifdef HAVE_SYS_SOCKET_H +#  include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#  include <netinet/in.h> +#endif +#ifdef HAVE_NETDB_H +#  include <netdb.h> +#endif +#ifdef HAVE_ARPA_INET_H +#  include <arpa/inet.h> +#endif +#ifdef HAVE_ARPA_NAMESER_H +#  include <arpa/nameser.h> +#else +#  include "nameser.h" +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +#  include <arpa/nameser_compat.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "ares.h" +#include "inet_net_pton.h" +#include "ares_private.h" + +#ifdef WATT32 +#undef WIN32 +#endif + +struct addr_query { +  /* Arguments passed to ares_gethostbyaddr() */ +  ares_channel channel; +  struct ares_addr addr; +  ares_host_callback callback; +  void *arg; + +  const char *remaining_lookups; +  int timeouts; +}; + +static void next_lookup(struct addr_query *aquery); +static void addr_callback(void *arg, int status, int timeouts, +                          unsigned char *abuf, int alen); +static void end_aquery(struct addr_query *aquery, int status, +                       struct hostent *host); +static int file_lookup(struct ares_addr *addr, struct hostent **host); +static void ptr_rr_name(char *name, const struct ares_addr *addr); + +void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen, +                        int family, ares_host_callback callback, void *arg) +{ +  struct addr_query *aquery; + +  if (family != AF_INET && family != AF_INET6) +    { +      callback(arg, ARES_ENOTIMP, 0, NULL); +      return; +    } + +  if ((family == AF_INET && addrlen != sizeof(struct in_addr)) || +      (family == AF_INET6 && addrlen != sizeof(struct in6_addr))) +    { +      callback(arg, ARES_ENOTIMP, 0, NULL); +      return; +    } + +  aquery = malloc(sizeof(struct addr_query)); +  if (!aquery) +    { +      callback(arg, ARES_ENOMEM, 0, NULL); +      return; +    } +  aquery->channel = channel; +  if (family == AF_INET) +    memcpy(&aquery->addr.addrV4, addr, sizeof(struct in_addr)); +  else +    memcpy(&aquery->addr.addrV6, addr, sizeof(struct in6_addr)); +  aquery->addr.family = family; +  aquery->callback = callback; +  aquery->arg = arg; +  aquery->remaining_lookups = channel->lookups; +  aquery->timeouts = 0; + +  next_lookup(aquery); +} + +static void next_lookup(struct addr_query *aquery) +{ +  const char *p; +  char name[128]; +  int status; +  struct hostent *host; + +  for (p = aquery->remaining_lookups; *p; p++) +    { +      switch (*p) +        { +        case 'b': +          ptr_rr_name(name, &aquery->addr); +          aquery->remaining_lookups = p + 1; +          ares_query(aquery->channel, name, C_IN, T_PTR, addr_callback, +                     aquery); +          return; +        case 'f': +          status = file_lookup(&aquery->addr, &host); + +          /* this status check below previously checked for !ARES_ENOTFOUND, +             but we should not assume that this single error code is the one +             that can occur, as that is in fact no longer the case */ +          if (status == ARES_SUCCESS) +            { +              end_aquery(aquery, status, host); +              return; +            } +          break; +        } +    } +  end_aquery(aquery, ARES_ENOTFOUND, NULL); +} + +static void addr_callback(void *arg, int status, int timeouts, +                          unsigned char *abuf, int alen) +{ +  struct addr_query *aquery = (struct addr_query *) arg; +  struct hostent *host; +  size_t addrlen; + +  aquery->timeouts += timeouts; +  if (status == ARES_SUCCESS) +    { +      if (aquery->addr.family == AF_INET) +        { +          addrlen = sizeof(struct in_addr); +          status = ares_parse_ptr_reply(abuf, alen, &aquery->addr.addrV4, +                                        (int)addrlen, AF_INET, &host); +        } +      else +        { +          addrlen = sizeof(struct in6_addr); +          status = ares_parse_ptr_reply(abuf, alen, &aquery->addr.addrV6, +                                        (int)addrlen, AF_INET6, &host); +        } +      end_aquery(aquery, status, host); +    } +  else if (status == ARES_EDESTRUCTION) +    end_aquery(aquery, status, NULL); +  else +    next_lookup(aquery); +} + +static void end_aquery(struct addr_query *aquery, int status, +                       struct hostent *host) +{ +  aquery->callback(aquery->arg, status, aquery->timeouts, host); +  if (host) +    ares_free_hostent(host); +  free(aquery); +} + +static int file_lookup(struct ares_addr *addr, struct hostent **host) +{ +  FILE *fp; +  int status; +  int error; + +#ifdef WIN32 +  char PATH_HOSTS[MAX_PATH]; +  if (IS_NT()) { +    char tmp[MAX_PATH]; +    HKEY hkeyHosts; + +    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, KEY_READ, &hkeyHosts) +        == ERROR_SUCCESS) +    { +      DWORD dwLength = MAX_PATH; +      RegQueryValueEx(hkeyHosts, DATABASEPATH, NULL, NULL, (LPBYTE)tmp, +                      &dwLength); +      ExpandEnvironmentStrings(tmp, PATH_HOSTS, MAX_PATH); +      RegCloseKey(hkeyHosts); +    } +  } +  else +    GetWindowsDirectory(PATH_HOSTS, MAX_PATH); + +  strcat(PATH_HOSTS, WIN_PATH_HOSTS); + +#elif defined(WATT32) +  extern const char *_w32_GetHostsFile (void); +  const char *PATH_HOSTS = _w32_GetHostsFile(); + +  if (!PATH_HOSTS) +    return ARES_ENOTFOUND; +#endif + +  fp = fopen(PATH_HOSTS, "r"); +  if (!fp) +    { +      error = ERRNO; +      switch(error) +        { +        case ENOENT: +        case ESRCH: +          return ARES_ENOTFOUND; +        default: +          DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", +                         error, strerror(error))); +          DEBUGF(fprintf(stderr, "Error opening file: %s\n", +                         PATH_HOSTS)); +          *host = NULL; +          return ARES_EFILE; +        } +    } +  while ((status = ares__get_hostent(fp, addr->family, host)) == ARES_SUCCESS) +    { +      if (addr->family != (*host)->h_addrtype) +        { +          ares_free_hostent(*host); +          continue; +        } +      if (addr->family == AF_INET) +        { +          if (memcmp((*host)->h_addr, &addr->addrV4, sizeof(struct in_addr)) == 0) +            break; +        } +      else if (addr->family == AF_INET6) +        { +          if (memcmp((*host)->h_addr, &addr->addrV6, sizeof(struct in6_addr)) == 0) +            break; +        } +      ares_free_hostent(*host); +    } +  fclose(fp); +  if (status == ARES_EOF) +    status = ARES_ENOTFOUND; +  if (status != ARES_SUCCESS) +    *host = NULL; +  return status; +} + +static void ptr_rr_name(char *name, const struct ares_addr *addr) +{ +  if (addr->family == AF_INET) +    { +       unsigned long laddr = ntohl(addr->addrV4.s_addr); +       int a1 = (int)((laddr >> 24) & 0xff); +       int a2 = (int)((laddr >> 16) & 0xff); +       int a3 = (int)((laddr >> 8) & 0xff); +       int a4 = (int)(laddr & 0xff); +       sprintf(name, "%d.%d.%d.%d.in-addr.arpa", a4, a3, a2, a1); +    } +  else +    { +       unsigned char *bytes = (unsigned char *)&addr->addrV6.s6_addr; +       /* There are too many arguments to do this in one line using +        * minimally C89-compliant compilers */ +       sprintf(name, +                "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.", +                bytes[15]&0xf, bytes[15] >> 4, bytes[14]&0xf, bytes[14] >> 4, +                bytes[13]&0xf, bytes[13] >> 4, bytes[12]&0xf, bytes[12] >> 4, +                bytes[11]&0xf, bytes[11] >> 4, bytes[10]&0xf, bytes[10] >> 4, +                bytes[9]&0xf, bytes[9] >> 4, bytes[8]&0xf, bytes[8] >> 4); +       sprintf(name+strlen(name), +                "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa", +                bytes[7]&0xf, bytes[7] >> 4, bytes[6]&0xf, bytes[6] >> 4, +                bytes[5]&0xf, bytes[5] >> 4, bytes[4]&0xf, bytes[4] >> 4, +                bytes[3]&0xf, bytes[3] >> 4, bytes[2]&0xf, bytes[2] >> 4, +                bytes[1]&0xf, bytes[1] >> 4, bytes[0]&0xf, bytes[0] >> 4); +    } +} diff --git a/3rdParty/CAres/src/ares_gethostbyname.c b/3rdParty/CAres/src/ares_gethostbyname.c new file mode 100644 index 0000000..fc66c6f --- /dev/null +++ b/3rdParty/CAres/src/ares_gethostbyname.c @@ -0,0 +1,511 @@ +/* $Id: ares_gethostbyname.c,v 1.50 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_SYS_SOCKET_H +#  include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#  include <netinet/in.h> +#endif +#ifdef HAVE_NETDB_H +#  include <netdb.h> +#endif +#ifdef HAVE_ARPA_INET_H +#  include <arpa/inet.h> +#endif +#ifdef HAVE_ARPA_NAMESER_H +#  include <arpa/nameser.h> +#else +#  include "nameser.h" +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +#  include <arpa/nameser_compat.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#ifdef HAVE_STRINGS_H +#include <strings.h> +#endif + +#include "ares.h" +#include "inet_net_pton.h" +#include "bitncmp.h" +#include "ares_private.h" + +#ifdef WATT32 +#undef WIN32 +#endif + +struct host_query { +  /* Arguments passed to ares_gethostbyname() */ +  ares_channel channel; +  char *name; +  ares_host_callback callback; +  void *arg; +  int sent_family; /* this family is what was is being used */ +  int want_family; /* this family is what is asked for in the API */ +  const char *remaining_lookups; +  int timeouts; +}; + +static void next_lookup(struct host_query *hquery, int status_code); +static void host_callback(void *arg, int status, int timeouts, +                          unsigned char *abuf, int alen); +static void end_hquery(struct host_query *hquery, int status, +                       struct hostent *host); +static int fake_hostent(const char *name, int family, +                        ares_host_callback callback, void *arg); +static int file_lookup(const char *name, int family, struct hostent **host); +static void sort_addresses(struct hostent *host, +                           const struct apattern *sortlist, int nsort); +static void sort6_addresses(struct hostent *host, +                            const struct apattern *sortlist, int nsort); +static int get_address_index(const struct in_addr *addr, +                             const struct apattern *sortlist, int nsort); +static int get6_address_index(const struct in6_addr *addr, +                              const struct apattern *sortlist, int nsort); + +void ares_gethostbyname(ares_channel channel, const char *name, int family, +                        ares_host_callback callback, void *arg) +{ +  struct host_query *hquery; + +  /* Right now we only know how to look up Internet addresses - and unspec +     means try both basically. */ +  switch (family) { +  case AF_INET: +  case AF_INET6: +  case AF_UNSPEC: +    break; +  default: +    callback(arg, ARES_ENOTIMP, 0, NULL); +    return; +  } + +  if (fake_hostent(name, family, callback, arg)) +    return; + +  /* Allocate and fill in the host query structure. */ +  hquery = malloc(sizeof(struct host_query)); +  if (!hquery) +    { +      callback(arg, ARES_ENOMEM, 0, NULL); +      return; +    } +  hquery->channel = channel; +  hquery->name = strdup(name); +  hquery->want_family = family; +  hquery->sent_family = -1; /* nothing is sent yet */ +  if (!hquery->name) { +    free(hquery); +    callback(arg, ARES_ENOMEM, 0, NULL); +    return; +  } +  hquery->callback = callback; +  hquery->arg = arg; +  hquery->remaining_lookups = channel->lookups; +  hquery->timeouts = 0; + +  /* Start performing lookups according to channel->lookups. */ +  next_lookup(hquery, ARES_ECONNREFUSED /* initial error code */); +} + +static void next_lookup(struct host_query *hquery, int status_code) +{ +  const char *p; +  struct hostent *host; +  int status = status_code; + +  for (p = hquery->remaining_lookups; *p; p++) +    { +      switch (*p) +        { +        case 'b': +          /* DNS lookup */ +          hquery->remaining_lookups = p + 1; +          if ((hquery->want_family == AF_INET6) || +              (hquery->want_family == AF_UNSPEC)) { +            /* if inet6 or unspec, start out with AAAA */ +            hquery->sent_family = AF_INET6; +            ares_search(hquery->channel, hquery->name, C_IN, T_AAAA, +                        host_callback, hquery); +          } +          else { +            hquery->sent_family = AF_INET; +            ares_search(hquery->channel, hquery->name, C_IN, T_A, host_callback, +                        hquery); +          } +          return; + +        case 'f': +          /* Host file lookup */ +          status = file_lookup(hquery->name, hquery->want_family, &host); + +          /* this status check below previously checked for !ARES_ENOTFOUND, +             but we should not assume that this single error code is the one +             that can occur, as that is in fact no longer the case */ +          if (status == ARES_SUCCESS) +            { +              end_hquery(hquery, status, host); +              return; +            } +          status = status_code;   /* Use original status code */ +          break; +        } +    } +  end_hquery(hquery, status, NULL); +} + +static void host_callback(void *arg, int status, int timeouts, +                          unsigned char *abuf, int alen) +{ +  struct host_query *hquery = (struct host_query *) arg; +  ares_channel channel = hquery->channel; +  struct hostent *host = NULL; + +  hquery->timeouts += timeouts; +  if (status == ARES_SUCCESS) +    { +      if (hquery->sent_family == AF_INET) +        { +          status = ares_parse_a_reply(abuf, alen, &host, NULL, NULL); +          if (host && channel->nsort) +            sort_addresses(host, channel->sortlist, channel->nsort); +        } +      else if (hquery->sent_family == AF_INET6) +        { +          status = ares_parse_aaaa_reply(abuf, alen, &host, NULL, NULL); +          if (status == ARES_ENODATA || status == ARES_EBADRESP) { +            /* The query returned something but either there were no AAAA records (e.g. just CNAME)  +               or the response was malformed.  Try looking up A instead.   +               We should possibly limit this attempt-next logic to AF_UNSPEC lookups only. */ +            hquery->sent_family = AF_INET; +            ares_search(hquery->channel, hquery->name, C_IN, T_A, +                        host_callback, hquery); +            return; +          } +          if (host && channel->nsort) +            sort6_addresses(host, channel->sortlist, channel->nsort); +        } +      end_hquery(hquery, status, host); +    } +  else if ((status == ARES_ENODATA || status == ARES_EBADRESP || status == ARES_ETIMEOUT) && hquery->sent_family == AF_INET6) +    { +      /* The AAAA query yielded no useful result.  Now look up an A instead.   +         We should possibly limit this attempt-next logic to AF_UNSPEC lookups only. */ +      hquery->sent_family = AF_INET; +      ares_search(hquery->channel, hquery->name, C_IN, T_A, host_callback, +                  hquery); +    } +  else if (status == ARES_EDESTRUCTION) +    end_hquery(hquery, status, NULL); +  else +    next_lookup(hquery, status); +} + +static void end_hquery(struct host_query *hquery, int status, +                       struct hostent *host) +{ +  hquery->callback(hquery->arg, status, hquery->timeouts, host); +  if (host) +    ares_free_hostent(host); +  free(hquery->name); +  free(hquery); +} + +/* If the name looks like an IP address, fake up a host entry, end the + * query immediately, and return true.  Otherwise return false. + */ +static int fake_hostent(const char *name, int family, ares_host_callback callback, +                        void *arg) +{ +  struct hostent hostent; +  char *aliases[1] = { NULL }; +  char *addrs[2]; +  int result = 0; +  struct in_addr in; +  struct in6_addr in6; + +  if (family == AF_INET || family == AF_INET6) +    { +      /* It only looks like an IP address if it's all numbers and dots. */ +      int numdots = 0, valid = 1; +      const char *p; +      for (p = name; *p; p++) +        { +          if (!ISDIGIT(*p) && *p != '.') { +            valid = 0; +            break; +          } else if (*p == '.') { +            numdots++; +          } +        } + +      /* if we don't have 3 dots, it is illegal +       * (although inet_addr doesn't think so). +       */ +      if (numdots != 3 || !valid) +        result = 0; +      else +        result = ((in.s_addr = inet_addr(name)) == INADDR_NONE ? 0 : 1); + +      if (result) +        family = AF_INET; +    } +  if (family == AF_INET6) +    result = (ares_inet_pton(AF_INET6, name, &in6) < 1 ? 0 : 1); + +  if (!result) +    return 0; + +  if (family == AF_INET) +    { +      hostent.h_length = (int)sizeof(struct in_addr); +      addrs[0] = (char *)∈ +    } +  else if (family == AF_INET6) +    { +      hostent.h_length = (int)sizeof(struct in6_addr); +      addrs[0] = (char *)&in6; +    } +  /* Duplicate the name, to avoid a constness violation. */ +  hostent.h_name = strdup(name); +  if (!hostent.h_name) +    { +      callback(arg, ARES_ENOMEM, 0, NULL); +      return 1; +    } + +  /* Fill in the rest of the host structure and terminate the query. */ +  addrs[1] = NULL; +  hostent.h_aliases = aliases; +  hostent.h_addrtype = family; +  hostent.h_addr_list = addrs; +  callback(arg, ARES_SUCCESS, 0, &hostent); + +  free((char *)(hostent.h_name)); +  return 1; +} + +/* This is an API method */ +int ares_gethostbyname_file(ares_channel channel, const char *name, +                            int family, struct hostent **host) +{ +  int result; + +  /* We only take the channel to ensure that ares_init() been called. */ +  if(channel == NULL) +    { +      /* Anything will do, really.  This seems fine, and is consistent with +         other error cases. */ +      *host = NULL; +      return ARES_ENOTFOUND; +    } + +  /* Just chain to the internal implementation we use here; it's exactly +   * what we want. +   */ +  result = file_lookup(name, family, host); +  if(result != ARES_SUCCESS) +    { +      /* We guarantee a NULL hostent on failure. */ +      *host = NULL; +    } +  return result; +} + +static int file_lookup(const char *name, int family, struct hostent **host) +{ +  FILE *fp; +  char **alias; +  int status; +  int error; + +#ifdef WIN32 +  char PATH_HOSTS[MAX_PATH]; +  if (IS_NT()) { +    char tmp[MAX_PATH]; +    HKEY hkeyHosts; + +    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, KEY_READ, &hkeyHosts) +        == ERROR_SUCCESS) +    { +      DWORD dwLength = MAX_PATH; +      RegQueryValueEx(hkeyHosts, DATABASEPATH, NULL, NULL, (LPBYTE)tmp, +                      &dwLength); +      ExpandEnvironmentStrings(tmp, PATH_HOSTS, MAX_PATH); +      RegCloseKey(hkeyHosts); +    } +  } +  else +    GetWindowsDirectory(PATH_HOSTS, MAX_PATH); + +  strcat(PATH_HOSTS, WIN_PATH_HOSTS); + +#elif defined(WATT32) +  extern const char *_w32_GetHostsFile (void); +  const char *PATH_HOSTS = _w32_GetHostsFile(); + +  if (!PATH_HOSTS) +    return ARES_ENOTFOUND; +#endif + +  fp = fopen(PATH_HOSTS, "r"); +  if (!fp) +    { +      error = ERRNO; +      switch(error) +        { +        case ENOENT: +        case ESRCH: +          return ARES_ENOTFOUND; +        default: +          DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", +                         error, strerror(error))); +          DEBUGF(fprintf(stderr, "Error opening file: %s\n", +                         PATH_HOSTS)); +          *host = NULL; +          return ARES_EFILE; +        } +    } +  while ((status = ares__get_hostent(fp, family, host)) == ARES_SUCCESS) +    { +      if (strcasecmp((*host)->h_name, name) == 0) +        break; +      for (alias = (*host)->h_aliases; *alias; alias++) +        { +          if (strcasecmp(*alias, name) == 0) +            break; +        } +      if (*alias) +        break; +      ares_free_hostent(*host); +    } +  fclose(fp); +  if (status == ARES_EOF) +    status = ARES_ENOTFOUND; +  if (status != ARES_SUCCESS) +    *host = NULL; +  return status; +} + +static void sort_addresses(struct hostent *host, const struct apattern *sortlist, +                           int nsort) +{ +  struct in_addr a1, a2; +  int i1, i2, ind1, ind2; + +  /* This is a simple insertion sort, not optimized at all.  i1 walks +   * through the address list, with the loop invariant that everything +   * to the left of i1 is sorted.  In the loop body, the value at i1 is moved +   * back through the list (via i2) until it is in sorted order. +   */ +  for (i1 = 0; host->h_addr_list[i1]; i1++) +    { +      memcpy(&a1, host->h_addr_list[i1], sizeof(struct in_addr)); +      ind1 = get_address_index(&a1, sortlist, nsort); +      for (i2 = i1 - 1; i2 >= 0; i2--) +        { +          memcpy(&a2, host->h_addr_list[i2], sizeof(struct in_addr)); +          ind2 = get_address_index(&a2, sortlist, nsort); +          if (ind2 <= ind1) +            break; +          memcpy(host->h_addr_list[i2 + 1], &a2, sizeof(struct in_addr)); +        } +      memcpy(host->h_addr_list[i2 + 1], &a1, sizeof(struct in_addr)); +    } +} + +/* Find the first entry in sortlist which matches addr.  Return nsort + * if none of them match. + */ +static int get_address_index(const struct in_addr *addr, +                             const struct apattern *sortlist, +                             int nsort) +{ +  int i; + +  for (i = 0; i < nsort; i++) +    { +      if (sortlist[i].family != AF_INET) +        continue; +      if (sortlist[i].type == PATTERN_MASK) +        { +          if ((addr->s_addr & sortlist[i].mask.addr4.s_addr) +              == sortlist[i].addrV4.s_addr) +            break; +        } +      else +        { +          if (!ares_bitncmp(&addr->s_addr, &sortlist[i].addrV4.s_addr, +                            sortlist[i].mask.bits)) +            break; +        } +    } +  return i; +} + +static void sort6_addresses(struct hostent *host, const struct apattern *sortlist, +                           int nsort) +{ +  struct in6_addr a1, a2; +  int i1, i2, ind1, ind2; + +  /* This is a simple insertion sort, not optimized at all.  i1 walks +   * through the address list, with the loop invariant that everything +   * to the left of i1 is sorted.  In the loop body, the value at i1 is moved +   * back through the list (via i2) until it is in sorted order. +   */ +  for (i1 = 0; host->h_addr_list[i1]; i1++) +    { +      memcpy(&a1, host->h_addr_list[i1], sizeof(struct in6_addr)); +      ind1 = get6_address_index(&a1, sortlist, nsort); +      for (i2 = i1 - 1; i2 >= 0; i2--) +        { +          memcpy(&a2, host->h_addr_list[i2], sizeof(struct in6_addr)); +          ind2 = get6_address_index(&a2, sortlist, nsort); +          if (ind2 <= ind1) +            break; +          memcpy(host->h_addr_list[i2 + 1], &a2, sizeof(struct in6_addr)); +        } +      memcpy(host->h_addr_list[i2 + 1], &a1, sizeof(struct in6_addr)); +    } +} + +/* Find the first entry in sortlist which matches addr.  Return nsort + * if none of them match. + */ +static int get6_address_index(const struct in6_addr *addr, +                              const struct apattern *sortlist, +                              int nsort) +{ +  int i; + +  for (i = 0; i < nsort; i++) +    { +      if (sortlist[i].family != AF_INET6) +        continue; +        if (!ares_bitncmp(&addr->s6_addr, &sortlist[i].addrV6.s6_addr, sortlist[i].mask.bits)) +          break; +    } +  return i; +} diff --git a/3rdParty/CAres/src/ares_getnameinfo.c b/3rdParty/CAres/src/ares_getnameinfo.c new file mode 100644 index 0000000..c1c0b16 --- /dev/null +++ b/3rdParty/CAres/src/ares_getnameinfo.c @@ -0,0 +1,409 @@ +/* $Id: ares_getnameinfo.c,v 1.36 2009-11-09 12:56:11 yangtse Exp $ */ + +/* Copyright 2005 by Dominick Meglio + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ +#include "ares_setup.h" + +#ifdef HAVE_GETSERVBYPORT_R +#  if !defined(GETSERVBYPORT_R_ARGS) || \ +     (GETSERVBYPORT_R_ARGS < 4) || (GETSERVBYPORT_R_ARGS > 6) +#    error "you MUST specifiy a valid number of arguments for getservbyport_r" +#  endif +#endif + +#ifdef HAVE_SYS_SOCKET_H +#  include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#  include <netinet/in.h> +#endif +#ifdef HAVE_NETDB_H +#  include <netdb.h> +#endif +#ifdef HAVE_ARPA_INET_H +#  include <arpa/inet.h> +#endif +#ifdef HAVE_ARPA_NAMESER_H +#  include <arpa/nameser.h> +#else +#  include "nameser.h" +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +#  include <arpa/nameser_compat.h> +#endif + +#ifdef HAVE_NET_IF_H +#include <net/if.h> +#endif + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "ares.h" +#include "ares_ipv6.h" +#include "inet_ntop.h" +#include "ares_private.h" + +struct nameinfo_query { +  ares_nameinfo_callback callback; +  void *arg; +  union { +    struct sockaddr_in addr4; +    struct sockaddr_in6 addr6; +  } addr; +  int family; +  int flags; +  int timeouts; +}; + +#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID +#define IPBUFSIZ 40+IF_NAMESIZE +#else +#define IPBUFSIZ 40 +#endif + +static void nameinfo_callback(void *arg, int status, int timeouts, struct hostent *host); +static char *lookup_service(unsigned short port, int flags, +                            char *buf, size_t buflen); +#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID +static void append_scopeid(struct sockaddr_in6 *addr6, unsigned int scopeid, +                           char *buf, size_t buflen); +#endif +static char *ares_striendstr(const char *s1, const char *s2); + +void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, +                      ares_socklen_t salen, +                      int flags, ares_nameinfo_callback callback, void *arg) +{ +  struct sockaddr_in *addr = NULL; +  struct sockaddr_in6 *addr6 = NULL; +  struct nameinfo_query *niquery; +  unsigned int port = 0; + +  /* Verify the buffer size */ +  if (salen == sizeof(struct sockaddr_in)) +    { +      addr = (struct sockaddr_in *)sa; +      port = addr->sin_port; +    } +  else if (salen == sizeof(struct sockaddr_in6)) +    { +      addr6 = (struct sockaddr_in6 *)sa; +      port = addr6->sin6_port; +    } +  else +    { +      callback(arg, ARES_ENOTIMP, 0, NULL, NULL); +      return; +    } + +  /* If neither, assume they want a host */ +  if (!(flags & ARES_NI_LOOKUPSERVICE) && !(flags & ARES_NI_LOOKUPHOST)) +    flags |= ARES_NI_LOOKUPHOST; + +  /* All they want is a service, no need for DNS */ +  if ((flags & ARES_NI_LOOKUPSERVICE) && !(flags & ARES_NI_LOOKUPHOST)) +    { +      char buf[33], *service; + +      service = lookup_service((unsigned short)(port & 0xffff), +                               flags, buf, sizeof(buf)); +      callback(arg, ARES_SUCCESS, 0, NULL, service); +      return; +    } + +  /* They want a host lookup */ +  if ((flags & ARES_NI_LOOKUPHOST)) +    { +     /* A numeric host can be handled without DNS */ +     if ((flags & ARES_NI_NUMERICHOST)) +      { +        char ipbuf[IPBUFSIZ]; +        char srvbuf[33]; +        char *service = NULL; +        ipbuf[0] = 0; + +        /* Specifying not to lookup a host, but then saying a host +         * is required has to be illegal. +         */ +        if (flags & ARES_NI_NAMEREQD) +          { +            callback(arg, ARES_EBADFLAGS, 0, NULL, NULL); +            return; +          } +        if (salen == sizeof(struct sockaddr_in6)) +          { +            ares_inet_ntop(AF_INET6, &addr6->sin6_addr, ipbuf, IPBUFSIZ); +            /* If the system supports scope IDs, use it */ +#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID +            append_scopeid(addr6, flags, ipbuf, sizeof(ipbuf)); +#endif +          } +        else +          { +            ares_inet_ntop(AF_INET, &addr->sin_addr, ipbuf, IPBUFSIZ); +          } +        /* They also want a service */ +        if (flags & ARES_NI_LOOKUPSERVICE) +          service = lookup_service((unsigned short)(port & 0xffff), +                                   flags, srvbuf, sizeof(srvbuf)); +        callback(arg, ARES_SUCCESS, 0, ipbuf, service); +        return; +      } +    /* This is where a DNS lookup becomes necessary */ +    else +      { +        niquery = malloc(sizeof(struct nameinfo_query)); +        if (!niquery) +          { +            callback(arg, ARES_ENOMEM, 0, NULL, NULL); +            return; +          } +        niquery->callback = callback; +        niquery->arg = arg; +        niquery->flags = flags; +        niquery->timeouts = 0; +        if (sa->sa_family == AF_INET) +          { +            niquery->family = AF_INET; +            memcpy(&niquery->addr.addr4, addr, sizeof(addr)); +            ares_gethostbyaddr(channel, &addr->sin_addr, sizeof(struct in_addr), AF_INET, +                               nameinfo_callback, niquery); +          } +        else +          { +            niquery->family = AF_INET6; +            memcpy(&niquery->addr.addr6, addr6, sizeof(addr6)); +            ares_gethostbyaddr(channel, &addr6->sin6_addr, sizeof(struct in6_addr), AF_INET6, +                               nameinfo_callback, niquery); +          } +      } +    } +} + +static void nameinfo_callback(void *arg, int status, int timeouts, struct hostent *host) +{ +  struct nameinfo_query *niquery = (struct nameinfo_query *) arg; +  char srvbuf[33]; +  char *service = NULL; + +  niquery->timeouts += timeouts; +  if (status == ARES_SUCCESS) +    { +      /* They want a service too */ +      if (niquery->flags & ARES_NI_LOOKUPSERVICE) +        { +          if (niquery->family == AF_INET) +            service = lookup_service(niquery->addr.addr4.sin_port, +                                     niquery->flags, srvbuf, sizeof(srvbuf)); +          else +            service = lookup_service(niquery->addr.addr6.sin6_port, +                                     niquery->flags, srvbuf, sizeof(srvbuf)); +        } +      /* NOFQDN means we have to strip off the domain name portion. +         We do this by determining our own domain name, then searching the string +         for this domain name and removing it. +       */ +#ifdef HAVE_GETHOSTNAME +      if (niquery->flags & ARES_NI_NOFQDN) +        { +           char buf[255]; +           char *domain; +           gethostname(buf, 255); +           if ((domain = strchr(buf, '.'))) +             { +               char *end = ares_striendstr(host->h_name, domain); +               if (end) +                 *end = 0; +             } +        } +#endif +      niquery->callback(niquery->arg, ARES_SUCCESS, niquery->timeouts, (char *)(host->h_name), +                        service); +      return; +    } +  /* We couldn't find the host, but it's OK, we can use the IP */ +  else if (status == ARES_ENOTFOUND && !(niquery->flags & ARES_NI_NAMEREQD)) +    { +      char ipbuf[IPBUFSIZ]; +      if (niquery->family == AF_INET) +        ares_inet_ntop(AF_INET, &niquery->addr.addr4.sin_addr, ipbuf, IPBUFSIZ); +      else +        { +          ares_inet_ntop(AF_INET6, &niquery->addr.addr6.sin6_addr, ipbuf, IPBUFSIZ); +#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID +          append_scopeid(&niquery->addr.addr6, niquery->flags, ipbuf, sizeof(ipbuf)); +#endif +        } +      /* They want a service too */ +      if (niquery->flags & ARES_NI_LOOKUPSERVICE) +        { +          if (niquery->family == AF_INET) +            service = lookup_service(niquery->addr.addr4.sin_port, +                                     niquery->flags, srvbuf, sizeof(srvbuf)); +          else +            service = lookup_service(niquery->addr.addr6.sin6_port, +                                     niquery->flags, srvbuf, sizeof(srvbuf)); +        } +      niquery->callback(niquery->arg, ARES_SUCCESS, niquery->timeouts, ipbuf, service); +      return; +    } +  niquery->callback(niquery->arg, status, niquery->timeouts, NULL, NULL); +  free(niquery); +} + +static char *lookup_service(unsigned short port, int flags, +                            char *buf, size_t buflen) +{ +  const char *proto; +  struct servent *sep; +#ifdef HAVE_GETSERVBYPORT_R +  struct servent se; +#endif +  char tmpbuf[4096]; + +  if (port) +    { +      if (flags & ARES_NI_NUMERICSERV) +        sep = NULL; +      else +        { +          if (flags & ARES_NI_UDP) +            proto = "udp"; +          else if (flags & ARES_NI_SCTP) +            proto = "sctp"; +          else if (flags & ARES_NI_DCCP) +            proto = "dccp"; +          else +            proto = "tcp"; +#ifdef HAVE_GETSERVBYPORT_R +          sep = &se; +          memset(tmpbuf, 0, sizeof(tmpbuf)); +#if GETSERVBYPORT_R_ARGS == 6 +          if (getservbyport_r(port, proto, &se, (void *)tmpbuf, sizeof(tmpbuf), &sep) != 0) +            sep = NULL; +#elif GETSERVBYPORT_R_ARGS == 5 +          sep = getservbyport_r(port, proto, &se, (void *)tmpbuf, sizeof(tmpbuf)); +#elif GETSERVBYPORT_R_ARGS == 4 +          if (getservbyport_r(port, proto, &se, (void *)tmpbuf) != 0) +            sep = NULL; +#else +          /* Lets just hope the OS uses TLS! */ +          sep = getservbyport(port, proto); +#endif +#else +          /* Lets just hope the OS uses TLS! */ +#if (defined(NETWARE) && !defined(__NOVELL_LIBC__)) +          sep = getservbyport(port, (char*)proto); +#else +          sep = getservbyport(port, proto); +#endif +#endif +        } +      if (sep && sep->s_name) +        /* get service name */ +        strcpy(tmpbuf, sep->s_name); +      else +        /* get port as a string */ +        sprintf(tmpbuf, "%u", (unsigned int)ntohs(port)); +      if (strlen(tmpbuf) < buflen) +        /* return it if buffer big enough */ +        strcpy(buf, tmpbuf); +      else +        /* avoid reusing previous one */ +        buf[0] = '\0'; +      return buf; +    } +  buf[0] = '\0'; +  return NULL; +} + +#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID +static void append_scopeid(struct sockaddr_in6 *addr6, unsigned int flags, +                           char *buf, size_t buflen) +{ +#ifdef HAVE_IF_INDEXTONAME +  int is_ll, is_mcll; +#endif +  char fmt_u[] = "%u"; +  char fmt_lu[] = "%lu"; +  char tmpbuf[IF_NAMESIZE + 2]; +  size_t bufl; +  char *fmt = (sizeof(addr6->sin6_scope_id) > sizeof(unsigned int))?fmt_lu:fmt_u; + +  tmpbuf[0] = '%'; + +#ifdef HAVE_IF_INDEXTONAME +  is_ll = IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr); +  is_mcll = IN6_IS_ADDR_MC_LINKLOCAL(&addr6->sin6_addr); +  if ((flags & ARES_NI_NUMERICSCOPE) || +      (!is_ll && !is_mcll)) +    { +       sprintf(&tmpbuf[1], fmt, addr6->sin6_scope_id); +    } +  else +    { +      if (if_indextoname(addr6->sin6_scope_id, &tmpbuf[1]) == NULL) +        sprintf(&tmpbuf[1], fmt, addr6->sin6_scope_id); +    } +#else +  sprintf(&tmpbuf[1], fmt, addr6->sin6_scope_id); +  (void) flags; +#endif +  tmpbuf[IF_NAMESIZE + 1] = '\0'; +  bufl = strlen(buf); + +  if(bufl + strlen(tmpbuf) < buflen) +    /* only append the scopeid string if it fits in the target buffer */ +    strcpy(&buf[bufl], tmpbuf); +} +#endif + +/* Determines if s1 ends with the string in s2 (case-insensitive) */ +static char *ares_striendstr(const char *s1, const char *s2) +{ +  const char *c1, *c2, *c1_begin; +  int lo1, lo2; +  size_t s1_len = strlen(s1), s2_len = strlen(s2); + +  /* If the substr is longer than the full str, it can't match */ +  if (s2_len > s1_len) +    return NULL; + +  /* Jump to the end of s1 minus the length of s2 */ +  c1_begin = s1+s1_len-s2_len; +  c1 = (const char *)c1_begin; +  c2 = s2; +  while (c2 < s2+s2_len) +    { +      lo1 = tolower(*c1); +      lo2 = tolower(*c2); +      if (lo1 != lo2) +        return NULL; +      else +        { +          c1++; +          c2++; +        } +    } +  if (c2 == c1 && c2 == NULL) +    return (char *)c1_begin; +  return NULL; +} diff --git a/3rdParty/CAres/src/ares_getopt.c b/3rdParty/CAres/src/ares_getopt.c new file mode 100644 index 0000000..67e1be7 --- /dev/null +++ b/3rdParty/CAres/src/ares_getopt.c @@ -0,0 +1,123 @@ +/* + * Original file name getopt.c  Initial import into the c-ares source tree + * on 2007-04-11.  Lifted from version 5.2 of the 'Open Mash' project with + * the modified BSD license, BSD license without the advertising clause. + * + * $Id: ares_getopt.c,v 1.9 2009-11-22 03:41:26 yangtse Exp $ + */ + +/* + * getopt.c -- + * + *      Standard UNIX getopt function.  Code is from BSD. + * + * Copyright (c) 1987-2001 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * A. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * B. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * C. Neither the names of the copyright holders nor the names of its + *    contributors may be used to endorse or promote products derived from this + *    software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS + * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* #if !defined(lint) + * static char sccsid[] = "@(#)getopt.c 8.2 (Berkeley) 4/2/94"; + * #endif + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "ares_getopt.h" + +int   opterr = 1,     /* if error message should be printed */ +      optind = 1;     /* index into parent argv vector */ +int   optopt = 0;     /* character checked for validity */ +static int optreset;  /* reset getopt */ +char  *optarg;        /* argument associated with option */ + +#define  BADCH   (int)'?' +#define  BADARG  (int)':' +#define  EMSG    (char *)"" + +/* + * ares_getopt -- + *    Parse argc/argv argument vector. + */ +int +ares_getopt(int nargc, char * const nargv[], const char *ostr) +{ +    static char *place = EMSG;                /* option letter processing */ +    char *oli;                                /* option letter list index */ + +    if (optreset || !*place) {                /* update scanning pointer */ +        optreset = 0; +        if (optind >= nargc || *(place = nargv[optind]) != '-') { +            place = EMSG; +            return (EOF); +        } +        if (place[1] && *++place == '-') {    /* found "--" */ +            ++optind; +            place = EMSG; +            return (EOF); +        } +    }                                         /* option letter okay? */ +    if ((optopt = (int)*place++) == (int)':' || +        (oli = strchr(ostr, optopt)) == NULL) { +        /* +         * if the user didn't specify '-' as an option, +         * assume it means EOF. +         */ +        if (optopt == (int)'-') +            return (EOF); +        if (!*place) +            ++optind; +        if (opterr && *ostr != ':') +            (void)fprintf(stderr, +                "%s: illegal option -- %c\n", __FILE__, optopt); +        return (BADCH); +    } +    if (*++oli != ':') {                      /* don't need argument */ +        optarg = NULL; +        if (!*place) +            ++optind; +    } +    else {                                    /* need an argument */ +        if (*place)                           /* no white space */ +            optarg = place; +        else if (nargc <= ++optind) {         /* no arg */ +            place = EMSG; +            if (*ostr == ':') +                return (BADARG); +            if (opterr) +                (void)fprintf(stderr, +                    "%s: option requires an argument -- %c\n", +                    __FILE__, optopt); +            return (BADCH); +        } +         else                                 /* white space */ +            optarg = nargv[optind]; +        place = EMSG; +        ++optind; +    } +    return (optopt);                          /* dump back option letter */ +} diff --git a/3rdParty/CAres/src/ares_getopt.h b/3rdParty/CAres/src/ares_getopt.h new file mode 100644 index 0000000..63acb3b --- /dev/null +++ b/3rdParty/CAres/src/ares_getopt.h @@ -0,0 +1,53 @@ +#ifndef ARES_GETOPT_H +#define ARES_GETOPT_H + +/* + * Copyright (c) 1987-2001 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * A. Redistributions of source code must retain the above copyright notice, + *    this list of conditions and the following disclaimer. + * B. Redistributions in binary form must reproduce the above copyright notice, + *    this list of conditions and the following disclaimer in the documentation + *    and/or other materials provided with the distribution. + * C. Neither the names of the copyright holders nor the names of its + *    contributors may be used to endorse or promote products derived from this + *    software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS + * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +int ares_getopt(int nargc, char * const nargv[], const char *ostr); + +#undef optarg +#undef optind +#undef opterr +#undef optopt +#undef optreset + +#define optarg   ares_optarg +#define optind   ares_optind +#define opterr   ares_opterr +#define optopt   ares_optopt +#define optreset ares_optreset + +extern char *optarg; +extern int optind; +extern int opterr; +extern int optopt; + +#endif /* ARES_GETOPT_H */ diff --git a/3rdParty/CAres/src/ares_getsock.c b/3rdParty/CAres/src/ares_getsock.c new file mode 100644 index 0000000..a25b83a --- /dev/null +++ b/3rdParty/CAres/src/ares_getsock.c @@ -0,0 +1,75 @@ +/* $Id: ares_getsock.c,v 1.8 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright (C) 2005 - 2007, Daniel Stenberg + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission.  M.I.T. makes no representations about the + * suitability of this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +#include "ares.h" +#include "ares_private.h" + +int ares_getsock(ares_channel channel, +                 int *s, +                 int numsocks) /* size of the 'socks' array */ +{ +  struct server_state *server; +  int i; +  int sockindex=0; +  int bitmap = 0; +  unsigned int setbits = 0xffffffff; + +  ares_socket_t *socks = (ares_socket_t *)s; + +  /* Are there any active queries? */ +  int active_queries = !ares__is_list_empty(&(channel->all_queries)); + +  for (i = 0; +       (i < channel->nservers) && (sockindex < ARES_GETSOCK_MAXNUM); +       i++) +    { +      server = &channel->servers[i]; +      /* We only need to register interest in UDP sockets if we have +       * outstanding queries. +       */ +      if (active_queries && server->udp_socket != ARES_SOCKET_BAD) +        { +          if(sockindex >= numsocks) +            break; +          socks[sockindex] = server->udp_socket; +          bitmap |= ARES_GETSOCK_READABLE(setbits, sockindex); +          sockindex++; +        } +      /* We always register for TCP events, because we want to know +       * when the other side closes the connection, so we don't waste +       * time trying to use a broken connection. +       */ +      if (server->tcp_socket != ARES_SOCKET_BAD) +       { +         if(sockindex >= numsocks) +           break; +         socks[sockindex] = server->tcp_socket; +         bitmap |= ARES_GETSOCK_READABLE(setbits, sockindex); + +         if (server->qhead && active_queries) +           /* then the tcp socket is also writable! */ +           bitmap |= ARES_GETSOCK_WRITABLE(setbits, sockindex); + +         sockindex++; +       } +    } +  return bitmap; +} diff --git a/3rdParty/CAres/src/ares_init.c b/3rdParty/CAres/src/ares_init.c new file mode 100644 index 0000000..cb541af --- /dev/null +++ b/3rdParty/CAres/src/ares_init.c @@ -0,0 +1,1582 @@ +/* $Id: ares_init.c,v 1.103 2009-11-18 10:33:54 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * Copyright (C) 2007-2009 by Daniel Stenberg + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef USE_WINSOCK +#include <iphlpapi.h> +#endif + +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif + +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif + +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif + +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif + +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif + +#ifdef HAVE_ARPA_NAMESER_H +#  include <arpa/nameser.h> +#else +#  include "nameser.h" +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +#  include <arpa/nameser_compat.h> +#endif + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <time.h> +#include <errno.h> +#include "ares.h" +#include "inet_net_pton.h" +#include "ares_library_init.h" +#include "ares_private.h" + +#ifdef WATT32 +#undef WIN32  /* Redefined in MingW/MSVC headers */ +#endif + +static int init_by_options(ares_channel channel, const struct ares_options *options, +                           int optmask); +static int init_by_environment(ares_channel channel); +static int init_by_resolv_conf(ares_channel channel); +static int init_by_defaults(ares_channel channel); + +#ifndef WATT32 +static int config_nameserver(struct server_state **servers, int *nservers, +                             char *str); +#endif +static int set_search(ares_channel channel, const char *str); +static int set_options(ares_channel channel, const char *str); +static const char *try_option(const char *p, const char *q, const char *opt); +static int init_id_key(rc4_key* key,int key_data_len); + +#if !defined(WIN32) && !defined(WATT32) +static int sortlist_alloc(struct apattern **sortlist, int *nsort, struct apattern *pat); +static int ip_addr(const char *s, int len, struct in_addr *addr); +static void natural_mask(struct apattern *pat); +static int config_domain(ares_channel channel, char *str); +static int config_lookup(ares_channel channel, const char *str, +                         const char *bindch, const char *filech); +static int config_sortlist(struct apattern **sortlist, int *nsort, +                           const char *str); +static char *try_config(char *s, const char *opt); +#endif + +#define ARES_CONFIG_CHECK(x) (x->lookups && x->nsort > -1 && \ +                             x->nservers > -1 && \ +                             x->ndomains > -1 && \ +                             x->ndots > -1 && x->timeout > -1 && \ +                             x->tries > -1) + +int ares_init(ares_channel *channelptr) +{ +  return ares_init_options(channelptr, NULL, 0); +} + +int ares_init_options(ares_channel *channelptr, struct ares_options *options, +                      int optmask) +{ +  ares_channel channel; +  int i; +  int status = ARES_SUCCESS; +  struct server_state *server; +  struct timeval now; + +#ifdef CURLDEBUG +  const char *env = getenv("CARES_MEMDEBUG"); + +  if (env) +    curl_memdebug(env); +  env = getenv("CARES_MEMLIMIT"); +  if (env) +    curl_memlimit(atoi(env)); +#endif + +  if (ares_library_initialized() != ARES_SUCCESS) +    return ARES_ENOTINITIALIZED; + +  channel = malloc(sizeof(struct ares_channeldata)); +  if (!channel) { +    *channelptr = NULL; +    return ARES_ENOMEM; +  } + +  now = ares__tvnow(); + +  /* Set everything to distinguished values so we know they haven't +   * been set yet. +   */ +  channel->flags = -1; +  channel->timeout = -1; +  channel->tries = -1; +  channel->ndots = -1; +  channel->rotate = -1; +  channel->udp_port = -1; +  channel->tcp_port = -1; +  channel->socket_send_buffer_size = -1; +  channel->socket_receive_buffer_size = -1; +  channel->nservers = -1; +  channel->ndomains = -1; +  channel->nsort = -1; +  channel->tcp_connection_generation = 0; +  channel->lookups = NULL; +  channel->domains = NULL; +  channel->sortlist = NULL; +  channel->servers = NULL; +  channel->sock_state_cb = NULL; +  channel->sock_state_cb_data = NULL; +  channel->sock_create_cb = NULL; +  channel->sock_create_cb_data = NULL; + +  channel->last_server = 0; +  channel->last_timeout_processed = (time_t)now.tv_sec; + +  /* Initialize our lists of queries */ +  ares__init_list_head(&(channel->all_queries)); +  for (i = 0; i < ARES_QID_TABLE_SIZE; i++) +    { +      ares__init_list_head(&(channel->queries_by_qid[i])); +    } +  for (i = 0; i < ARES_TIMEOUT_TABLE_SIZE; i++) +    { +      ares__init_list_head(&(channel->queries_by_timeout[i])); +    } + +  /* Initialize configuration by each of the four sources, from highest +   * precedence to lowest. +   */ + +  if (status == ARES_SUCCESS) { +    status = init_by_options(channel, options, optmask); +    if (status != ARES_SUCCESS) +      DEBUGF(fprintf(stderr, "Error: init_by_options failed: %s\n", +                     ares_strerror(status))); +  } +  if (status == ARES_SUCCESS) { +    status = init_by_environment(channel); +    if (status != ARES_SUCCESS) +      DEBUGF(fprintf(stderr, "Error: init_by_environment failed: %s\n", +                     ares_strerror(status))); +  } +  if (status == ARES_SUCCESS) { +    status = init_by_resolv_conf(channel); +    if (status != ARES_SUCCESS) +      DEBUGF(fprintf(stderr, "Error: init_by_resolv_conf failed: %s\n", +                     ares_strerror(status))); +  } + +  /* +   * No matter what failed or succeeded, seed defaults to provide +   * useful behavior for things that we missed. +   */ +  status = init_by_defaults(channel); +  if (status != ARES_SUCCESS) +    DEBUGF(fprintf(stderr, "Error: init_by_defaults failed: %s\n", +                   ares_strerror(status))); + +  /* Generate random key */ + +  if (status == ARES_SUCCESS) { +    status = init_id_key(&channel->id_key, ARES_ID_KEY_LEN); +    if (status == ARES_SUCCESS) +      channel->next_id = ares__generate_new_id(&channel->id_key); +    else +      DEBUGF(fprintf(stderr, "Error: init_id_key failed: %s\n", +                     ares_strerror(status))); +  } + +  if (status != ARES_SUCCESS) +    { +      /* Something failed; clean up memory we may have allocated. */ +      if (channel->servers) +        free(channel->servers); +      if (channel->domains) +        { +          for (i = 0; i < channel->ndomains; i++) +            free(channel->domains[i]); +          free(channel->domains); +        } +      if (channel->sortlist) +        free(channel->sortlist); +      if(channel->lookups) +        free(channel->lookups); +      free(channel); +      return status; +    } + +  /* Trim to one server if ARES_FLAG_PRIMARY is set. */ +  if ((channel->flags & ARES_FLAG_PRIMARY) && channel->nservers > 1) +    channel->nservers = 1; + +  /* Initialize server states. */ +  for (i = 0; i < channel->nservers; i++) +    { +      server = &channel->servers[i]; +      server->udp_socket = ARES_SOCKET_BAD; +      server->tcp_socket = ARES_SOCKET_BAD; +      server->tcp_connection_generation = ++channel->tcp_connection_generation; +      server->tcp_lenbuf_pos = 0; +      server->tcp_buffer = NULL; +      server->qhead = NULL; +      server->qtail = NULL; +      ares__init_list_head(&(server->queries_to_server)); +      server->channel = channel; +      server->is_broken = 0; +    } + +  *channelptr = channel; +  return ARES_SUCCESS; +} + +/* ares_dup() duplicates a channel handle with all its options and returns a +   new channel handle */ +int ares_dup(ares_channel *dest, ares_channel src) +{ +  struct ares_options opts; +  int rc; +  int optmask; + +  *dest = NULL; /* in case of failure return NULL explicitly */ + +  /* First get the options supported by the old ares_save_options() function, +     which is most of them */ +  rc = ares_save_options(src, &opts, &optmask); +  if(rc) +    return rc; + +  /* Then create the new channel with those options */ +  rc = ares_init_options(dest, &opts, optmask); + +  /* destroy the options copy to not leak any memory */ +  ares_destroy_options(&opts); + +  if(rc) +    return rc; + +  /* Now clone the options that ares_save_options() doesn't support. */ +  (*dest)->sock_create_cb      = src->sock_create_cb; +  (*dest)->sock_create_cb_data = src->sock_create_cb_data; + + +  return ARES_SUCCESS; /* everything went fine */ + +} + +/* Save options from initialized channel */ +int ares_save_options(ares_channel channel, struct ares_options *options, +                      int *optmask) +{ +  int i; + +  /* Zero everything out */ +  memset(options, 0, sizeof(struct ares_options)); + +  if (!ARES_CONFIG_CHECK(channel)) +    return ARES_ENODATA; + +  /* Traditionally the optmask wasn't saved in the channel struct so it was +     recreated here. ROTATE is the first option that has no struct field of +     its own in the public config struct */ +  (*optmask) = (ARES_OPT_FLAGS|ARES_OPT_TRIES|ARES_OPT_NDOTS| +                ARES_OPT_UDP_PORT|ARES_OPT_TCP_PORT|ARES_OPT_SOCK_STATE_CB| +                ARES_OPT_SERVERS|ARES_OPT_DOMAINS|ARES_OPT_LOOKUPS| +                ARES_OPT_SORTLIST|ARES_OPT_TIMEOUTMS) | +    (channel->optmask & ARES_OPT_ROTATE); + +  /* Copy easy stuff */ +  options->flags   = channel->flags; + +  /* We return full millisecond resolution but that's only because we don't +     set the ARES_OPT_TIMEOUT anymore, only the new ARES_OPT_TIMEOUTMS */ +  options->timeout = channel->timeout; +  options->tries   = channel->tries; +  options->ndots   = channel->ndots; +  options->udp_port = (unsigned short)channel->udp_port; +  options->tcp_port = (unsigned short)channel->tcp_port; +  options->sock_state_cb     = channel->sock_state_cb; +  options->sock_state_cb_data = channel->sock_state_cb_data; + +  /* Copy servers */ +  if (channel->nservers) { +    options->servers = +      malloc(channel->nservers * sizeof(struct server_state)); +    if (!options->servers && channel->nservers != 0) +      return ARES_ENOMEM; +    for (i = 0; i < channel->nservers; i++) +      options->servers[i] = channel->servers[i].addr; +  } +  options->nservers = channel->nservers; + +  /* copy domains */ +  if (channel->ndomains) { +    options->domains = malloc(channel->ndomains * sizeof(char *)); +    if (!options->domains) +      return ARES_ENOMEM; + +    for (i = 0; i < channel->ndomains; i++) +    { +      options->ndomains = i; +      options->domains[i] = strdup(channel->domains[i]); +      if (!options->domains[i]) +        return ARES_ENOMEM; +    } +  } +  options->ndomains = channel->ndomains; + +  /* copy lookups */ +  if (channel->lookups) { +    options->lookups = strdup(channel->lookups); +    if (!options->lookups && channel->lookups) +      return ARES_ENOMEM; +  } + +  /* copy sortlist */ +  if (channel->nsort) { +    options->sortlist = malloc(channel->nsort * sizeof(struct apattern)); +    if (!options->sortlist) +      return ARES_ENOMEM; +    for (i = 0; i < channel->nsort; i++) +    { +      memcpy(&(options->sortlist[i]), &(channel->sortlist[i]), +             sizeof(struct apattern)); +    } +  } +  options->nsort = channel->nsort; + +  return ARES_SUCCESS; +} + +static int init_by_options(ares_channel channel, +                           const struct ares_options *options, +                           int optmask) +{ +  int i; + +  /* Easy stuff. */ +  if ((optmask & ARES_OPT_FLAGS) && channel->flags == -1) +    channel->flags = options->flags; +  if ((optmask & ARES_OPT_TIMEOUTMS) && channel->timeout == -1) +    channel->timeout = options->timeout; +  else if ((optmask & ARES_OPT_TIMEOUT) && channel->timeout == -1) +    channel->timeout = options->timeout * 1000; +  if ((optmask & ARES_OPT_TRIES) && channel->tries == -1) +    channel->tries = options->tries; +  if ((optmask & ARES_OPT_NDOTS) && channel->ndots == -1) +    channel->ndots = options->ndots; +  if ((optmask & ARES_OPT_ROTATE) && channel->rotate == -1) +    channel->rotate = 1; +  if ((optmask & ARES_OPT_UDP_PORT) && channel->udp_port == -1) +    channel->udp_port = options->udp_port; +  if ((optmask & ARES_OPT_TCP_PORT) && channel->tcp_port == -1) +    channel->tcp_port = options->tcp_port; +  if ((optmask & ARES_OPT_SOCK_STATE_CB) && channel->sock_state_cb == NULL) +    { +      channel->sock_state_cb = options->sock_state_cb; +      channel->sock_state_cb_data = options->sock_state_cb_data; +    } +  if ((optmask & ARES_OPT_SOCK_SNDBUF) +      && channel->socket_send_buffer_size == -1) +    channel->socket_send_buffer_size = options->socket_send_buffer_size; +  if ((optmask & ARES_OPT_SOCK_RCVBUF) +      && channel->socket_receive_buffer_size == -1) +    channel->socket_receive_buffer_size = options->socket_receive_buffer_size; + +  /* Copy the servers, if given. */ +  if ((optmask & ARES_OPT_SERVERS) && channel->nservers == -1) +    { +      /* Avoid zero size allocations at any cost */ +      if (options->nservers > 0) +        { +          channel->servers = +            malloc(options->nservers * sizeof(struct server_state)); +          if (!channel->servers) +            return ARES_ENOMEM; +          for (i = 0; i < options->nservers; i++) +            channel->servers[i].addr = options->servers[i]; +        } +      channel->nservers = options->nservers; +    } + +  /* Copy the domains, if given.  Keep channel->ndomains consistent so +   * we can clean up in case of error. +   */ +  if ((optmask & ARES_OPT_DOMAINS) && channel->ndomains == -1) +    { +      /* Avoid zero size allocations at any cost */ +      if (options->ndomains > 0) +      { +        channel->domains = malloc(options->ndomains * sizeof(char *)); +        if (!channel->domains) +          return ARES_ENOMEM; +        for (i = 0; i < options->ndomains; i++) +          { +            channel->ndomains = i; +            channel->domains[i] = strdup(options->domains[i]); +            if (!channel->domains[i]) +              return ARES_ENOMEM; +          } +      } +      channel->ndomains = options->ndomains; +    } + +  /* Set lookups, if given. */ +  if ((optmask & ARES_OPT_LOOKUPS) && !channel->lookups) +    { +      channel->lookups = strdup(options->lookups); +      if (!channel->lookups) +        return ARES_ENOMEM; +    } + +  /* copy sortlist */ +  if ((optmask & ARES_OPT_SORTLIST) && channel->nsort == -1) +    { +      channel->sortlist = malloc(options->nsort * sizeof(struct apattern)); +      if (!channel->sortlist) +        return ARES_ENOMEM; +      for (i = 0; i < options->nsort; i++) +        { +          memcpy(&(channel->sortlist[i]), &(options->sortlist[i]), +                 sizeof(struct apattern)); +        } +      channel->nsort = options->nsort; +    } + +  channel->optmask = optmask; + +  return ARES_SUCCESS; +} + +static int init_by_environment(ares_channel channel) +{ +  const char *localdomain, *res_options; +  int status; + +  localdomain = getenv("LOCALDOMAIN"); +  if (localdomain && channel->ndomains == -1) +    { +      status = set_search(channel, localdomain); +      if (status != ARES_SUCCESS) +        return status; +    } + +  res_options = getenv("RES_OPTIONS"); +  if (res_options) +    { +      status = set_options(channel, res_options); +      if (status != ARES_SUCCESS) +        return status; +    } + +  return ARES_SUCCESS; +} + +#ifdef WIN32 +/* + * Warning: returns a dynamically allocated buffer, the user MUST + * use free() if the function returns 1 + */ +static int get_res_nt(HKEY hKey, const char *subkey, char **obuf) +{ +  /* Test for the size we need */ +  DWORD size = 0; +  int result; + +  result = RegQueryValueEx(hKey, subkey, 0, NULL, NULL, &size); +  if ((result != ERROR_SUCCESS && result != ERROR_MORE_DATA) || !size) +    return 0; +  *obuf = malloc(size+1); +  if (!*obuf) +    return 0; + +  if (RegQueryValueEx(hKey, subkey, 0, NULL, +                      (LPBYTE)*obuf, &size) != ERROR_SUCCESS) +  { +    free(*obuf); +    return 0; +  } +  if (size == 1) +  { +    free(*obuf); +    return 0; +  } +  return 1; +} + +static int get_res_interfaces_nt(HKEY hKey, const char *subkey, char **obuf) +{ +  char enumbuf[39]; /* GUIDs are 38 chars + 1 for NULL */ +  DWORD enum_size = 39; +  int idx = 0; +  HKEY hVal; + +  while (RegEnumKeyEx(hKey, idx++, enumbuf, &enum_size, 0, +                      NULL, NULL, NULL) != ERROR_NO_MORE_ITEMS) +  { +    int rc; + +    enum_size = 39; +    if (RegOpenKeyEx(hKey, enumbuf, 0, KEY_QUERY_VALUE, &hVal) != +        ERROR_SUCCESS) +      continue; +    rc = get_res_nt(hVal, subkey, obuf); +      RegCloseKey(hVal); +    if (rc) +      return 1; +    } +  return 0; +} + +static int get_iphlpapi_dns_info (char *ret_buf, size_t ret_size) +{ +  FIXED_INFO    *fi, *newfi; +  DWORD          size = sizeof (*fi); +  IP_ADDR_STRING *ipAddr; +  int            i, count = 0; +  int            debug  = 0; +  size_t         ip_size = sizeof("255.255.255.255,")-1; +  size_t         left = ret_size; +  char          *ret = ret_buf; +  HRESULT        res; + +  fi = malloc(size); +  if (!fi) +     return 0; + +  res = (*ares_fpGetNetworkParams) (fi, &size); +  if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS)) +     goto quit; + +  newfi = realloc(fi, size); +  if (!newfi) +     goto quit; + +  fi = newfi; +  res = (*ares_fpGetNetworkParams) (fi, &size); +  if (res != ERROR_SUCCESS) +     goto quit; + +  if (debug) +  { +    printf ("Host Name: %s\n", fi->HostName); +    printf ("Domain Name: %s\n", fi->DomainName); +    printf ("DNS Servers:\n" +            "    %s (primary)\n", fi->DnsServerList.IpAddress.String); +  } +  if (strlen(fi->DnsServerList.IpAddress.String) > 0 && +      inet_addr(fi->DnsServerList.IpAddress.String) != INADDR_NONE && +      left > ip_size) +  { +    ret += sprintf (ret, "%s,", fi->DnsServerList.IpAddress.String); +    left -= ret - ret_buf; +    count++; +  } + +  for (i = 0, ipAddr = fi->DnsServerList.Next; ipAddr && left > ip_size; +       ipAddr = ipAddr->Next, i++) +  { +    if (inet_addr(ipAddr->IpAddress.String) != INADDR_NONE) +    { +       ret += sprintf (ret, "%s,", ipAddr->IpAddress.String); +       left -= ret - ret_buf; +       count++; +    } +    if (debug) +       printf ("    %s (secondary %d)\n", ipAddr->IpAddress.String, i+1); +  } + +quit: +  if (fi) +     free(fi); + +  if (debug && left <= ip_size) +     printf ("Too many nameservers. Truncating to %d addressess", count); +  if (ret > ret_buf) +     ret[-1] = '\0'; +  return count; +} +#endif + +static int init_by_resolv_conf(ares_channel channel) +{ +#ifndef WATT32 +  char *line = NULL; +#endif +  int status = -1, nservers = 0, nsort = 0; +  struct server_state *servers = NULL; +  struct apattern *sortlist = NULL; + +#ifdef WIN32 + +    /* +  NameServer info via IPHLPAPI (IP helper API): +    GetNetworkParams() should be the trusted source for this. +    Available in Win-98/2000 and later. If that fail, fall-back to +    registry information. + +  NameServer Registry: + +   On Windows 9X, the DNS server can be found in: +HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxD\MSTCP\NameServer + +        On Windows NT/2000/XP/2003: +HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\NameServer +        or +HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\DhcpNameServer +        or +HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\{AdapterID}\ +NameServer +        or +HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\{AdapterID}\ +DhcpNameServer +   */ + +  HKEY mykey; +  HKEY subkey; +  DWORD data_type; +  DWORD bytes; +  DWORD result; +  char  buf[256]; + +  if (channel->nservers > -1)  /* don't override ARES_OPT_SERVER */ +     return ARES_SUCCESS; + +  if (get_iphlpapi_dns_info(buf,sizeof(buf)) > 0) +  { +    status = config_nameserver(&servers, &nservers, buf); +    if (status == ARES_SUCCESS) +      goto okay; +  } + +  if (IS_NT()) +  { +    if (RegOpenKeyEx( +          HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, +          KEY_READ, &mykey +          ) == ERROR_SUCCESS) +    { +      RegOpenKeyEx(mykey, "Interfaces", 0, +                   KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, &subkey); +      if (get_res_nt(mykey, NAMESERVER, &line)) +      { +        status = config_nameserver(&servers, &nservers, line); +        free(line); +      } +      else if (get_res_nt(mykey, DHCPNAMESERVER, &line)) +      { +        status = config_nameserver(&servers, &nservers, line); +        free(line); +      } +      /* Try the interfaces */ +      else if (get_res_interfaces_nt(subkey, NAMESERVER, &line)) +      { +        status = config_nameserver(&servers, &nservers, line); +        free(line); +      } +      else if (get_res_interfaces_nt(subkey, DHCPNAMESERVER, &line)) +      { +        status = config_nameserver(&servers, &nservers, line); +        free(line); +      } +      RegCloseKey(subkey); +      RegCloseKey(mykey); +    } +  } +  else +  { +    if (RegOpenKeyEx( +          HKEY_LOCAL_MACHINE, WIN_NS_9X, 0, +          KEY_READ, &mykey +          ) == ERROR_SUCCESS) +    { +      if ((result = RegQueryValueEx( +             mykey, NAMESERVER, NULL, &data_type, +             NULL, &bytes +             ) +            ) == ERROR_SUCCESS || +          result == ERROR_MORE_DATA) +      { +        if (bytes) +        { +          line = malloc(bytes+1); +          if (RegQueryValueEx(mykey, NAMESERVER, NULL, &data_type, +                              (unsigned char *)line, &bytes) == +              ERROR_SUCCESS) +          { +            status = config_nameserver(&servers, &nservers, line); +          } +          free(line); +        } +      } +    } +    RegCloseKey(mykey); +  } + +  if (status == ARES_SUCCESS) +    status = ARES_EOF; +  else +    /* Catch the case when all the above checks fail (which happens when there +       is no network card or the cable is unplugged) */ +    status = ARES_EFILE; + +#elif defined(__riscos__) + +  /* Under RISC OS, name servers are listed in the +     system variable Inet$Resolvers, space separated. */ + +  line = getenv("Inet$Resolvers"); +  status = ARES_EOF; +  if (line) { +    char *resolvers = strdup(line), *pos, *space; + +    if (!resolvers) +      return ARES_ENOMEM; + +    pos = resolvers; +    do { +      space = strchr(pos, ' '); +      if (space) +        *space = '\0'; +      status = config_nameserver(&servers, &nservers, pos); +      if (status != ARES_SUCCESS) +        break; +      pos = space + 1; +    } while (space); + +    if (status == ARES_SUCCESS) +      status = ARES_EOF; + +    free(resolvers); +  } + +#elif defined(WATT32) +  int i; + +  sock_init(); +  for (i = 0; def_nameservers[i]; i++) +      ; +  if (i == 0) +    return ARES_SUCCESS; /* use localhost DNS server */ + +  nservers = i; +  servers = calloc(i, sizeof(struct server_state)); +  if (!servers) +     return ARES_ENOMEM; + +  for (i = 0; def_nameservers[i]; i++) +      servers[i].addr.s_addr = htonl(def_nameservers[i]); +  status = ARES_EOF; + +#else +  { +    char *p; +    FILE *fp; +    size_t linesize; +    int error; + +    /* Don't read resolv.conf and friends if we don't have to */ +    if (ARES_CONFIG_CHECK(channel)) +        return ARES_SUCCESS; + +    fp = fopen(PATH_RESOLV_CONF, "r"); +    if (fp) { +      while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) +      { +        if ((p = try_config(line, "domain")) && channel->ndomains == -1) +          status = config_domain(channel, p); +        else if ((p = try_config(line, "lookup")) && !channel->lookups) +          status = config_lookup(channel, p, "bind", "file"); +        else if ((p = try_config(line, "search")) && channel->ndomains == -1) +          status = set_search(channel, p); +        else if ((p = try_config(line, "nameserver")) && channel->nservers == -1) +          status = config_nameserver(&servers, &nservers, p); +        else if ((p = try_config(line, "sortlist")) && channel->nsort == -1) +          status = config_sortlist(&sortlist, &nsort, p); +        else if ((p = try_config(line, "options"))) +          status = set_options(channel, p); +        else +          status = ARES_SUCCESS; +        if (status != ARES_SUCCESS) +          break; +      } +      fclose(fp); +    } +    else { +      error = ERRNO; +      switch(error) { +      case ENOENT: +      case ESRCH: +        status = ARES_EOF; +        break; +      default: +        DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", +                       error, strerror(error))); +        DEBUGF(fprintf(stderr, "Error opening file: %s\n", PATH_RESOLV_CONF)); +        status = ARES_EFILE; +      } +    } + +    if ((status == ARES_EOF) && (!channel->lookups)) { +      /* Many systems (Solaris, Linux, BSD's) use nsswitch.conf */ +      fp = fopen("/etc/nsswitch.conf", "r"); +      if (fp) { +        while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) +        { +          if ((p = try_config(line, "hosts:")) && !channel->lookups) +            status = config_lookup(channel, p, "dns", "files"); +        } +        fclose(fp); +      } +      else { +        error = ERRNO; +        switch(error) { +        case ENOENT: +        case ESRCH: +          status = ARES_EOF; +          break; +        default: +          DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", +                         error, strerror(error))); +          DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/nsswitch.conf")); +          status = ARES_EFILE; +        } +      } +    } + +    if ((status == ARES_EOF) && (!channel->lookups)) { +      /* Linux / GNU libc 2.x and possibly others have host.conf */ +      fp = fopen("/etc/host.conf", "r"); +      if (fp) { +        while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) +        { +          if ((p = try_config(line, "order")) && !channel->lookups) +            status = config_lookup(channel, p, "bind", "hosts"); +        } +        fclose(fp); +      } +      else { +        error = ERRNO; +        switch(error) { +        case ENOENT: +        case ESRCH: +          status = ARES_EOF; +          break; +        default: +          DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", +                         error, strerror(error))); +          DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/host.conf")); +          status = ARES_EFILE; +        } +      } +    } + +    if ((status == ARES_EOF) && (!channel->lookups)) { +      /* Tru64 uses /etc/svc.conf */ +      fp = fopen("/etc/svc.conf", "r"); +      if (fp) { +        while ((status = ares__read_line(fp, &line, &linesize)) == ARES_SUCCESS) +        { +          if ((p = try_config(line, "hosts=")) && !channel->lookups) +            status = config_lookup(channel, p, "bind", "local"); +        } +        fclose(fp); +      } +      else { +        error = ERRNO; +        switch(error) { +        case ENOENT: +        case ESRCH: +          status = ARES_EOF; +          break; +        default: +          DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", +                         error, strerror(error))); +          DEBUGF(fprintf(stderr, "Error opening file: %s\n", "/etc/svc.conf")); +          status = ARES_EFILE; +        } +      } +    } + +    if(line) +      free(line); +  } + +#endif + +  /* Handle errors. */ +  if (status != ARES_EOF) +    { +      if (servers != NULL) +        free(servers); +      if (sortlist != NULL) +        free(sortlist); +      return status; +    } + +  /* If we got any name server entries, fill them in. */ +#ifdef WIN32 +okay: +#endif +  if (servers) +    { +      channel->servers = servers; +      channel->nservers = nservers; +    } + +  /* If we got any sortlist entries, fill them in. */ +  if (sortlist) +    { +      channel->sortlist = sortlist; +      channel->nsort = nsort; +    } + +  return ARES_SUCCESS; +} + +static int init_by_defaults(ares_channel channel) +{ +  char *hostname = NULL; +  int rc = ARES_SUCCESS; +#ifdef HAVE_GETHOSTNAME +  char *dot; +#endif + +  if (channel->flags == -1) +    channel->flags = 0; +  if (channel->timeout == -1) +    channel->timeout = DEFAULT_TIMEOUT; +  if (channel->tries == -1) +    channel->tries = DEFAULT_TRIES; +  if (channel->ndots == -1) +    channel->ndots = 1; +  if (channel->rotate == -1) +    channel->rotate = 0; +  if (channel->udp_port == -1) +    channel->udp_port = htons(NAMESERVER_PORT); +  if (channel->tcp_port == -1) +    channel->tcp_port = htons(NAMESERVER_PORT); + +  if (channel->nservers == -1) { +    /* If nobody specified servers, try a local named. */ +    channel->servers = malloc(sizeof(struct server_state)); +    if (!channel->servers) { +      rc = ARES_ENOMEM; +      goto error; +    } +    channel->servers[0].addr.s_addr = htonl(INADDR_LOOPBACK); +    channel->nservers = 1; +  } + +#ifdef ENAMETOOLONG +#define toolong(x) (x == -1) && ((ENAMETOOLONG == errno) || (EINVAL == errno)) +#else +#define toolong(x) (x == -1) && (EINVAL == errno) +#endif + +  if (channel->ndomains == -1) { +    /* Derive a default domain search list from the kernel hostname, +     * or set it to empty if the hostname isn't helpful. +     */ +    size_t len = 64; +    int res; +    channel->ndomains = 0; /* default to none */ + +#ifdef HAVE_GETHOSTNAME +    hostname = malloc(len); +    if(!hostname) { +      rc = ARES_ENOMEM; +      goto error; +    } + +    do { +      res = gethostname(hostname, len); + +      if(toolong(res)) { +        char *p; +        len *= 2; +        p = realloc(hostname, len); +        if(!p) { +          rc = ARES_ENOMEM; +          goto error; +        } +        hostname = p; +        continue; +      } +      else if(res) { +        rc = ARES_EBADNAME; +        goto error; +      } + +    } while(0); + +    dot = strchr(hostname, '.'); +    if (dot) { +      /* a dot was found */ +      channel->domains = malloc(sizeof(char *)); +      if (!channel->domains) { +        rc = ARES_ENOMEM; +        goto error; +      } +      channel->domains[0] = strdup(dot + 1); +      if (!channel->domains[0]) { +        rc = ARES_ENOMEM; +        goto error; +      } +      channel->ndomains = 1; +    } +#endif +  } + +  if (channel->nsort == -1) { +    channel->sortlist = NULL; +    channel->nsort = 0; +  } + +  if (!channel->lookups) { +    channel->lookups = strdup("fb"); +    if (!channel->lookups) +      rc = ARES_ENOMEM; +  } + +  error: +  if(rc) { +    if(channel->servers) +      free(channel->servers); + +    if(channel->domains && channel->domains[0]) +      free(channel->domains[0]); +    if(channel->domains) +      free(channel->domains); +    if(channel->lookups) +      free(channel->lookups); +  } + +  if(hostname) +    free(hostname); + +  return rc; +} + +#if !defined(WIN32) && !defined(WATT32) +static int config_domain(ares_channel channel, char *str) +{ +  char *q; + +  /* Set a single search domain. */ +  q = str; +  while (*q && !ISSPACE(*q)) +    q++; +  *q = '\0'; +  return set_search(channel, str); +} + +#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \ +    defined(__OPTIMIZE__) && defined(__unix__) &&  defined(__i386__) +  /* workaround icc 9.1 optimizer issue */ +# define vqualifier volatile +#else +# define vqualifier +#endif + +static int config_lookup(ares_channel channel, const char *str, +                         const char *bindch, const char *filech) +{ +  char lookups[3], *l; +  const char *vqualifier p; + +  /* Set the lookup order.  Only the first letter of each work +   * is relevant, and it has to be "b" for DNS or "f" for the +   * host file.  Ignore everything else. +   */ +  l = lookups; +  p = str; +  while (*p) +    { +      if ((*p == *bindch || *p == *filech) && l < lookups + 2) { +        if (*p == *bindch) *l++ = 'b'; +        else *l++ = 'f'; +      } +      while (*p && !ISSPACE(*p) && (*p != ',')) +        p++; +      while (*p && (ISSPACE(*p) || (*p == ','))) +        p++; +    } +  *l = '\0'; +  channel->lookups = strdup(lookups); +  return (channel->lookups) ? ARES_SUCCESS : ARES_ENOMEM; +} +#endif  /* !WIN32 & !WATT32 */ + +#ifndef WATT32 +static int config_nameserver(struct server_state **servers, int *nservers, +                             char *str) +{ +  struct in_addr addr; +  struct server_state *newserv; +  /* On Windows, there may be more than one nameserver specified in the same +   * registry key, so we parse it as a space or comma seperated list. +   */ +#ifdef WIN32 +  char *p = str; +  char *begin = str; +  int more = 1; +  while (more) +  { +    more = 0; +    while (*p && !ISSPACE(*p) && *p != ',') +      p++; + +    if (*p) +    { +      *p = '\0'; +      more = 1; +    } + +    /* Skip multiple spaces or trailing spaces */ +    if (!*begin) +    { +      begin = ++p; +      continue; +    } + +    /* This is the part that actually sets the nameserver */ +    addr.s_addr = inet_addr(begin); +    if (addr.s_addr == INADDR_NONE) +      continue; +    newserv = realloc(*servers, (*nservers + 1) * sizeof(struct server_state)); +    if (!newserv) +      return ARES_ENOMEM; +    newserv[*nservers].addr = addr; +    *servers = newserv; +    (*nservers)++; + +    if (!more) +      break; +    begin = ++p; +  } +#else +  /* Add a nameserver entry, if this is a valid address. */ +  addr.s_addr = inet_addr(str); +  if (addr.s_addr == INADDR_NONE) +    return ARES_SUCCESS; +  newserv = realloc(*servers, (*nservers + 1) * sizeof(struct server_state)); +  if (!newserv) +    return ARES_ENOMEM; +  newserv[*nservers].addr = addr; +  *servers = newserv; +  (*nservers)++; +#endif +  return ARES_SUCCESS; +} + +#ifndef WIN32 +static int config_sortlist(struct apattern **sortlist, int *nsort, +                           const char *str) +{ +  struct apattern pat; +  const char *q; + +  /* Add sortlist entries. */ +  while (*str && *str != ';') +    { +      int bits; +      char ipbuf[16], ipbufpfx[32]; +      /* Find just the IP */ +      q = str; +      while (*q && *q != '/' && *q != ';' && !ISSPACE(*q)) +        q++; +      memcpy(ipbuf, str, (int)(q-str)); +      ipbuf[(int)(q-str)] = '\0'; +      /* Find the prefix */ +      if (*q == '/') +        { +          const char *str2 = q+1; +          while (*q && *q != ';' && !ISSPACE(*q)) +            q++; +          memcpy(ipbufpfx, str, (int)(q-str)); +          ipbufpfx[(int)(q-str)] = '\0'; +          str = str2; +        } +      else +        ipbufpfx[0] = '\0'; +      /* Lets see if it is CIDR */ +      /* First we'll try IPv6 */ +      if ((bits = ares_inet_net_pton(AF_INET6, ipbufpfx[0] ? ipbufpfx : ipbuf, +                                     &pat.addrV6, +                                     sizeof(pat.addrV6))) > 0) +        { +          pat.type = PATTERN_CIDR; +          pat.mask.bits = (unsigned short)bits; +          pat.family = AF_INET6; +          if (!sortlist_alloc(sortlist, nsort, &pat)) +            return ARES_ENOMEM; +        } +      if (ipbufpfx[0] && +          (bits = ares_inet_net_pton(AF_INET, ipbufpfx, &pat.addrV4, +                                     sizeof(pat.addrV4))) > 0) +        { +          pat.type = PATTERN_CIDR; +          pat.mask.bits = (unsigned short)bits; +          pat.family = AF_INET; +          if (!sortlist_alloc(sortlist, nsort, &pat)) +            return ARES_ENOMEM; +        } +      /* See if it is just a regular IP */ +      else if (ip_addr(ipbuf, (int)(q-str), &pat.addrV4) == 0) +        { +          if (ipbufpfx[0]) +            { +              memcpy(ipbuf, str, (int)(q-str)); +              ipbuf[(int)(q-str)] = '\0'; +              if (ip_addr(ipbuf, (int)(q - str), &pat.mask.addr4) != 0) +                natural_mask(&pat); +            } +          else +            natural_mask(&pat); +          pat.family = AF_INET; +          pat.type = PATTERN_MASK; +          if (!sortlist_alloc(sortlist, nsort, &pat)) +            return ARES_ENOMEM; +        } +      else +        { +          while (*q && *q != ';' && !ISSPACE(*q)) +            q++; +        } +      str = q; +      while (ISSPACE(*str)) +        str++; +    } + +  return ARES_SUCCESS; +} +#endif  /* !WIN32 */ +#endif  /* !WATT32 */ + +static int set_search(ares_channel channel, const char *str) +{ +  int n; +  const char *p, *q; + +  if(channel->ndomains != -1) { +    /* if we already have some domains present, free them first */ +    for(n=0; n < channel->ndomains; n++) +      free(channel->domains[n]); +    free(channel->domains); +    channel->domains = NULL; +    channel->ndomains = -1; +  } + +  /* Count the domains given. */ +  n = 0; +  p = str; +  while (*p) +    { +      while (*p && !ISSPACE(*p)) +        p++; +      while (ISSPACE(*p)) +        p++; +      n++; +    } + +  if (!n) +    { +      channel->ndomains = 0; +      return ARES_SUCCESS; +    } + +  channel->domains = malloc(n * sizeof(char *)); +  if (!channel->domains) +    return ARES_ENOMEM; + +  /* Now copy the domains. */ +  n = 0; +  p = str; +  while (*p) +    { +      channel->ndomains = n; +      q = p; +      while (*q && !ISSPACE(*q)) +        q++; +      channel->domains[n] = malloc(q - p + 1); +      if (!channel->domains[n]) +        return ARES_ENOMEM; +      memcpy(channel->domains[n], p, q - p); +      channel->domains[n][q - p] = 0; +      p = q; +      while (ISSPACE(*p)) +        p++; +      n++; +    } +  channel->ndomains = n; + +  return ARES_SUCCESS; +} + +static int set_options(ares_channel channel, const char *str) +{ +  const char *p, *q, *val; + +  p = str; +  while (*p) +    { +      q = p; +      while (*q && !ISSPACE(*q)) +        q++; +      val = try_option(p, q, "ndots:"); +      if (val && channel->ndots == -1) +        channel->ndots = atoi(val); +      val = try_option(p, q, "retrans:"); +      if (val && channel->timeout == -1) +        channel->timeout = atoi(val); +      val = try_option(p, q, "retry:"); +      if (val && channel->tries == -1) +        channel->tries = atoi(val); +      val = try_option(p, q, "rotate"); +      if (val && channel->rotate == -1) +        channel->rotate = 1; +      p = q; +      while (ISSPACE(*p)) +        p++; +    } + +  return ARES_SUCCESS; +} + +static const char *try_option(const char *p, const char *q, const char *opt) +{ +  size_t len = strlen(opt); +  return ((size_t)(q - p) >= len && !strncmp(p, opt, len)) ? &p[len] : NULL; +} + +#if !defined(WIN32) && !defined(WATT32) +static char *try_config(char *s, const char *opt) +{ +  size_t len; +  char *p; +  char *q; + +  if (!s || !opt) +    /* no line or no option */ +    return NULL; + +  /* trim line comment */ +  p = s; +  while (*p && (*p != '#')) +    p++; +  *p = '\0'; + +  /* trim trailing whitespace */ +  q = p - 1; +  while ((q >= s) && ISSPACE(*q)) +    q--; +  *++q = '\0'; + +  /* skip leading whitespace */ +  p = s; +  while (*p && ISSPACE(*p)) +    p++; + +  if (!*p) +    /* empty line */ +    return NULL; + +  if ((len = strlen(opt)) == 0) +    /* empty option */ +    return NULL; + +  if (strncmp(p, opt, len) != 0) +    /* line and option do not match */ +    return NULL; + +  /* skip over given option name */ +  p += len; + +  if (!*p) +    /* no option value */ +    return NULL; + +  if ((opt[len-1] != ':') && (opt[len-1] != '=') && !ISSPACE(*p)) +    /* whitespace between option name and value is mandatory +       for given option names which do not end with ':' or '=' */ +    return NULL; + +  /* skip over whitespace */ +  while (*p && ISSPACE(*p)) +    p++; + +  if (!*p) +    /* no option value */ +    return NULL; + +  /* return pointer to option value */ +  return p; +} + +static int sortlist_alloc(struct apattern **sortlist, int *nsort, +                          struct apattern *pat) +{ +  struct apattern *newsort; +  newsort = realloc(*sortlist, (*nsort + 1) * sizeof(struct apattern)); +  if (!newsort) +    return 0; +  newsort[*nsort] = *pat; +  *sortlist = newsort; +  (*nsort)++; +  return 1; +} + +static int ip_addr(const char *ipbuf, int len, struct in_addr *addr) +{ + +  /* Four octets and three periods yields at most 15 characters. */ +  if (len > 15) +    return -1; + +  addr->s_addr = inet_addr(ipbuf); +  if (addr->s_addr == INADDR_NONE && strcmp(ipbuf, "255.255.255.255") != 0) +    return -1; +  return 0; +} + +static void natural_mask(struct apattern *pat) +{ +  struct in_addr addr; + +  /* Store a host-byte-order copy of pat in a struct in_addr.  Icky, +   * but portable. +   */ +  addr.s_addr = ntohl(pat->addrV4.s_addr); + +  /* This is out of date in the CIDR world, but some people might +   * still rely on it. +   */ +  if (IN_CLASSA(addr.s_addr)) +    pat->mask.addr4.s_addr = htonl(IN_CLASSA_NET); +  else if (IN_CLASSB(addr.s_addr)) +    pat->mask.addr4.s_addr = htonl(IN_CLASSB_NET); +  else +    pat->mask.addr4.s_addr = htonl(IN_CLASSC_NET); +} +#endif /* !WIN32 && !WATT32 */ + +/* initialize an rc4 key. If possible a cryptographically secure random key +   is generated using a suitable function (for example win32's RtlGenRandom as +   described in +   http://blogs.msdn.com/michael_howard/archive/2005/01/14/353379.aspx +   otherwise the code defaults to cross-platform albeit less secure mechanism +   using rand +*/ +static void randomize_key(unsigned char* key,int key_data_len) +{ +  int randomized = 0; +  int counter=0; +#ifdef WIN32 +  BOOLEAN res; +  if (ares_fpSystemFunction036) +    { +      res = (*ares_fpSystemFunction036) (key, key_data_len); +      if (res) +        randomized = 1; +    } +#else /* !WIN32 */ +#ifdef RANDOM_FILE +  FILE *f = fopen(RANDOM_FILE, "rb"); +  if(f) { +    counter = fread(key, 1, key_data_len, f); +    fclose(f); +  } +#endif +#endif /* WIN32 */ + +  if ( !randomized ) { +    for (;counter<key_data_len;counter++) +      key[counter]=(unsigned char)(rand() % 256); +  } +} + +static int init_id_key(rc4_key* key,int key_data_len) +{ +  unsigned char index1; +  unsigned char index2; +  unsigned char* state; +  short counter; +  unsigned char *key_data_ptr = 0; + +  key_data_ptr = calloc(1,key_data_len); +  if (!key_data_ptr) +    return ARES_ENOMEM; + +  state = &key->state[0]; +  for(counter = 0; counter < 256; counter++) +    /* unnecessary AND but it keeps some compilers happier */ +    state[counter] = (unsigned char)(counter & 0xff); +  randomize_key(key->state,key_data_len); +  key->x = 0; +  key->y = 0; +  index1 = 0; +  index2 = 0; +  for(counter = 0; counter < 256; counter++) +  { +    index2 = (unsigned char)((key_data_ptr[index1] + state[counter] + +                              index2) % 256); +    ARES_SWAP_BYTE(&state[counter], &state[index2]); + +    index1 = (unsigned char)((index1 + 1) % key_data_len); +  } +  free(key_data_ptr); +  return ARES_SUCCESS; +} + +unsigned short ares__generate_new_id(rc4_key* key) +{ +  unsigned short r=0; +  ares__rc4(key, (unsigned char *)&r, sizeof(r)); +  return r; +} + +void ares_set_socket_callback(ares_channel channel, +                              ares_sock_create_callback cb, +                              void *data) +{ +  channel->sock_create_cb = cb; +  channel->sock_create_cb_data = data; +} diff --git a/3rdParty/CAres/src/ares_ipv6.h b/3rdParty/CAres/src/ares_ipv6.h new file mode 100644 index 0000000..18914d1 --- /dev/null +++ b/3rdParty/CAres/src/ares_ipv6.h @@ -0,0 +1,84 @@ +/* $Id: ares_ipv6.h,v 1.9 2009-05-02 02:36:48 yangtse Exp $ */ + +/* Copyright (C) 2005 by Dominick Meglio + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#ifndef ARES_IPV6_H +#define ARES_IPV6_H + +#ifndef HAVE_PF_INET6 +#define PF_INET6 AF_INET6 +#endif + +#if !defined(HAVE_STRUCT_IN6_ADDR) && !defined(s6_addr) +struct in6_addr { +  union { +    unsigned char _S6_u8[16]; +  } _S6_un; +}; +#define s6_addr _S6_un._S6_u8 +#endif + +#ifndef HAVE_STRUCT_SOCKADDR_IN6 +struct sockaddr_in6 +{ +  unsigned short  sin6_family; +  unsigned short  sin6_port; +  unsigned long   sin6_flowinfo; +  struct in6_addr sin6_addr; +  unsigned int    sin6_scope_id; +}; +#endif + +#ifndef HAVE_STRUCT_ADDRINFO +struct addrinfo +{ +  int              ai_flags; +  int              ai_family; +  int              ai_socktype; +  int              ai_protocol; +  ares_socklen_t   ai_addrlen;   /* Follow rfc3493 struct addrinfo */ +  char            *ai_canonname; +  struct sockaddr *ai_addr; +  struct addrinfo *ai_next; +}; +#endif + +#ifndef NS_IN6ADDRSZ +#if SIZEOF_STRUCT_IN6_ADDR == 0 +/* We cannot have it set to zero, so we pick a fixed value here */ +#define NS_IN6ADDRSZ 16 +#else +#define NS_IN6ADDRSZ SIZEOF_STRUCT_IN6_ADDR +#endif +#endif + +#ifndef NS_INADDRSZ +#define NS_INADDRSZ SIZEOF_STRUCT_IN_ADDR +#endif + +#ifndef NS_INT16SZ +#define NS_INT16SZ 2 +#endif + +#ifndef IF_NAMESIZE +#ifdef IFNAMSIZ +#define IF_NAMESIZE IFNAMSIZ +#else +#define IF_NAMESIZE 256 +#endif +#endif + +#endif /* ARES_IPV6_H */ diff --git a/3rdParty/CAres/src/ares_library_init.c b/3rdParty/CAres/src/ares_library_init.c new file mode 100644 index 0000000..049cfa4 --- /dev/null +++ b/3rdParty/CAres/src/ares_library_init.c @@ -0,0 +1,133 @@ +/* $Id: ares_library_init.c,v 1.11 2009-11-11 08:56:47 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * Copyright (C) 2004-2009 by Daniel Stenberg + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#include "ares.h" +#include "ares_library_init.h" +#include "ares_private.h" + +/* library-private global and unique instance vars */ + +#ifdef USE_WINSOCK +fpGetNetworkParams_t ares_fpGetNetworkParams = ZERO_NULL; +fpSystemFunction036_t ares_fpSystemFunction036 = ZERO_NULL; +#endif + +/* library-private global vars with source visibility restricted to this file */ + +static unsigned int ares_initialized; +static int          ares_init_flags; + +#ifdef USE_WINSOCK +static HMODULE hnd_iphlpapi; +static HMODULE hnd_advapi32; +#endif + + +static int ares_win32_init(void) +{ +#ifdef USE_WINSOCK + +  hnd_iphlpapi = 0; +  hnd_iphlpapi = LoadLibrary("iphlpapi.dll"); +  if (!hnd_iphlpapi) +    return ARES_ELOADIPHLPAPI; + +  ares_fpGetNetworkParams = (fpGetNetworkParams_t) +    GetProcAddress(hnd_iphlpapi, "GetNetworkParams"); +  if (!ares_fpGetNetworkParams) +    { +      FreeLibrary(hnd_iphlpapi); +      return ARES_EADDRGETNETWORKPARAMS; +    } + +  /* +   * When advapi32.dll is unavailable or advapi32.dll has no SystemFunction036, +   * also known as RtlGenRandom, which is the case for Windows versions prior +   * to WinXP then c-ares uses portable rand() function. Then don't error here. +   */ + +  hnd_advapi32 = 0; +  hnd_advapi32 = LoadLibrary("advapi32.dll"); +  if (hnd_advapi32) +    { +      ares_fpSystemFunction036 = (fpSystemFunction036_t) +        GetProcAddress(hnd_advapi32, "SystemFunction036"); +    } + +#endif +  return ARES_SUCCESS; +} + + +static void ares_win32_cleanup(void) +{ +#ifdef USE_WINSOCK +  if (hnd_advapi32) +    FreeLibrary(hnd_advapi32); +  if (hnd_iphlpapi) +    FreeLibrary(hnd_iphlpapi); +#endif +} + + +int ares_library_init(int flags) +{ +  int res; + +  if (ares_initialized) +    return ARES_SUCCESS; +  ares_initialized++; + +  if (flags & ARES_LIB_INIT_WIN32) +    { +      res = ares_win32_init(); +      if (res != ARES_SUCCESS) +        return res; +    } + +  ares_init_flags = flags; + +  return ARES_SUCCESS; +} + + +void ares_library_cleanup(void) +{ +  if (!ares_initialized) +    return; +  ares_initialized--; + +  if (ares_init_flags & ARES_LIB_INIT_WIN32) +    ares_win32_cleanup(); + +  ares_init_flags = ARES_LIB_INIT_NONE; +} + + +int ares_library_initialized(void) +{ +#ifdef USE_WINSOCK +  if (!ares_initialized) +    return ARES_ENOTINITIALIZED; +#endif +  return ARES_SUCCESS; +} + + diff --git a/3rdParty/CAres/src/ares_library_init.h b/3rdParty/CAres/src/ares_library_init.h new file mode 100644 index 0000000..a81d855 --- /dev/null +++ b/3rdParty/CAres/src/ares_library_init.h @@ -0,0 +1,40 @@ +#ifndef HEADER_CARES_LIBRARY_INIT_H +#define HEADER_CARES_LIBRARY_INIT_H + +/* $Id: ares_library_init.h,v 1.5 2009-11-11 08:56:47 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * Copyright (C) 2004-2009 by Daniel Stenberg + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef USE_WINSOCK + +#include <iphlpapi.h> + +typedef DWORD (WINAPI *fpGetNetworkParams_t) (FIXED_INFO*, DWORD*); +typedef BOOLEAN (APIENTRY *fpSystemFunction036_t) (void*, ULONG); + +/* Forward-declaration of variables defined in ares_library_init.c */ +/* that are global and unique instances for whole c-ares library.  */ + +extern fpGetNetworkParams_t ares_fpGetNetworkParams; +extern fpSystemFunction036_t ares_fpSystemFunction036; + +#endif /* USE_WINSOCK */ + +#endif /* HEADER_CARES_LIBRARY_INIT_H */ + diff --git a/3rdParty/CAres/src/ares_llist.c b/3rdParty/CAres/src/ares_llist.c new file mode 100644 index 0000000..c820ed1 --- /dev/null +++ b/3rdParty/CAres/src/ares_llist.c @@ -0,0 +1,87 @@ +/* $Id: ares_llist.c,v 1.2 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#include "ares.h" +#include "ares_private.h" + +/* Routines for managing doubly-linked circular linked lists with a + * dummy head. + */ + +/* Initialize a new head node */ +void ares__init_list_head(struct list_node* head) { +  head->prev = head; +  head->next = head; +  head->data = NULL; +} + +/* Initialize a list node */ +void ares__init_list_node(struct list_node* node, void* d) { +  node->prev = NULL; +  node->next = NULL; +  node->data = d; +} + +/* Returns true iff the given list is empty */ +int ares__is_list_empty(struct list_node* head) { +  return ((head->next == head) && (head->prev == head)); +} + +/* Inserts new_node before old_node */ +void ares__insert_in_list(struct list_node* new_node, +                          struct list_node* old_node) { +  new_node->next = old_node; +  new_node->prev = old_node->prev; +  old_node->prev->next = new_node; +  old_node->prev = new_node; +} + +/* Removes the node from the list it's in, if any */ +void ares__remove_from_list(struct list_node* node) { +  if (node->next != NULL) { +    node->prev->next = node->next; +    node->next->prev = node->prev; +    node->prev = NULL; +    node->next = NULL; +  } +} + +/* Swap the contents of two lists */ +void ares__swap_lists(struct list_node* head_a, +                      struct list_node* head_b) { +  int is_a_empty = ares__is_list_empty(head_a); +  int is_b_empty = ares__is_list_empty(head_b); +  struct list_node old_a = *head_a; +  struct list_node old_b = *head_b; + +  if (is_a_empty) { +    ares__init_list_head(head_b); +  } else { +    *head_b = old_a; +    old_a.next->prev = head_b; +    old_a.prev->next = head_b; +  } +  if (is_b_empty) { +    ares__init_list_head(head_a); +  } else { +    *head_a = old_b; +    old_b.next->prev = head_a; +    old_b.prev->next = head_a; +  } +} diff --git a/3rdParty/CAres/src/ares_llist.h b/3rdParty/CAres/src/ares_llist.h new file mode 100644 index 0000000..4875b3f --- /dev/null +++ b/3rdParty/CAres/src/ares_llist.h @@ -0,0 +1,43 @@ +#ifndef __ARES_LLIST_H +#define __ARES_LLIST_H + +/* $Id: ares_llist.h,v 1.1 2007-10-02 02:18:01 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + + +/* Node definition for circular, doubly-linked list */ +struct list_node { +  struct list_node *prev; +  struct list_node *next; +  void* data; +}; + +void ares__init_list_head(struct list_node* head); + +void ares__init_list_node(struct list_node* node, void* d); + +int ares__is_list_empty(struct list_node* head); + +void ares__insert_in_list(struct list_node* new_node, +                          struct list_node* old_node); + +void ares__remove_from_list(struct list_node* node); + +void ares__swap_lists(struct list_node* head_a, +                      struct list_node* head_b); + +#endif /* __ARES_LLIST_H */ diff --git a/3rdParty/CAres/src/ares_mkquery.c b/3rdParty/CAres/src/ares_mkquery.c new file mode 100644 index 0000000..04d2b6d --- /dev/null +++ b/3rdParty/CAres/src/ares_mkquery.c @@ -0,0 +1,196 @@ +/* $Id: ares_mkquery.c,v 1.17 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_SYS_SOCKET_H +#  include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#  include <netinet/in.h> +#endif +#ifdef HAVE_ARPA_NAMESER_H +#  include <arpa/nameser.h> +#else +#  include "nameser.h" +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +#  include <arpa/nameser_compat.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include "ares.h" +#include "ares_dns.h" +#include "ares_private.h" + +/* Header format, from RFC 1035: + *                                  1  1  1  1  1  1 + *    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5 + *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + *  |                      ID                       | + *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + *  |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   | + *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + *  |                    QDCOUNT                    | + *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + *  |                    ANCOUNT                    | + *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + *  |                    NSCOUNT                    | + *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + *  |                    ARCOUNT                    | + *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * + * AA, TC, RA, and RCODE are only set in responses.  Brief description + * of the remaining fields: + *      ID      Identifier to match responses with queries + *      QR      Query (0) or response (1) + *      Opcode  For our purposes, always QUERY + *      RD      Recursion desired + *      Z       Reserved (zero) + *      QDCOUNT Number of queries + *      ANCOUNT Number of answers + *      NSCOUNT Number of name server records + *      ARCOUNT Number of additional records + * + * Question format, from RFC 1035: + *                                  1  1  1  1  1  1 + *    0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5 + *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + *  |                                               | + *  /                     QNAME                     / + *  /                                               / + *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + *  |                     QTYPE                     | + *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + *  |                     QCLASS                    | + *  +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + * + * The query name is encoded as a series of labels, each represented + * as a one-byte length (maximum 63) followed by the text of the + * label.  The list is terminated by a label of length zero (which can + * be thought of as the root domain). + */ + +int ares_mkquery(const char *name, int dnsclass, int type, unsigned short id, +                 int rd, unsigned char **buf, int *buflen) +{ +  int len; +  unsigned char *q; +  const char *p; + +  /* Set our results early, in case we bail out early with an error. */ +  *buflen = 0; +  *buf = NULL; + +  /* Compute the length of the encoded name so we can check buflen. +   * Start counting at 1 for the zero-length label at the end. */ +  len = 1; +  for (p = name; *p; p++) +    { +      if (*p == '\\' && *(p + 1) != 0) +        p++; +      len++; +    } +  /* If there are n periods in the name, there are n + 1 labels, and +   * thus n + 1 length fields, unless the name is empty or ends with a +   * period.  So add 1 unless name is empty or ends with a period. +   */ +  if (*name && *(p - 1) != '.') +    len++; + +  /* Immediately reject names that are longer than the maximum of 255 +   * bytes that's specified in RFC 1035 ("To simplify implementations, +   * the total length of a domain name (i.e., label octets and label +   * length octets) is restricted to 255 octets or less."). We aren't +   * doing this just to be a stickler about RFCs. For names that are +   * too long, 'dnscache' closes its TCP connection to us immediately +   * (when using TCP) and ignores the request when using UDP, and +   * BIND's named returns ServFail (TCP or UDP). Sending a request +   * that we know will cause 'dnscache' to close the TCP connection is +   * painful, since that makes any other outstanding requests on that +   * connection fail. And sending a UDP request that we know +   * 'dnscache' will ignore is bad because resources will be tied up +   * until we time-out the request. +   */ +  if (len > MAXCDNAME) +    return ARES_EBADNAME; + +  *buflen = len + HFIXEDSZ + QFIXEDSZ; +  *buf = malloc(*buflen); +  if (!*buf) +      return ARES_ENOMEM; + +  /* Set up the header. */ +  q = *buf; +  memset(q, 0, HFIXEDSZ); +  DNS_HEADER_SET_QID(q, id); +  DNS_HEADER_SET_OPCODE(q, QUERY); +  if (rd) { +    DNS_HEADER_SET_RD(q, 1); +  } +  else { +    DNS_HEADER_SET_RD(q, 0); +  } +  DNS_HEADER_SET_QDCOUNT(q, 1); + +  /* A name of "." is a screw case for the loop below, so adjust it. */ +  if (strcmp(name, ".") == 0) +    name++; + +  /* Start writing out the name after the header. */ +  q += HFIXEDSZ; +  while (*name) +    { +      if (*name == '.') +        return ARES_EBADNAME; + +      /* Count the number of bytes in this label. */ +      len = 0; +      for (p = name; *p && *p != '.'; p++) +        { +          if (*p == '\\' && *(p + 1) != 0) +            p++; +          len++; +        } +      if (len > MAXLABEL) +        return ARES_EBADNAME; + +      /* Encode the length and copy the data. */ +      *q++ = (unsigned char)len; +      for (p = name; *p && *p != '.'; p++) +        { +          if (*p == '\\' && *(p + 1) != 0) +            p++; +          *q++ = *p; +        } + +      /* Go to the next label and repeat, unless we hit the end. */ +      if (!*p) +        break; +      name = p + 1; +    } + +  /* Add the zero-length label at the end. */ +  *q++ = 0; + +  /* Finish off the question with the type and class. */ +  DNS_QUESTION_SET_TYPE(q, type); +  DNS_QUESTION_SET_CLASS(q, dnsclass); + +  return ARES_SUCCESS; +} diff --git a/3rdParty/CAres/src/ares_parse_a_reply.c b/3rdParty/CAres/src/ares_parse_a_reply.c new file mode 100644 index 0000000..801c193 --- /dev/null +++ b/3rdParty/CAres/src/ares_parse_a_reply.c @@ -0,0 +1,257 @@ +/* $Id: ares_parse_a_reply.c,v 1.20 2009-11-23 01:24:17 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_SYS_SOCKET_H +#  include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#  include <netinet/in.h> +#endif +#ifdef HAVE_NETDB_H +#  include <netdb.h> +#endif +#ifdef HAVE_ARPA_INET_H +#  include <arpa/inet.h> +#endif +#ifdef HAVE_ARPA_NAMESER_H +#  include <arpa/nameser.h> +#else +#  include "nameser.h" +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +#  include <arpa/nameser_compat.h> +#endif + +#ifdef HAVE_STRINGS_H +#  include <strings.h> +#endif + +#include <stdlib.h> +#include <string.h> +#ifdef HAVE_LIMITS_H +#  include <limits.h> +#endif + +#include "ares.h" +#include "ares_dns.h" +#include "ares_private.h" + +int ares_parse_a_reply(const unsigned char *abuf, int alen, +                       struct hostent **host, +                       struct ares_addrttl *addrttls, int *naddrttls) +{ +  unsigned int qdcount, ancount; +  int status, i, rr_type, rr_class, rr_len, rr_ttl, naddrs; +  int cname_ttl = INT_MAX;  /* the TTL imposed by the CNAME chain */ +  int naliases; +  long len; +  const unsigned char *aptr; +  char *hostname, *rr_name, *rr_data, **aliases; +  struct in_addr *addrs; +  struct hostent *hostent; +  const int max_addr_ttls = (addrttls && naddrttls) ? *naddrttls : 0; + +  /* Set *host to NULL for all failure cases. */ +  if (host) +    *host = NULL; +  /* Same with *naddrttls. */ +  if (naddrttls) +    *naddrttls = 0; + +  /* Give up if abuf doesn't have room for a header. */ +  if (alen < HFIXEDSZ) +    return ARES_EBADRESP; + +  /* Fetch the question and answer count from the header. */ +  qdcount = DNS_HEADER_QDCOUNT(abuf); +  ancount = DNS_HEADER_ANCOUNT(abuf); +  if (qdcount != 1) +    return ARES_EBADRESP; + +  /* Expand the name from the question, and skip past the question. */ +  aptr = abuf + HFIXEDSZ; +  status = ares__expand_name_for_response(aptr, abuf, alen, &hostname, &len); +  if (status != ARES_SUCCESS) +    return status; +  if (aptr + len + QFIXEDSZ > abuf + alen) +    { +      free(hostname); +      return ARES_EBADRESP; +    } +  aptr += len + QFIXEDSZ; + +  if (host) +    { +      /* Allocate addresses and aliases; ancount gives an upper bound for +         both. */ +      addrs = malloc(ancount * sizeof(struct in_addr)); +      if (!addrs) +        { +          free(hostname); +          return ARES_ENOMEM; +        } +      aliases = malloc((ancount + 1) * sizeof(char *)); +      if (!aliases) +        { +          free(hostname); +          free(addrs); +          return ARES_ENOMEM; +        } +    } +  else +    { +      addrs = NULL; +      aliases = NULL; +    } + +  naddrs = 0; +  naliases = 0; + +  /* Examine each answer resource record (RR) in turn. */ +  for (i = 0; i < (int)ancount; i++) +    { +      /* Decode the RR up to the data field. */ +      status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len); +      if (status != ARES_SUCCESS) +        break; +      aptr += len; +      if (aptr + RRFIXEDSZ > abuf + alen) +        { +          status = ARES_EBADRESP; +          break; +        } +      rr_type = DNS_RR_TYPE(aptr); +      rr_class = DNS_RR_CLASS(aptr); +      rr_len = DNS_RR_LEN(aptr); +      rr_ttl = DNS_RR_TTL(aptr); +      aptr += RRFIXEDSZ; + +      if (rr_class == C_IN && rr_type == T_A +          && rr_len == sizeof(struct in_addr) +          && strcasecmp(rr_name, hostname) == 0) +        { +          if (addrs) +            { +              if (aptr + sizeof(struct in_addr) > abuf + alen) +              { +                status = ARES_EBADRESP; +                break; +              } +              memcpy(&addrs[naddrs], aptr, sizeof(struct in_addr)); +            } +          if (naddrs < max_addr_ttls) +            { +              struct ares_addrttl * const at = &addrttls[naddrs]; +              if (aptr + sizeof(struct in_addr) > abuf + alen) +              { +                status = ARES_EBADRESP; +                break; +              } +              memcpy(&at->ipaddr, aptr,  sizeof(struct in_addr)); +              at->ttl = rr_ttl; +            } +          naddrs++; +          status = ARES_SUCCESS; +        } + +      if (rr_class == C_IN && rr_type == T_CNAME) +        { +          /* Record the RR name as an alias. */ +          if (aliases) +            aliases[naliases] = rr_name; +          else +            free(rr_name); +          naliases++; + +          /* Decode the RR data and replace the hostname with it. */ +          status = ares__expand_name_for_response(aptr, abuf, alen, &rr_data, +                                                  &len); +          if (status != ARES_SUCCESS) +            break; +          free(hostname); +          hostname = rr_data; + +          /* Take the min of the TTLs we see in the CNAME chain. */ +          if (cname_ttl > rr_ttl) +            cname_ttl = rr_ttl; +        } +      else +        free(rr_name); + +      aptr += rr_len; +      if (aptr > abuf + alen) +        { +          status = ARES_EBADRESP; +          break; +        } +    } + +  if (status == ARES_SUCCESS && naddrs == 0) +    status = ARES_ENODATA; +  if (status == ARES_SUCCESS) +    { +      /* We got our answer. */ +      if (naddrttls) +        { +          const int n = naddrs < max_addr_ttls ? naddrs : max_addr_ttls; +          for (i = 0; i < n; i++) +            { +              /* Ensure that each A TTL is no larger than the CNAME TTL. */ +              if (addrttls[i].ttl > cname_ttl) +                addrttls[i].ttl = cname_ttl; +            } +          *naddrttls = n; +        } +      if (aliases) +        aliases[naliases] = NULL; +      if (host) +        { +          /* Allocate memory to build the host entry. */ +          hostent = malloc(sizeof(struct hostent)); +          if (hostent) +            { +              hostent->h_addr_list = malloc((naddrs + 1) * sizeof(char *)); +              if (hostent->h_addr_list) +                { +                  /* Fill in the hostent and return successfully. */ +                  hostent->h_name = hostname; +                  hostent->h_aliases = aliases; +                  hostent->h_addrtype = AF_INET; +                  hostent->h_length = sizeof(struct in_addr); +                  for (i = 0; i < naddrs; i++) +                    hostent->h_addr_list[i] = (char *) &addrs[i]; +                  hostent->h_addr_list[naddrs] = NULL; +                  *host = hostent; +                  return ARES_SUCCESS; +                } +              free(hostent); +            } +          status = ARES_ENOMEM; +        } +     } +  if (aliases) +    { +      for (i = 0; i < naliases; i++) +        free(aliases[i]); +      free(aliases); +    } +  free(addrs); +  free(hostname); +  return status; +} diff --git a/3rdParty/CAres/src/ares_parse_aaaa_reply.c b/3rdParty/CAres/src/ares_parse_aaaa_reply.c new file mode 100644 index 0000000..c2329cc --- /dev/null +++ b/3rdParty/CAres/src/ares_parse_aaaa_reply.c @@ -0,0 +1,257 @@ +/* $Id: ares_parse_aaaa_reply.c,v 1.16 2009-11-23 01:24:17 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * Copyright 2005 Dominick Meglio + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_SYS_SOCKET_H +#  include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#  include <netinet/in.h> +#endif +#ifdef HAVE_NETDB_H +#  include <netdb.h> +#endif +#ifdef HAVE_ARPA_INET_H +#  include <arpa/inet.h> +#endif +#ifdef HAVE_ARPA_NAMESER_H +#  include <arpa/nameser.h> +#else +#  include "nameser.h" +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +#  include <arpa/nameser_compat.h> +#endif + +#ifdef HAVE_STRINGS_H +#  include <strings.h> +#endif + +#include <stdlib.h> +#include <string.h> +#ifdef HAVE_LIMITS_H +#  include <limits.h> +#endif + +#include "ares.h" +#include "ares_dns.h" +#include "inet_net_pton.h" +#include "ares_private.h" + +int ares_parse_aaaa_reply(const unsigned char *abuf, int alen, +                          struct hostent **host, struct ares_addr6ttl *addrttls, +                          int *naddrttls) +{ +  unsigned int qdcount, ancount; +  int status, i, rr_type, rr_class, rr_len, rr_ttl, naddrs; +  int cname_ttl = INT_MAX;  /* the TTL imposed by the CNAME chain */ +  int naliases; +  long len; +  const unsigned char *aptr; +  char *hostname, *rr_name, *rr_data, **aliases; +  struct in6_addr *addrs; +  struct hostent *hostent; +  const int max_addr_ttls = (addrttls && naddrttls) ? *naddrttls : 0; + +  /* Set *host to NULL for all failure cases. */ +  if (host) +    *host = NULL; +  /* Same with *naddrttls. */ +  if (naddrttls) +    *naddrttls = 0; + +  /* Give up if abuf doesn't have room for a header. */ +  if (alen < HFIXEDSZ) +    return ARES_EBADRESP; + +  /* Fetch the question and answer count from the header. */ +  qdcount = DNS_HEADER_QDCOUNT(abuf); +  ancount = DNS_HEADER_ANCOUNT(abuf); +  if (qdcount != 1) +    return ARES_EBADRESP; + +  /* Expand the name from the question, and skip past the question. */ +  aptr = abuf + HFIXEDSZ; +  status = ares__expand_name_for_response(aptr, abuf, alen, &hostname, &len); +  if (status != ARES_SUCCESS) +    return status; +  if (aptr + len + QFIXEDSZ > abuf + alen) +    { +      free(hostname); +      return ARES_EBADRESP; +    } +  aptr += len + QFIXEDSZ; + +  /* Allocate addresses and aliases; ancount gives an upper bound for both. */ +  if (host) +    { +      addrs = malloc(ancount * sizeof(struct in6_addr)); +      if (!addrs) +        { +          free(hostname); +          return ARES_ENOMEM; +        } +      aliases = malloc((ancount + 1) * sizeof(char *)); +      if (!aliases) +        { +          free(hostname); +          free(addrs); +          return ARES_ENOMEM; +        } +    } +  else +    { +      addrs = NULL; +      aliases = NULL; +    } +  naddrs = 0; +  naliases = 0; + +  /* Examine each answer resource record (RR) in turn. */ +  for (i = 0; i < (int)ancount; i++) +    { +      /* Decode the RR up to the data field. */ +      status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len); +      if (status != ARES_SUCCESS) +        break; +      aptr += len; +      if (aptr + RRFIXEDSZ > abuf + alen) +        { +          status = ARES_EBADRESP; +          break; +        } +      rr_type = DNS_RR_TYPE(aptr); +      rr_class = DNS_RR_CLASS(aptr); +      rr_len = DNS_RR_LEN(aptr); +      rr_ttl = DNS_RR_TTL(aptr); +      aptr += RRFIXEDSZ; + +      if (rr_class == C_IN && rr_type == T_AAAA +          && rr_len == sizeof(struct in6_addr) +          && strcasecmp(rr_name, hostname) == 0) +        { +          if (addrs) +            { +              if (aptr + sizeof(struct in6_addr) > abuf + alen) +              { +                status = ARES_EBADRESP; +                break; +              } +              memcpy(&addrs[naddrs], aptr, sizeof(struct in6_addr)); +            } +          if (naddrs < max_addr_ttls) +            { +              struct ares_addr6ttl * const at = &addrttls[naddrs]; +              if (aptr + sizeof(struct in6_addr) > abuf + alen) +              { +                status = ARES_EBADRESP; +                break; +              } +              memcpy(&at->ip6addr, aptr,  sizeof(struct in6_addr)); +              at->ttl = rr_ttl; +            } +          naddrs++; +          status = ARES_SUCCESS; +        } + +      if (rr_class == C_IN && rr_type == T_CNAME) +        { +          /* Record the RR name as an alias. */ +          if (aliases) +            aliases[naliases] = rr_name; +          else +            free(rr_name); +          naliases++; + +          /* Decode the RR data and replace the hostname with it. */ +          status = ares__expand_name_for_response(aptr, abuf, alen, &rr_data, +                                                  &len); +          if (status != ARES_SUCCESS) +            break; +          free(hostname); +          hostname = rr_data; + +          /* Take the min of the TTLs we see in the CNAME chain. */ +          if (cname_ttl > rr_ttl) +            cname_ttl = rr_ttl; +        } +      else +        free(rr_name); + +      aptr += rr_len; +      if (aptr > abuf + alen) +        { +          status = ARES_EBADRESP; +          break; +        } +    } + +  if (status == ARES_SUCCESS && naddrs == 0) +    status = ARES_ENODATA; +  if (status == ARES_SUCCESS) +    { +      /* We got our answer. */ +      if (naddrttls) +        { +          const int n = naddrs < max_addr_ttls ? naddrs : max_addr_ttls; +          for (i = 0; i < n; i++) +            { +              /* Ensure that each A TTL is no larger than the CNAME TTL. */ +              if (addrttls[i].ttl > cname_ttl) +                addrttls[i].ttl = cname_ttl; +            } +          *naddrttls = n; +        } +      if (aliases) +        aliases[naliases] = NULL; +      if (host) +        { +          /* Allocate memory to build the host entry. */ +          hostent = malloc(sizeof(struct hostent)); +          if (hostent) +            { +              hostent->h_addr_list = malloc((naddrs + 1) * sizeof(char *)); +              if (hostent->h_addr_list) +                { +                  /* Fill in the hostent and return successfully. */ +                  hostent->h_name = hostname; +                  hostent->h_aliases = aliases; +                  hostent->h_addrtype = AF_INET6; +                  hostent->h_length = sizeof(struct in6_addr); +                  for (i = 0; i < naddrs; i++) +                    hostent->h_addr_list[i] = (char *) &addrs[i]; +                  hostent->h_addr_list[naddrs] = NULL; +                  *host = hostent; +                  return ARES_SUCCESS; +                } +              free(hostent); +            } +          status = ARES_ENOMEM; +        } +    } +  if (aliases) +    { +      for (i = 0; i < naliases; i++) +        free(aliases[i]); +      free(aliases); +    } +  free(addrs); +  free(hostname); +  return status; +} diff --git a/3rdParty/CAres/src/ares_parse_ns_reply.c b/3rdParty/CAres/src/ares_parse_ns_reply.c new file mode 100644 index 0000000..25c6329 --- /dev/null +++ b/3rdParty/CAres/src/ares_parse_ns_reply.c @@ -0,0 +1,182 @@ +/* $Id */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +/* + * ares_parse_ns_reply created by Vlad Dinulescu <vlad.dinulescu@avira.com> + *      on behalf of AVIRA Gmbh - http://www.avira.com + */ + +#include "ares_setup.h" + +#ifdef HAVE_SYS_SOCKET_H +#  include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#  include <netinet/in.h> +#endif +#ifdef HAVE_NETDB_H +#  include <netdb.h> +#endif +#ifdef HAVE_ARPA_INET_H +#  include <arpa/inet.h> +#endif +#ifdef HAVE_ARPA_NAMESER_H +#  include <arpa/nameser.h> +#else +#  include "nameser.h" +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +#  include <arpa/nameser_compat.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include "ares.h" +#include "ares_dns.h" +#include "ares_private.h" + +int ares_parse_ns_reply( const unsigned char* abuf, int alen, +                         struct hostent** host ) +{ +  unsigned int qdcount, ancount; +  int status, i, rr_type, rr_class, rr_len; +  int nameservers_num; +  long len; +  const unsigned char *aptr; +  char* hostname, *rr_name, *rr_data, **nameservers; +  struct hostent *hostent; + +  /* Set *host to NULL for all failure cases. */ +  *host = NULL; + +  /* Give up if abuf doesn't have room for a header. */ +  if ( alen < HFIXEDSZ ) +    return ARES_EBADRESP; + +  /* Fetch the question and answer count from the header. */ +  qdcount = DNS_HEADER_QDCOUNT( abuf ); +  ancount = DNS_HEADER_ANCOUNT( abuf ); +  if ( qdcount != 1 ) +    return ARES_EBADRESP; + +  /* Expand the name from the question, and skip past the question. */ +  aptr = abuf + HFIXEDSZ; +  status = ares__expand_name_for_response( aptr, abuf, alen, &hostname, &len); +  if ( status != ARES_SUCCESS ) +    return status; +  if ( aptr + len + QFIXEDSZ > abuf + alen ) +  { +    free( hostname ); +    return ARES_EBADRESP; +  } +  aptr += len + QFIXEDSZ; + +  /* Allocate nameservers array; ancount gives an upper bound */ +  nameservers = malloc( ( ancount + 1 ) * sizeof( char * ) ); +  if ( !nameservers ) +  { +    free( hostname ); +    return ARES_ENOMEM; +  } +  nameservers_num = 0; + +  /* Examine each answer resource record (RR) in turn. */ +  for ( i = 0; i < ( int ) ancount; i++ ) +  { +    /* Decode the RR up to the data field. */ +    status = ares__expand_name_for_response( aptr, abuf, alen, &rr_name, &len ); +    if ( status != ARES_SUCCESS ) +      break; +    aptr += len; +    if ( aptr + RRFIXEDSZ > abuf + alen ) +    { +      status = ARES_EBADRESP; +      break; +    } +    rr_type = DNS_RR_TYPE( aptr ); +    rr_class = DNS_RR_CLASS( aptr ); +    rr_len = DNS_RR_LEN( aptr ); +    aptr += RRFIXEDSZ; + +    if ( rr_class == C_IN && rr_type == T_NS ) +    { +      /* Decode the RR data and add it to the nameservers list */ +      status = ares__expand_name_for_response( aptr, abuf, alen, &rr_data, +                                               &len); +      if ( status != ARES_SUCCESS ) +      { +        break; +      } + +      nameservers[nameservers_num] = malloc(strlen(rr_data)+1); + +      if (nameservers[nameservers_num]==NULL) +      { +        free(rr_name); +        free(rr_data); +        status=ARES_ENOMEM; +        break; +      } +      strcpy(nameservers[nameservers_num],rr_data); +      free(rr_data); + +      nameservers_num++; +    } + +    free( rr_name ); + +    aptr += rr_len; +    if ( aptr > abuf + alen ) +    { +      status = ARES_EBADRESP; +      break; +    } +  } + +  if ( status == ARES_SUCCESS && nameservers_num == 0 ) +  { +    status = ARES_ENODATA; +  } +  if ( status == ARES_SUCCESS ) +  { +    /* We got our answer.  Allocate memory to build the host entry. */ +    nameservers[nameservers_num] = NULL; +    hostent = malloc( sizeof( struct hostent ) ); +    if ( hostent ) +    { +      hostent->h_addr_list = malloc( 1 * sizeof( char * ) ); +      if ( hostent->h_addr_list ) +      { +        /* Fill in the hostent and return successfully. */ +        hostent->h_name = hostname; +        hostent->h_aliases = nameservers; +        hostent->h_addrtype = AF_INET; +        hostent->h_length = sizeof( struct in_addr ); +        hostent->h_addr_list[0] = NULL; +        *host = hostent; +        return ARES_SUCCESS; +      } +      free( hostent ); +    } +    status = ARES_ENOMEM; +  } +  for ( i = 0; i < nameservers_num; i++ ) +    free( nameservers[i] ); +  free( nameservers ); +  free( hostname ); +  return status; +} diff --git a/3rdParty/CAres/src/ares_parse_ptr_reply.c b/3rdParty/CAres/src/ares_parse_ptr_reply.c new file mode 100644 index 0000000..6f039b9 --- /dev/null +++ b/3rdParty/CAres/src/ares_parse_ptr_reply.c @@ -0,0 +1,209 @@ +/* $Id: ares_parse_ptr_reply.c,v 1.21 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_SYS_SOCKET_H +#  include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#  include <netinet/in.h> +#endif +#ifdef HAVE_NETDB_H +#  include <netdb.h> +#endif +#ifdef HAVE_ARPA_NAMESER_H +#  include <arpa/nameser.h> +#else +#  include "nameser.h" +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +#  include <arpa/nameser_compat.h> +#endif + +#ifdef HAVE_STRINGS_H +#  include <strings.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include "ares.h" +#include "ares_dns.h" +#include "ares_private.h" + +int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr, +                         int addrlen, int family, struct hostent **host) +{ +  unsigned int qdcount, ancount; +  int status, i, rr_type, rr_class, rr_len; +  long len; +  const unsigned char *aptr; +  char *ptrname, *hostname, *rr_name, *rr_data; +  struct hostent *hostent; +  int aliascnt = 0; +  int alias_alloc = 8; +  char ** aliases; + +  /* Set *host to NULL for all failure cases. */ +  *host = NULL; + +  /* Give up if abuf doesn't have room for a header. */ +  if (alen < HFIXEDSZ) +    return ARES_EBADRESP; + +  /* Fetch the question and answer count from the header. */ +  qdcount = DNS_HEADER_QDCOUNT(abuf); +  ancount = DNS_HEADER_ANCOUNT(abuf); +  if (qdcount != 1) +    return ARES_EBADRESP; + +  /* Expand the name from the question, and skip past the question. */ +  aptr = abuf + HFIXEDSZ; +  status = ares__expand_name_for_response(aptr, abuf, alen, &ptrname, &len); +  if (status != ARES_SUCCESS) +    return status; +  if (aptr + len + QFIXEDSZ > abuf + alen) +    { +      free(ptrname); +      return ARES_EBADRESP; +    } +  aptr += len + QFIXEDSZ; + +  /* Examine each answer resource record (RR) in turn. */ +  hostname = NULL; +  aliases = malloc(alias_alloc * sizeof(char *)); +  if (!aliases) +    { +      free(ptrname); +      return ARES_ENOMEM; +    } +  for (i = 0; i < (int)ancount; i++) +    { +      /* Decode the RR up to the data field. */ +      status = ares__expand_name_for_response(aptr, abuf, alen, &rr_name, &len); +      if (status != ARES_SUCCESS) +        break; +      aptr += len; +      if (aptr + RRFIXEDSZ > abuf + alen) +        { +          status = ARES_EBADRESP; +          break; +        } +      rr_type = DNS_RR_TYPE(aptr); +      rr_class = DNS_RR_CLASS(aptr); +      rr_len = DNS_RR_LEN(aptr); +      aptr += RRFIXEDSZ; + +      if (rr_class == C_IN && rr_type == T_PTR +          && strcasecmp(rr_name, ptrname) == 0) +        { +          /* Decode the RR data and set hostname to it. */ +          status = ares__expand_name_for_response(aptr, abuf, alen, &rr_data, +                                                  &len); +          if (status != ARES_SUCCESS) +            break; +          if (hostname) +            free(hostname); +          hostname = rr_data; +          aliases[aliascnt] = malloc((strlen(rr_data)+1) * sizeof(char *)); +          if (!aliases[aliascnt]) +            { +              status = ARES_ENOMEM; +              break; +            } +          strncpy(aliases[aliascnt], rr_data, strlen(rr_data)+1); +          aliascnt++; +          if (aliascnt >= alias_alloc) { +            char **ptr; +            alias_alloc *= 2; +            ptr = realloc(aliases, alias_alloc * sizeof(char *)); +            if(!ptr) { +              status = ARES_ENOMEM; +              break; +            } +            aliases = ptr; +          } +        } + +      if (rr_class == C_IN && rr_type == T_CNAME) +        { +          /* Decode the RR data and replace ptrname with it. */ +          status = ares__expand_name_for_response(aptr, abuf, alen, &rr_data, +                                                  &len); +          if (status != ARES_SUCCESS) +            break; +          free(ptrname); +          ptrname = rr_data; +        } + +      free(rr_name); +      aptr += rr_len; +      if (aptr > abuf + alen) +        { +          status = ARES_EBADRESP; +          break; +        } +    } + +  if (status == ARES_SUCCESS && !hostname) +    status = ARES_ENODATA; +  if (status == ARES_SUCCESS) +    { +      /* We got our answer.  Allocate memory to build the host entry. */ +      hostent = malloc(sizeof(struct hostent)); +      if (hostent) +        { +          hostent->h_addr_list = malloc(2 * sizeof(char *)); +          if (hostent->h_addr_list) +            { +              hostent->h_addr_list[0] = malloc(addrlen); +              if (hostent->h_addr_list[0]) +                { +                  hostent->h_aliases = malloc((aliascnt+1) * sizeof (char *)); +                  if (hostent->h_aliases) +                    { +                      /* Fill in the hostent and return successfully. */ +                      hostent->h_name = hostname; +                      for (i=0 ; i<aliascnt ; i++) +                        hostent->h_aliases[i] = aliases[i]; +                      hostent->h_aliases[aliascnt] = NULL; +                      hostent->h_addrtype = family; +                      hostent->h_length = addrlen; +                      memcpy(hostent->h_addr_list[0], addr, addrlen); +                      hostent->h_addr_list[1] = NULL; +                      *host = hostent; +                      free(aliases); +                      free(ptrname); +                      return ARES_SUCCESS; +                    } +                  free(hostent->h_addr_list[0]); +                } +              free(hostent->h_addr_list); +            } +          free(hostent); +        } +      status = ARES_ENOMEM; +    } +  for (i=0 ; i<aliascnt ; i++) +    if (aliases[i])  +      free(aliases[i]); +  free(aliases); +  if (hostname) +    free(hostname); +  free(ptrname); +  return status; +} diff --git a/3rdParty/CAres/src/ares_parse_srv_reply.c b/3rdParty/CAres/src/ares_parse_srv_reply.c new file mode 100644 index 0000000..72830af --- /dev/null +++ b/3rdParty/CAres/src/ares_parse_srv_reply.c @@ -0,0 +1,180 @@ +/* $Id: ares_parse_srv_reply.c,v 1.12 2009-11-26 01:21:21 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * Copyright (C) 2009 by Jakub Hrozek <jhrozek@redhat.com> + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_SYS_SOCKET_H +#  include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#  include <netinet/in.h> +#endif +#ifdef HAVE_NETDB_H +#  include <netdb.h> +#endif +#ifdef HAVE_ARPA_INET_H +#  include <arpa/inet.h> +#endif +#ifdef HAVE_ARPA_NAMESER_H +#  include <arpa/nameser.h> +#else +#  include "nameser.h" +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +#  include <arpa/nameser_compat.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include "ares.h" +#include "ares_dns.h" +#include "ares_data.h" +#include "ares_private.h" + +/* AIX portability check */ +#ifndef T_SRV +#  define T_SRV 33 /* server selection */ +#endif + +int +ares_parse_srv_reply (const unsigned char *abuf, int alen, +                      struct ares_srv_reply **srv_out) +{ +  unsigned int qdcount, ancount, i; +  const unsigned char *aptr, *vptr; +  int status, rr_type, rr_class, rr_len; +  long len; +  char *hostname = NULL, *rr_name = NULL; +  struct ares_srv_reply *srv_head = NULL; +  struct ares_srv_reply *srv_last = NULL; +  struct ares_srv_reply *srv_curr; + +  /* Set *srv_out to NULL for all failure cases. */ +  *srv_out = NULL; + +  /* Give up if abuf doesn't have room for a header. */ +  if (alen < HFIXEDSZ) +    return ARES_EBADRESP; + +  /* Fetch the question and answer count from the header. */ +  qdcount = DNS_HEADER_QDCOUNT (abuf); +  ancount = DNS_HEADER_ANCOUNT (abuf); +  if (qdcount != 1) +    return ARES_EBADRESP; +  if (ancount == 0) +    return ARES_ENODATA; + +  /* Expand the name from the question, and skip past the question. */ +  aptr = abuf + HFIXEDSZ; +  status = ares_expand_name (aptr, abuf, alen, &hostname, &len); +  if (status != ARES_SUCCESS) +    return status; + +  if (aptr + len + QFIXEDSZ > abuf + alen) +    { +      free (hostname); +      return ARES_EBADRESP; +    } +  aptr += len + QFIXEDSZ; + +  /* Examine each answer resource record (RR) in turn. */ +  for (i = 0; i < ancount; i++) +    { +      /* Decode the RR up to the data field. */ +      status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); +      if (status != ARES_SUCCESS) +        { +          break; +        } +      aptr += len; +      if (aptr + RRFIXEDSZ > abuf + alen) +        { +          status = ARES_EBADRESP; +          break; +        } +      rr_type = DNS_RR_TYPE (aptr); +      rr_class = DNS_RR_CLASS (aptr); +      rr_len = DNS_RR_LEN (aptr); +      aptr += RRFIXEDSZ; + +      /* Check if we are really looking at a SRV record */ +      if (rr_class == C_IN && rr_type == T_SRV) +        { +          /* parse the SRV record itself */ +          if (rr_len < 6) +            { +              status = ARES_EBADRESP; +              break; +            } + +          /* Allocate storage for this SRV answer appending it to the list */ +          srv_curr = ares_malloc_data(ARES_DATATYPE_SRV_REPLY); +          if (!srv_curr) +            { +              status = ARES_ENOMEM; +              break; +            } +          if (srv_last) +            { +              srv_last->next = srv_curr; +            } +          else +            { +              srv_head = srv_curr; +            } +          srv_last = srv_curr; + +          vptr = aptr; +          srv_curr->priority = ntohs (*((unsigned short *)vptr)); +          vptr += sizeof(unsigned short); +          srv_curr->weight = ntohs (*((unsigned short *)vptr)); +          vptr += sizeof(unsigned short); +          srv_curr->port = ntohs (*((unsigned short *)vptr)); +          vptr += sizeof(unsigned short); + +          status = ares_expand_name (vptr, abuf, alen, &srv_curr->host, &len); +          if (status != ARES_SUCCESS) +            break; +        } + +      /* Don't lose memory in the next iteration */ +      free (rr_name); +      rr_name = NULL; + +      /* Move on to the next record */ +      aptr += rr_len; +    } + +  if (hostname) +    free (hostname); +  if (rr_name) +    free (rr_name); + +  /* clean up on error */ +  if (status != ARES_SUCCESS) +    { +      if (srv_head) +        ares_free_data (srv_head); +      return status; +    } + +  /* everything looks fine, return the data */ +  *srv_out = srv_head; + +  return ARES_SUCCESS; +} diff --git a/3rdParty/CAres/src/ares_parse_txt_reply.c b/3rdParty/CAres/src/ares_parse_txt_reply.c new file mode 100644 index 0000000..b6af850 --- /dev/null +++ b/3rdParty/CAres/src/ares_parse_txt_reply.c @@ -0,0 +1,202 @@ +/* $Id: ares_parse_txt_reply.c,v 1.9 2009-11-26 01:21:21 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * Copyright (C) 2009 by Jakub Hrozek <jhrozek@redhat.com> + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_SYS_SOCKET_H +#  include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#  include <netinet/in.h> +#endif +#ifdef HAVE_NETDB_H +#  include <netdb.h> +#endif +#ifdef HAVE_ARPA_INET_H +#  include <arpa/inet.h> +#endif +#ifdef HAVE_ARPA_NAMESER_H +#  include <arpa/nameser.h> +#else +#  include "nameser.h" +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +#  include <arpa/nameser_compat.h> +#endif + +#ifdef HAVE_STRINGS_H +#  include <strings.h> +#endif + +#include <stdlib.h> +#include <string.h> + +#include "ares.h" +#include "ares_dns.h" +#include "ares_data.h" +#include "ares_private.h" + +int +ares_parse_txt_reply (const unsigned char *abuf, int alen, +                      struct ares_txt_reply **txt_out) +{ +  size_t substr_len, str_len; +  unsigned int qdcount, ancount, i; +  const unsigned char *aptr; +  const unsigned char *strptr; +  int status, rr_type, rr_class, rr_len; +  long len; +  char *hostname = NULL, *rr_name = NULL; +  struct ares_txt_reply *txt_head = NULL; +  struct ares_txt_reply *txt_last = NULL; +  struct ares_txt_reply *txt_curr; + +  /* Set *txt_out to NULL for all failure cases. */ +  *txt_out = NULL; + +  /* Give up if abuf doesn't have room for a header. */ +  if (alen < HFIXEDSZ) +    return ARES_EBADRESP; + +  /* Fetch the question and answer count from the header. */ +  qdcount = DNS_HEADER_QDCOUNT (abuf); +  ancount = DNS_HEADER_ANCOUNT (abuf); +  if (qdcount != 1) +    return ARES_EBADRESP; +  if (ancount == 0) +    return ARES_ENODATA; + +  /* Expand the name from the question, and skip past the question. */ +  aptr = abuf + HFIXEDSZ; +  status = ares_expand_name (aptr, abuf, alen, &hostname, &len); +  if (status != ARES_SUCCESS) +    return status; + +  if (aptr + len + QFIXEDSZ > abuf + alen) +    { +      free (hostname); +      return ARES_EBADRESP; +    } +  aptr += len + QFIXEDSZ; + +  /* Examine each answer resource record (RR) in turn. */ +  for (i = 0; i < ancount; i++) +    { +      /* Decode the RR up to the data field. */ +      status = ares_expand_name (aptr, abuf, alen, &rr_name, &len); +      if (status != ARES_SUCCESS) +        { +          break; +        } +      aptr += len; +      if (aptr + RRFIXEDSZ > abuf + alen) +        { +          status = ARES_EBADRESP; +          break; +        } +      rr_type = DNS_RR_TYPE (aptr); +      rr_class = DNS_RR_CLASS (aptr); +      rr_len = DNS_RR_LEN (aptr); +      aptr += RRFIXEDSZ; + +      /* Check if we are really looking at a TXT record */ +      if (rr_class == C_IN && rr_type == T_TXT) +        { +          /* Allocate storage for this TXT answer appending it to the list */ +          txt_curr = ares_malloc_data(ARES_DATATYPE_TXT_REPLY); +          if (!txt_curr) +            { +              status = ARES_ENOMEM; +              break; +            } +          if (txt_last) +            { +              txt_last->next = txt_curr; +            } +          else +            { +              txt_head = txt_curr; +            } +          txt_last = txt_curr; + +          /* +           * There may be multiple substrings in a single TXT record. Each +           * substring may be up to 255 characters in length, with a +           * "length byte" indicating the size of the substring payload. +           * RDATA contains both the length-bytes and payloads of all +           * substrings contained therein. +           */ + +          /* Compute total length to allow a single memory allocation */ +          strptr = aptr; +          while (strptr < (aptr + rr_len)) +            { +              substr_len = (unsigned char)*strptr; +              txt_curr->length += substr_len; +              strptr += substr_len + 1; +            } + +          /* Including null byte */ +          txt_curr->txt = malloc (txt_curr->length + 1); +          if (txt_curr->txt == NULL) +            { +              status = ARES_ENOMEM; +              break; +            } + +          /* Step through the list of substrings, concatenating them */ +          str_len = 0; +          strptr = aptr; +          while (strptr < (aptr + rr_len)) +            { +              substr_len = (unsigned char)*strptr; +              strptr++; +              memcpy ((char *) txt_curr->txt + str_len, strptr, substr_len); +              str_len += substr_len; +              strptr += substr_len; +            } +          /* Make sure we NULL-terminate */ +          *((char *) txt_curr->txt + txt_curr->length) = '\0'; +        } + +      /* Don't lose memory in the next iteration */ +      free (rr_name); +      rr_name = NULL; + +      /* Move on to the next record */ +      aptr += rr_len; +    } + +  if (hostname) +    free (hostname); +  if (rr_name) +    free (rr_name); + +  /* clean up on error */ +  if (status != ARES_SUCCESS) +    { +      if (txt_head) +        ares_free_data (txt_head); +      return status; +    } + +  /* everything looks fine, return the data */ +  *txt_out = txt_head; + +  return ARES_SUCCESS; +} diff --git a/3rdParty/CAres/src/ares_private.h b/3rdParty/CAres/src/ares_private.h new file mode 100644 index 0000000..4726d7a --- /dev/null +++ b/3rdParty/CAres/src/ares_private.h @@ -0,0 +1,343 @@ +#ifndef __ARES_PRIVATE_H +#define __ARES_PRIVATE_H + +/* $Id: ares_private.h,v 1.50 2009-11-09 12:56:50 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * Copyright (C) 2004-2009 by Daniel Stenberg + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +/* + * Define WIN32 when build target is Win32 API + */ + +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +#define WIN32 +#endif + +#include <stdio.h> +#include <sys/types.h> + +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif + +#ifdef WATT32 +#include <tcp.h> +#include <sys/ioctl.h> +#define writev(s,v,c)     writev_s(s,v,c) +#define HAVE_WRITEV 1 +#endif + +#ifdef NETWARE +#include <time.h> +#endif + +#define DEFAULT_TIMEOUT         5000 /* milliseconds */ +#define DEFAULT_TRIES           4 +#ifndef INADDR_NONE +#define INADDR_NONE 0xffffffff +#endif + +#if defined(WIN32) && !defined(WATT32) + +#define IS_NT()        ((int)GetVersion() > 0) +#define WIN_NS_9X      "System\\CurrentControlSet\\Services\\VxD\\MSTCP" +#define WIN_NS_NT_KEY  "System\\CurrentControlSet\\Services\\Tcpip\\Parameters" +#define NAMESERVER     "NameServer" +#define DHCPNAMESERVER "DhcpNameServer" +#define DATABASEPATH   "DatabasePath" +#define WIN_PATH_HOSTS  "\\hosts" + +#elif defined(WATT32) + +#define PATH_RESOLV_CONF "/dev/ENV/etc/resolv.conf" + +#elif defined(NETWARE) + +#define PATH_RESOLV_CONF "sys:/etc/resolv.cfg" +#define PATH_HOSTS              "sys:/etc/hosts" + +#elif defined(__riscos__) + +#define PATH_HOSTS             "InetDBase:Hosts" + +#else + +#define PATH_RESOLV_CONF        "/etc/resolv.conf" +#ifdef ETC_INET +#define PATH_HOSTS              "/etc/inet/hosts" +#else +#define PATH_HOSTS              "/etc/hosts" +#endif + +#endif + +#define ARES_ID_KEY_LEN 31 + +#include "ares_ipv6.h" +#include "ares_llist.h" + +#ifndef HAVE_STRDUP +#  include "ares_strdup.h" +#  define strdup(ptr) ares_strdup(ptr) +#endif + +#ifndef HAVE_STRCASECMP +#  include "ares_strcasecmp.h" +#  define strcasecmp(p1,p2) ares_strcasecmp(p1,p2) +#endif + +#ifndef HAVE_STRNCASECMP +#  include "ares_strcasecmp.h" +#  define strncasecmp(p1,p2,n) ares_strncasecmp(p1,p2,n) +#endif + +#ifndef HAVE_WRITEV +#  include "ares_writev.h" +#  define writev(s,ptr,cnt) ares_writev(s,ptr,cnt) +#endif + +struct ares_addr { +  int family; +  union { +    struct in_addr  addr4; +    struct in6_addr addr6; +  } addr; +}; +#define addrV4 addr.addr4 +#define addrV6 addr.addr6 + +struct query; + +struct send_request { +  /* Remaining data to send */ +  const unsigned char *data; +  size_t len; + +  /* The query for which we're sending this data */ +  struct query* owner_query; +  /* The buffer we're using, if we have our own copy of the packet */ +  unsigned char *data_storage; + +  /* Next request in queue */ +  struct send_request *next; +}; + +struct server_state { +  struct in_addr addr; +  ares_socket_t udp_socket; +  ares_socket_t tcp_socket; + +  /* Mini-buffer for reading the length word */ +  unsigned char tcp_lenbuf[2]; +  int tcp_lenbuf_pos; +  int tcp_length; + +  /* Buffer for reading actual TCP data */ +  unsigned char *tcp_buffer; +  int tcp_buffer_pos; + +  /* TCP output queue */ +  struct send_request *qhead; +  struct send_request *qtail; + +  /* Which incarnation of this connection is this? We don't want to +   * retransmit requests into the very same socket, but if the server +   * closes on us and we re-open the connection, then we do want to +   * re-send. */ +  int tcp_connection_generation; + +  /* Circular, doubly-linked list of outstanding queries to this server */ +  struct list_node queries_to_server; + +  /* Link back to owning channel */ +  ares_channel channel; + +  /* Is this server broken? We mark connections as broken when a +   * request that is queued for sending times out. +   */ +  int is_broken; +}; + +/* State to represent a DNS query */ +struct query { +  /* Query ID from qbuf, for faster lookup, and current timeout */ +  unsigned short qid; +  struct timeval timeout; + +  /* +   * Links for the doubly-linked lists in which we insert a query. +   * These circular, doubly-linked lists that are hash-bucketed based +   * the attributes we care about, help making most important +   * operations O(1). +   */ +  struct list_node queries_by_qid;    /* hopefully in same cache line as qid */ +  struct list_node queries_by_timeout; +  struct list_node queries_to_server; +  struct list_node all_queries; + +  /* Query buf with length at beginning, for TCP transmission */ +  unsigned char *tcpbuf; +  int tcplen; + +  /* Arguments passed to ares_send() (qbuf points into tcpbuf) */ +  const unsigned char *qbuf; +  int qlen; +  ares_callback callback; +  void *arg; + +  /* Query status */ +  int try; /* Number of times we tried this query already. */ +  int server; /* Server this query has last been sent to. */ +  struct query_server_info *server_info;   /* per-server state */ +  int using_tcp; +  int error_status; +  int timeouts; /* number of timeouts we saw for this request */ +}; + +/* Per-server state for a query */ +struct query_server_info { +  int skip_server;  /* should we skip server, due to errors, etc? */ +  int tcp_connection_generation;  /* into which TCP connection did we send? */ +}; + +/* An IP address pattern; matches an IP address X if X & mask == addr */ +#define PATTERN_MASK 0x1 +#define PATTERN_CIDR 0x2 + +struct apattern { +  union +  { +    struct in_addr  addr4; +    struct in6_addr addr6; +  } addr; +  union +  { +    struct in_addr  addr4; +    struct in6_addr addr6; +    unsigned short  bits; +  } mask; +  int family; +  unsigned short type; +}; + +typedef struct rc4_key +{ +  unsigned char state[256]; +  unsigned char x; +  unsigned char y; +} rc4_key; + +struct ares_channeldata { +  /* Configuration data */ +  int flags; +  int timeout; /* in milliseconds */ +  int tries; +  int ndots; +  int rotate; /* if true, all servers specified are used */ +  int udp_port; +  int tcp_port; +  int socket_send_buffer_size; +  int socket_receive_buffer_size; +  char **domains; +  int ndomains; +  struct apattern *sortlist; +  int nsort; +  char *lookups; + +  int optmask; /* the option bitfield passed in at init time */ + +  /* Server addresses and communications state */ +  struct server_state *servers; +  int nservers; + +  /* ID to use for next query */ +  unsigned short next_id; +  /* key to use when generating new ids */ +  rc4_key id_key; + +  /* Generation number to use for the next TCP socket open/close */ +  int tcp_connection_generation; + +  /* The time at which we last called process_timeouts(). Uses integer seconds +     just to draw the line somewhere. */ +  time_t last_timeout_processed; + +  /* Last server we sent a query to. */ +  int last_server; + +  /* Circular, doubly-linked list of queries, bucketed various ways.... */ +  /* All active queries in a single list: */ +  struct list_node all_queries; +  /* Queries bucketed by qid, for quickly dispatching DNS responses: */ +#define ARES_QID_TABLE_SIZE 2048 +  struct list_node queries_by_qid[ARES_QID_TABLE_SIZE]; +  /* Queries bucketed by timeout, for quickly handling timeouts: */ +#define ARES_TIMEOUT_TABLE_SIZE 1024 +  struct list_node queries_by_timeout[ARES_TIMEOUT_TABLE_SIZE]; + +  ares_sock_state_cb sock_state_cb; +  void *sock_state_cb_data; + +  ares_sock_create_callback sock_create_cb; +  void *sock_create_cb_data; +}; + +/* return true if now is exactly check time or later */ +int ares__timedout(struct timeval *now, +                   struct timeval *check); +/* add the specific number of milliseconds to the time in the first argument */ +int ares__timeadd(struct timeval *now, +                  int millisecs); +/* return time offset between now and (future) check, in milliseconds */ +long ares__timeoffset(struct timeval *now, +                      struct timeval *check); +/* returns ARES_SUCCESS if library has been initialized */ +int ares_library_initialized(void); +void ares__rc4(rc4_key* key,unsigned char *buffer_ptr, int buffer_len); +void ares__send_query(ares_channel channel, struct query *query, +                      struct timeval *now); +void ares__close_sockets(ares_channel channel, struct server_state *server); +int ares__get_hostent(FILE *fp, int family, struct hostent **host); +int ares__read_line(FILE *fp, char **buf, size_t *bufsize); +void ares__free_query(struct query *query); +unsigned short ares__generate_new_id(rc4_key* key); +struct timeval ares__tvnow(void); +int ares__expand_name_for_response(const unsigned char *encoded, +                                   const unsigned char *abuf, int alen, +                                   char **s, long *enclen); +#if 0 /* Not used */ +long ares__tvdiff(struct timeval t1, struct timeval t2); +#endif + +#define ARES_SWAP_BYTE(a,b) \ +  { unsigned char swapByte = *(a);  *(a) = *(b);  *(b) = swapByte; } + +#define SOCK_STATE_CALLBACK(c, s, r, w)                                 \ +  do {                                                                  \ +    if ((c)->sock_state_cb)                                             \ +      (c)->sock_state_cb((c)->sock_state_cb_data, (s), (r), (w));       \ +  } while (0) + +#ifdef CURLDEBUG +/* This is low-level hard-hacking memory leak tracking and similar. Using the +   libcurl lowlevel code from within library is ugly and only works when +   c-ares is built and linked with a similarly curldebug-enabled libcurl, +   but we do this anyway for convenience. */ +#include "../lib/memdebug.h" +#endif + +#endif /* __ARES_PRIVATE_H */ diff --git a/3rdParty/CAres/src/ares_process.c b/3rdParty/CAres/src/ares_process.c new file mode 100644 index 0000000..6182ccc --- /dev/null +++ b/3rdParty/CAres/src/ares_process.c @@ -0,0 +1,1170 @@ +/* $Id: ares_process.c,v 1.79 2009-11-18 10:33:54 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * Copyright (C) 2004-2009 by Daniel Stenberg + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_SYS_SOCKET_H +#  include <sys/socket.h> +#endif +#ifdef HAVE_SYS_UIO_H +#  include <sys/uio.h> +#endif +#ifdef HAVE_NETINET_IN_H +#  include <netinet/in.h> +#endif +#ifdef HAVE_NETINET_TCP_H +#  include <netinet/tcp.h> +#endif +#ifdef HAVE_NETDB_H +#  include <netdb.h> +#endif +#ifdef HAVE_ARPA_NAMESER_H +#  include <arpa/nameser.h> +#else +#  include "nameser.h" +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +#  include <arpa/nameser_compat.h> +#endif + +#ifdef HAVE_SYS_TIME_H +#  include <sys/time.h> +#endif + +#ifdef HAVE_STRINGS_H +#  include <strings.h> +#endif +#ifdef HAVE_UNISTD_H +#  include <unistd.h> +#endif +#ifdef HAVE_SYS_IOCTL_H +#  include <sys/ioctl.h> +#endif +#ifdef NETWARE +#  include <sys/filio.h> +#endif + +#include <assert.h> +#include <string.h> +#include <stdlib.h> +#include <fcntl.h> +#include <time.h> +#include <errno.h> + +#include "ares.h" +#include "ares_dns.h" +#include "ares_private.h" + + +static int try_again(int errnum); +static void write_tcp_data(ares_channel channel, fd_set *write_fds, +                           ares_socket_t write_fd, struct timeval *now); +static void read_tcp_data(ares_channel channel, fd_set *read_fds, +                          ares_socket_t read_fd, struct timeval *now); +static void read_udp_packets(ares_channel channel, fd_set *read_fds, +                             ares_socket_t read_fd, struct timeval *now); +static void advance_tcp_send_queue(ares_channel channel, int whichserver, +                                   ssize_t num_bytes); +static void process_timeouts(ares_channel channel, struct timeval *now); +static void process_broken_connections(ares_channel channel, +                                       struct timeval *now); +static void process_answer(ares_channel channel, unsigned char *abuf, +                           int alen, int whichserver, int tcp, +                           struct timeval *now); +static void handle_error(ares_channel channel, int whichserver, +                         struct timeval *now); +static void skip_server(ares_channel channel, struct query *query, +                        int whichserver); +static void next_server(ares_channel channel, struct query *query, +                        struct timeval *now); +static int configure_socket(int s, ares_channel channel); +static int open_tcp_socket(ares_channel channel, struct server_state *server); +static int open_udp_socket(ares_channel channel, struct server_state *server); +static int same_questions(const unsigned char *qbuf, int qlen, +                          const unsigned char *abuf, int alen); +static void end_query(ares_channel channel, struct query *query, int status, +                      unsigned char *abuf, int alen); + +/* return true if now is exactly check time or later */ +int ares__timedout(struct timeval *now, +                   struct timeval *check) +{ +  long secs = (now->tv_sec - check->tv_sec); + +  if(secs > 0) +    return 1; /* yes, timed out */ +  if(secs < 0) +    return 0; /* nope, not timed out */ + +  /* if the full seconds were identical, check the sub second parts */ +  return (now->tv_usec - check->tv_usec >= 0); +} + +/* add the specific number of milliseconds to the time in the first argument */ +int ares__timeadd(struct timeval *now, +                  int millisecs) +{ +  now->tv_sec += millisecs/1000; +  now->tv_usec += (millisecs%1000)*1000; + +  if(now->tv_usec >= 1000000) { +    ++(now->tv_sec); +    now->tv_usec -= 1000000; +  } + +  return 0; +} + +/* return time offset between now and (future) check, in milliseconds */ +long ares__timeoffset(struct timeval *now, +                      struct timeval *check) +{ +  return (check->tv_sec - now->tv_sec)*1000 + +         (check->tv_usec - now->tv_usec)/1000; +} + + +/* Something interesting happened on the wire, or there was a timeout. + * See what's up and respond accordingly. + */ +void ares_process(ares_channel channel, fd_set *read_fds, fd_set *write_fds) +{ +  struct timeval now = ares__tvnow(); + +  write_tcp_data(channel, write_fds, ARES_SOCKET_BAD, &now); +  read_tcp_data(channel, read_fds, ARES_SOCKET_BAD, &now); +  read_udp_packets(channel, read_fds, ARES_SOCKET_BAD, &now); +  process_timeouts(channel, &now); +  process_broken_connections(channel, &now); +} + +/* Something interesting happened on the wire, or there was a timeout. + * See what's up and respond accordingly. + */ +void ares_process_fd(ares_channel channel, +                     ares_socket_t read_fd, /* use ARES_SOCKET_BAD or valid +                                               file descriptors */ +                     ares_socket_t write_fd) +{ +  struct timeval now = ares__tvnow(); + +  write_tcp_data(channel, NULL, write_fd, &now); +  read_tcp_data(channel, NULL, read_fd, &now); +  read_udp_packets(channel, NULL, read_fd, &now); +  process_timeouts(channel, &now); +} + + +/* Return 1 if the specified error number describes a readiness error, or 0 + * otherwise. This is mostly for HP-UX, which could return EAGAIN or + * EWOULDBLOCK. See this man page + * + *      http://devrsrc1.external.hp.com/STKS/cgi-bin/man2html?manpage=/usr/share/man/man2.Z/send.2 + */ +static int try_again(int errnum) +{ +#if !defined EWOULDBLOCK && !defined EAGAIN +#error "Neither EWOULDBLOCK nor EAGAIN defined" +#endif +  switch (errnum) +    { +#ifdef EWOULDBLOCK +    case EWOULDBLOCK: +      return 1; +#endif +#if defined EAGAIN && EAGAIN != EWOULDBLOCK +    case EAGAIN: +      return 1; +#endif +    } +  return 0; +} + +/* If any TCP sockets select true for writing, write out queued data + * we have for them. + */ +static void write_tcp_data(ares_channel channel, +                           fd_set *write_fds, +                           ares_socket_t write_fd, +                           struct timeval *now) +{ +  struct server_state *server; +  struct send_request *sendreq; +  struct iovec *vec; +  int i; +  ssize_t scount; +  ssize_t wcount; +  size_t n; + +  if(!write_fds && (write_fd == ARES_SOCKET_BAD)) +    /* no possible action */ +    return; + +  for (i = 0; i < channel->nservers; i++) +    { +      /* Make sure server has data to send and is selected in write_fds or +         write_fd. */ +      server = &channel->servers[i]; +      if (!server->qhead || server->tcp_socket == ARES_SOCKET_BAD || +          server->is_broken) +        continue; + +      if(write_fds) { +        if(!FD_ISSET(server->tcp_socket, write_fds)) +          continue; +      } +      else { +        if(server->tcp_socket != write_fd) +          continue; +      } + +      if(write_fds) +        /* If there's an error and we close this socket, then open +         * another with the same fd to talk to another server, then we +         * don't want to think that it was the new socket that was +         * ready. This is not disastrous, but is likely to result in +         * extra system calls and confusion. */ +        FD_CLR(server->tcp_socket, write_fds); + +      /* Count the number of send queue items. */ +      n = 0; +      for (sendreq = server->qhead; sendreq; sendreq = sendreq->next) +        n++; + +      /* Allocate iovecs so we can send all our data at once. */ +      vec = malloc(n * sizeof(struct iovec)); +      if (vec) +        { +          /* Fill in the iovecs and send. */ +          n = 0; +          for (sendreq = server->qhead; sendreq; sendreq = sendreq->next) +            { +              vec[n].iov_base = (char *) sendreq->data; +              vec[n].iov_len = sendreq->len; +              n++; +            } +          wcount = (ssize_t)writev(server->tcp_socket, vec, (int)n); +          free(vec); +          if (wcount < 0) +            { +              if (!try_again(SOCKERRNO)) +                  handle_error(channel, i, now); +              continue; +            } + +          /* Advance the send queue by as many bytes as we sent. */ +          advance_tcp_send_queue(channel, i, wcount); +        } +      else +        { +          /* Can't allocate iovecs; just send the first request. */ +          sendreq = server->qhead; + +          scount = swrite(server->tcp_socket, sendreq->data, sendreq->len); +          if (scount < 0) +            { +              if (!try_again(SOCKERRNO)) +                  handle_error(channel, i, now); +              continue; +            } + +          /* Advance the send queue by as many bytes as we sent. */ +          advance_tcp_send_queue(channel, i, scount); +        } +    } +} + +/* Consume the given number of bytes from the head of the TCP send queue. */ +static void advance_tcp_send_queue(ares_channel channel, int whichserver, +                                   ssize_t num_bytes) +{ +  struct send_request *sendreq; +  struct server_state *server = &channel->servers[whichserver]; +  while (num_bytes > 0) +    { +      sendreq = server->qhead; +      if ((size_t)num_bytes >= sendreq->len) +       { +         num_bytes -= sendreq->len; +         server->qhead = sendreq->next; +         if (server->qhead == NULL) +           { +             SOCK_STATE_CALLBACK(channel, server->tcp_socket, 1, 0); +             server->qtail = NULL; +           } +         if (sendreq->data_storage != NULL) +           free(sendreq->data_storage); +         free(sendreq); +       } +      else +       { +         sendreq->data += num_bytes; +         sendreq->len -= num_bytes; +         num_bytes = 0; +       } +    } +} + +/* If any TCP socket selects true for reading, read some data, + * allocate a buffer if we finish reading the length word, and process + * a packet if we finish reading one. + */ +static void read_tcp_data(ares_channel channel, fd_set *read_fds, +                          ares_socket_t read_fd, struct timeval *now) +{ +  struct server_state *server; +  int i; +  ssize_t count; + +  if(!read_fds && (read_fd == ARES_SOCKET_BAD)) +    /* no possible action */ +    return; + +  for (i = 0; i < channel->nservers; i++) +    { +      /* Make sure the server has a socket and is selected in read_fds. */ +      server = &channel->servers[i]; +      if (server->tcp_socket == ARES_SOCKET_BAD || server->is_broken) +        continue; + +      if(read_fds) { +        if(!FD_ISSET(server->tcp_socket, read_fds)) +          continue; +      } +      else { +        if(server->tcp_socket != read_fd) +          continue; +      } + +      if(read_fds) +        /* If there's an error and we close this socket, then open +         * another with the same fd to talk to another server, then we +         * don't want to think that it was the new socket that was +         * ready. This is not disastrous, but is likely to result in +         * extra system calls and confusion. */ +        FD_CLR(server->tcp_socket, read_fds); + +      if (server->tcp_lenbuf_pos != 2) +        { +          /* We haven't yet read a length word, so read that (or +           * what's left to read of it). +           */ +          count = sread(server->tcp_socket, +                        server->tcp_lenbuf + server->tcp_lenbuf_pos, +                        2 - server->tcp_lenbuf_pos); +          if (count <= 0) +            { +              if (!(count == -1 && try_again(SOCKERRNO))) +                  handle_error(channel, i, now); +              continue; +            } + +          server->tcp_lenbuf_pos += (int)count; +          if (server->tcp_lenbuf_pos == 2) +            { +              /* We finished reading the length word.  Decode the +               * length and allocate a buffer for the data. +               */ +              server->tcp_length = server->tcp_lenbuf[0] << 8 +                | server->tcp_lenbuf[1]; +              server->tcp_buffer = malloc(server->tcp_length); +              if (!server->tcp_buffer) +                handle_error(channel, i, now); +              server->tcp_buffer_pos = 0; +            } +        } +      else +        { +          /* Read data into the allocated buffer. */ +          count = sread(server->tcp_socket, +                        server->tcp_buffer + server->tcp_buffer_pos, +                        server->tcp_length - server->tcp_buffer_pos); +          if (count <= 0) +            { +              if (!(count == -1 && try_again(SOCKERRNO))) +                  handle_error(channel, i, now); +              continue; +            } + +          server->tcp_buffer_pos += (int)count; +          if (server->tcp_buffer_pos == server->tcp_length) +            { +              /* We finished reading this answer; process it and +               * prepare to read another length word. +               */ +              process_answer(channel, server->tcp_buffer, server->tcp_length, +                             i, 1, now); +          if (server->tcp_buffer) +                        free(server->tcp_buffer); +              server->tcp_buffer = NULL; +              server->tcp_lenbuf_pos = 0; +              server->tcp_buffer_pos = 0; +            } +        } +    } +} + +/* If any UDP sockets select true for reading, process them. */ +static void read_udp_packets(ares_channel channel, fd_set *read_fds, +                             ares_socket_t read_fd, struct timeval *now) +{ +  struct server_state *server; +  int i; +  ssize_t count; +  unsigned char buf[PACKETSZ + 1]; +#ifdef HAVE_RECVFROM +  struct sockaddr_in from; +  ares_socklen_t fromlen; +#endif + +  if(!read_fds && (read_fd == ARES_SOCKET_BAD)) +    /* no possible action */ +    return; + +  for (i = 0; i < channel->nservers; i++) +    { +      /* Make sure the server has a socket and is selected in read_fds. */ +      server = &channel->servers[i]; + +      if (server->udp_socket == ARES_SOCKET_BAD || server->is_broken) +        continue; + +      if(read_fds) { +        if(!FD_ISSET(server->udp_socket, read_fds)) +          continue; +      } +      else { +        if(server->udp_socket != read_fd) +          continue; +      } + +      if(read_fds) +        /* If there's an error and we close this socket, then open +         * another with the same fd to talk to another server, then we +         * don't want to think that it was the new socket that was +         * ready. This is not disastrous, but is likely to result in +         * extra system calls and confusion. */ +        FD_CLR(server->udp_socket, read_fds); + +      /* To reduce event loop overhead, read and process as many +       * packets as we can. */ +      do { +#ifdef HAVE_RECVFROM +        fromlen = sizeof(from); +        count = (ssize_t)recvfrom(server->udp_socket, (void *)buf, sizeof(buf), +                                  0, (struct sockaddr *)&from, &fromlen); +#else +        count = sread(server->udp_socket, buf, sizeof(buf)); +#endif +        if (count == -1 && try_again(SOCKERRNO)) +          continue; +        else if (count <= 0) +          handle_error(channel, i, now); +#ifdef HAVE_RECVFROM +        else if (from.sin_addr.s_addr != server->addr.s_addr) +          /* Address response came from did not match the address +           * we sent the request to.  Someone may be attempting +           * to perform a cache poisoning attack */ +          break; +#endif +        else +          process_answer(channel, buf, (int)count, i, 0, now); +       } while (count > 0); +    } +} + +/* If any queries have timed out, note the timeout and move them on. */ +static void process_timeouts(ares_channel channel, struct timeval *now) +{ +  time_t t;  /* the time of the timeouts we're processing */ +  struct query *query; +  struct list_node* list_head; +  struct list_node* list_node; + +  /* Process all the timeouts that have fired since the last time we +   * processed timeouts. If things are going well, then we'll have +   * hundreds/thousands of queries that fall into future buckets, and +   * only a handful of requests that fall into the "now" bucket, so +   * this should be quite quick. +   */ +  for (t = channel->last_timeout_processed; t <= now->tv_sec; t++) +    { +      list_head = &(channel->queries_by_timeout[t % ARES_TIMEOUT_TABLE_SIZE]); +      for (list_node = list_head->next; list_node != list_head; ) +        { +          query = list_node->data; +          list_node = list_node->next;  /* in case the query gets deleted */ +          if (query->timeout.tv_sec && ares__timedout(now, &query->timeout)) +            { +              query->error_status = ARES_ETIMEOUT; +              ++query->timeouts; +              next_server(channel, query, now); +            } +        } +     } +  channel->last_timeout_processed = now->tv_sec; +} + +/* Handle an answer from a server. */ +static void process_answer(ares_channel channel, unsigned char *abuf, +                           int alen, int whichserver, int tcp, +                           struct timeval *now) +{ +  int tc, rcode; +  unsigned short id; +  struct query *query; +  struct list_node* list_head; +  struct list_node* list_node; + +  /* If there's no room in the answer for a header, we can't do much +   * with it. */ +  if (alen < HFIXEDSZ) +    return; + +  /* Grab the query ID, truncate bit, and response code from the packet. */ +  id = DNS_HEADER_QID(abuf); +  tc = DNS_HEADER_TC(abuf); +  rcode = DNS_HEADER_RCODE(abuf); + +  /* Find the query corresponding to this packet. The queries are +   * hashed/bucketed by query id, so this lookup should be quick. +   * Note that both the query id and the questions must be the same; +   * when the query id wraps around we can have multiple outstanding +   * queries with the same query id, so we need to check both the id and +   * question. +   */ +  query = NULL; +  list_head = &(channel->queries_by_qid[id % ARES_QID_TABLE_SIZE]); +  for (list_node = list_head->next; list_node != list_head; +       list_node = list_node->next) +    { +      struct query *q = list_node->data; +      if ((q->qid == id) && same_questions(q->qbuf, q->qlen, abuf, alen)) +        { +          query = q; +          break; +        } +    } +  if (!query) +    return; + +  /* If we got a truncated UDP packet and are not ignoring truncation, +   * don't accept the packet, and switch the query to TCP if we hadn't +   * done so already. +   */ +  if ((tc || alen > PACKETSZ) && !tcp && !(channel->flags & ARES_FLAG_IGNTC)) +    { +      if (!query->using_tcp) +        { +          query->using_tcp = 1; +          ares__send_query(channel, query, now); +        } +      return; +    } + +  /* Limit alen to PACKETSZ if we aren't using TCP (only relevant if we +   * are ignoring truncation. +   */ +  if (alen > PACKETSZ && !tcp) +    alen = PACKETSZ; + +  /* If we aren't passing through all error packets, discard packets +   * with SERVFAIL, NOTIMP, or REFUSED response codes. +   */ +  if (!(channel->flags & ARES_FLAG_NOCHECKRESP)) +    { +      if (rcode == SERVFAIL || rcode == NOTIMP || rcode == REFUSED) +        { +          skip_server(channel, query, whichserver); +          if (query->server == whichserver) +            next_server(channel, query, now); +          return; +        } +    } + +  end_query(channel, query, ARES_SUCCESS, abuf, alen); +} + +/* Close all the connections that are no longer usable. */ +static void process_broken_connections(ares_channel channel, +                                       struct timeval *now) +{ +  int i; +  for (i = 0; i < channel->nservers; i++) +    { +      struct server_state *server = &channel->servers[i]; +      if (server->is_broken) +        { +          handle_error(channel, i, now); +        } +    } +} + +static void handle_error(ares_channel channel, int whichserver, +                         struct timeval *now) +{ +  struct server_state *server; +  struct query *query; +  struct list_node list_head; +  struct list_node* list_node; + +  server = &channel->servers[whichserver]; + +  /* Reset communications with this server. */ +  ares__close_sockets(channel, server); + +  /* Tell all queries talking to this server to move on and not try +   * this server again. We steal the current list of queries that were +   * in-flight to this server, since when we call next_server this can +   * cause the queries to be re-sent to this server, which will +   * re-insert these queries in that same server->queries_to_server +   * list. +   */ +  ares__init_list_head(&list_head); +  ares__swap_lists(&list_head, &(server->queries_to_server)); +  for (list_node = list_head.next; list_node != &list_head; ) +    { +      query = list_node->data; +      list_node = list_node->next;  /* in case the query gets deleted */ +      assert(query->server == whichserver); +      skip_server(channel, query, whichserver); +      next_server(channel, query, now); +    } +  /* Each query should have removed itself from our temporary list as +   * it re-sent itself or finished up... +   */ +  assert(ares__is_list_empty(&list_head)); +} + +static void skip_server(ares_channel channel, struct query *query, +                        int whichserver) { +  /* The given server gave us problems with this query, so if we have +   * the luxury of using other servers, then let's skip the +   * potentially broken server and just use the others. If we only +   * have one server and we need to retry then we should just go ahead +   * and re-use that server, since it's our only hope; perhaps we +   * just got unlucky, and retrying will work (eg, the server timed +   * out our TCP connection just as we were sending another request). +   */ +  if (channel->nservers > 1) +    { +      query->server_info[whichserver].skip_server = 1; +    } +} + +static void next_server(ares_channel channel, struct query *query, +                        struct timeval *now) +{ +  /* We need to try each server channel->tries times. We have channel->nservers +   * servers to try. In total, we need to do channel->nservers * channel->tries +   * attempts. Use query->try to remember how many times we already attempted +   * this query. Use modular arithmetic to find the next server to try. */ +  while (++(query->try) < (channel->nservers * channel->tries)) +    { +      struct server_state *server; + +      /* Move on to the next server. */ +      query->server = (query->server + 1) % channel->nservers; +      server = &channel->servers[query->server]; + +      /* We don't want to use this server if (1) we decided this +       * connection is broken, and thus about to be closed, (2) +       * we've decided to skip this server because of earlier +       * errors we encountered, or (3) we already sent this query +       * over this exact connection. +       */ +      if (!server->is_broken && +           !query->server_info[query->server].skip_server && +           !(query->using_tcp && +             (query->server_info[query->server].tcp_connection_generation == +              server->tcp_connection_generation))) +        { +           ares__send_query(channel, query, now); +           return; +        } + +      /* You might think that with TCP we only need one try. However, +       * even when using TCP, servers can time-out our connection just +       * as we're sending a request, or close our connection because +       * they die, or never send us a reply because they get wedged or +       * tickle a bug that drops our request. +       */ +    } + +  /* If we are here, all attempts to perform query failed. */ +  end_query(channel, query, query->error_status, NULL, 0); +} + +void ares__send_query(ares_channel channel, struct query *query, +                      struct timeval *now) +{ +  struct send_request *sendreq; +  struct server_state *server; +  int timeplus; + +  server = &channel->servers[query->server]; +  if (query->using_tcp) +    { +      /* Make sure the TCP socket for this server is set up and queue +       * a send request. +       */ +      if (server->tcp_socket == ARES_SOCKET_BAD) +        { +          if (open_tcp_socket(channel, server) == -1) +            { +              skip_server(channel, query, query->server); +              next_server(channel, query, now); +              return; +            } +        } +      sendreq = calloc(1, sizeof(struct send_request)); +      if (!sendreq) +        { +        end_query(channel, query, ARES_ENOMEM, NULL, 0); +          return; +        } +      /* To make the common case fast, we avoid copies by using the +       * query's tcpbuf for as long as the query is alive. In the rare +       * case where the query ends while it's queued for transmission, +       * then we give the sendreq its own copy of the request packet +       * and put it in sendreq->data_storage. +       */ +      sendreq->data_storage = NULL; +      sendreq->data = query->tcpbuf; +      sendreq->len = query->tcplen; +      sendreq->owner_query = query; +      sendreq->next = NULL; +      if (server->qtail) +        server->qtail->next = sendreq; +      else +        { +          SOCK_STATE_CALLBACK(channel, server->tcp_socket, 1, 1); +          server->qhead = sendreq; +        } +      server->qtail = sendreq; +      query->server_info[query->server].tcp_connection_generation = +        server->tcp_connection_generation; +    } +  else +    { +      if (server->udp_socket == ARES_SOCKET_BAD) +        { +          if (open_udp_socket(channel, server) == -1) +            { +              skip_server(channel, query, query->server); +              next_server(channel, query, now); +              return; +            } +        } +      if (swrite(server->udp_socket, query->qbuf, query->qlen) == -1) +        { +          /* FIXME: Handle EAGAIN here since it likely can happen. */ +          skip_server(channel, query, query->server); +          next_server(channel, query, now); +          return; +        } +    } +    timeplus = channel->timeout << (query->try / channel->nservers); +    timeplus = (timeplus * (9 + (rand () & 7))) / 16; +    query->timeout = *now; +    ares__timeadd(&query->timeout, +                  timeplus); +    /* Keep track of queries bucketed by timeout, so we can process +     * timeout events quickly. +     */ +    ares__remove_from_list(&(query->queries_by_timeout)); +    ares__insert_in_list( +        &(query->queries_by_timeout), +        &(channel->queries_by_timeout[query->timeout.tv_sec % +                                      ARES_TIMEOUT_TABLE_SIZE])); + +    /* Keep track of queries bucketed by server, so we can process server +     * errors quickly. +     */ +    ares__remove_from_list(&(query->queries_to_server)); +    ares__insert_in_list(&(query->queries_to_server), +                         &(server->queries_to_server)); +} + +/* + * setsocknonblock sets the given socket to either blocking or non-blocking mode + * based on the 'nonblock' boolean argument. This function is highly portable. + */ +static int setsocknonblock(ares_socket_t sockfd,    /* operate on this */ +                    int nonblock   /* TRUE or FALSE */) +{ +#if defined(USE_BLOCKING_SOCKETS) + +  return 0; /* returns success */ + +#elif defined(HAVE_FCNTL_O_NONBLOCK) + +  /* most recent unix versions */ +  int flags; +  flags = fcntl(sockfd, F_GETFL, 0); +  if (FALSE != nonblock) +    return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); +  else +    return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); + +#elif defined(HAVE_IOCTL_FIONBIO) + +  /* older unix versions */ +  int flags; +  flags = nonblock; +  return ioctl(sockfd, FIONBIO, &flags); + +#elif defined(HAVE_IOCTLSOCKET_FIONBIO) + +#ifdef WATT32 +  char flags; +#else +  /* Windows */ +  unsigned long flags; +#endif +  flags = nonblock; +  return ioctlsocket(sockfd, FIONBIO, &flags); + +#elif defined(HAVE_IOCTLSOCKET_CAMEL_FIONBIO) + +  /* Amiga */ +  return IoctlSocket(sockfd, FIONBIO, (long)nonblock); + +#elif defined(HAVE_SETSOCKOPT_SO_NONBLOCK) + +  /* BeOS */ +  long b = nonblock ? 1 : 0; +  return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); + +#else +#  error "no non-blocking method was found/used/set" +#endif +} + +static int configure_socket(int s, ares_channel channel) +{ +  setsocknonblock(s, TRUE); + +#if defined(FD_CLOEXEC) && !defined(MSDOS) +  /* Configure the socket fd as close-on-exec. */ +  if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) +    return -1; +#endif + +  /* Set the socket's send and receive buffer sizes. */ +  if ((channel->socket_send_buffer_size > 0) && +      setsockopt(s, SOL_SOCKET, SO_SNDBUF, +                 (void *)&channel->socket_send_buffer_size, +                 sizeof(channel->socket_send_buffer_size)) == -1) +    return -1; + +  if ((channel->socket_receive_buffer_size > 0) && +      setsockopt(s, SOL_SOCKET, SO_RCVBUF, +                 (void *)&channel->socket_receive_buffer_size, +                 sizeof(channel->socket_receive_buffer_size)) == -1) +    return -1; + +  return 0; + } + +static int open_tcp_socket(ares_channel channel, struct server_state *server) +{ +  ares_socket_t s; +  int opt; +  struct sockaddr_in sockin; + +  /* Acquire a socket. */ +  s = socket(AF_INET, SOCK_STREAM, 0); +  if (s == ARES_SOCKET_BAD) +    return -1; + +  /* Configure it. */ +  if (configure_socket(s, channel) < 0) +    { +       sclose(s); +       return -1; +    } + +#ifdef TCP_NODELAY +  /* +   * Disable the Nagle algorithm (only relevant for TCP sockets, and thus not in +   * configure_socket). In general, in DNS lookups we're pretty much interested +   * in firing off a single request and then waiting for a reply, so batching +   * isn't very interesting in general. +   */ +  opt = 1; +  if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, +                 (void *)&opt, sizeof(opt)) == -1) +    { +       sclose(s); +       return -1; +    } +#endif + +  /* Connect to the server. */ +  memset(&sockin, 0, sizeof(sockin)); +  sockin.sin_family = AF_INET; +  sockin.sin_addr = server->addr; +  sockin.sin_port = (unsigned short)(channel->tcp_port & 0xffff); +  if (connect(s, (struct sockaddr *) &sockin, sizeof(sockin)) == -1) +    { +      int err = SOCKERRNO; + +      if (err != EINPROGRESS && err != EWOULDBLOCK) +        { +          sclose(s); +          return -1; +        } +    } + +  if (channel->sock_create_cb) +    { +      int err = channel->sock_create_cb(s, SOCK_STREAM, +                                        channel->sock_create_cb_data); +      if (err < 0) +        { +          sclose(s); +          return err; +        } +    } + +  SOCK_STATE_CALLBACK(channel, s, 1, 0); +  server->tcp_buffer_pos = 0; +  server->tcp_socket = s; +  server->tcp_connection_generation = ++channel->tcp_connection_generation; +  return 0; +} + +static int open_udp_socket(ares_channel channel, struct server_state *server) +{ +  ares_socket_t s; +  struct sockaddr_in sockin; + +  /* Acquire a socket. */ +  s = socket(AF_INET, SOCK_DGRAM, 0); +  if (s == ARES_SOCKET_BAD) +    return -1; + +  /* Set the socket non-blocking. */ +  if (configure_socket(s, channel) < 0) +    { +       sclose(s); +       return -1; +    } + +  /* Connect to the server. */ +  memset(&sockin, 0, sizeof(sockin)); +  sockin.sin_family = AF_INET; +  sockin.sin_addr = server->addr; +  sockin.sin_port = (unsigned short)(channel->udp_port & 0xffff); +  if (connect(s, (struct sockaddr *) &sockin, sizeof(sockin)) == -1) +    { +      int err = SOCKERRNO; + +      if (err != EINPROGRESS && err != EWOULDBLOCK) +        { +          sclose(s); +          return -1; +        } +    } + +  if (channel->sock_create_cb) +    { +      int err = channel->sock_create_cb(s, SOCK_DGRAM, +                                        channel->sock_create_cb_data); +      if (err < 0) +        { +          sclose(s); +          return err; +        } +    } + +  SOCK_STATE_CALLBACK(channel, s, 1, 0); + +  server->udp_socket = s; +  return 0; +} + +static int same_questions(const unsigned char *qbuf, int qlen, +                          const unsigned char *abuf, int alen) +{ +  struct { +    const unsigned char *p; +    int qdcount; +    char *name; +    long namelen; +    int type; +    int dnsclass; +  } q, a; +  int i, j; + +  if (qlen < HFIXEDSZ || alen < HFIXEDSZ) +    return 0; + +  /* Extract qdcount from the request and reply buffers and compare them. */ +  q.qdcount = DNS_HEADER_QDCOUNT(qbuf); +  a.qdcount = DNS_HEADER_QDCOUNT(abuf); +  if (q.qdcount != a.qdcount) +    return 0; + +  /* For each question in qbuf, find it in abuf. */ +  q.p = qbuf + HFIXEDSZ; +  for (i = 0; i < q.qdcount; i++) +    { +      /* Decode the question in the query. */ +      if (ares_expand_name(q.p, qbuf, qlen, &q.name, &q.namelen) +          != ARES_SUCCESS) +        return 0; +      q.p += q.namelen; +      if (q.p + QFIXEDSZ > qbuf + qlen) +        { +          free(q.name); +          return 0; +        } +      q.type = DNS_QUESTION_TYPE(q.p); +      q.dnsclass = DNS_QUESTION_CLASS(q.p); +      q.p += QFIXEDSZ; + +      /* Search for this question in the answer. */ +      a.p = abuf + HFIXEDSZ; +      for (j = 0; j < a.qdcount; j++) +        { +          /* Decode the question in the answer. */ +          if (ares_expand_name(a.p, abuf, alen, &a.name, &a.namelen) +              != ARES_SUCCESS) +            { +              free(q.name); +              return 0; +            } +          a.p += a.namelen; +          if (a.p + QFIXEDSZ > abuf + alen) +            { +              free(q.name); +              free(a.name); +              return 0; +            } +          a.type = DNS_QUESTION_TYPE(a.p); +          a.dnsclass = DNS_QUESTION_CLASS(a.p); +          a.p += QFIXEDSZ; + +          /* Compare the decoded questions. */ +          if (strcasecmp(q.name, a.name) == 0 && q.type == a.type +              && q.dnsclass == a.dnsclass) +            { +              free(a.name); +              break; +            } +          free(a.name); +        } + +      free(q.name); +      if (j == a.qdcount) +        return 0; +    } +  return 1; +} + +static void end_query (ares_channel channel, struct query *query, int status, +                       unsigned char *abuf, int alen) +{ +  int i; + +  /* First we check to see if this query ended while one of our send +   * queues still has pointers to it. +   */ +  for (i = 0; i < channel->nservers; i++) +    { +      struct server_state *server = &channel->servers[i]; +      struct send_request *sendreq; +      for (sendreq = server->qhead; sendreq; sendreq = sendreq->next) +        if (sendreq->owner_query == query) +          { +            sendreq->owner_query = NULL; +            assert(sendreq->data_storage == NULL); +            if (status == ARES_SUCCESS) +              { +                /* We got a reply for this query, but this queued +                 * sendreq points into this soon-to-be-gone query's +                 * tcpbuf. Probably this means we timed out and queued +                 * the query for retransmission, then received a +                 * response before actually retransmitting. This is +                 * perfectly fine, so we want to keep the connection +                 * running smoothly if we can. But in the worst case +                 * we may have sent only some prefix of the query, +                 * with some suffix of the query left to send. Also, +                 * the buffer may be queued on multiple queues. To +                 * prevent dangling pointers to the query's tcpbuf and +                 * handle these cases, we just give such sendreqs +                 * their own copy of the query packet. +                 */ +               sendreq->data_storage = malloc(sendreq->len); +               if (sendreq->data_storage != NULL) +                 { +                   memcpy(sendreq->data_storage, sendreq->data, sendreq->len); +                   sendreq->data = sendreq->data_storage; +                 } +              } +            if ((status != ARES_SUCCESS) || (sendreq->data_storage == NULL)) +              { +                /* We encountered an error (probably a timeout, +                 * suggesting the DNS server we're talking to is +                 * probably unreachable, wedged, or severely +                 * overloaded) or we couldn't copy the request, so +                 * mark the connection as broken. When we get to +                 * process_broken_connections() we'll close the +                 * connection and try to re-send requests to another +                 * server. +                 */ +               server->is_broken = 1; +               /* Just to be paranoid, zero out this sendreq... */ +               sendreq->data = NULL; +               sendreq->len = 0; +             } +          } +    } + +  /* Invoke the callback */ +  query->callback(query->arg, status, query->timeouts, abuf, alen); +  ares__free_query(query); + +  /* Simple cleanup policy: if no queries are remaining, close all +   * network sockets unless STAYOPEN is set. +   */ +  if (!(channel->flags & ARES_FLAG_STAYOPEN) && +      ares__is_list_empty(&(channel->all_queries))) +    { +      for (i = 0; i < channel->nservers; i++) +        ares__close_sockets(channel, &channel->servers[i]); +    } +} + +void ares__free_query(struct query *query) +{ +  /* Remove the query from all the lists in which it is linked */ +  ares__remove_from_list(&(query->queries_by_qid)); +  ares__remove_from_list(&(query->queries_by_timeout)); +  ares__remove_from_list(&(query->queries_to_server)); +  ares__remove_from_list(&(query->all_queries)); +  /* Zero out some important stuff, to help catch bugs */ +  query->callback = NULL; +  query->arg = NULL; +  /* Deallocate the memory associated with the query */ +  free(query->tcpbuf); +  free(query->server_info); +  free(query); +} diff --git a/3rdParty/CAres/src/ares_query.c b/3rdParty/CAres/src/ares_query.c new file mode 100644 index 0000000..7052d7a --- /dev/null +++ b/3rdParty/CAres/src/ares_query.c @@ -0,0 +1,184 @@ +/* $Id: ares_query.c,v 1.21 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_SYS_SOCKET_H +#  include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#  include <netinet/in.h> +#endif +#ifdef HAVE_ARPA_NAMESER_H +#  include <arpa/nameser.h> +#else +#  include "nameser.h" +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +#  include <arpa/nameser_compat.h> +#endif + +#include <stdlib.h> +#include "ares.h" +#include "ares_dns.h" +#include "ares_private.h" + +struct qquery { +  ares_callback callback; +  void *arg; +}; + +static void qcallback(void *arg, int status, int timeouts, unsigned char *abuf, int alen); + +void ares__rc4(rc4_key* key, unsigned char *buffer_ptr, int buffer_len) +{ +  unsigned char x; +  unsigned char y; +  unsigned char* state; +  unsigned char xorIndex; +  short counter; + +  x = key->x; +  y = key->y; + +  state = &key->state[0]; +  for(counter = 0; counter < buffer_len; counter ++) +  { +    x = (unsigned char)((x + 1) % 256); +    y = (unsigned char)((state[x] + y) % 256); +    ARES_SWAP_BYTE(&state[x], &state[y]); + +    xorIndex = (unsigned char)((state[x] + state[y]) % 256); + +    buffer_ptr[counter] = (unsigned char)(buffer_ptr[counter]^state[xorIndex]); +  } +  key->x = x; +  key->y = y; +} + +static struct query* find_query_by_id(ares_channel channel, unsigned short id) +{ +  unsigned short qid; +  struct list_node* list_head; +  struct list_node* list_node; +  DNS_HEADER_SET_QID(((unsigned char*)&qid), id); + +  /* Find the query corresponding to this packet. */ +  list_head = &(channel->queries_by_qid[qid % ARES_QID_TABLE_SIZE]); +  for (list_node = list_head->next; list_node != list_head; +       list_node = list_node->next) +    { +       struct query *q = list_node->data; +       if (q->qid == qid) +	  return q; +    } +  return NULL; +} + + +/* a unique query id is generated using an rc4 key. Since the id may already +   be used by a running query (as infrequent as it may be), a lookup is +   performed per id generation. In practice this search should happen only +   once per newly generated id +*/ +static unsigned short generate_unique_id(ares_channel channel) +{ +  unsigned short id; + +  do { +    id = ares__generate_new_id(&channel->id_key); +  } while (find_query_by_id(channel, id)); + +  return (unsigned short)id; +} + +void ares_query(ares_channel channel, const char *name, int dnsclass, +                int type, ares_callback callback, void *arg) +{ +  struct qquery *qquery; +  unsigned char *qbuf; +  int qlen, rd, status; + +  /* Compose the query. */ +  rd = !(channel->flags & ARES_FLAG_NORECURSE); +  status = ares_mkquery(name, dnsclass, type, channel->next_id, rd, &qbuf, +                        &qlen); +  if (status != ARES_SUCCESS) +    { +      if (qbuf != NULL) free(qbuf); +      callback(arg, status, 0, NULL, 0); +      return; +    } + +  channel->next_id = generate_unique_id(channel); + +  /* Allocate and fill in the query structure. */ +  qquery = malloc(sizeof(struct qquery)); +  if (!qquery) +    { +      ares_free_string(qbuf); +      callback(arg, ARES_ENOMEM, 0, NULL, 0); +      return; +    } +  qquery->callback = callback; +  qquery->arg = arg; + +  /* Send it off.  qcallback will be called when we get an answer. */ +  ares_send(channel, qbuf, qlen, qcallback, qquery); +  ares_free_string(qbuf); +} + +static void qcallback(void *arg, int status, int timeouts, unsigned char *abuf, int alen) +{ +  struct qquery *qquery = (struct qquery *) arg; +  unsigned int ancount; +  int rcode; + +  if (status != ARES_SUCCESS) +    qquery->callback(qquery->arg, status, timeouts, abuf, alen); +  else +    { +      /* Pull the response code and answer count from the packet. */ +      rcode = DNS_HEADER_RCODE(abuf); +      ancount = DNS_HEADER_ANCOUNT(abuf); + +      /* Convert errors. */ +      switch (rcode) +        { +        case NOERROR: +          status = (ancount > 0) ? ARES_SUCCESS : ARES_ENODATA; +          break; +        case FORMERR: +          status = ARES_EFORMERR; +          break; +        case SERVFAIL: +          status = ARES_ESERVFAIL; +          break; +        case NXDOMAIN: +          status = ARES_ENOTFOUND; +          break; +        case NOTIMP: +          status = ARES_ENOTIMP; +          break; +        case REFUSED: +          status = ARES_EREFUSED; +          break; +        } +      qquery->callback(qquery->arg, status, timeouts, abuf, alen); +    } +  free(qquery); +} diff --git a/3rdParty/CAres/src/ares_rules.h b/3rdParty/CAres/src/ares_rules.h new file mode 100644 index 0000000..65bc1eb --- /dev/null +++ b/3rdParty/CAres/src/ares_rules.h @@ -0,0 +1,145 @@ +#ifndef __CARES_RULES_H +#define __CARES_RULES_H + +/* $Id: ares_rules.h,v 1.3 2009-10-27 16:56:20 yangtse Exp $ */ + +/* Copyright (C) 2009 by Daniel Stenberg et al + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission.  M.I.T. makes no representations about the + * suitability of this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +/* ================================================================ */ +/*                    COMPILE TIME SANITY CHECKS                    */ +/* ================================================================ */ + +/* + * NOTE 1: + * ------- + * + * All checks done in this file are intentionally placed in a public + * header file which is pulled by ares.h when an application is + * being built using an already built c-ares library. Additionally + * this file is also included and used when building the library. + * + * If compilation fails on this file it is certainly sure that the + * problem is elsewhere. It could be a problem in the ares_build.h + * header file, or simply that you are using different compilation + * settings than those used to build the library. + * + * Nothing in this file is intended to be modified or adjusted by the + * c-ares library user nor by the c-ares library builder. + * + * Do not deactivate any check, these are done to make sure that the + * library is properly built and used. + * + * You can find further help on the c-ares development mailing list: + * http://cool.haxx.se/mailman/listinfo/c-ares/ + * + * NOTE 2 + * ------ + * + * Some of the following compile time checks are based on the fact + * that the dimension of a constant array can not be a negative one. + * In this way if the compile time verification fails, the compilation + * will fail issuing an error. The error description wording is compiler + * dependent but it will be quite similar to one of the following: + * + *   "negative subscript or subscript is too large" + *   "array must have at least one element" + *   "-1 is an illegal array size" + *   "size of array is negative" + * + * If you are building an application which tries to use an already + * built c-ares library and you are getting this kind of errors on + * this file, it is a clear indication that there is a mismatch between + * how the library was built and how you are trying to use it for your + * application. Your already compiled or binary library provider is the + * only one who can give you the details you need to properly use it. + */ + +/* + * Verify that some macros are actually defined. + */ + +#ifndef CARES_SIZEOF_LONG +#  error "CARES_SIZEOF_LONG definition is missing!" +   Error Compilation_aborted_CARES_SIZEOF_LONG_is_missing +#endif + +#ifndef CARES_TYPEOF_ARES_SOCKLEN_T +#  error "CARES_TYPEOF_ARES_SOCKLEN_T definition is missing!" +   Error Compilation_aborted_CARES_TYPEOF_ARES_SOCKLEN_T_is_missing +#endif + +#ifndef CARES_SIZEOF_ARES_SOCKLEN_T +#  error "CARES_SIZEOF_ARES_SOCKLEN_T definition is missing!" +   Error Compilation_aborted_CARES_SIZEOF_ARES_SOCKLEN_T_is_missing +#endif + +/* + * Macros private to this header file. + */ + +#define CareschkszEQ(t, s) sizeof(t) == s ? 1 : -1 + +#define CareschkszGE(t1, t2) sizeof(t1) >= sizeof(t2) ? 1 : -1 + +/* + * Verify that the size previously defined and expected for long + * is the same as the one reported by sizeof() at compile time. + */ + +typedef char +  __cares_rule_01__ +    [CareschkszEQ(long, CARES_SIZEOF_LONG)]; + +/* + * Verify that the size previously defined and expected for + * ares_socklen_t is actually the the same as the one reported + * by sizeof() at compile time. + */ + +typedef char +  __cares_rule_02__ +    [CareschkszEQ(ares_socklen_t, CARES_SIZEOF_ARES_SOCKLEN_T)]; + +/* + * Verify at compile time that the size of ares_socklen_t as reported + * by sizeof() is greater or equal than the one reported for int for + * the current compilation. + */ + +typedef char +  __cares_rule_03__ +    [CareschkszGE(ares_socklen_t, int)]; + +/* ================================================================ */ +/*          EXTERNALLY AND INTERNALLY VISIBLE DEFINITIONS           */ +/* ================================================================ */ + +/* + * Get rid of macros private to this header file. + */ + +#undef CareschkszEQ +#undef CareschkszGE + +/* + * Get rid of macros not intended to exist beyond this point. + */ + +#undef CARES_PULL_WS2TCPIP_H +#undef CARES_PULL_SYS_TYPES_H +#undef CARES_PULL_SYS_SOCKET_H + +#undef CARES_TYPEOF_ARES_SOCKLEN_T + +#endif /* __CARES_RULES_H */ diff --git a/3rdParty/CAres/src/ares_search.c b/3rdParty/CAres/src/ares_search.c new file mode 100644 index 0000000..9a44397 --- /dev/null +++ b/3rdParty/CAres/src/ares_search.c @@ -0,0 +1,323 @@ +/* $Id: ares_search.c,v 1.20 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> + +#ifdef HAVE_STRINGS_H +#  include <strings.h> +#endif + +#include "ares.h" +#include "ares_private.h" + +struct search_query { +  /* Arguments passed to ares_search */ +  ares_channel channel; +  char *name;                   /* copied into an allocated buffer */ +  int dnsclass; +  int type; +  ares_callback callback; +  void *arg; + +  int status_as_is;             /* error status from trying as-is */ +  int next_domain;              /* next search domain to try */ +  int trying_as_is;             /* current query is for name as-is */ +  int timeouts;                 /* number of timeouts we saw for this request */ +  int ever_got_nodata;          /* did we ever get ARES_ENODATA along the way? */ +}; + +static void search_callback(void *arg, int status, int timeouts, +                            unsigned char *abuf, int alen); +static void end_squery(struct search_query *squery, int status, +                       unsigned char *abuf, int alen); +static int cat_domain(const char *name, const char *domain, char **s); +static int single_domain(ares_channel channel, const char *name, char **s); + +void ares_search(ares_channel channel, const char *name, int dnsclass, +                 int type, ares_callback callback, void *arg) +{ +  struct search_query *squery; +  char *s; +  const char *p; +  int status, ndots; + +  /* If name only yields one domain to search, then we don't have +   * to keep extra state, so just do an ares_query(). +   */ +  status = single_domain(channel, name, &s); +  if (status != ARES_SUCCESS) +    { +      callback(arg, status, 0, NULL, 0); +      return; +    } +  if (s) +    { +      ares_query(channel, s, dnsclass, type, callback, arg); +      free(s); +      return; +    } + +  /* Allocate a search_query structure to hold the state necessary for +   * doing multiple lookups. +   */ +  squery = malloc(sizeof(struct search_query)); +  if (!squery) +    { +      callback(arg, ARES_ENOMEM, 0, NULL, 0); +      return; +    } +  squery->channel = channel; +  squery->name = strdup(name); +  if (!squery->name) +    { +      free(squery); +      callback(arg, ARES_ENOMEM, 0, NULL, 0); +      return; +    } +  squery->dnsclass = dnsclass; +  squery->type = type; +  squery->status_as_is = -1; +  squery->callback = callback; +  squery->arg = arg; +  squery->timeouts = 0; +  squery->ever_got_nodata = 0; + +  /* Count the number of dots in name. */ +  ndots = 0; +  for (p = name; *p; p++) +    { +      if (*p == '.') +        ndots++; +    } + +  /* If ndots is at least the channel ndots threshold (usually 1), +   * then we try the name as-is first.  Otherwise, we try the name +   * as-is last. +   */ +  if (ndots >= channel->ndots) +    { +      /* Try the name as-is first. */ +      squery->next_domain = 0; +      squery->trying_as_is = 1; +      ares_query(channel, name, dnsclass, type, search_callback, squery); +    } +  else +    { +      /* Try the name as-is last; start with the first search domain. */ +      squery->next_domain = 1; +      squery->trying_as_is = 0; +      status = cat_domain(name, channel->domains[0], &s); +      if (status == ARES_SUCCESS) +        { +          ares_query(channel, s, dnsclass, type, search_callback, squery); +          free(s); +        } +      else +      { +        /* failed, free the malloc()ed memory */ +        free(squery->name); +        free(squery); +        callback(arg, status, 0, NULL, 0); +      } +    } +} + +static void search_callback(void *arg, int status, int timeouts, +                            unsigned char *abuf, int alen) +{ +  struct search_query *squery = (struct search_query *) arg; +  ares_channel channel = squery->channel; +  char *s; + +  squery->timeouts += timeouts; + +  /* Stop searching unless we got a non-fatal error. */ +  if (status != ARES_ENODATA && status != ARES_ESERVFAIL +      && status != ARES_ENOTFOUND) +    end_squery(squery, status, abuf, alen); +  else +    { +      /* Save the status if we were trying as-is. */ +      if (squery->trying_as_is) +        squery->status_as_is = status; + +      /* +       * If we ever get ARES_ENODATA along the way, record that; if the search +       * should run to the very end and we got at least one ARES_ENODATA, +       * then callers like ares_gethostbyname() may want to try a T_A search +       * even if the last domain we queried for T_AAAA resource records +       * returned ARES_ENOTFOUND. +       */ +      if (status == ARES_ENODATA) +        squery->ever_got_nodata = 1; + +      if (squery->next_domain < channel->ndomains) +        { +          /* Try the next domain. */ +          status = cat_domain(squery->name, +                              channel->domains[squery->next_domain], &s); +          if (status != ARES_SUCCESS) +            end_squery(squery, status, NULL, 0); +          else +            { +              squery->trying_as_is = 0; +              squery->next_domain++; +              ares_query(channel, s, squery->dnsclass, squery->type, +                         search_callback, squery); +              free(s); +            } +        } +      else if (squery->status_as_is == -1) +        { +          /* Try the name as-is at the end. */ +          squery->trying_as_is = 1; +          ares_query(channel, squery->name, squery->dnsclass, squery->type, +                     search_callback, squery); +        } +      else { +        if (squery->status_as_is == ARES_ENOTFOUND && squery->ever_got_nodata) { +          end_squery(squery, ARES_ENODATA, NULL, 0); +        } +        else +          end_squery(squery, squery->status_as_is, NULL, 0); +      } +    } +} + +static void end_squery(struct search_query *squery, int status, +                       unsigned char *abuf, int alen) +{ +  squery->callback(squery->arg, status, squery->timeouts, abuf, alen); +  free(squery->name); +  free(squery); +} + +/* Concatenate two domains. */ +static int cat_domain(const char *name, const char *domain, char **s) +{ +  size_t nlen = strlen(name); +  size_t dlen = strlen(domain); + +  *s = malloc(nlen + 1 + dlen + 1); +  if (!*s) +    return ARES_ENOMEM; +  memcpy(*s, name, nlen); +  (*s)[nlen] = '.'; +  memcpy(*s + nlen + 1, domain, dlen); +  (*s)[nlen + 1 + dlen] = 0; +  return ARES_SUCCESS; +} + +/* Determine if this name only yields one query.  If it does, set *s to + * the string we should query, in an allocated buffer.  If not, set *s + * to NULL. + */ +static int single_domain(ares_channel channel, const char *name, char **s) +{ +  size_t len = strlen(name); +  const char *hostaliases; +  FILE *fp; +  char *line = NULL; +  int status; +  size_t linesize; +  const char *p, *q; +  int error; + +  /* If the name contains a trailing dot, then the single query is the name +   * sans the trailing dot. +   */ +  if (name[len - 1] == '.') +    { +      *s = strdup(name); +      return (*s) ? ARES_SUCCESS : ARES_ENOMEM; +    } + +  if (!(channel->flags & ARES_FLAG_NOALIASES) && !strchr(name, '.')) +    { +      /* The name might be a host alias. */ +      hostaliases = getenv("HOSTALIASES"); +      if (hostaliases) +        { +          fp = fopen(hostaliases, "r"); +          if (fp) +            { +              while ((status = ares__read_line(fp, &line, &linesize)) +                     == ARES_SUCCESS) +                { +                  if (strncasecmp(line, name, len) != 0 || +                      !ISSPACE(line[len])) +                    continue; +                  p = line + len; +                  while (ISSPACE(*p)) +                    p++; +                  if (*p) +                    { +                      q = p + 1; +                      while (*q && !ISSPACE(*q)) +                        q++; +                      *s = malloc(q - p + 1); +                      if (*s) +                        { +                          memcpy(*s, p, q - p); +                          (*s)[q - p] = 0; +                        } +                      free(line); +                      fclose(fp); +                      return (*s) ? ARES_SUCCESS : ARES_ENOMEM; +                    } +                } +              free(line); +              fclose(fp); +              if (status != ARES_SUCCESS) +                return status; +            } +          else +            { +              error = errno; +              switch(error) +                { +                case ENOENT: +                case ESRCH: +                  break; +                default: +                  DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", +                                 error, strerror(error))); +                  DEBUGF(fprintf(stderr, "Error opening file: %s\n", +                                 hostaliases)); +                  *s = NULL; +                  return ARES_EFILE; +                } +            } +        } +    } + +  if (channel->flags & ARES_FLAG_NOSEARCH || channel->ndomains == 0) +    { +      /* No domain search to do; just try the name as-is. */ +      *s = strdup(name); +      return (*s) ? ARES_SUCCESS : ARES_ENOMEM; +    } + +  *s = NULL; +  return ARES_SUCCESS; +} diff --git a/3rdParty/CAres/src/ares_send.c b/3rdParty/CAres/src/ares_send.c new file mode 100644 index 0000000..eb35b47 --- /dev/null +++ b/3rdParty/CAres/src/ares_send.c @@ -0,0 +1,135 @@ +/* $Id: ares_send.c,v 1.21 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_SYS_SOCKET_H +#  include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#  include <netinet/in.h> +#endif +#ifdef HAVE_ARPA_NAMESER_H +#  include <arpa/nameser.h> +#else +#  include "nameser.h" +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +#  include <arpa/nameser_compat.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include "ares.h" +#include "ares_dns.h" +#include "ares_private.h" + +void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen, +               ares_callback callback, void *arg) +{ +  struct query *query; +  int i; +  struct timeval now; + +  /* Verify that the query is at least long enough to hold the header. */ +  if (qlen < HFIXEDSZ || qlen >= (1 << 16)) +    { +      callback(arg, ARES_EBADQUERY, 0, NULL, 0); +      return; +    } + +  /* Allocate space for query and allocated fields. */ +  query = malloc(sizeof(struct query)); +  if (!query) +    { +      callback(arg, ARES_ENOMEM, 0, NULL, 0); +      return; +    } +  query->tcpbuf = malloc(qlen + 2); +  if (!query->tcpbuf) +    { +      free(query); +      callback(arg, ARES_ENOMEM, 0, NULL, 0); +      return; +    } +  query->server_info = malloc(channel->nservers * +                              sizeof(query->server_info[0])); +  if (!query->server_info) +    { +      free(query->tcpbuf); +      free(query); +      callback(arg, ARES_ENOMEM, 0, NULL, 0); +      return; +    } + +  /* Compute the query ID.  Start with no timeout. */ +  query->qid = (unsigned short)DNS_HEADER_QID(qbuf); +  query->timeout.tv_sec = 0; +  query->timeout.tv_usec = 0; + +  /* Form the TCP query buffer by prepending qlen (as two +   * network-order bytes) to qbuf. +   */ +  query->tcpbuf[0] = (unsigned char)((qlen >> 8) & 0xff); +  query->tcpbuf[1] = (unsigned char)(qlen & 0xff); +  memcpy(query->tcpbuf + 2, qbuf, qlen); +  query->tcplen = qlen + 2; + +  /* Fill in query arguments. */ +  query->qbuf = query->tcpbuf + 2; +  query->qlen = qlen; +  query->callback = callback; +  query->arg = arg; + +  /* Initialize query status. */ +  query->try = 0; + +  /* Choose the server to send the query to. If rotation is enabled, keep track +   * of the next server we want to use. */ +  query->server = channel->last_server; +  if (channel->rotate == 1) +    channel->last_server = (channel->last_server + 1) % channel->nservers; + +  for (i = 0; i < channel->nservers; i++) +    { +      query->server_info[i].skip_server = 0; +      query->server_info[i].tcp_connection_generation = 0; +    } +  query->using_tcp = (channel->flags & ARES_FLAG_USEVC) || qlen > PACKETSZ; +  query->error_status = ARES_ECONNREFUSED; +  query->timeouts = 0; + +  /* Initialize our list nodes. */ +  ares__init_list_node(&(query->queries_by_qid),     query); +  ares__init_list_node(&(query->queries_by_timeout), query); +  ares__init_list_node(&(query->queries_to_server),  query); +  ares__init_list_node(&(query->all_queries),        query); + +  /* Chain the query into the list of all queries. */ +  ares__insert_in_list(&(query->all_queries), &(channel->all_queries)); +  /* Keep track of queries bucketed by qid, so we can process DNS +   * responses quickly. +   */ +  ares__insert_in_list( +    &(query->queries_by_qid), +    &(channel->queries_by_qid[query->qid % ARES_QID_TABLE_SIZE])); + +  /* Perform the first query action. */ +  now = ares__tvnow(); +  ares__send_query(channel, query, &now); +} diff --git a/3rdParty/CAres/src/ares_setup.h b/3rdParty/CAres/src/ares_setup.h new file mode 100644 index 0000000..5ce9398 --- /dev/null +++ b/3rdParty/CAres/src/ares_setup.h @@ -0,0 +1,198 @@ +#ifndef HEADER_CARES_SETUP_H +#define HEADER_CARES_SETUP_H + +/* $Id: ares_setup.h,v 1.2 2009-11-14 18:51:37 yangtse Exp $ */ + +/* Copyright (C) 2004 - 2009 by Daniel Stenberg et al + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission.  M.I.T. makes no representations about the + * suitability of this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +/* + * Define WIN32 when build target is Win32 API + */ + +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +#define WIN32 +#endif + +/* + * Include configuration script results or hand-crafted + * configuration file for platforms which lack config tool. + */ + +#ifdef HAVE_CONFIG_H +#include "ares_config.h" +#else + +#ifdef WIN32 +#include "config-win32.h" +#endif + +#endif /* HAVE_CONFIG_H */ + +/* ================================================================ */ +/* Definition of preprocessor macros/symbols which modify compiler  */ +/* behaviour or generated code characteristics must be done here,   */ +/* as appropriate, before any system header file is included. It is */ +/* also possible to have them defined in the config file included   */ +/* before this point. As a result of all this we frown inclusion of */ +/* system header files in our config files, avoid this at any cost. */ +/* ================================================================ */ + +/* + * AIX 4.3 and newer needs _THREAD_SAFE defined to build + * proper reentrant code. Others may also need it. + */ + +#ifdef NEED_THREAD_SAFE +#  ifndef _THREAD_SAFE +#    define _THREAD_SAFE +#  endif +#endif + +/* + * Tru64 needs _REENTRANT set for a few function prototypes and + * things to appear in the system header files. Unixware needs it + * to build proper reentrant code. Others may also need it. + */ + +#ifdef NEED_REENTRANT +#  ifndef _REENTRANT +#    define _REENTRANT +#  endif +#endif + +/* ================================================================ */ +/*  If you need to include a system header file for your platform,  */ +/*  please, do it beyond the point further indicated in this file.  */ +/* ================================================================ */ + +/* + * c-ares external interface definitions are also used internally, + * and might also include required system header files to define them. + */ + +#include <ares_build.h> + +/* + * Compile time sanity checks must also be done when building the library. + */ + +#include <ares_rules.h> + +/* ================================================================= */ +/* No system header file shall be included in this file before this  */ +/* point. The only allowed ones are those included from ares_build.h */ +/* ================================================================= */ + +/* + * Include header files for windows builds before redefining anything. + * Use this preproessor block only to include or exclude windows.h, + * winsock2.h, ws2tcpip.h or winsock.h. Any other windows thing belongs + * to any other further and independent block.  Under Cygwin things work + * just as under linux (e.g. <sys/socket.h>) and the winsock headers should + * never be included when __CYGWIN__ is defined.  configure script takes + * care of this, not defining HAVE_WINDOWS_H, HAVE_WINSOCK_H, HAVE_WINSOCK2_H, + * neither HAVE_WS2TCPIP_H when __CYGWIN__ is defined. + */ + +#ifdef HAVE_WINDOWS_H +#  ifndef WIN32_LEAN_AND_MEAN +#    define WIN32_LEAN_AND_MEAN +#  endif +#  include <windows.h> +#  ifdef HAVE_WINSOCK2_H +#    include <winsock2.h> +#    ifdef HAVE_WS2TCPIP_H +#       include <ws2tcpip.h> +#    endif +#  else +#    ifdef HAVE_WINSOCK_H +#      include <winsock.h> +#    endif +#  endif +#endif + +/* + * Define USE_WINSOCK to 2 if we have and use WINSOCK2 API, else + * define USE_WINSOCK to 1 if we have and use WINSOCK  API, else + * undefine USE_WINSOCK. + */ + +#undef USE_WINSOCK + +#ifdef HAVE_WINSOCK2_H +#  define USE_WINSOCK 2 +#else +#  ifdef HAVE_WINSOCK_H +#    define USE_WINSOCK 1 +#  endif +#endif + +/* + * Work-arounds for systems without configure support + */ + +#ifndef HAVE_CONFIG_H + +#if !defined(HAVE_SYS_TIME_H) && !defined(_MSC_VER) && !defined(__WATCOMC__) +#define HAVE_SYS_TIME_H +#endif + +#if !defined(HAVE_UNISTD_H) && !defined(_MSC_VER) +#define HAVE_UNISTD_H 1 +#endif + +#if !defined(HAVE_SYS_UIO_H) && !defined(WIN32) && !defined(MSDOS) +#define HAVE_SYS_UIO_H +#endif + +#endif /* HAVE_CONFIG_H */ + +#ifdef __POCC__ +#  include <sys/types.h> +#  include <unistd.h> +#  define ESRCH 3 +#endif + +/* + * Recent autoconf versions define these symbols in ares_config.h. We don't + * want them (since they collide with the libcurl ones when we build + *  --enable-debug) so we undef them again here. + */ + +#undef PACKAGE_STRING +#undef PACKAGE_TARNAME +#undef PACKAGE_VERSION +#undef PACKAGE_BUGREPORT +#undef PACKAGE_NAME +#undef VERSION +#undef PACKAGE + +/* IPv6 compatibility */ +#if !defined(HAVE_AF_INET6) +#if defined(HAVE_PF_INET6) +#define AF_INET6 PF_INET6 +#else +#define AF_INET6 AF_MAX+1 +#endif +#endif + +/* + * Include macros and defines that should only be processed once. + */ + +#ifndef __SETUP_ONCE_H +#include "setup_once.h" +#endif + +#endif /* HEADER_CARES_SETUP_H */ diff --git a/3rdParty/CAres/src/ares_strcasecmp.c b/3rdParty/CAres/src/ares_strcasecmp.c new file mode 100644 index 0000000..8329e30 --- /dev/null +++ b/3rdParty/CAres/src/ares_strcasecmp.c @@ -0,0 +1,67 @@ + +/* $Id: ares_strcasecmp.c,v 1.2 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" +#include "ares_strcasecmp.h" + +#ifndef HAVE_STRCASECMP +int ares_strcasecmp(const char *a, const char *b) +{ +#if defined(HAVE_STRCMPI) +  return strcmpi(a, b); +#elif defined(HAVE_STRICMP) +  return stricmp(a, b); +#else +  size_t i; + +  for (i = 0; i < (size_t)-1; i++) { +    int c1 = ISUPPER(a[i]) ? tolower(a[i]) : a[i]; +    int c2 = ISUPPER(b[i]) ? tolower(b[i]) : b[i]; +    if (c1 != c2) +      return c1-c2; +    if (!c1) +      break; +  } +  return 0; +#endif +} +#endif + +#ifndef HAVE_STRNCASECMP +int ares_strncasecmp(const char *a, const char *b, size_t n) +{ +#if defined(HAVE_STRNCMPI) +  return strncmpi(a, b, n); +#elif defined(HAVE_STRNICMP) +  return strnicmp(a, b, n); +#else +  size_t i; + +  for (i = 0; i < n; i++) { +    int c1 = ISUPPER(a[i]) ? tolower(a[i]) : a[i]; +    int c2 = ISUPPER(b[i]) ? tolower(b[i]) : b[i]; +    if (c1 != c2) +      return c1-c2; +    if (!c1) +      break; +  } +  return 0; +#endif +} +#endif + diff --git a/3rdParty/CAres/src/ares_strcasecmp.h b/3rdParty/CAres/src/ares_strcasecmp.h new file mode 100644 index 0000000..db170be --- /dev/null +++ b/3rdParty/CAres/src/ares_strcasecmp.h @@ -0,0 +1,31 @@ +#ifndef HEADER_CARES_STRCASECMP_H +#define HEADER_CARES_STRCASECMP_H + +/* $Id: ares_strcasecmp.h,v 1.2 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifndef HAVE_STRCASECMP +extern int ares_strcasecmp(const char *a, const char *b); +#endif + +#ifndef HAVE_STRNCASECMP +extern int ares_strncasecmp(const char *a, const char *b, size_t n); +#endif + +#endif /* HEADER_CARES_STRCASECMP_H */ diff --git a/3rdParty/CAres/src/ares_strdup.c b/3rdParty/CAres/src/ares_strdup.c new file mode 100644 index 0000000..d3f2b22 --- /dev/null +++ b/3rdParty/CAres/src/ares_strdup.c @@ -0,0 +1,43 @@ + +/* $Id: ares_strdup.c,v 1.3 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" +#include "ares_strdup.h" + +#ifndef HAVE_STRDUP +char *ares_strdup(const char *s1) +{ +  size_t sz; +  char * s2; + +  if(s1) { +    sz = strlen(s1); +    if(sz < (size_t)-1) { +      sz++; +      if(sz < ((size_t)-1) / sizeof(char)) { +        s2 = malloc(sz * sizeof(char)); +        if(s2) { +          memcpy(s2, s1, sz * sizeof(char)); +          return s2; +        } +      } +    } +  } +  return (char *)NULL; +} +#endif diff --git a/3rdParty/CAres/src/ares_strdup.h b/3rdParty/CAres/src/ares_strdup.h new file mode 100644 index 0000000..f88f8d1 --- /dev/null +++ b/3rdParty/CAres/src/ares_strdup.h @@ -0,0 +1,27 @@ +#ifndef HEADER_CARES_STRDUP_H +#define HEADER_CARES_STRDUP_H + +/* $Id: ares_strdup.h,v 1.3 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifndef HAVE_STRDUP +extern char *ares_strdup(const char *s1); +#endif + +#endif /* HEADER_CARES_STRDUP_H */ diff --git a/3rdParty/CAres/src/ares_strerror.c b/3rdParty/CAres/src/ares_strerror.c new file mode 100644 index 0000000..57fcf8f --- /dev/null +++ b/3rdParty/CAres/src/ares_strerror.c @@ -0,0 +1,57 @@ +/* $Id: ares_strerror.c,v 1.18 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" +#include <assert.h> +#include "ares.h" + +const char *ares_strerror(int code) +{ +  /* Return a string literal from a table. */ +  const char *errtext[] = { +    "Successful completion", +    "DNS server returned answer with no data", +    "DNS server claims query was misformatted", +    "DNS server returned general failure", +    "Domain name not found", +    "DNS server does not implement requested operation", +    "DNS server refused query", +    "Misformatted DNS query", +    "Misformatted domain name", +    "Unsupported address family", +    "Misformatted DNS reply", +    "Could not contact DNS servers", +    "Timeout while contacting DNS servers", +    "End of file", +    "Error reading file", +    "Out of memory", +    "Channel is being destroyed", +    "Misformatted string", +    "Illegal flags specified", +    "Given hostname is not numeric", +    "Illegal hints flags specified", +    "c-ares library initialization not yet performed", +    "Error loading iphlpapi.dll", +    "Could not find GetNetworkParams function", +    "DNS query cancelled" +  }; + +  if(code >= 0 && code < (int)(sizeof(errtext) / sizeof(*errtext))) +    return errtext[code]; +  else +    return "unknown"; +} diff --git a/3rdParty/CAres/src/ares_timeout.c b/3rdParty/CAres/src/ares_timeout.c new file mode 100644 index 0000000..a522de7 --- /dev/null +++ b/3rdParty/CAres/src/ares_timeout.c @@ -0,0 +1,81 @@ +/* $Id: ares_timeout.c,v 1.13 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +#include <time.h> + +#include "ares.h" +#include "ares_private.h" + +/* WARNING: Beware that this is linear in the number of outstanding + * requests! You are probably far better off just calling ares_process() + * once per second, rather than calling ares_timeout() to figure out + * when to next call ares_process(). + */ +struct timeval *ares_timeout(ares_channel channel, struct timeval *maxtv, +                             struct timeval *tvbuf) +{ +  struct query *query; +  struct list_node* list_head; +  struct list_node* list_node; +  struct timeval now; +  struct timeval nextstop; +  long offset, min_offset; + +  /* No queries, no timeout (and no fetch of the current time). */ +  if (ares__is_list_empty(&(channel->all_queries))) +    return maxtv; + +  /* Find the minimum timeout for the current set of queries. */ +  now = ares__tvnow(); +  min_offset = -1; + +  list_head = &(channel->all_queries); +  for (list_node = list_head->next; list_node != list_head; +       list_node = list_node->next) +    { +      query = list_node->data; +      if (query->timeout.tv_sec == 0) +        continue; +      offset = ares__timeoffset(&now, &query->timeout); +      if (offset < 0) +        offset = 0; +      if (min_offset == -1 || offset < min_offset) +        min_offset = offset; +    } + +  if(min_offset != -1) { +    nextstop.tv_sec = min_offset/1000; +    nextstop.tv_usec = (min_offset%1000)*1000; +  } + +  /* If we found a minimum timeout and it's sooner than the one specified in +   * maxtv (if any), return it.  Otherwise go with maxtv. +   */ +  if (min_offset != -1 && (!maxtv || ares__timedout(maxtv, &nextstop))) +    { +      *tvbuf = nextstop; +      return tvbuf; +    } +  else +    return maxtv; +} diff --git a/3rdParty/CAres/src/ares_version.c b/3rdParty/CAres/src/ares_version.c new file mode 100644 index 0000000..3007150 --- /dev/null +++ b/3rdParty/CAres/src/ares_version.c @@ -0,0 +1,12 @@ +/* $Id: ares_version.c,v 1.5 2009-11-02 11:55:53 yangtse Exp $ */ + +#include "ares_setup.h" +#include "ares.h" + +const char *ares_version(int *version) +{ +  if(version) +    *version = ARES_VERSION; + +  return ARES_VERSION_STR; +} diff --git a/3rdParty/CAres/src/ares_version.h b/3rdParty/CAres/src/ares_version.h new file mode 100644 index 0000000..d3a6295 --- /dev/null +++ b/3rdParty/CAres/src/ares_version.h @@ -0,0 +1,22 @@ +/* $Id: ares_version.h,v 1.19 2009-11-23 12:03:33 yangtse Exp $ */ + +#ifndef ARES__VERSION_H +#define ARES__VERSION_H + +#define ARES_VERSION_MAJOR 1 +#define ARES_VERSION_MINOR 7 +#define ARES_VERSION_PATCH 0 +#define ARES_VERSION ((ARES_VERSION_MAJOR<<16)|\ +                       (ARES_VERSION_MINOR<<8)|\ +                       (ARES_VERSION_PATCH)) +#define ARES_VERSION_STR "1.7.0" + +#if (ARES_VERSION >= 0x010700) +#  define CARES_HAVE_ARES_LIBRARY_INIT 1 +#  define CARES_HAVE_ARES_LIBRARY_CLEANUP 1 +#else +#  undef CARES_HAVE_ARES_LIBRARY_INIT +#  undef CARES_HAVE_ARES_LIBRARY_CLEANUP +#endif + +#endif diff --git a/3rdParty/CAres/src/ares_writev.c b/3rdParty/CAres/src/ares_writev.c new file mode 100644 index 0000000..855ce14 --- /dev/null +++ b/3rdParty/CAres/src/ares_writev.c @@ -0,0 +1,80 @@ + +/* $Id: ares_writev.c,v 1.3 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" + +#ifdef HAVE_LIMITS_H +#  include <limits.h> +#endif + +#include "ares.h" +#include "ares_private.h" + +#ifndef HAVE_WRITEV +ssize_t ares_writev(ares_socket_t s, const struct iovec *iov, int iovcnt) +{ +  char *buffer, *bp; +  int i; +  size_t bytes = 0; +  ssize_t result; + +  /* Validate iovcnt */ +  if (iovcnt <= 0) +  { +    SET_ERRNO(EINVAL); +    return (-1); +  } + +  /* Validate and find the sum of the iov_len values in the iov array */ +  for (i = 0; i < iovcnt; i++) +  { +    if (iov[i].iov_len > INT_MAX - bytes) +    { +      SET_ERRNO(EINVAL); +      return (-1); +    } +    bytes += iov[i].iov_len; +  } + +  if (bytes == 0) +    return (0); + +  /* Allocate a temporary buffer to hold the data */ +  buffer = malloc(bytes); +  if (!buffer) +  { +    SET_ERRNO(ENOMEM); +    return (-1); +  } + +  /* Copy the data into buffer */ +  for (bp = buffer, i = 0; i < iovcnt; ++i) +  { +    memcpy (bp, iov[i].iov_base, iov[i].iov_len); +    bp += iov[i].iov_len; +  } + +  /* Send buffer contents */ +  result = swrite(s, buffer, bytes); + +  free(buffer); + +  return (result); +} +#endif + diff --git a/3rdParty/CAres/src/ares_writev.h b/3rdParty/CAres/src/ares_writev.h new file mode 100644 index 0000000..631baf8 --- /dev/null +++ b/3rdParty/CAres/src/ares_writev.h @@ -0,0 +1,37 @@ +#ifndef HEADER_CARES_WRITEV_H +#define HEADER_CARES_WRITEV_H + +/* $Id: ares_writev.h,v 1.2 2009-11-02 11:55:53 yangtse Exp $ */ + +/* Copyright 1998 by the Massachusetts Institute of Technology. + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#include "ares_setup.h" +#include "ares.h" + +#ifndef HAVE_WRITEV + +/* Structure for scatter/gather I/O. */ +struct iovec +{ +  void *iov_base;  /* Pointer to data. */ +  size_t iov_len;  /* Length of data.  */ +}; + +extern ssize_t ares_writev(ares_socket_t s, const struct iovec *iov, int iovcnt); + +#endif + +#endif /* HEADER_CARES_WRITEV_H */ diff --git a/3rdParty/CAres/src/bitncmp.c b/3rdParty/CAres/src/bitncmp.c new file mode 100644 index 0000000..f36ffaa --- /dev/null +++ b/3rdParty/CAres/src/bitncmp.c @@ -0,0 +1,60 @@ +/* $Id: bitncmp.c,v 1.8 2009-11-02 11:55:54 yangtse Exp $ */ + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef HAVE_BITNCMP + +#include "ares_setup.h" +#include "bitncmp.h" + +/* + * int + * bitncmp(l, r, n) + *	compare bit masks l and r, for n bits. + * return: + *	-1, 1, or 0 in the libc tradition. + * note: + *	network byte order assumed.  this means 192.5.5.240/28 has + *	0x11110000 in its fourth octet. + * author: + *	Paul Vixie (ISC), June 1996 + */ +int +ares_bitncmp(const void *l, const void *r, int n) { +	unsigned int lb, rb; +	int x, b; + +	b = n / 8; +	x = memcmp(l, r, b); +	if (x || (n % 8) == 0) +		return (x); + +	lb = ((const unsigned char *)l)[b]; +	rb = ((const unsigned char *)r)[b]; +	for (b = n % 8; b > 0; b--) { +		if ((lb & 0x80) != (rb & 0x80)) { +			if (lb & 0x80) +				return (1); +			return (-1); +		} +		lb <<= 1; +		rb <<= 1; +	} +	return (0); +} +#endif diff --git a/3rdParty/CAres/src/bitncmp.h b/3rdParty/CAres/src/bitncmp.h new file mode 100644 index 0000000..4805683 --- /dev/null +++ b/3rdParty/CAres/src/bitncmp.h @@ -0,0 +1,27 @@ +#ifndef __ARES_BITNCMP_H +#define __ARES_BITNCMP_H + +/* $Id: bitncmp.h,v 1.3 2007-11-19 15:47:01 bagder Exp $ */ + +/* Copyright (C) 2005 by Dominick Meglio + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#ifndef HAVE_BITNCMP +int ares_bitncmp(const void *l, const void *r, int n); +#else +#define ares_bitncmp(x,y,z) bitncmp(x,y,z) +#endif + +#endif /* __ARES_BITNCMP_H */ diff --git a/3rdParty/CAres/src/config-win32.h b/3rdParty/CAres/src/config-win32.h new file mode 100644 index 0000000..295df81 --- /dev/null +++ b/3rdParty/CAres/src/config-win32.h @@ -0,0 +1,341 @@ +#ifndef __ARES_CONFIG_WIN32_H +#define __ARES_CONFIG_WIN32_H + +/* $Id: config-win32.h,v 1.32 2009-10-27 16:38:42 yangtse Exp $ */ + +/* Copyright (C) 2004 - 2008 by Daniel Stenberg et al + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission.  M.I.T. makes no representations about the + * suitability of this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +/* ================================================================ */ +/*    ares/config-win32.h - Hand crafted config file for Windows    */ +/* ================================================================ */ + +/* ---------------------------------------------------------------- */ +/*                          HEADER FILES                            */ +/* ---------------------------------------------------------------- */ + +/* Define if you have the <getopt.h> header file.  */ +#if defined(__MINGW32__) || defined(__POCC__) +#define HAVE_GETOPT_H 1 +#endif + +/* Define if you have the <limits.h> header file.  */ +#define HAVE_LIMITS_H 1 + +/* Define if you have the <process.h> header file.  */ +#ifndef __SALFORDC__ +#define HAVE_PROCESS_H 1 +#endif + +/* Define if you have the <signal.h> header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define if you have the <sys/time.h> header file */ +/* #define HAVE_SYS_TIME_H 1 */ + +/* Define if you have the <time.h> header file.  */ +#define HAVE_TIME_H 1 + +/* Define if you have the <unistd.h> header file.  */ +#if defined(__MINGW32__) || defined(__WATCOMC__) || defined(__LCC__) || \ +    defined(__POCC__) +#define HAVE_UNISTD_H 1 +#endif + +/* Define if you have the <windows.h> header file.  */ +#define HAVE_WINDOWS_H 1 + +/* Define if you have the <winsock.h> header file.  */ +#define HAVE_WINSOCK_H 1 + +/* Define if you have the <winsock2.h> header file.  */ +#ifndef __SALFORDC__ +#define HAVE_WINSOCK2_H 1 +#endif + +/* Define if you have the <ws2tcpip.h> header file.  */ +#ifndef __SALFORDC__ +#define HAVE_WS2TCPIP_H 1 +#endif + +/* ---------------------------------------------------------------- */ +/*                        OTHER HEADER INFO                         */ +/* ---------------------------------------------------------------- */ + +/* Define if sig_atomic_t is an available typedef. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define if you have the ANSI C header files.  */ +#define STDC_HEADERS 1 + +/* Define if you can safely include both <sys/time.h> and <time.h>.  */ +/* #define TIME_WITH_SYS_TIME 1 */ + +/* ---------------------------------------------------------------- */ +/*                             FUNCTIONS                            */ +/* ---------------------------------------------------------------- */ + +/* Define if you have the gethostname function.  */ +#define HAVE_GETHOSTNAME 1 + +/* Define if you have the ioctlsocket function. */ +#define HAVE_IOCTLSOCKET 1 + +/* Define if you have a working ioctlsocket FIONBIO function. */ +#define HAVE_IOCTLSOCKET_FIONBIO 1 + +/* Define if you have the strcasecmp function. */ +/* #define HAVE_STRCASECMP 1 */ + +/* Define if you have the strdup function. */ +#define HAVE_STRDUP 1 + +/* Define if you have the stricmp function. */ +#define HAVE_STRICMP 1 + +/* Define if you have the strncasecmp function. */ +/* #define HAVE_STRNCASECMP 1 */ + +/* Define if you have the strnicmp function. */ +#define HAVE_STRNICMP 1 + +/* Define if you have the recv function. */ +#define HAVE_RECV 1 + +/* Define to the type of arg 1 for recv. */ +#define RECV_TYPE_ARG1 SOCKET + +/* Define to the type of arg 2 for recv. */ +#define RECV_TYPE_ARG2 char * + +/* Define to the type of arg 3 for recv. */ +#define RECV_TYPE_ARG3 int + +/* Define to the type of arg 4 for recv. */ +#define RECV_TYPE_ARG4 int + +/* Define to the function return type for recv. */ +#define RECV_TYPE_RETV int + +/* Define if you have the recvfrom function. */ +#define HAVE_RECVFROM 1 + +/* Define to the type of arg 1 for recvfrom. */ +#define RECVFROM_TYPE_ARG1 SOCKET + +/* Define to the type pointed by arg 2 for recvfrom. */ +#define RECVFROM_TYPE_ARG2 char + +/* Define to the type of arg 3 for recvfrom. */ +#define RECVFROM_TYPE_ARG3 int + +/* Define to the type of arg 4 for recvfrom. */ +#define RECVFROM_TYPE_ARG4 int + +/* Define to the type pointed by arg 5 for recvfrom. */ +#define RECVFROM_TYPE_ARG5 struct sockaddr + +/* Define to the type pointed by arg 6 for recvfrom. */ +#define RECVFROM_TYPE_ARG6 int + +/* Define to the function return type for recvfrom. */ +#define RECVFROM_TYPE_RETV int + +/* Define if you have the send function. */ +#define HAVE_SEND 1 + +/* Define to the type of arg 1 for send. */ +#define SEND_TYPE_ARG1 SOCKET + +/* Define to the type qualifier of arg 2 for send. */ +#define SEND_QUAL_ARG2 const + +/* Define to the type of arg 2 for send. */ +#define SEND_TYPE_ARG2 char * + +/* Define to the type of arg 3 for send. */ +#define SEND_TYPE_ARG3 int + +/* Define to the type of arg 4 for send. */ +#define SEND_TYPE_ARG4 int + +/* Define to the function return type for send. */ +#define SEND_TYPE_RETV int + +/* Specifics for the Watt-32 tcp/ip stack */ +#ifdef WATT32 +  #define SOCKET              int +  #define NS_INADDRSZ         4 +  #define HAVE_ARPA_NAMESER_H 1 +  #define HAVE_ARPA_INET_H    1 +  #define HAVE_NETDB_H        1 +  #define HAVE_NETINET_IN_H   1 +  #define HAVE_SYS_SOCKET_H   1 +  #define HAVE_NETINET_TCP_H  1 +  #define HAVE_AF_INET6       1 +  #define HAVE_PF_INET6       1 +  #define HAVE_STRUCT_IN6_ADDR     1 +  #define HAVE_STRUCT_SOCKADDR_IN6 1 +  #undef HAVE_WINSOCK_H +  #undef HAVE_WINSOCK2_H +  #undef HAVE_WS2TCPIP_H +#endif + +/* ---------------------------------------------------------------- */ +/*                       TYPEDEF REPLACEMENTS                       */ +/* ---------------------------------------------------------------- */ + +/* Define this if in_addr_t is not an available 'typedefed' type */ +#define in_addr_t unsigned long + +/* Define as the return type of signal handlers (int or void).  */ +#define RETSIGTYPE void + +/* Define ssize_t if it is not an available 'typedefed' type */ +#ifndef _SSIZE_T_DEFINED +#  if (defined(__WATCOMC__) && (__WATCOMC__ >= 1240)) || \ +      defined(__POCC__) || \ +      defined(__MINGW32__) +#  elif defined(_WIN64) +#    define _SSIZE_T_DEFINED +#    define ssize_t __int64 +#  else +#    define _SSIZE_T_DEFINED +#    define ssize_t int +#  endif +#endif + +/* ---------------------------------------------------------------- */ +/*                          STRUCT RELATED                          */ +/* ---------------------------------------------------------------- */ + +/* Define this if you have struct addrinfo */ +#define HAVE_STRUCT_ADDRINFO 1 + +/* Define this if you have struct sockaddr_storage */ +#ifndef __SALFORDC__ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 +#endif + +/* Define this if you have struct timeval */ +#define HAVE_STRUCT_TIMEVAL 1 + +/* ---------------------------------------------------------------- */ +/*                        COMPILER SPECIFIC                         */ +/* ---------------------------------------------------------------- */ + +/* Define to avoid VS2005 complaining about portable C functions */ +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#define _CRT_SECURE_NO_DEPRECATE 1 +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif + +/* Officially, Microsoft's Windows SDK versions 6.X do not support Windows +   2000 as a supported build target. VS2008 default installations provide an +   embedded Windows SDK v6.0A along with the claim that Windows 2000 is a +   valid build target for VS2008. Popular belief is that binaries built using +   Windows SDK versions 6.X and Windows 2000 as a build target are functional */ +#if defined(_MSC_VER) && (_MSC_VER >= 1500) +#  define VS2008_MINIMUM_TARGET 0x0500 +#endif + +/* When no build target is specified VS2008 default build target is Windows +   Vista, which leaves out even Winsows XP. If no build target has been given +   for VS2008 we will target the minimum Officially supported build target, +   which happens to be Windows XP. */ +#if defined(_MSC_VER) && (_MSC_VER >= 1500) +#  define VS2008_DEFAULT_TARGET  0x0501 +#endif + +/* VS2008 default target settings and minimum build target check */ +#if defined(_MSC_VER) && (_MSC_VER >= 1500) +#  ifndef _WIN32_WINNT +#    define _WIN32_WINNT VS2008_DEFAULT_TARGET +#  endif +#  ifndef WINVER +#    define WINVER VS2008_DEFAULT_TARGET +#  endif +#  if (_WIN32_WINNT < VS2008_MINIMUM_TARGET) || (WINVER < VS2008_MINIMUM_TARGET) +#    error VS2008 does not support Windows build targets prior to Windows 2000 +#  endif +#endif + +/* When no build target is specified Pelles C 5.00 and later default build +   target is Windows Vista. We override default target to be Windows 2000. */ +#if defined(__POCC__) && (__POCC__ >= 500) +#  ifndef _WIN32_WINNT +#    define _WIN32_WINNT 0x0500 +#  endif +#  ifndef WINVER +#    define WINVER 0x0500 +#  endif +#endif + +/* Availability of freeaddrinfo, getaddrinfo and getnameinfo functions is +   quite convoluted, compiler dependent and even build target dependent. */ +#if defined(HAVE_WS2TCPIP_H) +#  if defined(__POCC__) +#    define HAVE_FREEADDRINFO 1 +#    define HAVE_GETADDRINFO  1 +#    define HAVE_GETNAMEINFO  1 +#  elif defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501) +#    define HAVE_FREEADDRINFO 1 +#    define HAVE_GETADDRINFO  1 +#    define HAVE_GETNAMEINFO  1 +#  elif defined(_MSC_VER) && (_MSC_VER >= 1200) +#    define HAVE_FREEADDRINFO 1 +#    define HAVE_GETADDRINFO  1 +#    define HAVE_GETNAMEINFO  1 +#  endif +#endif + +#if defined(__POCC__) +#  ifndef _MSC_VER +#    error Microsoft extensions /Ze compiler option is required +#  endif +#  ifndef __POCC__OLDNAMES +#    error Compatibility names /Go compiler option is required +#  endif +#endif + +/* ---------------------------------------------------------------- */ +/*                         IPV6 COMPATIBILITY                       */ +/* ---------------------------------------------------------------- */ + +/* Define this if you have address family AF_INET6 */ +#ifdef HAVE_WINSOCK2_H +#define HAVE_AF_INET6 1 +#endif + +/* Define this if you have protocol family PF_INET6 */ +#ifdef HAVE_WINSOCK2_H +#define HAVE_PF_INET6 1 +#endif + +/* Define this if you have struct in6_addr */ +#ifdef HAVE_WS2TCPIP_H +#define HAVE_STRUCT_IN6_ADDR 1 +#endif + +/* Define this if you have struct sockaddr_in6 */ +#ifdef HAVE_WS2TCPIP_H +#define HAVE_STRUCT_SOCKADDR_IN6 1 +#endif + +/* Define this if you have sockaddr_in6 with scopeid */ +#ifdef HAVE_WS2TCPIP_H +#define HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 1 +#endif + + +#endif  /* __ARES_CONFIG_WIN32_H */ diff --git a/3rdParty/CAres/src/inet_net_pton.c b/3rdParty/CAres/src/inet_net_pton.c new file mode 100644 index 0000000..de09ace --- /dev/null +++ b/3rdParty/CAres/src/inet_net_pton.c @@ -0,0 +1,446 @@ +/* $Id: inet_net_pton.c,v 1.17 2009-11-02 11:55:54 yangtse Exp $ */ + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996,1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "ares_setup.h" + +#ifdef HAVE_SYS_SOCKET_H +#  include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#  include <netinet/in.h> +#endif +#ifdef HAVE_ARPA_INET_H +#  include <arpa/inet.h> +#endif +#ifdef HAVE_ARPA_NAMESER_H +#  include <arpa/nameser.h> +#else +#  include "nameser.h" +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +#  include <arpa/nameser_compat.h> +#endif + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "ares_ipv6.h" +#include "inet_net_pton.h" + +#if !defined(HAVE_INET_NET_PTON) || !defined(HAVE_INET_NET_PTON_IPV6) + +/* + * static int + * inet_net_pton_ipv4(src, dst, size) + *      convert IPv4 network number from presentation to network format. + *      accepts hex octets, hex strings, decimal octets, and /CIDR. + *      "size" is in bytes and describes "dst". + * return: + *      number of bits, either imputed classfully or specified with /CIDR, + *      or -1 if some failure occurred (check errno).  ENOENT means it was + *      not an IPv4 network specification. + * note: + *      network byte order assumed.  this means 192.5.5.240/28 has + *      0b11110000 in its fourth octet. + * note: + *      On Windows we store the error in the thread errno, not + *      in the winsock error code. This is to avoid loosing the + *      actual last winsock error. So use macro ERRNO to fetch the + *      errno this funtion sets when returning (-1), not SOCKERRNO. + * author: + *      Paul Vixie (ISC), June 1996 + */ +static int +inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size) +{ +  static const char xdigits[] = "0123456789abcdef"; +  static const char digits[] = "0123456789"; +  int n, ch, tmp = 0, dirty, bits; +  const unsigned char *odst = dst; + +  ch = *src++; +  if (ch == '0' && (src[0] == 'x' || src[0] == 'X') +      && ISXDIGIT(src[1])) { +    /* Hexadecimal: Eat nybble string. */ +    if (!size) +      goto emsgsize; +    dirty = 0; +    src++;  /* skip x or X. */ +    while ((ch = *src++) != '\0' && ISXDIGIT(ch)) { +      if (ISUPPER(ch)) +        ch = tolower(ch); +      n = (int)(strchr(xdigits, ch) - xdigits); +      if (dirty == 0) +        tmp = n; +      else +        tmp = (tmp << 4) | n; +      if (++dirty == 2) { +        if (!size--) +          goto emsgsize; +        *dst++ = (unsigned char) tmp; +        dirty = 0; +      } +    } +    if (dirty) {  /* Odd trailing nybble? */ +      if (!size--) +        goto emsgsize; +      *dst++ = (unsigned char) (tmp << 4); +    } +  } else if (ISDIGIT(ch)) { +    /* Decimal: eat dotted digit string. */ +    for (;;) { +      tmp = 0; +      do { +        n = (int)(strchr(digits, ch) - digits); +        tmp *= 10; +        tmp += n; +        if (tmp > 255) +          goto enoent; +      } while ((ch = *src++) != '\0' && +               ISDIGIT(ch)); +      if (!size--) +        goto emsgsize; +      *dst++ = (unsigned char) tmp; +      if (ch == '\0' || ch == '/') +        break; +      if (ch != '.') +        goto enoent; +      ch = *src++; +      if (!ISDIGIT(ch)) +        goto enoent; +    } +  } else +    goto enoent; + +  bits = -1; +  if (ch == '/' && +      ISDIGIT(src[0]) && dst > odst) { +    /* CIDR width specifier.  Nothing can follow it. */ +    ch = *src++;    /* Skip over the /. */ +    bits = 0; +    do { +      n = (int)(strchr(digits, ch) - digits); +      bits *= 10; +      bits += n; +    } while ((ch = *src++) != '\0' && ISDIGIT(ch)); +    if (ch != '\0') +      goto enoent; +    if (bits > 32) +      goto emsgsize; +  } + +  /* Firey death and destruction unless we prefetched EOS. */ +  if (ch != '\0') +    goto enoent; + +  /* If nothing was written to the destination, we found no address. */ +  if (dst == odst) +    goto enoent; +  /* If no CIDR spec was given, infer width from net class. */ +  if (bits == -1) { +    if (*odst >= 240)       /* Class E */ +      bits = 32; +    else if (*odst >= 224)  /* Class D */ +      bits = 8; +    else if (*odst >= 192)  /* Class C */ +      bits = 24; +    else if (*odst >= 128)  /* Class B */ +      bits = 16; +    else                    /* Class A */ +      bits = 8; +    /* If imputed mask is narrower than specified octets, widen. */ +    if (bits < ((dst - odst) * 8)) +      bits = (int)(dst - odst) * 8; +    /* +     * If there are no additional bits specified for a class D +     * address adjust bits to 4. +     */ +    if (bits == 8 && *odst == 224) +      bits = 4; +  } +  /* Extend network to cover the actual mask. */ +  while (bits > ((dst - odst) * 8)) { +    if (!size--) +      goto emsgsize; +    *dst++ = '\0'; +  } +  return (bits); + +  enoent: +  SET_ERRNO(ENOENT); +  return (-1); + +  emsgsize: +  SET_ERRNO(EMSGSIZE); +  return (-1); +} + +static int +getbits(const char *src, int *bitsp) +{ +  static const char digits[] = "0123456789"; +  int n; +  int val; +  char ch; + +  val = 0; +  n = 0; +  while ((ch = *src++) != '\0') { +    const char *pch; + +    pch = strchr(digits, ch); +    if (pch != NULL) { +      if (n++ != 0 && val == 0)       /* no leading zeros */ +        return (0); +      val *= 10; +      val += (pch - digits); +      if (val > 128)                  /* range */ +        return (0); +      continue; +    } +    return (0); +  } +  if (n == 0) +    return (0); +  *bitsp = val; +  return (1); +} + +static int +getv4(const char *src, unsigned char *dst, int *bitsp) +{ +  static const char digits[] = "0123456789"; +  unsigned char *odst = dst; +  int n; +  unsigned int val; +  char ch; + +  val = 0; +  n = 0; +  while ((ch = *src++) != '\0') { +    const char *pch; + +    pch = strchr(digits, ch); +    if (pch != NULL) { +      if (n++ != 0 && val == 0)       /* no leading zeros */ +        return (0); +      val *= 10; +      val += (pch - digits); +      if (val > 255)                  /* range */ +        return (0); +      continue; +    } +    if (ch == '.' || ch == '/') { +      if (dst - odst > 3)             /* too many octets? */ +        return (0); +      *dst++ = (unsigned char)val; +      if (ch == '/') +        return (getbits(src, bitsp)); +      val = 0; +      n = 0; +      continue; +    } +    return (0); +  } +  if (n == 0) +    return (0); +  if (dst - odst > 3)             /* too many octets? */ +    return (0); +  *dst++ = (unsigned char)val; +  return (1); +} + +static int +inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size) +{ +  static const char xdigits_l[] = "0123456789abcdef", +    xdigits_u[] = "0123456789ABCDEF"; +  unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; +  const char *xdigits, *curtok; +  int ch, saw_xdigit; +  unsigned int val; +  int digits; +  int bits; +  size_t bytes; +  int words; +  int ipv4; + +  memset((tp = tmp), '\0', NS_IN6ADDRSZ); +  endp = tp + NS_IN6ADDRSZ; +  colonp = NULL; +  /* Leading :: requires some special handling. */ +  if (*src == ':') +    if (*++src != ':') +      goto enoent; +  curtok = src; +  saw_xdigit = 0; +  val = 0; +  digits = 0; +  bits = -1; +  ipv4 = 0; +  while ((ch = *src++) != '\0') { +    const char *pch; + +    if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) +      pch = strchr((xdigits = xdigits_u), ch); +    if (pch != NULL) { +      val <<= 4; +      val |= (pch - xdigits); +      if (++digits > 4) +        goto enoent; +      saw_xdigit = 1; +      continue; +    } +    if (ch == ':') { +      curtok = src; +      if (!saw_xdigit) { +        if (colonp) +          goto enoent; +        colonp = tp; +        continue; +      } else if (*src == '\0') +        goto enoent; +      if (tp + NS_INT16SZ > endp) +        return (0); +      *tp++ = (unsigned char)((val >> 8) & 0xff); +      *tp++ = (unsigned char)(val & 0xff); +      saw_xdigit = 0; +      digits = 0; +      val = 0; +      continue; +    } +    if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && +        getv4(curtok, tp, &bits) > 0) { +      tp += NS_INADDRSZ; +      saw_xdigit = 0; +      ipv4 = 1; +      break;  /* '\0' was seen by inet_pton4(). */ +    } +    if (ch == '/' && getbits(src, &bits) > 0) +      break; +    goto enoent; +  } +  if (saw_xdigit) { +    if (tp + NS_INT16SZ > endp) +      goto enoent; +    *tp++ = (unsigned char)((val >> 8) & 0xff); +    *tp++ = (unsigned char)(val & 0xff); +  } +  if (bits == -1) +    bits = 128; + +  words = (bits + 15) / 16; +  if (words < 2) +    words = 2; +  if (ipv4) +    words = 8; +  endp =  tmp + 2 * words; + +  if (colonp != NULL) { +    /* +     * Since some memmove()'s erroneously fail to handle +     * overlapping regions, we'll do the shift by hand. +     */ +    const int n = (int)(tp - colonp); +    int i; + +    if (tp == endp) +      goto enoent; +    for (i = 1; i <= n; i++) { +      endp[- i] = colonp[n - i]; +      colonp[n - i] = 0; +    } +    tp = endp; +  } +  if (tp != endp) +    goto enoent; + +  bytes = (bits + 7) / 8; +  if (bytes > size) +    goto emsgsize; +  memcpy(dst, tmp, bytes); +  return (bits); + +  enoent: +  SET_ERRNO(ENOENT); +  return (-1); + +  emsgsize: +  SET_ERRNO(EMSGSIZE); +  return (-1); +} + +/* + * int + * inet_net_pton(af, src, dst, size) + *      convert network number from presentation to network format. + *      accepts hex octets, hex strings, decimal octets, and /CIDR. + *      "size" is in bytes and describes "dst". + * return: + *      number of bits, either imputed classfully or specified with /CIDR, + *      or -1 if some failure occurred (check errno).  ENOENT means it was + *      not a valid network specification. + * note: + *      On Windows we store the error in the thread errno, not + *      in the winsock error code. This is to avoid loosing the + *      actual last winsock error. So use macro ERRNO to fetch the + *      errno this funtion sets when returning (-1), not SOCKERRNO. + * author: + *      Paul Vixie (ISC), June 1996 + */ +int +ares_inet_net_pton(int af, const char *src, void *dst, size_t size) +{ +  switch (af) { +  case AF_INET: +    return (inet_net_pton_ipv4(src, dst, size)); +  case AF_INET6: +    return (inet_net_pton_ipv6(src, dst, size)); +  default: +    SET_ERRNO(EAFNOSUPPORT); +    return (-1); +  } +} + +#endif + +#ifndef HAVE_INET_PTON +int ares_inet_pton(int af, const char *src, void *dst) +{ +  int result; +  size_t size; + +  if (af == AF_INET) +    size = sizeof(struct in_addr); +  else if (af == AF_INET6) +    size = sizeof(struct in6_addr); +  else +  { +    SET_ERRNO(EAFNOSUPPORT); +    return -1; +  } +  result = ares_inet_net_pton(af, src, dst, size); +  if (result == -1 && ERRNO == ENOENT) +    return 0; +  return (result > -1 ? 1 : -1); +} +#endif diff --git a/3rdParty/CAres/src/inet_net_pton.h b/3rdParty/CAres/src/inet_net_pton.h new file mode 100644 index 0000000..eb38afa --- /dev/null +++ b/3rdParty/CAres/src/inet_net_pton.h @@ -0,0 +1,32 @@ +#ifndef __ARES_INET_NET_PTON_H +#define __ARES_INET_NET_PTON_H + +/* $Id: inet_net_pton.h,v 1.6 2008-09-24 19:13:02 yangtse Exp $ */ + +/* Copyright (C) 2005 by Daniel Stenberg + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#ifdef HAVE_INET_PTON +#define ares_inet_pton(x,y,z) inet_pton(x,y,z) +#else +int ares_inet_pton(int af, const char *src, void *dst); +#endif +#if defined(HAVE_INET_NET_PTON) && defined(HAVE_INET_NET_PTON_IPV6) +#define ares_inet_net_pton(w,x,y,z) inet_net_pton(w,x,y,z) +#else +int ares_inet_net_pton(int af, const char *src, void *dst, size_t size); +#endif + +#endif /* __ARES_INET_NET_PTON_H */ diff --git a/3rdParty/CAres/src/inet_ntop.c b/3rdParty/CAres/src/inet_ntop.c new file mode 100644 index 0000000..5b0d097 --- /dev/null +++ b/3rdParty/CAres/src/inet_ntop.c @@ -0,0 +1,232 @@ +/* $Id: inet_ntop.c,v 1.12 2009-11-02 11:55:54 yangtse Exp $ */ + +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include "ares_setup.h" + +#ifdef HAVE_SYS_SOCKET_H +#  include <sys/socket.h> +#endif +#ifdef HAVE_NETINET_IN_H +#  include <netinet/in.h> +#endif +#ifdef HAVE_ARPA_INET_H +#  include <arpa/inet.h> +#endif +#ifdef HAVE_ARPA_NAMESER_H +#  include <arpa/nameser.h> +#else +#  include "nameser.h" +#endif +#ifdef HAVE_ARPA_NAMESER_COMPAT_H +#  include <arpa/nameser_compat.h> +#endif + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "ares_ipv6.h" +#include "inet_ntop.h" + + +#ifndef HAVE_INET_NTOP + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static const char *inet_ntop4(const unsigned char *src, char *dst, size_t size); +static const char *inet_ntop6(const unsigned char *src, char *dst, size_t size); + +/* char * + * inet_ntop(af, src, dst, size) + *     convert a network format address to presentation format. + * return: + *     pointer to presentation format address (`dst'), or NULL (see errno). + * note: + *      On Windows we store the error in the thread errno, not + *      in the winsock error code. This is to avoid loosing the + *      actual last winsock error. So use macro ERRNO to fetch the + *      errno this funtion sets when returning NULL, not SOCKERRNO. + * author: + *     Paul Vixie, 1996. + */ +const char * +ares_inet_ntop(int af, const void *src, char *dst, size_t size) +{ +  switch (af) +    { +    case AF_INET: +      return (inet_ntop4(src, dst, size)); +    case AF_INET6: +      return (inet_ntop6(src, dst, size)); +    default: +      SET_ERRNO(EAFNOSUPPORT); +      return (NULL); +    } +  /* NOTREACHED */ +} + +/* const char * + * inet_ntop4(src, dst, size) + *     format an IPv4 address, more or less like inet_ntoa() + * return: + *     `dst' (as a const) + * notes: + *     (1) uses no statics + *     (2) takes a unsigned char* not an in_addr as input + * author: + *     Paul Vixie, 1996. + */ +static const char * +inet_ntop4(const unsigned char *src, char *dst, size_t size) +{ +  static const char fmt[] = "%u.%u.%u.%u"; +  char tmp[sizeof "255.255.255.255"]; + +  if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) > size) +    { +      SET_ERRNO(ENOSPC); +      return (NULL); +    } +    strcpy(dst, tmp); +    return (dst); +} + +/* const char * + * inet_ntop6(src, dst, size) + *    convert IPv6 binary address into presentation (printable) format + * author: + *    Paul Vixie, 1996. + */ +static const char * +inet_ntop6(const unsigned char *src, char *dst, size_t size) +{ +  /* +   * Note that int32_t and int16_t need only be "at least" large enough +   * to contain a value of the specified size.  On some systems, like +   * Crays, there is no such thing as an integer variable with 16 bits. +   * Keep this in mind if you think this function should have been coded +   * to use pointer overlays.  All the world's not a VAX. +   */ +  char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; +  char *tp; +  struct { +    long base; +    long len; +  } best, cur; +  unsigned long words[NS_IN6ADDRSZ / NS_INT16SZ]; +  int i; + +  /* +   * Preprocess: +   *  Copy the input (bytewise) array into a wordwise array. +   *  Find the longest run of 0x00's in src[] for :: shorthanding. +   */ +  memset(words, '\0', sizeof(words)); +  for (i = 0; i < NS_IN6ADDRSZ; i++) +      words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + +  best.base = -1; +  cur.base = -1; +  best.len = 0; +  cur.len = 0; + +  for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) +    { +      if (words[i] == 0) +        { +          if (cur.base == -1) +            cur.base = i, cur.len = 1; +          else +            cur.len++; +        } +      else +        { +          if (cur.base != -1) +            { +              if (best.base == -1 || cur.len > best.len) +                best = cur; +              cur.base = -1; +            } +        } +    } +  if (cur.base != -1) +    { +      if (best.base == -1 || cur.len > best.len) +        best = cur; +    } +  if (best.base != -1 && best.len < 2) +    best.base = -1; + +  /* +   * Format the result. +   */ +  tp = tmp; +  for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) +    { +      /* Are we inside the best run of 0x00's? */ +      if (best.base != -1 && i >= best.base && +          i < (best.base + best.len)) +        { +          if (i == best.base) +             *tp++ = ':'; +          continue; +        } +      /* Are we following an initial run of 0x00s or any real hex? */ +      if (i != 0) +        *tp++ = ':'; +      /* Is this address an encapsulated IPv4? */ +      if (i == 6 && best.base == 0 && +          (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) +        { +          if (!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp))) +            return (NULL); +          tp += strlen(tp); +          break; +        } +        tp += SPRINTF((tp, "%lx", words[i])); +    } + +  /* Was it a trailing run of 0x00's? */ +  if (best.base != -1 && (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ)) +    *tp++ = ':'; +  *tp++ = '\0'; + +  /* +   * Check for overflow, copy, and we're done. +   */ +  if ((size_t)(tp - tmp) > size) +    { +      SET_ERRNO(ENOSPC); +      return (NULL); +    } +  strcpy(dst, tmp); +  return (dst); +} +#endif + diff --git a/3rdParty/CAres/src/inet_ntop.h b/3rdParty/CAres/src/inet_ntop.h new file mode 100644 index 0000000..923689e --- /dev/null +++ b/3rdParty/CAres/src/inet_ntop.h @@ -0,0 +1,27 @@ +#ifndef __ARES_INET_NTOP_H +#define __ARES_INET_NTOP_H + +/* $Id: inet_ntop.h,v 1.4 2008-09-24 16:43:12 yangtse Exp $ */ + +/* Copyright (C) 2005 by Dominick Meglio + * + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * M.I.T. makes no representations about the suitability of + * this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + +#ifdef HAVE_INET_NTOP +#define ares_inet_ntop(w,x,y,z) inet_ntop(w,x,y,z) +#else +const char *ares_inet_ntop(int af, const void *src, char *dst, size_t size); +#endif + +#endif /* __ARES_INET_NTOP_H */ diff --git a/3rdParty/CAres/src/nameser.h b/3rdParty/CAres/src/nameser.h new file mode 100644 index 0000000..db324c0 --- /dev/null +++ b/3rdParty/CAres/src/nameser.h @@ -0,0 +1,194 @@ +/* $Id: nameser.h,v 1.29 2008-09-17 01:02:57 yangtse Exp $ */ + +#ifndef ARES_NAMESER_H +#define ARES_NAMESER_H + +/* header file provided by liren@vivisimo.com */ + +#ifndef HAVE_ARPA_NAMESER_H + +#define NS_PACKETSZ     512   /* maximum packet size */ +#define NS_MAXDNAME     256   /* maximum domain name */ +#define NS_MAXCDNAME    255   /* maximum compressed domain name */ +#define NS_MAXLABEL     63 +#define NS_HFIXEDSZ     12    /* #/bytes of fixed data in header */ +#define NS_QFIXEDSZ     4     /* #/bytes of fixed data in query */ +#define NS_RRFIXEDSZ    10    /* #/bytes of fixed data in r record */ +#define NS_INT16SZ      2 +#define NS_INADDRSZ     4 +#define NS_IN6ADDRSZ    16 +#define NS_CMPRSFLGS    0xc0  /* Flag bits indicating name compression. */ +#define NS_DEFAULTPORT  53    /* For both TCP and UDP. */ + +typedef enum __ns_class { +    ns_c_invalid = 0,       /* Cookie. */ +    ns_c_in = 1,            /* Internet. */ +    ns_c_2 = 2,             /* unallocated/unsupported. */ +    ns_c_chaos = 3,         /* MIT Chaos-net. */ +    ns_c_hs = 4,            /* MIT Hesiod. */ +    /* Query class values which do not appear in resource records */ +    ns_c_none = 254,        /* for prereq. sections in update requests */ +    ns_c_any = 255,         /* Wildcard match. */ +    ns_c_max = 65536 +} ns_class; + +typedef enum __ns_type { +    ns_t_invalid = 0,       /* Cookie. */ +    ns_t_a = 1,             /* Host address. */ +    ns_t_ns = 2,            /* Authoritative server. */ +    ns_t_md = 3,            /* Mail destination. */ +    ns_t_mf = 4,            /* Mail forwarder. */ +    ns_t_cname = 5,         /* Canonical name. */ +    ns_t_soa = 6,           /* Start of authority zone. */ +    ns_t_mb = 7,            /* Mailbox domain name. */ +    ns_t_mg = 8,            /* Mail group member. */ +    ns_t_mr = 9,            /* Mail rename name. */ +    ns_t_null = 10,         /* Null resource record. */ +    ns_t_wks = 11,          /* Well known service. */ +    ns_t_ptr = 12,          /* Domain name pointer. */ +    ns_t_hinfo = 13,        /* Host information. */ +    ns_t_minfo = 14,        /* Mailbox information. */ +    ns_t_mx = 15,           /* Mail routing information. */ +    ns_t_txt = 16,          /* Text strings. */ +    ns_t_rp = 17,           /* Responsible person. */ +    ns_t_afsdb = 18,        /* AFS cell database. */ +    ns_t_x25 = 19,          /* X_25 calling address. */ +    ns_t_isdn = 20,         /* ISDN calling address. */ +    ns_t_rt = 21,           /* Router. */ +    ns_t_nsap = 22,         /* NSAP address. */ +    ns_t_nsap_ptr = 23,     /* Reverse NSAP lookup (deprecated). */ +    ns_t_sig = 24,          /* Security signature. */ +    ns_t_key = 25,          /* Security key. */ +    ns_t_px = 26,           /* X.400 mail mapping. */ +    ns_t_gpos = 27,         /* Geographical position (withdrawn). */ +    ns_t_aaaa = 28,         /* Ip6 Address. */ +    ns_t_loc = 29,          /* Location Information. */ +    ns_t_nxt = 30,          /* Next domain (security). */ +    ns_t_eid = 31,          /* Endpoint identifier. */ +    ns_t_nimloc = 32,       /* Nimrod Locator. */ +    ns_t_srv = 33,          /* Server Selection. */ +    ns_t_atma = 34,         /* ATM Address */ +    ns_t_naptr = 35,        /* Naming Authority PoinTeR */ +    ns_t_kx = 36,           /* Key Exchange */ +    ns_t_cert = 37,         /* Certification record */ +    ns_t_a6 = 38,           /* IPv6 address (deprecates AAAA) */ +    ns_t_dname = 39,        /* Non-terminal DNAME (for IPv6) */ +    ns_t_sink = 40,         /* Kitchen sink (experimentatl) */ +    ns_t_opt = 41,          /* EDNS0 option (meta-RR) */ +    ns_t_apl = 42,          /* Address prefix list (RFC3123) */ +    ns_t_tkey = 249,        /* Transaction key */ +    ns_t_tsig = 250,        /* Transaction signature. */ +    ns_t_ixfr = 251,        /* Incremental zone transfer. */ +    ns_t_axfr = 252,        /* Transfer zone of authority. */ +    ns_t_mailb = 253,       /* Transfer mailbox records. */ +    ns_t_maila = 254,       /* Transfer mail agent records. */ +    ns_t_any = 255,         /* Wildcard match. */ +    ns_t_zxfr = 256,        /* BIND-specific, nonstandard. */ +    ns_t_max = 65536 +} ns_type; + +typedef enum __ns_opcode { +    ns_o_query = 0,         /* Standard query. */ +    ns_o_iquery = 1,        /* Inverse query (deprecated/unsupported). */ +    ns_o_status = 2,        /* Name server status query (unsupported). */ +                                /* Opcode 3 is undefined/reserved. */ +    ns_o_notify = 4,        /* Zone change notification. */ +    ns_o_update = 5,        /* Zone update message. */ +    ns_o_max = 6 +} ns_opcode; + +typedef enum __ns_rcode { +    ns_r_noerror = 0,       /* No error occurred. */ +    ns_r_formerr = 1,       /* Format error. */ +    ns_r_servfail = 2,      /* Server failure. */ +    ns_r_nxdomain = 3,      /* Name error. */ +    ns_r_notimpl = 4,       /* Unimplemented. */ +    ns_r_refused = 5,       /* Operation refused. */ +    /* these are for BIND_UPDATE */ +    ns_r_yxdomain = 6,      /* Name exists */ +    ns_r_yxrrset = 7,       /* RRset exists */ +    ns_r_nxrrset = 8,       /* RRset does not exist */ +    ns_r_notauth = 9,       /* Not authoritative for zone */ +    ns_r_notzone = 10,      /* Zone of record different from zone section */ +    ns_r_max = 11, +    /* The following are TSIG extended errors */ +    ns_r_badsig = 16, +    ns_r_badkey = 17, +    ns_r_badtime = 18 +} ns_rcode; + +#endif /* HAVE_ARPA_NAMESER_H */ + +#ifndef HAVE_ARPA_NAMESER_COMPAT_H + +#define PACKETSZ         NS_PACKETSZ +#define MAXDNAME         NS_MAXDNAME +#define MAXCDNAME        NS_MAXCDNAME +#define MAXLABEL         NS_MAXLABEL +#define HFIXEDSZ         NS_HFIXEDSZ +#define QFIXEDSZ         NS_QFIXEDSZ +#define RRFIXEDSZ        NS_RRFIXEDSZ +#define INDIR_MASK       NS_CMPRSFLGS +#define NAMESERVER_PORT  NS_DEFAULTPORT + +#define QUERY           ns_o_query + +#define SERVFAIL        ns_r_servfail +#define NOTIMP          ns_r_notimpl +#define REFUSED         ns_r_refused +#undef NOERROR /* it seems this is already defined in winerror.h */ +#define NOERROR         ns_r_noerror +#define FORMERR         ns_r_formerr +#define NXDOMAIN        ns_r_nxdomain + +#define C_IN            ns_c_in +#define C_CHAOS         ns_c_chaos +#define C_HS            ns_c_hs +#define C_NONE          ns_c_none +#define C_ANY           ns_c_any + +#define T_A             ns_t_a +#define T_NS            ns_t_ns +#define T_MD            ns_t_md +#define T_MF            ns_t_mf +#define T_CNAME         ns_t_cname +#define T_SOA           ns_t_soa +#define T_MB            ns_t_mb +#define T_MG            ns_t_mg +#define T_MR            ns_t_mr +#define T_NULL          ns_t_null +#define T_WKS           ns_t_wks +#define T_PTR           ns_t_ptr +#define T_HINFO         ns_t_hinfo +#define T_MINFO         ns_t_minfo +#define T_MX            ns_t_mx +#define T_TXT           ns_t_txt +#define T_RP            ns_t_rp +#define T_AFSDB         ns_t_afsdb +#define T_X25           ns_t_x25 +#define T_ISDN          ns_t_isdn +#define T_RT            ns_t_rt +#define T_NSAP          ns_t_nsap +#define T_NSAP_PTR      ns_t_nsap_ptr +#define T_SIG           ns_t_sig +#define T_KEY           ns_t_key +#define T_PX            ns_t_px +#define T_GPOS          ns_t_gpos +#define T_AAAA          ns_t_aaaa +#define T_LOC           ns_t_loc +#define T_NXT           ns_t_nxt +#define T_EID           ns_t_eid +#define T_NIMLOC        ns_t_nimloc +#define T_SRV           ns_t_srv +#define T_ATMA          ns_t_atma +#define T_NAPTR         ns_t_naptr +#define T_TSIG          ns_t_tsig +#define T_IXFR          ns_t_ixfr +#define T_AXFR          ns_t_axfr +#define T_MAILB         ns_t_mailb +#define T_MAILA         ns_t_maila +#define T_ANY           ns_t_any + +#endif /* HAVE_ARPA_NAMESER_COMPAT_H */ + +#endif /* ARES_NAMESER_H */ diff --git a/3rdParty/CAres/src/setup_once.h b/3rdParty/CAres/src/setup_once.h new file mode 100644 index 0000000..9d93ebc --- /dev/null +++ b/3rdParty/CAres/src/setup_once.h @@ -0,0 +1,444 @@ +#ifndef __SETUP_ONCE_H +#define __SETUP_ONCE_H + +/* $Id: setup_once.h,v 1.36 2009-06-19 00:41:03 yangtse Exp $ */ + +/* Copyright (C) 2004 - 2009 by Daniel Stenberg et al + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission.  M.I.T. makes no representations about the + * suitability of this software for any purpose.  It is provided "as is" + * without express or implied warranty. + */ + + +/******************************************************************** + *                              NOTICE                              * + *                             ========                             * + *                                                                  * + *  Content of header files lib/setup_once.h and ares/setup_once.h  * + *  must be kept in sync. Modify the other one if you change this.  * + *                                                                  * + ********************************************************************/ + + +/* + * Inclusion of common header files. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <ctype.h> +#include <errno.h> + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#ifdef NEED_MALLOC_H +#include <malloc.h> +#endif + +#ifdef NEED_MEMORY_H +#include <memory.h> +#endif + +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif + +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#ifdef TIME_WITH_SYS_TIME +#include <time.h> +#endif +#else +#ifdef HAVE_TIME_H +#include <time.h> +#endif +#endif + +#ifdef WIN32 +#include <io.h> +#include <fcntl.h> +#endif + +#ifdef HAVE_STDBOOL_H +#include <stdbool.h> +#endif + + +/* + * Definition of timeval struct for platforms that don't have it. + */ + +#ifndef HAVE_STRUCT_TIMEVAL +struct timeval { + long tv_sec; + long tv_usec; +}; +#endif + + +/* + * If we have the MSG_NOSIGNAL define, make sure we use + * it as the fourth argument of function send() + */ + +#ifdef HAVE_MSG_NOSIGNAL +#define SEND_4TH_ARG MSG_NOSIGNAL +#else +#define SEND_4TH_ARG 0 +#endif + + +#if defined(__minix) +/* Minix doesn't support recv on TCP sockets */ +#define sread(x,y,z) (ssize_t)read((RECV_TYPE_ARG1)(x), \ +                                   (RECV_TYPE_ARG2)(y), \ +                                   (RECV_TYPE_ARG3)(z)) + +#elif defined(HAVE_RECV) +/* + * The definitions for the return type and arguments types + * of functions recv() and send() belong and come from the + * configuration file. Do not define them in any other place. + * + * HAVE_RECV is defined if you have a function named recv() + * which is used to read incoming data from sockets. If your + * function has another name then don't define HAVE_RECV. + * + * If HAVE_RECV is defined then RECV_TYPE_ARG1, RECV_TYPE_ARG2, + * RECV_TYPE_ARG3, RECV_TYPE_ARG4 and RECV_TYPE_RETV must also + * be defined. + * + * HAVE_SEND is defined if you have a function named send() + * which is used to write outgoing data on a connected socket. + * If yours has another name then don't define HAVE_SEND. + * + * If HAVE_SEND is defined then SEND_TYPE_ARG1, SEND_QUAL_ARG2, + * SEND_TYPE_ARG2, SEND_TYPE_ARG3, SEND_TYPE_ARG4 and + * SEND_TYPE_RETV must also be defined. + */ + +#if !defined(RECV_TYPE_ARG1) || \ +    !defined(RECV_TYPE_ARG2) || \ +    !defined(RECV_TYPE_ARG3) || \ +    !defined(RECV_TYPE_ARG4) || \ +    !defined(RECV_TYPE_RETV) +  /* */ +  Error Missing_definition_of_return_and_arguments_types_of_recv +  /* */ +#else +#define sread(x,y,z) (ssize_t)recv((RECV_TYPE_ARG1)(x), \ +                                   (RECV_TYPE_ARG2)(y), \ +                                   (RECV_TYPE_ARG3)(z), \ +                                   (RECV_TYPE_ARG4)(0)) +#endif +#else /* HAVE_RECV */ +#ifndef sread +  /* */ +  Error Missing_definition_of_macro_sread +  /* */ +#endif +#endif /* HAVE_RECV */ + + +#if defined(__minix) +/* Minix doesn't support send on TCP sockets */ +#define swrite(x,y,z) (ssize_t)write((SEND_TYPE_ARG1)(x), \ +                                    (SEND_TYPE_ARG2)(y), \ +                                    (SEND_TYPE_ARG3)(z)) + +#elif defined(HAVE_SEND) +#if !defined(SEND_TYPE_ARG1) || \ +    !defined(SEND_QUAL_ARG2) || \ +    !defined(SEND_TYPE_ARG2) || \ +    !defined(SEND_TYPE_ARG3) || \ +    !defined(SEND_TYPE_ARG4) || \ +    !defined(SEND_TYPE_RETV) +  /* */ +  Error Missing_definition_of_return_and_arguments_types_of_send +  /* */ +#else +#define swrite(x,y,z) (ssize_t)send((SEND_TYPE_ARG1)(x), \ +                                    (SEND_TYPE_ARG2)(y), \ +                                    (SEND_TYPE_ARG3)(z), \ +                                    (SEND_TYPE_ARG4)(SEND_4TH_ARG)) +#endif +#else /* HAVE_SEND */ +#ifndef swrite +  /* */ +  Error Missing_definition_of_macro_swrite +  /* */ +#endif +#endif /* HAVE_SEND */ + + +#if 0 +#if defined(HAVE_RECVFROM) +/* + * Currently recvfrom is only used on udp sockets. + */ +#if !defined(RECVFROM_TYPE_ARG1) || \ +    !defined(RECVFROM_TYPE_ARG2) || \ +    !defined(RECVFROM_TYPE_ARG3) || \ +    !defined(RECVFROM_TYPE_ARG4) || \ +    !defined(RECVFROM_TYPE_ARG5) || \ +    !defined(RECVFROM_TYPE_ARG6) || \ +    !defined(RECVFROM_TYPE_RETV) +  /* */ +  Error Missing_definition_of_return_and_arguments_types_of_recvfrom +  /* */ +#else +#define sreadfrom(s,b,bl,f,fl) (ssize_t)recvfrom((RECVFROM_TYPE_ARG1)  (s),  \ +                                                 (RECVFROM_TYPE_ARG2 *)(b),  \ +                                                 (RECVFROM_TYPE_ARG3)  (bl), \ +                                                 (RECVFROM_TYPE_ARG4)  (0),  \ +                                                 (RECVFROM_TYPE_ARG5 *)(f),  \ +                                                 (RECVFROM_TYPE_ARG6 *)(fl)) +#endif +#else /* HAVE_RECVFROM */ +#ifndef sreadfrom +  /* */ +  Error Missing_definition_of_macro_sreadfrom +  /* */ +#endif +#endif /* HAVE_RECVFROM */ + + +#ifdef RECVFROM_TYPE_ARG6_IS_VOID +#  define RECVFROM_ARG6_T int +#else +#  define RECVFROM_ARG6_T RECVFROM_TYPE_ARG6 +#endif +#endif /* if 0 */ + + +/* + * Function-like macro definition used to close a socket. + */ + +#if defined(HAVE_CLOSESOCKET) +#  define sclose(x)  closesocket((x)) +#elif defined(HAVE_CLOSESOCKET_CAMEL) +#  define sclose(x)  CloseSocket((x)) +#else +#  define sclose(x)  close((x)) +#endif + + +/* + * Uppercase macro versions of ANSI/ISO is*() functions/macros which + * avoid negative number inputs with argument byte codes > 127. + */ + +#define ISSPACE(x)  (isspace((int)  ((unsigned char)x))) +#define ISDIGIT(x)  (isdigit((int)  ((unsigned char)x))) +#define ISALNUM(x)  (isalnum((int)  ((unsigned char)x))) +#define ISXDIGIT(x) (isxdigit((int) ((unsigned char)x))) +#define ISGRAPH(x)  (isgraph((int)  ((unsigned char)x))) +#define ISALPHA(x)  (isalpha((int)  ((unsigned char)x))) +#define ISPRINT(x)  (isprint((int)  ((unsigned char)x))) +#define ISUPPER(x)  (isupper((int)  ((unsigned char)x))) +#define ISLOWER(x)  (islower((int)  ((unsigned char)x))) + +#define ISBLANK(x)  (int)((((unsigned char)x) == ' ') || \ +                          (((unsigned char)x) == '\t')) + + +/* + * Typedef to 'unsigned char' if bool is not an available 'typedefed' type. + */ + +#ifndef HAVE_BOOL_T +typedef unsigned char bool; +#define HAVE_BOOL_T +#endif + + +/* + * Default definition of uppercase TRUE and FALSE. + */ + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + + +/* + * Typedef to 'int' if sig_atomic_t is not an available 'typedefed' type. + */ + +#ifndef HAVE_SIG_ATOMIC_T +typedef int sig_atomic_t; +#define HAVE_SIG_ATOMIC_T +#endif + + +/* + * Convenience SIG_ATOMIC_T definition + */ + +#ifdef HAVE_SIG_ATOMIC_T_VOLATILE +#define SIG_ATOMIC_T static sig_atomic_t +#else +#define SIG_ATOMIC_T static volatile sig_atomic_t +#endif + + +/* + * Default return type for signal handlers. + */ + +#ifndef RETSIGTYPE +#define RETSIGTYPE void +#endif + + +/* + * Macro used to include code only in debug builds. + */ + +#ifdef DEBUGBUILD +#define DEBUGF(x) x +#else +#define DEBUGF(x) do { } while (0) +#endif + + +/* + * Macro used to include assertion code only in debug builds. + */ + +#if defined(DEBUGBUILD) && defined(HAVE_ASSERT_H) +#define DEBUGASSERT(x) assert(x) +#else +#define DEBUGASSERT(x) do { } while (0) +#endif + + +/* + * Macro SOCKERRNO / SET_SOCKERRNO() returns / sets the *socket-related* errno + * (or equivalent) on this platform to hide platform details to code using it. + */ + +#ifdef USE_WINSOCK +#define SOCKERRNO         ((int)WSAGetLastError()) +#define SET_SOCKERRNO(x)  (WSASetLastError((int)(x))) +#else +#define SOCKERRNO         (errno) +#define SET_SOCKERRNO(x)  (errno = (x)) +#endif + + +/* + * Macro ERRNO / SET_ERRNO() returns / sets the NOT *socket-related* errno + * (or equivalent) on this platform to hide platform details to code using it. + */ + +#ifdef WIN32 +#define ERRNO         ((int)GetLastError()) +#define SET_ERRNO(x)  (SetLastError((DWORD)(x))) +#else +#define ERRNO         (errno) +#define SET_ERRNO(x)  (errno = (x)) +#endif + + +/* + * Portable error number symbolic names defined to Winsock error codes. + */ + +#ifdef USE_WINSOCK +#undef  EBADF            /* override definition in errno.h */ +#define EBADF            WSAEBADF +#undef  EINTR            /* override definition in errno.h */ +#define EINTR            WSAEINTR +#undef  EINVAL           /* override definition in errno.h */ +#define EINVAL           WSAEINVAL +#define EWOULDBLOCK      WSAEWOULDBLOCK +#define EINPROGRESS      WSAEINPROGRESS +#define EALREADY         WSAEALREADY +#define ENOTSOCK         WSAENOTSOCK +#define EDESTADDRREQ     WSAEDESTADDRREQ +#define EMSGSIZE         WSAEMSGSIZE +#define EPROTOTYPE       WSAEPROTOTYPE +#define ENOPROTOOPT      WSAENOPROTOOPT +#define EPROTONOSUPPORT  WSAEPROTONOSUPPORT +#define ESOCKTNOSUPPORT  WSAESOCKTNOSUPPORT +#define EOPNOTSUPP       WSAEOPNOTSUPP +#define EPFNOSUPPORT     WSAEPFNOSUPPORT +#define EAFNOSUPPORT     WSAEAFNOSUPPORT +#define EADDRINUSE       WSAEADDRINUSE +#define EADDRNOTAVAIL    WSAEADDRNOTAVAIL +#define ENETDOWN         WSAENETDOWN +#define ENETUNREACH      WSAENETUNREACH +#define ENETRESET        WSAENETRESET +#define ECONNABORTED     WSAECONNABORTED +#define ECONNRESET       WSAECONNRESET +#define ENOBUFS          WSAENOBUFS +#define EISCONN          WSAEISCONN +#define ENOTCONN         WSAENOTCONN +#define ESHUTDOWN        WSAESHUTDOWN +#define ETOOMANYREFS     WSAETOOMANYREFS +#define ETIMEDOUT        WSAETIMEDOUT +#define ECONNREFUSED     WSAECONNREFUSED +#define ELOOP            WSAELOOP +#ifndef ENAMETOOLONG     /* possible previous definition in errno.h */ +#define ENAMETOOLONG     WSAENAMETOOLONG +#endif +#define EHOSTDOWN        WSAEHOSTDOWN +#define EHOSTUNREACH     WSAEHOSTUNREACH +#ifndef ENOTEMPTY        /* possible previous definition in errno.h */ +#define ENOTEMPTY        WSAENOTEMPTY +#endif +#define EPROCLIM         WSAEPROCLIM +#define EUSERS           WSAEUSERS +#define EDQUOT           WSAEDQUOT +#define ESTALE           WSAESTALE +#define EREMOTE          WSAEREMOTE +#endif + + +/* + *  Actually use __32_getpwuid() on 64-bit VMS builds for getpwuid() + */ + +#if defined(VMS) && \ +    defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64) +#define getpwuid __32_getpwuid +#endif + + +/* + * Macro argv_item_t hides platform details to code using it. + */ + +#ifdef VMS +#define argv_item_t  __char_ptr32 +#else +#define argv_item_t  char * +#endif + + +/* + * We use this ZERO_NULL to avoid picky compiler warnings, + * when assigning a NULL pointer to a function pointer var. + */ + +#define ZERO_NULL 0 + + +#endif /* __SETUP_ONCE_H */ + diff --git a/3rdParty/CAres/src/windows_port.c b/3rdParty/CAres/src/windows_port.c new file mode 100644 index 0000000..ce129ae --- /dev/null +++ b/3rdParty/CAres/src/windows_port.c @@ -0,0 +1,23 @@ +#include "ares_setup.h" + +/* $Id: windows_port.c,v 1.22 2009-11-02 11:55:54 yangtse Exp $ */ + +/* only do the following on windows + */ +#if (defined(WIN32) || defined(WATT32)) && !defined(MSDOS) + +#ifdef __WATCOMC__ +/* + * Watcom needs a DllMain() in order to initialise the clib startup code. + */ +BOOL +WINAPI DllMain (HINSTANCE hnd, DWORD reason, LPVOID reserved) +{ +  (void) hnd; +  (void) reason; +  (void) reserved; +  return (TRUE); +} +#endif + +#endif /* WIN32 builds only */ @@ -321,6 +321,7 @@ SConscript(dirs = [  		"3rdParty/CppUnit",  		"3rdParty/Boost",  		"3rdParty/LibIDN", +		#"3rdParty/CAres",  		"3rdParty/SQLite"])  # Checker  | 
 Swift