about summary refs log tree commit diff
path: root/resolv/nss_dns
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2000-05-27 08:17:05 +0000
committerUlrich Drepper <drepper@redhat.com>2000-05-27 08:17:05 +0000
commitb455972fdaf438fec1ee1467fee5d29ee5569333 (patch)
treeffd9da46c9e37ffb1e14d7abd81b82854b4e11f3 /resolv/nss_dns
parent9c42c64d305549cc74dd10739d1fc5de813abe31 (diff)
downloadglibc-b455972fdaf438fec1ee1467fee5d29ee5569333.tar.gz
glibc-b455972fdaf438fec1ee1467fee5d29ee5569333.tar.xz
glibc-b455972fdaf438fec1ee1467fee5d29ee5569333.zip
Update.
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.
Diffstat (limited to 'resolv/nss_dns')
-rw-r--r--resolv/nss_dns/dns-host.c84
1 files changed, 56 insertions, 28 deletions
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;