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