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