mirror of
https://github.com/moparisthebest/curl
synced 2024-12-22 08:08:50 -05:00
Curl_resolv() now returns a different struct, and it contains a reference
counter so that the caller needs to decrease that counter when done with the returned data. If compiled with MALLOCDEBUG I've added some extra checking that the counter is decreased before a handle is closed etc.
This commit is contained in:
parent
73d996bf26
commit
2cff251863
@ -206,7 +206,7 @@ static CURLcode bindlocal(struct connectdata *conn,
|
|||||||
*************************************************************/
|
*************************************************************/
|
||||||
if (strlen(data->set.device)<255) {
|
if (strlen(data->set.device)<255) {
|
||||||
struct sockaddr_in sa;
|
struct sockaddr_in sa;
|
||||||
Curl_addrinfo *h=NULL;
|
struct Curl_dns_entry *h=NULL;
|
||||||
size_t size;
|
size_t size;
|
||||||
char myhost[256] = "";
|
char myhost[256] = "";
|
||||||
in_addr_t in;
|
in_addr_t in;
|
||||||
@ -247,12 +247,17 @@ static CURLcode bindlocal(struct connectdata *conn,
|
|||||||
if (INADDR_NONE != in) {
|
if (INADDR_NONE != in) {
|
||||||
|
|
||||||
if ( h ) {
|
if ( h ) {
|
||||||
|
Curl_addrinfo *addr = h->addr;
|
||||||
|
|
||||||
|
h->inuse--; /* decrease the use-counter, we don't need it anymore
|
||||||
|
after this function has returned */
|
||||||
|
|
||||||
memset((char *)&sa, 0, sizeof(sa));
|
memset((char *)&sa, 0, sizeof(sa));
|
||||||
#ifdef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
memcpy((char *)&sa.sin_addr, h->ai_addr, h->ai_addrlen);
|
memcpy((char *)&sa.sin_addr, addr->ai_addr, addr->ai_addrlen);
|
||||||
sa.sin_family = h->ai_family;
|
sa.sin_family = addr->ai_family;
|
||||||
#else
|
#else
|
||||||
memcpy((char *)&sa.sin_addr, h->h_addr, h->h_length);
|
memcpy((char *)&sa.sin_addr, addr->h_addr, addr->h_length);
|
||||||
sa.sin_family = AF_INET;
|
sa.sin_family = AF_INET;
|
||||||
#endif
|
#endif
|
||||||
sa.sin_addr.s_addr = in;
|
sa.sin_addr.s_addr = in;
|
||||||
@ -410,7 +415,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
||||||
Curl_addrinfo *remotehost, /* use one in here */
|
struct Curl_dns_entry *remotehost, /* use this one */
|
||||||
int port, /* connect to this */
|
int port, /* connect to this */
|
||||||
int *sockconn, /* the connected socket */
|
int *sockconn, /* the connected socket */
|
||||||
Curl_ipconnect **addr, /* the one we used */
|
Curl_ipconnect **addr, /* the one we used */
|
||||||
@ -479,7 +484,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
|
|||||||
struct addrinfo *ai;
|
struct addrinfo *ai;
|
||||||
port =0; /* prevent compiler warning */
|
port =0; /* prevent compiler warning */
|
||||||
|
|
||||||
for (ai = remotehost; ai; ai = ai->ai_next, aliasindex++) {
|
for (ai = remotehost->addr; ai; ai = ai->ai_next, aliasindex++) {
|
||||||
sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||||
if (sockfd < 0)
|
if (sockfd < 0)
|
||||||
continue;
|
continue;
|
||||||
|
@ -31,7 +31,7 @@ CURLcode Curl_is_connected(struct connectdata *conn,
|
|||||||
bool *connected);
|
bool *connected);
|
||||||
|
|
||||||
CURLcode Curl_connecthost(struct connectdata *conn,
|
CURLcode Curl_connecthost(struct connectdata *conn,
|
||||||
Curl_addrinfo *host, /* connect to this */
|
struct Curl_dns_entry *host, /* connect to this */
|
||||||
int port, /* connect to this port number */
|
int port, /* connect to this port number */
|
||||||
int *sockconn, /* not set if error is returned */
|
int *sockconn, /* not set if error is returned */
|
||||||
Curl_ipconnect **addr, /* the one we used */
|
Curl_ipconnect **addr, /* the one we used */
|
||||||
|
11
lib/ftp.c
11
lib/ftp.c
@ -1184,7 +1184,6 @@ CURLcode ftp_use_port(struct connectdata *conn)
|
|||||||
*/
|
*/
|
||||||
struct sockaddr_in sa;
|
struct sockaddr_in sa;
|
||||||
struct hostent *h=NULL;
|
struct hostent *h=NULL;
|
||||||
char *hostdataptr=NULL;
|
|
||||||
unsigned short porttouse;
|
unsigned short porttouse;
|
||||||
char myhost[256] = "";
|
char myhost[256] = "";
|
||||||
bool sa_filled_in = FALSE;
|
bool sa_filled_in = FALSE;
|
||||||
@ -1215,6 +1214,9 @@ CURLcode ftp_use_port(struct connectdata *conn)
|
|||||||
sa_filled_in = TRUE; /* the sa struct is filled in */
|
sa_filled_in = TRUE; /* the sa struct is filled in */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(h)
|
||||||
|
h->inuse--; /* when we return from here, we can forget about this */
|
||||||
|
|
||||||
if ( h || sa_filled_in) {
|
if ( h || sa_filled_in) {
|
||||||
if( (portsock = socket(AF_INET, SOCK_STREAM, 0)) >= 0 ) {
|
if( (portsock = socket(AF_INET, SOCK_STREAM, 0)) >= 0 ) {
|
||||||
int size;
|
int size;
|
||||||
@ -1250,19 +1252,16 @@ CURLcode ftp_use_port(struct connectdata *conn)
|
|||||||
|
|
||||||
if ( listen(portsock, 1) < 0 ) {
|
if ( listen(portsock, 1) < 0 ) {
|
||||||
failf(data, "listen(2) failed on socket");
|
failf(data, "listen(2) failed on socket");
|
||||||
free(hostdataptr);
|
|
||||||
return CURLE_FTP_PORT_FAILED;
|
return CURLE_FTP_PORT_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
failf(data, "bind(2) failed on socket");
|
failf(data, "bind(2) failed on socket");
|
||||||
free(hostdataptr);
|
|
||||||
return CURLE_FTP_PORT_FAILED;
|
return CURLE_FTP_PORT_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
failf(data, "socket(2) failed (%s)");
|
failf(data, "socket(2) failed (%s)");
|
||||||
free(hostdataptr);
|
|
||||||
return CURLE_FTP_PORT_FAILED;
|
return CURLE_FTP_PORT_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1332,7 +1331,7 @@ CURLcode ftp_use_pasv(struct connectdata *conn,
|
|||||||
char *buf = data->state.buffer; /* this is our buffer */
|
char *buf = data->state.buffer; /* this is our buffer */
|
||||||
int ftpcode; /* receive FTP response codes in this */
|
int ftpcode; /* receive FTP response codes in this */
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
Curl_addrinfo *addr=NULL;
|
struct Curl_dns_entry *addr=NULL;
|
||||||
Curl_ipconnect *conninfo;
|
Curl_ipconnect *conninfo;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1480,6 +1479,8 @@ CURLcode ftp_use_pasv(struct connectdata *conn,
|
|||||||
&conninfo,
|
&conninfo,
|
||||||
connected);
|
connected);
|
||||||
|
|
||||||
|
addr->inuse--; /* we're done using this address */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When this is used from the multi interface, this might've returned with
|
* When this is used from the multi interface, this might've returned with
|
||||||
* the 'connected' set to FALSE and thus we are now awaiting a non-blocking
|
* the 'connected' set to FALSE and thus we are now awaiting a non-blocking
|
||||||
|
18
lib/hash.c
18
lib/hash.c
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "llist.h"
|
#include "llist.h"
|
||||||
|
|
||||||
@ -128,7 +129,6 @@ _mk_hash_element (curl_hash_element **e, char *key, size_t key_len, const void *
|
|||||||
(*e)->key = strdup(key);
|
(*e)->key = strdup(key);
|
||||||
(*e)->key_len = key_len;
|
(*e)->key_len = key_len;
|
||||||
(*e)->ptr = (void *) p;
|
(*e)->ptr = (void *) p;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
@ -195,10 +195,10 @@ Curl_hash_delete(curl_hash *h, char *key, size_t key_len)
|
|||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ int curl_hash_find (curl_hash *, char *, size_t, void **)
|
/* {{{ int curl_hash_pick (curl_hash *, char *, size_t, void **)
|
||||||
*/
|
*/
|
||||||
int
|
void *
|
||||||
Curl_hash_find(curl_hash *h, char *key, size_t key_len, void **p)
|
Curl_hash_pick(curl_hash *h, char *key, size_t key_len)
|
||||||
{
|
{
|
||||||
curl_llist_element *le;
|
curl_llist_element *le;
|
||||||
curl_hash_element *he;
|
curl_hash_element *he;
|
||||||
@ -209,12 +209,11 @@ Curl_hash_find(curl_hash *h, char *key, size_t key_len, void **p)
|
|||||||
le = CURL_LLIST_NEXT(le)) {
|
le = CURL_LLIST_NEXT(le)) {
|
||||||
he = CURL_LLIST_VALP(le);
|
he = CURL_LLIST_VALP(le);
|
||||||
if (_hash_key_compare(he->key, he->key_len, key, key_len)) {
|
if (_hash_key_compare(he->key, he->key_len, key, key_len)) {
|
||||||
*p = he->ptr;
|
return he->ptr;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
@ -222,7 +221,7 @@ Curl_hash_find(curl_hash *h, char *key, size_t key_len, void **p)
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
Curl_hash_apply(curl_hash *h, void *user,
|
Curl_hash_apply(curl_hash *h, void *user,
|
||||||
void (*cb)(void *, curl_hash_element *))
|
void (*cb)(void *user, void *ptr))
|
||||||
{
|
{
|
||||||
curl_llist_element *le;
|
curl_llist_element *le;
|
||||||
int i;
|
int i;
|
||||||
@ -231,7 +230,8 @@ Curl_hash_apply(curl_hash *h, void *user,
|
|||||||
for (le = CURL_LLIST_HEAD(h->table[i]);
|
for (le = CURL_LLIST_HEAD(h->table[i]);
|
||||||
le != NULL;
|
le != NULL;
|
||||||
le = CURL_LLIST_NEXT(le)) {
|
le = CURL_LLIST_NEXT(le)) {
|
||||||
cb(user, (curl_hash_element *) CURL_LLIST_VALP(le));
|
curl_hash_element *el = CURL_LLIST_VALP(le);
|
||||||
|
cb(user, el->ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ typedef struct _curl_hash {
|
|||||||
typedef struct _curl_hash_element {
|
typedef struct _curl_hash_element {
|
||||||
void *ptr;
|
void *ptr;
|
||||||
char *key;
|
char *key;
|
||||||
size_t key_len;
|
size_t key_len;
|
||||||
} curl_hash_element;
|
} curl_hash_element;
|
||||||
|
|
||||||
|
|
||||||
@ -49,15 +49,14 @@ void Curl_hash_init(curl_hash *, int, curl_hash_dtor);
|
|||||||
curl_hash *Curl_hash_alloc(int, curl_hash_dtor);
|
curl_hash *Curl_hash_alloc(int, curl_hash_dtor);
|
||||||
int Curl_hash_add(curl_hash *, char *, size_t, const void *);
|
int Curl_hash_add(curl_hash *, char *, size_t, const void *);
|
||||||
int Curl_hash_delete(curl_hash *h, char *key, size_t key_len);
|
int Curl_hash_delete(curl_hash *h, char *key, size_t key_len);
|
||||||
int Curl_hash_find(curl_hash *, char *, size_t, void **p);
|
void *Curl_hash_pick(curl_hash *, char *, size_t);
|
||||||
void Curl_hash_apply(curl_hash *h, void *user, void (*cb)(void *, curl_hash_element *));
|
void Curl_hash_apply(curl_hash *h, void *user,
|
||||||
|
void (*cb)(void *user, void *ptr));
|
||||||
int Curl_hash_count(curl_hash *h);
|
int Curl_hash_count(curl_hash *h);
|
||||||
void Curl_hash_clean(curl_hash *h);
|
void Curl_hash_clean(curl_hash *h);
|
||||||
void Curl_hash_clean_with_criterium(curl_hash *h, void *user, int (*comp)(void *, void *));
|
void Curl_hash_clean_with_criterium(curl_hash *h, void *user, int (*comp)(void *, void *));
|
||||||
void Curl_hash_destroy(curl_hash *h);
|
void Curl_hash_destroy(curl_hash *h);
|
||||||
|
|
||||||
#define Curl_hash_update Curl_hash_add
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
150
lib/hostip.c
150
lib/hostip.c
@ -80,6 +80,11 @@
|
|||||||
static curl_hash hostname_cache;
|
static curl_hash hostname_cache;
|
||||||
static int host_cache_initialized;
|
static int host_cache_initialized;
|
||||||
|
|
||||||
|
static Curl_addrinfo *my_getaddrinfo(struct SessionHandle *data,
|
||||||
|
char *hostname,
|
||||||
|
int port,
|
||||||
|
char **bufp);
|
||||||
|
|
||||||
void Curl_global_host_cache_init(void)
|
void Curl_global_host_cache_init(void)
|
||||||
{
|
{
|
||||||
if (!host_cache_initialized) {
|
if (!host_cache_initialized) {
|
||||||
@ -101,11 +106,6 @@ void Curl_global_host_cache_dtor(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct curl_dns_cache_entry {
|
|
||||||
Curl_addrinfo *addr;
|
|
||||||
time_t timestamp;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* count the number of characters that an integer takes up */
|
/* count the number of characters that an integer takes up */
|
||||||
static int _num_chars(int i)
|
static int _num_chars(int i)
|
||||||
{
|
{
|
||||||
@ -129,7 +129,7 @@ static int _num_chars(int i)
|
|||||||
|
|
||||||
/* Create a hostcache id */
|
/* Create a hostcache id */
|
||||||
static char *
|
static char *
|
||||||
_create_hostcache_id(char *server, int port, ssize_t *entry_len)
|
create_hostcache_id(char *server, int port, ssize_t *entry_len)
|
||||||
{
|
{
|
||||||
char *id = NULL;
|
char *id = NULL;
|
||||||
|
|
||||||
@ -162,16 +162,19 @@ struct hostcache_prune_data {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_curl_hostcache_timestamp_remove(void *datap, void *hc)
|
hostcache_timestamp_remove(void *datap, void *hc)
|
||||||
{
|
{
|
||||||
struct hostcache_prune_data *data =
|
struct hostcache_prune_data *data =
|
||||||
(struct hostcache_prune_data *) datap;
|
(struct hostcache_prune_data *) datap;
|
||||||
struct curl_dns_cache_entry *c = (struct curl_dns_cache_entry *) hc;
|
struct Curl_dns_entry *c = (struct Curl_dns_entry *) hc;
|
||||||
|
|
||||||
if (data->now - c->timestamp < data->cache_timeout) {
|
if ((data->now - c->timestamp < data->cache_timeout) ||
|
||||||
|
c->inuse) {
|
||||||
|
/* please don't remove */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* fine, remove */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,14 +188,30 @@ hostcache_prune(curl_hash *hostcache, int cache_timeout, int now)
|
|||||||
|
|
||||||
Curl_hash_clean_with_criterium(hostcache,
|
Curl_hash_clean_with_criterium(hostcache,
|
||||||
(void *) &user,
|
(void *) &user,
|
||||||
_curl_hostcache_timestamp_remove);
|
hostcache_timestamp_remove);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MALLOCDEBUG
|
||||||
|
/* Called from Curl_done() to check that there's no DNS cache entry with
|
||||||
|
a non-zero counter left. */
|
||||||
|
void Curl_scan_cache_used(void *user, void *ptr)
|
||||||
|
{
|
||||||
|
struct Curl_dns_entry *e = ptr;
|
||||||
|
(void)user; /* prevent compiler warning */
|
||||||
|
if(e->inuse) {
|
||||||
|
fprintf(stderr, "*** WARNING: locked DNS cache entry detected: %s\n",
|
||||||
|
e->entry_id);
|
||||||
|
/* perform a segmentation fault to draw attention */
|
||||||
|
*(void **)0 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Macro to save redundant free'ing of entry_id */
|
/* Macro to save redundant free'ing of entry_id */
|
||||||
#define _hostcache_return(__v) \
|
#define HOSTCACHE_RETURN(dns) \
|
||||||
{ \
|
{ \
|
||||||
free(entry_id); \
|
free(entry_id); \
|
||||||
return (__v); \
|
return dns; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SIGSETJMP
|
#ifdef HAVE_SIGSETJMP
|
||||||
@ -200,72 +219,69 @@ hostcache_prune(curl_hash *hostcache, int cache_timeout, int now)
|
|||||||
sigjmp_buf curl_jmpenv;
|
sigjmp_buf curl_jmpenv;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Curl_addrinfo *Curl_resolv(struct SessionHandle *data,
|
struct Curl_dns_entry *Curl_resolv(struct SessionHandle *data,
|
||||||
char *hostname,
|
char *hostname,
|
||||||
int port)
|
int port)
|
||||||
{
|
{
|
||||||
char *entry_id = NULL;
|
char *entry_id = NULL;
|
||||||
struct curl_dns_cache_entry *p = NULL;
|
struct Curl_dns_entry *dns = NULL;
|
||||||
ssize_t entry_len;
|
ssize_t entry_len;
|
||||||
time_t now;
|
time_t now;
|
||||||
char *bufp;
|
char *bufp;
|
||||||
|
|
||||||
#ifdef HAVE_SIGSETJMP
|
#ifdef HAVE_SIGSETJMP
|
||||||
if(sigsetjmp(curl_jmpenv, 1) != 0) {
|
/* this allows us to time-out from the name resolver, as the timeout
|
||||||
|
will generate a signal and we will siglongjmp() from that here */
|
||||||
|
if(!data->set.no_signal && sigsetjmp(curl_jmpenv, 1)) {
|
||||||
/* this is coming from a siglongjmp() */
|
/* this is coming from a siglongjmp() */
|
||||||
failf(data, "name lookup time-outed");
|
failf(data, "name lookup time-outed");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
/* Create an entry id, based upon the hostname and port */
|
||||||
/* If the host cache timeout is 0, we don't do DNS cach'ing
|
entry_len = strlen(hostname);
|
||||||
so fall through */
|
entry_id = create_hostcache_id(hostname, port, &entry_len);
|
||||||
if (data->set.dns_cache_timeout == 0) {
|
/* If we can't create the entry id, fail */
|
||||||
return Curl_getaddrinfo(data, hostname, port, &bufp);
|
if (!entry_id)
|
||||||
}
|
return NULL;
|
||||||
#endif
|
|
||||||
|
|
||||||
|
/* See if its already in our dns cache */
|
||||||
|
dns = Curl_hash_pick(data->hostcache, entry_id, entry_len+1);
|
||||||
|
|
||||||
|
if (!dns) {
|
||||||
|
Curl_addrinfo *addr = my_getaddrinfo(data, hostname, port, &bufp);
|
||||||
|
|
||||||
|
if (!addr) {
|
||||||
|
HOSTCACHE_RETURN(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a new cache entry */
|
||||||
|
dns = (struct Curl_dns_entry *) malloc(sizeof(struct Curl_dns_entry));
|
||||||
|
if (!dns) {
|
||||||
|
Curl_freeaddrinfo(addr);
|
||||||
|
HOSTCACHE_RETURN(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
dns->inuse = 0;
|
||||||
|
dns->addr = addr;
|
||||||
|
/* Save it in our host cache */
|
||||||
|
Curl_hash_add(data->hostcache, entry_id, entry_len+1, (const void *) dns);
|
||||||
|
}
|
||||||
time(&now);
|
time(&now);
|
||||||
|
|
||||||
/* Remove outdated entries from the hostcache */
|
dns->timestamp = now;
|
||||||
|
dns->inuse++; /* mark entry as in-use */
|
||||||
|
#ifdef MALLOCDEBUG
|
||||||
|
dns->entry_id = entry_id;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Remove outdated and unused entries from the hostcache */
|
||||||
hostcache_prune(data->hostcache,
|
hostcache_prune(data->hostcache,
|
||||||
data->set.dns_cache_timeout,
|
data->set.dns_cache_timeout,
|
||||||
now);
|
now);
|
||||||
|
|
||||||
/* Create an entry id, based upon the hostname and port */
|
HOSTCACHE_RETURN(dns);
|
||||||
entry_len = strlen(hostname);
|
|
||||||
entry_id = _create_hostcache_id(hostname, port, &entry_len);
|
|
||||||
/* If we can't create the entry id, don't cache, just fall-through
|
|
||||||
to the plain Curl_getaddrinfo() */
|
|
||||||
if (!entry_id) {
|
|
||||||
return Curl_getaddrinfo(data, hostname, port, &bufp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* See if its already in our dns cache */
|
|
||||||
if (entry_id &&
|
|
||||||
Curl_hash_find(data->hostcache, entry_id, entry_len+1, (void **) &p)) {
|
|
||||||
_hostcache_return(p->addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create a new cache entry */
|
|
||||||
p = (struct curl_dns_cache_entry *)
|
|
||||||
malloc(sizeof(struct curl_dns_cache_entry));
|
|
||||||
if (!p) {
|
|
||||||
_hostcache_return(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
p->addr = Curl_getaddrinfo(data, hostname, port, &bufp);
|
|
||||||
if (!p->addr) {
|
|
||||||
free(p);
|
|
||||||
_hostcache_return(NULL);
|
|
||||||
}
|
|
||||||
p->timestamp = now;
|
|
||||||
|
|
||||||
/* Save it in our host cache */
|
|
||||||
Curl_hash_update(data->hostcache, entry_id, entry_len+1, (const void *) p);
|
|
||||||
|
|
||||||
_hostcache_return(p->addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -275,7 +291,7 @@ Curl_addrinfo *Curl_resolv(struct SessionHandle *data,
|
|||||||
*/
|
*/
|
||||||
void Curl_freeaddrinfo(void *freethis)
|
void Curl_freeaddrinfo(void *freethis)
|
||||||
{
|
{
|
||||||
struct curl_dns_cache_entry *p = (struct curl_dns_cache_entry *) freethis;
|
struct Curl_dns_entry *p = (struct Curl_dns_entry *) freethis;
|
||||||
|
|
||||||
#ifdef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
freeaddrinfo(p->addr);
|
freeaddrinfo(p->addr);
|
||||||
@ -333,10 +349,10 @@ void curl_freeaddrinfo(struct addrinfo *freethis,
|
|||||||
* memory we need to free after use. That meory *MUST* be freed with
|
* memory we need to free after use. That meory *MUST* be freed with
|
||||||
* Curl_freeaddrinfo(), nothing else.
|
* Curl_freeaddrinfo(), nothing else.
|
||||||
*/
|
*/
|
||||||
Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
|
static Curl_addrinfo *my_getaddrinfo(struct SessionHandle *data,
|
||||||
char *hostname,
|
char *hostname,
|
||||||
int port,
|
int port,
|
||||||
char **bufp)
|
char **bufp)
|
||||||
{
|
{
|
||||||
struct addrinfo hints, *res;
|
struct addrinfo hints, *res;
|
||||||
int error;
|
int error;
|
||||||
@ -509,10 +525,10 @@ static void hostcache_fixoffset(struct hostent *h, int offset)
|
|||||||
/* The original code to this function was once stolen from the Dancer source
|
/* The original code to this function was once stolen from the Dancer source
|
||||||
code, written by Bjorn Reese, it has since been patched and modified
|
code, written by Bjorn Reese, it has since been patched and modified
|
||||||
considerably. */
|
considerably. */
|
||||||
Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
|
static Curl_addrinfo *my_getaddrinfo(struct SessionHandle *data,
|
||||||
char *hostname,
|
char *hostname,
|
||||||
int port,
|
int port,
|
||||||
char **bufp)
|
char **bufp)
|
||||||
{
|
{
|
||||||
struct hostent *h = NULL;
|
struct hostent *h = NULL;
|
||||||
in_addr_t in;
|
in_addr_t in;
|
||||||
|
25
lib/hostip.h
25
lib/hostip.h
@ -23,6 +23,7 @@
|
|||||||
* $Id$
|
* $Id$
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "setup.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
|
|
||||||
struct addrinfo;
|
struct addrinfo;
|
||||||
@ -35,15 +36,23 @@ curl_hash *Curl_global_host_cache_get(void);
|
|||||||
|
|
||||||
#define Curl_global_host_cache_use(__p) ((__p)->set.global_dns_cache)
|
#define Curl_global_host_cache_use(__p) ((__p)->set.global_dns_cache)
|
||||||
|
|
||||||
Curl_addrinfo *Curl_resolv(struct SessionHandle *data,
|
struct Curl_dns_entry {
|
||||||
char *hostname,
|
Curl_addrinfo *addr;
|
||||||
int port);
|
time_t timestamp;
|
||||||
|
long inuse; /* use-counter, make very sure you decrease this
|
||||||
|
when you're done using the address you received */
|
||||||
|
#ifdef MALLOCDEBUG
|
||||||
|
char *entry_id;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Curl_dns_entry *Curl_resolv(struct SessionHandle *data,
|
||||||
|
char *hostname,
|
||||||
|
int port);
|
||||||
|
|
||||||
|
/* for debugging purposes only: */
|
||||||
|
void Curl_scan_cache_used(void *user, void *ptr);
|
||||||
|
|
||||||
/* Get name info */
|
|
||||||
Curl_addrinfo *Curl_getaddrinfo(struct SessionHandle *data,
|
|
||||||
char *hostname,
|
|
||||||
int port,
|
|
||||||
char **bufp);
|
|
||||||
/* free name info */
|
/* free name info */
|
||||||
void Curl_freeaddrinfo(void *freethis);
|
void Curl_freeaddrinfo(void *freethis);
|
||||||
|
|
||||||
|
34
lib/url.c
34
lib/url.c
@ -1484,18 +1484,23 @@ static int handleSock5Proxy(
|
|||||||
socksreq[3] = 1; /* IPv4 = 1 */
|
socksreq[3] = 1; /* IPv4 = 1 */
|
||||||
|
|
||||||
{
|
{
|
||||||
Curl_addrinfo *hp;
|
#ifndef ENABLE_IPV6
|
||||||
hp = Curl_resolv(conn->data, conn->hostname, conn->remote_port);
|
struct Curl_dns_entry *dns;
|
||||||
|
Curl_addrinfo *hp=NULL;
|
||||||
|
dns = Curl_resolv(conn->data, conn->hostname, conn->remote_port);
|
||||||
/*
|
/*
|
||||||
* We cannot use 'hostent' as a struct that Curl_resolv() returns. It
|
* We cannot use 'hostent' as a struct that Curl_resolv() returns. It
|
||||||
* returns a Curl_addrinfo pointer that may not always look the same.
|
* returns a Curl_addrinfo pointer that may not always look the same.
|
||||||
*/
|
*/
|
||||||
#ifndef ENABLE_IPV6
|
if(dns)
|
||||||
|
hp=dns->addr;
|
||||||
if (hp && hp->h_addr_list[0]) {
|
if (hp && hp->h_addr_list[0]) {
|
||||||
socksreq[4] = ((char*)hp->h_addr_list[0])[0];
|
socksreq[4] = ((char*)hp->h_addr_list[0])[0];
|
||||||
socksreq[5] = ((char*)hp->h_addr_list[0])[1];
|
socksreq[5] = ((char*)hp->h_addr_list[0])[1];
|
||||||
socksreq[6] = ((char*)hp->h_addr_list[0])[2];
|
socksreq[6] = ((char*)hp->h_addr_list[0])[2];
|
||||||
socksreq[7] = ((char*)hp->h_addr_list[0])[3];
|
socksreq[7] = ((char*)hp->h_addr_list[0])[3];
|
||||||
|
|
||||||
|
dns->inuse--; /* not used anymore from now on */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
failf(conn->data, "Failed to resolve \"%s\" for SOCKS5 connect.",
|
failf(conn->data, "Failed to resolve \"%s\" for SOCKS5 connect.",
|
||||||
@ -1548,7 +1553,7 @@ static int handleSock5Proxy(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode ConnectPlease(struct connectdata *conn,
|
static CURLcode ConnectPlease(struct connectdata *conn,
|
||||||
Curl_addrinfo *hostaddr,
|
struct Curl_dns_entry *hostaddr,
|
||||||
bool *connected)
|
bool *connected)
|
||||||
{
|
{
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
@ -1567,6 +1572,8 @@ static CURLcode ConnectPlease(struct connectdata *conn,
|
|||||||
/* All is cool, then we store the current information from the hostaddr
|
/* All is cool, then we store the current information from the hostaddr
|
||||||
struct to the serv_addr, as it might be needed later. The address
|
struct to the serv_addr, as it might be needed later. The address
|
||||||
returned from the function above is crucial here. */
|
returned from the function above is crucial here. */
|
||||||
|
conn->connect_addr = hostaddr;
|
||||||
|
|
||||||
#ifdef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
conn->serv_addr = addr;
|
conn->serv_addr = addr;
|
||||||
#else
|
#else
|
||||||
@ -1597,7 +1604,7 @@ static CURLcode ConnectPlease(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void verboseconnect(struct connectdata *conn,
|
static void verboseconnect(struct connectdata *conn,
|
||||||
Curl_addrinfo *hostaddr)
|
struct Curl_dns_entry *dns)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_INET_NTOA_R
|
#ifdef HAVE_INET_NTOA_R
|
||||||
char ntoa_buf[64];
|
char ntoa_buf[64];
|
||||||
@ -1606,7 +1613,7 @@ static void verboseconnect(struct connectdata *conn,
|
|||||||
|
|
||||||
/* Figure out the ip-number and display the first host name it shows: */
|
/* Figure out the ip-number and display the first host name it shows: */
|
||||||
#ifdef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
(void)hostaddr; /* not used in the IPv6 enabled version */
|
(void)dns; /* not used in the IPv6 enabled version */
|
||||||
{
|
{
|
||||||
char hbuf[NI_MAXHOST];
|
char hbuf[NI_MAXHOST];
|
||||||
#ifdef NI_WITHSCOPEID
|
#ifdef NI_WITHSCOPEID
|
||||||
@ -1629,6 +1636,7 @@ static void verboseconnect(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
|
Curl_addrinfo *hostaddr=dns->addr;
|
||||||
struct in_addr in;
|
struct in_addr in;
|
||||||
(void) memcpy(&in.s_addr, &conn->serv_addr.sin_addr, sizeof (in.s_addr));
|
(void) memcpy(&in.s_addr, &conn->serv_addr.sin_addr, sizeof (in.s_addr));
|
||||||
infof(data, "Connected to %s (%s) port %d\n",
|
infof(data, "Connected to %s (%s) port %d\n",
|
||||||
@ -1654,7 +1662,7 @@ static void verboseconnect(struct connectdata *conn,
|
|||||||
* 'serv_addr' field in the connectdata struct for most of it.
|
* 'serv_addr' field in the connectdata struct for most of it.
|
||||||
*/
|
*/
|
||||||
CURLcode Curl_protocol_connect(struct connectdata *conn,
|
CURLcode Curl_protocol_connect(struct connectdata *conn,
|
||||||
Curl_addrinfo *hostaddr)
|
struct Curl_dns_entry *hostaddr)
|
||||||
{
|
{
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
CURLcode result=CURLE_OK;
|
CURLcode result=CURLE_OK;
|
||||||
@ -1689,7 +1697,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
struct connectdata *conn;
|
struct connectdata *conn;
|
||||||
struct connectdata *conn_temp;
|
struct connectdata *conn_temp;
|
||||||
int urllen;
|
int urllen;
|
||||||
Curl_addrinfo *hostaddr;
|
struct Curl_dns_entry *hostaddr;
|
||||||
#ifdef HAVE_ALARM
|
#ifdef HAVE_ALARM
|
||||||
unsigned int prev_alarm=0;
|
unsigned int prev_alarm=0;
|
||||||
#endif
|
#endif
|
||||||
@ -2811,7 +2819,6 @@ CURLcode Curl_connect(struct SessionHandle *data,
|
|||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CURLcode Curl_done(struct connectdata *conn)
|
CURLcode Curl_done(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
struct SessionHandle *data=conn->data;
|
struct SessionHandle *data=conn->data;
|
||||||
@ -2830,6 +2837,15 @@ CURLcode Curl_done(struct connectdata *conn)
|
|||||||
conn->newurl = NULL;
|
conn->newurl = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(conn->connect_addr)
|
||||||
|
conn->connect_addr->inuse--; /* done with this */
|
||||||
|
|
||||||
|
#ifdef MALLOCDEBUG
|
||||||
|
/* scan for DNS cache entries still marked as in use */
|
||||||
|
Curl_hash_apply(data->hostcache,
|
||||||
|
NULL, Curl_scan_cache_used);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* this calls the protocol-specific function pointer previously set */
|
/* this calls the protocol-specific function pointer previously set */
|
||||||
if(conn->curl_done)
|
if(conn->curl_done)
|
||||||
result = conn->curl_done(conn);
|
result = conn->curl_done(conn);
|
||||||
|
@ -36,5 +36,5 @@ CURLcode Curl_do_more(struct connectdata *);
|
|||||||
CURLcode Curl_done(struct connectdata *);
|
CURLcode Curl_done(struct connectdata *);
|
||||||
CURLcode Curl_disconnect(struct connectdata *);
|
CURLcode Curl_disconnect(struct connectdata *);
|
||||||
CURLcode Curl_protocol_connect(struct connectdata *conn,
|
CURLcode Curl_protocol_connect(struct connectdata *conn,
|
||||||
Curl_addrinfo *hostaddr);
|
struct Curl_dns_entry *dns);
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,8 +26,6 @@
|
|||||||
/* This file is for lib internal stuff */
|
/* This file is for lib internal stuff */
|
||||||
|
|
||||||
#include "setup.h"
|
#include "setup.h"
|
||||||
#include "hostip.h"
|
|
||||||
#include "hash.h"
|
|
||||||
|
|
||||||
#define PORT_FTP 21
|
#define PORT_FTP 21
|
||||||
#define PORT_TELNET 23
|
#define PORT_TELNET 23
|
||||||
@ -81,6 +79,8 @@
|
|||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
#include "http_chunks.h" /* for the structs and enum stuff */
|
#include "http_chunks.h" /* for the structs and enum stuff */
|
||||||
|
#include "hostip.h"
|
||||||
|
#include "hash.h"
|
||||||
|
|
||||||
#ifdef HAVE_ZLIB_H
|
#ifdef HAVE_ZLIB_H
|
||||||
#include <zlib.h> /* for content-encoding 08/28/02 jhrg */
|
#include <zlib.h> /* for content-encoding 08/28/02 jhrg */
|
||||||
@ -311,8 +311,11 @@ struct connectdata {
|
|||||||
#define PROT_FTPS (1<<9)
|
#define PROT_FTPS (1<<9)
|
||||||
#define PROT_SSL (1<<10) /* protocol requires SSL */
|
#define PROT_SSL (1<<10) /* protocol requires SSL */
|
||||||
|
|
||||||
|
/* the particular host we use, in two different ways */
|
||||||
|
struct Curl_dns_entry *connect_addr;
|
||||||
|
|
||||||
#ifdef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
struct addrinfo *serv_addr; /* the particular host we use */
|
struct addrinfo *serv_addr;
|
||||||
#else
|
#else
|
||||||
struct sockaddr_in serv_addr;
|
struct sockaddr_in serv_addr;
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user