diff options
author | Ulrich Drepper <drepper@redhat.com> | 2004-08-05 23:32:24 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2004-08-05 23:32:24 +0000 |
commit | 87bb6b6c6bb6d5ff5e5b2a719fa32c77e9898459 (patch) | |
tree | 62536f4dd4680dc660ad8293e9a47ed7249ce4d3 /resolv | |
parent | a79d752f3da1085b4f00ef1a817d8beadcc3014a (diff) | |
download | glibc-87bb6b6c6bb6d5ff5e5b2a719fa32c77e9898459.tar.gz glibc-87bb6b6c6bb6d5ff5e5b2a719fa32c77e9898459.tar.xz glibc-87bb6b6c6bb6d5ff5e5b2a719fa32c77e9898459.zip |
Update.
2004-08-04 Jakub Jelinek <jakub@redhat.com> * hesiod/hesiod.c (__hesiod_res_get): Use calloc instead of malloc + memset. (__hesiod_res_set): Free nsaddrs. * include/resolv.h (__res_maybe_init): Add prototype. * resolv/resolv.h (struct __res_state): Add _u._ext.initstamp field. * resolv/Versions (libc): Add __res_maybe_init@@GLIBC_PRIVATE. * resolv/res_libc.c (__res_initstamp, lock): New variables. (res_init): Increase __res_initstamp. (__res_maybe_init): New function. * resolv/res_init.c (__res_vinit): Initialize _u._ext.initstamp. * hesiod/hesiod.c (__hesiod_res_get): Use __res_maybe_init instead of RES_INIT check and {res_ninit,__res_ninit,res_init} call. * sysdeps/posix/getaddrinfo.c (gaih_inet): Likewise. * resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname2_r, _nss_dns_gethostbyaddr_r): Likewise. * resolv/nss_dns/dns-network.c (_nss_dns_getnetbyname_r, _nss_dns_getnetbyaddr_r): Likewise. * resolv/gethnamaddr.c (gethostbyname, gethostbyname2, gethostbyaddr): Likewise. * resolv/res_data.c (fp_nquery, res_mkquery, res_mkupdate, res_isourserver, res_sendsigned, res_update, res_search, res_querydomain): Likewise. * nss/getXXbyYY_r.c (INTERNAL (REENTRANT_NAME)): Likewise. * nss/digits_dots.c (__nss_hostname_digits_dots): Likewise. * nss/getnssent_r.c (__nss_setent, __nss_endent, __nss_getent_r): Likewise. * sysdeps/posix/getaddrinfo.c (gaih_inet): Set ai_family for V4-mapped IPv6 addresses and req->ai_family==AF_INET. Reported by A. Guru <a.guru@sympatico.ca>. * po/pl.po: Likewise. characters than necessary.
Diffstat (limited to 'resolv')
-rw-r--r-- | resolv/Versions | 2 | ||||
-rw-r--r-- | resolv/gethnamaddr.c | 8 | ||||
-rw-r--r-- | resolv/nss_dns/dns-host.c | 4 | ||||
-rw-r--r-- | resolv/nss_dns/dns-network.c | 7 | ||||
-rw-r--r-- | resolv/res_data.c | 18 | ||||
-rw-r--r-- | resolv/res_init.c | 4 | ||||
-rw-r--r-- | resolv/res_libc.c | 52 | ||||
-rw-r--r-- | resolv/resolv.h | 6 |
8 files changed, 83 insertions, 18 deletions
diff --git a/resolv/Versions b/resolv/Versions index 1a24d30e96..a809508aa0 100644 --- a/resolv/Versions +++ b/resolv/Versions @@ -38,6 +38,8 @@ libc { # This version is for the TLS symbol, GLIBC_2.0 is the old object symbol. h_errno; __resp; %endif + + __res_maybe_init; } } diff --git a/resolv/gethnamaddr.c b/resolv/gethnamaddr.c index c93ca51c88..a02d0fb617 100644 --- a/resolv/gethnamaddr.c +++ b/resolv/gethnamaddr.c @@ -493,10 +493,10 @@ gethostbyname(name) { struct hostent *hp; - if ((_res.options & RES_INIT) == 0 && __res_ninit(&_res) == -1) { + if (__res_maybe_init (&_res, 0) == -1) { __set_h_errno (NETDB_INTERNAL); return (NULL); - } + } if (_res.options & RES_USE_INET6) { hp = gethostbyname2(name, AF_INET6); if (hp) @@ -522,7 +522,7 @@ gethostbyname2(name, af) struct hostent *ret; extern struct hostent *_gethtbyname2(); - if ((_res.options & RES_INIT) == 0 && __res_ninit(&_res) == -1) { + if (__res_maybe_init (&_res, 0) == -1) { __set_h_errno (NETDB_INTERNAL); return (NULL); } @@ -665,7 +665,7 @@ gethostbyaddr(addr, len, af) #endif /*SUNSECURITY*/ extern struct hostent *_gethtbyaddr(); - if ((_res.options & RES_INIT) == 0 && __res_ninit(&_res) == -1) { + if (__res_maybe_init (&_res, 0) == -1) { __set_h_errno (NETDB_INTERNAL); return (NULL); } diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c index 0424cb9e2a..91699cc50d 100644 --- a/resolv/nss_dns/dns-host.c +++ b/resolv/nss_dns/dns-host.c @@ -145,7 +145,7 @@ _nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result, int olderr = errno; enum nss_status status; - if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1) + if (__res_maybe_init (&_res, 0) == -1) return NSS_STATUS_UNAVAIL; switch (af) { @@ -263,7 +263,7 @@ _nss_dns_gethostbyaddr_r (const void *addr, socklen_t len, int af, int n, status; int olderr = errno; - if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1) + if (__res_maybe_init (&_res, 0) == -1) return NSS_STATUS_UNAVAIL; if (af == AF_INET6 && len == IN6ADDRSZ diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c index efda486b8c..a5d2c7945f 100644 --- a/resolv/nss_dns/dns-network.c +++ b/resolv/nss_dns/dns-network.c @@ -1,4 +1,5 @@ -/* Copyright (C) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc. +/* Copyright (C) 1996, 1997, 1998, 1999, 2002, 2004 + Free Software Foundation, Inc. This file is part of the GNU C Library. Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996. @@ -120,7 +121,7 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result, char *qbuf; enum nss_status status; - if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1) + if (__res_maybe_init (&_res, 0) == -1) return NSS_STATUS_UNAVAIL; qbuf = strdupa (name); @@ -171,7 +172,7 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result, if (type != AF_INET) return NSS_STATUS_UNAVAIL; - if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1) + if (__res_maybe_init (&_res, 0) == -1) return NSS_STATUS_UNAVAIL; net2 = (u_int32_t) net; diff --git a/resolv/res_data.c b/resolv/res_data.c index 7488ba7772..2183e022c8 100644 --- a/resolv/res_data.c +++ b/resolv/res_data.c @@ -141,7 +141,7 @@ fp_query(const u_char *msg, FILE *file) { void fp_nquery(const u_char *msg, int len, FILE *file) { - if ((_res.options & RES_INIT) == 0 && __res_ninit(&_res) == -1) + if (__res_maybe_init (&_res, 0) == -1) return; res_pquery(&_res, msg, len, file); @@ -157,7 +157,7 @@ res_mkquery(int op, /* opcode of query */ u_char *buf, /* buffer to put query */ int buflen) /* size of buffer */ { - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + if (__res_maybe_init (&_res, 1) == -1) { RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); return (-1); } @@ -169,7 +169,7 @@ res_mkquery(int op, /* opcode of query */ #ifdef BIND_UPDATE int res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) { - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + if (__res_maybe_init (&_res, 1) == -1) { RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); return (-1); } @@ -184,7 +184,7 @@ res_query(const char *name, /* domain name */ u_char *answer, /* buffer to put answer */ int anslen) /* size of answer buffer */ { - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + if (__res_maybe_init (&_res, 1) == -1) { RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); return (-1); } @@ -208,7 +208,7 @@ res_isourserver(const struct sockaddr_in *inp) { int res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) { - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + if (__res_maybe_init (&_res, 1) == -1) { /* errno should have been set by res_init() in this case. */ return (-1); } @@ -221,7 +221,7 @@ int res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key, u_char *ans, int anssiz) { - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + if (__res_maybe_init (&_res, 1) == -1) { /* errno should have been set by res_init() in this case. */ return (-1); } @@ -249,7 +249,7 @@ res_close(void) { #ifdef BIND_UPDATE int res_update(ns_updrec *rrecp_in) { - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + if (__res_maybe_init (&_res, 1) == -1) { RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); return (-1); } @@ -264,7 +264,7 @@ res_search(const char *name, /* domain name */ u_char *answer, /* buffer to put answer */ int anslen) /* size of answer */ { - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + if (__res_maybe_init (&_res, 1) == -1) { RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); return (-1); } @@ -279,7 +279,7 @@ res_querydomain(const char *name, u_char *answer, /* buffer to put answer */ int anslen) /* size of answer */ { - if ((_res.options & RES_INIT) == 0 && res_init() == -1) { + if (__res_maybe_init (&_res, 1) == -1) { RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); return (-1); } diff --git a/resolv/res_init.c b/resolv/res_init.c index d0559c3821..078480cb61 100644 --- a/resolv/res_init.c +++ b/resolv/res_init.c @@ -161,6 +161,10 @@ __res_vinit(res_state statp, int preinit) { #ifndef RFC1535 int dots; #endif +#ifdef _LIBC + extern unsigned long long int __res_initstamp attribute_hidden; + statp->_u._ext.initstamp = __res_initstamp; +#endif if (!preinit) { statp->retrans = RES_TIMEOUT; diff --git a/resolv/res_libc.c b/resolv/res_libc.c index 94bb2fdca6..b1047f009b 100644 --- a/resolv/res_libc.c +++ b/resolv/res_libc.c @@ -15,16 +15,31 @@ * SOFTWARE. */ +#include <limits.h> #include <sys/types.h> #include <netinet/in.h> #include <arpa/nameser.h> #include <resolv.h> +#include <bits/libc-lock.h> /* The following bit is copied from res_data.c (where it is #ifdef'ed out) since res_init() should go into libc.so but the rest of that file should not. */ +unsigned long long int __res_initstamp attribute_hidden; +/* We have atomic increment operations on 64-bit platforms. */ +#if __WORDSIZE == 64 +# define atomicinclock(lock) (void) 0 +# define atomicincunlock(lock) (void) 0 +# define atomicinc(var) atomic_increment (&(var)) +#else +__libc_lock_define_initialized (static, lock); +# define atomicinclock(lock) __libc_lock_lock (lock) +# define atomicincunlock(lock) __libc_lock_unlock (lock) +# define atomicinc(var) ++var +#endif + int res_init(void) { extern int __res_vinit(res_state, int); @@ -70,8 +85,45 @@ res_init(void) { if (!_res.id) _res.id = res_randomid(); + atomicinclock (lock); + /* Request all threads to re-initialize their resolver states, + resolv.conf might have changed. */ + atomicinc (__res_initstamp); + atomicincunlock (lock); + return (__res_vinit(&_res, 1)); } + +/* Initialize resp if RES_INIT is not yet set or if res_init in some other + thread requested re-initializing. */ +int +__res_maybe_init (res_state resp, int preinit) +{ + if (resp->options & RES_INIT) { + if (__res_initstamp != resp->_u._ext.initstamp) { + if (resp->nscount > 0) { + __res_nclose (resp); + for (int ns = 0; ns < MAXNS; ns++) { + free (resp->_u._ext.nsaddrs[ns]); + resp->_u._ext.nsaddrs[ns] = NULL; + } + return __res_vinit (resp, 1); + } + } + return 0; + } else if (preinit) { + if (!resp->retrans) + resp->retrans = RES_TIMEOUT; + if (!resp->retry) + resp->retry = 4; + resp->options = RES_DEFAULT; + if (!resp->id) + resp->id = res_randomid (); + return __res_vinit (resp, 1); + } else + return __res_ninit (resp); +} +libc_hidden_def (__res_maybe_init) /* This needs to be after the use of _res in res_init, above. */ #undef _res diff --git a/resolv/resolv.h b/resolv/resolv.h index 010d7dd897..00eabe8694 100644 --- a/resolv/resolv.h +++ b/resolv/resolv.h @@ -134,6 +134,12 @@ struct __res_state { u_int16_t nscount6; u_int16_t nsinit; struct sockaddr_in6 *nsaddrs[MAXNS]; +#ifdef _LIBC + unsigned long long int initstamp + __attribute__((packed)); +#else + unsigned int _initstamp[2]; +#endif } _ext; } _u; }; |