]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - nscd/aicache.c
resolv: Remove support for RES_USE_INET6 and the inet6 option
[thirdparty/glibc.git] / nscd / aicache.c
index 3190a13b06efd740a6c139a0cb693ba01ec75609..5b94e2aa9e8c611eab3b074ca1d0df023d6db78a 100644 (file)
@@ -1,5 +1,5 @@
 /* Cache handling for host lookup.
-   Copyright (C) 2004-2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 2004-2019 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
 
@@ -14,8 +14,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
 
 #include <assert.h>
 #include <errno.h>
 #include <time.h>
 #include <unistd.h>
 #include <sys/mman.h>
+#include <resolv/resolv-internal.h>
+#include <resolv/resolv_context.h>
+#include <scratch_buffer.h>
 
 #include "dbg_log.h"
 #include "nscd.h"
-#ifdef HAVE_SENDFILE
-# include <kernel-features.h>
-#endif
 
 
 typedef enum nss_status (*nss_gethostbyname4_r)
@@ -77,7 +76,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
     char strdata[0];
   } *dataset = NULL;
 
-  if (__builtin_expect (debug_level > 0, 0))
+  if (__glibc_unlikely (debug_level > 0))
     {
       if (he == NULL)
        dbg_log (_("Haven't found \"%s\" in hosts cache!"), (char *) key);
@@ -86,35 +85,32 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
     }
 
   static service_user *hosts_database;
-  service_user *nip = NULL;
+  service_user *nip;
   int no_more;
   int rc6 = 0;
   int rc4 = 0;
   int herrno = 0;
 
-  if (hosts_database != NULL)
-    {
-      nip = hosts_database;
-      no_more = 0;
-    }
-  else
+  if (hosts_database == NULL)
     no_more = __nss_database_lookup ("hosts", NULL,
-                                    "dns [!UNAVAIL=return] files", &nip);
-
-  if (__res_maybe_init (&_res, 0) == -1)
-           no_more = 1;
-
-  /* If we are looking for both IPv4 and IPv6 address we don't want
-     the lookup functions to automatically promote IPv4 addresses to
-     IPv6 addresses.  Currently this is decided by setting the
-     RES_USE_INET6 bit in _res.options.  */
-  int old_res_options = _res.options;
-  _res.options &= ~RES_USE_INET6;
-
-  size_t tmpbuf6len = 1024;
-  char *tmpbuf6 = alloca (tmpbuf6len);
-  size_t tmpbuf4len = 0;
-  char *tmpbuf4 = NULL;
+                                    "dns [!UNAVAIL=return] files",
+                                    &hosts_database);
+  else
+    no_more = 0;
+  nip = hosts_database;
+
+  /* Initialize configurations.  */
+  struct resolv_context *ctx = __resolv_context_get ();
+  if (ctx == NULL)
+    no_more = 1;
+
+  struct scratch_buffer tmpbuf6;
+  scratch_buffer_init (&tmpbuf6);
+  struct scratch_buffer tmpbuf4;
+  scratch_buffer_init (&tmpbuf4);
+  struct scratch_buffer canonbuf;
+  scratch_buffer_init (&canonbuf);
+
   int32_t ttl = INT32_MAX;
   ssize_t total = 0;
   char *key_copy = NULL;
@@ -127,6 +123,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
       int status[2] = { NSS_STATUS_UNAVAIL, NSS_STATUS_UNAVAIL };
       int naddrs = 0;
       size_t addrslen = 0;
+
       char *canon = NULL;
       size_t canonlen;
 
@@ -141,12 +138,17 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
              at = &atmem;
              rc6 = 0;
              herrno = 0;
