aboutsummaryrefslogtreecommitdiff
path: root/nscd/nscd_gethst_r.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>1998-10-18 15:16:22 +0000
committerUlrich Drepper <drepper@redhat.com>1998-10-18 15:16:22 +0000
commit67479a700e3bd2e52980c00ac35c888589ac0a36 (patch)
tree2a13dea0fbd27ba19d0b19d5849699128d495806 /nscd/nscd_gethst_r.c
parent6cde0c6047769a661b8cf7e4f93842914a4bb54f (diff)
downloadglibc-67479a700e3bd2e52980c00ac35c888589ac0a36.tar
glibc-67479a700e3bd2e52980c00ac35c888589ac0a36.tar.gz
glibc-67479a700e3bd2e52980c00ac35c888589ac0a36.tar.bz2
glibc-67479a700e3bd2e52980c00ac35c888589ac0a36.zip
Update.
1998-10-18 Ulrich Drepper <drepper@cygnus.com> * resolv/nss_dns/dns-host.c: Add missing errnop parameter to the NSS functions. * resolv/nss_dns/dns-network.c: Likewise. * grp/Makefile: Don't search for linuxhtreads in add-ons, use have-thread-library to determine whether threads are available. * pwd/Makefile: Remove wrong comment. * inet/Makefile: Define CFLAGS-gethstbyad_r.c, CFLAGS-gethstbynm_r.c, and CFLAGS-gethstbynm2_r.c to -DUSE_NSCD=1. * locale/C-messages.c: Define default strings for YESTR and NOSTR. * nss/Versions: Add __nss_hosts_lookup. * nss/getXXbyYY.c: Remove unneeded assignment. * nss/getXXbyYY_r.c: Include nscd/nscd_proto.h only if needed. Almost complete rewrite of the NSCD to make it smaller, faster, add more functionnality and make it easier to extend. * nscd/Makfile (routines): Add nscd_gethst_r. (nscd-modules): Add hstcache, gethstbyad_r, gethstbynm2_r, and cache. * nscd/cache.c: New file. * nscd/gethstbyad_r.c: New file. * nscd/gethstbynm2_r.c: New file. * nscd/hstcache.c: New file. * nscd/nscd_gethst_r.c: New file. * nscd/connections.c: Rewritten. Don't start new thread for every new connection. Use a fixed set of threads which handle all connections and also the cache cleanup. * nscd/grpcache.c: Rewritten to use generic cache handling functions in cache.c. * nscd/nscd.c: Recognize new parameter nthreads. Adjust initialization for rewrite. Remove handle_requests function. * nscd/nscd.h (NSCD_VERSION): Bump to 2. Define new data structure for the new unified cache and the host database entries. * nscd/nscd_conf.c: Rewrite parsing partly to allow adding of more databases easily. Recognize check-files and threads definitions. * nscd/nscd.conf: Add definition of enable-cache and check-files to passwd and group definitions. Add new set of definitions for hosts. * nscd/nscd_getgr_r.c: Rewrite for new protocol. * nscd/nscd_getpw_r.c: Likewise. * nscd/nscd_proto.h: Add prototype for host database functions. * nscd/nscd_stat.c: Rewrite to simplify printing of information for many databases. * nscd/dbg_log.c: Remove unnecessary variable initializations. Global variable debug_flag is renamed to dbg_level. * nscd/dbg_log.h: Declare set_logfile.
Diffstat (limited to 'nscd/nscd_gethst_r.c')
-rw-r--r--nscd/nscd_gethst_r.c302
1 files changed, 302 insertions, 0 deletions
diff --git a/nscd/nscd_gethst_r.c b/nscd/nscd_gethst_r.c
new file mode 100644
index 0000000000..f78b104103
--- /dev/null
+++ b/nscd/nscd_gethst_r.c
@@ -0,0 +1,302 @@
+/* Copyright (C) 1998 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <arpa/nameser.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <sys/un.h>
+
+#include "nscd.h"
+#include "nscd_proto.h"
+
+int __nss_not_use_nscd_hosts;
+
+static int nscd_gethst_r (const char *key, size_t keylen, request_type type,
+ struct hostent *resultbuf, char *buffer,
+ size_t buflen, int *h_errnop);
+
+
+int
+__nscd_gethostbyname_r (const char *name, struct hostent *resultbuf,
+ char *buffer, size_t buflen, int *h_errnop)
+{
+ request_type reqtype;
+
+ reqtype = (_res.options & RES_USE_INET6) ? GETHOSTBYNAMEv6 : GETHOSTBYNAME;
+
+ return nscd_gethst_r (name, strlen (name) + 1, reqtype, resultbuf,
+ buffer, buflen, h_errnop);
+}
+
+
+int
+__nscd_gethostbyname2_r (const char *name, int af, struct hostent *resultbuf,
+ char *buffer, size_t buflen, int *h_errnop)
+{
+ request_type reqtype;
+
+ reqtype = af == AF_INET6 ? GETHOSTBYNAMEv6 : GETHOSTBYNAME;
+
+ return nscd_gethst_r (name, strlen (name) + 1, reqtype, resultbuf,
+ buffer, buflen, h_errnop);
+}
+
+
+int
+__nscd_gethostbyaddr_r (const char *addr, int len, int type,
+ struct hostent *resultbuf, char *buffer, size_t buflen,
+ int *h_errnop)
+{
+ request_type reqtype;
+
+ if (!((len == INADDRSZ && type == AF_INET)
+ || (len == IN6ADDRSZ && type == AF_INET6)))
+ /* LEN and TYPE do not match. */
+ return 1;
+
+ reqtype = type == AF_INET6 ? GETHOSTBYADDRv6 : GETHOSTBYADDR;
+
+ return nscd_gethst_r (addr, len, reqtype, resultbuf, buffer, buflen,
+ h_errnop);
+}
+
+
+/* Create a socket connected to a name. */
+static int
+open_socket (void)
+{
+ struct sockaddr_un addr;
+ int sock;
+ int saved_errno = errno;
+
+ sock = __socket (PF_UNIX, SOCK_STREAM, 0);
+ if (sock < 0)
+ {
+ __set_errno (saved_errno);
+ return -1;
+ }
+
+ addr.sun_family = AF_UNIX;
+ strcpy (addr.sun_path, _PATH_NSCDSOCKET);
+ if (__connect (sock, (struct sockaddr *) &addr, sizeof (addr)) < 0)
+ {
+ __close (sock);
+ __set_errno (saved_errno);
+ return -1;
+ }
+
+ return sock;
+}
+
+
+static int
+nscd_gethst_r (const char *key, size_t keylen, request_type type,
+ struct hostent *resultbuf, char *buffer, size_t buflen,
+ int *h_errnop)
+{
+ int sock = open_socket ();
+ hst_response_header hst_resp;
+ request_header req;
+ ssize_t nbytes;
+
+ if (sock == -1)
+ {
+ __nss_not_use_nscd_group = 1;
+ return 1;
+ }
+
+ req.version = NSCD_VERSION;
+ req.type = type;
+ req.key_len = keylen;
+ nbytes = __write (sock, &req, sizeof (request_header));
+ if (nbytes != sizeof (request_header))
+ {
+ __close (sock);
+ return 1;
+ }
+
+ nbytes = __write (sock, key, req.key_len);
+ if (nbytes != req.key_len)
+ {
+ __close (sock);
+ return 1;
+ }
+
+ nbytes = __read (sock, &hst_resp, sizeof (hst_response_header));
+ if (nbytes != sizeof (hst_response_header))
+ {
+ __close (sock);
+ return 1;
+ }
+
+ if (hst_resp.found == -1)
+ {
+ /* The daemon does not cache this database. */
+ __close (sock);
+ __nss_not_use_nscd_hosts = 1;
+ return 1;
+ }
+
+ if (hst_resp.found == 1)
+ {
+ struct iovec vec[4];
+ size_t *aliases_len;
+ char *cp = buffer;
+ uintptr_t align;
+ size_t total_len;
+ ssize_t cnt;
+ char *ignore;
+ int n;
+
+ /* A first check whether the buffer is sufficently large is possible. */
+ /* Now allocate the buffer the array for the group members. We must
+ align the pointer. */
+ align = ((__alignof__ (char *) - (cp - ((char *) 0)))
+ & (__alignof__ (char *) - 1));
+ if (buflen < (align + hst_resp.h_name_len
+ + ((hst_resp.h_aliases_cnt + hst_resp.h_addr_list_cnt + 2)
+ * sizeof (char *))
+ + hst_resp.h_addr_list_cnt * (type == AF_INET
+ ? INADDRSZ : IN6ADDRSZ)))
+ {
+ no_room:
+ __set_errno (ERANGE);
+ __close (sock);
+ return -1;
+ }
+ cp += align;
+
+ /* Prepare the result as far as we can. */
+ resultbuf->h_aliases = (char **) cp;
+ cp += (hst_resp.h_aliases_cnt + 1) * sizeof (char *);
+ resultbuf->h_addr_list = (char **) cp;
+ cp += (hst_resp.h_addr_list_cnt + 1) * sizeof (char *);
+
+ resultbuf->h_name = cp;
+ cp += hst_resp.h_name_len;
+ vec[0].iov_base = resultbuf->h_name;
+ vec[0].iov_len = hst_resp.h_name_len;
+
+ aliases_len = alloca (hst_resp.h_aliases_cnt * sizeof (size_t));
+ vec[1].iov_base = aliases_len;
+ vec[1].iov_len = hst_resp.h_aliases_cnt * sizeof (size_t);
+
+ total_len = (hst_resp.h_name_len
+ + hst_resp.h_aliases_cnt * sizeof (size_t));
+
+ n = 2;
+ if (type == GETHOSTBYADDR || type == GETHOSTBYNAME)
+ {
+ vec[2].iov_base = cp;
+ vec[2].iov_len = hst_resp.h_addr_list_cnt * INADDRSZ;
+
+ ignore = alloca (hst_resp.h_addr_list_cnt * IN6ADDRSZ);
+ vec[3].iov_base = ignore;
+ vec[3].iov_len = hst_resp.h_addr_list_cnt * IN6ADDRSZ;
+
+ for (cnt = 0; cnt < hst_resp.h_addr_list_cnt; ++cnt)
+ {
+ resultbuf->h_addr_list[cnt] = cp;
+ cp += INADDRSZ;
+ }
+
+ resultbuf->h_addrtype = AF_INET;
+ resultbuf->h_length = INADDRSZ;
+
+ total_len += hst_resp.h_addr_list_cnt * (INADDRSZ + IN6ADDRSZ);
+
+ n = 4;
+ }
+ else
+ {
+ if (hst_resp.h_length == INADDRSZ)
+ {
+ ignore = alloca (hst_resp.h_addr_list_cnt * INADDRSZ);
+ vec[2].iov_base = ignore;
+ vec[2].iov_len = hst_resp.h_addr_list_cnt * INADDRSZ;
+
+ total_len += hst_resp.h_addr_list_cnt * INADDRSZ;
+
+ n = 3;
+ }
+
+ vec[n].iov_base = cp;
+ vec[n].iov_len = hst_resp.h_addr_list_cnt * IN6ADDRSZ;
+
+ for (cnt = 0; cnt < hst_resp.h_addr_list_cnt; ++cnt)
+ {
+ resultbuf->h_addr_list[cnt] = cp;
+ cp += IN6ADDRSZ;
+ }
+
+ resultbuf->h_addrtype = AF_INET6;
+ resultbuf->h_length = IN6ADDRSZ;
+
+ total_len += hst_resp.h_addr_list_cnt * IN6ADDRSZ;
+
+ ++n;
+ }
+ resultbuf->h_addr_list[cnt] = NULL;
+
+ if (__readv (sock, vec, n) != total_len)
+ {
+ __close (sock);
+ return 1;
+ }
+
+ /* Now we also can read the aliases. */
+ total_len = 0;
+ for (cnt = 0; cnt < hst_resp.h_aliases_cnt; ++cnt)
+ {
+ resultbuf->h_aliases[cnt] = cp;
+ cp += aliases_len[cnt];
+ total_len += aliases_len[cnt];
+ }
+ resultbuf->h_aliases[cnt] = NULL;
+
+ /* See whether this would exceed the buffer capacity. */
+ if (cp > buffer + buflen)
+ goto no_room;
+
+ /* And finally read the aliases. */
+ if (__read (sock, resultbuf->h_aliases[0], total_len) != total_len)
+ {
+ __close (sock);
+ return 1;
+ }
+
+ __close (sock);
+ return 0;
+ }
+ else
+ {
+ /* Store the error number. */
+ *h_errnop = hst_resp.error;
+
+ __close (sock);
+ return -1;
+ }
+}