15331Samw /* 25331Samw * CDDL HEADER START 35331Samw * 45331Samw * The contents of this file are subject to the terms of the 55331Samw * Common Development and Distribution License (the "License"). 65331Samw * You may not use this file except in compliance with the License. 75331Samw * 85331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 95331Samw * or http://www.opensolaris.org/os/licensing. 105331Samw * See the License for the specific language governing permissions 115331Samw * and limitations under the License. 125331Samw * 135331Samw * When distributing Covered Code, include this CDDL HEADER in each 145331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 155331Samw * If applicable, add the following below this CDDL HEADER, with the 165331Samw * fields enclosed by brackets "[]" replaced with your own identifying 175331Samw * information: Portions Copyright [yyyy] [name of copyright owner] 185331Samw * 195331Samw * CDDL HEADER END 205331Samw */ 215331Samw /* 22*5772Sas200622 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 235331Samw * Use is subject to license terms. 245331Samw */ 255331Samw 265331Samw #pragma ident "%Z%%M% %I% %E% SMI" 275331Samw 285331Samw /* 295331Samw * Context functions to support the RPC interface library. 305331Samw */ 315331Samw 325331Samw #include <sys/errno.h> 335331Samw #include <strings.h> 345331Samw 355331Samw #include <smbsrv/libsmb.h> 365331Samw #include <smbsrv/libsmbrdr.h> 375521Sas200622 #include <smbsrv/ndr.h> 385521Sas200622 #include <smbsrv/mlrpc.h> 395331Samw #include <smbsrv/mlsvc_util.h> 405331Samw 415331Samw static int mlsvc_xa_init(struct mlrpc_client *, struct mlrpc_xaction *, 425331Samw mlrpc_heap_t *); 435331Samw static int mlsvc_xa_exchange(struct mlrpc_client *, struct mlrpc_xaction *); 445331Samw static int mlsvc_xa_read(struct mlrpc_client *, struct mlrpc_xaction *); 455331Samw static int mlsvc_xa_preserve(struct mlrpc_client *, struct mlrpc_xaction *, 465331Samw mlrpc_heapref_t *); 475331Samw static int mlsvc_xa_destruct(struct mlrpc_client *, struct mlrpc_xaction *); 485331Samw static void mlsvc_xa_release(struct mlrpc_client *, mlrpc_heapref_t *heapref); 495331Samw 505331Samw /* 515331Samw * mlsvc_rpc_bind 525331Samw * 535331Samw * This the entry point for all client RPC services. This call must be 545331Samw * made to initialize an RPC context structure and bind to the remote 555331Samw * service before any RPCs can be exchanged with that service. The 565331Samw * descriptor is a wrapper that is used to associate an RPC handle with 575331Samw * the context data for that specific instance of the interface. The 585331Samw * handle is zeroed to ensure that it doesn't look like a valid handle. 595331Samw * The context handle is assigned to point at the RPC handle so that we 605331Samw * know when to free the context. As each handle is initialized it will 615331Samw * include a pointer to this context but only when we close this initial 625331Samw * RPC handle can the context be freed. 635331Samw * 645331Samw * On success, return a pointer to the descriptor. Otherwise return a 655331Samw * null pointer. 665331Samw */ 675331Samw int 685331Samw mlsvc_rpc_bind(mlsvc_handle_t *desc, int fid, char *service) 695331Samw { 705331Samw struct mlsvc_rpc_context *context; 715331Samw int rc; 725331Samw 735331Samw bzero(&desc->handle, sizeof (ms_handle_t)); 745331Samw 755331Samw context = malloc(sizeof (struct mlsvc_rpc_context)); 765331Samw if ((desc->context = context) == NULL) 775331Samw return (-1); 785331Samw 795331Samw bzero(context, sizeof (struct mlsvc_rpc_context)); 805331Samw context->cli.context = context; 815331Samw 825331Samw mlrpc_binding_pool_initialize(&context->cli.binding_list, 835331Samw context->binding_pool, CTXT_N_BINDING_POOL); 845331Samw 855331Samw context->fid = fid; 865331Samw context->handle = &desc->handle; 875331Samw context->cli.xa_init = mlsvc_xa_init; 885331Samw context->cli.xa_exchange = mlsvc_xa_exchange; 895331Samw context->cli.xa_read = mlsvc_xa_read; 905331Samw context->cli.xa_preserve = mlsvc_xa_preserve; 915331Samw context->cli.xa_destruct = mlsvc_xa_destruct; 925331Samw context->cli.xa_release = mlsvc_xa_release; 935331Samw 945331Samw rc = mlrpc_c_bind(&context->cli, service, &context->binding); 955331Samw if (MLRPC_DRC_IS_FAULT(rc)) { 965331Samw free(context); 975331Samw desc->context = NULL; 985331Samw return (-1); 995331Samw } 1005331Samw 1015331Samw return (rc); 1025331Samw } 1035331Samw 1045331Samw /* 1055331Samw * mlsvc_rpc_init 1065331Samw * 1075331Samw * This function must be called by client side applications before 1085331Samw * calling mlsvc_rpc_call to allocate a heap. The heap must be 1095331Samw * destroyed by either calling mlrpc_heap_destroy or mlsvc_rpc_free. 1105331Samw * Use mlrpc_heap_destroy if mlsvc_rpc_call has not yet been called. 1115331Samw * Otherwise use mlsvc_rpc_free. 1125331Samw * 1135331Samw * Returns 0 on success. Otherwise returns -1 to indicate an error. 1145331Samw */ 1155331Samw int 1165331Samw mlsvc_rpc_init(mlrpc_heapref_t *heapref) 1175331Samw { 1185331Samw bzero(heapref, sizeof (mlrpc_heapref_t)); 1195331Samw 1205331Samw if ((heapref->heap = mlrpc_heap_create()) == NULL) 1215331Samw return (-1); 1225331Samw 1235331Samw return (0); 1245331Samw } 1255331Samw 1265331Samw /* 1275331Samw * mlsvc_rpc_call 1285331Samw * 1295331Samw * This function should be called by the client RPC interface functions 1305331Samw * to make an RPC call. The remote service is identified by the context 1315331Samw * handle, which should have been initialized with by mlsvc_rpc_bind. 1325331Samw */ 1335331Samw int 1345331Samw mlsvc_rpc_call(struct mlsvc_rpc_context *context, int opnum, void *params, 1355331Samw mlrpc_heapref_t *heapref) 1365331Samw { 1375331Samw return (mlrpc_c_call(context->binding, opnum, params, heapref)); 1385331Samw } 1395331Samw 1405331Samw /* 1415331Samw * mlsvc_rpc_free 1425331Samw * 1435331Samw * This function should be called by the client RPC interface functions 1445331Samw * to free the heap after an RPC call returns. 1455331Samw */ 1465331Samw void 1475331Samw mlsvc_rpc_free(struct mlsvc_rpc_context *context, mlrpc_heapref_t *heapref) 1485331Samw { 1495331Samw mlrpc_c_free_heap(context->binding, heapref); 1505331Samw } 1515331Samw 1525331Samw /* 1535331Samw * The following functions provide the callback interface in the 1545331Samw * context handle. 1555331Samw */ 1565331Samw /*ARGSUSED*/ 1575331Samw static int 1585331Samw mlsvc_xa_init(struct mlrpc_client *mcli, struct mlrpc_xaction *mxa, 1595331Samw mlrpc_heap_t *heap) 1605331Samw { 1615331Samw struct mlndr_stream *recv_mlnds = &mxa->recv_mlnds; 1625331Samw struct mlndr_stream *send_mlnds = &mxa->send_mlnds; 1635331Samw 1645331Samw /* 1655331Samw * If the caller hasn't provided a heap, create one here. 1665331Samw */ 1675331Samw if (heap == 0) { 1685331Samw if ((heap = mlrpc_heap_create()) == 0) 1695331Samw return (-1); 1705331Samw } 1715331Samw 1725331Samw mxa->heap = heap; 1735331Samw 1745331Samw mlnds_initialize(send_mlnds, 0, NDR_MODE_CALL_SEND, heap); 1755331Samw mlnds_initialize(recv_mlnds, 16 * 1024, NDR_MODE_RETURN_RECV, heap); 1765331Samw return (0); 1775331Samw } 1785331Samw 1795331Samw /* 1805331Samw * mlsvc_xa_exchange 1815331Samw * 1825331Samw * This is the entry pointy for an RPC client call exchange with 1835331Samw * a server, which will result in an smbrdr SmbTransact request. 1845331Samw * 1855331Samw * SmbTransact should return the number of bytes received, which 1865331Samw * we record as the PDU size, or a negative error code. 1875331Samw */ 1885331Samw static int 1895331Samw mlsvc_xa_exchange(struct mlrpc_client *mcli, struct mlrpc_xaction *mxa) 1905331Samw { 1915331Samw struct mlsvc_rpc_context *context = mcli->context; 1925331Samw struct mlndr_stream *recv_mlnds = &mxa->recv_mlnds; 1935331Samw struct mlndr_stream *send_mlnds = &mxa->send_mlnds; 1945331Samw int rc; 1955331Samw 196*5772Sas200622 rc = smbrdr_transact(context->fid, 1975331Samw (char *)send_mlnds->pdu_base_offset, send_mlnds->pdu_size, 1985331Samw (char *)recv_mlnds->pdu_base_offset, recv_mlnds->pdu_max_size); 1995331Samw 2005331Samw if (rc < 0) 2015331Samw recv_mlnds->pdu_size = 0; 2025331Samw else 2035331Samw recv_mlnds->pdu_size = rc; 2045331Samw 2055331Samw return (rc); 2065331Samw } 2075331Samw 2085331Samw /* 2095331Samw * mlsvc_xa_read 2105331Samw * 2115331Samw * This entry point will be invoked if the xa-exchange response contained 2125331Samw * only the first fragment of a multi-fragment response. The RPC client 2135331Samw * code will then make repeated xa-read requests to obtain the remaining 2145331Samw * fragments, which will result in smbrdr SmbReadX requests. 2155331Samw * 2165331Samw * SmbReadX should return the number of bytes received, in which case we 2175331Samw * expand the PDU size to include the received data, or a negative error 2185331Samw * code. 2195331Samw */ 2205331Samw static int 2215331Samw mlsvc_xa_read(struct mlrpc_client *mcli, struct mlrpc_xaction *mxa) 2225331Samw { 2235331Samw struct mlsvc_rpc_context *context = mcli->context; 2245331Samw struct mlndr_stream *mlnds = &mxa->recv_mlnds; 2255331Samw int len; 2265331Samw int rc; 2275331Samw 2285331Samw if ((len = (mlnds->pdu_max_size - mlnds->pdu_size)) < 0) 2295331Samw return (-1); 2305331Samw 231*5772Sas200622 rc = smbrdr_readx(context->fid, 2325331Samw (char *)mlnds->pdu_base_offset + mlnds->pdu_size, len); 2335331Samw 2345331Samw if (rc < 0) 2355331Samw return (-1); 2365331Samw 2375331Samw mlnds->pdu_size += rc; 2385331Samw 2395331Samw if (mlnds->pdu_size > mlnds->pdu_max_size) { 2405331Samw mlnds->pdu_size = mlnds->pdu_max_size; 2415331Samw return (-1); 2425331Samw } 2435331Samw 2445331Samw return (rc); 2455331Samw } 2465331Samw 2475331Samw /* 2485331Samw * mlsvc_xa_preserve 2495331Samw * 2505331Samw * This function is called to preserve the heap. We save a reference 2515331Samw * to the heap and set the mxa heap pointer to null so that the heap 2525331Samw * will not be discarded when mlsvc_xa_destruct is called. 2535331Samw */ 2545331Samw /*ARGSUSED*/ 2555331Samw static int 2565331Samw mlsvc_xa_preserve(struct mlrpc_client *mcli, struct mlrpc_xaction *mxa, 2575331Samw mlrpc_heapref_t *heapref) 2585331Samw { 2595331Samw heapref->state = MLRPC_HRST_PRESERVED; 2605331Samw heapref->heap = mxa->heap; 2615331Samw heapref->recv_pdu_buf = (char *)mxa->recv_mlnds.pdu_base_addr; 2625331Samw heapref->send_pdu_buf = (char *)mxa->send_mlnds.pdu_base_addr; 2635331Samw 2645331Samw mxa->heap = NULL; 2655331Samw return (0); 2665331Samw } 2675331Samw 2685331Samw /* 2695331Samw * mlsvc_xa_destruct 2705331Samw * 2715331Samw * This function is called to dispose of the heap. If the heap has 2725331Samw * been preserved via mlsvc_xa_preserve, the mxa heap pointer will 2735331Samw * be null and we assume that the heap will be released later via 2745331Samw * a call to mlsvc_xa_release. Otherwise we free the memory here. 2755331Samw */ 2765331Samw /*ARGSUSED*/ 2775331Samw static int 2785331Samw mlsvc_xa_destruct(struct mlrpc_client *mcli, struct mlrpc_xaction *mxa) 2795331Samw { 2805331Samw if (mxa->heap) { 2815331Samw mlnds_destruct(&mxa->recv_mlnds); 2825331Samw mlnds_destruct(&mxa->send_mlnds); 2835331Samw mlrpc_heap_destroy(mxa->heap); 2845331Samw } 2855331Samw 2865331Samw return (0); 2875331Samw } 2885331Samw 2895331Samw /* 2905331Samw * mlsvc_xa_release 2915331Samw * 2925331Samw * This function is called, via some indirection, as a result of a 2935331Samw * call to mlsvc_rpc_free. This is where we free the heap memory 2945331Samw * that was preserved during an RPC call. 2955331Samw */ 2965331Samw /*ARGSUSED*/ 2975331Samw static void 2985331Samw mlsvc_xa_release(struct mlrpc_client *mcli, mlrpc_heapref_t *heapref) 2995331Samw { 3005331Samw if (heapref == NULL) 3015331Samw return; 3025331Samw 3035331Samw if (heapref->state == MLRPC_HRST_PRESERVED) { 3045331Samw free(heapref->recv_pdu_buf); 3055331Samw free(heapref->send_pdu_buf); 3065331Samw mlrpc_heap_destroy(heapref->heap); 3075331Samw } 3085331Samw } 309