xref: /illumos-gate/usr/src/cmd/fs.d/nfs/lib/ref_subr.c (revision 51396a8ee7fb52fe0ab33bfe7b4f495ad431904a)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <strings.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <sys/errno.h>
34 #include <limits.h>
35 #include <libnvpair.h>
36 #include <dlfcn.h>
37 #include <link.h>
38 #include <rp_plugin.h>
39 #include <fcntl.h>
40 #include <uuid/uuid.h>
41 #include <rpc/types.h>
42 #include <rpc/xdr.h>
43 #include <rpc/auth.h>
44 #include <rpc/clnt.h>
45 #include <rpc/rpc_msg.h>
46 #include <sys/param.h>
47 #include <nfs/nfs4.h>
48 #include <rpcsvc/nfs4_prot.h>
49 
50 /*
51  * str_to_utf8 - converts a null-terminated C string to a utf8 string
52  */
53 utf8string *
54 str_to_utf8(char *nm, utf8string *str)
55 {
56 	int len;
57 
58 	if (str == NULL)
59 		return (NULL);
60 
61 	if (nm == NULL || *nm == '\0') {
62 		str->utf8string_len = 0;
63 		str->utf8string_val = NULL;
64 		return (NULL);
65 	}
66 
67 	len = strlen(nm);
68 
69 	str->utf8string_val = malloc(len);
70 	if (str->utf8string_val == NULL) {
71 		str->utf8string_len = 0;
72 		return (NULL);
73 	}
74 	str->utf8string_len = len;
75 	bcopy(nm, str->utf8string_val, len);
76 
77 	return (str);
78 }
79 
80 /*
81  * Converts a utf8 string to a C string.
82  * kmem_allocs a new string if not supplied
83  */
84 char *
85 utf8_to_str(utf8string *str, uint_t *lenp, char *s)
86 {
87 	char	*sp;
88 	char	*u8p;
89 	int	len;
90 	int	 i;
91 
92 	if (str == NULL)
93 		return (NULL);
94 
95 	u8p = str->utf8string_val;
96 	len = str->utf8string_len;
97 	if (len <= 0 || u8p == NULL) {
98 		if (s)
99 			*s = '\0';
100 		return (NULL);
101 	}
102 
103 	sp = s;
104 	if (sp == NULL)
105 		sp = malloc(len + 1);
106 	if (sp == NULL)
107 		return (NULL);
108 
109 	/*
110 	 * At least check for embedded nulls
111 	 */
112 	for (i = 0; i < len; i++) {
113 		sp[i] = u8p[i];
114 		if (u8p[i] == '\0') {
115 			if (s == NULL)
116 				free(sp);
117 			return (NULL);
118 		}
119 	}
120 	sp[len] = '\0';
121 	*lenp = len + 1;
122 
123 	return (sp);
124 }
125 
126 void
127 print_referral_summary(fs_locations4 *fsl)
128 {
129 	int i, j;
130 	uint_t l;
131 	char *s;
132 	fs_location4 *fs;
133 
134 	if (fsl == NULL) {
135 		printf("NULL\n");
136 		return;
137 	}
138 
139 	for (i = 0; i < fsl->locations.locations_len; i++) {
140 		if (i > 0)
141 			printf("\n");
142 		fs = &fsl->locations.locations_val[i];
143 		for (j = 0; j < fs->server.server_len; j++) {
144 			s = utf8_to_str(&fs->server.server_val[j], &l, NULL);
145 			if (j > 0)
146 				printf(",");
147 			printf("%s", s ? s : "");
148 			if (s)
149 				free(s);
150 		}
151 		printf(":");
152 		for (j = 0; j < fs->rootpath.pathname4_len; j++) {
153 			s = utf8_to_str(&fs->rootpath.pathname4_val[j],
154 			    &l, NULL);
155 			printf("/%s", s ? s : "");
156 			if (s)
157 				free(s);
158 		}
159 		if (fs->rootpath.pathname4_len == 0)
160 			printf("/");
161 	}
162 	printf("\n");
163 }
164 
165 /*
166  * There is a kernel copy of this routine in nfs4_srv.c.
167  * Changes should be kept in sync.
168  */
169 static int
170 nfs4_create_components(char *path, component4 *comp4)
171 {
172 	int slen, plen, ncomp;
173 	char *ori_path, *nxtc, buf[MAXNAMELEN];
174 
175 	if (path == NULL)
176 		return (0);
177 
178 	plen = strlen(path) + 1;	/* include the terminator */
179 	ori_path = path;
180 	ncomp = 0;
181 
182 	/* count number of components in the path */
183 	for (nxtc = path; nxtc < ori_path + plen; nxtc++) {
184 		if (*nxtc == '/' || *nxtc == '\0' || *nxtc == '\n') {
185 			if ((slen = nxtc - path) == 0) {
186 				path = nxtc + 1;
187 				continue;
188 			}
189 
190 			if (comp4 != NULL) {
191 				bcopy(path, buf, slen);
192 				buf[slen] = '\0';
193 				if (str_to_utf8(buf, &comp4[ncomp]) == NULL)
194 					return (0);
195 			}
196 
197 			ncomp++;	/* 1 valid component */
198 			path = nxtc + 1;
199 		}
200 		if (*nxtc == '\0' || *nxtc == '\n')
201 			break;
202 	}
203 
204 	return (ncomp);
205 }
206 
207 /*
208  * There is a kernel copy of this routine in nfs4_srv.c.
209  * Changes should be kept in sync.
210  */
211 int
212 make_pathname4(char *path, pathname4 *pathname)
213 {
214 	int ncomp;
215 	component4 *comp4;
216 
217 	if (pathname == NULL)
218 		return (0);
219 
220 	if (path == NULL) {
221 		pathname->pathname4_val = NULL;
222 		pathname->pathname4_len = 0;
223 		return (0);
224 	}
225 
226 	/* count number of components to alloc buffer */
227 	if ((ncomp = nfs4_create_components(path, NULL)) == 0) {
228 		pathname->pathname4_val = NULL;
229 		pathname->pathname4_len = 0;
230 		return (0);
231 	}
232 	comp4 = calloc(ncomp * sizeof (component4), 1);
233 	if (comp4 == NULL) {
234 		pathname->pathname4_val = NULL;
235 		pathname->pathname4_len = 0;
236 		return (0);
237 	}
238 
239 	/* copy components into allocated buffer */
240 	ncomp = nfs4_create_components(path, comp4);
241 
242 	pathname->pathname4_val = comp4;
243 	pathname->pathname4_len = ncomp;
244 
245 	return (ncomp);
246 }
247 
248 bool_t
249 xdr_component4(register XDR *xdrs, component4 *objp)
250 {
251 
252 	if (!xdr_utf8string(xdrs, objp))
253 		return (FALSE);
254 	return (TRUE);
255 }
256 
257 bool_t
258 xdr_utf8string(register XDR *xdrs, utf8string *objp)
259 {
260 
261 	if (xdrs->x_op != XDR_FREE)
262 		return (xdr_bytes(xdrs, (char **)&objp->utf8string_val,
263 		    (uint_t *)&objp->utf8string_len, NFS4_MAX_UTF8STRING));
264 	return (TRUE);
265 }
266 
267 bool_t
268 xdr_pathname4(register XDR *xdrs, pathname4 *objp)
269 {
270 
271 	if (!xdr_array(xdrs, (char **)&objp->pathname4_val,
272 	    (uint_t *)&objp->pathname4_len, NFS4_MAX_PATHNAME4,
273 	    sizeof (component4), (xdrproc_t)xdr_component4))
274 		return (FALSE);
275 	return (TRUE);
276 }
277 
278 bool_t
279 xdr_fs_location4(register XDR *xdrs, fs_location4 *objp)
280 {
281 
282 	if (xdrs->x_op == XDR_DECODE) {
283 		objp->server.server_val = NULL;
284 		objp->rootpath.pathname4_val = NULL;
285 	}
286 	if (!xdr_array(xdrs, (char **)&objp->server.server_val,
287 	    (uint_t *)&objp->server.server_len, ~0,
288 	    sizeof (utf8string), (xdrproc_t)xdr_utf8string))
289 		return (FALSE);
290 	if (!xdr_pathname4(xdrs, &objp->rootpath))
291 		return (FALSE);
292 	return (TRUE);
293 }
294 
295 bool_t
296 xdr_fs_locations4(register XDR *xdrs, fs_locations4 *objp)
297 {
298 
299 	if (xdrs->x_op == XDR_DECODE) {
300 		objp->fs_root.pathname4_len = 0;
301 		objp->fs_root.pathname4_val = NULL;
302 		objp->locations.locations_val = NULL;
303 	}
304 	if (!xdr_pathname4(xdrs, &objp->fs_root))
305 		return (FALSE);
306 	if (!xdr_array(xdrs, (char **)&objp->locations.locations_val,
307 	    (uint_t *)&objp->locations.locations_len, ~0,
308 	    sizeof (fs_location4), (xdrproc_t)xdr_fs_location4))
309 		return (FALSE);
310 	return (TRUE);
311 }
312