1
0
mirror of https://github.com/samba-team/samba.git synced 2025-11-26 04:23:49 +03:00

r25543: Merge libreplace support for inet_pton, inet_ntop, getaddrinfo, getnameinfo

(and friends) from SAMBA_3_2, with some minor tweaks:

- avoid including network headers in replace.h unless absolutely required
- autoconf tests for getaddrinfo() in lib/replace

The heimdal-specific code also no longer looks for these functions anymore.
This commit is contained in:
Jelmer Vernooij
2007-10-05 23:54:12 +00:00
committed by Gerald (Jerry) Carter
parent 0e77e3e316
commit b6d3fd84a5
12 changed files with 1129 additions and 124 deletions

View File

@@ -10,6 +10,6 @@ OBJ_FILES = kerberos.o \
gssapi_parse.o \ gssapi_parse.o \
krb5_init_context.o krb5_init_context.o
PUBLIC_DEPENDENCIES = HEIMDAL_KRB5 NDR_KRB5PAC samba-socket LIBCLI_RESOLVE PUBLIC_DEPENDENCIES = HEIMDAL_KRB5 NDR_KRB5PAC samba-socket LIBCLI_RESOLVE
PRIVATE_DEPENDENCIES = ASN1_UTIL HEIMDAL_ROKEN_ADDRINFO auth_sam CREDENTIALS_KRB5 PRIVATE_DEPENDENCIES = ASN1_UTIL auth_sam CREDENTIALS_KRB5
# End SUBSYSTEM KERBEROS # End SUBSYSTEM KERBEROS
################################# #################################

View File

