xref: /onnv-gate/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_client.c (revision 5772:237ac22142fe)
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