10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*2830Sdjl  * Common Development and Distribution License (the "License").
6*2830Sdjl  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*2830Sdjl  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*
280Sstevel@tonic-gate  * nis_common.c
290Sstevel@tonic-gate  *
300Sstevel@tonic-gate  * Common code and structures used by name-service-switch "nis" backends.
310Sstevel@tonic-gate  */
320Sstevel@tonic-gate 
330Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
340Sstevel@tonic-gate 
350Sstevel@tonic-gate #include "nis_common.h"
360Sstevel@tonic-gate #include <string.h>
370Sstevel@tonic-gate #include <synch.h>
380Sstevel@tonic-gate #include <rpcsvc/ypclnt.h>
390Sstevel@tonic-gate #include <rpcsvc/yp_prot.h>
400Sstevel@tonic-gate #include <thread.h>
410Sstevel@tonic-gate #include <ctype.h>
420Sstevel@tonic-gate #include <stdlib.h>
430Sstevel@tonic-gate #include <signal.h>
440Sstevel@tonic-gate 
450Sstevel@tonic-gate #ifndef	MT_UNSAFE_YP		/* Is the libnsl YP client code MT-unsafe? */
460Sstevel@tonic-gate #define	MT_UNSAFE_YP	0	/* No, not any longer */
470Sstevel@tonic-gate #endif
480Sstevel@tonic-gate 
490Sstevel@tonic-gate #if	MT_UNSAFE_YP
500Sstevel@tonic-gate static mutex_t	one_lane = DEFAULTMUTEX;
510Sstevel@tonic-gate #endif
520Sstevel@tonic-gate 
530Sstevel@tonic-gate /* <rpcsvc/ypclnt.h> uses (char *) where it should use (const char *) */
540Sstevel@tonic-gate typedef char *grrr;
550Sstevel@tonic-gate 
560Sstevel@tonic-gate /*
570Sstevel@tonic-gate  * The YP client code thinks it's being helpful by appending '\n' and '\0'
580Sstevel@tonic-gate  *   to the values returned by yp_match() et al.  In order to do this it
590Sstevel@tonic-gate  *   ends up doing more malloc()ing and data copying than would otherwise
600Sstevel@tonic-gate  *   be necessary.  If we're interested in performance we should provide
610Sstevel@tonic-gate  *   alternative library interfaces that skip the helpfulness and instead
620Sstevel@tonic-gate  *   let the XDR routines dump the value directly into the buffer where
630Sstevel@tonic-gate  *   we really want it.  For now, though, we just use the vanilla interface.
640Sstevel@tonic-gate  */
650Sstevel@tonic-gate 
660Sstevel@tonic-gate static nss_status_t
670Sstevel@tonic-gate switch_err(ypstatus, ismatch)
680Sstevel@tonic-gate 	int			ypstatus;
690Sstevel@tonic-gate 	int			ismatch;
700Sstevel@tonic-gate {
710Sstevel@tonic-gate 	switch (ypstatus) {
720Sstevel@tonic-gate 	case 0:
73*2830Sdjl 		errno = 0;
740Sstevel@tonic-gate 		return (NSS_SUCCESS);
750Sstevel@tonic-gate 
760Sstevel@tonic-gate 	case YPERR_BADARGS:
770Sstevel@tonic-gate 	case YPERR_KEY:
78*2830Sdjl 		errno = 0;
790Sstevel@tonic-gate 		return (NSS_NOTFOUND);
800Sstevel@tonic-gate 
810Sstevel@tonic-gate 		/*
820Sstevel@tonic-gate 		 *  When the YP server is running in DNS forwarding mode,
830Sstevel@tonic-gate 		 *  the forwarder will return YPERR_NOMORE to us if it
840Sstevel@tonic-gate 		 *  is unable to contact a server (i.e., it has timed out).
850Sstevel@tonic-gate 		 *  The NSS_NISSERVDNS_TRYAGAIN is returned for timeout errors.
860Sstevel@tonic-gate 		 */
870Sstevel@tonic-gate 	case YPERR_NOMORE:
880Sstevel@tonic-gate 		if (ismatch)
890Sstevel@tonic-gate 			return (NSS_NISSERVDNS_TRYAGAIN);
900Sstevel@tonic-gate 		else
910Sstevel@tonic-gate 			return (NSS_NOTFOUND);
920Sstevel@tonic-gate 
930Sstevel@tonic-gate 	case YPERR_DOMAIN:
940Sstevel@tonic-gate 	case YPERR_YPSERV:
950Sstevel@tonic-gate 	case YPERR_BUSY:
960Sstevel@tonic-gate 		return (NSS_TRYAGAIN);
970Sstevel@tonic-gate 
980Sstevel@tonic-gate 	default:
990Sstevel@tonic-gate 		return (NSS_UNAVAIL);
1000Sstevel@tonic-gate 	}
1010Sstevel@tonic-gate }
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate /*ARGSUSED*/
1040Sstevel@tonic-gate nss_status_t
1050Sstevel@tonic-gate _nss_nis_setent(be, dummy)
1060Sstevel@tonic-gate 	nis_backend_ptr_t	be;
1070Sstevel@tonic-gate 	void			*dummy;
1080Sstevel@tonic-gate {
1090Sstevel@tonic-gate 	if (be->enum_key != 0) {
1100Sstevel@tonic-gate 		free(be->enum_key);
1110Sstevel@tonic-gate 		be->enum_key = 0;
1120Sstevel@tonic-gate 	}
1130Sstevel@tonic-gate 	be->enum_keylen = 0;
1140Sstevel@tonic-gate 	return (NSS_SUCCESS);
1150Sstevel@tonic-gate }
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate nss_status_t
1180Sstevel@tonic-gate _nss_nis_endent(be, dummy)
1190Sstevel@tonic-gate 	nis_backend_ptr_t	be;
1200Sstevel@tonic-gate 	void			*dummy;
1210Sstevel@tonic-gate {
1220Sstevel@tonic-gate 	return (_nss_nis_setent(be, dummy));
1230Sstevel@tonic-gate 	/* Nothing else we can clean up, is there? */
1240Sstevel@tonic-gate }
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate void
1270Sstevel@tonic-gate massage_netdb(const char **valp, int *vallenp)
1280Sstevel@tonic-gate {
1290Sstevel@tonic-gate 	const char		*first;
1300Sstevel@tonic-gate 	const char		*last;
1310Sstevel@tonic-gate 	const char		*val	= *valp;
1320Sstevel@tonic-gate 	int			vallen	= *vallenp;
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 	if ((last = memchr(val, '#', vallen)) == 0) {
1350Sstevel@tonic-gate 		last = val + vallen;
1360Sstevel@tonic-gate 	}
1370Sstevel@tonic-gate 	for (first = val;  first < last && isspace(*first);  first++) {
1380Sstevel@tonic-gate 		;
1390Sstevel@tonic-gate 	}
1400Sstevel@tonic-gate 	for (/* cstyle */;  first < last && isspace(last[-1]);  last--) {
1410Sstevel@tonic-gate 		;
1420Sstevel@tonic-gate 	}
1430Sstevel@tonic-gate 	/*
1440Sstevel@tonic-gate 	 * Don't check for an empty line because it shouldn't ever
1450Sstevel@tonic-gate 	 *   have made it into the YP map.
1460Sstevel@tonic-gate 	 */
1470Sstevel@tonic-gate 	*valp = first;
1480Sstevel@tonic-gate 	*vallenp = (int)(last - first);
1490Sstevel@tonic-gate }
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate nss_status_t
1520Sstevel@tonic-gate _nss_nis_ypmatch(domain, map, key, valp, vallenp, ypstatusp)
1530Sstevel@tonic-gate 	const char		*domain;
1540Sstevel@tonic-gate 	const char		*map;
1550Sstevel@tonic-gate 	const char		*key;
1560Sstevel@tonic-gate 	char			**valp;
1570Sstevel@tonic-gate 	int			*vallenp;
1580Sstevel@tonic-gate 	int			*ypstatusp;
1590Sstevel@tonic-gate {
1600Sstevel@tonic-gate 	int			ypstatus;
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate #if	MT_UNSAFE_YP
1630Sstevel@tonic-gate 	sigset_t		oldmask, newmask;
1640Sstevel@tonic-gate 
165*2830Sdjl 	(void) sigfillset(&newmask);
1660Sstevel@tonic-gate 	_thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
1670Sstevel@tonic-gate 	_mutex_lock(&one_lane);
1680Sstevel@tonic-gate #endif
1690Sstevel@tonic-gate 	ypstatus = __yp_match_cflookup((grrr)domain, (grrr)map,
1700Sstevel@tonic-gate 			    (grrr)key, (int)strlen(key), valp, vallenp, 0);
1710Sstevel@tonic-gate #if	MT_UNSAFE_YP
1720Sstevel@tonic-gate 	_mutex_unlock(&one_lane);
1730Sstevel@tonic-gate 	_thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
1740Sstevel@tonic-gate #endif
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 	if (ypstatusp != 0) {
1770Sstevel@tonic-gate 		*ypstatusp = ypstatus;
1780Sstevel@tonic-gate 	}
1790Sstevel@tonic-gate 	return (switch_err(ypstatus, 1));
1800Sstevel@tonic-gate }
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate /*
1830Sstevel@tonic-gate  * XXX special version of _nss_nis_ypmatch() for handling C2 (passwd.adjunct)
1840Sstevel@tonic-gate  * lookups when we need a reserved port.
1850Sstevel@tonic-gate  */
186*2830Sdjl 
187*2830Sdjl static nss_status_t
1880Sstevel@tonic-gate _nss_nis_ypmatch_rsvdport(domain, map, key, valp, vallenp, ypstatusp)
1890Sstevel@tonic-gate 	const char		*domain;
1900Sstevel@tonic-gate 	const char		*map;
1910Sstevel@tonic-gate 	const char		*key;
1920Sstevel@tonic-gate 	char			**valp;
1930Sstevel@tonic-gate 	int			*vallenp;
1940Sstevel@tonic-gate 	int			*ypstatusp;
1950Sstevel@tonic-gate {
1960Sstevel@tonic-gate 	int			ypstatus;
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate #if	MT_UNSAFE_YP
1990Sstevel@tonic-gate 	sigset_t		oldmask, newmask;
2000Sstevel@tonic-gate 
201*2830Sdjl 	(void) sigfillset(&newmask);
2020Sstevel@tonic-gate 	_thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
2030Sstevel@tonic-gate 	_mutex_lock(&one_lane);
2040Sstevel@tonic-gate #endif
2050Sstevel@tonic-gate 	ypstatus = __yp_match_rsvdport_cflookup((grrr)domain, (grrr)map,
2060Sstevel@tonic-gate 			    (grrr)key, strlen(key), valp, vallenp, 0);
2070Sstevel@tonic-gate #if	MT_UNSAFE_YP
2080Sstevel@tonic-gate 	_mutex_unlock(&one_lane);
2090Sstevel@tonic-gate 	_thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
2100Sstevel@tonic-gate #endif
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 	if (ypstatusp != 0) {
2130Sstevel@tonic-gate 		*ypstatusp = ypstatus;
2140Sstevel@tonic-gate 	}
2150Sstevel@tonic-gate 	return (switch_err(ypstatus, 1));
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate nss_status_t
2190Sstevel@tonic-gate _nss_nis_lookup(be, args, netdb, map, key, ypstatusp)
2200Sstevel@tonic-gate 	nis_backend_ptr_t	be;
2210Sstevel@tonic-gate 	nss_XbyY_args_t		*args;
2220Sstevel@tonic-gate 	int			netdb;
2230Sstevel@tonic-gate 	const char		*map;
2240Sstevel@tonic-gate 	const char		*key;
2250Sstevel@tonic-gate 	int			*ypstatusp;
2260Sstevel@tonic-gate {
2270Sstevel@tonic-gate 	nss_status_t		res;
2280Sstevel@tonic-gate 	int			vallen;
2290Sstevel@tonic-gate 	char			*val;
2300Sstevel@tonic-gate 	char			*free_ptr;
2310Sstevel@tonic-gate 	int			parsestat;
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate 	if ((res = _nss_nis_ypmatch(be->domain, map, key, &val, &vallen,
2340Sstevel@tonic-gate 				    ypstatusp)) != NSS_SUCCESS) {
2350Sstevel@tonic-gate 		return (res);
2360Sstevel@tonic-gate 	}
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate 	free_ptr = val;
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 	if (netdb) {
2410Sstevel@tonic-gate 		massage_netdb((const char **)&val, &vallen);
2420Sstevel@tonic-gate 	}
2430Sstevel@tonic-gate 
244*2830Sdjl 	args->returnval = NULL;
245*2830Sdjl 	args->returnlen = 0;
2460Sstevel@tonic-gate 	parsestat = (*args->str2ent)(val, vallen,
2470Sstevel@tonic-gate 			args->buf.result, args->buf.buffer, args->buf.buflen);
2480Sstevel@tonic-gate 	if (parsestat == NSS_STR_PARSE_SUCCESS) {
2490Sstevel@tonic-gate 		args->returnval = args->buf.result;
250*2830Sdjl 		args->returnlen = vallen;
2510Sstevel@tonic-gate 		res = NSS_SUCCESS;
2520Sstevel@tonic-gate 	} else if (parsestat == NSS_STR_PARSE_ERANGE) {
2530Sstevel@tonic-gate 		args->erange = 1;
2540Sstevel@tonic-gate 		/* We won't find this otherwise, anyway */
2550Sstevel@tonic-gate 		res = NSS_NOTFOUND;
2560Sstevel@tonic-gate 	} /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 	free(free_ptr);
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 	return (res);
2610Sstevel@tonic-gate }
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate nss_status_t
2640Sstevel@tonic-gate _nss_nis_lookup_rsvdport(be, args, netdb, map, key, ypstatusp)
2650Sstevel@tonic-gate 	nis_backend_ptr_t	be;
2660Sstevel@tonic-gate 	nss_XbyY_args_t		*args;
2670Sstevel@tonic-gate 	int			netdb;
2680Sstevel@tonic-gate 	const char		*map;
2690Sstevel@tonic-gate 	const char		*key;
2700Sstevel@tonic-gate 	int			*ypstatusp;
2710Sstevel@tonic-gate {
2720Sstevel@tonic-gate 	nss_status_t		res;
2730Sstevel@tonic-gate 	int			vallen;
2740Sstevel@tonic-gate 	char			*val;
2750Sstevel@tonic-gate 	char			*free_ptr;
2760Sstevel@tonic-gate 	int			parsestat;
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate 	if ((res = _nss_nis_ypmatch_rsvdport(be->domain, map, key, &val,
2790Sstevel@tonic-gate 				    &vallen, ypstatusp)) != NSS_SUCCESS) {
2800Sstevel@tonic-gate 		return (res);
2810Sstevel@tonic-gate 	}
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 	free_ptr = val;
2840Sstevel@tonic-gate 
2850Sstevel@tonic-gate 	if (netdb) {
2860Sstevel@tonic-gate 		massage_netdb((const char **)&val, &vallen);
2870Sstevel@tonic-gate 	}
2880Sstevel@tonic-gate 
289*2830Sdjl 	args->returnval = NULL;
290*2830Sdjl 	args->returnlen = 0;
2910Sstevel@tonic-gate 	parsestat = (*args->str2ent)(val, vallen,
2920Sstevel@tonic-gate 			args->buf.result, args->buf.buffer, args->buf.buflen);
2930Sstevel@tonic-gate 	if (parsestat == NSS_STR_PARSE_SUCCESS) {
2940Sstevel@tonic-gate 		args->returnval = args->buf.result;
295*2830Sdjl 		args->returnlen = vallen;
2960Sstevel@tonic-gate 		res = NSS_SUCCESS;
2970Sstevel@tonic-gate 	} else if (parsestat == NSS_STR_PARSE_ERANGE) {
2980Sstevel@tonic-gate 		args->erange = 1;
2990Sstevel@tonic-gate 		/* We won't find this otherwise, anyway */
3000Sstevel@tonic-gate 		res = NSS_NOTFOUND;
3010Sstevel@tonic-gate 	} /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 	free(free_ptr);
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate 	return (res);
3060Sstevel@tonic-gate }
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate static nss_status_t
3090Sstevel@tonic-gate do_getent(be, args, netdb)
3100Sstevel@tonic-gate 	nis_backend_ptr_t	be;
3110Sstevel@tonic-gate 	nss_XbyY_args_t		*args;
3120Sstevel@tonic-gate 	int			netdb;
3130Sstevel@tonic-gate {
3140Sstevel@tonic-gate 	nss_status_t		res;
3150Sstevel@tonic-gate 	int			ypstatus;
3160Sstevel@tonic-gate 	int			outkeylen, outvallen;
3170Sstevel@tonic-gate 	char			*outkey, *outval;
3180Sstevel@tonic-gate 	char			*free_ptr;
3190Sstevel@tonic-gate 	int			parsestat;
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate #if	MT_UNSAFE_YP
3220Sstevel@tonic-gate 	sigset_t		oldmask, newmask;
3230Sstevel@tonic-gate 
324*2830Sdjl 	(void) sigfillset(&newmask);
3250Sstevel@tonic-gate 	_thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
3260Sstevel@tonic-gate 	_mutex_lock(&one_lane);
3270Sstevel@tonic-gate #endif
3280Sstevel@tonic-gate 	if (be->enum_key == 0) {
3290Sstevel@tonic-gate 		ypstatus = __yp_first_cflookup((grrr)be->domain,
3300Sstevel@tonic-gate 					    (grrr)be->enum_map, &outkey,
3310Sstevel@tonic-gate 					    &outkeylen, &outval,
3320Sstevel@tonic-gate 					    &outvallen, 0);
3330Sstevel@tonic-gate 	} else {
3340Sstevel@tonic-gate 		ypstatus = __yp_next_cflookup((grrr)be->domain,
3350Sstevel@tonic-gate 					    (grrr)be->enum_map, be->enum_key,
3360Sstevel@tonic-gate 					    be->enum_keylen, &outkey,
3370Sstevel@tonic-gate 					    &outkeylen, &outval,
3380Sstevel@tonic-gate 					    &outvallen, 0);
3390Sstevel@tonic-gate 	}
3400Sstevel@tonic-gate #if	MT_UNSAFE_YP
3410Sstevel@tonic-gate 	_mutex_unlock(&one_lane);
3420Sstevel@tonic-gate 	_thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
3430Sstevel@tonic-gate #endif
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate 	if ((res = switch_err(ypstatus, 0)) != NSS_SUCCESS) {
3460Sstevel@tonic-gate 		return (res);
3470Sstevel@tonic-gate 	}
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 	free_ptr = outval;
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate 	if (netdb) {
3520Sstevel@tonic-gate 		massage_netdb((const char **)&outval, &outvallen);
3530Sstevel@tonic-gate 	}
3540Sstevel@tonic-gate 
355*2830Sdjl 	args->returnval = NULL;
356*2830Sdjl 	args->returnlen = 0;
3570Sstevel@tonic-gate 	parsestat = (*args->str2ent)(outval, outvallen,
3580Sstevel@tonic-gate 			args->buf.result, args->buf.buffer, args->buf.buflen);
3590Sstevel@tonic-gate 	if (parsestat == NSS_STR_PARSE_SUCCESS) {
3600Sstevel@tonic-gate 		args->returnval = args->buf.result;
361*2830Sdjl 		args->returnlen = outvallen;
3620Sstevel@tonic-gate 		res = NSS_SUCCESS;
3630Sstevel@tonic-gate 	} else if (parsestat == NSS_STR_PARSE_ERANGE) {
3640Sstevel@tonic-gate 		args->erange = 1;
3650Sstevel@tonic-gate 		/* We won't find this otherwise, anyway */
3660Sstevel@tonic-gate 		res = NSS_NOTFOUND;
3670Sstevel@tonic-gate 	} /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate 	free(free_ptr);
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate 	if (be->enum_key != 0) {
3720Sstevel@tonic-gate 		free(be->enum_key);
3730Sstevel@tonic-gate 	}
3740Sstevel@tonic-gate 	be->enum_key = outkey;
3750Sstevel@tonic-gate 	be->enum_keylen = outkeylen;
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate 	return (res);
3780Sstevel@tonic-gate }
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate nss_status_t
3810Sstevel@tonic-gate _nss_nis_getent_rigid(be, args)
3820Sstevel@tonic-gate 	nis_backend_ptr_t	be;
3830Sstevel@tonic-gate 	void			*args;
3840Sstevel@tonic-gate {
3850Sstevel@tonic-gate 	return (do_getent(be, (nss_XbyY_args_t *)args, 0));
3860Sstevel@tonic-gate }
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate nss_status_t
3890Sstevel@tonic-gate _nss_nis_getent_netdb(be, args)
3900Sstevel@tonic-gate 	nis_backend_ptr_t	be;
3910Sstevel@tonic-gate 	void			*args;
3920Sstevel@tonic-gate {
3930Sstevel@tonic-gate 	return (do_getent(be, (nss_XbyY_args_t *)args, 1));
3940Sstevel@tonic-gate }
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate struct cb_data {
3980Sstevel@tonic-gate 	void			*args;
3990Sstevel@tonic-gate 	const char		*filter;
4000Sstevel@tonic-gate 	nis_do_all_func_t	func;
4010Sstevel@tonic-gate 	nss_status_t		result;
4020Sstevel@tonic-gate };
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate enum { ITER_NEXT = 0, ITER_STOP = 1 };	/* Should be in <rpcsvc/ypclnt.h> */
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate /*ARGSUSED*/
4070Sstevel@tonic-gate static int
4080Sstevel@tonic-gate do_cback(instatus, inkey, inkeylen, inval, invallen, indata)
4090Sstevel@tonic-gate 	int			instatus;
4100Sstevel@tonic-gate 	const char		*inkey;
4110Sstevel@tonic-gate 	int			inkeylen;
4120Sstevel@tonic-gate 	const char		*inval;
4130Sstevel@tonic-gate 	int			invallen;
4140Sstevel@tonic-gate 	struct cb_data		*indata;
4150Sstevel@tonic-gate {
4160Sstevel@tonic-gate 	nss_status_t		res;
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate 	if (instatus != YP_TRUE) {
4190Sstevel@tonic-gate 		return (ITER_NEXT);	/* yp_all may decide otherwise... */
4200Sstevel@tonic-gate 	}
4210Sstevel@tonic-gate 
4220Sstevel@tonic-gate 	if (indata->filter != 0 && strstr(inval, indata->filter) == 0) {
4230Sstevel@tonic-gate 		/*
4240Sstevel@tonic-gate 		 * Optimization:  if the entry doesn't contain the filter
4250Sstevel@tonic-gate 		 *   string then it can't be the entry we want, so don't
4260Sstevel@tonic-gate 		 *   bother looking more closely at it.
4270Sstevel@tonic-gate 		 */
4280Sstevel@tonic-gate 		return (ITER_NEXT);
4290Sstevel@tonic-gate 	}
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 	res = (*indata->func)(inval, invallen, indata->args);
4320Sstevel@tonic-gate 
4330Sstevel@tonic-gate 	if (res == NSS_NOTFOUND) {
4340Sstevel@tonic-gate 		return (ITER_NEXT);
4350Sstevel@tonic-gate 	} else {
4360Sstevel@tonic-gate 		indata->result = res;
4370Sstevel@tonic-gate 		return (ITER_STOP);
4380Sstevel@tonic-gate 	}
4390Sstevel@tonic-gate }
4400Sstevel@tonic-gate 
4410Sstevel@tonic-gate nss_status_t
4420Sstevel@tonic-gate _nss_nis_do_all(be, args, filter, func)
4430Sstevel@tonic-gate 	nis_backend_ptr_t	be;
4440Sstevel@tonic-gate 	void			*args;
4450Sstevel@tonic-gate 	const char		*filter;
4460Sstevel@tonic-gate 	nis_do_all_func_t	func;
4470Sstevel@tonic-gate {
4480Sstevel@tonic-gate 	int			ypall_status;
4490Sstevel@tonic-gate 	struct cb_data		data;
4500Sstevel@tonic-gate 	struct ypall_callback	cback;
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate 	data.args	= args;
4530Sstevel@tonic-gate 	data.filter	= filter;
4540Sstevel@tonic-gate 	data.func	= func;
4550Sstevel@tonic-gate 	data.result	= NSS_NOTFOUND;
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate 	cback.foreach	= do_cback;
4580Sstevel@tonic-gate 	cback.data	= (char *)&data;
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate #if	MT_UNSAFE_YP
4610Sstevel@tonic-gate 	sigset_t		oldmask, newmask;
4620Sstevel@tonic-gate 
463*2830Sdjl 	(void) sigfillset(&newmask);
4640Sstevel@tonic-gate 	_thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
4650Sstevel@tonic-gate 	_mutex_lock(&one_lane);
4660Sstevel@tonic-gate #endif
4670Sstevel@tonic-gate 	ypall_status = __yp_all_cflookup((grrr)be->domain,
4680Sstevel@tonic-gate 			(grrr) be->enum_map, &cback, 0);
4690Sstevel@tonic-gate #if	MT_UNSAFE_YP
4700Sstevel@tonic-gate 	_mutex_unlock(&one_lane);
4710Sstevel@tonic-gate 	_thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
4720Sstevel@tonic-gate #endif
4730Sstevel@tonic-gate 
4740Sstevel@tonic-gate 	switch (ypall_status) {
4750Sstevel@tonic-gate 	    case 0:
4760Sstevel@tonic-gate 		return (data.result);
4770Sstevel@tonic-gate 	    case YPERR_DOMAIN:
4780Sstevel@tonic-gate 	    case YPERR_YPSERV:
4790Sstevel@tonic-gate 	    case YPERR_BUSY:		/* Probably never get this, but... */
4800Sstevel@tonic-gate 		return (NSS_TRYAGAIN);
4810Sstevel@tonic-gate 	    default:
4820Sstevel@tonic-gate 		return (NSS_UNAVAIL);
4830Sstevel@tonic-gate 	}
4840Sstevel@tonic-gate }
4850Sstevel@tonic-gate 
4860Sstevel@tonic-gate struct XbyY_data {
4870Sstevel@tonic-gate 	nss_XbyY_args_t		*args;
4880Sstevel@tonic-gate 	nis_XY_check_func	func;
4890Sstevel@tonic-gate 	int			netdb;
4900Sstevel@tonic-gate };
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate static nss_status_t
4930Sstevel@tonic-gate XbyY_iterator(instr, instr_len, a)
4940Sstevel@tonic-gate 	const char		*instr;
4950Sstevel@tonic-gate 	int			instr_len;
4960Sstevel@tonic-gate 	void			*a;
4970Sstevel@tonic-gate {
4980Sstevel@tonic-gate 	struct XbyY_data	*xydata	= (struct XbyY_data *)a;
4990Sstevel@tonic-gate 	nss_XbyY_args_t		*args	= xydata->args;
5000Sstevel@tonic-gate 	nss_status_t		res;
5010Sstevel@tonic-gate 	int			parsestat;
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate 	if (xydata->netdb) {
5040Sstevel@tonic-gate 		massage_netdb(&instr, &instr_len);
5050Sstevel@tonic-gate 	}
5060Sstevel@tonic-gate 
507*2830Sdjl 	args->returnval = NULL;
508*2830Sdjl 	args->returnlen = 0;
5090Sstevel@tonic-gate 	parsestat = (*args->str2ent)(instr, instr_len,
5100Sstevel@tonic-gate 			args->buf.result, args->buf.buffer, args->buf.buflen);
5110Sstevel@tonic-gate 	if (parsestat == NSS_STR_PARSE_SUCCESS) {
5120Sstevel@tonic-gate 		args->returnval = args->buf.result;
5130Sstevel@tonic-gate 		if ((*xydata->func)(args)) {
5140Sstevel@tonic-gate 			res = NSS_SUCCESS;
515*2830Sdjl 			args->returnlen = instr_len;
5160Sstevel@tonic-gate 		} else {
5170Sstevel@tonic-gate 			res = NSS_NOTFOUND;
5180Sstevel@tonic-gate 			args->returnval = 0;
5190Sstevel@tonic-gate 		}
5200Sstevel@tonic-gate 	} else if (parsestat == NSS_STR_PARSE_ERANGE) {
5210Sstevel@tonic-gate 		/*
5220Sstevel@tonic-gate 		 * If we got here because (*str2ent)() found that the buffer
5230Sstevel@tonic-gate 		 * wasn't big enough, maybe we should quit and return erange.
5240Sstevel@tonic-gate 		 * Instead we'll keep looking and eventually return "not
5250Sstevel@tonic-gate 		 * found" -- it's a bug, but not an earth-shattering one.
5260Sstevel@tonic-gate 		 */
5270Sstevel@tonic-gate 		args->erange = 1;	/* <== Is this a good idea? */
5280Sstevel@tonic-gate 		res = NSS_NOTFOUND;
5290Sstevel@tonic-gate 	} /* else if (parsestat == NSS_STR_PARSE_PARSE) won't happen ! */
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate 	return (res);
5320Sstevel@tonic-gate }
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate nss_status_t
5350Sstevel@tonic-gate _nss_nis_XY_all(be, args, netdb, filter, func)
5360Sstevel@tonic-gate 	nis_backend_ptr_t	be;
5370Sstevel@tonic-gate 	nss_XbyY_args_t		*args;
5380Sstevel@tonic-gate 	int			netdb;
5390Sstevel@tonic-gate 	const char		*filter;
5400Sstevel@tonic-gate 	nis_XY_check_func	func;
5410Sstevel@tonic-gate {
5420Sstevel@tonic-gate 	struct XbyY_data	data;
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate 	data.args = args;
5450Sstevel@tonic-gate 	data.func = func;
5460Sstevel@tonic-gate 	data.netdb = netdb;
5470Sstevel@tonic-gate 
5480Sstevel@tonic-gate 	return (_nss_nis_do_all(be, &data, filter, XbyY_iterator));
5490Sstevel@tonic-gate 	/* Now how many levels of callbacks was that? */
5500Sstevel@tonic-gate }
5510Sstevel@tonic-gate 
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate /*ARGSUSED*/
5540Sstevel@tonic-gate nss_status_t
5550Sstevel@tonic-gate _nss_nis_destr(be, dummy)
5560Sstevel@tonic-gate 	nis_backend_ptr_t	be;
5570Sstevel@tonic-gate 	void			*dummy;
5580Sstevel@tonic-gate {
5590Sstevel@tonic-gate 	if (be != 0) {
5600Sstevel@tonic-gate 		/* === Should change to invoke ops[ENDENT] ? */
561*2830Sdjl 		(void) _nss_nis_endent(be, 0);
5620Sstevel@tonic-gate 		free(be);
5630Sstevel@tonic-gate 	}
5640Sstevel@tonic-gate 	return (NSS_SUCCESS);	/* In case anyone is dumb enough to check */
5650Sstevel@tonic-gate }
5660Sstevel@tonic-gate 
5670Sstevel@tonic-gate /* We want to lock this even if the YP routines are MT-safe */
5680Sstevel@tonic-gate static mutex_t	yp_domain_lock = DEFAULTMUTEX;
5690Sstevel@tonic-gate static char	*yp_domain;
5700Sstevel@tonic-gate 
5710Sstevel@tonic-gate const char *
5720Sstevel@tonic-gate _nss_nis_domain()
5730Sstevel@tonic-gate {
5740Sstevel@tonic-gate 	char			*domain;
5750Sstevel@tonic-gate 
5760Sstevel@tonic-gate 	/*
5770Sstevel@tonic-gate 	 * This much locking is probably more "by the book" than necessary...
5780Sstevel@tonic-gate 	 */
5790Sstevel@tonic-gate 	sigset_t		oldmask, newmask;
5800Sstevel@tonic-gate 
581*2830Sdjl 	(void) sigfillset(&newmask);
5820Sstevel@tonic-gate 	(void) _thr_sigsetmask(SIG_SETMASK, &newmask, &oldmask);
5830Sstevel@tonic-gate 	(void) _mutex_lock(&yp_domain_lock);
5840Sstevel@tonic-gate 
5850Sstevel@tonic-gate 	if ((domain = yp_domain) == 0) {
5860Sstevel@tonic-gate #if	MT_UNSAFE_YP
5870Sstevel@tonic-gate 		_mutex_lock(&one_lane);
5880Sstevel@tonic-gate #endif
5890Sstevel@tonic-gate 		if (yp_get_default_domain(&yp_domain) == 0) {
5900Sstevel@tonic-gate 			domain = yp_domain;
5910Sstevel@tonic-gate 		}
5920Sstevel@tonic-gate #if	MT_UNSAFE_YP
5930Sstevel@tonic-gate 		_mutex_unlock(&one_lane);
5940Sstevel@tonic-gate #endif
5950Sstevel@tonic-gate 	}
5960Sstevel@tonic-gate 
5970Sstevel@tonic-gate 	_mutex_unlock(&yp_domain_lock);
5980Sstevel@tonic-gate 	_thr_sigsetmask(SIG_SETMASK, &oldmask, NULL);
5990Sstevel@tonic-gate 
6000Sstevel@tonic-gate 	return (domain);
6010Sstevel@tonic-gate }
6020Sstevel@tonic-gate 
6030Sstevel@tonic-gate nss_backend_t *
6040Sstevel@tonic-gate _nss_nis_constr(ops, n_ops, enum_map)
6050Sstevel@tonic-gate 	nis_backend_op_t	ops[];
6060Sstevel@tonic-gate 	int			n_ops;
6070Sstevel@tonic-gate 	const char		*enum_map;
6080Sstevel@tonic-gate {
6090Sstevel@tonic-gate 	const char		*domain;
6100Sstevel@tonic-gate 	nis_backend_ptr_t	be;
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate 	if ((domain = _nss_nis_domain()) == 0 ||
6130Sstevel@tonic-gate 	    (be = (nis_backend_ptr_t)malloc(sizeof (*be))) == 0) {
6140Sstevel@tonic-gate 		return (0);
6150Sstevel@tonic-gate 	}
6160Sstevel@tonic-gate 	be->ops		= ops;
6170Sstevel@tonic-gate 	be->n_ops	= n_ops;
6180Sstevel@tonic-gate 	be->domain	= domain;
6190Sstevel@tonic-gate 	be->enum_map	= enum_map;   /* Don't strdup, assume valid forever */
6200Sstevel@tonic-gate 	be->enum_key	= 0;
6210Sstevel@tonic-gate 	be->enum_keylen	= 0;
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate 	return ((nss_backend_t *)be);
6240Sstevel@tonic-gate }
625*2830Sdjl 
626*2830Sdjl /*
627*2830Sdjl  * This routine is used to parse lines of the form:
628*2830Sdjl  * 	name number aliases
629*2830Sdjl  * It returns 1 if the key in argp matches any one of the
630*2830Sdjl  * names in the line, otherwise 0
631*2830Sdjl  * Used by rpc
632*2830Sdjl  */
633*2830Sdjl int
634*2830Sdjl _nss_nis_check_name_aliases(nss_XbyY_args_t *argp, const char *line,
635*2830Sdjl 	int linelen)
636*2830Sdjl {
637*2830Sdjl 	const char	*limit, *linep, *keyp;
638*2830Sdjl 
639*2830Sdjl 	linep = line;
640*2830Sdjl 	limit = line + linelen;
641*2830Sdjl 	keyp = argp->key.name;
642*2830Sdjl 
643*2830Sdjl 	/* compare name */
644*2830Sdjl 	while (*keyp && linep < limit && !isspace(*linep) && *keyp == *linep) {
645*2830Sdjl 		keyp++;
646*2830Sdjl 		linep++;
647*2830Sdjl 	}
648*2830Sdjl 	if (*keyp == '\0' && linep < limit && isspace(*linep))
649*2830Sdjl 		return (1);
650*2830Sdjl 	/* skip remainder of the name, if any */
651*2830Sdjl 	while (linep < limit && !isspace(*linep))
652*2830Sdjl 		linep++;
653*2830Sdjl 	/* skip the delimiting spaces */
654*2830Sdjl 	while (linep < limit && isspace(*linep))
655*2830Sdjl 		linep++;
656*2830Sdjl 	/* compare with the aliases */
657*2830Sdjl 	while (linep < limit) {
658*2830Sdjl 		/*
659*2830Sdjl 		 * 1st pass: skip number
660*2830Sdjl 		 * Other passes: skip remainder of the alias name, if any
661*2830Sdjl 		 */
662*2830Sdjl 		while (linep < limit && !isspace(*linep))
663*2830Sdjl 			linep++;
664*2830Sdjl 		/* skip the delimiting spaces */
665*2830Sdjl 		while (linep < limit && isspace(*linep))
666*2830Sdjl 			linep++;
667*2830Sdjl 		/* compare with the alias name */
668*2830Sdjl 		keyp = argp->key.name;
669*2830Sdjl 		while (*keyp && linep < limit && !isspace(*linep) &&
670*2830Sdjl 				*keyp == *linep) {
671*2830Sdjl 			keyp++;
672*2830Sdjl 			linep++;
673*2830Sdjl 		}
674*2830Sdjl 		if (*keyp == '\0' && (linep == limit || isspace(*linep)))
675*2830Sdjl 			return (1);
676*2830Sdjl 	}
677*2830Sdjl 	return (0);
678*2830Sdjl }
679