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