@@ -71,8 +71,6 @@ AC_CHECK_FUNCS([ \
cgetent \ cgetent \
getprogname \ getprogname \
inet_aton \ inet_aton \
inet_ntop \
inet_pton \
gethostname \ gethostname \
getnameinfo \ getnameinfo \
iruserok \ iruserok \
@@ -100,8 +98,6 @@ AC_CHECK_FUNCS([ \
errx \ errx \
warnx \ warnx \
flock \ flock \
getaddrinfo \
freeaddrinfo \
getipnodebyname \ getipnodebyname \
getipnodebyaddr \ getipnodebyaddr \
freehostent \ freehostent \
@@ -229,49 +225,6 @@ SMB_ENABLE(KERBEROS_LIB, YES)
SMB_ENABLE(asn1_compile, YES) SMB_ENABLE(asn1_compile, YES)
SMB_ENABLE(compile_et, YES) SMB_ENABLE(compile_et, YES)
# only add getaddrinfo and related functions if needed
SMB_ENABLE(HEIMDAL_ROKEN_ADDRINFO, NO)
if test t$ac_cv_func_getaddrinfo != tyes; then
SMB_ENABLE(HEIMDAL_ROKEN_ADDRINFO, YES)
fi
SMB_ENABLE(HEIMDAL_ROKEN_GETNAMEINFO, NO)
if test t$ac_cv_func_getnameinfo != tyes; then
SMB_ENABLE(HEIMDAL_ROKEN_GETNAMEINFO, YES)
fi
# only add inet_aton if needed
SMB_ENABLE(HEIMDAL_ROKEN_INET_ATON, NO)
if test t$ac_cv_func_inet_aton != tyes; then
SMB_ENABLE(HEIMDAL_ROKEN_INET_ATON, YES)
fi
SMB_ENABLE(HEIMDAL_ROKEN_INET_NTOP, NO)
if test x"$ac_cv_func_inet_ntop" = x"no"; then
AC_CHECK_LIB_EXT(nsl_s, NSL_LIBS, inet_ntop)
AC_CHECK_LIB_EXT(nsl, NSL_LIBS, inet_ntop)
if test x"$ac_cv_lib_ext_nsl_s_inet_ntop" != x"yes" &&
test x"$ac_cv_lib_ext_nsl_inet_ntop" != x"yes"; then
SMB_ENABLE(HEIMDAL_ROKEN_INET_NTOP, YES)
else
SMB_ENABLE(NSL,YES)
fi
fi
SMB_ENABLE(HEIMDAL_ROKEN_INET_PTON, NO)
if test x"$ac_cv_func_inet_pton" = x"no"; then
AC_CHECK_LIB_EXT(nsl_s, NSL_LIBS, inet_pton)
AC_CHECK_LIB_EXT(nsl, NSL_LIBS, inet_pton)
if test x"$ac_cv_lib_ext_nsl_s_inet_pton" != x"yes" &&
test x"$ac_cv_lib_ext_nsl_inet_pton" != x"yes"; then
SMB_ENABLE(HEIMDAL_ROKEN_INET_PTON, YES)
else
SMB_ENABLE(NSL,YES)
fi
fi
SMB_EXT_LIB(NSL,[${NSL_LIBS}],[],[],[])
# only add closefrom if needed # only add closefrom if needed
SMB_ENABLE(HEIMDAL_ROKEN_CLOSEFROM, NO) SMB_ENABLE(HEIMDAL_ROKEN_CLOSEFROM, NO)
if test t$ac_cv_func_closefrom != tyes; then if test t$ac_cv_func_closefrom != tyes; then
@@ -285,29 +238,3 @@ if test t$ac_cv_func_getprogname != tyes; then
SMB_ENABLE(HEIMDAL_ROKEN_GETPROGNAME, YES) SMB_ENABLE(HEIMDAL_ROKEN_GETPROGNAME, YES)
SMB_ENABLE(HEIMDAL_ROKEN_GETPROGNAME_H, YES) SMB_ENABLE(HEIMDAL_ROKEN_GETPROGNAME_H, YES)
fi fi
# only add gai_strerror if needed
SMB_ENABLE(HEIMDAL_ROKEN_GAI_STRERROR, NO)
AC_CHECK_FUNC(gai_strerror)
if test t$ac_cv_func_gai_strerror != tyes; then
AC_CHECK_LIB_EXT(nsl, GAI_LIBS, gai_strerror)
AC_CHECK_LIB_EXT(socket, GAI_LIBS, gai_strerror)
AC_CHECK_LIB_EXT(xnet, GAI_LIBS, gai_strerror)
dnl We can't just call AC_CHECK_FUNCS(gai_strerror) here, because the value
dnl has been cached.
if test x"$ac_cv_lib_ext_nsl_gai_strerror" = x"yes" ||
test x"$ac_cv_lib_ext_socket_gai_strerror" = x"yes" ||
test x"$ac_cv_lib_ext_xnet_gai_strerror" = x"yes"; then
AC_DEFINE(HAVE_GAI_STRERROR,1,[Whether the system has gai_strerror()])
SMB_ENABLE(GAI, YES)
else
SMB_ENABLE(HEIMDAL_ROKEN_GAI_STRERROR, YES)
fi
else
AC_DEFINE(HAVE_GAI_STRERROR,1,[Whether gai_strerror() is available])
fi
SMB_EXT_LIB(GAI,[${GAI_LIBS}],[${GAI_CFLAGS}],[${GAI_CPPFLAGS}],[${GAI_LDFLAGS}])

View File

@@ -369,24 +369,6 @@ OBJ_FILES = \
# End SUBSYSTEM HEIMDAL_HX509 # End SUBSYSTEM HEIMDAL_HX509
####################### #######################
#######################
# Start SUBSYSTEM HEIMDAL_ROKEN_GAI_STRERROR
[SUBSYSTEM::HEIMDAL_ROKEN_GAI_STRERROR]
CFLAGS = -Iheimdal_build -Iheimdal/lib/roken -Ilib/socket_wrapper
OBJ_FILES = ../heimdal/lib/roken/gai_strerror.o
[SUBSYSTEM::HEIMDAL_ROKEN_INET_ATON]
CFLAGS = -Iheimdal_build -Iheimdal/lib/roken -Ilib/socket_wrapper
OBJ_FILES = ../heimdal/lib/roken/inet_aton.o
[SUBSYSTEM::HEIMDAL_ROKEN_INET_NTOP]
CFLAGS = -Iheimdal_build -Iheimdal/lib/roken -Ilib/socket_wrapper
OBJ_FILES = ../heimdal/lib/roken/inet_ntop.o
[SUBSYSTEM::HEIMDAL_ROKEN_INET_PTON]
CFLAGS = -Iheimdal_build -Iheimdal/lib/roken -Ilib/socket_wrapper
OBJ_FILES = ../heimdal/lib/roken/inet_pton.o
[SUBSYSTEM::HEIMDAL_ROKEN_GETPROGNAME] [SUBSYSTEM::HEIMDAL_ROKEN_GETPROGNAME]
CFLAGS = -Iheimdal_build -Iheimdal/lib/roken -Ilib/socket_wrapper CFLAGS = -Iheimdal_build -Iheimdal/lib/roken -Ilib/socket_wrapper
OBJ_FILES = ../heimdal/lib/roken/getprogname.o OBJ_FILES = ../heimdal/lib/roken/getprogname.o
@@ -399,24 +381,6 @@ OBJ_FILES = ../heimdal/lib/roken/closefrom.o
CFLAGS = -Iheimdal_build -Iheimdal/lib/roken -Ilib/socket_wrapper CFLAGS = -Iheimdal_build -Iheimdal/lib/roken -Ilib/socket_wrapper
OBJ_FILES = ../heimdal/lib/roken/getprogname.ho OBJ_FILES = ../heimdal/lib/roken/getprogname.ho
[SUBSYSTEM::HEIMDAL_ROKEN_GETNAMEINFO]
CFLAGS = -Iheimdal_build -Iheimdal/lib/roken -Ilib/socket_wrapper
OBJ_FILES = ../heimdal/lib/roken/getnameinfo.o
#######################
# Start SUBSYSTEM HEIMDAL_ROKEN_ADDRINFO
[SUBSYSTEM::HEIMDAL_ROKEN_ADDRINFO]
CFLAGS = -Iheimdal_build -Iheimdal/lib/roken
OBJ_FILES = \
../heimdal/lib/roken/getaddrinfo.o \
../heimdal/lib/roken/freeaddrinfo.o \
../heimdal/lib/roken/getipnodebyaddr.o \
../heimdal/lib/roken/getipnodebyname.o \
../heimdal/lib/roken/freehostent.o \
../heimdal/lib/roken/copyhostent.o \
../heimdal/lib/roken/hostent_find_fqdn.o
PRIVATE_DEPENDENCIES = HEIMDAL_ROKEN_INET_PTON EXT_SOCKET
####################### #######################
# Start SUBSYSTEM HEIMDAL_ROKEN # Start SUBSYSTEM HEIMDAL_ROKEN
[SUBSYSTEM::HEIMDAL_ROKEN] [SUBSYSTEM::HEIMDAL_ROKEN]
@@ -453,16 +417,8 @@ OBJ_FILES = \
../heimdal/lib/roken/rtbl.o \ ../heimdal/lib/roken/rtbl.o \
replace.o replace.o
PUBLIC_DEPENDENCIES = \ PUBLIC_DEPENDENCIES = \
HEIMDAL_ROKEN_ADDRINFO \
HEIMDAL_ROKEN_GAI_STRERROR \
HEIMDAL_ROKEN_INET_ATON \
HEIMDAL_ROKEN_INET_NTOP \
HEIMDAL_ROKEN_INET_PTON \
HEIMDAL_ROKEN_GETPROGNAME \ HEIMDAL_ROKEN_GETPROGNAME \
HEIMDAL_ROKEN_CLOSEFROM \ HEIMDAL_ROKEN_CLOSEFROM \
HEIMDAL_ROKEN_GETNAMEINFO \
GAI \
NSL \
RESOLV \ RESOLV \
EXT_SOCKET EXT_SOCKET
# End SUBSYSTEM HEIMDAL_ROKEN # End SUBSYSTEM HEIMDAL_ROKEN

View File

@@ -0,0 +1,502 @@
/*
PostgreSQL Database Management System
(formerly known as Postgres, then as Postgres95)
Portions Copyright (c) 1996-2005, The PostgreSQL Global Development Group
Portions Copyright (c) 1994, The Regents of the University of California
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose, without fee, and without a written agreement
is hereby granted, provided that the above copyright notice and this paragraph
and the following two paragraphs appear in all copies.
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS
TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
/*-------------------------------------------------------------------------
*
* getaddrinfo.c
* Support getaddrinfo() on platforms that don't have it.
*
* We also supply getnameinfo() here, assuming that the platform will have
* it if and only if it has getaddrinfo(). If this proves false on some
* platform, we'll need to split this file and provide a separate configure
* test for getnameinfo().
*
* Copyright (c) 2003-2007, PostgreSQL Global Development Group
*
* Copyright (C) 2007 Jeremy Allison.
* Modified to return multiple IPv4 addresses for Samba.
*
*-------------------------------------------------------------------------
*/
#include "replace.h"
#include "system/network.h"
#ifndef SMB_MALLOC
#define SMB_MALLOC(s) malloc(s)
#endif
#ifndef SMB_STRDUP
#define SMB_STRDUP(s) strdup(s)
#endif
static int check_hostent_err(struct hostent *hp)
{
if (!hp) {
switch (h_errno) {
case HOST_NOT_FOUND:
case NO_DATA:
return EAI_NONAME;
case TRY_AGAIN:
return EAI_AGAIN;
case NO_RECOVERY:
default:
return EAI_FAIL;
}
}
if (!hp->h_name || hp->h_addrtype != AF_INET) {
return EAI_FAIL;
}
return 0;
}
static char *canon_name_from_hostent(struct hostent *hp,
int *perr)
{
char *ret = NULL;
*perr = check_hostent_err(hp);
if (*perr) {
return NULL;
}
ret = SMB_STRDUP(hp->h_name);
if (!ret) {
*perr = EAI_MEMORY;
}
return ret;
}
static char *get_my_canon_name(int *perr)
{
char name[HOST_NAME_MAX+1];
if (gethostname(name, HOST_NAME_MAX) == -1) {
*perr = EAI_FAIL;
return NULL;
}
/* Ensure null termination. */
name[HOST_NAME_MAX] = '\0';
return canon_name_from_hostent(gethostbyname(name), perr);
}
static char *get_canon_name_from_addr(struct in_addr ip,
int *perr)
{
return canon_name_from_hostent(
gethostbyaddr(&ip, sizeof(ip), AF_INET),
perr);
}
static struct addrinfo *alloc_entry(const struct addrinfo *hints,
struct in_addr ip,
unsigned short port)
{
struct sockaddr_in *psin = NULL;
struct addrinfo *ai = SMB_MALLOC(sizeof(*ai));
if (!ai) {
return NULL;
}
memset(ai, '\0', sizeof(*ai));
psin = SMB_MALLOC(sizeof(*psin));
if (!psin) {
free(ai);
return NULL;
}
memset(psin, '\0', sizeof(*psin));
psin->sin_family = AF_INET;
psin->sin_port = htons(port);
psin->sin_addr = ip;
ai->ai_flags = 0;
ai->ai_family = AF_INET;
ai->ai_socktype = hints->ai_socktype;
ai->ai_protocol = hints->ai_protocol;
ai->ai_addrlen = sizeof(*psin);
ai->ai_addr = (struct sockaddr *) psin;
ai->ai_canonname = NULL;
ai->ai_next = NULL;
return ai;
}
/*
* get address info for a single ipv4 address.
*
* Bugs: - servname can only be a number, not text.
*/
static int getaddr_info_single_addr(const char *service,
uint32_t addr,
const struct addrinfo *hints,
struct addrinfo **res)
{
struct addrinfo *ai = NULL;
struct in_addr ip;
unsigned short port = 0;
if (service) {
port = (unsigned short)atoi(service);
}
ip.s_addr = htonl(addr);
ai = alloc_entry(hints, ip, port);
if (!ai) {
return EAI_MEMORY;
}
/* If we're asked for the canonical name,
* make sure it returns correctly. */
if (!(hints->ai_flags & AI_NUMERICSERV) &&
hints->ai_flags & AI_CANONNAME) {
int err;
if (addr == INADDR_LOOPBACK || addr == INADDR_ANY) {
ai->ai_canonname = get_my_canon_name(&err);
} else {
ai->ai_canonname =
get_canon_name_from_addr(ip,&err);
}
if (ai->ai_canonname == NULL) {
freeaddrinfo(ai);
return err;
}
}
*res = ai;
return 0;
}
/*
* get address info for multiple ipv4 addresses.
*
* Bugs: - servname can only be a number, not text.
*/
static int getaddr_info_name(const char *node,
const char *service,
const struct addrinfo *hints,
struct addrinfo **res)
{
struct addrinfo *listp = NULL, *prevp = NULL;
char **pptr = NULL;
int err;
struct hostent *hp = NULL;
unsigned short port = 0;
if (service) {
port = (unsigned short)atoi(service);
}
hp = gethostbyname(node);
err = check_hostent_err(hp);
if (err) {
return err;
}
for(pptr = hp->h_addr_list; *pptr; pptr++) {
struct in_addr ip = *(struct in_addr *)pptr;
struct addrinfo *ai = alloc_entry(hints, ip, port);
if (!ai) {
freeaddrinfo(listp);
return EAI_MEMORY;
}
if (!listp) {
listp = ai;
prevp = ai;
ai->ai_canonname = SMB_STRDUP(hp->h_name);
if (!ai->ai_canonname) {
freeaddrinfo(listp);
return EAI_MEMORY;
}
} else {
prevp->ai_next = ai;
prevp = ai;
}
}
*res = listp;
return 0;
}
/*
* get address info for ipv4 sockets.
*
* Bugs: - servname can only be a number, not text.
*/
int getaddrinfo(const char *node,
const char *service,
const struct addrinfo * hintp,
struct addrinfo ** res)
{
struct addrinfo hints;
/* Setup the hints struct. */
if (hintp == NULL) {
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
} else {
memcpy(&hints, hintp, sizeof(hints));
}
if (hints.ai_family != AF_INET && hints.ai_family != AF_UNSPEC) {
return EAI_FAMILY;
}
if (hints.ai_socktype == 0) {
hints.ai_socktype = SOCK_STREAM;
}
if (!node && !service) {
return EAI_NONAME;
}
if (node) {
if (node[0] == '\0') {
return getaddr_info_single_addr(service,
INADDR_ANY,
&hints,
res);
} else if (hints.ai_flags & AI_NUMERICHOST) {
struct in_addr ip;
if (!inet_aton(node, &ip)) {
return EAI_FAIL;
}
return getaddr_info_single_addr(service,
ntohl(ip.s_addr),
&hints,
res);
} else {
return getaddr_info_name(node,
service,
&hints,
res);
}
} else if (hints.ai_flags & AI_PASSIVE) {
return getaddr_info_single_addr(service,
INADDR_ANY,
&hints,
res);
}
return getaddr_info_single_addr(service,
INADDR_LOOPBACK,
&hints,
res);
}
void freeaddrinfo(struct addrinfo *res)
{
struct addrinfo *next = NULL;
for (;res; res = next) {
next = res->ai_next;
if (res->ai_canonname) {
free(res->ai_canonname);
}
if (res->ai_addr) {
free(res->ai_addr);
}
free(res);
}
}
const char *gai_strerror(int errcode)
{
#ifdef HAVE_HSTRERROR
int hcode;
switch (errcode)
{
case EAI_NONAME:
hcode = HOST_NOT_FOUND;
break;
case EAI_AGAIN:
hcode = TRY_AGAIN;
break;
case EAI_FAIL:
default:
hcode = NO_RECOVERY;
break;
}
return hstrerror(hcode);
#else /* !HAVE_HSTRERROR */
switch (errcode)
{
case EAI_NONAME:
return "Unknown host";
case EAI_AGAIN:
return "Host name lookup failure";
#ifdef EAI_BADFLAGS
case EAI_BADFLAGS:
return "Invalid argument";
#endif
#ifdef EAI_FAMILY
case EAI_FAMILY:
return "Address family not supported";
#endif
#ifdef EAI_MEMORY
case EAI_MEMORY:
return "Not enough memory";
#endif
#ifdef EAI_NODATA
case EAI_NODATA:
return "No host data of that type was found";
#endif
#ifdef EAI_SERVICE
case EAI_SERVICE:
return "Class type not found";
#endif
#ifdef EAI_SOCKTYPE
case EAI_SOCKTYPE:
return "Socket type not supported";
#endif
default:
return "Unknown server error";
}
#endif /* HAVE_HSTRERROR */
}
static int gethostnameinfo(const struct sockaddr *sa,
char *node,
size_t nodelen,
int flags)
{
int ret = -1;
char *p = NULL;
if (!(flags & NI_NUMERICHOST)) {
struct hostent *hp = gethostbyaddr(
&((struct sockaddr_in *)sa)->sin_addr,
sizeof(struct in_addr),
sa->sa_family);
ret = check_hostent_err(hp);
if (ret == 0) {
/* Name looked up successfully. */
ret = snprintf(node, nodelen, "%s", hp->h_name);
if (ret == -1 || ret > nodelen) {
return EAI_MEMORY;
}
if (flags & NI_NOFQDN) {
p = strchr(node,'.');
if (p) {
*p = '\0';
}
}
return 0;
}
if (flags & NI_NAMEREQD) {
/* If we require a name and didn't get one,
* automatically fail. */
return ret;
}
/* Otherwise just fall into the numeric host code... */
}
p = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
ret = snprintf(node, nodelen, "%s", p);
if (ret == -1 || ret > nodelen) {
return EAI_MEMORY;
}
return 0;
}
static int getservicenameinfo(const struct sockaddr *sa,
char *service,
size_t servicelen,
int flags)
{
int ret = -1;
int port = ntohs(((struct sockaddr_in *)sa)->sin_port);
if (!(flags & NI_NUMERICSERV)) {
struct servent *se = getservbyport(
port,
(flags & NI_DGRAM) ? "udp" : "tcp");
if (se && se->s_name) {
/* Service name looked up successfully. */
ret = snprintf(service, servicelen, "%s", se->s_name);
if (ret == -1 || ret > servicelen) {
return EAI_MEMORY;
}
return 0;
}
/* Otherwise just fall into the numeric service code... */
}
ret = snprintf(service, servicelen, "%d", port);
if (ret == -1 || ret > servicelen) {
return EAI_MEMORY;
}
return 0;
}
/*
* Convert an ipv4 address to a hostname.
*
* Bugs: - No IPv6 support.
*/
int getnameinfo(const struct sockaddr *sa, socklen_t salen,
char *node, size_t nodelen,
char *service, size_t servicelen, int flags)
{
/* Invalid arguments. */
if (sa == NULL || (node == NULL && service == NULL)) {
return EAI_FAIL;
}
if (sa->sa_family != AF_INET) {
return EAI_FAIL;
}
if (salen < sizeof(struct sockaddr_in)) {
return EAI_FAIL;
}
/* We don't support those. */
if ((node && !(flags & NI_NUMERICHOST))
|| (service && !(flags & NI_NUMERICSERV)))
return EAI_FAIL;
if (node) {
return gethostnameinfo(sa, node, nodelen, flags);
}
if (service) {
return getservicenameinfo(sa, service, servicelen, flags);
}
return 0;
}

View File

@@ -0,0 +1,158 @@
/*
PostgreSQL Database Management System
(formerly known as Postgres, then as Postgres95)
Portions Copyright (c) 1996-2005, The PostgreSQL Global Development Group
Portions Copyright (c) 1994, The Regents of the University of California
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose, without fee, and without a written agreement
is hereby granted, provided that the above copyright notice and this paragraph
and the following two paragraphs appear in all copies.
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS
TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
/*-------------------------------------------------------------------------
*
* getaddrinfo.h
* Support getaddrinfo() on platforms that don't have it.
*
* Note: we use our own routines on platforms that don't HAVE_STRUCT_ADDRINFO,
* whether or not the library routine getaddrinfo() can be found. This
* policy is needed because on some platforms a manually installed libbind.a
* may provide getaddrinfo(), yet the system headers may not provide the
* struct definitions needed to call it. To avoid conflict with the libbind
* definition in such cases, we rename our routines to pg_xxx() via macros.
*
* This code will also work on platforms where struct addrinfo is defined
* in the system headers but no getaddrinfo() can be located.
*
* Copyright (c) 2003-2007, PostgreSQL Global Development Group
*
*-------------------------------------------------------------------------
*/
#ifndef GETADDRINFO_H
#define GETADDRINFO_H
/* Various macros that ought to be in <netdb.h>, but might not be */
#ifndef EAI_FAIL
#define EAI_BADFLAGS (-1)
#define EAI_NONAME (-2)
#define EAI_AGAIN (-3)
#define EAI_FAIL (-4)
#define EAI_FAMILY (-6)
#define EAI_SOCKTYPE (-7)
#define EAI_SERVICE (-8)
#define EAI_MEMORY (-10)
#define EAI_SYSTEM (-11)
#endif /* !EAI_FAIL */
#ifndef AI_PASSIVE
#define AI_PASSIVE 0x0001
#endif
#ifndef AI_NUMERICHOST
/*
* some platforms don't support AI_NUMERICHOST; define as zero if using
* the system version of getaddrinfo...
*/
#if defined(HAVE_STRUCT_ADDRINFO) && defined(HAVE_GETADDRINFO)
#define AI_NUMERICHOST 0
#else
#define AI_NUMERICHOST 0x0004
#endif
#endif
#ifndef NI_NUMERICHOST
#define NI_NUMERICHOST 1
#endif
#ifndef NI_NUMERICSERV
#define NI_NUMERICSERV 2
#endif
#ifndef NI_NOFQDN
#define NI_NOFQDN 4
#endif
#ifndef NI_NAMEREQD
#define NI_NAMEREQD 8
#endif
#ifndef NI_DGRAM
#define NI_DGRAM 16
#endif
#ifndef NI_MAXHOST
#define NI_MAXHOST 1025
#endif
#ifndef NI_MAXSERV
#define NI_MAXSERV 32
#endif
#ifndef HAVE_STRUCT_ADDRINFO
struct addrinfo
{
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
size_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
};
#endif /* HAVE_STRUCT_ADDRINFO */
#ifndef HAVE_GETADDRINFO
/* Rename private copies per comments above */
#ifdef getaddrinfo
#undef getaddrinfo
#endif
#define getaddrinfo pg_getaddrinfo
#ifdef freeaddrinfo
#undef freeaddrinfo
#endif
#define freeaddrinfo pg_freeaddrinfo
#ifdef gai_strerror
#undef gai_strerror
#endif
#define gai_strerror pg_gai_strerror
#ifdef getnameinfo
#undef getnameinfo
#endif
#define getnameinfo pg_getnameinfo
extern int getaddrinfo(const char *node, const char *service,
const struct addrinfo * hints, struct addrinfo ** res);
extern void freeaddrinfo(struct addrinfo * res);
extern const char *gai_strerror(int errcode);
extern int getnameinfo(const struct sockaddr * sa, socklen_t salen,
char *node, size_t nodelen,
char *service, size_t servicelen, int flags);
#endif /* HAVE_GETADDRINFO */
#endif /* GETADDRINFO_H */

View File

@@ -0,0 +1,191 @@
/*
* Copyright (C) 1996-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "replace.h"
#include "system/network.h"
#define NS_INT16SZ 2
#define NS_IN6ADDRSZ 16
/*
* WARNING: Don't even consider trying to compile this on a system where
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
*/
static const char *inet_ntop4(const unsigned char *src, char *dst,
socklen_t size);
#ifdef AF_INET6
static const char *inet_ntop6(const unsigned char *src, char *dst,
socklen_t size);
#endif
/* char *
* isc_net_ntop(af, src, dst, size)
* convert a network format address to presentation format.
* return:
* pointer to presentation format address (`dst'), or NULL (see errno).
* author:
* Paul Vixie, 1996.
*/
const char *
rep_inet_ntop(int af, const void *src, char *dst, socklen_t size)
{
switch (af) {
case AF_INET:
return (inet_ntop4(src, dst, size));
#ifdef AF_INET6
case AF_INET6:
return (inet_ntop6(src, dst, size));
#endif
default:
errno = EAFNOSUPPORT;
return (NULL);
}
/* NOTREACHED */
}
/* const char *
* inet_ntop4(src, dst, size)
* format an IPv4 address
* return:
* `dst' (as a const)
* notes:
* (1) uses no statics
* (2) takes a unsigned char* not an in_addr as input
* author:
* Paul Vixie, 1996.
*/
static const char *
inet_ntop4(const unsigned char *src, char *dst, socklen_t size)
{
static const char *fmt = "%u.%u.%u.%u";
char tmp[sizeof "255.255.255.255"];
size_t len;
len = snprintf(tmp, sizeof tmp, fmt, src[0], src[1], src[2], src[3]);
if (len >= size) {
errno = ENOSPC;
return (NULL);
}
memcpy(dst, tmp, len + 1);
return (dst);
}
/* const char *
* isc_inet_ntop6(src, dst, size)
* convert IPv6 binary address into presentation (printable) format
* author:
* Paul Vixie, 1996.
*/
#ifdef AF_INET6
static const char *
inet_ntop6(const unsigned char *src, char *dst, socklen_t size)
{
/*
* Note that int32_t and int16_t need only be "at least" large enough
* to contain a value of the specified size. On some systems, like
* Crays, there is no such thing as an integer variable with 16 bits.
* Keep this in mind if you think this function should have been coded
* to use pointer overlays. All the world's not a VAX.
*/
char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
struct { int base, len; } best, cur;
unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
int i, inc;
/*
* Preprocess:
* Copy the input (bytewise) array into a wordwise array.
* Find the longest run of 0x00's in src[] for :: shorthanding.
*/
memset(words, '\0', sizeof words);
for (i = 0; i < NS_IN6ADDRSZ; i++)
words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
best.base = -1;
best.len = 0;
cur.base = -1;
cur.len = 0;
for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
if (words[i] == 0) {
if (cur.base == -1)
cur.base = i, cur.len = 1;
else
cur.len++;
} else {
if (cur.base != -1) {
if (best.base == -1 || cur.len > best.len)
best = cur;
cur.base = -1;
}
}
}
if (cur.base != -1) {
if (best.base == -1 || cur.len > best.len)
best = cur;
}
if (best.base != -1 && best.len < 2)
best.base = -1;
/*
* Format the result.
*/
tp = tmp;
for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
/* Are we inside the best run of 0x00's? */
if (best.base != -1 && i >= best.base &&
i < (best.base + best.len)) {
if (i == best.base)
*tp++ = ':';
continue;
}
/* Are we following an initial run of 0x00s or any real hex? */
if (i != 0)
*tp++ = ':';
/* Is this address an encapsulated IPv4? */
if (i == 6 && best.base == 0 &&
(best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
return (NULL);
tp += strlen(tp);
break;
}
inc = snprintf(tp, 5, "%x", words[i]);
if (inc >= 5) {
abort();
}
tp += inc;
}
/* Was it a trailing run of 0x00's? */
if (best.base != -1 && (best.base + best.len) ==
(NS_IN6ADDRSZ / NS_INT16SZ))
*tp++ = ':';
*tp++ = '\0';
/*
* Check for overflow, copy, and we're done.
*/
if ((size_t)(tp - tmp) > size) {
errno = ENOSPC;
return (NULL);
}
memcpy(dst, tmp, tp - tmp);
return (dst);
}
#endif /* AF_INET6 */

View File

@@ -0,0 +1 @@
AC_CHECK_FUNCS(inet_ntop,[],[LIBREPLACEOBJ="${LIBREPLACEOBJ} inet_ntop.o"])

View File

@@ -0,0 +1,213 @@
/*
* Copyright (C) 1996-2001 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "replace.h"
#include "system/network.h"
#define NS_INT16SZ 2
#define NS_INADDRSZ 4
#define NS_IN6ADDRSZ 16
/*
* WARNING: Don't even consider trying to compile this on a system where
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
*/
static int inet_pton4(const char *src, unsigned char *dst);
#ifdef AF_INET6
static int inet_pton6(const char *src, unsigned char *dst);
#endif
/* int
* inet_pton(af, src, dst)
* convert from presentation format (which usually means ASCII printable)
* to network format (which is usually some kind of binary format).
* return:
* 1 if the address was valid for the specified address family
* 0 if the address wasn't valid (`dst' is untouched in this case)
* -1 if some other error occurred (`dst' is untouched in this case, too)
* author:
* Paul Vixie, 1996.
*/
int
rep_inet_pton(int af,
const char *src,
void *dst)
{
switch (af) {
case AF_INET:
return (inet_pton4(src, dst));
#ifdef AF_INET6
case AF_INET6:
return (inet_pton6(src, dst));
#endif
default:
errno = EAFNOSUPPORT;
return (-1);
}
/* NOTREACHED */
}
/* int
* inet_pton4(src, dst)
* like inet_aton() but without all the hexadecimal and shorthand.
* return:
* 1 if `src' is a valid dotted quad, else 0.
* notice:
* does not touch `dst' unless it's returning 1.
* author:
* Paul Vixie, 1996.
*/
static int
inet_pton4(src, dst)
const char *src;
unsigned char *dst;
{
static const char digits[] = "0123456789";
int saw_digit, octets, ch;
unsigned char tmp[NS_INADDRSZ], *tp;
saw_digit = 0;
octets = 0;
*(tp = tmp) = 0;
while ((ch = *src++) != '\0') {
const char *pch;
if ((pch = strchr(digits, ch)) != NULL) {
unsigned int new = *tp * 10 + (pch - digits);
if (new > 255)
return (0);
*tp = new;
if (! saw_digit) {
if (++octets > 4)
return (0);
saw_digit = 1;
}
} else if (ch == '.' && saw_digit) {
if (octets == 4)
return (0);
*++tp = 0;
saw_digit = 0;
} else
return (0);
}
if (octets < 4)
return (0);
memcpy(dst, tmp, NS_INADDRSZ);
return (1);
}
/* int
* inet_pton6(src, dst)
* convert presentation level address to network order binary form.
* return:
* 1 if `src' is a valid [RFC1884 2.2] address, else 0.
* notice:
* (1) does not touch `dst' unless it's returning 1.
* (2) :: in a full address is silently ignored.
* credit:
* inspired by Mark Andrews.
* author:
* Paul Vixie, 1996.
*/
#ifdef AF_INET6
static int
inet_pton6(src, dst)
const char *src;
unsigned char *dst;
{
static const char xdigits_l[] = "0123456789abcdef",
xdigits_u[] = "0123456789ABCDEF";
unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
const char *xdigits, *curtok;
int ch, saw_xdigit;
unsigned int val;
memset((tp = tmp), '\0', NS_IN6ADDRSZ);
endp = tp + NS_IN6ADDRSZ;
colonp = NULL;
/* Leading :: requires some special handling. */
if (*src == ':')
if (*++src != ':')
return (0);
curtok = src;
saw_xdigit = 0;
val = 0;
while ((ch = *src++) != '\0') {
const char *pch;
if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
pch = strchr((xdigits = xdigits_u), ch);
if (pch != NULL) {
val <<= 4;
val |= (pch - xdigits);
if (val > 0xffff)
return (0);
saw_xdigit = 1;
continue;
}
if (ch == ':') {
curtok = src;
if (!saw_xdigit) {
if (colonp)
return (0);
colonp = tp;
continue;
}
if (tp + NS_INT16SZ > endp)
return (0);
*tp++ = (unsigned char) (val >> 8) & 0xff;
*tp++ = (unsigned char) val & 0xff;
saw_xdigit = 0;
val = 0;
continue;
}
if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
inet_pton4(curtok, tp) > 0) {
tp += NS_INADDRSZ;
saw_xdigit = 0;
break; /* '\0' was seen by inet_pton4(). */
}
return (0);
}
if (saw_xdigit) {
if (tp + NS_INT16SZ > endp)
return (0);
*tp++ = (unsigned char) (val >> 8) & 0xff;
*tp++ = (unsigned char) val & 0xff;
}
if (colonp != NULL) {
/*
* Since some memmove()'s erroneously fail to handle
* overlapping regions, we'll do the shift by hand.
*/
const int n = tp - colonp;
int i;
for (i = 1; i <= n; i++) {
endp[- i] = colonp[n - i];
colonp[n - i] = 0;
}
tp = endp;
}
if (tp != endp)
return (0);
memcpy(dst, tmp, NS_IN6ADDRSZ);
return (1);
}
#endif

View File

@@ -0,0 +1 @@
AC_CHECK_FUNCS(inet_pton,[],[LIBREPLACEOBJ="${LIBREPLACEOBJ} inet_pton.o"])

View File

@@ -137,6 +137,45 @@ if test x"$samba_cv_REPLACE_INET_NTOA" = x"yes"; then
AC_DEFINE(REPLACE_INET_NTOA,1,[Whether inet_ntoa should be replaced]) AC_DEFINE(REPLACE_INET_NTOA,1,[Whether inet_ntoa should be replaced])
fi fi
dnl test for struct addrinfo
AC_CACHE_CHECK([for struct addrinfo],samba_cv_HAVE_STRUCT_ADDRINFO,[
AC_TRY_COMPILE([
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>],
[
struct addrinfo ai;
],
samba_cv_HAVE_STRUCT_ADDRINFO=yes,samba_cv_HAVE_STRUCT_ADDRINFO=no)])
if test x"$samba_cv_HAVE_STRUCT_ADDRINFO" = x"yes"; then
AC_DEFINE(HAVE_STRUCT_ADDRINFO,1,[Whether the system has struct addrinfo])
fi
dnl test for getaddrinfo/getnameinfo
AC_CACHE_CHECK([for getaddrinfo],samba_cv_HAVE_GETADDRINFO,[
AC_TRY_COMPILE([
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>],
[
struct sockaddr sa;
struct addrinfo *ai = NULL;
int ret = getaddrinfo(NULL, NULL, NULL, &ai);
if (ret != 0) {
const char *es = gai_strerror(ret);
}
freeaddrinfo(ai);
ret = getnameinfo(&sa, sizeof(sa),
NULL, 0,
NULL, 0, 0);
],
samba_cv_HAVE_GETADDRINFO=yes,samba_cv_HAVE_GETADDRINFO=no)])
if test x"$samba_cv_HAVE_GETADDRINFO" = x"yes"; then
AC_DEFINE(HAVE_GETADDRINFO,1,[Whether the system has getaddrinfo and getnameinfo])
fi
dnl Provided by replace.c: dnl Provided by replace.c:
AC_TRY_COMPILE([ AC_TRY_COMPILE([
#include <sys/types.h> #include <sys/types.h>
@@ -304,7 +343,7 @@ AC_TRY_COMPILE([
samba_cv_HAVE_OPEN_O_DIRECT=yes,samba_cv_HAVE_OPEN_O_DIRECT=no)]) samba_cv_HAVE_OPEN_O_DIRECT=yes,samba_cv_HAVE_OPEN_O_DIRECT=no)])
if test x"$samba_cv_HAVE_OPEN_O_DIRECT" = x"yes"; then if test x"$samba_cv_HAVE_OPEN_O_DIRECT" = x"yes"; then
AC_DEFINE(HAVE_OPEN_O_DIRECT,1,[Whether the open(2) accepts O_DIRECT]) AC_DEFINE(HAVE_OPEN_O_DIRECT,1,[Whether the open(2) accepts O_DIRECT])
fi fi
dnl Check if the C compiler understands volatile (it should, being ANSI). dnl Check if the C compiler understands volatile (it should, being ANSI).
@@ -322,6 +361,8 @@ m4_include(getpass.m4)
m4_include(strptime.m4) m4_include(strptime.m4)
m4_include(win32.m4) m4_include(win32.m4)
m4_include(timegm.m4) m4_include(timegm.m4)
m4_include(inet_ntop.m4)
m4_include(inet_pton.m4)
m4_include(repdir.m4) m4_include(repdir.m4)
AC_CHECK_FUNCS([syslog memset memcpy],,[AC_MSG_ERROR([Required function not found])]) AC_CHECK_FUNCS([syslog memset memcpy],,[AC_MSG_ERROR([Required function not found])])

View File

@@ -1,15 +1,16 @@
/* /*
Unix SMB/CIFS implementation. Unix SMB/CIFS implementation.
macros to go along with the lib/replace/ portability layer code macros to go along with the lib/replace/ portability layer code
Copyright (C) Andrew Tridgell 2005 Copyright (C) Andrew Tridgell 2005
Copyright (C) Jelmer Vernooij 2006 Copyright (C) Jelmer Vernooij 2006
Copyright (C) Jeremy Allison 2007.
** NOTE! The following LGPL license applies to the replace ** NOTE! The following LGPL license applies to the replace
** library. This does NOT imply that all of Samba is released ** library. This does NOT imply that all of Samba is released
** under the LGPL ** under the LGPL
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
@@ -71,7 +72,6 @@
#include <stddef.h> #include <stddef.h>
#endif #endif
#ifndef HAVE_STRERROR #ifndef HAVE_STRERROR
extern char *sys_errlist[]; extern char *sys_errlist[];
#define strerror(i) sys_errlist[i] #define strerror(i) sys_errlist[i]
@@ -139,7 +139,7 @@ int setenv(const char *name, const char *value, int overwrite);
#ifndef HAVE_UNSETENV #ifndef HAVE_UNSETENV
#define unsetenv rep_unsetenv #define unsetenv rep_unsetenv
int rep_unsetenv(const char *name); int rep_unsetenv(const char *name);
#endif #endif
#ifndef HAVE_SETEUID #ifndef HAVE_SETEUID
@@ -163,7 +163,7 @@ char *rep_strcasestr(const char *haystack, const char *needle);
#endif #endif
#ifndef HAVE_STRTOK_R #ifndef HAVE_STRTOK_R
#define strtok_r rep_strtok_r #define strtok_r rep_strtok_r
char *rep_strtok_r(char *s, const char *delim, char **save_ptr); char *rep_strtok_r(char *s, const char *delim, char **save_ptr);
#endif #endif
@@ -330,6 +330,17 @@ ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset);
ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset); ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset);
#endif #endif
#ifndef HAVE_INET_PTON
int rep_inet_pton(int af, const char *src, void *dst);
#define inet_pton rep_inet_pton
#endif
#ifndef HAVE_INET_NTOP
#include "system/network.h"
const char *rep_inet_ntop(int af, const void *src, char *dst, socklen_t size);
#define inet_ntop rep_inet_ntop
#endif
#ifdef HAVE_LIMITS_H #ifdef HAVE_LIMITS_H
#include <limits.h> #include <limits.h>
#endif #endif

View File

@@ -49,6 +49,10 @@
#include <netinet/tcp.h> #include <netinet/tcp.h>
#endif #endif
#if !defined(HAVE_GETADDRINFO)
#include "getaddrinfo.h"
#endif
/* /*
* The next three defines are needed to access the IPTOS_* options * The next three defines are needed to access the IPTOS_* options
* on some systems. * on some systems.