diff --git a/lib/connect.c b/lib/connect.c index 5da4ac996..cd024edde 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -330,7 +330,6 @@ static CURLcode bindlocal(struct connectdata *conn, Curl_resolv_unlock(data, h); /* we don't need it anymore after this function has returned */ -#ifdef ENABLE_IPV6 if( bind(sockfd, addr->ai_addr, addr->ai_addrlen) >= 0) { /* we succeeded to bind */ struct sockaddr_in6 add; @@ -344,31 +343,7 @@ static CURLcode bindlocal(struct connectdata *conn, return CURLE_HTTP_PORT_FAILED; } } -#else - { - struct sockaddr_in sa; - memset((char *)&sa, 0, sizeof(sa)); - memcpy((char *)&sa.sin_addr, addr->h_addr, addr->h_length); - sa.sin_family = AF_INET; - sa.sin_addr.s_addr = in; - sa.sin_port = 0; /* get any port */ - - if( bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) >= 0) { - /* we succeeded to bind */ - struct sockaddr_in add; - - bindworked = TRUE; - - size = sizeof(add); - if(getsockname(sockfd, (struct sockaddr *) &add, - (socklen_t *)&size)<0) { - failf(data, "getsockname() failed"); - return CURLE_HTTP_PORT_FAILED; - } - } - } -#endif if(!bindworked) { failf(data, "%s", Curl_strerror(conn, Curl_ourerrno())); return CURLE_HTTP_PORT_FAILED; @@ -540,9 +515,8 @@ static void tcpnodelay(struct connectdata *conn, CURLcode Curl_connecthost(struct connectdata *conn, /* context */ struct Curl_dns_entry *remotehost, /* use this one */ - int port, /* connect to this */ curl_socket_t *sockconn, /* the connected socket */ - Curl_ipconnect **addr, /* the one we used */ + Curl_addrinfo **addr, /* the one we used */ bool *connected) /* really connected? */ { struct SessionHandle *data = conn->data; @@ -552,8 +526,9 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ int num_addr; bool conected; char addr_buf[256]; + Curl_addrinfo *ai; + Curl_addrinfo *curr_addr; - Curl_ipconnect *curr_addr; struct timeval after; struct timeval before = Curl_tvnow(); @@ -601,17 +576,18 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ num_addr = Curl_num_addresses(remotehost->addr); timeout_per_addr = timeout_ms / num_addr; + ai = remotehost->addr; + /* Below is the loop that attempts to connect to all IP-addresses we * know for the given host. One by one until one IP succeedes. */ -#ifdef ENABLE_IPV6 + /* * Connecting with a getaddrinfo chain */ - (void)port; /* the port number is already included in the getaddrinfo - struct */ - for (curr_addr = remotehost->addr, aliasindex=0; curr_addr; + for (curr_addr = ai, aliasindex=0; curr_addr; curr_addr = curr_addr->ai_next, aliasindex++) { + sockfd = socket(curr_addr->ai_family, curr_addr->ai_socktype, curr_addr->ai_protocol); if (sockfd == CURL_SOCKET_BAD) { @@ -619,31 +595,6 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ continue; } -#else - /* - * Connecting with old style IPv4-only support - */ - curr_addr = (Curl_ipconnect*)remotehost->addr->h_addr_list[0]; - for(aliasindex=0; curr_addr; - curr_addr=(Curl_ipconnect*)remotehost->addr->h_addr_list[++aliasindex]) { - struct sockaddr_in serv_addr; - - /* create an IPv4 TCP socket */ - sockfd = socket(AF_INET, SOCK_STREAM, 0); - if(CURL_SOCKET_BAD == sockfd) { - failf(data, "couldn't create socket"); - return CURLE_COULDNT_CONNECT; /* big time error */ - } - - /* nasty address work before connect can be made */ - memset((char *) &serv_addr, '\0', sizeof(serv_addr)); - memcpy((char *)&(serv_addr.sin_addr), curr_addr, - sizeof(struct in_addr)); - serv_addr.sin_family = remotehost->addr->h_addrtype; - serv_addr.sin_port = htons((unsigned short)port); -#endif - - Curl_printable_address(curr_addr, addr_buf, sizeof(addr_buf)); infof(data, " Trying %s... ", addr_buf); @@ -664,11 +615,8 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */ /* do not use #ifdef within the function arguments below, as connect() is a defined macro on some platforms and some compilers don't like to mix #ifdefs with macro usage! (AmigaOS is one such platform) */ -#ifdef ENABLE_IPV6 + rc = connect(sockfd, curr_addr->ai_addr, curr_addr->ai_addrlen); -#else - rc = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); -#endif if(-1 == rc) { error = Curl_ourerrno(); diff --git a/lib/connect.h b/lib/connect.h index bccb84387..bf46ed348 100644 --- a/lib/connect.h +++ b/lib/connect.h @@ -32,9 +32,8 @@ CURLcode Curl_is_connected(struct connectdata *conn, CURLcode Curl_connecthost(struct connectdata *conn, struct Curl_dns_entry *host, /* connect to this */ - int port, /* connect to this port number */ curl_socket_t *sockconn, /* not set if error */ - Curl_ipconnect **addr, /* the one we used */ + Curl_addrinfo **addr, /* the one we used */ bool *connected /* truly connected? */ ); diff --git a/lib/easy.c b/lib/easy.c index b007b97ed..8371afbae 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -1,8 +1,8 @@ /*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. @@ -10,7 +10,7 @@ * 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. @@ -96,36 +96,36 @@ static void win32_cleanup(void) stack to allow networking */ static CURLcode win32_init(void) { - WORD wVersionRequested; - WSADATA wsaData; - int err; + WORD wVersionRequested; + WSADATA wsaData; + int err; #ifdef ENABLE_IPV6 wVersionRequested = MAKEWORD(2, 0); #else wVersionRequested = MAKEWORD(1, 1); #endif - - err = WSAStartup(wVersionRequested, &wsaData); - - if (err != 0) - /* Tell the user that we couldn't find a useable */ - /* winsock.dll. */ - return CURLE_FAILED_INIT; - - /* Confirm that the Windows Sockets DLL supports what we need.*/ - /* Note that if the DLL supports versions greater */ - /* than wVersionRequested, it will still return */ + + err = WSAStartup(wVersionRequested, &wsaData); + + if (err != 0) + /* Tell the user that we couldn't find a useable */ + /* winsock.dll. */ + return CURLE_FAILED_INIT; + + /* Confirm that the Windows Sockets DLL supports what we need.*/ + /* Note that if the DLL supports versions greater */ + /* than wVersionRequested, it will still return */ /* wVersionRequested in wVersion. wHighVersion contains the */ /* highest supported version. */ - if ( LOBYTE( wsaData.wVersion ) != LOBYTE(wVersionRequested) || - HIBYTE( wsaData.wVersion ) != HIBYTE(wVersionRequested) ) { - /* Tell the user that we couldn't find a useable */ + if ( LOBYTE( wsaData.wVersion ) != LOBYTE(wVersionRequested) || + HIBYTE( wsaData.wVersion ) != HIBYTE(wVersionRequested) ) { + /* Tell the user that we couldn't find a useable */ - /* winsock.dll. */ - WSACleanup(); - return CURLE_FAILED_INIT; + /* winsock.dll. */ + WSACleanup(); + return CURLE_FAILED_INIT; } /* The Windows Sockets DLL is acceptable. Proceed. */ return CURLE_OK; @@ -207,7 +207,7 @@ CURLcode curl_global_init(long flags) initialized = 1; init_flags = flags; - + return CURLE_OK; } @@ -292,7 +292,7 @@ CURL *curl_easy_init(void) return data; } -/* +/* * curl_easy_setopt() is the external interface for setting options on an * easy handle. */ @@ -373,9 +373,9 @@ CURLcode curl_easy_perform(CURL *curl) screwed up and we should bail out! */ return CURLE_OUT_OF_MEMORY; } - + } - + return Curl_perform(data); } diff --git a/lib/formdata.c b/lib/formdata.c index ea5c4acd8..c338052da 100644 --- a/lib/formdata.c +++ b/lib/formdata.c @@ -1426,60 +1426,6 @@ int main() #endif -#ifdef _OLD_FORM_DEBUG - -int main(int argc, char **argv) -{ -#if 0 - char *testargs[]={ - "name1 = data in number one", - "name2 = number two data", - "test = @upload" - }; -#endif - int i; - char *nextarg; - struct curl_httppost *httppost=NULL; - struct curl_httppost *last_post=NULL; - struct curl_httppost *post; - int size; - int nread; - char buffer[4096]; - - struct FormData *form; - struct Form formread; - - for(i=1; idata, "Connecting to %s (%s) port %u\n", - answer?answer->h_name:newhost, -#if defined(HAVE_INET_NTOA_R) - inet_ntoa_r(in, ntoa_buf, sizeof(ntoa_buf)), -#else - inet_ntoa(in), -#endif - port); - -#else - /***************************************************************** - * - * IPv6-only code section - */ - char hbuf[NI_MAXHOST]; /* ~1KB */ - char nbuf[NI_MAXHOST]; /* ~1KB */ - char sbuf[NI_MAXSERV]; /* around 32 */ - (void)port; /* prevent compiler warning */ - if (getnameinfo(addr->ai_addr, addr->ai_addrlen, - nbuf, sizeof(nbuf), sbuf, sizeof(sbuf), NIFLAGS)) { - snprintf(nbuf, sizeof(nbuf), "?"); - snprintf(sbuf, sizeof(sbuf), "?"); - } - - if (getnameinfo(addr->ai_addr, addr->ai_addrlen, - hbuf, sizeof(hbuf), NULL, 0, 0)) { - infof(conn->data, "Connecting to %s (%s) port %s\n", nbuf, newhost, sbuf); - } - else { - infof(conn->data, "Connecting to %s (%s) port %s\n", hbuf, nbuf, sbuf); - } -#endif + char buf[256]; + Curl_printable_address(ai, buf, sizeof(buf)); + infof(conn->data, "Connecting to %s (%s) port %d\n", newhost, buf, port); } /*********************************************************************** @@ -1381,36 +1274,44 @@ CURLcode ftp_use_port(struct connectdata *conn) * */ struct sockaddr_in sa; - struct Curl_dns_entry *h=NULL; unsigned short porttouse; char myhost[256] = ""; bool sa_filled_in = FALSE; + Curl_addrinfo *addr = NULL; + unsigned short ip[4]; if(data->set.ftpport) { in_addr_t in; - int rc; /* First check if the given name is an IP address */ in=inet_addr(data->set.ftpport); - if((in == CURL_INADDR_NONE) && - Curl_if2ip(data->set.ftpport, myhost, sizeof(myhost))) { - rc = Curl_resolv(conn, myhost, 0, &h); - if(rc == CURLRESOLV_PENDING) - rc = Curl_wait_for_resolv(conn, &h); - } + if(in != CURL_INADDR_NONE) + /* this is an IPv4 address */ + addr = Curl_ip2addr(in, data->set.ftpport, 0); else { - size_t len = strlen(data->set.ftpport); - if(len>1) { - rc = Curl_resolv(conn, data->set.ftpport, 0, &h); + if(Curl_if2ip(data->set.ftpport, myhost, sizeof(myhost))) { + /* The interface to IP conversion provided a dotted address */ + in=inet_addr(myhost); + addr = Curl_ip2addr(in, myhost, 0); + } + else if(strlen(data->set.ftpport)> 1) { + /* might be a host name! */ + struct Curl_dns_entry *h=NULL; + int rc = Curl_resolv(conn, myhost, 0, &h); if(rc == CURLRESOLV_PENDING) rc = Curl_wait_for_resolv(conn, &h); - } - if(h) - strcpy(myhost, data->set.ftpport); /* buffer overflow risk */ - } - } - if(! *myhost) { + if(h) { + addr = h->addr; + /* when we return from this function, we can forget about this entry + to we can unlock it now already */ + Curl_resolv_unlock(data, h); + } /* (h) */ + } /* strlen */ + } /* CURL_INADDR_NONE */ + } /* data->set.ftpport */ + + if(!addr) { /* pick a suitable default here */ socklen_t sslen; @@ -1425,12 +1326,9 @@ CURLcode ftp_use_port(struct connectdata *conn) sa_filled_in = TRUE; /* the sa struct is filled in */ } - if(h) - /* when we return from here, we can forget about this */ - Curl_resolv_unlock(data, h); - - if ( h || sa_filled_in) { - if( (portsock = socket(AF_INET, SOCK_STREAM, 0)) != CURL_SOCKET_BAD ) { + if (addr || sa_filled_in) { + portsock = socket(AF_INET, SOCK_STREAM, 0); + if(CURL_SOCKET_BAD != portsock) { int size; /* we set the secondary socket variable to this for now, it @@ -1439,11 +1337,7 @@ CURLcode ftp_use_port(struct connectdata *conn) conn->sock[SECONDARYSOCKET] = portsock; if(!sa_filled_in) { - memset((char *)&sa, 0, sizeof(sa)); - memcpy((char *)&sa.sin_addr, - h->addr->h_addr, - h->addr->h_length); - sa.sin_family = AF_INET; + memcpy(&sa, addr->ai_addr, sizeof(sa)); sa.sin_addr.s_addr = INADDR_ANY; } @@ -1478,29 +1372,19 @@ CURLcode ftp_use_port(struct connectdata *conn) } } else { - failf(data, "could't find my own IP address (%s)", myhost); + failf(data, "could't find IP address to use"); return CURLE_FTP_PORT_FAILED; } - { -#ifdef HAVE_INET_NTOA_R - char ntoa_buf[64]; -#endif - struct in_addr in; - unsigned short ip[5]; - (void) memcpy(&in.s_addr, - h?*h->addr->h_addr_list:(char *)&sa.sin_addr.s_addr, - sizeof (in.s_addr)); -#ifdef HAVE_INET_NTOA_R - /* ignore the return code from inet_ntoa_r() as it is int or - char * depending on system */ - inet_ntoa_r(in, ntoa_buf, sizeof(ntoa_buf)); - sscanf( ntoa_buf, "%hu.%hu.%hu.%hu", - &ip[0], &ip[1], &ip[2], &ip[3]); -#else - sscanf( inet_ntoa(in), "%hu.%hu.%hu.%hu", - &ip[0], &ip[1], &ip[2], &ip[3]); -#endif + if(sa_filled_in) + Curl_inet_ntop(AF_INET, &((struct sockaddr_in *)&sa)->sin_addr, + myhost, sizeof(myhost)); + else + Curl_printable_address(addr, myhost, sizeof(myhost)); + + if(4 == sscanf(myhost, "%hu.%hu.%hu.%hu", + &ip[0], &ip[1], &ip[2], &ip[3])) { + infof(data, "Telling server to connect to %d.%d.%d.%d:%d\n", ip[0], ip[1], ip[2], ip[3], porttouse); @@ -1510,7 +1394,12 @@ CURLcode ftp_use_port(struct connectdata *conn) porttouse & 255); if(result) return result; + } + else + return CURLE_FTP_PORT_FAILED; + + Curl_freeaddrinfo(addr); result = Curl_GetFTPResponse(&nread, conn, &ftpcode); if(result) @@ -1544,7 +1433,7 @@ CURLcode ftp_use_pasv(struct connectdata *conn, int ftpcode; /* receive FTP response codes in this */ CURLcode result; struct Curl_dns_entry *addr=NULL; - Curl_ipconnect *conninfo; + Curl_addrinfo *conninfo; int rc; /* @@ -1693,7 +1582,6 @@ CURLcode ftp_use_pasv(struct connectdata *conn, result = Curl_connecthost(conn, addr, - connectport, &conn->sock[SECONDARYSOCKET], &conninfo, connected); diff --git a/lib/hash.c b/lib/hash.c index f33d91dc8..be841b3fe 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -1,8 +1,8 @@ /*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. @@ -10,7 +10,7 @@ * 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. @@ -47,7 +47,7 @@ hash_str(const char *key, size_t key_length) return h; } -static void +static void hash_element_dtor(void *user, void *element) { curl_hash *h = (curl_hash *) user; @@ -70,7 +70,7 @@ Curl_hash_init(curl_hash *h, int slots, curl_hash_dtor dtor) h->dtor = dtor; h->size = 0; - h->slots = slots; + h->slots = slots; h->table = (curl_llist **) malloc(slots * sizeof(curl_llist *)); if(h->table) { @@ -106,10 +106,10 @@ Curl_hash_alloc(int slots, curl_hash_dtor dtor) return h; } -static int +static int hash_key_compare(char *key1, size_t key1_len, char *key2, size_t key2_len) { - if (key1_len == key2_len && + if (key1_len == key2_len && *key1 == *key2 && memcmp(key1, key2, key1_len) == 0) { return 1; @@ -180,29 +180,6 @@ Curl_hash_add(curl_hash *h, char *key, size_t key_len, void *p) return NULL; /* failure */ } -#if 0 -int -Curl_hash_delete(curl_hash *h, char *key, size_t key_len) -{ - curl_hash_element *he; - curl_llist_element *le; - curl_llist *l = FETCH_LIST(h, key, key_len); - - for (le = l->head; - le; - le = le->next) { - he = le->ptr; - if (hash_key_compare(he->key, he->key_len, key, key_len)) { - Curl_llist_remove(l, le, (void *) h); - --h->size; - return 1; - } - } - - return 0; -} -#endif - void * Curl_hash_pick(curl_hash *h, char *key, size_t key_len) { @@ -223,7 +200,7 @@ Curl_hash_pick(curl_hash *h, char *key, size_t key_len) } #if defined(CURLDEBUG) && defined(AGGRESIVE_TEST) -void +void Curl_hash_apply(curl_hash *h, void *user, void (*cb)(void *user, void *ptr)) { @@ -278,15 +255,7 @@ Curl_hash_clean_with_criterium(curl_hash *h, void *user, } } -#if 0 -int -Curl_hash_count(curl_hash *h) -{ - return h->size; -} -#endif - -void +void Curl_hash_destroy(curl_hash *h) { if (!h) diff --git a/lib/hash.h b/lib/hash.h index 60fd84d52..7814674fd 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -1,10 +1,10 @@ #ifndef __HASH_H #define __HASH_H /*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. @@ -12,7 +12,7 @@ * 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. diff --git a/lib/hostares.c b/lib/hostares.c index 07a79fd96..80d1ecd6c 100644 --- a/lib/hostares.c +++ b/lib/hostares.c @@ -1,8 +1,8 @@ /*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. @@ -10,7 +10,7 @@ * 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. @@ -204,7 +204,7 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn, store.tv_sec = (int)timeout/1000; store.tv_usec = (timeout%1000)*1000; - + FD_ZERO(&read_fds); FD_ZERO(&write_fds); nfds = ares_fds(data->state.areschannel, &read_fds, &write_fds); @@ -229,7 +229,7 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn, /* Operation complete, if the lookup was successful we now have the entry in the cache. */ - + if(entry) *entry = conn->async.dns; @@ -251,7 +251,7 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn, cleaning up this connection properly */ Curl_disconnect(conn); } - + return rc; } @@ -273,10 +273,11 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, in_addr_t in = inet_addr(hostname); *waitp = FALSE; - - if (in != CURL_INADDR_NONE) + + if (in != CURL_INADDR_NONE) { /* This is a dotted IP address 123.123.123.123-style */ - return Curl_ip2addr(in, hostname); + return Curl_ip2addr(in, hostname, port); + } bufp = strdup(hostname); @@ -290,8 +291,8 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, /* areschannel is already setup in the Curl_open() function */ ares_gethostbyname(data->state.areschannel, hostname, PF_INET, - Curl_addrinfo_callback, conn); - + Curl_addrinfo4_callback, conn); + *waitp = TRUE; /* please wait for the response */ } return NULL; /* no struct yet */ diff --git a/lib/hostasyn.c b/lib/hostasyn.c index d308cd17d..da072a043 100644 --- a/lib/hostasyn.c +++ b/lib/hostasyn.c @@ -108,9 +108,9 @@ * * The storage operation locks and unlocks the DNS cache. */ -void Curl_addrinfo_callback(void *arg, /* "struct connectdata *" */ - int status, - Curl_addrinfo *hostent) +static void addrinfo_callback(void *arg, /* "struct connectdata *" */ + int status, + void *addr) { struct connectdata *conn = (struct connectdata *)arg; struct Curl_dns_entry *dns = NULL; @@ -126,19 +126,19 @@ void Curl_addrinfo_callback(void *arg, /* "struct connectdata *" */ * * IPv6: Curl_addrinfo_copy() returns the input pointer! */ - Curl_addrinfo *he = Curl_addrinfo_copy(hostent); - if(he) { + Curl_addrinfo *ai = Curl_addrinfo_copy(addr, conn->async.port); + if(ai) { struct SessionHandle *data = conn->data; if(data->share) Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); - dns = Curl_cache_addr(data, he, + dns = Curl_cache_addr(data, ai, conn->async.hostname, conn->async.port); if(!dns) /* failed to store, cleanup and return error */ - Curl_freeaddrinfo(he); + Curl_freeaddrinfo(ai); if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); @@ -151,4 +151,20 @@ void Curl_addrinfo_callback(void *arg, /* "struct connectdata *" */ this function */ } +void Curl_addrinfo4_callback(void *arg, /* "struct connectdata *" */ + int status, + struct hostent *hostent) +{ + addrinfo_callback(arg, status, hostent); +} + +#ifdef CURLRES_IPV6 +void Curl_addrinfo6_callback(void *arg, /* "struct connectdata *" */ + int status, + struct addrinfo *hostent) +{ + addrinfo_callback(arg, status, hostent); +} +#endif + #endif /* CURLRES_ASYNC */ diff --git a/lib/hostip.c b/lib/hostip.c index b5c710339..7a32d1728 100644 --- a/lib/hostip.c +++ b/lib/hostip.c @@ -174,14 +174,8 @@ void Curl_global_host_cache_dtor(void) int Curl_num_addresses(const Curl_addrinfo *addr) { int i; - -#ifdef ENABLE_IPV6 - for (i = 0; addr; addr = addr->ai_next, i++) -#else - for (i = 0; addr->h_addr_list[i]; i++) -#endif - ; - return (i); + for (i = 0; addr; addr = addr->ai_next, i++); + return i; } /* @@ -191,18 +185,18 @@ int Curl_num_addresses(const Curl_addrinfo *addr) * * If the conversion fails, it returns NULL. */ -const char *Curl_printable_address(const Curl_ipconnect *ip, +const char *Curl_printable_address(const Curl_addrinfo *ip, char *buf, size_t bufsize) { -#ifdef CURLRES_IPV6 const void *ip4 = &((const struct sockaddr_in*)ip->ai_addr)->sin_addr; - const void *ip6 = &((const struct sockaddr_in6*)ip->ai_addr)->sin6_addr; int af = ip->ai_family; - - return Curl_inet_ntop(af, af == AF_INET6 ? ip6 : ip4, buf, bufsize); +#ifdef CURLRES_IPV6 + const void *ip6 = &((const struct sockaddr_in6*)ip->ai_addr)->sin6_addr; #else - return Curl_inet_ntop(AF_INET, ip, buf, bufsize); + const void *ip6 = NULL; #endif + + return Curl_inet_ntop(af, af == AF_INET ? ip4 : ip6, buf, bufsize); } /* @@ -547,35 +541,6 @@ curl_hash *Curl_mk_dnscache(void) return Curl_hash_alloc(7, freednsentry); } -#ifdef CURLRES_HOSTENT_RELOCATE -/* - * Curl_hostent_relocate() ajusts all pointers in the given hostent struct - * according to the offset. This is typically used when a hostent has been - * reallocated and needs to be setup properly on the new address. - */ -void Curl_hostent_relocate(struct hostent *h, long offset) -{ - int i=0; - - h->h_name=(char *)((long)h->h_name+offset); - if(h->h_aliases) { - /* only relocate aliases if there are any! */ - h->h_aliases=(char **)((long)h->h_aliases+offset); - while(h->h_aliases[i]) { - h->h_aliases[i]=(char *)((long)h->h_aliases[i]+offset); - i++; - } - } - - h->h_addr_list=(char **)((long)h->h_addr_list+offset); - i=0; - while(h->h_addr_list[i]) { - h->h_addr_list[i]=(char *)((long)h->h_addr_list[i]+offset); - i++; - } -} -#endif /* CURLRES_HOSTENT_RELOCATE */ - #ifdef CURLRES_ADDRINFO_COPY /* align on even 64bit boundaries */ @@ -586,94 +551,10 @@ void Curl_hostent_relocate(struct hostent *h, long offset) * returns a pointer to the malloc()ed copy. You need to call free() on the * returned buffer when you're done with it. */ -Curl_addrinfo *Curl_addrinfo_copy(Curl_addrinfo *orig) +Curl_addrinfo *Curl_addrinfo_copy(void *org, int port) { - char *newbuf; - Curl_addrinfo *copy; - int i; - char *str; - size_t len; - char *aptr = (char *)malloc(CURL_HOSTENT_SIZE); - char *bufptr = aptr; + struct hostent *orig = org; - if(!bufptr) - return NULL; /* major bad */ - - copy = (Curl_addrinfo *)bufptr; - - bufptr += sizeof(Curl_addrinfo); - copy->h_name = bufptr; - len = strlen(orig->h_name) + 1; - strncpy(bufptr, orig->h_name, len); - bufptr += len; - - /* This must be aligned properly to work on many CPU architectures! */ - bufptr = MEMALIGN(bufptr); - - copy->h_aliases = (char**)bufptr; - - /* Figure out how many aliases there are */ - for (i = 0; orig->h_aliases && orig->h_aliases[i]; ++i); - - /* Reserve room for the array */ - bufptr += (i + 1) * sizeof(char*); - - /* Clone all known aliases */ - if(orig->h_aliases) { - for(i = 0; (str = orig->h_aliases[i]); i++) { - len = strlen(str) + 1; - strncpy(bufptr, str, len); - copy->h_aliases[i] = bufptr; - bufptr += len; - } - } - /* if(!orig->h_aliases) i was already set to 0 */ - - /* Terminate the alias list with a NULL */ - copy->h_aliases[i] = NULL; - - copy->h_addrtype = orig->h_addrtype; - copy->h_length = orig->h_length; - - /* align it for (at least) 32bit accesses */ - bufptr = MEMALIGN(bufptr); - - copy->h_addr_list = (char**)bufptr; - - /* Figure out how many addresses there are */ - for (i = 0; orig->h_addr_list[i] != NULL; ++i); - - /* Reserve room for the array */ - bufptr += (i + 1) * sizeof(char*); - - i = 0; - len = orig->h_length; - str = orig->h_addr_list[i]; - while (str != NULL) { - memcpy(bufptr, str, len); - copy->h_addr_list[i] = bufptr; - bufptr += len; - str = orig->h_addr_list[++i]; - } - copy->h_addr_list[i] = NULL; - - /* now, shrink the allocated buffer to the size we actually need, which - most often is only a fraction of the original alloc */ - newbuf=(char *)realloc(aptr, (long)(bufptr-aptr)); - - if(!newbuf) { - /* serious error, but since this is shrinking only requested, we can - still use the previous memory block */ - newbuf = aptr; - } - - /* if the alloc moved, we need to adjust the hostent struct */ - else if(newbuf != aptr) - Curl_hostent_relocate((struct hostent*)newbuf, (long)(newbuf-aptr)); - - /* setup the return */ - copy = (Curl_addrinfo *)newbuf; - - return copy; + return Curl_he2ai(orig, port); } #endif /* CURLRES_ADDRINFO_COPY */ diff --git a/lib/hostip.h b/lib/hostip.h index 24d6fcfe1..aa3aba05f 100644 --- a/lib/hostip.h +++ b/lib/hostip.h @@ -26,6 +26,85 @@ #include "setup.h" #include "hash.h" +/* + * Setup comfortable CURLRES_* defines to use in the host*.c sources. + */ + +#ifdef USE_ARES +#define CURLRES_ASYNCH +#define CURLRES_ARES +#endif + +#ifdef USE_THREADING_GETHOSTBYNAME +#define CURLRES_ASYNCH +#define CURLRES_THREADED +#endif + +#ifdef USE_THREADING_GETADDRINFO +#define CURLRES_ASYNCH +#define CURLRES_THREADED +#endif + +#ifdef ENABLE_IPV6 +#define CURLRES_IPV6 +#else +#define CURLRES_IPV4 +#endif + +#ifdef CURLRES_IPV4 +#if !defined(HAVE_GETHOSTBYNAME_R) || defined(CURLRES_ASYNCH) +/* If built for ipv4 and missing gethostbyname_r(), or if using async name + resolve, we need the Curl_addrinfo_copy() function (which itself needs the + Curl_hostent_relocate() function)) */ +#define CURLRES_ADDRINFO_COPY +#endif +#endif /* IPv4-only */ + +#ifndef CURLRES_ASYNCH +#define CURLRES_SYNCH +#endif + +#ifndef USE_LIBIDN +#define CURLRES_IDN +#endif + +/* Allocate enough memory to hold the full name information structs and + * everything. OSF1 is known to require at least 8872 bytes. The buffer + * required for storing all possible aliases and IP numbers is according to + * Stevens' Unix Network Programming 2nd edition, p. 304: 8192 bytes! + */ +#define CURL_HOSTENT_SIZE 9000 + +#define CURL_TIMEOUT_RESOLVE 300 /* when using asynch methods, we allow this + many seconds for a name resolve */ + +#ifdef CURLRES_ARES +#define CURL_ASYNC_SUCCESS ARES_SUCCESS +#else +#define CURL_ASYNC_SUCCESS CURLE_OK +#endif + +/* + * Curl_addrinfo MUST be used for all name resolved info. + */ +#ifdef CURLRES_IPV6 +typedef struct addrinfo Curl_addrinfo; +#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; + size_t ai_addrlen; + struct sockaddr *ai_addr; + char *ai_canonname; + struct Curl_addrinfo *ai_next; +}; +typedef struct Curl_addrinfo Curl_addrinfo; +#endif + struct addrinfo; struct hostent; struct SessionHandle; @@ -119,28 +198,37 @@ int curl_dogetnameinfo(const struct sockaddr *sa, socklen_t salen, #endif /* This is the callback function that is used when we build with asynch - resolve */ -void Curl_addrinfo_callback(void *arg, + resolve, ipv4 */ +void Curl_addrinfo4_callback(void *arg, int status, - Curl_addrinfo *hostent); + struct hostent *hostent); +/* This is the callback function that is used when we build with asynch + resolve, ipv6 */ +void Curl_addrinfo6_callback(void *arg, + int status, + struct hostent *hostent); -/* This is a utility-function for ipv4-builds to create a hostent struct - from a numerical-only IP address */ -Curl_addrinfo *Curl_ip2addr(in_addr_t num, char *hostname); + +/* [ipv4 only] Creates a Curl_addrinfo struct from a numerical-only IP + address */ +Curl_addrinfo *Curl_ip2addr(in_addr_t num, char *hostname, int port); + +/* [ipv4 only] Curl_he2ai() converts a struct hostent to a Curl_addrinfo chain + and returns it */ +Curl_addrinfo *Curl_he2ai(struct hostent *, unsigned short port); /* relocate a hostent struct */ void Curl_hostent_relocate(struct hostent *h, long offset); -/* copy a Curl_addrinfo struct, currently this only supports copying - a hostent (ipv4-style) struct */ -Curl_addrinfo *Curl_addrinfo_copy(Curl_addrinfo *orig); +/* Clone a Curl_addrinfo struct, works protocol independently */ +Curl_addrinfo *Curl_addrinfo_copy(void *orig, int port); /* * Curl_printable_address() returns a printable version of the 1st address * given in the 'ip' argument. The result will be stored in the buf that is * bufsize bytes big. */ -const char *Curl_printable_address(const Curl_ipconnect *ip, +const char *Curl_printable_address(const Curl_addrinfo *ip, char *buf, size_t bufsize); /* @@ -158,71 +246,7 @@ Curl_cache_addr(struct SessionHandle *data, Curl_addrinfo *addr, #define CURL_INADDR_NONE INADDR_NONE #endif -/* - * Setup comfortable CURLRES_* defines to use in the host*.c sources. - */ -#ifdef USE_ARES -#define CURLRES_ASYNCH -#define CURLRES_ARES -#endif -#ifdef USE_THREADING_GETHOSTBYNAME -#define CURLRES_ASYNCH -#define CURLRES_THREADED -#endif - -#ifdef USE_THREADING_GETADDRINFO -#define CURLRES_ASYNCH -#define CURLRES_THREADED -#endif - -#ifdef ENABLE_IPV6 -#define CURLRES_IPV6 -#else -#define CURLRES_IPV4 -#endif - -#ifdef CURLRES_IPV4 -#if !defined(HAVE_GETHOSTBYNAME_R) || defined(CURLRES_ASYNCH) -/* If built for ipv4 and missing gethostbyname_r(), or if using async name - resolve, we need the Curl_addrinfo_copy() function (which itself needs the - Curl_hostent_relocate() function)) */ -#define CURLRES_ADDRINFO_COPY -#define CURLRES_HOSTENT_RELOCATE -#endif -#endif /* IPv4-only */ - -#ifdef HAVE_GETHOSTBYNAME_R_6 -#define CURLRES_HOSTENT_RELOCATE -#endif - -#ifdef HAVE_GETHOSTBYNAME_R_5 -#define CURLRES_HOSTENT_RELOCATE -#endif - -#ifndef CURLRES_ASYNCH -#define CURLRES_SYNCH -#endif - -#ifndef USE_LIBIDN -#define CURLRES_IDN -#endif - -/* Allocate enough memory to hold the full name information structs and - * everything. OSF1 is known to require at least 8872 bytes. The buffer - * required for storing all possible aliases and IP numbers is according to - * Stevens' Unix Network Programming 2nd edition, p. 304: 8192 bytes! - */ -#define CURL_HOSTENT_SIZE 9000 - -#define CURL_TIMEOUT_RESOLVE 300 /* when using asynch methods, we allow this - many seconds for a name resolve */ - -#ifdef CURLRES_ARES -#define CURL_ASYNC_SUCCESS ARES_SUCCESS -#else -#define CURL_ASYNC_SUCCESS CURLE_OK -#endif #endif diff --git a/lib/hostip4.c b/lib/hostip4.c index eef1f1ab6..4dfa31b80 100644 --- a/lib/hostip4.c +++ b/lib/hostip4.c @@ -1,8 +1,8 @@ /*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. @@ -10,7 +10,7 @@ * 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. @@ -97,13 +97,19 @@ #ifdef CURLRES_IPV4 /* plain ipv4 code coming up */ /* - * This is a wrapper function for freeing name information in a protocol - * independent way. This takes care of using the appropriate underlying - * function. + * This is a function for freeing name information in a protocol independent + * way. */ -void Curl_freeaddrinfo(Curl_addrinfo *p) +void Curl_freeaddrinfo(Curl_addrinfo *ai) { - free(p); /* works fine for the ARES case too */ + Curl_addrinfo *next; + + /* walk over the list and free all entries */ + while(ai) { + next = ai->ai_next; + free(ai); + ai = next; + } } /* @@ -119,28 +125,29 @@ bool Curl_ipvalid(struct SessionHandle *data) return TRUE; /* OK, proceed */ } +struct namebuf { + struct hostent hostentry; + char *h_addr_list[2]; + struct in_addr addrentry; + char h_name[16]; /* 123.123.123.123 = 15 letters is maximum */ +}; + /* * Curl_ip2addr() takes a 32bit ipv4 internet address as input parameter * together with a pointer to the string version of the address, and it - * retruns a malloc()ed version of a hostent struct filled in correctly with - * information for this address/host. + * returns a Curl_addrinfo chain filled in correctly with information for this + * address/host. * * The input parameters ARE NOT checked for validity but they are expected * to have been checked already when this is called. */ -Curl_addrinfo *Curl_ip2addr(in_addr_t num, char *hostname) +Curl_addrinfo *Curl_ip2addr(in_addr_t num, char *hostname, int port) { + Curl_addrinfo *ai; struct hostent *h; struct in_addr *addrentry; - struct namebuf { - struct hostent hostentry; - char *h_addr_list[2]; - struct in_addr addrentry; - char h_name[16]; /* 123.123.123.123 = 15 letters is maximum */ - } *buf = (struct namebuf *)malloc(sizeof(struct namebuf)); - - if(!buf) - return NULL; /* major failure */ + struct namebuf buffer; + struct namebuf *buf = &buffer; h = &buf->hostentry; h->h_addr_list = &buf->h_addr_list[0]; @@ -156,7 +163,9 @@ Curl_addrinfo *Curl_ip2addr(in_addr_t num, char *hostname) /* Now store the dotted version of the address */ snprintf(h->h_name, 16, "%s", hostname); - return h; + ai = Curl_he2ai(h, port); + + return ai; } #ifdef CURLRES_SYNCH /* the functions below are for synchronous resolves */ @@ -183,6 +192,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, int port, int *waitp) { + Curl_addrinfo *ai = NULL; struct hostent *h = NULL; in_addr_t in; struct SessionHandle *data = conn->data; @@ -191,9 +201,10 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, *waitp = 0; /* don't wait, we act synchronously */ in=inet_addr(hostname); - if (in != CURL_INADDR_NONE) + if (in != CURL_INADDR_NONE) { /* This is a dotted IP address 123.123.123.123-style */ - return Curl_ip2addr(in, hostname); + return Curl_ip2addr(in, hostname, port); + } #if defined(HAVE_GETHOSTBYNAME_R) /* @@ -204,7 +215,6 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, else { int h_errnop; int res=ERANGE; - int step_size=200; int *buf = (int *)calloc(CURL_HOSTENT_SIZE, 1); if(!buf) return NULL; /* major failure */ @@ -217,99 +227,64 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, #ifdef HAVE_GETHOSTBYNAME_R_5 /* Solaris, IRIX and more */ (void)res; /* prevent compiler warning */ - while(!h) { - h = gethostbyname_r(hostname, - (struct hostent *)buf, - (char *)buf + sizeof(struct hostent), - step_size - sizeof(struct hostent), - &h_errnop); + h = gethostbyname_r(hostname, + (struct hostent *)buf, + (char *)buf + sizeof(struct hostent), + CURL_HOSTENT_SIZE - sizeof(struct hostent), + &h_errnop); - /* If the buffer is too small, it returns NULL and sets errno to - * ERANGE. The errno is thread safe if this is compiled with - * -D_REENTRANT as then the 'errno' variable is a macro defined to get - * used properly for threads. - */ - - if(h || (errno != ERANGE)) - break; - - step_size+=200; - } - -#ifdef CURLDEBUG - infof(data, "gethostbyname_r() uses %d bytes\n", step_size); -#endif + /* If the buffer is too small, it returns NULL and sets errno to + * ERANGE. The errno is thread safe if this is compiled with + * -D_REENTRANT as then the 'errno' variable is a macro defined to get + * used properly for threads. + */ if(h) { - int offset; - h=(struct hostent *)realloc(buf, step_size); - offset=(long)h-(long)buf; - Curl_hostent_relocate(h, offset); - buf=(int *)h; + ; } else #endif /* HAVE_GETHOSTBYNAME_R_5 */ #ifdef HAVE_GETHOSTBYNAME_R_6 /* Linux */ - do { - res=gethostbyname_r(hostname, - (struct hostent *)buf, - (char *)buf + sizeof(struct hostent), - step_size - sizeof(struct hostent), - &h, /* DIFFERENCE */ - &h_errnop); - /* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a - * sudden this function returns EAGAIN if the given buffer size is too - * small. Previous versions are known to return ERANGE for the same - * problem. - * - * This wouldn't be such a big problem if older versions wouldn't - * sometimes return EAGAIN on a common failure case. Alas, we can't - * assume that EAGAIN *or* ERANGE means ERANGE for any given version of - * glibc. - * - * For now, we do that and thus we may call the function repeatedly and - * fail for older glibc versions that return EAGAIN, until we run out of - * buffer size (step_size grows beyond CURL_HOSTENT_SIZE). - * - * If anyone has a better fix, please tell us! - * - * ------------------------------------------------------------------- - * - * On October 23rd 2003, Dan C dug up more details on the mysteries of - * gethostbyname_r() in glibc: - * - * In glibc 2.2.5 the interface is different (this has also been - * discovered in glibc 2.1.1-6 as shipped by Redhat 6). What I can't - * explain, is that tests performed on glibc 2.2.4-34 and 2.2.4-32 - * (shipped/upgraded by Redhat 7.2) don't show this behavior! - * - * In this "buggy" version, the return code is -1 on error and 'errno' - * is set to the ERANGE or EAGAIN code. Note that 'errno' is not a - * thread-safe variable. - */ - if(((ERANGE == res) || (EAGAIN == res)) || - ((res<0) && ((ERANGE == errno) || (EAGAIN == errno)))) - step_size+=200; - else - break; - } while(step_size <= CURL_HOSTENT_SIZE); + res=gethostbyname_r(hostname, + (struct hostent *)buf, + (char *)buf + sizeof(struct hostent), + CURL_HOSTENT_SIZE - sizeof(struct hostent), + &h, /* DIFFERENCE */ + &h_errnop); + /* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a + * sudden this function returns EAGAIN if the given buffer size is too + * small. Previous versions are known to return ERANGE for the same + * problem. + * + * This wouldn't be such a big problem if older versions wouldn't + * sometimes return EAGAIN on a common failure case. Alas, we can't + * assume that EAGAIN *or* ERANGE means ERANGE for any given version of + * glibc. + * + * For now, we do that and thus we may call the function repeatedly and + * fail for older glibc versions that return EAGAIN, until we run out of + * buffer size (step_size grows beyond CURL_HOSTENT_SIZE). + * + * If anyone has a better fix, please tell us! + * + * ------------------------------------------------------------------- + * + * On October 23rd 2003, Dan C dug up more details on the mysteries of + * gethostbyname_r() in glibc: + * + * In glibc 2.2.5 the interface is different (this has also been + * discovered in glibc 2.1.1-6 as shipped by Redhat 6). What I can't + * explain, is that tests performed on glibc 2.2.4-34 and 2.2.4-32 + * (shipped/upgraded by Redhat 7.2) don't show this behavior! + * + * In this "buggy" version, the return code is -1 on error and 'errno' + * is set to the ERANGE or EAGAIN code. Note that 'errno' is not a + * thread-safe variable. + */ if(!h) /* failure */ - res=1; - -#ifdef CURLDEBUG - infof(data, "gethostbyname_r() uses %d bytes\n", step_size); -#endif - if(!res) { - int offset; - h=(struct hostent *)realloc(buf, step_size); - offset=(long)h-(long)buf; - Curl_hostent_relocate(h, offset); - buf=(int *)h; - } - else #endif/* HAVE_GETHOSTBYNAME_R_6 */ #ifdef HAVE_GETHOSTBYNAME_R_3 /* AIX, Digital Unix/Tru64, HPUX 10, more? */ @@ -361,7 +336,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, * calling Curl_addrinfo_copy() that subsequent realloc()s down the new * memory area to the actually used amount. */ - } + } else #endif /* HAVE_GETHOSTBYNAME_R_3 */ { @@ -386,14 +361,95 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, * between threads, which thus the copying here them allows the app to * do. */ - h = Curl_addrinfo_copy(h); + return Curl_addrinfo_copy(h); } #endif /*HAVE_GETHOSTBYNAME_R */ } - return h; + if(h) { + ai = Curl_he2ai(h, port); + + free(h); + } + + return ai; } #endif /* CURLRES_SYNCH */ +/* + * 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. + +struct Curl_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 addrinfo *ai_next; +}; + +struct hostent { + char *h_name; * official name of host * + char **h_aliases; * alias list * + int h_addrtype; * host address type * + int h_length; * length of address * + char **h_addr_list; * list of addresses * +} +#define h_addr h_addr_list[0] * for backward compatibility * + +*/ + +Curl_addrinfo *Curl_he2ai(struct hostent *he, unsigned short port) +{ + Curl_addrinfo *ai; + Curl_addrinfo *prevai = NULL; + Curl_addrinfo *firstai = NULL; + struct sockaddr_in *addr; + int i; + struct in_addr *curr; + + if(!he) + /* no input == no output! */ + return NULL; + + for(i=0; (curr = (struct in_addr *)he->h_addr_list[i]); i++) { + + ai = calloc(1, sizeof(struct addrinfo) + sizeof(struct sockaddr_in)); + + if(!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 = AF_INET; /* we only support this */ + ai->ai_socktype = SOCK_STREAM; /* we only support this */ + ai->ai_addrlen = sizeof(struct sockaddr_in); + /* make the ai_addr point to the address immediately following this struct + and use that area to store the address */ + ai->ai_addr = (struct sockaddr *) ((char*)ai + sizeof(struct addrinfo)); + + /* leave the rest of the struct filled with zero */ + + addr = (struct sockaddr_in *)ai->ai_addr; /* storage area for this info */ + + memcpy((char *)&(addr->sin_addr), curr, sizeof(struct in_addr)); + addr->sin_family = he->h_addrtype; + addr->sin_port = htons((unsigned short)port); + + prevai = ai; + } + return firstai; +} + #endif /* CURLRES_IPV4 */ diff --git a/lib/hostthre.c b/lib/hostthre.c index 9014b02c9..29b6ab387 100644 --- a/lib/hostthre.c +++ b/lib/hostthre.c @@ -469,7 +469,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn, hostname, port, Curl_strerror(conn,WSAGetLastError())); return NULL; } - return h; + return Curl_he2ai(h, port); } #endif /* CURLRES_IPV4 */ diff --git a/lib/if2ip.c b/lib/if2ip.c index b816d246f..237d1f758 100644 --- a/lib/if2ip.c +++ b/lib/if2ip.c @@ -1,8 +1,8 @@ /*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. @@ -10,7 +10,7 @@ * 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. @@ -64,7 +64,7 @@ #include #endif -#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL) +#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL) #include "inet_ntoa_r.h" #endif @@ -84,7 +84,7 @@ char *Curl_if2ip(const char *interface, char *buf, int buf_size) { int dummy; char *ip=NULL; - + if(!interface) return NULL; diff --git a/lib/if2ip.h b/lib/if2ip.h index 30a6540a4..45a180531 100644 --- a/lib/if2ip.h +++ b/lib/if2ip.h @@ -1,10 +1,10 @@ #ifndef __IF2IP_H #define __IF2IP_H /*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. @@ -12,7 +12,7 @@ * 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. @@ -63,7 +63,7 @@ struct ifreq { #define ifr_metric ifr_ifru.ifru_metric /* metric */ #define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ -#define SIOCGIFADDR _IOW('s', 102, struct ifreq) /* Get if addr */ +#define SIOCGIFADDR _IOW('s', 102, struct ifreq) /* Get if addr */ #endif /* interix */ #endif diff --git a/lib/krb4.c b/lib/krb4.c index 994e6111f..743f3f121 100644 --- a/lib/krb4.c +++ b/lib/krb4.c @@ -10,22 +10,22 @@ * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * + * * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -70,7 +70,7 @@ #include "memdebug.h" #define LOCAL_ADDR (&conn->local_addr) -#define REMOTE_ADDR (&conn->serv_addr) +#define REMOTE_ADDR conn->ip_addr->ai_addr #define myctladdr LOCAL_ADDR #define hisctladdr REMOTE_ADDR @@ -120,13 +120,13 @@ krb4_decode(void *app_data, void *buf, int len, int level, MSG_DAT m; int e; struct krb4_data *d = app_data; - + if(level == prot_safe) e = krb_rd_safe(buf, len, &d->key, (struct sockaddr_in *)REMOTE_ADDR, (struct sockaddr_in *)LOCAL_ADDR, &m); else - e = krb_rd_priv(buf, len, d->schedule, &d->key, + e = krb_rd_priv(buf, len, d->schedule, &d->key, (struct sockaddr_in *)REMOTE_ADDR, (struct sockaddr_in *)LOCAL_ADDR, &m); if(e) { @@ -155,11 +155,11 @@ krb4_encode(void *app_data, void *from, int length, int level, void **to, struct krb4_data *d = app_data; *to = malloc(length + 31); if(level == prot_safe) - return krb_mk_safe(from, *to, length, &d->key, + return krb_mk_safe(from, *to, length, &d->key, (struct sockaddr_in *)LOCAL_ADDR, (struct sockaddr_in *)REMOTE_ADDR); else if(level == prot_private) - return krb_mk_priv(from, *to, length, d->schedule, &d->key, + return krb_mk_priv(from, *to, length, d->schedule, &d->key, (struct sockaddr_in *)LOCAL_ADDR, (struct sockaddr_in *)REMOTE_ADDR); else @@ -167,7 +167,7 @@ krb4_encode(void *app_data, void *from, int length, int level, void **to, } static int -mk_auth(struct krb4_data *d, KTEXT adat, +mk_auth(struct krb4_data *d, KTEXT adat, const char *service, char *host, int checksum) { int ret; @@ -223,7 +223,7 @@ krb4_auth(void *app_data, struct connectdata *conn) Curl_infof(data, "%s\n", krb_get_err_text(ret)); return AUTH_CONTINUE; } - + #ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM if (krb_get_config_bool("nat_in_use")) { struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR; @@ -281,11 +281,11 @@ krb4_auth(void *app_data, struct connectdata *conn) return AUTH_ERROR; } adat.length = len; - ret = krb_rd_safe(adat.dat, adat.length, &d->key, - (struct sockaddr_in *)hisctladdr, + ret = krb_rd_safe(adat.dat, adat.length, &d->key, + (struct sockaddr_in *)hisctladdr, (struct sockaddr_in *)myctladdr, &msg_data); if(ret) { - Curl_failf(data, "Error reading reply from server: %s", + Curl_failf(data, "Error reading reply from server: %s", krb_get_err_text(ret)); return AUTH_ERROR; } @@ -354,7 +354,7 @@ CURLcode Curl_krb_kauth(struct connectdata *conn) } tkt.length = tmp; tktcopy.length = tkt.length; - + p = strstr(conn->data->state.buffer, "P="); if(!p) { Curl_failf(conn->data, "Bad reply from server"); @@ -367,7 +367,7 @@ CURLcode Curl_krb_kauth(struct connectdata *conn) des_string_to_key (conn->passwd, &key); des_key_sched(&key, schedule); - + des_pcbc_encrypt((void *)tkt.dat, (void *)tktcopy.dat, tkt.length, schedule, &key, DES_DECRYPT); diff --git a/lib/llist.c b/lib/llist.c index 2f059991d..961848692 100644 --- a/lib/llist.c +++ b/lib/llist.c @@ -1,8 +1,8 @@ /*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. @@ -10,7 +10,7 @@ * 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. @@ -32,7 +32,7 @@ /* this must be the last include file */ #include "memdebug.h" -void +void Curl_llist_init(curl_llist *l, curl_llist_dtor dtor) { l->size = 0; @@ -90,36 +90,7 @@ Curl_llist_insert_next(curl_llist *list, curl_llist_element *e, const void *p) return 1; } -#if 0 -int -Curl_llist_insert_prev(curl_llist *list, curl_llist_element *e, const void *p) -{ - curl_llist_element *ne; - - ne = (curl_llist_element *) malloc(sizeof(curl_llist_element)); - ne->ptr = (void *) p; - if (list->size == 0) { - list->head = ne; - list->head->prev = NULL; - list->head->next = NULL; - list->tail = ne; - } else { - ne->next = e; - ne->prev = e->prev; - if (e->prev) - e->prev->next = ne; - else - list->head = ne; - e->prev = ne; - } - - ++list->size; - - return 1; -} -#endif - -int +int Curl_llist_remove(curl_llist *list, curl_llist_element *e, void *user) { if (e == NULL || list->size == 0) @@ -147,27 +118,7 @@ Curl_llist_remove(curl_llist *list, curl_llist_element *e, void *user) return 1; } -#if 0 -int -Curl_llist_remove_next(curl_llist *list, curl_llist_element *e, void *user) -{ - return Curl_llist_remove(list, e->next, user); -} - -int -Curl_llist_remove_prev(curl_llist *list, curl_llist_element *e, void *user) -{ - return Curl_llist_remove(list, e->prev, user); -} - -size_t -Curl_llist_count(curl_llist *list) -{ - return list->size; -} -#endif - -void +void Curl_llist_destroy(curl_llist *list, void *user) { if(list) { diff --git a/lib/memdebug.c b/lib/memdebug.c index 718391cdb..f5ef34d44 100644 --- a/lib/memdebug.c +++ b/lib/memdebug.c @@ -1,9 +1,9 @@ #ifdef CURLDEBUG /*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. @@ -11,7 +11,7 @@ * 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. @@ -99,12 +99,12 @@ static bool countcheck(const char *func, int line, const char *source) } else memsize--; /* countdown */ - + /* log the countdown */ if(logfile && source) fprintf(logfile, "LIMIT %s:%d %ld ALLOCS left\n", source, line, memsize); - + } return FALSE; /* allow this */ @@ -166,7 +166,7 @@ char *curl_dostrdup(const char *str, int line, const char *source) size_t len; curlassert(str != NULL); - + if(countcheck("strdup", line, source)) return NULL; @@ -221,7 +221,7 @@ void curl_dofree(void *ptr, int line, const char *source) /* destroy */ memset(mem->mem, 0x13, mem->size); - + /* free for real */ (Curl_cfree)(mem); @@ -285,7 +285,7 @@ int curl_fclose(FILE *file, int line, const char *source) } #else #ifdef VMS -int VOID_VAR_MEMDEBUG; +int VOID_VAR_MEMDEBUG; #else /* we provide a fake do-nothing function here to avoid compiler warnings */ void curl_memdebug(void) {} diff --git a/lib/mprintf.c b/lib/mprintf.c index cd096c599..6e77075c2 100644 --- a/lib/mprintf.c +++ b/lib/mprintf.c @@ -142,9 +142,6 @@ typedef struct { LONG_LONG lnum; #endif double dnum; -#if 0 /*SIZEOF_LONG_DOUBLE */ - long double ldnum; -#endif } data; } va_stack_t; @@ -227,7 +224,7 @@ int dprintf_Pass1Report(va_stack_t *vto, int max) break; case FORMAT_LONGDOUBLE: type = "long double"; - break; + break; } @@ -317,7 +314,7 @@ static long dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, /* Handle the positional case (N$) */ param_num++; - + this_param = dprintf_DollarString(fmt, &fmt); if (0 == this_param) /* we got no positional, get the next counter */ @@ -418,7 +415,7 @@ static long dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, case '*': /* Special case */ flags |= FLAGS_WIDTHPARAM; param_num++; - + i = dprintf_DollarString(fmt, &fmt); if(i) width = i; @@ -471,7 +468,7 @@ static long dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, case 'c': vto[i].type = FORMAT_INT; flags |= FLAGS_CHAR; - break; + break; case 'f': vto[i].type = FORMAT_DOUBLE; break; @@ -486,11 +483,11 @@ static long dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, case 'g': vto[i].type = FORMAT_DOUBLE; flags |= FLAGS_FLOATG; - break; + break; case 'G': vto[i].type = FORMAT_DOUBLE; flags |= FLAGS_FLOATG|FLAGS_UPPER; - break; + break; default: vto[i].type = FORMAT_UNKNOWN; break; @@ -499,7 +496,7 @@ static long dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, vto[i].flags = flags; vto[i].width = width; vto[i].precision = precision; - + if (flags & FLAGS_WIDTHPARAM) { /* we have the width specified from a parameter, so we make that parameter's info setup properly */ @@ -508,7 +505,7 @@ static long dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, vto[i].type = FORMAT_WIDTH; vto[i].flags = FLAGS_NEW; vto[i].precision = vto[i].width = 0; /* can't use width or precision - of width! */ + of width! */ } if (flags & FLAGS_PRECPARAM) { /* we have the precision specified from a parameter, so we make that @@ -543,13 +540,13 @@ static long dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, case FORMAT_STRING: vto[i].data.str = va_arg(arglist, char *); break; - + case FORMAT_INTPTR: case FORMAT_UNKNOWN: case FORMAT_PTR: vto[i].data.ptr = va_arg(arglist, void *); break; - + case FORMAT_INT: #ifdef ENABLE_64BIT if(vto[i].flags & FLAGS_LONGLONG) @@ -561,23 +558,18 @@ static long dprintf_Pass1(char *format, va_stack_t *vto, char **endpos, else vto[i].data.num = va_arg(arglist, int); break; - + case FORMAT_DOUBLE: -#if 0 /*SIZEOF_LONG_DOUBLE */ - if(vto[i].flags & FLAGS_LONG) - vto[i].data.ldnum = va_arg(arglist, long double); - else -#endif - vto[i].data.dnum = va_arg(arglist, double); + vto[i].data.dnum = va_arg(arglist, double); break; - + case FORMAT_WIDTH: /* Argument has been read. Silently convert it into an integer * for later use */ vto[i].type = FORMAT_INT; break; - + default: break; } @@ -620,21 +612,21 @@ static int dprintf_formatf( end = &endpos[0]; /* the initial end-position from the list dprintf_Pass1() created for us */ - + f = (char *)format; while (*f != '\0') { /* Format spec modifiers. */ char alt; - + /* Width of a field. */ long width; /* Precision of a field. */ long prec; - + /* Decimal integer is negative. */ char is_neg; - + /* Base of a number to be written. */ long base; @@ -645,7 +637,7 @@ static int dprintf_formatf( unsigned long num; #endif long signed_num; - + if (*f != '%') { /* This isn't a format spec, so write everything out until the next one OR end of string is reached. */ @@ -654,9 +646,9 @@ static int dprintf_formatf( } while(*++f && ('%' != *f)); continue; } - + ++f; - + /* Check for "%%". Note that although the ANSI standard lists '%' as a conversion specifier, it says "The complete format specification shall be `%%'," so we can avoid all the width @@ -675,7 +667,7 @@ static int dprintf_formatf( param = param_num; else --param; - + param_num++; /* increase this always to allow "%2$s %1$s %s" and then the third %s will pick the 3rd argument */ @@ -696,7 +688,7 @@ static int dprintf_formatf( prec = -1; alt = (p->flags & FLAGS_ALT)?TRUE:FALSE; - + switch (p->type) { case FORMAT_INT: num = p->data.num; @@ -742,26 +734,26 @@ static int dprintf_formatf( #endif { signed_num = (long) num; - + is_neg = signed_num < 0; num = is_neg ? (- signed_num) : signed_num; } goto number; - + unsigned_number:; /* Unsigned number of base BASE. */ is_neg = 0; - + number:; /* Number of base BASE. */ { char *workend = &work[sizeof(work) - 1]; char *w; - + /* Supply a default precision if none was given. */ if (prec == -1) prec = 1; - + /* Put the number in WORK. */ w = workend; while (num > 0) { @@ -770,35 +762,35 @@ static int dprintf_formatf( } width -= workend - w; prec -= workend - w; - + if (alt && base == 8 && prec <= 0) { *w-- = '0'; --width; } - + if (prec > 0) { width -= prec; while (prec-- > 0) *w-- = '0'; } - + if (alt && base == 16) width -= 2; - + if (is_neg || (p->flags & FLAGS_SHOWSIGN) || (p->flags & FLAGS_SPACE)) --width; - + if (!(p->flags & FLAGS_LEFT) && !(p->flags & FLAGS_PAD_NIL)) while (width-- > 0) OUTCHAR(' '); - + if (is_neg) OUTCHAR('-'); else if (p->flags & FLAGS_SHOWSIGN) OUTCHAR('+'); else if (p->flags & FLAGS_SPACE) OUTCHAR(' '); - + if (alt && base == 16) { OUTCHAR('0'); if(p->flags & FLAGS_UPPER) @@ -810,25 +802,25 @@ static int dprintf_formatf( if (!(p->flags & FLAGS_LEFT) && (p->flags & FLAGS_PAD_NIL)) while (width-- > 0) OUTCHAR('0'); - + /* Write the number. */ while (++w <= workend) { OUTCHAR(*w); } - + if (p->flags & FLAGS_LEFT) while (width-- > 0) OUTCHAR(' '); } break; - + case FORMAT_STRING: /* String. */ { static char null[] = "(nil)"; char *str; size_t len; - + str = (char *) p->data.str; if ( str == NULL) { /* Write null[] if there's space. */ @@ -845,7 +837,7 @@ static int dprintf_formatf( } else len = strlen(str); - + if (prec != -1 && (size_t) prec < len) len = prec; width -= len; @@ -856,7 +848,7 @@ static int dprintf_formatf( if (!(p->flags&FLAGS_LEFT)) while (width-- > 0) OUTCHAR(' '); - + while (len-- > 0) OUTCHAR(*str++); if (p->flags&FLAGS_LEFT) @@ -867,7 +859,7 @@ static int dprintf_formatf( OUTCHAR('"'); } break; - + case FORMAT_PTR: /* Generic pointer. */ { @@ -886,7 +878,7 @@ static int dprintf_formatf( /* Write "(nil)" for a nil pointer. */ static char strnil[] = "(nil)"; char *point; - + width -= sizeof(strnil) - 1; if (p->flags & FLAGS_LEFT) while (width-- > 0) @@ -904,7 +896,7 @@ static int dprintf_formatf( { char formatbuf[32]="%"; char *fptr; - + width = -1; if (p->flags & FLAGS_WIDTH) width = p->width; @@ -948,13 +940,7 @@ static int dprintf_formatf( /* NOTE NOTE NOTE!! Not all sprintf() implementations returns number of output characters */ -#if 0 /*SIZEOF_LONG_DOUBLE*/ - if (p->flags & FLAGS_LONG) - /* This is for support of the 'long double' type */ - (sprintf)(work, formatbuf, p->data.ldnum); - else -#endif - (sprintf)(work, formatbuf, p->data.dnum); + (sprintf)(work, formatbuf, p->data.dnum); for(fptr=work; *fptr; fptr++) OUTCHAR(*fptr); @@ -990,7 +976,7 @@ static int addbyter(int output, FILE *data) { struct nsprintf *infop=(struct nsprintf *)data; unsigned char outc = (unsigned char)output; - + if(infop->length < infop->max) { /* only do this if we haven't reached max length yet */ infop->buffer[0] = outc; /* store */ @@ -1038,7 +1024,7 @@ static int alloc_addbyter(int output, FILE *data) { struct asprintf *infop=(struct asprintf *)data; unsigned char outc = (unsigned char)output; - + if(!infop->buffer) { infop->buffer=(char *)malloc(32); if(!infop->buffer) { @@ -1195,7 +1181,7 @@ int main() #endif curl_mprintf("%3d %5d\n", 10, 1998); - + ptr=curl_maprintf("test this then baby %s%s%s%s%s%s %d %d %d loser baby get a hit in yer face now!", "", "pretty long string pretty long string pretty long string pretty long string pretty long string", "/", "/", "/", "pretty long string", 1998, 1999, 2001); puts(ptr); diff --git a/lib/setup.h b/lib/setup.h index 936199138..2ee7ee267 100644 --- a/lib/setup.h +++ b/lib/setup.h @@ -270,19 +270,6 @@ typedef int curl_socket_t; #endif #endif -/* - * Curl_addrinfo MUST be used for name resolving information. - * Information regarding a single IP witin a Curl_addrinfo MUST be stored in - * a Curl_ipconnect struct. - */ -#ifdef ENABLE_IPV6 -typedef struct addrinfo Curl_addrinfo; -typedef struct addrinfo Curl_ipconnect; -#else -typedef struct hostent Curl_addrinfo; -typedef struct in_addr Curl_ipconnect; -#endif - #ifdef mpeix #define IOCTL_3_ARGS #endif diff --git a/lib/telnet.c b/lib/telnet.c index fb4ba5e00..6915e601d 100644 --- a/lib/telnet.c +++ b/lib/telnet.c @@ -1,8 +1,8 @@ /*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * * Copyright (C) 1998 - 2004, Daniel Stenberg, , et al. @@ -10,7 +10,7 @@ * 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. @@ -151,12 +151,12 @@ typedef enum struct TELNET { int please_negotiate; int already_negotiated; - int us[256]; - int usq[256]; - int us_preferred[256]; - int him[256]; - int himq[256]; - int him_preferred[256]; + int us[256]; + int usq[256]; + int us_preferred[256]; + int him[256]; + int himq[256]; + int him_preferred[256]; char subopt_ttype[32]; /* Set with suboption TTYPE */ char subopt_xdisploc[128]; /* Set with suboption XDISPLOC */ struct curl_slist *telnet_vars; /* Environment variables */ @@ -164,7 +164,7 @@ struct TELNET { /* suboptions */ char subbuffer[SUBBUFSIZE]; char *subpointer, *subend; /* buffer for sub-options */ - + TelnetReceive telrcv_state; }; @@ -172,22 +172,22 @@ struct TELNET { static CURLcode check_wsock2 ( struct SessionHandle *data ) { - int err; - WORD wVersionRequested; - WSADATA wsaData; + int err; + WORD wVersionRequested; + WSADATA wsaData; curlassert(data); /* telnet requires at least WinSock 2.0 so ask for it. */ wVersionRequested = MAKEWORD(2, 0); - err = WSAStartup(wVersionRequested, &wsaData); - + err = WSAStartup(wVersionRequested, &wsaData); + /* We must've called this once already, so this call */ /* should always succeed. But, just in case... */ if (err != 0) { failf(data,"WSAStartup failed (%d)",err); - return CURLE_FAILED_INIT; + return CURLE_FAILED_INIT; } /* We have to have a WSACleanup call for every successful */ @@ -212,29 +212,17 @@ CURLcode init_telnet(struct connectdata *conn) { struct TELNET *tn; - tn = (struct TELNET *)malloc(sizeof(struct TELNET)); + tn = (struct TELNET *)calloc(1, sizeof(struct TELNET)); if(!tn) return CURLE_OUT_OF_MEMORY; - - conn->proto.telnet = (void *)tn; /* make us known */ - memset(tn, 0, sizeof(struct TELNET)); + conn->proto.telnet = (void *)tn; /* make us known */ tn->telrcv_state = CURL_TS_DATA; /* Init suboptions */ CURL_SB_CLEAR(tn); - /* Set all options to NO */ -#if 0 - /* NO is zero => default fill pattern */ - memset(tn->us, CURL_NO, 256); - memset(tn->usq, CURL_NO, 256); - memset(tn->us_preferred, CURL_NO, 256); - memset(tn->him, CURL_NO, 256); - memset(tn->himq, CURL_NO, 256); - memset(tn->him_preferred, CURL_NO, 256); -#endif /* Set the options we want by default */ tn->us_preferred[CURL_TELOPT_BINARY] = CURL_YES; tn->us_preferred[CURL_TELOPT_SGA] = CURL_YES; @@ -248,12 +236,12 @@ static void negotiate(struct connectdata *conn) { int i; struct TELNET *tn = (struct TELNET *)conn->proto.telnet; - + for(i = 0;i < CURL_NTELOPTS;i++) { if(tn->us_preferred[i] == CURL_YES) set_local_option(conn, i, CURL_YES); - + if(tn->him_preferred[i] == CURL_YES) set_remote_option(conn, i, CURL_YES); } @@ -264,7 +252,7 @@ static void printoption(struct SessionHandle *data, { const char *fmt; const char *opt; - + if (data->set.verbose) { if (cmd == CURL_IAC) @@ -305,9 +293,9 @@ static void send_negotiation(struct connectdata *conn, int cmd, int option) buf[0] = CURL_IAC; buf[1] = cmd; buf[2] = option; - + (void)swrite(conn->sock[FIRSTSOCKET], buf, 3); - + printoption(conn->data, "SENT", cmd, option); } @@ -323,11 +311,11 @@ void set_remote_option(struct connectdata *conn, int option, int newstate) tn->him[option] = CURL_WANTYES; send_negotiation(conn, CURL_DO, option); break; - + case CURL_YES: /* Already enabled */ break; - + case CURL_WANTNO: switch(tn->himq[option]) { @@ -340,7 +328,7 @@ void set_remote_option(struct connectdata *conn, int option, int newstate) break; } break; - + case CURL_WANTYES: switch(tn->himq[option]) { @@ -361,12 +349,12 @@ void set_remote_option(struct connectdata *conn, int option, int newstate) case CURL_NO: /* Already disabled */ break; - + case CURL_YES: tn->him[option] = CURL_WANTNO; send_negotiation(conn, CURL_DONT, option); break; - + case CURL_WANTNO: switch(tn->himq[option]) { @@ -378,7 +366,7 @@ void set_remote_option(struct connectdata *conn, int option, int newstate) break; } break; - + case CURL_WANTYES: switch(tn->himq[option]) { @@ -410,11 +398,11 @@ void rec_will(struct connectdata *conn, int option) send_negotiation(conn, CURL_DONT, option); } break; - + case CURL_YES: /* Already enabled */ break; - + case CURL_WANTNO: switch(tn->himq[option]) { @@ -429,7 +417,7 @@ void rec_will(struct connectdata *conn, int option) break; } break; - + case CURL_WANTYES: switch(tn->himq[option]) { @@ -445,7 +433,7 @@ void rec_will(struct connectdata *conn, int option) break; } } - + static void rec_wont(struct connectdata *conn, int option) { @@ -455,19 +443,19 @@ void rec_wont(struct connectdata *conn, int option) case CURL_NO: /* Already disabled */ break; - + case CURL_YES: tn->him[option] = CURL_NO; send_negotiation(conn, CURL_DONT, option); break; - + case CURL_WANTNO: switch(tn->himq[option]) { case CURL_EMPTY: tn->him[option] = CURL_NO; break; - + case CURL_OPPOSITE: tn->him[option] = CURL_WANTYES; tn->himq[option] = CURL_EMPTY; @@ -475,7 +463,7 @@ void rec_wont(struct connectdata *conn, int option) break; } break; - + case CURL_WANTYES: switch(tn->himq[option]) { @@ -490,7 +478,7 @@ void rec_wont(struct connectdata *conn, int option) break; } } - + static void set_local_option(struct connectdata *conn, int option, int newstate) { @@ -503,11 +491,11 @@ set_local_option(struct connectdata *conn, int option, int newstate) tn->us[option] = CURL_WANTYES; send_negotiation(conn, CURL_WILL, option); break; - + case CURL_YES: /* Already enabled */ break; - + case CURL_WANTNO: switch(tn->usq[option]) { @@ -520,7 +508,7 @@ set_local_option(struct connectdata *conn, int option, int newstate) break; } break; - + case CURL_WANTYES: switch(tn->usq[option]) { @@ -541,12 +529,12 @@ set_local_option(struct connectdata *conn, int option, int newstate) case CURL_NO: /* Already disabled */ break; - + case CURL_YES: tn->us[option] = CURL_WANTNO; send_negotiation(conn, CURL_WONT, option); break; - + case CURL_WANTNO: switch(tn->usq[option]) { @@ -558,7 +546,7 @@ set_local_option(struct connectdata *conn, int option, int newstate) break; } break; - + case CURL_WANTYES: switch(tn->usq[option]) { @@ -590,11 +578,11 @@ void rec_do(struct connectdata *conn, int option) send_negotiation(conn, CURL_WONT, option); } break; - + case CURL_YES: /* Already enabled */ break; - + case CURL_WANTNO: switch(tn->usq[option]) { @@ -609,7 +597,7 @@ void rec_do(struct connectdata *conn, int option) break; } break; - + case CURL_WANTYES: switch(tn->usq[option]) { @@ -626,7 +614,7 @@ void rec_do(struct connectdata *conn, int option) } } -static +static void rec_dont(struct connectdata *conn, int option) { struct TELNET *tn = (struct TELNET *)conn->proto.telnet; @@ -635,19 +623,19 @@ void rec_dont(struct connectdata *conn, int option) case CURL_NO: /* Already disabled */ break; - + case CURL_YES: tn->us[option] = CURL_NO; send_negotiation(conn, CURL_WONT, option); break; - + case CURL_WANTNO: switch(tn->usq[option]) { case CURL_EMPTY: tn->us[option] = CURL_NO; break; - + case CURL_OPPOSITE: tn->us[option] = CURL_WANTYES; tn->usq[option] = CURL_EMPTY; @@ -655,7 +643,7 @@ void rec_dont(struct connectdata *conn, int option) break; } break; - + case CURL_WANTYES: switch(tn->usq[option]) { @@ -746,7 +734,7 @@ static void printsub(struct SessionHandle *data, Curl_infof(data, " NAME"); break; } - + switch(pointer[0]) { case CURL_TELOPT_TTYPE: case CURL_TELOPT_XDISPLOC: @@ -776,7 +764,7 @@ static void printsub(struct SessionHandle *data, Curl_infof(data, " %.2x", pointer[i]); break; } - + if (direction) { Curl_infof(data, "\n"); @@ -986,21 +974,21 @@ void telrcv(struct connectdata *conn, rec_will(conn, c); tn->telrcv_state = CURL_TS_DATA; continue; - + case CURL_TS_WONT: printoption(data, "RCVD", CURL_WONT, c); tn->please_negotiate = 1; rec_wont(conn, c); tn->telrcv_state = CURL_TS_DATA; continue; - + case CURL_TS_DO: printoption(data, "RCVD", CURL_DO, c); tn->please_negotiate = 1; rec_do(conn, c); tn->telrcv_state = CURL_TS_DATA; continue; - + case CURL_TS_DONT: printoption(data, "RCVD", CURL_DONT, c); tn->please_negotiate = 1; @@ -1040,7 +1028,7 @@ void telrcv(struct connectdata *conn, CURL_SB_ACCUM(tn, c); tn->subpointer -= 2; CURL_SB_TERM(tn); - + printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c); suboption(conn); /* handle sub-option */ tn->telrcv_state = CURL_TS_IAC; @@ -1090,7 +1078,7 @@ CURLcode Curl_telnet(struct connectdata *conn) WSAEVENT event_handle; WSANETWORKEVENTS events; HANDLE stdin_handle; - HANDLE objs[2]; + HANDLE objs[2]; DWORD obj_count; DWORD wait_timeout; DWORD waitret; @@ -1099,7 +1087,7 @@ CURLcode Curl_telnet(struct connectdata *conn) fd_set readfd; fd_set keepfd; #endif - ssize_t nread; + ssize_t nread; bool keepon = TRUE; char *buf = data->state.buffer; struct TELNET *tn; @@ -1193,19 +1181,19 @@ CURLcode Curl_telnet(struct connectdata *conn) FreeLibrary(wsock2); return 0; } - - /* If stdin_handle is a pipe, use PeekNamedPipe() method to check it, - else use the old WaitForMultipleObjects() way */ + + /* If stdin_handle is a pipe, use PeekNamedPipe() method to check it, + else use the old WaitForMultipleObjects() way */ if(GetFileType(stdin_handle) == FILE_TYPE_PIPE) { /* Don't wait for stdin_handle, just wait for event_handle */ - obj_count = 1; + obj_count = 1; /* Check stdin_handle per 100 milliseconds */ - wait_timeout = 100; + wait_timeout = 100; } else { obj_count = 2; wait_timeout = INFINITE; } - + /* Keep on listening and act on events */ while(keepon) { waitret = WaitForMultipleObjects(obj_count, objs, FALSE, wait_timeout); @@ -1222,67 +1210,67 @@ CURLcode Curl_telnet(struct connectdata *conn) keepon = FALSE; break; } - + if(!nread) break; - + if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer), &readfile_read, NULL)) { keepon = FALSE; break; } nread = readfile_read; - + while(nread--) { outbuf[0] = *buffer++; out_count = 1; if(outbuf[0] == CURL_IAC) outbuf[out_count++] = CURL_IAC; - + Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf, out_count, &bytes_written); } } - } + } break; - + case WAIT_OBJECT_0 + 1: { unsigned char outbuf[2]; int out_count = 0; ssize_t bytes_written; char *buffer = buf; - + if(!ReadFile(stdin_handle, buf, sizeof(data->state.buffer), &readfile_read, NULL)) { keepon = FALSE; break; } nread = readfile_read; - + while(nread--) { outbuf[0] = *buffer++; out_count = 1; if(outbuf[0] == CURL_IAC) outbuf[out_count++] = CURL_IAC; - + Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf, out_count, &bytes_written); } } break; - + case WAIT_OBJECT_0: if(enum_netevents_func(sockfd, event_handle, &events) != SOCKET_ERROR) { if(events.lNetworkEvents & FD_READ) { /* This reallu OUGHT to check its return code. */ (void)Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread); - + telrcv(conn, (unsigned char *)buf, nread); - + fflush(stdout); - + /* Negotiate if the peer has started negotiating, otherwise don't. We don't want to speak telnet with non-telnet servers, like POP or SMTP. */ @@ -1291,7 +1279,7 @@ CURLcode Curl_telnet(struct connectdata *conn) tn->already_negotiated = 1; } } - + if(events.lNetworkEvents & FD_CLOSE) { keepon = FALSE; } @@ -1340,7 +1328,7 @@ CURLcode Curl_telnet(struct connectdata *conn) int out_count = 0; ssize_t bytes_written; char *buffer = buf; - + nread = read(0, buf, 255); while(nread--) { @@ -1348,7 +1336,7 @@ CURLcode Curl_telnet(struct connectdata *conn) out_count = 1; if(outbuf[0] == CURL_IAC) outbuf[out_count++] = CURL_IAC; - + Curl_write(conn, conn->sock[FIRSTSOCKET], outbuf, out_count, &bytes_written); } diff --git a/lib/transfer.c b/lib/transfer.c index c4e732191..b087fcd86 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -870,13 +870,6 @@ CURLcode Curl_readwrite(struct connectdata *conn, return CURLE_OUT_OF_MEMORY; } } -#if 0 /* for consideration */ - else { - /* This is a Location: but we have not been instructed to - follow it */ - infof(data, "We ignore this location header as instructed\n"); - } -#endif } #endif /* CURL_DISABLE_HTTP */ diff --git a/lib/url.c b/lib/url.c index 4c4453a77..be46e7bcb 100644 --- a/lib/url.c +++ b/lib/url.c @@ -273,13 +273,11 @@ CURLcode Curl_open(struct SessionHandle **curl) CURLcode res = CURLE_OK; struct SessionHandle *data; /* Very simple start-up: alloc the struct, init it with zeroes and return */ - data = (struct SessionHandle *)malloc(sizeof(struct SessionHandle)); + data = (struct SessionHandle *)calloc(1, sizeof(struct SessionHandle)); if(!data) /* this is a very serious error */ return CURLE_OUT_OF_MEMORY; - memset(data, 0, sizeof(struct SessionHandle)); - #ifdef USE_ARES if(ARES_SUCCESS != ares_init(&data->state.areschannel)) { free(data); @@ -1859,7 +1857,6 @@ static int handleSock5Proxy(const char *proxy_name, socksreq[3] = 1; /* IPv4 = 1 */ { -#ifndef ENABLE_IPV6 struct Curl_dns_entry *dns; Curl_addrinfo *hp=NULL; int rc = Curl_resolv(conn, conn->host.name, conn->remote_port, &dns); @@ -1877,24 +1874,28 @@ static int handleSock5Proxy(const char *proxy_name, */ if(dns) hp=dns->addr; - if (hp && hp->h_addr_list[0]) { - socksreq[4] = ((char*)hp->h_addr_list[0])[0]; - socksreq[5] = ((char*)hp->h_addr_list[0])[1]; - socksreq[6] = ((char*)hp->h_addr_list[0])[2]; - socksreq[7] = ((char*)hp->h_addr_list[0])[3]; + if (hp) { + char buf[64]; + unsigned short ip[4]; + Curl_printable_address(hp, buf, sizeof(buf)); + + if(4 == sscanf( buf, "%hu.%hu.%hu.%hu", + &ip[0], &ip[1], &ip[2], &ip[3])) { + socksreq[4] = ip[0]; + socksreq[5] = ip[1]; + socksreq[6] = ip[2]; + socksreq[7] = ip[3]; + } + else + hp = NULL; /* fail! */ Curl_resolv_unlock(conn->data, dns); /* not used anymore from now on */ } - else { + if(!hp) { failf(conn->data, "Failed to resolve \"%s\" for SOCKS5 connect.", conn->host.name); return 1; } -#else - failf(conn->data, - "%s:%d has an internal error and needs to be fixed to work", - __FILE__, __LINE__); -#endif } *((unsigned short*)&socksreq[8]) = htons(conn->remote_port); @@ -1939,7 +1940,7 @@ static CURLcode ConnectPlease(struct connectdata *conn, bool *connected) { CURLcode result; - Curl_ipconnect *addr; + Curl_addrinfo *addr; struct SessionHandle *data = conn->data; char *hostname = data->change.proxy?conn->proxy.name:conn->host.name; @@ -1951,25 +1952,13 @@ static CURLcode ConnectPlease(struct connectdata *conn, *************************************************************/ result= Curl_connecthost(conn, hostaddr, - conn->port, &conn->sock[FIRSTSOCKET], &addr, connected); if(CURLE_OK == result) { - /* 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 - returned from the function above is crucial here. */ - conn->connect_addr = hostaddr; - -#ifdef ENABLE_IPV6 - conn->serv_addr = addr; -#else - memset((char *) &conn->serv_addr, '\0', sizeof(conn->serv_addr)); - memcpy((char *)&(conn->serv_addr.sin_addr), - (struct in_addr *)addr, sizeof(struct in_addr)); - conn->serv_addr.sin_family = hostaddr->addr->h_addrtype; - conn->serv_addr.sin_port = htons((unsigned short)conn->port); -#endif + /* All is cool, then we store the current information */ + conn->dns_entry = hostaddr; + conn->ip_addr = addr; if (conn->data->set.proxytype == CURLPROXY_SOCKS5) { return handleSock5Proxy(conn->proxyuser, @@ -1995,15 +1984,10 @@ static CURLcode ConnectPlease(struct connectdata *conn, static void verboseconnect(struct connectdata *conn) { struct SessionHandle *data = conn->data; - char addrbuf[256] = ""; -#ifdef ENABLE_IPV6 - const Curl_ipconnect *addr = conn->serv_addr; -#else - const Curl_ipconnect *addr = &conn->serv_addr.sin_addr; -#endif + char addrbuf[256]; /* Get a printable version of the network address. */ - Curl_printable_address(addr, addrbuf, sizeof(addrbuf)); + Curl_printable_address(conn->ip_addr, addrbuf, sizeof(addrbuf)); infof(data, "Connected to %s (%s) port %d\n", conn->bits.httpproxy ? conn->proxy.dispname : conn->host.dispname, addrbuf[0] ? addrbuf : "??", conn->port); @@ -3221,8 +3205,8 @@ static CURLcode CreateConnection(struct SessionHandle *data, if(conn->bits.reuse) { /* re-used connection, no resolving is necessary */ hostaddr = NULL; - conn->connect_addr = NULL; /* we don't connect now so we don't have any - fresh connect_addr struct to point to */ + conn->dns_entry = NULL; /* we don't connect now so we don't have any fresh + dns entry struct to point to */ } else { /* this is a fresh connect */ @@ -3476,8 +3460,8 @@ CURLcode Curl_done(struct connectdata **connp, conn->newurl = NULL; } - if(conn->connect_addr) - Curl_resolv_unlock(conn->data, conn->connect_addr); /* done with this */ + if(conn->dns_entry) + Curl_resolv_unlock(conn->data, conn->dns_entry); /* done with this */ #if defined(CURLDEBUG) && defined(AGGRESIVE_TEST) /* scan for DNS cache entries still marked as in use */ diff --git a/lib/urldata.h b/lib/urldata.h index 95aa5fb65..517dc0f3d 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -446,13 +446,9 @@ struct connectdata { #define PROT_SSL (1<<10) /* protocol requires SSL */ /* the particular host we use, in two different ways */ - struct Curl_dns_entry *connect_addr; + struct Curl_dns_entry *dns_entry; + Curl_addrinfo *ip_addr; /* the particular IP we connected to */ -#ifdef ENABLE_IPV6 - struct addrinfo *serv_addr; -#else - struct sockaddr_in serv_addr; -#endif char protostr[16]; /* store the protocol string in this buffer */ struct hostname host; @@ -574,10 +570,6 @@ struct connectdata { struct FTP *ftp; struct FILEPROTO *file; void *telnet; /* private for telnet.c-eyes only */ -#if 0 /* no need for special ones for these: */ - struct LDAP *ldap; - struct DICT *dict; -#endif void *generic; } proto;