1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 1998-2002 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate 
28*0Sstevel@tonic-gate /*
29*0Sstevel@tonic-gate  * nis_common.c
30*0Sstevel@tonic-gate  *
31*0Sstevel@tonic-gate  * Common code and structures used by name-service-switch "nis" backends.
32*0Sstevel@tonic-gate  */
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
35*0Sstevel@tonic-gate 
36*0Sstevel@tonic-gate #include "nis_common.h"
37*0Sstevel@tonic-gate #include <string.h>
38*0Sstevel@tonic-gate #include <synch.h>
39*0Sstevel@tonic-gate #include <rpcsvc/ypclnt.h>
40*0Sstevel@tonic-gate #include <rpcsvc/yp_prot.h>
41*0Sstevel@tonic-gate #include <thread.h>
42*0Sstevel@tonic-gate #include <ctype.h>
43*0Sstevel@tonic-gate #include <stdlib.h>
44*0Sstevel@tonic-gate #include <signal.h>
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate #ifndef	MT_UNSAFE_YP		/* Is the libnsl YP client code MT-unsafe? */
47*0Sstevel@tonic-gate #define	MT_UNSAFE_YP	0	/* No, not any longer */
48*0Sstevel@tonic-gate #endif
49*0Sstevel@tonic-gate 
50*0Sstevel@tonic-gate #if	MT_UNSAFE_YP
51*0Sstevel@tonic-gate static mutex_t	one_lane = DEFAULTMUTEX;
52*0Sstevel@tonic-gate #endif
53*0Sstevel@tonic-gate 
54*0Sstevel@tonic-gate /* <rpcsvc/ypclnt.h> uses (char *) where it should use (const char *) */
55*0Sstevel@tonic-gate typedef char *grrr;
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate /*
58*0Sstevel@tonic-gate  * The YP client code thinks it's being helpful by appending '\n' and '\0'
59*0Sstevel@tonic-gate  *   to the values returned by yp_match() et al.  In order to do this it
60*0Sstevel@tonic-gate  *   ends up doing more malloc()ing and data copying than would otherwise
61*0Sstevel@tonic-gate  *   be necessary.  If we're interested in performance we should provide
62*0Sstevel@tonic-gate  *   alternative library interfaces that skip the helpfulness and instead
63*0Sstevel@tonic-gate  *   let the XDR routines dump the value directly into the buffer where
64*0Sstevel@tonic-gate  *   we really want it.  For now, though, we just use the vanilla interface.
65*0Sstevel@tonic-gate  */
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate static nss_status_t
68*0Sstevel@tonic-gate switch_err(ypstatus, ismatch)
69*0Sstevel@tonic-gate 	int			ypstatus;
70*0Sstevel@tonic-gate 	int			ismatch;
71*0Sstevel@tonic-gate {
72*0Sstevel@tonic-gate 	switch (ypstatus) {
73*0Sstevel@tonic-gate 	case 0:
74*0Sstevel@tonic-gate 		return (NSS_SUCCESS);
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate 	case YPERR_BADARGS:
77*0Sstevel@tonic-gate 	case YPERR_KEY:
78*0Sstevel@tonic-gate 		return (NSS_NOTFOUND);
79*0Sstevel@tonic-gate 
80*0Sstevel@tonic-gate 		/*
81*0Sstevel@tonic-gate 		 *  When the YP server is running in DNS forwarding mode,
82*0Sstevel@tonic-gate 		 *  the forwarder will return YPERR_NOMORE to us if it
83*0Sstevel@tonic-gate 		 *  is unable to contact a server (i.e., it has timed out).
84*0Sstevel@tonic-gate 		 *  The NSS_NISSERVDNS_TRYAGAIN is returned for timeout errors.
85*0Sstevel@tonic-gate 		 */
86*0Sstevel@tonic-gate 	case YPERR_NOMORE:
87*0Sstevel@tonic-gate 		if (ismatch)
88*0Sstevel@tonic-gate 			return (NSS_NISSERVDNS_TRYAGAIN);
89*0Sstevel@tonic-gate 		else
90*0Sstevel@tonic-gate 			return (NSS_NOTFOUND);
91*0Sstevel@tonic-gate 
92*0Sstevel@tonic-gate 	case YPERR_DOMAIN:
93*0Sstevel@tonic-gate 	case YPERR_YPSERV:
94*0Sstevel@tonic-gate 	case YPERR_BUSY:
95*0Sstevel@tonic-gate 		return (NSS_TRYAGAIN);
96*0Sstevel@tonic-gate 
97*0Sstevel@tonic-gate 	default:
98*0Sstevel@tonic-gate 		return (NSS_UNAVAIL);
99*0Sstevel@tonic-gate 	}
100*0Sstevel@tonic-gate }
101*0Sstevel@tonic-gate 
102*0Sstevel@tonic-gate /*ARGSUSED*/
103*0Sstevel@tonic-gate nss_status_t
104*0Sstevel@tonic-gate _nss_nis_setent(be, dummy)
105*0Sstevel@tonic-gate 	nis_backend_ptr_t	be;
106*0Sstevel@tonic-gate 	void			*dummy;
107*0Sstevel@tonic-gate {
108*0Sstevel@tonic-gate 	if (be->enum_key != 0) {
109*0Sstevel@tonic-gate 		free(be->enum_key);
110*0Sstevel@tonic-gate 		be->enum_key = 0;
111*0Sstevel@tonic-gate 	}
112*0Sstevel@tonic-gate 	be->enum_keylen = 0;
113*0Sstevel@tonic-gate 	return (NSS_SUCCESS);
114*0Sstevel@tonic-gate }
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate nss_status_t
117*0Sstevel@tonic-gate _nss_nis_endent(be, dummy)
118*0Sstevel@tonic-gate 	nis_backend_ptr_t	be;
119*0Sstevel@tonic-gate 	void			*dummy;
120*0Sstevel@tonic-gate {
121*0Sstevel@tonic-gate 	return (_nss_nis_setent(be, dummy));
122*0Sstevel@tonic-gate 	/* Nothing else we can clean up, is there? */
123*0Sstevel@tonic-gate }
124*0Sstevel@tonic-gate 
125*0Sstevel@tonic-gate void
126*0Sstevel@tonic-gate massage_netdb(const char **valp, int *vallenp)
127*0Sstevel@tonic-gate {
128*0Sstevel@tonic-gate 	const char		*first;
129*0Sstevel@tonic-gate 	const char		*last;
130*0Sstevel@tonic-gate 	const char		*val	= *valp;
131*0Sstevel@tonic-gate 	int			vallen	= *vallenp;
132*0Sstevel@tonic-gate 
133*0Sstevel@tonic-gate 	if ((last = memchr(val, '#', vallen)) == 0) {
134*0Sstevel@tonic-gate 		last = val + vallen;
135*0Sstevel@tonic-gate 	}
136*0Sstevel@tonic-gate 	for (first = val;  first < last && isspace(*first);  first++) {
137*0Sstevel@tonic-gate 		;
138*0Sstevel@tonic-gate 	}
139*0Sstevel@tonic-gate 	for (/* cstyle */;  first < last && isspace(last[-1]);  last--) {
140*0Sstevel@tonic-gate 		;
141*0Sstevel@tonic-gate 	}
142*0Sstevel@tonic-gate 	/*
143*0Sstevel@tonic-gate 	 * Don't check for an empty line because it shouldn't ever
144*0Sstevel@tonic-gate 	 *   have made it into the YP map.
145*0Sstevel@tonic-gate 	 */
146*0Sstevel@tonic-gate 	*valp = first;
147*0Sstevel@tonic-gate 	*vallenp = (int)(last - first);
148*0Sstevel@tonic-gate }
149*0Sstevel@tonic-gate 
150*0Sstevel@tonic-gate nss_status_t
151*0Sstevel@tonic-gate _nss_nis_ypmatch(domain, map, key, valp, vallenp, ypstatusp)
152*0Sstevel@tonic-gate 	const char		*domain;
153*0Sstevel@tonic-gate 	const char		*map;
154*0Sstevel@tonic-gate 	const char		*key;
155*0Sstevel@tonic-gate 	char			**valp;
156*0Sstevel@tonic-gate 	int			*vallenp;
157*0Sstevel@tonic-gate 	int			*ypstatusp;
158*0Sstevel@tonic-gate {
159*0Sstevel@tonic-gate 	int			ypstatus;
160*0Sstevel@tonic-gate 
161*0Sstevel@tonic-gate #if	MT_UNSAFE_YP
162*0Sstevel@tonic-gate 	sigset_t		oldmask, newmask;
163*0Sstevel@tonic-gate 
164*0Sstevel@tonic-gate 	sigfillset(&newmask);
165*0Sstevel@tonic-gate 	_thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
166*0Sstevel@tonic-gate 	_mutex_lock(&one_lane);
167*0Sstevel@tonic-gate #endif
168*0Sstevel@tonic-gate 	ypstatus = __yp_match_cflookup((grrr)domain, (grrr)map,
169*0Sstevel@tonic-gate 			    (grrr)key, (int)strlen(key), valp, vallenp, 0);
170*0Sstevel@tonic-gate #if	MT_UNSAFE_YP
171*0Sstevel@tonic-gate 	_mutex_unlock(&one_lane);
172*0Sstevel@tonic-gate 	_thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
173*0Sstevel@tonic-gate #endif
174*0Sstevel@tonic-gate 
175*0Sstevel@tonic-gate 	if (ypstatusp != 0) {
176*0Sstevel@tonic-gate 		*ypstatusp = ypstatus;
177*0Sstevel@tonic-gate 	}
178*0Sstevel@tonic-gate 	return (switch_err(ypstatus, 1));
179*0Sstevel@tonic-gate }
180*0Sstevel@tonic-gate 
181*0Sstevel@tonic-gate /*
182*0Sstevel@tonic-gate  * XXX special version of _nss_nis_ypmatch() for handling C2 (passwd.adjunct)
183*0Sstevel@tonic-gate  * lookups when we need a reserved port.
184*0Sstevel@tonic-gate  */
185*0Sstevel@tonic-gate nss_status_t
186*0Sstevel@tonic-gate _nss_nis_ypmatch_rsvdport(domain, map, key, valp, vallenp, ypstatusp)
187*0Sstevel@tonic-gate 	const char		*domain;
188*0Sstevel@tonic-gate 	const char		*map;
189*0Sstevel@tonic-gate 	const char		*key;
190*0Sstevel@tonic-gate 	char			**valp;
191*0Sstevel@tonic-gate 	int			*vallenp;
192*0Sstevel@tonic-gate 	int			*ypstatusp;
193*0Sstevel@tonic-gate {
194*0Sstevel@tonic-gate 	int			ypstatus;
195*0Sstevel@tonic-gate 	extern int yp_match_rsvdport();
196*0Sstevel@tonic-gate 
197*0Sstevel@tonic-gate #if	MT_UNSAFE_YP
198*0Sstevel@tonic-gate 	sigset_t		oldmask, newmask;
199*0Sstevel@tonic-gate 
200*0Sstevel@tonic-gate 	sigfillset(&newmask);
201*0Sstevel@tonic-gate 	_thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
202*0Sstevel@tonic-gate 	_mutex_lock(&one_lane);
203*0Sstevel@tonic-gate #endif
204*0Sstevel@tonic-gate 	ypstatus = __yp_match_rsvdport_cflookup((grrr)domain, (grrr)map,
205*0Sstevel@tonic-gate 			    (grrr)key, strlen(key), valp, vallenp, 0);
206*0Sstevel@tonic-gate #if	MT_UNSAFE_YP
207*0Sstevel@tonic-gate 	_mutex_unlock(&one_lane);
208*0Sstevel@tonic-gate 	_thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
209*0Sstevel@tonic-gate #endif
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate 	if (ypstatusp != 0) {
212*0Sstevel@tonic-gate 		*ypstatusp = ypstatus;
213*0Sstevel@tonic-gate 	}
214*0Sstevel@tonic-gate 	return (switch_err(ypstatus, 1));
215*0Sstevel@tonic-gate }
216*0Sstevel@tonic-gate 
217*0Sstevel@tonic-gate nss_status_t
218*0Sstevel@tonic-gate _nss_nis_lookup(be, args, netdb, map, key, ypstatusp)
219*0Sstevel@tonic-gate 	nis_backend_ptr_t	be;
220*0Sstevel@tonic-gate 	nss_XbyY_args_t		*args;
221*0Sstevel@tonic-gate 	int			netdb;
222*0Sstevel@tonic-gate 	const char		*map;
223*0Sstevel@tonic-gate 	const char		*key;
224*0Sstevel@tonic-gate 	int			*ypstatusp;
225*0Sstevel@tonic-gate {
226*0Sstevel@tonic-gate 	nss_status_t		res;
227*0Sstevel@tonic-gate 	int			vallen;
228*0Sstevel@tonic-gate 	char			*val;
229*0Sstevel@tonic-gate 	char			*free_ptr;
230*0Sstevel@tonic-gate 	int			parsestat;
231*0Sstevel@tonic-gate 
232*0Sstevel@tonic-gate 	if ((res = _nss_nis_ypmatch(be->domain, map, key, &val, &vallen,
233*0Sstevel@tonic-gate 				    ypstatusp)) != NSS_SUCCESS) {
234*0Sstevel@tonic-gate 		return (res);
235*0Sstevel@tonic-gate 	}
236*0Sstevel@tonic-gate 
237*0Sstevel@tonic-gate 	free_ptr = val;
238*0Sstevel@tonic-gate 
239*0Sstevel@tonic-gate 	if (netdb) {
240*0Sstevel@tonic-gate 		massage_netdb((const char **)&val, &vallen);
241*0Sstevel@tonic-gate 	}
242*0Sstevel@tonic-gate 
243*0Sstevel@tonic-gate 	parsestat = (*args->str2ent)(val, vallen,
244*0Sstevel@tonic-gate 			args->buf.result, args->buf.buffer, args->buf.buflen);
245*0Sstevel@tonic-gate 	if (parsestat == NSS_STR_PARSE_SUCCESS) {
246*0Sstevel@tonic-gate 		args->returnval = args->buf.result;
247*0Sstevel@tonic-gate 		res = NSS_SUCCESS;
248*0Sstevel@tonic-gate 	} else if (parsestat == NSS_STR_PARSE_ERANGE) {
249*0Sstevel@tonic-gate 		args->erange = 1;
250*0Sstevel@tonic-gate 		/* We won't find this otherwise, anyway */
251*0Sstevel@tonic-gate 		res = NSS_NOTFOUND;
252*0Sstevel@tonic-gate 	} /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */
253*0Sstevel@tonic-gate 
254*0Sstevel@tonic-gate 	free(free_ptr);
255*0Sstevel@tonic-gate 
256*0Sstevel@tonic-gate 	return (res);
257*0Sstevel@tonic-gate }
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate nss_status_t
260*0Sstevel@tonic-gate _nss_nis_lookup_rsvdport(be, args, netdb, map, key, ypstatusp)
261*0Sstevel@tonic-gate 	nis_backend_ptr_t	be;
262*0Sstevel@tonic-gate 	nss_XbyY_args_t		*args;
263*0Sstevel@tonic-gate 	int			netdb;
264*0Sstevel@tonic-gate 	const char		*map;
265*0Sstevel@tonic-gate 	const char		*key;
266*0Sstevel@tonic-gate 	int			*ypstatusp;
267*0Sstevel@tonic-gate {
268*0Sstevel@tonic-gate 	nss_status_t		res;
269*0Sstevel@tonic-gate 	int			vallen;
270*0Sstevel@tonic-gate 	char			*val;
271*0Sstevel@tonic-gate 	char			*free_ptr;
272*0Sstevel@tonic-gate 	int			parsestat;
273*0Sstevel@tonic-gate 
274*0Sstevel@tonic-gate 	if ((res = _nss_nis_ypmatch_rsvdport(be->domain, map, key, &val,
275*0Sstevel@tonic-gate 				    &vallen, ypstatusp)) != NSS_SUCCESS) {
276*0Sstevel@tonic-gate 		return (res);
277*0Sstevel@tonic-gate 	}
278*0Sstevel@tonic-gate 
279*0Sstevel@tonic-gate 	free_ptr = val;
280*0Sstevel@tonic-gate 
281*0Sstevel@tonic-gate 	if (netdb) {
282*0Sstevel@tonic-gate 		massage_netdb((const char **)&val, &vallen);
283*0Sstevel@tonic-gate 	}
284*0Sstevel@tonic-gate 
285*0Sstevel@tonic-gate 	parsestat = (*args->str2ent)(val, vallen,
286*0Sstevel@tonic-gate 			args->buf.result, args->buf.buffer, args->buf.buflen);
287*0Sstevel@tonic-gate 	if (parsestat == NSS_STR_PARSE_SUCCESS) {
288*0Sstevel@tonic-gate 		args->returnval = args->buf.result;
289*0Sstevel@tonic-gate 		res = NSS_SUCCESS;
290*0Sstevel@tonic-gate 	} else if (parsestat == NSS_STR_PARSE_ERANGE) {
291*0Sstevel@tonic-gate 		args->erange = 1;
292*0Sstevel@tonic-gate 		/* We won't find this otherwise, anyway */
293*0Sstevel@tonic-gate 		res = NSS_NOTFOUND;
294*0Sstevel@tonic-gate 	} /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */
295*0Sstevel@tonic-gate 
296*0Sstevel@tonic-gate 	free(free_ptr);
297*0Sstevel@tonic-gate 
298*0Sstevel@tonic-gate 	return (res);
299*0Sstevel@tonic-gate }
300*0Sstevel@tonic-gate 
301*0Sstevel@tonic-gate static nss_status_t
302*0Sstevel@tonic-gate do_getent(be, args, netdb)
303*0Sstevel@tonic-gate 	nis_backend_ptr_t	be;
304*0Sstevel@tonic-gate 	nss_XbyY_args_t		*args;
305*0Sstevel@tonic-gate 	int			netdb;
306*0Sstevel@tonic-gate {
307*0Sstevel@tonic-gate 	nss_status_t		res;
308*0Sstevel@tonic-gate 	int			ypstatus;
309*0Sstevel@tonic-gate 	int			outkeylen, outvallen;
310*0Sstevel@tonic-gate 	char			*outkey, *outval;
311*0Sstevel@tonic-gate 	char			*free_ptr;
312*0Sstevel@tonic-gate 	int			parsestat;
313*0Sstevel@tonic-gate 
314*0Sstevel@tonic-gate #if	MT_UNSAFE_YP
315*0Sstevel@tonic-gate 	sigset_t		oldmask, newmask;
316*0Sstevel@tonic-gate 
317*0Sstevel@tonic-gate 	sigfillset(&newmask);
318*0Sstevel@tonic-gate 	_thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
319*0Sstevel@tonic-gate 	_mutex_lock(&one_lane);
320*0Sstevel@tonic-gate #endif
321*0Sstevel@tonic-gate 	if (be->enum_key == 0) {
322*0Sstevel@tonic-gate 		ypstatus = __yp_first_cflookup((grrr)be->domain,
323*0Sstevel@tonic-gate 					    (grrr)be->enum_map, &outkey,
324*0Sstevel@tonic-gate 					    &outkeylen, &outval,
325*0Sstevel@tonic-gate 					    &outvallen, 0);
326*0Sstevel@tonic-gate 	} else {
327*0Sstevel@tonic-gate 		ypstatus = __yp_next_cflookup((grrr)be->domain,
328*0Sstevel@tonic-gate 					    (grrr)be->enum_map, be->enum_key,
329*0Sstevel@tonic-gate 					    be->enum_keylen, &outkey,
330*0Sstevel@tonic-gate 					    &outkeylen, &outval,
331*0Sstevel@tonic-gate 					    &outvallen, 0);
332*0Sstevel@tonic-gate 	}
333*0Sstevel@tonic-gate #if	MT_UNSAFE_YP
334*0Sstevel@tonic-gate 	_mutex_unlock(&one_lane);
335*0Sstevel@tonic-gate 	_thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
336*0Sstevel@tonic-gate #endif
337*0Sstevel@tonic-gate 
338*0Sstevel@tonic-gate 	if ((res = switch_err(ypstatus, 0)) != NSS_SUCCESS) {
339*0Sstevel@tonic-gate 		return (res);
340*0Sstevel@tonic-gate 	}
341*0Sstevel@tonic-gate 
342*0Sstevel@tonic-gate 	free_ptr = outval;
343*0Sstevel@tonic-gate 
344*0Sstevel@tonic-gate 	if (netdb) {
345*0Sstevel@tonic-gate 		massage_netdb((const char **)&outval, &outvallen);
346*0Sstevel@tonic-gate 	}
347*0Sstevel@tonic-gate 
348*0Sstevel@tonic-gate 	parsestat = (*args->str2ent)(outval, outvallen,
349*0Sstevel@tonic-gate 			args->buf.result, args->buf.buffer, args->buf.buflen);
350*0Sstevel@tonic-gate 	if (parsestat == NSS_STR_PARSE_SUCCESS) {
351*0Sstevel@tonic-gate 		args->returnval = args->buf.result;
352*0Sstevel@tonic-gate 		res = NSS_SUCCESS;
353*0Sstevel@tonic-gate 	} else if (parsestat == NSS_STR_PARSE_ERANGE) {
354*0Sstevel@tonic-gate 		args->erange = 1;
355*0Sstevel@tonic-gate 		/* We won't find this otherwise, anyway */
356*0Sstevel@tonic-gate 		res = NSS_NOTFOUND;
357*0Sstevel@tonic-gate 	} /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */
358*0Sstevel@tonic-gate 
359*0Sstevel@tonic-gate 	free(free_ptr);
360*0Sstevel@tonic-gate 
361*0Sstevel@tonic-gate 	if (be->enum_key != 0) {
362*0Sstevel@tonic-gate 		free(be->enum_key);
363*0Sstevel@tonic-gate 	}
364*0Sstevel@tonic-gate 	be->enum_key = outkey;
365*0Sstevel@tonic-gate 	be->enum_keylen = outkeylen;
366*0Sstevel@tonic-gate 
367*0Sstevel@tonic-gate 	return (res);
368*0Sstevel@tonic-gate }
369*0Sstevel@tonic-gate 
370*0Sstevel@tonic-gate nss_status_t
371*0Sstevel@tonic-gate _nss_nis_getent_rigid(be, args)
372*0Sstevel@tonic-gate 	nis_backend_ptr_t	be;
373*0Sstevel@tonic-gate 	void			*args;
374*0Sstevel@tonic-gate {
375*0Sstevel@tonic-gate 	return (do_getent(be, (nss_XbyY_args_t *)args, 0));
376*0Sstevel@tonic-gate }
377*0Sstevel@tonic-gate 
378*0Sstevel@tonic-gate nss_status_t
379*0Sstevel@tonic-gate _nss_nis_getent_netdb(be, args)
380*0Sstevel@tonic-gate 	nis_backend_ptr_t	be;
381*0Sstevel@tonic-gate 	void			*args;
382*0Sstevel@tonic-gate {
383*0Sstevel@tonic-gate 	return (do_getent(be, (nss_XbyY_args_t *)args, 1));
384*0Sstevel@tonic-gate }
385*0Sstevel@tonic-gate 
386*0Sstevel@tonic-gate 
387*0Sstevel@tonic-gate struct cb_data {
388*0Sstevel@tonic-gate 	void			*args;
389*0Sstevel@tonic-gate 	const char		*filter;
390*0Sstevel@tonic-gate 	nis_do_all_func_t	func;
391*0Sstevel@tonic-gate 	nss_status_t		result;
392*0Sstevel@tonic-gate };
393*0Sstevel@tonic-gate 
394*0Sstevel@tonic-gate enum { ITER_NEXT = 0, ITER_STOP = 1 };	/* Should be in <rpcsvc/ypclnt.h> */
395*0Sstevel@tonic-gate 
396*0Sstevel@tonic-gate /*ARGSUSED*/
397*0Sstevel@tonic-gate static int
398*0Sstevel@tonic-gate do_cback(instatus, inkey, inkeylen, inval, invallen, indata)
399*0Sstevel@tonic-gate 	int			instatus;
400*0Sstevel@tonic-gate 	const char		*inkey;
401*0Sstevel@tonic-gate 	int			inkeylen;
402*0Sstevel@tonic-gate 	const char		*inval;
403*0Sstevel@tonic-gate 	int			invallen;
404*0Sstevel@tonic-gate 	struct cb_data		*indata;
405*0Sstevel@tonic-gate {
406*0Sstevel@tonic-gate 	nss_status_t		res;
407*0Sstevel@tonic-gate 
408*0Sstevel@tonic-gate 	if (instatus != YP_TRUE) {
409*0Sstevel@tonic-gate 		return (ITER_NEXT);	/* yp_all may decide otherwise... */
410*0Sstevel@tonic-gate 	}
411*0Sstevel@tonic-gate 
412*0Sstevel@tonic-gate 	if (indata->filter != 0 && strstr(inval, indata->filter) == 0) {
413*0Sstevel@tonic-gate 		/*
414*0Sstevel@tonic-gate 		 * Optimization:  if the entry doesn't contain the filter
415*0Sstevel@tonic-gate 		 *   string then it can't be the entry we want, so don't
416*0Sstevel@tonic-gate 		 *   bother looking more closely at it.
417*0Sstevel@tonic-gate 		 */
418*0Sstevel@tonic-gate 		return (ITER_NEXT);
419*0Sstevel@tonic-gate 	}
420*0Sstevel@tonic-gate 
421*0Sstevel@tonic-gate 	res = (*indata->func)(inval, invallen, indata->args);
422*0Sstevel@tonic-gate 
423*0Sstevel@tonic-gate 	if (res == NSS_NOTFOUND) {
424*0Sstevel@tonic-gate 		return (ITER_NEXT);
425*0Sstevel@tonic-gate 	} else {
426*0Sstevel@tonic-gate 		indata->result = res;
427*0Sstevel@tonic-gate 		return (ITER_STOP);
428*0Sstevel@tonic-gate 	}
429*0Sstevel@tonic-gate }
430*0Sstevel@tonic-gate 
431*0Sstevel@tonic-gate nss_status_t
432*0Sstevel@tonic-gate _nss_nis_do_all(be, args, filter, func)
433*0Sstevel@tonic-gate 	nis_backend_ptr_t	be;
434*0Sstevel@tonic-gate 	void			*args;
435*0Sstevel@tonic-gate 	const char		*filter;
436*0Sstevel@tonic-gate 	nis_do_all_func_t	func;
437*0Sstevel@tonic-gate {
438*0Sstevel@tonic-gate 	int			ypall_status;
439*0Sstevel@tonic-gate 	struct cb_data		data;
440*0Sstevel@tonic-gate 	struct ypall_callback	cback;
441*0Sstevel@tonic-gate 
442*0Sstevel@tonic-gate 	data.args	= args;
443*0Sstevel@tonic-gate 	data.filter	= filter;
444*0Sstevel@tonic-gate 	data.func	= func;
445*0Sstevel@tonic-gate 	data.result	= NSS_NOTFOUND;
446*0Sstevel@tonic-gate 
447*0Sstevel@tonic-gate 	cback.foreach	= do_cback;
448*0Sstevel@tonic-gate 	cback.data	= (char *)&data;
449*0Sstevel@tonic-gate 
450*0Sstevel@tonic-gate #if	MT_UNSAFE_YP
451*0Sstevel@tonic-gate 	sigset_t		oldmask, newmask;
452*0Sstevel@tonic-gate 
453*0Sstevel@tonic-gate 	sigfillset(&newmask);
454*0Sstevel@tonic-gate 	_thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
455*0Sstevel@tonic-gate 	_mutex_lock(&one_lane);
456*0Sstevel@tonic-gate #endif
457*0Sstevel@tonic-gate 	ypall_status = __yp_all_cflookup((grrr)be->domain,
458*0Sstevel@tonic-gate 			(grrr) be->enum_map, &cback, 0);
459*0Sstevel@tonic-gate #if	MT_UNSAFE_YP
460*0Sstevel@tonic-gate 	_mutex_unlock(&one_lane);
461*0Sstevel@tonic-gate 	_thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
462*0Sstevel@tonic-gate #endif
463*0Sstevel@tonic-gate 
464*0Sstevel@tonic-gate 	switch (ypall_status) {
465*0Sstevel@tonic-gate 	    case 0:
466*0Sstevel@tonic-gate 		return (data.result);
467*0Sstevel@tonic-gate 	    case YPERR_DOMAIN:
468*0Sstevel@tonic-gate 	    case YPERR_YPSERV:
469*0Sstevel@tonic-gate 	    case YPERR_BUSY:		/* Probably never get this, but... */
470*0Sstevel@tonic-gate 		return (NSS_TRYAGAIN);
471*0Sstevel@tonic-gate 	    default:
472*0Sstevel@tonic-gate 		return (NSS_UNAVAIL);
473*0Sstevel@tonic-gate 	}
474*0Sstevel@tonic-gate }
475*0Sstevel@tonic-gate 
476*0Sstevel@tonic-gate struct XbyY_data {
477*0Sstevel@tonic-gate 	nss_XbyY_args_t		*args;
478*0Sstevel@tonic-gate 	nis_XY_check_func	func;
479*0Sstevel@tonic-gate 	int			netdb;
480*0Sstevel@tonic-gate };
481*0Sstevel@tonic-gate 
482*0Sstevel@tonic-gate static nss_status_t
483*0Sstevel@tonic-gate XbyY_iterator(instr, instr_len, a)
484*0Sstevel@tonic-gate 	const char		*instr;
485*0Sstevel@tonic-gate 	int			instr_len;
486*0Sstevel@tonic-gate 	void			*a;
487*0Sstevel@tonic-gate {
488*0Sstevel@tonic-gate 	struct XbyY_data	*xydata	= (struct XbyY_data *)a;
489*0Sstevel@tonic-gate 	nss_XbyY_args_t		*args	= xydata->args;
490*0Sstevel@tonic-gate 	nss_status_t		res;
491*0Sstevel@tonic-gate 	int			parsestat;
492*0Sstevel@tonic-gate 
493*0Sstevel@tonic-gate 	if (xydata->netdb) {
494*0Sstevel@tonic-gate 		massage_netdb(&instr, &instr_len);
495*0Sstevel@tonic-gate 	}
496*0Sstevel@tonic-gate 
497*0Sstevel@tonic-gate 	parsestat = (*args->str2ent)(instr, instr_len,
498*0Sstevel@tonic-gate 			args->buf.result, args->buf.buffer, args->buf.buflen);
499*0Sstevel@tonic-gate 	if (parsestat == NSS_STR_PARSE_SUCCESS) {
500*0Sstevel@tonic-gate 		args->returnval = args->buf.result;
501*0Sstevel@tonic-gate 		if ((*xydata->func)(args)) {
502*0Sstevel@tonic-gate 			res = NSS_SUCCESS;
503*0Sstevel@tonic-gate 		} else {
504*0Sstevel@tonic-gate 			res = NSS_NOTFOUND;
505*0Sstevel@tonic-gate 			args->returnval = 0;
506*0Sstevel@tonic-gate 		}
507*0Sstevel@tonic-gate 	} else if (parsestat == NSS_STR_PARSE_ERANGE) {
508*0Sstevel@tonic-gate 		/*
509*0Sstevel@tonic-gate 		 * If we got here because (*str2ent)() found that the buffer
510*0Sstevel@tonic-gate 		 * wasn't big enough, maybe we should quit and return erange.
511*0Sstevel@tonic-gate 		 * Instead we'll keep looking and eventually return "not
512*0Sstevel@tonic-gate 		 * found" -- it's a bug, but not an earth-shattering one.
513*0Sstevel@tonic-gate 		 */
514*0Sstevel@tonic-gate 		args->erange = 1;	/* <== Is this a good idea? */
515*0Sstevel@tonic-gate 		res = NSS_NOTFOUND;
516*0Sstevel@tonic-gate 	} /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */
517*0Sstevel@tonic-gate 
518*0Sstevel@tonic-gate 	return (res);
519*0Sstevel@tonic-gate }
520*0Sstevel@tonic-gate 
521*0Sstevel@tonic-gate nss_status_t
522*0Sstevel@tonic-gate _nss_nis_XY_all(be, args, netdb, filter, func)
523*0Sstevel@tonic-gate 	nis_backend_ptr_t	be;
524*0Sstevel@tonic-gate 	nss_XbyY_args_t		*args;
525*0Sstevel@tonic-gate 	int			netdb;
526*0Sstevel@tonic-gate 	const char		*filter;
527*0Sstevel@tonic-gate 	nis_XY_check_func	func;
528*0Sstevel@tonic-gate {
529*0Sstevel@tonic-gate 	struct XbyY_data	data;
530*0Sstevel@tonic-gate 
531*0Sstevel@tonic-gate 	data.args = args;
532*0Sstevel@tonic-gate 	data.func = func;
533*0Sstevel@tonic-gate 	data.netdb = netdb;
534*0Sstevel@tonic-gate 
535*0Sstevel@tonic-gate 	return (_nss_nis_do_all(be, &data, filter, XbyY_iterator));
536*0Sstevel@tonic-gate 	/* Now how many levels of callbacks was that? */
537*0Sstevel@tonic-gate }
538*0Sstevel@tonic-gate 
539*0Sstevel@tonic-gate 
540*0Sstevel@tonic-gate /*ARGSUSED*/
541*0Sstevel@tonic-gate nss_status_t
542*0Sstevel@tonic-gate _nss_nis_destr(be, dummy)
543*0Sstevel@tonic-gate 	nis_backend_ptr_t	be;
544*0Sstevel@tonic-gate 	void			*dummy;
545*0Sstevel@tonic-gate {
546*0Sstevel@tonic-gate 	if (be != 0) {
547*0Sstevel@tonic-gate 		/* === Should change to invoke ops[ENDENT] ? */
548*0Sstevel@tonic-gate 		_nss_nis_endent(be, 0);
549*0Sstevel@tonic-gate 		free(be);
550*0Sstevel@tonic-gate 	}
551*0Sstevel@tonic-gate 	return (NSS_SUCCESS);	/* In case anyone is dumb enough to check */
552*0Sstevel@tonic-gate }
553*0Sstevel@tonic-gate 
554*0Sstevel@tonic-gate /* We want to lock this even if the YP routines are MT-safe */
555*0Sstevel@tonic-gate static mutex_t	yp_domain_lock = DEFAULTMUTEX;
556*0Sstevel@tonic-gate static char	*yp_domain;
557*0Sstevel@tonic-gate 
558*0Sstevel@tonic-gate const char *
559*0Sstevel@tonic-gate _nss_nis_domain()
560*0Sstevel@tonic-gate {
561*0Sstevel@tonic-gate 	char			*domain;
562*0Sstevel@tonic-gate 
563*0Sstevel@tonic-gate 	/*
564*0Sstevel@tonic-gate 	 * This much locking is probably more "by the book" than necessary...
565*0Sstevel@tonic-gate 	 */
566*0Sstevel@tonic-gate 	sigset_t		oldmask, newmask;
567*0Sstevel@tonic-gate 
568*0Sstevel@tonic-gate 	sigfillset(&newmask);
569*0Sstevel@tonic-gate 	(void) _thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
570*0Sstevel@tonic-gate 	(void) _mutex_lock(&yp_domain_lock);
571*0Sstevel@tonic-gate 
572*0Sstevel@tonic-gate 	if ((domain = yp_domain) == 0) {
573*0Sstevel@tonic-gate #if	MT_UNSAFE_YP
574*0Sstevel@tonic-gate 		_mutex_lock(&one_lane);
575*0Sstevel@tonic-gate #endif
576*0Sstevel@tonic-gate 		if (yp_get_default_domain(&yp_domain) == 0) {
577*0Sstevel@tonic-gate 			domain = yp_domain;
578*0Sstevel@tonic-gate 		}
579*0Sstevel@tonic-gate #if	MT_UNSAFE_YP
580*0Sstevel@tonic-gate 		_mutex_unlock(&one_lane);
581*0Sstevel@tonic-gate #endif
582*0Sstevel@tonic-gate 	}
583*0Sstevel@tonic-gate 
584*0Sstevel@tonic-gate 	_mutex_unlock(&yp_domain_lock);
585*0Sstevel@tonic-gate 	_thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
586*0Sstevel@tonic-gate 
587*0Sstevel@tonic-gate 	return (domain);
588*0Sstevel@tonic-gate }
589*0Sstevel@tonic-gate 
590*0Sstevel@tonic-gate nss_backend_t *
591*0Sstevel@tonic-gate _nss_nis_constr(ops, n_ops, enum_map)
592*0Sstevel@tonic-gate 	nis_backend_op_t	ops[];
593*0Sstevel@tonic-gate 	int			n_ops;
594*0Sstevel@tonic-gate 	const char		*enum_map;
595*0Sstevel@tonic-gate {
596*0Sstevel@tonic-gate 	const char		*domain;
597*0Sstevel@tonic-gate 	nis_backend_ptr_t	be;
598*0Sstevel@tonic-gate 
599*0Sstevel@tonic-gate 	if ((domain = _nss_nis_domain()) == 0 ||
600*0Sstevel@tonic-gate 	    (be = (nis_backend_ptr_t)malloc(sizeof (*be))) == 0) {
601*0Sstevel@tonic-gate 		return (0);
602*0Sstevel@tonic-gate 	}
603*0Sstevel@tonic-gate 	be->ops		= ops;
604*0Sstevel@tonic-gate 	be->n_ops	= n_ops;
605*0Sstevel@tonic-gate 	be->domain	= domain;
606*0Sstevel@tonic-gate 	be->enum_map	= enum_map;   /* Don't strdup, assume valid forever */
607*0Sstevel@tonic-gate 	be->enum_key	= 0;
608*0Sstevel@tonic-gate 	be->enum_keylen	= 0;
609*0Sstevel@tonic-gate 
610*0Sstevel@tonic-gate 	return ((nss_backend_t *)be);
611*0Sstevel@tonic-gate }
612