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