diff --git a/ChangeLog b/ChangeLog index 834fca6fdc..bbf38b690a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +2019-01-21 Florian Weimer + + [BZ #20018] + CVE-2016-10739 + resolv: Reject trailing characters in host names + * include/arpa/inet.h (__inet_aton_exact): Declare. + (inet_aton): Remove hidden prototype. No longer used internally. + * nscd/gai.c (__inet_aton): Do not define. + * nscd/gethstbynm3_r.c (__inet_aton): Likewise. + * nss/digits_dots.c (__inet_aton): Likewise. + (__nss_hostname_digits_dots_context): Call __inet_aton_exact. + * resolv/Makefile (tests-internal): Add tst-inet_aton_exact. + (tests): Add tst-resolv-nondecimal, tst-resolv-trailing. + (tst-resolv-nondecimal): Link with libresolv.so and libpthread. + (tst-resolv-trailing): Likewise. + * resolv/Versions (GLIBC_PRIVATE): Export __inet_aton_exact from + libc. + * resolv/inet_addr.c (inet_aton_end): Remame from __inet_aton. + Make static. Add endp parameter. + (__inet_aton_exact): New function. + (__inet_aton_ignore_trailing): New function, aliased to inet_aton. + (__inet_addr): Call inet_aton_end. + * resolv/res_init.c (res_vinit_1): Truncate nameserver for IPv4, + not just IPv6. Call __inet_aton_exact. + * resolv/tst-aton.c: Switch to . + (tests): Make const. Add additional test cases with trailing + characters. + (do_test): Use array_length. + * resolv/tst-inet_aton_exact.c: New file. + * resolv/tst-resolv-trailing.c: Likewise. + * resolv/tst-resolv-nondecimal.c: Likewise. + * sysdeps/posix/getaddrinfo.c (gaih_inet): Call __inet_aton_exact. + 2019-01-21 H.J. Lu [BZ# 24097] diff --git a/NEWS b/NEWS index 7b3af113bf..d863d80f3a 100644 --- a/NEWS +++ b/NEWS @@ -107,6 +107,10 @@ Security related changes: in the assembly string/memory functions would cause a buffer overflow. Reported by H.J. Lu. + CVE-2016-10739: The getaddrinfo function could successfully parse IPv4 + addresses with arbitrary trailing characters, potentially leading to data + or command injection issues in applications. + The following bugs are resolved with this release: [The release manager will add the list generated by diff --git a/include/arpa/inet.h b/include/arpa/inet.h index c3f28f2baa..19aec74275 100644 --- a/include/arpa/inet.h +++ b/include/arpa/inet.h @@ -1,10 +1,10 @@ #include #ifndef _ISOMAC -extern int __inet_aton (const char *__cp, struct in_addr *__inp); -libc_hidden_proto (__inet_aton) +/* Variant of inet_aton which rejects trailing garbage. */ +extern int __inet_aton_exact (const char *__cp, struct in_addr *__inp); +libc_hidden_proto (__inet_aton_exact) -libc_hidden_proto (inet_aton) libc_hidden_proto (inet_ntop) libc_hidden_proto (inet_pton) extern __typeof (inet_pton) __inet_pton; diff --git a/nscd/gai.c b/nscd/gai.c index fd4e8e092f..801d304d47 100644 --- a/nscd/gai.c +++ b/nscd/gai.c @@ -19,7 +19,6 @@ /* This file uses the getaddrinfo code but it compiles it without NSCD support. We just need a few symbol renames. */ -#define __inet_aton inet_aton #define __ioctl ioctl #define __getsockname getsockname #define __socket socket diff --git a/nscd/gethstbynm3_r.c b/nscd/gethstbynm3_r.c index 9f70a86a58..ff594b6d27 100644 --- a/nscd/gethstbynm3_r.c +++ b/nscd/gethstbynm3_r.c @@ -38,8 +38,6 @@ #define HAVE_LOOKUP_BUFFER 1 #define HAVE_AF 1 -#define __inet_aton inet_aton - /* We are nscd, so we don't want to be talking to ourselves. */ #undef USE_NSCD diff --git a/nss/digits_dots.c b/nss/digits_dots.c index 95015896a4..440d9955d2 100644 --- a/nss/digits_dots.c +++ b/nss/digits_dots.c @@ -29,7 +29,6 @@ #include "nsswitch.h" #ifdef USE_NSCD -# define inet_aton __inet_aton # include #endif @@ -160,7 +159,7 @@ __nss_hostname_digits_dots_context (struct resolv_context *ctx, 255.255.255.255? The test below will succeed spuriously... ??? */ if (af == AF_INET) - ok = __inet_aton (name, (struct in_addr *) host_addr); + ok = __inet_aton_exact (name, (struct in_addr *) host_addr); else { assert (af == AF_INET6); diff --git a/resolv/Makefile b/resolv/Makefile index 450e171b01..8f22e6a154 100644 --- a/resolv/Makefile +++ b/resolv/Makefile @@ -34,6 +34,9 @@ routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \ tests = tst-aton tst-leaks tst-inet_ntop xtests = tst-leaks2 +tests-internal += tst-inet_aton_exact + + generate := mtrace-tst-leaks.out tst-leaks.mtrace tst-leaks2.mtrace extra-libs := libresolv libnss_dns @@ -54,8 +57,10 @@ tests += \ tst-resolv-binary \ tst-resolv-edns \ tst-resolv-network \ + tst-resolv-nondecimal \ tst-resolv-res_init-multi \ tst-resolv-search \ + tst-resolv-trailing \ # These tests need libdl. ifeq (yes,$(build-shared)) @@ -190,9 +195,11 @@ $(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \ $(shared-thread-library) $(objpfx)tst-resolv-res_init-thread: $(libdl) $(objpfx)libresolv.so \ $(shared-thread-library) +$(objpfx)tst-resolv-nondecimal: $(objpfx)libresolv.so $(shared-thread-library) $(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library) $(objpfx)tst-resolv-rotate: $(objpfx)libresolv.so $(shared-thread-library) $(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library) +$(objpfx)tst-resolv-trailing: $(objpfx)libresolv.so $(shared-thread-library) $(objpfx)tst-resolv-threads: \ $(libdl) $(objpfx)libresolv.so $(shared-thread-library) $(objpfx)tst-resolv-canonname: \ diff --git a/resolv/Versions b/resolv/Versions index b05778d965..9a82704af7 100644 --- a/resolv/Versions +++ b/resolv/Versions @@ -27,6 +27,7 @@ libc { __h_errno; __resp; __res_iclose; + __inet_aton_exact; __inet_pton_length; __resolv_context_get; __resolv_context_get_preinit; diff --git a/resolv/inet_addr.c b/resolv/inet_addr.c index 32f58b0e13..41b6166a5b 100644 --- a/resolv/inet_addr.c +++ b/resolv/inet_addr.c @@ -96,26 +96,14 @@ #include #include -/* ASCII IPv4 Internet address interpretation routine. The value - returned is in network order. */ -in_addr_t -__inet_addr (const char *cp) -{ - struct in_addr val; - - if (__inet_aton (cp, &val)) - return val.s_addr; - return INADDR_NONE; -} -weak_alias (__inet_addr, inet_addr) - /* Check whether "cp" is a valid ASCII representation of an IPv4 Internet address and convert it to a binary address. Returns 1 if the address is valid, 0 if not. This replaces inet_addr, the return value from which cannot distinguish between failure and a - local broadcast address. */ -int -__inet_aton (const char *cp, struct in_addr *addr) + local broadcast address. Write a pointer to the first + non-converted character to *endp. */ +static int +inet_aton_end (const char *cp, struct in_addr *addr, const char **endp) { static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff }; in_addr_t val; @@ -180,6 +168,7 @@ __inet_aton (const char *cp, struct in_addr *addr) if (addr != NULL) addr->s_addr = res.word | htonl (val); + *endp = cp; __set_errno (saved_errno); return 1; @@ -188,6 +177,41 @@ __inet_aton (const char *cp, struct in_addr *addr) __set_errno (saved_errno); return 0; } -weak_alias (__inet_aton, inet_aton) -libc_hidden_def (__inet_aton) -libc_hidden_weak (inet_aton) + +int +__inet_aton_exact (const char *cp, struct in_addr *addr) +{ + struct in_addr val; + const char *endp; + /* Check that inet_aton_end parsed the entire string. */ + if (inet_aton_end (cp, &val, &endp) != 0 && *endp == 0) + { + *addr = val; + return 1; + } + else + return 0; +} +libc_hidden_def (__inet_aton_exact) + +/* inet_aton ignores trailing garbage. */ +int +__inet_aton_ignore_trailing (const char *cp, struct in_addr *addr) +{ + const char *endp; + return inet_aton_end (cp, addr, &endp); +} +weak_alias (__inet_aton_ignore_trailing, inet_aton) + +/* ASCII IPv4 Internet address interpretation routine. The value + returned is in network order. */ +in_addr_t +__inet_addr (const char *cp) +{ + struct in_addr val; + const char *endp; + if (inet_aton_end (cp, &val, &endp)) + return val.s_addr; + return INADDR_NONE; +} +weak_alias (__inet_addr, inet_addr) diff --git a/resolv/res_init.c b/resolv/res_init.c index 58c563898e..265e3cc6e3 100644 --- a/resolv/res_init.c +++ b/resolv/res_init.c @@ -399,8 +399,16 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser) cp = parser->buffer + sizeof ("nameserver") - 1; while (*cp == ' ' || *cp == '\t') cp++; + + /* Ignore trailing contents on the name server line. */ + { + char *el; + if ((el = strpbrk (cp, " \t\n")) != NULL) + *el = '\0'; + } + struct sockaddr *sa; - if ((*cp != '\0') && (*cp != '\n') && __inet_aton (cp, &a)) + if ((*cp != '\0') && (*cp != '\n') && __inet_aton_exact (cp, &a)) { sa = allocate_address_v4 (a, NAMESERVER_PORT); if (sa == NULL) @@ -410,9 +418,6 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser) { struct in6_addr a6; char *el; - - if ((el = strpbrk (cp, " \t\n")) != NULL) - *el = '\0'; if ((el = strchr (cp, SCOPE_DELIMITER)) != NULL) *el = '\0'; if ((*cp != '\0') && (__inet_pton (AF_INET6, cp, &a6) > 0)) @@ -472,7 +477,7 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser) char separator = *cp; *cp = 0; struct resolv_sortlist_entry e; - if (__inet_aton (net, &a)) + if (__inet_aton_exact (net, &a)) { e.addr = a; if (is_sort_mask (separator)) @@ -484,7 +489,7 @@ res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser) cp++; separator = *cp; *cp = 0; - if (__inet_aton (net, &a)) + if (__inet_aton_exact (net, &a)) e.mask = a.s_addr; else e.mask = net_mask (e.addr); diff --git a/resolv/tst-aton.c b/resolv/tst-aton.c index 08110a007a..eb734d7758 100644 --- a/resolv/tst-aton.c +++ b/resolv/tst-aton.c @@ -1,11 +1,29 @@ +/* Test legacy IPv4 text-to-address function inet_aton. + Copyright (C) 1998-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include #include #include #include #include #include - -static struct tests +static const struct tests { const char *input; int valid; @@ -16,6 +34,7 @@ static struct tests { "-1", 0, 0 }, { "256", 1, 0x00000100 }, { "256.", 0, 0 }, + { "255a", 0, 0 }, { "256a", 0, 0 }, { "0x100", 1, 0x00000100 }, { "0200.0x123456", 1, 0x80123456 }, @@ -40,7 +59,12 @@ static struct tests { "1.2.256.4", 0, 0 }, { "1.2.3.0x100", 0, 0 }, { "323543357756889", 0, 0 }, - { "10.1.2.3.4", 0, 0}, + { "10.1.2.3.4", 0, 0 }, + { "192.0.2.1", 1, 0xc0000201 }, + { "192.0.2.2\nX", 1, 0xc0000202 }, + { "192.0.2.3 Y", 1, 0xc0000203 }, + { "192.0.2.3Z", 0, 0 }, + { "192.000.002.010", 1, 0xc0000208 }, }; @@ -50,7 +74,7 @@ do_test (void) int result = 0; size_t cnt; - for (cnt = 0; cnt < sizeof (tests) / sizeof (tests[0]); ++cnt) + for (cnt = 0; cnt < array_length (tests); ++cnt) { struct in_addr addr; @@ -73,5 +97,4 @@ do_test (void) return result; } -#define TEST_FUNCTION do_test () -#include "../test-skeleton.c" +#include diff --git a/resolv/tst-inet_aton_exact.c b/resolv/tst-inet_aton_exact.c new file mode 100644 index 0000000000..0fdfa3d6aa --- /dev/null +++ b/resolv/tst-inet_aton_exact.c @@ -0,0 +1,47 @@ +/* Test internal legacy IPv4 text-to-address function __inet_aton_exact. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include + +static int +do_test (void) +{ + struct in_addr addr = { }; + + TEST_COMPARE (__inet_aton_exact ("192.0.2.1", &addr), 1); + TEST_COMPARE (ntohl (addr.s_addr), 0xC0000201); + + TEST_COMPARE (__inet_aton_exact ("192.000.002.010", &addr), 1); + TEST_COMPARE (ntohl (addr.s_addr), 0xC0000208); + TEST_COMPARE (__inet_aton_exact ("0xC0000234", &addr), 1); + TEST_COMPARE (ntohl (addr.s_addr), 0xC0000234); + + /* Trailing content is not accepted. */ + TEST_COMPARE (__inet_aton_exact ("192.0.2.2X", &addr), 0); + TEST_COMPARE (__inet_aton_exact ("192.0.2.3 Y", &addr), 0); + TEST_COMPARE (__inet_aton_exact ("192.0.2.4\nZ", &addr), 0); + TEST_COMPARE (__inet_aton_exact ("192.0.2.5\tT", &addr), 0); + TEST_COMPARE (__inet_aton_exact ("192.0.2.6 Y", &addr), 0); + TEST_COMPARE (__inet_aton_exact ("192.0.2.7\n", &addr), 0); + TEST_COMPARE (__inet_aton_exact ("192.0.2.8\t", &addr), 0); + + return 0; +} + +#include diff --git a/resolv/tst-resolv-nondecimal.c b/resolv/tst-resolv-nondecimal.c new file mode 100644 index 0000000000..a0df6f332a --- /dev/null +++ b/resolv/tst-resolv-nondecimal.c @@ -0,0 +1,139 @@ +/* Test name resolution behavior for octal, hexadecimal IPv4 addresses. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include + +static void +response (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype) +{ + /* The tests are not supposed send any DNS queries. */ + FAIL_EXIT1 ("unexpected DNS query for %s/%d/%d", qname, qclass, qtype); +} + +static void +run_query_addrinfo (const char *query, const char *address) +{ + char *quoted_query = support_quote_string (query); + + struct addrinfo *ai; + struct addrinfo hints = + { + .ai_socktype = SOCK_STREAM, + .ai_protocol = IPPROTO_TCP, + }; + + char *context = xasprintf ("getaddrinfo \"%s\" AF_INET", quoted_query); + char *expected = xasprintf ("address: STREAM/TCP %s 80\n", address); + hints.ai_family = AF_INET; + int ret = getaddrinfo (query, "80", &hints, &ai); + check_addrinfo (context, ai, ret, expected); + if (ret == 0) + freeaddrinfo (ai); + free (context); + + context = xasprintf ("getaddrinfo \"%s\" AF_UNSPEC", quoted_query); + hints.ai_family = AF_UNSPEC; + ret = getaddrinfo (query, "80", &hints, &ai); + check_addrinfo (context, ai, ret, expected); + if (ret == 0) + freeaddrinfo (ai); + free (expected); + free (context); + + context = xasprintf ("getaddrinfo \"%s\" AF_INET6", quoted_query); + expected = xasprintf ("flags: AI_V4MAPPED\n" + "address: STREAM/TCP ::ffff:%s 80\n", + address); + hints.ai_family = AF_INET6; + hints.ai_flags = AI_V4MAPPED; + ret = getaddrinfo (query, "80", &hints, &ai); + check_addrinfo (context, ai, ret, expected); + if (ret == 0) + freeaddrinfo (ai); + free (expected); + free (context); + + free (quoted_query); +} + +static void +run_query (const char *query, const char *address) +{ + char *quoted_query = support_quote_string (query); + char *context = xasprintf ("gethostbyname (\"%s\")", quoted_query); + char *expected = xasprintf ("name: %s\n" + "address: %s\n", query, address); + check_hostent (context, gethostbyname (query), expected); + free (context); + + context = xasprintf ("gethostbyname_r \"%s\"", quoted_query); + struct hostent storage; + char buf[4096]; + struct hostent *e = NULL; + TEST_COMPARE (gethostbyname_r (query, &storage, buf, sizeof (buf), + &e, &h_errno), 0); + check_hostent (context, e, expected); + free (context); + + context = xasprintf ("gethostbyname2 (\"%s\", AF_INET)", quoted_query); + check_hostent (context, gethostbyname2 (query, AF_INET), expected); + free (context); + + context = xasprintf ("gethostbyname2_r \"%s\" AF_INET", quoted_query); + e = NULL; + TEST_COMPARE (gethostbyname2_r (query, AF_INET, &storage, buf, sizeof (buf), + &e, &h_errno), 0); + check_hostent (context, e, expected); + free (context); + free (expected); + + free (quoted_query); + + /* The gethostbyname tests are always valid for getaddrinfo, but not + vice versa. */ + run_query_addrinfo (query, address); +} + +static int +do_test (void) +{ + struct resolv_test *aux = resolv_test_start + ((struct resolv_redirect_config) + { + .response_callback = response, + }); + + run_query ("192.000.002.010", "192.0.2.8"); + + /* Hexadecimal numbers are not accepted by gethostbyname. */ + run_query_addrinfo ("0xc0000210", "192.0.2.16"); + run_query_addrinfo ("192.0x234", "192.0.2.52"); + + resolv_test_end (aux); + + return 0; +} + +#include diff --git a/resolv/tst-resolv-trailing.c b/resolv/tst-resolv-trailing.c new file mode 100644 index 0000000000..7504bdae57 --- /dev/null +++ b/resolv/tst-resolv-trailing.c @@ -0,0 +1,136 @@ +/* Test name resolution behavior with trailing characters. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include + +static void +response (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype) +{ + /* The tests are not supposed send any DNS queries. */ + FAIL_EXIT1 ("unexpected DNS query for %s/%d/%d", qname, qclass, qtype); +} + +static int +do_test (void) +{ + struct resolv_test *aux = resolv_test_start + ((struct resolv_redirect_config) + { + .response_callback = response, + }); + + static const char *const queries[] = + { + "192.0.2.1 ", + "192.0.2.2\t", + "192.0.2.3\n", + "192.0.2.4 X", + "192.0.2.5\tY", + "192.0.2.6\nZ", + "192.0.2. ", + "192.0.2.\t", + "192.0.2.\n", + "192.0.2. X", + "192.0.2.\tY", + "192.0.2.\nZ", + "2001:db8::1 ", + "2001:db8::2\t", + "2001:db8::3\n", + "2001:db8::4 X", + "2001:db8::5\tY", + "2001:db8::6\nZ", + }; + for (size_t query_idx = 0; query_idx < array_length (queries); ++query_idx) + { + const char *query = queries[query_idx]; + struct hostent storage; + char buf[4096]; + struct hostent *e; + + h_errno = 0; + TEST_VERIFY (gethostbyname (query) == NULL); + TEST_COMPARE (h_errno, HOST_NOT_FOUND); + + h_errno = 0; + e = NULL; + TEST_COMPARE (gethostbyname_r (query, &storage, buf, sizeof (buf), + &e, &h_errno), 0); + TEST_VERIFY (e == NULL); + TEST_COMPARE (h_errno, HOST_NOT_FOUND); + + h_errno = 0; + TEST_VERIFY (gethostbyname2 (query, AF_INET) == NULL); + TEST_COMPARE (h_errno, HOST_NOT_FOUND); + + h_errno = 0; + e = NULL; + TEST_COMPARE (gethostbyname2_r (query, AF_INET, + &storage, buf, sizeof (buf), + &e, &h_errno), 0); + TEST_VERIFY (e == NULL); + TEST_COMPARE (h_errno, HOST_NOT_FOUND); + + h_errno = 0; + TEST_VERIFY (gethostbyname2 (query, AF_INET6) == NULL); + TEST_COMPARE (h_errno, HOST_NOT_FOUND); + + h_errno = 0; + e = NULL; + TEST_COMPARE (gethostbyname2_r (query, AF_INET6, + &storage, buf, sizeof (buf), + &e, &h_errno), 0); + TEST_VERIFY (e == NULL); + TEST_COMPARE (h_errno, HOST_NOT_FOUND); + + static const int gai_flags[] = + { + 0, + AI_ADDRCONFIG, + AI_NUMERICHOST, + AI_IDN, + AI_IDN | AI_NUMERICHOST, + AI_V4MAPPED, + AI_V4MAPPED | AI_NUMERICHOST, + }; + for (size_t gai_flags_idx; gai_flags_idx < array_length (gai_flags); + ++gai_flags_idx) + { + struct addrinfo hints = { .ai_flags = gai_flags[gai_flags_idx], }; + struct addrinfo *ai; + hints.ai_family = AF_INET; + TEST_COMPARE (getaddrinfo (query, "80", &hints, &ai), EAI_NONAME); + hints.ai_family = AF_INET6; + TEST_COMPARE (getaddrinfo (query, "80", &hints, &ai), EAI_NONAME); + hints.ai_family = AF_UNSPEC; + TEST_COMPARE (getaddrinfo (query, "80", &hints, &ai), EAI_NONAME); + } + }; + + resolv_test_end (aux); + + return 0; +} + +#include diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c index aa69eb7e54..aa054b620f 100644 --- a/sysdeps/posix/getaddrinfo.c +++ b/sysdeps/posix/getaddrinfo.c @@ -488,7 +488,7 @@ gaih_inet (const char *name, const struct gaih_service *service, malloc_name = true; } - if (__inet_aton (name, (struct in_addr *) at->addr) != 0) + if (__inet_aton_exact (name, (struct in_addr *) at->addr) != 0) { if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET) at->family = AF_INET;