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
50a701b1eSRobert Gordon  * Common Development and Distribution License (the "License").
60a701b1eSRobert 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 /*
220a701b1eSRobert Gordon  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
24919f1431SAndrew Stormont  *
25919f1431SAndrew Stormont  * Copyright 2017 RackTop Systems.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <rpc/types.h>
297c478bd9Sstevel@tonic-gate #include <rpc/xdr.h>
307c478bd9Sstevel@tonic-gate #include <sys/types.h>
310a701b1eSRobert Gordon #include <sys/sdt.h>
327c478bd9Sstevel@tonic-gate #include <rpc/auth.h>
337c478bd9Sstevel@tonic-gate #include <rpc/rpc_rdma.h>
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate struct private {
367c478bd9Sstevel@tonic-gate 	int	min_chunk;
377c478bd9Sstevel@tonic-gate 	uint_t	flags;			/* controls setting for rdma xdr */
387c478bd9Sstevel@tonic-gate 	int	num_chunk;
397c478bd9Sstevel@tonic-gate 	caddr_t	inline_buf;		/* temporary buffer for xdr inlining */
407c478bd9Sstevel@tonic-gate 	int	inline_len;		/* inline buffer length */
410a701b1eSRobert Gordon 	uint_t	xp_reply_chunk_len;
420a701b1eSRobert Gordon 	uint_t	xp_reply_chunk_len_alt;
437c478bd9Sstevel@tonic-gate };
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate /* ARGSUSED */
467c478bd9Sstevel@tonic-gate static bool_t
x_putint32_t(XDR * xdrs,int32_t * ip)477c478bd9Sstevel@tonic-gate x_putint32_t(XDR *xdrs, int32_t *ip)
487c478bd9Sstevel@tonic-gate {
497c478bd9Sstevel@tonic-gate 	xdrs->x_handy += BYTES_PER_XDR_UNIT;
507c478bd9Sstevel@tonic-gate 	return (TRUE);
517c478bd9Sstevel@tonic-gate }
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate /* ARGSUSED */
547c478bd9Sstevel@tonic-gate static bool_t
x_putbytes(XDR * xdrs,char * bp,int len)557c478bd9Sstevel@tonic-gate x_putbytes(XDR *xdrs, char *bp, int len)
567c478bd9Sstevel@tonic-gate {
577c478bd9Sstevel@tonic-gate 	struct private *xdrp = (struct private *)xdrs->x_private;
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate 	/*
607c478bd9Sstevel@tonic-gate 	 * min_chunk = 0, means that the stream of bytes, to estimate size of,
617c478bd9Sstevel@tonic-gate 	 * contains no chunks to seperate out. See xdrrdma_putbytes()
627c478bd9Sstevel@tonic-gate 	 */
630a701b1eSRobert Gordon 	if (len < xdrp->min_chunk || !(xdrp->flags & XDR_RDMA_CHUNK)) {
647c478bd9Sstevel@tonic-gate 		xdrs->x_handy += len;
657c478bd9Sstevel@tonic-gate 		return (TRUE);
667c478bd9Sstevel@tonic-gate 	}
677c478bd9Sstevel@tonic-gate 	/*
687c478bd9Sstevel@tonic-gate 	 * Chunk item. No impact on xdr size.
697c478bd9Sstevel@tonic-gate 	 */
707c478bd9Sstevel@tonic-gate 	xdrp->num_chunk++;
710a701b1eSRobert Gordon 
727c478bd9Sstevel@tonic-gate 	return (TRUE);
737c478bd9Sstevel@tonic-gate }
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate static uint_t
x_getpostn(XDR * xdrs)767c478bd9Sstevel@tonic-gate x_getpostn(XDR *xdrs)
777c478bd9Sstevel@tonic-gate {
787c478bd9Sstevel@tonic-gate 	return (xdrs->x_handy);
797c478bd9Sstevel@tonic-gate }
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate /* ARGSUSED */
827c478bd9Sstevel@tonic-gate static bool_t
x_setpostn(XDR * xdrs,uint_t pos)837c478bd9Sstevel@tonic-gate x_setpostn(XDR *xdrs, uint_t pos)
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate 	/* This is not allowed */
867c478bd9Sstevel@tonic-gate 	return (FALSE);
877c478bd9Sstevel@tonic-gate }
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate /* ARGSUSED */
907c478bd9Sstevel@tonic-gate static bool_t
x_control(XDR * xdrs,int request,void * info)917c478bd9Sstevel@tonic-gate x_control(XDR *xdrs, int request, void *info)
927c478bd9Sstevel@tonic-gate {
937c478bd9Sstevel@tonic-gate 	int32_t *int32p;
947c478bd9Sstevel@tonic-gate 	uint_t in_flags;
950a701b1eSRobert Gordon 	rdma_chunkinfo_t *rcip = NULL;
960a701b1eSRobert Gordon 	rdma_chunkinfo_lengths_t *rcilp = NULL;
977c478bd9Sstevel@tonic-gate 	struct private *xdrp = (struct private *)xdrs->x_private;
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 	switch (request) {
1000a701b1eSRobert Gordon 	case XDR_RDMA_SET_FLAGS:
1017c478bd9Sstevel@tonic-gate 		/*
1027c478bd9Sstevel@tonic-gate 		 * Set the flags provided in the *info in xp_flags for rdma xdr
1037c478bd9Sstevel@tonic-gate 		 * stream control.
1047c478bd9Sstevel@tonic-gate 		 */
1057c478bd9Sstevel@tonic-gate 		int32p = (int32_t *)info;
1067c478bd9Sstevel@tonic-gate 		in_flags = (uint_t)(*int32p);
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 		xdrp->flags = in_flags;
1097c478bd9Sstevel@tonic-gate 		return (TRUE);
1107c478bd9Sstevel@tonic-gate 
1110a701b1eSRobert Gordon 	case XDR_RDMA_GET_FLAGS:
1127c478bd9Sstevel@tonic-gate 		/*
1137c478bd9Sstevel@tonic-gate 		 * Get the flags provided in xp_flags return through *info
1147c478bd9Sstevel@tonic-gate 		 */
1157c478bd9Sstevel@tonic-gate 		int32p = (int32_t *)info;
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 		*int32p = (int32_t)xdrp->flags;
1187c478bd9Sstevel@tonic-gate 		return (TRUE);
1197c478bd9Sstevel@tonic-gate 
1200a701b1eSRobert Gordon 	case XDR_RDMA_GET_CHUNK_LEN:
1210a701b1eSRobert Gordon 		rcilp = (rdma_chunkinfo_lengths_t *)info;
1220a701b1eSRobert Gordon 		rcilp->rcil_len = xdrp->xp_reply_chunk_len;
1230a701b1eSRobert Gordon 		rcilp->rcil_len_alt = xdrp->xp_reply_chunk_len_alt;
1240a701b1eSRobert Gordon 
1250a701b1eSRobert Gordon 		return (TRUE);
1260a701b1eSRobert Gordon 
1270a701b1eSRobert Gordon 	case XDR_RDMA_ADD_CHUNK:
1280a701b1eSRobert Gordon 		rcip = (rdma_chunkinfo_t *)info;
1290a701b1eSRobert Gordon 
1300a701b1eSRobert Gordon 		switch (rcip->rci_type) {
1310a701b1eSRobert Gordon 		case RCI_WRITE_UIO_CHUNK:
1320a701b1eSRobert Gordon 			xdrp->xp_reply_chunk_len_alt += rcip->rci_len;
1330a701b1eSRobert Gordon 			break;
1340a701b1eSRobert Gordon 
1350a701b1eSRobert Gordon 		case RCI_WRITE_ADDR_CHUNK:
1360a701b1eSRobert Gordon 			xdrp->xp_reply_chunk_len_alt += rcip->rci_len;
1370a701b1eSRobert Gordon 			break;
1380a701b1eSRobert Gordon 
1390a701b1eSRobert Gordon 		case RCI_REPLY_CHUNK:
1400a701b1eSRobert Gordon 			xdrp->xp_reply_chunk_len += rcip->rci_len;
1410a701b1eSRobert Gordon 			break;
1420a701b1eSRobert Gordon 		}
1430a701b1eSRobert Gordon 		return (TRUE);
1440a701b1eSRobert Gordon 
1457c478bd9Sstevel@tonic-gate 	default:
1467c478bd9Sstevel@tonic-gate 		return (FALSE);
1477c478bd9Sstevel@tonic-gate 	}
1487c478bd9Sstevel@tonic-gate }
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate /* ARGSUSED */
1517c478bd9Sstevel@tonic-gate static rpc_inline_t *
x_inline(XDR * xdrs,int len)1527c478bd9Sstevel@tonic-gate x_inline(XDR *xdrs, int len)
1537c478bd9Sstevel@tonic-gate {
1547c478bd9Sstevel@tonic-gate 	struct private *xdrp = (struct private *)xdrs->x_private;
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	if (len == 0) {
1577c478bd9Sstevel@tonic-gate 		return (NULL);
1587c478bd9Sstevel@tonic-gate 	}
1597c478bd9Sstevel@tonic-gate 	if (xdrs->x_op != XDR_ENCODE) {
1607c478bd9Sstevel@tonic-gate 		return (NULL);
1617c478bd9Sstevel@tonic-gate 	}
1627c478bd9Sstevel@tonic-gate 	if (len >= xdrp->min_chunk) {
1637c478bd9Sstevel@tonic-gate 		return (NULL);
1647c478bd9Sstevel@tonic-gate 	}
1657c478bd9Sstevel@tonic-gate 	if (len <= xdrp->inline_len) {
1667c478bd9Sstevel@tonic-gate 		/* inline_buf was already allocated, just reuse it */
1677c478bd9Sstevel@tonic-gate 		xdrs->x_handy += len;
1687c478bd9Sstevel@tonic-gate 		return ((rpc_inline_t *)xdrp->inline_buf);
1697c478bd9Sstevel@tonic-gate 	} else {
1707c478bd9Sstevel@tonic-gate 		/* Free the earlier space and allocate new area */
1717c478bd9Sstevel@tonic-gate 		if (xdrp->inline_buf)
1727c478bd9Sstevel@tonic-gate 			mem_free(xdrp->inline_buf, xdrp->inline_len);
1737c478bd9Sstevel@tonic-gate 		if ((xdrp->inline_buf = (caddr_t)mem_alloc(len)) == NULL) {
1747c478bd9Sstevel@tonic-gate 			xdrp->inline_len = 0;
1757c478bd9Sstevel@tonic-gate 			return (NULL);
1767c478bd9Sstevel@tonic-gate 		}
1777c478bd9Sstevel@tonic-gate 		xdrp->inline_len = len;
1787c478bd9Sstevel@tonic-gate 		xdrs->x_handy += len;
1797c478bd9Sstevel@tonic-gate 		return ((rpc_inline_t *)xdrp->inline_buf);
1807c478bd9Sstevel@tonic-gate 	}
1817c478bd9Sstevel@tonic-gate }
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate static int
harmless()1847c478bd9Sstevel@tonic-gate harmless()
1857c478bd9Sstevel@tonic-gate {
1867c478bd9Sstevel@tonic-gate 	/* Always return FALSE/NULL, as the case may be */
1877c478bd9Sstevel@tonic-gate 	return (0);
1887c478bd9Sstevel@tonic-gate }
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate static void
x_destroy(XDR * xdrs)1917c478bd9Sstevel@tonic-gate x_destroy(XDR *xdrs)
1927c478bd9Sstevel@tonic-gate {
1937c478bd9Sstevel@tonic-gate 	struct private *xdrp = (struct private *)xdrs->x_private;
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 	xdrs->x_handy = 0;
1967c478bd9Sstevel@tonic-gate 	if (xdrp) {
1977c478bd9Sstevel@tonic-gate 		if (xdrp->inline_buf)
1987c478bd9Sstevel@tonic-gate 			mem_free(xdrp->inline_buf, xdrp->inline_len);
1997c478bd9Sstevel@tonic-gate 		mem_free(xdrp, sizeof (struct private));
2007c478bd9Sstevel@tonic-gate 		xdrs->x_private = NULL;
2017c478bd9Sstevel@tonic-gate 	}
2027c478bd9Sstevel@tonic-gate 	xdrs->x_base = 0;
2037c478bd9Sstevel@tonic-gate }
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate static bool_t
xdrrdma_common(XDR * xdrs,int min_chunk)2067c478bd9Sstevel@tonic-gate xdrrdma_common(XDR *xdrs, int min_chunk)
2077c478bd9Sstevel@tonic-gate {
2087c478bd9Sstevel@tonic-gate 	struct private *xdrp;
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	xdrs->x_ops = xdrrdma_xops();
2117c478bd9Sstevel@tonic-gate 	xdrs->x_op = XDR_ENCODE;
2127c478bd9Sstevel@tonic-gate 	xdrs->x_handy = 0;
2137c478bd9Sstevel@tonic-gate 	xdrs->x_base = NULL;
2147c478bd9Sstevel@tonic-gate 	xdrs->x_private = kmem_zalloc(sizeof (struct private), KM_SLEEP);
2157c478bd9Sstevel@tonic-gate 	xdrp = (struct private *)xdrs->x_private;
2167c478bd9Sstevel@tonic-gate 	xdrp->min_chunk = min_chunk;
2177c478bd9Sstevel@tonic-gate 	xdrp->flags = 0;
2180a701b1eSRobert Gordon 	if (xdrp->min_chunk != 0)
2190a701b1eSRobert Gordon 		xdrp->flags |= XDR_RDMA_CHUNK;
2200a701b1eSRobert Gordon 
2210a701b1eSRobert Gordon 	xdrp->xp_reply_chunk_len = 0;
2220a701b1eSRobert Gordon 	xdrp->xp_reply_chunk_len_alt = 0;
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate 	return (TRUE);
2257c478bd9Sstevel@tonic-gate }
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate unsigned int
xdrrdma_sizeof(xdrproc_t func,void * data,int min_chunk,uint_t * reply_size,uint_t * reply_size_alt)2280a701b1eSRobert Gordon xdrrdma_sizeof(xdrproc_t func, void *data, int min_chunk,
2290a701b1eSRobert Gordon     uint_t *reply_size, uint_t *reply_size_alt)
2307c478bd9Sstevel@tonic-gate {
2317c478bd9Sstevel@tonic-gate 	XDR x;
2327c478bd9Sstevel@tonic-gate 	struct xdr_ops ops;
2337c478bd9Sstevel@tonic-gate 	bool_t stat;
2347c478bd9Sstevel@tonic-gate 	struct private *xdrp;
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 	x.x_ops = &ops;
2377c478bd9Sstevel@tonic-gate 	(void) xdrrdma_common(&x, min_chunk);
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 	stat = func(&x, data);
2407c478bd9Sstevel@tonic-gate 	xdrp = (struct private *)x.x_private;
2417c478bd9Sstevel@tonic-gate 	if (xdrp) {
2420a701b1eSRobert Gordon 		if (reply_size != NULL)
2430a701b1eSRobert Gordon 			*reply_size = xdrp->xp_reply_chunk_len;
2440a701b1eSRobert Gordon 		if (reply_size_alt != NULL)
2450a701b1eSRobert Gordon 			*reply_size_alt = xdrp->xp_reply_chunk_len_alt;
2467c478bd9Sstevel@tonic-gate 		if (xdrp->inline_buf)
2477c478bd9Sstevel@tonic-gate 			mem_free(xdrp->inline_buf, xdrp->inline_len);
2487c478bd9Sstevel@tonic-gate 		mem_free(xdrp, sizeof (struct private));
2497c478bd9Sstevel@tonic-gate 	}
2507c478bd9Sstevel@tonic-gate 	return (stat == TRUE ? (unsigned int)x.x_handy: 0);
2517c478bd9Sstevel@tonic-gate }
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate unsigned int
xdrrdma_authsize(AUTH * auth,struct cred * cred,int min_chunk)2547c478bd9Sstevel@tonic-gate xdrrdma_authsize(AUTH *auth, struct cred *cred, int min_chunk)
2557c478bd9Sstevel@tonic-gate {
2567c478bd9Sstevel@tonic-gate 	XDR x;
2577c478bd9Sstevel@tonic-gate 	struct xdr_ops ops;
2587c478bd9Sstevel@tonic-gate 	bool_t stat;
2597c478bd9Sstevel@tonic-gate 	struct private *xdrp;
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 	x.x_ops = &ops;
2627c478bd9Sstevel@tonic-gate 	(void) xdrrdma_common(&x, min_chunk);
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate 	stat = AUTH_MARSHALL(auth, &x, cred);
2657c478bd9Sstevel@tonic-gate 	xdrp = (struct private *)x.x_private;
2667c478bd9Sstevel@tonic-gate 	if (xdrp) {
2677c478bd9Sstevel@tonic-gate 		if (xdrp->inline_buf)
2687c478bd9Sstevel@tonic-gate 			mem_free(xdrp->inline_buf, xdrp->inline_len);
2697c478bd9Sstevel@tonic-gate 		mem_free(xdrp, sizeof (struct private));
2707c478bd9Sstevel@tonic-gate 	}
2717c478bd9Sstevel@tonic-gate 	return (stat == TRUE ? (unsigned int)x.x_handy: 0);
2727c478bd9Sstevel@tonic-gate }
2737c478bd9Sstevel@tonic-gate 
2740a701b1eSRobert Gordon struct xdr_ops *
xdrrdma_xops(void)2757c478bd9Sstevel@tonic-gate xdrrdma_xops(void)
2767c478bd9Sstevel@tonic-gate {
2777c478bd9Sstevel@tonic-gate 	static struct xdr_ops ops;
2787c478bd9Sstevel@tonic-gate 
279*0827cc77SDan McDonald 	/* to stop ANSI-C compiler from complaining */
280*0827cc77SDan McDonald 	typedef  bool_t (* dummyfunc1)(XDR *, caddr_t, int);
281*0827cc77SDan McDonald #if defined(_LP64) || defined(_KERNEL)
282*0827cc77SDan McDonald 	typedef  bool_t (* dummyfunc2)(XDR *, int32_t *);
283*0827cc77SDan McDonald #endif
284*0827cc77SDan McDonald 
2857c478bd9Sstevel@tonic-gate 	ops.x_putbytes = x_putbytes;
2867c478bd9Sstevel@tonic-gate 	ops.x_inline = x_inline;
2877c478bd9Sstevel@tonic-gate 	ops.x_getpostn = x_getpostn;
2887c478bd9Sstevel@tonic-gate 	ops.x_setpostn = x_setpostn;
2897c478bd9Sstevel@tonic-gate 	ops.x_destroy = x_destroy;
2907c478bd9Sstevel@tonic-gate 	ops.x_control = x_control;
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate #if defined(_LP64) || defined(_KERNEL)
293*0827cc77SDan McDonald 	ops.x_getint32 = (dummyfunc2)harmless;
2947c478bd9Sstevel@tonic-gate 	ops.x_putint32 = x_putint32_t;
2957c478bd9Sstevel@tonic-gate #endif
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	/* the other harmless ones */
298*0827cc77SDan McDonald 	ops.x_getbytes = (dummyfunc1)harmless;
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 	return (&ops);
3017c478bd9Sstevel@tonic-gate }
302