curlx_inet_ntop: return `CURLcode`, drop setting `errno`
No binary (build failed)
—
(log yok)
| @@ -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 | |
| @@ -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; |
| } | |
| } | |
| @@ -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 */ | |
| @@ -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; | |
| @@ -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; | |
| } | |
| @@ -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; | |
| } | |
| @@ -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, "<error parsing address>"); | |
| else | |
| result = curlx_dyn_addf(dyn, "%s%s", sep, buf); | |
| @@ -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); | |
| @@ -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); | |
| @@ -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); | |
| @@ -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) |
| - | return 1; /* fail */ |
| - | if(ipv6ptr != ipv6res) |
| + | if(curlx_inet_ntop(AF_INET6, ipv6a, ipv6res, sizeof(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) |
| - | return 1; /* fail */ |
| - | if(ipv6ptr != ipv6res) |
| + | if(curlx_inet_ntop(AF_INET6, ipv6a, ipv6res, sizeof(ipv6res))) |
| return 1; /* fail */ | |
| - | if(!ipv6ptr[0]) |
| + | if(!ipv6res[0]) |
| return 1; /* fail */ | |
| if(memcmp(ipv6res, "::127.0.0.1", 11)) | |
| return 1; /* fail */ | |