Fix lock handling in memory hander of nscd.
[platform/upstream/glibc.git] / nscd / hstcache.c
1 /* Cache handling for host lookup.
2    Copyright (C) 1998-2008, 2009 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published
8    by the Free Software Foundation; version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software Foundation,
18    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20 #include <alloca.h>
21 #include <assert.h>
22 #include <errno.h>
23 #include <error.h>
24 #include <libintl.h>
25 #include <netdb.h>
26 #include <stdbool.h>
27 #include <stddef.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <time.h>
32 #include <unistd.h>
33 #include <arpa/inet.h>
34 #include <arpa/nameser.h>
35 #include <sys/mman.h>
36 #include <stackinfo.h>
37
38 #include "nscd.h"
39 #include "dbg_log.h"
40 #ifdef HAVE_SENDFILE
41 # include <kernel-features.h>
42 #endif
43
44
45 /* This is the standard reply in case the service is disabled.  */
46 static const hst_response_header disabled =
47 {
48   .version = NSCD_VERSION,
49   .found = -1,
50   .h_name_len = 0,
51   .h_aliases_cnt = 0,
52   .h_addrtype = -1,
53   .h_length = -1,
54   .h_addr_list_cnt = 0,
55   .error = NETDB_INTERNAL
56 };
57
58 /* This is the struct describing how to write this record.  */
59 const struct iovec hst_iov_disabled =
60 {
61   .iov_base = (void *) &disabled,
62   .iov_len = sizeof (disabled)
63 };
64
65
66 /* This is the standard reply in case we haven't found the dataset.  */
67 static const hst_response_header notfound =
68 {
69   .version = NSCD_VERSION,
70   .found = 0,
71   .h_name_len = 0,
72   .h_aliases_cnt = 0,
73   .h_addrtype = -1,
74   .h_length = -1,
75   .h_addr_list_cnt = 0,
76   .error = HOST_NOT_FOUND
77 };
78
79
80 static void
81 cache_addhst (struct database_dyn *db, int fd, request_header *req,
82               const void *key, struct hostent *hst, uid_t owner,
83               struct hashentry *const he, struct datahead *dh, int errval,
84               int32_t ttl)
85 {
86   bool all_written = true;
87   time_t t = time (NULL);
88
89   /* We allocate all data in one memory block: the iov vector,
90      the response header and the dataset itself.  */
91   struct dataset
92   {
93     struct datahead head;
94     hst_response_header resp;
95     char strdata[0];
96   } *dataset;
97
98   assert (offsetof (struct dataset, resp) == offsetof (struct datahead, data));
99
100   if (hst == NULL)
101     {
102       if (he != NULL && errval == EAGAIN)
103         {
104           /* If we have an old record available but cannot find one
105              now because the service is not available we keep the old
106              record and make sure it does not get removed.  */
107           if (reload_count != UINT_MAX)
108             /* Do not reset the value if we never not reload the record.  */
109             dh->nreloads = reload_count - 1;
110         }
111       else
112         {
113           /* We have no data.  This means we send the standard reply for this
114              case.  */
115           ssize_t total = sizeof (notfound);
116
117           if (fd != -1 &&
118               TEMP_FAILURE_RETRY (send (fd, &notfound, total,
119                                         MSG_NOSIGNAL)) != total)
120             all_written = false;
121
122           dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len,
123                                    1);
124           /* If we cannot permanently store the result, so be it.  */
125           if (dataset != NULL)
126             {
127               dataset->head.allocsize = sizeof (struct dataset) + req->key_len;
128               dataset->head.recsize = total;
129               dataset->head.notfound = true;
130               dataset->head.nreloads = 0;
131               dataset->head.usable = true;
132
133               /* Compute the timeout time.  */
134               dataset->head.timeout = t + (ttl == INT32_MAX
135                                            ? db->negtimeout : ttl);
136
137               /* This is the reply.  */
138               memcpy (&dataset->resp, &notfound, total);
139
140               /* Copy the key data.  */
141               memcpy (dataset->strdata, key, req->key_len);
142
143               /* If necessary, we also propagate the data to disk.  */
144               if (db->persistent)
145                 {
146                   // XXX async OK?
147                   uintptr_t pval = (uintptr_t) dataset & ~pagesize_m1;
148                   msync ((void *) pval,
149                          ((uintptr_t) dataset & pagesize_m1)
150                          + sizeof (struct dataset) + req->key_len, MS_ASYNC);
151                 }
152
153               (void) cache_add (req->type, &dataset->strdata, req->key_len,
154                                 &dataset->head, true, db, owner, he == NULL);
155
156               /* Mark the old entry as obsolete.  */
157               if (dh != NULL)
158                 dh->usable = false;
159             }
160         }
161     }
162   else
163     {
164       /* Determine the I/O structure.  */
165       size_t h_name_len = strlen (hst->h_name) + 1;
166       size_t h_aliases_cnt;
167       uint32_t *h_aliases_len;
168       size_t h_addr_list_cnt;
169       int addr_list_type;
170       char *addresses;
171       char *aliases;
172       char *key_copy = NULL;
173       char *cp;
174       size_t cnt;
175       ssize_t total;
176
177       /* Determine the number of aliases.  */
178       h_aliases_cnt = 0;
179       for (cnt = 0; hst->h_aliases[cnt] != NULL; ++cnt)
180         ++h_aliases_cnt;
181       /* Determine the length of all aliases.  */
182       h_aliases_len = (uint32_t *) alloca (h_aliases_cnt * sizeof (uint32_t));
183       total = 0;
184       for (cnt = 0; cnt < h_aliases_cnt; ++cnt)
185         {
186           h_aliases_len[cnt] = strlen (hst->h_aliases[cnt]) + 1;
187           total += h_aliases_len[cnt];
188         }
189
190       /* Determine the number of addresses.  */
191       h_addr_list_cnt = 0;
192       while (hst->h_addr_list[h_addr_list_cnt] != NULL)
193         ++h_addr_list_cnt;
194
195       if (h_addr_list_cnt == 0)
196         /* Invalid entry.  */
197         return;
198
199       total += (sizeof (struct dataset)
200                 + h_name_len
201                 + h_aliases_cnt * sizeof (uint32_t)
202                 + h_addr_list_cnt * hst->h_length);
203
204       /* If we refill the cache, first assume the reconrd did not
205          change.  Allocate memory on the cache since it is likely
206          discarded anyway.  If it turns out to be necessary to have a
207          new record we can still allocate real memory.  */
208       bool alloca_used = false;
209       dataset = NULL;
210
211       /* If the record contains more than one IP address (used for
212          load balancing etc) don't cache the entry.  This is something
213          the current cache handling cannot handle and it is more than
214          questionable whether it is worthwhile complicating the cache
215          handling just for handling such a special case. */
216       if (he == NULL && h_addr_list_cnt == 1)
217         dataset = (struct dataset *) mempool_alloc (db, total + req->key_len,
218                                                     1);
219
220       if (dataset == NULL)
221         {
222           /* We cannot permanently add the result in the moment.  But
223              we can provide the result as is.  Store the data in some
224              temporary memory.  */
225           dataset = (struct dataset *) alloca (total + req->key_len);
226
227           /* We cannot add this record to the permanent database.  */
228           alloca_used = true;
229         }
230
231       dataset->head.allocsize = total + req->key_len;
232       dataset->head.recsize = total - offsetof (struct dataset, resp);
233       dataset->head.notfound = false;
234       dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1);
235       dataset->head.usable = true;
236
237       /* Compute the timeout time.  */
238       dataset->head.timeout = t + (ttl == INT32_MAX ? db->postimeout : ttl);
239
240       dataset->resp.version = NSCD_VERSION;
241       dataset->resp.found = 1;
242       dataset->resp.h_name_len = h_name_len;
243       dataset->resp.h_aliases_cnt = h_aliases_cnt;
244       dataset->resp.h_addrtype = hst->h_addrtype;
245       dataset->resp.h_length = hst->h_length;
246       dataset->resp.h_addr_list_cnt = h_addr_list_cnt;
247       dataset->resp.error = NETDB_SUCCESS;
248
249       /* Make sure there is no gap.  */
250       assert ((char *) (&dataset->resp.error + 1) == dataset->strdata);
251
252       cp = dataset->strdata;
253
254       cp = mempcpy (cp, hst->h_name, h_name_len);
255       cp = mempcpy (cp, h_aliases_len, h_aliases_cnt * sizeof (uint32_t));
256
257       /* The normal addresses first.  */
258       addresses = cp;
259       for (cnt = 0; cnt < h_addr_list_cnt; ++cnt)
260         cp = mempcpy (cp, hst->h_addr_list[cnt], hst->h_length);
261
262       /* Then the aliases.  */
263       aliases = cp;
264       for (cnt = 0; cnt < h_aliases_cnt; ++cnt)
265         cp = mempcpy (cp, hst->h_aliases[cnt], h_aliases_len[cnt]);
266
267       assert (cp
268               == dataset->strdata + total - offsetof (struct dataset,
269                                                       strdata));
270
271       /* If we are adding a GETHOSTBYNAME{,v6} entry we must be prepared
272          that the answer we get from the NSS does not contain the key
273          itself.  This is the case if the resolver is used and the name
274          is extended by the domainnames from /etc/resolv.conf.  Therefore
275          we explicitly add the name here.  */
276       key_copy = memcpy (cp, key, req->key_len);
277
278       assert ((char *) &dataset->resp + dataset->head.recsize == cp);
279
280       /* Now we can determine whether on refill we have to create a new
281          record or not.  */
282       if (he != NULL)
283         {
284           assert (fd == -1);
285
286           if (total + req->key_len == dh->allocsize
287               && total - offsetof (struct dataset, resp) == dh->recsize
288               && memcmp (&dataset->resp, dh->data,
289                          dh->allocsize - offsetof (struct dataset, resp)) == 0)
290             {
291               /* The data has not changed.  We will just bump the
292                  timeout value.  Note that the new record has been
293                  allocated on the stack and need not be freed.  */
294               assert (h_addr_list_cnt == 1);
295               dh->timeout = dataset->head.timeout;
296               ++dh->nreloads;
297             }
298           else
299             {
300               if (h_addr_list_cnt == 1)
301                 {
302                   /* We have to create a new record.  Just allocate
303                      appropriate memory and copy it.  */
304                   struct dataset *newp
305                     = (struct dataset *) mempool_alloc (db,
306                                                         total + req->key_len,
307                                                         1);
308                   if (newp != NULL)
309                     {
310                       /* Adjust pointers into the memory block.  */
311                       addresses = (char *) newp + (addresses
312                                                    - (char *) dataset);
313                       aliases = (char *) newp + (aliases - (char *) dataset);
314                       assert (key_copy != NULL);
315                       key_copy = (char *) newp + (key_copy - (char *) dataset);
316
317                       dataset = memcpy (newp, dataset, total + req->key_len);
318                       alloca_used = false;
319                     }
320                 }
321
322               /* Mark the old record as obsolete.  */
323               dh->usable = false;
324             }
325         }
326       else
327         {
328           /* We write the dataset before inserting it to the database
329              since while inserting this thread might block and so would
330              unnecessarily keep the receiver waiting.  */
331           assert (fd != -1);
332
333 #ifdef HAVE_SENDFILE
334           if (__builtin_expect (db->mmap_used, 1) && !alloca_used)
335             {
336               assert (db->wr_fd != -1);
337               assert ((char *) &dataset->resp > (char *) db->data);
338               assert ((char *) &dataset->resp - (char *) db->head
339                       + total
340                       <= (sizeof (struct database_pers_head)
341                           + db->head->module * sizeof (ref_t)
342                           + db->head->data_size));
343               ssize_t written = sendfileall (fd, db->wr_fd,
344                                              (char *) &dataset->resp
345                                              - (char *) db->head,
346                                              dataset->head.recsize);
347               if (written != dataset->head.recsize)
348                 {
349 # ifndef __ASSUME_SENDFILE
350                   if (written == -1 && errno == ENOSYS)
351                     goto use_write;
352 # endif
353                   all_written = false;
354                 }
355             }
356           else
357 # ifndef __ASSUME_SENDFILE
358           use_write:
359 # endif
360 #endif
361             if (writeall (fd, &dataset->resp, dataset->head.recsize)
362                 != dataset->head.recsize)
363               all_written = false;
364         }
365
366       /* Add the record to the database.  But only if it has not been
367          stored on the stack.
368
369          If the record contains more than one IP address (used for
370          load balancing etc) don't cache the entry.  This is something
371          the current cache handling cannot handle and it is more than
372          questionable whether it is worthwhile complicating the cache
373          handling just for handling such a special case. */
374       if (! alloca_used)
375         {
376           /* If necessary, we also propagate the data to disk.  */
377           if (db->persistent)
378             {
379               // XXX async OK?
380               uintptr_t pval = (uintptr_t) dataset & ~pagesize_m1;
381               msync ((void *) pval,
382                      ((uintptr_t) dataset & pagesize_m1)
383                      + total + req->key_len, MS_ASYNC);
384             }
385
386           addr_list_type = (hst->h_length == NS_INADDRSZ
387                             ? GETHOSTBYADDR : GETHOSTBYADDRv6);
388
389           /* NB: the following code is really complicated.  It has
390              seemlingly duplicated code paths which do the same.  The
391              problem is that we always must add the hash table entry
392              with the FIRST flag set first.  Otherwise we get dangling
393              pointers in case memory allocation fails.  */
394           assert (hst->h_addr_list[1] == NULL);
395
396           /* Avoid adding names if more than one address is available.  See
397              above for more info.  */
398           assert (req->type == GETHOSTBYNAME
399                   || req->type == GETHOSTBYNAMEv6
400                   || req->type == GETHOSTBYADDR
401                   || req->type == GETHOSTBYADDRv6);
402
403           (void) cache_add (req->type, key_copy, req->key_len,
404                             &dataset->head, true, db, owner, he == NULL);
405         }
406     }
407
408   if (__builtin_expect (!all_written, 0) && debug_level > 0)
409     {
410       char buf[256];
411       dbg_log (_("short write in %s: %s"),  __FUNCTION__,
412                strerror_r (errno, buf, sizeof (buf)));
413     }
414 }
415
416
417 static int
418 lookup (int type, void *key, struct hostent *resultbufp, char *buffer,
419         size_t buflen, struct hostent **hst, int32_t *ttlp)
420 {
421   if (type == GETHOSTBYNAME)
422     return __gethostbyname3_r (key, AF_INET, resultbufp, buffer, buflen, hst,
423                                &h_errno, ttlp, NULL);
424   if (type == GETHOSTBYNAMEv6)
425     return __gethostbyname3_r (key, AF_INET6, resultbufp, buffer, buflen, hst,
426                                &h_errno, ttlp, NULL);
427   if (type == GETHOSTBYADDR)
428     return __gethostbyaddr2_r (key, NS_INADDRSZ, AF_INET, resultbufp, buffer,
429                                buflen, hst, &h_errno, ttlp);
430   return __gethostbyaddr2_r (key, NS_IN6ADDRSZ, AF_INET6, resultbufp, buffer,
431                              buflen, hst, &h_errno, ttlp);
432 }
433
434
435 static void
436 addhstbyX (struct database_dyn *db, int fd, request_header *req,
437            void *key, uid_t uid, struct hashentry *he, struct datahead *dh)
438 {
439   /* Search for the entry matching the key.  Please note that we don't
440      look again in the table whether the dataset is now available.  We
441      simply insert it.  It does not matter if it is in there twice.  The
442      pruning function only will look at the timestamp.  */
443   int buflen = 1024;
444   char *buffer = (char *) alloca (buflen);
445   struct hostent resultbuf;
446   struct hostent *hst;
447   bool use_malloc = false;
448   int errval = 0;
449   int32_t ttl = INT32_MAX;
450
451   if (__builtin_expect (debug_level > 0, 0))
452     {
453       const char *str;
454       char buf[INET6_ADDRSTRLEN + 1];
455       if (req->type == GETHOSTBYNAME || req->type == GETHOSTBYNAMEv6)
456         str = key;
457       else
458         str = inet_ntop (req->type == GETHOSTBYADDR ? AF_INET : AF_INET6,
459                          key, buf, sizeof (buf));
460
461       if (he == NULL)
462         dbg_log (_("Haven't found \"%s\" in hosts cache!"), (char *) str);
463       else
464         dbg_log (_("Reloading \"%s\" in hosts cache!"), (char *) str);
465     }
466
467   while (lookup (req->type, key, &resultbuf, buffer, buflen, &hst, &ttl) != 0
468          && h_errno == NETDB_INTERNAL
469          && (errval = errno) == ERANGE)
470     {
471       errno = 0;
472
473       if (__builtin_expect (buflen > 32768, 0))
474         {
475           char *old_buffer = buffer;
476           buflen *= 2;
477           buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen);
478           if (buffer == NULL)
479             {
480               /* We ran out of memory.  We cannot do anything but
481                  sending a negative response.  In reality this should
482                  never happen.  */
483               hst = NULL;
484               buffer = old_buffer;
485
486               /* We set the error to indicate this is (possibly) a
487                  temporary error and that it does not mean the entry
488                  is not available at all.  */
489               errval = EAGAIN;
490               break;
491             }
492           use_malloc = true;
493         }
494       else
495         /* Allocate a new buffer on the stack.  If possible combine it
496            with the previously allocated buffer.  */
497         buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen);
498     }
499
500   cache_addhst (db, fd, req, key, hst, uid, he, dh,
501                 h_errno == TRY_AGAIN ? errval : 0, ttl);
502
503   if (use_malloc)
504     free (buffer);
505 }
506
507
508 void
509 addhstbyname (struct database_dyn *db, int fd, request_header *req,
510               void *key, uid_t uid)
511 {
512   addhstbyX (db, fd, req, key, uid, NULL, NULL);
513 }
514
515
516 void
517 readdhstbyname (struct database_dyn *db, struct hashentry *he,
518                 struct datahead *dh)
519 {
520   request_header req =
521     {
522       .type = GETHOSTBYNAME,
523       .key_len = he->len
524     };
525
526   addhstbyX (db, -1, &req, db->data + he->key, he->owner, he, dh);
527 }
528
529
530 void
531 addhstbyaddr (struct database_dyn *db, int fd, request_header *req,
532               void *key, uid_t uid)
533 {
534   addhstbyX (db, fd, req, key, uid, NULL, NULL);
535 }
536
537
538 void
539 readdhstbyaddr (struct database_dyn *db, struct hashentry *he,
540                 struct datahead *dh)
541 {
542   request_header req =
543     {
544       .type = GETHOSTBYADDR,
545       .key_len = he->len
546     };
547
548   addhstbyX (db, -1, &req, db->data + he->key, he->owner, he, dh);
549 }
550
551
552 void
553 addhstbynamev6 (struct database_dyn *db, int fd, request_header *req,
554                 void *key, uid_t uid)
555 {
556   addhstbyX (db, fd, req, key, uid, NULL, NULL);
557 }
558
559
560 void
561 readdhstbynamev6 (struct database_dyn *db, struct hashentry *he,
562                   struct datahead *dh)
563 {
564   request_header req =
565     {
566       .type = GETHOSTBYNAMEv6,
567       .key_len = he->len
568     };
569
570   addhstbyX (db, -1, &req, db->data + he->key, he->owner, he, dh);
571 }
572
573
574 void
575 addhstbyaddrv6 (struct database_dyn *db, int fd, request_header *req,
576                 void *key, uid_t uid)
577 {
578   addhstbyX (db, fd, req, key, uid, NULL, NULL);
579 }
580
581
582 void
583 readdhstbyaddrv6 (struct database_dyn *db, struct hashentry *he,
584                   struct datahead *dh)
585 {
586   request_header req =
587     {
588       .type = GETHOSTBYADDRv6,
589       .key_len = he->len
590     };
591
592   addhstbyX (db, -1, &req, db->data + he->key, he->owner, he, dh);
593 }