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