Home | History | Annotate | Download | only in nfs
      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 (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     27 
     28 #include <sys/types.h>
     29 #include <sys/systm.h>
     30 #include <sys/cmn_err.h>
     31 #include <sys/kmem.h>
     32 #include <sys/cred.h>
     33 #include <sys/dirent.h>
     34 #include <rpc/types.h>
     35 #include <nfs/nfs.h>
     36 #include <nfs/export.h>
     37 #include <rpc/svc.h>
     38 #include <rpc/xdr.h>
     39 #include <rpc/rpcb_prot.h>
     40 #include <rpc/clnt.h>
     41 #include <nfs/nfs_log.h>
     42 
     43 /*
     44  * nfsl_principal_name_get - extracts principal from transport struct.
     45  * Based on "uts/common/rpc/sec/sec_svc.c" function sec_svc_getcred.
     46  */
     47 static char *
     48 nfsl_principal_name_get(struct svc_req *req)
     49 {
     50 	char				*principal_name = NULL;
     51 	struct authdes_cred		*adc;
     52 	rpc_gss_rawcred_t		*rcred;
     53 	rpc_gss_ucred_t			*ucred;
     54 	void				*cookie;
     55 
     56 	switch (req->rq_cred.oa_flavor) {
     57 	case AUTH_UNIX:
     58 	case AUTH_NONE:
     59 		/* no principal name provided */
     60 		break;
     61 
     62 	case AUTH_DES:
     63 		adc = (struct authdes_cred *)req->rq_clntcred;
     64 		principal_name = adc->adc_fullname.name;
     65 		break;
     66 
     67 	case RPCSEC_GSS:
     68 		(void) rpc_gss_getcred(req, &rcred, &ucred, &cookie);
     69 		principal_name = (caddr_t)rcred->client_principal;
     70 		break;
     71 
     72 	default:
     73 		break;
     74 	}
     75 	return (principal_name);
     76 }
     77 
     78 bool_t
     79 xdr_timestruc32_t(XDR *xdrs, timestruc32_t *objp)
     80 {
     81 	if (!xdr_int(xdrs, &objp->tv_sec))
     82 		return (FALSE);
     83 	return (xdr_int(xdrs, &objp->tv_nsec));
     84 }
     85 
     86 bool_t
     87 xdr_nfsstat(XDR *xdrs, nfsstat *objp)
     88 {
     89 	return (xdr_enum(xdrs, (enum_t *)objp));
     90 }
     91 
     92 bool_t
     93 xdr_nfslog_sharefsres(XDR *xdrs, nfslog_sharefsres *objp)
     94 {
     95 	return (xdr_nfsstat(xdrs, objp));
     96 }
     97 
     98 bool_t
     99 xdr_nfsreadargs(XDR *xdrs, struct nfsreadargs *ra)
    100 {
    101 	if (xdr_fhandle(xdrs, &ra->ra_fhandle) &&
    102 	    xdr_u_int(xdrs, &ra->ra_offset) &&
    103 	    xdr_u_int(xdrs, &ra->ra_count) &&
    104 	    xdr_u_int(xdrs, &ra->ra_totcount)) {
    105 		return (TRUE);
    106 	}
    107 	return (FALSE);
    108 }
    109 
    110 bool_t
    111 xdr_nfslog_nfsreadargs(xdrs, objp)
    112 	register XDR *xdrs;
    113 	nfslog_nfsreadargs *objp;
    114 {
    115 	return (xdr_nfsreadargs(xdrs, objp));
    116 }
    117 
    118 /*
    119  * Current version (2 and up) xdr function for buffer header
    120  * uses 64-bit offset (relocated to an 8 byte boundary), version 1 uses 32.
    121  */
    122 bool_t
    123 xdr_nfslog_buffer_header(xdrs, objp)
    124 	register XDR *xdrs;
    125 	nfslog_buffer_header *objp;
    126 {
    127 	if (!xdr_u_int(xdrs, &objp->bh_length))
    128 		return (FALSE);
    129 	if (!xdr_rpcvers(xdrs, &objp->bh_version))
    130 		return (FALSE);
    131 	ASSERT(objp->bh_version > 1);
    132 	if (!xdr_u_longlong_t(xdrs, &objp->bh_offset))
    133 		return (FALSE);
    134 	if (!xdr_u_int(xdrs, &objp->bh_flags))
    135 		return (FALSE);
    136 	return (xdr_timestruc32_t(xdrs, &objp->bh_timestamp));
    137 }
    138 
    139 /*
    140  * Hand coded xdr functions for the kernel ENCODE path
    141  */
    142 
    143 bool_t
    144 xdr_nfslog_request_record(
    145 	XDR *xdrs,
    146 	struct exportinfo *exi,
    147 	struct svc_req *req,
    148 	cred_t *cr,
    149 	struct netbuf *pnb,
    150 	unsigned int	reclen,
    151 	unsigned int	record_id)
    152 {
    153 	char *netid = NULL;
    154 	char *prin = NULL;
    155 	unsigned int flavor;
    156 	timestruc32_t ts;
    157 	timestruc_t now;
    158 	uid_t ruid;
    159 	gid_t rgid;
    160 
    161 	if (xdrs->x_op != XDR_ENCODE)
    162 		return (FALSE);
    163 
    164 	/*
    165 	 * First we do the encoding of the record header
    166 	 */
    167 	if (!xdr_u_int(xdrs, &reclen))
    168 		return (FALSE);
    169 	if (!xdr_u_int(xdrs, &record_id))
    170 		return (FALSE);
    171 	if (!xdr_rpcprog(xdrs, &req->rq_prog))
    172 		return (FALSE);
    173 	if (!xdr_rpcproc(xdrs, &req->rq_proc))
    174 		return (FALSE);
    175 	if (!xdr_rpcvers(xdrs, &req->rq_vers))
    176 		return (FALSE);
    177 	flavor = req->rq_cred.oa_flavor;
    178 	if (!xdr_u_int(xdrs, &flavor))
    179 		return (FALSE);
    180 
    181 	gethrestime(&now);
    182 	TIMESPEC_TO_TIMESPEC32(&ts, &now);
    183 	if (!xdr_timestruc32_t(xdrs, &ts))
    184 		return (FALSE);
    185 
    186 	/* This code depends on us doing XDR_ENCODE ops only */
    187 	ruid = crgetruid(cr);
    188 	if (!xdr_uid_t(xdrs, &ruid))
    189 		return (FALSE);
    190 	rgid = crgetrgid(cr);
    191 	if (!xdr_gid_t(xdrs, &rgid))
    192 		return (FALSE);
    193 
    194 	/*
    195 	 * Now encode the rest of the request record (but not args/res)
    196 	 */
    197 	prin = nfsl_principal_name_get(req);
    198 	if (!xdr_string(xdrs, &prin, ~0))
    199 		return (FALSE);
    200 	if (req->rq_xprt)
    201 		netid = svc_getnetid(req->rq_xprt);
    202 	if (!xdr_string(xdrs, &netid, ~0))
    203 		return (FALSE);
    204 	if (!xdr_string(xdrs, &exi->exi_export.ex_tag, ~0))
    205 		return (FALSE);
    206 	return (xdr_netbuf(xdrs, pnb));
    207 }
    208 
    209 bool_t
    210 xdr_nfslog_sharefsargs(XDR *xdrs, struct exportinfo *objp)
    211 {
    212 
    213 	if (xdrs->x_op != XDR_ENCODE)
    214 		return (FALSE);
    215 
    216 	if (!xdr_int(xdrs, &objp->exi_export.ex_flags))
    217 		return (FALSE);
    218 	if (!xdr_u_int(xdrs, &objp->exi_export.ex_anon))
    219 		return (FALSE);
    220 	if (!xdr_string(xdrs, &objp->exi_export.ex_path, ~0))
    221 		return (FALSE);
    222 	return (xdr_fhandle(xdrs, &objp->exi_fh));
    223 }
    224 
    225 bool_t
    226 xdr_nfslog_getfhargs(XDR *xdrs, nfslog_getfhargs *objp)
    227 {
    228 	if (!xdr_fhandle(xdrs, &objp->gfh_fh_buf))
    229 		return (FALSE);
    230 	return (xdr_string(xdrs, &objp->gfh_path, ~0));
    231 }
    232 
    233 bool_t
    234 xdr_nfslog_drok(XDR *xdrs, struct nfsdrok *objp)
    235 {
    236 	return (xdr_fhandle(xdrs, &objp->drok_fhandle));
    237 }
    238 
    239 bool_t
    240 xdr_nfslog_diropres(XDR *xdrs, struct nfsdiropres *objp)
    241 {
    242 	if (!xdr_nfsstat(xdrs, &objp->dr_status))
    243 		return (FALSE);
    244 	switch (objp->dr_status) {
    245 	case NFS_OK:
    246 		if (!xdr_nfslog_drok(xdrs, &objp->dr_drok))
    247 			return (FALSE);
    248 		break;
    249 	}
    250 	return (TRUE);
    251 }
    252 
    253 bool_t
    254 xdr_nfslog_getattrres(XDR *xdrs, struct nfsattrstat *objp)
    255 {
    256 	return (xdr_nfsstat(xdrs, &objp->ns_status));
    257 }
    258 
    259 bool_t
    260 xdr_nfslog_rrok(XDR *xdrs, struct nfsrrok *objp)
    261 {
    262 	if (!xdr_u_int(xdrs, &objp->rrok_attr.na_size))
    263 		return (FALSE);
    264 	return (xdr_u_int(xdrs, &objp->rrok_count));
    265 }
    266 
    267 bool_t
    268 xdr_nfslog_rdresult(XDR *xdrs, struct nfsrdresult *objp)
    269 {
    270 	if (!xdr_nfsstat(xdrs, &objp->rr_status))
    271 		return (FALSE);
    272 	switch (objp->rr_status) {
    273 	case NFS_OK:
    274 		if (!xdr_nfslog_rrok(xdrs, &objp->rr_u.rr_ok_u))
    275 			return (FALSE);
    276 		break;
    277 	}
    278 	return (TRUE);
    279 }
    280 
    281 bool_t
    282 xdr_nfslog_writeargs(XDR *xdrs, struct nfswriteargs *objp)
    283 {
    284 	if (!xdr_fhandle(xdrs, &objp->wa_args->otw_wa_fhandle))
    285 		return (FALSE);
    286 	if (!xdr_u_int(xdrs, &objp->wa_args->otw_wa_begoff))
    287 		return (FALSE);
    288 	if (!xdr_u_int(xdrs, &objp->wa_args->otw_wa_offset))
    289 		return (FALSE);
    290 	if (!xdr_u_int(xdrs, &objp->wa_args->otw_wa_totcount))
    291 		return (FALSE);
    292 	return (xdr_u_int(xdrs, &objp->wa_count));
    293 }
    294 
    295 bool_t
    296 xdr_nfslog_writeresult(XDR *xdrs, struct nfsattrstat *objp)
    297 {
    298 	if (!xdr_nfsstat(xdrs, &objp->ns_status))
    299 		return (FALSE);
    300 	switch (objp->ns_status) {
    301 	case NFS_OK:
    302 		if (!xdr_u_int(xdrs, &objp->ns_u.ns_attr_u.na_size))
    303 			return (FALSE);
    304 		break;
    305 	}
    306 	return (TRUE);
    307 }
    308 
    309 bool_t
    310 xdr_nfslog_diropargs(XDR *xdrs, struct nfsdiropargs *objp)
    311 {
    312 	if (!xdr_fhandle(xdrs, objp->da_fhandle))
    313 		return (FALSE);
    314 	return (xdr_string(xdrs, &objp->da_name, ~0));
    315 }
    316 
    317 bool_t
    318 xdr_nfslog_sattr(XDR *xdrs, struct nfssattr *objp)
    319 {
    320 	if (!xdr_u_int(xdrs, &objp->sa_mode))
    321 		return (FALSE);
    322 	if (!xdr_u_int(xdrs, &objp->sa_uid))
    323 		return (FALSE);
    324 	if (!xdr_u_int(xdrs, &objp->sa_gid))
    325 		return (FALSE);
    326 	if (!xdr_u_int(xdrs, &objp->sa_size))
    327 		return (FALSE);
    328 	if (!xdr_nfs2_timeval(xdrs, (nfs2_timeval *)&objp->sa_atime))
    329 		return (FALSE);
    330 	return (xdr_nfs2_timeval(xdrs, (nfs2_timeval *)&objp->sa_mtime));
    331 }
    332 
    333 bool_t
    334 xdr_nfslog_createargs(XDR *xdrs, struct nfscreatargs *objp)
    335 {
    336 	if (!xdr_nfslog_sattr(xdrs, objp->ca_sa))
    337 		return (FALSE);
    338 	return (xdr_nfslog_diropargs(xdrs, &objp->ca_da));
    339 }
    340 
    341 bool_t
    342 xdr_nfslog_setattrargs(XDR *xdrs, struct nfssaargs *objp)
    343 {
    344 	if (!xdr_fhandle(xdrs, &objp->saa_fh))
    345 		return (FALSE);
    346 	return (xdr_nfslog_sattr(xdrs, &objp->saa_sa));
    347 }
    348 
    349 bool_t
    350 xdr_nfslog_rdlnres(XDR *xdrs, struct nfsrdlnres *objp)
    351 {
    352 	caddr_t	lnres = NULL;
    353 	int count;
    354 
    355 	if (!xdr_nfsstat(xdrs, &objp->rl_status))
    356 		return (FALSE);
    357 	switch (objp->rl_status) {
    358 	case NFS_OK:
    359 		if ((count = objp->rl_u.rl_srok_u.srok_count) != 0) {
    360 			/*
    361 			 * allocate extra element for terminating NULL
    362 			 */
    363 			lnres = kmem_alloc(count + 1, KM_SLEEP);
    364 			bcopy(objp->rl_u.rl_srok_u.srok_data, lnres, count);
    365 			lnres[count] = '\0';
    366 		}
    367 		if (!xdr_string(xdrs, &lnres, ~0)) {
    368 			if (lnres != NULL)
    369 				kmem_free(lnres, count + 1);
    370 			return (FALSE);
    371 		}
    372 		if (lnres != NULL)
    373 			kmem_free(lnres, count + 1);
    374 		break;
    375 	}
    376 	return (TRUE);
    377 }
    378 
    379 bool_t
    380 xdr_nfslog_rnmargs(XDR *xdrs, struct nfsrnmargs *objp)
    381 {
    382 	if (!xdr_nfslog_diropargs(xdrs, &objp->rna_from))
    383 		return (FALSE);
    384 	return (xdr_nfslog_diropargs(xdrs, &objp->rna_to));
    385 }
    386 
    387 bool_t
    388 xdr_nfslog_linkargs(XDR *xdrs, struct nfslinkargs *objp)
    389 {
    390 	if (!xdr_fhandle(xdrs, objp->la_from))
    391 		return (FALSE);
    392 	return (xdr_nfslog_diropargs(xdrs, &objp->la_to));
    393 }
    394 
    395 bool_t
    396 xdr_nfslog_symlinkargs(XDR *xdrs, struct nfsslargs *objp)
    397 {
    398 	if (!xdr_nfslog_diropargs(xdrs, &objp->sla_from))
    399 		return (FALSE);
    400 	if (!xdr_string(xdrs, &objp->sla_tnm, ~0))
    401 		return (FALSE);
    402 	return (xdr_nfslog_sattr(xdrs, objp->sla_sa));
    403 }
    404 
    405 bool_t
    406 xdr_nfslog_statfs(XDR *xdrs, struct nfsstatfs *objp)
    407 {
    408 	return (xdr_nfsstat(xdrs, &objp->fs_status));
    409 }
    410 
    411 bool_t
    412 xdr_nfslog_rddirargs(XDR *xdrs, struct nfsrddirargs *objp)
    413 {
    414 	if (!xdr_fhandle(xdrs, &objp->rda_fh))
    415 		return (FALSE);
    416 	if (!xdr_u_int(xdrs, &objp->rda_offset))
    417 		return (FALSE);
    418 	return (xdr_u_int(xdrs, &objp->rda_count));
    419 }
    420 
    421 bool_t
    422 xdr_nfslog_rdok(XDR *xdrs, struct nfsrdok *objp)
    423 {
    424 	if (!xdr_u_int(xdrs, &objp->rdok_offset))
    425 		return (FALSE);
    426 	if (!xdr_u_int(xdrs, &objp->rdok_size))
    427 		return (FALSE);
    428 	return (xdr_bool(xdrs, &objp->rdok_eof));
    429 }
    430 
    431 bool_t
    432 xdr_nfslog_rddirres(XDR *xdrs, struct nfsrddirres *objp)
    433 {
    434 	if (!xdr_nfsstat(xdrs, &objp->rd_status))
    435 		return (FALSE);
    436 	switch (objp->rd_status) {
    437 	case NFS_OK:
    438 		if (!xdr_nfslog_rdok(xdrs, &objp->rd_u.rd_rdok_u))
    439 			return (FALSE);
    440 		break;
    441 	}
    442 	return (TRUE);
    443 }
    444 
    445 bool_t
    446 xdr_nfslog_diropargs3(XDR *xdrs, diropargs3 *objp)
    447 {
    448 	char *name;
    449 
    450 	if (!xdr_nfslog_nfs_fh3(xdrs, &objp->dir))
    451 		return (FALSE);
    452 	if (objp->name != nfs3nametoolong)
    453 		name = objp->name;
    454 	else {
    455 		/*
    456 		 * The name is not defined, set it to the
    457 		 * zero length string.
    458 		 */
    459 		name = NULL;
    460 	}
    461 	return (xdr_string(xdrs, &name, ~0));
    462 }
    463 
    464 bool_t
    465 xdr_nfslog_LOOKUP3res(XDR *xdrs, LOOKUP3res *objp)
    466 {
    467 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
    468 		return (FALSE);
    469 	switch (objp->status) {
    470 	case NFS3_OK:
    471 		if (!xdr_nfslog_nfs_fh3(xdrs, &objp->res_u.ok.object))
    472 			return (FALSE);
    473 		break;
    474 	}
    475 	return (TRUE);
    476 }
    477 
    478 bool_t
    479 xdr_set_size3(XDR *xdrs, set_size3 *objp)
    480 {
    481 	if (!xdr_bool(xdrs, &objp->set_it))
    482 		return (FALSE);
    483 	switch (objp->set_it) {
    484 	case TRUE:
    485 		if (!xdr_uint64(xdrs, &objp->size))
    486 			return (FALSE);
    487 		break;
    488 	}
    489 	return (TRUE);
    490 }
    491 
    492 bool_t
    493 xdr_nfslog_createhow3(XDR *xdrs, createhow3 *objp)
    494 {
    495 	if (!xdr_enum(xdrs, (enum_t *)&objp->mode))
    496 		return (FALSE);
    497 	switch (objp->mode) {
    498 	case UNCHECKED:
    499 	case GUARDED:
    500 		if (!xdr_set_size3(xdrs,
    501 			&objp->createhow3_u.obj_attributes.size))
    502 			return (FALSE);
    503 		break;
    504 	case EXCLUSIVE:
    505 		break;
    506 	default:
    507 		return (FALSE);
    508 	}
    509 	return (TRUE);
    510 }
    511 
    512 bool_t
    513 xdr_nfslog_CREATE3args(XDR *xdrs, CREATE3args *objp)
    514 {
    515 	if (!xdr_nfslog_diropargs3(xdrs, &objp->where))
    516 		return (FALSE);
    517 	return (xdr_nfslog_createhow3(xdrs, &objp->how));
    518 }
    519 
    520 bool_t
    521 xdr_nfslog_CREATE3resok(XDR *xdrs, CREATE3resok *objp)
    522 {
    523 	return (xdr_post_op_fh3(xdrs, &objp->obj));
    524 }
    525 
    526 bool_t
    527 xdr_nfslog_CREATE3res(XDR *xdrs, CREATE3res *objp)
    528 {
    529 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
    530 		return (FALSE);
    531 	switch (objp->status) {
    532 	case NFS3_OK:
    533 		if (!xdr_nfslog_CREATE3resok(xdrs, &objp->res_u.ok))
    534 			return (FALSE);
    535 		break;
    536 	}
    537 	return (TRUE);
    538 }
    539 
    540 bool_t
    541 xdr_nfslog_GETATTR3res(XDR *xdrs, GETATTR3res *objp)
    542 {
    543 	return (xdr_enum(xdrs, (enum_t *)&objp->status));
    544 }
    545 
    546 bool_t
    547 xdr_nfslog_ACCESS3args(XDR *xdrs, ACCESS3args *objp)
    548 {
    549 	return (xdr_nfslog_nfs_fh3(xdrs, &objp->object));
    550 }
    551 
    552 bool_t
    553 xdr_nfslog_ACCESS3res(XDR *xdrs, ACCESS3res *objp)
    554 {
    555 	return (xdr_enum(xdrs, (enum_t *)&objp->status));
    556 }
    557 
    558 bool_t
    559 xdr_nfslog_SETATTR3args(XDR *xdrs, SETATTR3args *objp)
    560 {
    561 	if (!xdr_nfslog_nfs_fh3(xdrs, &objp->object))
    562 		return (FALSE);
    563 	return (xdr_set_size3(xdrs, &objp->new_attributes.size));
    564 }
    565 
    566 bool_t
    567 xdr_nfslog_SETATTR3res(XDR *xdrs, SETATTR3res *objp)
    568 {
    569 	return (xdr_enum(xdrs, (enum_t *)&objp->status));
    570 }
    571 
    572 bool_t
    573 xdr_nfslog_READLINK3res(XDR *xdrs, READLINK3res *objp)
    574 {
    575 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
    576 		return (FALSE);
    577 	switch (objp->status) {
    578 	case NFS3_OK:
    579 		if (!xdr_string(xdrs, &objp->res_u.ok.data, ~0))
    580 			return (FALSE);
    581 		break;
    582 	}
    583 	return (TRUE);
    584 }
    585 
    586 bool_t
    587 xdr_nfslog_READ3args(XDR *xdrs, READ3args *objp)
    588 {
    589 	if (!xdr_nfslog_nfs_fh3(xdrs, &objp->file))
    590 		return (FALSE);
    591 	if (!xdr_uint64(xdrs, &objp->offset))
    592 		return (FALSE);
    593 	return (xdr_uint32(xdrs, &objp->count));
    594 }
    595 
    596 bool_t
    597 xdr_nfslog_READ3resok(XDR *xdrs, READ3resok *objp)
    598 {
    599 	if (!xdr_uint64(xdrs, &objp->file_attributes.attr.size))
    600 		return (FALSE);
    601 	if (!xdr_uint32(xdrs, &objp->count))
    602 		return (FALSE);
    603 	if (!xdr_bool(xdrs, &objp->eof))
    604 		return (FALSE);
    605 	return (xdr_u_int(xdrs, &objp->size));
    606 }
    607 
    608 bool_t
    609 xdr_nfslog_READ3res(XDR *xdrs, READ3res *objp)
    610 {
    611 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
    612 		return (FALSE);
    613 	switch (objp->status) {
    614 	case NFS3_OK:
    615 		if (!xdr_nfslog_READ3resok(xdrs, &objp->res_u.ok))
    616 			return (FALSE);
    617 		break;
    618 	}
    619 	return (TRUE);
    620 }
    621 
    622 bool_t
    623 xdr_nfslog_WRITE3args(XDR *xdrs, WRITE3args *objp)
    624 {
    625 	if (!xdr_nfslog_nfs_fh3(xdrs, &objp->file))
    626 		return (FALSE);
    627 	if (!xdr_uint64(xdrs, &objp->offset))
    628 		return (FALSE);
    629 	if (!xdr_uint32(xdrs, &objp->count))
    630 		return (FALSE);
    631 	return (xdr_enum(xdrs, (enum_t *)&objp->stable));
    632 }
    633 
    634 bool_t
    635 xdr_nfslog_WRITE3resok(XDR *xdrs, WRITE3resok *objp)
    636 {
    637 	if (!xdr_uint64(xdrs, &objp->file_wcc.after.attr.size))
    638 		return (FALSE);
    639 	if (!xdr_uint32(xdrs, &objp->count))
    640 		return (FALSE);
    641 	return (xdr_enum(xdrs, (enum_t *)&objp->committed));
    642 }
    643 
    644 bool_t
    645 xdr_nfslog_WRITE3res(XDR *xdrs, WRITE3res *objp)
    646 {
    647 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
    648 		return (FALSE);
    649 	switch (objp->status) {
    650 	case NFS3_OK:
    651 		if (!xdr_nfslog_WRITE3resok(xdrs, &objp->res_u.ok))
    652 			return (FALSE);
    653 		break;
    654 	}
    655 	return (TRUE);
    656 }
    657 
    658 bool_t
    659 xdr_nfslog_MKDIR3args(XDR *xdrs, MKDIR3args *objp)
    660 {
    661 	return (xdr_nfslog_diropargs3(xdrs, &objp->where));
    662 }
    663 
    664 bool_t
    665 xdr_nfslog_MKDIR3res(XDR *xdrs, MKDIR3res *objp)
    666 {
    667 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
    668 		return (FALSE);
    669 	switch (objp->status) {
    670 	case NFS3_OK:
    671 		if (!xdr_post_op_fh3(xdrs, &objp->res_u.ok.obj))
    672 			return (FALSE);
    673 		break;
    674 	}
    675 	return (TRUE);
    676 }
    677 
    678 bool_t
    679 xdr_nfslog_SYMLINK3args(XDR *xdrs, SYMLINK3args *objp)
    680 {
    681 	if (!xdr_nfslog_diropargs3(xdrs, &objp->where))
    682 		return (FALSE);
    683 	return (xdr_string(xdrs, &objp->symlink.symlink_data, ~0));
    684 }
    685 
    686 bool_t
    687 xdr_nfslog_SYMLINK3res(XDR *xdrs, SYMLINK3res *objp)
    688 {
    689 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
    690 		return (FALSE);
    691 	switch (objp->status) {
    692 	case NFS3_OK:
    693 		if (!xdr_post_op_fh3(xdrs, &objp->res_u.ok.obj))
    694 			return (FALSE);
    695 		break;
    696 	}
    697 	return (TRUE);
    698 }
    699 
    700 bool_t
    701 xdr_nfslog_MKNOD3args(XDR *xdrs, MKNOD3args *objp)
    702 {
    703 	if (!xdr_nfslog_diropargs3(xdrs, &objp->where))
    704 		return (FALSE);
    705 	return (xdr_enum(xdrs, (enum_t *)&objp->what.type));
    706 }
    707 
    708 bool_t
    709 xdr_nfslog_MKNOD3res(XDR *xdrs, MKNOD3res *objp)
    710 {
    711 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
    712 		return (FALSE);
    713 	switch (objp->status) {
    714 	case NFS3_OK:
    715 		if (!xdr_post_op_fh3(xdrs, &objp->res_u.ok.obj))
    716 			return (FALSE);
    717 		break;
    718 	}
    719 	return (TRUE);
    720 }
    721 
    722 bool_t
    723 xdr_nfslog_REMOVE3args(XDR *xdrs, REMOVE3args *objp)
    724 {
    725 	return (xdr_nfslog_diropargs3(xdrs, &objp->object));
    726 }
    727 
    728 bool_t
    729 xdr_nfslog_REMOVE3res(XDR *xdrs, REMOVE3res *objp)
    730 {
    731 	return (xdr_enum(xdrs, (enum_t *)&objp->status));
    732 }
    733 
    734 bool_t
    735 xdr_nfslog_RMDIR3args(XDR *xdrs, RMDIR3args *objp)
    736 {
    737 	return (xdr_nfslog_diropargs3(xdrs, &objp->object));
    738 }
    739 
    740 bool_t
    741 xdr_nfslog_RMDIR3res(XDR *xdrs, RMDIR3res *objp)
    742 {
    743 	return (xdr_enum(xdrs, (enum_t *)&objp->status));
    744 }
    745 
    746 bool_t
    747 xdr_nfslog_RENAME3args(XDR *xdrs, RENAME3args *objp)
    748 {
    749 	if (!xdr_nfslog_diropargs3(xdrs, &objp->from))
    750 		return (FALSE);
    751 	return (xdr_nfslog_diropargs3(xdrs, &objp->to));
    752 }
    753 
    754 bool_t
    755 xdr_nfslog_RENAME3res(XDR *xdrs, RENAME3res *objp)
    756 {
    757 	return (xdr_enum(xdrs, (enum_t *)&objp->status));
    758 }
    759 
    760 bool_t
    761 xdr_nfslog_LINK3args(XDR *xdrs, LINK3args *objp)
    762 {
    763 	if (!xdr_nfslog_nfs_fh3(xdrs, &objp->file))
    764 		return (FALSE);
    765 	return (xdr_nfslog_diropargs3(xdrs, &objp->link));
    766 }
    767 
    768 bool_t
    769 xdr_nfslog_LINK3res(XDR *xdrs, LINK3res *objp)
    770 {
    771 	return (xdr_enum(xdrs, (enum_t *)&objp->status));
    772 }
    773 
    774 bool_t
    775 xdr_nfslog_READDIR3args(XDR *xdrs, READDIR3args *objp)
    776 {
    777 	return (xdr_nfslog_nfs_fh3(xdrs, &objp->dir));
    778 }
    779 
    780 bool_t
    781 xdr_nfslog_READDIR3res(XDR *xdrs, READDIR3res *objp)
    782 {
    783 	return (xdr_enum(xdrs, (enum_t *)&objp->status));
    784 }
    785 
    786 bool_t
    787 xdr_nfslog_READDIRPLUS3args(XDR *xdrs, READDIRPLUS3args *objp)
    788 {
    789 	if (!xdr_nfslog_nfs_fh3(xdrs, &objp->dir))
    790 		return (FALSE);
    791 	if (!xdr_uint32(xdrs, &objp->dircount))
    792 		return (FALSE);
    793 	return (xdr_uint32(xdrs, &objp->maxcount));
    794 }
    795 
    796 #ifdef	nextdp
    797 #undef	nextdp
    798 #endif
    799 #define	nextdp(dp)	((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
    800 
    801 bool_t
    802 xdr_nfslog_READDIRPLUS3resok(XDR *xdrs, READDIRPLUS3resok *objp)
    803 {
    804 	struct dirent64 *dp;
    805 	bool_t true = TRUE;
    806 	bool_t false = FALSE;
    807 	int nents;
    808 	char *name;
    809 	entryplus3_info *infop;
    810 
    811 	dp = (struct dirent64 *)objp->reply.entries;
    812 	nents = objp->size;
    813 	infop = objp->infop;
    814 	while (nents > 0) {
    815 		if (dp->d_reclen == 0)
    816 			return (FALSE);
    817 		if (dp->d_ino == 0) {
    818 			dp = nextdp(dp);
    819 			infop++;
    820 			nents--;
    821 			continue;
    822 		}
    823 		name = dp->d_name;
    824 
    825 		if (!xdr_bool(xdrs, &true) ||
    826 		    !xdr_post_op_fh3(xdrs, &infop->fh) ||
    827 		    !xdr_string(xdrs, &name, ~0)) {
    828 			return (FALSE);
    829 		}
    830 		dp = nextdp(dp);
    831 		infop++;
    832 		nents--;
    833 	}
    834 	if (!xdr_bool(xdrs, &false))
    835 		return (FALSE);
    836 
    837 	return (xdr_bool(xdrs, &objp->reply.eof));
    838 }
    839 
    840 bool_t
    841 xdr_nfslog_READDIRPLUS3res(XDR *xdrs, READDIRPLUS3res *objp)
    842 {
    843 	if (!xdr_enum(xdrs, (enum_t *)&objp->status))
    844 		return (FALSE);
    845 	switch (objp->status) {
    846 	case NFS3_OK:
    847 		if (!xdr_nfslog_READDIRPLUS3resok(xdrs, &objp->res_u.ok))
    848 			return (FALSE);
    849 		break;
    850 	}
    851 	return (TRUE);
    852 }
    853 
    854 bool_t
    855 xdr_nfslog_FSSTAT3args(XDR *xdrs, FSSTAT3args *objp)
    856 {
    857 	return (xdr_nfslog_nfs_fh3(xdrs, &objp->fsroot));
    858 }
    859 
    860 bool_t
    861 xdr_nfslog_FSSTAT3res(XDR *xdrs, FSSTAT3res *objp)
    862 {
    863 	return (xdr_enum(xdrs, (enum_t *)&objp->status));
    864 }
    865 
    866 bool_t
    867 xdr_nfslog_FSINFO3args(XDR *xdrs, FSINFO3args *objp)
    868 {
    869 	return (xdr_nfslog_nfs_fh3(xdrs, &objp->fsroot));
    870 }
    871 
    872 bool_t
    873 xdr_nfslog_FSINFO3res(XDR *xdrs, FSINFO3res *objp)
    874 {
    875 	return (xdr_enum(xdrs, (enum_t *)&objp->status));
    876 }
    877 
    878 bool_t
    879 xdr_nfslog_PATHCONF3args(XDR *xdrs, PATHCONF3args *objp)
    880 {
    881 	return (xdr_nfslog_nfs_fh3(xdrs, &objp->object));
    882 }
    883 
    884 bool_t
    885 xdr_nfslog_PATHCONF3res(XDR *xdrs, PATHCONF3res *objp)
    886 {
    887 	return (xdr_enum(xdrs, (enum_t *)&objp->status));
    888 }
    889 
    890 bool_t
    891 xdr_nfslog_COMMIT3args(XDR *xdrs, COMMIT3args *objp)
    892 {
    893 	if (!xdr_nfslog_nfs_fh3(xdrs, &objp->file))
    894 		return (FALSE);
    895 	if (!xdr_uint64(xdrs, &objp->offset))
    896 		return (FALSE);
    897 	return (xdr_uint32(xdrs, &objp->count));
    898 }
    899 
    900 bool_t
    901 xdr_nfslog_COMMIT3res(XDR *xdrs, COMMIT3res *objp)
    902 {
    903 	return (xdr_enum(xdrs, (enum_t *)&objp->status));
    904 }
    905 
    906 bool_t
    907 xdr_nfslog_nfs_fh3(XDR *xdrs, nfs_fh3 *objp)
    908 {
    909 	nfs_fh3 fh;
    910 
    911 	if (objp->fh3_len > NFS_FHMAXDATA || objp->fh3_xlen > NFS_FHMAXDATA) {
    912 		fh = *objp;
    913 		fh.fh3_len = NFS_FHMAXDATA;
    914 		fh.fh3_xlen = NFS_FHMAXDATA;
    915 		fh.fh3_length = NFS3_OLDFHSIZE;
    916 		return (xdr_nfs_fh3_server(xdrs, &fh));
    917 	}
    918 	return (xdr_nfs_fh3_server(xdrs, objp));
    919 }
    920