gethostby_door.c revision 61961e0f20c7637a3846bb39786bb9dffa91dfb9
1N/A/*
1N/A * CDDL HEADER START
1N/A *
1N/A * The contents of this file are subject to the terms of the
1N/A * Common Development and Distribution License, Version 1.0 only
1N/A * (the "License"). You may not use this file except in compliance
1N/A * with the License.
1N/A *
1N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1N/A * or http://www.opensolaris.org/os/licensing.
1N/A * See the License for the specific language governing permissions
1N/A * and limitations under the License.
1N/A *
1N/A * When distributing Covered Code, include this CDDL HEADER in each
1N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1N/A * If applicable, add the following below this CDDL HEADER, with the
1N/A * fields enclosed by brackets "[]" replaced with your own identifying
1N/A * information: Portions Copyright [yyyy] [name of copyright owner]
1N/A *
1N/A * CDDL HEADER END
1N/A */
1N/A
1N/A/*
1N/A * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
1N/A * Use is subject to license terms.
1N/A */
1N/A
1N/A#pragma ident "%Z%%M% %I% %E% SMI"
1N/A
1N/A#include <pwd.h>
1N/A#include <strings.h>
1N/A#include <sys/mman.h>
1N/A#include <sys/door.h>
1N/A#include <errno.h>
1N/A#include <fcntl.h>
1N/A#include <synch.h>
1N/A#include <getxby_door.h>
1N/A#include "nss.h"
1N/A
1N/A#ifdef PIC
1N/A
1N/Astatic struct hostent *process_gethost(struct hostent *, char *, int, int *,
1N/A nsc_data_t *);
1N/A
1N/Astruct hostent *
1N/A_door_gethostbyname_r(const char *name, struct hostent *result, char *buffer,
1N/A int buflen, int *h_errnop)
1N/A{
1N/A
1N/A /*
1N/A * allocate space on the stack for the nscd to return
1N/A * host and host alias information
1N/A */
1N/A union {
1N/A nsc_data_t s_d;
1N/A char s_b[8192];
1N/A } space;
1N/A nsc_data_t *sptr;
1N/A int ndata;
1N/A int adata;
1N/A struct hostent *resptr = NULL;
1N/A
1N/A if ((name == NULL) ||
1N/A (strlen(name) >= (sizeof (space) - sizeof (nsc_data_t)))) {
1N/A errno = ERANGE;
1N/A if (h_errnop)
1N/A *h_errnop = HOST_NOT_FOUND;
1N/A return (NULL);
1N/A }
1N/A
1N/A adata = (sizeof (nsc_call_t) + strlen(name) + 1);
1N/A ndata = sizeof (space);
1N/A space.s_d.nsc_call.nsc_callnumber = GETHOSTBYNAME;
1N/A (void) strcpy(space.s_d.nsc_call.nsc_u.name, name);
1N/A sptr = &space.s_d;
1N/A
1N/A switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) {
1N/A case SUCCESS: /* positive cache hit */
1N/A break;
1N/A case NOTFOUND: /* negative cache hit */
1N/A if (h_errnop)
1N/A *h_errnop = space.s_d.nsc_ret.nsc_errno;
1N/A return (NULL);
1N/A default:
1N/A return ((struct hostent *)_switch_gethostbyname_r(name,
1N/A result, buffer, buflen, h_errnop));
1N/A }
1N/A resptr = process_gethost(result, buffer, buflen, h_errnop, sptr);
1N/A
1N/A /*
1N/A * check if doors realloced buffer underneath of us....
1N/A * munmap or suffer a memory leak
1N/A */
1N/A
1N/A if (sptr != &space.s_d) {
1N/A munmap((char *)sptr, ndata); /* return memory */
1N/A }
1N/A
1N/A return (resptr);
1N/A}
1N/A
1N/Astruct hostent *
1N/A_door_gethostbyaddr_r(const char *addr, int length, int type,
1N/A struct hostent *result, char *buffer, int buflen, int *h_errnop)
1N/A{
1N/A /*
1N/A * allocate space on the stack for the nscd to return
1N/A * host and host alias information
1N/A */
1N/A union {
1N/A nsc_data_t s_d;
1N/A char s_b[8192];
1N/A } space;
1N/A nsc_data_t *sptr;
1N/A int ndata;
1N/A int adata;
1N/A struct hostent *resptr = NULL;
1N/A
1N/A if (addr == NULL) {
1N/A if (h_errnop)
1N/A *h_errnop = HOST_NOT_FOUND;
1N/A return (NULL);
1N/A }
1N/A
1N/A ndata = sizeof (space);
1N/A adata = length + sizeof (nsc_call_t) + 1;
1N/A sptr = &space.s_d;
1N/A
1N/A space.s_d.nsc_call.nsc_callnumber = GETHOSTBYADDR;
1N/A space.s_d.nsc_call.nsc_u.addr.a_type = type;
1N/A space.s_d.nsc_call.nsc_u.addr.a_length = length;
1N/A (void) memcpy(space.s_d.nsc_call.nsc_u.addr.a_data, addr, length);
1N/A
1N/A switch (_nsc_trydoorcall(&sptr, &ndata, &adata)) {
1N/A case SUCCESS: /* positive cache hit */
1N/A break;
1N/A case NOTFOUND: /* negative cache hit */
1N/A if (h_errnop)
1N/A *h_errnop = space.s_d.nsc_ret.nsc_errno;
1N/A return (NULL);
1N/A default:
1N/A return ((struct hostent *)_switch_gethostbyaddr_r(addr,
1N/A length, type, result, buffer, buflen, h_errnop));
1N/A }
1N/A
1N/A resptr = process_gethost(result, buffer, buflen, h_errnop, sptr);
1N/A
1N/A /*
1N/A * check if doors realloced buffer underneath of us....
1N/A * munmap it or suffer a memory leak
1N/A */
1N/A
1N/A if (sptr != &space.s_d) {
1N/A munmap((char *)sptr, ndata); /* return memory */
1N/A }
1N/A
1N/A return (resptr);
1N/A
1N/A}
1N/A
1N/A#if !defined(_LP64)
1N/A
1N/Astatic struct hostent *
1N/Aprocess_gethost(struct hostent *result, char *buffer, int buflen,
1N/A int *h_errnop, nsc_data_t *sptr)
1N/A{
1N/A int i;
1N/A
1N/A char *fixed;
1N/A
1N/A fixed = (char *)(((int)buffer +3) & ~3);
1N/A buflen -= fixed - buffer;
1N/A buffer = fixed;
1N/A
1N/A if (buflen + sizeof (struct hostent)
1N/A < sptr->nsc_ret.nsc_bufferbytesused) {
1N/A /*
1N/A * no enough space allocated by user
1N/A */
1N/A errno = ERANGE;
1N/A if (h_errnop)
1N/A *h_errnop = HOST_NOT_FOUND;
1N/A return (NULL);
1N/A }
1N/A
1N/A (void) memcpy(buffer,
1N/A sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent),
1N/A sptr->nsc_ret.nsc_bufferbytesused - sizeof (struct hostent));
1N/A
1N/A sptr->nsc_ret.nsc_u.hst.h_name += (int)buffer;
1N/A sptr->nsc_ret.nsc_u.hst.h_aliases =
1N/A (char **)((char *)sptr->nsc_ret.nsc_u.hst.h_aliases + (int)buffer);
1N/A sptr->nsc_ret.nsc_u.hst.h_addr_list =
1N/A (char **)((char *)sptr->nsc_ret.nsc_u.hst.h_addr_list +
1N/A (int)buffer);
1N/A for (i = 0; sptr->nsc_ret.nsc_u.hst.h_aliases[i]; i++) {
1N/A sptr->nsc_ret.nsc_u.hst.h_aliases[i] += (int)buffer;
1N/A }
1N/A for (i = 0; sptr->nsc_ret.nsc_u.hst.h_addr_list[i]; i++) {
1N/A sptr->nsc_ret.nsc_u.hst.h_addr_list[i] += (int)buffer;
1N/A }
1N/A
1N/A *result = sptr->nsc_ret.nsc_u.hst;
1N/A
1N/A return (result);
1N/A}
1N/A
1N/A#else /* _LP64 */
1N/A
1N/A#define RNDUP(buf, n) (((uintptr_t)buf + n - 1l) & ~(n - 1l))
1N/A
1N/Astatic struct hostent *
1N/Aprocess_gethost(struct hostent *result, char *buffer, int buflen,
1N/A int *h_errnop, nsc_data_t *sptr)
1N/A{
1N/A char *fixed;
1N/A char *dest;
1N/A char *start;
1N/A char **aliaseslist;
1N/A char **addrlist;
1N/A int *alias;
1N/A int *address;
1N/A size_t strs;
1N/A int numaliases;
1N/A int numaddrs;
1N/A int i;
1N/A
1N/A fixed = (char *)RNDUP(buffer, sizeof (char *));
1N/A buflen -= fixed - buffer;
1N/A buffer = fixed;
1N/A
1N/A if (buflen < 0) {
1N/A /* no enough space allocated by user */
1N/A errno = ERANGE;
1N/A if (h_errnop)
1N/A *h_errnop = HOST_NOT_FOUND;
1N/A return (NULL);
1N/A }
1N/A
1N/A /* find out whether the user has provided sufficient space */
1N/A
1N/A start = sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent32);
1N/A strs = 1 + strlen(sptr->nsc_ret.nsc_u.hst.h_name + start);
1N/A alias = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_aliases);
1N/A for (numaliases = 0; alias[numaliases]; numaliases++)
1N/A strs += 1 + strlen(start + alias[numaliases]);
1N/A strs = RNDUP(strs, sizeof (int));
1N/A strs += sizeof (char *) * (numaliases + 1);
1N/A address = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_addr_list);
for (numaddrs = 0; address[numaddrs]; numaddrs++)
strs += RNDUP(sptr->nsc_ret.nsc_u.hst.h_length, sizeof (int));
strs += sizeof (char *) * (numaddrs + 1);
if (buflen < strs) {
/* no enough space allocated by user */
errno = ERANGE;
if (h_errnop)
*h_errnop = HOST_NOT_FOUND;
return (NULL);
}
/*
* allocat the h_aliases list and the h_addr_list first to align 'em.
*/
dest = buffer;
aliaseslist = (char **)dest;
dest += sizeof (char *) * (numaliases + 1);
addrlist = (char **)dest;
dest += sizeof (char *) * (numaddrs + 1);
/* fill out h_name */
start = sptr->nsc_ret.nsc_u.buff + sizeof (struct hostent32);
(void) strcpy(dest, sptr->nsc_ret.nsc_u.hst.h_name + start);
strs = 1 + strlen(sptr->nsc_ret.nsc_u.hst.h_name + start);
result->h_name = dest;
dest += strs;
/*
* fill out the h_aliases list
*/
for (i = 0; i < numaliases; i++) {
alias = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_aliases);
(void) strcpy(dest, start + alias[i]);
strs = 1 + strlen(start + alias[i]);
aliaseslist[i] = dest;
dest += strs;
}
aliaseslist[i] = 0; /* null term ptr chain */
result->h_aliases = aliaseslist;
/*
* fill out the h_addr list
*/
dest = (char *)RNDUP(dest, sizeof (int));
for (i = 0; i < numaddrs; i++) {
address = (int *)(start + sptr->nsc_ret.nsc_u.hst.h_addr_list);
(void) memcpy(dest, start + address[i],
sptr->nsc_ret.nsc_u.hst.h_length);
strs = sptr->nsc_ret.nsc_u.hst.h_length;
addrlist[i] = dest;
dest += strs;
dest = (char *)RNDUP(dest, sizeof (int));
}
addrlist[i] = 0; /* null term ptr chain */
result->h_addr_list = addrlist;
result->h_length = sptr->nsc_ret.nsc_u.hst.h_length;
result->h_addrtype = sptr->nsc_ret.nsc_u.hst.h_addrtype;
return (result);
}
#endif /* _LP64 */
#endif /* PIC */