Add x86 init-arch to nptl
[glibc.git] / nscd / hstcache.c
blob0d421fcbbb5e8823b660973e08b73e15e0dac3c8
1 /* Cache handling for host lookup.
2 Copyright (C) 1998-2013 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
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.
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.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>. */
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 <stdint.h>
33 #include <arpa/inet.h>
34 #include <arpa/nameser.h>
35 #include <sys/mman.h>
36 #include <stackinfo.h>
38 #include "nscd.h"
39 #include "dbg_log.h"
40 #ifdef HAVE_SENDFILE
41 # include <kernel-features.h>
42 #endif
45 /* This is the standard reply in case the service is disabled. */
46 static const hst_response_header disabled =
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
58 /* This is the struct describing how to write this record. */
59 const struct iovec hst_iov_disabled =
61 .iov_base = (void *) &disabled,
62 .iov_len = sizeof (disabled)
66 /* This is the standard reply in case we haven't found the dataset. */
67 static const hst_response_header notfound =
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
80 /* This is the standard reply in case there are temporary problems. */
81 static const hst_response_header tryagain =
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
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)
100 bool all_written = true;
101 time_t t = time (NULL);
103 /* We allocate all data in one memory block: the iov vector,
104 the response header and the dataset itself. */
105 struct dataset
107 struct datahead head;
108 hst_response_header resp;
109 char strdata[0];
110 } *dataset;
112 assert (offsetof (struct dataset, resp) == offsetof (struct datahead, data));
114 time_t timeout = MAX_TIMEOUT_VALUE;
115 if (hst == NULL)
117 if (he != NULL && errval == EAGAIN)
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;
126 /* Reload with the same time-to-live value. */
127 timeout = dh->timeout = t + dh->ttl;
129 else
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));
136 const hst_response_header *resp = (errval == EAGAIN
137 ? &tryagain : &notfound);
139 if (fd != -1 &&
140 TEMP_FAILURE_RETRY (send (fd, resp, total,
141 MSG_NOSIGNAL)) != total)
142 all_written = false;
144 /* If we have a transient error or cannot permanently store
145 the result, so be it. */
146 if (errval == EAGAIN || __builtin_expect (db->negtimeout == 0, 0))
148 /* Mark the old entry as obsolete. */
149 if (dh != NULL)
150 dh->usable = false;
152 else if ((dataset = mempool_alloc (db, (sizeof (struct dataset)
153 + req->key_len), 1)) != NULL)
155 dataset->head.allocsize = sizeof (struct dataset) + req->key_len;
156 dataset->head.recsize = total;
157 dataset->head.notfound = true;
158 dataset->head.nreloads = 0;
159 dataset->head.usable = true;
161 /* Compute the timeout time. */
162 dataset->head.ttl = ttl == INT32_MAX ? db->negtimeout : ttl;
163 timeout = dataset->head.timeout = t + dataset->head.ttl;
165 /* This is the reply. */
166 memcpy (&dataset->resp, resp, total);
168 /* Copy the key data. */
169 memcpy (dataset->strdata, key, req->key_len);
171 /* If necessary, we also propagate the data to disk. */
172 if (db->persistent)
174 // XXX async OK?
175 uintptr_t pval = (uintptr_t) dataset & ~pagesize_m1;
176 msync ((void *) pval,
177 ((uintptr_t) dataset & pagesize_m1)
178 + sizeof (struct dataset) + req->key_len, MS_ASYNC);
181 (void) cache_add (req->type, &dataset->strdata, req->key_len,
182 &dataset->head, true, db, owner, he == NULL);
184 pthread_rwlock_unlock (&db->lock);
186 /* Mark the old entry as obsolete. */
187 if (dh != NULL)
188 dh->usable = false;
192 else
194 /* Determine the I/O structure. */
195 size_t h_name_len = strlen (hst->h_name) + 1;
196 size_t h_aliases_cnt;
197 uint32_t *h_aliases_len;
198 size_t h_addr_list_cnt;
199 char *addresses;
200 char *aliases;
201 char *key_copy = NULL;
202 char *cp;
203 size_t cnt;
204 ssize_t total;
206 /* Determine the number of aliases. */
207 h_aliases_cnt = 0;
208 for (cnt = 0; hst->h_aliases[cnt] != NULL; ++cnt)
209 ++h_aliases_cnt;
210 /* Determine the length of all aliases. */
211 h_aliases_len = (uint32_t *) alloca (h_aliases_cnt * sizeof (uint32_t));
212 total = 0;
213 for (cnt = 0; cnt < h_aliases_cnt; ++cnt)
215 h_aliases_len[cnt] = strlen (hst->h_aliases[cnt]) + 1;
216 total += h_aliases_len[cnt];
219 /* Determine the number of addresses. */
220 h_addr_list_cnt = 0;
221 while (hst->h_addr_list[h_addr_list_cnt] != NULL)
222 ++h_addr_list_cnt;
224 if (h_addr_list_cnt == 0)
225 /* Invalid entry. */
226 return MAX_TIMEOUT_VALUE;
228 total += (sizeof (struct dataset)
229 + h_name_len
230 + h_aliases_cnt * sizeof (uint32_t)
231 + h_addr_list_cnt * hst->h_length);
233 /* If we refill the cache, first assume the reconrd did not
234 change. Allocate memory on the cache since it is likely
235 discarded anyway. If it turns out to be necessary to have a
236 new record we can still allocate real memory. */
237 bool alloca_used = false;
238 dataset = NULL;
240 /* If the record contains more than one IP address (used for
241 load balancing etc) don't cache the entry. This is something
242 the current cache handling cannot handle and it is more than
243 questionable whether it is worthwhile complicating the cache
244 handling just for handling such a special case. */
245 if (he == NULL && h_addr_list_cnt == 1)
246 dataset = (struct dataset *) mempool_alloc (db, total + req->key_len,
249 if (dataset == NULL)
251 /* We cannot permanently add the result in the moment. But
252 we can provide the result as is. Store the data in some
253 temporary memory. */
254 dataset = (struct dataset *) alloca (total + req->key_len);
256 /* We cannot add this record to the permanent database. */
257 alloca_used = true;
260 dataset->head.allocsize = total + req->key_len;
261 dataset->head.recsize = total - offsetof (struct dataset, resp);
262 dataset->head.notfound = false;
263 dataset->head.nreloads = he == NULL ? 0 : (dh->nreloads + 1);
264 dataset->head.usable = true;
266 /* Compute the timeout time. */
267 dataset->head.ttl = ttl == INT32_MAX ? db->postimeout : ttl;
268 timeout = dataset->head.timeout = t + dataset->head.ttl;
270 dataset->resp.version = NSCD_VERSION;
271 dataset->resp.found = 1;
272 dataset->resp.h_name_len = h_name_len;
273 dataset->resp.h_aliases_cnt = h_aliases_cnt;
274 dataset->resp.h_addrtype = hst->h_addrtype;
275 dataset->resp.h_length = hst->h_length;
276 dataset->resp.h_addr_list_cnt = h_addr_list_cnt;
277 dataset->resp.error = NETDB_SUCCESS;
279 /* Make sure there is no gap. */
280 assert ((char *) (&dataset->resp.error + 1) == dataset->strdata);
282 cp = dataset->strdata;
284 cp = mempcpy (cp, hst->h_name, h_name_len);
285 cp = mempcpy (cp, h_aliases_len, h_aliases_cnt * sizeof (uint32_t));
287 /* The normal addresses first. */
288 addresses = cp;
289 for (cnt = 0; cnt < h_addr_list_cnt; ++cnt)
290 cp = mempcpy (cp, hst->h_addr_list[cnt], hst->h_length);
292 /* Then the aliases. */
293 aliases = cp;
294 for (cnt = 0; cnt < h_aliases_cnt; ++cnt)
295 cp = mempcpy (cp, hst->h_aliases[cnt], h_aliases_len[cnt]);
297 assert (cp
298 == dataset->strdata + total - offsetof (struct dataset,
299 strdata));
301 /* If we are adding a GETHOSTBYNAME{,v6} entry we must be prepared
302 that the answer we get from the NSS does not contain the key
303 itself. This is the case if the resolver is used and the name
304 is extended by the domainnames from /etc/resolv.conf. Therefore
305 we explicitly add the name here. */
306 key_copy = memcpy (cp, key, req->key_len);
308 assert ((char *) &dataset->resp + dataset->head.recsize == cp);
310 /* Now we can determine whether on refill we have to create a new
311 record or not. */
312 if (he != NULL)
314 assert (fd == -1);
316 if (total + req->key_len == dh->allocsize
317 && total - offsetof (struct dataset, resp) == dh->recsize
318 && memcmp (&dataset->resp, dh->data,
319 dh->allocsize - offsetof (struct dataset, resp)) == 0)
321 /* The data has not changed. We will just bump the
322 timeout value. Note that the new record has been
323 allocated on the stack and need not be freed. */
324 assert (h_addr_list_cnt == 1);
325 dh->ttl = dataset->head.ttl;
326 dh->timeout = dataset->head.timeout;
327 ++dh->nreloads;
329 else
331 if (h_addr_list_cnt == 1)
333 /* We have to create a new record. Just allocate
334 appropriate memory and copy it. */
335 struct dataset *newp
336 = (struct dataset *) mempool_alloc (db,
337 total + req->key_len,
339 if (newp != NULL)
341 /* Adjust pointers into the memory block. */
342 addresses = (char *) newp + (addresses
343 - (char *) dataset);
344 aliases = (char *) newp + (aliases - (char *) dataset);
345 assert (key_copy != NULL);
346 key_copy = (char *) newp + (key_copy - (char *) dataset);
348 dataset = memcpy (newp, dataset, total + req->key_len);
349 alloca_used = false;
353 /* Mark the old record as obsolete. */
354 dh->usable = false;
357 else
359 /* We write the dataset before inserting it to the database
360 since while inserting this thread might block and so would
361 unnecessarily keep the receiver waiting. */
362 assert (fd != -1);
364 #ifdef HAVE_SENDFILE
365 if (__builtin_expect (db->mmap_used, 1) && !alloca_used)
367 assert (db->wr_fd != -1);
368 assert ((char *) &dataset->resp > (char *) db->data);
369 assert ((char *) dataset - (char *) db->head
370 + total
371 <= (sizeof (struct database_pers_head)
372 + db->head->module * sizeof (ref_t)
373 + db->head->data_size));
374 ssize_t written = sendfileall (fd, db->wr_fd,
375 (char *) &dataset->resp
376 - (char *) db->head,
377 dataset->head.recsize);
378 if (written != dataset->head.recsize)
380 # ifndef __ASSUME_SENDFILE
381 if (written == -1 && errno == ENOSYS)
382 goto use_write;
383 # endif
384 all_written = false;
387 else
388 # ifndef __ASSUME_SENDFILE
389 use_write:
390 # endif
391 #endif
392 if (writeall (fd, &dataset->resp, dataset->head.recsize)
393 != dataset->head.recsize)
394 all_written = false;
397 /* Add the record to the database. But only if it has not been
398 stored on the stack.
400 If the record contains more than one IP address (used for
401 load balancing etc) don't cache the entry. This is something
402 the current cache handling cannot handle and it is more than
403 questionable whether it is worthwhile complicating the cache
404 handling just for handling such a special case. */
405 if (! alloca_used)
407 /* If necessary, we also propagate the data to disk. */
408 if (db->persistent)
410 // XXX async OK?
411 uintptr_t pval = (uintptr_t) dataset & ~pagesize_m1;
412 msync ((void *) pval,
413 ((uintptr_t) dataset & pagesize_m1)
414 + total + req->key_len, MS_ASYNC);
417 /* NB: the following code is really complicated. It has
418 seemlingly duplicated code paths which do the same. The
419 problem is that we always must add the hash table entry
420 with the FIRST flag set first. Otherwise we get dangling
421 pointers in case memory allocation fails. */
422 assert (hst->h_addr_list[1] == NULL);
424 /* Avoid adding names if more than one address is available. See
425 above for more info. */
426 assert (req->type == GETHOSTBYNAME
427 || req->type == GETHOSTBYNAMEv6
428 || req->type == GETHOSTBYADDR
429 || req->type == GETHOSTBYADDRv6);
431 (void) cache_add (req->type, key_copy, req->key_len,
432 &dataset->head, true, db, owner, he == NULL);
434 pthread_rwlock_unlock (&db->lock);
438 if (__builtin_expect (!all_written, 0) && debug_level > 0)
440 char buf[256];
441 dbg_log (_("short write in %s: %s"), __FUNCTION__,
442 strerror_r (errno, buf, sizeof (buf)));
445 return timeout;
449 static int
450 lookup (int type, void *key, struct hostent *resultbufp, char *buffer,
451 size_t buflen, struct hostent **hst, int32_t *ttlp)
453 if (type == GETHOSTBYNAME)
454 return __gethostbyname3_r (key, AF_INET, resultbufp, buffer, buflen, hst,
455 &h_errno, ttlp, NULL);
456 if (type == GETHOSTBYNAMEv6)
457 return __gethostbyname3_r (key, AF_INET6, resultbufp, buffer, buflen, hst,
458 &h_errno, ttlp, NULL);
459 if (type == GETHOSTBYADDR)
460 return __gethostbyaddr2_r (key, NS_INADDRSZ, AF_INET, resultbufp, buffer,
461 buflen, hst, &h_errno, ttlp);
462 return __gethostbyaddr2_r (key, NS_IN6ADDRSZ, AF_INET6, resultbufp, buffer,
463 buflen, hst, &h_errno, ttlp);
467 static time_t
468 addhstbyX (struct database_dyn *db, int fd, request_header *req,
469 void *key, uid_t uid, struct hashentry *he, struct datahead *dh)
471 /* Search for the entry matching the key. Please note that we don't
472 look again in the table whether the dataset is now available. We
473 simply insert it. It does not matter if it is in there twice. The
474 pruning function only will look at the timestamp. */
475 int buflen = 1024;
476 char *buffer = (char *) alloca (buflen);
477 struct hostent resultbuf;
478 struct hostent *hst;
479 bool use_malloc = false;
480 int errval = 0;
481 int32_t ttl = INT32_MAX;
483 if (__builtin_expect (debug_level > 0, 0))
485 const char *str;
486 char buf[INET6_ADDRSTRLEN + 1];
487 if (req->type == GETHOSTBYNAME || req->type == GETHOSTBYNAMEv6)
488 str = key;
489 else
490 str = inet_ntop (req->type == GETHOSTBYADDR ? AF_INET : AF_INET6,
491 key, buf, sizeof (buf));
493 if (he == NULL)
494 dbg_log (_("Haven't found \"%s\" in hosts cache!"), (char *) str);
495 else
496 dbg_log (_("Reloading \"%s\" in hosts cache!"), (char *) str);
499 while (lookup (req->type, key, &resultbuf, buffer, buflen, &hst, &ttl) != 0
500 && h_errno == NETDB_INTERNAL
501 && (errval = errno) == ERANGE)
503 errno = 0;
505 if (__builtin_expect (buflen > 32768, 0))
507 char *old_buffer = buffer;
508 buflen *= 2;
509 buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen);
510 if (buffer == NULL)
512 /* We ran out of memory. We cannot do anything but
513 sending a negative response. In reality this should
514 never happen. */
515 hst = NULL;
516 buffer = old_buffer;
518 /* We set the error to indicate this is (possibly) a
519 temporary error and that it does not mean the entry
520 is not available at all. */
521 h_errno = TRY_AGAIN;
522 errval = EAGAIN;
523 break;
525 use_malloc = true;
527 else
528 /* Allocate a new buffer on the stack. If possible combine it
529 with the previously allocated buffer. */
530 buffer = (char *) extend_alloca (buffer, buflen, 2 * buflen);
533 time_t timeout = cache_addhst (db, fd, req, key, hst, uid, he, dh,
534 h_errno == TRY_AGAIN ? errval : 0, ttl);
536 if (use_malloc)
537 free (buffer);
539 return timeout;
543 void
544 addhstbyname (struct database_dyn *db, int fd, request_header *req,
545 void *key, uid_t uid)
547 addhstbyX (db, fd, req, key, uid, NULL, NULL);
551 time_t
552 readdhstbyname (struct database_dyn *db, struct hashentry *he,
553 struct datahead *dh)
555 request_header req =
557 .type = GETHOSTBYNAME,
558 .key_len = he->len
561 return addhstbyX (db, -1, &req, db->data + he->key, he->owner, he, dh);
565 void
566 addhstbyaddr (struct database_dyn *db, int fd, request_header *req,
567 void *key, uid_t uid)
569 addhstbyX (db, fd, req, key, uid, NULL, NULL);
573 time_t
574 readdhstbyaddr (struct database_dyn *db, struct hashentry *he,
575 struct datahead *dh)
577 request_header req =
579 .type = GETHOSTBYADDR,
580 .key_len = he->len
583 return addhstbyX (db, -1, &req, db->data + he->key, he->owner, he, dh);
587 void
588 addhstbynamev6 (struct database_dyn *db, int fd, request_header *req,
589 void *key, uid_t uid)
591 addhstbyX (db, fd, req, key, uid, NULL, NULL);
595 time_t
596 readdhstbynamev6 (struct database_dyn *db, struct hashentry *he,
597 struct datahead *dh)
599 request_header req =
601 .type = GETHOSTBYNAMEv6,
602 .key_len = he->len
605 return addhstbyX (db, -1, &req, db->data + he->key, he->owner, he, dh);
609 void
610 addhstbyaddrv6 (struct database_dyn *db, int fd, request_header *req,
611 void *key, uid_t uid)
613 addhstbyX (db, fd, req, key, uid, NULL, NULL);
617 time_t
618 readdhstbyaddrv6 (struct database_dyn *db, struct hashentry *he,
619 struct datahead *dh)
621 request_header req =
623 .type = GETHOSTBYADDRv6,
624 .key_len = he->len
627 return addhstbyX (db, -1, &req, db->data + he->key, he->owner, he, dh);