summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog20
-rw-r--r--nss/nss_files/files-hosts.c34
-rw-r--r--resolv/nss_dns/dns-host.c84
3 files changed, 88 insertions, 50 deletions
diff --git a/ChangeLog b/ChangeLog
index 534068cca1..386b666504 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2000-05-27 Ulrich Drepper <drepper@redhat.com>
+
+ * sysdeps/posix/getaddrinfo.c (gaih_inet): If req->ai_family ==
+ AF_UNSPEC don't allow the IPv6 lookup to return mapped IPv4 addresses.
+
+ * nss/nss_files/files-hosts.c (LINE_PARSER): Simplify. Correct
+ handling of AI_V4MAPPED flag.
+
+ * resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname2_r): If lookup
+ of IPv6 address failed and RES_USE_INET6 bit in _res.options is set,
+ perform lookup for T_A type and tell getanswer_r to convert the
+ result with new argument.
+ (_nss_dns_gethostbyaddr_r): Pass zero as new argument to getanswer_r.
+ Don't convert addresses from IPv4 to IPv6 here.
+ (getanswer_r): Take new parameter indicating if mapping from IPv4 to
+ IPv6 is wanted. Allow qtype and type from reply to disagree if
+ IPv4 mapping has to be done. Perform mappings if required by the
+ caller and not if RES_USE_INET6 bit in _res.options is set.
+ Add several __builtin_expect.
+
2000-05-26 Ulrich Drepper <drepper@redhat.com>
* catgets/open_catalog.c (__open_catalog): Add a few __builtin_expect.
diff --git a/nss/nss_files/files-hosts.c b/nss/nss_files/files-hosts.c
index 6f9f68c685..e73fee0b14 100644
--- a/nss/nss_files/files-hosts.c
+++ b/nss/nss_files/files-hosts.c
@@ -53,31 +53,19 @@ LINE_PARSER
STRING_FIELD (addr, isspace, 1);
/* Parse address. */
- if (af == AF_INET && inet_pton (AF_INET, addr, entdata->host_addr) > 0)
- {
- if (flags & AI_V4MAPPED)
- {
- map_v4v6_address ((char *) entdata->host_addr,
- (char *) entdata->host_addr);
- result->h_addrtype = AF_INET6;
- result->h_length = IN6ADDRSZ;
- }
- else
- {
- result->h_addrtype = AF_INET;
- result->h_length = INADDRSZ;
- }
- }
- else if (af == AF_INET6
- && inet_pton (AF_INET6, addr, entdata->host_addr) > 0)
- {
- result->h_addrtype = AF_INET6;
- result->h_length = IN6ADDRSZ;
- }
- else
+ if (inet_pton (af, addr, entdata->host_addr) <= 0
+ && (af != AF_INET6 || (flags & AI_V4MAPPED) == 0
+ || inet_pton (AF_INET, addr, entdata->host_addr) <= 0
+ || (map_v4v6_address ((char *) entdata->host_addr,
+ (char *) entdata->host_addr),
+ 0)))
/* Illegal address: ignore line. */
return 0;
+ /* We always return entries of the requested form. */
+ result->h_addrtype = af;
+ result->h_length = af == AF_INET ? INADDRSZ : IN6ADDRSZ;
+
/* Store a pointer to the address in the expected form. */
entdata->h_addr_ptrs[0] = entdata->host_addr;
entdata->h_addr_ptrs[1] = NULL;
@@ -97,6 +85,8 @@ DB_LOOKUP (hostbyname, ,,
}, const char *name)
#undef EXTRA_ARGS_VALUE
+/* XXX Is using _res to determine whether we want to convert IPv4 addresses
+ to IPv6 addresses really the right thing to do? */
#define EXTRA_ARGS_VALUE \
, af, ((_res.options & RES_USE_INET6) ? AI_V4MAPPED : 0)
DB_LOOKUP (hostbyname2, ,,
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index 483e791801..e99d964203 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996.
@@ -114,15 +114,16 @@ typedef union querybuf
/* These functions are defined in res_comp.c. */
#define NS_MAXCDNAME 255 /* maximum compressed domain name */
-extern int __ns_name_ntop __P ((const u_char *, char *, size_t));
-extern int __ns_name_unpack __P ((const u_char *, const u_char *,
- const u_char *, u_char *, size_t));
+extern int __ns_name_ntop (const u_char *, char *, size_t);
+extern int __ns_name_unpack (const u_char *, const u_char *,
+ const u_char *, u_char *, size_t);
static enum nss_status getanswer_r (const querybuf *answer, int anslen,
const char *qname, int qtype,
struct hostent *result, char *buffer,
- size_t buflen, int *errnop, int *h_errnop);
+ size_t buflen, int *errnop, int *h_errnop,
+ int map);
enum nss_status
_nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
@@ -132,6 +133,7 @@ _nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
querybuf host_buffer;
int size, type, n;
const char *cp;
+ int map = 0;
if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1)
return NSS_STATUS_UNAVAIL;
@@ -166,13 +168,29 @@ _nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
sizeof (host_buffer.buf));
if (n < 0)
{
+ enum nss_status status = (errno == ECONNREFUSED
+ ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND);
*h_errnop = h_errno;
- *errnop = *h_errnop == TRY_AGAIN ? EAGAIN : ENOENT;
- return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
+ *errnop = h_errno == TRY_AGAIN ? EAGAIN : ENOENT;
+
+ /* If we are looking for a IPv6 address and mapping is enabled
+ by having the RES_USE_INET6 bit in _res.options set, we try
+ another lookup. */
+ if (af == AF_INET6 && (_res.options & RES_USE_INET6))
+ n = res_nsearch (&_res, name, C_IN, T_A, host_buffer.buf,
+ sizeof (host_buffer.buf));
+
+ if (n < 0)
+ return status;
+
+ map = 1;
+
+ result->h_addrtype = AF_INET;
+ result->h_length = INADDRSZ;;
}
return getanswer_r (&host_buffer, n, name, type, result, buffer, buflen,
- errnop, h_errnop);
+ errnop, h_errnop, map);
}
@@ -276,7 +294,7 @@ _nss_dns_gethostbyaddr_r (const char *addr, size_t len, int af,
}
status = getanswer_r (&host_buffer, n, qbuf, T_PTR, result, buffer, buflen,
- errnop, h_errnop);
+ errnop, h_errnop, 0 /* XXX */);
if (status != NSS_STATUS_SUCCESS)
{
*h_errnop = h_errno;
@@ -294,6 +312,9 @@ _nss_dns_gethostbyaddr_r (const char *addr, size_t len, int af,
memcpy (host_data->host_addr, addr, len);
host_data->h_addr_ptrs[0] = (char *) host_data->host_addr;
host_data->h_addr_ptrs[1] = NULL;
+#if 0
+ /* XXX I think this is wrong. Why should an IPv4 address be
+ converted to IPv6 if the user explicitly asked for IPv4? */
if (af == AF_INET && (_res.options & RES_USE_INET6))
{
map_v4v6_address ((char *) host_data->host_addr,
@@ -301,6 +322,7 @@ _nss_dns_gethostbyaddr_r (const char *addr, size_t len, int af,
result->h_addrtype = AF_INET6;
result->h_length = IN6ADDRSZ;
}
+#endif
*h_errnop = NETDB_SUCCESS;
return NSS_STATUS_SUCCESS;
}
@@ -309,7 +331,7 @@ _nss_dns_gethostbyaddr_r (const char *addr, size_t len, int af,
static enum nss_status
getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
struct hostent *result, char *buffer, size_t buflen,
- int *errnop, int *h_errnop)
+ int *errnop, int *h_errnop, int map)
{
struct host_data
{
@@ -326,10 +348,11 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
char *bp, **ap, **hap;
char tbuf[MAXDNAME];
const char *tname;
- int (*name_ok) __P ((const char *));
+ int (*name_ok) (const char *);
u_char packtmp[NS_MAXCDNAME];
+ int have_to_map = 0;
- if (linebuflen < 0)
+ if (__builtin_expect (linebuflen, 0) < 0)
{
/* The buffer is too small. */
too_small:
@@ -363,7 +386,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
ancount = ntohs (hp->ancount);
qdcount = ntohs (hp->qdcount);
cp = answer->buf + HFIXEDSZ;
- if (qdcount != 1)
+ if (__builtin_expect (qdcount, 1) != 1)
{
*h_errnop = NO_RECOVERY;
*errnop = ENOENT;
@@ -374,7 +397,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
packtmp, sizeof packtmp);
if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
{
- if (errno == EMSGSIZE)
+ if (__builtin_expect (errno, 0) == EMSGSIZE)
goto too_small;
n = -1;
@@ -430,7 +453,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
packtmp, sizeof packtmp);
if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
{
- if (errno == EMSGSIZE)
+ if (__builtin_expect (errno, 0) == EMSGSIZE)
goto too_small;
n = -1;
@@ -469,7 +492,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
/* Store alias. */
*ap++ = bp;
n = strlen (bp) + 1; /* For the \0. */
- if (n >= MAXHOSTNAMELEN)
+ if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN)
{
++had_error;
continue;
@@ -478,9 +501,9 @@ 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 (n > linebuflen)
+ if (__builtin_expect (n > linebuflen, 0))
goto too_small;
- if (n >= MAXHOSTNAMELEN)
+ if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN)
{
++had_error;
continue;
@@ -502,9 +525,9 @@ 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 (n > linebuflen)
+ if (__builtin_expect (n > linebuflen, 0))
goto too_small;
- if (n >= MAXHOSTNAMELEN)
+ if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN)
{
++had_error;
continue;
@@ -514,7 +537,9 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
linebuflen -= n;
continue;
}
- if (type == T_SIG || type == T_KEY || type == T_NXT)
+ 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. */
@@ -524,7 +549,10 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
cp += n;
continue;
}
- if (type != qtype)
+
+ if (type == T_A && qtype == T_AAAA && map)
+ have_to_map = 1;
+ else if (__builtin_expect (type != qtype, 0))
{
syslog (LOG_NOTICE | LOG_AUTH,
"gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
@@ -547,7 +575,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
packtmp, sizeof packtmp);
if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
{
- if (errno == EMSGSIZE)
+ if (__builtin_expect (errno, 0) == EMSGSIZE)
goto too_small;
n = -1;
@@ -569,7 +597,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
if (n != -1)
{
n = strlen (bp) + 1; /* for the \0 */
- if (n >= MAXHOSTNAMELEN)
+ if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN)
{
++had_error;
break;
@@ -580,7 +608,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
break;
#else
result->h_name = bp;
- if (_res.options & RES_USE_INET6)
+ if (have_to_map)
{
n = strlen (bp) + 1; /* for the \0 */
if (n >= MAXHOSTNAMELEN)
@@ -597,7 +625,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
#endif
case T_A:
case T_AAAA:
- if (strcasecmp (result->h_name, bp) != 0)
+ if (__builtin_expect (strcasecmp (result->h_name, bp), 0) != 0)
{
syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, result->h_name, bp);
cp += n;
@@ -621,7 +649,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 (n > linebuflen)
+ if (__builtin_expect (n > linebuflen, 0))
goto too_small;
if (hap >= &host_data->h_addr_ptrs[MAX_NR_ADDRS-1])
{
@@ -665,7 +693,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
linebuflen -= n;
}
- if (_res.options & RES_USE_INET6)
+ if (have_to_map)
map_v4v6_hostent (result, &bp, &linebuflen);
*h_errnop = NETDB_SUCCESS;
return NSS_STATUS_SUCCESS;