xref: /titanic_52/usr/src/lib/libnsl/nis/gen/nis_subr.c (revision 36e852a172cba914383d7341c988128b2c667fbd)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5004388ebScasper  * Common Development and Distribution License (the "License").
6004388ebScasper  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
2161961e0fSrobinson 
227c478bd9Sstevel@tonic-gate /*
23*36e852a1SRaja Andra  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * This module contains the subroutines used by the server to manipulate
307c478bd9Sstevel@tonic-gate  * objects and names.
317c478bd9Sstevel@tonic-gate  */
327c478bd9Sstevel@tonic-gate #include "mt.h"
337c478bd9Sstevel@tonic-gate #include <pwd.h>
347c478bd9Sstevel@tonic-gate #include <grp.h>
357c478bd9Sstevel@tonic-gate #include <syslog.h>
367c478bd9Sstevel@tonic-gate #include <stdio.h>
377c478bd9Sstevel@tonic-gate #include <string.h>
387c478bd9Sstevel@tonic-gate #include <ctype.h>
397c478bd9Sstevel@tonic-gate #include <stdlib.h>
407c478bd9Sstevel@tonic-gate #include <unistd.h>
417c478bd9Sstevel@tonic-gate #include <sys/time.h>
427c478bd9Sstevel@tonic-gate #include <sys/fcntl.h>
437c478bd9Sstevel@tonic-gate #include <netinet/in.h>
447c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>	/* Must be ahead of rpcb_clnt.h */
457c478bd9Sstevel@tonic-gate #include <rpc/svc.h>
467c478bd9Sstevel@tonic-gate #include <tiuser.h>
477c478bd9Sstevel@tonic-gate #include <netconfig.h>
487c478bd9Sstevel@tonic-gate #include <netdir.h>
497c478bd9Sstevel@tonic-gate #include <rpc/rpcb_clnt.h>
507c478bd9Sstevel@tonic-gate #include <rpc/pmap_clnt.h>
517c478bd9Sstevel@tonic-gate #include <rpcsvc/nis.h>
527c478bd9Sstevel@tonic-gate #include <rpcsvc/nis_dhext.h>
537c478bd9Sstevel@tonic-gate #include "nis_clnt.h"
547c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
557c478bd9Sstevel@tonic-gate #include <nsswitch.h>
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate #define	MAXIPRINT	(11)	/* max length of printed integer */
587c478bd9Sstevel@tonic-gate /*
597c478bd9Sstevel@tonic-gate  * send and receive buffer size used for clnt_tli_create if not specified.
607c478bd9Sstevel@tonic-gate  * This is only used for "UDP" connection.
617c478bd9Sstevel@tonic-gate  * This limit can be changed from the application if this value is too
627c478bd9Sstevel@tonic-gate  * small for the application.  To use the maximum value for the transport,
637c478bd9Sstevel@tonic-gate  * set this value to 0.
647c478bd9Sstevel@tonic-gate  */
657c478bd9Sstevel@tonic-gate int __nisipbufsize = 8192;
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate /*
697c478bd9Sstevel@tonic-gate  * Static function prototypes.
707c478bd9Sstevel@tonic-gate  */
717c478bd9Sstevel@tonic-gate static struct local_names *__get_local_names(void);
727c478bd9Sstevel@tonic-gate static char *__map_addr(struct netconfig *, char *, rpcprog_t, rpcvers_t);
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate /*
757c478bd9Sstevel@tonic-gate  * nis_dir_cmp() -- the results can be read as:
767c478bd9Sstevel@tonic-gate  * 	"Name 'n1' is a $result than name 'n2'"
777c478bd9Sstevel@tonic-gate  */
787c478bd9Sstevel@tonic-gate name_pos
797c478bd9Sstevel@tonic-gate nis_dir_cmp(
807c478bd9Sstevel@tonic-gate 	nis_name	n1,
817c478bd9Sstevel@tonic-gate 	nis_name	n2)	/* See if these are the same domain */
827c478bd9Sstevel@tonic-gate {
837c478bd9Sstevel@tonic-gate 	size_t		l1, l2;
847c478bd9Sstevel@tonic-gate 	name_pos	result;
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate 	if ((n1 == NULL) || (n2 == NULL))
877c478bd9Sstevel@tonic-gate 		return (BAD_NAME);
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate 	l1 = strlen(n1);
907c478bd9Sstevel@tonic-gate 	l2 = strlen(n2);
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	/* In this routine we're lenient and don't require a trailing '.' */
937c478bd9Sstevel@tonic-gate 	/*   so we need to ignore it if it does appear.			  */
947c478bd9Sstevel@tonic-gate 	/* ==== That's what the previous version did so this one does	  */
957c478bd9Sstevel@tonic-gate 	/*   too, but why?  Is this inconsistent with rest of system?	  */
967c478bd9Sstevel@tonic-gate 	if (l1 != 0 && n1[l1 - 1] == '.') {
977c478bd9Sstevel@tonic-gate 		--l1;
987c478bd9Sstevel@tonic-gate 	}
997c478bd9Sstevel@tonic-gate 	if (l2 != 0 && n2[l2 - 1] == '.') {
1007c478bd9Sstevel@tonic-gate 		--l2;
1017c478bd9Sstevel@tonic-gate 	}
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate 	if (l1 > l2) {
1047c478bd9Sstevel@tonic-gate 		result = LOWER_NAME;
1057c478bd9Sstevel@tonic-gate 	} else if (l1 == l2) {
1067c478bd9Sstevel@tonic-gate 		result = SAME_NAME;
1077c478bd9Sstevel@tonic-gate 	} else /* (l1 < l2); swap l1/l2 and n1/n2 */ {
1087c478bd9Sstevel@tonic-gate 		nis_name	ntmp;
1097c478bd9Sstevel@tonic-gate 		size_t		ltmp;
1107c478bd9Sstevel@tonic-gate 		ntmp = n1; n1 = n2; n2 = ntmp;
1117c478bd9Sstevel@tonic-gate 		ltmp = l1; l1 = l2; l2 = ltmp;
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 		result = HIGHER_NAME;
1147c478bd9Sstevel@tonic-gate 	}
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	/* Now l1 >= l2 in all cases */
1177c478bd9Sstevel@tonic-gate 	if (l2 == 0) {
1187c478bd9Sstevel@tonic-gate 		/* Special case for n2 == "." or "" */
1197c478bd9Sstevel@tonic-gate 		return (result);
1207c478bd9Sstevel@tonic-gate 	}
1217c478bd9Sstevel@tonic-gate 	if (l1 > l2) {
1227c478bd9Sstevel@tonic-gate 		n1 += l1 - l2;
1237c478bd9Sstevel@tonic-gate 		if (n1[-1] != '.') {
1247c478bd9Sstevel@tonic-gate 			return (NOT_SEQUENTIAL);
1257c478bd9Sstevel@tonic-gate 		}
1267c478bd9Sstevel@tonic-gate 	}
1277c478bd9Sstevel@tonic-gate 	if (strncasecmp(n1, n2, l2) == 0) {
1287c478bd9Sstevel@tonic-gate 		return (result);
1297c478bd9Sstevel@tonic-gate 	}
1307c478bd9Sstevel@tonic-gate 	return (NOT_SEQUENTIAL);
1317c478bd9Sstevel@tonic-gate }
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate #define	LN_BUFSIZE	(size_t)1024
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate struct principal_list {
1367c478bd9Sstevel@tonic-gate 	uid_t uid;
1377c478bd9Sstevel@tonic-gate 	char principal[LN_BUFSIZE];
1387c478bd9Sstevel@tonic-gate 	struct principal_list *next;
1397c478bd9Sstevel@tonic-gate };
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate struct local_names {
1437c478bd9Sstevel@tonic-gate 	char domain[LN_BUFSIZE];
1447c478bd9Sstevel@tonic-gate 	char host[LN_BUFSIZE];
1457c478bd9Sstevel@tonic-gate 	char *rpcdomain;
1467c478bd9Sstevel@tonic-gate 	struct principal_list *principal_map;
1477c478bd9Sstevel@tonic-gate 	char group[LN_BUFSIZE];
1487c478bd9Sstevel@tonic-gate };
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate static mutex_t ln_lock = DEFAULTMUTEX; /* lock level 2 */
1517c478bd9Sstevel@tonic-gate static struct local_names *ln = NULL;
1527c478bd9Sstevel@tonic-gate static struct local_names *__get_local_names1();
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate static struct local_names *
1557c478bd9Sstevel@tonic-gate __get_local_names(void)
1567c478bd9Sstevel@tonic-gate {
1577c478bd9Sstevel@tonic-gate 	struct local_names *names;
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	sig_mutex_lock(&ln_lock);
1607c478bd9Sstevel@tonic-gate 	names = __get_local_names1();
1617c478bd9Sstevel@tonic-gate 	sig_mutex_unlock(&ln_lock);
1627c478bd9Sstevel@tonic-gate 	return (names);
1637c478bd9Sstevel@tonic-gate }
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate static struct local_names *
1677c478bd9Sstevel@tonic-gate __get_local_names1(void)
1687c478bd9Sstevel@tonic-gate {
1697c478bd9Sstevel@tonic-gate 	char		*t;
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate 	if (ln != NULL) {
1727c478bd9Sstevel@tonic-gate 		/* Second and subsequent calls go this way */
1737c478bd9Sstevel@tonic-gate 		return (ln);
1747c478bd9Sstevel@tonic-gate 	}
1757c478bd9Sstevel@tonic-gate 	/* First call goes this way */
17661961e0fSrobinson 	ln = calloc(1, sizeof (*ln));
1777c478bd9Sstevel@tonic-gate 	if (ln == NULL) {
1787c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "__get_local_names: Out of heap.");
1797c478bd9Sstevel@tonic-gate 		return (NULL);
1807c478bd9Sstevel@tonic-gate 	}
1817c478bd9Sstevel@tonic-gate 	ln->principal_map = NULL;
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate 	if (sysinfo(SI_SRPC_DOMAIN, ln->domain, LN_BUFSIZE) < 0)
1847c478bd9Sstevel@tonic-gate 		return (ln);
1857c478bd9Sstevel@tonic-gate 	/* If no dot exists, add one. */
1867c478bd9Sstevel@tonic-gate 	if (ln->domain[strlen(ln->domain)-1] != '.')
1877c478bd9Sstevel@tonic-gate 		(void) strcat(ln->domain, ".");
1887c478bd9Sstevel@tonic-gate 	if (sysinfo(SI_HOSTNAME, ln->host, LN_BUFSIZE) < 0)
1897c478bd9Sstevel@tonic-gate 		return (ln);
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	/*
1927c478bd9Sstevel@tonic-gate 	 * Check for fully qualified hostname.  If it's a fully qualified
1937c478bd9Sstevel@tonic-gate 	 * hostname, strip off the domain part.  We always use the local
1947c478bd9Sstevel@tonic-gate 	 * domainname for the host principal name.
1957c478bd9Sstevel@tonic-gate 	 */
1967c478bd9Sstevel@tonic-gate 	t = strchr(ln->host, '.');
1977c478bd9Sstevel@tonic-gate 	if (t)
1987c478bd9Sstevel@tonic-gate 		*t = 0;
1997c478bd9Sstevel@tonic-gate 	if (ln->domain[0] != '.')
2007c478bd9Sstevel@tonic-gate 		(void) strcat(ln->host, ".");
2017c478bd9Sstevel@tonic-gate 	ln->rpcdomain = strdup(ln->domain);
20261961e0fSrobinson 	(void) strcat(ln->host, ln->domain);
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	t = getenv("NIS_GROUP");
2057c478bd9Sstevel@tonic-gate 	if (t == NULL) {
2067c478bd9Sstevel@tonic-gate 		ln->group[0] = '\0';
2077c478bd9Sstevel@tonic-gate 	} else {
2087c478bd9Sstevel@tonic-gate 		size_t maxlen = LN_BUFSIZE-1;	/* max chars to copy */
2097c478bd9Sstevel@tonic-gate 		char *temp;			/* temp marker */
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 		/*
2127c478bd9Sstevel@tonic-gate 		 * Copy <= maximum characters from NIS_GROUP; strncpy()
2137c478bd9Sstevel@tonic-gate 		 * doesn't terminate, so we do that manually. #1223323
2147c478bd9Sstevel@tonic-gate 		 * Also check to see if it's "".  If it's the null string,
2157c478bd9Sstevel@tonic-gate 		 * we return because we don't want to add ".domain".
2167c478bd9Sstevel@tonic-gate 		 */
2177c478bd9Sstevel@tonic-gate 		(void) strncpy(ln->group, t, maxlen);
2187c478bd9Sstevel@tonic-gate 		if (strcmp(ln->group, "") == 0) {
2197c478bd9Sstevel@tonic-gate 			return (ln);
2207c478bd9Sstevel@tonic-gate 		}
2217c478bd9Sstevel@tonic-gate 		ln->group[maxlen] = '\0';
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 		/* Is the group name somewhat fully-qualified? */
2247c478bd9Sstevel@tonic-gate 		temp = strrchr(ln->group, '.');
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 		/* If not, we need to add ".domain" to the group */
2277c478bd9Sstevel@tonic-gate 		if ((temp == NULL) || (temp[1] != '\0')) {
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 			/* truncate to make room for ".domain" */
2307c478bd9Sstevel@tonic-gate 			ln->group[maxlen - (strlen(ln->domain)+1)] = '\0';
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 			/* concat '.' if domain doesn't already have it */
2337c478bd9Sstevel@tonic-gate 			if (ln->domain[0] != '.') {
2347c478bd9Sstevel@tonic-gate 				(void) strcat(ln->group, ".");
2357c478bd9Sstevel@tonic-gate 			}
2367c478bd9Sstevel@tonic-gate 			(void) strcat(ln->group, ln->domain);
2377c478bd9Sstevel@tonic-gate 		}
2387c478bd9Sstevel@tonic-gate 	}
2397c478bd9Sstevel@tonic-gate 	return (ln);
2407c478bd9Sstevel@tonic-gate }
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate /*
2437c478bd9Sstevel@tonic-gate  * nis_local_group()
2447c478bd9Sstevel@tonic-gate  *
2457c478bd9Sstevel@tonic-gate  * Return's the group name of the current user.
2467c478bd9Sstevel@tonic-gate  */
2477c478bd9Sstevel@tonic-gate nis_name
2487c478bd9Sstevel@tonic-gate nis_local_group(void)
2497c478bd9Sstevel@tonic-gate {
2507c478bd9Sstevel@tonic-gate 	struct local_names	*ln = __get_local_names();
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 	/* LOCK NOTE: Warning, after initialization, "ln" is expected	 */
2537c478bd9Sstevel@tonic-gate 	/* to stay constant, So no need to lock here. If this assumption */
2547c478bd9Sstevel@tonic-gate 	/* is changed, this code must be protected.			 */
2557c478bd9Sstevel@tonic-gate 	if (!ln)
2567c478bd9Sstevel@tonic-gate 		return (NULL);
2577c478bd9Sstevel@tonic-gate 	return (ln->group);
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate /*
2617c478bd9Sstevel@tonic-gate  * __nis_nextsep_of()
2627c478bd9Sstevel@tonic-gate  *
2637c478bd9Sstevel@tonic-gate  * This internal funtion will accept a pointer to a NIS name string and
2647c478bd9Sstevel@tonic-gate  * return a pointer to the next separator occurring in it (it will point
2657c478bd9Sstevel@tonic-gate  * just past the first label).  It allows for labels to be "quoted" to
2667c478bd9Sstevel@tonic-gate  * prevent the the dot character within them to be interpreted as a
2677c478bd9Sstevel@tonic-gate  * separator, also the quote character itself can be quoted by using
2687c478bd9Sstevel@tonic-gate  * it twice.  If the the name contains only one label and no trailing
2697c478bd9Sstevel@tonic-gate  * dot character, a pointer to the terminating NULL is returned.
2707c478bd9Sstevel@tonic-gate  */
2717c478bd9Sstevel@tonic-gate nis_name
2727c478bd9Sstevel@tonic-gate __nis_nextsep_of(char *s)
2737c478bd9Sstevel@tonic-gate {
2747c478bd9Sstevel@tonic-gate 	char	*d;
275*36e852a1SRaja Andra 	int	in_quotes = FALSE, quote_quote = FALSE;
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	if (!s)
2787c478bd9Sstevel@tonic-gate 		return (NULL);
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 	for (d = s; (in_quotes && (*d != '\0')) ||
2817c478bd9Sstevel@tonic-gate 	    (!in_quotes && (*d != '.') && (*d != '\0')); d++) {
2827c478bd9Sstevel@tonic-gate 		if (quote_quote && in_quotes && (*d != '"')) {
2837c478bd9Sstevel@tonic-gate 			quote_quote = FALSE;
2847c478bd9Sstevel@tonic-gate 			in_quotes = FALSE;
2857c478bd9Sstevel@tonic-gate 			if (*d == '.')
2867c478bd9Sstevel@tonic-gate 				break;
2877c478bd9Sstevel@tonic-gate 		} else if (quote_quote && in_quotes && (*d == '"')) {
2887c478bd9Sstevel@tonic-gate 			quote_quote = FALSE;
2897c478bd9Sstevel@tonic-gate 		} else if (quote_quote && (*d != '"')) {
2907c478bd9Sstevel@tonic-gate 			quote_quote = FALSE;
2917c478bd9Sstevel@tonic-gate 			in_quotes = TRUE;
2927c478bd9Sstevel@tonic-gate 		} else if (quote_quote && (*d == '"')) {
2937c478bd9Sstevel@tonic-gate 			quote_quote = FALSE;
2947c478bd9Sstevel@tonic-gate 		} else if (in_quotes && (*d == '"')) {
2957c478bd9Sstevel@tonic-gate 			quote_quote = TRUE;
2967c478bd9Sstevel@tonic-gate 		} else if (!in_quotes && (*d == '"')) {
2977c478bd9Sstevel@tonic-gate 			quote_quote = TRUE;
2987c478bd9Sstevel@tonic-gate 		}
2997c478bd9Sstevel@tonic-gate 	}
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 	if (quote_quote || in_quotes) {
3027c478bd9Sstevel@tonic-gate 		syslog(LOG_DEBUG, "__nis_nextsep_of: "
3037c478bd9Sstevel@tonic-gate 		    "Mismatched quotes in %s", s);
3047c478bd9Sstevel@tonic-gate 	}
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 	return (d);
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate /*
3107c478bd9Sstevel@tonic-gate  * nis_domain_of()
3117c478bd9Sstevel@tonic-gate  *
3127c478bd9Sstevel@tonic-gate  * This internal funtion will accept a pointer to a NIS name string and
3137c478bd9Sstevel@tonic-gate  * return a pointer to the "domain" part of it.
3147c478bd9Sstevel@tonic-gate  *
3157c478bd9Sstevel@tonic-gate  * ==== We don't need nis_domain_of_r(), but should we provide one for
3167c478bd9Sstevel@tonic-gate  *	uniformity?
3177c478bd9Sstevel@tonic-gate  */
3187c478bd9Sstevel@tonic-gate nis_name
3197c478bd9Sstevel@tonic-gate nis_domain_of(char *s)
3207c478bd9Sstevel@tonic-gate {
3217c478bd9Sstevel@tonic-gate 	char	*d;
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 	d = __nis_nextsep_of(s);
3247c478bd9Sstevel@tonic-gate 	if (d == NULL)
3257c478bd9Sstevel@tonic-gate 		return (NULL);
3267c478bd9Sstevel@tonic-gate 	if (*d == '.')
3277c478bd9Sstevel@tonic-gate 		d++;
3287c478bd9Sstevel@tonic-gate 	if (*d == '\0')	/* Don't return a zero length string */
3297c478bd9Sstevel@tonic-gate 		return ("."); /* return root domain instead */
3307c478bd9Sstevel@tonic-gate 	return (d);
3317c478bd9Sstevel@tonic-gate }
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate /*
3357c478bd9Sstevel@tonic-gate  * nis_leaf_of()
3367c478bd9Sstevel@tonic-gate  *
3377c478bd9Sstevel@tonic-gate  * Returns the first label of a name. (other half of __domain_of)
3387c478bd9Sstevel@tonic-gate  */
3397c478bd9Sstevel@tonic-gate nis_name
3407c478bd9Sstevel@tonic-gate nis_leaf_of_r(
3417c478bd9Sstevel@tonic-gate 	const nis_name	s,
3427c478bd9Sstevel@tonic-gate 	char		*buf,
3437c478bd9Sstevel@tonic-gate 	size_t		bufsize)
3447c478bd9Sstevel@tonic-gate {
3457c478bd9Sstevel@tonic-gate 	size_t		nchars;
3467c478bd9Sstevel@tonic-gate 	const char	*d = __nis_nextsep_of((char *)s);
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	if (d == 0) {
3497c478bd9Sstevel@tonic-gate 		return (0);
3507c478bd9Sstevel@tonic-gate 	}
3517c478bd9Sstevel@tonic-gate 	nchars = d - s;
3527c478bd9Sstevel@tonic-gate 	if (bufsize < nchars + 1) {
3537c478bd9Sstevel@tonic-gate 		return (0);
3547c478bd9Sstevel@tonic-gate 	}
3557c478bd9Sstevel@tonic-gate 	(void) strncpy(buf, s, nchars);
3567c478bd9Sstevel@tonic-gate 	buf[nchars] = '\0';
3577c478bd9Sstevel@tonic-gate 	return (buf);
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate 
360cb620785Sraf static pthread_key_t buf_key = PTHREAD_ONCE_KEY_NP;
3617c478bd9Sstevel@tonic-gate static char buf_main[LN_BUFSIZE];
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate nis_name
3647c478bd9Sstevel@tonic-gate nis_leaf_of(char *s)
3657c478bd9Sstevel@tonic-gate {
3667c478bd9Sstevel@tonic-gate 	char *buf = thr_main()? buf_main :
3677c478bd9Sstevel@tonic-gate 	    thr_get_storage(&buf_key, LN_BUFSIZE, free);
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	if (buf == NULL)
3707c478bd9Sstevel@tonic-gate 		return (NULL);
3717c478bd9Sstevel@tonic-gate 	return (nis_leaf_of_r(s, buf,  LN_BUFSIZE));
3727c478bd9Sstevel@tonic-gate }
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate /*
3757c478bd9Sstevel@tonic-gate  * nis_name_of()
3767c478bd9Sstevel@tonic-gate  * This internal function will remove from the NIS name, the domain
3777c478bd9Sstevel@tonic-gate  * name of the current server, this will leave the unique part in
3787c478bd9Sstevel@tonic-gate  * the name this becomes the "internal" version of the name. If this
3797c478bd9Sstevel@tonic-gate  * function returns NULL then the name we were given to resolve is
3807c478bd9Sstevel@tonic-gate  * bad somehow.
3817c478bd9Sstevel@tonic-gate  * NB: Uses static storage and this is a no-no with threads. XXX
3827c478bd9Sstevel@tonic-gate  */
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate nis_name
3857c478bd9Sstevel@tonic-gate nis_name_of_r(
3867c478bd9Sstevel@tonic-gate 	char	*s,	/* string with the name in it. */
3877c478bd9Sstevel@tonic-gate 	char		*buf,
3887c478bd9Sstevel@tonic-gate 	size_t		bufsize)
3897c478bd9Sstevel@tonic-gate {
3907c478bd9Sstevel@tonic-gate 	char			*d;
3917c478bd9Sstevel@tonic-gate 	struct local_names 	*ln = __get_local_names();
3927c478bd9Sstevel@tonic-gate 	size_t			dl, sl;
3937c478bd9Sstevel@tonic-gate 	name_pos		p;
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate #ifdef lint
3967c478bd9Sstevel@tonic-gate 	bufsize = bufsize;
3977c478bd9Sstevel@tonic-gate #endif /* lint */
3987c478bd9Sstevel@tonic-gate 	if ((!s) || (!ln))
3997c478bd9Sstevel@tonic-gate 		return (NULL);		/* No string, this can't continue */
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	d  = &(ln->domain[0]);
4027c478bd9Sstevel@tonic-gate 	dl = strlen(ln->domain); 	/* _always dot terminated_   */
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 	sl = strlen(s);
4057c478bd9Sstevel@tonic-gate 	if (sl >= bufsize || (s[sl-1] != '.' && sl >= bufsize-1))
4067c478bd9Sstevel@tonic-gate 		return (NULL);
4077c478bd9Sstevel@tonic-gate 	(void) strcpy(buf, s);		/* Make a private copy of 's'   */
4087c478bd9Sstevel@tonic-gate 	if (buf[sl-1] != '.') {	/* Add a dot if necessary.  */
4097c478bd9Sstevel@tonic-gate 		(void) strcat(buf, ".");
4107c478bd9Sstevel@tonic-gate 		sl++;
4117c478bd9Sstevel@tonic-gate 	}
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 	if (dl == 1) {			/* We're the '.' directory   */
4147c478bd9Sstevel@tonic-gate 		buf[sl-1] = '\0';	/* Lose the 'dot'	  */
4157c478bd9Sstevel@tonic-gate 		return (buf);
4167c478bd9Sstevel@tonic-gate 	}
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 	p = nis_dir_cmp(buf, d);
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 	/* 's' is above 'd' in the tree */
4217c478bd9Sstevel@tonic-gate 	if ((p == HIGHER_NAME) || (p == NOT_SEQUENTIAL) || (p == SAME_NAME))
4227c478bd9Sstevel@tonic-gate 		return (NULL);
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	/* Insert a NUL where the domain name starts in the string */
4257c478bd9Sstevel@tonic-gate 	buf[(sl - dl) - 1] = '\0';
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 	/* Don't return a zero length name */
4287c478bd9Sstevel@tonic-gate 	if (buf[0] == '\0')
4297c478bd9Sstevel@tonic-gate 		return (NULL);
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	return (buf);
4327c478bd9Sstevel@tonic-gate }
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate nis_name
4357c478bd9Sstevel@tonic-gate nis_name_of(
4367c478bd9Sstevel@tonic-gate 	char	*s)	/* string with the name in it. */
4377c478bd9Sstevel@tonic-gate {
4387c478bd9Sstevel@tonic-gate 	char *buf = thr_main()? buf_main :
4397c478bd9Sstevel@tonic-gate 	    thr_get_storage(&buf_key, LN_BUFSIZE, free);
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate 	if (!buf)
4427c478bd9Sstevel@tonic-gate 		return (NULL);
4437c478bd9Sstevel@tonic-gate 	return (nis_name_of_r(s, buf,  LN_BUFSIZE));
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate /*
4497c478bd9Sstevel@tonic-gate  * nis_local_directory()
4507c478bd9Sstevel@tonic-gate  *
4517c478bd9Sstevel@tonic-gate  * Return a pointer to a string with the local directory name in it.
4527c478bd9Sstevel@tonic-gate  */
4537c478bd9Sstevel@tonic-gate nis_name
4547c478bd9Sstevel@tonic-gate nis_local_directory(void)
4557c478bd9Sstevel@tonic-gate {
4567c478bd9Sstevel@tonic-gate 	struct local_names	*ln = __get_local_names();
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	/* LOCK NOTE: Warning, after initialization, "ln" is expected	 */
4597c478bd9Sstevel@tonic-gate 	/* to stay constant, So no need to lock here. If this assumption */
4607c478bd9Sstevel@tonic-gate 	/* is changed, this code must be protected.			 */
4617c478bd9Sstevel@tonic-gate 	if (ln == NULL)
4627c478bd9Sstevel@tonic-gate 		return (NULL);
4637c478bd9Sstevel@tonic-gate 	return (ln->domain);
4647c478bd9Sstevel@tonic-gate }
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate /*
4677c478bd9Sstevel@tonic-gate  * __nis_rpc_domain()
4687c478bd9Sstevel@tonic-gate  *
4697c478bd9Sstevel@tonic-gate  * Return a pointer to a string with the rpc domain name in it.
4707c478bd9Sstevel@tonic-gate  */
4717c478bd9Sstevel@tonic-gate nis_name
4727c478bd9Sstevel@tonic-gate __nis_rpc_domain()
4737c478bd9Sstevel@tonic-gate {
4747c478bd9Sstevel@tonic-gate 	struct local_names	*ln = __get_local_names();
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 	/* LOCK NOTE: Warning, after initialization, "ln" is expected	 */
4777c478bd9Sstevel@tonic-gate 	/* to stay constant, So no need to lock here. If this assumption */
4787c478bd9Sstevel@tonic-gate 	/* is changed, this code must be protected.			 */
4797c478bd9Sstevel@tonic-gate 	if (ln == NULL)
4807c478bd9Sstevel@tonic-gate 		return (NULL);
4817c478bd9Sstevel@tonic-gate 	return (ln->rpcdomain);
4827c478bd9Sstevel@tonic-gate }
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate 
4857c478bd9Sstevel@tonic-gate /*
4867c478bd9Sstevel@tonic-gate  * nis_local_host()
4877c478bd9Sstevel@tonic-gate  * Generate the principal name for this host, "hostname"+"domainname"
4887c478bd9Sstevel@tonic-gate  * unless the hostname already has "dots" in its name.
4897c478bd9Sstevel@tonic-gate  */
4907c478bd9Sstevel@tonic-gate nis_name
4917c478bd9Sstevel@tonic-gate nis_local_host(void)
4927c478bd9Sstevel@tonic-gate {
4937c478bd9Sstevel@tonic-gate 	struct local_names	*ln = __get_local_names();
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate 	/* LOCK NOTE: Warning, after initialization, "ln" is expected	 */
4967c478bd9Sstevel@tonic-gate 	/* to stay constant, So no need to lock here. If this assumption */
4977c478bd9Sstevel@tonic-gate 	/* is changed, this code must be protected.			 */
4987c478bd9Sstevel@tonic-gate 	if (ln == NULL)
4997c478bd9Sstevel@tonic-gate 		return (NULL);
5007c478bd9Sstevel@tonic-gate 
5017c478bd9Sstevel@tonic-gate 	return (ln->host);
5027c478bd9Sstevel@tonic-gate }
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate /*
5057c478bd9Sstevel@tonic-gate  * nis_destroy_object()
5067c478bd9Sstevel@tonic-gate  * This function takes a pointer to a NIS object and deallocates it. This
5077c478bd9Sstevel@tonic-gate  * is the inverse of __clone_object below. It must be able to correctly
5087c478bd9Sstevel@tonic-gate  * deallocate partially allocated objects because __clone_object will call
5097c478bd9Sstevel@tonic-gate  * it if it runs out of memory and has to abort. Everything is freed,
5107c478bd9Sstevel@tonic-gate  * INCLUDING the pointer that is passed.
5117c478bd9Sstevel@tonic-gate  */
5127c478bd9Sstevel@tonic-gate void
5137c478bd9Sstevel@tonic-gate nis_destroy_object(nis_object *obj)	/* The object to clone */
5147c478bd9Sstevel@tonic-gate {
5157c478bd9Sstevel@tonic-gate 	if (obj == 0)
5167c478bd9Sstevel@tonic-gate 		return;
5177c478bd9Sstevel@tonic-gate 	xdr_free(xdr_nis_object, (char *)obj);
5187c478bd9Sstevel@tonic-gate 	free(obj);
5197c478bd9Sstevel@tonic-gate } /* nis_destroy_object */
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate static void
5227c478bd9Sstevel@tonic-gate destroy_nis_sdata(void *p)
5237c478bd9Sstevel@tonic-gate {
5247c478bd9Sstevel@tonic-gate 	struct nis_sdata	*ns = p;
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 	if (ns->buf != 0)
5277c478bd9Sstevel@tonic-gate 		free(ns->buf);
5287c478bd9Sstevel@tonic-gate 	free(ns);
5297c478bd9Sstevel@tonic-gate }
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate /* XXX Why are these static ? */
5327c478bd9Sstevel@tonic-gate /* static XDR in_xdrs, out_xdrs; */
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate /*
5367c478bd9Sstevel@tonic-gate  * __clone_object_r()
5377c478bd9Sstevel@tonic-gate  * This function takes a pointer to a NIS object and clones it. This
5387c478bd9Sstevel@tonic-gate  * duplicate object is now available for use in the local context.
5397c478bd9Sstevel@tonic-gate  */
5407c478bd9Sstevel@tonic-gate nis_object *
5417c478bd9Sstevel@tonic-gate nis_clone_object_r(
5427c478bd9Sstevel@tonic-gate 	nis_object	*obj,	/* The object to clone */
5437c478bd9Sstevel@tonic-gate 	nis_object	*dest,	/* Use this pointer if non-null */
5447c478bd9Sstevel@tonic-gate 	struct nis_sdata *clone_buf_ptr)
5457c478bd9Sstevel@tonic-gate {
5467c478bd9Sstevel@tonic-gate 	nis_object	*result; /* The clone itself */
5477c478bd9Sstevel@tonic-gate 	int		status; /* a counter variable */
5487c478bd9Sstevel@tonic-gate 	XDR		in_xdrs, out_xdrs;
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	if (!nis_get_static_storage(clone_buf_ptr, 1,
5517c478bd9Sstevel@tonic-gate 	    xdr_sizeof(xdr_nis_object, obj)))
5527c478bd9Sstevel@tonic-gate 		return (NULL);
5537c478bd9Sstevel@tonic-gate 
55461961e0fSrobinson 	(void) memset(&in_xdrs, 0, sizeof (in_xdrs));
55561961e0fSrobinson 	(void) memset(&out_xdrs, 0, sizeof (out_xdrs));
5567c478bd9Sstevel@tonic-gate 	xdrmem_create(&in_xdrs, clone_buf_ptr->buf, clone_buf_ptr->size,
5577c478bd9Sstevel@tonic-gate 	    XDR_ENCODE);
5587c478bd9Sstevel@tonic-gate 	xdrmem_create(&out_xdrs, clone_buf_ptr->buf, clone_buf_ptr->size,
5597c478bd9Sstevel@tonic-gate 	    XDR_DECODE);
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 	/* Allocate a basic NIS object structure */
5627c478bd9Sstevel@tonic-gate 	if (dest) {
56361961e0fSrobinson 		(void) memset(dest, 0, sizeof (nis_object));
5647c478bd9Sstevel@tonic-gate 		result = dest;
5657c478bd9Sstevel@tonic-gate 	} else
56661961e0fSrobinson 		result = calloc(1, sizeof (nis_object));
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate 	if (result == NULL)
5697c478bd9Sstevel@tonic-gate 		return (NULL);
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 	/* Encode our object into the clone buffer */
5727c478bd9Sstevel@tonic-gate 	(void) xdr_setpos(&in_xdrs, 0);
5737c478bd9Sstevel@tonic-gate 	status = xdr_nis_object(&in_xdrs, obj);
5747c478bd9Sstevel@tonic-gate 	if (status == FALSE)
5757c478bd9Sstevel@tonic-gate 		return (NULL);
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate 	/* Now decode the buffer into our result pointer ... */
5787c478bd9Sstevel@tonic-gate 	(void) xdr_setpos(&out_xdrs, 0);
5797c478bd9Sstevel@tonic-gate 	status = xdr_nis_object(&out_xdrs, result);
5807c478bd9Sstevel@tonic-gate 	if (status == FALSE)
5817c478bd9Sstevel@tonic-gate 		return (NULL);
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 	/* presto changeo, a new object */
5847c478bd9Sstevel@tonic-gate 	return (result);
5857c478bd9Sstevel@tonic-gate } /* __clone_object_r */
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate nis_object *
5897c478bd9Sstevel@tonic-gate nis_clone_object(
5907c478bd9Sstevel@tonic-gate 	nis_object	*obj,	/* The object to clone */
5917c478bd9Sstevel@tonic-gate 	nis_object	*dest)	/* Use this pointer if non-null */
5927c478bd9Sstevel@tonic-gate {
593cb620785Sraf 	static pthread_key_t clone_buf_key = PTHREAD_ONCE_KEY_NP;
5947c478bd9Sstevel@tonic-gate 	static struct nis_sdata clone_buf_main;
5957c478bd9Sstevel@tonic-gate 	struct nis_sdata *clone_buf_ptr;
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate 	clone_buf_ptr = thr_main()? &clone_buf_main :
5987c478bd9Sstevel@tonic-gate 	    thr_get_storage(&clone_buf_key, sizeof (struct nis_sdata),
5997c478bd9Sstevel@tonic-gate 	    destroy_nis_sdata);
6007c478bd9Sstevel@tonic-gate 	return (nis_clone_object_r(obj, dest, clone_buf_ptr));
6017c478bd9Sstevel@tonic-gate } /* __clone_object */
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate /* Various subroutines used by the server code */
6047c478bd9Sstevel@tonic-gate nis_object *
6057c478bd9Sstevel@tonic-gate nis_read_obj(char *f)	/* name of the object to read */
6067c478bd9Sstevel@tonic-gate {
6077c478bd9Sstevel@tonic-gate 	FILE	*rootfile;
6087c478bd9Sstevel@tonic-gate 	int	status;	/* Status of the XDR decoding */
6097c478bd9Sstevel@tonic-gate 	XDR	xdrs;	/* An xdr stream handle */
6107c478bd9Sstevel@tonic-gate 	nis_object	*res;
6117c478bd9Sstevel@tonic-gate 
61261961e0fSrobinson 	res = calloc(1, sizeof (nis_object));
6137c478bd9Sstevel@tonic-gate 	if (!res)
6147c478bd9Sstevel@tonic-gate 		return (NULL);
6157c478bd9Sstevel@tonic-gate 
616004388ebScasper 	rootfile = fopen(f, "rF");
6177c478bd9Sstevel@tonic-gate 	if (rootfile == NULL) {
6187c478bd9Sstevel@tonic-gate 		/* This is ok if we are the root of roots. */
6197c478bd9Sstevel@tonic-gate 		free(res);
6207c478bd9Sstevel@tonic-gate 		return (NULL);
6217c478bd9Sstevel@tonic-gate 	}
6227c478bd9Sstevel@tonic-gate 	/* Now read in the object */
6237c478bd9Sstevel@tonic-gate 	xdrstdio_create(&xdrs, rootfile, XDR_DECODE);
6247c478bd9Sstevel@tonic-gate 	status = xdr_nis_object(&xdrs, res);
6257c478bd9Sstevel@tonic-gate 	xdr_destroy(&xdrs);
6267c478bd9Sstevel@tonic-gate 	(void) fclose(rootfile);
6277c478bd9Sstevel@tonic-gate 	if (!status) {
6287c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "Object file %s is corrupt!", f);
6297c478bd9Sstevel@tonic-gate 		xdr_free(xdr_nis_object, (char *)res);
6307c478bd9Sstevel@tonic-gate 		free(res);
6317c478bd9Sstevel@tonic-gate 		return (NULL);
6327c478bd9Sstevel@tonic-gate 	}
6337c478bd9Sstevel@tonic-gate 	return (res);
6347c478bd9Sstevel@tonic-gate }
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate int
6377c478bd9Sstevel@tonic-gate nis_write_obj(
6387c478bd9Sstevel@tonic-gate 	char	*f,	/* name of the object to read */
6397c478bd9Sstevel@tonic-gate 	nis_object *o)	/* The object to write */
6407c478bd9Sstevel@tonic-gate {
6417c478bd9Sstevel@tonic-gate 	FILE	*rootfile;
6427c478bd9Sstevel@tonic-gate 	int	status;	/* Status of the XDR decoding */
6437c478bd9Sstevel@tonic-gate 	XDR	xdrs;	/* An xdr stream handle */
6447c478bd9Sstevel@tonic-gate 
645004388ebScasper 	rootfile = fopen(f, "wF");
6467c478bd9Sstevel@tonic-gate 	if (rootfile == NULL) {
6477c478bd9Sstevel@tonic-gate 		return (0);
6487c478bd9Sstevel@tonic-gate 	}
6497c478bd9Sstevel@tonic-gate 	/* Now encode the object */
6507c478bd9Sstevel@tonic-gate 	xdrstdio_create(&xdrs, rootfile, XDR_ENCODE);
6517c478bd9Sstevel@tonic-gate 	status = xdr_nis_object(&xdrs, o);
6527c478bd9Sstevel@tonic-gate 	xdr_destroy(&xdrs);
6537c478bd9Sstevel@tonic-gate 	(void) fclose(rootfile);
6547c478bd9Sstevel@tonic-gate 	return (status);
6557c478bd9Sstevel@tonic-gate }
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate /*
6587c478bd9Sstevel@tonic-gate  * Transport INDEPENDENT RPC code. This code assumes you
6597c478bd9Sstevel@tonic-gate  * are using the new RPC/tli code and will build
6607c478bd9Sstevel@tonic-gate  * a ping handle on top of a datagram transport.
6617c478bd9Sstevel@tonic-gate  */
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate /*
6647c478bd9Sstevel@tonic-gate  * __map_addr()
6657c478bd9Sstevel@tonic-gate  *
6667c478bd9Sstevel@tonic-gate  * This is our internal function that replaces rpcb_getaddr(). We
6677c478bd9Sstevel@tonic-gate  * build our own to prevent calling netdir_getbyname() which could
6687c478bd9Sstevel@tonic-gate  * recurse to the nameservice.
6697c478bd9Sstevel@tonic-gate  */
6707c478bd9Sstevel@tonic-gate static char *
6717c478bd9Sstevel@tonic-gate __map_addr(
6727c478bd9Sstevel@tonic-gate 	struct netconfig	*nc,		/* Our transport	*/
6737c478bd9Sstevel@tonic-gate 	char			*uaddr,		/* RPCBIND address */
6747c478bd9Sstevel@tonic-gate 	rpcprog_t		prog,		/* Name service Prog */
6757c478bd9Sstevel@tonic-gate 	rpcvers_t		ver)
6767c478bd9Sstevel@tonic-gate {
6777c478bd9Sstevel@tonic-gate 	CLIENT *client;
6787c478bd9Sstevel@tonic-gate 	RPCB 		parms;		/* Parameters for RPC binder	  */
6797c478bd9Sstevel@tonic-gate 	enum clnt_stat	clnt_st;	/* Result from the rpc call	  */
6807c478bd9Sstevel@tonic-gate 	char 		*ua = NULL;	/* Universal address of service	  */
6817c478bd9Sstevel@tonic-gate 	char		*res = NULL;	/* Our result to the parent	  */
6827c478bd9Sstevel@tonic-gate 	struct timeval	tv;		/* Timeout for our rpcb call	  */
6837c478bd9Sstevel@tonic-gate 	int		ilen, olen;	/* buffer length for clnt_tli_create */
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate 	/*
6867c478bd9Sstevel@tonic-gate 	 * If using "udp", use __nisipbufsize if inbuf and outbuf are set to 0.
6877c478bd9Sstevel@tonic-gate 	 */
6887c478bd9Sstevel@tonic-gate 	if (strcmp(NC_UDP, nc->nc_proto) == 0) {
6897c478bd9Sstevel@tonic-gate 			/* for udp only */
6907c478bd9Sstevel@tonic-gate 		ilen = olen = __nisipbufsize;
6917c478bd9Sstevel@tonic-gate 	} else {
6927c478bd9Sstevel@tonic-gate 		ilen = olen = 0;
6937c478bd9Sstevel@tonic-gate 	}
6947c478bd9Sstevel@tonic-gate 	client = __nis_clnt_create(RPC_ANYFD, nc, uaddr, 0, 0,
6957c478bd9Sstevel@tonic-gate 	    RPCBPROG, RPCBVERS, ilen, olen);
69661961e0fSrobinson 	if (!client)
6977c478bd9Sstevel@tonic-gate 		return (NULL);
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate 	(void) clnt_control(client, CLSET_FD_CLOSE, NULL);
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 	/*
7027c478bd9Sstevel@tonic-gate 	 * Now make the call to get the NIS service address.
7037c478bd9Sstevel@tonic-gate 	 * We set the retry timeout to 3 seconds so that we
7047c478bd9Sstevel@tonic-gate 	 * will retry a few times.  Retries should be rare
7057c478bd9Sstevel@tonic-gate 	 * because we are usually only called when we know
7067c478bd9Sstevel@tonic-gate 	 * a server is available.
7077c478bd9Sstevel@tonic-gate 	 */
7087c478bd9Sstevel@tonic-gate 	tv.tv_sec = 3;
7097c478bd9Sstevel@tonic-gate 	tv.tv_usec = 0;
7107c478bd9Sstevel@tonic-gate 	(void) clnt_control(client, CLSET_RETRY_TIMEOUT, (char *)&tv);
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate 	tv.tv_sec = 10;
7137c478bd9Sstevel@tonic-gate 	tv.tv_usec = 0;
7147c478bd9Sstevel@tonic-gate 	parms.r_prog = prog;
7157c478bd9Sstevel@tonic-gate 	parms.r_vers = ver;
7167c478bd9Sstevel@tonic-gate 	parms.r_netid = nc->nc_netid;	/* not needed */
7177c478bd9Sstevel@tonic-gate 	parms.r_addr = "";	/* not needed; just for xdring */
7187c478bd9Sstevel@tonic-gate 	parms.r_owner = "";	/* not needed; just for xdring */
7197c478bd9Sstevel@tonic-gate 	clnt_st = clnt_call(client, RPCBPROC_GETADDR, xdr_rpcb, (char *)&parms,
7207c478bd9Sstevel@tonic-gate 	    xdr_wrapstring, (char *)&ua, tv);
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate 	if (clnt_st == RPC_SUCCESS) {
7237c478bd9Sstevel@tonic-gate 		clnt_destroy(client);
7247c478bd9Sstevel@tonic-gate 		if (*ua == '\0') {
72561961e0fSrobinson 			free(ua);
7267c478bd9Sstevel@tonic-gate 			return (NULL);
7277c478bd9Sstevel@tonic-gate 		}
7287c478bd9Sstevel@tonic-gate 		res = strdup(ua);
7297c478bd9Sstevel@tonic-gate 		xdr_free(xdr_wrapstring, (char *)&ua);
7307c478bd9Sstevel@tonic-gate 		return (res);
7317c478bd9Sstevel@tonic-gate 	} else if (((clnt_st == RPC_PROGVERSMISMATCH) ||
7327c478bd9Sstevel@tonic-gate 	    (clnt_st == RPC_PROGUNAVAIL)) &&
7337c478bd9Sstevel@tonic-gate 	    (strcmp(nc->nc_protofmly, NC_INET) == 0)) {
7347c478bd9Sstevel@tonic-gate 		/*
7357c478bd9Sstevel@tonic-gate 		 * version 3 not available. Try version 2
7367c478bd9Sstevel@tonic-gate 		 * The assumption here is that the netbuf
7377c478bd9Sstevel@tonic-gate 		 * is arranged in the sockaddr_in
7387c478bd9Sstevel@tonic-gate 		 * style for IP cases.
7397c478bd9Sstevel@tonic-gate 		 *
7407c478bd9Sstevel@tonic-gate 		 * Note:	If the remote host doesn't support version 3,
7417c478bd9Sstevel@tonic-gate 		 *		we assume it doesn't know IPv6 either.
7427c478bd9Sstevel@tonic-gate 		 */
7437c478bd9Sstevel@tonic-gate 		ushort_t 		port;
7447c478bd9Sstevel@tonic-gate 		struct sockaddr_in	*sa;
7457c478bd9Sstevel@tonic-gate 		struct netbuf 		remote;
7467c478bd9Sstevel@tonic-gate 		int			protocol;
7477c478bd9Sstevel@tonic-gate 		char			buf[32];
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 		(void) clnt_control(client, CLGET_SVC_ADDR, (char *)&remote);
75061961e0fSrobinson 		/* LINTED pointer cast */
7517c478bd9Sstevel@tonic-gate 		sa = (struct sockaddr_in *)(remote.buf);
7527c478bd9Sstevel@tonic-gate 		protocol = strcmp(nc->nc_proto, NC_TCP) ?
7537c478bd9Sstevel@tonic-gate 		    IPPROTO_UDP : IPPROTO_TCP;
7547c478bd9Sstevel@tonic-gate 		port = (ushort_t)pmap_getport(sa, prog, ver, protocol);
7557c478bd9Sstevel@tonic-gate 
7567c478bd9Sstevel@tonic-gate 		if (port != 0) {
7577c478bd9Sstevel@tonic-gate 			port = htons(port);
7587c478bd9Sstevel@tonic-gate 			(void) sprintf(buf, "%d.%d.%d.%d.%d.%d",
7597c478bd9Sstevel@tonic-gate 			    (sa->sin_addr.s_addr >> 24) & 0xff,
7607c478bd9Sstevel@tonic-gate 			    (sa->sin_addr.s_addr >> 16) & 0xff,
7617c478bd9Sstevel@tonic-gate 			    (sa->sin_addr.s_addr >>  8) & 0xff,
7627c478bd9Sstevel@tonic-gate 			    (sa->sin_addr.s_addr) & 0xff,
7637c478bd9Sstevel@tonic-gate 			    (port >> 8) & 0xff,
7647c478bd9Sstevel@tonic-gate 			    port & 0xff);
7657c478bd9Sstevel@tonic-gate 			res = strdup(buf);
7667c478bd9Sstevel@tonic-gate 		} else
7677c478bd9Sstevel@tonic-gate 			res = NULL;
7687c478bd9Sstevel@tonic-gate 		clnt_destroy(client);
7697c478bd9Sstevel@tonic-gate 		return (res);
7707c478bd9Sstevel@tonic-gate 	}
7717c478bd9Sstevel@tonic-gate 	if (clnt_st == RPC_TIMEDOUT)
7727c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "NIS+ server not responding");
7737c478bd9Sstevel@tonic-gate 	else
7747c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "NIS+ server could not be contacted: %s",
7757c478bd9Sstevel@tonic-gate 		    clnt_sperrno(clnt_st));
7767c478bd9Sstevel@tonic-gate 	clnt_destroy(client);
7777c478bd9Sstevel@tonic-gate 	return (NULL);
7787c478bd9Sstevel@tonic-gate }
7797c478bd9Sstevel@tonic-gate 
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate #define	MAX_EP (20)
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate extern int __can_use_af(sa_family_t af);
7847c478bd9Sstevel@tonic-gate 
7857c478bd9Sstevel@tonic-gate CLIENT *
7867c478bd9Sstevel@tonic-gate __nis_clnt_create(int fd, struct netconfig *nc, char *uaddr,
7877c478bd9Sstevel@tonic-gate 			struct netbuf *addr, int domapaddr,
7887c478bd9Sstevel@tonic-gate 			int prog, int ver, int inbuf, int outbuf) {
7897c478bd9Sstevel@tonic-gate 
7907c478bd9Sstevel@tonic-gate 	char		*svc_addr;
7917c478bd9Sstevel@tonic-gate 	CLIENT		*clnt;
7927c478bd9Sstevel@tonic-gate 	int		freeaddr = 0;
7937c478bd9Sstevel@tonic-gate 
7947c478bd9Sstevel@tonic-gate 	/* Sanity check */
7957c478bd9Sstevel@tonic-gate 	if (nc == 0 || (addr == 0 && uaddr == 0)) {
7967c478bd9Sstevel@tonic-gate 		return (0);
7977c478bd9Sstevel@tonic-gate 	}
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate 	/*
8007c478bd9Sstevel@tonic-gate 	 * Check if we have a useable interface for this address family.
8017c478bd9Sstevel@tonic-gate 	 * This check properly belongs in RPC (or even further down),
8027c478bd9Sstevel@tonic-gate 	 * but until they provide it, we roll our own.
8037c478bd9Sstevel@tonic-gate 	 */
8047c478bd9Sstevel@tonic-gate 	if (__can_use_af((strcmp(nc->nc_protofmly, NC_INET6) == 0) ?
8057c478bd9Sstevel@tonic-gate 			AF_INET6 : AF_INET) == 0) {
8067c478bd9Sstevel@tonic-gate 		return (0);
8077c478bd9Sstevel@tonic-gate 	}
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 	if (domapaddr) {
8107c478bd9Sstevel@tonic-gate 		svc_addr = __map_addr(nc, uaddr, prog, ver);
8117c478bd9Sstevel@tonic-gate 		if (svc_addr == 0)
8127c478bd9Sstevel@tonic-gate 			return (0);
8137c478bd9Sstevel@tonic-gate 		addr = uaddr2taddr(nc, svc_addr);
8147c478bd9Sstevel@tonic-gate 		freeaddr = 1;
8157c478bd9Sstevel@tonic-gate 		free(svc_addr);
8167c478bd9Sstevel@tonic-gate 	} else if (addr == 0) {
8177c478bd9Sstevel@tonic-gate 		addr = uaddr2taddr(nc, uaddr);
8187c478bd9Sstevel@tonic-gate 		freeaddr = 1;
8197c478bd9Sstevel@tonic-gate 	}
8207c478bd9Sstevel@tonic-gate 
8217c478bd9Sstevel@tonic-gate 	if (addr == 0) {
8227c478bd9Sstevel@tonic-gate 		return (0);
8237c478bd9Sstevel@tonic-gate 	}
8247c478bd9Sstevel@tonic-gate 
8257c478bd9Sstevel@tonic-gate 	clnt = clnt_tli_create(fd, nc, addr, prog, ver, outbuf, inbuf);
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate 	if (clnt) {
8287c478bd9Sstevel@tonic-gate 		if (clnt_control(clnt, CLGET_FD, (char *)&fd))
8297c478bd9Sstevel@tonic-gate 			/* make it "close on exec" */
830e8031f0aSraf 			(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
8317c478bd9Sstevel@tonic-gate 		(void) clnt_control(clnt, CLSET_FD_CLOSE, NULL);
8327c478bd9Sstevel@tonic-gate 	}
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate 	if (freeaddr)
8357c478bd9Sstevel@tonic-gate 		netdir_free(addr, ND_ADDR);
8367c478bd9Sstevel@tonic-gate 
8377c478bd9Sstevel@tonic-gate 	return (clnt);
8387c478bd9Sstevel@tonic-gate }
8397c478bd9Sstevel@tonic-gate 
8407c478bd9Sstevel@tonic-gate static mutex_t __nis_ss_used_lock = DEFAULTMUTEX; /* lock level 3 */
8417c478bd9Sstevel@tonic-gate int	__nis_ss_used = 0;
8427c478bd9Sstevel@tonic-gate 
8437c478bd9Sstevel@tonic-gate /*
8447c478bd9Sstevel@tonic-gate  * nis_get_static_storage()
8457c478bd9Sstevel@tonic-gate  *
8467c478bd9Sstevel@tonic-gate  * This function is used by various functions in their effort to minimize the
8477c478bd9Sstevel@tonic-gate  * hassles of memory management in an RPC daemon. Because the service doesn't
8487c478bd9Sstevel@tonic-gate  * implement any hard limits, this function allows people to get automatically
8497c478bd9Sstevel@tonic-gate  * growing buffers that meet their storage requirements. It returns the
8507c478bd9Sstevel@tonic-gate  * pointer in the nis_sdata structure.
8517c478bd9Sstevel@tonic-gate  *
8527c478bd9Sstevel@tonic-gate  */
8537c478bd9Sstevel@tonic-gate void *
8547c478bd9Sstevel@tonic-gate nis_get_static_storage(
8557c478bd9Sstevel@tonic-gate 	struct nis_sdata	*bs,    /* User buffer structure */
8567c478bd9Sstevel@tonic-gate 	uint_t			el,	/* Sizeof elements	 */
8577c478bd9Sstevel@tonic-gate 	uint_t			nel)    /* Number of elements    */
8587c478bd9Sstevel@tonic-gate {
8597c478bd9Sstevel@tonic-gate 	uint_t	sz;
8607c478bd9Sstevel@tonic-gate 
8617c478bd9Sstevel@tonic-gate 	sz = nel * el;
8627c478bd9Sstevel@tonic-gate 	if (!bs)
8637c478bd9Sstevel@tonic-gate 		return (NULL);
8647c478bd9Sstevel@tonic-gate 
8657c478bd9Sstevel@tonic-gate 	if (!bs->buf) {
86661961e0fSrobinson 		bs->buf = malloc(sz);
8677c478bd9Sstevel@tonic-gate 		if (!bs->buf)
8687c478bd9Sstevel@tonic-gate 			return (NULL);
8697c478bd9Sstevel@tonic-gate 		bs->size = sz;
8707c478bd9Sstevel@tonic-gate 		sig_mutex_lock(&__nis_ss_used_lock);
8717c478bd9Sstevel@tonic-gate 		__nis_ss_used += sz;
8727c478bd9Sstevel@tonic-gate 		sig_mutex_unlock(&__nis_ss_used_lock);
8737c478bd9Sstevel@tonic-gate 	} else if (bs->size < sz) {
8747c478bd9Sstevel@tonic-gate 		int	size_delta;
8757c478bd9Sstevel@tonic-gate 
8767c478bd9Sstevel@tonic-gate 		free(bs->buf);
8777c478bd9Sstevel@tonic-gate 		size_delta = - (bs->size);
87861961e0fSrobinson 		bs->buf = malloc(sz);
8797c478bd9Sstevel@tonic-gate 
8807c478bd9Sstevel@tonic-gate 		/* check the result of malloc() first   */
8817c478bd9Sstevel@tonic-gate 		/* then update the statistic.		*/
8827c478bd9Sstevel@tonic-gate 		if (!bs->buf)
8837c478bd9Sstevel@tonic-gate 			return (NULL);
8847c478bd9Sstevel@tonic-gate 		bs->size = sz;
8857c478bd9Sstevel@tonic-gate 		size_delta += sz;
8867c478bd9Sstevel@tonic-gate 		sig_mutex_lock(&__nis_ss_used_lock);
8877c478bd9Sstevel@tonic-gate 		__nis_ss_used += size_delta;
8887c478bd9Sstevel@tonic-gate 		sig_mutex_unlock(&__nis_ss_used_lock);
8897c478bd9Sstevel@tonic-gate 	}
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate 	(void) memset(bs->buf, 0, sz); /* SYSV version of bzero() */
8927c478bd9Sstevel@tonic-gate 	return (bs->buf);
8937c478bd9Sstevel@tonic-gate }
894