Commit fa6fca1e authored by Denis Bilenko's avatar Denis Bilenko

add c-ares to the distribution (release 1.7.4 + a few patches)

parent 9a98b694
c-ares is based on ares, and these are the people that have worked on it since
the fork was made:
Alexander Lazic
Alexey Simak
Andreas Rieke
Ashish Sharma
Brad House
Brad Spencer
Bram Matthys
Dan Fandrich
Daniel Stenberg
Dirk Manske
Dominick Meglio
Doug Goldstein
Duncan Wilcox
Eino Tuominen
Erik Kline
George Neill
Gisle Vanem
Guilherme Balena Versiani
Gunter Knauf
Henrik Stoerner
James Bursa
Michael Wallner
Nick Mathewson
Phil Blundell
Ravi Pratap
Robin Cornelius
Sebastian at basti79.de
Shmulik Regev
Steinar H. Gunderson
Tofu Linden
Vlad Dinulescu
William Ahern
Yang Tse
liren at vivisimo.com
c-ares
======
This is c-ares, an asynchronous resolver library. It is intended for
applications which need to perform DNS queries without blocking, or need to
perform multiple DNS queries in parallel. The primary examples of such
applications are servers which communicate with multiple clients and programs
with graphical user interfaces.
The full source code is available in the 'c-ares' release archives, and in a
git repository: http://github.com/bagder/c-ares
If you find bugs, correct flaws, have questions or have comments in general in
regard to c-ares (or by all means the original ares too), get in touch with us
on the c-ares mailing list: http://cool.haxx.se/mailman/listinfo/c-ares
c-ares is of course distributed under the same MIT-style license as the
original ares.
You'll find all c-ares details and news here:
http://c-ares.haxx.se/
NOTES FOR C-ARES HACKERS
The following notes apply to c-ares version 1.7.0 and later.
* The distributed ares_build.h file is only intended to be used on systems
which can not run the also distributed configure script.
* The distributed ares_build.h file is generated as a copy of ares_build.h.dist
when the c-ares source code distribution archive file is originally created.
* If you check out from git on a non-configure platform, you must run the
appropriate buildconf* script to set up ares_build.h and other local files
before being able of compiling the library.
* 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, this new file is
generated from the ares_build.h.in template file.
* If you intend to distribute an already compiled c-ares library you _MUST_
also distribute along with it the generated ares_build.h which has been
used to compile it. Otherwise the library will be of no use for the users of
the library that you have built. It is _your_ responsibility to provide this
file. No one at the c-ares project can know how you have built the library.
* File ares_build.h includes platform and configuration dependent info,
and must not be modified by anyone. Configure script generates it for you.
* We cannot assume anything else but very basic compiler features being
present. While c-ares requires an ANSI C compiler to build, some of the
earlier ANSI compilers clearly can't deal with some preprocessor operators.
* Newlines must remain unix-style for older compilers' sake.
* Comments must be written in the old-style /* unnested C-fashion */
This diff is collapsed.
/* 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;
}
}
/* Copyright 1998, 2010 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(addr.addrV4);
}
}
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(addr.addrV6);
}
}
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(addr.addrV4));
else
memcpy(hostent->h_addr_list[0], &addr.addrV6, sizeof(addr.addrV6));
/* 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;
}
/* 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_nowarn.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 (;;)
{
int bytestoread = aresx_uztosi(*bufsize - offset);
if (!fgets(*buf + offset, bytestoread, 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;
if(len < *bufsize - 1)
continue;
/* Allocate more space. */
newbuf = realloc(*buf, *bufsize * 2);
if (!newbuf)
return ARES_ENOMEM;
*buf = newbuf;
*bufsize *= 2;
}
return ARES_SUCCESS;
}
/* 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
#ifndef __CARES_BUILD_H
#define __CARES_BUILD_H
/* Copyright (C) 2009 - 2010 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 git 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 git 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 */
#ifndef __CARES_BUILD_H
#define __CARES_BUILD_H
/* 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:
* -------
*
* 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/
*
* 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.in or ares_build.h,
* this is due to the following reason:
*
* 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.
*
*/
/* ================================================================ */
/* 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 CONFIGURE CAPABLE SYSTEMS ONLY */
/* ================================================================ */
/* Configure process defines this to 1 when it finds out that system */
/* header file ws2tcpip.h must be included by the external interface. */
#undef CARES_PULL_WS2TCPIP_H
#ifdef CARES_PULL_WS2TCPIP_H
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# include <winsock2.h>
# include <ws2tcpip.h>
#endif
/* Configure process defines this to 1 when it finds out that system */
/* header file sys/types.h must be included by the external interface. */
#undef CARES_PULL_SYS_TYPES_H
#ifdef CARES_PULL_SYS_TYPES_H
# include <sys/types.h>
#endif
/* Configure process defines this to 1 when it finds out that system */
/* header file sys/socket.h must be included by the external interface. */
#undef CARES_PULL_SYS_SOCKET_H
#ifdef CARES_PULL_SYS_SOCKET_H
# include <sys/socket.h>
#endif
/* The size of `long', as computed by sizeof. */
#undef CARES_SIZEOF_LONG
/* Integral data type used for ares_socklen_t. */
#undef CARES_TYPEOF_ARES_SOCKLEN_T
/* The size of `ares_socklen_t', as computed by sizeof. */
#undef CARES_SIZEOF_ARES_SOCKLEN_T
/* Data type definition of ares_socklen_t. */
typedef CARES_TYPEOF_ARES_SOCKLEN_T ares_socklen_t;
#endif /* __CARES_BUILD_H */
This diff is collapsed.
/* Copyright (C) 2009-2010 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_get_servers()
** ares_parse_srv_reply()
** ares_parse_txt_reply()
*/
void ares_free_data(void *dataptr)
{
struct ares_data *ptr;
if (!dataptr)
return;
#ifdef __INTEL_COMPILER
# pragma warning(push)
# pragma warning(disable:1684)
/* 1684: conversion from pointer to same-sized integral type */
#endif
ptr = (void *)((char *)dataptr - offsetof(struct ares_data, data));
#ifdef __INTEL_COMPILER
# pragma warning(pop)
#endif
if (ptr->mark != ARES_DATATYPE_MARK)
return;
switch (ptr->type)
{
case ARES_DATATYPE_MX_REPLY:
if (ptr->data.mx_reply.next)
ares_free_data(ptr->data.mx_reply.next);
if (ptr->data.mx_reply.host)
free(ptr->data.mx_reply.host);
break;
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;
case ARES_DATATYPE_ADDR_NODE:
if (ptr->data.addr_node.next)
ares_free_data(ptr->data.addr_node.next);
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_MX_REPLY:
ptr->data.mx_reply.next = NULL;
ptr->data.mx_reply.host = NULL;
ptr->data.mx_reply.priority = 0;
break;
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;
case ARES_DATATYPE_ADDR_NODE:
ptr->data.addr_node.next = NULL;
ptr->data.addr_node.family = 0;
memset(&ptr->data.addr_node.addrV6, 0,
sizeof(ptr->data.addr_node.addrV6));
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;
#ifdef __INTEL_COMPILER
# pragma warning(push)
# pragma warning(disable:1684)
/* 1684: conversion from pointer to same-sized integral type */
#endif
ptr = (void *)((char *)dataptr - offsetof(struct ares_data, data));
#ifdef __INTEL_COMPILER
# pragma warning(pop)
#endif
if (ptr->mark == ARES_DATATYPE_MARK)
return ptr->type;
return ARES_DATATYPE_UNKNOWN;
}
#ifndef ARES_DATA_H
#define ARES_DATA_H
/* Copyright (C) 2009-2010 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 */
ARES_DATATYPE_ADDR_NODE, /* struct ares_addr_node - introduced in 1.7.1 */
ARES_DATATYPE_MX_REPLY, /* struct ares_mx_reply - introduced in 1.7.2 */
#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;
struct ares_addr_node addr_node;
struct ares_mx_reply mx_reply;
} data;
};
void *ares_malloc_data(ares_datatype type);
ares_datatype ares_get_datatype(void * dataptr);
#endif
/* Copyright 1998 by the Massachusetts Institute of Technology.
* Copyright (C) 2004-2010 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 <assert.h>
#include <stdlib.h>
#include "ares.h"
#include "ares_private.h"
void ares_destroy_options(struct ares_options *options)
{
int i;
if(options->servers)
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
ares__destroy_servers_state(channel);
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);
}
void ares__destroy_servers_state(ares_channel channel)
{
struct server_state *server;
int i;
if (channel->servers)
{
for (i = 0; i < channel->nservers; i++)
{
server = &channel->servers[i];
ares__close_sockets(channel, server);
assert(ares__is_list_empty(&server->queries_to_server));
}
free(channel->servers);
channel->servers = NULL;
}
channel->nservers = -1;
}
/* 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 */
/* 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;
union {
ssize_t sig;
size_t uns;
} nlen;
nlen.sig = name_length(encoded, abuf, alen);
if (nlen.sig < 0)
return ARES_EBADNAME;
*s = malloc(nlen.uns + 1);
if (!*s)
return ARES_ENOMEM;
q = *s;
if (nlen.uns == 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;
}
/* 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);
}
/* 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);
}
/* 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 gethostbyaddr_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 gethostbyaddr_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(aquery->addr.addrV4)) ||
(family == AF_INET6 && addrlen != sizeof(aquery->addr.addrV6)))
{
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(aquery->addr.addrV4));
else
memcpy(&aquery->addr.addrV6, addr, sizeof(aquery->addr.addrV6));
aquery->addr.family = family;
aquery->callback = callback;
aquery->arg = arg;
aquery->remaining_lookups = channel->lookups;
aquery->timeouts = 0;
gethostbyaddr_next_lookup(aquery);
}
static void gethostbyaddr_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 = gethostbyaddr_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(aquery->addr.addrV4);
status = ares_parse_ptr_reply(abuf, alen, &aquery->addr.addrV4,
(int)addrlen, AF_INET, &host);
}
else
{
addrlen = sizeof(aquery->addr.addrV6);
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
gethostbyaddr_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 gethostbyaddr_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(addr->addrV4)) == 0)
break;
}
else if (addr->family == AF_INET6)
{
if (memcmp((*host)->h_addr, &addr->addrV6,
sizeof(addr->addrV6)) == 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);
unsigned long a1 = (laddr >> 24UL) & 0xFFUL;
unsigned long a2 = (laddr >> 16UL) & 0xFFUL;
unsigned long a3 = (laddr >> 8UL) & 0xFFUL;
unsigned long a4 = laddr & 0xFFUL;
sprintf(name, "%lu.%lu.%lu.%lu.in-addr.arpa", a4, a3, a2, a1);
}
else
{
unsigned char *bytes = (unsigned char *)&addr->addrV6;
/* 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);
}
}
This diff is collapsed.
This diff is collapsed.
#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 */
This diff is collapsed.
/* 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
#ifndef HAVE_STRUCT_SOCKADDR_IN6
struct sockaddr_in6
{
unsigned short sin6_family;
unsigned short sin6_port;
unsigned long sin6_flowinfo;
struct ares_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
/* Defined in ares_net_pton.c for no particular reason. */
extern const struct ares_in6_addr ares_in6addr_any; /* :: */
#endif /* ARES_IPV6_H */
/* 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;
}
#ifndef HEADER_CARES_LIBRARY_INIT_H
#define HEADER_CARES_LIBRARY_INIT_H
/* 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 */
/* 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;
}
}
#ifndef __ARES_LLIST_H
#define __ARES_LLIST_H
/* 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 */
/* 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;
}
/* Copyright (C) 2010 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_nowarn.h"
#if (SIZEOF_INT == 2)
# define CARES_MASK_SINT 0x7FFF
# define CARES_MASK_UINT 0xFFFF
#elif (SIZEOF_INT == 4)
# define CARES_MASK_SINT 0x7FFFFFFF
# define CARES_MASK_UINT 0xFFFFFFFF
#elif (SIZEOF_INT == 8)
# define CARES_MASK_SINT 0x7FFFFFFFFFFFFFFF
# define CARES_MASK_UINT 0xFFFFFFFFFFFFFFFF
#elif (SIZEOF_INT == 16)
# define CARES_MASK_SINT 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
# define CARES_MASK_UINT 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
#endif
/*
** size_t to signed int
*/
int aresx_uztosi(size_t uznum)
{
#ifdef __INTEL_COMPILER
# pragma warning(push)
# pragma warning(disable:810) /* conversion may lose significant bits */
#endif
return (int)(uznum & (size_t) CARES_MASK_SINT);
#ifdef __INTEL_COMPILER
# pragma warning(pop)
#endif
}
/*
** signed long to signed int
*/
int aresx_sltosi(long slnum)
{
#ifdef __INTEL_COMPILER
# pragma warning(push)
# pragma warning(disable:810) /* conversion may lose significant bits */
#endif
return (int)(slnum & (long) CARES_MASK_SINT);
#ifdef __INTEL_COMPILER
# pragma warning(pop)
#endif
}
#ifndef HEADER_CARES_NOWARN_H
#define HEADER_CARES_NOWARN_H
/* Copyright (C) 2010 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.
*/
int aresx_uztosi(size_t uznum);
int aresx_sltosi(long slnum);
#endif /* HEADER_CARES_NOWARN_H */
/* Copyright 1998 by the Massachusetts Institute of Technology.
* Copyright (C) 2008-2010 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_ARPA_INET_H
# include <arpa/inet.h>
#endif
#include "ares.h"
#include "ares_data.h"
#include "inet_net_pton.h"
#include "ares_private.h"
int ares_get_servers(ares_channel channel,
struct ares_addr_node **servers)
{
struct ares_addr_node *srvr_head = NULL;
struct ares_addr_node *srvr_last = NULL;
struct ares_addr_node *srvr_curr;
int status = ARES_SUCCESS;
int i;
if (!channel)
return ARES_ENODATA;
for (i = 0; i < channel->nservers; i++)
{
/* Allocate storage for this server node appending it to the list */
srvr_curr = ares_malloc_data(ARES_DATATYPE_ADDR_NODE);
if (!srvr_curr)
{
status = ARES_ENOMEM;
break;
}
if (srvr_last)
{
srvr_last->next = srvr_curr;
}
else
{
srvr_head = srvr_curr;
}
srvr_last = srvr_curr;
/* Fill this server node data */
srvr_curr->family = channel->servers[i].addr.family;
if (srvr_curr->family == AF_INET)
memcpy(&srvr_curr->addrV4, &channel->servers[i].addr.addrV4,
sizeof(srvr_curr->addrV4));
else
memcpy(&srvr_curr->addrV6, &channel->servers[i].addr.addrV6,
sizeof(srvr_curr->addrV6));
}
if (status != ARES_SUCCESS)
{
if (srvr_head)
{
ares_free_data(srvr_head);
srvr_head = NULL;
}
}
*servers = srvr_head;
return status;
}
int ares_set_servers(ares_channel channel,
struct ares_addr_node *servers)
{
struct ares_addr_node *srvr;
int num_srvrs = 0;
int i;
if (ares_library_initialized() != ARES_SUCCESS)
return ARES_ENOTINITIALIZED;
if (!channel)
return ARES_ENODATA;
ares__destroy_servers_state(channel);
for (srvr = servers; srvr; srvr = srvr->next)
{
num_srvrs++;
}
if (num_srvrs > 0)
{
/* Allocate storage for servers state */
channel->servers = malloc(num_srvrs * sizeof(struct server_state));
if (!channel->servers)
{
return ARES_ENOMEM;
}
channel->nservers = num_srvrs;
/* Fill servers state address data */
for (i = 0, srvr = servers; srvr; i++, srvr = srvr->next)
{
channel->servers[i].addr.family = srvr->family;
if (srvr->family == AF_INET)
memcpy(&channel->servers[i].addr.addrV4, &srvr->addrV4,
sizeof(srvr->addrV4));
else
memcpy(&channel->servers[i].addr.addrV6, &srvr->addrV6,
sizeof(srvr->addrV6));
}
/* Initialize servers state remaining data */
ares__init_servers_state(channel);
}
return ARES_SUCCESS;
}
/* Incomming string format: host[:port][,host[:port]]... */
int ares_set_servers_csv(ares_channel channel,
const char* _csv)
{
int i;
char* csv = NULL;
char* ptr;
char* start_host;
long port;
bool found_port;
int rv = ARES_SUCCESS;
struct ares_addr_node *servers = NULL;
struct ares_addr_node *last = NULL;
if (ares_library_initialized() != ARES_SUCCESS)
return ARES_ENOTINITIALIZED;
if (!channel)
return ARES_ENODATA;
ares__destroy_servers_state(channel);
i = strlen(_csv);
if (i == 0)
return ARES_SUCCESS; /* blank all servers */
csv = malloc(i + 2);
strcpy(csv, _csv);
if (csv[i-1] != ',') { /* make parsing easier by ensuring ending ',' */
csv[i] = ',';
csv[i+1] = 0;
}
start_host = csv;
found_port = false;
for (ptr = csv; *ptr; ptr++) {
if (*ptr == ',') {
char* pp = ptr - 1;
struct in_addr in4;
struct ares_in6_addr in6;
struct ares_addr_node *s = NULL;
*ptr = 0; /* null terminate host:port string */
/* Got an entry..see if port was specified. */
while (pp > start_host) {
if (*pp == ':')
break; /* yes */
if (!ISDIGIT(*pp)) {
/* Found end of digits before we found :, so wasn't a port */
pp = ptr;
break;
}
pp--;
}
if ((pp != start_host) && ((pp + 1) < ptr)) {
/* Found it. */
found_port = true;
port = strtol(pp + 1, NULL, 10);
*pp = 0; /* null terminate host */
}
/* resolve host, try ipv4 first, rslt is in network byte order */
rv = ares_inet_pton(AF_INET, start_host, &in4);
if (!rv) {
/* Ok, try IPv6 then */
rv = ares_inet_pton(AF_INET6, start_host, &in6);
if (!rv) {
rv = ARES_EBADSTR;
goto out;
}
/* was ipv6, add new server */
s = malloc(sizeof(*s));
if (!s) {
rv = ARES_ENOMEM;
goto out;
}
s->family = AF_INET6;
memcpy(&s->addr, &in6, sizeof(struct ares_in6_addr));
}
else {
/* was ipv4, add new server */
s = malloc(sizeof(*s));
if (!s) {
rv = ARES_ENOMEM;
goto out;
}
s->family = AF_INET;
memcpy(&s->addr, &in4, sizeof(struct in_addr));
}
if (s) {
/* TODO: Add port to ares_addr_node and assign it here. */
s->next = NULL;
if (last) {
last->next = s;
}
else {
servers = s;
last = s;
}
}
/* Set up for next one */
found_port = false;
start_host = ptr + 1;
}
}
rv = ares_set_servers(channel, servers);
out:
if (csv)
free(csv);
while (servers) {
struct ares_addr_node *s = servers;
servers = servers->next;
free(s);
}
return rv;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#ifndef HEADER_CARES_STRCASECMP_H
#define HEADER_CARES_STRCASECMP_H
/* 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 */
This diff is collapsed.
#ifndef HEADER_CARES_STRDUP_H
#define HEADER_CARES_STRDUP_H
/* 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 */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment