1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <rpc/types.h>
30*7c478bd9Sstevel@tonic-gate #include <rpc/xdr.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
32*7c478bd9Sstevel@tonic-gate #include <rpc/auth.h>
33*7c478bd9Sstevel@tonic-gate #include <rpc/rpc_rdma.h>
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate static struct xdr_ops *xdrrdma_xops(void);
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate struct private {
38*7c478bd9Sstevel@tonic-gate 	int	min_chunk;
39*7c478bd9Sstevel@tonic-gate 	uint_t	flags;			/* controls setting for rdma xdr */
40*7c478bd9Sstevel@tonic-gate 	int	num_chunk;
41*7c478bd9Sstevel@tonic-gate 	caddr_t	inline_buf;		/* temporary buffer for xdr inlining */
42*7c478bd9Sstevel@tonic-gate 	int	inline_len;		/* inline buffer length */
43*7c478bd9Sstevel@tonic-gate };
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
46*7c478bd9Sstevel@tonic-gate static bool_t
47*7c478bd9Sstevel@tonic-gate x_putint32_t(XDR *xdrs, int32_t *ip)
48*7c478bd9Sstevel@tonic-gate {
49*7c478bd9Sstevel@tonic-gate 	xdrs->x_handy += BYTES_PER_XDR_UNIT;
50*7c478bd9Sstevel@tonic-gate 	return (TRUE);
51*7c478bd9Sstevel@tonic-gate }
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
54*7c478bd9Sstevel@tonic-gate static bool_t
55*7c478bd9Sstevel@tonic-gate x_putbytes(XDR *xdrs, char *bp, int len)
56*7c478bd9Sstevel@tonic-gate {
57*7c478bd9Sstevel@tonic-gate 	struct private *xdrp = (struct private *)xdrs->x_private;
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate 	/*
60*7c478bd9Sstevel@tonic-gate 	 * min_chunk = 0, means that the stream of bytes, to estimate size of,
61*7c478bd9Sstevel@tonic-gate 	 * contains no chunks to seperate out. See xdrrdma_putbytes()
62*7c478bd9Sstevel@tonic-gate 	 */
63*7c478bd9Sstevel@tonic-gate 	if (len < xdrp->min_chunk || (xdrp->flags & RDMA_NOCHUNK)) {
64*7c478bd9Sstevel@tonic-gate 		xdrs->x_handy += len;
65*7c478bd9Sstevel@tonic-gate 		return (TRUE);
66*7c478bd9Sstevel@tonic-gate 	}
67*7c478bd9Sstevel@tonic-gate 	/*
68*7c478bd9Sstevel@tonic-gate 	 * Chunk item. No impact on xdr size.
69*7c478bd9Sstevel@tonic-gate 	 */
70*7c478bd9Sstevel@tonic-gate 	xdrp->num_chunk++;
71*7c478bd9Sstevel@tonic-gate 	return (TRUE);
72*7c478bd9Sstevel@tonic-gate }
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate static uint_t
75*7c478bd9Sstevel@tonic-gate x_getpostn(XDR *xdrs)
76*7c478bd9Sstevel@tonic-gate {
77*7c478bd9Sstevel@tonic-gate 	return (xdrs->x_handy);
78*7c478bd9Sstevel@tonic-gate }
79*7c478bd9Sstevel@tonic-gate 
80*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
81*7c478bd9Sstevel@tonic-gate static bool_t
82*7c478bd9Sstevel@tonic-gate x_setpostn(XDR *xdrs, uint_t pos)
83*7c478bd9Sstevel@tonic-gate {
84*7c478bd9Sstevel@tonic-gate 	/* This is not allowed */
85*7c478bd9Sstevel@tonic-gate 	return (FALSE);
86*7c478bd9Sstevel@tonic-gate }
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
89*7c478bd9Sstevel@tonic-gate static bool_t
90*7c478bd9Sstevel@tonic-gate x_control(XDR *xdrs, int request, void *info)
91*7c478bd9Sstevel@tonic-gate {
92*7c478bd9Sstevel@tonic-gate 	int32_t *int32p;
93*7c478bd9Sstevel@tonic-gate 	uint_t in_flags;
94*7c478bd9Sstevel@tonic-gate 	struct private *xdrp = (struct private *)xdrs->x_private;
95*7c478bd9Sstevel@tonic-gate 
96*7c478bd9Sstevel@tonic-gate 	switch (request) {
97*7c478bd9Sstevel@tonic-gate 	case XDR_RDMASET:
98*7c478bd9Sstevel@tonic-gate 		/*
99*7c478bd9Sstevel@tonic-gate 		 * Set the flags provided in the *info in xp_flags for rdma xdr
100*7c478bd9Sstevel@tonic-gate 		 * stream control.
101*7c478bd9Sstevel@tonic-gate 		 */
102*7c478bd9Sstevel@tonic-gate 		int32p = (int32_t *)info;
103*7c478bd9Sstevel@tonic-gate 		in_flags = (uint_t)(*int32p);
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate 		xdrp->flags = in_flags;
106*7c478bd9Sstevel@tonic-gate 		return (TRUE);
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate 	case XDR_RDMAGET:
109*7c478bd9Sstevel@tonic-gate 		/*
110*7c478bd9Sstevel@tonic-gate 		 * Get the flags provided in xp_flags return through *info
111*7c478bd9Sstevel@tonic-gate 		 */
112*7c478bd9Sstevel@tonic-gate 		int32p = (int32_t *)info;
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate 		*int32p = (int32_t)xdrp->flags;
115*7c478bd9Sstevel@tonic-gate 		return (TRUE);
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate 	default:
118*7c478bd9Sstevel@tonic-gate 		return (FALSE);
119*7c478bd9Sstevel@tonic-gate 	}
120*7c478bd9Sstevel@tonic-gate }
121*7c478bd9Sstevel@tonic-gate 
122*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
123*7c478bd9Sstevel@tonic-gate static rpc_inline_t *
124*7c478bd9Sstevel@tonic-gate x_inline(XDR *xdrs, int len)
125*7c478bd9Sstevel@tonic-gate {
126*7c478bd9Sstevel@tonic-gate 	struct private *xdrp = (struct private *)xdrs->x_private;
127*7c478bd9Sstevel@tonic-gate 
128*7c478bd9Sstevel@tonic-gate 	if (len == 0) {
129*7c478bd9Sstevel@tonic-gate 		return (NULL);
130*7c478bd9Sstevel@tonic-gate 	}
131*7c478bd9Sstevel@tonic-gate 	if (xdrs->x_op != XDR_ENCODE) {
132*7c478bd9Sstevel@tonic-gate 		return (NULL);
133*7c478bd9Sstevel@tonic-gate 	}
134*7c478bd9Sstevel@tonic-gate 	if (len >= xdrp->min_chunk) {
135*7c478bd9Sstevel@tonic-gate 		return (NULL);
136*7c478bd9Sstevel@tonic-gate 	}
137*7c478bd9Sstevel@tonic-gate 	if (len <= xdrp->inline_len) {
138*7c478bd9Sstevel@tonic-gate 		/* inline_buf was already allocated, just reuse it */
139*7c478bd9Sstevel@tonic-gate 		xdrs->x_handy += len;
140*7c478bd9Sstevel@tonic-gate 		return ((rpc_inline_t *)xdrp->inline_buf);
141*7c478bd9Sstevel@tonic-gate 	} else {
142*7c478bd9Sstevel@tonic-gate 		/* Free the earlier space and allocate new area */
143*7c478bd9Sstevel@tonic-gate 		if (xdrp->inline_buf)
144*7c478bd9Sstevel@tonic-gate 			mem_free(xdrp->inline_buf, xdrp->inline_len);
145*7c478bd9Sstevel@tonic-gate 		if ((xdrp->inline_buf = (caddr_t)mem_alloc(len)) == NULL) {
146*7c478bd9Sstevel@tonic-gate 			xdrp->inline_len = 0;
147*7c478bd9Sstevel@tonic-gate 			return (NULL);
148*7c478bd9Sstevel@tonic-gate 		}
149*7c478bd9Sstevel@tonic-gate 		xdrp->inline_len = len;
150*7c478bd9Sstevel@tonic-gate 		xdrs->x_handy += len;
151*7c478bd9Sstevel@tonic-gate 		return ((rpc_inline_t *)xdrp->inline_buf);
152*7c478bd9Sstevel@tonic-gate 	}
153*7c478bd9Sstevel@tonic-gate }
154*7c478bd9Sstevel@tonic-gate 
155*7c478bd9Sstevel@tonic-gate static int
156*7c478bd9Sstevel@tonic-gate harmless()
157*7c478bd9Sstevel@tonic-gate {
158*7c478bd9Sstevel@tonic-gate 	/* Always return FALSE/NULL, as the case may be */
159*7c478bd9Sstevel@tonic-gate 	return (0);
160*7c478bd9Sstevel@tonic-gate }
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate static void
163*7c478bd9Sstevel@tonic-gate x_destroy(XDR *xdrs)
164*7c478bd9Sstevel@tonic-gate {
165*7c478bd9Sstevel@tonic-gate 	struct private *xdrp = (struct private *)xdrs->x_private;
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate 	xdrs->x_handy = 0;
168*7c478bd9Sstevel@tonic-gate 	if (xdrp) {
169*7c478bd9Sstevel@tonic-gate 		if (xdrp->inline_buf)
170*7c478bd9Sstevel@tonic-gate 			mem_free(xdrp->inline_buf, xdrp->inline_len);
171*7c478bd9Sstevel@tonic-gate 		mem_free(xdrp, sizeof (struct private));
172*7c478bd9Sstevel@tonic-gate 		xdrs->x_private = NULL;
173*7c478bd9Sstevel@tonic-gate 	}
174*7c478bd9Sstevel@tonic-gate 	xdrs->x_base = 0;
175*7c478bd9Sstevel@tonic-gate }
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate static bool_t
178*7c478bd9Sstevel@tonic-gate xdrrdma_common(XDR *xdrs, int min_chunk)
179*7c478bd9Sstevel@tonic-gate {
180*7c478bd9Sstevel@tonic-gate 	struct private *xdrp;
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate 	xdrs->x_ops = xdrrdma_xops();
183*7c478bd9Sstevel@tonic-gate 	xdrs->x_op = XDR_ENCODE;
184*7c478bd9Sstevel@tonic-gate 	xdrs->x_handy = 0;
185*7c478bd9Sstevel@tonic-gate 	xdrs->x_base = NULL;
186*7c478bd9Sstevel@tonic-gate 	xdrs->x_private = kmem_zalloc(sizeof (struct private), KM_SLEEP);
187*7c478bd9Sstevel@tonic-gate 	xdrp = (struct private *)xdrs->x_private;
188*7c478bd9Sstevel@tonic-gate 	xdrp->min_chunk = min_chunk;
189*7c478bd9Sstevel@tonic-gate 	xdrp->flags = 0;
190*7c478bd9Sstevel@tonic-gate 	if (xdrp->min_chunk == 0)
191*7c478bd9Sstevel@tonic-gate 		xdrp->flags |= RDMA_NOCHUNK;
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate 	return (TRUE);
194*7c478bd9Sstevel@tonic-gate }
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate unsigned int
197*7c478bd9Sstevel@tonic-gate xdrrdma_sizeof(xdrproc_t func, void *data, int min_chunk)
198*7c478bd9Sstevel@tonic-gate {
199*7c478bd9Sstevel@tonic-gate 	XDR x;
200*7c478bd9Sstevel@tonic-gate 	struct xdr_ops ops;
201*7c478bd9Sstevel@tonic-gate 	bool_t stat;
202*7c478bd9Sstevel@tonic-gate 	struct private *xdrp;
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate 	x.x_ops = &ops;
205*7c478bd9Sstevel@tonic-gate 	(void) xdrrdma_common(&x, min_chunk);
206*7c478bd9Sstevel@tonic-gate 
207*7c478bd9Sstevel@tonic-gate 	stat = func(&x, data);
208*7c478bd9Sstevel@tonic-gate 	xdrp = (struct private *)x.x_private;
209*7c478bd9Sstevel@tonic-gate 	if (xdrp) {
210*7c478bd9Sstevel@tonic-gate 		if (xdrp->inline_buf)
211*7c478bd9Sstevel@tonic-gate 			mem_free(xdrp->inline_buf, xdrp->inline_len);
212*7c478bd9Sstevel@tonic-gate 		mem_free(xdrp, sizeof (struct private));
213*7c478bd9Sstevel@tonic-gate 	}
214*7c478bd9Sstevel@tonic-gate 	return (stat == TRUE ? (unsigned int)x.x_handy: 0);
215*7c478bd9Sstevel@tonic-gate }
216*7c478bd9Sstevel@tonic-gate 
217*7c478bd9Sstevel@tonic-gate unsigned int
218*7c478bd9Sstevel@tonic-gate xdrrdma_authsize(AUTH *auth, struct cred *cred, int min_chunk)
219*7c478bd9Sstevel@tonic-gate {
220*7c478bd9Sstevel@tonic-gate 	XDR x;
221*7c478bd9Sstevel@tonic-gate 	struct xdr_ops ops;
222*7c478bd9Sstevel@tonic-gate 	bool_t stat;
223*7c478bd9Sstevel@tonic-gate 	struct private *xdrp;
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate 	x.x_ops = &ops;
226*7c478bd9Sstevel@tonic-gate 	(void) xdrrdma_common(&x, min_chunk);
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate 	stat = AUTH_MARSHALL(auth, &x, cred);
229*7c478bd9Sstevel@tonic-gate 	xdrp = (struct private *)x.x_private;
230*7c478bd9Sstevel@tonic-gate 	if (xdrp) {
231*7c478bd9Sstevel@tonic-gate 		if (xdrp->inline_buf)
232*7c478bd9Sstevel@tonic-gate 			mem_free(xdrp->inline_buf, xdrp->inline_len);
233*7c478bd9Sstevel@tonic-gate 		mem_free(xdrp, sizeof (struct private));
234*7c478bd9Sstevel@tonic-gate 	}
235*7c478bd9Sstevel@tonic-gate 	return (stat == TRUE ? (unsigned int)x.x_handy: 0);
236*7c478bd9Sstevel@tonic-gate }
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate static struct xdr_ops *
239*7c478bd9Sstevel@tonic-gate xdrrdma_xops(void)
240*7c478bd9Sstevel@tonic-gate {
241*7c478bd9Sstevel@tonic-gate 	static struct xdr_ops ops;
242*7c478bd9Sstevel@tonic-gate 
243*7c478bd9Sstevel@tonic-gate 	/* to stop ANSI-C compiler from complaining */
244*7c478bd9Sstevel@tonic-gate 	typedef  bool_t (* dummyfunc1)(XDR *, long *);
245*7c478bd9Sstevel@tonic-gate 	typedef  bool_t (* dummyfunc2)(XDR *, caddr_t, int);
246*7c478bd9Sstevel@tonic-gate 	typedef  bool_t (* dummyfunc3)(XDR *, int32_t *);
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate 	ops.x_putbytes = x_putbytes;
249*7c478bd9Sstevel@tonic-gate 	ops.x_inline = x_inline;
250*7c478bd9Sstevel@tonic-gate 	ops.x_getpostn = x_getpostn;
251*7c478bd9Sstevel@tonic-gate 	ops.x_setpostn = x_setpostn;
252*7c478bd9Sstevel@tonic-gate 	ops.x_destroy = x_destroy;
253*7c478bd9Sstevel@tonic-gate 	ops.x_control = x_control;
254*7c478bd9Sstevel@tonic-gate 
255*7c478bd9Sstevel@tonic-gate #if defined(_LP64) || defined(_KERNEL)
256*7c478bd9Sstevel@tonic-gate 	ops.x_getint32 = (dummyfunc3)harmless;
257*7c478bd9Sstevel@tonic-gate 	ops.x_putint32 = x_putint32_t;
258*7c478bd9Sstevel@tonic-gate #endif
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate 	/* the other harmless ones */
261*7c478bd9Sstevel@tonic-gate 	ops.x_getbytes = (dummyfunc2)harmless;
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate 	return (&ops);
264*7c478bd9Sstevel@tonic-gate }
265