summaryrefslogtreecommitdiff
path: root/src/port
diff options
context:
space:
mode:
authorAndreas Baumann <abaumann@yahoo.com>2009-04-01 15:48:39 +0200
committerAndreas Baumann <abaumann@yahoo.com>2009-04-01 15:48:39 +0200
commit8caf15e38c6c1a803c110028b0d8a10d6fece776 (patch)
treedcc3b99e2e716ce17172b94c2f7adc5ca3d522eb /src/port
parentdde2d0138dd3d6d603b476f7e5f50aff2270251e (diff)
downloadwolfbones-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/port')
-rwxr-xr-xsrc/port/getaddrinfo.c225
-rwxr-xr-xsrc/port/getaddrinfo.h93
-rw-r--r--src/port/netdb.c247
3 files changed, 246 insertions, 319 deletions
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 */