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
58200fe25Srmesta  * Common Development and Distribution License (the "License").
68200fe25Srmesta  * 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  */
217c478bd9Sstevel@tonic-gate /*
22dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * Door server routines for nfsmapid daemon
287c478bd9Sstevel@tonic-gate  * Translate NFSv4 users and groups between numeric and string values
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate #include <stdio.h>
317c478bd9Sstevel@tonic-gate #include <stdlib.h>
327c478bd9Sstevel@tonic-gate #include <alloca.h>
337c478bd9Sstevel@tonic-gate #include <signal.h>
347c478bd9Sstevel@tonic-gate #include <libintl.h>
357c478bd9Sstevel@tonic-gate #include <limits.h>
367c478bd9Sstevel@tonic-gate #include <errno.h>
377c478bd9Sstevel@tonic-gate #include <sys/types.h>
387c478bd9Sstevel@tonic-gate #include <string.h>
397c478bd9Sstevel@tonic-gate #include <memory.h>
407c478bd9Sstevel@tonic-gate #include <pwd.h>
417c478bd9Sstevel@tonic-gate #include <grp.h>
427c478bd9Sstevel@tonic-gate #include <door.h>
437c478bd9Sstevel@tonic-gate #include <syslog.h>
447c478bd9Sstevel@tonic-gate #include <fcntl.h>
457c478bd9Sstevel@tonic-gate #include <unistd.h>
467c478bd9Sstevel@tonic-gate #include <assert.h>
477c478bd9Sstevel@tonic-gate #include <deflt.h>
487c478bd9Sstevel@tonic-gate #include <nfs/nfs4.h>
497c478bd9Sstevel@tonic-gate #include <nfs/nfssys.h>
507c478bd9Sstevel@tonic-gate #include <nfs/nfsid_map.h>
518200fe25Srmesta #include <nfs/mapid.h>
528200fe25Srmesta #include <sys/sdt.h>
53dd5829d1Sbaban #include <sys/idmap.h>
54dd5829d1Sbaban #include <idmap.h>
552f172c55SRobert Thurlow #include <sys/fs/autofs.h>
562f172c55SRobert Thurlow #include <sys/mkdev.h>
572f172c55SRobert Thurlow #include "nfs_resolve.h"
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate #define		UID_MAX_STR_LEN		11	/* Digits in UID_MAX + 1 */
607c478bd9Sstevel@tonic-gate #define		DIAG_FILE		"/var/run/nfs4_domain"
618200fe25Srmesta 
628200fe25Srmesta /*
638200fe25Srmesta  * idmap_kcall() takes a door descriptor as it's argument when we
648200fe25Srmesta  * need to (re)establish the in-kernel door handles. When we only
658200fe25Srmesta  * want to flush the id kernel caches, we don't redo the door setup.
668200fe25Srmesta  */
678200fe25Srmesta #define		FLUSH_KCACHES_ONLY	(int)-1
688200fe25Srmesta 
697c478bd9Sstevel@tonic-gate FILE		*n4_fp;
708200fe25Srmesta int		 n4_fd;
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate extern size_t	pwd_buflen;
737c478bd9Sstevel@tonic-gate extern size_t	grp_buflen;
747c478bd9Sstevel@tonic-gate extern thread_t	sig_thread;
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate /*
777c478bd9Sstevel@tonic-gate  * Prototypes
787c478bd9Sstevel@tonic-gate  */
797c478bd9Sstevel@tonic-gate extern void	 check_domain(int);
807c478bd9Sstevel@tonic-gate extern void	 idmap_kcall(int);
817c478bd9Sstevel@tonic-gate extern int	 _nfssys(int, void *);
828200fe25Srmesta extern int	 valid_domain(const char *);
838200fe25Srmesta extern int	 validate_id_str(const char *);
848200fe25Srmesta extern int	 extract_domain(char *, char **, char **);
857c478bd9Sstevel@tonic-gate extern void	 update_diag_file(char *);
868200fe25Srmesta extern void	*cb_update_domain(void *);
878200fe25Srmesta extern int	 cur_domain_null(void);
887c478bd9Sstevel@tonic-gate 
898200fe25Srmesta void
nfsmapid_str_uid(struct mapid_arg * argp,size_t arg_size)907c478bd9Sstevel@tonic-gate nfsmapid_str_uid(struct mapid_arg *argp, size_t arg_size)
917c478bd9Sstevel@tonic-gate {
927c478bd9Sstevel@tonic-gate 	struct mapid_res result;
937c478bd9Sstevel@tonic-gate 	struct passwd	 pwd;
94dd5829d1Sbaban 	struct passwd	*pwd_ptr;
95dd5829d1Sbaban 	int		 pwd_rc;
967c478bd9Sstevel@tonic-gate 	char		*pwd_buf;
977c478bd9Sstevel@tonic-gate 	char		*user;
987c478bd9Sstevel@tonic-gate 	char		*domain;
99dd5829d1Sbaban 	idmap_stat	 rc;
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 	if (argp->u_arg.len <= 0 || arg_size < MAPID_ARG_LEN(argp->u_arg.len)) {
1027c478bd9Sstevel@tonic-gate 		result.status = NFSMAPID_INVALID;
1037c478bd9Sstevel@tonic-gate 		result.u_res.uid = UID_NOBODY;
1047c478bd9Sstevel@tonic-gate 		goto done;
1057c478bd9Sstevel@tonic-gate 	}
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 	if (!extract_domain(argp->str, &user, &domain)) {
108dd5829d1Sbaban 		unsigned long id;
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 		/*
111dd5829d1Sbaban 		 * Invalid "user@domain" string. Still, the user
1127c478bd9Sstevel@tonic-gate 		 * part might be an encoded uid, so do a final check.
1137c478bd9Sstevel@tonic-gate 		 * Remember, domain part of string was not set since
1147c478bd9Sstevel@tonic-gate 		 * not a valid string.
1157c478bd9Sstevel@tonic-gate 		 */
1167c478bd9Sstevel@tonic-gate 		if (!validate_id_str(user)) {
1177c478bd9Sstevel@tonic-gate 			result.status = NFSMAPID_UNMAPPABLE;
1187c478bd9Sstevel@tonic-gate 			result.u_res.uid = UID_NOBODY;
1197c478bd9Sstevel@tonic-gate 			goto done;
1207c478bd9Sstevel@tonic-gate 		}
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 		errno = 0;
123dd5829d1Sbaban 		id = strtoul(user, (char **)NULL, 10);
1247c478bd9Sstevel@tonic-gate 
125dd5829d1Sbaban 		/*
126dd5829d1Sbaban 		 * We don't accept ephemeral ids from the wire.
127dd5829d1Sbaban 		 */
128dd5829d1Sbaban 		if (errno || id > UID_MAX) {
1297c478bd9Sstevel@tonic-gate 			result.status = NFSMAPID_UNMAPPABLE;
1307c478bd9Sstevel@tonic-gate 			result.u_res.uid = UID_NOBODY;
1317c478bd9Sstevel@tonic-gate 			goto done;
1327c478bd9Sstevel@tonic-gate 		}
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 		result.u_res.uid = (uid_t)id;
1357c478bd9Sstevel@tonic-gate 		result.status = NFSMAPID_NUMSTR;
1367c478bd9Sstevel@tonic-gate 		goto done;
1377c478bd9Sstevel@tonic-gate 	}
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	/*
1407c478bd9Sstevel@tonic-gate 	 * String properly constructed. Now we check for domain and
141dd5829d1Sbaban 	 * group validity.
1427c478bd9Sstevel@tonic-gate 	 */
1438200fe25Srmesta 	if (!cur_domain_null() && !valid_domain(domain)) {
144dd5829d1Sbaban 		/*
145dd5829d1Sbaban 		 * If the domain part of the string does not
146dd5829d1Sbaban 		 * match the NFS domain, try to map it using
147dd5829d1Sbaban 		 * idmap service.
148dd5829d1Sbaban 		 */
1493ee87bcaSJulian Pullen 		rc = idmap_getuidbywinname(user, domain, 0, &result.u_res.uid);
150dd5829d1Sbaban 		if (rc != IDMAP_SUCCESS) {
1517c478bd9Sstevel@tonic-gate 			result.status = NFSMAPID_BADDOMAIN;
1527c478bd9Sstevel@tonic-gate 			result.u_res.uid = UID_NOBODY;
1537c478bd9Sstevel@tonic-gate 			goto done;
1547c478bd9Sstevel@tonic-gate 		}
155dd5829d1Sbaban 		result.status = NFSMAPID_OK;
156dd5829d1Sbaban 		goto done;
157dd5829d1Sbaban 	}
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	if ((pwd_buf = malloc(pwd_buflen)) == NULL ||
160dd5829d1Sbaban 	    (pwd_rc = getpwnam_r(user, &pwd, pwd_buf, pwd_buflen, &pwd_ptr))
161dd5829d1Sbaban 	    != 0 || pwd_ptr == NULL) {
1627c478bd9Sstevel@tonic-gate 
163dd5829d1Sbaban 		if (pwd_buf == NULL || pwd_rc != 0)
1647c478bd9Sstevel@tonic-gate 			result.status = NFSMAPID_INTERNAL;
1657c478bd9Sstevel@tonic-gate 		else {
1667c478bd9Sstevel@tonic-gate 			/*
1677c478bd9Sstevel@tonic-gate 			 * Not a valid user
1687c478bd9Sstevel@tonic-gate 			 */
1697c478bd9Sstevel@tonic-gate 			result.status = NFSMAPID_NOTFOUND;
1707c478bd9Sstevel@tonic-gate 			free(pwd_buf);
1717c478bd9Sstevel@tonic-gate 		}
1727c478bd9Sstevel@tonic-gate 		result.u_res.uid = UID_NOBODY;
1737c478bd9Sstevel@tonic-gate 		goto done;
1747c478bd9Sstevel@tonic-gate 	}
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	/*
1777c478bd9Sstevel@tonic-gate 	 * Valid user entry
1787c478bd9Sstevel@tonic-gate 	 */
1797c478bd9Sstevel@tonic-gate 	result.u_res.uid = pwd.pw_uid;
1807c478bd9Sstevel@tonic-gate 	result.status = NFSMAPID_OK;
1817c478bd9Sstevel@tonic-gate 	free(pwd_buf);
1827c478bd9Sstevel@tonic-gate done:
1837c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&result, sizeof (struct mapid_res), NULL, 0);
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate /* ARGSUSED1 */
1878200fe25Srmesta void
nfsmapid_uid_str(struct mapid_arg * argp,size_t arg_size)1887c478bd9Sstevel@tonic-gate nfsmapid_uid_str(struct mapid_arg *argp, size_t arg_size)
1897c478bd9Sstevel@tonic-gate {
1907c478bd9Sstevel@tonic-gate 	struct mapid_res	 result;
1917c478bd9Sstevel@tonic-gate 	struct mapid_res	*resp;
1927c478bd9Sstevel@tonic-gate 	struct passwd		 pwd;
193dd5829d1Sbaban 	struct passwd		 *pwd_ptr;
194dd5829d1Sbaban 	char			*pwd_buf = NULL;
195dd5829d1Sbaban 	char			*idmap_buf = NULL;
1967c478bd9Sstevel@tonic-gate 	uid_t			 uid = argp->u_arg.uid;
1977c478bd9Sstevel@tonic-gate 	size_t			 uid_str_len;
1987c478bd9Sstevel@tonic-gate 	char			*pw_str;
1997c478bd9Sstevel@tonic-gate 	size_t			 pw_str_len;
2007c478bd9Sstevel@tonic-gate 	char			*at_str;
2017c478bd9Sstevel@tonic-gate 	size_t			 at_str_len;
2028200fe25Srmesta 	char			 dom_str[DNAMEMAX];
2037c478bd9Sstevel@tonic-gate 	size_t			 dom_str_len;
204dd5829d1Sbaban 	idmap_stat		 rc;
2057c478bd9Sstevel@tonic-gate 
206dd5829d1Sbaban 	if (uid == (uid_t)-1) {
2077c478bd9Sstevel@tonic-gate 		/*
208dd5829d1Sbaban 		 * Sentinel uid is not a valid id
2097c478bd9Sstevel@tonic-gate 		 */
2107c478bd9Sstevel@tonic-gate 		resp = &result;
2117c478bd9Sstevel@tonic-gate 		resp->status = NFSMAPID_BADID;
2127c478bd9Sstevel@tonic-gate 		resp->u_res.len = 0;
2137c478bd9Sstevel@tonic-gate 		goto done;
2147c478bd9Sstevel@tonic-gate 	}
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate 	/*
2177c478bd9Sstevel@tonic-gate 	 * Make local copy of domain for further manipuation
2188200fe25Srmesta 	 * NOTE: mapid_get_domain() returns a ptr to TSD.
2197c478bd9Sstevel@tonic-gate 	 */
2208200fe25Srmesta 	if (cur_domain_null()) {
2217c478bd9Sstevel@tonic-gate 		dom_str_len = 0;
2227c478bd9Sstevel@tonic-gate 		dom_str[0] = '\0';
2237c478bd9Sstevel@tonic-gate 	} else {
2248200fe25Srmesta 		dom_str_len = strlcpy(dom_str, mapid_get_domain(), DNAMEMAX);
2257c478bd9Sstevel@tonic-gate 	}
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	/*
228dd5829d1Sbaban 	 * If uid is ephemeral then resolve it using idmap service
229dd5829d1Sbaban 	 */
230dd5829d1Sbaban 	if (uid > UID_MAX) {
2313ee87bcaSJulian Pullen 		rc = idmap_getwinnamebyuid(uid, 0, &idmap_buf, NULL);
232dd5829d1Sbaban 		if (rc != IDMAP_SUCCESS) {
233dd5829d1Sbaban 			/*
234dd5829d1Sbaban 			 * We don't put stringified ephemeral uids on
235dd5829d1Sbaban 			 * the wire.
236dd5829d1Sbaban 			 */
237dd5829d1Sbaban 			resp = &result;
238dd5829d1Sbaban 			resp->status = NFSMAPID_UNMAPPABLE;
239dd5829d1Sbaban 			resp->u_res.len = 0;
240dd5829d1Sbaban 			goto done;
241dd5829d1Sbaban 		}
242dd5829d1Sbaban 
243dd5829d1Sbaban 		/*
244dd5829d1Sbaban 		 * idmap_buf is already in the desired form i.e. name@domain
245dd5829d1Sbaban 		 */
246dd5829d1Sbaban 		pw_str = idmap_buf;
247dd5829d1Sbaban 		pw_str_len = strlen(pw_str);
248dd5829d1Sbaban 		at_str_len = dom_str_len = 0;
249dd5829d1Sbaban 		at_str = "";
250dd5829d1Sbaban 		dom_str[0] = '\0';
251dd5829d1Sbaban 		goto gen_result;
252dd5829d1Sbaban 	}
253dd5829d1Sbaban 
254dd5829d1Sbaban 	/*
255dd5829d1Sbaban 	 * Handling non-ephemeral uids
256dd5829d1Sbaban 	 *
2577c478bd9Sstevel@tonic-gate 	 * We want to encode the uid into a literal string... :
2587c478bd9Sstevel@tonic-gate 	 *
2597c478bd9Sstevel@tonic-gate 	 *	- upon failure to allocate space from the heap
2607c478bd9Sstevel@tonic-gate 	 *	- if there is no current domain configured
2617c478bd9Sstevel@tonic-gate 	 *	- if there is no such uid in the passwd DB's
2627c478bd9Sstevel@tonic-gate 	 */
2637c478bd9Sstevel@tonic-gate 	if ((pwd_buf = malloc(pwd_buflen)) == NULL || dom_str_len == 0 ||
264dd5829d1Sbaban 	    getpwuid_r(uid, &pwd, pwd_buf, pwd_buflen, &pwd_ptr) != 0 ||
265dd5829d1Sbaban 	    pwd_ptr == NULL) {
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 		/*
2687c478bd9Sstevel@tonic-gate 		 * If we could not allocate from the heap, try
2697c478bd9Sstevel@tonic-gate 		 * allocating from the stack as a last resort.
2707c478bd9Sstevel@tonic-gate 		 */
2717c478bd9Sstevel@tonic-gate 		if (pwd_buf == NULL && (pwd_buf =
2727c478bd9Sstevel@tonic-gate 		    alloca(MAPID_RES_LEN(UID_MAX_STR_LEN))) == NULL) {
2737c478bd9Sstevel@tonic-gate 			resp = &result;
2747c478bd9Sstevel@tonic-gate 			resp->status = NFSMAPID_INTERNAL;
2757c478bd9Sstevel@tonic-gate 			resp->u_res.len = 0;
2767c478bd9Sstevel@tonic-gate 			goto done;
2777c478bd9Sstevel@tonic-gate 		}
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 		/*
2807c478bd9Sstevel@tonic-gate 		 * Constructing literal string without '@' so that
2817c478bd9Sstevel@tonic-gate 		 * we'll know that it's not a user, but rather a
282dd5829d1Sbaban 		 * uid encoded string.
2837c478bd9Sstevel@tonic-gate 		 */
2847c478bd9Sstevel@tonic-gate 		pw_str = pwd_buf;
285dd5829d1Sbaban 		(void) sprintf(pw_str, "%u", uid);
2867c478bd9Sstevel@tonic-gate 		pw_str_len = strlen(pw_str);
2877c478bd9Sstevel@tonic-gate 		at_str_len = dom_str_len = 0;
2887c478bd9Sstevel@tonic-gate 		at_str = "";
2897c478bd9Sstevel@tonic-gate 		dom_str[0] = '\0';
2907c478bd9Sstevel@tonic-gate 	} else {
2917c478bd9Sstevel@tonic-gate 		/*
292dd5829d1Sbaban 		 * Otherwise, we construct the "user@domain" string if
293dd5829d1Sbaban 		 * it's not already in that form.
2947c478bd9Sstevel@tonic-gate 		 */
2957c478bd9Sstevel@tonic-gate 		pw_str = pwd.pw_name;
2967c478bd9Sstevel@tonic-gate 		pw_str_len = strlen(pw_str);
297dd5829d1Sbaban 		if (strchr(pw_str, '@') == NULL) {
2987c478bd9Sstevel@tonic-gate 			at_str = "@";
2997c478bd9Sstevel@tonic-gate 			at_str_len = 1;
300dd5829d1Sbaban 		} else {
301dd5829d1Sbaban 			at_str_len = dom_str_len = 0;
302dd5829d1Sbaban 			at_str = "";
303dd5829d1Sbaban 			dom_str[0] = '\0';
304dd5829d1Sbaban 		}
3057c478bd9Sstevel@tonic-gate 	}
3067c478bd9Sstevel@tonic-gate 
307dd5829d1Sbaban gen_result:
3087c478bd9Sstevel@tonic-gate 	uid_str_len = pw_str_len + at_str_len + dom_str_len;
309dd5829d1Sbaban 	if ((resp = alloca(MAPID_RES_LEN(uid_str_len))) == NULL) {
3107c478bd9Sstevel@tonic-gate 		resp = &result;
3117c478bd9Sstevel@tonic-gate 		resp->status = NFSMAPID_INTERNAL;
3127c478bd9Sstevel@tonic-gate 		resp->u_res.len = 0;
3137c478bd9Sstevel@tonic-gate 		goto done;
3147c478bd9Sstevel@tonic-gate 	}
3157c478bd9Sstevel@tonic-gate 	/* LINTED format argument to sprintf */
3167c478bd9Sstevel@tonic-gate 	(void) sprintf(resp->str, "%s%s%s", pw_str, at_str, dom_str);
3177c478bd9Sstevel@tonic-gate 	resp->u_res.len = uid_str_len;
318dd5829d1Sbaban 	if (pwd_buf)
3197c478bd9Sstevel@tonic-gate 		free(pwd_buf);
320dd5829d1Sbaban 	if (idmap_buf)
321dd5829d1Sbaban 		idmap_free(idmap_buf);
3227c478bd9Sstevel@tonic-gate 	resp->status = NFSMAPID_OK;
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate done:
3257c478bd9Sstevel@tonic-gate 	/*
3267c478bd9Sstevel@tonic-gate 	 * There is a chance that the door_return will fail because the
3277c478bd9Sstevel@tonic-gate 	 * resulting string is too large, try to indicate that if possible
3287c478bd9Sstevel@tonic-gate 	 */
3297c478bd9Sstevel@tonic-gate 	if (door_return((char *)resp,
3307c478bd9Sstevel@tonic-gate 	    MAPID_RES_LEN(resp->u_res.len), NULL, 0) == -1) {
3317c478bd9Sstevel@tonic-gate 		resp->status = NFSMAPID_INTERNAL;
3327c478bd9Sstevel@tonic-gate 		resp->u_res.len = 0;
3337c478bd9Sstevel@tonic-gate 		(void) door_return((char *)&result, sizeof (struct mapid_res),
3347c478bd9Sstevel@tonic-gate 		    NULL, 0);
3357c478bd9Sstevel@tonic-gate 	}
3367c478bd9Sstevel@tonic-gate }
3377c478bd9Sstevel@tonic-gate 
3388200fe25Srmesta void
nfsmapid_str_gid(struct mapid_arg * argp,size_t arg_size)3397c478bd9Sstevel@tonic-gate nfsmapid_str_gid(struct mapid_arg *argp, size_t arg_size)
3407c478bd9Sstevel@tonic-gate {
3417c478bd9Sstevel@tonic-gate 	struct mapid_res	result;
3427c478bd9Sstevel@tonic-gate 	struct group		grp;
343dd5829d1Sbaban 	struct group		*grp_ptr;
344dd5829d1Sbaban 	int			grp_rc;
3457c478bd9Sstevel@tonic-gate 	char			*grp_buf;
3467c478bd9Sstevel@tonic-gate 	char			*group;
3477c478bd9Sstevel@tonic-gate 	char			*domain;
348dd5829d1Sbaban 	idmap_stat		rc;
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	if (argp->u_arg.len <= 0 ||
3517c478bd9Sstevel@tonic-gate 	    arg_size < MAPID_ARG_LEN(argp->u_arg.len)) {
3527c478bd9Sstevel@tonic-gate 		result.status = NFSMAPID_INVALID;
3537c478bd9Sstevel@tonic-gate 		result.u_res.gid = GID_NOBODY;
3547c478bd9Sstevel@tonic-gate 		goto done;
3557c478bd9Sstevel@tonic-gate 	}
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 	if (!extract_domain(argp->str, &group, &domain)) {
358dd5829d1Sbaban 		unsigned long id;
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 		/*
361dd5829d1Sbaban 		 * Invalid "group@domain" string. Still, the
3627c478bd9Sstevel@tonic-gate 		 * group part might be an encoded gid, so do a
3637c478bd9Sstevel@tonic-gate 		 * final check. Remember, domain part of string
3647c478bd9Sstevel@tonic-gate 		 * was not set since not a valid string.
3657c478bd9Sstevel@tonic-gate 		 */
3667c478bd9Sstevel@tonic-gate 		if (!validate_id_str(group)) {
3677c478bd9Sstevel@tonic-gate 			result.status = NFSMAPID_UNMAPPABLE;
3687c478bd9Sstevel@tonic-gate 			result.u_res.gid = GID_NOBODY;
3697c478bd9Sstevel@tonic-gate 			goto done;
3707c478bd9Sstevel@tonic-gate 		}
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 		errno = 0;
373dd5829d1Sbaban 		id = strtoul(group, (char **)NULL, 10);
3747c478bd9Sstevel@tonic-gate 
375dd5829d1Sbaban 		/*
376dd5829d1Sbaban 		 * We don't accept ephemeral ids from the wire.
377dd5829d1Sbaban 		 */
378dd5829d1Sbaban 		if (errno || id > UID_MAX) {
3797c478bd9Sstevel@tonic-gate 			result.status = NFSMAPID_UNMAPPABLE;
3807c478bd9Sstevel@tonic-gate 			result.u_res.gid = GID_NOBODY;
3817c478bd9Sstevel@tonic-gate 			goto done;
3827c478bd9Sstevel@tonic-gate 		}
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 		result.u_res.gid = (gid_t)id;
3857c478bd9Sstevel@tonic-gate 		result.status = NFSMAPID_NUMSTR;
3867c478bd9Sstevel@tonic-gate 		goto done;
3877c478bd9Sstevel@tonic-gate 	}
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate 	/*
3907c478bd9Sstevel@tonic-gate 	 * String properly constructed. Now we check for domain and
391dd5829d1Sbaban 	 * group validity.
3927c478bd9Sstevel@tonic-gate 	 */
3938200fe25Srmesta 	if (!cur_domain_null() && !valid_domain(domain)) {
394dd5829d1Sbaban 		/*
395dd5829d1Sbaban 		 * If the domain part of the string does not
396dd5829d1Sbaban 		 * match the NFS domain, try to map it using
397dd5829d1Sbaban 		 * idmap service.
398dd5829d1Sbaban 		 */
3993ee87bcaSJulian Pullen 		rc = idmap_getgidbywinname(group, domain, 0, &result.u_res.gid);
400dd5829d1Sbaban 		if (rc != IDMAP_SUCCESS) {
4017c478bd9Sstevel@tonic-gate 			result.status = NFSMAPID_BADDOMAIN;
4027c478bd9Sstevel@tonic-gate 			result.u_res.gid = GID_NOBODY;
4037c478bd9Sstevel@tonic-gate 			goto done;
4047c478bd9Sstevel@tonic-gate 		}
405dd5829d1Sbaban 		result.status = NFSMAPID_OK;
406dd5829d1Sbaban 		goto done;
407dd5829d1Sbaban 	}
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 	if ((grp_buf = malloc(grp_buflen)) == NULL ||
410dd5829d1Sbaban 	    (grp_rc = getgrnam_r(group, &grp, grp_buf, grp_buflen, &grp_ptr))
411dd5829d1Sbaban 	    != 0 || grp_ptr == NULL) {
4127c478bd9Sstevel@tonic-gate 
413dd5829d1Sbaban 		if (grp_buf == NULL || grp_rc != 0)
4147c478bd9Sstevel@tonic-gate 			result.status = NFSMAPID_INTERNAL;
4157c478bd9Sstevel@tonic-gate 		else {
4167c478bd9Sstevel@tonic-gate 			/*
4177c478bd9Sstevel@tonic-gate 			 * Not a valid group
4187c478bd9Sstevel@tonic-gate 			 */
4197c478bd9Sstevel@tonic-gate 			result.status = NFSMAPID_NOTFOUND;
4207c478bd9Sstevel@tonic-gate 			free(grp_buf);
4217c478bd9Sstevel@tonic-gate 		}
4227c478bd9Sstevel@tonic-gate 		result.u_res.gid = GID_NOBODY;
4237c478bd9Sstevel@tonic-gate 		goto done;
4247c478bd9Sstevel@tonic-gate 	}
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 	/*
4277c478bd9Sstevel@tonic-gate 	 * Valid group entry
4287c478bd9Sstevel@tonic-gate 	 */
4297c478bd9Sstevel@tonic-gate 	result.status = NFSMAPID_OK;
4307c478bd9Sstevel@tonic-gate 	result.u_res.gid = grp.gr_gid;
4317c478bd9Sstevel@tonic-gate 	free(grp_buf);
4327c478bd9Sstevel@tonic-gate done:
4337c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&result, sizeof (struct mapid_res), NULL, 0);
4347c478bd9Sstevel@tonic-gate }
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate /* ARGSUSED1 */
4378200fe25Srmesta void
nfsmapid_gid_str(struct mapid_arg * argp,size_t arg_size)4387c478bd9Sstevel@tonic-gate nfsmapid_gid_str(struct mapid_arg *argp, size_t arg_size)
4397c478bd9Sstevel@tonic-gate {
4407c478bd9Sstevel@tonic-gate 	struct mapid_res	 result;
4417c478bd9Sstevel@tonic-gate 	struct mapid_res	*resp;
4427c478bd9Sstevel@tonic-gate 	struct group		 grp;
443dd5829d1Sbaban 	struct group		*grp_ptr;
444dd5829d1Sbaban 	char			*grp_buf = NULL;
445dd5829d1Sbaban 	char			*idmap_buf = NULL;
446dd5829d1Sbaban 	idmap_stat		 rc;
4477c478bd9Sstevel@tonic-gate 	gid_t			 gid = argp->u_arg.gid;
4487c478bd9Sstevel@tonic-gate 	size_t			 gid_str_len;
4497c478bd9Sstevel@tonic-gate 	char			*gr_str;
4507c478bd9Sstevel@tonic-gate 	size_t			 gr_str_len;
4517c478bd9Sstevel@tonic-gate 	char			*at_str;
4527c478bd9Sstevel@tonic-gate 	size_t			 at_str_len;
4538200fe25Srmesta 	char			 dom_str[DNAMEMAX];
4547c478bd9Sstevel@tonic-gate 	size_t			 dom_str_len;
4557c478bd9Sstevel@tonic-gate 
456dd5829d1Sbaban 	if (gid == (gid_t)-1) {
4577c478bd9Sstevel@tonic-gate 		/*
458dd5829d1Sbaban 		 * Sentinel gid is not a valid id
4597c478bd9Sstevel@tonic-gate 		 */
4607c478bd9Sstevel@tonic-gate 		resp = &result;
4617c478bd9Sstevel@tonic-gate 		resp->status = NFSMAPID_BADID;
4627c478bd9Sstevel@tonic-gate 		resp->u_res.len = 0;
4637c478bd9Sstevel@tonic-gate 		goto done;
4647c478bd9Sstevel@tonic-gate 	}
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 	/*
4677c478bd9Sstevel@tonic-gate 	 * Make local copy of domain for further manipuation
4688200fe25Srmesta 	 * NOTE: mapid_get_domain() returns a ptr to TSD.
4697c478bd9Sstevel@tonic-gate 	 */
4708200fe25Srmesta 	if (cur_domain_null()) {
4717c478bd9Sstevel@tonic-gate 		dom_str_len = 0;
4727c478bd9Sstevel@tonic-gate 		dom_str[0] = '\0';
4737c478bd9Sstevel@tonic-gate 	} else {
4748200fe25Srmesta 		dom_str_len = strlen(mapid_get_domain());
4758200fe25Srmesta 		bcopy(mapid_get_domain(), dom_str, dom_str_len);
4767c478bd9Sstevel@tonic-gate 		dom_str[dom_str_len] = '\0';
4777c478bd9Sstevel@tonic-gate 	}
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 	/*
480dd5829d1Sbaban 	 * If gid is ephemeral then resolve it using idmap service
481dd5829d1Sbaban 	 */
482dd5829d1Sbaban 	if (gid > UID_MAX) {
4833ee87bcaSJulian Pullen 		rc = idmap_getwinnamebygid(gid, 0, &idmap_buf, NULL);
484dd5829d1Sbaban 		if (rc != IDMAP_SUCCESS) {
485dd5829d1Sbaban 			/*
486dd5829d1Sbaban 			 * We don't put stringified ephemeral gids on
487dd5829d1Sbaban 			 * the wire.
488dd5829d1Sbaban 			 */
489dd5829d1Sbaban 			resp = &result;
490dd5829d1Sbaban 			resp->status = NFSMAPID_UNMAPPABLE;
491dd5829d1Sbaban 			resp->u_res.len = 0;
492dd5829d1Sbaban 			goto done;
493dd5829d1Sbaban 		}
494dd5829d1Sbaban 
495dd5829d1Sbaban 		/*
496dd5829d1Sbaban 		 * idmap_buf is already in the desired form i.e. name@domain
497dd5829d1Sbaban 		 */
498dd5829d1Sbaban 		gr_str = idmap_buf;
499dd5829d1Sbaban 		gr_str_len = strlen(gr_str);
500dd5829d1Sbaban 		at_str_len = dom_str_len = 0;
501dd5829d1Sbaban 		at_str = "";
502dd5829d1Sbaban 		dom_str[0] = '\0';
503dd5829d1Sbaban 		goto gen_result;
504dd5829d1Sbaban 	}
505dd5829d1Sbaban 
506dd5829d1Sbaban 	/*
507dd5829d1Sbaban 	 * Handling non-ephemeral gids
508dd5829d1Sbaban 	 *
5097c478bd9Sstevel@tonic-gate 	 * We want to encode the gid into a literal string... :
5107c478bd9Sstevel@tonic-gate 	 *
5117c478bd9Sstevel@tonic-gate 	 *	- upon failure to allocate space from the heap
5127c478bd9Sstevel@tonic-gate 	 *	- if there is no current domain configured
5137c478bd9Sstevel@tonic-gate 	 *	- if there is no such gid in the group DB's
5147c478bd9Sstevel@tonic-gate 	 */
5157c478bd9Sstevel@tonic-gate 	if ((grp_buf = malloc(grp_buflen)) == NULL || dom_str_len == 0 ||
516dd5829d1Sbaban 	    getgrgid_r(gid, &grp, grp_buf, grp_buflen, &grp_ptr) != 0 ||
517dd5829d1Sbaban 	    grp_ptr == NULL) {
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 		/*
5207c478bd9Sstevel@tonic-gate 		 * If we could not allocate from the heap, try
5217c478bd9Sstevel@tonic-gate 		 * allocating from the stack as a last resort.
5227c478bd9Sstevel@tonic-gate 		 */
5237c478bd9Sstevel@tonic-gate 		if (grp_buf == NULL && (grp_buf =
5247c478bd9Sstevel@tonic-gate 		    alloca(MAPID_RES_LEN(UID_MAX_STR_LEN))) == NULL) {
5257c478bd9Sstevel@tonic-gate 			resp = &result;
5267c478bd9Sstevel@tonic-gate 			resp->status = NFSMAPID_INTERNAL;
5277c478bd9Sstevel@tonic-gate 			resp->u_res.len = 0;
5287c478bd9Sstevel@tonic-gate 			goto done;
5297c478bd9Sstevel@tonic-gate 		}
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 		/*
5327c478bd9Sstevel@tonic-gate 		 * Constructing literal string without '@' so that
5337c478bd9Sstevel@tonic-gate 		 * we'll know that it's not a group, but rather a
534dd5829d1Sbaban 		 * gid encoded string.
5357c478bd9Sstevel@tonic-gate 		 */
5367c478bd9Sstevel@tonic-gate 		gr_str = grp_buf;
537dd5829d1Sbaban 		(void) sprintf(gr_str, "%u", gid);
5387c478bd9Sstevel@tonic-gate 		gr_str_len = strlen(gr_str);
5397c478bd9Sstevel@tonic-gate 		at_str_len = dom_str_len = 0;
5407c478bd9Sstevel@tonic-gate 		at_str = "";
5417c478bd9Sstevel@tonic-gate 		dom_str[0] = '\0';
5427c478bd9Sstevel@tonic-gate 	} else {
5437c478bd9Sstevel@tonic-gate 		/*
544dd5829d1Sbaban 		 * Otherwise, we construct the "group@domain" string if
545dd5829d1Sbaban 		 * it's not already in that form.
5467c478bd9Sstevel@tonic-gate 		 */
5477c478bd9Sstevel@tonic-gate 		gr_str = grp.gr_name;
5487c478bd9Sstevel@tonic-gate 		gr_str_len = strlen(gr_str);
549dd5829d1Sbaban 		if (strchr(gr_str, '@') == NULL) {
5507c478bd9Sstevel@tonic-gate 			at_str = "@";
5517c478bd9Sstevel@tonic-gate 			at_str_len = 1;
552dd5829d1Sbaban 		} else {
553dd5829d1Sbaban 			at_str_len = dom_str_len = 0;
554dd5829d1Sbaban 			at_str = "";
555dd5829d1Sbaban 			dom_str[0] = '\0';
556dd5829d1Sbaban 		}
5577c478bd9Sstevel@tonic-gate 	}
5587c478bd9Sstevel@tonic-gate 
559dd5829d1Sbaban gen_result:
5607c478bd9Sstevel@tonic-gate 	gid_str_len = gr_str_len + at_str_len + dom_str_len;
561dd5829d1Sbaban 	if ((resp = alloca(MAPID_RES_LEN(gid_str_len))) == NULL) {
5627c478bd9Sstevel@tonic-gate 		resp = &result;
5637c478bd9Sstevel@tonic-gate 		resp->status = NFSMAPID_INTERNAL;
5647c478bd9Sstevel@tonic-gate 		resp->u_res.len = 0;
5657c478bd9Sstevel@tonic-gate 		goto done;
5667c478bd9Sstevel@tonic-gate 	}
5677c478bd9Sstevel@tonic-gate 	/* LINTED format argument to sprintf */
5687c478bd9Sstevel@tonic-gate 	(void) sprintf(resp->str, "%s%s%s", gr_str, at_str, dom_str);
5697c478bd9Sstevel@tonic-gate 	resp->u_res.len = gid_str_len;
570dd5829d1Sbaban 	if (grp_buf)
5717c478bd9Sstevel@tonic-gate 		free(grp_buf);
572dd5829d1Sbaban 	if (idmap_buf)
573dd5829d1Sbaban 		idmap_free(idmap_buf);
5747c478bd9Sstevel@tonic-gate 	resp->status = NFSMAPID_OK;
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate done:
5777c478bd9Sstevel@tonic-gate 	/*
5787c478bd9Sstevel@tonic-gate 	 * There is a chance that the door_return will fail because the
5797c478bd9Sstevel@tonic-gate 	 * resulting string is too large, try to indicate that if possible
5807c478bd9Sstevel@tonic-gate 	 */
5817c478bd9Sstevel@tonic-gate 	if (door_return((char *)resp,
5827c478bd9Sstevel@tonic-gate 	    MAPID_RES_LEN(resp->u_res.len), NULL, 0) == -1) {
5837c478bd9Sstevel@tonic-gate 		resp->status = NFSMAPID_INTERNAL;
5847c478bd9Sstevel@tonic-gate 		resp->u_res.len = 0;
5857c478bd9Sstevel@tonic-gate 		(void) door_return((char *)&result, sizeof (struct mapid_res),
5867c478bd9Sstevel@tonic-gate 		    NULL, 0);
5877c478bd9Sstevel@tonic-gate 	}
5887c478bd9Sstevel@tonic-gate }
5897c478bd9Sstevel@tonic-gate 
5902f172c55SRobert Thurlow void
nfsmapid_server_netinfo(refd_door_args_t * referral_args,size_t arg_size)5912f172c55SRobert Thurlow nfsmapid_server_netinfo(refd_door_args_t *referral_args, size_t arg_size)
5922f172c55SRobert Thurlow {
5932f172c55SRobert Thurlow 	char *res;
5942f172c55SRobert Thurlow 	int res_size;
5952f172c55SRobert Thurlow 	int error;
5962f172c55SRobert Thurlow 	int srsz = 0;
5972f172c55SRobert Thurlow 	char host[MAXHOSTNAMELEN];
5982f172c55SRobert Thurlow 	utf8string	*nfsfsloc_args;
5992f172c55SRobert Thurlow 	refd_door_res_t	*door_res;
6002f172c55SRobert Thurlow 	refd_door_res_t	failed_res;
6012f172c55SRobert Thurlow 	struct nfs_fsl_info *nfs_fsloc_res;
6022f172c55SRobert Thurlow 
6032f172c55SRobert Thurlow 	if (arg_size < sizeof (refd_door_args_t)) {
6042f172c55SRobert Thurlow 		failed_res.res_status = EINVAL;
6052f172c55SRobert Thurlow 		res = (char *)&failed_res;
6062f172c55SRobert Thurlow 		res_size = sizeof (refd_door_res_t);
6072f172c55SRobert Thurlow 		syslog(LOG_ERR,
6082f172c55SRobert Thurlow 		    "nfsmapid_server_netinfo failed: Invalid data\n");
6092f172c55SRobert Thurlow 		goto send_response;
6102f172c55SRobert Thurlow 	}
6112f172c55SRobert Thurlow 
6122f172c55SRobert Thurlow 	if (decode_args(xdr_utf8string, (refd_door_args_t *)referral_args,
6132f172c55SRobert Thurlow 	    (caddr_t *)&nfsfsloc_args, sizeof (utf8string))) {
6142f172c55SRobert Thurlow 		syslog(LOG_ERR, "cannot allocate memory");
6152f172c55SRobert Thurlow 		failed_res.res_status = ENOMEM;
6162f172c55SRobert Thurlow 		failed_res.xdr_len = 0;
6172f172c55SRobert Thurlow 		res = (caddr_t)&failed_res;
6182f172c55SRobert Thurlow 		res_size = sizeof (refd_door_res_t);
6192f172c55SRobert Thurlow 		goto send_response;
6202f172c55SRobert Thurlow 	}
6212f172c55SRobert Thurlow 
6222f172c55SRobert Thurlow 	if (nfsfsloc_args->utf8string_len >= MAXHOSTNAMELEN) {
6232f172c55SRobert Thurlow 		syslog(LOG_ERR, "argument too large");
6242f172c55SRobert Thurlow 		failed_res.res_status = EOVERFLOW;
6252f172c55SRobert Thurlow 		failed_res.xdr_len = 0;
6262f172c55SRobert Thurlow 		res = (caddr_t)&failed_res;
6272f172c55SRobert Thurlow 		res_size = sizeof (refd_door_res_t);
6282f172c55SRobert Thurlow 		goto send_response;
6292f172c55SRobert Thurlow 	}
6302f172c55SRobert Thurlow 
6312f172c55SRobert Thurlow 	snprintf(host, nfsfsloc_args->utf8string_len + 1,
6322f172c55SRobert Thurlow 	    "%s", nfsfsloc_args->utf8string_val);
6332f172c55SRobert Thurlow 
6342f172c55SRobert Thurlow 	nfs_fsloc_res =
6352f172c55SRobert Thurlow 	    get_nfs4ref_info(host, NFS_PORT, NFS_V4);
6362f172c55SRobert Thurlow 
6372f172c55SRobert Thurlow 	xdr_free(xdr_utf8string, (char *)&nfsfsloc_args);
6382f172c55SRobert Thurlow 
6392f172c55SRobert Thurlow 	if (nfs_fsloc_res) {
6402f172c55SRobert Thurlow 		error = 0;
6412f172c55SRobert Thurlow 		error = encode_res(xdr_nfs_fsl_info, &door_res,
6422f172c55SRobert Thurlow 		    (caddr_t)nfs_fsloc_res, &res_size);
6432f172c55SRobert Thurlow 		free_nfs4ref_info(nfs_fsloc_res);
6442f172c55SRobert Thurlow 		if (error != 0) {
6452f172c55SRobert Thurlow 			syslog(LOG_ERR,
6462f172c55SRobert Thurlow 			    "error allocating fs_locations "
6472f172c55SRobert Thurlow 			    "results buffer");
6482f172c55SRobert Thurlow 			failed_res.res_status = error;
6492f172c55SRobert Thurlow 			failed_res.xdr_len = srsz;
6502f172c55SRobert Thurlow 			res = (caddr_t)&failed_res;
6512f172c55SRobert Thurlow 			res_size = sizeof (refd_door_res_t);
6522f172c55SRobert Thurlow 		} else {
6532f172c55SRobert Thurlow 			door_res->res_status = 0;
6542f172c55SRobert Thurlow 			res = (caddr_t)door_res;
6552f172c55SRobert Thurlow 		}
6562f172c55SRobert Thurlow 	} else {
6572f172c55SRobert Thurlow 		failed_res.res_status = EINVAL;
6582f172c55SRobert Thurlow 		failed_res.xdr_len = 0;
6592f172c55SRobert Thurlow 		res = (caddr_t)&failed_res;
6602f172c55SRobert Thurlow 		res_size = sizeof (refd_door_res_t);
6612f172c55SRobert Thurlow 	}
6622f172c55SRobert Thurlow 
6632f172c55SRobert Thurlow send_response:
6642f172c55SRobert Thurlow 	srsz = res_size;
6652f172c55SRobert Thurlow 	errno = 0;
6662f172c55SRobert Thurlow 
6672f172c55SRobert Thurlow 	error = door_return(res, res_size, NULL, 0);
6682f172c55SRobert Thurlow 	if (errno == E2BIG) {
6692f172c55SRobert Thurlow 		failed_res.res_status = EOVERFLOW;
6702f172c55SRobert Thurlow 		failed_res.xdr_len = srsz;
6712f172c55SRobert Thurlow 		res = (caddr_t)&failed_res;
6722f172c55SRobert Thurlow 		res_size = sizeof (refd_door_res_t);
6732f172c55SRobert Thurlow 	} else {
6742f172c55SRobert Thurlow 		res = NULL;
6752f172c55SRobert Thurlow 		res_size = 0;
6762f172c55SRobert Thurlow 	}
6772f172c55SRobert Thurlow 
6782f172c55SRobert Thurlow 	door_return(res, res_size, NULL, 0);
6792f172c55SRobert Thurlow }
6802f172c55SRobert Thurlow 
6817c478bd9Sstevel@tonic-gate /* ARGSUSED */
6827c478bd9Sstevel@tonic-gate void
nfsmapid_func(void * cookie,char * argp,size_t arg_size,door_desc_t * dp,uint_t n_desc)6837c478bd9Sstevel@tonic-gate nfsmapid_func(void *cookie, char *argp, size_t arg_size,
6847c478bd9Sstevel@tonic-gate 						door_desc_t *dp, uint_t n_desc)
6857c478bd9Sstevel@tonic-gate {
6867c478bd9Sstevel@tonic-gate 	struct mapid_arg	*mapargp;
6877c478bd9Sstevel@tonic-gate 	struct mapid_res	mapres;
6882f172c55SRobert Thurlow 	refd_door_args_t	*referral_args;
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 	/*
6917c478bd9Sstevel@tonic-gate 	 * Make sure we have a valid argument
6927c478bd9Sstevel@tonic-gate 	 */
6937c478bd9Sstevel@tonic-gate 	if (arg_size < sizeof (struct mapid_arg)) {
6947c478bd9Sstevel@tonic-gate 		mapres.status = NFSMAPID_INVALID;
6957c478bd9Sstevel@tonic-gate 		mapres.u_res.len = 0;
6967c478bd9Sstevel@tonic-gate 		(void) door_return((char *)&mapres, sizeof (struct mapid_res),
6977c478bd9Sstevel@tonic-gate 		    NULL, 0);
6987c478bd9Sstevel@tonic-gate 		return;
6997c478bd9Sstevel@tonic-gate 	}
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 	/* LINTED pointer cast */
7027c478bd9Sstevel@tonic-gate 	mapargp = (struct mapid_arg *)argp;
7032f172c55SRobert Thurlow 	referral_args = (refd_door_args_t *)argp;
7047c478bd9Sstevel@tonic-gate 	switch (mapargp->cmd) {
7057c478bd9Sstevel@tonic-gate 	case NFSMAPID_STR_UID:
7067c478bd9Sstevel@tonic-gate 		nfsmapid_str_uid(mapargp, arg_size);
7077c478bd9Sstevel@tonic-gate 		return;
7087c478bd9Sstevel@tonic-gate 	case NFSMAPID_UID_STR:
7097c478bd9Sstevel@tonic-gate 		nfsmapid_uid_str(mapargp, arg_size);
7107c478bd9Sstevel@tonic-gate 		return;
7117c478bd9Sstevel@tonic-gate 	case NFSMAPID_STR_GID:
7127c478bd9Sstevel@tonic-gate 		nfsmapid_str_gid(mapargp, arg_size);
7137c478bd9Sstevel@tonic-gate 		return;
7147c478bd9Sstevel@tonic-gate 	case NFSMAPID_GID_STR:
7157c478bd9Sstevel@tonic-gate 		nfsmapid_gid_str(mapargp, arg_size);
7167c478bd9Sstevel@tonic-gate 		return;
7172f172c55SRobert Thurlow 	case NFSMAPID_SRV_NETINFO:
7182f172c55SRobert Thurlow 		nfsmapid_server_netinfo(referral_args, arg_size);
7197c478bd9Sstevel@tonic-gate 	default:
7207c478bd9Sstevel@tonic-gate 		break;
7217c478bd9Sstevel@tonic-gate 	}
7227c478bd9Sstevel@tonic-gate 	mapres.status = NFSMAPID_INVALID;
7237c478bd9Sstevel@tonic-gate 	mapres.u_res.len = 0;
7247c478bd9Sstevel@tonic-gate 	(void) door_return((char *)&mapres, sizeof (struct mapid_res), NULL, 0);
7257c478bd9Sstevel@tonic-gate }
7267c478bd9Sstevel@tonic-gate 
7278200fe25Srmesta /*
7288200fe25Srmesta  * mapid_get_domain() always returns a ptr to TSD, so the
7298200fe25Srmesta  * check for a NULL domain is not a simple comparison with
7308200fe25Srmesta  * NULL but we need to check the contents of the TSD data.
7318200fe25Srmesta  */
7328200fe25Srmesta int
cur_domain_null(void)7338200fe25Srmesta cur_domain_null(void)
7348200fe25Srmesta {
7358200fe25Srmesta 	char	*p;
7368200fe25Srmesta 
7378200fe25Srmesta 	if ((p = mapid_get_domain()) == NULL)
7388200fe25Srmesta 		return (1);
7398200fe25Srmesta 
7408200fe25Srmesta 	return (p[0] == '\0');
7418200fe25Srmesta }
7428200fe25Srmesta 
7438200fe25Srmesta int
extract_domain(char * cp,char ** upp,char ** dpp)7447c478bd9Sstevel@tonic-gate extract_domain(char *cp, char **upp, char **dpp)
7457c478bd9Sstevel@tonic-gate {
7467c478bd9Sstevel@tonic-gate 	/*
7477c478bd9Sstevel@tonic-gate 	 * Caller must insure that the string is valid
7487c478bd9Sstevel@tonic-gate 	 */
7497c478bd9Sstevel@tonic-gate 	*upp = cp;
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate 	if ((*dpp = strchr(cp, '@')) == NULL)
7527c478bd9Sstevel@tonic-gate 		return (0);
7537c478bd9Sstevel@tonic-gate 	*(*dpp)++ = '\0';
7547c478bd9Sstevel@tonic-gate 	return (1);
7557c478bd9Sstevel@tonic-gate }
7567c478bd9Sstevel@tonic-gate 
7578200fe25Srmesta int
valid_domain(const char * dom)7587c478bd9Sstevel@tonic-gate valid_domain(const char *dom)
7597c478bd9Sstevel@tonic-gate {
7607c478bd9Sstevel@tonic-gate 	const char	*whoami = "valid_domain";
7617c478bd9Sstevel@tonic-gate 
7628200fe25Srmesta 	if (!mapid_stdchk_domain(dom)) {
7638200fe25Srmesta 		syslog(LOG_ERR, gettext("%s: Invalid inbound domain name %s."),
7648200fe25Srmesta 		    whoami, dom);
7657c478bd9Sstevel@tonic-gate 		return (0);
7667c478bd9Sstevel@tonic-gate 	}
7677c478bd9Sstevel@tonic-gate 
7688200fe25Srmesta 	/*
7698200fe25Srmesta 	 * NOTE: mapid_get_domain() returns a ptr to TSD.
7708200fe25Srmesta 	 */
7718200fe25Srmesta 	return (strcasecmp(dom, mapid_get_domain()) == 0);
7727c478bd9Sstevel@tonic-gate }
7737c478bd9Sstevel@tonic-gate 
7748200fe25Srmesta int
validate_id_str(const char * id)7757c478bd9Sstevel@tonic-gate validate_id_str(const char *id)
7767c478bd9Sstevel@tonic-gate {
7777c478bd9Sstevel@tonic-gate 	while (*id) {
7787c478bd9Sstevel@tonic-gate 		if (!isdigit(*id++))
7797c478bd9Sstevel@tonic-gate 			return (0);
7807c478bd9Sstevel@tonic-gate 	}
7817c478bd9Sstevel@tonic-gate 	return (1);
7827c478bd9Sstevel@tonic-gate }
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate void
idmap_kcall(int door_id)7858200fe25Srmesta idmap_kcall(int door_id)
7867c478bd9Sstevel@tonic-gate {
7877c478bd9Sstevel@tonic-gate 	struct nfsidmap_args args;
7887c478bd9Sstevel@tonic-gate 
7898200fe25Srmesta 	if (door_id >= 0) {
7907c478bd9Sstevel@tonic-gate 		args.state = 1;
7918200fe25Srmesta 		args.did = door_id;
7927c478bd9Sstevel@tonic-gate 	} else {
7937c478bd9Sstevel@tonic-gate 		args.state = 0;
7947c478bd9Sstevel@tonic-gate 		args.did = 0;
7957c478bd9Sstevel@tonic-gate 	}
7967c478bd9Sstevel@tonic-gate 	(void) _nfssys(NFS_IDMAP, &args);
7977c478bd9Sstevel@tonic-gate }
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate /*
8007c478bd9Sstevel@tonic-gate  * Get the current NFS domain.
8017c478bd9Sstevel@tonic-gate  *
802dd51520eSPavan Mettu - Oracle Corporation - Menlo Park United States  * If nfsmapid_domain is set in NFS SMF, then it is the NFS domain;
8037c478bd9Sstevel@tonic-gate  * otherwise, the DNS domain is used.
8047c478bd9Sstevel@tonic-gate  */
8057c478bd9Sstevel@tonic-gate void
check_domain(int sighup)8068200fe25Srmesta check_domain(int sighup)
8077c478bd9Sstevel@tonic-gate {
8087c478bd9Sstevel@tonic-gate 	const char	*whoami = "check_domain";
8097c478bd9Sstevel@tonic-gate 	static int	 setup_done = 0;
8108200fe25Srmesta 	static cb_t	 cb;
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate 	/*
8138200fe25Srmesta 	 * Construct the arguments to be passed to libmapid interface
8148200fe25Srmesta 	 * If called in response to a SIGHUP, reset any cached DNS TXT
8158200fe25Srmesta 	 * RR state.
8167c478bd9Sstevel@tonic-gate 	 */
8178200fe25Srmesta 	cb.fcn = cb_update_domain;
8188200fe25Srmesta 	cb.signal = sighup;
8198200fe25Srmesta 	mapid_reeval_domain(&cb);
8207c478bd9Sstevel@tonic-gate 
8217c478bd9Sstevel@tonic-gate 	/*
8227c478bd9Sstevel@tonic-gate 	 * Restart the signal handler thread if we're still setting up
8237c478bd9Sstevel@tonic-gate 	 */
8247c478bd9Sstevel@tonic-gate 	if (!setup_done) {
8257c478bd9Sstevel@tonic-gate 		setup_done = 1;
8267c478bd9Sstevel@tonic-gate 		if (thr_continue(sig_thread)) {
8277c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, gettext("%s: Fatal error: signal "
8287c478bd9Sstevel@tonic-gate 			    "handler thread could not be restarted."), whoami);
8297c478bd9Sstevel@tonic-gate 			exit(6);
8307c478bd9Sstevel@tonic-gate 		}
8317c478bd9Sstevel@tonic-gate 	}
8327c478bd9Sstevel@tonic-gate }
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate /*
835*bbf21555SRichard Lowe  * Need to be able to open the DIAG_FILE before nfsmapid(8)
8367c478bd9Sstevel@tonic-gate  * releases it's root priviledges. The DIAG_FILE then remains
8378200fe25Srmesta  * open for the duration of this nfsmapid instance via n4_fd.
8387c478bd9Sstevel@tonic-gate  */
8397c478bd9Sstevel@tonic-gate void
open_diag_file()8407c478bd9Sstevel@tonic-gate open_diag_file()
8417c478bd9Sstevel@tonic-gate {
8427c478bd9Sstevel@tonic-gate 	static int	msg_done = 0;
8437c478bd9Sstevel@tonic-gate 
8448200fe25Srmesta 	if ((n4_fp = fopen(DIAG_FILE, "w+")) != NULL) {
8458200fe25Srmesta 		n4_fd = fileno(n4_fp);
8467c478bd9Sstevel@tonic-gate 		return;
8478200fe25Srmesta 	}
8487c478bd9Sstevel@tonic-gate 
8497c478bd9Sstevel@tonic-gate 	if (msg_done)
8507c478bd9Sstevel@tonic-gate 		return;
8517c478bd9Sstevel@tonic-gate 
8527c478bd9Sstevel@tonic-gate 	syslog(LOG_ERR, "Failed to create %s. Enable syslog "
8537c478bd9Sstevel@tonic-gate 	    "daemon.debug for more info", DIAG_FILE);
8547c478bd9Sstevel@tonic-gate 	msg_done = 1;
8557c478bd9Sstevel@tonic-gate }
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate /*
8587c478bd9Sstevel@tonic-gate  * When a new domain name is configured, save to DIAG_FILE
8597c478bd9Sstevel@tonic-gate  * and log to syslog, with LOG_DEBUG level (if configured).
8607c478bd9Sstevel@tonic-gate  */
8617c478bd9Sstevel@tonic-gate void
update_diag_file(char * new)8627c478bd9Sstevel@tonic-gate update_diag_file(char *new)
8637c478bd9Sstevel@tonic-gate {
8648200fe25Srmesta 	char	buf[DNAMEMAX];
8658200fe25Srmesta 	ssize_t	n;
8668200fe25Srmesta 	size_t	len;
8678200fe25Srmesta 
8688200fe25Srmesta 	(void) lseek(n4_fd, (off_t)0, SEEK_SET);
8698200fe25Srmesta 	(void) ftruncate(n4_fd, 0);
8708200fe25Srmesta 	(void) snprintf(buf, DNAMEMAX, "%s\n", new);
8718200fe25Srmesta 
8728200fe25Srmesta 	len = strlen(buf);
8738200fe25Srmesta 	n = write(n4_fd, buf, len);
8748200fe25Srmesta 	if (n < 0 || n < len)
8758200fe25Srmesta 		syslog(LOG_DEBUG, "Could not write %s to diag file", new);
876dd5829d1Sbaban 	(void) fsync(n4_fd);
8777c478bd9Sstevel@tonic-gate 
8787c478bd9Sstevel@tonic-gate 	syslog(LOG_DEBUG, "nfsmapid domain = %s", new);
8797c478bd9Sstevel@tonic-gate }
8808200fe25Srmesta 
8818200fe25Srmesta /*
8828200fe25Srmesta  * Callback function for libmapid. This will be called
883*bbf21555SRichard Lowe  * by the lib, everytime the nfsmapid(8) domain changes.
8848200fe25Srmesta  */
8858200fe25Srmesta void *
cb_update_domain(void * arg)8868200fe25Srmesta cb_update_domain(void *arg)
8878200fe25Srmesta {
8888200fe25Srmesta 	char	*new_dname = (char *)arg;
8898200fe25Srmesta 
8908200fe25Srmesta 	DTRACE_PROBE1(nfsmapid, daemon__domain, new_dname);
8918200fe25Srmesta 	update_diag_file(new_dname);
8928200fe25Srmesta 	idmap_kcall(FLUSH_KCACHES_ONLY);
8938200fe25Srmesta 
8948200fe25Srmesta 	return (NULL);
8958200fe25Srmesta }
8962f172c55SRobert Thurlow 
8972f172c55SRobert Thurlow bool_t
xdr_utf8string(XDR * xdrs,utf8string * objp)8982f172c55SRobert Thurlow xdr_utf8string(XDR *xdrs, utf8string *objp)
8992f172c55SRobert Thurlow {
9002f172c55SRobert Thurlow 	if (xdrs->x_op != XDR_FREE)
9012f172c55SRobert Thurlow 		return (xdr_bytes(xdrs, (char **)&objp->utf8string_val,
9022f172c55SRobert Thurlow 		    (uint_t *)&objp->utf8string_len, NFS4_MAX_UTF8STRING));
9032f172c55SRobert Thurlow 	return (TRUE);
9042f172c55SRobert Thurlow }
9052f172c55SRobert Thurlow 
9062f172c55SRobert Thurlow 
9072f172c55SRobert Thurlow int
decode_args(xdrproc_t xdrfunc,refd_door_args_t * argp,caddr_t * xdrargs,int size)9082f172c55SRobert Thurlow decode_args(xdrproc_t xdrfunc, refd_door_args_t *argp, caddr_t *xdrargs,
9092f172c55SRobert Thurlow     int size)
9102f172c55SRobert Thurlow {
9112f172c55SRobert Thurlow 	XDR xdrs;
9122f172c55SRobert Thurlow 
9132f172c55SRobert Thurlow 	caddr_t tmpargs = (caddr_t)&((refd_door_args_t *)argp)->xdr_arg;
9142f172c55SRobert Thurlow 	size_t arg_size = ((refd_door_args_t *)argp)->xdr_len;
9152f172c55SRobert Thurlow 
9162f172c55SRobert Thurlow 	xdrmem_create(&xdrs, tmpargs, arg_size, XDR_DECODE);
9172f172c55SRobert Thurlow 
9182f172c55SRobert Thurlow 	*xdrargs = calloc(1, size);
9192f172c55SRobert Thurlow 	if (*xdrargs == NULL) {
9202f172c55SRobert Thurlow 		syslog(LOG_ERR, "error allocating arguments buffer");
9212f172c55SRobert Thurlow 		return (ENOMEM);
9222f172c55SRobert Thurlow 	}
9232f172c55SRobert Thurlow 
9242f172c55SRobert Thurlow 	if (!(*xdrfunc)(&xdrs, *xdrargs)) {
9252f172c55SRobert Thurlow 		free(*xdrargs);
9262f172c55SRobert Thurlow 		*xdrargs = NULL;
9272f172c55SRobert Thurlow 		syslog(LOG_ERR, "error decoding arguments");
9282f172c55SRobert Thurlow 		return (EINVAL);
9292f172c55SRobert Thurlow 	}
9302f172c55SRobert Thurlow 
9312f172c55SRobert Thurlow 	return (0);
9322f172c55SRobert Thurlow }
9332f172c55SRobert Thurlow 
9342f172c55SRobert Thurlow int
encode_res(xdrproc_t xdrfunc,refd_door_res_t ** results,caddr_t resp,int * size)9352f172c55SRobert Thurlow encode_res(
9362f172c55SRobert Thurlow 	xdrproc_t xdrfunc,
9372f172c55SRobert Thurlow 	refd_door_res_t **results,
9382f172c55SRobert Thurlow 	caddr_t resp,
9392f172c55SRobert Thurlow 	int *size)
9402f172c55SRobert Thurlow {
9412f172c55SRobert Thurlow 	XDR xdrs;
9422f172c55SRobert Thurlow 
9432f172c55SRobert Thurlow 	*size = xdr_sizeof((*xdrfunc), resp);
9442f172c55SRobert Thurlow 	*results = malloc(sizeof (refd_door_res_t) + *size);
9452f172c55SRobert Thurlow 	if (*results == NULL) {
9462f172c55SRobert Thurlow 		return (ENOMEM);
9472f172c55SRobert Thurlow 	}
9482f172c55SRobert Thurlow 	(*results)->xdr_len = *size;
9492f172c55SRobert Thurlow 	*size = sizeof (refd_door_res_t) + (*results)->xdr_len;
9502f172c55SRobert Thurlow 	xdrmem_create(&xdrs, (caddr_t)((*results)->xdr_res),
9512f172c55SRobert Thurlow 	    (*results)->xdr_len, XDR_ENCODE);
9522f172c55SRobert Thurlow 	if (!(*xdrfunc)(&xdrs, resp)) {
9532f172c55SRobert Thurlow 		(*results)->res_status = EINVAL;
9542f172c55SRobert Thurlow 		syslog(LOG_ERR, "error encoding results");
9552f172c55SRobert Thurlow 		return ((*results)->res_status);
9562f172c55SRobert Thurlow 	}
9572f172c55SRobert Thurlow 	(*results)->res_status = 0;
9582f172c55SRobert Thurlow 	return ((*results)->res_status);
9592f172c55SRobert Thurlow }
9602f172c55SRobert Thurlow 
9612f172c55SRobert Thurlow 
9622f172c55SRobert Thurlow bool_t
xdr_knetconfig(XDR * xdrs,struct knetconfig * objp)9632f172c55SRobert Thurlow xdr_knetconfig(XDR *xdrs, struct knetconfig *objp)
9642f172c55SRobert Thurlow {
9652f172c55SRobert Thurlow 	rpc_inline_t *buf;
9662f172c55SRobert Thurlow 	int i;
9672f172c55SRobert Thurlow 	u_longlong_t dev64;
9682f172c55SRobert Thurlow #if !defined(_LP64)
9692f172c55SRobert Thurlow 	uint32_t major, minor;
9702f172c55SRobert Thurlow #endif
9712f172c55SRobert Thurlow 
9722f172c55SRobert Thurlow 	if (!xdr_u_int(xdrs, &objp->knc_semantics))
9732f172c55SRobert Thurlow 		return (FALSE);
9742f172c55SRobert Thurlow 	if (!xdr_opaque(xdrs, objp->knc_protofmly, KNC_STRSIZE))
9752f172c55SRobert Thurlow 		return (FALSE);
9762f172c55SRobert Thurlow 	if (!xdr_opaque(xdrs, objp->knc_proto, KNC_STRSIZE))
9772f172c55SRobert Thurlow 		return (FALSE);
9782f172c55SRobert Thurlow 
9792f172c55SRobert Thurlow 	/*
9802f172c55SRobert Thurlow 	 * For interoperability between 32-bit daemon and 64-bit kernel,
9812f172c55SRobert Thurlow 	 * we always treat dev_t as 64-bit number and do the expanding
9822f172c55SRobert Thurlow 	 * or compression of dev_t as needed.
9832f172c55SRobert Thurlow 	 * We have to hand craft the conversion since there is no available
9842f172c55SRobert Thurlow 	 * function in ddi.c. Besides ddi.c is available only in the kernel
9852f172c55SRobert Thurlow 	 * and we want to keep both user and kernel of xdr_knetconfig() the
9862f172c55SRobert Thurlow 	 * same for consistency.
9872f172c55SRobert Thurlow 	 */
9882f172c55SRobert Thurlow 
9892f172c55SRobert Thurlow 	if (xdrs->x_op == XDR_ENCODE) {
9902f172c55SRobert Thurlow #if defined(_LP64)
9912f172c55SRobert Thurlow 		dev64 = objp->knc_rdev;
9922f172c55SRobert Thurlow #else
9932f172c55SRobert Thurlow 		major = (objp->knc_rdev >> NBITSMINOR32) & MAXMAJ32;
9942f172c55SRobert Thurlow 		minor = objp->knc_rdev & MAXMIN32;
9952f172c55SRobert Thurlow 		dev64 = (((unsigned long long)major) << NBITSMINOR64) | minor;
9962f172c55SRobert Thurlow #endif
9972f172c55SRobert Thurlow 		if (!xdr_u_longlong_t(xdrs, &dev64))
9982f172c55SRobert Thurlow 			return (FALSE);
9992f172c55SRobert Thurlow 	}
10002f172c55SRobert Thurlow 	if (xdrs->x_op == XDR_DECODE) {
10012f172c55SRobert Thurlow #if defined(_LP64)
10022f172c55SRobert Thurlow 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->knc_rdev))
10032f172c55SRobert Thurlow 			return (FALSE);
10042f172c55SRobert Thurlow #else
10052f172c55SRobert Thurlow 		if (!xdr_u_longlong_t(xdrs, &dev64))
10062f172c55SRobert Thurlow 			return (FALSE);
10072f172c55SRobert Thurlow 
10082f172c55SRobert Thurlow 		major = (dev64 >> NBITSMINOR64) & L_MAXMAJ32;
10092f172c55SRobert Thurlow 		minor = dev64 & L_MAXMIN32;
10102f172c55SRobert Thurlow 		objp->knc_rdev = (major << L_BITSMINOR32) | minor;
10112f172c55SRobert Thurlow #endif
10122f172c55SRobert Thurlow 	}
10132f172c55SRobert Thurlow 
10142f172c55SRobert Thurlow 	if (xdrs->x_op == XDR_ENCODE) {
10152f172c55SRobert Thurlow 		buf = XDR_INLINE(xdrs, (8) * BYTES_PER_XDR_UNIT);
10162f172c55SRobert Thurlow 		if (buf == NULL) {
10172f172c55SRobert Thurlow 			if (!xdr_vector(xdrs, (char *)objp->knc_unused, 8,
10182f172c55SRobert Thurlow 			    sizeof (uint_t), (xdrproc_t)xdr_u_int))
10192f172c55SRobert Thurlow 				return (FALSE);
10202f172c55SRobert Thurlow 		} else {
10212f172c55SRobert Thurlow 			uint_t *genp;
10222f172c55SRobert Thurlow 
10232f172c55SRobert Thurlow 			for (i = 0, genp = objp->knc_unused;
10242f172c55SRobert Thurlow 			    i < 8; i++) {
10252f172c55SRobert Thurlow #if defined(_LP64) || defined(_KERNEL)
10262f172c55SRobert Thurlow 				IXDR_PUT_U_INT32(buf, *genp++);
10272f172c55SRobert Thurlow #else
10282f172c55SRobert Thurlow 				IXDR_PUT_U_LONG(buf, *genp++);
10292f172c55SRobert Thurlow #endif
10302f172c55SRobert Thurlow 			}
10312f172c55SRobert Thurlow 		}
10322f172c55SRobert Thurlow 		return (TRUE);
10332f172c55SRobert Thurlow 	} else if (xdrs->x_op == XDR_DECODE) {
10342f172c55SRobert Thurlow 		buf = XDR_INLINE(xdrs, (8) * BYTES_PER_XDR_UNIT);
10352f172c55SRobert Thurlow 		if (buf == NULL) {
10362f172c55SRobert Thurlow 			if (!xdr_vector(xdrs, (char *)objp->knc_unused, 8,
10372f172c55SRobert Thurlow 			    sizeof (uint_t), (xdrproc_t)xdr_u_int))
10382f172c55SRobert Thurlow 				return (FALSE);
10392f172c55SRobert Thurlow 		} else {
10402f172c55SRobert Thurlow 			uint_t *genp;
10412f172c55SRobert Thurlow 
10422f172c55SRobert Thurlow 			for (i = 0, genp = objp->knc_unused;
10432f172c55SRobert Thurlow 			    i < 8; i++) {
10442f172c55SRobert Thurlow #if defined(_LP64) || defined(_KERNEL)
10452f172c55SRobert Thurlow 				*genp++ = IXDR_GET_U_INT32(buf);
10462f172c55SRobert Thurlow #else
10472f172c55SRobert Thurlow 				*genp++ = IXDR_GET_U_LONG(buf);
10482f172c55SRobert Thurlow #endif
10492f172c55SRobert Thurlow 			}
10502f172c55SRobert Thurlow 		}
10512f172c55SRobert Thurlow 		return (TRUE);
10522f172c55SRobert Thurlow 	}
10532f172c55SRobert Thurlow 
10542f172c55SRobert Thurlow 	if (!xdr_vector(xdrs, (char *)objp->knc_unused, 8,
10552f172c55SRobert Thurlow 	    sizeof (uint_t), (xdrproc_t)xdr_u_int))
10562f172c55SRobert Thurlow 		return (FALSE);
10572f172c55SRobert Thurlow 	return (TRUE);
10582f172c55SRobert Thurlow }
10592f172c55SRobert Thurlow 
10602f172c55SRobert Thurlow /*
10612f172c55SRobert Thurlow  * used by NFSv4 referrals to get info needed for NFSv4 referral mount.
10622f172c55SRobert Thurlow  */
10632f172c55SRobert Thurlow bool_t
xdr_nfs_fsl_info(XDR * xdrs,struct nfs_fsl_info * objp)10642f172c55SRobert Thurlow xdr_nfs_fsl_info(XDR *xdrs, struct nfs_fsl_info *objp)
10652f172c55SRobert Thurlow {
10662f172c55SRobert Thurlow 
10672f172c55SRobert Thurlow 	if (!xdr_u_int(xdrs, &objp->netbuf_len))
10682f172c55SRobert Thurlow 		return (FALSE);
10692f172c55SRobert Thurlow 	if (!xdr_u_int(xdrs, &objp->netnm_len))
10702f172c55SRobert Thurlow 		return (FALSE);
10712f172c55SRobert Thurlow 	if (!xdr_u_int(xdrs, &objp->knconf_len))
10722f172c55SRobert Thurlow 		return (FALSE);
10732f172c55SRobert Thurlow 	if (!xdr_string(xdrs, &objp->netname, ~0))
10742f172c55SRobert Thurlow 		return (FALSE);
10752f172c55SRobert Thurlow 	if (!xdr_pointer(xdrs, (char **)&objp->addr, objp->netbuf_len,
10762f172c55SRobert Thurlow 	    (xdrproc_t)xdr_netbuf))
10772f172c55SRobert Thurlow 		return (FALSE);
10782f172c55SRobert Thurlow 	if (!xdr_pointer(xdrs, (char **)&objp->knconf,
10792f172c55SRobert Thurlow 	    objp->knconf_len, (xdrproc_t)xdr_knetconfig))
10802f172c55SRobert Thurlow 		return (FALSE);
10812f172c55SRobert Thurlow 	return (TRUE);
10822f172c55SRobert Thurlow }
1083