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