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