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