10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7387SRobert.Gordon@Sun.COM * Common Development and Distribution License (the "License").
6*7387SRobert.Gordon@Sun.COM * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*7387SRobert.Gordon@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <rpc/types.h>
270Sstevel@tonic-gate #include <rpc/xdr.h>
280Sstevel@tonic-gate #include <sys/types.h>
29*7387SRobert.Gordon@Sun.COM #include <sys/sdt.h>
300Sstevel@tonic-gate #include <rpc/auth.h>
310Sstevel@tonic-gate #include <rpc/rpc_rdma.h>
320Sstevel@tonic-gate
330Sstevel@tonic-gate struct private {
340Sstevel@tonic-gate int min_chunk;
350Sstevel@tonic-gate uint_t flags; /* controls setting for rdma xdr */
360Sstevel@tonic-gate int num_chunk;
370Sstevel@tonic-gate caddr_t inline_buf; /* temporary buffer for xdr inlining */
380Sstevel@tonic-gate int inline_len; /* inline buffer length */
39*7387SRobert.Gordon@Sun.COM uint_t xp_reply_chunk_len;
40*7387SRobert.Gordon@Sun.COM uint_t xp_reply_chunk_len_alt;
410Sstevel@tonic-gate };
420Sstevel@tonic-gate
430Sstevel@tonic-gate /* ARGSUSED */
440Sstevel@tonic-gate static bool_t
x_putint32_t(XDR * xdrs,int32_t * ip)450Sstevel@tonic-gate x_putint32_t(XDR *xdrs, int32_t *ip)
460Sstevel@tonic-gate {
470Sstevel@tonic-gate xdrs->x_handy += BYTES_PER_XDR_UNIT;
480Sstevel@tonic-gate return (TRUE);
490Sstevel@tonic-gate }
500Sstevel@tonic-gate
510Sstevel@tonic-gate /* ARGSUSED */
520Sstevel@tonic-gate static bool_t
x_putbytes(XDR * xdrs,char * bp,int len)530Sstevel@tonic-gate x_putbytes(XDR *xdrs, char *bp, int len)
540Sstevel@tonic-gate {
550Sstevel@tonic-gate struct private *xdrp = (struct private *)xdrs->x_private;
560Sstevel@tonic-gate
570Sstevel@tonic-gate /*
580Sstevel@tonic-gate * min_chunk = 0, means that the stream of bytes, to estimate size of,
590Sstevel@tonic-gate * contains no chunks to seperate out. See xdrrdma_putbytes()
600Sstevel@tonic-gate */
61*7387SRobert.Gordon@Sun.COM if (len < xdrp->min_chunk || !(xdrp->flags & XDR_RDMA_CHUNK)) {
620Sstevel@tonic-gate xdrs->x_handy += len;
630Sstevel@tonic-gate return (TRUE);
640Sstevel@tonic-gate }
650Sstevel@tonic-gate /*
660Sstevel@tonic-gate * Chunk item. No impact on xdr size.
670Sstevel@tonic-gate */
680Sstevel@tonic-gate xdrp->num_chunk++;
69*7387SRobert.Gordon@Sun.COM
700Sstevel@tonic-gate return (TRUE);
710Sstevel@tonic-gate }
720Sstevel@tonic-gate
730Sstevel@tonic-gate static uint_t
x_getpostn(XDR * xdrs)740Sstevel@tonic-gate x_getpostn(XDR *xdrs)
750Sstevel@tonic-gate {
760Sstevel@tonic-gate return (xdrs->x_handy);
770Sstevel@tonic-gate }
780Sstevel@tonic-gate
790Sstevel@tonic-gate /* ARGSUSED */
800Sstevel@tonic-gate static bool_t
x_setpostn(XDR * xdrs,uint_t pos)810Sstevel@tonic-gate x_setpostn(XDR *xdrs, uint_t pos)
820Sstevel@tonic-gate {
830Sstevel@tonic-gate /* This is not allowed */
840Sstevel@tonic-gate return (FALSE);
850Sstevel@tonic-gate }
860Sstevel@tonic-gate
870Sstevel@tonic-gate /* ARGSUSED */
880Sstevel@tonic-gate static bool_t
x_control(XDR * xdrs,int request,void * info)890Sstevel@tonic-gate x_control(XDR *xdrs, int request, void *info)
900Sstevel@tonic-gate {
910Sstevel@tonic-gate int32_t *int32p;
920Sstevel@tonic-gate uint_t in_flags;
93*7387SRobert.Gordon@Sun.COM rdma_chunkinfo_t *rcip = NULL;
94*7387SRobert.Gordon@Sun.COM rdma_chunkinfo_lengths_t *rcilp = NULL;
950Sstevel@tonic-gate struct private *xdrp = (struct private *)xdrs->x_private;
960Sstevel@tonic-gate
970Sstevel@tonic-gate switch (request) {
98*7387SRobert.Gordon@Sun.COM case XDR_RDMA_SET_FLAGS:
990Sstevel@tonic-gate /*
1000Sstevel@tonic-gate * Set the flags provided in the *info in xp_flags for rdma xdr
1010Sstevel@tonic-gate * stream control.
1020Sstevel@tonic-gate */
1030Sstevel@tonic-gate int32p = (int32_t *)info;
1040Sstevel@tonic-gate in_flags = (uint_t)(*int32p);
1050Sstevel@tonic-gate
1060Sstevel@tonic-gate xdrp->flags = in_flags;
1070Sstevel@tonic-gate return (TRUE);
1080Sstevel@tonic-gate
109*7387SRobert.Gordon@Sun.COM case XDR_RDMA_GET_FLAGS:
1100Sstevel@tonic-gate /*
1110Sstevel@tonic-gate * Get the flags provided in xp_flags return through *info
1120Sstevel@tonic-gate */
1130Sstevel@tonic-gate int32p = (int32_t *)info;
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate *int32p = (int32_t)xdrp->flags;
1160Sstevel@tonic-gate return (TRUE);
1170Sstevel@tonic-gate
118*7387SRobert.Gordon@Sun.COM case XDR_RDMA_GET_CHUNK_LEN:
119*7387SRobert.Gordon@Sun.COM rcilp = (rdma_chunkinfo_lengths_t *)info;
120*7387SRobert.Gordon@Sun.COM rcilp->rcil_len = xdrp->xp_reply_chunk_len;
121*7387SRobert.Gordon@Sun.COM rcilp->rcil_len_alt = xdrp->xp_reply_chunk_len_alt;
122*7387SRobert.Gordon@Sun.COM
123*7387SRobert.Gordon@Sun.COM return (TRUE);
124*7387SRobert.Gordon@Sun.COM
125*7387SRobert.Gordon@Sun.COM case XDR_RDMA_ADD_CHUNK:
126*7387SRobert.Gordon@Sun.COM rcip = (rdma_chunkinfo_t *)info;
127*7387SRobert.Gordon@Sun.COM
128*7387SRobert.Gordon@Sun.COM switch (rcip->rci_type) {
129*7387SRobert.Gordon@Sun.COM case RCI_WRITE_UIO_CHUNK:
130*7387SRobert.Gordon@Sun.COM xdrp->xp_reply_chunk_len_alt += rcip->rci_len;
131*7387SRobert.Gordon@Sun.COM break;
132*7387SRobert.Gordon@Sun.COM
133*7387SRobert.Gordon@Sun.COM case RCI_WRITE_ADDR_CHUNK:
134*7387SRobert.Gordon@Sun.COM xdrp->xp_reply_chunk_len_alt += rcip->rci_len;
135*7387SRobert.Gordon@Sun.COM break;
136*7387SRobert.Gordon@Sun.COM
137*7387SRobert.Gordon@Sun.COM case RCI_REPLY_CHUNK:
138*7387SRobert.Gordon@Sun.COM xdrp->xp_reply_chunk_len += rcip->rci_len;
139*7387SRobert.Gordon@Sun.COM break;
140*7387SRobert.Gordon@Sun.COM }
141*7387SRobert.Gordon@Sun.COM return (TRUE);
142*7387SRobert.Gordon@Sun.COM
1430Sstevel@tonic-gate default:
1440Sstevel@tonic-gate return (FALSE);
1450Sstevel@tonic-gate }
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate
1480Sstevel@tonic-gate /* ARGSUSED */
1490Sstevel@tonic-gate static rpc_inline_t *
x_inline(XDR * xdrs,int len)1500Sstevel@tonic-gate x_inline(XDR *xdrs, int len)
1510Sstevel@tonic-gate {
1520Sstevel@tonic-gate struct private *xdrp = (struct private *)xdrs->x_private;
1530Sstevel@tonic-gate
1540Sstevel@tonic-gate if (len == 0) {
1550Sstevel@tonic-gate return (NULL);
1560Sstevel@tonic-gate }
1570Sstevel@tonic-gate if (xdrs->x_op != XDR_ENCODE) {
1580Sstevel@tonic-gate return (NULL);
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate if (len >= xdrp->min_chunk) {
1610Sstevel@tonic-gate return (NULL);
1620Sstevel@tonic-gate }
1630Sstevel@tonic-gate if (len <= xdrp->inline_len) {
1640Sstevel@tonic-gate /* inline_buf was already allocated, just reuse it */
1650Sstevel@tonic-gate xdrs->x_handy += len;
1660Sstevel@tonic-gate return ((rpc_inline_t *)xdrp->inline_buf);
1670Sstevel@tonic-gate } else {
1680Sstevel@tonic-gate /* Free the earlier space and allocate new area */
1690Sstevel@tonic-gate if (xdrp->inline_buf)
1700Sstevel@tonic-gate mem_free(xdrp->inline_buf, xdrp->inline_len);
1710Sstevel@tonic-gate if ((xdrp->inline_buf = (caddr_t)mem_alloc(len)) == NULL) {
1720Sstevel@tonic-gate xdrp->inline_len = 0;
1730Sstevel@tonic-gate return (NULL);
1740Sstevel@tonic-gate }
1750Sstevel@tonic-gate xdrp->inline_len = len;
1760Sstevel@tonic-gate xdrs->x_handy += len;
1770Sstevel@tonic-gate return ((rpc_inline_t *)xdrp->inline_buf);
1780Sstevel@tonic-gate }
1790Sstevel@tonic-gate }
1800Sstevel@tonic-gate
1810Sstevel@tonic-gate static int
harmless()1820Sstevel@tonic-gate harmless()
1830Sstevel@tonic-gate {
1840Sstevel@tonic-gate /* Always return FALSE/NULL, as the case may be */
1850Sstevel@tonic-gate return (0);
1860Sstevel@tonic-gate }
1870Sstevel@tonic-gate
1880Sstevel@tonic-gate static void
x_destroy(XDR * xdrs)1890Sstevel@tonic-gate x_destroy(XDR *xdrs)
1900Sstevel@tonic-gate {
1910Sstevel@tonic-gate struct private *xdrp = (struct private *)xdrs->x_private;
1920Sstevel@tonic-gate
1930Sstevel@tonic-gate xdrs->x_handy = 0;
1940Sstevel@tonic-gate if (xdrp) {
1950Sstevel@tonic-gate if (xdrp->inline_buf)
1960Sstevel@tonic-gate mem_free(xdrp->inline_buf, xdrp->inline_len);
1970Sstevel@tonic-gate mem_free(xdrp, sizeof (struct private));
1980Sstevel@tonic-gate xdrs->x_private = NULL;
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate xdrs->x_base = 0;
2010Sstevel@tonic-gate }
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate static bool_t
xdrrdma_common(XDR * xdrs,int min_chunk)2040Sstevel@tonic-gate xdrrdma_common(XDR *xdrs, int min_chunk)
2050Sstevel@tonic-gate {
2060Sstevel@tonic-gate struct private *xdrp;
2070Sstevel@tonic-gate
2080Sstevel@tonic-gate xdrs->x_ops = xdrrdma_xops();
2090Sstevel@tonic-gate xdrs->x_op = XDR_ENCODE;
2100Sstevel@tonic-gate xdrs->x_handy = 0;
2110Sstevel@tonic-gate xdrs->x_base = NULL;
2120Sstevel@tonic-gate xdrs->x_private = kmem_zalloc(sizeof (struct private), KM_SLEEP);
2130Sstevel@tonic-gate xdrp = (struct private *)xdrs->x_private;
2140Sstevel@tonic-gate xdrp->min_chunk = min_chunk;
2150Sstevel@tonic-gate xdrp->flags = 0;
216*7387SRobert.Gordon@Sun.COM if (xdrp->min_chunk != 0)
217*7387SRobert.Gordon@Sun.COM xdrp->flags |= XDR_RDMA_CHUNK;
218*7387SRobert.Gordon@Sun.COM
219*7387SRobert.Gordon@Sun.COM xdrp->xp_reply_chunk_len = 0;
220*7387SRobert.Gordon@Sun.COM xdrp->xp_reply_chunk_len_alt = 0;
2210Sstevel@tonic-gate
2220Sstevel@tonic-gate return (TRUE);
2230Sstevel@tonic-gate }
2240Sstevel@tonic-gate
2250Sstevel@tonic-gate unsigned int
xdrrdma_sizeof(xdrproc_t func,void * data,int min_chunk,uint_t * reply_size,uint_t * reply_size_alt)226*7387SRobert.Gordon@Sun.COM xdrrdma_sizeof(xdrproc_t func, void *data, int min_chunk,
227*7387SRobert.Gordon@Sun.COM uint_t *reply_size, uint_t *reply_size_alt)
2280Sstevel@tonic-gate {
2290Sstevel@tonic-gate XDR x;
2300Sstevel@tonic-gate struct xdr_ops ops;
2310Sstevel@tonic-gate bool_t stat;
2320Sstevel@tonic-gate struct private *xdrp;
2330Sstevel@tonic-gate
2340Sstevel@tonic-gate x.x_ops = &ops;
2350Sstevel@tonic-gate (void) xdrrdma_common(&x, min_chunk);
2360Sstevel@tonic-gate
2370Sstevel@tonic-gate stat = func(&x, data);
2380Sstevel@tonic-gate xdrp = (struct private *)x.x_private;
2390Sstevel@tonic-gate if (xdrp) {
240*7387SRobert.Gordon@Sun.COM if (reply_size != NULL)
241*7387SRobert.Gordon@Sun.COM *reply_size = xdrp->xp_reply_chunk_len;
242*7387SRobert.Gordon@Sun.COM if (reply_size_alt != NULL)
243*7387SRobert.Gordon@Sun.COM *reply_size_alt = xdrp->xp_reply_chunk_len_alt;
2440Sstevel@tonic-gate if (xdrp->inline_buf)
2450Sstevel@tonic-gate mem_free(xdrp->inline_buf, xdrp->inline_len);
2460Sstevel@tonic-gate mem_free(xdrp, sizeof (struct private));
2470Sstevel@tonic-gate }
2480Sstevel@tonic-gate return (stat == TRUE ? (unsigned int)x.x_handy: 0);
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate unsigned int
xdrrdma_authsize(AUTH * auth,struct cred * cred,int min_chunk)2520Sstevel@tonic-gate xdrrdma_authsize(AUTH *auth, struct cred *cred, int min_chunk)
2530Sstevel@tonic-gate {
2540Sstevel@tonic-gate XDR x;
2550Sstevel@tonic-gate struct xdr_ops ops;
2560Sstevel@tonic-gate bool_t stat;
2570Sstevel@tonic-gate struct private *xdrp;
2580Sstevel@tonic-gate
2590Sstevel@tonic-gate x.x_ops = &ops;
2600Sstevel@tonic-gate (void) xdrrdma_common(&x, min_chunk);
2610Sstevel@tonic-gate
2620Sstevel@tonic-gate stat = AUTH_MARSHALL(auth, &x, cred);
2630Sstevel@tonic-gate xdrp = (struct private *)x.x_private;
2640Sstevel@tonic-gate if (xdrp) {
2650Sstevel@tonic-gate if (xdrp->inline_buf)
2660Sstevel@tonic-gate mem_free(xdrp->inline_buf, xdrp->inline_len);
2670Sstevel@tonic-gate mem_free(xdrp, sizeof (struct private));
2680Sstevel@tonic-gate }
2690Sstevel@tonic-gate return (stat == TRUE ? (unsigned int)x.x_handy: 0);
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate
272*7387SRobert.Gordon@Sun.COM struct xdr_ops *
xdrrdma_xops(void)2730Sstevel@tonic-gate xdrrdma_xops(void)
2740Sstevel@tonic-gate {
2750Sstevel@tonic-gate static struct xdr_ops ops;
2760Sstevel@tonic-gate
2770Sstevel@tonic-gate /* to stop ANSI-C compiler from complaining */
2780Sstevel@tonic-gate typedef bool_t (* dummyfunc1)(XDR *, long *);
2790Sstevel@tonic-gate typedef bool_t (* dummyfunc2)(XDR *, caddr_t, int);
2800Sstevel@tonic-gate typedef bool_t (* dummyfunc3)(XDR *, int32_t *);
2810Sstevel@tonic-gate
2820Sstevel@tonic-gate ops.x_putbytes = x_putbytes;
2830Sstevel@tonic-gate ops.x_inline = x_inline;
2840Sstevel@tonic-gate ops.x_getpostn = x_getpostn;
2850Sstevel@tonic-gate ops.x_setpostn = x_setpostn;
2860Sstevel@tonic-gate ops.x_destroy = x_destroy;
2870Sstevel@tonic-gate ops.x_control = x_control;
2880Sstevel@tonic-gate
2890Sstevel@tonic-gate #if defined(_LP64) || defined(_KERNEL)
2900Sstevel@tonic-gate ops.x_getint32 = (dummyfunc3)harmless;
2910Sstevel@tonic-gate ops.x_putint32 = x_putint32_t;
2920Sstevel@tonic-gate #endif
2930Sstevel@tonic-gate
2940Sstevel@tonic-gate /* the other harmless ones */
2950Sstevel@tonic-gate ops.x_getbytes = (dummyfunc2)harmless;
2960Sstevel@tonic-gate
2970Sstevel@tonic-gate return (&ops);
2980Sstevel@tonic-gate }
299