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