xref: /illumos-gate/usr/src/stand/lib/fs/nfs/nfs4_xdr.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/salib.h>
30 #include <rpc/types.h>
31 #include <rpc/xdr.h>
32 #include <rpc/rpc.h>
33 #include <rpcsvc/nfs4_prot.h>
34 #include "nfs_inet.h"
35 
36 #define	dprintf if (boothowto & RB_DEBUG) printf
37 
38 /*
39  * XDR routines for NFSv4 ops.
40  */
41 static bool_t
42 xdr_b_utf8string(XDR *xdrs, utf8string *objp)
43 {
44 	return (xdr_bytes(xdrs, (char **)&objp->utf8string_val,
45 		(uint_t *)&objp->utf8string_len, NFS4_MAX_UTF8STRING));
46 }
47 
48 static bool_t
49 xdr_nfs_bfh4(XDR *xdrs, struct nfs_bfh4 *objp)
50 {
51 	char *data = (char *)&objp->data;
52 	return (xdr_bytes(xdrs, (char **)&data, (uint_t *)&objp->len,
53 				NFS4_FHSIZE));
54 }
55 
56 static bool_t
57 xdr_b_putfh4_args(XDR *xdrs, putfh4arg_t *objp)
58 {
59 	if (!xdr_u_int(xdrs, (uint_t *)&objp->pf_opnum))
60 		return (FALSE);
61 	return (xdr_nfs_bfh4(xdrs, (struct nfs_bfh4 *)&objp->pf_filehandle));
62 }
63 
64 /*
65  * Common xdr routines for compound.  Let the specific op routines handle
66  * op specific portions of the compound.
67  */
68 static bool_t
69 xdr_b_compound_args(XDR *xdrs, b_compound_t *objp)
70 {
71 	if (!xdr_b_utf8string(xdrs, &objp->ca_tag)) {
72 		return (FALSE);
73 	}
74 	if (!xdr_u_int(xdrs, &objp->ca_minorversion))
75 		return (FALSE);
76 	if (!xdr_u_int(xdrs, &objp->ca_argarray_len))
77 		return (FALSE);
78 	if (objp->ca_isputrootfh)
79 		return (xdr_u_int(xdrs, &objp->ca_opputfh.pf_opnum));
80 	return (xdr_b_putfh4_args(xdrs, &objp->ca_opputfh));
81 }
82 
83 static bool_t
84 xdr_b_compound_res(XDR *xdrs, b_compound_t *objp)
85 {
86 	if (!xdr_enum(xdrs, (enum_t *)&objp->cr_status))
87 		return (FALSE);
88 	if (!xdr_b_utf8string(xdrs, &objp->cr_tag))
89 		return (FALSE);
90 	if (!xdr_u_int(xdrs, &objp->cr_resarray_len))
91 		return (FALSE);
92 	if (!xdr_u_int(xdrs, &objp->cr_opputfh))
93 		return (FALSE);
94 	return (xdr_enum(xdrs, (enum_t *)&objp->cr_putfh_status));
95 }
96 
97 static bool_t
98 xdr_b_bitmap4(XDR *xdrs, b_bitmap4_t *objp)
99 {
100 	char *arp = (char *)&objp->b_bitmap_val;
101 	return (xdr_array(xdrs, (char **)&arp,
102 				(uint_t *)&objp->b_bitmap_len, ~0,
103 				sizeof (uint_t), (xdrproc_t)xdr_u_int));
104 }
105 
106 static bool_t
107 xdr_b_stateid4(XDR *xdrs, stateid4 *objp)
108 {
109 	if (!xdr_u_int(xdrs, (uint_t *)&objp->seqid))
110 		return (FALSE);
111 	return (xdr_opaque(xdrs, objp->other, 12));
112 }
113 
114 bool_t
115 xdr_getattr4_args(XDR *xdrs, getattr4arg_t *objp)
116 {
117 	if (!xdr_b_compound_args(xdrs, (b_compound_t *)&objp->ga_arg))
118 		return (FALSE);
119 	if (!xdr_u_int(xdrs, (uint_t *)&objp->ga_opgetattr))
120 		return (FALSE);
121 	return (xdr_b_bitmap4(xdrs, (b_bitmap4_t *)&objp->ga_attr_req));
122 }
123 
124 static bool_t
125 xdr_b_getattr_res_common(XDR *xdrs, getattrres_cmn_t *objp)
126 {
127 	if (!xdr_u_int(xdrs, (uint_t *)&objp->gc_opgetattr))
128 		return (FALSE);
129 	if (!xdr_enum(xdrs, (enum_t *)&objp->gc_attr_status))
130 		return (FALSE);
131 
132 	/*
133 	 * If the getattr suceeded, proceed and begin to decode the attributes.
134 	 */
135 	if (objp->gc_attr_status == NFS4_OK) {
136 		char		attrvals[sizeof (b_fattr4_t)];
137 		char		*ap = attrvals;
138 
139 		if (!xdr_b_bitmap4(xdrs, (b_bitmap4_t *)&objp->gc_retattr))
140 			return (FALSE);
141 
142 		bzero(&attrvals, sizeof (attrvals));
143 		if (!xdr_bytes(xdrs, (char **)&ap,
144 				(uint_t *)&objp->gc_attrlist_len,
145 				sizeof (b_fattr4_t)))
146 			return (FALSE);
147 #ifdef DEBUG
148 		printf("xdr_b_getattr_res_common: attrlist_len = %d\n",
149 			objp->gc_attrlist_len);
150 #endif
151 		/*
152 		 * Go through the bitmap and see if the server
153 		 * sent us anything.
154 		 */
155 		if (objp->gc_attrlist_len > 0) {
156 			XDR		mxdrs;
157 			b_fattr4_t	*fattrp = &objp->gc_attrs;
158 			attr4_bitmap1_t bitmap1;
159 			attr4_bitmap2_t bitmap2;
160 #ifdef DEBUG
161 			int i;
162 
163 			printf("dumping contents of attr buffer\n");
164 			for (i = 0; i < objp->gc_attrlist_len; i++) {
165 				printf("[%d] = 0x%x\n", i, ap[i]);
166 			}
167 #endif
168 			bitmap1.word = objp->gc_retattr.b_bitmap_val[0];
169 			bitmap2.word = objp->gc_retattr.b_bitmap_val[1];
170 
171 #ifdef DEBUG
172 			printf("xdr_b_getattr_res_common: bitmap1 = %d "
173 				"			bitmap2 = %d\n",
174 				bitmap1.word, bitmap2.word);
175 #endif
176 			xdrmem_create(&mxdrs, ap, objp->gc_attrlist_len,
177 					XDR_DECODE);
178 
179 			/*
180 			 * Start with the first bitmap
181 			 */
182 			if (bitmap1.word > 0) {
183 				if (bitmap1.bm_supported_attrs) {
184 					if (!xdr_b_bitmap4(&mxdrs,
185 				(b_bitmap4_t *)&fattrp->b_supported_attrs))
186 						return (FALSE);
187 				}
188 
189 				if (bitmap1.bm_fattr4_type) {
190 					if (!xdr_enum(&mxdrs,
191 				(enum_t *)&fattrp->b_fattr4_type)) {
192 						return (FALSE);
193 					}
194 				}
195 				if (bitmap1.bm_fattr4_size) {
196 					if (!xdr_u_longlong_t(&mxdrs,
197 				(u_longlong_t *)&fattrp->b_fattr4_size))
198 						return (FALSE);
199 				}
200 
201 				if (bitmap1.bm_fattr4_fsid) {
202 					if (!xdr_u_longlong_t(&mxdrs,
203 			(u_longlong_t *)&fattrp->b_fattr4_fsid.major))
204 						return (FALSE);
205 
206 					if (!xdr_u_longlong_t(&mxdrs,
207 			(u_longlong_t *)&fattrp->b_fattr4_fsid.minor))
208 						return (FALSE);
209 				}
210 				if (bitmap1.bm_fattr4_filehandle) {
211 					if (!xdr_nfs_bfh4(&mxdrs,
212 		(struct nfs_bfh4 *)&fattrp->b_fattr4_filehandle))
213 						return (FALSE);
214 				}
215 				if (bitmap1.bm_fattr4_fileid) {
216 					if (!xdr_u_longlong_t(&mxdrs,
217 			(u_longlong_t *)&fattrp->b_fattr4_fileid))
218 						return (FALSE);
219 				}
220 			}
221 
222 			/*
223 			 * Now the second bitmap
224 			 */
225 			if (bitmap2.word > 0) {
226 				if (bitmap2.bm_fattr4_mode) {
227 					if (!xdr_u_int(&mxdrs,
228 				(uint_t *)&objp->gc_attrs.b_fattr4_mode))
229 						return (FALSE);
230 				}
231 
232 				if (bitmap2.bm_fattr4_time_access) {
233 					if (!xdr_longlong_t(&mxdrs,
234 		(longlong_t *)&objp->gc_attrs.b_fattr4_time_access.seconds))
235 						return (FALSE);
236 					if (!xdr_u_int(&mxdrs,
237 		(uint_t *)&objp->gc_attrs.b_fattr4_time_access.nseconds))
238 						return (FALSE);
239 				}
240 
241 				if (bitmap2.bm_fattr4_time_metadata) {
242 					if (!xdr_longlong_t(&mxdrs,
243 		(longlong_t *)&objp->gc_attrs.b_fattr4_time_metadata.seconds))
244 						return (FALSE);
245 					if (!xdr_u_int(&mxdrs,
246 		(uint_t *)&objp->gc_attrs.b_fattr4_time_metadata.nseconds))
247 						return (FALSE);
248 				}
249 
250 				if (bitmap2.bm_fattr4_time_modify) {
251 					if (!xdr_longlong_t(&mxdrs,
252 		(longlong_t *)&objp->gc_attrs.b_fattr4_time_modify.seconds))
253 						return (FALSE);
254 					if (!xdr_u_int(&mxdrs,
255 		(uint_t *)&objp->gc_attrs.b_fattr4_time_modify.nseconds))
256 						return (FALSE);
257 				}
258 			}
259 		}
260 	}
261 	return (TRUE);
262 }
263 
264 bool_t
265 xdr_getattr4_res(XDR *xdrs, getattr4res_t *objp)
266 {
267 	if (!xdr_b_compound_res(xdrs, (b_compound_t *)&objp->gr_res))
268 		return (FALSE);
269 	return (xdr_b_getattr_res_common(xdrs,
270 					(getattrres_cmn_t *)&objp->gr_cmn));
271 }
272 
273 bool_t
274 xdr_lookup4_args(XDR *xdrs, lookup4arg_t *objp)
275 {
276 	if (!xdr_b_compound_args(xdrs, (b_compound_t *)&objp->la_arg))
277 		return (FALSE);
278 	if (!xdr_u_int(xdrs, (uint_t *)&objp->la_oplookup))
279 		return (FALSE);
280 	if (!xdr_b_utf8string(xdrs, (utf8string *)&objp->la_pathname))
281 		return (FALSE);
282 	if (!xdr_u_int(xdrs, (uint_t *)&objp->la_opgetattr))
283 		return (FALSE);
284 	return (xdr_b_bitmap4(xdrs, (b_bitmap4_t *)&objp->la_attr_req));
285 }
286 
287 bool_t
288 xdr_lookup4_res(XDR *xdrs, lookup4res_t *objp)
289 {
290 	if (!xdr_b_compound_res(xdrs, (b_compound_t *)&objp->lr_res))
291 		return (FALSE);
292 	if (!xdr_u_int(xdrs, (uint_t *)&objp->lr_oplookup))
293 		return (FALSE);
294 	if (!xdr_enum(xdrs, (enum_t *)&objp->lr_lookup_status))
295 		return (FALSE);
296 	if (objp->lr_lookup_status == NFS4_OK) {
297 		return (xdr_b_getattr_res_common(xdrs,
298 					(getattrres_cmn_t *)&objp->lr_gcmn));
299 	}
300 	return (TRUE);
301 }
302 
303 bool_t
304 xdr_lookupp4_args(XDR *xdrs, lookupp4arg_t *objp)
305 {
306 	if (!xdr_b_compound_args(xdrs, (b_compound_t *)&objp->la_arg))
307 		return (FALSE);
308 	if (!xdr_u_int(xdrs, (uint_t *)&objp->la_oplookupp))
309 		return (FALSE);
310 	if (!xdr_u_int(xdrs, (uint_t *)&objp->la_opgetattr))
311 		return (FALSE);
312 	return (xdr_b_bitmap4(xdrs, (b_bitmap4_t *)&objp->la_attr_req));
313 }
314 
315 bool_t
316 xdr_read4_args(XDR *xdrs, read4arg_t *objp)
317 {
318 	if (!xdr_b_compound_args(xdrs, (b_compound_t *)&objp->r_arg))
319 		return (FALSE);
320 	if (!xdr_u_int(xdrs, (uint_t *)&objp->r_opread))
321 		return (FALSE);
322 	if (!xdr_b_stateid4(xdrs, (stateid4 *)&objp->r_stateid))
323 		return (FALSE);
324 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->r_offset))
325 		return (FALSE);
326 	return (xdr_u_int(xdrs, (uint_t *)&objp->r_count));
327 }
328 
329 bool_t
330 xdr_read4_res(XDR *xdrs, read4res_t *objp)
331 {
332 	if (!xdr_b_compound_res(xdrs, (b_compound_t *)&objp->r_res))
333 		return (FALSE);
334 	if (!xdr_u_int(xdrs, (uint_t *)&objp->r_opread))
335 		return (FALSE);
336 	if (!xdr_enum(xdrs, (enum_t *)&objp->r_status))
337 		return (FALSE);
338 	if (objp->r_status == NFS4_OK) {
339 		if (!xdr_bool(xdrs, (bool_t *)&objp->r_eof))
340 			return (FALSE);
341 		return (xdr_bytes(xdrs, (char **)&objp->r_data_val,
342 					(uint_t *)&objp->r_data_len, ~0));
343 	}
344 	return (TRUE);
345 }
346 
347 bool_t
348 xdr_readdir4_args(XDR *xdrs, readdir4arg_t *objp)
349 {
350 	if (!xdr_b_compound_args(xdrs, (b_compound_t *)&objp->rd_arg))
351 		return (FALSE);
352 	if (!xdr_u_int(xdrs, (uint_t *)&objp->rd_opreaddir))
353 		return (FALSE);
354 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->rd_cookie))
355 		return (FALSE);
356 	if (!xdr_opaque(xdrs, objp->rd_cookieverf, NFS4_VERIFIER_SIZE))
357 		return (FALSE);
358 	if (!xdr_u_int(xdrs, (uint_t *)&objp->rd_dircount))
359 		return (FALSE);
360 	if (!xdr_u_int(xdrs, (uint_t *)&objp->rd_maxcount))
361 		return (FALSE);
362 	return (xdr_b_bitmap4(xdrs, (b_bitmap4_t *)&objp->rd_attr_req));
363 }
364 
365 static bool_t
366 xdr_b_entry4(XDR *xdrs, b_entry4_t *objp)
367 {
368 	uint_t		attrlen;
369 	char		attrvals[sizeof (b_fattr4_t)];
370 	char		*ap = attrvals;
371 	XDR		mxdrs;
372 
373 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->b_cookie))
374 		return (FALSE);
375 	if (!xdr_b_utf8string(xdrs, &objp->b_name))
376 		return (FALSE);
377 
378 	bzero(&attrvals, sizeof (attrvals));
379 	if (!xdr_bytes(xdrs, (char **)&ap, (uint_t *)&attrlen,
380 			sizeof (b_fattr4_t)))
381 		return (FALSE);
382 
383 	/*
384 	 * We are *only* interested in the fileid, so just extract that.
385 	 */
386 	if (attrlen < sizeof (uint64_t))
387 		return (FALSE);
388 
389 	xdrmem_create(&mxdrs, ap, attrlen, XDR_DECODE);
390 
391 	if (!xdr_u_longlong_t(&mxdrs, (u_longlong_t *)&objp->b_fileid))
392 		return (FALSE);
393 	return (xdr_pointer(xdrs, (char **)&objp->b_nextentry,
394 			sizeof (b_entry4_t), (xdrproc_t)xdr_b_entry4));
395 }
396 
397 bool_t
398 xdr_readdir4_res(XDR *xdrs, readdir4res_t *objp)
399 {
400 	if (!xdr_b_compound_res(xdrs, (b_compound_t *)&objp->rd_res))
401 		return (FALSE);
402 	if (!xdr_u_int(xdrs, (uint_t *)&objp->rd_opreaddir))
403 		return (FALSE);
404 	if (!xdr_enum(xdrs, (enum_t *)&objp->rd_status))
405 		return (FALSE);
406 	if (objp->rd_status == NFS4_OK) {
407 		if (!xdr_opaque(xdrs, objp->rd_cookieverf, NFS4_VERIFIER_SIZE))
408 			return (FALSE);
409 		if (!xdr_pointer(xdrs, (char **)&objp->rd_entries,
410 				sizeof (b_entry4_t), (xdrproc_t)xdr_b_entry4))
411 			return (FALSE);
412 		return (xdr_bool(xdrs, &objp->rd_eof));
413 	}
414 	return (TRUE);
415 }
416 
417 bool_t
418 xdr_readlink4_args(XDR *xdrs, readlink4arg_t *objp)
419 {
420 	if (!xdr_b_compound_args(xdrs, (b_compound_t *)&objp->rl_arg))
421 		return (FALSE);
422 	return (xdr_u_int(xdrs, (uint_t *)&objp->rl_opreadlink));
423 }
424 
425 bool_t
426 xdr_readlink4_res(XDR *xdrs, readlink4res_t *objp)
427 {
428 	if (!xdr_b_compound_res(xdrs, (b_compound_t *)&objp->rl_res))
429 		return (FALSE);
430 	if (!xdr_u_int(xdrs, (uint_t *)&objp->rl_opreadlink))
431 		return (FALSE);
432 	if (!xdr_enum(xdrs, (enum_t *)&objp->rl_status))
433 		return (FALSE);
434 	if (objp->rl_status == NFS4_OK)
435 		return (xdr_b_utf8string(xdrs, (utf8string *)&objp->rl_link));
436 	return (TRUE);
437 }
438