diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2016-08-20 20:54:39 +0200 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2016-08-20 20:54:39 +0200 |
commit | 29af7775cfef6ed3b466b92e44387574122ed61b (patch) | |
tree | c968738daba6d87d69dc4e8b4cb1445a7b6420cb /resolv | |
parent | 4893e0ed57daaff901442bacc10ae09cd3e1850f (diff) | |
parent | f76453c31593957fec1a99b986bfa5506618b79c (diff) |
Merge branch 'baseline' into refs/top-bases/tschwinge/Roger_Whittaker
Diffstat (limited to 'resolv')
-rw-r--r-- | resolv/Depend | 1 | ||||
-rw-r--r-- | resolv/Makefile | 50 | ||||
-rw-r--r-- | resolv/Versions | 4 | ||||
-rw-r--r-- | resolv/gai_cancel.c | 2 | ||||
-rw-r--r-- | resolv/gai_error.c | 2 | ||||
-rw-r--r-- | resolv/gai_misc.c | 2 | ||||
-rw-r--r-- | resolv/gai_misc.h | 4 | ||||
-rw-r--r-- | resolv/gai_notify.c | 2 | ||||
-rw-r--r-- | resolv/gai_sigqueue.c | 2 | ||||
-rw-r--r-- | resolv/gai_suspend.c | 4 | ||||
-rw-r--r-- | resolv/getaddrinfo_a.c | 6 | ||||
-rw-r--r-- | resolv/gethnamaddr.c | 42 | ||||
-rw-r--r-- | resolv/inet_addr.c | 3 | ||||
-rw-r--r-- | resolv/inet_pton.c | 6 | ||||
-rw-r--r-- | resolv/netdb.h | 12 | ||||
-rw-r--r-- | resolv/nss_dns/dns-canon.c | 4 | ||||
-rw-r--r-- | resolv/nss_dns/dns-host.c | 132 | ||||
-rw-r--r-- | resolv/nss_dns/dns-network.c | 12 | ||||
-rw-r--r-- | resolv/res-state.c | 2 | ||||
-rw-r--r-- | resolv/res_hconf.c | 28 | ||||
-rw-r--r-- | resolv/res_hconf.h | 2 | ||||
-rw-r--r-- | resolv/res_init.c | 56 | ||||
-rw-r--r-- | resolv/res_mkquery.c | 4 | ||||
-rw-r--r-- | resolv/res_query.c | 89 | ||||
-rw-r--r-- | resolv/res_send.c | 249 | ||||
-rw-r--r-- | resolv/rpc/netdb.h | 3 | ||||
-rw-r--r-- | resolv/tst-inet_ntop.c | 7 | ||||
-rw-r--r-- | resolv/tst-leaks.c | 2 | ||||
-rw-r--r-- | resolv/tst-leaks2.c | 2 | ||||
-rw-r--r-- | resolv/tst-res_hconf_reorder.c | 112 |
30 files changed, 487 insertions, 359 deletions
diff --git a/resolv/Depend b/resolv/Depend index 5c6ec03451..c29ffb5e96 100644 --- a/resolv/Depend +++ b/resolv/Depend @@ -1,3 +1,2 @@ -linuxthreads nptl libpthread diff --git a/resolv/Makefile b/resolv/Makefile index b96b8ed927..1dcb75f7c7 100644 --- a/resolv/Makefile +++ b/resolv/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1994-2014 Free Software Foundation, Inc. +# Copyright (C) 1994-2015 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 @@ -20,6 +20,8 @@ # subdir := resolv +include ../Makeconfig + headers := resolv.h \ netdb.h bits/netdb.h \ arpa/nameser.h arpa/nameser_compat.h \ @@ -31,14 +33,13 @@ routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \ tests = tst-aton tst-leaks tst-inet_ntop xtests = tst-leaks2 -generate := mtrace-tst-leaks tst-leaks.mtrace tst-leaks2.mtrace - -include ../Makeconfig +generate := mtrace-tst-leaks.out tst-leaks.mtrace tst-leaks2.mtrace extra-libs := libresolv libnss_dns ifeq ($(have-thread-library),yes) extra-libs += libanl routines += gai_sigqueue +tests += tst-res_hconf_reorder endif extra-libs-others = $(extra-libs) libresolv-routines := gethnamaddr res_comp res_debug \ @@ -64,8 +65,22 @@ ifeq (yesyes,$(build-shared)$(have-thread-library)) tests: $(objpfx)ga_test endif -generated := mtrace-tst-leaks tst-leaks.mtrace \ - mtrace-tst-leaks2 tst-leaks2.mtrace +ifeq ($(run-built-tests),yes) +ifneq (no,$(PERL)) +tests-special += $(objpfx)mtrace-tst-leaks.out +xtests-special += $(objpfx)mtrace-tst-leaks2.out +endif +endif + +ifeq (,$(filter sunrpc,$(subdirs))) +# The netdb.h we install does '#include <rpc/netdb.h>', so one must exist. +# If sunrpc/ is built in this configuration, it installs a real <rpc/netdb.h>. +# If that's not going to happen, install our dummy file. +headers += rpc/netdb.h +endif + +generated += mtrace-tst-leaks.out tst-leaks.mtrace \ + mtrace-tst-leaks2.out tst-leaks2.mtrace include ../Rules @@ -91,21 +106,16 @@ $(objpfx)libanl.so: $(shared-thread-library) $(objpfx)ga_test: $(objpfx)libanl.so $(shared-thread-library) +$(objpfx)tst-res_hconf_reorder: $(libdl) $(shared-thread-library) +tst-res_hconf_reorder-ENV = RESOLV_REORDER=on + $(objpfx)tst-leaks: $(objpfx)libresolv.so tst-leaks-ENV = MALLOC_TRACE=$(objpfx)tst-leaks.mtrace -$(objpfx)mtrace-tst-leaks: $(objpfx)tst-leaks.out - $(common-objpfx)malloc/mtrace $(objpfx)tst-leaks.mtrace > $@ -ifeq ($(run-built-tests),yes) -ifneq (no,$(PERL)) -tests: $(objpfx)mtrace-tst-leaks -endif -endif +$(objpfx)mtrace-tst-leaks.out: $(objpfx)tst-leaks.out + $(common-objpfx)malloc/mtrace $(objpfx)tst-leaks.mtrace > $@; \ + $(evaluate-test) tst-leaks2-ENV = MALLOC_TRACE=$(objpfx)tst-leaks2.mtrace -$(objpfx)mtrace-tst-leaks2: $(objpfx)tst-leaks2.out - $(common-objpfx)malloc/mtrace $(objpfx)tst-leaks2.mtrace > $@ -ifeq ($(run-built-tests),yes) -ifneq (no,$(PERL)) -xtests: $(objpfx)mtrace-tst-leaks2 -endif -endif +$(objpfx)mtrace-tst-leaks2.out: $(objpfx)tst-leaks2.out + $(common-objpfx)malloc/mtrace $(objpfx)tst-leaks2.mtrace > $@; \ + $(evaluate-test) diff --git a/resolv/Versions b/resolv/Versions index 6f02597372..e561bce1a4 100644 --- a/resolv/Versions +++ b/resolv/Versions @@ -1,5 +1,3 @@ -%include <tls.h> - libc { GLIBC_2.0 { _res; @@ -26,7 +24,7 @@ libc { GLIBC_PRIVATE { __gai_sigqueue; - h_errno; __resp; + __h_errno; __resp; __res_maybe_init; __res_iclose; } diff --git a/resolv/gai_cancel.c b/resolv/gai_cancel.c index caf31455a2..6be2e5b16d 100644 --- a/resolv/gai_cancel.c +++ b/resolv/gai_cancel.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2014 Free Software Foundation, Inc. +/* Copyright (C) 2001-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. diff --git a/resolv/gai_error.c b/resolv/gai_error.c index e8d1baa1b5..085c82e1b9 100644 --- a/resolv/gai_error.c +++ b/resolv/gai_error.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2014 Free Software Foundation, Inc. +/* Copyright (C) 2001-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. diff --git a/resolv/gai_misc.c b/resolv/gai_misc.c index 9c53876bf9..0244b20c69 100644 --- a/resolv/gai_misc.c +++ b/resolv/gai_misc.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2014 Free Software Foundation, Inc. +/* Copyright (C) 2001-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. diff --git a/resolv/gai_misc.h b/resolv/gai_misc.h index b87b9e3d32..92f968830c 100644 --- a/resolv/gai_misc.h +++ b/resolv/gai_misc.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2014 Free Software Foundation, Inc. +/* Copyright (C) 2001-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. @@ -31,7 +31,7 @@ struct waitlist #ifndef DONT_NEED_GAI_MISC_COND pthread_cond_t *cond; #endif - volatile int *counterp; + volatile unsigned int *counterp; /* The next field is used in asynchronous `lio_listio' operations. */ struct sigevent *sigevp; /* XXX See requestlist, it's used to work around the broken signal diff --git a/resolv/gai_notify.c b/resolv/gai_notify.c index 7bee10211b..ab048620da 100644 --- a/resolv/gai_notify.c +++ b/resolv/gai_notify.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2014 Free Software Foundation, Inc. +/* Copyright (C) 2001-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. diff --git a/resolv/gai_sigqueue.c b/resolv/gai_sigqueue.c index f6e391c729..e2c78785eb 100644 --- a/resolv/gai_sigqueue.c +++ b/resolv/gai_sigqueue.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2014 Free Software Foundation, Inc. +/* Copyright (C) 2001-2015 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 diff --git a/resolv/gai_suspend.c b/resolv/gai_suspend.c index b795cdecb8..c3a1288360 100644 --- a/resolv/gai_suspend.c +++ b/resolv/gai_suspend.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2014 Free Software Foundation, Inc. +/* Copyright (C) 2001-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. @@ -35,7 +35,7 @@ gai_suspend (const struct gaicb *const list[], int ent, pthread_cond_t cond = PTHREAD_COND_INITIALIZER; #endif int cnt; - int cntr = 1; + unsigned int cntr = 1; int none = 1; int result; diff --git a/resolv/getaddrinfo_a.c b/resolv/getaddrinfo_a.c index 38b48c627e..e6372228c9 100644 --- a/resolv/getaddrinfo_a.c +++ b/resolv/getaddrinfo_a.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2014 Free Software Foundation, Inc. +/* Copyright (C) 2001-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. @@ -28,7 +28,7 @@ /* We need this special structure to handle asynchronous I/O. */ struct async_waitlist { - int counter; + unsigned int counter; struct sigevent sigev; struct waitlist list[0]; }; @@ -40,7 +40,7 @@ getaddrinfo_a (int mode, struct gaicb *list[], int ent, struct sigevent *sig) struct sigevent defsigev; struct requestlist *requests[ent]; int cnt; - volatile int total = 0; + volatile unsigned int total = 0; int result = 0; /* Check arguments. */ diff --git a/resolv/gethnamaddr.c b/resolv/gethnamaddr.c index 1fd8f92680..7fd0e497b1 100644 --- a/resolv/gethnamaddr.c +++ b/resolv/gethnamaddr.c @@ -49,6 +49,11 @@ * --Copyright-- */ +/* XXX This file is not used by any of the resolver functions implemented by + glibc (i.e. get*info and gethostby*). It cannot be removed however because + it exports symbols in the libresolv ABI. The file is not maintained any + more, nor are these functions. */ + #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ @@ -326,23 +331,18 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype) buflen -= n; continue; } - if ((type == T_SIG) || (type == T_KEY) || (type == T_NXT)) { - /* We don't support DNSSEC yet. For now, ignore - * the record and send a low priority message - * to syslog. - */ - syslog(LOG_DEBUG|LOG_AUTH, - "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", - qname, p_class(C_IN), p_type(qtype), - p_type(type)); - cp += n; - continue; - } if (type != qtype) { - syslog(LOG_NOTICE|LOG_AUTH, + /* Log a low priority message if we get an unexpected + * record, but skip it if we are using DNSSEC since it + * uses many different types in responses that do not + * match QTYPE. + */ + if ((_res.options & RES_USE_DNSSEC) == 0) { + syslog(LOG_NOTICE|LOG_AUTH, "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", - qname, p_class(C_IN), p_type(qtype), - p_type(type)); + qname, p_class(C_IN), p_type(qtype), + p_type(type)); + } cp += n; continue; /* XXX - had_error++ ? */ } @@ -621,7 +621,7 @@ gethostbyname2(name, af) buf.buf = origbuf = (querybuf *) alloca (1024); if ((n = __libc_res_nsearch(&_res, name, C_IN, type, buf.buf->buf, 1024, - &buf.ptr, NULL, NULL, NULL)) < 0) { + &buf.ptr, NULL, NULL, NULL, NULL)) < 0) { if (buf.buf != origbuf) free (buf.buf); Dprintf("res_nsearch failed (%d)\n", n); @@ -667,8 +667,8 @@ gethostbyaddr(addr, len, af) return (NULL); } if (af == AF_INET6 && len == IN6ADDRSZ && - (!bcmp(uaddr, mapped, sizeof mapped) || - !bcmp(uaddr, tunnelled, sizeof tunnelled))) { + (!memcmp(uaddr, mapped, sizeof mapped) || + !memcmp(uaddr, tunnelled, sizeof tunnelled))) { /* Unmap. */ addr += sizeof mapped; uaddr += sizeof mapped; @@ -716,12 +716,12 @@ gethostbyaddr(addr, len, af) buf.buf = orig_buf = (querybuf *) alloca (1024); n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf, 1024, - &buf.ptr, NULL, NULL, NULL); + &buf.ptr, NULL, NULL, NULL, NULL); if (n < 0 && af == AF_INET6 && (_res.options & RES_NOIP6DOTINT) == 0) { strcpy(qp, "ip6.int"); n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf, buf.buf != orig_buf ? MAXPACKET : 1024, - &buf.ptr, NULL, NULL, NULL); + &buf.ptr, NULL, NULL, NULL, NULL); } if (n < 0) { if (buf.buf != orig_buf) @@ -917,7 +917,7 @@ _gethtbyaddr(addr, len, af) _sethtent(0); while ((p = _gethtent())) - if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len)) + if (p->h_addrtype == af && !memcmp(p->h_addr, addr, len)) break; _endhtent(); return (p); diff --git a/resolv/inet_addr.c b/resolv/inet_addr.c index 144b87a74c..ee42093754 100644 --- a/resolv/inet_addr.c +++ b/resolv/inet_addr.c @@ -90,13 +90,14 @@ static const char rcsid[] = "$BINDId: inet_addr.c,v 8.11 1999/10/13 16:39:25 vix * The value returned is in network order. */ in_addr_t -inet_addr(const char *cp) { +__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 diff --git a/resolv/inet_pton.c b/resolv/inet_pton.c index c507013e4e..3d8819512e 100644 --- a/resolv/inet_pton.c +++ b/resolv/inet_pton.c @@ -49,7 +49,7 @@ static int inet_pton6 (const char *src, u_char *dst) internal_function; * Paul Vixie, 1996. */ int -inet_pton(af, src, dst) +__inet_pton(af, src, dst) int af; const char *src; void *dst; @@ -65,7 +65,9 @@ inet_pton(af, src, dst) } /* NOTREACHED */ } -libc_hidden_def (inet_pton) +libc_hidden_def (__inet_pton) +weak_alias (__inet_pton, inet_pton) +libc_hidden_weak (inet_pton) /* int * inet_pton4(src, dst) diff --git a/resolv/netdb.h b/resolv/netdb.h index f9e2bf00cb..44cf6923b2 100644 --- a/resolv/netdb.h +++ b/resolv/netdb.h @@ -1,4 +1,4 @@ - /* Copyright (C) 1996-2014 Free Software Foundation, Inc. + /* Copyright (C) 1996-2015 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 @@ -70,7 +70,7 @@ extern int *__h_errno_location (void) __THROW __attribute__ ((__const__)); # define NO_DATA 4 /* Valid name, no data record of requested type. */ #endif -#if defined __USE_MISC || defined __USE_GNU +#ifdef __USE_MISC # define NETDB_INTERNAL -1 /* See errno. */ # define NETDB_SUCCESS 0 /* No problem. */ # define NO_ADDRESS NO_DATA /* No address, look for MX record. */ @@ -104,7 +104,7 @@ struct hostent int h_addrtype; /* Host address type. */ int h_length; /* Length of address. */ char **h_addr_list; /* List of addresses from name server. */ -#if defined __USE_MISC || defined __USE_GNU +#ifdef __USE_MISC # define h_addr h_addr_list[0] /* Address, for backward compatibility.*/ #endif }; @@ -436,7 +436,7 @@ extern int getnetgrent_r (char **__restrict __hostp, #endif /* misc */ -#ifdef __USE_BSD +#ifdef __USE_MISC /* Call `rshd' at port RPORT on remote machine *AHOST to execute CMD. The local user is LOCUSER, on the remote machine the command is executed as REMUSER. In *FD2P the descriptor to the socket for the @@ -561,8 +561,8 @@ extern int rresvport_af (int *__alport, sa_family_t __af); #endif -/* Extension from POSIX.1g. */ -#ifdef __USE_POSIX +/* Extension from POSIX.1:2001. */ +#ifdef __USE_XOPEN2K /* Structure to contain information about address of a service provider. */ struct addrinfo { diff --git a/resolv/nss_dns/dns-canon.c b/resolv/nss_dns/dns-canon.c index a9db232c7b..14ddd6cca0 100644 --- a/resolv/nss_dns/dns-canon.c +++ b/resolv/nss_dns/dns-canon.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2004-2014 Free Software Foundation, Inc. +/* Copyright (C) 2004-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2004. @@ -62,7 +62,7 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen, { int r = __libc_res_nquery (&_res, name, ns_c_in, qtypes[i], buf, sizeof (buf), &ansp.ptr, NULL, NULL, - NULL); + NULL, NULL); if (r > 0) { /* We need to decode the response. Just one question record. diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c index f8f192e5af..357ac04693 100644 --- a/resolv/nss_dns/dns-host.c +++ b/resolv/nss_dns/dns-host.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-2014 Free Software Foundation, Inc. +/* Copyright (C) 1996-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996. @@ -190,7 +190,7 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result, host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024); n = __libc_res_nsearch (&_res, name, C_IN, type, host_buffer.buf->buf, - 1024, &host_buffer.ptr, NULL, NULL, NULL); + 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL); if (n < 0) { switch (errno) @@ -225,7 +225,7 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result, n = __libc_res_nsearch (&_res, name, C_IN, T_A, host_buffer.buf->buf, host_buffer.buf != orig_host_buffer ? MAXPACKET : 1024, &host_buffer.ptr, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); if (n < 0) { @@ -308,13 +308,20 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, u_char *ans2p = NULL; int nans2p = 0; int resplen2 = 0; + int ans2p_malloced = 0; int olderr = errno; enum nss_status status; int n = __libc_res_nsearch (&_res, name, C_IN, T_UNSPEC, host_buffer.buf->buf, 2048, &host_buffer.ptr, - &ans2p, &nans2p, &resplen2); - if (n < 0) + &ans2p, &nans2p, &resplen2, &ans2p_malloced); + if (n >= 0) + { + status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p, + resplen2, name, pat, buffer, buflen, + errnop, herrnop, ttlp); + } + else { switch (errno) { @@ -341,16 +348,11 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, *errnop = EAGAIN; else __set_errno (olderr); - - if (host_buffer.buf != orig_host_buffer) - free (host_buffer.buf); - - return status; } - status = gaih_getanswer(host_buffer.buf, n, (const querybuf *) ans2p, - resplen2, name, pat, buffer, buflen, - errnop, herrnop, ttlp); + /* Check whether ans2p was separately allocated. */ + if (ans2p_malloced) + free (ans2p); if (host_buffer.buf != orig_host_buffer) free (host_buffer.buf); @@ -398,7 +400,7 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af, buffer += pad; buflen = buflen > pad ? buflen - pad : 0; - if (__builtin_expect (buflen < sizeof (struct host_data), 0)) + if (__glibc_unlikely (buflen < sizeof (struct host_data))) { *errnop = ERANGE; *h_errnop = NETDB_INTERNAL; @@ -452,7 +454,7 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af, break; case AF_INET6: /* Only lookup with the byte string format if the user wants it. */ - if (__builtin_expect (_res.options & RES_USEBSTRING, 0)) + if (__glibc_unlikely (_res.options & RES_USEBSTRING)) { qp = stpcpy (qbuf, "\\[x"); for (n = 0; n < IN6ADDRSZ; ++n) @@ -460,7 +462,7 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af, strcpy (qp, "].ip6.arpa"); n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf, 1024, &host_buffer.ptr, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); if (n >= 0) goto got_it_already; } @@ -481,14 +483,14 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af, } n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf, - 1024, &host_buffer.ptr, NULL, NULL, NULL); + 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL); if (n < 0 && af == AF_INET6 && (_res.options & RES_NOIP6DOTINT) == 0) { strcpy (qp, "ip6.int"); n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf, host_buffer.buf != orig_host_buffer ? MAXPACKET : 1024, &host_buffer.ptr, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); } if (n < 0) { @@ -613,7 +615,8 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, int have_to_map = 0; uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data); buffer += pad; - if (__builtin_expect (buflen < sizeof (struct host_data) + pad, 0)) + buflen = buflen > pad ? buflen - pad : 0; + if (__glibc_unlikely (buflen < sizeof (struct host_data))) { /* The buffer is too small. */ too_small: @@ -727,14 +730,14 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, n = -1; } - if (__builtin_expect (n < 0 || (*name_ok) (bp) == 0, 0)) + if (__glibc_unlikely (n < 0 || (*name_ok) (bp) == 0)) { ++had_error; continue; } cp += n; /* name */ - if (__builtin_expect (cp + 10 > end_of_message, 0)) + if (__glibc_unlikely (cp + 10 > end_of_message)) { ++had_error; continue; @@ -748,7 +751,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, cp += INT32SZ; /* TTL */ n = __ns_get16 (cp); cp += INT16SZ; /* len */ - if (__builtin_expect (class != C_IN, 0)) + if (__glibc_unlikely (class != C_IN)) { /* XXX - debug? syslog? */ cp += n; @@ -764,7 +767,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, if (ap >= &host_data->aliases[MAX_NR_ALIASES - 1]) continue; n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf); - if (__builtin_expect (n < 0 || (*name_ok) (tbuf) == 0, 0)) + if (__glibc_unlikely (n < 0 || (*name_ok) (tbuf) == 0)) { ++had_error; continue; @@ -782,7 +785,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, linebuflen -= n; /* Get canonical name. */ n = strlen (tbuf) + 1; /* For the \0. */ - if (__builtin_expect (n > linebuflen, 0)) + if (__glibc_unlikely (n > linebuflen)) goto too_small; if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN) { @@ -797,8 +800,12 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, if (qtype == T_PTR && type == T_CNAME) { + /* A CNAME could also have a TTL entry. */ + if (ttlp != NULL && ttl < *ttlp) + *ttlp = ttl; + n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf); - if (__builtin_expect (n < 0 || res_dnok (tbuf) == 0, 0)) + if (__glibc_unlikely (n < 0 || res_dnok (tbuf) == 0)) { ++had_error; continue; @@ -806,7 +813,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, cp += n; /* Get canonical name. */ n = strlen (tbuf) + 1; /* For the \0. */ - if (__builtin_expect (n > linebuflen, 0)) + if (__glibc_unlikely (n > linebuflen)) goto too_small; if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN) { @@ -818,26 +825,19 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, linebuflen -= n; continue; } - if (__builtin_expect (type == T_SIG, 0) - || __builtin_expect (type == T_KEY, 0) - || __builtin_expect (type == T_NXT, 0)) - { - /* We don't support DNSSEC yet. For now, ignore the record - and send a low priority message to syslog. */ - syslog (LOG_DEBUG | LOG_AUTH, - "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", - qname, p_class (C_IN), p_type(qtype), p_type (type)); - cp += n; - continue; - } if (type == T_A && qtype == T_AAAA && map) have_to_map = 1; - else if (__builtin_expect (type != qtype, 0)) + else if (__glibc_unlikely (type != qtype)) { - syslog (LOG_NOTICE | LOG_AUTH, - "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", - qname, p_class (C_IN), p_type (qtype), p_type (type)); + /* Log a low priority message if we get an unexpected record, but + skip it if we are using DNSSEC since it uses many different types + in responses that do not match QTYPE. */ + if ((_res.options & RES_USE_DNSSEC) == 0) + syslog (LOG_NOTICE | LOG_AUTH, + "gethostby*.getanswer: asked for \"%s %s %s\", " + "got type \"%s\"", + qname, p_class (C_IN), p_type (qtype), p_type (type)); cp += n; continue; /* XXX - had_error++ ? */ } @@ -845,7 +845,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, switch (type) { case T_PTR: - if (__builtin_expect (strcasecmp (tname, bp) != 0, 0)) + if (__glibc_unlikely (strcasecmp (tname, bp) != 0)) { syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, qname, bp); cp += n; @@ -862,37 +862,20 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, n = -1; } - if (__builtin_expect (n < 0 || res_hnok (bp) == 0, 0)) + if (__glibc_unlikely (n < 0 || res_hnok (bp) == 0)) { ++had_error; break; } -#if MULTI_PTRS_ARE_ALIASES - cp += n; - if (haveanswer == 0) - result->h_name = bp; - else if (ap < &host_data->aliases[MAXALIASES-1]) - *ap++ = bp; - else - n = -1; - if (n != -1) - { - n = strlen (bp) + 1; /* for the \0 */ - if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN) - { - ++had_error; - break; - } - bp += n; - linebuflen -= n; - } - break; -#else + if (ttlp != NULL && ttl < *ttlp) + *ttlp = ttl; + /* bind would put multiple PTR records as aliases, but we don't do + that. */ result->h_name = bp; if (have_to_map) { n = strlen (bp) + 1; /* for the \0 */ - if (__builtin_expect (n >= MAXHOSTNAMELEN, 0)) + if (__glibc_unlikely (n >= MAXHOSTNAMELEN)) { ++had_error; break; @@ -904,7 +887,6 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, } *h_errnop = NETDB_SUCCESS; return NSS_STATUS_SUCCESS; -#endif case T_A: case T_AAAA: if (__builtin_expect (strcasecmp (result->h_name, bp), 0) != 0) @@ -938,7 +920,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, linebuflen -= sizeof (align) - ((u_long) bp % sizeof (align)); bp += sizeof (align) - ((u_long) bp % sizeof (align)); - if (__builtin_expect (n > linebuflen, 0)) + if (__glibc_unlikely (n > linebuflen)) goto too_small; bp = __mempcpy (*hap++ = bp, cp, n); cp += n; @@ -1009,7 +991,7 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, int qdcount = ntohs (hp->qdcount); const u_char *cp = answer->buf + HFIXEDSZ; const u_char *end_of_message = answer->buf + anslen; - if (__builtin_expect (qdcount != 1, 0)) + if (__glibc_unlikely (qdcount != 1)) { *h_errnop = NO_RECOVERY; return NSS_STATUS_UNAVAIL; @@ -1063,7 +1045,7 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, n = -1; } - if (__builtin_expect (n < 0 || res_hnok (buffer) == 0, 0)) + if (__glibc_unlikely (n < 0 || res_hnok (buffer) == 0)) { ++had_error; continue; @@ -1077,7 +1059,7 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, cp += n; /* name */ - if (__builtin_expect (cp + 10 > end_of_message, 0)) + if (__glibc_unlikely (cp + 10 > end_of_message)) { ++had_error; continue; @@ -1107,7 +1089,7 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, *ttlp = ttl; n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf); - if (__builtin_expect (n < 0 || res_hnok (tbuf) == 0, 0)) + if (__glibc_unlikely (n < 0 || res_hnok (tbuf) == 0)) { ++had_error; continue; @@ -1124,9 +1106,9 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, } n = strlen (tbuf) + 1; - if (__builtin_expect (n > buflen, 0)) + if (__glibc_unlikely (n > buflen)) goto too_small; - if (__builtin_expect (n >= MAXHOSTNAMELEN, 0)) + if (__glibc_unlikely (n >= MAXHOSTNAMELEN)) { ++had_error; continue; @@ -1143,7 +1125,7 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, // We should not see any types other than those explicitly listed // below. Some types sent by server seem missing, though. Just // collect the data for now. - if (__builtin_expect (type != T_A && type != T_AAAA, 0)) + if (__glibc_unlikely (type != T_A && type != T_AAAA)) #else if (__builtin_expect (type == T_SIG, 0) || __builtin_expect (type == T_KEY, 0) diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c index 8e80a6010e..00f4490c5d 100644 --- a/resolv/nss_dns/dns-network.c +++ b/resolv/nss_dns/dns-network.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-2014 Free Software Foundation, Inc. +/* Copyright (C) 1996-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996. @@ -129,7 +129,7 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result, net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024); anslen = __libc_res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf, - 1024, &net_buffer.ptr, NULL, NULL, NULL); + 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL); if (anslen < 0) { /* Nothing found. */ @@ -205,7 +205,7 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result, net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024); anslen = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf, - 1024, &net_buffer.ptr, NULL, NULL, NULL); + 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL); if (anslen < 0) { /* Nothing found. */ @@ -268,7 +268,7 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result, uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct net_data); buffer += pad; - if (__builtin_expect (buflen < sizeof (*net_data) + pad, 0)) + if (__glibc_unlikely (buflen < sizeof (*net_data) + pad)) { /* The buffer is too small. */ too_small: @@ -398,8 +398,8 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result, case BYNAME: { - char **ap = result->n_aliases++; - while (*ap != NULL) + char **ap; + for (ap = result->n_aliases; *ap != NULL; ++ap) { /* Check each alias name for being of the forms: 4.3.2.1.in-addr.arpa = net 1.2.3.4 diff --git a/resolv/res-state.c b/resolv/res-state.c index 440940312e..d6775532b7 100644 --- a/resolv/res-state.c +++ b/resolv/res-state.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-2014 Free Software Foundation, Inc. +/* Copyright (C) 1996-2015 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 diff --git a/resolv/res_hconf.c b/resolv/res_hconf.c index b4c86227f8..0d4f3f45bc 100644 --- a/resolv/res_hconf.c +++ b/resolv/res_hconf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993-2014 Free Software Foundation, Inc. +/* Copyright (C) 1993-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by David Mosberger (davidm@azstarnet.com). @@ -46,6 +46,10 @@ #include "res_hconf.h" #include <wchar.h> +#if IS_IN (libc) +# define fgets_unlocked __fgets_unlocked +#endif + #define _PATH_HOSTCONF "/etc/host.conf" /* Environment vars that all user to override default behavior: */ @@ -358,7 +362,7 @@ _res_hconf_init (void) } -#ifndef NOT_IN_libc +#if IS_IN (libc) # if defined SIOCGIFCONF && defined SIOCGIFNETMASK /* List of known interfaces. */ libc_freeres_ptr ( @@ -417,7 +421,7 @@ _res_hconf_reorder_addrs (struct hostent *hp) /* Get lock. */ __libc_lock_lock (lock); - /* Recheck, somebody else might have done the work by done. */ + /* Recheck, somebody else might have done the work by now. */ if (num_ifs <= 0) { int new_num_ifs = 0; @@ -435,18 +439,24 @@ _res_hconf_reorder_addrs (struct hostent *hp) for (cur_ifr = ifr, i = 0; i < num; cur_ifr = __if_nextreq (cur_ifr), ++i) { + union + { + struct sockaddr sa; + struct sockaddr_in sin; + } ss; + if (cur_ifr->ifr_addr.sa_family != AF_INET) continue; ifaddrs[new_num_ifs].addrtype = AF_INET; - ifaddrs[new_num_ifs].u.ipv4.addr = - ((struct sockaddr_in *) &cur_ifr->ifr_addr)->sin_addr.s_addr; + ss.sa = cur_ifr->ifr_addr; + ifaddrs[new_num_ifs].u.ipv4.addr = ss.sin.sin_addr.s_addr; if (__ioctl (sd, SIOCGIFNETMASK, cur_ifr) < 0) continue; - ifaddrs[new_num_ifs].u.ipv4.mask = - ((struct sockaddr_in *) &cur_ifr->ifr_netmask)->sin_addr.s_addr; + ss.sa = cur_ifr->ifr_netmask; + ifaddrs[new_num_ifs].u.ipv4.mask = ss.sin.sin_addr.s_addr; /* Now we're committed to this entry. */ ++new_num_ifs; @@ -463,10 +473,10 @@ _res_hconf_reorder_addrs (struct hostent *hp) errno = save; num_ifs = new_num_ifs; - - __libc_lock_unlock (lock); } + __libc_lock_unlock (lock); + __close (sd); } diff --git a/resolv/res_hconf.h b/resolv/res_hconf.h index 1e0c2d9a22..42cef79965 100644 --- a/resolv/res_hconf.h +++ b/resolv/res_hconf.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1993-2014 Free Software Foundation, Inc. +/* Copyright (C) 1993-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by David Mosberger (davidm@azstarnet.com). diff --git a/resolv/res_init.c b/resolv/res_init.c index 5e1a747a4a..66561ffac2 100644 --- a/resolv/res_init.c +++ b/resolv/res_init.c @@ -153,10 +153,8 @@ __res_vinit(res_state statp, int preinit) { char *cp, **pp; int n; char buf[BUFSIZ]; - int nserv = 0; /* number of nameserver records read from file */ -#ifdef _LIBC - int nservall = 0; /* number of NS records read, nserv IPv4 only */ -#endif + int nserv = 0; /* number of nameservers read from file */ + int have_serv6 = 0; int haveenv = 0; int havesearch = 0; #ifdef RESOLVSORT @@ -184,15 +182,9 @@ __res_vinit(res_state statp, int preinit) { statp->_flags = 0; statp->qhook = NULL; statp->rhook = NULL; - statp->_u._ext.nsinit = 0; statp->_u._ext.nscount = 0; -#ifdef _LIBC - statp->_u._ext.nscount6 = 0; - for (n = 0; n < MAXNS; n++) { - statp->_u._ext.nsaddrs[n] = NULL; - statp->_u._ext.nsmap[n] = MAXNS; - } -#endif + for (n = 0; n < MAXNS; n++) + statp->_u._ext.nsaddrs[n] = NULL; /* Allow user to override the local domain definition */ if ((cp = getenv("LOCALDOMAIN")) != NULL) { @@ -238,7 +230,7 @@ __res_vinit(res_state statp, int preinit) { /* No threads use this stream. */ __fsetlocking (fp, FSETLOCKING_BYCALLER); /* read the config file */ - while (fgets_unlocked(buf, sizeof(buf), fp) != NULL) { + while (__fgets_unlocked(buf, sizeof(buf), fp) != NULL) { /* skip comments */ if (*buf == ';' || *buf == '#') continue; @@ -296,11 +288,7 @@ __res_vinit(res_state statp, int preinit) { continue; } /* read nameservers to query */ -#ifdef _LIBC - if (MATCH(buf, "nameserver") && nservall < MAXNS) { -#else if (MATCH(buf, "nameserver") && nserv < MAXNS) { -#endif struct in_addr a; cp = buf + sizeof("nameserver") - 1; @@ -308,13 +296,12 @@ __res_vinit(res_state statp, int preinit) { cp++; if ((*cp != '\0') && (*cp != '\n') && __inet_aton(cp, &a)) { - statp->nsaddr_list[nservall].sin_addr = a; - statp->nsaddr_list[nservall].sin_family = AF_INET; - statp->nsaddr_list[nservall].sin_port = + statp->nsaddr_list[nserv].sin_addr = a; + statp->nsaddr_list[nserv].sin_family = AF_INET; + statp->nsaddr_list[nserv].sin_port = htons(NAMESERVER_PORT); nserv++; #ifdef _LIBC - nservall++; } else { struct in6_addr a6; char *el; @@ -324,7 +311,7 @@ __res_vinit(res_state statp, int preinit) { if ((el = strchr(cp, SCOPE_DELIMITER)) != NULL) *el = '\0'; if ((*cp != '\0') && - (inet_pton(AF_INET6, cp, &a6) > 0)) { + (__inet_pton(AF_INET6, cp, &a6) > 0)) { struct sockaddr_in6 *sa6; sa6 = malloc(sizeof(*sa6)); @@ -334,14 +321,14 @@ __res_vinit(res_state statp, int preinit) { sa6->sin6_flowinfo = 0; sa6->sin6_addr = a6; - if (__builtin_expect (el == NULL, 1)) + if (__glibc_likely (el == NULL)) sa6->sin6_scope_id = 0; else { int try_numericscope = 1; if (IN6_IS_ADDR_LINKLOCAL (&a6) || IN6_IS_ADDR_MC_LINKLOCAL (&a6)) { sa6->sin6_scope_id - = if_nametoindex (el + 1); + = __if_nametoindex (el + 1); if (sa6->sin6_scope_id != 0) try_numericscope = 0; } @@ -356,10 +343,11 @@ __res_vinit(res_state statp, int preinit) { } } - statp->_u._ext.nsaddrs[nservall] = sa6; - statp->_u._ext.nssocks[nservall] = -1; - statp->_u._ext.nsmap[nservall] = MAXNS + 1; - nservall++; + statp->nsaddr_list[nserv].sin_family = 0; + statp->_u._ext.nsaddrs[nserv] = sa6; + statp->_u._ext.nssocks[nserv] = -1; + have_serv6 = 1; + nserv++; } } #endif @@ -414,10 +402,9 @@ __res_vinit(res_state statp, int preinit) { continue; } } - statp->nscount = nservall; + statp->nscount = nserv; #ifdef _LIBC - if (nservall - nserv > 0) { - statp->_u._ext.nscount6 = nservall - nserv; + if (have_serv6) { /* We try IPv6 servers again. */ statp->ipv6_unavail = false; } @@ -428,7 +415,7 @@ __res_vinit(res_state statp, int preinit) { (void) fclose(fp); } if (__builtin_expect(statp->nscount == 0, 0)) { - statp->nsaddr.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1); + statp->nsaddr.sin_addr = __inet_makeaddr(IN_LOOPBACKNET, 1); statp->nsaddr.sin_family = AF_INET; statp->nsaddr.sin_port = htons(NAMESERVER_PORT); statp->nscount = 1; @@ -606,11 +593,7 @@ __res_iclose(res_state statp, bool free_addr) { statp->_vcsock = -1; statp->_flags &= ~(RES_F_VC | RES_F_CONN); } -#ifdef _LIBC - for (ns = 0; ns < MAXNS; ns++) -#else for (ns = 0; ns < statp->_u._ext.nscount; ns++) -#endif if (statp->_u._ext.nsaddrs[ns]) { if (statp->_u._ext.nssocks[ns] != -1) { close_not_cancel_no_status(statp->_u._ext.nssocks[ns]); @@ -621,7 +604,6 @@ __res_iclose(res_state statp, bool free_addr) { statp->_u._ext.nsaddrs[ns] = NULL; } } - statp->_u._ext.nsinit = 0; } libc_hidden_def (__res_iclose) diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c index 6170763fa3..1635e6a035 100644 --- a/resolv/res_mkquery.c +++ b/resolv/res_mkquery.c @@ -180,7 +180,7 @@ res_nmkquery(res_state statp, n = ns_name_compress((char *)data, cp, buflen, (const u_char **) dnptrs, (const u_char **) lastdnptr); - if (__builtin_expect (n < 0, 0)) + if (__glibc_unlikely (n < 0)) return (-1); cp += n; buflen -= n; @@ -195,7 +195,7 @@ res_nmkquery(res_state statp, /* * Initialize answer section */ - if (__builtin_expect (buflen < 1 + RRFIXEDSZ + datalen, 0)) + if (__glibc_unlikely (buflen < 1 + RRFIXEDSZ + datalen)) return (-1); *cp++ = '\0'; /* no domain name */ NS_PUT16 (type, cp); diff --git a/resolv/res_query.c b/resolv/res_query.c index 1325f9772d..4a9b3b3f27 100644 --- a/resolv/res_query.c +++ b/resolv/res_query.c @@ -98,7 +98,7 @@ static int __libc_res_nquerydomain(res_state statp, const char *name, const char *domain, int class, int type, u_char *answer, int anslen, u_char **answerp, u_char **answerp2, int *nanswerp2, - int *resplen2); + int *resplen2, int *answerp2_malloced); /* * Formulate a normal query, send, and await answer. @@ -119,7 +119,8 @@ __libc_res_nquery(res_state statp, u_char **answerp, /* if buffer needs to be enlarged */ u_char **answerp2, int *nanswerp2, - int *resplen2) + int *resplen2, + int *answerp2_malloced) { HEADER *hp = (HEADER *) answer; HEADER *hp2; @@ -202,7 +203,7 @@ __libc_res_nquery(res_state statp, goto again; } } - if (__builtin_expect (n <= 0, 0)) { + if (__glibc_unlikely (n <= 0)) { /* If the query choked with EDNS0, retry without EDNS0. */ if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0 && ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) { @@ -224,7 +225,8 @@ __libc_res_nquery(res_state statp, } assert (answerp == NULL || (void *) *answerp == (void *) answer); n = __libc_res_nsend(statp, query1, nquery1, query2, nquery2, answer, - anslen, answerp, answerp2, nanswerp2, resplen2); + anslen, answerp, answerp2, nanswerp2, resplen2, + answerp2_malloced); if (use_malloc) free (buf); if (n < 0) { @@ -316,7 +318,7 @@ res_nquery(res_state statp, int anslen) /* size of answer buffer */ { return __libc_res_nquery(statp, name, class, type, answer, anslen, - NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, NULL); } libresolv_hidden_def (res_nquery) @@ -335,7 +337,8 @@ __libc_res_nsearch(res_state statp, u_char **answerp, u_char **answerp2, int *nanswerp2, - int *resplen2) + int *resplen2, + int *answerp2_malloced) { const char *cp, * const *domain; HEADER *hp = (HEADER *) answer; @@ -360,7 +363,7 @@ __libc_res_nsearch(res_state statp, if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL) return (__libc_res_nquery(statp, cp, class, type, answer, anslen, answerp, answerp2, - nanswerp2, resplen2)); + nanswerp2, resplen2, answerp2_malloced)); #ifdef DEBUG if (statp->options & RES_DEBUG) @@ -377,8 +380,11 @@ __libc_res_nsearch(res_state statp, if (dots >= statp->ndots || trailing_dot) { ret = __libc_res_nquerydomain(statp, name, NULL, class, type, answer, anslen, answerp, - answerp2, nanswerp2, resplen2); - if (ret > 0 || trailing_dot) + answerp2, nanswerp2, resplen2, + answerp2_malloced); + if (ret > 0 || trailing_dot + /* If the second response is valid then we use that. */ + || (ret == 0 && resplen2 != NULL && *resplen2 > 0)) return (ret); saved_herrno = h_errno; tried_as_is++; @@ -386,11 +392,11 @@ __libc_res_nsearch(res_state statp, answer = *answerp; anslen = MAXPACKET; } - if (answerp2 - && (*answerp2 < answer || *answerp2 >= answer + anslen)) + if (answerp2 && *answerp2_malloced) { free (*answerp2); *answerp2 = NULL; + *answerp2_malloced = 0; } } @@ -407,30 +413,41 @@ __libc_res_nsearch(res_state statp, for (domain = (const char * const *)statp->dnsrch; *domain && !done; domain++) { + const char *dname = domain[0]; searched = 1; - if (domain[0][0] == '\0' || - (domain[0][0] == '.' && domain[0][1] == '\0')) + /* __libc_res_nquerydoman concatenates name + with dname with a "." in between. If we + pass it in dname the "." we got from the + configured default search path, we'll end + up with "name..", which won't resolve. + OTOH, passing it "" will result in "name.", + which has the intended effect for both + possible representations of the root + domain. */ + if (dname[0] == '.') + dname++; + if (dname[0] == '\0') root_on_list++; - ret = __libc_res_nquerydomain(statp, name, *domain, + ret = __libc_res_nquerydomain(statp, name, dname, class, type, answer, anslen, answerp, answerp2, nanswerp2, - resplen2); - if (ret > 0) + resplen2, answerp2_malloced); + if (ret > 0 || (ret == 0 && resplen2 != NULL + && *resplen2 > 0)) return (ret); if (answerp && *answerp != answer) { answer = *answerp; anslen = MAXPACKET; } - if (answerp2 - && (*answerp2 < answer - || *answerp2 >= answer + anslen)) + if (answerp2 && *answerp2_malloced) { free (*answerp2); *answerp2 = NULL; + *answerp2_malloced = 0; } /* @@ -479,15 +496,17 @@ __libc_res_nsearch(res_state statp, } /* - * f the query has not already been tried as is then try it + * If the query has not already been tried as is then try it * unless RES_NOTLDQUERY is set and there were no dots. */ if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0) && !(tried_as_is || root_on_list)) { ret = __libc_res_nquerydomain(statp, name, NULL, class, type, answer, anslen, answerp, - answerp2, nanswerp2, resplen2); - if (ret > 0) + answerp2, nanswerp2, resplen2, + answerp2_malloced); + if (ret > 0 || (ret == 0 && resplen2 != NULL + && *resplen2 > 0)) return (ret); } @@ -498,10 +517,11 @@ __libc_res_nsearch(res_state statp, * else send back meaningless H_ERRNO, that being the one from * the last DNSRCH we did. */ - if (answerp2 && (*answerp2 < answer || *answerp2 >= answer + anslen)) + if (answerp2 && *answerp2_malloced) { free (*answerp2); *answerp2 = NULL; + *answerp2_malloced = 0; } if (saved_herrno != -1) RES_SET_H_ERRNO(statp, saved_herrno); @@ -521,13 +541,12 @@ res_nsearch(res_state statp, int anslen) /* size of answer */ { return __libc_res_nsearch(statp, name, class, type, answer, - anslen, NULL, NULL, NULL, NULL); + anslen, NULL, NULL, NULL, NULL, NULL); } libresolv_hidden_def (res_nsearch) /* - * Perform a call on res_query on the concatenation of name and domain, - * removing a trailing dot from name if domain is NULL. + * Perform a call on res_query on the concatenation of name and domain. */ static int __libc_res_nquerydomain(res_state statp, @@ -539,7 +558,8 @@ __libc_res_nquerydomain(res_state statp, u_char **answerp, u_char **answerp2, int *nanswerp2, - int *resplen2) + int *resplen2, + int *answerp2_malloced) { char nbuf[MAXDNAME]; const char *longname = nbuf; @@ -551,10 +571,6 @@ __libc_res_nquerydomain(res_state statp, name, domain?domain:"<Nil>", class, type); #endif if (domain == NULL) { - /* - * Check for trailing '.'; - * copy without '.' if present. - */ n = strlen(name); /* Decrement N prior to checking it against MAXDNAME @@ -565,11 +581,7 @@ __libc_res_nquerydomain(res_state statp, RES_SET_H_ERRNO(statp, NO_RECOVERY); return (-1); } - if (name[n] == '.') { - strncpy(nbuf, name, n); - nbuf[n] = '\0'; - } else - longname = name; + longname = name; } else { n = strlen(name); d = strlen(domain); @@ -581,7 +593,7 @@ __libc_res_nquerydomain(res_state statp, } return (__libc_res_nquery(statp, longname, class, type, answer, anslen, answerp, answerp2, nanswerp2, - resplen2)); + resplen2, answerp2_malloced)); } int @@ -593,7 +605,8 @@ res_nquerydomain(res_state statp, int anslen) /* size of answer */ { return __libc_res_nquerydomain(statp, name, domain, class, type, - answer, anslen, NULL, NULL, NULL, NULL); + answer, anslen, NULL, NULL, NULL, NULL, + NULL); } libresolv_hidden_def (res_nquerydomain) diff --git a/resolv/res_send.c b/resolv/res_send.c index 7f2e85f324..5e53cc2df6 100644 --- a/resolv/res_send.c +++ b/resolv/res_send.c @@ -96,6 +96,7 @@ static const char rcsid[] = "$BINDId: res_send.c,v 8.38 2000/03/30 20:16:51 vixi #include <string.h> #include <unistd.h> #include <kernel-features.h> +#include <libc-internal.h> #if PACKETSZ > 65536 #define MAXPACKET PACKETSZ @@ -183,15 +184,16 @@ evNowTime(struct timespec *res) { /* Forward. */ +static struct sockaddr *get_nsaddr (res_state, int); static int send_vc(res_state, const u_char *, int, const u_char *, int, u_char **, int *, int *, int, u_char **, - u_char **, int *, int *); + u_char **, int *, int *, int *); static int send_dg(res_state, const u_char *, int, const u_char *, int, u_char **, int *, int *, int, int *, int *, u_char **, - u_char **, int *, int *); + u_char **, int *, int *, int *); #ifdef DEBUG static void Aerror(const res_state, FILE *, const char *, int, const struct sockaddr *); @@ -220,20 +222,21 @@ res_ourserver_p(const res_state statp, const struct sockaddr_in6 *inp) in_port_t port = in4p->sin_port; in_addr_t addr = in4p->sin_addr.s_addr; - for (ns = 0; ns < MAXNS; ns++) { + for (ns = 0; ns < statp->nscount; ns++) { const struct sockaddr_in *srv = - (struct sockaddr_in *)EXT(statp).nsaddrs[ns]; + (struct sockaddr_in *) get_nsaddr (statp, ns); - if ((srv != NULL) && (srv->sin_family == AF_INET) && + if ((srv->sin_family == AF_INET) && (srv->sin_port == port) && (srv->sin_addr.s_addr == INADDR_ANY || srv->sin_addr.s_addr == addr)) return (1); } } else if (inp->sin6_family == AF_INET6) { - for (ns = 0; ns < MAXNS; ns++) { - const struct sockaddr_in6 *srv = EXT(statp).nsaddrs[ns]; - if ((srv != NULL) && (srv->sin6_family == AF_INET6) && + for (ns = 0; ns < statp->nscount; ns++) { + const struct sockaddr_in6 *srv + = (struct sockaddr_in6 *) get_nsaddr (statp, ns); + if ((srv->sin6_family == AF_INET6) && (srv->sin6_port == inp->sin6_port) && !(memcmp(&srv->sin6_addr, &in6addr_any, sizeof (struct in6_addr)) && @@ -343,7 +346,7 @@ int __libc_res_nsend(res_state statp, const u_char *buf, int buflen, const u_char *buf2, int buflen2, u_char *ans, int anssiz, u_char **ansp, u_char **ansp2, - int *nansp2, int *resplen2) + int *nansp2, int *resplen2, int *ansp2_malloced) { int gotsomewhere, terrno, try, v_circuit, resplen, ns, n; @@ -358,7 +361,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen, } #ifdef USE_HOOKS - if (__builtin_expect (statp->qhook || statp->rhook, 0)) { + if (__glibc_unlikely (statp->qhook || statp->rhook)) { if (anssiz < MAXPACKET && ansp) { u_char *buf = malloc (MAXPACKET); if (buf == NULL) @@ -383,74 +386,48 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen, * If the ns_addr_list in the resolver context has changed, then * invalidate our cached copy and the associated timing data. */ - if (EXT(statp).nsinit) { + if (EXT(statp).nscount != 0) { int needclose = 0; if (EXT(statp).nscount != statp->nscount) needclose++; else - for (ns = 0; ns < MAXNS; ns++) { - unsigned int map = EXT(statp).nsmap[ns]; - if (map < MAXNS + for (ns = 0; ns < statp->nscount; ns++) { + if (statp->nsaddr_list[ns].sin_family != 0 && !sock_eq((struct sockaddr_in6 *) - &statp->nsaddr_list[map], + &statp->nsaddr_list[ns], EXT(statp).nsaddrs[ns])) { needclose++; break; } } - if (needclose) + if (needclose) { __res_iclose(statp, false); + EXT(statp).nscount = 0; + } } /* * Maybe initialize our private copy of the ns_addr_list. */ - if (EXT(statp).nsinit == 0) { - unsigned char map[MAXNS]; - - memset (map, MAXNS, sizeof (map)); - for (n = 0; n < MAXNS; n++) { - ns = EXT(statp).nsmap[n]; - if (ns < statp->nscount) - map[ns] = n; - else if (ns < MAXNS) { - free(EXT(statp).nsaddrs[n]); - EXT(statp).nsaddrs[n] = NULL; - EXT(statp).nsmap[n] = MAXNS; - } - } - n = statp->nscount; - if (statp->nscount > EXT(statp).nscount) - for (n = EXT(statp).nscount, ns = 0; - n < statp->nscount; n++) { - while (ns < MAXNS - && EXT(statp).nsmap[ns] != MAXNS) - ns++; - if (ns == MAXNS) - break; - EXT(statp).nsmap[ns] = n; - map[n] = ns++; - } - EXT(statp).nscount = n; - for (ns = 0; ns < EXT(statp).nscount; ns++) { - n = map[ns]; - if (EXT(statp).nsaddrs[n] == NULL) - EXT(statp).nsaddrs[n] = + if (EXT(statp).nscount == 0) { + for (ns = 0; ns < statp->nscount; ns++) { + EXT(statp).nssocks[ns] = -1; + if (statp->nsaddr_list[ns].sin_family == 0) + continue; + if (EXT(statp).nsaddrs[ns] == NULL) + EXT(statp).nsaddrs[ns] = malloc(sizeof (struct sockaddr_in6)); - if (EXT(statp).nsaddrs[n] != NULL) { - memset (mempcpy(EXT(statp).nsaddrs[n], + if (EXT(statp).nsaddrs[ns] != NULL) + memset (mempcpy(EXT(statp).nsaddrs[ns], &statp->nsaddr_list[ns], sizeof (struct sockaddr_in)), '\0', sizeof (struct sockaddr_in6) - sizeof (struct sockaddr_in)); - EXT(statp).nssocks[n] = -1; - n++; - } } - EXT(statp).nsinit = 1; + EXT(statp).nscount = statp->nscount; } /* @@ -459,47 +436,40 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen, */ if (__builtin_expect ((statp->options & RES_ROTATE) != 0, 0) && (statp->options & RES_BLAST) == 0) { - struct sockaddr_in6 *ina; - unsigned int map; - - n = 0; - while (n < MAXNS && EXT(statp).nsmap[n] == MAXNS) - n++; - if (n < MAXNS) { - ina = EXT(statp).nsaddrs[n]; - map = EXT(statp).nsmap[n]; - for (;;) { - ns = n + 1; - while (ns < MAXNS - && EXT(statp).nsmap[ns] == MAXNS) - ns++; - if (ns == MAXNS) - break; - EXT(statp).nsaddrs[n] = EXT(statp).nsaddrs[ns]; - EXT(statp).nsmap[n] = EXT(statp).nsmap[ns]; - n = ns; - } - EXT(statp).nsaddrs[n] = ina; - EXT(statp).nsmap[n] = map; + struct sockaddr_in ina; + struct sockaddr_in6 *inp; + int lastns = statp->nscount - 1; + int fd; + + inp = EXT(statp).nsaddrs[0]; + ina = statp->nsaddr_list[0]; + fd = EXT(statp).nssocks[0]; + for (ns = 0; ns < lastns; ns++) { + EXT(statp).nsaddrs[ns] = EXT(statp).nsaddrs[ns + 1]; + statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1]; + EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1]; } + EXT(statp).nsaddrs[lastns] = inp; + statp->nsaddr_list[lastns] = ina; + EXT(statp).nssocks[lastns] = fd; } /* * Send request, RETRY times, or until successful. */ for (try = 0; try < statp->retry; try++) { - for (ns = 0; ns < MAXNS; ns++) + for (ns = 0; ns < statp->nscount; ns++) { #ifdef DEBUG char tmpbuf[40]; #endif - struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns]; +#if defined USE_HOOKS || defined DEBUG + struct sockaddr *nsap = get_nsaddr (statp, ns); +#endif - if (nsap == NULL) - goto next_ns; same_ns: #ifdef USE_HOOKS - if (__builtin_expect (statp->qhook != NULL, 0)) { + if (__glibc_unlikely (statp->qhook != NULL)) { int done = 0, loops = 0; do { @@ -535,18 +505,19 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen, Dprint(statp->options & RES_DEBUG, (stdout, ";; Querying server (# %d) address = %s\n", - ns + 1, inet_ntop(nsap->sin6_family, - (nsap->sin6_family == AF_INET6 - ? &nsap->sin6_addr + ns + 1, inet_ntop(nsap->sa_family, + (nsap->sa_family == AF_INET6 + ? &((struct sockaddr_in6 *) nsap)->sin6_addr : &((struct sockaddr_in *) nsap)->sin_addr), tmpbuf, sizeof (tmpbuf)))); - if (__builtin_expect (v_circuit, 0)) { + if (__glibc_unlikely (v_circuit)) { /* Use VC; at most one attempt per server. */ try = statp->retry; n = send_vc(statp, buf, buflen, buf2, buflen2, &ans, &anssiz, &terrno, - ns, ansp, ansp2, nansp2, resplen2); + ns, ansp, ansp2, nansp2, resplen2, + ansp2_malloced); if (n < 0) return (-1); if (n == 0 && (buf2 == NULL || *resplen2 == 0)) @@ -556,7 +527,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen, n = send_dg(statp, buf, buflen, buf2, buflen2, &ans, &anssiz, &terrno, ns, &v_circuit, &gotsomewhere, ansp, - ansp2, nansp2, resplen2); + ansp2, nansp2, resplen2, ansp2_malloced); if (n < 0) return (-1); if (n == 0 && (buf2 == NULL || *resplen2 == 0)) @@ -595,7 +566,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen, __res_iclose(statp, false); } #ifdef USE_HOOKS - if (__builtin_expect (statp->rhook, 0)) { + if (__glibc_unlikely (statp->rhook)) { int done = 0, loops = 0; do { @@ -646,18 +617,33 @@ res_nsend(res_state statp, const u_char *buf, int buflen, u_char *ans, int anssiz) { return __libc_res_nsend(statp, buf, buflen, NULL, 0, ans, anssiz, - NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, NULL); } libresolv_hidden_def (res_nsend) /* Private */ +static struct sockaddr * +get_nsaddr (res_state statp, int n) +{ + + if (statp->nsaddr_list[n].sin_family == 0 && EXT(statp).nsaddrs[n] != NULL) + /* EXT(statp).nsaddrs[n] holds an address that is larger than + struct sockaddr, and user code did not update + statp->nsaddr_list[n]. */ + return (struct sockaddr *) EXT(statp).nsaddrs[n]; + else + /* User code updated statp->nsaddr_list[n], or statp->nsaddr_list[n] + has the same content as EXT(statp).nsaddrs[n]. */ + return (struct sockaddr *) (void *) &statp->nsaddr_list[n]; +} + static int send_vc(res_state statp, const u_char *buf, int buflen, const u_char *buf2, int buflen2, u_char **ansp, int *anssizp, int *terrno, int ns, u_char **anscp, u_char **ansp2, int *anssizp2, - int *resplen2) + int *resplen2, int *ansp2_malloced) { const HEADER *hp = (HEADER *) buf; const HEADER *hp2 = (HEADER *) buf2; @@ -666,8 +652,25 @@ send_vc(res_state statp, // XXX REMOVE // int anssiz = *anssizp; HEADER *anhp = (HEADER *) ans; - struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns]; - int truncating, connreset, resplen, n; + struct sockaddr *nsap = get_nsaddr (statp, ns); + int truncating, connreset, n; + /* On some architectures compiler might emit a warning indicating + 'resplen' may be used uninitialized. However if buf2 == NULL + then this code won't be executed; if buf2 != NULL, then first + time round the loop recvresp1 and recvresp2 will be 0 so this + code won't be executed but "thisresplenp = &resplen;" followed + by "*thisresplenp = rlen;" will be executed so that subsequent + times round the loop resplen has been initialized. So this is + a false-positive. + */ +#if __GNUC_PREREQ (4, 7) + DIAG_PUSH_NEEDS_COMMENT; + DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized"); +#endif + int resplen; +#if __GNUC_PREREQ (4, 7) + DIAG_POP_NEEDS_COMMENT; +#endif struct iovec iov[4]; u_short len; u_short len2; @@ -686,8 +689,8 @@ send_vc(res_state statp, if (getpeername(statp->_vcsock, (struct sockaddr *)&peer, &size) < 0 || - !sock_eq(&peer, nsap)) { - __res_iclose(statp, false); + !sock_eq(&peer, (struct sockaddr_in6 *) nsap)) { + __res_iclose(statp, false); statp->_flags &= ~RES_F_VC; } } @@ -696,20 +699,19 @@ send_vc(res_state statp, if (statp->_vcsock >= 0) __res_iclose(statp, false); - statp->_vcsock = socket(nsap->sin6_family, SOCK_STREAM, 0); + statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0); if (statp->_vcsock < 0) { *terrno = errno; Perror(statp, stderr, "socket(vc)", errno); return (-1); } __set_errno (0); - if (connect(statp->_vcsock, (struct sockaddr *)nsap, - nsap->sin6_family == AF_INET + if (connect(statp->_vcsock, nsap, + nsap->sa_family == AF_INET ? sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6)) < 0) { *terrno = errno; - Aerror(statp, stderr, "connect/vc", errno, - (struct sockaddr *) nsap); + Aerror(statp, stderr, "connect/vc", errno, nsap); __res_iclose(statp, false); return (0); } @@ -786,7 +788,11 @@ send_vc(res_state statp, /* No buffer allocated for the first reply. We can try to use the rest of the user-provided buffer. */ -#ifdef _STRING_ARCH_unaligned +#if __GNUC_PREREQ (4, 7) + DIAG_PUSH_NEEDS_COMMENT; + DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized"); +#endif +#if _STRING_ARCH_unaligned *anssizp2 = orig_anssizp - resplen; *ansp2 = *ansp + resplen; #else @@ -796,6 +802,9 @@ send_vc(res_state statp, *anssizp2 = orig_anssizp - aligned_resplen; *ansp2 = *ansp + aligned_resplen; #endif +#if __GNUC_PREREQ (4, 7) + DIAG_POP_NEEDS_COMMENT; +#endif } else { /* The first reply did not fit into the user-provided buffer. Maybe the second @@ -814,7 +823,7 @@ send_vc(res_state statp, if (rlen > *thisanssizp) { /* Yes, we test ANSCP here. If we have two buffers both will be allocatable. */ - if (__builtin_expect (anscp != NULL, 1)) { + if (__glibc_likely (anscp != NULL)) { u_char *newp = malloc (MAXPACKET); if (newp == NULL) { *terrno = ENOMEM; @@ -823,6 +832,8 @@ send_vc(res_state statp, } *thisanssizp = MAXPACKET; *thisansp = newp; + if (thisansp == ansp2) + *ansp2_malloced = 1; anhp = (HEADER *) newp; len = rlen; } else { @@ -835,7 +846,7 @@ send_vc(res_state statp, } else len = rlen; - if (__builtin_expect (len < HFIXEDSZ, 0)) { + if (__glibc_unlikely (len < HFIXEDSZ)) { /* * Undersized message. */ @@ -851,13 +862,13 @@ send_vc(res_state statp, cp += n; len -= n; } - if (__builtin_expect (n <= 0, 0)) { + if (__glibc_unlikely (n <= 0)) { *terrno = errno; Perror(statp, stderr, "read(vc)", errno); __res_iclose(statp, false); return (0); } - if (__builtin_expect (truncating, 0)) { + if (__glibc_unlikely (truncating)) { /* * Flush rest of answer so connection stays in synch. */ @@ -911,13 +922,12 @@ static int reopen (res_state statp, int *terrno, int ns) { if (EXT(statp).nssocks[ns] == -1) { - struct sockaddr *nsap - = (struct sockaddr *) EXT(statp).nsaddrs[ns]; + struct sockaddr *nsap = get_nsaddr (statp, ns); socklen_t slen; /* only try IPv6 if IPv6 NS and if not failed before */ if (nsap->sa_family == AF_INET6 && !statp->ipv6_unavail) { - if (__builtin_expect (__have_o_nonblock >= 0, 1)) { + if (__glibc_likely (__have_o_nonblock >= 0)) { EXT(statp).nssocks[ns] = socket(PF_INET6, SOCK_DGRAM|SOCK_NONBLOCK, 0); @@ -928,14 +938,14 @@ reopen (res_state statp, int *terrno, int ns) && errno == EINVAL ? -1 : 1); #endif } - if (__builtin_expect (__have_o_nonblock < 0, 0)) + if (__glibc_unlikely (__have_o_nonblock < 0)) EXT(statp).nssocks[ns] = socket(PF_INET6, SOCK_DGRAM, 0); if (EXT(statp).nssocks[ns] < 0) statp->ipv6_unavail = errno == EAFNOSUPPORT; slen = sizeof (struct sockaddr_in6); } else if (nsap->sa_family == AF_INET) { - if (__builtin_expect (__have_o_nonblock >= 0, 1)) { + if (__glibc_likely (__have_o_nonblock >= 0)) { EXT(statp).nssocks[ns] = socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK, 0); @@ -946,7 +956,7 @@ reopen (res_state statp, int *terrno, int ns) && errno == EINVAL ? -1 : 1); #endif } - if (__builtin_expect (__have_o_nonblock < 0, 0)) + if (__glibc_unlikely (__have_o_nonblock < 0)) EXT(statp).nssocks[ns] = socket(PF_INET, SOCK_DGRAM, 0); slen = sizeof (struct sockaddr_in); @@ -973,7 +983,7 @@ reopen (res_state statp, int *terrno, int ns) __res_iclose(statp, false); return (0); } - if (__builtin_expect (__have_o_nonblock < 0, 0)) { + if (__glibc_unlikely (__have_o_nonblock < 0)) { /* Make socket non-blocking. */ int fl = __fcntl (EXT(statp).nssocks[ns], F_GETFL); if (fl != -1) @@ -992,7 +1002,7 @@ send_dg(res_state statp, const u_char *buf, int buflen, const u_char *buf2, int buflen2, u_char **ansp, int *anssizp, int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp, - u_char **ansp2, int *anssizp2, int *resplen2) + u_char **ansp2, int *anssizp2, int *resplen2, int *ansp2_malloced) { const HEADER *hp = (HEADER *) buf; const HEADER *hp2 = (HEADER *) buf2; @@ -1055,7 +1065,7 @@ send_dg(res_state statp, n = 0; if (nwritten == 0) n = __poll (pfd, 1, 0); - if (__builtin_expect (n == 0, 0)) { + if (__glibc_unlikely (n == 0)) { n = __poll (pfd, 1, ptimeout); need_recompute = 1; } @@ -1130,7 +1140,7 @@ send_dg(res_state statp, reqs[1].msg_hdr.msg_controllen = 0; int ndg = __sendmmsg (pfd[0].fd, reqs, 2, MSG_NOSIGNAL); - if (__builtin_expect (ndg == 2, 1)) + if (__glibc_likely (ndg == 2)) { if (reqs[0].msg_len != buflen || reqs[1].msg_len != buflen2) @@ -1146,7 +1156,7 @@ send_dg(res_state statp, else { #ifndef __ASSUME_SENDMMSG - if (__builtin_expect (have_sendmmsg == 0, 0)) + if (__glibc_unlikely (have_sendmmsg == 0)) { if (ndg < 0 && errno == ENOSYS) { @@ -1202,7 +1212,7 @@ send_dg(res_state statp, /* No buffer allocated for the first reply. We can try to use the rest of the user-provided buffer. */ -#ifdef _STRING_ARCH_unaligned +#if _STRING_ARCH_unaligned *anssizp2 = orig_anssizp - resplen; *ansp2 = *ansp + resplen; #else @@ -1238,6 +1248,8 @@ send_dg(res_state statp, if (newp != NULL) { *anssizp = MAXPACKET; *thisansp = ans = newp; + if (thisansp == ansp2) + *ansp2_malloced = 1; } } HEADER *anhp = (HEADER *) *thisansp; @@ -1246,7 +1258,7 @@ send_dg(res_state statp, *thisresplenp = recvfrom(pfd[0].fd, (char*)*thisansp, *thisanssizp, 0, (struct sockaddr *)&from, &fromlen); - if (__builtin_expect (*thisresplenp <= 0, 0)) { + if (__glibc_unlikely (*thisresplenp <= 0)) { if (errno == EINTR || errno == EAGAIN) { need_recompute = 1; goto wait; @@ -1255,7 +1267,7 @@ send_dg(res_state statp, goto err_out; } *gotsomewhere = 1; - if (__builtin_expect (*thisresplenp < HFIXEDSZ, 0)) { + if (__glibc_unlikely (*thisresplenp < HFIXEDSZ)) { /* * Undersized message. */ @@ -1346,6 +1358,7 @@ send_dg(res_state statp, (*thisresplenp > *thisanssizp) ? *thisanssizp : *thisresplenp); + next_ns: if (recvresp1 || (buf2 != NULL && recvresp2)) { *resplen2 = 0; return resplen; @@ -1363,7 +1376,6 @@ send_dg(res_state statp, goto wait; } - next_ns: __res_iclose(statp, false); /* don't retry if called from dig */ if (!statp->pfcode) @@ -1405,6 +1417,7 @@ send_dg(res_state statp, retval = reopen (statp, terrno, ns); if (retval <= 0) return retval; + pfd[0].fd = EXT(statp).nssocks[ns]; } } goto wait; diff --git a/resolv/rpc/netdb.h b/resolv/rpc/netdb.h new file mode 100644 index 0000000000..eecea3cb06 --- /dev/null +++ b/resolv/rpc/netdb.h @@ -0,0 +1,3 @@ +/* This is a dummy file for <rpc/netdb.h>, which is included by <netdb.h>. + This file is installed when the C library does not support the SunRPC + interfaces (including 'struct rpcent' et al) at all. */ diff --git a/resolv/tst-inet_ntop.c b/resolv/tst-inet_ntop.c index f968ec4dcb..f0de06306c 100644 --- a/resolv/tst-inet_ntop.c +++ b/resolv/tst-inet_ntop.c @@ -4,8 +4,8 @@ #include <stdio.h> #include <string.h> -int -main (void) +static int +do_test (void) { struct in_addr addr4; struct in6_addr addr6; @@ -109,3 +109,6 @@ main (void) return result; } + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/resolv/tst-leaks.c b/resolv/tst-leaks.c index e1f42f1264..290d936cd4 100644 --- a/resolv/tst-leaks.c +++ b/resolv/tst-leaks.c @@ -1,5 +1,5 @@ /* Tests for res_query in libresolv - Copyright (C) 2003-2014 Free Software Foundation, Inc. + Copyright (C) 2003-2015 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 diff --git a/resolv/tst-leaks2.c b/resolv/tst-leaks2.c index b964ae7435..dfb7ca26b0 100644 --- a/resolv/tst-leaks2.c +++ b/resolv/tst-leaks2.c @@ -1,5 +1,5 @@ /* Tests for res_init in libresolv - Copyright (C) 2004-2014 Free Software Foundation, Inc. + Copyright (C) 2004-2015 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 diff --git a/resolv/tst-res_hconf_reorder.c b/resolv/tst-res_hconf_reorder.c new file mode 100644 index 0000000000..1e7e0e2fa5 --- /dev/null +++ b/resolv/tst-res_hconf_reorder.c @@ -0,0 +1,112 @@ +/* BZ #17977 _res_hconf_reorder_addrs test. + + Copyright (C) 2015 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 + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <dlfcn.h> +#include <pthread.h> +#include <netdb.h> +#include <netinet/in.h> +#include <sys/socket.h> + +static struct timespec ts; + +/* The first thread that gets a lock in _res_hconf_reorder_addrs() + should hold the lock long enough to make two other threads blocked. + This is achieved by slowing down realloc(3) that is called several times + by _res_hconf_reorder_addrs(). */ + +void * +realloc (void *ptr, size_t len) +{ + static void *(*fun) (void *, size_t); + + if (!fun) + fun = dlsym (RTLD_NEXT, "realloc"); + + if (ts.tv_nsec) + nanosleep (&ts, NULL); + + return (*fun) (ptr, len); +} + +static void * +resolve (void *arg) +{ + struct in_addr addr; + struct hostent ent; + struct hostent *result; + int err; + char buf[1024]; + + addr.s_addr = htonl (INADDR_LOOPBACK); + (void) gethostbyaddr_r ((void *) &addr, sizeof (addr), AF_INET, + &ent, buf, sizeof (buf), &result, &err); + return arg; +} + +static int +do_test (void) +{ + #define N 3 + pthread_t thr[N]; + unsigned int i; + int result = 0; + + /* turn on realloc slowdown */ + ts.tv_nsec = 100000000; + + for (i = 0; i < N; ++i) + { + int rc = pthread_create (&thr[i], NULL, resolve, NULL); + + if (rc) + { + printf ("pthread_create: %s\n", strerror(rc)); + exit (1); + } + } + + for (i = 0; i < N; ++i) + { + void *retval; + int rc = pthread_join (thr[i], &retval); + + if (rc) + { + printf ("pthread_join: %s\n", strerror(rc)); + exit (1); + } + if (retval) + { + printf ("thread %u exit status %p\n", i, retval); + result = 1; + } + } + + /* turn off realloc slowdown, no longer needed */ + ts.tv_nsec = 0; + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" |