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