(linenum→info "unix/slp.c:2238")

glibc/2.7/nscd/nscd_getai.c

    1: /* Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
    2:    This file is part of the GNU C Library.
    3:    Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
    4: 
    5:    The GNU C Library is free software; you can redistribute it and/or
    6:    modify it under the terms of the GNU Lesser General Public
    7:    License as published by the Free Software Foundation; either
    8:    version 2.1 of the License, or (at your option) any later version.
    9: 
   10:    The GNU C Library is distributed in the hope that it will be useful,
   11:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   12:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   13:    Lesser General Public License for more details.
   14: 
   15:    You should have received a copy of the GNU Lesser General Public
   16:    License along with the GNU C Library; if not, write to the Free
   17:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   18:    02111-1307 USA.  */
   19: 
   20: #include <assert.h>
   21: #include <errno.h>
   22: #include <netdb.h>
   23: #include <stdlib.h>
   24: #include <string.h>
   25: #include <unistd.h>
   26: #include <not-cancel.h>
   27: 
   28: #include "nscd-client.h"
   29: #include "nscd_proto.h"
   30: 
   31: 
   32: /* Define in nscd_gethst_r.c.  */
   33: extern int __nss_not_use_nscd_hosts;
   34: 
   35: 
   36: /* We use the mapping from nscd_gethst.  */
   37: libc_locked_map_ptr (extern, __hst_map_handle) attribute_hidden;
   38: 
   39: 
   40: int
   41: __nscd_getai (const char *key, struct nscd_ai_result **result, int *h_errnop)
   42: {
   43:   size_t keylen = strlen (key) + 1;
   44:   int gc_cycle;
   45:   int nretries = 0;
   46: 
   47:   /* If the mapping is available, try to search there instead of
   48:      communicating with the nscd.  */
   49:   struct mapped_database *mapped;
   50:   mapped = __nscd_get_map_ref (GETFDHST, "hosts", &__hst_map_handle,
   51:                                &gc_cycle);
   52: 
   53:  retry:;
   54:   struct nscd_ai_result *resultbuf = NULL;
   55:   const char *recend = (const char *) ~UINTMAX_C (0);
   56:   char *respdata = NULL;
   57:   int retval = -1;
   58:   int sock = -1;
   59:   ai_response_header ai_resp;
   60: 
   61:   if (mapped != NO_MAPPING)
   62:     {
   63:       struct datahead *found = __nscd_cache_search (GETAI, key, keylen,
   64:                                                     mapped);
   65:       if (found != NULL)
   66:         {
   67:           respdata = (char *) (&found->data[0].aidata + 1);
   68:           ai_resp = found->data[0].aidata;
   69:           recend = (const char *) found->data + found->recsize;
   70:           /* Now check if we can trust ai_resp fields.  If GC is
   71:              in progress, it can contain anything.  */
   72:           if (mapped->head->gc_cycle != gc_cycle)
   73:             {
   74:               retval = -2;
   75:               goto out;
   76:             }
   77:         }
   78:     }
   79: 
   80:   /* If we do not have the cache mapped, try to get the data over the
   81:      socket.  */
   82:   if (respdata == NULL)
   83:     {
   84:       sock = __nscd_open_socket (key, keylen, GETAI, &ai_resp,
   85:                                  sizeof (ai_resp));
   86:       if (sock == -1)
   87:         {
   88:           /* nscd not running or wrong version.  */
   89:           __nss_not_use_nscd_hosts = 1;
   90:           goto out;
   91:         }
   92:     }
   93: 
   94:   if (ai_resp.found == 1)
   95:     {
   96:       size_t datalen = ai_resp.naddrs + ai_resp.addrslen + ai_resp.canonlen;
   97: 
   98:       /* This check really only affects the case where the data
   99:          comes from the mapped cache.  */
  100:       if (respdata + datalen > recend)
  101:         {
  102:           assert (sock == -1);
  103:           goto out;
  104:         }
  105: 
  106:       /* Create result.  */
  107:       resultbuf = (struct nscd_ai_result *) malloc (sizeof (*resultbuf)
  108:                                                     + datalen);
  109:       if (resultbuf == NULL)
  110:         {
  111:           *h_errnop = NETDB_INTERNAL;
  112:           goto out_close;
  113:         }
  114: 
  115:       /* Set up the data structure, including pointers.  */
  116:       resultbuf->naddrs = ai_resp.naddrs;
  117:       resultbuf->addrs = (char *) (resultbuf + 1);
  118:       resultbuf->family = (uint8_t *) (resultbuf->addrs + ai_resp.addrslen);
  119:       if (ai_resp.canonlen != 0)
  120:         resultbuf->canon = (char *) (resultbuf->family + resultbuf->naddrs);
  121:       else
  122:         resultbuf->canon = NULL;
  123: 
  124:       if (respdata == NULL)
  125:         {
  126:           /* Read the data from the socket.  */
  127:           if ((size_t) __readall (sock, resultbuf + 1, datalen) == datalen)
  128:             {
  129:               retval = 0;
  130:               *result = resultbuf;
  131:             }
  132:           else
  133:             {
  134:               free (resultbuf);
  135:               *h_errnop = NETDB_INTERNAL;
  136:             }
  137:         }
  138:       else
  139:         {
  140:           /* Copy the data in the block.  */
  141:           memcpy (resultbuf + 1, respdata, datalen);
  142: 
  143:           /* Try to detect corrupt databases.  */
  144:           if (resultbuf->canon != NULL
  145:               && resultbuf->canon[ai_resp.canonlen - 1] != '\0')
  146:             /* We cannot use the database.  */
  147:             {
  148:               if (mapped->head->gc_cycle != gc_cycle)
  149:                 retval = -2;
  150:               else
  151:                 free (resultbuf);
  152:               goto out_close;
  153:             }
  154: 
  155:           retval = 0;
  156:           *result = resultbuf;
  157:         }
  158:     }
  159:   else
  160:     {
  161:       if (__builtin_expect (ai_resp.found == -1, 0))
  162:         {
  163:           /* The daemon does not cache this database.  */
  164:           __nss_not_use_nscd_hosts = 1;
  165:           goto out_close;
  166:         }
  167: 
  168:       /* Store the error number.  */
  169:       *h_errnop = ai_resp.error;
  170: 
  171:       /* Set errno to 0 to indicate no error, just no found record.  */
  172:       __set_errno (0);
  173:       /* Even though we have not found anything, the result is zero.  */
  174:       retval = 0;
  175:     }
  176: 
  177:  out_close:
  178:   if (sock != -1)
  179:     close_not_cancel_no_status (sock);
  180:  out:
  181:   if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0)
  182:     {
  183:       /* When we come here this means there has been a GC cycle while we
  184:          were looking for the data.  This means the data might have been
  185:          inconsistent.  Retry if possible.  */
  186:       if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1)
  187:         {
  188:           /* nscd is just running gc now.  Disable using the mapping.  */
  189:           if (atomic_decrement_val (&mapped->counter) == 0)
  190:             __nscd_unmap (mapped);
  191:           mapped = NO_MAPPING;
  192:         }
  193: 
  194:       if (retval != -1)
  195:         {
  196:           *result = NULL;
  197:           free (resultbuf);
  198:           goto retry;
  199:         }
  200:     }
  201: 
  202:   return retval;
  203: }
Syntax (Markdown)