xref: /illumos-gate/usr/src/cmd/fs.d/nfs/lib/ref_subr.c (revision 8509e9ca)
12f172c55SRobert Thurlow /*
22f172c55SRobert Thurlow  * CDDL HEADER START
32f172c55SRobert Thurlow  *
42f172c55SRobert Thurlow  * The contents of this file are subject to the terms of the
52f172c55SRobert Thurlow  * Common Development and Distribution License (the "License").
62f172c55SRobert Thurlow  * You may not use this file except in compliance with the License.
72f172c55SRobert Thurlow  *
82f172c55SRobert Thurlow  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92f172c55SRobert Thurlow  * or http://www.opensolaris.org/os/licensing.
102f172c55SRobert Thurlow  * See the License for the specific language governing permissions
112f172c55SRobert Thurlow  * and limitations under the License.
122f172c55SRobert Thurlow  *
132f172c55SRobert Thurlow  * When distributing Covered Code, include this CDDL HEADER in each
142f172c55SRobert Thurlow  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152f172c55SRobert Thurlow  * If applicable, add the following below this CDDL HEADER, with the
162f172c55SRobert Thurlow  * fields enclosed by brackets "[]" replaced with your own identifying
172f172c55SRobert Thurlow  * information: Portions Copyright [yyyy] [name of copyright owner]
182f172c55SRobert Thurlow  *
192f172c55SRobert Thurlow  * CDDL HEADER END
202f172c55SRobert Thurlow  */
212f172c55SRobert Thurlow 
222f172c55SRobert Thurlow /*
232f172c55SRobert Thurlow  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
242f172c55SRobert Thurlow  * Use is subject to license terms.
252f172c55SRobert Thurlow  */
262f172c55SRobert Thurlow 
272f172c55SRobert Thurlow #include <stdio.h>
282f172c55SRobert Thurlow #include <unistd.h>
292f172c55SRobert Thurlow #include <strings.h>
302f172c55SRobert Thurlow #include <string.h>
312f172c55SRobert Thurlow #include <sys/types.h>
322f172c55SRobert Thurlow #include <sys/stat.h>
332f172c55SRobert Thurlow #include <sys/errno.h>
342f172c55SRobert Thurlow #include <limits.h>
352f172c55SRobert Thurlow #include <libnvpair.h>
362f172c55SRobert Thurlow #include <dlfcn.h>
372f172c55SRobert Thurlow #include <link.h>
382f172c55SRobert Thurlow #include <rp_plugin.h>
392f172c55SRobert Thurlow #include <fcntl.h>
402f172c55SRobert Thurlow #include <uuid/uuid.h>
412f172c55SRobert Thurlow #include <rpc/types.h>
422f172c55SRobert Thurlow #include <rpc/xdr.h>
432f172c55SRobert Thurlow #include <rpc/auth.h>
442f172c55SRobert Thurlow #include <rpc/clnt.h>
452f172c55SRobert Thurlow #include <rpc/rpc_msg.h>
462f172c55SRobert Thurlow #include <sys/param.h>
472f172c55SRobert Thurlow #include <nfs/nfs4.h>
482f172c55SRobert Thurlow #include <rpcsvc/nfs4_prot.h>
492f172c55SRobert Thurlow 
502f172c55SRobert Thurlow /*
512f172c55SRobert Thurlow  * str_to_utf8 - converts a null-terminated C string to a utf8 string
522f172c55SRobert Thurlow  */
532f172c55SRobert Thurlow utf8string *
str_to_utf8(char * nm,utf8string * str)542f172c55SRobert Thurlow str_to_utf8(char *nm, utf8string *str)
552f172c55SRobert Thurlow {
562f172c55SRobert Thurlow 	int len;
572f172c55SRobert Thurlow 
582f172c55SRobert Thurlow 	if (str == NULL)
592f172c55SRobert Thurlow 		return (NULL);
602f172c55SRobert Thurlow 
612f172c55SRobert Thurlow 	if (nm == NULL || *nm == '\0') {
622f172c55SRobert Thurlow 		str->utf8string_len = 0;
632f172c55SRobert Thurlow 		str->utf8string_val = NULL;
642f172c55SRobert Thurlow 		return (NULL);
652f172c55SRobert Thurlow 	}
662f172c55SRobert Thurlow 
672f172c55SRobert Thurlow 	len = strlen(nm);
682f172c55SRobert Thurlow 
692f172c55SRobert Thurlow 	str->utf8string_val = malloc(len);
702f172c55SRobert Thurlow 	if (str->utf8string_val == NULL) {
712f172c55SRobert Thurlow 		str->utf8string_len = 0;
722f172c55SRobert Thurlow 		return (NULL);
732f172c55SRobert Thurlow 	}
742f172c55SRobert Thurlow 	str->utf8string_len = len;
752f172c55SRobert Thurlow 	bcopy(nm, str->utf8string_val, len);
762f172c55SRobert Thurlow 
772f172c55SRobert Thurlow 	return (str);
782f172c55SRobert Thurlow }
792f172c55SRobert Thurlow 
802f172c55SRobert Thurlow /*
812f172c55SRobert Thurlow  * Converts a utf8 string to a C string.
822f172c55SRobert Thurlow  * kmem_allocs a new string if not supplied
832f172c55SRobert Thurlow  */
842f172c55SRobert Thurlow char *
utf8_to_str(utf8string * str,uint_t * lenp,char * s)852f172c55SRobert Thurlow utf8_to_str(utf8string *str, uint_t *lenp, char *s)
862f172c55SRobert Thurlow {
872f172c55SRobert Thurlow 	char	*sp;
882f172c55SRobert Thurlow 	char	*u8p;
892f172c55SRobert Thurlow 	int	len;
902f172c55SRobert Thurlow 	int	 i;
912f172c55SRobert Thurlow 
922f172c55SRobert Thurlow 	if (str == NULL)
932f172c55SRobert Thurlow 		return (NULL);
942f172c55SRobert Thurlow 
952f172c55SRobert Thurlow 	u8p = str->utf8string_val;
962f172c55SRobert Thurlow 	len = str->utf8string_len;
972f172c55SRobert Thurlow 	if (len <= 0 || u8p == NULL) {
982f172c55SRobert Thurlow 		if (s)
992f172c55SRobert Thurlow 			*s = '\0';
1002f172c55SRobert Thurlow 		return (NULL);
1012f172c55SRobert Thurlow 	}
1022f172c55SRobert Thurlow 
1032f172c55SRobert Thurlow 	sp = s;
1042f172c55SRobert Thurlow 	if (sp == NULL)
1052f172c55SRobert Thurlow 		sp = malloc(len + 1);
1062f172c55SRobert Thurlow 	if (sp == NULL)
1072f172c55SRobert Thurlow 		return (NULL);
1082f172c55SRobert Thurlow 
1092f172c55SRobert Thurlow 	/*
1102f172c55SRobert Thurlow 	 * At least check for embedded nulls
1112f172c55SRobert Thurlow 	 */
1122f172c55SRobert Thurlow 	for (i = 0; i < len; i++) {
1132f172c55SRobert Thurlow 		sp[i] = u8p[i];
1142f172c55SRobert Thurlow 		if (u8p[i] == '\0') {
1152f172c55SRobert Thurlow 			if (s == NULL)
1162f172c55SRobert Thurlow 				free(sp);
1172f172c55SRobert Thurlow 			return (NULL);
1182f172c55SRobert Thurlow 		}
1192f172c55SRobert Thurlow 	}
1202f172c55SRobert Thurlow 	sp[len] = '\0';
1212f172c55SRobert Thurlow 	*lenp = len + 1;
1222f172c55SRobert Thurlow 
1232f172c55SRobert Thurlow 	return (sp);
1242f172c55SRobert Thurlow }
1252f172c55SRobert Thurlow 
1262f172c55SRobert Thurlow void
print_referral_summary(fs_locations4 * fsl)1272f172c55SRobert Thurlow print_referral_summary(fs_locations4 *fsl)
1282f172c55SRobert Thurlow {
1292f172c55SRobert Thurlow 	int i, j;
1302f172c55SRobert Thurlow 	uint_t l;
1312f172c55SRobert Thurlow 	char *s;
1322f172c55SRobert Thurlow 	fs_location4 *fs;
1332f172c55SRobert Thurlow 
1342f172c55SRobert Thurlow 	if (fsl == NULL) {
1352f172c55SRobert Thurlow 		printf("NULL\n");
1362f172c55SRobert Thurlow 		return;
1372f172c55SRobert Thurlow 	}
1382f172c55SRobert Thurlow 
1392f172c55SRobert Thurlow 	for (i = 0; i < fsl->locations.locations_len; i++) {
1402f172c55SRobert Thurlow 		if (i > 0)
1412f172c55SRobert Thurlow 			printf("\n");
1422f172c55SRobert Thurlow 		fs = &fsl->locations.locations_val[i];
1432f172c55SRobert Thurlow 		for (j = 0; j < fs->server.server_len; j++) {
1442f172c55SRobert Thurlow 			s = utf8_to_str(&fs->server.server_val[j], &l, NULL);
1452f172c55SRobert Thurlow 			if (j > 0)
1462f172c55SRobert Thurlow 				printf(",");
1472f172c55SRobert Thurlow 			printf("%s", s ? s : "");
1482f172c55SRobert Thurlow 			if (s)
1492f172c55SRobert Thurlow 				free(s);
1502f172c55SRobert Thurlow 		}
1512f172c55SRobert Thurlow 		printf(":");
1522f172c55SRobert Thurlow 		for (j = 0; j < fs->rootpath.pathname4_len; j++) {
1532f172c55SRobert Thurlow 			s = utf8_to_str(&fs->rootpath.pathname4_val[j],
1542f172c55SRobert Thurlow 			    &l, NULL);
1552f172c55SRobert Thurlow 			printf("/%s", s ? s : "");
1562f172c55SRobert Thurlow 			if (s)
1572f172c55SRobert Thurlow 				free(s);
1582f172c55SRobert Thurlow 		}
1592f172c55SRobert Thurlow 		if (fs->rootpath.pathname4_len == 0)
1602f172c55SRobert Thurlow 			printf("/");
1612f172c55SRobert Thurlow 	}
1622f172c55SRobert Thurlow 	printf("\n");
1632f172c55SRobert Thurlow }
1642f172c55SRobert Thurlow 
1652f172c55SRobert Thurlow /*
1662f172c55SRobert Thurlow  * There is a kernel copy of this routine in nfs4_srv.c.
1672f172c55SRobert Thurlow  * Changes should be kept in sync.
1682f172c55SRobert Thurlow  */
1692f172c55SRobert Thurlow static int
nfs4_create_components(char * path,component4 * comp4)1702f172c55SRobert Thurlow nfs4_create_components(char *path, component4 *comp4)
1712f172c55SRobert Thurlow {
1722f172c55SRobert Thurlow 	int slen, plen, ncomp;
1732f172c55SRobert Thurlow 	char *ori_path, *nxtc, buf[MAXNAMELEN];
1742f172c55SRobert Thurlow 
1752f172c55SRobert Thurlow 	if (path == NULL)
1762f172c55SRobert Thurlow 		return (0);
1772f172c55SRobert Thurlow 
1782f172c55SRobert Thurlow 	plen = strlen(path) + 1;	/* include the terminator */
1792f172c55SRobert Thurlow 	ori_path = path;
1802f172c55SRobert Thurlow 	ncomp = 0;
1812f172c55SRobert Thurlow 
1822f172c55SRobert Thurlow 	/* count number of components in the path */
1832f172c55SRobert Thurlow 	for (nxtc = path; nxtc < ori_path + plen; nxtc++) {
1842f172c55SRobert Thurlow 		if (*nxtc == '/' || *nxtc == '\0' || *nxtc == '\n') {
1852f172c55SRobert Thurlow 			if ((slen = nxtc - path) == 0) {
1862f172c55SRobert Thurlow 				path = nxtc + 1;
1872f172c55SRobert Thurlow 				continue;
1882f172c55SRobert Thurlow 			}
1892f172c55SRobert Thurlow 
1902f172c55SRobert Thurlow 			if (comp4 != NULL) {
1912f172c55SRobert Thurlow 				bcopy(path, buf, slen);
1922f172c55SRobert Thurlow 				buf[slen] = '\0';
1932f172c55SRobert Thurlow 				if (str_to_utf8(buf, &comp4[ncomp]) == NULL)
194*8509e9caSToomas Soome 					return (0);
1952f172c55SRobert Thurlow 			}
1962f172c55SRobert Thurlow 
1972f172c55SRobert Thurlow 			ncomp++;	/* 1 valid component */
1982f172c55SRobert Thurlow 			path = nxtc + 1;
1992f172c55SRobert Thurlow 		}
2002f172c55SRobert Thurlow 		if (*nxtc == '\0' || *nxtc == '\n')
2012f172c55SRobert Thurlow 			break;
2022f172c55SRobert Thurlow 	}
2032f172c55SRobert Thurlow 
2042f172c55SRobert Thurlow 	return (ncomp);
2052f172c55SRobert Thurlow }
2062f172c55SRobert Thurlow 
2072f172c55SRobert Thurlow /*
2082f172c55SRobert Thurlow  * There is a kernel copy of this routine in nfs4_srv.c.
2092f172c55SRobert Thurlow  * Changes should be kept in sync.
2102f172c55SRobert Thurlow  */
2112f172c55SRobert Thurlow int
make_pathname4(char * path,pathname4 * pathname)2122f172c55SRobert Thurlow make_pathname4(char *path, pathname4 *pathname)
2132f172c55SRobert Thurlow {
2142f172c55SRobert Thurlow 	int ncomp;
2152f172c55SRobert Thurlow 	component4 *comp4;
2162f172c55SRobert Thurlow 
2172f172c55SRobert Thurlow 	if (pathname == NULL)
2182f172c55SRobert Thurlow 		return (0);
2192f172c55SRobert Thurlow 
2202f172c55SRobert Thurlow 	if (path == NULL) {
2212f172c55SRobert Thurlow 		pathname->pathname4_val = NULL;
2222f172c55SRobert Thurlow 		pathname->pathname4_len = 0;
2232f172c55SRobert Thurlow 		return (0);
2242f172c55SRobert Thurlow 	}
2252f172c55SRobert Thurlow 
2262f172c55SRobert Thurlow 	/* count number of components to alloc buffer */
2272f172c55SRobert Thurlow 	if ((ncomp = nfs4_create_components(path, NULL)) == 0) {
2282f172c55SRobert Thurlow 		pathname->pathname4_val = NULL;
2292f172c55SRobert Thurlow 		pathname->pathname4_len = 0;
2302f172c55SRobert Thurlow 		return (0);
2312f172c55SRobert Thurlow 	}
2322f172c55SRobert Thurlow 	comp4 = calloc(ncomp * sizeof (component4), 1);
2332f172c55SRobert Thurlow 	if (comp4 == NULL) {
2342f172c55SRobert Thurlow 		pathname->pathname4_val = NULL;
2352f172c55SRobert Thurlow 		pathname->pathname4_len = 0;
2362f172c55SRobert Thurlow 		return (0);
2372f172c55SRobert Thurlow 	}
2382f172c55SRobert Thurlow 
2392f172c55SRobert Thurlow 	/* copy components into allocated buffer */
2402f172c55SRobert Thurlow 	ncomp = nfs4_create_components(path, comp4);
2412f172c55SRobert Thurlow 
2422f172c55SRobert Thurlow 	pathname->pathname4_val = comp4;
2432f172c55SRobert Thurlow 	pathname->pathname4_len = ncomp;
2442f172c55SRobert Thurlow 
2452f172c55SRobert Thurlow 	return (ncomp);
2462f172c55SRobert Thurlow }
2472f172c55SRobert Thurlow 
2482f172c55SRobert Thurlow bool_t
xdr_component4(register XDR * xdrs,component4 * objp)2492f172c55SRobert Thurlow xdr_component4(register XDR *xdrs, component4 *objp)
2502f172c55SRobert Thurlow {
2512f172c55SRobert Thurlow 
2522f172c55SRobert Thurlow 	if (!xdr_utf8string(xdrs, objp))
2532f172c55SRobert Thurlow 		return (FALSE);
2542f172c55SRobert Thurlow 	return (TRUE);
2552f172c55SRobert Thurlow }
2562f172c55SRobert Thurlow 
2572f172c55SRobert Thurlow bool_t
xdr_utf8string(register XDR * xdrs,utf8string * objp)2582f172c55SRobert Thurlow xdr_utf8string(register XDR *xdrs, utf8string *objp)
2592f172c55SRobert Thurlow {
2602f172c55SRobert Thurlow 
2612f172c55SRobert Thurlow 	if (xdrs->x_op != XDR_FREE)
2622f172c55SRobert Thurlow 		return (xdr_bytes(xdrs, (char **)&objp->utf8string_val,
2632f172c55SRobert Thurlow 		    (uint_t *)&objp->utf8string_len, NFS4_MAX_UTF8STRING));
2642f172c55SRobert Thurlow 	return (TRUE);
2652f172c55SRobert Thurlow }
2662f172c55SRobert Thurlow 
2672f172c55SRobert Thurlow bool_t
xdr_pathname4(register XDR * xdrs,pathname4 * objp)2682f172c55SRobert Thurlow xdr_pathname4(register XDR *xdrs, pathname4 *objp)
2692f172c55SRobert Thurlow {
2702f172c55SRobert Thurlow 
2712f172c55SRobert Thurlow 	if (!xdr_array(xdrs, (char **)&objp->pathname4_val,
2722f172c55SRobert Thurlow 	    (uint_t *)&objp->pathname4_len, NFS4_MAX_PATHNAME4,
2732f172c55SRobert Thurlow 	    sizeof (component4), (xdrproc_t)xdr_component4))
2742f172c55SRobert Thurlow 		return (FALSE);
2752f172c55SRobert Thurlow 	return (TRUE);
2762f172c55SRobert Thurlow }
2772f172c55SRobert Thurlow 
2782f172c55SRobert Thurlow bool_t
xdr_fs_location4(register XDR * xdrs,fs_location4 * objp)2792f172c55SRobert Thurlow xdr_fs_location4(register XDR *xdrs, fs_location4 *objp)
2802f172c55SRobert Thurlow {
2812f172c55SRobert Thurlow 
2822f172c55SRobert Thurlow 	if (xdrs->x_op == XDR_DECODE) {
2832f172c55SRobert Thurlow 		objp->server.server_val = NULL;
2842f172c55SRobert Thurlow 		objp->rootpath.pathname4_val = NULL;
2852f172c55SRobert Thurlow 	}
2862f172c55SRobert Thurlow 	if (!xdr_array(xdrs, (char **)&objp->server.server_val,
2872f172c55SRobert Thurlow 	    (uint_t *)&objp->server.server_len, ~0,
2882f172c55SRobert Thurlow 	    sizeof (utf8string), (xdrproc_t)xdr_utf8string))
2892f172c55SRobert Thurlow 		return (FALSE);
2902f172c55SRobert Thurlow 	if (!xdr_pathname4(xdrs, &objp->rootpath))
2912f172c55SRobert Thurlow 		return (FALSE);
2922f172c55SRobert Thurlow 	return (TRUE);
2932f172c55SRobert Thurlow }
2942f172c55SRobert Thurlow 
2952f172c55SRobert Thurlow bool_t
xdr_fs_locations4(register XDR * xdrs,fs_locations4 * objp)2962f172c55SRobert Thurlow xdr_fs_locations4(register XDR *xdrs, fs_locations4 *objp)
2972f172c55SRobert Thurlow {
2982f172c55SRobert Thurlow 
2992f172c55SRobert Thurlow 	if (xdrs->x_op == XDR_DECODE) {
3002f172c55SRobert Thurlow 		objp->fs_root.pathname4_len = 0;
3012f172c55SRobert Thurlow 		objp->fs_root.pathname4_val = NULL;
3022f172c55SRobert Thurlow 		objp->locations.locations_val = NULL;
3032f172c55SRobert Thurlow 	}
3042f172c55SRobert Thurlow 	if (!xdr_pathname4(xdrs, &objp->fs_root))
3052f172c55SRobert Thurlow 		return (FALSE);
3062f172c55SRobert Thurlow 	if (!xdr_array(xdrs, (char **)&objp->locations.locations_val,
3072f172c55SRobert Thurlow 	    (uint_t *)&objp->locations.locations_len, ~0,
3082f172c55SRobert Thurlow 	    sizeof (fs_location4), (xdrproc_t)xdr_fs_location4))
3092f172c55SRobert Thurlow 		return (FALSE);
3102f172c55SRobert Thurlow 	return (TRUE);
3112f172c55SRobert Thurlow }
312