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
xdr_b_utf8string(XDR * xdrs,utf8string * objp)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
xdr_nfs_bfh4(XDR * xdrs,struct nfs_bfh4 * objp)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
xdr_b_putfh4_args(XDR * xdrs,putfh4arg_t * objp)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
xdr_b_compound_args(XDR * xdrs,b_compound_t * objp)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
xdr_b_compound_res(XDR * xdrs,b_compound_t * objp)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
xdr_b_bitmap4(XDR * xdrs,b_bitmap4_t * objp)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
xdr_b_stateid4(XDR * xdrs,stateid4 * objp)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
xdr_getattr4_args(XDR * xdrs,getattr4arg_t * objp)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
xdr_b_getattr_res_common(XDR * xdrs,getattrres_cmn_t * objp)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
xdr_getattr4_res(XDR * xdrs,getattr4res_t * objp)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
xdr_lookup4_args(XDR * xdrs,lookup4arg_t * objp)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
xdr_lookup4_res(XDR * xdrs,lookup4res_t * objp)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
xdr_lookupp4_args(XDR * xdrs,lookupp4arg_t * objp)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
xdr_read4_args(XDR * xdrs,read4arg_t * objp)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
xdr_read4_res(XDR * xdrs,read4res_t * objp)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
xdr_readdir4_args(XDR * xdrs,readdir4arg_t * objp)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
xdr_b_entry4(XDR * xdrs,b_entry4_t * objp)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
xdr_readdir4_res(XDR * xdrs,readdir4res_t * objp)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
xdr_readlink4_args(XDR * xdrs,readlink4arg_t * objp)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
xdr_readlink4_res(XDR * xdrs,readlink4res_t * objp)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