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       /* If the record contains more than one IP address (used for
203          load balancing etc) don't cache the entry.  This is something
204          the current cache handling cannot handle and it is more than
205          questionable whether it is worthwhile complicating the cache
206          handling just for handling such a special case.  */
207       if (!add_addr && hst->h_addr_list[1] != NULL)
208         {
209           free (data);
210           return;
211         }
212
213       addr_list_type = (hst->h_length == NS_INADDRSZ
214                         ? GETHOSTBYADDR : GETHOSTBYADDRv6);
215
216       /* Compute the timeout time.  */
217       t += db->postimeout;
218
219       /* Now get the lock to safely insert the records.  */
220       pthread_rwlock_rdlock (&db->lock);
221
222       /* First add all the aliases.  */
223       assert (add_addr || hst->h_addr_list[1] == NULL);
224       if (!add_addr)
225         for (cnt = 0; cnt < h_aliases_cnt; ++cnt)
226           {
227             if (addr_list_type == GETHOSTBYADDR)
228               cache_add (GETHOSTBYNAME, aliases, h_aliases_len[cnt], data,
229                          total, data, 0, t, db, owner);
230
231             cache_add (GETHOSTBYNAMEv6, aliases, h_aliases_len[cnt], data,
232                        total, data, 0, t, db, owner);
233
234             aliases += h_aliases_len[cnt];
235           }
236
237       /* Next the normal addresses.  */
238       if (add_addr)
239         for (cnt = 0; cnt < h_addr_list_cnt; ++cnt)
240           {
241             cache_add (addr_list_type, addresses, hst->h_length, data, total,
242                        data, cnt + 1 == h_addr_list_cnt, t, db, owner);
243             addresses += hst->h_length;
244           }
245
246       /* If necessary the IPv6 addresses.  */
247       if (add_addr && addr_list_type == GETHOSTBYADDR)
248         for (cnt = 0; cnt < h_addr_list_cnt; ++cnt)
249           {
250             cache_add (GETHOSTBYADDRv6, addresses, IN6ADDRSZ, data, total,
251                        data, 0, t, db, owner);
252             addresses += IN6ADDRSZ;
253           }
254
255       /* Avoid adding names if more than one address is available.  See
256          above for more info.  */
257       if (!add_addr)
258         {
259           /* If necessary add the key for this request.
260
261              Note: hst->h_addr_list[1] == NULL.  */
262           if (req->type == GETHOSTBYNAME || req->type == GETHOSTBYNAMEv6)
263             {
264               if (addr_list_type == GETHOSTBYADDR)
265                 cache_add (GETHOSTBYNAME, key_copy, req->key_len, data, total,
266                            data, 0, t, db, owner);
267               cache_add (GETHOSTBYNAMEv6, key_copy, req->key_len, data,
268                          total, data, 0, t, db, owner);
269             }
270
271           /* And finally the name.  We mark this as the last entry.  */
272           if (addr_list_type == GETHOSTBYADDR)
273             cache_add (GETHOSTBYNAME, data->strdata, h_name_len, data, total,
274                        data, 0, t, db, owner);
275           cache_add (GETHOSTBYNAMEv6, data->strdata, h_name_len, data,
276                      total, data, 1, t, db, owner);
277         }
278
279       pthread_rwlock_unlock (&db->lock);
280     }
281
282   if (__builtin_expect (written != total, 0) && debug_level > 0)
283     {
284       char buf[256];
285       dbg_log (_("short write in %s: %s"),  __FUNCTION__,
286                strerror_r (errno, buf, sizeof (buf)));
287     }
288 }
289
290
291 void
292 addhstbyname (struct database *db, int fd, request_header *req,
293               void *key, uid_t uid)
294 {
295   /* Search for the entry matching the key.  Please note that we don't
296      look again in the table whether the dataset is now available.  We
297      simply insert it.  It does not matter if it is in there twice.  The
298      pruning function only will look at the timestamp.  */
299   int buflen = 1024;
300   char *buffer = (char *) alloca (buflen);
301   struct hostent resultbuf;
302   struct hostent *hst;
303   uid_t oldeuid = 0;
304   bool use_malloc = false;
305
306   if (__builtin_expect (debug_level > 0, 0))
307     dbg_log (_("Haven't found \"%s\" in hosts cache!"), (char *) key);
308
309   if (secure[hstdb])
310     {
311       oldeuid = geteuid ();
312       seteuid (uid);
313     }
314
315   while (__gethostbyname2_r (key, AF_INET, &resultbuf, buffer, buflen,
316                              &hst, &h_errno) != 0
317          && h_errno == NETDB_INTERNAL
318          && errno == ERANGE)
319     {
320       char *old_buffer = buffer;
321       errno = 0;
322 #define INCR 1024
323
324       if (__builtin_expect (buflen > 32768, 0))
325         {
326           buflen += INCR;
327           buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen);
328           if (buffer == NULL)
329             {
330               /* We ran out of memory.  We cannot do anything but
331                  sending a negative response.  In reality this should
332                  never happen.  */
333               hst = NULL;
334               buffer = old_buffer;
335               break;
336             }
337           use_malloc = true;
338         }
339       else
340         /* Allocate a new buffer on the stack.  If possible combine it
341            with the previously allocated buffer.  */
342         buffer = (char *) extend_alloca (buffer, buflen, buflen + INCR);
343     }
344
345   if (secure[hstdb])
346     seteuid (oldeuid);
347
348   cache_addhst (db, fd, req, key, hst, uid, 0);
349
350   if (use_malloc)
351     free (buffer);
352 }
353
354
355 void
356 addhstbyaddr (struct database *db, int fd, request_header *req,
357               void *key, uid_t uid)
358 {
359   /* Search for the entry matching the key.  Please note that we don't
360      look again in the table whether the dataset is now available.  We
361      simply insert it.  It does not matter if it is in there twice.  The
362      pruning function only will look at the timestamp.  */
363   int buflen = 1024;
364   char *buffer = (char *) alloca (buflen);
365   struct hostent resultbuf;
366   struct hostent *hst;
367   uid_t oldeuid = 0;
368   bool use_malloc = false;
369
370   if (__builtin_expect (debug_level > 0, 0))
371     {
372       char buf[INET_ADDRSTRLEN];
373       dbg_log (_("Haven't found \"%s\" in hosts cache!"),
374                inet_ntop (AF_INET, key, buf, sizeof (buf)));
375     }
376
377   if (secure[hstdb])
378     {
379       oldeuid = geteuid ();
380       seteuid (uid);
381     }
382
383   while (__gethostbyaddr_r (key, NS_INADDRSZ, AF_INET, &resultbuf, buffer,
384                             buflen, &hst, &h_errno) != 0
385          && h_errno == NETDB_INTERNAL
386          && errno == ERANGE)
387     {
388       char *old_buffer = buffer;
389       errno = 0;
390
391       if (__builtin_expect (buflen > 32768, 0))
392         {
393           buflen += INCR;
394           buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen);
395           if (buffer == NULL)
396             {
397               /* We ran out of memory.  We cannot do anything but
398                  sending a negative response.  In reality this should
399                  never happen.  */
400               hst = NULL;
401               buffer = old_buffer;
402               break;
403             }
404           use_malloc = true;
405         }
406       else
407         /* Allocate a new buffer on the stack.  If possible combine it
408            with the previously allocated buffer.  */
409         buffer = (char *) extend_alloca (buffer, buflen, buflen + INCR);
410     }
411
412   if (secure[hstdb])
413     seteuid (oldeuid);
414
415   cache_addhst (db, fd, req, key, hst, uid, 1);
416
417   if (use_malloc)
418     free (buffer);
419 }
420
421
422 void
423 addhstbynamev6 (struct database *db, int fd, request_header *req,
424                 void *key, uid_t uid)
425 {
426   /* Search for the entry matching the key.  Please note that we don't
427      look again in the table whether the dataset is now available.  We
428      simply insert it.  It does not matter if it is in there twice.  The
429      pruning function only will look at the timestamp.  */
430   int buflen = 1024;
431   char *buffer = (char *) alloca (buflen);
432   struct hostent resultbuf;
433   struct hostent *hst;
434   uid_t oldeuid = 0;
435   bool use_malloc = false;
436
437   if (__builtin_expect (debug_level > 0, 0))
438     dbg_log (_("Haven't found \"%s\" in hosts cache!"), (char *) key);
439
440   if (secure[hstdb])
441     {
442       oldeuid = geteuid ();
443       seteuid (uid);
444     }
445
446   while (__gethostbyname2_r (key, AF_INET6, &resultbuf, buffer, buflen,
447                              &hst, &h_errno) != 0
448          && h_errno == NETDB_INTERNAL
449          && errno == ERANGE)
450     {
451       char *old_buffer = buffer;
452       errno = 0;
453
454       if (__builtin_expect (buflen > 32768, 0))
455         {
456           buflen += INCR;
457           buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen);
458           if (buffer == NULL)
459             {
460               /* We ran out of memory.  We cannot do anything but
461                  sending a negative response.  In reality this should
462                  never happen.  */
463               hst = NULL;
464               buffer = old_buffer;
465               break;
466             }
467           use_malloc = true;
468         }
469       else
470         /* Allocate a new buffer on the stack.  If possible combine it
471            with the previously allocated buffer.  */
472         buffer = (char *) extend_alloca (buffer, buflen, buflen + INCR);
473     }
474
475   if (secure[hstdb])
476     seteuid (oldeuid);
477
478   cache_addhst (db, fd, req, key, hst, uid, 0);
479
480   if (use_malloc)
481     free (buffer);
482 }
483
484
485 void
486 addhstbyaddrv6 (struct database *db, int fd, request_header *req,
487                 void *key, uid_t uid)
488 {
489   /* Search for the entry matching the key.  Please note that we don't
490      look again in the table whether the dataset is now available.  We
491      simply insert it.  It does not matter if it is in there twice.  The
492      pruning function only will look at the timestamp.  */
493   int buflen = 1024;
494   char *buffer = (char *) alloca (buflen);
495   struct hostent resultbuf;
496   struct hostent *hst;
497   uid_t oldeuid = 0;
498   bool use_malloc = false;
499
500   if (__builtin_expect (debug_level > 0, 0))
501     {
502       char buf[INET6_ADDRSTRLEN];
503       dbg_log (_("Haven't found \"%s\" in hosts cache!"),
504                inet_ntop (AF_INET6, key, buf, sizeof (buf)));
505     }
506
507   if (secure[hstdb])
508     {
509       oldeuid = geteuid ();
510       seteuid (uid);
511     }
512
513   while (__gethostbyaddr_r (key, NS_IN6ADDRSZ, AF_INET6, &resultbuf,
514                             buffer, buflen, &hst, &h_errno) != 0
515          && h_errno == NETDB_INTERNAL
516          && errno == ERANGE)
517     {
518       char *old_buffer = buffer;
519       errno = 0;
520
521       if (__builtin_expect (buflen > 32768, 0))
522         {
523           buflen += INCR;
524           buffer = (char *) realloc (use_malloc ? buffer : NULL, buflen);
525           if (buffer == NULL)
526             {
527               /* We ran out of memory.  We cannot do anything but
528                  sending a negative response.  In reality this should
529                  never happen.  */
530               hst = NULL;
531               buffer = old_buffer;
532               break;
533             }
534           use_malloc = true;
535         }
536       else
537         /* Allocate a new buffer on the stack.  If possible combine it
538            with the previously allocated buffer.  */
539         buffer = (char *) extend_alloca (buffer, buflen, buflen + INCR);
540     }
541
542   if (secure[hstdb])
543     seteuid (oldeuid);
544
545   cache_addhst (db, fd, req, key, hst, uid, 1);
546
547   if (use_malloc)
548     free (buffer);
549 }