mirror of
https://github.com/moparisthebest/curl
synced 2024-12-22 08:08:50 -05:00
Use our Curl_addrinfo definition even when an addrinfo struct is available.
Use a wrapper function to call system's getaddrinfo().
This commit is contained in:
parent
197ad60d21
commit
0ce97f77e0
@ -9,7 +9,7 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
|
|||||||
http_negotiate.c http_ntlm.c inet_pton.c strtoofft.c strerror.c \
|
http_negotiate.c http_ntlm.c inet_pton.c strtoofft.c strerror.c \
|
||||||
hostares.c hostasyn.c hostip4.c hostip6.c hostsyn.c hostthre.c \
|
hostares.c hostasyn.c hostip4.c hostip6.c hostsyn.c hostthre.c \
|
||||||
inet_ntop.c parsedate.c select.c gtls.c sslgen.c tftp.c splay.c \
|
inet_ntop.c parsedate.c select.c gtls.c sslgen.c tftp.c splay.c \
|
||||||
strdup.c socks.c ssh.c nss.c qssl.c rawstr.c
|
strdup.c socks.c ssh.c nss.c qssl.c rawstr.c curl_addrinfo.c
|
||||||
|
|
||||||
HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \
|
HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \
|
||||||
progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \
|
progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \
|
||||||
@ -20,4 +20,4 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \
|
|||||||
strtoofft.h strerror.h inet_ntop.h curlx.h memory.h setup.h \
|
strtoofft.h strerror.h inet_ntop.h curlx.h memory.h setup.h \
|
||||||
transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h gtls.h \
|
transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h gtls.h \
|
||||||
tftp.h sockaddr.h splay.h strdup.h setup_once.h socks.h ssh.h nssg.h \
|
tftp.h sockaddr.h splay.h strdup.h setup_once.h socks.h ssh.h nssg.h \
|
||||||
curl_base64.h rawstr.h
|
curl_base64.h rawstr.h curl_addrinfo.h
|
||||||
|
332
lib/curl_addrinfo.c
Normal file
332
lib/curl_addrinfo.c
Normal file
@ -0,0 +1,332 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2008, 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
|
||||||
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "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
|
||||||
|
#ifdef HAVE_NETDB_H
|
||||||
|
# include <netdb.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ARPA_INET_H
|
||||||
|
# include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef VMS
|
||||||
|
# include <in.h>
|
||||||
|
# include <inet.h>
|
||||||
|
# include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(NETWARE) && defined(__NOVELL_LIBC__)
|
||||||
|
# undef in_addr_t
|
||||||
|
# define in_addr_t unsigned long
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "curl_addrinfo.h"
|
||||||
|
|
||||||
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
|
#include "memory.h"
|
||||||
|
/* The last #include file should be: */
|
||||||
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_freeaddrinfo()
|
||||||
|
*
|
||||||
|
* This is used to free a linked list of Curl_addrinfo structs along
|
||||||
|
* with all its associated allocated storage. This function should be
|
||||||
|
* called once for each successful call to Curl_getaddrinfo_ex() or to
|
||||||
|
* any function call which actually allocates a Curl_addrinfo struct.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
Curl_freeaddrinfo(Curl_addrinfo *cahead)
|
||||||
|
{
|
||||||
|
Curl_addrinfo *ca, *canext;
|
||||||
|
|
||||||
|
for(ca = cahead; ca != NULL; ca = canext) {
|
||||||
|
|
||||||
|
if(ca->ai_addr)
|
||||||
|
free(ca->ai_addr);
|
||||||
|
|
||||||
|
if(ca->ai_canonname)
|
||||||
|
free(ca->ai_canonname);
|
||||||
|
|
||||||
|
canext = ca->ai_next;
|
||||||
|
|
||||||
|
free(ca);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_GETADDRINFO
|
||||||
|
/*
|
||||||
|
* Curl_getaddrinfo_ex()
|
||||||
|
*
|
||||||
|
* This is a warapper function around system's getaddrinfo(), with
|
||||||
|
* the only difference that instead of returning a linked list of
|
||||||
|
* addrinfo structs this one returns a linked list of Curl_addrinfo
|
||||||
|
* ones. The memory allocated by this function *MUST* be free'd with
|
||||||
|
* Curl_freeaddrinfo(). For each successful call to this function
|
||||||
|
* there must be an associated call later to Curl_freeaddrinfo().
|
||||||
|
*
|
||||||
|
* There should be no single call to system's getaddrinfo() in the
|
||||||
|
* whole library, any such call should be 'routed' through this one.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
Curl_getaddrinfo_ex(const char *nodename,
|
||||||
|
const char *servname,
|
||||||
|
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;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
*result = NULL; /* assume failure */
|
||||||
|
|
||||||
|
error = getaddrinfo(nodename, servname, hints, &aihead);
|
||||||
|
if(error)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
for(ai = aihead; ai != NULL; ai = ainext) {
|
||||||
|
|
||||||
|
if((ca = malloc(sizeof(Curl_addrinfo))) == NULL) {
|
||||||
|
error = EAI_MEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy each structure member individually, member ordering, */
|
||||||
|
/* size, or padding might be different for each structure. */
|
||||||
|
|
||||||
|
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_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(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);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if the return list is empty, this becomes the first element */
|
||||||
|
if(!cafirst)
|
||||||
|
cafirst = ca;
|
||||||
|
|
||||||
|
/* add this element last in the return list */
|
||||||
|
if(calast)
|
||||||
|
calast->ai_next = ca;
|
||||||
|
calast = ca;
|
||||||
|
|
||||||
|
/* fetch next element fom the addrinfo list */
|
||||||
|
ainext = ai->ai_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* destroy the addrinfo list */
|
||||||
|
if(aihead)
|
||||||
|
freeaddrinfo(aihead);
|
||||||
|
|
||||||
|
/* if we failed, also destroy the Curl_addrinfo list */
|
||||||
|
if(error) {
|
||||||
|
Curl_freeaddrinfo(cafirst);
|
||||||
|
cafirst = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*result = cafirst;
|
||||||
|
|
||||||
|
return error; /* This is not a CURLcode */
|
||||||
|
}
|
||||||
|
#endif /* HAVE_GETADDRINFO */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_he2ai()
|
||||||
|
*
|
||||||
|
* This function returns a pointer to the first element of a newly allocated
|
||||||
|
* Curl_addrinfo struct linked list filled with the data of a given hostent.
|
||||||
|
* Curl_addrinfo is meant to work like the addrinfo struct does for a IPv6
|
||||||
|
* stack, but usable also for IPv4, all hosts and environments.
|
||||||
|
*
|
||||||
|
* The memory allocated by this function *MUST* be free'd later on calling
|
||||||
|
* Curl_freeaddrinfo(). For each successful call to this function there
|
||||||
|
* must be an associated call later to Curl_freeaddrinfo().
|
||||||
|
*
|
||||||
|
* Curl_addrinfo defined in "lib/curl_addrinfo.h"
|
||||||
|
*
|
||||||
|
* struct Curl_addrinfo {
|
||||||
|
* int ai_flags;
|
||||||
|
* int ai_family;
|
||||||
|
* int ai_socktype;
|
||||||
|
* int ai_protocol;
|
||||||
|
* socklen_t ai_addrlen; * Follow rfc3493 struct addrinfo *
|
||||||
|
* char *ai_canonname;
|
||||||
|
* struct sockaddr *ai_addr;
|
||||||
|
* struct Curl_addrinfo *ai_next;
|
||||||
|
* };
|
||||||
|
* typedef struct Curl_addrinfo Curl_addrinfo;
|
||||||
|
*
|
||||||
|
* hostent defined in <netdb.h>
|
||||||
|
*
|
||||||
|
* struct hostent {
|
||||||
|
* char *h_name;
|
||||||
|
* char **h_aliases;
|
||||||
|
* int h_addrtype;
|
||||||
|
* int h_length;
|
||||||
|
* char **h_addr_list;
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* for backward compatibility:
|
||||||
|
*
|
||||||
|
* #define h_addr h_addr_list[0]
|
||||||
|
*/
|
||||||
|
|
||||||
|
Curl_addrinfo *
|
||||||
|
Curl_he2ai(const struct hostent *he, int port)
|
||||||
|
{
|
||||||
|
Curl_addrinfo *ai;
|
||||||
|
Curl_addrinfo *prevai = NULL;
|
||||||
|
Curl_addrinfo *firstai = NULL;
|
||||||
|
struct sockaddr_in *addr;
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
struct sockaddr_in6 *addr6;
|
||||||
|
#endif
|
||||||
|
CURLcode result = CURLE_OK;
|
||||||
|
int i;
|
||||||
|
char *curr;
|
||||||
|
|
||||||
|
if(!he)
|
||||||
|
/* no input == no output! */
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for(i=0; (curr = he->h_addr_list[i]) != NULL; i++) {
|
||||||
|
|
||||||
|
int ss_size;
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
if (he->h_addrtype == AF_INET6)
|
||||||
|
ss_size = sizeof (struct sockaddr_in6);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
ss_size = sizeof (struct sockaddr_in);
|
||||||
|
|
||||||
|
if((ai = calloc(1, sizeof(Curl_addrinfo))) == NULL) {
|
||||||
|
result = CURLE_OUT_OF_MEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if((ai->ai_canonname = strdup(he->h_name)) == NULL) {
|
||||||
|
result = CURLE_OUT_OF_MEMORY;
|
||||||
|
free(ai);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if((ai->ai_addr = calloc(1, ss_size)) == NULL) {
|
||||||
|
result = CURLE_OUT_OF_MEMORY;
|
||||||
|
free(ai->ai_canonname);
|
||||||
|
free(ai);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!firstai)
|
||||||
|
/* store the pointer we want to return from this function */
|
||||||
|
firstai = ai;
|
||||||
|
|
||||||
|
if(prevai)
|
||||||
|
/* make the previous entry point to this */
|
||||||
|
prevai->ai_next = ai;
|
||||||
|
|
||||||
|
ai->ai_family = he->h_addrtype;
|
||||||
|
|
||||||
|
/* we return all names as STREAM, so when using this address for TFTP
|
||||||
|
the type must be ignored and conn->socktype be used instead! */
|
||||||
|
ai->ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
|
ai->ai_addrlen = ss_size;
|
||||||
|
|
||||||
|
/* leave the rest of the struct filled with zero */
|
||||||
|
|
||||||
|
switch (ai->ai_family) {
|
||||||
|
case AF_INET:
|
||||||
|
addr = (struct sockaddr_in *)ai->ai_addr; /* storage area for this info */
|
||||||
|
|
||||||
|
memcpy(&addr->sin_addr, curr, sizeof(struct in_addr));
|
||||||
|
addr->sin_family = (unsigned short)(he->h_addrtype);
|
||||||
|
addr->sin_port = htons((unsigned short)port);
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
case AF_INET6:
|
||||||
|
addr6 = (struct sockaddr_in6 *)ai->ai_addr; /* storage area for this info */
|
||||||
|
|
||||||
|
memcpy(&addr6->sin6_addr, curr, sizeof(struct in6_addr));
|
||||||
|
addr6->sin6_family = (unsigned short)(he->h_addrtype);
|
||||||
|
addr6->sin6_port = htons((unsigned short)port);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
prevai = ai;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result != CURLE_OK) {
|
||||||
|
/* Use parenthesis to prevent memdebug from replacing this */
|
||||||
|
Curl_freeaddrinfo(firstai);
|
||||||
|
firstai = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return firstai;
|
||||||
|
}
|
||||||
|
|
81
lib/curl_addrinfo.h
Normal file
81
lib/curl_addrinfo.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#ifndef HEADER_CURL_ADDRINFO_H
|
||||||
|
#define HEADER_CURL_ADDRINFO_H
|
||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2008, 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
|
||||||
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "setup.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
# include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
# include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETDB_H
|
||||||
|
# include <netdb.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ARPA_INET_H
|
||||||
|
# include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef VMS
|
||||||
|
# include <in.h>
|
||||||
|
# include <inet.h>
|
||||||
|
# include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Curl_addrinfo is our internal struct definition that we use to allow
|
||||||
|
* consistent internal handling of this data. We use this even when the
|
||||||
|
* system provides an addrinfo structure definition. And we use this for
|
||||||
|
* all sorts of IPv4 and IPV6 builds.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct Curl_addrinfo {
|
||||||
|
int ai_flags;
|
||||||
|
int ai_family;
|
||||||
|
int ai_socktype;
|
||||||
|
int ai_protocol;
|
||||||
|
socklen_t ai_addrlen; /* Follow rfc3493 struct addrinfo */
|
||||||
|
char *ai_canonname;
|
||||||
|
struct sockaddr *ai_addr;
|
||||||
|
struct Curl_addrinfo *ai_next;
|
||||||
|
};
|
||||||
|
typedef struct Curl_addrinfo Curl_addrinfo;
|
||||||
|
|
||||||
|
void
|
||||||
|
Curl_freeaddrinfo(Curl_addrinfo *cahead);
|
||||||
|
|
||||||
|
#ifdef HAVE_GETADDRINFO
|
||||||
|
int
|
||||||
|
Curl_getaddrinfo_ex(const char *nodename,
|
||||||
|
const char *servname,
|
||||||
|
const struct addrinfo *hints,
|
||||||
|
Curl_addrinfo **result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Curl_addrinfo *
|
||||||
|
Curl_he2ai(const struct hostent *he, int port);
|
||||||
|
|
||||||
|
#endif /* HEADER_CURL_ADDRINFO_H */
|
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@ -160,7 +160,7 @@ CURLcode Curl_addrinfo6_callback(void *arg, /* "struct connectdata *" */
|
|||||||
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
|
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
|
||||||
int timeouts,
|
int timeouts,
|
||||||
#endif
|
#endif
|
||||||
struct addrinfo *ai)
|
Curl_addrinfo *ai)
|
||||||
{
|
{
|
||||||
/* NOTE: for CURLRES_ARES, the 'ai' argument is really a
|
/* NOTE: for CURLRES_ARES, the 'ai' argument is really a
|
||||||
* 'struct hostent' pointer.
|
* 'struct hostent' pointer.
|
||||||
|
146
lib/hostip.c
146
lib/hostip.c
@ -693,8 +693,10 @@ static void freednsentry(void *freethis)
|
|||||||
{
|
{
|
||||||
struct Curl_dns_entry *p = (struct Curl_dns_entry *) freethis;
|
struct Curl_dns_entry *p = (struct Curl_dns_entry *) freethis;
|
||||||
|
|
||||||
|
if(p) {
|
||||||
Curl_freeaddrinfo(p->addr);
|
Curl_freeaddrinfo(p->addr);
|
||||||
free(p);
|
free(p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -729,25 +731,6 @@ Curl_addrinfo *Curl_addrinfo_copy(const void *org, int port)
|
|||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
#if defined(CURLRES_IPV4) || defined(CURLRES_ARES)
|
#if defined(CURLRES_IPV4) || defined(CURLRES_ARES)
|
||||||
/*
|
|
||||||
* This is a function for freeing name information in a protocol independent
|
|
||||||
* way.
|
|
||||||
*/
|
|
||||||
void Curl_freeaddrinfo(Curl_addrinfo *ai)
|
|
||||||
{
|
|
||||||
Curl_addrinfo *next;
|
|
||||||
|
|
||||||
/* walk over the list and free all entries */
|
|
||||||
while(ai) {
|
|
||||||
next = ai->ai_next;
|
|
||||||
if(ai->ai_addr)
|
|
||||||
free(ai->ai_addr);
|
|
||||||
if(ai->ai_canonname)
|
|
||||||
free(ai->ai_canonname);
|
|
||||||
free(ai);
|
|
||||||
ai = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct namebuf4 {
|
struct namebuf4 {
|
||||||
struct hostent hostentry;
|
struct hostent hostentry;
|
||||||
@ -825,129 +808,4 @@ Curl_addrinfo *Curl_ip2addr(in_addr_t num, const char *hostname, int port)
|
|||||||
return ai;
|
return ai;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Curl_he2ai() translates from a hostent struct to a Curl_addrinfo struct.
|
|
||||||
* The Curl_addrinfo is meant to work like the addrinfo struct does for IPv6
|
|
||||||
* stacks, but for all hosts and environments.
|
|
||||||
*
|
|
||||||
* Curl_addrinfo defined in "lib/hostip.h"
|
|
||||||
*
|
|
||||||
* struct Curl_addrinfo {
|
|
||||||
* int ai_flags;
|
|
||||||
* int ai_family;
|
|
||||||
* int ai_socktype;
|
|
||||||
* int ai_protocol;
|
|
||||||
* socklen_t ai_addrlen; * Follow rfc3493 struct addrinfo *
|
|
||||||
* char *ai_canonname;
|
|
||||||
* struct sockaddr *ai_addr;
|
|
||||||
* struct Curl_addrinfo *ai_next;
|
|
||||||
* };
|
|
||||||
*
|
|
||||||
* hostent defined in <netdb.h>
|
|
||||||
*
|
|
||||||
* struct hostent {
|
|
||||||
* char *h_name;
|
|
||||||
* char **h_aliases;
|
|
||||||
* int h_addrtype;
|
|
||||||
* int h_length;
|
|
||||||
* char **h_addr_list;
|
|
||||||
* };
|
|
||||||
*
|
|
||||||
* for backward compatibility:
|
|
||||||
*
|
|
||||||
* #define h_addr h_addr_list[0]
|
|
||||||
*/
|
|
||||||
|
|
||||||
Curl_addrinfo *Curl_he2ai(const struct hostent *he, int port)
|
|
||||||
{
|
|
||||||
Curl_addrinfo *ai;
|
|
||||||
Curl_addrinfo *prevai = NULL;
|
|
||||||
Curl_addrinfo *firstai = NULL;
|
|
||||||
struct sockaddr_in *addr;
|
|
||||||
#ifdef CURLRES_IPV6
|
|
||||||
struct sockaddr_in6 *addr6;
|
|
||||||
#endif /* CURLRES_IPV6 */
|
|
||||||
CURLcode result = CURLE_OK;
|
|
||||||
int i;
|
|
||||||
char *curr;
|
|
||||||
|
|
||||||
if(!he)
|
|
||||||
/* no input == no output! */
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
for(i=0; (curr = he->h_addr_list[i]) != NULL; i++) {
|
|
||||||
|
|
||||||
int ss_size;
|
|
||||||
#ifdef CURLRES_IPV6
|
|
||||||
if (he->h_addrtype == AF_INET6)
|
|
||||||
ss_size = sizeof (struct sockaddr_in6);
|
|
||||||
else
|
|
||||||
#endif /* CURLRES_IPV6 */
|
|
||||||
ss_size = sizeof (struct sockaddr_in);
|
|
||||||
|
|
||||||
if((ai = calloc(1, sizeof(Curl_addrinfo))) == NULL) {
|
|
||||||
result = CURLE_OUT_OF_MEMORY;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if((ai->ai_canonname = strdup(he->h_name)) == NULL) {
|
|
||||||
result = CURLE_OUT_OF_MEMORY;
|
|
||||||
free(ai);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if((ai->ai_addr = calloc(1, ss_size)) == NULL) {
|
|
||||||
result = CURLE_OUT_OF_MEMORY;
|
|
||||||
free(ai->ai_canonname);
|
|
||||||
free(ai);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!firstai)
|
|
||||||
/* store the pointer we want to return from this function */
|
|
||||||
firstai = ai;
|
|
||||||
|
|
||||||
if(prevai)
|
|
||||||
/* make the previous entry point to this */
|
|
||||||
prevai->ai_next = ai;
|
|
||||||
|
|
||||||
ai->ai_family = he->h_addrtype;
|
|
||||||
|
|
||||||
/* we return all names as STREAM, so when using this address for TFTP
|
|
||||||
the type must be ignored and conn->socktype be used instead! */
|
|
||||||
ai->ai_socktype = SOCK_STREAM;
|
|
||||||
|
|
||||||
ai->ai_addrlen = ss_size;
|
|
||||||
|
|
||||||
/* leave the rest of the struct filled with zero */
|
|
||||||
|
|
||||||
switch (ai->ai_family) {
|
|
||||||
case AF_INET:
|
|
||||||
addr = (struct sockaddr_in *)ai->ai_addr; /* storage area for this info */
|
|
||||||
|
|
||||||
memcpy(&addr->sin_addr, curr, sizeof(struct in_addr));
|
|
||||||
addr->sin_family = (unsigned short)(he->h_addrtype);
|
|
||||||
addr->sin_port = htons((unsigned short)port);
|
|
||||||
break;
|
|
||||||
|
|
||||||
#ifdef CURLRES_IPV6
|
|
||||||
case AF_INET6:
|
|
||||||
addr6 = (struct sockaddr_in6 *)ai->ai_addr; /* storage area for this info */
|
|
||||||
|
|
||||||
memcpy(&addr6->sin6_addr, curr, sizeof(struct in6_addr));
|
|
||||||
addr6->sin6_family = (unsigned short)(he->h_addrtype);
|
|
||||||
addr6->sin6_port = htons((unsigned short)port);
|
|
||||||
break;
|
|
||||||
#endif /* CURLRES_IPV6 */
|
|
||||||
}
|
|
||||||
|
|
||||||
prevai = ai;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(result != CURLE_OK) {
|
|
||||||
Curl_freeaddrinfo(firstai);
|
|
||||||
firstai = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return firstai;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* CURLRES_IPV4 || CURLRES_ARES */
|
#endif /* CURLRES_IPV4 || CURLRES_ARES */
|
||||||
|
32
lib/hostip.h
32
lib/hostip.h
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "setup.h"
|
#include "setup.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
|
#include "curl_addrinfo.h"
|
||||||
|
|
||||||
#ifdef HAVE_SETJMP_H
|
#ifdef HAVE_SETJMP_H
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
@ -103,30 +104,10 @@
|
|||||||
#define ares_destroy(x) do {} while(0)
|
#define ares_destroy(x) do {} while(0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
#if defined(CURLRES_IPV6) && defined(CURLRES_ARES)
|
||||||
* Curl_addrinfo MUST be used for all name resolved info.
|
|
||||||
*/
|
|
||||||
#ifdef CURLRES_IPV6
|
|
||||||
typedef struct addrinfo Curl_addrinfo;
|
|
||||||
#ifdef CURLRES_ARES
|
|
||||||
Curl_addrinfo *Curl_ip2addr6(struct in6_addr *in,
|
Curl_addrinfo *Curl_ip2addr6(struct in6_addr *in,
|
||||||
const char *hostname, int port);
|
const char *hostname, int port);
|
||||||
#endif
|
#endif
|
||||||
#else
|
|
||||||
/* OK, so some ipv4-only include tree probably have the addrinfo struct, but
|
|
||||||
to work even on those that don't, we provide our own look-alike! */
|
|
||||||
struct Curl_addrinfo {
|
|
||||||
int ai_flags;
|
|
||||||
int ai_family;
|
|
||||||
int ai_socktype;
|
|
||||||
int ai_protocol;
|
|
||||||
socklen_t ai_addrlen; /* Follow rfc3493 struct addrinfo */
|
|
||||||
char *ai_canonname;
|
|
||||||
struct sockaddr *ai_addr;
|
|
||||||
struct Curl_addrinfo *ai_next;
|
|
||||||
};
|
|
||||||
typedef struct Curl_addrinfo Curl_addrinfo;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct addrinfo;
|
struct addrinfo;
|
||||||
struct hostent;
|
struct hostent;
|
||||||
@ -207,9 +188,6 @@ void Curl_resolv_unlock(struct SessionHandle *data,
|
|||||||
/* for debugging purposes only: */
|
/* for debugging purposes only: */
|
||||||
void Curl_scan_cache_used(void *user, void *ptr);
|
void Curl_scan_cache_used(void *user, void *ptr);
|
||||||
|
|
||||||
/* free name info */
|
|
||||||
void Curl_freeaddrinfo(Curl_addrinfo *freeaddr);
|
|
||||||
|
|
||||||
/* make a new dns cache and return the handle */
|
/* make a new dns cache and return the handle */
|
||||||
struct curl_hash *Curl_mk_dnscache(void);
|
struct curl_hash *Curl_mk_dnscache(void);
|
||||||
|
|
||||||
@ -251,17 +229,13 @@ CURLcode Curl_addrinfo6_callback(void *arg,
|
|||||||
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
|
#ifdef HAVE_CARES_CALLBACK_TIMEOUTS
|
||||||
int timeouts,
|
int timeouts,
|
||||||
#endif
|
#endif
|
||||||
struct addrinfo *ai);
|
Curl_addrinfo *ai);
|
||||||
|
|
||||||
|
|
||||||
/* [ipv4/ares only] Creates a Curl_addrinfo struct from a numerical-only IP
|
/* [ipv4/ares only] Creates a Curl_addrinfo struct from a numerical-only IP
|
||||||
address */
|
address */
|
||||||
Curl_addrinfo *Curl_ip2addr(in_addr_t num, const char *hostname, int port);
|
Curl_addrinfo *Curl_ip2addr(in_addr_t num, const char *hostname, int port);
|
||||||
|
|
||||||
/* [ipv4/ares only] Curl_he2ai() converts a struct hostent to a Curl_addrinfo chain
|
|
||||||
and returns it */
|
|
||||||
Curl_addrinfo *Curl_he2ai(const struct hostent *, int port);
|
|
||||||
|
|
||||||
/* Clone a Curl_addrinfo struct, works protocol independently */
|
/* Clone a Curl_addrinfo struct, works protocol independently */
|
||||||
Curl_addrinfo *Curl_addrinfo_copy(const void *orig, int port);
|
Curl_addrinfo *Curl_addrinfo_copy(const void *orig, int port);
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@ -77,18 +77,8 @@
|
|||||||
* Only for ipv6-enabled builds
|
* Only for ipv6-enabled builds
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
#ifdef CURLRES_IPV6
|
#ifdef CURLRES_IPV6
|
||||||
#ifndef CURLRES_ARES
|
|
||||||
/*
|
|
||||||
* This is a wrapper function for freeing name information in a protocol
|
|
||||||
* independent way. This takes care of using the appropriate underlaying
|
|
||||||
* function.
|
|
||||||
*/
|
|
||||||
void Curl_freeaddrinfo(Curl_addrinfo *p)
|
|
||||||
{
|
|
||||||
if(p)
|
|
||||||
freeaddrinfo(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
#ifndef CURLRES_ARES
|
||||||
#ifdef CURLRES_ASYNCH
|
#ifdef CURLRES_ASYNCH
|
||||||
/*
|
/*
|
||||||
* Curl_addrinfo_copy() is used by the asynch callback to copy a given
|
* Curl_addrinfo_copy() is used by the asynch callback to copy a given
|
||||||
@ -189,7 +179,7 @@ bool Curl_ipvalid(struct SessionHandle *data)
|
|||||||
#if !defined(USE_THREADING_GETADDRINFO) && !defined(CURLRES_ARES)
|
#if !defined(USE_THREADING_GETADDRINFO) && !defined(CURLRES_ARES)
|
||||||
|
|
||||||
#ifdef DEBUG_ADDRINFO
|
#ifdef DEBUG_ADDRINFO
|
||||||
static void dump_addrinfo(struct connectdata *conn, const struct addrinfo *ai)
|
static void dump_addrinfo(struct connectdata *conn, const Curl_addrinfo *ai)
|
||||||
{
|
{
|
||||||
printf("dump_addrinfo:\n");
|
printf("dump_addrinfo:\n");
|
||||||
for ( ; ai; ai = ai->ai_next) {
|
for ( ; ai; ai = ai->ai_next) {
|
||||||
@ -221,7 +211,8 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
|||||||
int port,
|
int port,
|
||||||
int *waitp)
|
int *waitp)
|
||||||
{
|
{
|
||||||
struct addrinfo hints, *res;
|
struct addrinfo hints;
|
||||||
|
Curl_addrinfo *res;
|
||||||
int error;
|
int error;
|
||||||
char sbuf[NI_MAXSERV];
|
char sbuf[NI_MAXSERV];
|
||||||
char *sbufptr = NULL;
|
char *sbufptr = NULL;
|
||||||
@ -283,7 +274,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
|||||||
snprintf(sbuf, sizeof(sbuf), "%d", port);
|
snprintf(sbuf, sizeof(sbuf), "%d", port);
|
||||||
sbufptr=sbuf;
|
sbufptr=sbuf;
|
||||||
}
|
}
|
||||||
error = getaddrinfo(hostname, sbufptr, &hints, &res);
|
error = Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &res);
|
||||||
if(error) {
|
if(error) {
|
||||||
infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port);
|
infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -288,7 +288,7 @@ static unsigned __stdcall getaddrinfo_thread (void *arg)
|
|||||||
{
|
{
|
||||||
struct connectdata *conn = (struct connectdata*) arg;
|
struct connectdata *conn = (struct connectdata*) arg;
|
||||||
struct thread_data *td = (struct thread_data*) conn->async.os_specific;
|
struct thread_data *td = (struct thread_data*) conn->async.os_specific;
|
||||||
struct addrinfo *res;
|
Curl_addrinfo *res;
|
||||||
char service [NI_MAXSERV];
|
char service [NI_MAXSERV];
|
||||||
int rc;
|
int rc;
|
||||||
struct addrinfo hints = td->hints;
|
struct addrinfo hints = td->hints;
|
||||||
@ -313,7 +313,7 @@ static unsigned __stdcall getaddrinfo_thread (void *arg)
|
|||||||
need */
|
need */
|
||||||
SetEvent(td->event_thread_started);
|
SetEvent(td->event_thread_started);
|
||||||
|
|
||||||
rc = getaddrinfo(tsd.hostname, service, &hints, &res);
|
rc = Curl_getaddrinfo_ex(tsd.hostname, service, &hints, &res);
|
||||||
|
|
||||||
/* is parent thread waiting for us and are we able to access conn members? */
|
/* is parent thread waiting for us and are we able to access conn members? */
|
||||||
if(acquire_thread_sync(&tsd)) {
|
if(acquire_thread_sync(&tsd)) {
|
||||||
@ -703,7 +703,8 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
|||||||
int port,
|
int port,
|
||||||
int *waitp)
|
int *waitp)
|
||||||
{
|
{
|
||||||
struct addrinfo hints, *res;
|
struct addrinfo hints;
|
||||||
|
Curl_addrinfo *res;
|
||||||
int error;
|
int error;
|
||||||
char sbuf[NI_MAXSERV];
|
char sbuf[NI_MAXSERV];
|
||||||
int pf;
|
int pf;
|
||||||
@ -762,7 +763,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
|||||||
infof(data, "init_resolve_thread() failed for %s; %s\n",
|
infof(data, "init_resolve_thread() failed for %s; %s\n",
|
||||||
hostname, Curl_strerror(conn, ERRNO));
|
hostname, Curl_strerror(conn, ERRNO));
|
||||||
|
|
||||||
error = getaddrinfo(hostname, sbuf, &hints, &res);
|
error = Curl_getaddrinfo_ex(hostname, sbuf, &hints, &res);
|
||||||
if(error) {
|
if(error) {
|
||||||
infof(data, "getaddrinfo() failed for %s:%d; %s\n",
|
infof(data, "getaddrinfo() failed for %s:%d; %s\n",
|
||||||
hostname, port, Curl_strerror(conn, SOCKERRNO));
|
hostname, port, Curl_strerror(conn, SOCKERRNO));
|
||||||
|
@ -315,6 +315,7 @@ static void sh_freeentry(void *freethis)
|
|||||||
{
|
{
|
||||||
struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
|
struct Curl_sh_entry *p = (struct Curl_sh_entry *) freethis;
|
||||||
|
|
||||||
|
if(p)
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,11 +10,17 @@
|
|||||||
|
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
# include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
# include <netinet/in.h>
|
||||||
|
#endif
|
||||||
#ifdef HAVE_NETDB_H
|
#ifdef HAVE_NETDB_H
|
||||||
#include <netdb.h>
|
# include <netdb.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_ARPA_INET_H
|
#ifdef HAVE_ARPA_INET_H
|
||||||
#include <arpa/inet.h>
|
# include <arpa/inet.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ENABLE_CURLX_PRINTF
|
#define ENABLE_CURLX_PRINTF
|
||||||
@ -64,13 +70,6 @@ static Curl_addrinfo *fake_ai(void)
|
|||||||
ai->ai_family = AF_INET;
|
ai->ai_family = AF_INET;
|
||||||
ai->ai_addrlen = ss_size;
|
ai->ai_addrlen = ss_size;
|
||||||
|
|
||||||
#if defined(ENABLE_IPV6) && defined(CURLDEBUG)
|
|
||||||
/* For tracing purposes log a fake call to getaddrinfo */
|
|
||||||
if(logfile)
|
|
||||||
fprintf(logfile, "ADDR %s:%d getaddrinfo() = %p\n",
|
|
||||||
__FILE__, __LINE__, (void *)ai);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return ai;
|
return ai;
|
||||||
}
|
}
|
||||||
#endif /* LIB559 */
|
#endif /* LIB559 */
|
||||||
|
Loading…
Reference in New Issue
Block a user