-             status[1] = DL_CALL_FCT (fct4, (key, &at, tmpbuf6, tmpbuf6len,
+             status[1] = DL_CALL_FCT (fct4, (key, &at,
+                                             tmpbuf6.data, tmpbuf6.length,
                                              &rc6, &herrno, &ttl));
              if (rc6 != ERANGE || (herrno != NETDB_INTERNAL
                                    && herrno != TRY_AGAIN))
                break;
-             tmpbuf6 = extend_alloca (tmpbuf6, tmpbuf6len, 2 * tmpbuf6len);
+             if (!scratch_buffer_grow (&tmpbuf6))
+               {
+                 rc6 = ENOMEM;
+                 break;
+               }
            }
 
          if (rc6 != 0 && herrno == NETDB_INTERNAL)
@@ -224,41 +226,38 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
          while (1)
            {
              rc6 = 0;
-             status[0] = DL_CALL_FCT (fct, (key, AF_INET6, &th[0], tmpbuf6,
-                                            tmpbuf6len, &rc6, &herrno, &ttl,
+             status[0] = DL_CALL_FCT (fct, (key, AF_INET6, &th[0],
+                                            tmpbuf6.data, tmpbuf6.length,
+                                            &rc6, &herrno, &ttl,
                                             &canon));
              if (rc6 != ERANGE || herrno != NETDB_INTERNAL)
                break;
-             tmpbuf6 = extend_alloca (tmpbuf6, tmpbuf6len, 2 * tmpbuf6len);
+             if (!scratch_buffer_grow (&tmpbuf6))
+               {
+                 rc6 = ENOMEM;
+                 break;
+               }
            }
 
          if (rc6 != 0 && herrno == NETDB_INTERNAL)
            goto out;
 
-         /* If the IPv6 lookup has been successful do not use the
-            buffer used in that lookup, use a new one.  */
-         if (status[0] == NSS_STATUS_SUCCESS && rc6 == 0)
-           {
-             tmpbuf4len = 512;
-             tmpbuf4 = alloca (tmpbuf4len);
-           }
-         else
-           {
-             tmpbuf4len = tmpbuf6len;
-             tmpbuf4 = tmpbuf6;
-           }
-
          /* Next collect IPv4 information.  */
          while (1)
            {
              rc4 = 0;
-             status[1] = DL_CALL_FCT (fct, (key, AF_INET, &th[1], tmpbuf4,
-                                            tmpbuf4len, &rc4, &herrno,
+             status[1] = DL_CALL_FCT (fct, (key, AF_INET, &th[1],
+                                            tmpbuf4.data, tmpbuf4.length,
+                                            &rc4, &herrno,
                                             ttl == INT32_MAX ? &ttl : NULL,
                                             canon == NULL ? &canon : NULL));
              if (rc4 != ERANGE || herrno != NETDB_INTERNAL)
                break;
-             tmpbuf4 = extend_alloca (tmpbuf4, tmpbuf4len, 2 * tmpbuf4len);
+             if (!scratch_buffer_grow (&tmpbuf4))
+               {
+                 rc4 = ENOMEM;
+                 break;
+               }
            }
 
          if (rc4 != 0 && herrno == NETDB_INTERNAL)
@@ -284,13 +283,11 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
              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))
+                 if (DL_CALL_FCT (cfct, (key, canonbuf.data, canonbuf.length,
+                                         &s, &rc, &herrno))
                      == NSS_STATUS_SUCCESS)
                    canon = s;
                  else
@@ -319,18 +316,20 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
                      addrfamily = AF_INET6;
                    }
 
-                 size_t tmpbuflen = 512;
-                 char *tmpbuf = alloca (tmpbuflen);
                  int rc;
                  while (1)
                    {
                      rc = __gethostbyaddr2_r (addr, addrlen, addrfamily,
-                                              &hstent_mem, tmpbuf, tmpbuflen,
+                                              &hstent_mem,
+                                              canonbuf.data, canonbuf.length,
                                               &hstent, &herrno, NULL);
                      if (rc != ERANGE || herrno != NETDB_INTERNAL)
                        break;
-                     tmpbuf = extend_alloca (tmpbuf, tmpbuflen,
-                                             tmpbuflen * 2);
+                     if (!scratch_buffer_grow (&canonbuf))
+                       {
+                         rc = ENOMEM;
+                         break;
+                       }
                    }
 
                  if (rc == 0)
@@ -381,17 +380,12 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
          cp = family;
        }
 
-      /* Fill in the rest of the dataset.  */
-      dataset->head.allocsize = total + req->key_len;
-      dataset->head.recsize = total - offsetof (struct dataset, resp);
-      dataset->head.notfound = false;
-      dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1);
-      dataset->head.usable = true;
-
-      /* Compute the timeout time.  */
-      dataset->head.ttl = ttl == INT32_MAX ? db->postimeout : ttl;
-      timeout = dataset->head.timeout = time (NULL) + dataset->head.ttl;
+      timeout = datahead_init_pos (&dataset->head, total + req->key_len,
+                                  total - offsetof (struct dataset, resp),
+                                  he == NULL ? 0 : dh->nreloads + 1,
+                                  ttl == INT32_MAX ? db->postimeout : ttl);
 
