xref: /illumos-gate/usr/src/lib/libc/port/gen/nss_dbdefs.c (revision 8548bf79039833dba8615afdf63258b2cb122121)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include "synonyms.h"
30 #include <mtlib.h>
31 #include <ctype.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <nss_dbdefs.h>
36 #include <limits.h>
37 #include <dlfcn.h>
38 #include <link.h>
39 #include <thread.h>
40 #include <atomic.h>
41 /* headers for key2str/str2key routines */
42 #include <sys/ethernet.h>
43 #include <exec_attr.h>
44 #include <grp.h>
45 
46 /*
47  * functions in nss_dbdefs.c deal more with the mechanics of
48  * the data structures like nss_XbyY_args_t and the interaction
49  * with the packed buffers etc.  versus the mechanics of the
50  * actual policy component operations such as nss_search sequencing.
51  */
52 
53 /*
54  * ALIGN? is there an official definition of this?
55  * We use sizeof(long) to cover what we want
56  * for both the 32-bit world and 64-bit world.
57  */
58 
59 #define	ALIGN(x) ((((long)(x)) + sizeof (long) - 1) & ~(sizeof (long) - 1))
60 
61 nss_XbyY_buf_t *
62 _nss_XbyY_buf_alloc(int struct_size, int buffer_size)
63 {
64 	nss_XbyY_buf_t	*b;
65 
66 	/* Use one malloc for dbargs, result struct and buffer */
67 	b = (nss_XbyY_buf_t *)
68 		malloc(ALIGN(sizeof (*b)) + struct_size + buffer_size);
69 	if (b == 0) {
70 		return (0);
71 	}
72 	b->result = (void *)ALIGN(&b[1]);
73 	b->buffer = (char *)(b->result) + struct_size;
74 	b->buflen = buffer_size;
75 	return (b);
76 }
77 
78 void
79 _nss_XbyY_buf_free(nss_XbyY_buf_t *b)
80 {
81 	if (b != 0) {
82 		free(b);
83 	}
84 }
85 
86 /* === Comment:  used by fget{gr,pw,sp}ent */
87 /* ==== Should do ye olde syslog()ing of suspiciously long lines */
88 
89 void
90 _nss_XbyY_fgets(FILE *f, nss_XbyY_args_t *b)
91 {
92 	char		buf[LINE_MAX];
93 	int		len, parsestat;
94 
95 	if (fgets(buf, LINE_MAX, f) == 0) {
96 		/* End of file */
97 		b->returnval = 0;
98 		b->erange    = 0;
99 		return;
100 	}
101 	len = (int)strlen(buf);
102 	/* len >= 0 (otherwise we would have got EOF) */
103 	if (buf[len - 1] != '\n') {
104 		if ((len + 1) == LINE_MAX) {
105 			/* Line too long for buffer; too bad */
106 			while (fgets(buf, LINE_MAX, f) != 0 &&
107 			    buf[strlen(buf) - 1] != '\n') {
108 				;
109 			}
110 			b->returnval = 0;
111 			b->erange    = 1;
112 			return;
113 		}
114 		/* case where the file is not terminated with a Newline */
115 		len++;
116 	}
117 	parsestat = (*b->str2ent)(buf, (len - 1), b->buf.result, b->buf.buffer,
118 		b->buf.buflen);
119 	if (parsestat == NSS_STR_PARSE_ERANGE) {
120 		b->returnval = 0;
121 		b->erange    = 1;
122 	} else if (parsestat == NSS_STR_PARSE_SUCCESS) {
123 		b->returnval = b->buf.result;
124 	}
125 }
126 
127 /*
128  * parse the aliases string into the buffer and if successful return
129  * a char ** pointer to the beginning of the aliases.
130  *
131  * CAUTION: (instr, instr+lenstr) and (buffer, buffer+buflen) are
132  * non-intersecting memory areas. Since this is an internal interface,
133  * we should be able to live with that.
134  */
135 char **
136 _nss_netdb_aliases(const char *instr, int lenstr, char *buffer, int buflen)
137 	/* "instr" is the beginning of the aliases string */
138 	/* "buffer" has the return val for success */
139 	/* "buflen" is the length of the buffer available for aliases */
140 {
141 	/*
142 	 * Build the alias-list in the start of the buffer, and copy
143 	 * the strings to the end of the buffer.
144 	 */
145 	const char
146 		*instr_limit	= instr + lenstr;
147 	char	*copyptr	= buffer + buflen;
148 	char	**aliasp	= (char **)ROUND_UP(buffer, sizeof (*aliasp));
149 	char	**alias_start	= aliasp;
150 	int	nstrings	= 0;
151 
152 	for (;;) {
153 		const char	*str_start;
154 		size_t		str_len;
155 
156 		while (instr < instr_limit && isspace(*instr)) {
157 			instr++;
158 		}
159 		if (instr >= instr_limit || *instr == '#') {
160 			break;
161 		}
162 		str_start = instr;
163 		while (instr < instr_limit && !isspace(*instr)) {
164 			instr++;
165 		}
166 
167 		++nstrings;
168 
169 		str_len = instr - str_start;
170 		copyptr -= str_len + 1;
171 		if (copyptr <= (char *)(&aliasp[nstrings + 1])) {
172 			/* Has to be room for the pointer to */
173 			/* the alias we're about to add,   */
174 			/* as well as the final NULL ptr.  */
175 			return (0);
176 		}
177 		*aliasp++ = copyptr;
178 		(void) memcpy(copyptr, str_start, str_len);
179 		copyptr[str_len] = '\0';
180 	}
181 	*aliasp++ = 0;
182 	return (alias_start);
183 }
184 
185 
186 extern nss_status_t process_cstr(const char *, int, struct nss_groupsbymem *);
187 
188 /*
189  * pack well known getXbyY keys to packed buffer prior to the door_call
190  * to nscd.  Some consideration is given to ordering the tests based on
191  * usage.  Note: buf is nssuint_t aligned.
192  */
193 
194 typedef struct {
195 	const char	*name;		/* NSS_DBNAM_* */
196 	const char	*defconf;	/* NSS_DEFCONF_* */
197 	const char	*initfn;	/* init function name */
198 	const char	*strfn;		/* str2X function name */
199 	const char	*cstrfn;	/* cstr2X function name */
200 	uint32_t	dbop;		/* NSS_DBOP_* */
201 	const char	*tostr;		/* key2str cvt str */
202 } getXbyY_to_dbop_t;
203 
204 #define	NSS_MK_GETXYDBOP(x, y, f, e)	\
205 	{ NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" f, "str2" f, \
206 		NULL, NSS_DBOP_##x##_##y, (e) }
207 
208 #define	NSS_MK_GETXYDBOPA(x, a, f, e)	\
209 	{ NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" f, "str2" f, \
210 		NULL, NSS_DBOP_##a, (e) }
211 
212 #define	NSS_MK_GETXYDBOPB(x, b, a, f, s, e)	\
213 	{ NSS_DBNAM_##x, NSS_DEFCONF_##b, "_nss_initf_" f, s,  \
214 		NULL, NSS_DBOP_##a, (e) }
215 
216 #define	NSS_MK_GETXYDBOPC(x, a, f, s, e)	\
217 	{ NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" f, s, \
218 		NULL, NSS_DBOP_##x##_##a, (e) }
219 
220 #define	NSS_MK_GETXYDBOPD(x, y, i, f, e)	\
221 	{ NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" i, "str2" f, \
222 		NULL, NSS_DBOP_##x##_##y, (e) }
223 
224 #define	NSS_MK_GETXYDBOPCSTR(x, a, f, s, e)	\
225 	{ NSS_DBNAM_##x, NSS_DEFCONF_##x, "_nss_initf_" f, s, \
226 		"process_cstr", NSS_DBOP_##x##_##a, (e) }
227 
228 /*
229  * The getXbyY_to_dbop structure is hashed on first call in order to
230  * reduce the search time for the well known getXbyY operations.
231  * A binary search was not fast enough.  There were on average
232  * 3-4 tests (strcmps) per getXbyY call.
233  *
234  * DBOP_PRIME_HASH must be a prime number (reasonably small) but that
235  * is sufficient to uniquely map the entries in the following table
236  * without collision.
237  *
238  * The DBOP_PRIME_HASH was selected as the smallest hash value
239  * for this table without collisions. Changing this table WILL
240  * necessitate re-testing for possible collisions.
241  */
242 
243 #define	DBOP_PRIME_HASH		223
244 #define	DBOP_HASH_TAG		0xf0000000
245 static int getXbyYdbopHASH[DBOP_PRIME_HASH] = { 0 };
246 static mutex_t getXbydbop_hash_lock = DEFAULTMUTEX;
247 static int getXbyYdbop_hashed = 0;
248 
249 static getXbyY_to_dbop_t getXbyY_to_dbop[] = {
250 	/* NSS_MK_GETXYDBOP(ALIASES, ?, ?), */
251 	NSS_MK_GETXYDBOPD(AUDITUSER, BYNAME, "auuser", "audituser", "n"),
252 	NSS_MK_GETXYDBOP(AUTHATTR, BYNAME, "authattr", "n"),
253 	/* NSS_MK_GETXYDBOP(AUTOMOUNT, ?, ?), */
254 	NSS_MK_GETXYDBOP(BOOTPARAMS, BYNAME, "bootparams", "n"),
255 	NSS_MK_GETXYDBOPC(ETHERS, HOSTTON, "ethers", "str2ether", "n"),
256 	NSS_MK_GETXYDBOPC(ETHERS, NTOHOST, "ethers", "str2ether", "e"),
257 	NSS_MK_GETXYDBOP(EXECATTR, BYNAME, "execattr", "A"),
258 	NSS_MK_GETXYDBOP(EXECATTR, BYID, "execattr", "A"),
259 	NSS_MK_GETXYDBOP(EXECATTR, BYNAMEID, "execattr", "A"),
260 	NSS_MK_GETXYDBOP(GROUP, BYNAME, "group", "n"),
261 	NSS_MK_GETXYDBOP(GROUP, BYGID, "group", "g"),
262 	NSS_MK_GETXYDBOPCSTR(GROUP, BYMEMBER, "group", "str2group", "I"),
263 	NSS_MK_GETXYDBOPC(HOSTS, BYNAME, "hosts", "str2hostent", "n"),
264 	NSS_MK_GETXYDBOPC(HOSTS, BYADDR, "hosts", "str2hostent", "h"),
265 	NSS_MK_GETXYDBOPC(IPNODES, BYNAME, "ipnodes", "str2hostent", "i"),
266 	NSS_MK_GETXYDBOPC(IPNODES, BYADDR, "ipnodes", "str2hostent", "h"),
267 	NSS_MK_GETXYDBOP(NETGROUP, IN, "netgroup", "t"),
268 	NSS_MK_GETXYDBOP(NETGROUP, SET, "netgroup", "T"),
269 	NSS_MK_GETXYDBOPC(NETMASKS, BYNET, "netmasks", "str2addr", "n"),
270 	NSS_MK_GETXYDBOPC(NETWORKS, BYNAME, "net", "str2netent", "n"),
271 	NSS_MK_GETXYDBOPC(NETWORKS, BYADDR, "net", "str2netent", "a"),
272 	NSS_MK_GETXYDBOP(PASSWD, BYNAME, "passwd", "n"),
273 	NSS_MK_GETXYDBOP(PASSWD, BYUID, "passwd", "u"),
274 	NSS_MK_GETXYDBOP(PRINTERS, BYNAME, "printers", "n"),
275 	NSS_MK_GETXYDBOP(PROFATTR, BYNAME, "profattr", "n"),
276 	NSS_MK_GETXYDBOP(PROJECT, BYNAME, "project", "n"),
277 	NSS_MK_GETXYDBOP(PROJECT, BYID, "project", "p"),
278 	NSS_MK_GETXYDBOPC(PROTOCOLS, BYNAME, "proto", "str2protoent", "n"),
279 	NSS_MK_GETXYDBOPC(PROTOCOLS, BYNUMBER, "proto", "str2protoent", "N"),
280 	NSS_MK_GETXYDBOPA(PUBLICKEY, KEYS_BYNAME, "publickey", "k"),
281 	NSS_MK_GETXYDBOPC(RPC, BYNAME, "rpc", "str2rpcent", "n"),
282 	NSS_MK_GETXYDBOPC(RPC, BYNUMBER, "rpc", "str2rpcent", "N"),
283 	NSS_MK_GETXYDBOPC(SERVICES, BYNAME, "services", "str2servent", "s"),
284 	NSS_MK_GETXYDBOPC(SERVICES, BYPORT, "services", "str2servent", "S"),
285 	NSS_MK_GETXYDBOPB(SHADOW, PASSWD, PASSWD_BYNAME, "shadow",
286 				"str2spwd", "n"),
287 	NSS_MK_GETXYDBOPC(TSOL_RH, BYADDR, "tsol_rh", "str_to_rhstr", "h"),
288 	NSS_MK_GETXYDBOPC(TSOL_TP, BYNAME, "tsol_tp", "str_to_tpstr", "n"),
289 	NSS_MK_GETXYDBOPC(TSOL_ZC, BYNAME, "tsol_zc", "str_to_zcstr", "n"),
290 	NSS_MK_GETXYDBOP(USERATTR, BYNAME, "userattr", "n"),
291 };
292 
293 static int
294 nss_dbop_search(const char *name, uint32_t dbop)
295 {
296 	getXbyY_to_dbop_t *hptr;
297 	int count = (sizeof (getXbyY_to_dbop) / sizeof (getXbyY_to_dbop_t));
298 	uint32_t hval, g;
299 	const char *cp;
300 	int i, idx;
301 
302 	/* Uses a table size is known to have no collisions */
303 	if (getXbyYdbop_hashed == 0) {
304 		lmutex_lock(&getXbydbop_hash_lock);
305 		if (getXbyYdbop_hashed == 0) {
306 			for (i = 0; i < count; i++) {
307 				cp = getXbyY_to_dbop[i].name;
308 				hval = 0;
309 				while (*cp) {
310 					hval = (hval << 4) + *cp++;
311 					if ((g = (hval & 0xf00000000)) != 0)
312 						hval ^= g >> 24;
313 					hval &= ~g;
314 				}
315 				hval += getXbyY_to_dbop[i].dbop;
316 				hval %= DBOP_PRIME_HASH;
317 				if (getXbyYdbopHASH[hval] != 0) {
318 					/* hash table collision-see above */
319 					lmutex_unlock(&getXbydbop_hash_lock);
320 					return (-1);
321 				}
322 				getXbyYdbopHASH[hval] = i | DBOP_HASH_TAG;
323 			}
324 			membar_producer();
325 			getXbyYdbop_hashed = 1;
326 		}
327 		lmutex_unlock(&getXbydbop_hash_lock);
328 	}
329 	membar_consumer();
330 	cp = name;
331 	hval = 0;
332 	while (*cp) {
333 		hval = (hval << 4) + *cp++;
334 		if ((g = (hval & 0xf00000000)) != 0)
335 			hval ^= g >> 24;
336 		hval &= ~g;
337 	}
338 	hval += dbop;
339 	hval %= DBOP_PRIME_HASH;
340 	idx = getXbyYdbopHASH[hval];
341 	if ((idx & DBOP_HASH_TAG) != DBOP_HASH_TAG)
342 		return (-1);
343 	idx &= ~DBOP_HASH_TAG;
344 	if (idx >= count)
345 		return (-1);
346 	hptr = &getXbyY_to_dbop[idx];
347 	if (hptr->dbop != dbop || strcmp(name, hptr->name) != 0)
348 		return (-1);
349 	return (idx);
350 }
351 
352 /*
353  * nss_pack_key2str
354  * Private key to string packing function for getXbyY routines
355  * This routine performs a printf like parse over the argument
356  * key, given a string of items to pack and assembles the key in
357  * the packed structure.  This routine is called (currently) by
358  * nss_default_key2str, but will be used by other external
359  * APIs in the future.
360  *
361  * buffer - Start of the key buffer location [in packed buffer]
362  * length - Length of key buffer component
363  * Key offsets are relative to start of key buffer location.
364  *
365  * Pack fields			Key
366  *   key.name			n
367  *   key.number			N
368  *   key.uid			u
369  *   key.gid			g
370  *   key.hostaddr		h
371  *   key.ipnode			i
372  *   key.projid			p
373  *   key.serv(name)		s
374  *   key.serv(port)		S
375  *   key.ether			e
376  *   key.pkey			k
377  *   key.netaddr		a
378  *   key.attrp			A
379  *   groupsbymember		I
380  *   innetgr_args		t
381  *   setnetgr_args		T
382  */
383 
384 /*ARGSUSED*/
385 static nss_status_t
386 nss_pack_key2str(void *buffer, size_t length, nss_XbyY_args_t *arg,
387 	const char *dbname, int dbop, size_t *rlen, const char *typestr)
388 {
389 	int				i, j;
390 	size_t				len, len2, len3, len4, len5, slop;
391 	nssuint_t 			*uptr, offv, offc;
392 	struct nss_setnetgrent_args	*sng;
393 	struct nss_innetgr_args		*ing;
394 	struct nss_groupsbymem		*gbm;
395 	char				**cv, *dptr;
396 	nss_pnetgr_t			*pptr;
397 	_priv_execattr			*pe;
398 
399 	if (buffer == NULL || length == 0 || arg == NULL ||
400 	    dbname == NULL || rlen == NULL || typestr == NULL)
401 		return (NSS_ERROR);
402 
403 	while (typestr && *typestr) {
404 		switch (*typestr++) {
405 		case 'n':
406 			if (arg->key.name == NULL)
407 				return (NSS_NOTFOUND);
408 			len = strlen(arg->key.name) + 1;
409 			if (len >= length)
410 				return (NSS_ERROR);
411 			(void) strlcpy(buffer, arg->key.name, len);
412 			*rlen = len;
413 			break;
414 		case 'N':
415 			len = sizeof (nssuint_t);
416 			if (len >= length)
417 				return (NSS_ERROR);
418 			*(nssuint_t *)buffer = (nssuint_t)arg->key.number;
419 			*rlen = len;
420 			break;
421 		case 'u':
422 			len = sizeof (nssuint_t);
423 			if (len >= length)
424 				return (NSS_ERROR);
425 			*(nssuint_t *)buffer = (nssuint_t)arg->key.uid;
426 			*rlen = len;
427 			break;
428 		case 'g':
429 			len = sizeof (nssuint_t);
430 			if (len >= length)
431 				return (NSS_ERROR);
432 			*(nssuint_t *)buffer = (nssuint_t)arg->key.gid;
433 			*rlen = len;
434 			break;
435 		case 'h':
436 			if (arg->key.hostaddr.addr == NULL)
437 				return (-1);
438 			len = arg->key.hostaddr.len;
439 			len = ROUND_UP(len, sizeof (nssuint_t));
440 			len2 = (sizeof (nssuint_t) * 2) + len;
441 			if (len2 >= length)
442 				return (NSS_ERROR);
443 			*(nssuint_t *)buffer =
444 			    (nssuint_t)arg->key.hostaddr.len;
445 			buffer = (void *)((char *)buffer + sizeof (nssuint_t));
446 			*(nssuint_t *)buffer =
447 			    (nssuint_t)arg->key.hostaddr.type;
448 			buffer = (void *)((char *)buffer + sizeof (nssuint_t));
449 			(void) memcpy(buffer, arg->key.hostaddr.addr,
450 				    arg->key.hostaddr.len);
451 			*rlen = len2;
452 			break;
453 		case 'i':
454 			if (arg->key.ipnode.name == NULL)
455 				return (NSS_NOTFOUND);
456 			len = strlen(arg->key.ipnode.name) + 1;
457 			len = ROUND_UP(len, sizeof (nssuint_t));
458 			len2 = (sizeof (nssuint_t) * 2) + len;
459 			if (len2 >= length)
460 				return (NSS_ERROR);
461 			*(nssuint_t *)buffer =
462 			    (nssuint_t)arg->key.ipnode.af_family;
463 			buffer = (void *)((char *)buffer + sizeof (nssuint_t));
464 			*(nssuint_t *)buffer =
465 			    (nssuint_t)arg->key.ipnode.flags;
466 			buffer = (void *)((char *)buffer + sizeof (nssuint_t));
467 			(void) strlcpy(buffer, arg->key.ipnode.name, len);
468 			*rlen = len2;
469 			break;
470 		case 'p':
471 			len = sizeof (nssuint_t);
472 			if (len >= length)
473 				return (NSS_ERROR);
474 			*(nssuint_t *)buffer = (nssuint_t)arg->key.projid;
475 			*rlen = len;
476 			break;
477 		case 's':
478 			if (arg->key.serv.serv.name == NULL)
479 				return (NSS_NOTFOUND);
480 			len = strlen(arg->key.serv.serv.name) + 1;
481 			len2 = 1;
482 			if (arg->key.serv.proto != NULL)
483 				len2 += strlen(arg->key.serv.proto);
484 			len3 = len + len2;
485 			len3 = ROUND_UP(len3, sizeof (nssuint_t));
486 			if (len3 >= length)
487 				return (NSS_ERROR);
488 			(void) strlcpy(buffer, arg->key.serv.serv.name, len);
489 			buffer = (void *)((char *)buffer + len);
490 			if (len2 > 1)
491 				(void) strlcpy(buffer, arg->key.serv.proto,
492 						len2);
493 			else
494 				*(char *)buffer = '\0';
495 			*rlen = len3;
496 			break;
497 		case 'S':
498 			len2 = 0;
499 			if (arg->key.serv.proto != NULL)
500 				len2 = strlen(arg->key.serv.proto) + 1;
501 			len = sizeof (nssuint_t) + len2;
502 			if (len >= length)
503 				return (NSS_ERROR);
504 			uptr = (nssuint_t *)buffer;
505 			*uptr++ = (nssuint_t)arg->key.serv.serv.port;
506 			if (len2) {
507 				(void) strlcpy((char *)uptr,
508 						arg->key.serv.proto, len2);
509 			}
510 			*rlen = len;
511 			break;
512 		case 'e':
513 			if (arg->key.ether == NULL)
514 				return (NSS_NOTFOUND);
515 			len = sizeof (struct ether_addr);
516 			len = ROUND_UP(len, sizeof (nssuint_t));
517 			if (len >= length)
518 				return (NSS_ERROR);
519 			*(struct ether_addr *)buffer =
520 					*(struct ether_addr *)arg->key.ether;
521 			*rlen = len;
522 			break;
523 		case 'k':
524 			if (arg->key.pkey.name == NULL ||
525 			    arg->key.pkey.keytype == NULL)
526 				return (NSS_NOTFOUND);
527 			len = strlen(arg->key.pkey.name) + 1;
528 			len2 = strlen(arg->key.pkey.keytype) + 1;
529 			len3 = len + len2;
530 			len3 = ROUND_UP(len3, sizeof (nssuint_t));
531 			if (len3 >= length)
532 				return (NSS_ERROR);
533 			(void) strlcpy(buffer, arg->key.pkey.name, len);
534 			buffer = (void *)((char *)buffer + len);
535 			(void) strlcpy(buffer, arg->key.pkey.keytype, len2);
536 			*rlen = len3;
537 			break;
538 		case 'a':
539 			uptr = (nssuint_t *)buffer;
540 			len = sizeof (nssuint_t) * 2;
541 			if (len >= length)
542 				return (NSS_ERROR);
543 			*uptr++ = (nssuint_t)arg->key.netaddr.net;
544 			*uptr++ = (nssuint_t)arg->key.netaddr.type;
545 			*rlen = len;
546 			break;
547 		case 'A':
548 			pe = (_priv_execattr *)(arg->key.attrp);
549 			if (pe == NULL)
550 				return (NSS_NOTFOUND);
551 			/* for search flag */
552 			len = sizeof (nssuint_t);
553 			/* for sizeof (_priv_execattr) static buffer */
554 			/* Plus lots of slop just in case... */
555 			slop = sizeof (nssuint_t) * 16;
556 			len += slop;
557 
558 			len2 = len3 = len4 = len5 = 1;
559 			if (pe->name != NULL)
560 				len2 = strlen(pe->name) + 1;
561 			if (pe->type != NULL)
562 				len3 = strlen(pe->type) + 1;
563 			if (pe->id != NULL)
564 				len4 = strlen(pe->id) + 1;
565 			if (pe->policy != NULL)
566 				len5 = strlen(pe->policy) + 1;
567 			/* head_exec, prev_exec - are client side only... */
568 			len += len2 + len3 + len4 + len5;
569 			len = ROUND_UP(len, sizeof (nssuint_t));
570 			if (len >= length)
571 				return (NSS_ERROR);
572 			(void) memset((void *)buffer, 0, slop);
573 			uptr = (nssuint_t *)((void *)((char *)buffer + slop));
574 			*uptr++ = (nssuint_t)pe->search_flag;
575 			dptr = (char *)uptr;
576 			if (len2 == 1)
577 				*dptr++ = '\0';
578 			else {
579 				(void) strlcpy(dptr, pe->name, len2);
580 				dptr += len2;
581 			}
582 			if (len3 == 1)
583 				*dptr++ = '\0';
584 			else {
585 				(void) strlcpy(dptr, pe->type, len3);
586 				dptr += len3;
587 			}
588 			if (len4 == 1)
589 				*dptr++ = '\0';
590 			else {
591 				(void) strlcpy(dptr, pe->id, len4);
592 				dptr += len4;
593 			}
594 			if (len5 == 1)
595 				*dptr++ = '\0';
596 			else
597 				(void) strlcpy(dptr, pe->policy, len5);
598 			*rlen = len;
599 			break;
600 		case 'I':
601 			gbm = (struct nss_groupsbymem *)arg;
602 			if (gbm->username == NULL)
603 				return (NSS_NOTFOUND);
604 			len = strlen(gbm->username) + 1;
605 			len2 = sizeof (nssuint_t) * 4;
606 			len2 += ROUND_UP(len, sizeof (nssuint_t));
607 			if (len2 >= length)
608 				return (NSS_ERROR);
609 			uptr = (nssuint_t *)buffer;
610 			*uptr++ = (nssuint_t)gbm->force_slow_way;
611 			*uptr++ = (nssuint_t)gbm->maxgids;
612 			*uptr++ = (nssuint_t)gbm->numgids;
613 			if (gbm->numgids == 1) {
614 				*uptr++ = (nssuint_t)gbm->gid_array[0];
615 			} else {
616 				*uptr++ = (nssuint_t)0;
617 			}
618 			(void) strlcpy((void *)uptr, gbm->username, len);
619 			*rlen = len2;
620 			break;
621 		case 't':
622 			pptr = (nss_pnetgr_t *)buffer;
623 			ing = (struct nss_innetgr_args *)arg;
624 			len = sizeof (nss_pnetgr_t);
625 			len2 = ing->arg[NSS_NETGR_MACHINE].argc +
626 				ing->arg[NSS_NETGR_USER].argc +
627 				ing->arg[NSS_NETGR_DOMAIN].argc +
628 				ing->groups.argc;
629 			len2 *= sizeof (nssuint_t);
630 			len3 = 0;
631 			for (j = 0; j < NSS_NETGR_N; j++) {
632 				cv = ing->arg[j].argv;
633 				for (i = ing->arg[j].argc; --i >= 0; ) {
634 					if (*cv)
635 						len3 += strlen(*cv++) + 1;
636 				}
637 			}
638 			cv = ing->groups.argv;
639 			for (i = ing->groups.argc; --i >= 0; ) {
640 				if (*cv)
641 					len3 += strlen(*cv++) + 1;
642 			}
643 			len3 = ROUND_UP(len3, sizeof (nssuint_t));
644 			/*
645 			 * Double argv space. Reason:
646 			 *    First 1/2 offsets
647 			 *    Second 1/2 for client side pointer arrays
648 			 *    resolves malloc/free issues with unpacked argvs
649 			 */
650 			if ((len + (len2 << 1) + len3) >= length)
651 				return (NSS_ERROR);
652 			*rlen = len + (len2 << 1) + len3;
653 
654 			pptr->machine_argc = ing->arg[NSS_NETGR_MACHINE].argc;
655 			pptr->user_argc = ing->arg[NSS_NETGR_USER].argc;
656 			pptr->domain_argc = ing->arg[NSS_NETGR_DOMAIN].argc;
657 			pptr->groups_argc = ing->groups.argc;
658 			offv = len;
659 			uptr = (nssuint_t *)((void *)((char *)buffer + offv));
660 			offc = len + (len2 << 1);
661 			dptr = (char *)buffer + offc;
662 			if (pptr->machine_argc == 0) {
663 				pptr->machine_offv = (nssuint_t)0;
664 			} else {
665 				pptr->machine_offv = offv;
666 				cv = ing->arg[NSS_NETGR_MACHINE].argv;
667 				i = pptr->machine_argc;
668 				offv += sizeof (nssuint_t) * i;
669 				for (; --i >= 0; ) {
670 					*uptr++ = offc;
671 					len3 = strlen(*cv) + 1;
672 					(void) strlcpy(dptr, *cv++, len3);
673 					offc += len3;
674 					dptr += len3;
675 				}
676 			}
677 			if (pptr->user_argc == 0) {
678 				pptr->user_offv = (nssuint_t)0;
679 			} else {
680 				pptr->user_offv = offv;
681 				cv = ing->arg[NSS_NETGR_USER].argv;
682 				i = pptr->user_argc;
683 				offv += sizeof (nssuint_t) * i;
684 				for (; --i >= 0; ) {
685 					*uptr++ = offc;
686 					len3 = strlen(*cv) + 1;
687 					(void) strlcpy(dptr, *cv++, len3);
688 					offc += len3;
689 					dptr += len3;
690 				}
691 			}
692 			if (pptr->domain_argc == 0) {
693 				pptr->domain_offv = (nssuint_t)0;
694 			} else {
695 				pptr->domain_offv = offv;
696 				cv = ing->arg[NSS_NETGR_DOMAIN].argv;
697 				i = pptr->domain_argc;
698 				offv += sizeof (nssuint_t) * i;
699 				for (; --i >= 0; ) {
700 					*uptr++ = offc;
701 					len3 = strlen(*cv) + 1;
702 					(void) strlcpy(dptr, *cv++, len3);
703 					offc += len3;
704 					dptr += len3;
705 				}
706 			}
707 			if (pptr->groups_argc == 0) {
708 				pptr->groups_offv = (nssuint_t)0;
709 			} else {
710 				pptr->groups_offv = offv;
711 				cv = ing->groups.argv;
712 				i = pptr->groups_argc;
713 				offv += sizeof (nssuint_t) * i;
714 				for (; --i >= 0; ) {
715 					*uptr++ = offc;
716 					len3 = strlen(*cv) + 1;
717 					(void) strlcpy(dptr, *cv++, len3);
718 					offc += len3;
719 					dptr += len3;
720 				}
721 			}
722 			break;
723 		case 'T':
724 			sng = (struct nss_setnetgrent_args *)arg;
725 			if (sng->netgroup == NULL)
726 				return (NSS_NOTFOUND);
727 			len = strlen(sng->netgroup) + 1;
728 			if (len >= length)
729 				return (NSS_ERROR);
730 			(void) strlcpy(buffer, sng->netgroup, len);
731 			*rlen = len;
732 			break;
733 		default:
734 			return (NSS_ERROR);
735 		}
736 	}
737 	return (NSS_SUCCESS);
738 }
739 
740 nss_status_t
741 nss_default_key2str(void *buffer, size_t length, nss_XbyY_args_t *arg,
742 	const char *dbname, int dbop, size_t *rlen)
743 {
744 	int		index;
745 
746 	if (buffer == NULL || length == 0 || arg == NULL ||
747 	    dbname == NULL || rlen == NULL)
748 		return (NSS_ERROR);
749 
750 	/*
751 	 * If this is not one of the well known getXbyYs
752 	 * (IE _printers special processing etc.) use a
753 	 * local (non-nscd) getXbyY lookup.
754 	 */
755 	if ((index = nss_dbop_search(dbname, (uint32_t)dbop)) < 0)
756 		return (NSS_TRYLOCAL);
757 
758 	return (nss_pack_key2str(buffer, length, arg, dbname,
759 				dbop, rlen, getXbyY_to_dbop[index].tostr));
760 }
761 
762 /*ARGSUSED*/
763 void
764 nss_packed_set_status(void *buffer, size_t length, nss_status_t status,
765 		nss_XbyY_args_t *arg)
766 {
767 	nss_pheader_t 	*pbuf = (nss_pheader_t *)buffer;
768 	nss_dbd_t	*pdbd;
769 	char		*dbn;
770 
771 	/* sidestep odd cases */
772 	pdbd = (nss_dbd_t *)((void *)((char *)buffer + pbuf->dbd_off));
773 	dbn = (char *)pdbd + pdbd->o_name;
774 	if (pbuf->nss_dbop == NSS_DBOP_GROUP_BYMEMBER) {
775 		if (strcmp(dbn, NSS_DBNAM_GROUP) == 0) {
776 			struct nss_groupsbymem *in =
777 				(struct nss_groupsbymem *)arg;
778 
779 			if (in->numgids >= 0) {
780 				pbuf->p_status = NSS_SUCCESS;
781 				pbuf->data_len = in->numgids *
782 					sizeof (gid_t);
783 				pbuf->p_herrno = 0;
784 			} else {
785 				pbuf->p_status = status;
786 				pbuf->p_errno = errno;
787 				pbuf->data_len = 0;
788 				pbuf->p_herrno = (uint32_t)arg->h_errno;
789 			}
790 			return;
791 		}
792 	}
793 	if (pbuf->nss_dbop == NSS_DBOP_NETGROUP_IN) {
794 		if (strcmp(dbn, NSS_DBNAM_NETGROUP) == 0) {
795 			struct nss_innetgr_args *in =
796 				(struct nss_innetgr_args *)arg;
797 
798 			/* tell nss_unpack() operation is successful */
799 			pbuf->data_len = 1;
800 
801 			if (in->status == NSS_NETGR_FOUND) {
802 				pbuf->p_status = NSS_SUCCESS;
803 			} else {
804 				pbuf->p_status = NSS_NOTFOUND;
805 				pbuf->p_errno = errno;
806 			}
807 			return;
808 		}
809 	}
810 
811 	/* process normal cases */
812 	if ((pbuf->p_status = status) != NSS_SUCCESS) {
813 		if (arg->erange == 1)
814 			pbuf->p_errno = ERANGE;
815 		else
816 			pbuf->p_errno = errno;
817 	} else
818 		pbuf->p_errno = 0;
819 	if (arg != NULL) {
820 		pbuf->p_herrno = (uint32_t)arg->h_errno;
821 		pbuf->data_len = (nssuint_t)arg->returnlen;
822 	} else {
823 		pbuf->p_herrno = 0;
824 		pbuf->data_len = 0;
825 	}
826 }
827 
828 /*
829  * nss_upack_key2arg
830  * Private string to key unpacking function for getXbyY routines
831  * This routine performs a scanf/printf like parse over the packed
832  * string, to uppack and re-assemble the key in the args structure.
833  *
834  * buffer - Start of the key buffer location [in packed buffer]
835  * length - Length of key buffer component
836  * Key offsets are relative to start of key buffer location.
837  *
838  * Unpack fields		Key
839  *   key.name			n
840  *   key.number			N
841  *   key.uid			u
842  *   key.gid			g
843  *   key.hostaddr		h
844  *   key.ipnode			i
845  *   key.projid			p
846  *   key.serv(name)		s
847  *   key.serv(port)		S
848  *   key.ether			e
849  *   key.pkey			k
850  *   key.netaddr		a
851  *   key.attrp			A
852  *   groupsbymember		I
853  *   innetgr_args		t
854  *   setnetgr_args		T
855  * Assumes arguments are all valid
856  */
857 
858 /*ARGSUSED*/
859 static nss_status_t
860 nss_upack_key2arg(void *buffer, size_t length, char **dbname,
861 		int *dbop, nss_XbyY_args_t *arg, int index)
862 {
863 	nss_pheader_t 			*pbuf = (nss_pheader_t *)buffer;
864 	const char			*strtype = NULL;
865 	nssuint_t 			off, *uptr;
866 	size_t				len, slop;
867 	int				i, j;
868 	char				**cv, *bptr;
869 	struct nss_setnetgrent_args	*sng;
870 	struct nss_innetgr_args		*ing;
871 	struct nss_groupsbymem		*gbm;
872 	nss_pnetgr_t			*pptr;
873 	_priv_execattr			*pe;
874 
875 	off = pbuf->key_off;
876 	bptr = (char *)buffer + off;
877 	uptr = (nssuint_t *)((void *)bptr);
878 	strtype = getXbyY_to_dbop[index].tostr;
879 	if (strtype == NULL)
880 		return (NSS_ERROR);
881 	while (*strtype) {
882 		switch (*strtype++) {
883 		case 'n':
884 			arg->key.name = (const char *)bptr;
885 			break;
886 		case 'N':
887 			arg->key.number = (int)(*uptr);
888 			break;
889 		case 'u':
890 			arg->key.uid = (uid_t)(*uptr);
891 			break;
892 		case 'g':
893 			arg->key.gid = (gid_t)(*uptr);
894 			break;
895 		case 'h':
896 			arg->key.hostaddr.len = (int)(*uptr++);
897 			arg->key.hostaddr.type = (int)(*uptr++);
898 			arg->key.hostaddr.addr = (const char *)uptr;
899 			break;
900 		case 'i':
901 			arg->key.ipnode.af_family = (int)(*uptr++);
902 			arg->key.ipnode.flags = (int)(*uptr++);
903 			arg->key.ipnode.name = (const char *)uptr;
904 			break;
905 		case 'p':
906 			arg->key.projid = (projid_t)(*uptr);
907 			break;
908 		case 's':
909 			arg->key.serv.serv.name = (const char *)bptr;
910 			len = strlen(arg->key.serv.serv.name) + 1;
911 			bptr += len;
912 			if (*(const char *)bptr == '\0')
913 				arg->key.serv.proto = NULL;
914 			else
915 				arg->key.serv.proto = (const char *)bptr;
916 			break;
917 		case 'S':
918 			arg->key.serv.serv.port = (int)(*uptr++);
919 			if (pbuf->key_len == sizeof (nssuint_t)) {
920 				arg->key.serv.proto = NULL;
921 			} else {
922 				bptr += sizeof (nssuint_t);
923 				arg->key.serv.proto = (const char *)bptr;
924 			}
925 			break;
926 		case 'e':
927 			arg->key.ether = bptr;
928 			break;
929 		case 'k':
930 			arg->key.pkey.name = (const char *)bptr;
931 			len = strlen(arg->key.pkey.name) + 1;
932 			bptr += len;
933 			arg->key.pkey.keytype = (const char *)bptr;
934 			break;
935 		case 'a':
936 			arg->key.netaddr.net = (uint32_t)(*uptr++);
937 			arg->key.netaddr.type = (int)(*uptr++);
938 			break;
939 		case 'A':
940 			pe = (_priv_execattr *)((void *)bptr);
941 			/* use slop space as priv_execattr structure */
942 			arg->key.attrp = (void *)pe;
943 			/* skip over slop ... */
944 			slop = sizeof (nssuint_t) * 16;
945 			uptr = (nssuint_t *)((void *)((char *)bptr + slop));
946 			pe->search_flag = (int)*uptr++;
947 			bptr = (char *)uptr;
948 			if (*bptr == '\0') {
949 				pe->name = NULL;
950 				bptr++;
951 			} else {
952 				pe->name = (char *)bptr;
953 				bptr += strlen(pe->name) + 1;
954 			}
955 			if (*bptr == '\0') {
956 				pe->type = NULL;
957 				bptr++;
958 			} else {
959 				pe->type = (char *)bptr;
960 				bptr += strlen(pe->type) + 1;
961 			}
962 			if (*bptr == '\0') {
963 				pe->id = NULL;
964 				bptr++;
965 			} else {
966 				pe->id = (char *)bptr;
967 				bptr += strlen(pe->id) + 1;
968 			}
969 			if (*bptr == '\0') {
970 				pe->policy = NULL;
971 			} else {
972 				pe->policy = (char *)bptr;
973 			}
974 			pe->head_exec = NULL;
975 			pe->prev_exec = NULL;
976 			break;
977 		case 'I':
978 			gbm = (struct nss_groupsbymem *)arg;
979 			gbm->gid_array = (gid_t *)
980 				((void *)((char *)pbuf + pbuf->data_off));
981 			gbm->force_slow_way = (int)(*uptr++);
982 			gbm->maxgids = (int)(*uptr++);
983 			gbm->numgids = (int)(*uptr++);
984 			if (gbm->numgids == 1) {
985 				/* insert initial group into data area */
986 				gbm->gid_array[0] = (gid_t)(*uptr++);
987 			} else
988 				uptr++;
989 			gbm->username = (const char *)uptr;
990 			break;
991 		case 't':
992 			pptr = (nss_pnetgr_t *)((void *)bptr);
993 			ing = (struct nss_innetgr_args *)arg;
994 			ing->arg[NSS_NETGR_MACHINE].argc = pptr->machine_argc;
995 			ing->arg[NSS_NETGR_USER].argc = pptr->user_argc;
996 			ing->arg[NSS_NETGR_DOMAIN].argc = pptr->domain_argc;
997 			ing->groups.argc = pptr->groups_argc;
998 
999 			/*
1000 			 * Start of argv pointer storage
1001 			 */
1002 			off = ing->arg[NSS_NETGR_MACHINE].argc +
1003 				ing->arg[NSS_NETGR_USER].argc +
1004 				ing->arg[NSS_NETGR_DOMAIN].argc +
1005 				ing->groups.argc;
1006 			off *= sizeof (nssuint_t);
1007 			off += sizeof (nss_pnetgr_t);
1008 
1009 			cv = (char **)((void *)(bptr + off));
1010 			uptr = (nssuint_t *)
1011 				((void *)(bptr + sizeof (nss_pnetgr_t)));
1012 			for (j = 0; j < NSS_NETGR_N; j++) {
1013 				ing->arg[j].argv = cv;
1014 				for (i = 0; i < ing->arg[j].argc; i++) {
1015 					*cv++ = (bptr + *uptr++);
1016 				}
1017 			}
1018 			ing->groups.argv = cv;
1019 			for (i = 0; i < ing->groups.argc; i++) {
1020 				*cv++ = (bptr + *uptr++);
1021 			}
1022 			break;
1023 		case 'T':
1024 			sng = (struct nss_setnetgrent_args *)arg;
1025 			sng->netgroup = (const char *)bptr;
1026 			sng->iterator = 0;
1027 			break;
1028 
1029 		default:
1030 			return (NSS_ERROR);
1031 		}
1032 	}
1033 	return (NSS_SUCCESS);
1034 }
1035 
1036 static nss_status_t
1037 nss_pinit_funcs(int index, nss_db_initf_t *initf, nss_str2ent_t *s2e)
1038 {
1039 	const char	*name;
1040 	void	*handle;
1041 	void	*sym;
1042 
1043 	if ((handle = dlopen((const char *)0, RTLD_LAZY)) != NULL) {
1044 		if (initf) {
1045 			name = getXbyY_to_dbop[index].initfn;
1046 			if ((sym = dlsym(handle, name)) == 0) {
1047 				(void) dlclose(handle);
1048 				return (NSS_ERROR);
1049 			} else {
1050 				*initf = (nss_db_initf_t)sym;
1051 			}
1052 		}
1053 		if (s2e) {
1054 			name = getXbyY_to_dbop[index].strfn;
1055 			if ((sym = dlsym(handle, name)) == 0) {
1056 				(void) dlclose(handle);
1057 				return (NSS_ERROR);
1058 			} else {
1059 				*s2e = (nss_str2ent_t)sym;
1060 			}
1061 		}
1062 	}
1063 	return (NSS_SUCCESS);
1064 }
1065 
1066 nss_status_t
1067 nss_packed_getkey(void *buffer, size_t length, char **dbname,
1068 		int *dbop, nss_XbyY_args_t *arg)
1069 {
1070 	nss_pheader_t 	*pbuf = (nss_pheader_t *)buffer;
1071 	nss_dbd_t	*pdbd;
1072 	nssuint_t 	off;
1073 	int		index;
1074 
1075 	if (buffer == NULL || length == 0 || dbop == NULL ||
1076 			arg == NULL || dbname == NULL)
1077 		return (NSS_ERROR);
1078 
1079 	*dbop = pbuf->nss_dbop;
1080 	off = pbuf->dbd_off;
1081 	pdbd = (nss_dbd_t *)((void *)((char *)buffer + off));
1082 	*dbname = (char *)buffer + off + pdbd->o_name;
1083 	if ((index = nss_dbop_search(*dbname, (uint32_t)*dbop)) < 0)
1084 		return (NSS_ERROR);
1085 	return (nss_upack_key2arg(buffer, length, dbname, dbop, arg, index));
1086 }
1087 
1088 
1089 /*
1090  * str2packent: Standard format interposed str2X function for normal APIs
1091  *
1092  * Return values: 0 = success, 1 = parse error, 2 = erange ...
1093  *
1094  * The structure pointer is ignored since this is a nscd side packed request.
1095  * The client side routine does all the real parsing; we just check limits and
1096  * store the entry in the buffer we were passed by the caller.
1097  */
1098 
1099 /*ARGSUSED*/
1100 static int
1101 str2packent(
1102     const char *instr,
1103     int lenstr,
1104     void *ent,		/* really (char *) */
1105     char *buffer,
1106     int buflen
1107 )
1108 {
1109 	if (buflen <= lenstr) {		/* not enough buffer */
1110 		return (NSS_STR_PARSE_ERANGE);
1111 	}
1112 	(void) memmove(buffer, instr, lenstr);
1113 	buffer[lenstr] = '\0';
1114 
1115 	return (NSS_STR_PARSE_SUCCESS);
1116 }
1117 
1118 /*
1119  * Initialize db_root, initf, dbop and arg from a packed buffer
1120  */
1121 
1122 /*ARGSUSED*/
1123 nss_status_t
1124 nss_packed_arg_init(void *buffer, size_t length, nss_db_root_t *db_root,
1125 		nss_db_initf_t *initf, int *dbop, nss_XbyY_args_t *arg)
1126 {
1127 	nss_pheader_t 		*pbuf = (nss_pheader_t *)buffer;
1128 	nss_str2ent_t		s2e = str2packent;
1129 	nss_str2ent_t		real_s2e = NULL;
1130 	nss_dbd_t		*pdbd;
1131 	nssuint_t 		off;
1132 	char			*dbname, *bptr;
1133 	size_t			len;
1134 	int			index;
1135 
1136 	if (buffer == NULL || length == 0 ||
1137 			dbop == NULL || arg == NULL)
1138 		return (NSS_ERROR);
1139 
1140 	/* init dbop */
1141 	*dbop = pbuf->nss_dbop;
1142 	off = pbuf->dbd_off;
1143 	pdbd = (nss_dbd_t *)((void *)((char *)buffer + off));
1144 	dbname = (char *)buffer + off + pdbd->o_name;
1145 	if ((index = nss_dbop_search(dbname, (uint32_t)*dbop)) < 0)
1146 		return (NSS_ERROR);
1147 
1148 	/* db_root is initialized by nscd's based on door info */
1149 	/* do nothing here */
1150 
1151 	/* init key information - (and get dbname dbop etc...) */
1152 	if (nss_upack_key2arg(buffer, length, &dbname,
1153 				dbop, arg, index) != NSS_SUCCESS)
1154 		return (NSS_ERROR);
1155 
1156 	/* possible audituser init */
1157 	if (strcmp(dbname, NSS_DBNAM_AUTHATTR) == 0)
1158 		arg->h_errno = (int)pbuf->p_herrno;
1159 
1160 	bptr = (char *)buffer + pbuf->data_off;
1161 	len = (size_t)pbuf->data_len;
1162 
1163 	/* sidestep odd arg cases */
1164 	if (*dbop == NSS_DBOP_GROUP_BYMEMBER &&
1165 	    strcmp(dbname, NSS_DBNAM_GROUP) == 0) {
1166 		/* get initf  and str2ent functions */
1167 		if (nss_pinit_funcs(index, initf, &real_s2e) != NSS_SUCCESS)
1168 			return (NSS_ERROR);
1169 		((struct nss_groupsbymem *)arg)->str2ent = real_s2e;
1170 		((struct nss_groupsbymem *)arg)->process_cstr = process_cstr;
1171 		return (NSS_SUCCESS);
1172 	}
1173 	if (pbuf->nss_dbop == NSS_DBOP_NETGROUP_IN &&
1174 		strcmp(dbname, NSS_DBNAM_NETGROUP) == 0) {
1175 		return (NSS_SUCCESS);
1176 	}
1177 
1178 	/* get initf  and str2ent functions */
1179 	if (nss_pinit_funcs(index, initf, NULL) != NSS_SUCCESS)
1180 		return (NSS_ERROR);
1181 
1182 	/* init normal arg cases */
1183 	NSS_XbyY_INIT(arg, NULL, bptr, len, s2e);
1184 	arg->h_errno = 0;
1185 
1186 	return (NSS_SUCCESS);
1187 }
1188 
1189 /*
1190  * Initialize db_root, initf, dbop, contextp and arg from a packed buffer
1191  */
1192 
1193 /*ARGSUSED*/
1194 nss_status_t
1195 nss_packed_context_init(void *buffer, size_t length, nss_db_root_t *db_root,
1196 		nss_db_initf_t *initf, nss_getent_t **contextp,
1197 		nss_XbyY_args_t *arg)
1198 {
1199 	nss_pheader_t 	*pbuf = (nss_pheader_t *)buffer;
1200 	nss_str2ent_t	s2e = str2packent;
1201 	char		*bptr;
1202 	size_t		len;
1203 
1204 	/* init arg */
1205 	if (arg != NULL) {
1206 		bptr = (char *)buffer + pbuf->data_off;
1207 		len = (size_t)pbuf->data_len;
1208 		NSS_XbyY_INIT(arg, NULL, bptr, len, s2e);
1209 	}
1210 
1211 	return (NSS_SUCCESS);
1212 }
1213