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