From 0b6f512e8e37935481de1d11b90c739070cb2565 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 29 Mar 2009 16:46:46 +0200 Subject: added stub implementation of getaddrinfo on Cygwin --- src/port/getaddrinfo.c | 165 +++++++++++++++++++++++++++++++++ src/port/getaddrinfo.h | 247 +++++++++++++++++++++++++++++++++++++++++++++++++ src/port/netdb.c | 3 +- 3 files changed, 413 insertions(+), 2 deletions(-) create mode 100755 src/port/getaddrinfo.c create mode 100755 src/port/getaddrinfo.h (limited to 'src') diff --git a/src/port/getaddrinfo.c b/src/port/getaddrinfo.c new file mode 100755 index 0000000..558cb9e --- /dev/null +++ b/src/port/getaddrinfo.c @@ -0,0 +1,165 @@ +/* + Copyright (C) 2008 Andreas Baumann + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "port/getaddrinfo.h" + +#if !defined HAVE_GETADDRINFO || defined TEST_GETADDRINFO + +#include "port/string.h" /* for memset, memcpy */ +#include "port/stdlib.h" /* for atoi, malloc, free, NULL */ + +#include /* for struct sockaddr_in */ + +int wolf_port_getaddrinfo( const char *host_name, + const char *service_name, + const struct wolf_port_addrinfo *hintp, + struct wolf_port_addrinfo **result ) { + struct wolf_port_addrinfo *ai; + struct sockaddr_in sin, + *psin; + struct wolf_port_addrinfo hints; + + if( hintp == NULL ) { + memset( &hints, 0, sizeof( struct wolf_port_addrinfo ) ); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + } else { + memcpy( &hints, hintp, sizeof( struct wolf_port_addrinfo ) ); + } + + 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( ( host_name == NULL ) && ( service_name == NULL ) ) { + return EAI_NONAME; + } + + memset( &sin, 0, sizeof( struct sockaddr_in) ); + + sin.sin_family = AF_INET; + + if( host_name != NULL ) { + if( host_name[0] == '\0' ) { + sin.sin_addr.s_addr = htonl( INADDR_ANY ); + } else if( hints.ai_flags & AI_NUMERICHOST ) { + if( !inet_aton( host_name, &sin.sin_addr ) ) { + return EAI_FAIL; + } + } else { + struct hostent *hp; + + hp = gethostbyname( host_name ); + + if( hp == NULL ) { + 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_addrtype != AF_INET ) { + return EAI_FAIL; + } + + memcpy( &(sin.sin_addr), hp->h_addr, hp->h_length ); + } + } else { + if( hints.ai_flags & AI_PASSIVE ) { + sin.sin_addr.s_addr = htonl( INADDR_ANY ); + } else { + sin.sin_addr.s_addr = htonl( INADDR_LOOPBACK ); + } + } + + if( service_name != NULL ) { + sin.sin_port = htons( (unsigned short)atoi( service_name ) ); + } + + ai = (struct wolf_port_addrinfo *)malloc( sizeof( struct wolf_port_addrinfo ) ); + if( ai == NULL ) { + return EAI_MEMORY; + } + + psin = (struct sockaddr_in *)malloc( sizeof( struct sockaddr_in ) ); + if (!psin) + { + free(ai); + return EAI_MEMORY; + } + + memcpy( psin, &sin, sizeof( struct sockaddr_in ) ); + + 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; + + *result = ai; + + return 0; +} + +void wolf_port_freeaddrinfo( struct wolf_port_addrinfo *result ) { + /* stub doesn't have more than one element in list, adapt if you change that! */ + if( result != NULL ) { + if( result->ai_addr != NULL ) { + free( result->ai_addr ); + } + free( result ); + } +} + +const char *wolf_port_gai_strerror( int errcode ) { + switch( errcode ) { + case EAI_NONAME: + return "host nor service provided, or not known"; + + case EAI_AGAIN: + return "temporary failure in name resolution"; + + case EAI_FAIL: + return "non-recoverable failure in name resultion"; + + case EAI_FAMILY: + return "socket family not supported"; + + case EAI_MEMORY: + return "memory allocation failure"; + + default: + return "Unknown GAI error"; + } +} + +#endif /* !defined HAVE_GETADDRINFO || defined TEST_GETADDRINFO */ diff --git a/src/port/getaddrinfo.h b/src/port/getaddrinfo.h new file mode 100755 index 0000000..2177afa --- /dev/null +++ b/src/port/getaddrinfo.h @@ -0,0 +1,247 @@ +/* + Copyright (C) 2008 Andreas Baumann + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/* + * Bases on ideas found in: + * + * Postgres src/port/getaddrinfo.c, Copyright (c) 2003-2008, PostgreSQL Global Development Group + * Unix Stevens Network Programming, libgai implementation in unpv12e + * + * At least Windows 2000 and Cygwin don't know getaddrinfo.. + */ + +#ifndef __GETADDRINFO_H +#define __GETADDRINFO_H + +#include "port/sys_internal.h" + +/* for errors returned by getaddrinfo */ +#if !defined EAI_NONAME +#define EAI_NONAME -2 /**< NAME or SERVICE is unknown */ +#define EAI_AGAIN -3 /**< temporary failure in name resolution */ +#define EAI_FAIL -4 /**< non-recoverable failure in name resultion */ +#define EAI_FAMILY -6 /**< socket family not supported */ +#define EAI_MEMORY -10 /**< memory allocation failure */ +#endif + +/* for ai_flags */ +#if !defined AI_PASSIVE +#define AI_PASSIVE 1 /**< socket is intended for bind() + listen() */ +#define AI_CANONNAME 2 /**< return canonical name */ +#define AI_NUMERICHOST 4 /**< don't use name resolution */ +#endif + +#if !defined HAVE_GETADDRINFO || defined TEST_GETADDRINFO +struct wolf_port_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 wolf_port_addrinfo *ai_next; +}; + +extern int wolf_port_getaddrinfo( const char *host_name, + const char *service_name, + const struct wolf_port_addrinfo *hints, + struct wolf_port_addrinfo **result ); + +extern void wolf_port_freeaddrinfo( struct wolf_port_addrinfo *result ); +extern const char *wolf_port_gai_strerror( int errcode ); + +#if !defined HAVE_GETADDRINFO +#define addrinfo wolf_port_addrinfo +#define getaddrinfo( host_name, service_name, hints, result ) wolf_port_getaddrinfo( host_name, service_name, hints, result ) +#define freeaddrinfo( result ) wolf_port_freeaddrinfo( result ) +#define gai_strerror( errcode ) wolf_port_gai_strerror( errcode ) +#endif + +#endif /* !defined HAVE_GETADDRINFO || defined TEST_GETADDRINFO */ + +#endif /* ifndef __GETADDRINFO_H */ + +#if 0 + +/*------------------------------------------------------------------------- + * + * 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-2008, PostgreSQL Global Development Group + * + * $PostgreSQL: pgsql/src/include/getaddrinfo.h,v 1.25 2008/01/01 19:45:56 momjian Exp $ + * + *------------------------------------------------------------------------- + */ +#ifndef GETADDRINFO_H +#define GETADDRINFO_H + +#include +#include + + +/* Various macros that ought to be in , but might not be */ + +#ifndef EAI_FAIL +#ifndef WIN32 +#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) +#else /* WIN32 */ +#ifdef WIN32_ONLY_COMPILER +#ifndef WSA_NOT_ENOUGH_MEMORY +#define WSA_NOT_ENOUGH_MEMORY (WSAENOBUFS) +#endif +#ifndef __BORLANDC__ +#define WSATYPE_NOT_FOUND (WSABASEERR+109) +#endif +#endif +#define EAI_AGAIN WSATRY_AGAIN +#define EAI_BADFLAGS WSAEINVAL +#define EAI_FAIL WSANO_RECOVERY +#define EAI_FAMILY WSAEAFNOSUPPORT +#define EAI_MEMORY WSA_NOT_ENOUGH_MEMORY +#define EAI_NODATA WSANO_DATA +#define EAI_NONAME WSAHOST_NOT_FOUND +#define EAI_SERVICE WSATYPE_NOT_FOUND +#define EAI_SOCKTYPE WSAESOCKTNOSUPPORT +#endif /* !WIN32 */ +#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_MAXHOST +#define NI_MAXHOST 1025 +#endif +#ifndef NI_MAXSERV +#define NI_MAXSERV 32 +#endif + + +#ifndef HAVE_STRUCT_ADDRINFO + +#ifndef WIN32 +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; +}; +#else +/* + * The order of the structure elements on Win32 doesn't match the + * order specified in the standard, but we have to match it for + * IPv6 to work. + */ +struct addrinfo +{ + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + size_t ai_addrlen; + char *ai_canonname; + struct sockaddr *ai_addr; + struct addrinfo *ai_next; +}; +#endif +#endif /* HAVE_STRUCT_ADDRINFO */ + + +#ifndef HAVE_GETADDRINFO + +#if 0 +/* 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 +#endif + + +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, int salen, + char *node, int nodelen, + char *service, int servicelen, int flags); +#endif /* HAVE_GETADDRINFO */ + +#endif /* GETADDRINFO_H */ + +#endif diff --git a/src/port/netdb.c b/src/port/netdb.c index 3995c5a..1e5b2eb 100644 --- a/src/port/netdb.c +++ b/src/port/netdb.c @@ -19,7 +19,6 @@ #if !defined HAVE_GETADDRINFO || defined TEST_GETADDRINFO -void wolf_port_getaddrinfo( void ) { -} +#include "port/getaddrinfo.c" #endif /* !defined HAVE_GETADDRINFO || defined TEST_GETADDRINFO */ -- cgit v1.2.3-54-g00ecf