diff --git a/lib/cf-socket.c b/lib/cf-socket.c index b059a3cfe2..1511d6f036 100644 --- a/lib/cf-socket.c +++ b/lib/cf-socket.c @@ -86,14 +86,15 @@ #endif /* 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 CURLcode. * @unittest 1607 */ -UNITTEST bool sockaddr2string(struct sockaddr *sa, curl_socklen_t salen, - char *addr, uint16_t *port); -UNITTEST bool sockaddr2string(struct sockaddr *sa, curl_socklen_t salen, - char *addr, uint16_t *port) +UNITTEST CURLcode sockaddr2string(struct sockaddr *sa, curl_socklen_t salen, + char *addr, uint16_t *port); +UNITTEST CURLcode sockaddr2string(struct sockaddr *sa, curl_socklen_t salen, + char *addr, uint16_t *port) { + CURLcode result; struct sockaddr_in *si = NULL; #ifdef USE_IPV6 struct sockaddr_in6 *si6 = NULL; @@ -107,17 +108,21 @@ 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)) { + result = curlx_inet_ntop(sa->sa_family, &si->sin_addr, addr, + MAX_IPADR_LEN); + if(!result) { *port = ntohs(si->sin_port); - return TRUE; + return result; } break; #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)) { + result = curlx_inet_ntop(sa->sa_family, &si6->sin6_addr, addr, + MAX_IPADR_LEN); + if(!result) { *port = ntohs(si6->sin6_port); - return TRUE; + return result; } break; #endif @@ -130,16 +135,16 @@ UNITTEST bool sockaddr2string(struct sockaddr *sa, curl_socklen_t salen, else addr[0] = 0; /* socket with no name */ *port = 0; - return TRUE; + return CURLE_OK; #endif default: + result = CURLE_UNSUPPORTED_PROTOCOL; break; } addr[0] = '\0'; *port = 0; - errno = SOCKEAFNOSUPPORT; - return FALSE; + return result; } static void tcpnodelay(struct Curl_cfilter *cf, @@ -1087,18 +1092,19 @@ static void set_local_ip(struct Curl_cfilter *cf, /* 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); - VERBOSE(char buffer[STRERROR_LEN]); memset(&ssloc, 0, sizeof(ssloc)); if(getsockname(ctx->sock, (struct sockaddr *)&ssloc, &slen)) { + VERBOSE(char buffer[STRERROR_LEN]); VERBOSE(int 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)) { - infof(data, "ssloc inet_ntop() failed with errno %d: %s", - errno, curlx_strerror(errno, buffer, sizeof(buffer))); + else { + CURLcode result = sockaddr2string((struct sockaddr *)&ssloc, slen, + ctx->ip.local_ip, &ctx->ip.local_port); + if(result) + infof(data, "ssloc inet_ntop() failed with %d", (int)result); } } #else @@ -1110,21 +1116,17 @@ static CURLcode set_remote_ip(struct Curl_cfilter *cf, struct Curl_easy *data) { struct cf_socket_ctx *ctx = cf->ctx; + CURLcode result; /* 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)) { - 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; + result = sockaddr2string(&ctx->addr.curl_sa_addr, + (curl_socklen_t)ctx->addr.addrlen, + ctx->ip.remote_ip, &ctx->ip.remote_port); + if(result) { + ctx->sockerr = SOCKEAFNOSUPPORT; /* 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))); + failf(data, "curl_sa_addr inet_ntop() failed with %d", (int)result); return CURLE_FAILED_INIT; } return CURLE_OK; @@ -2156,7 +2158,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]; + CURLcode result; struct Curl_sockaddr_storage ssrem; curl_socklen_t plen; @@ -2165,15 +2167,16 @@ 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)) { + char buffer[STRERROR_LEN]; int 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)) { - failf(data, "ssrem inet_ntop() failed with errno %d: %s", - errno, curlx_strerror(errno, buffer, sizeof(buffer))); + result = sockaddr2string((struct sockaddr *)&ssrem, plen, + ctx->ip.remote_ip, &ctx->ip.remote_port); + if(result) { + failf(data, "ssrem inet_ntop() failed with %d", (int)result); return; } #else diff --git a/lib/curlx/inet_ntop.c b/lib/curlx/inet_ntop.c index 7f6028a791..ed06314520 100644 --- a/lib/curlx/inet_ntop.c +++ b/lib/curlx/inet_ntop.c @@ -48,12 +48,12 @@ /* * Format an IPv4 address, more or less like inet_ntop(). * - * Returns `dst' (as a const) + * Returns CURLcode. * Note: * - 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 CURLcode inet_ntop4(const unsigned char *src, char *dst, size_t size) { char tmp[sizeof("255.255.255.255")]; size_t len; @@ -68,22 +68,16 @@ static char *inet_ntop4(const unsigned char *src, char *dst, size_t size) ((int)((unsigned char)src[3])) & 0xff); len = strlen(tmp); - if(len == 0 || len >= size) { -#ifdef USE_WINSOCK - errno = WSAEINVAL; -#else - errno = ENOSPC; -#endif - return NULL; - } + if(len == 0 || len >= size) + return CURLE_TOO_LARGE; curlx_strcopy(dst, size, tmp, len); - return dst; + return CURLE_OK; } /* * Convert IPv6 binary address into presentation (printable) format. */ -static char *inet_ntop6(const unsigned char *src, char *dst, size_t size) +static CURLcode inet_ntop6(const unsigned char *src, char *dst, size_t size) { /* * Note that int32_t and int16_t need only be "at least" large enough @@ -152,9 +146,9 @@ 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))) { - return NULL; - } + CURLcode result = inet_ntop4(src + 12, tp, sizeof(tmp) - (tp - tmp)); + if(result) + return result; tp += strlen(tp); break; } @@ -181,31 +175,18 @@ static char *inet_ntop6(const unsigned char *src, char *dst, size_t size) *tp++ = ':'; /* Check for overflow, copy, and we are done. */ - if((size_t)(tp - tmp) >= size) { -#ifdef USE_WINSOCK - errno = WSAEINVAL; -#else - errno = ENOSPC; -#endif - return NULL; - } - + if((size_t)(tp - tmp) >= size) + return CURLE_TOO_LARGE; curlx_strcopy(dst, size, tmp, tp - tmp); - return dst; + return CURLE_OK; } /* * 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. + * Copies result to 'buf' and returns CURLcode. */ -char *curlx_inet_ntop(int af, const void *src, char *buf, size_t size) +CURLcode curlx_inet_ntop(int af, const void *src, char *buf, size_t size) { switch(af) { case AF_INET: @@ -213,7 +194,6 @@ char *curlx_inet_ntop(int af, const void *src, char *buf, size_t size) case AF_INET6: return inet_ntop6((const unsigned char *)src, buf, size); default: - errno = SOCKEAFNOSUPPORT; - return NULL; + return CURLE_UNSUPPORTED_PROTOCOL; } } diff --git a/lib/curlx/inet_ntop.h b/lib/curlx/inet_ntop.h index 8f4c636d69..f0abeb80b7 100644 --- a/lib/curlx/inet_ntop.h +++ b/lib/curlx/inet_ntop.h @@ -25,6 +25,6 @@ ***************************************************************************/ #include "curl_setup.h" -char *curlx_inet_ntop(int af, const void *src, char *buf, size_t size); +CURLcode curlx_inet_ntop(int af, const void *src, char *buf, size_t size); #endif /* HEADER_CURL_INET_NTOP_H */ diff --git a/lib/ftp.c b/lib/ftp.c index 1e17cb3467..3a4859d188 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -1022,7 +1022,7 @@ static CURLcode ftp_port_default_host(struct Curl_easy *data, struct sockaddr_in6 * const sa6 = (void *)sa; #endif char buffer[STRERROR_LEN]; - const char *r; + CURLcode result; *sslenp = sizeof(*ss); if(getsockname(conn->sock[FIRSTSOCKET], sa, sslenp)) { @@ -1033,14 +1033,14 @@ 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); + result = curlx_inet_ntop(sa->sa_family, &sa6->sin6_addr, hbuf, hbuflen); break; #endif default: - r = curlx_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, hbuflen); + result = curlx_inet_ntop(sa->sa_family, &sa4->sin_addr, hbuf, hbuflen); break; } - if(!r) + if(result) return CURLE_FTP_PORT_FAILED; *hostp = hbuf; diff --git a/lib/if2ip.c b/lib/if2ip.c index 5ae256e13c..9a9fbe7691 100644 --- a/lib/if2ip.c +++ b/lib/if2ip.c @@ -112,9 +112,9 @@ if2ip_result_t Curl_if2ip(int af, if(iface->ifa_addr->sa_family == af) { if(curl_strequal(iface->ifa_name, interf)) { void *addr; - const char *ip; char scope[12] = ""; char ipstr[64]; + CURLcode result; #ifdef USE_IPV6 if(af == AF_INET6) { #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID @@ -155,8 +155,8 @@ 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)); - curl_msnprintf(buf, buf_size, "%s%s", ip, scope); + result = curlx_inet_ntop(af, addr, ipstr, sizeof(ipstr)); + curl_msnprintf(buf, buf_size, "%s%s", result ? "" : ipstr, scope); break; } } @@ -188,7 +188,7 @@ if2ip_result_t Curl_if2ip(int af, struct sockaddr_in *s; curl_socket_t dummy; size_t len; - const char *r; + CURLcode result; #ifdef USE_IPV6 (void)remote_scope; @@ -228,10 +228,10 @@ 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); + result = curlx_inet_ntop(s->sin_family, &in, buf, buf_size); sclose(dummy); - if(!r) + if(result) return IF2IP_NOT_FOUND; return IF2IP_FOUND; } diff --git a/lib/urlapi.c b/lib/urlapi.c index 1b498e95d0..e787773ced 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)) { hlen = strlen(hostname); /* might be shorter now */ hostname[hlen + 1] = 0; } diff --git a/lib/vdns/httpsrr.c b/lib/vdns/httpsrr.c index 29c78a333b..98a3c89496 100644 --- a/lib/vdns/httpsrr.c +++ b/lib/vdns/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))) result = curlx_dyn_add(dyn, ""); else result = curlx_dyn_addf(dyn, "%s%s", sep, buf); diff --git a/tests/server/dnsd.c b/tests/server/dnsd.c index 62cbb8d9cf..c2d01c0aaa 100644 --- a/tests/server/dnsd.c +++ b/tests/server/dnsd.c @@ -606,6 +606,7 @@ static int dnsd_make_answer(struct blob *blob, int query_id, }; uint16_t ancount = 0; unsigned char rcode = 0; + CURLcode result; /* read once per incoming query, which is probably more than one per test case */ @@ -656,12 +657,11 @@ static int dnsd_make_answer(struct blob *blob, int query_id, case QTYPE_A: for(a = 0; !rcode && (a < ancount_a); a++) { const unsigned char *store = ipv4_pref; - const char *ip; if(add_answer(blob, store, sizeof(ipv4_pref), QTYPE_A)) return 1; - ip = curlx_inet_ntop(AF_INET, store, addrbuf, sizeof(addrbuf)); - logmsg("[%d] response A (%x) '%s'", query_id, (unsigned int)QTYPE_A, - ip ? ip : "(null)"); + result = curlx_inet_ntop(AF_INET, store, addrbuf, sizeof(addrbuf)); + logmsg("[%d] response A (%x) '%s' (%d)", query_id, + (unsigned int)QTYPE_A, result ? "?" : addrbuf, (int)result); } if(!ancount_a) logmsg("[%d] response A empty", query_id); @@ -669,12 +669,11 @@ static int dnsd_make_answer(struct blob *blob, int query_id, case QTYPE_AAAA: for(a = 0; !rcode && (a < ancount_aaaa); a++) { const unsigned char *store = ipv6_pref; - const char *ip; if(add_answer(blob, store, sizeof(ipv6_pref), QTYPE_AAAA)) return 1; - ip = curlx_inet_ntop(AF_INET6, store, addrbuf, sizeof(addrbuf)); - logmsg("[%d] response AAAA (%x) '%s'", query_id, - (unsigned int)QTYPE_AAAA, ip ? ip : "(null)"); + result = curlx_inet_ntop(AF_INET6, store, addrbuf, sizeof(addrbuf)); + logmsg("[%d] response AAAA (%x) '%s' (%d)", query_id, + (unsigned int)QTYPE_AAAA, result ? "?" : addrbuf, (int)result); } if(!ancount_aaaa) logmsg("[%d] response AAAA empty", query_id); diff --git a/tests/unit/unit1607.c b/tests/unit/unit1607.c index 2b55621340..72df3808ca 100644 --- a/tests/unit/unit1607.c +++ b/tests/unit/unit1607.c @@ -147,8 +147,8 @@ static CURLcode test_unit1607(const char *arg) if(tests[i].address[j] == &skip) continue; - if(addr && !sockaddr2string(addr->ai_addr, addr->ai_addrlen, - ipaddress, &port)) { + if(addr && sockaddr2string(addr->ai_addr, addr->ai_addrlen, + ipaddress, &port)) { 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..076bf21499 100644 --- a/tests/unit/unit1609.c +++ b/tests/unit/unit1609.c @@ -146,8 +146,8 @@ static CURLcode test_unit1609(const char *arg) if(!addr && !tests[i].address[j]) break; - if(addr && !sockaddr2string(addr->ai_addr, addr->ai_addrlen, - ipaddress, &port)) { + if(addr && sockaddr2string(addr->ai_addr, addr->ai_addrlen, + ipaddress, &port)) { 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..1aa28a25bf 100644 --- a/tests/unit/unit1961.c +++ b/tests/unit/unit1961.c @@ -48,8 +48,6 @@ static int test_ntop(void) char ipv4res[sizeof("255.255.255.255")]; unsigned char ipv6a[26]; unsigned char ipv4a[5]; - const char *ipv6ptr = 0; - const char *ipv4ptr = 0; ipv4res[0] = '\0'; ipv4a[0] = 0xc0; @@ -57,12 +55,9 @@ static int test_ntop(void) ipv4a[2] = 0x64; ipv4a[3] = 0x01; ipv4a[4] = 0x01; - ipv4ptr = curlx_inet_ntop(AF_INET, ipv4a, ipv4res, sizeof(ipv4res)); - if(!ipv4ptr) + if(curlx_inet_ntop(AF_INET, ipv4a, ipv4res, sizeof(ipv4res))) return 1; /* fail */ - if(ipv4ptr != ipv4res) - return 1; /* fail */ - if(!ipv4ptr[0]) + if(!ipv4res[0]) return 1; /* fail */ if(memcmp(ipv4res, "192.168.100.1", 13)) return 1; /* fail */ @@ -80,12 +75,9 @@ static int test_ntop(void) ipv6a[14] = 0x76; ipv6a[15] = 0xc8; ipv6a[25] = 0x01; - ipv6ptr = curlx_inet_ntop(AF_INET6, ipv6a, ipv6res, sizeof(ipv6res)); - if(!ipv6ptr) + if(curlx_inet_ntop(AF_INET6, ipv6a, ipv6res, sizeof(ipv6res))) return 1; /* fail */ - if(ipv6ptr != ipv6res) - return 1; /* fail */ - if(!ipv6ptr[0]) + if(!ipv6res[0]) return 1; /* fail */ if(memcmp(ipv6res, "fe80::214:4fff:fe0b:76c8", 24)) return 1; /* fail */ @@ -96,12 +88,9 @@ static int test_ntop(void) ipv6a[13] = 0x0; ipv6a[14] = 0x0; ipv6a[15] = 0x01; - ipv6ptr = curlx_inet_ntop(AF_INET6, ipv6a, ipv6res, sizeof(ipv6res)); - if(!ipv6ptr) + if(curlx_inet_ntop(AF_INET6, ipv6a, ipv6res, sizeof(ipv6res))) return 1; /* fail */ - if(ipv6ptr != ipv6res) - return 1; /* fail */ - if(!ipv6ptr[0]) + if(!ipv6res[0]) return 1; /* fail */ if(memcmp(ipv6res, "::127.0.0.1", 11)) return 1; /* fail */