17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0a701b1eSRobert Gordon  * Common Development and Distribution License (the "License").
6*0a701b1eSRobert Gordon  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*0a701b1eSRobert Gordon  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <rpc/types.h>
277c478bd9Sstevel@tonic-gate #include <rpc/xdr.h>
287c478bd9Sstevel@tonic-gate #include <sys/types.h>
29*0a701b1eSRobert Gordon #include <sys/sdt.h>
307c478bd9Sstevel@tonic-gate #include <rpc/auth.h>
317c478bd9Sstevel@tonic-gate #include <rpc/rpc_rdma.h>
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate struct private {
347c478bd9Sstevel@tonic-gate 	int	min_chunk;
357c478bd9Sstevel@tonic-gate 	uint_t	flags;			/* controls setting for rdma xdr */
367c478bd9Sstevel@tonic-gate 	int	num_chunk;
377c478bd9Sstevel@tonic-gate 	caddr_t	inline_buf;		/* temporary buffer for xdr inlining */
387c478bd9Sstevel@tonic-gate 	int	inline_len;		/* inline buffer length */
39*0a701b1eSRobert Gordon 	uint_t	xp_reply_chunk_len;
40*0a701b1eSRobert Gordon 	uint_t	xp_reply_chunk_len_alt;
417c478bd9Sstevel@tonic-gate };
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate /* ARGSUSED */
447c478bd9Sstevel@tonic-gate static bool_t
457c478bd9Sstevel@tonic-gate x_putint32_t(XDR *xdrs, int32_t *ip)
467c478bd9Sstevel@tonic-gate {
477c478bd9Sstevel@tonic-gate 	xdrs->x_handy += BYTES_PER_XDR_UNIT;
487c478bd9Sstevel@tonic-gate 	return (TRUE);
497c478bd9Sstevel@tonic-gate }
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate /* ARGSUSED */
527c478bd9Sstevel@tonic-gate static bool_t
537c478bd9Sstevel@tonic-gate x_putbytes(XDR *xdrs, char *bp, int len)
547c478bd9Sstevel@tonic-gate {
557c478bd9Sstevel@tonic-gate 	struct private *xdrp = (struct private *)xdrs->x_private;
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate 	/*
587c478bd9Sstevel@tonic-gate 	 * min_chunk = 0, means that the stream of bytes, to estimate size of,
597c478bd9Sstevel@tonic-gate 	 * contains no chunks to seperate out. See xdrrdma_putbytes()
607c478bd9Sstevel@tonic-gate 	 */
61*0a701b1eSRobert Gordon 	if (len < xdrp->min_chunk || !(xdrp->flags & XDR_RDMA_CHUNK)) {
627c478bd9Sstevel@tonic-gate 		xdrs->x_handy += len;
637c478bd9Sstevel@tonic-gate 		return (TRUE);
647c478bd9Sstevel@tonic-gate 	}
657c478bd9Sstevel@tonic-gate 	/*
667c478bd9Sstevel@tonic-gate 	 * Chunk item. No impact on xdr size.
677c478bd9Sstevel@tonic-gate 	 */
687c478bd9Sstevel@tonic-gate 	xdrp->num_chunk++;
69*0a701b1eSRobert Gordon 
707c478bd9Sstevel@tonic-gate 	return (TRUE);
717c478bd9Sstevel@tonic-gate }
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate static uint_t
747c478bd9Sstevel@tonic-gate x_getpostn(XDR *xdrs)
757c478bd9Sstevel@tonic-gate {
767c478bd9Sstevel@tonic-gate 	return (xdrs->x_handy);
777c478bd9Sstevel@tonic-gate }
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate /* ARGSUSED */
807c478bd9Sstevel@tonic-gate static bool_t
817c478bd9Sstevel@tonic-gate x_setpostn(XDR *xdrs, uint_t pos)
827c478bd9Sstevel@tonic-gate {
837c478bd9Sstevel@tonic-gate 	/* This is not allowed */
847c478bd9Sstevel@tonic-gate 	return (FALSE);
857c478bd9Sstevel@tonic-gate }
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate /* ARGSUSED */
887c478bd9Sstevel@tonic-gate static bool_t
897c478bd9Sstevel@tonic-gate x_control(XDR *xdrs, int request, void *info)
907c478bd9Sstevel@tonic-gate {
917c478bd9Sstevel@tonic-gate 	int32_t *int32p;
927c478bd9Sstevel@tonic-gate 	uint_t in_flags;
93*0a701b1eSRobert Gordon 	rdma_chunkinfo_t *rcip = NULL;
94*0a701b1eSRobert Gordon 	rdma_chunkinfo_lengths_t *rcilp = NULL;
957c478bd9Sstevel@tonic-gate 	struct private *xdrp = (struct private *)xdrs->x_private;
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate 	switch (request) {
98*0a701b1eSRobert Gordon 	case XDR_RDMA_SET_FLAGS:
997c478bd9Sstevel@tonic-gate 		/*
1007c478bd9Sstevel@tonic-gate 		 * Set the flags provided in the *info in xp_flags for rdma xdr
1017c478bd9Sstevel@tonic-gate 		 * stream control.
1027c478bd9Sstevel@tonic-gate 		 */
1037c478bd9Sstevel@tonic-gate 		int32p = (int32_t *)info;
1047c478bd9Sstevel@tonic-gate 		in_flags = (uint_t)(*int32p);
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 		xdrp->flags = in_flags;
1077c478bd9Sstevel@tonic-gate 		return (TRUE);
1087c478bd9Sstevel@tonic-gate 
109*0a701b1eSRobert Gordon 	case XDR_RDMA_GET_FLAGS:
1107c478bd9Sstevel@tonic-gate 		/*
1117c478bd9Sstevel@tonic-gate 		 * Get the flags provided in xp_flags return through *info
1127c478bd9Sstevel@tonic-gate 		 */
1137c478bd9Sstevel@tonic-gate 		int32p = (int32_t *)info;
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 		*int32p = (int32_t)xdrp->flags;
1167c478bd9Sstevel@tonic-gate 		return (TRUE);
1177c478bd9Sstevel@tonic-gate 
118*0a701b1eSRobert Gordon 	case XDR_RDMA_GET_CHUNK_LEN:
119*0a701b1eSRobert Gordon 		rcilp = (rdma_chunkinfo_lengths_t *)info;
120*0a701b1eSRobert Gordon 		rcilp->rcil_len = xdrp->xp_reply_chunk_len;
121*0a701b1eSRobert Gordon 		rcilp->rcil_len_alt = xdrp->xp_reply_chunk_len_alt;
122*0a701b1eSRobert Gordon 
123*0a701b1eSRobert Gordon 		return (TRUE);
124*0a701b1eSRobert Gordon 
125*0a701b1eSRobert Gordon 	case XDR_RDMA_ADD_CHUNK:
126*0a701b1eSRobert Gordon 		rcip = (rdma_chunkinfo_t *)info;
127*0a701b1eSRobert Gordon 
128*0a701b1eSRobert Gordon 		switch (rcip->rci_type) {
129*0a701b1eSRobert Gordon 		case RCI_WRITE_UIO_CHUNK:
130*0a701b1eSRobert Gordon 			xdrp->xp_reply_chunk_len_alt += rcip->rci_len;
131*0a701b1eSRobert Gordon 			break;
132*0a701b1eSRobert Gordon 
133*0a701b1eSRobert Gordon 		case RCI_WRITE_ADDR_CHUNK:
134*0a701b1eSRobert Gordon 			xdrp->xp_reply_chunk_len_alt += rcip->rci_len;
135*0a701b1eSRobert Gordon 			break;
136*0a701b1eSRobert Gordon 
137*0a701b1eSRobert Gordon 		case RCI_REPLY_CHUNK:
138*0a701b1eSRobert Gordon 			xdrp->xp_reply_chunk_len += rcip->rci_len;
139*0a701b1eSRobert Gordon 			break;
140*0a701b1eSRobert Gordon 		}
141*0a701b1eSRobert Gordon 		return (TRUE);
142*0a701b1eSRobert Gordon 
1437c478bd9Sstevel@tonic-gate 	default:
1447c478bd9Sstevel@tonic-gate 		return (FALSE);
1457c478bd9Sstevel@tonic-gate 	}
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate /* ARGSUSED */
1497c478bd9Sstevel@tonic-gate static rpc_inline_t *
1507c478bd9Sstevel@tonic-gate x_inline(XDR *xdrs, int len)
1517c478bd9Sstevel@tonic-gate {
1527c478bd9Sstevel@tonic-gate 	struct private *xdrp = (struct private *)xdrs->x_private;
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	if (len == 0) {
1557c478bd9Sstevel@tonic-gate 		return (NULL);
1567c478bd9Sstevel@tonic-gate 	}
1577c478bd9Sstevel@tonic-gate 	if (xdrs->x_op != XDR_ENCODE) {
1587c478bd9Sstevel@tonic-gate 		return (NULL);
1597c478bd9Sstevel@tonic-gate 	}
1607c478bd9Sstevel@tonic-gate 	if (len >= xdrp->min_chunk) {
1617c478bd9Sstevel@tonic-gate 		return (NULL);
1627c478bd9Sstevel@tonic-gate 	}
1637c478bd9Sstevel@tonic-gate 	if (len <= xdrp->inline_len) {
1647c478bd9Sstevel@tonic-gate 		/* inline_buf was already allocated, just reuse it */
1657c478bd9Sstevel@tonic-gate 		xdrs->x_handy += len;
1667c478bd9Sstevel@tonic-gate 		return ((rpc_inline_t *)xdrp->inline_buf);
1677c478bd9Sstevel@tonic-gate 	} else {
1687c478bd9Sstevel@tonic-gate 		/* Free the earlier space and allocate new area */
1697c478bd9Sstevel@tonic-gate 		if (xdrp->inline_buf)
1707c478bd9Sstevel@tonic-gate 			mem_free(xdrp->inline_buf, xdrp->inline_len);
1717c478bd9Sstevel@tonic-gate 		if ((xdrp->inline_buf = (caddr_t)mem_alloc(len)) == NULL) {
1727c478bd9Sstevel@tonic-gate 			xdrp->inline_len = 0;
1737c478bd9Sstevel@tonic-gate 			return (NULL);
1747c478bd9Sstevel@tonic-gate 		}
1757c478bd9Sstevel@tonic-gate 		xdrp->inline_len = len;
1767c478bd9Sstevel@tonic-gate 		xdrs->x_handy += len;
1777c478bd9Sstevel@tonic-gate 		return ((rpc_inline_t *)xdrp->inline_buf);
1787c478bd9Sstevel@tonic-gate 	}
1797c478bd9Sstevel@tonic-gate }
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate static int
1827c478bd9Sstevel@tonic-gate harmless()
1837c478bd9Sstevel@tonic-gate {
1847c478bd9Sstevel@tonic-gate 	/* Always return FALSE/NULL, as the case may be */
1857c478bd9Sstevel@tonic-gate 	return (0);
1867c478bd9Sstevel@tonic-gate }
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate static void
1897c478bd9Sstevel@tonic-gate x_destroy(XDR *xdrs)
1907c478bd9Sstevel@tonic-gate {
1917c478bd9Sstevel@tonic-gate 	struct private *xdrp = (struct private *)xdrs->x_private;
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate 	xdrs->x_handy = 0;
1947c478bd9Sstevel@tonic-gate 	if (xdrp) {
1957c478bd9Sstevel@tonic-gate 		if (xdrp->inline_buf)
1967c478bd9Sstevel@tonic-gate 			mem_free(xdrp->inline_buf, xdrp->inline_len);
1977c478bd9Sstevel@tonic-gate 		mem_free(xdrp, sizeof (struct private));
1987c478bd9Sstevel@tonic-gate 		xdrs->x_private = NULL;
1997c478bd9Sstevel@tonic-gate 	}
2007c478bd9Sstevel@tonic-gate 	xdrs->x_base = 0;
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate static bool_t
2047c478bd9Sstevel@tonic-gate xdrrdma_common(XDR *xdrs, int min_chunk)
2057c478bd9Sstevel@tonic-gate {
2067c478bd9Sstevel@tonic-gate 	struct private *xdrp;
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	xdrs->x_ops = xdrrdma_xops();
2097c478bd9Sstevel@tonic-gate 	xdrs->x_op = XDR_ENCODE;
2107c478bd9Sstevel@tonic-gate 	xdrs->x_handy = 0;
2117c478bd9Sstevel@tonic-gate 	xdrs->x_base = NULL;
2127c478bd9Sstevel@tonic-gate 	xdrs->x_private = kmem_zalloc(sizeof (struct private), KM_SLEEP);
2137c478bd9Sstevel@tonic-gate 	xdrp = (struct private *)xdrs->x_private;
2147c478bd9Sstevel@tonic-gate 	xdrp->min_chunk = min_chunk;
2157c478bd9Sstevel@tonic-gate 	xdrp->flags = 0;
216*0a701b1eSRobert Gordon 	if (xdrp->min_chunk != 0)
217*0a701b1eSRobert Gordon 		xdrp->flags |= XDR_RDMA_CHUNK;
218*0a701b1eSRobert Gordon 
219*0a701b1eSRobert Gordon 	xdrp->xp_reply_chunk_len = 0;
220*0a701b1eSRobert Gordon 	xdrp->xp_reply_chunk_len_alt = 0;
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate 	return (TRUE);
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate unsigned int
226*0a701b1eSRobert Gordon xdrrdma_sizeof(xdrproc_t func, void *data, int min_chunk,
227*0a701b1eSRobert Gordon     uint_t *reply_size, uint_t *reply_size_alt)
2287c478bd9Sstevel@tonic-gate {
2297c478bd9Sstevel@tonic-gate 	XDR x;
2307c478bd9Sstevel@tonic-gate 	struct xdr_ops ops;
2317c478bd9Sstevel@tonic-gate 	bool_t stat;
2327c478bd9Sstevel@tonic-gate 	struct private *xdrp;
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	x.x_ops = &ops;
2357c478bd9Sstevel@tonic-gate 	(void) xdrrdma_common(&x, min_chunk);
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 	stat = func(&x, data);
2387c478bd9Sstevel@tonic-gate 	xdrp = (struct private *)x.x_private;
2397c478bd9Sstevel@tonic-gate 	if (xdrp) {
240*0a701b1eSRobert Gordon 		if (reply_size != NULL)
241*0a701b1eSRobert Gordon 			*reply_size = xdrp->xp_reply_chunk_len;
242*0a701b1eSRobert Gordon 		if (reply_size_alt != NULL)
243*0a701b1eSRobert Gordon 			*reply_size_alt = xdrp->xp_reply_chunk_len_alt;
2447c478bd9Sstevel@tonic-gate 		if (xdrp->inline_buf)
2457c478bd9Sstevel@tonic-gate 			mem_free(xdrp->inline_buf, xdrp->inline_len);
2467c478bd9Sstevel@tonic-gate 		mem_free(xdrp, sizeof (struct private));
2477c478bd9Sstevel@tonic-gate 	}
2487c478bd9Sstevel@tonic-gate 	return (stat == TRUE ? (unsigned int)x.x_handy: 0);
2497c478bd9Sstevel@tonic-gate }
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate unsigned int
2527c478bd9Sstevel@tonic-gate xdrrdma_authsize(AUTH *auth, struct cred *cred, int min_chunk)
2537c478bd9Sstevel@tonic-gate {
2547c478bd9Sstevel@tonic-gate 	XDR x;
2557c478bd9Sstevel@tonic-gate 	struct xdr_ops ops;
2567c478bd9Sstevel@tonic-gate 	bool_t stat;
2577c478bd9Sstevel@tonic-gate 	struct private *xdrp;
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 	x.x_ops = &ops;
2607c478bd9Sstevel@tonic-gate 	(void) xdrrdma_common(&x, min_chunk);
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 	stat = AUTH_MARSHALL(auth, &x, cred);
2637c478bd9Sstevel@tonic-gate 	xdrp = (struct private *)x.x_private;
2647c478bd9Sstevel@tonic-gate 	if (xdrp) {
2657c478bd9Sstevel@tonic-gate 		if (xdrp->inline_buf)
2667c478bd9Sstevel@tonic-gate 			mem_free(xdrp->inline_buf, xdrp->inline_len);
2677c478bd9Sstevel@tonic-gate 		mem_free(xdrp, sizeof (struct private));
2687c478bd9Sstevel@tonic-gate 	}
2697c478bd9Sstevel@tonic-gate 	return (stat == TRUE ? (unsigned int)x.x_handy: 0);
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate 
272*0a701b1eSRobert Gordon struct xdr_ops *
2737c478bd9Sstevel@tonic-gate xdrrdma_xops(void)
2747c478bd9Sstevel@tonic-gate {
2757c478bd9Sstevel@tonic-gate 	static struct xdr_ops ops;
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	/* to stop ANSI-C compiler from complaining */
2787c478bd9Sstevel@tonic-gate 	typedef  bool_t (* dummyfunc1)(XDR *, long *);
2797c478bd9Sstevel@tonic-gate 	typedef  bool_t (* dummyfunc2)(XDR *, caddr_t, int);
2807c478bd9Sstevel@tonic-gate 	typedef  bool_t (* dummyfunc3)(XDR *, int32_t *);
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 	ops.x_putbytes = x_putbytes;
2837c478bd9Sstevel@tonic-gate 	ops.x_inline = x_inline;
2847c478bd9Sstevel@tonic-gate 	ops.x_getpostn = x_getpostn;
2857c478bd9Sstevel@tonic-gate 	ops.x_setpostn = x_setpostn;
2867c478bd9Sstevel@tonic-gate 	ops.x_destroy = x_destroy;
2877c478bd9Sstevel@tonic-gate 	ops.x_control = x_control;
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate #if defined(_LP64) || defined(_KERNEL)
2907c478bd9Sstevel@tonic-gate 	ops.x_getint32 = (dummyfunc3)harmless;
2917c478bd9Sstevel@tonic-gate 	ops.x_putint32 = x_putint32_t;
2927c478bd9Sstevel@tonic-gate #endif
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	/* the other harmless ones */
2957c478bd9Sstevel@tonic-gate 	ops.x_getbytes = (dummyfunc2)harmless;
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	return (&ops);
2987c478bd9Sstevel@tonic-gate }
299