diff --git a/lib/cf-socket.c b/lib/cf-socket.c index 9c65963ce3..74dbc65317 100644 --- a/lib/cf-socket.c +++ b/lib/cf-socket.c @@ -84,13 +84,13 @@ /* retrieves ip address and port from a sockaddr structure. note it calls - * curlx_inet_ntop which sets errno on fail, not SOCKERRNO. + * curlx_inet_ntop() and returns socket error. * @unittest 1607 */ UNITTEST bool sockaddr2string(struct sockaddr *sa, curl_socklen_t salen, - char *addr, uint16_t *port); + char *addr, uint16_t *port, int *sockerr); UNITTEST bool sockaddr2string(struct sockaddr *sa, curl_socklen_t salen, - char *addr, uint16_t *port) + char *addr, uint16_t *port, int *sockerr) { struct sockaddr_in *si = NULL; #ifdef USE_IPV6 @@ -105,7 +105,8 @@ UNITTEST bool sockaddr2string(struct sockaddr *sa, curl_socklen_t salen, switch(sa->sa_family) { case AF_INET: si = (struct sockaddr_in *)(void *)sa; - if(curlx_inet_ntop(sa->sa_family, &si->sin_addr, addr, MAX_IPADR_LEN)) { + if(curlx_inet_ntop(sa->sa_family, &si->sin_addr, addr, MAX_IPADR_LEN, + sockerr)) { *port = ntohs(si->sin_port); return TRUE; } @@ -113,7 +114,8 @@ UNITTEST bool sockaddr2string(struct sockaddr *sa, curl_socklen_t salen, #ifdef USE_IPV6 case AF_INET6: si6 = (struct sockaddr_in6 *)(void *)sa; - if(curlx_inet_ntop(sa->sa_family, &si6->sin6_addr, addr, MAX_IPADR_LEN)) { + if(curlx_inet_ntop(sa->sa_family, &si6->sin6_addr, addr, MAX_IPADR_LEN, + sockerr)) { *port = ntohs(si6->sin6_port); return TRUE; } @@ -128,6 +130,7 @@ UNITTEST bool sockaddr2string(struct sockaddr *sa, curl_socklen_t salen, else addr[0] = 0; /* socket with no name */ *port = 0; + *sockerr = 0; return TRUE; #endif default: @@ -136,7 +139,7 @@ UNITTEST bool sockaddr2string(struct sockaddr *sa, curl_socklen_t salen, addr[0] = '\0'; *port = 0; - errno = SOCKEAFNOSUPPORT; + *sockerr = SOCKEAFNOSUPPORT; return FALSE; } @@ -1082,6 +1085,7 @@ static void set_local_ip(struct Curl_cfilter *cf, #ifdef HAVE_GETSOCKNAME if((ctx->sock != CURL_SOCKET_BAD) && !(data->conn->scheme->protocol & CURLPROTO_TFTP)) { + int sockerr; /* TFTP does not connect, so it cannot get the IP like this */ struct Curl_sockaddr_storage ssloc; curl_socklen_t slen = sizeof(struct Curl_sockaddr_storage); @@ -1089,14 +1093,15 @@ static void set_local_ip(struct Curl_cfilter *cf, memset(&ssloc, 0, sizeof(ssloc)); if(getsockname(ctx->sock, (struct sockaddr *)&ssloc, &slen)) { - VERBOSE(int sockerr = SOCKERRNO); + sockerr = SOCKERRNO; infof(data, "getsockname() failed with errno %d: %s", sockerr, curlx_strerror(sockerr, buffer, sizeof(buffer))); } else if(!sockaddr2string((struct sockaddr *)&ssloc, slen, - ctx->ip.local_ip, &ctx->ip.local_port)) { + ctx->ip.local_ip, &ctx->ip.local_port, + &sockerr)) { infof(data, "ssloc inet_ntop() failed with errno %d: %s", - errno, curlx_strerror(errno, buffer, sizeof(buffer))); + sockerr, curlx_strerror(sockerr, buffer, sizeof(buffer))); } } #else @@ -1108,21 +1113,18 @@ static CURLcode set_remote_ip(struct Curl_cfilter *cf, struct Curl_easy *data) { struct cf_socket_ctx *ctx = cf->ctx; + int sockerr; /* store remote address and port used in this connection attempt */ ctx->ip.transport = ctx->transport; if(!sockaddr2string(&ctx->addr.curl_sa_addr, (curl_socklen_t)ctx->addr.addrlen, - ctx->ip.remote_ip, &ctx->ip.remote_port)) { + ctx->ip.remote_ip, &ctx->ip.remote_port, &sockerr)) { char buffer[STRERROR_LEN]; - - /* using bare errno instead of SOCKERRNO is safe here, because - sockaddr2string() calls curlx_inet_ntop(), and they both report failures - via errno (even on Windows builds). */ - ctx->sockerr = errno; + ctx->sockerr = sockerr; /* malformed address or bug in inet_ntop, try next address */ failf(data, "curl_sa_addr inet_ntop() failed with errno %d: %s", - errno, curlx_strerror(errno, buffer, sizeof(buffer))); + sockerr, curlx_strerror(sockerr, buffer, sizeof(buffer))); return CURLE_FAILED_INIT; } return CURLE_OK; @@ -2106,6 +2108,7 @@ static void cf_tcp_set_accepted_remote_ip(struct Curl_cfilter *cf, struct cf_socket_ctx *ctx = cf->ctx; #ifdef HAVE_GETPEERNAME char buffer[STRERROR_LEN]; + int sockerr; struct Curl_sockaddr_storage ssrem; curl_socklen_t plen; @@ -2114,15 +2117,15 @@ static void cf_tcp_set_accepted_remote_ip(struct Curl_cfilter *cf, plen = sizeof(ssrem); memset(&ssrem, 0, plen); if(getpeername(ctx->sock, (struct sockaddr *)&ssrem, &plen)) { - int sockerr = SOCKERRNO; + sockerr = SOCKERRNO; failf(data, "getpeername() failed with errno %d: %s", sockerr, curlx_strerror(sockerr, buffer, sizeof(buffer))); return; } if(!sockaddr2string((struct sockaddr *)&ssrem, plen, - ctx->ip.remote_ip, &ctx->ip.remote_port)) { + ctx->ip.remote_ip, &ctx->ip.remote_port, &sockerr)) { failf(data, "ssrem inet_ntop() failed with errno %d: %s", - errno, curlx_strerror(errno, buffer, sizeof(buffer))); + sockerr, curlx_strerror(sockerr, buffer, sizeof(buffer))); return; } #else diff --git a/lib/curlx/inet_ntop.c b/lib/curlx/inet_ntop.c index 7f6028a791..751266dbbc 100644 --- a/lib/curlx/inet_ntop.c +++ b/lib/curlx/inet_ntop.c @@ -53,7 +53,8 @@ * - uses no static variables * - takes an unsigned char* not an in_addr as input */ -static char *inet_ntop4(const unsigned char *src, char *dst, size_t size) +static char *inet_ntop4(const unsigned char *src, char *dst, size_t size, + int *sockerr) { char tmp[sizeof("255.255.255.255")]; size_t len; @@ -69,13 +70,12 @@ static char *inet_ntop4(const unsigned char *src, char *dst, size_t size) len = strlen(tmp); if(len == 0 || len >= size) { -#ifdef USE_WINSOCK - errno = WSAEINVAL; -#else - errno = ENOSPC; -#endif + if(sockerr) + *sockerr = SOCKEINVAL; return NULL; } + if(sockerr) + *sockerr = 0; curlx_strcopy(dst, size, tmp, len); return dst; } @@ -83,7 +83,8 @@ static char *inet_ntop4(const unsigned char *src, char *dst, size_t size) /* * Convert IPv6 binary address into presentation (printable) format. */ -static char *inet_ntop6(const unsigned char *src, char *dst, size_t size) +static char *inet_ntop6(const unsigned char *src, char *dst, size_t size, + int *sockerr) { /* * Note that int32_t and int16_t need only be "at least" large enough @@ -152,7 +153,7 @@ static char *inet_ntop6(const unsigned char *src, char *dst, size_t size) */ if(i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { - if(!inet_ntop4(src + 12, tp, sizeof(tmp) - (tp - tmp))) { + if(!inet_ntop4(src + 12, tp, sizeof(tmp) - (tp - tmp), sockerr)) { return NULL; } tp += strlen(tp); @@ -182,14 +183,12 @@ static char *inet_ntop6(const unsigned char *src, char *dst, size_t size) /* Check for overflow, copy, and we are done. */ if((size_t)(tp - tmp) >= size) { -#ifdef USE_WINSOCK - errno = WSAEINVAL; -#else - errno = ENOSPC; -#endif + if(sockerr) + *sockerr = SOCKEINVAL; return NULL; } - + if(sockerr) + *sockerr = 0; curlx_strcopy(dst, size, tmp, tp - tmp); return dst; } @@ -198,22 +197,20 @@ static char *inet_ntop6(const unsigned char *src, char *dst, size_t size) * Convert a network format address to presentation format. * * Returns pointer to presentation format address (`buf'). - * Returns NULL on error and errno set with the specific - * error, EAFNOSUPPORT or ENOSPC. - * - * On Windows we store the error in the thread errno, not in the Winsock error - * code. This is to avoid losing the actual last Winsock error. When this - * function returns NULL, check errno not SOCKERRNO. + * Returns NULL on error and sockerr set (if not NULL) with the specific error, + * SOCKEAFNOSUPPORT or SOCKEINVAL. */ -char *curlx_inet_ntop(int af, const void *src, char *buf, size_t size) +char *curlx_inet_ntop(int af, const void *src, char *buf, size_t size, + int *sockerr) { switch(af) { case AF_INET: - return inet_ntop4((const unsigned char *)src, buf, size); + return inet_ntop4((const unsigned char *)src, buf, size, sockerr); case AF_INET6: - return inet_ntop6((const unsigned char *)src, buf, size); + return inet_ntop6((const unsigned char *)src, buf, size, sockerr); default: - errno = SOCKEAFNOSUPPORT; + if(sockerr) + *sockerr = SOCKEAFNOSUPPORT; return NULL; } } diff --git a/lib/curlx/inet_ntop.h b/lib/curlx/inet_ntop.h index 8f4c636d69..421a14036a 100644 --- a/lib/curlx/inet_ntop.h +++ b/lib/curlx/inet_ntop.h @@ -25,6 +25,7 @@ ***************************************************************************/ #include "curl_setup.h" -char *curlx_inet_ntop(int af, const void *src, char *buf, size_t size); +char *curlx_inet_ntop(int af, const void *src, char *buf, size_t size, + int *sockerr); #endif /* HEADER_CURL_INET_NTOP_H */ diff --git a/lib/curlx/inet_pton.c b/lib/curlx/inet_pton.c index b3e806602a..23e76725fe 100644 --- a/lib/curlx/inet_pton.c +++ b/lib/curlx/inet_pton.c @@ -196,10 +196,6 @@ static int inet_pton6(const char *src, unsigned char *dst) * 0 if the address was not valid (`dst' is untouched in this case) * -1 if some other error occurred (`dst' is untouched in this case, too) * - * On Windows we store the error in the thread errno, not in the Winsock error - * code. This is to avoid losing the actual last Winsock error. When this - * function returns NULL, check errno not SOCKERRNO. - * * author: * Paul Vixie, 1996. */ @@ -211,7 +207,6 @@ int curlx_inet_pton(int af, const char *src, void *dst) case AF_INET6: return inet_pton6(src, (unsigned char *)dst); default: - errno = SOCKEAFNOSUPPORT; return -1; } /* NOTREACHED */ diff --git a/lib/ftp.c b/lib/ftp.c index 811e58508b..3755813d00 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -1033,11 +1033,11 @@ static CURLcode ftp_port_default_host(struct Curl_easy *data, switch(sa->sa_family) { #ifdef USE_IPV6 case AF_INET6: - r = curlx_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, hbuflen); + r = curlx_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, hbuflen, NULL); break; #endif default: - r = curlx_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, hbuflen); + r = curlx_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, hbuflen, NULL); break; } if(!r) diff --git a/lib/hostip.c b/lib/hostip.c index 7427f8fdd9..d63585f518 100644 --- a/lib/hostip.c +++ b/lib/hostip.c @@ -182,14 +182,16 @@ void Curl_printable_address(const struct Curl_addrinfo *ai, char *buf, case AF_INET: { const struct sockaddr_in *sa4 = (const void *)ai->ai_addr; const struct in_addr *ipaddr4 = &sa4->sin_addr; - (void)curlx_inet_ntop(ai->ai_family, (const void *)ipaddr4, buf, bufsize); + (void)curlx_inet_ntop(ai->ai_family, (const void *)ipaddr4, buf, bufsize, + NULL); break; } #ifdef USE_IPV6 case AF_INET6: { const struct sockaddr_in6 *sa6 = (const void *)ai->ai_addr; const struct in6_addr *ipaddr6 = &sa6->sin6_addr; - (void)curlx_inet_ntop(ai->ai_family, (const void *)ipaddr6, buf, bufsize); + (void)curlx_inet_ntop(ai->ai_family, (const void *)ipaddr6, buf, bufsize, + NULL); break; } #endif diff --git a/lib/httpsrr.c b/lib/httpsrr.c index 441fe350b1..ac2fc2ffc9 100644 --- a/lib/httpsrr.c +++ b/lib/httpsrr.c @@ -82,7 +82,7 @@ static CURLcode httpsrr_print_addr(struct dynbuf *dyn, CURLcode result = CURLE_OK; for(i = 0; (i < (total_len / alen)) && !result; ++i) { - if(!curlx_inet_ntop(ai_family, addr + (i * alen), buf, sizeof(buf))) + if(!curlx_inet_ntop(ai_family, addr + (i * alen), buf, sizeof(buf), NULL)) result = curlx_dyn_add(dyn, ""); else result = curlx_dyn_addf(dyn, "%s%s", sep, buf); diff --git a/lib/if2ip.c b/lib/if2ip.c index 5ae256e13c..d8b7f0142a 100644 --- a/lib/if2ip.c +++ b/lib/if2ip.c @@ -155,7 +155,7 @@ if2ip_result_t Curl_if2ip(int af, addr = &((struct sockaddr_in *)(void *)iface->ifa_addr)->sin_addr; res = IF2IP_FOUND; - ip = curlx_inet_ntop(af, addr, ipstr, sizeof(ipstr)); + ip = curlx_inet_ntop(af, addr, ipstr, sizeof(ipstr), NULL); curl_msnprintf(buf, buf_size, "%s%s", ip, scope); break; } @@ -228,7 +228,7 @@ if2ip_result_t Curl_if2ip(int af, s = (struct sockaddr_in *)(void *)&req.ifr_addr; memcpy(&in, &s->sin_addr, sizeof(in)); - r = curlx_inet_ntop(s->sin_family, &in, buf, buf_size); + r = curlx_inet_ntop(s->sin_family, &in, buf, buf_size, NULL); sclose(dummy); if(!r) diff --git a/lib/urlapi.c b/lib/urlapi.c index 1e61fbcae5..5d997b7f5d 100644 --- a/lib/urlapi.c +++ b/lib/urlapi.c @@ -467,7 +467,7 @@ UNITTEST CURLUcode ipv6_parse(struct Curl_URL *u, char *hostname, hostname[hlen] = 0; /* end the address there */ if(curlx_inet_pton(AF_INET6, hostname, dest) != 1) return CURLUE_BAD_IPV6; - if(curlx_inet_ntop(AF_INET6, dest, hostname, hlen + 1)) { + if(curlx_inet_ntop(AF_INET6, dest, hostname, hlen + 1, NULL)) { hlen = strlen(hostname); /* might be shorter now */ hostname[hlen + 1] = 0; } diff --git a/tests/server/dnsd.c b/tests/server/dnsd.c index 9d460d9452..73a6ebeb5c 100644 --- a/tests/server/dnsd.c +++ b/tests/server/dnsd.c @@ -508,7 +508,7 @@ create_resp(int qid, const struct sockaddr *addr, curl_socklen_t addrlen, const char *ip; if(add_answer(&resp->body, store, sizeof(ipv4_pref), QTYPE_A)) goto error; - ip = curlx_inet_ntop(AF_INET, store, addrbuf, sizeof(addrbuf)); + ip = curlx_inet_ntop(AF_INET, store, addrbuf, sizeof(addrbuf), NULL); logmsg("[%d] response A (%x) '%s'", qid, (unsigned int)QTYPE_A, ip ? ip : "(null)"); } @@ -521,7 +521,7 @@ create_resp(int qid, const struct sockaddr *addr, curl_socklen_t addrlen, const char *ip; if(add_answer(&resp->body, store, sizeof(ipv6_pref), QTYPE_AAAA)) goto error; - ip = curlx_inet_ntop(AF_INET6, store, addrbuf, sizeof(addrbuf)); + ip = curlx_inet_ntop(AF_INET6, store, addrbuf, sizeof(addrbuf), NULL); logmsg("[%d] response AAAA (%x) '%s'", qid, (unsigned int)QTYPE_AAAA, ip ? ip : "(null)"); } diff --git a/tests/unit/unit1607.c b/tests/unit/unit1607.c index 2b55621340..f234588466 100644 --- a/tests/unit/unit1607.c +++ b/tests/unit/unit1607.c @@ -140,6 +140,7 @@ static CURLcode test_unit1607(const char *arg) for(j = 0; j < addressnum; ++j) { uint16_t port = 0; char ipaddress[MAX_IPADR_LEN] = { 0 }; + int sockerr; if(!addr && !tests[i].address[j]) break; @@ -148,7 +149,7 @@ static CURLcode test_unit1607(const char *arg) continue; if(addr && !sockaddr2string(addr->ai_addr, addr->ai_addrlen, - ipaddress, &port)) { + ipaddress, &port, &sockerr)) { curl_mfprintf(stderr, "%s:%d tests[%zu] failed. " "getaddressinfo failed.\n", __FILE__, __LINE__, i); diff --git a/tests/unit/unit1609.c b/tests/unit/unit1609.c index d7970a5cc6..614170b946 100644 --- a/tests/unit/unit1609.c +++ b/tests/unit/unit1609.c @@ -142,12 +142,13 @@ static CURLcode test_unit1609(const char *arg) for(j = 0; j < addressnum; ++j) { uint16_t port = 0; char ipaddress[MAX_IPADR_LEN] = { 0 }; + int sockerr; if(!addr && !tests[i].address[j]) break; if(addr && !sockaddr2string(addr->ai_addr, addr->ai_addrlen, - ipaddress, &port)) { + ipaddress, &port, &sockerr)) { curl_mfprintf(stderr, "%s:%d tests[%zu] failed. Curl_addr2string failed.\n", __FILE__, __LINE__, i); diff --git a/tests/unit/unit1961.c b/tests/unit/unit1961.c index 338eeb176b..84d6e12d1f 100644 --- a/tests/unit/unit1961.c +++ b/tests/unit/unit1961.c @@ -57,7 +57,7 @@ static int test_ntop(void) ipv4a[2] = 0x64; ipv4a[3] = 0x01; ipv4a[4] = 0x01; - ipv4ptr = curlx_inet_ntop(AF_INET, ipv4a, ipv4res, sizeof(ipv4res)); + ipv4ptr = curlx_inet_ntop(AF_INET, ipv4a, ipv4res, sizeof(ipv4res), NULL); if(!ipv4ptr) return 1; /* fail */ if(ipv4ptr != ipv4res) @@ -80,7 +80,7 @@ static int test_ntop(void) ipv6a[14] = 0x76; ipv6a[15] = 0xc8; ipv6a[25] = 0x01; - ipv6ptr = curlx_inet_ntop(AF_INET6, ipv6a, ipv6res, sizeof(ipv6res)); + ipv6ptr = curlx_inet_ntop(AF_INET6, ipv6a, ipv6res, sizeof(ipv6res), NULL); if(!ipv6ptr) return 1; /* fail */ if(ipv6ptr != ipv6res) @@ -96,7 +96,7 @@ static int test_ntop(void) ipv6a[13] = 0x0; ipv6a[14] = 0x0; ipv6a[15] = 0x01; - ipv6ptr = curlx_inet_ntop(AF_INET6, ipv6a, ipv6res, sizeof(ipv6res)); + ipv6ptr = curlx_inet_ntop(AF_INET6, ipv6a, ipv6res, sizeof(ipv6res), NULL); if(!ipv6ptr) return 1; /* fail */ if(ipv6ptr != ipv6res)