xref: /onnv-gate/usr/src/lib/libc/port/gen/nss_dbdefs.c (revision 11411:c2fe1bf96826)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52830Sdjl  * Common Development and Distribution License (the "License").
62830Sdjl  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
213864Sraf 
220Sstevel@tonic-gate /*
238765SMilan.Jurik@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
276812Sraf #include "lint.h"
282830Sdjl #include <mtlib.h>
290Sstevel@tonic-gate #include <ctype.h>
300Sstevel@tonic-gate #include <stdio.h>
310Sstevel@tonic-gate #include <stdlib.h>
320Sstevel@tonic-gate #include <string.h>
330Sstevel@tonic-gate #include <nss_dbdefs.h>
340Sstevel@tonic-gate #include <limits.h>
352830Sdjl #include <dlfcn.h>
362830Sdjl #include <link.h>
372830Sdjl #include <thread.h>
383864Sraf #include <atomic.h>
392830Sdjl /* headers for key2str/str2key routines */
402830Sdjl #include <sys/ethernet.h>
412830Sdjl #include <exec_attr.h>
422830Sdjl #include <grp.h>
432830Sdjl 
442830Sdjl /*
452830Sdjl  * functions in nss_dbdefs.c deal more with the mechanics of
462830Sdjl  * the data structures like nss_XbyY_args_t and the interaction
472830Sdjl  * with the packed buffers etc.  versus the mechanics of the
482830Sdjl  * actual policy component operations such as nss_search sequencing.
492830Sdjl  */
500Sstevel@tonic-gate 
510Sstevel@tonic-gate /*
520Sstevel@tonic-gate  * ALIGN? is there an official definition of this?
530Sstevel@tonic-gate  * We use sizeof(long) to cover what we want
540Sstevel@tonic-gate  * for both the 32-bit world and 64-bit world.
550Sstevel@tonic-gate  */
560Sstevel@tonic-gate 
570Sstevel@tonic-gate #define	ALIGN(x) ((((long)(x)) + sizeof (long) - 1) & ~(sizeof (long) - 1))
580Sstevel@tonic-gate 
590Sstevel@tonic-gate nss_XbyY_buf_t *
_nss_XbyY_buf_alloc(int struct_size,int buffer_size)600Sstevel@tonic-gate _nss_XbyY_buf_alloc(int struct_size, int buffer_size)
610Sstevel@tonic-gate {
620Sstevel@tonic-gate 	nss_XbyY_buf_t	*b;
630Sstevel@tonic-gate 
640Sstevel@tonic-gate 	/* Use one malloc for dbargs, result struct and buffer */
650Sstevel@tonic-gate 	b = (nss_XbyY_buf_t *)
665477Sandra 	    malloc(ALIGN(sizeof (*b)) + struct_size + buffer_size);
670Sstevel@tonic-gate 	if (b == 0) {
680Sstevel@tonic-gate 		return (0);
690Sstevel@tonic-gate 	}
700Sstevel@tonic-gate 	b->result = (void *)ALIGN(&b[1]);
710Sstevel@tonic-gate 	b->buffer = (char *)(b->result) + struct_size;
720Sstevel@tonic-gate 	b->buflen = buffer_size;
730Sstevel@tonic-gate 	return (b);
740Sstevel@tonic-gate }
750Sstevel@tonic-gate 
760Sstevel@tonic-gate void
_nss_XbyY_buf_free(nss_XbyY_buf_t * b)770Sstevel@tonic-gate _nss_XbyY_buf_free(nss_XbyY_buf_t *b)
780Sstevel@tonic-gate {
790Sstevel@tonic-gate 	if (b != 0) {
800Sstevel@tonic-gate 		free(b);
810Sstevel@tonic-gate 	}
820Sstevel@tonic-gate }
830Sstevel@tonic-gate 
840Sstevel@tonic-gate /* === Comment:  used by fget{gr,pw,sp}ent */
850Sstevel@tonic-gate /* ==== Should do ye olde syslog()ing of suspiciously long lines */
860Sstevel@tonic-gate 
870Sstevel@tonic-gate void
_nss_XbyY_fgets(FILE * f,nss_XbyY_args_t * b)880Sstevel@tonic-gate _nss_XbyY_fgets(FILE *f, nss_XbyY_args_t *b)
890Sstevel@tonic-gate {
900Sstevel@tonic-gate 	char		buf[LINE_MAX];
910Sstevel@tonic-gate 	int		len, parsestat;
920Sstevel@tonic-gate 
930Sstevel@tonic-gate 	if (fgets(buf, LINE_MAX, f) == 0) {
940Sstevel@tonic-gate 		/* End of file */
950Sstevel@tonic-gate 		b->returnval = 0;
960Sstevel@tonic-gate 		b->erange    = 0;
970Sstevel@tonic-gate 		return;
980Sstevel@tonic-gate 	}
990Sstevel@tonic-gate 	len = (int)strlen(buf);
1000Sstevel@tonic-gate 	/* len >= 0 (otherwise we would have got EOF) */
1010Sstevel@tonic-gate 	if (buf[len - 1] != '\n') {
1020Sstevel@tonic-gate 		if ((len + 1) == LINE_MAX) {
1030Sstevel@tonic-gate 			/* Line too long for buffer; too bad */
1040Sstevel@tonic-gate 			while (fgets(buf, LINE_MAX, f) != 0 &&
1050Sstevel@tonic-gate 			    buf[strlen(buf) - 1] != '\n') {
1060Sstevel@tonic-gate 				;
1070Sstevel@tonic-gate 			}
1080Sstevel@tonic-gate 			b->returnval = 0;
1090Sstevel@tonic-gate 			b->erange    = 1;
1100Sstevel@tonic-gate 			return;
1110Sstevel@tonic-gate 		}
1120Sstevel@tonic-gate 		/* case where the file is not terminated with a Newline */
1130Sstevel@tonic-gate 		len++;
1140Sstevel@tonic-gate 	}
1150Sstevel@tonic-gate 	parsestat = (*b->str2ent)(buf, (len - 1), b->buf.result, b->buf.buffer,
1165477Sandra 	    b->buf.buflen);
1170Sstevel@tonic-gate 	if (parsestat == NSS_STR_PARSE_ERANGE) {
1180Sstevel@tonic-gate 		b->returnval = 0;
1190Sstevel@tonic-gate 		b->erange    = 1;
1200Sstevel@tonic-gate 	} else if (parsestat == NSS_STR_PARSE_SUCCESS) {
1210Sstevel@tonic-gate 		b->returnval = b->buf.result;
1220Sstevel@tonic-gate 	}
1230Sstevel@tonic-gate }
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate /*
1260Sstevel@tonic-gate  * parse the aliases string into the buffer and if successful return
1270Sstevel@tonic-gate  * a char ** pointer to the beginning of the aliases.
1280Sstevel@tonic-gate  *
1290Sstevel@tonic-gate  * CAUTION: (instr, instr+lenstr) and (buffer, buffer+buflen) are
1300Sstevel@tonic-gate  * non-intersecting memory areas. Since this is an internal interface,
1310Sstevel@tonic-gate  * we should be able to live with that.
1320Sstevel@tonic-gate  */
1330Sstevel@tonic-gate char **
_nss_netdb_aliases(const char * instr,int lenstr,char * buffer,int buflen)1340Sstevel@tonic-gate _nss_netdb_aliases(const char *instr, int lenstr, char *buffer, int buflen)
1350Sstevel@tonic-gate 	/* "instr" is the beginning of the aliases string */
1360Sstevel@tonic-gate 	/* "buffer" has the return val for success */
1370Sstevel@tonic-gate 	/* "buflen" is the length of the buffer available for aliases */
1380Sstevel@tonic-gate {
1390Sstevel@tonic-gate 	/*
1400Sstevel@tonic-gate 	 * Build the alias-list in the start of the buffer, and copy
1410Sstevel@tonic-gate 	 * the strings to the end of the buffer.
1420Sstevel@tonic-gate 	 */
1430Sstevel@tonic-gate 	const char
1440Sstevel@tonic-gate 		*instr_limit	= instr + lenstr;
1450Sstevel@tonic-gate 	char	*copyptr	= buffer + buflen;
1460Sstevel@tonic-gate 	char	**aliasp	= (char **)ROUND_UP(buffer, sizeof (*aliasp));
1470Sstevel@tonic-gate 	char	**alias_start	= aliasp;
1480Sstevel@tonic-gate 	int	nstrings	= 0;
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	for (;;) {
1510Sstevel@tonic-gate 		const char	*str_start;
1520Sstevel@tonic-gate 		size_t		str_len;
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 		while (instr < instr_limit && isspace(*instr)) {
1550Sstevel@tonic-gate 			instr++;
1560Sstevel@tonic-gate 		}
1570Sstevel@tonic-gate 		if (instr >= instr_limit || *instr == '#') {
1580Sstevel@tonic-gate 			break;
1590Sstevel@tonic-gate 		}
1600Sstevel@tonic-gate 		str_start = instr;
1610Sstevel@tonic-gate 		while (instr < instr_limit && !isspace(*instr)) {
1620Sstevel@tonic-gate 			instr++;
1630Sstevel@tonic-gate 		}
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 		++nstrings;
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate 		str_len = instr - str_start;
1680Sstevel@tonic-gate 		copyptr -= str_len + 1;
1690Sstevel@tonic-gate 		if (copyptr <= (char *)(&aliasp[nstrings + 1])) {
1700Sstevel@tonic-gate 			/* Has to be room for the pointer to */
1710Sstevel@tonic-gate 			/* the alias we're about to add,   */
1720Sstevel@tonic-gate 			/* as well as the final NULL ptr.  */
1730Sstevel@tonic-gate 			return (0);
1740Sstevel@tonic-gate 		}
1750Sstevel@tonic-gate 		*aliasp++ = copyptr;
1760Sstevel@tonic-gate 		(void) memcpy(copyptr, str_start, str_len);
1770Sstevel@tonic-gate 		copyptr[str_len] = '\0';
1780Sstevel@tonic-gate 	}
1790Sstevel@tonic-gate 	*aliasp++ = 0;
1800Sstevel@tonic-gate 	return (alias_start);
1810Sstevel@tonic-gate }
1822830Sdjl 
1832830Sdjl 
1843099Smichen extern nss_status_t process_cstr(const char *, int, struct nss_groupsbymem *);
1853099Smichen 
1862830Sdjl /*
1872830Sdjl  * pack well known getXbyY keys to packed buffer prior to the door_call
1882830Sdjl  * to nscd.  Some consideration is given to ordering the tests based on
1892830Sdjl  * usage.  Note: buf is nssuint_t aligned.
1902830Sdjl  */
1912830Sdjl 
1922830Sdjl typedef struct {
1932830Sdjl 	const char	*name;		/* NSS_DBNAM_* */
1942830Sdjl 	const char	*defconf;	/* NSS_DEFCONF_* */
1952830Sdjl 	const char	*initfn;	/* init function name */
1962830Sdjl 	const char	*strfn;		/* str2X function name */
1972830Sdjl 	const char	*cstrfn;	/* cstr2X function name */
1984046Smichen 	void		*initfnp;	/* init function pointer */
1994046Smichen 	void		*strfnp;	/* str2X function pointer */
2002830Sdjl 	uint32_t	dbop;		/* NSS_DBOP_* */
2012830Sdjl 	const char	*tostr;		/* key2str cvt str */
2022830Sdjl } getXbyY_to_dbop_t;
2032830Sdjl 
2042830Sdjl #define	NSS_MK_GETXYDBOP(x, y, f, e)	\
2052830Sdjl 	{ NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" f, "str2" f, \
2064046Smichen 		NULL, NULL, NULL, NSS_DBOP_##x##_##y, (e) }
2072830Sdjl 
2082830Sdjl #define	NSS_MK_GETXYDBOPA(x, a, f, e)	\
2092830Sdjl 	{ NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" f, "str2" f, \
2104046Smichen 		NULL, NULL, NULL, NSS_DBOP_##a, (e) }
2112830Sdjl 
2122830Sdjl #define	NSS_MK_GETXYDBOPB(x, b, a, f, s, e)	\
2132830Sdjl 	{ NSS_DBNAM_##x, NSS_DEFCONF_##b, "_nss_initf_" f, s,  \
2144046Smichen 		NULL, NULL, NULL, NSS_DBOP_##a, (e) }
2152830Sdjl 
2162830Sdjl #define	NSS_MK_GETXYDBOPC(x, a, f, s, e)	\
2172830Sdjl 	{ NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" f, s, \
2184046Smichen 		NULL, NULL, NULL, NSS_DBOP_##x##_##a, (e) }
2192830Sdjl 
2202830Sdjl #define	NSS_MK_GETXYDBOPD(x, y, i, f, e)	\
2212830Sdjl 	{ NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" i, "str2" f, \
2224046Smichen 		NULL, NULL, NULL, NSS_DBOP_##x##_##y, (e) }
2232830Sdjl 
2242830Sdjl #define	NSS_MK_GETXYDBOPCSTR(x, a, f, s, e)	\
2252830Sdjl 	{ NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" f, s, \
2264046Smichen 		"process_cstr", NULL, NULL, NSS_DBOP_##x##_##a, (e) }
2272830Sdjl 
2282830Sdjl /*
2292830Sdjl  * The getXbyY_to_dbop structure is hashed on first call in order to
2302830Sdjl  * reduce the search time for the well known getXbyY operations.
2312830Sdjl  * A binary search was not fast enough.  There were on average
2322830Sdjl  * 3-4 tests (strcmps) per getXbyY call.
2332830Sdjl  *
2342830Sdjl  * DBOP_PRIME_HASH must be a prime number (reasonably small) but that
2352830Sdjl  * is sufficient to uniquely map the entries in the following table
2362830Sdjl  * without collision.
2372830Sdjl  *
2382830Sdjl  * The DBOP_PRIME_HASH was selected as the smallest hash value
2392830Sdjl  * for this table without collisions. Changing this table WILL
2402830Sdjl  * necessitate re-testing for possible collisions.
2412830Sdjl  */
2422830Sdjl 
2438765SMilan.Jurik@Sun.COM #define	DBOP_PRIME_HASH		227
2442830Sdjl #define	DBOP_HASH_TAG		0xf0000000
2452830Sdjl static int getXbyYdbopHASH[DBOP_PRIME_HASH] = { 0 };
2462830Sdjl static mutex_t getXbydbop_hash_lock = DEFAULTMUTEX;
2472830Sdjl static int getXbyYdbop_hashed = 0;
2482830Sdjl 
2498765SMilan.Jurik@Sun.COM /*
2508765SMilan.Jurik@Sun.COM  * If the size of getXbyY_to_dbop[] is changed then hash function must be
2518765SMilan.Jurik@Sun.COM  * corrected to be without collisions in nss_dbop_search().
2528765SMilan.Jurik@Sun.COM  */
2532830Sdjl static getXbyY_to_dbop_t getXbyY_to_dbop[] = {
2542830Sdjl 	/* NSS_MK_GETXYDBOP(ALIASES, ?, ?), */
2552830Sdjl 	NSS_MK_GETXYDBOPD(AUDITUSER, BYNAME, "auuser", "audituser", "n"),
2562830Sdjl 	NSS_MK_GETXYDBOP(AUTHATTR, BYNAME, "authattr", "n"),
2572830Sdjl 	/* NSS_MK_GETXYDBOP(AUTOMOUNT, ?, ?), */
2582830Sdjl 	NSS_MK_GETXYDBOP(BOOTPARAMS, BYNAME, "bootparams", "n"),
2592830Sdjl 	NSS_MK_GETXYDBOPC(ETHERS, HOSTTON, "ethers", "str2ether", "n"),
2602830Sdjl 	NSS_MK_GETXYDBOPC(ETHERS, NTOHOST, "ethers", "str2ether", "e"),
2612830Sdjl 	NSS_MK_GETXYDBOP(EXECATTR, BYNAME, "execattr", "A"),
2622830Sdjl 	NSS_MK_GETXYDBOP(EXECATTR, BYID, "execattr", "A"),
2632830Sdjl 	NSS_MK_GETXYDBOP(EXECATTR, BYNAMEID, "execattr", "A"),
2642830Sdjl 	NSS_MK_GETXYDBOP(GROUP, BYNAME, "group", "n"),
2652830Sdjl 	NSS_MK_GETXYDBOP(GROUP, BYGID, "group", "g"),
2662830Sdjl 	NSS_MK_GETXYDBOPCSTR(GROUP, BYMEMBER, "group", "str2group", "I"),
2672830Sdjl 	NSS_MK_GETXYDBOPC(HOSTS, BYNAME, "hosts", "str2hostent", "n"),
2682830Sdjl 	NSS_MK_GETXYDBOPC(HOSTS, BYADDR, "hosts", "str2hostent", "h"),
2692830Sdjl 	NSS_MK_GETXYDBOPC(IPNODES, BYNAME, "ipnodes", "str2hostent", "i"),
2702830Sdjl 	NSS_MK_GETXYDBOPC(IPNODES, BYADDR, "ipnodes", "str2hostent", "h"),
2712830Sdjl 	NSS_MK_GETXYDBOP(NETGROUP, IN, "netgroup", "t"),
2722830Sdjl 	NSS_MK_GETXYDBOP(NETGROUP, SET, "netgroup", "T"),
2732830Sdjl 	NSS_MK_GETXYDBOPC(NETMASKS, BYNET, "netmasks", "str2addr", "n"),
2742830Sdjl 	NSS_MK_GETXYDBOPC(NETWORKS, BYNAME, "net", "str2netent", "n"),
2752830Sdjl 	NSS_MK_GETXYDBOPC(NETWORKS, BYADDR, "net", "str2netent", "a"),
2762830Sdjl 	NSS_MK_GETXYDBOP(PASSWD, BYNAME, "passwd", "n"),
2772830Sdjl 	NSS_MK_GETXYDBOP(PASSWD, BYUID, "passwd", "u"),
2782830Sdjl 	NSS_MK_GETXYDBOP(PRINTERS, BYNAME, "printers", "n"),
2792830Sdjl 	NSS_MK_GETXYDBOP(PROFATTR, BYNAME, "profattr", "n"),
2802830Sdjl 	NSS_MK_GETXYDBOP(PROJECT, BYNAME, "project", "n"),
2812830Sdjl 	NSS_MK_GETXYDBOP(PROJECT, BYID, "project", "p"),
2822830Sdjl 	NSS_MK_GETXYDBOPC(PROTOCOLS, BYNAME, "proto", "str2protoent", "n"),
2832830Sdjl 	NSS_MK_GETXYDBOPC(PROTOCOLS, BYNUMBER, "proto", "str2protoent", "N"),
2842830Sdjl 	NSS_MK_GETXYDBOPA(PUBLICKEY, KEYS_BYNAME, "publickey", "k"),
2852830Sdjl 	NSS_MK_GETXYDBOPC(RPC, BYNAME, "rpc", "str2rpcent", "n"),
2862830Sdjl 	NSS_MK_GETXYDBOPC(RPC, BYNUMBER, "rpc", "str2rpcent", "N"),
2872830Sdjl 	NSS_MK_GETXYDBOPC(SERVICES, BYNAME, "services", "str2servent", "s"),
2882830Sdjl 	NSS_MK_GETXYDBOPC(SERVICES, BYPORT, "services", "str2servent", "S"),
2892830Sdjl 	NSS_MK_GETXYDBOPB(SHADOW, PASSWD, PASSWD_BYNAME, "shadow",
2902830Sdjl 				"str2spwd", "n"),
2912830Sdjl 	NSS_MK_GETXYDBOPC(TSOL_RH, BYADDR, "tsol_rh", "str_to_rhstr", "h"),
2922830Sdjl 	NSS_MK_GETXYDBOPC(TSOL_TP, BYNAME, "tsol_tp", "str_to_tpstr", "n"),
2932830Sdjl 	NSS_MK_GETXYDBOPC(TSOL_ZC, BYNAME, "tsol_zc", "str_to_zcstr", "n"),
2942830Sdjl 	NSS_MK_GETXYDBOP(USERATTR, BYNAME, "userattr", "n"),
2952830Sdjl };
2962830Sdjl 
2972830Sdjl static int
nss_dbop_search(const char * name,uint32_t dbop)2982830Sdjl nss_dbop_search(const char *name, uint32_t dbop)
2992830Sdjl {
3002830Sdjl 	getXbyY_to_dbop_t *hptr;
3012830Sdjl 	int count = (sizeof (getXbyY_to_dbop) / sizeof (getXbyY_to_dbop_t));
3022830Sdjl 	uint32_t hval, g;
3032830Sdjl 	const char *cp;
3042830Sdjl 	int i, idx;
3058765SMilan.Jurik@Sun.COM 	static const uint32_t hbits_tst = 0xf0000000;
3062830Sdjl 
3072830Sdjl 	/* Uses a table size is known to have no collisions */
3082830Sdjl 	if (getXbyYdbop_hashed == 0) {
3092830Sdjl 		lmutex_lock(&getXbydbop_hash_lock);
3102830Sdjl 		if (getXbyYdbop_hashed == 0) {
3112830Sdjl 			for (i = 0; i < count; i++) {
3122830Sdjl 				cp = getXbyY_to_dbop[i].name;
3132830Sdjl 				hval = 0;
3142830Sdjl 				while (*cp) {
3152830Sdjl 					hval = (hval << 4) + *cp++;
3168765SMilan.Jurik@Sun.COM 					if ((g = (hval & hbits_tst)) != 0)
3172830Sdjl 						hval ^= g >> 24;
3182830Sdjl 					hval &= ~g;
3192830Sdjl 				}
3202830Sdjl 				hval += getXbyY_to_dbop[i].dbop;
3212830Sdjl 				hval %= DBOP_PRIME_HASH;
3222830Sdjl 				if (getXbyYdbopHASH[hval] != 0) {
3232830Sdjl 					/* hash table collision-see above */
3242830Sdjl 					lmutex_unlock(&getXbydbop_hash_lock);
3252830Sdjl 					return (-1);
3262830Sdjl 				}
3272830Sdjl 				getXbyYdbopHASH[hval] = i | DBOP_HASH_TAG;
3282830Sdjl 			}
3293864Sraf 			membar_producer();
3302830Sdjl 			getXbyYdbop_hashed = 1;
3312830Sdjl 		}
3322830Sdjl 		lmutex_unlock(&getXbydbop_hash_lock);
3332830Sdjl 	}
3343864Sraf 	membar_consumer();
3352830Sdjl 	cp = name;
3362830Sdjl 	hval = 0;
3372830Sdjl 	while (*cp) {
3382830Sdjl 		hval = (hval << 4) + *cp++;
3398765SMilan.Jurik@Sun.COM 		if ((g = (hval & hbits_tst)) != 0)
3402830Sdjl 			hval ^= g >> 24;
3412830Sdjl 		hval &= ~g;
3422830Sdjl 	}
3432830Sdjl 	hval += dbop;
3442830Sdjl 	hval %= DBOP_PRIME_HASH;
3452830Sdjl 	idx = getXbyYdbopHASH[hval];
3462830Sdjl 	if ((idx & DBOP_HASH_TAG) != DBOP_HASH_TAG)
3472830Sdjl 		return (-1);
3482830Sdjl 	idx &= ~DBOP_HASH_TAG;
3492830Sdjl 	if (idx >= count)
3502830Sdjl 		return (-1);
3512830Sdjl 	hptr = &getXbyY_to_dbop[idx];
3522830Sdjl 	if (hptr->dbop != dbop || strcmp(name, hptr->name) != 0)
3532830Sdjl 		return (-1);
3542830Sdjl 	return (idx);
3552830Sdjl }
3562830Sdjl 
3572830Sdjl /*
3582830Sdjl  * nss_pack_key2str
3592830Sdjl  * Private key to string packing function for getXbyY routines
3602830Sdjl  * This routine performs a printf like parse over the argument
3612830Sdjl  * key, given a string of items to pack and assembles the key in
3622830Sdjl  * the packed structure.  This routine is called (currently) by
3632830Sdjl  * nss_default_key2str, but will be used by other external
3642830Sdjl  * APIs in the future.
3652830Sdjl  *
3662830Sdjl  * buffer - Start of the key buffer location [in packed buffer]
3672830Sdjl  * length - Length of key buffer component
3682830Sdjl  * Key offsets are relative to start of key buffer location.
3692830Sdjl  *
3702830Sdjl  * Pack fields			Key
3712830Sdjl  *   key.name			n
3722830Sdjl  *   key.number			N
3732830Sdjl  *   key.uid			u
3742830Sdjl  *   key.gid			g
3752830Sdjl  *   key.hostaddr		h
3762830Sdjl  *   key.ipnode			i
3772830Sdjl  *   key.projid			p
3782830Sdjl  *   key.serv(name)		s
3792830Sdjl  *   key.serv(port)		S
3802830Sdjl  *   key.ether			e
3812830Sdjl  *   key.pkey			k
3822830Sdjl  *   key.netaddr		a
3832830Sdjl  *   key.attrp			A
3842830Sdjl  *   groupsbymember		I
3852830Sdjl  *   innetgr_args		t
3862830Sdjl  *   setnetgr_args		T
3872830Sdjl  */
3882830Sdjl 
3892830Sdjl /*ARGSUSED*/
3902830Sdjl static nss_status_t
nss_pack_key2str(void * buffer,size_t length,nss_XbyY_args_t * arg,const char * dbname,int dbop,size_t * rlen,const char * typestr)3912830Sdjl nss_pack_key2str(void *buffer, size_t length, nss_XbyY_args_t *arg,
3922830Sdjl 	const char *dbname, int dbop, size_t *rlen, const char *typestr)
3932830Sdjl {
3942830Sdjl 	int				i, j;
3952830Sdjl 	size_t				len, len2, len3, len4, len5, slop;
3962830Sdjl 	nssuint_t 			*uptr, offv, offc;
3972830Sdjl 	struct nss_setnetgrent_args	*sng;
3982830Sdjl 	struct nss_innetgr_args		*ing;
3992830Sdjl 	struct nss_groupsbymem		*gbm;
4002830Sdjl 	char				**cv, *dptr;
4012830Sdjl 	nss_pnetgr_t			*pptr;
4022830Sdjl 	_priv_execattr			*pe;
4032830Sdjl 
4042830Sdjl 	if (buffer == NULL || length == 0 || arg == NULL ||
4052830Sdjl 	    dbname == NULL || rlen == NULL || typestr == NULL)
4062830Sdjl 		return (NSS_ERROR);
4072830Sdjl 
4082830Sdjl 	while (typestr && *typestr) {
4092830Sdjl 		switch (*typestr++) {
4102830Sdjl 		case 'n':
4112830Sdjl 			if (arg->key.name == NULL)
4122830Sdjl 				return (NSS_NOTFOUND);
4132830Sdjl 			len = strlen(arg->key.name) + 1;
4142830Sdjl 			if (len >= length)
4152830Sdjl 				return (NSS_ERROR);
4162830Sdjl 			(void) strlcpy(buffer, arg->key.name, len);
4172830Sdjl 			*rlen = len;
4182830Sdjl 			break;
4192830Sdjl 		case 'N':
4202830Sdjl 			len = sizeof (nssuint_t);
4212830Sdjl 			if (len >= length)
4222830Sdjl 				return (NSS_ERROR);
4232830Sdjl 			*(nssuint_t *)buffer = (nssuint_t)arg->key.number;
4242830Sdjl 			*rlen = len;
4252830Sdjl 			break;
4262830Sdjl 		case 'u':
4272830Sdjl 			len = sizeof (nssuint_t);
4282830Sdjl 			if (len >= length)
4292830Sdjl 				return (NSS_ERROR);
4302830Sdjl 			*(nssuint_t *)buffer = (nssuint_t)arg->key.uid;
4312830Sdjl 			*rlen = len;
4322830Sdjl 			break;
4332830Sdjl 		case 'g':
4342830Sdjl 			len = sizeof (nssuint_t);
4352830Sdjl 			if (len >= length)
4362830Sdjl 				return (NSS_ERROR);
4372830Sdjl 			*(nssuint_t *)buffer = (nssuint_t)arg->key.gid;
4382830Sdjl 			*rlen = len;
4392830Sdjl 			break;
4402830Sdjl 		case 'h':
4412830Sdjl 			if (arg->key.hostaddr.addr == NULL)
4422830Sdjl 				return (-1);
4432830Sdjl 			len = arg->key.hostaddr.len;
4442830Sdjl 			len = ROUND_UP(len, sizeof (nssuint_t));
4452830Sdjl 			len2 = (sizeof (nssuint_t) * 2) + len;
4462830Sdjl 			if (len2 >= length)
4472830Sdjl 				return (NSS_ERROR);
4482830Sdjl 			*(nssuint_t *)buffer =
4492830Sdjl 			    (nssuint_t)arg->key.hostaddr.len;
4502830Sdjl 			buffer = (void *)((char *)buffer + sizeof (nssuint_t));
4512830Sdjl 			*(nssuint_t *)buffer =
4522830Sdjl 			    (nssuint_t)arg->key.hostaddr.type;
4532830Sdjl 			buffer = (void *)((char *)buffer + sizeof (nssuint_t));
4542830Sdjl 			(void) memcpy(buffer, arg->key.hostaddr.addr,
4555477Sandra 			    arg->key.hostaddr.len);
4562830Sdjl 			*rlen = len2;
4572830Sdjl 			break;
4582830Sdjl 		case 'i':
4592830Sdjl 			if (arg->key.ipnode.name == NULL)
4602830Sdjl 				return (NSS_NOTFOUND);
4612830Sdjl 			len = strlen(arg->key.ipnode.name) + 1;
4622830Sdjl 			len = ROUND_UP(len, sizeof (nssuint_t));
4632830Sdjl 			len2 = (sizeof (nssuint_t) * 2) + len;
4642830Sdjl 			if (len2 >= length)
4652830Sdjl 				return (NSS_ERROR);
4662830Sdjl 			*(nssuint_t *)buffer =
4672830Sdjl 			    (nssuint_t)arg->key.ipnode.af_family;
4682830Sdjl 			buffer = (void *)((char *)buffer + sizeof (nssuint_t));
4692830Sdjl 			*(nssuint_t *)buffer =
4702830Sdjl 			    (nssuint_t)arg->key.ipnode.flags;
4712830Sdjl 			buffer = (void *)((char *)buffer + sizeof (nssuint_t));
4722830Sdjl 			(void) strlcpy(buffer, arg->key.ipnode.name, len);
4732830Sdjl 			*rlen = len2;
4742830Sdjl 			break;
4752830Sdjl 		case 'p':
4762830Sdjl 			len = sizeof (nssuint_t);
4772830Sdjl 			if (len >= length)
4782830Sdjl 				return (NSS_ERROR);
4792830Sdjl 			*(nssuint_t *)buffer = (nssuint_t)arg->key.projid;
4802830Sdjl 			*rlen = len;
4812830Sdjl 			break;
4822830Sdjl 		case 's':
4832830Sdjl 			if (arg->key.serv.serv.name == NULL)
4842830Sdjl 				return (NSS_NOTFOUND);
4852830Sdjl 			len = strlen(arg->key.serv.serv.name) + 1;
4862830Sdjl 			len2 = 1;
4872830Sdjl 			if (arg->key.serv.proto != NULL)
4882830Sdjl 				len2 += strlen(arg->key.serv.proto);
4892830Sdjl 			len3 = len + len2;
4902830Sdjl 			len3 = ROUND_UP(len3, sizeof (nssuint_t));
4912830Sdjl 			if (len3 >= length)
4922830Sdjl 				return (NSS_ERROR);
4932830Sdjl 			(void) strlcpy(buffer, arg->key.serv.serv.name, len);
4942830Sdjl 			buffer = (void *)((char *)buffer + len);
4952830Sdjl 			if (len2 > 1)
4962830Sdjl 				(void) strlcpy(buffer, arg->key.serv.proto,
4975477Sandra 				    len2);
4982830Sdjl 			else
4992830Sdjl 				*(char *)buffer = '\0';
5002830Sdjl 			*rlen = len3;
5012830Sdjl 			break;
5022830Sdjl 		case 'S':
5032830Sdjl 			len2 = 0;
5042830Sdjl 			if (arg->key.serv.proto != NULL)
5052830Sdjl 				len2 = strlen(arg->key.serv.proto) + 1;
5062830Sdjl 			len = sizeof (nssuint_t) + len2;
5072830Sdjl 			if (len >= length)
5082830Sdjl 				return (NSS_ERROR);
5092830Sdjl 			uptr = (nssuint_t *)buffer;
5102830Sdjl 			*uptr++ = (nssuint_t)arg->key.serv.serv.port;
5112830Sdjl 			if (len2) {
5122830Sdjl 				(void) strlcpy((char *)uptr,
5135477Sandra 				    arg->key.serv.proto, len2);
5142830Sdjl 			}
5152830Sdjl 			*rlen = len;
5162830Sdjl 			break;
5172830Sdjl 		case 'e':
5182830Sdjl 			if (arg->key.ether == NULL)
5192830Sdjl 				return (NSS_NOTFOUND);
5202830Sdjl 			len = sizeof (struct ether_addr);
5212830Sdjl 			len = ROUND_UP(len, sizeof (nssuint_t));
5222830Sdjl 			if (len >= length)
5232830Sdjl 				return (NSS_ERROR);
5242830Sdjl 			*(struct ether_addr *)buffer =
5255477Sandra 			    *(struct ether_addr *)arg->key.ether;
5262830Sdjl 			*rlen = len;
5272830Sdjl 			break;
5282830Sdjl 		case 'k':
5292830Sdjl 			if (arg->key.pkey.name == NULL ||
5302830Sdjl 			    arg->key.pkey.keytype == NULL)
5312830Sdjl 				return (NSS_NOTFOUND);
5322830Sdjl 			len = strlen(arg->key.pkey.name) + 1;
5332830Sdjl 			len2 = strlen(arg->key.pkey.keytype) + 1;
5342830Sdjl 			len3 = len + len2;
5352830Sdjl 			len3 = ROUND_UP(len3, sizeof (nssuint_t));
5362830Sdjl 			if (len3 >= length)
5372830Sdjl 				return (NSS_ERROR);
5382830Sdjl 			(void) strlcpy(buffer, arg->key.pkey.name, len);
5392830Sdjl 			buffer = (void *)((char *)buffer + len);
5402830Sdjl 			(void) strlcpy(buffer, arg->key.pkey.keytype, len2);
5412830Sdjl 			*rlen = len3;
5422830Sdjl 			break;
5432830Sdjl 		case 'a':
5442830Sdjl 			uptr = (nssuint_t *)buffer;
5452830Sdjl 			len = sizeof (nssuint_t) * 2;
5462830Sdjl 			if (len >= length)
5472830Sdjl 				return (NSS_ERROR);
5482830Sdjl 			*uptr++ = (nssuint_t)arg->key.netaddr.net;
5492830Sdjl 			*uptr++ = (nssuint_t)arg->key.netaddr.type;
5502830Sdjl 			*rlen = len;
5512830Sdjl 			break;
5522830Sdjl 		case 'A':
5532830Sdjl 			pe = (_priv_execattr *)(arg->key.attrp);
5542830Sdjl 			if (pe == NULL)
5552830Sdjl 				return (NSS_NOTFOUND);
5562830Sdjl 			/* for search flag */
5572830Sdjl 			len = sizeof (nssuint_t);
5582830Sdjl 			/* for sizeof (_priv_execattr) static buffer */
5592830Sdjl 			/* Plus lots of slop just in case... */
5602830Sdjl 			slop = sizeof (nssuint_t) * 16;
5612830Sdjl 			len += slop;
5622830Sdjl 
5632830Sdjl 			len2 = len3 = len4 = len5 = 1;
5642830Sdjl 			if (pe->name != NULL)
5652830Sdjl 				len2 = strlen(pe->name) + 1;
5662830Sdjl 			if (pe->type != NULL)
5672830Sdjl 				len3 = strlen(pe->type) + 1;
5682830Sdjl 			if (pe->id != NULL)
5692830Sdjl 				len4 = strlen(pe->id) + 1;
5702830Sdjl 			if (pe->policy != NULL)
5712830Sdjl 				len5 = strlen(pe->policy) + 1;
5722830Sdjl 			/* head_exec, prev_exec - are client side only... */
5732830Sdjl 			len += len2 + len3 + len4 + len5;
5742830Sdjl 			len = ROUND_UP(len, sizeof (nssuint_t));
5752830Sdjl 			if (len >= length)
5762830Sdjl 				return (NSS_ERROR);
5772830Sdjl 			(void) memset((void *)buffer, 0, slop);
5782830Sdjl 			uptr = (nssuint_t *)((void *)((char *)buffer + slop));
5792830Sdjl 			*uptr++ = (nssuint_t)pe->search_flag;
5802830Sdjl 			dptr = (char *)uptr;
5812830Sdjl 			if (len2 == 1)
5822830Sdjl 				*dptr++ = '\0';
5832830Sdjl 			else {
5842830Sdjl 				(void) strlcpy(dptr, pe->name, len2);
5852830Sdjl 				dptr += len2;
5862830Sdjl 			}
5872830Sdjl 			if (len3 == 1)
5882830Sdjl 				*dptr++ = '\0';
5892830Sdjl 			else {
5902830Sdjl 				(void) strlcpy(dptr, pe->type, len3);
5912830Sdjl 				dptr += len3;
5922830Sdjl 			}
5932830Sdjl 			if (len4 == 1)
5942830Sdjl 				*dptr++ = '\0';
5952830Sdjl 			else {
5962830Sdjl 				(void) strlcpy(dptr, pe->id, len4);
5972830Sdjl 				dptr += len4;
5982830Sdjl 			}
5992830Sdjl 			if (len5 == 1)
6002830Sdjl 				*dptr++ = '\0';
6012830Sdjl 			else
6022830Sdjl 				(void) strlcpy(dptr, pe->policy, len5);
6032830Sdjl 			*rlen = len;
6042830Sdjl 			break;
6052830Sdjl 		case 'I':
6062830Sdjl 			gbm = (struct nss_groupsbymem *)arg;
6072830Sdjl 			if (gbm->username == NULL)
6082830Sdjl 				return (NSS_NOTFOUND);
6092830Sdjl 			len = strlen(gbm->username) + 1;
6102830Sdjl 			len2 = sizeof (nssuint_t) * 4;
6112830Sdjl 			len2 += ROUND_UP(len, sizeof (nssuint_t));
6122830Sdjl 			if (len2 >= length)
6132830Sdjl 				return (NSS_ERROR);
6142830Sdjl 			uptr = (nssuint_t *)buffer;
6152830Sdjl 			*uptr++ = (nssuint_t)gbm->force_slow_way;
6162830Sdjl 			*uptr++ = (nssuint_t)gbm->maxgids;
6172830Sdjl 			*uptr++ = (nssuint_t)gbm->numgids;
6182830Sdjl 			if (gbm->numgids == 1) {
6192830Sdjl 				*uptr++ = (nssuint_t)gbm->gid_array[0];
6202830Sdjl 			} else {
6212830Sdjl 				*uptr++ = (nssuint_t)0;
6222830Sdjl 			}
6232830Sdjl 			(void) strlcpy((void *)uptr, gbm->username, len);
6242830Sdjl 			*rlen = len2;
6252830Sdjl 			break;
6262830Sdjl 		case 't':
6272830Sdjl 			pptr = (nss_pnetgr_t *)buffer;
6282830Sdjl 			ing = (struct nss_innetgr_args *)arg;
6292830Sdjl 			len = sizeof (nss_pnetgr_t);
6302830Sdjl 			len2 = ing->arg[NSS_NETGR_MACHINE].argc +
6315477Sandra 			    ing->arg[NSS_NETGR_USER].argc +
6325477Sandra 			    ing->arg[NSS_NETGR_DOMAIN].argc +
6335477Sandra 			    ing->groups.argc;
6342830Sdjl 			len2 *= sizeof (nssuint_t);
6352830Sdjl 			len3 = 0;
6362830Sdjl 			for (j = 0; j < NSS_NETGR_N; j++) {
6372830Sdjl 				cv = ing->arg[j].argv;
6382830Sdjl 				for (i = ing->arg[j].argc; --i >= 0; ) {
6392830Sdjl 					if (*cv)
6402830Sdjl 						len3 += strlen(*cv++) + 1;
6412830Sdjl 				}
6422830Sdjl 			}
6432830Sdjl 			cv = ing->groups.argv;
6442830Sdjl 			for (i = ing->groups.argc; --i >= 0; ) {
6452830Sdjl 				if (*cv)
6462830Sdjl 					len3 += strlen(*cv++) + 1;
6472830Sdjl 			}
6482830Sdjl 			len3 = ROUND_UP(len3, sizeof (nssuint_t));
6492830Sdjl 			/*
6502830Sdjl 			 * Double argv space. Reason:
6512830Sdjl 			 *    First 1/2 offsets
6522830Sdjl 			 *    Second 1/2 for client side pointer arrays
6532830Sdjl 			 *    resolves malloc/free issues with unpacked argvs
6542830Sdjl 			 */
6552830Sdjl 			if ((len + (len2 << 1) + len3) >= length)
6562830Sdjl 				return (NSS_ERROR);
6572830Sdjl 			*rlen = len + (len2 << 1) + len3;
6582830Sdjl 
6592830Sdjl 			pptr->machine_argc = ing->arg[NSS_NETGR_MACHINE].argc;
6602830Sdjl 			pptr->user_argc = ing->arg[NSS_NETGR_USER].argc;
6612830Sdjl 			pptr->domain_argc = ing->arg[NSS_NETGR_DOMAIN].argc;
6622830Sdjl 			pptr->groups_argc = ing->groups.argc;
6632830Sdjl 			offv = len;
6642830Sdjl 			uptr = (nssuint_t *)((void *)((char *)buffer + offv));
6652830Sdjl 			offc = len + (len2 << 1);
6662830Sdjl 			dptr = (char *)buffer + offc;
6672830Sdjl 			if (pptr->machine_argc == 0) {
6682830Sdjl 				pptr->machine_offv = (nssuint_t)0;
6692830Sdjl 			} else {
6702830Sdjl 				pptr->machine_offv = offv;
6712830Sdjl 				cv = ing->arg[NSS_NETGR_MACHINE].argv;
6722830Sdjl 				i = pptr->machine_argc;
6732830Sdjl 				offv += sizeof (nssuint_t) * i;
6742830Sdjl 				for (; --i >= 0; ) {
6752830Sdjl 					*uptr++ = offc;
6762830Sdjl 					len3 = strlen(*cv) + 1;
6772830Sdjl 					(void) strlcpy(dptr, *cv++, len3);
6782830Sdjl 					offc += len3;
6792830Sdjl 					dptr += len3;
6802830Sdjl 				}
6812830Sdjl 			}
6822830Sdjl 			if (pptr->user_argc == 0) {
6832830Sdjl 				pptr->user_offv = (nssuint_t)0;
6842830Sdjl 			} else {
6852830Sdjl 				pptr->user_offv = offv;
6862830Sdjl 				cv = ing->arg[NSS_NETGR_USER].argv;
6872830Sdjl 				i = pptr->user_argc;
6882830Sdjl 				offv += sizeof (nssuint_t) * i;
6892830Sdjl 				for (; --i >= 0; ) {
6902830Sdjl 					*uptr++ = offc;
6912830Sdjl 					len3 = strlen(*cv) + 1;
6922830Sdjl 					(void) strlcpy(dptr, *cv++, len3);
6932830Sdjl 					offc += len3;
6942830Sdjl 					dptr += len3;
6952830Sdjl 				}
6962830Sdjl 			}
6972830Sdjl 			if (pptr->domain_argc == 0) {
6982830Sdjl 				pptr->domain_offv = (nssuint_t)0;
6992830Sdjl 			} else {
7002830Sdjl 				pptr->domain_offv = offv;
7012830Sdjl 				cv = ing->arg[NSS_NETGR_DOMAIN].argv;
7022830Sdjl 				i = pptr->domain_argc;
7032830Sdjl 				offv += sizeof (nssuint_t) * i;
7042830Sdjl 				for (; --i >= 0; ) {
7052830Sdjl 					*uptr++ = offc;
7062830Sdjl 					len3 = strlen(*cv) + 1;
7072830Sdjl 					(void) strlcpy(dptr, *cv++, len3);
7082830Sdjl 					offc += len3;
7092830Sdjl 					dptr += len3;
7102830Sdjl 				}
7112830Sdjl 			}
7122830Sdjl 			if (pptr->groups_argc == 0) {
7132830Sdjl 				pptr->groups_offv = (nssuint_t)0;
7142830Sdjl 			} else {
7152830Sdjl 				pptr->groups_offv = offv;
7162830Sdjl 				cv = ing->groups.argv;
7172830Sdjl 				i = pptr->groups_argc;
7182830Sdjl 				offv += sizeof (nssuint_t) * i;
7192830Sdjl 				for (; --i >= 0; ) {
7202830Sdjl 					*uptr++ = offc;
7212830Sdjl 					len3 = strlen(*cv) + 1;
7222830Sdjl 					(void) strlcpy(dptr, *cv++, len3);
7232830Sdjl 					offc += len3;
7242830Sdjl 					dptr += len3;
7252830Sdjl 				}
7262830Sdjl 			}
7272830Sdjl 			break;
7282830Sdjl 		case 'T':
7292830Sdjl 			sng = (struct nss_setnetgrent_args *)arg;
7302830Sdjl 			if (sng->netgroup == NULL)
7312830Sdjl 				return (NSS_NOTFOUND);
7322830Sdjl 			len = strlen(sng->netgroup) + 1;
7332830Sdjl 			if (len >= length)
7342830Sdjl 				return (NSS_ERROR);
7352830Sdjl 			(void) strlcpy(buffer, sng->netgroup, len);
7362830Sdjl 			*rlen = len;
7372830Sdjl 			break;
7382830Sdjl 		default:
7392830Sdjl 			return (NSS_ERROR);
7402830Sdjl 		}
7412830Sdjl 	}
7422830Sdjl 	return (NSS_SUCCESS);
7432830Sdjl }
7442830Sdjl 
7452830Sdjl nss_status_t
nss_default_key2str(void * buffer,size_t length,nss_XbyY_args_t * arg,const char * dbname,int dbop,size_t * rlen)7462830Sdjl nss_default_key2str(void *buffer, size_t length, nss_XbyY_args_t *arg,
7472830Sdjl 	const char *dbname, int dbop, size_t *rlen)
7482830Sdjl {
7492830Sdjl 	int		index;
7502830Sdjl 
7512830Sdjl 	if (buffer == NULL || length == 0 || arg == NULL ||
7522830Sdjl 	    dbname == NULL || rlen == NULL)
7532830Sdjl 		return (NSS_ERROR);
7542830Sdjl 
7552830Sdjl 	/*
7562830Sdjl 	 * If this is not one of the well known getXbyYs
7572830Sdjl 	 * (IE _printers special processing etc.) use a
7582830Sdjl 	 * local (non-nscd) getXbyY lookup.
7592830Sdjl 	 */
7602830Sdjl 	if ((index = nss_dbop_search(dbname, (uint32_t)dbop)) < 0)
7612830Sdjl 		return (NSS_TRYLOCAL);
7622830Sdjl 
7632830Sdjl 	return (nss_pack_key2str(buffer, length, arg, dbname,
7645477Sandra 	    dbop, rlen, getXbyY_to_dbop[index].tostr));
7652830Sdjl }
7662830Sdjl 
7672830Sdjl /*ARGSUSED*/
7682830Sdjl void
nss_packed_set_status(void * buffer,size_t length,nss_status_t status,nss_XbyY_args_t * arg)7692830Sdjl nss_packed_set_status(void *buffer, size_t length, nss_status_t status,
7702830Sdjl 		nss_XbyY_args_t *arg)
7712830Sdjl {
7722830Sdjl 	nss_pheader_t 	*pbuf = (nss_pheader_t *)buffer;
7732830Sdjl 	nss_dbd_t	*pdbd;
7742830Sdjl 	char		*dbn;
7752830Sdjl 
7762830Sdjl 	/* sidestep odd cases */
7772830Sdjl 	pdbd = (nss_dbd_t *)((void *)((char *)buffer + pbuf->dbd_off));
7782830Sdjl 	dbn = (char *)pdbd + pdbd->o_name;
7792830Sdjl 	if (pbuf->nss_dbop == NSS_DBOP_GROUP_BYMEMBER) {
7802830Sdjl 		if (strcmp(dbn, NSS_DBNAM_GROUP) == 0) {
7812830Sdjl 			struct nss_groupsbymem *in =
7825477Sandra 			    (struct nss_groupsbymem *)arg;
7832830Sdjl 
7842830Sdjl 			if (in->numgids >= 0) {
7852830Sdjl 				pbuf->p_status = NSS_SUCCESS;
7862830Sdjl 				pbuf->data_len = in->numgids *
7875477Sandra 				    sizeof (gid_t);
7882830Sdjl 				pbuf->p_herrno = 0;
7892830Sdjl 			} else {
7902830Sdjl 				pbuf->p_status = status;
7912830Sdjl 				pbuf->p_errno = errno;
7922830Sdjl 				pbuf->data_len = 0;
7932830Sdjl 				pbuf->p_herrno = (uint32_t)arg->h_errno;
7942830Sdjl 			}
7952830Sdjl 			return;
7962830Sdjl 		}
7972830Sdjl 	}
7982830Sdjl 	if (pbuf->nss_dbop == NSS_DBOP_NETGROUP_IN) {
7992830Sdjl 		if (strcmp(dbn, NSS_DBNAM_NETGROUP) == 0) {
8002830Sdjl 			struct nss_innetgr_args *in =
8015477Sandra 			    (struct nss_innetgr_args *)arg;
8022830Sdjl 
8032830Sdjl 			/* tell nss_unpack() operation is successful */
8042830Sdjl 			pbuf->data_len = 1;
8052830Sdjl 
8065477Sandra 			if (status != NSS_SUCCESS && status != NSS_NOTFOUND) {
8075477Sandra 				pbuf->p_status = status;
8085477Sandra 				pbuf->p_errno = errno;
8095477Sandra 				return;
8105477Sandra 			}
8115477Sandra 
8122830Sdjl 			if (in->status == NSS_NETGR_FOUND) {
8132830Sdjl 				pbuf->p_status = NSS_SUCCESS;
8142830Sdjl 			} else {
8152830Sdjl 				pbuf->p_status = NSS_NOTFOUND;
8162830Sdjl 				pbuf->p_errno = errno;
8172830Sdjl 			}
8182830Sdjl 			return;
8192830Sdjl 		}
8202830Sdjl 	}
8212830Sdjl 
8222830Sdjl 	/* process normal cases */
8232830Sdjl 	if ((pbuf->p_status = status) != NSS_SUCCESS) {
8242830Sdjl 		if (arg->erange == 1)
8252830Sdjl 			pbuf->p_errno = ERANGE;
8262830Sdjl 		else
8272830Sdjl 			pbuf->p_errno = errno;
8282830Sdjl 	} else
8292830Sdjl 		pbuf->p_errno = 0;
8302830Sdjl 	if (arg != NULL) {
8312830Sdjl 		pbuf->p_herrno = (uint32_t)arg->h_errno;
8322830Sdjl 		pbuf->data_len = (nssuint_t)arg->returnlen;
8332830Sdjl 	} else {
8342830Sdjl 		pbuf->p_herrno = 0;
8352830Sdjl 		pbuf->data_len = 0;
8362830Sdjl 	}
8372830Sdjl }
8382830Sdjl 
8392830Sdjl /*
8402830Sdjl  * nss_upack_key2arg
8412830Sdjl  * Private string to key unpacking function for getXbyY routines
8422830Sdjl  * This routine performs a scanf/printf like parse over the packed
8432830Sdjl  * string, to uppack and re-assemble the key in the args structure.
8442830Sdjl  *
8452830Sdjl  * buffer - Start of the key buffer location [in packed buffer]
8462830Sdjl  * length - Length of key buffer component
8472830Sdjl  * Key offsets are relative to start of key buffer location.
8482830Sdjl  *
8492830Sdjl  * Unpack fields		Key
8502830Sdjl  *   key.name			n
8512830Sdjl  *   key.number			N
8522830Sdjl  *   key.uid			u
8532830Sdjl  *   key.gid			g
8542830Sdjl  *   key.hostaddr		h
8552830Sdjl  *   key.ipnode			i
8562830Sdjl  *   key.projid			p
8572830Sdjl  *   key.serv(name)		s
8582830Sdjl  *   key.serv(port)		S
8592830Sdjl  *   key.ether			e
8602830Sdjl  *   key.pkey			k
8612830Sdjl  *   key.netaddr		a
8622830Sdjl  *   key.attrp			A
8632830Sdjl  *   groupsbymember		I
8642830Sdjl  *   innetgr_args		t
8652830Sdjl  *   setnetgr_args		T
8662830Sdjl  * Assumes arguments are all valid
8672830Sdjl  */
8682830Sdjl 
8692830Sdjl /*ARGSUSED*/
8702830Sdjl static nss_status_t
nss_upack_key2arg(void * buffer,size_t length,char ** dbname,int * dbop,nss_XbyY_args_t * arg,int index)8712830Sdjl nss_upack_key2arg(void *buffer, size_t length, char **dbname,
8722830Sdjl 		int *dbop, nss_XbyY_args_t *arg, int index)
8732830Sdjl {
8742830Sdjl 	nss_pheader_t 			*pbuf = (nss_pheader_t *)buffer;
8752830Sdjl 	const char			*strtype = NULL;
8764142Smichen 	nssuint_t 			off, *uptr, keysize;
8772830Sdjl 	size_t				len, slop;
8782830Sdjl 	int				i, j;
8792830Sdjl 	char				**cv, *bptr;
8802830Sdjl 	struct nss_setnetgrent_args	*sng;
8812830Sdjl 	struct nss_innetgr_args		*ing;
8822830Sdjl 	struct nss_groupsbymem		*gbm;
8832830Sdjl 	nss_pnetgr_t			*pptr;
8842830Sdjl 	_priv_execattr			*pe;
8852830Sdjl 
8864142Smichen 	/* keysize is length of the key area */
8874142Smichen 	keysize = pbuf->data_off - pbuf->key_off;
8884142Smichen 
8892830Sdjl 	off = pbuf->key_off;
8902830Sdjl 	bptr = (char *)buffer + off;
8912830Sdjl 	uptr = (nssuint_t *)((void *)bptr);
8922830Sdjl 	strtype = getXbyY_to_dbop[index].tostr;
8932830Sdjl 	if (strtype == NULL)
8942830Sdjl 		return (NSS_ERROR);
8952830Sdjl 	while (*strtype) {
8962830Sdjl 		switch (*strtype++) {
8972830Sdjl 		case 'n':
8982830Sdjl 			arg->key.name = (const char *)bptr;
8992830Sdjl 			break;
9002830Sdjl 		case 'N':
9012830Sdjl 			arg->key.number = (int)(*uptr);
9022830Sdjl 			break;
9032830Sdjl 		case 'u':
9042830Sdjl 			arg->key.uid = (uid_t)(*uptr);
9052830Sdjl 			break;
9062830Sdjl 		case 'g':
9072830Sdjl 			arg->key.gid = (gid_t)(*uptr);
9082830Sdjl 			break;
9092830Sdjl 		case 'h':
9102830Sdjl 			arg->key.hostaddr.len = (int)(*uptr++);
9112830Sdjl 			arg->key.hostaddr.type = (int)(*uptr++);
9122830Sdjl 			arg->key.hostaddr.addr = (const char *)uptr;
9132830Sdjl 			break;
9142830Sdjl 		case 'i':
9152830Sdjl 			arg->key.ipnode.af_family = (int)(*uptr++);
9162830Sdjl 			arg->key.ipnode.flags = (int)(*uptr++);
9172830Sdjl 			arg->key.ipnode.name = (const char *)uptr;
9182830Sdjl 			break;
9192830Sdjl 		case 'p':
9202830Sdjl 			arg->key.projid = (projid_t)(*uptr);
9212830Sdjl 			break;
9222830Sdjl 		case 's':
9232830Sdjl 			arg->key.serv.serv.name = (const char *)bptr;
9242830Sdjl 			len = strlen(arg->key.serv.serv.name) + 1;
9252830Sdjl 			bptr += len;
9262830Sdjl 			if (*(const char *)bptr == '\0')
9272830Sdjl 				arg->key.serv.proto = NULL;
9282830Sdjl 			else
9292830Sdjl 				arg->key.serv.proto = (const char *)bptr;
9302830Sdjl 			break;
9312830Sdjl 		case 'S':
9322830Sdjl 			arg->key.serv.serv.port = (int)(*uptr++);
9332830Sdjl 			if (pbuf->key_len == sizeof (nssuint_t)) {
9342830Sdjl 				arg->key.serv.proto = NULL;
9352830Sdjl 			} else {
9362830Sdjl 				bptr += sizeof (nssuint_t);
9372830Sdjl 				arg->key.serv.proto = (const char *)bptr;
9382830Sdjl 			}
9392830Sdjl 			break;
9402830Sdjl 		case 'e':
9412830Sdjl 			arg->key.ether = bptr;
9422830Sdjl 			break;
9432830Sdjl 		case 'k':
9442830Sdjl 			arg->key.pkey.name = (const char *)bptr;
9452830Sdjl 			len = strlen(arg->key.pkey.name) + 1;
9462830Sdjl 			bptr += len;
9472830Sdjl 			arg->key.pkey.keytype = (const char *)bptr;
9482830Sdjl 			break;
9492830Sdjl 		case 'a':
9502830Sdjl 			arg->key.netaddr.net = (uint32_t)(*uptr++);
9512830Sdjl 			arg->key.netaddr.type = (int)(*uptr++);
9522830Sdjl 			break;
9532830Sdjl 		case 'A':
9542830Sdjl 			pe = (_priv_execattr *)((void *)bptr);
9552830Sdjl 			/* use slop space as priv_execattr structure */
9562830Sdjl 			arg->key.attrp = (void *)pe;
9572830Sdjl 			/* skip over slop ... */
9582830Sdjl 			slop = sizeof (nssuint_t) * 16;
9592830Sdjl 			uptr = (nssuint_t *)((void *)((char *)bptr + slop));
9602830Sdjl 			pe->search_flag = (int)*uptr++;
9612830Sdjl 			bptr = (char *)uptr;
9622830Sdjl 			if (*bptr == '\0') {
9632830Sdjl 				pe->name = NULL;
9642830Sdjl 				bptr++;
9652830Sdjl 			} else {
9662830Sdjl 				pe->name = (char *)bptr;
9672830Sdjl 				bptr += strlen(pe->name) + 1;
9682830Sdjl 			}
9692830Sdjl 			if (*bptr == '\0') {
9702830Sdjl 				pe->type = NULL;
9712830Sdjl 				bptr++;
9722830Sdjl 			} else {
9732830Sdjl 				pe->type = (char *)bptr;
9742830Sdjl 				bptr += strlen(pe->type) + 1;
9752830Sdjl 			}
9762830Sdjl 			if (*bptr == '\0') {
9772830Sdjl 				pe->id = NULL;
9782830Sdjl 				bptr++;
9792830Sdjl 			} else {
9802830Sdjl 				pe->id = (char *)bptr;
9812830Sdjl 				bptr += strlen(pe->id) + 1;
9822830Sdjl 			}
9832830Sdjl 			if (*bptr == '\0') {
9842830Sdjl 				pe->policy = NULL;
9852830Sdjl 			} else {
9862830Sdjl 				pe->policy = (char *)bptr;
9872830Sdjl 			}
9882830Sdjl 			pe->head_exec = NULL;
9892830Sdjl 			pe->prev_exec = NULL;
9902830Sdjl 			break;
9912830Sdjl 		case 'I':
9922830Sdjl 			gbm = (struct nss_groupsbymem *)arg;
9932830Sdjl 			gbm->gid_array = (gid_t *)
9945477Sandra 			    ((void *)((char *)pbuf + pbuf->data_off));
9952830Sdjl 			gbm->force_slow_way = (int)(*uptr++);
9962830Sdjl 			gbm->maxgids = (int)(*uptr++);
9972830Sdjl 			gbm->numgids = (int)(*uptr++);
9982830Sdjl 			if (gbm->numgids == 1) {
9992830Sdjl 				/* insert initial group into data area */
10003099Smichen 				gbm->gid_array[0] = (gid_t)(*uptr++);
10013099Smichen 			} else
10023099Smichen 				uptr++;
10032830Sdjl 			gbm->username = (const char *)uptr;
10042830Sdjl 			break;
10052830Sdjl 		case 't':
10062830Sdjl 			pptr = (nss_pnetgr_t *)((void *)bptr);
10072830Sdjl 			ing = (struct nss_innetgr_args *)arg;
10082830Sdjl 			ing->arg[NSS_NETGR_MACHINE].argc = pptr->machine_argc;
10092830Sdjl 			ing->arg[NSS_NETGR_USER].argc = pptr->user_argc;
10102830Sdjl 			ing->arg[NSS_NETGR_DOMAIN].argc = pptr->domain_argc;
10112830Sdjl 			ing->groups.argc = pptr->groups_argc;
10122830Sdjl 
10132830Sdjl 			/*
10142830Sdjl 			 * Start of argv pointer storage
10152830Sdjl 			 */
10162830Sdjl 			off = ing->arg[NSS_NETGR_MACHINE].argc +
10175477Sandra 			    ing->arg[NSS_NETGR_USER].argc +
10185477Sandra 			    ing->arg[NSS_NETGR_DOMAIN].argc +
10195477Sandra 			    ing->groups.argc;
10202830Sdjl 			off *= sizeof (nssuint_t);
10212830Sdjl 			off += sizeof (nss_pnetgr_t);
10222830Sdjl 
10232830Sdjl 			cv = (char **)((void *)(bptr + off));
10242830Sdjl 			uptr = (nssuint_t *)
10255477Sandra 			    ((void *)(bptr + sizeof (nss_pnetgr_t)));
10262830Sdjl 			for (j = 0; j < NSS_NETGR_N; j++) {
10272830Sdjl 				ing->arg[j].argv = cv;
10282830Sdjl 				for (i = 0; i < ing->arg[j].argc; i++) {
10294142Smichen 					if (*uptr >= keysize)
10304142Smichen 						return (NSS_ERROR);
10312830Sdjl 					*cv++ = (bptr + *uptr++);
10322830Sdjl 				}
10332830Sdjl 			}
10342830Sdjl 			ing->groups.argv = cv;
10352830Sdjl 			for (i = 0; i < ing->groups.argc; i++) {
10364142Smichen 				if (*uptr >= keysize)
10374142Smichen 					return (NSS_ERROR);
10382830Sdjl 				*cv++ = (bptr + *uptr++);
10392830Sdjl 			}
10402830Sdjl 			break;
10412830Sdjl 		case 'T':
10422830Sdjl 			sng = (struct nss_setnetgrent_args *)arg;
10432830Sdjl 			sng->netgroup = (const char *)bptr;
10442830Sdjl 			sng->iterator = 0;
10452830Sdjl 			break;
10462830Sdjl 
10472830Sdjl 		default:
10482830Sdjl 			return (NSS_ERROR);
10492830Sdjl 		}
10502830Sdjl 	}
10512830Sdjl 	return (NSS_SUCCESS);
10522830Sdjl }
10532830Sdjl 
10542830Sdjl static nss_status_t
nss_pinit_funcs(int index,nss_db_initf_t * initf,nss_str2ent_t * s2e)10552830Sdjl nss_pinit_funcs(int index, nss_db_initf_t *initf, nss_str2ent_t *s2e)
10562830Sdjl {
10572830Sdjl 	const char	*name;
10584046Smichen 	void		*htmp = NULL;
10594046Smichen 	void		*sym;
10604046Smichen 	static void	*handle = NULL;
10614046Smichen 	static mutex_t	handle_lock = DEFAULTMUTEX;
10624046Smichen 	static mutex_t	initf_lock = DEFAULTMUTEX;
10634046Smichen 	static mutex_t	s2e_lock = DEFAULTMUTEX;
10642830Sdjl 
10654046Smichen 	if (handle == NULL) {
10665914Sraf 		htmp = dlopen((const char *)0, RTLD_LAZY);
10675914Sraf 
10684046Smichen 		lmutex_lock(&handle_lock);
10694046Smichen 		if (handle == NULL) {
10704046Smichen 			if (htmp == NULL) {
10714046Smichen 				lmutex_unlock(&handle_lock);
10722830Sdjl 				return (NSS_ERROR);
10732830Sdjl 			} else {
10744046Smichen 				membar_producer();
10754046Smichen 				handle = htmp;
10765914Sraf 				htmp = NULL;
10772830Sdjl 			}
10782830Sdjl 		}
10794046Smichen 		lmutex_unlock(&handle_lock);
10805914Sraf 		if (htmp)
1081*11411SSurya.Prakki@Sun.COM 			(void) dlclose(htmp);
10824046Smichen 	}
10834046Smichen 	membar_consumer();
10844046Smichen 
10854046Smichen 	if (initf) {
10866515Sraf 		if (getXbyY_to_dbop[index].initfnp == NULL) {
10876515Sraf 			name = getXbyY_to_dbop[index].initfn;
10886515Sraf 			if ((sym = dlsym(handle, name)) == NULL)
10896515Sraf 				return (NSS_ERROR);
10904046Smichen 			lmutex_lock(&initf_lock);
10916515Sraf 			if (getXbyY_to_dbop[index].initfnp == NULL)
10924046Smichen 				getXbyY_to_dbop[index].initfnp = sym;
10934046Smichen 			membar_producer();
10944046Smichen 			lmutex_unlock(&initf_lock);
10952830Sdjl 		}
10966515Sraf 		membar_consumer();
10976515Sraf 		*initf = (nss_db_initf_t)getXbyY_to_dbop[index].initfnp;
10982830Sdjl 	}
10994046Smichen 	if (s2e) {
11006515Sraf 		if (getXbyY_to_dbop[index].strfnp == NULL) {
11016515Sraf 			name = getXbyY_to_dbop[index].strfn;
11026515Sraf 			if ((sym = dlsym(handle, name)) == NULL)
11036515Sraf 				return (NSS_ERROR);
11044046Smichen 			lmutex_lock(&s2e_lock);
11056515Sraf 			if (getXbyY_to_dbop[index].strfnp == NULL)
11064046Smichen 				getXbyY_to_dbop[index].strfnp = sym;
11074046Smichen 			membar_producer();
11084046Smichen 			lmutex_unlock(&s2e_lock);
11094046Smichen 		}
11106515Sraf 		membar_consumer();
11116515Sraf 		*s2e = (nss_str2ent_t)getXbyY_to_dbop[index].strfnp;
11124046Smichen 	}
11134046Smichen 
11142830Sdjl 	return (NSS_SUCCESS);
11152830Sdjl }
11162830Sdjl 
11172830Sdjl nss_status_t
nss_packed_getkey(void * buffer,size_t length,char ** dbname,int * dbop,nss_XbyY_args_t * arg)11182830Sdjl nss_packed_getkey(void *buffer, size_t length, char **dbname,
11192830Sdjl 		int *dbop, nss_XbyY_args_t *arg)
11202830Sdjl {
11212830Sdjl 	nss_pheader_t 	*pbuf = (nss_pheader_t *)buffer;
11222830Sdjl 	nss_dbd_t	*pdbd;
11234142Smichen 	nssuint_t 	off, dbdsize;
11242830Sdjl 	int		index;
11252830Sdjl 
11262830Sdjl 	if (buffer == NULL || length == 0 || dbop == NULL ||
11275477Sandra 	    arg == NULL || dbname == NULL)
11282830Sdjl 		return (NSS_ERROR);
11292830Sdjl 
11302830Sdjl 	*dbop = pbuf->nss_dbop;
11312830Sdjl 	off = pbuf->dbd_off;
11322830Sdjl 	pdbd = (nss_dbd_t *)((void *)((char *)buffer + off));
11334142Smichen 	dbdsize = pbuf->key_off - pbuf->dbd_off;
11344142Smichen 	if (pdbd->o_name >= dbdsize || pdbd->o_config_name >= dbdsize ||
11355477Sandra 	    pdbd->o_default_config >= dbdsize)
11364142Smichen 		return (NSS_ERROR);
11372830Sdjl 	*dbname = (char *)buffer + off + pdbd->o_name;
11382830Sdjl 	if ((index = nss_dbop_search(*dbname, (uint32_t)*dbop)) < 0)
11392830Sdjl 		return (NSS_ERROR);
11402830Sdjl 	return (nss_upack_key2arg(buffer, length, dbname, dbop, arg, index));
11412830Sdjl }
11422830Sdjl 
11432830Sdjl 
11442830Sdjl /*
11452830Sdjl  * str2packent: Standard format interposed str2X function for normal APIs
11462830Sdjl  *
11472830Sdjl  * Return values: 0 = success, 1 = parse error, 2 = erange ...
11482830Sdjl  *
11492830Sdjl  * The structure pointer is ignored since this is a nscd side packed request.
11502830Sdjl  * The client side routine does all the real parsing; we just check limits and
11512830Sdjl  * store the entry in the buffer we were passed by the caller.
11522830Sdjl  */
11532830Sdjl 
11542830Sdjl /*ARGSUSED*/
11552830Sdjl static int
str2packent(const char * instr,int lenstr,void * ent,char * buffer,int buflen)11562830Sdjl str2packent(
11572830Sdjl     const char *instr,
11582830Sdjl     int lenstr,
11592830Sdjl     void *ent,		/* really (char *) */
11602830Sdjl     char *buffer,
11612830Sdjl     int buflen
11622830Sdjl )
11632830Sdjl {
11642830Sdjl 	if (buflen <= lenstr) {		/* not enough buffer */
11652830Sdjl 		return (NSS_STR_PARSE_ERANGE);
11662830Sdjl 	}
11672830Sdjl 	(void) memmove(buffer, instr, lenstr);
11682830Sdjl 	buffer[lenstr] = '\0';
11692830Sdjl 
11702830Sdjl 	return (NSS_STR_PARSE_SUCCESS);
11712830Sdjl }
11722830Sdjl 
11732830Sdjl /*
11742830Sdjl  * Initialize db_root, initf, dbop and arg from a packed buffer
11752830Sdjl  */
11762830Sdjl 
11772830Sdjl /*ARGSUSED*/
11782830Sdjl nss_status_t
nss_packed_arg_init(void * buffer,size_t length,nss_db_root_t * db_root,nss_db_initf_t * initf,int * dbop,nss_XbyY_args_t * arg)11792830Sdjl nss_packed_arg_init(void *buffer, size_t length, nss_db_root_t *db_root,
11802830Sdjl 		nss_db_initf_t *initf, int *dbop, nss_XbyY_args_t *arg)
11812830Sdjl {
11822830Sdjl 	nss_pheader_t 		*pbuf = (nss_pheader_t *)buffer;
11832830Sdjl 	nss_str2ent_t		s2e = str2packent;
11842830Sdjl 	nss_str2ent_t		real_s2e = NULL;
11852830Sdjl 	nss_dbd_t		*pdbd;
11864142Smichen 	nssuint_t		off, dbdsize;
11872830Sdjl 	char			*dbname, *bptr;
11882830Sdjl 	size_t			len;
11892830Sdjl 	int			index;
11902830Sdjl 
11912830Sdjl 	if (buffer == NULL || length == 0 ||
11925477Sandra 	    dbop == NULL || arg == NULL)
11932830Sdjl 		return (NSS_ERROR);
11942830Sdjl 
11952830Sdjl 	/* init dbop */
11962830Sdjl 	*dbop = pbuf->nss_dbop;
11972830Sdjl 	off = pbuf->dbd_off;
11982830Sdjl 	pdbd = (nss_dbd_t *)((void *)((char *)buffer + off));
11994142Smichen 	dbdsize = pbuf->key_off - pbuf->dbd_off;
12004142Smichen 	if (pdbd->o_name >= dbdsize || pdbd->o_config_name >= dbdsize ||
12015477Sandra 	    pdbd->o_default_config >= dbdsize)
12024142Smichen 		return (NSS_ERROR);
12032830Sdjl 	dbname = (char *)buffer + off + pdbd->o_name;
12042830Sdjl 	if ((index = nss_dbop_search(dbname, (uint32_t)*dbop)) < 0)
12052830Sdjl 		return (NSS_ERROR);
12062830Sdjl 
12072830Sdjl 	/* db_root is initialized by nscd's based on door info */
12082830Sdjl 	/* do nothing here */
12092830Sdjl 
12102830Sdjl 	/* init key information - (and get dbname dbop etc...) */
12112830Sdjl 	if (nss_upack_key2arg(buffer, length, &dbname,
12125477Sandra 	    dbop, arg, index) != NSS_SUCCESS)
12132830Sdjl 		return (NSS_ERROR);
12142830Sdjl 
12152830Sdjl 	/* possible audituser init */
12162830Sdjl 	if (strcmp(dbname, NSS_DBNAM_AUTHATTR) == 0)
12172830Sdjl 		arg->h_errno = (int)pbuf->p_herrno;
12182830Sdjl 
12192830Sdjl 	bptr = (char *)buffer + pbuf->data_off;
12202830Sdjl 	len = (size_t)pbuf->data_len;
12212830Sdjl 
12222830Sdjl 	/* sidestep odd arg cases */
12232830Sdjl 	if (*dbop == NSS_DBOP_GROUP_BYMEMBER &&
12242830Sdjl 	    strcmp(dbname, NSS_DBNAM_GROUP) == 0) {
12252830Sdjl 		/* get initf  and str2ent functions */
12262830Sdjl 		if (nss_pinit_funcs(index, initf, &real_s2e) != NSS_SUCCESS)
12272830Sdjl 			return (NSS_ERROR);
12282830Sdjl 		((struct nss_groupsbymem *)arg)->str2ent = real_s2e;
12293099Smichen 		((struct nss_groupsbymem *)arg)->process_cstr = process_cstr;
12302830Sdjl 		return (NSS_SUCCESS);
12312830Sdjl 	}
12322830Sdjl 	if (pbuf->nss_dbop == NSS_DBOP_NETGROUP_IN &&
12335477Sandra 	    strcmp(dbname, NSS_DBNAM_NETGROUP) == 0) {
12342830Sdjl 		return (NSS_SUCCESS);
12352830Sdjl 	}
12362830Sdjl 
12372830Sdjl 	/* get initf  and str2ent functions */
12382830Sdjl 	if (nss_pinit_funcs(index, initf, NULL) != NSS_SUCCESS)
12392830Sdjl 		return (NSS_ERROR);
12402830Sdjl 
12412830Sdjl 	/* init normal arg cases */
12422830Sdjl 	NSS_XbyY_INIT(arg, NULL, bptr, len, s2e);
12432830Sdjl 	arg->h_errno = 0;
12442830Sdjl 
12452830Sdjl 	return (NSS_SUCCESS);
12462830Sdjl }
12472830Sdjl 
12482830Sdjl /*
12492830Sdjl  * Initialize db_root, initf, dbop, contextp and arg from a packed buffer
12502830Sdjl  */
12512830Sdjl 
12522830Sdjl /*ARGSUSED*/
12532830Sdjl nss_status_t
nss_packed_context_init(void * buffer,size_t length,nss_db_root_t * db_root,nss_db_initf_t * initf,nss_getent_t ** contextp,nss_XbyY_args_t * arg)12542830Sdjl nss_packed_context_init(void *buffer, size_t length, nss_db_root_t *db_root,
12552830Sdjl 		nss_db_initf_t *initf, nss_getent_t **contextp,
12562830Sdjl 		nss_XbyY_args_t *arg)
12572830Sdjl {
12582830Sdjl 	nss_pheader_t 	*pbuf = (nss_pheader_t *)buffer;
12592830Sdjl 	nss_str2ent_t	s2e = str2packent;
12602830Sdjl 	char		*bptr;
12612830Sdjl 	size_t		len;
12622830Sdjl 
12632830Sdjl 	/* init arg */
12642830Sdjl 	if (arg != NULL) {
12652830Sdjl 		bptr = (char *)buffer + pbuf->data_off;
12662830Sdjl 		len = (size_t)pbuf->data_len;
12672830Sdjl 		NSS_XbyY_INIT(arg, NULL, bptr, len, s2e);
12682830Sdjl 	}
12692830Sdjl 
12702830Sdjl 	return (NSS_SUCCESS);
12712830Sdjl }
1272