* nscd/aicache.c: Prefer using gethostbyname3_r NSS callback to also
	get ttl and canonical name.  Use these two values.
	* resolv/Versions: Export _nss_dns_gethostbyname3_r from libnss_dns.
	* resolv/nss_dns/dns-host.c (getanswer_r): Take two new parameters.
	If nonnull fill with TTL and pointer to canonical name respectively.
	(_nss_dns_gethostbyaddr_r): Pass NULL in new parameters of getanswer_r.
	(_nss_dns_gethostbyname2_r): Just wrapper around
	_nss_dns_gethostbyname3_r.
	(_nss_dns_gethostbyname3_r): Renamed from _nss_dns_gethostbyname2_r.
	Take two new parameters which as passed to getanswer_r.
This commit is contained in:
Ulrich Drepper 2004-09-15 10:10:05 +00:00
parent dc4f1624fc
commit d1fe1f2219
5 changed files with 114 additions and 35 deletions

View File

@ -1,5 +1,16 @@
2004-09-15 Ulrich Drepper <drepper@redhat.com> 2004-09-15 Ulrich Drepper <drepper@redhat.com>
* nscd/aicache.c: Prefer using gethostbyname3_r NSS callback to also
get ttl and canonical name. Use these two values.
* resolv/Versions: Export _nss_dns_gethostbyname3_r from libnss_dns.
* resolv/nss_dns/dns-host.c (getanswer_r): Take two new parameters.
If nonnull fill with TTL and pointer to canonical name respectively.
(_nss_dns_gethostbyaddr_r): Pass NULL in new parameters of getanswer_r.
(_nss_dns_gethostbyname2_r): Just wrapper around
_nss_dns_gethostbyname3_r.
(_nss_dns_gethostbyname3_r): Renamed from _nss_dns_gethostbyname2_r.
Take two new parameters which as passed to getanswer_r.
* nscd/Makefile (rountines): Add nscd_getai. * nscd/Makefile (rountines): Add nscd_getai.
(nscd-modules): Add aicache. (nscd-modules): Add aicache.
* nscd/aicache.c: New file. * nscd/aicache.c: New file.

View File

