diff options
author | Olivier Nicole <olivier@chnik.fr> | 2022-08-01 14:08:56 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-01 14:08:56 +0200 |
commit | 4ec8c91d5a8ea245f2ba6e980fb9a16b536a4263 (patch) | |
tree | 3d94d47b1f8d92f849ab145cebbe19e42704419c /otherlibs | |
parent | 9653e0d6b092b5147aa1a7c4518dd747092e21b8 (diff) | |
download | ocaml-4ec8c91d5a8ea245f2ba6e980fb9a16b536a4263.tar.gz |
Fix gethostbyaddr for IPv6 arguments and make it domain-safe (#11461)
caml_gethostbyaddr would always call gethostbyaddr with an IPv4 address
type and structure, even when its argument is an IPv6 address. This
commit also removes a file-local mutable variable for the sake of domain
safety.
Added a test.
Diffstat (limited to 'otherlibs')
-rw-r--r-- | otherlibs/unix/gethost.c | 50 |
1 files changed, 34 insertions, 16 deletions
diff --git a/otherlibs/unix/gethost.c b/otherlibs/unix/gethost.c index e7fa2c2db7..34480cdc04 100644 --- a/otherlibs/unix/gethost.c +++ b/otherlibs/unix/gethost.c @@ -36,22 +36,22 @@ #define GETHOSTBYNAME_IS_REENTRANT 1 #endif -static int entry_h_length; - -static value alloc_one_addr(char const *a) +static value alloc_one_addr_ipv4(char const *a) { struct in_addr addr; -#ifdef HAS_IPV6 - struct in6_addr addr6; - if (entry_h_length == 16) { - memmove(&addr6, a, 16); - return caml_unix_alloc_inet6_addr(&addr6); - } -#endif memmove (&addr, a, 4); return caml_unix_alloc_inet_addr(&addr); } +#ifdef HAS_IPV6 +static value alloc_one_addr_ipv6(char const *a) +{ + struct in6_addr addr6; + memmove(&addr6, a, 16); + return caml_unix_alloc_inet6_addr(&addr6); +} +#endif + static value alloc_host_entry(struct hostent *entry) { CAMLparam0(); @@ -65,9 +65,10 @@ static value alloc_host_entry(struct hostent *entry) aliases = caml_copy_string_array((const char**)entry->h_aliases); else aliases = Atom(0); - entry_h_length = entry->h_length; addr_list = - caml_alloc_array(alloc_one_addr, (const char**)entry->h_addr_list); + caml_alloc_array((entry->h_addrtype == AF_INET6) ? + alloc_one_addr_ipv6 : alloc_one_addr_ipv4, + (const char**)entry->h_addr_list); res = caml_alloc_small(4, 0); Field(res, 0) = name; Field(res, 1) = aliases; @@ -82,14 +83,31 @@ static value alloc_host_entry(struct hostent *entry) CAMLprim value caml_unix_gethostbyaddr(value a) { - struct in_addr adr = GET_INET_ADDR(a); + char * adr; + struct in_addr in4; struct hostent * hp; + int addr_type = AF_INET; + socklen_t addr_len = 4; +#if HAS_IPV6 + struct in6_addr in6; + if (caml_string_length(a) == 16) { + addr_type = AF_INET6; + addr_len = 16; + in6 = GET_INET6_ADDR(a); + adr = (char *)&in6; + } else { +#endif + in4 = GET_INET_ADDR(a); + adr = (char *)&in4; +#if HAS_IPV6 + } +#endif #if HAS_GETHOSTBYADDR_R == 7 struct hostent h; char buffer[NETDB_BUFFER_SIZE]; int h_errnop; caml_enter_blocking_section(); - hp = gethostbyaddr_r((char *) &adr, 4, AF_INET, + hp = gethostbyaddr_r(adr, addr_len, addr_type, &h, buffer, sizeof(buffer), &h_errnop); caml_leave_blocking_section(); #elif HAS_GETHOSTBYADDR_R == 8 @@ -97,7 +115,7 @@ CAMLprim value caml_unix_gethostbyaddr(value a) char buffer[NETDB_BUFFER_SIZE]; int h_errnop, rc; caml_enter_blocking_section(); - rc = gethostbyaddr_r((char *) &adr, 4, AF_INET, + rc = gethostbyaddr_r(adr, addr_len, addr_type, &h, buffer, sizeof(buffer), &hp, &h_errnop); caml_leave_blocking_section(); if (rc != 0) hp = NULL; @@ -105,7 +123,7 @@ CAMLprim value caml_unix_gethostbyaddr(value a) #ifdef GETHOSTBYADDR_IS_REENTRANT caml_enter_blocking_section(); #endif - hp = gethostbyaddr((char *) &adr, 4, AF_INET); + hp = gethostbyaddr(adr, addr_len, addr_type); #ifdef GETHOSTBYADDR_IS_REENTRANT caml_leave_blocking_section(); #endif |