+      /* Fill in the rest of the dataset.  */
       dataset->resp.version = NSCD_VERSION;
       dataset->resp.found = 1;
       dataset->resp.naddrs = naddrs;
@@ -432,7 +426,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
              struct dataset *newp
                = (struct dataset *) mempool_alloc (db, total + req->key_len,
                                                    1);
-             if (__builtin_expect (newp != NULL, 1))
+             if (__glibc_likely (newp != NULL))
                {
                  /* Adjust pointer into the memory block.  */
                  key_copy = (char *) newp + (key_copy - (char *) dataset);
@@ -452,29 +446,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
             would unnecessarily let the receiver wait.  */
          assert (fd != -1);
 
-#ifdef HAVE_SENDFILE
-         if (__builtin_expect (db->mmap_used, 1) && !alloca_used)
-           {
-             assert (db->wr_fd != -1);
-             assert ((char *) &dataset->resp > (char *) db->data);
-             assert ((char *) dataset - (char *) db->head + total
-                     <= (sizeof (struct database_pers_head)
-                         + db->head->module * sizeof (ref_t)
-                         + db->head->data_size));
-             ssize_t written;
-             written = sendfileall (fd, db->wr_fd, (char *) &dataset->resp
-                                    - (char *) db->head, dataset->head.recsize);
-# ifndef __ASSUME_SENDFILE
-             if (written == -1 && errno == ENOSYS)
-               goto use_write;
-# endif
-           }
-         else
-# ifndef __ASSUME_SENDFILE
-         use_write:
-# endif
-#endif
-           writeall (fd, &dataset->resp, dataset->head.recsize);
+         writeall (fd, &dataset->resp, dataset->head.recsize);
        }
 
       goto out;
@@ -511,19 +483,21 @@ next_nip:
       if (fd != -1)
        TEMP_FAILURE_RETRY (send (fd, &notfound, total, MSG_NOSIGNAL));
 
-      dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1);
-      /* If we cannot permanently store the result, so be it.  */
-      if (dataset != NULL)
+      /* If we have a transient error or cannot permanently store the
+        result, so be it.  */
+      if (rc4 == EAGAIN || __builtin_expect (db->negtimeout == 0, 0))
        {
-         dataset->head.allocsize = sizeof (struct dataset) + req->key_len;
-         dataset->head.recsize = total;
-         dataset->head.notfound = true;
-         dataset->head.nreloads = 0;
-         dataset->head.usable = true;
-
-         /* Compute the timeout time.  */
-         timeout = dataset->head.timeout = time (NULL) + db->negtimeout;
-         dataset->head.ttl = db->negtimeout;
+         /* Mark the old entry as obsolete.  */
+         if (dh != NULL)
+           dh->usable = false;
+         dataset = NULL;
+       }
+      else if ((dataset = mempool_alloc (db, (sizeof (struct dataset)
+                                             + req->key_len), 1)) != NULL)
+       {
+         timeout = datahead_init_neg (&dataset->head,
+                                      sizeof (struct dataset) + req->key_len,
+                                      total, db->negtimeout);
 
          /* This is the reply.  */
          memcpy (&dataset->resp, &notfound, total);
@@ -534,7 +508,7 @@ next_nip:
    }
 
  out:
-  _res.options = old_res_options;
+  __resolv_context_put (ctx);
 
   if (dataset != NULL && !alloca_used)
     {
@@ -558,6 +532,10 @@ next_nip:
        dh->usable = false;
     }
 
+  scratch_buffer_free (&tmpbuf6);
+  scratch_buffer_free (&tmpbuf4);
+  scratch_buffer_free (&canonbuf);
+
   return timeout;
 }