diff options
author | Andreas Baumann <abaumann@yahoo.com> | 2009-04-01 15:48:39 +0200 |
---|---|---|
committer | Andreas Baumann <abaumann@yahoo.com> | 2009-04-01 15:48:39 +0200 |
commit | 8caf15e38c6c1a803c110028b0d8a10d6fece776 (patch) | |
tree | dcc3b99e2e716ce17172b94c2f7adc5ca3d522eb /src | |
parent | dde2d0138dd3d6d603b476f7e5f50aff2270251e (diff) | |
download | wolfbones-8caf15e38c6c1a803c110028b0d8a10d6fece776.tar.gz wolfbones-8caf15e38c6c1a803c110028b0d8a10d6fece776.tar.bz2 |
removed extern in function prototypes; added gai_strerror_r and a test, cleanup in netdb.h and netdb.c
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.W32 | 3 | ||||
-rwxr-xr-x | src/port/getaddrinfo.c | 225 | ||||
-rwxr-xr-x | src/port/getaddrinfo.h | 93 | ||||
-rw-r--r-- | src/port/netdb.c | 247 |
4 files changed, 248 insertions, 320 deletions
diff --git a/src/Makefile.W32 b/src/Makefile.W32 index b321eeb..d0f7a99 100644 --- a/src/Makefile.W32 +++ b/src/Makefile.W32 @@ -20,7 +20,8 @@ PORT_OBJS = \ port\string.obj \ port\stdio.obj \ port\stdlib.obj \ - port\time.obj + port\time.obj \ + port\netdb.obj LOG_OBJS = \ log\log.obj diff --git a/src/port/getaddrinfo.c b/src/port/getaddrinfo.c deleted file mode 100755 index 8f9db2a..0000000 --- a/src/port/getaddrinfo.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - Copyright (C) 2008 Andreas Baumann <abaumann@yahoo.com> - - 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 <http://www.gnu.org/licenses/>. -*/ - -#include "port/getaddrinfo.h" - -#if !defined HAVE_GETADDRINFO || defined TEST_GETADDRINFO - -#include "port/string.h" /* for memset, memcpy */ -#include "port/stdlib.h" /* for atoi, itoa, malloc, free, NULL */ -#include "port/unused.h" - -#include <netinet/in.h> /* 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 ); - } -} - -/* - * Convert an ipv4 address to a hostname. - * - * Bugs: - Only supports NI_NUMERICHOST and NI_NUMERICSERV - * It will never resolv a hostname. - * - No IPv6 support. - */ -extern int getnameinfo( const struct sockaddr *sa, socklen_t salen, - char *host, size_t hostlen, - char *serv, size_t servlen, - int flags ) { - WOLF_UNUSED( salen ); - - /* Invalid arguments. */ - if( sa == NULL || ( host == NULL && serv == NULL ) ) { - return EAI_FAIL; - } - - /* We don't support those. */ - if( ( host && !( flags & NI_NUMERICHOST ) ) - || ( serv && !( flags & NI_NUMERICSERV ) ) ) { - return EAI_FAIL; - } - -#ifdef HAVE_IPV6 - /* no IPV6 here */ - if( sa->sa_family == AF_INET6 ) { - return EAI_FAMILY; - } -#endif - - if( host != NULL ) { - if( sa->sa_family == AF_INET ) { - char *p; - - /* maximal size of an IP4 addres 255.255.255.255.255 */ - if( hostlen < 16 ) { - return EAI_MEMORY; - } - - p = inet_ntoa( ( (const struct sockaddr_in * ) sa)->sin_addr ); - - strlcpy( host, p, hostlen ); - } - } - - if( serv != NULL ) { - if (sa->sa_family == AF_INET ) { - /* maximal number of digits in an unsigned short */ - if( servlen < 10 ) { - return EAI_MEMORY; - } - (void)itoa( ntohs( ( (const struct sockaddr_in * )sa)->sin_port ), serv, servlen ); - } - } - - return 0; -} - -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 deleted file mode 100755 index 746ac47..0000000 --- a/src/port/getaddrinfo.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - Copyright (C) 2008 Andreas Baumann <abaumann@yahoo.com> - - 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 <http://www.gnu.org/licenses/>. -*/ - -/* - * 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 - */ - -#ifndef __GETADDRINFO_H -#define __GETADDRINFO_H - -#include "port/sys_internal.h" - -#if !defined HAVE_GETADDRINFO || defined TEST_GETADDRINFO - -#include <sys/types.h> /* for size_t */ -#include <sys/socket.h> /* for AF_UNSPEC */ -#include <arpa/inet.h> /* for TCPPROTO and others */ - -/* 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 - -/* for flags in getnameinfo */ -#if !defined NI_NUMERICHOST -#define NI_NUMERICHOST 1 /**< don't try to look up hostname. */ -#define NI_NUMERICSERV 2 /**< don't convert port number to name. */ -#endif - -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 int wolf_port_getnameinfo( const struct sockaddr *sa, socklen_t salen, - char *host, size_t hostlen, - char *serv, size_t servlen, - int flags ); - -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 getnameinfo( sa, salen, host, hostlen, serv, servlen, flags ) wolf_port_getnameinfo( sa, salen, host, hostlen, serv, servlen, flags ) -#define gai_strerror( errcode ) wolf_port_gai_strerror( errcode ) -#endif - -#endif /* !defined HAVE_GETADDRINFO || defined TEST_GETADDRINFO */ - -#endif /* ifndef __GETADDRINFO_H */ diff --git a/src/port/netdb.c b/src/port/netdb.c index 916b908..a61acd2 100644 --- a/src/port/netdb.c +++ b/src/port/netdb.c @@ -18,5 +18,250 @@ #include "port/netdb.h" #if !defined HAVE_GETADDRINFO || defined TEST_GETADDRINFO -#include "port/getaddrinfo.c" + +#include "port/string.h" /* for memset, memcpy */ +#include "port/stdlib.h" /* for atoi, itoa, malloc, free, NULL */ +#include "port/stdio.h" /* for snprintf */ +#include "port/unused.h" + +#include <netinet/in.h> /* 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 ); + } +} + +/* + * Convert an ipv4 address to a hostname. + * + * Bugs: - Only supports NI_NUMERICHOST and NI_NUMERICSERV + * It will never resolv a hostname. + * - No IPv6 support. + */ +extern int getnameinfo( const struct sockaddr *sa, socklen_t salen, + char *host, size_t hostlen, + char *serv, size_t servlen, + int flags ) { + WOLF_UNUSED( salen ); + + /* Invalid arguments. */ + if( sa == NULL || ( host == NULL && serv == NULL ) ) { + return EAI_FAIL; + } + + /* We don't support those. */ + if( ( host && !( flags & NI_NUMERICHOST ) ) + || ( serv && !( flags & NI_NUMERICSERV ) ) ) { + return EAI_FAIL; + } + +#ifdef HAVE_IPV6 + /* no IPV6 here */ + if( sa->sa_family == AF_INET6 ) { + return EAI_FAMILY; + } +#endif + + if( host != NULL ) { + if( sa->sa_family == AF_INET ) { + char *p; + + /* maximal size of an IP4 addres 255.255.255.255.255 */ + if( hostlen < 16 ) { + return EAI_MEMORY; + } + + p = inet_ntoa( ( (const struct sockaddr_in * ) sa)->sin_addr ); + + strlcpy( host, p, hostlen ); + } + } + + if( serv != NULL ) { + if (sa->sa_family == AF_INET ) { + /* maximal number of digits in an unsigned short */ + if( servlen < 10 ) { + return EAI_MEMORY; + } + (void)itoa( ntohs( ( (const struct sockaddr_in * )sa)->sin_port ), serv, servlen ); + } + } + + return 0; +} + +const char *wolf_port_gai_strerror( int errcode ) { + static char buf[256]; + + 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: + snprintf( buf, 256, "Unknown GAI error %d", errcode ); + return buf; + } +} + #endif /* !defined HAVE_GETADDRINFO || defined TEST_GETADDRINFO */ + +#if !defined HAVE_GAI_STRERROR_R || defined TEST_GAI_STRERROR_R + +#include "threads/mutex.h" /* for mutexes */ +#include "port/stdio.h" /* for snprintf */ +#include "port/stdbool.h" /* for bool */ +#include "port/string.h" /* for strncmp */ +#include <errno.h> /* for errno */ + +static bool mutex_initialized = false; +static wolf_mutex_t mutex; + +int wolf_port_gai_strerror_r( int errcode, char *buf, size_t buflen ) { + int safe_errno = errno; + const char *msg; + + /* critical section as gai_strerror is not thread-safe */ + if( !mutex_initialized ) { + wolf_mutex_init( &mutex ); + mutex_initialized = true; + } + wolf_mutex_lock( &mutex ); + + msg = gai_strerror( errcode ); + if( strncmp( msg, "Unknown GAI errror", strlen( "Unknown GAI error" ) ) == 0 /* our own stub implementation */ ) { + (void)snprintf( buf, buflen, "Unknown GAI error %d", errcode ); + errno = EINVAL; + wolf_mutex_unlock( &mutex ); + return -1; + } + + strncpy( buf, msg, buflen-1 ); + errno = safe_errno; + wolf_mutex_unlock( &mutex ); + return 0; +} + +#endif /* !defined HAVE_GAI_STRERROR_R || defined TEST_GAI_STRERROR_R */ |