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