mirror of
https://github.com/moparisthebest/curl
synced 2024-12-21 23:58:49 -05:00
Added ares_getnameinfo which mimics the getnameinfo API
This commit is contained in:
parent
f425a25c98
commit
645729e943
@ -1,5 +1,10 @@
|
|||||||
Changelog for the c-ares project
|
Changelog for the c-ares project
|
||||||
|
|
||||||
|
* May 16
|
||||||
|
|
||||||
|
- Added ares_getnameinfo which mimics the getnameinfo API (another feature
|
||||||
|
that could use testing).
|
||||||
|
|
||||||
* May 14
|
* May 14
|
||||||
|
|
||||||
- Added an inet_ntop function from BIND for systems that do not have it.
|
- Added an inet_ntop function from BIND for systems that do not have it.
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
CSOURCES = ares_fds.c ares_process.c ares_free_hostent.c ares_query.c \
|
CSOURCES = ares_fds.c ares_process.c ares_free_hostent.c ares_query.c \
|
||||||
ares__close_sockets.c ares_free_string.c ares_search.c ares__get_hostent.c \
|
ares__close_sockets.c ares_free_string.c ares_search.c ares__get_hostent.c \
|
||||||
ares_gethostbyaddr.c ares_send.c ares__read_line.c ares_gethostbyname.c \
|
ares_gethostbyaddr.c ares_send.c ares__read_line.c ares_gethostbyname.c \
|
||||||
ares_strerror.c ares_cancel.c ares_init.c ares_timeout.c ares_destroy.c \
|
ares_strerror.c ares_cancel.c ares_init.c ares_timeout.c ares_destroy.c \
|
||||||
ares_mkquery.c ares_version.c ares_expand_name.c ares_parse_a_reply.c \
|
ares_mkquery.c ares_version.c ares_expand_name.c ares_parse_a_reply.c \
|
||||||
windows_port.c ares_expand_string.c ares_parse_ptr_reply.c \
|
windows_port.c ares_expand_string.c ares_parse_ptr_reply.c \
|
||||||
ares_parse_aaaa_reply.c inet_net_pton.c bitncmp.c inet_ntop.c
|
ares_parse_aaaa_reply.c ares_getnameinfo.c inet_net_pton.c bitncmp.c \
|
||||||
|
inet_ntop.c
|
||||||
|
|
||||||
HHEADERS = ares.h ares_private.h setup.h ares_dns.h ares_version.h nameser.h \
|
HHEADERS = ares.h ares_private.h setup.h ares_dns.h ares_version.h \
|
||||||
inet_net_pton.h ares_ipv6.h bitncmp.h
|
nameser.h inet_net_pton.h inet_ntop.h ares_ipv6.h bitncmp.h
|
||||||
|
|
||||||
MANPAGES= ares_destroy.3 ares_expand_name.3 ares_expand_string.3 ares_fds.3 \
|
MANPAGES= ares_destroy.3 ares_expand_name.3 ares_expand_string.3 ares_fds.3 \
|
||||||
ares_free_hostent.3 ares_free_string.3 ares_gethostbyaddr.3 \
|
ares_free_hostent.3 ares_free_string.3 ares_gethostbyaddr.3 \
|
||||||
ares_gethostbyname.3 ares_init.3 ares_init_options.3 ares_mkquery.3 \
|
ares_gethostbyname.3 ares_init.3 ares_init_options.3 ares_mkquery.3 \
|
||||||
ares_parse_a_reply.3 ares_parse_ptr_reply.3 ares_process.3 \
|
ares_parse_a_reply.3 ares_parse_ptr_reply.3 ares_process.3 \
|
||||||
ares_query.3 ares_search.3 ares_send.3 ares_strerror.3 ares_timeout.3 \
|
ares_query.3 ares_search.3 ares_send.3 ares_strerror.3 ares_timeout.3 \
|
||||||
ares_version.3 ares_cancel.3 ares_parse_aaaa_reply.3
|
ares_version.3 ares_cancel.3 ares_parse_aaaa_reply.3 ares_getnameinfo.3
|
||||||
|
@ -119,6 +119,26 @@ AC_DEFUN([CARES_CHECK_STRUCT], [
|
|||||||
fi
|
fi
|
||||||
])
|
])
|
||||||
|
|
||||||
|
dnl This macro determins if the specified struct contains a specific member.
|
||||||
|
dnl Syntax:
|
||||||
|
dnl CARES_CHECK_STRUCT_MEMBER(headers, struct name, member name, if found, [if not found])
|
||||||
|
|
||||||
|
AC_DEFUN([CARES_CHECK_STRUCT_MEMBER], [
|
||||||
|
AC_MSG_CHECKING([if struct $2 has member $3])
|
||||||
|
AC_TRY_COMPILE([$1],
|
||||||
|
[
|
||||||
|
struct $2 struct_instance;
|
||||||
|
struct_instance.$3 = 0;
|
||||||
|
], ac_struct="yes", ac_found="no")
|
||||||
|
if test "$ac_struct" = "yes" ; then
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
$4
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
$5
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
|
||||||
dnl This macro determines if the specified constant exists in the specified file
|
dnl This macro determines if the specified constant exists in the specified file
|
||||||
dnl Syntax:
|
dnl Syntax:
|
||||||
dnl CARES_CHECK_CONSTANT(headers, constant name, if found, [if not found])
|
dnl CARES_CHECK_CONSTANT(headers, constant name, if found, [if not found])
|
||||||
|
30
ares/ares.h
30
ares/ares.h
@ -29,12 +29,14 @@
|
|||||||
|
|
||||||
#if defined(WATT32)
|
#if defined(WATT32)
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <tcp.h>
|
#include <tcp.h>
|
||||||
#elif defined(WIN32)
|
#elif defined(WIN32)
|
||||||
#include <winsock.h>
|
#include <winsock.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#else
|
#else
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -64,6 +66,9 @@ extern "C" {
|
|||||||
#define ARES_EDESTRUCTION 16
|
#define ARES_EDESTRUCTION 16
|
||||||
#define ARES_EBADSTR 17
|
#define ARES_EBADSTR 17
|
||||||
|
|
||||||
|
/* ares_getnameinfo error codes */
|
||||||
|
#define ARES_EBADFLAGS 18
|
||||||
|
|
||||||
/* Flag values */
|
/* Flag values */
|
||||||
#define ARES_FLAG_USEVC (1 << 0)
|
#define ARES_FLAG_USEVC (1 << 0)
|
||||||
#define ARES_FLAG_PRIMARY (1 << 1)
|
#define ARES_FLAG_PRIMARY (1 << 1)
|
||||||
@ -85,6 +90,24 @@ extern "C" {
|
|||||||
#define ARES_OPT_DOMAINS (1 << 7)
|
#define ARES_OPT_DOMAINS (1 << 7)
|
||||||
#define ARES_OPT_LOOKUPS (1 << 8)
|
#define ARES_OPT_LOOKUPS (1 << 8)
|
||||||
|
|
||||||
|
/* 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_ALLOW_UNASSIGNED (1 << 11)
|
||||||
|
#define ARES_NI_USE_STD3_ASCII_RULES (1 << 12)
|
||||||
|
|
||||||
struct ares_options {
|
struct ares_options {
|
||||||
int flags;
|
int flags;
|
||||||
int timeout;
|
int timeout;
|
||||||
@ -101,12 +124,15 @@ struct ares_options {
|
|||||||
|
|
||||||
struct hostent;
|
struct hostent;
|
||||||
struct timeval;
|
struct timeval;
|
||||||
|
struct sockaddr;
|
||||||
struct ares_channeldata;
|
struct ares_channeldata;
|
||||||
typedef struct ares_channeldata *ares_channel;
|
typedef struct ares_channeldata *ares_channel;
|
||||||
typedef void (*ares_callback)(void *arg, int status, unsigned char *abuf,
|
typedef void (*ares_callback)(void *arg, int status, unsigned char *abuf,
|
||||||
int alen);
|
int alen);
|
||||||
typedef void (*ares_host_callback)(void *arg, int status,
|
typedef void (*ares_host_callback)(void *arg, int status,
|
||||||
struct hostent *hostent);
|
struct hostent *hostent);
|
||||||
|
typedef void (*ares_nameinfo_callback)(void *arg, int status,
|
||||||
|
char *node, char *service);
|
||||||
|
|
||||||
int ares_init(ares_channel *channelptr);
|
int ares_init(ares_channel *channelptr);
|
||||||
int ares_init_options(ares_channel *channelptr, struct ares_options *options,
|
int ares_init_options(ares_channel *channelptr, struct ares_options *options,
|
||||||
@ -123,7 +149,9 @@ void ares_gethostbyname(ares_channel channel, const char *name, int family,
|
|||||||
ares_host_callback callback, void *arg);
|
ares_host_callback callback, void *arg);
|
||||||
void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen,
|
void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen,
|
||||||
int family, ares_host_callback callback, void *arg);
|
int family, ares_host_callback callback, void *arg);
|
||||||
|
void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa,
|
||||||
|
socklen_t salen, int flags, ares_nameinfo_callback callback,
|
||||||
|
void *arg);
|
||||||
int ares_fds(ares_channel channel, fd_set *read_fds, fd_set *write_fds);
|
int ares_fds(ares_channel channel, fd_set *read_fds, fd_set *write_fds);
|
||||||
struct timeval *ares_timeout(ares_channel channel, struct timeval *maxtv,
|
struct timeval *ares_timeout(ares_channel channel, struct timeval *maxtv,
|
||||||
struct timeval *tv);
|
struct timeval *tv);
|
||||||
|
145
ares/ares_getnameinfo.3
Normal file
145
ares/ares_getnameinfo.3
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
.\" $Id$
|
||||||
|
.\"
|
||||||
|
.\" 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.
|
||||||
|
.\"
|
||||||
|
.TH ARES_GETNAMEINFO 3 "16 May 2005"
|
||||||
|
.SH NAME
|
||||||
|
ares_getnameinfo \- Address-to-nodename translation in protocol-independent manner
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.nf
|
||||||
|
.B #include <ares.h>
|
||||||
|
.PP
|
||||||
|
.B typedef void (*ares_nameinfo_callback)(void *\fIarg\fP, int \fIstatus\fP,
|
||||||
|
.B char *\fInode\fP, char *\fIservice\fP)
|
||||||
|
.PP
|
||||||
|
.B void ares_getnameinfo(ares_channel \fIchannel\fP, const struct sockaddr *\fIsa\fP,
|
||||||
|
.B socklen_t \fIsalen\fP, int \fIflags\fP, ares_nameinfo_callback \fIcallback\fP,
|
||||||
|
.B void *\fIarg\fP)
|
||||||
|
.fi
|
||||||
|
.SH DESCRIPTION
|
||||||
|
The
|
||||||
|
.B ares_getnameinfo
|
||||||
|
function is defined for protocol-independent address translation. The function
|
||||||
|
is a combination of \fIares_gethostbyaddr(3)\fP and \fIgetservbyport(3)\fP. The function will
|
||||||
|
translate the address either by executing a host query on the name service channel
|
||||||
|
identified by
|
||||||
|
.IR channel
|
||||||
|
or it will attempt to resolve it locally if possible.
|
||||||
|
The parameters
|
||||||
|
.I sa
|
||||||
|
and
|
||||||
|
.I len
|
||||||
|
give the address as a sockaddr structure, and
|
||||||
|
.I flags
|
||||||
|
gives the options that the function will use. Valid flags are listed below:
|
||||||
|
.TP 19
|
||||||
|
.B ARES_NI_NOFQDN
|
||||||
|
Only the nodename portion of the FQDN is returned for local hosts.
|
||||||
|
.TP 19
|
||||||
|
.B ARES_NI_NUMERICHOST
|
||||||
|
The numeric form of the hostname is returned rather than the name.
|
||||||
|
.TP 19
|
||||||
|
.B ARES_NI_NAMEREQD
|
||||||
|
An error is returned if the hostname cannot be found in the DNS.
|
||||||
|
.TP 19
|
||||||
|
.B ARES_NI_NUMERICSERV
|
||||||
|
The numeric form of the service is returned rather than the name.
|
||||||
|
.TP 19
|
||||||
|
.B ARES_NI_TCP
|
||||||
|
The service name is to be looked up for the TCP protocol.
|
||||||
|
.TP 19
|
||||||
|
.B ARES_NI_UDP
|
||||||
|
The service name is to be looked up for the UDP protocol.
|
||||||
|
.TP 19
|
||||||
|
.B ARES_NI_SCTP
|
||||||
|
The service name is to be looked up for the SCTP protocol.
|
||||||
|
.TP 19
|
||||||
|
.B ARES_NI_DCCP
|
||||||
|
The service name is to be looked up for the DCCP protocol.
|
||||||
|
.TP 19
|
||||||
|
.B ARES_NI_NUMERICSCOPE
|
||||||
|
The numeric form of the scope ID is returned rather than the name.
|
||||||
|
.TP 19
|
||||||
|
.B ARES_NI_LOOKUPHOST
|
||||||
|
A hostname lookup is being requested.
|
||||||
|
.TP 19
|
||||||
|
.B ARES_NI_LOOKUPSERVICE
|
||||||
|
A service name lookup is being requested.
|
||||||
|
.PP
|
||||||
|
When the query
|
||||||
|
is complete or has
|
||||||
|
failed, the ares library will invoke \fIcallback\fP. Completion or failure of
|
||||||
|
the query may happen immediately, or may happen during a later call to
|
||||||
|
\fIares_process(3)\fP, \fIares_destroy(3)\fP or \fIares_cancel(3)\fP.
|
||||||
|
.PP
|
||||||
|
The callback argument
|
||||||
|
.I arg
|
||||||
|
is copied from the
|
||||||
|
.B ares_getnameinfo
|
||||||
|
argument
|
||||||
|
.IR arg .
|
||||||
|
The callback argument
|
||||||
|
.I status
|
||||||
|
indicates whether the query succeeded and, if not, how it failed. It
|
||||||
|
may have any of the following values:
|
||||||
|
.TP 19
|
||||||
|
.B ARES_SUCCESS
|
||||||
|
The host lookup completed successfully.
|
||||||
|
.TP 19
|
||||||
|
.B ARES_ENOTIMP
|
||||||
|
The ares library does not know how to look up addresses of type
|
||||||
|
.IR family .
|
||||||
|
.TP 19
|
||||||
|
.B ARES_ENOTFOUND
|
||||||
|
The address
|
||||||
|
.I addr
|
||||||
|
was not found.
|
||||||
|
.TP 19
|
||||||
|
.B ARES_ENOMEM
|
||||||
|
Memory was exhausted.
|
||||||
|
.TP 19
|
||||||
|
.B ARES_EDESTRUCTION
|
||||||
|
The name service channel
|
||||||
|
.I channel
|
||||||
|
is being destroyed; the query will not be completed.
|
||||||
|
.TP 19
|
||||||
|
.B ARES_EBADFLAGS
|
||||||
|
The
|
||||||
|
.I flags
|
||||||
|
parameter contains an illegal value.
|
||||||
|
.PP
|
||||||
|
On successful completion of the query, the callback argument
|
||||||
|
.I node
|
||||||
|
contains a string representing the hostname (assuming
|
||||||
|
.B ARES_NI_LOOKUPHOST
|
||||||
|
was specified). Additionally,
|
||||||
|
.I service
|
||||||
|
contains a string representing the service name (assuming
|
||||||
|
.B ARES_NI_LOOKUPSERVICE
|
||||||
|
was specified).
|
||||||
|
If the query did not complete successfully, or one of the values
|
||||||
|
was not requested,
|
||||||
|
.I node
|
||||||
|
or
|
||||||
|
.I service
|
||||||
|
will be
|
||||||
|
.BR NULL .
|
||||||
|
.SH SEE ALSO
|
||||||
|
.BR ares_process (3),
|
||||||
|
.BR ares_getaddrinfo (3)
|
||||||
|
.SH AUTHOR
|
||||||
|
Dominick Meglio
|
||||||
|
.br
|
||||||
|
Copyright 2005 by Dominick Meglio.
|
322
ares/ares_getnameinfo.c
Normal file
322
ares/ares_getnameinfo.c
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
/* 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 "setup.h"
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#if defined(WIN32) && !defined(WATT32)
|
||||||
|
#include "nameser.h"
|
||||||
|
#else
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <arpa/nameser.h>
|
||||||
|
#ifdef HAVE_ARPA_NAMESER_COMPAT_H
|
||||||
|
#include <arpa/nameser_compat.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_NET_IF_H
|
||||||
|
#include <net/if.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "ares.h"
|
||||||
|
#include "ares_private.h"
|
||||||
|
#include "ares_ipv6.h"
|
||||||
|
#include "inet_ntop.h"
|
||||||
|
|
||||||
|
#ifdef WATT32
|
||||||
|
#undef WIN32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct nameinfo_query {
|
||||||
|
ares_nameinfo_callback callback;
|
||||||
|
void *arg;
|
||||||
|
union {
|
||||||
|
struct sockaddr_in addr4;
|
||||||
|
struct sockaddr_in6 addr6;
|
||||||
|
} addr;
|
||||||
|
int family;
|
||||||
|
int flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
#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, struct hostent *host);
|
||||||
|
static char *lookup_service(unsigned short port, int flags, char *buf);
|
||||||
|
static char *append_scopeid(struct sockaddr_in6 *addr6, unsigned int scopeid, char *buf);
|
||||||
|
static char *ares_striendstr(const char *s1, const char *s2);
|
||||||
|
|
||||||
|
void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, socklen_t salen,
|
||||||
|
int flags, ares_nameinfo_callback callback, void *arg)
|
||||||
|
{
|
||||||
|
struct sockaddr_in *addr;
|
||||||
|
struct sockaddr_in6 *addr6;
|
||||||
|
struct nameinfo_query *niquery;
|
||||||
|
|
||||||
|
/* Verify the buffer size */
|
||||||
|
if (salen == sizeof(struct sockaddr_in))
|
||||||
|
addr = (struct sockaddr_in *)sa;
|
||||||
|
else if (salen == sizeof(struct sockaddr_in6))
|
||||||
|
addr6 = (struct sockaddr_in6 *)sa;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
callback(arg, ARES_ENOTIMP, 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;
|
||||||
|
unsigned int port = 0;
|
||||||
|
|
||||||
|
if (salen == sizeof(struct sockaddr_in))
|
||||||
|
port = addr->sin_port;
|
||||||
|
else
|
||||||
|
port = addr6->sin6_port;
|
||||||
|
service = lookup_service(port, flags, buf);
|
||||||
|
callback(arg, ARES_SUCCESS, 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))
|
||||||
|
{
|
||||||
|
unsigned int port = 0;
|
||||||
|
char ipbuf[IPBUFSIZ];
|
||||||
|
char srvbuf[32];
|
||||||
|
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, NULL, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (salen == sizeof(struct sockaddr_in6))
|
||||||
|
{
|
||||||
|
ares_inet_ntop(AF_INET6, &addr6->sin6_addr, ipbuf, IPBUFSIZ);
|
||||||
|
port = addr6->sin6_port;
|
||||||
|
/* If the system supports scope IDs, use it */
|
||||||
|
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
|
||||||
|
append_scopeid(addr6, flags, ipbuf);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ares_inet_ntop(AF_INET, &addr->sin_addr, ipbuf, IPBUFSIZ);
|
||||||
|
port = addr->sin_port;
|
||||||
|
}
|
||||||
|
/* They also want a service */
|
||||||
|
if (flags & ARES_NI_LOOKUPSERVICE)
|
||||||
|
service = lookup_service(port, flags, srvbuf);
|
||||||
|
callback(arg, ARES_SUCCESS, ipbuf, service);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* This is where a DNS lookup becomes necessary */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
niquery = malloc(sizeof(struct nameinfo_query));
|
||||||
|
if (!niquery)
|
||||||
|
{
|
||||||
|
callback(arg, ARES_ENOMEM, NULL, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
niquery->callback = callback;
|
||||||
|
niquery->arg = arg;
|
||||||
|
niquery->flags = flags;
|
||||||
|
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, struct hostent *host)
|
||||||
|
{
|
||||||
|
struct nameinfo_query *niquery = (struct nameinfo_query *) arg;
|
||||||
|
char srvbuf[33];
|
||||||
|
char *service = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
else
|
||||||
|
service = lookup_service(niquery->addr.addr6.sin6_port, niquery->flags, 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.
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callback(niquery->arg, ARES_SUCCESS, 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);
|
||||||
|
#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);
|
||||||
|
else
|
||||||
|
service = lookup_service(niquery->addr.addr6.sin6_port, niquery->flags, srvbuf);
|
||||||
|
}
|
||||||
|
callback(niquery->arg, ARES_SUCCESS, ipbuf, service);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
callback(niquery->arg, status, NULL, NULL);
|
||||||
|
free(niquery);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *lookup_service(unsigned short port, int flags, char *buf)
|
||||||
|
{
|
||||||
|
if (port)
|
||||||
|
{
|
||||||
|
/* Just return the port as a string */
|
||||||
|
if (flags & ARES_NI_NUMERICSERV)
|
||||||
|
sprintf(buf, "%u", ntohs(port));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct servent *se;
|
||||||
|
char *proto;
|
||||||
|
|
||||||
|
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";
|
||||||
|
se = getservbyport(port, proto);
|
||||||
|
if (se && se->s_name)
|
||||||
|
strcpy(buf, se->s_name);
|
||||||
|
else
|
||||||
|
sprintf(buf, "%u", ntohs(port));
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
|
||||||
|
static char *append_scopeid(struct sockaddr_in6 *addr6, unsigned int flags, char *buf)
|
||||||
|
{
|
||||||
|
char tmpbuf[IF_NAMESIZE + 1];
|
||||||
|
|
||||||
|
tmpbuf[0] = '%';
|
||||||
|
#ifdef HAVE_IF_INDEXTONAME
|
||||||
|
if ((flags & ARES_NI_NUMERICSCOPE) || (!IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr)
|
||||||
|
&& !IN6_IS_ADDR_MC_LINKLOCAL(&addr6->sin6_addr)))
|
||||||
|
{
|
||||||
|
sprintf(&tmpbuf[1], "%u", addr6->sin6_scope_id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (if_indextoname(addr6->sin6_scope_id, &tmpbuf[1]) == NULL)
|
||||||
|
sprintf(&tmpbuf[1], "%u", addr6->sin6_scope_id);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
sprintf(&tmpbuf[1], "%u", addr6->sin6_scope_id);
|
||||||
|
#endif
|
||||||
|
strcat(buf, tmpbuf);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
#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;
|
||||||
|
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 = (const char *)c1_begin = s1+s1_len-s2_len;
|
||||||
|
c2 = s2;
|
||||||
|
while (c2 < s2+s2_len)
|
||||||
|
{
|
||||||
|
if (tolower(*c1) != tolower(*c2))
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c1++;
|
||||||
|
c2++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c2 == c1 == NULL)
|
||||||
|
return c1_begin;
|
||||||
|
return NULL;
|
||||||
|
}
|
@ -28,6 +28,17 @@ struct in6_addr
|
|||||||
};
|
};
|
||||||
#endif
|
#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 NS_IN6ADDRSZ
|
#ifndef NS_IN6ADDRSZ
|
||||||
#if SIZEOF_STRUCT_IN6_ADDR == 0
|
#if SIZEOF_STRUCT_IN6_ADDR == 0
|
||||||
/* We cannot have it set to zero, so we pick a fixed value here */
|
/* We cannot have it set to zero, so we pick a fixed value here */
|
||||||
@ -45,4 +56,12 @@ struct in6_addr
|
|||||||
#define NS_INT16SZ 2
|
#define NS_INT16SZ 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef IF_NAMESIZE
|
||||||
|
#ifdef IFNAMSIZ
|
||||||
|
#define IF_NAMESIZE IFNAMSIZ
|
||||||
|
#else
|
||||||
|
#define IF_NAMESIZE 256
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* ARES_IPV6_H */
|
#endif /* ARES_IPV6_H */
|
||||||
|
@ -38,7 +38,8 @@ const char *ares_strerror(int code)
|
|||||||
"Error reading file",
|
"Error reading file",
|
||||||
"Out of memory",
|
"Out of memory",
|
||||||
"Channel is being destroyed",
|
"Channel is being destroyed",
|
||||||
"Misformatted string"
|
"Misformatted string",
|
||||||
|
"Illegal flags specified"
|
||||||
};
|
};
|
||||||
|
|
||||||
assert(code >= 0 && code < (int)(sizeof(errtext) / sizeof(*errtext)));
|
assert(code >= 0 && code < (int)(sizeof(errtext) / sizeof(*errtext)));
|
||||||
|
@ -67,6 +67,7 @@ AC_CHECK_HEADERS(
|
|||||||
sys/socket.h \
|
sys/socket.h \
|
||||||
winsock.h \
|
winsock.h \
|
||||||
netinet/in.h \
|
netinet/in.h \
|
||||||
|
net/if.h \
|
||||||
arpa/nameser.h \
|
arpa/nameser.h \
|
||||||
arpa/nameser_compat.h \
|
arpa/nameser_compat.h \
|
||||||
arpa/inet.h, , ,
|
arpa/inet.h, , ,
|
||||||
@ -80,9 +81,31 @@ dnl (and others?) is not designed to allow this.
|
|||||||
#ifdef HAVE_ARPA_NAMESER_H
|
#ifdef HAVE_ARPA_NAMESER_H
|
||||||
#include <arpa/nameser.h>
|
#include <arpa/nameser.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
dnl *Sigh* these are needed in order for net/if.h to get properly detected.
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_WINSOCK_H
|
||||||
|
#include <winsock.h>
|
||||||
|
#endif
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
AC_CHECK_TYPE(socklen_t, ,
|
||||||
|
AC_DEFINE(socklen_t, int, [the length of a socket address]),
|
||||||
|
[
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_WINSOCK_H
|
||||||
|
#include <winsock.h>
|
||||||
|
#endif
|
||||||
|
])
|
||||||
|
|
||||||
dnl check for AF_INET6
|
dnl check for AF_INET6
|
||||||
CARES_CHECK_CONSTANT(
|
CARES_CHECK_CONSTANT(
|
||||||
[
|
[
|
||||||
@ -134,6 +157,41 @@ CARES_CHECK_STRUCT(
|
|||||||
AC_DEFINE_UNQUOTED(HAVE_STRUCT_IN6_ADDR,1,[Define to 1 if you have struct in6_addr.])
|
AC_DEFINE_UNQUOTED(HAVE_STRUCT_IN6_ADDR,1,[Define to 1 if you have struct in6_addr.])
|
||||||
)
|
)
|
||||||
|
|
||||||
|
dnl check for the sockaddr_in6 structure
|
||||||
|
CARES_CHECK_STRUCT(
|
||||||
|
[
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_WINSOCK_H
|
||||||
|
#include <winsock.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
], [sockaddr_in6],
|
||||||
|
AC_DEFINE_UNQUOTED(HAVE_STRUCT_SOCKADDR_IN6,1,
|
||||||
|
[Define to 1 if you have struct sockaddr_in6.]) ac_have_sockaddr_in6=yes
|
||||||
|
)
|
||||||
|
|
||||||
|
if test "$ac_have_sockaddr_in6" = "yes" ; then
|
||||||
|
CARES_CHECK_STRUCT_MEMBER(
|
||||||
|
[
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_WINSOCK_H
|
||||||
|
#include <winsock.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
], [sockaddr_in6], [sin6_scope_id],
|
||||||
|
AC_DEFINE_UNQUOTED(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID,1,
|
||||||
|
[Define to 1 if your struct sockaddr_in6 has sin6_scope_id.])
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
dnl check for inet_pton
|
dnl check for inet_pton
|
||||||
AC_CHECK_FUNCS(inet_pton)
|
AC_CHECK_FUNCS(inet_pton)
|
||||||
dnl Some systems have it, but not IPv6
|
dnl Some systems have it, but not IPv6
|
||||||
@ -268,7 +326,7 @@ AC_CHECK_SIZEOF(struct in_addr, ,
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
AC_CHECK_FUNCS(bitncmp)
|
AC_CHECK_FUNCS([bitncmp if_indextoname])
|
||||||
|
|
||||||
|
|
||||||
AC_OUTPUT(Makefile)
|
AC_OUTPUT(Makefile)
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#else
|
#else
|
||||||
/* simple work-around for now, for systems without configure support */
|
/* simple work-around for now, for systems without configure support */
|
||||||
#define ssize_t int
|
#define ssize_t int
|
||||||
|
#define socklen_t int
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Recent autoconf versions define these symbols in config.h. We don't want
|
/* Recent autoconf versions define these symbols in config.h. We don't want
|
||||||
|
Loading…
Reference in New Issue
Block a user