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