@ -30,10 +30,10 @@
#include <nscd.h> #include <nscd.h>
typedef enum nss_status (*nss_gethostbyname2_r) typedef enum nss_status (*nss_gethostbyname3_r)
(const char *name, int af, struct hostent *host, (const char *name, int af, struct hostent *host,
char *buffer, size_t buflen, int *errnop, char *buffer, size_t buflen, int *errnop,
int *h_errnop); int *h_errnop, int32_t *, char **);
typedef enum nss_status (*nss_getcanonname_r) typedef enum nss_status (*nss_getcanonname_r)
(const char *name, char *buffer, size_t buflen, char **result, (const char *name, char *buffer, size_t buflen, char **result,
int *errnop, int *h_errnop); int *errnop, int *h_errnop);
@ -114,19 +114,23 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
size_t tmpbuf4len = 0; size_t tmpbuf4len = 0;
char *tmpbuf4 = NULL; char *tmpbuf4 = NULL;
char *canon = NULL; char *canon = NULL;
int32_t ttl = UINT32_MAX;
ssize_t total = 0; ssize_t total = 0;
char *key_copy = NULL; char *key_copy = NULL;
bool alloca_used = false; bool alloca_used = false;
while (!no_more) while (!no_more)
{ {
nss_gethostbyname2_r fct = __nss_lookup_function (nip,
"gethostbyname2_r");
int status[2] = { NSS_STATUS_UNAVAIL, NSS_STATUS_UNAVAIL }; int status[2] = { NSS_STATUS_UNAVAIL, NSS_STATUS_UNAVAIL };
/* Prefer the function which also returns the TTL and canonical name. */
nss_gethostbyname3_r fct = __nss_lookup_function (nip,
"gethostbyname3_r");
if (fct == NULL)
fct = __nss_lookup_function (nip, "gethostbyname2_r");
if (fct != NULL) if (fct != NULL)
{ {
printf("fct=%p\n",fct);
struct hostent th[2]; struct hostent th[2];
/* Collect IPv6 information first. */ /* Collect IPv6 information first. */
@ -134,7 +138,8 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
{ {
rc6 = 0; rc6 = 0;
status[0] = DL_CALL_FCT (fct, (key, AF_INET6, &th[0], tmpbuf6, status[0] = DL_CALL_FCT (fct, (key, AF_INET6, &th[0], tmpbuf6,
tmpbuf6len, &rc6, &herrno)); tmpbuf6len, &rc6, &herrno,
&ttl, &canon));
if (rc6 != ERANGE || herrno != NETDB_INTERNAL) if (rc6 != ERANGE || herrno != NETDB_INTERNAL)
break; break;
tmpbuf6 = extend_alloca (tmpbuf6, tmpbuf6len, 2 * tmpbuf6len); tmpbuf6 = extend_alloca (tmpbuf6, tmpbuf6len, 2 * tmpbuf6len);
@ -161,10 +166,12 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
{ {
rc4 = 0; rc4 = 0;
status[1] = DL_CALL_FCT (fct, (key, AF_INET, &th[1], tmpbuf4, status[1] = DL_CALL_FCT (fct, (key, AF_INET, &th[1], tmpbuf4,
tmpbuf4len, &rc4, &herrno)); tmpbuf4len, &rc4, &herrno,
ttl == UINT32_MAX ? &ttl : NULL,
canon == NULL ? &canon : NULL));
if (rc4 != ERANGE || herrno != NETDB_INTERNAL) if (rc4 != ERANGE || herrno != NETDB_INTERNAL)
break; break;
tmpbuf4 = extend_alloca (tmpbuf6, tmpbuf6len, 2 * tmpbuf6len); tmpbuf4 = extend_alloca (tmpbuf4, tmpbuf4len, 2 * tmpbuf4len);
} }
if (rc4 != 0 || herrno == NETDB_INTERNAL) if (rc4 != 0 || herrno == NETDB_INTERNAL)
@ -184,26 +191,69 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
addrslen += th[j].h_length; addrslen += th[j].h_length;
} }
/* Determine the canonical name. */ if (canon == NULL)
nss_getcanonname_r cfct;
cfct = __nss_lookup_function (nip, "getcanonname_r");
if (cfct != NULL)
{ {
const size_t max_fqdn_len = 256; /* Determine the canonical name. */
char *buf = alloca (max_fqdn_len); nss_getcanonname_r cfct;
char *s; cfct = __nss_lookup_function (nip, "getcanonname_r");
int rc; if (cfct != NULL)
{
const size_t max_fqdn_len = 256;
char *buf = alloca (max_fqdn_len);
char *s;
int rc;
if (DL_CALL_FCT (cfct, (key, buf, max_fqdn_len, &s, &rc, if (DL_CALL_FCT (cfct, (key, buf, max_fqdn_len, &s, &rc,
&herrno)) == NSS_STATUS_SUCCESS) &herrno)) == NSS_STATUS_SUCCESS)
canon = s; canon = s;
else
/* Set to name now to avoid using gethostbyaddr. */
canon = key;
}
else else
/* Set to name now to avoid using gethostbyaddr. */ {
canon = key; struct hostent *he = NULL;
} int herrno;
else struct hostent he_mem;
{ void *addr;
// XXX use gethostbyaddr size_t addrlen;
int addrfamily;
if (status[1] == NSS_STATUS_SUCCESS)
{
addr = th[1].h_addr_list[0];
addrlen = sizeof (struct in_addr);
addrfamily = AF_INET;
}
else
{
addr = th[0].h_addr_list[0];
addrlen = sizeof (struct in6_addr);
addrfamily = AF_INET6;
}
size_t tmpbuflen = 512;
char *tmpbuf = alloca (tmpbuflen);
int rc;
while (1)
{
rc = __gethostbyaddr_r (addr, addrlen, addrfamily,
&he_mem, tmpbuf, tmpbuflen,
&he, &herrno);
if (rc != ERANGE || herrno != NETDB_INTERNAL)
break;
tmpbuf = extend_alloca (tmpbuf, tmpbuflen,
tmpbuflen * 2);
}
if (rc == 0)
{
if (he != NULL)
canon = he->h_name;
else
canon = key;
}
}
} }
size_t canonlen = canon == NULL ? 0 : (strlen (canon) + 1); size_t canonlen = canon == NULL ? 0 : (strlen (canon) + 1);
@ -237,7 +287,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
dataset->head.usable = true; dataset->head.usable = true;
/* Compute the timeout time. */ /* Compute the timeout time. */
dataset->head.timeout = time (NULL) + db->postimeout; dataset->head.timeout = time (NULL) + MIN (db->postimeout, ttl);
dataset->resp.version = NSCD_VERSION; dataset->resp.version = NSCD_VERSION;
dataset->resp.found = 1; dataset->resp.found = 1;

View File

@ -126,7 +126,7 @@ endif
endif endif
CFLAGS-regex.c = -Wno-strict-prototypes CFLAGS-regex.c = -Wno-strict-prototypes
CFLAGS-getaddrinfo.c = -DRESOLVER -fexceptions CFLAGS-getaddrinfo.c = -DRESOLVER -fexceptions -DUSE_NSCD
CFLAGS-pread.c = -fexceptions -fasynchronous-unwind-tables CFLAGS-pread.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-pread64.c = -fexceptions -fasynchronous-unwind-tables CFLAGS-pread64.c = -fexceptions -fasynchronous-unwind-tables
CFLAGS-pwrite.c = -fexceptions -fasynchronous-unwind-tables CFLAGS-pwrite.c = -fexceptions -fasynchronous-unwind-tables

View File

@ -77,7 +77,7 @@ libresolv {
GLIBC_PRIVATE { GLIBC_PRIVATE {
# Needed in libnss_dns. # Needed in libnss_dns.
__ns_name_unpack; __ns_name_ntop; __ns_name_unpack; __ns_name_ntop;
__ns_get16; __ns_get16; __ns_get32;
__libc_res_nquery; __libc_res_nsearch; __libc_res_nquery; __libc_res_nsearch;
} }
} }
@ -85,6 +85,7 @@ libresolv {
libnss_dns { libnss_dns {
GLIBC_PRIVATE { GLIBC_PRIVATE {
_nss_dns_gethostbyaddr_r; _nss_dns_gethostbyname2_r; _nss_dns_gethostbyaddr_r; _nss_dns_gethostbyname2_r;
_nss_dns_gethostbyname3_r;
_nss_dns_gethostbyname_r; _nss_dns_getnetbyaddr_r; _nss_dns_gethostbyname_r; _nss_dns_getnetbyaddr_r;
_nss_dns_getnetbyname_r; _nss_dns_getcanonname_r; _nss_dns_getnetbyname_r; _nss_dns_getcanonname_r;
} }

View File

@ -125,12 +125,12 @@ static enum nss_status getanswer_r (const querybuf *answer, int anslen,
const char *qname, int qtype, const char *qname, int qtype,
struct hostent *result, char *buffer, struct hostent *result, char *buffer,
size_t buflen, int *errnop, int *h_errnop, size_t buflen, int *errnop, int *h_errnop,
int map); int map, int32_t *ttlp, char **canonp);
enum nss_status enum nss_status
_nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result, _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
char *buffer, size_t buflen, int *errnop, char *buffer, size_t buflen, int *errnop,
int *h_errnop) int *h_errnop, int32_t *ttlp, char **canonp)
{ {
union union
{ {
@ -211,13 +211,23 @@ _nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
} }
status = getanswer_r (host_buffer.buf, n, name, type, result, buffer, buflen, status = getanswer_r (host_buffer.buf, n, name, type, result, buffer, buflen,
errnop, h_errnop, map); errnop, h_errnop, map, ttlp, canonp);
if (host_buffer.buf != orig_host_buffer) if (host_buffer.buf != orig_host_buffer)
free (host_buffer.buf); free (host_buffer.buf);
return status; return status;
} }
enum nss_status
_nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
char *buffer, size_t buflen, int *errnop,
int *h_errnop)
{
return _nss_dns_gethostbyname3_r (name, af, result, buffer, buflen, errnop,
h_errnop, NULL, NULL);
}
enum nss_status enum nss_status
_nss_dns_gethostbyname_r (const char *name, struct hostent *result, _nss_dns_gethostbyname_r (const char *name, struct hostent *result,
char *buffer, size_t buflen, int *errnop, char *buffer, size_t buflen, int *errnop,
@ -355,7 +365,7 @@ _nss_dns_gethostbyaddr_r (const void *addr, socklen_t len, int af,
got_it_already: got_it_already:
status = getanswer_r (host_buffer.buf, n, qbuf, T_PTR, result, buffer, buflen, status = getanswer_r (host_buffer.buf, n, qbuf, T_PTR, result, buffer, buflen,
errnop, h_errnop, 0 /* XXX */); errnop, h_errnop, 0 /* XXX */, NULL, NULL);
if (host_buffer.buf != orig_host_buffer) if (host_buffer.buf != orig_host_buffer)
free (host_buffer.buf); free (host_buffer.buf);
if (status != NSS_STATUS_SUCCESS) if (status != NSS_STATUS_SUCCESS)
@ -439,7 +449,7 @@ addrsort (char **ap, int num)
static enum nss_status static enum nss_status
getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
struct hostent *result, char *buffer, size_t buflen, struct hostent *result, char *buffer, size_t buflen,
int *errnop, int *h_errnop, int map) int *errnop, int *h_errnop, int map, int32_t *ttlp, char **canonp)
{ {
struct host_data struct host_data
{ {
@ -458,6 +468,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
int (*name_ok) (const char *); int (*name_ok) (const char *);
u_char packtmp[NS_MAXCDNAME]; u_char packtmp[NS_MAXCDNAME];
int have_to_map = 0; int have_to_map = 0;
int32_t ttl = 0;
if (__builtin_expect (linebuflen, 0) < 0) if (__builtin_expect (linebuflen, 0) < 0)
{ {
@ -577,7 +588,9 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
type = ns_get16 (cp); type = ns_get16 (cp);
cp += INT16SZ; /* type */ cp += INT16SZ; /* type */
class = ns_get16 (cp); class = ns_get16 (cp);
cp += INT16SZ + INT32SZ; /* class, TTL */ cp += INT16SZ; /* class */
ttl = ns_get32 (cp);
cp += INT32SZ; /* TTL */
n = ns_get16 (cp); n = ns_get16 (cp);
cp += INT16SZ; /* len */ cp += INT16SZ; /* len */
if (class != C_IN) if (class != C_IN)
@ -749,6 +762,10 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
{ {
register int nn; register int nn;
if (ttlp != NULL && ttl != 0)
*ttlp = ttl;
if (canonp != NULL)
*canonp = bp;
result->h_name = bp; result->h_name = bp;
nn = strlen (bp) + 1; /* for the \0 */ nn = strlen (bp) + 1; /* for the \0 */
bp += nn; bp += nn;