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