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