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