Update.
authorUlrich Drepper <drepper@redhat.com>
Wed, 15 Sep 2004 10:10:05 +0000 (10:10 +0000)
committerUlrich Drepper <drepper@redhat.com>
Wed, 15 Sep 2004 10:10:05 +0000 (10:10 +0000)
* 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.

ChangeLog
nscd/aicache.c
posix/Makefile
resolv/Versions
resolv/nss_dns/dns-host.c

index 9478b28..e562bcc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 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-modules): Add aicache.
        * nscd/aicache.c: New file.
index e748906..7fddd7d 100644 (file)
 #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,
    char *buffer, size_t buflen, int *errnop,
-   int *h_errnop);
+   int *h_errnop, int32_t *, char **);
 typedef enum nss_status (*nss_getcanonname_r)
   (const char *name, char *buffer, size_t buflen, char **result,
    int *errnop, int *h_errnop);
@@ -114,19 +114,23 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
   size_t tmpbuf4len = 0;
   char *tmpbuf4 = NULL;
   char *canon = NULL;
+  int32_t ttl = UINT32_MAX;
   ssize_t total = 0;
   char *key_copy = NULL;
   bool alloca_used = false;
 
   while (!no_more)
     {
-      nss_gethostbyname2_r fct = __nss_lookup_function (nip,
-                                                       "gethostbyname2_r");
       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)
        {
- printf("fct=%p\n",fct);
          struct hostent th[2];
 
          /* Collect IPv6 information first.  */
@@ -134,7 +138,8 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
            {
              rc6 = 0;
              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)
                break;
              tmpbuf6 = extend_alloca (tmpbuf6, tmpbuf6len, 2 * tmpbuf6len);
@@ -161,10 +166,12 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
            {
              rc4 = 0;
              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)
                break;
-             tmpbuf4 = extend_alloca (tmpbuf6, tmpbuf6len, 2 * tmpbuf6len);
+             tmpbuf4 = extend_alloca (tmpbuf4, tmpbuf4len, 2 * tmpbuf4len);
            }
 
          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;
                    }
 
-             /* Determine the canonical name.  */
-             nss_getcanonname_r cfct;
-             cfct = __nss_lookup_function (nip, "getcanonname_r");
-             if (cfct != NULL)
+             if (canon == 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,
-                                         &herrno)) == NSS_STATUS_SUCCESS)
-                   canon = s;
+                 /* Determine the canonical name.  */
+                 nss_getcanonname_r cfct;
+                 cfct = __nss_lookup_function (nip, "getcanonname_r");
+                 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,
+                                             &herrno)) == NSS_STATUS_SUCCESS)
+                       canon = s;
+                     else
+                       /* Set to name now to avoid using gethostbyaddr.  */
+                       canon = key;
+                   }
                  else
-                   /* Set to name now to avoid using gethostbyaddr.  */
-                   canon = key;
-               }
-             else
-               {
-                 // XXX use gethostbyaddr
+                   {
+                     struct hostent *he = NULL;
+                     int herrno;
+                     struct hostent he_mem;
+                     void *addr;
+                     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);
 
@@ -237,7 +287,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
              dataset->head.usable = true;
 
              /* 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.found = 1;
index d0ad95d..766c1dd 100644 (file)
@@ -126,7 +126,7 @@ endif
 endif
 
 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-pread64.c = -fexceptions -fasynchronous-unwind-tables
 CFLAGS-pwrite.c = -fexceptions -fasynchronous-unwind-tables
index 0e4fea5..2a67677 100644 (file)
@@ -77,7 +77,7 @@ libresolv {
   GLIBC_PRIVATE {
     # Needed in libnss_dns.
     __ns_name_unpack; __ns_name_ntop;
-    __ns_get16;
+    __ns_get16; __ns_get32;
     __libc_res_nquery; __libc_res_nsearch;
   }
 }
@@ -85,6 +85,7 @@ libresolv {
 libnss_dns {
   GLIBC_PRIVATE {
     _nss_dns_gethostbyaddr_r; _nss_dns_gethostbyname2_r;
+    _nss_dns_gethostbyname3_r;
     _nss_dns_gethostbyname_r; _nss_dns_getnetbyaddr_r;
     _nss_dns_getnetbyname_r; _nss_dns_getcanonname_r;
   }
index 91699cc..f6a2fa6 100644 (file)
@@ -125,12 +125,12 @@ 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 map);
+                                   int map, int32_t *ttlp, char **canonp);
 
 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,
-                          int *h_errnop)
+                          int *h_errnop, int32_t *ttlp, char **canonp)
 {
   union
   {
@@ -211,7 +211,7 @@ _nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
     }
 
   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)
     free (host_buffer.buf);
   return status;
@@ -219,6 +219,16 @@ _nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
 
 
 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
 _nss_dns_gethostbyname_r (const char *name, struct hostent *result,
                          char *buffer, size_t buflen, int *errnop,
                          int *h_errnop)
@@ -355,7 +365,7 @@ _nss_dns_gethostbyaddr_r (const void *addr, socklen_t len, int af,
 
  got_it_already:
   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)
     free (host_buffer.buf);
   if (status != NSS_STATUS_SUCCESS)
@@ -439,7 +449,7 @@ addrsort (char **ap, int num)
 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 map)
+            int *errnop, int *h_errnop, int map, int32_t *ttlp, char **canonp)
 {
   struct host_data
   {
@@ -458,6 +468,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
   int (*name_ok) (const char *);
   u_char packtmp[NS_MAXCDNAME];
   int have_to_map = 0;
+  int32_t ttl = 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);
       cp += INT16SZ;                   /* type */
       class = ns_get16 (cp);
-      cp += INT16SZ + INT32SZ;         /* class, TTL */
+      cp += INT16SZ;                   /* class */
+      ttl = ns_get32 (cp);
+      cp += INT32SZ;                   /* TTL */
       n = ns_get16 (cp);
       cp += INT16SZ;                   /* len */
       if (class != C_IN)
@@ -749,6 +762,10 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
            {
              register int nn;
 
+             if (ttlp != NULL && ttl != 0)
+               *ttlp = ttl;
+             if (canonp != NULL)
+               *canonp = bp;
              result->h_name = bp;
              nn = strlen (bp) + 1;     /* for the \0 */
              bp += nn;