* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
- * $Id$
***************************************************************************/
-#include "setup.h"
+#include "curl_setup.h"
#include <curl/curl.h>
-#ifdef NEED_MALLOC_H
-# include <malloc.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
# include <arpa/inet.h>
#endif
-#ifdef VMS
+#ifdef __VMS
# include <in.h>
# include <inet.h>
-# include <stdlib.h>
#endif
#if defined(NETWARE) && defined(__NOVELL_LIBC__)
#endif
#include "curl_addrinfo.h"
+#include "inet_pton.h"
+#include "warnless.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
-#include "memory.h"
+#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
* any function call which actually allocates a Curl_addrinfo struct.
*/
+#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \
+ defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__)
+ /* workaround icc 9.1 optimizer issue */
+# define vqualifier volatile
+#else
+# define vqualifier
+#endif
+
void
Curl_freeaddrinfo(Curl_addrinfo *cahead)
{
-#if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910)
- volatile Curl_addrinfo * volatile ca;
- volatile Curl_addrinfo * volatile canext;
-#else
- Curl_addrinfo *ca, *canext;
-#endif
+ Curl_addrinfo *vqualifier canext;
+ Curl_addrinfo *ca;
for(ca = cahead; ca != NULL; ca = canext) {
const struct addrinfo *hints,
Curl_addrinfo **result)
{
- const struct addrinfo *ainext;
const struct addrinfo *ai;
struct addrinfo *aihead;
Curl_addrinfo *cafirst = NULL;
Curl_addrinfo *calast = NULL;
Curl_addrinfo *ca;
+ size_t ss_size;
int error;
*result = NULL; /* assume failure */
if(error)
return error;
- for(ai = aihead; ai != NULL; ai = ainext) {
+ /* traverse the addrinfo list */
+
+ for(ai = aihead; ai != NULL; ai = ai->ai_next) {
+
+ /* ignore elements with unsupported address family, */
+ /* settle family-specific sockaddr structure size. */
+ if(ai->ai_family == AF_INET)
+ ss_size = sizeof(struct sockaddr_in);
+#ifdef ENABLE_IPV6
+ else if(ai->ai_family == AF_INET6)
+ ss_size = sizeof(struct sockaddr_in6);
+#endif
+ else
+ continue;
+
+ /* ignore elements without required address info */
+ if((ai->ai_addr == NULL) || !(ai->ai_addrlen > 0))
+ continue;
+
+ /* ignore elements with bogus address size */
+ if((size_t)ai->ai_addrlen < ss_size)
+ continue;
if((ca = malloc(sizeof(Curl_addrinfo))) == NULL) {
error = EAI_MEMORY;
}
/* copy each structure member individually, member ordering, */
- /* size, or padding might be different for each structure. */
+ /* size, or padding might be different for each platform. */
ca->ai_flags = ai->ai_flags;
ca->ai_family = ai->ai_family;
ca->ai_socktype = ai->ai_socktype;
ca->ai_protocol = ai->ai_protocol;
- ca->ai_addrlen = 0;
+ ca->ai_addrlen = (curl_socklen_t)ss_size;
ca->ai_addr = NULL;
ca->ai_canonname = NULL;
ca->ai_next = NULL;
- if((ai->ai_addrlen > 0) && (ai->ai_addr != NULL)) {
- ca->ai_addrlen = ai->ai_addrlen;
- if((ca->ai_addr = malloc(ca->ai_addrlen)) == NULL) {
- error = EAI_MEMORY;
- free(ca);
- break;
- }
- memcpy(ca->ai_addr, ai->ai_addr, ca->ai_addrlen);
+ if((ca->ai_addr = malloc(ss_size)) == NULL) {
+ error = EAI_MEMORY;
+ free(ca);
+ break;
}
+ memcpy(ca->ai_addr, ai->ai_addr, ss_size);
if(ai->ai_canonname != NULL) {
if((ca->ai_canonname = strdup(ai->ai_canonname)) == NULL) {
error = EAI_MEMORY;
- if(ca->ai_addr)
- free(ca->ai_addr);
+ free(ca->ai_addr);
free(ca);
break;
}
calast->ai_next = ca;
calast = ca;
- /* fetch next element fom the addrinfo list */
- ainext = ai->ai_next;
}
/* destroy the addrinfo list */
Curl_freeaddrinfo(cafirst);
cafirst = NULL;
}
+ else if(!cafirst) {
+#ifdef EAI_NONAME
+ /* rfc3493 conformant */
+ error = EAI_NONAME;
+#else
+ /* rfc3493 obsoleted */
+ error = EAI_NODATA;
+#endif
+#ifdef USE_WINSOCK
+ SET_SOCKERRNO(error);
+#endif
+ }
*result = cafirst;
* int ai_family;
* int ai_socktype;
* int ai_protocol;
- * socklen_t ai_addrlen; * Follow rfc3493 struct addrinfo *
+ * curl_socklen_t ai_addrlen; * Follow rfc3493 struct addrinfo *
* char *ai_canonname;
* struct sockaddr *ai_addr;
* struct Curl_addrinfo *ai_next;
size_t ss_size;
#ifdef ENABLE_IPV6
- if (he->h_addrtype == AF_INET6)
+ if(he->h_addrtype == AF_INET6)
ss_size = sizeof (struct sockaddr_in6);
else
#endif
the type must be ignored and conn->socktype be used instead! */
ai->ai_socktype = SOCK_STREAM;
- ai->ai_addrlen = (int)ss_size;
+ ai->ai_addrlen = (curl_socklen_t)ss_size;
/* leave the rest of the struct filled with zero */
{
Curl_addrinfo *ai;
-#if defined(VMS) && \
+#if defined(__VMS) && \
defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
#pragma pointer_size save
#pragma pointer_size short
h->h_addr_list[0] = addrentry;
h->h_addr_list[1] = NULL; /* terminate list of entries */
-#if defined(VMS) && \
+#if defined(__VMS) && \
defined(__INITIAL_POINTER_SIZE) && (__INITIAL_POINTER_SIZE == 64)
#pragma pointer_size restore
#pragma message enable PTRMISMATCH
return ai;
}
+/*
+ * Given an IPv4 or IPv6 dotted string address, this converts it to a proper
+ * allocated Curl_addrinfo struct and returns it.
+ */
+Curl_addrinfo *Curl_str2addr(char *address, int port)
+{
+ struct in_addr in;
+ if(Curl_inet_pton(AF_INET, address, &in) > 0)
+ /* This is a dotted IP address 123.123.123.123-style */
+ return Curl_ip2addr(AF_INET, &in, address, port);
+#ifdef ENABLE_IPV6
+ else {
+ struct in6_addr in6;
+ if(Curl_inet_pton(AF_INET6, address, &in6) > 0)
+ /* This is a dotted IPv6 address ::1-style */
+ return Curl_ip2addr(AF_INET6, &in6, address, port);
+ }
+#endif
+ return NULL; /* bad input format */
+}
#if defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO)
/*
*
* This is strictly for memory tracing and are using the same style as the
* family otherwise present in memdebug.c. I put these ones here since they
- * require a bunch of structs I didn't wanna include in memdebug.c
+ * require a bunch of structs I didn't want to include in memdebug.c
*/
void
int line, const char *source)
{
(freeaddrinfo)(freethis);
- if(logfile)
- fprintf(logfile, "ADDR %s:%d freeaddrinfo(%p)\n",
- source, line, (void *)freethis);
+ curl_memlog("ADDR %s:%d freeaddrinfo(%p)\n",
+ source, line, (void *)freethis);
}
#endif /* defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) */
*
* This is strictly for memory tracing and are using the same style as the
* family otherwise present in memdebug.c. I put these ones here since they
- * require a bunch of structs I didn't wanna include in memdebug.c
+ * require a bunch of structs I didn't want to include in memdebug.c
*/
int
int line, const char *source)
{
int res=(getaddrinfo)(hostname, service, hints, result);
- if(0 == res) {
+ if(0 == res)
/* success */
- if(logfile)
- fprintf(logfile, "ADDR %s:%d getaddrinfo() = %p\n",
- source, line, (void *)*result);
- }
- else {
- if(logfile)
- fprintf(logfile, "ADDR %s:%d getaddrinfo() failed\n",
- source, line);
- }
+ curl_memlog("ADDR %s:%d getaddrinfo() = %p\n",
+ source, line, (void *)*result);
+ else
+ curl_memlog("ADDR %s:%d getaddrinfo() failed\n",
+ source, line);
return res;
}
#endif /* defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) */