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 /* 225772Sas200622 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 235331Samw * Use is subject to license terms. 245331Samw */ 255331Samw 265331Samw /* 27*8334SJose.Borrego@Sun.COM * Client NDR RPC interface. 285331Samw */ 295331Samw 305331Samw #include <sys/errno.h> 315331Samw #include <strings.h> 32*8334SJose.Borrego@Sun.COM #include <assert.h> 335331Samw #include <smbsrv/libsmb.h> 345331Samw #include <smbsrv/libsmbrdr.h> 35*8334SJose.Borrego@Sun.COM #include <smbsrv/libmlrpc.h> 36*8334SJose.Borrego@Sun.COM #include <smbsrv/libmlsvc.h> 375331Samw 38*8334SJose.Borrego@Sun.COM static int ndr_xa_init(ndr_client_t *, ndr_xa_t *); 39*8334SJose.Borrego@Sun.COM static int ndr_xa_exchange(ndr_client_t *, ndr_xa_t *); 40*8334SJose.Borrego@Sun.COM static int ndr_xa_read(ndr_client_t *, ndr_xa_t *); 41*8334SJose.Borrego@Sun.COM static void ndr_xa_preserve(ndr_client_t *, ndr_xa_t *); 42*8334SJose.Borrego@Sun.COM static void ndr_xa_destruct(ndr_client_t *, ndr_xa_t *); 43*8334SJose.Borrego@Sun.COM static void ndr_xa_release(ndr_client_t *); 445331Samw 455331Samw /* 46*8334SJose.Borrego@Sun.COM * This call must be made to initialize an RPC client structure and bind 47*8334SJose.Borrego@Sun.COM * to the remote service before any RPCs can be exchanged with that service. 485331Samw * 49*8334SJose.Borrego@Sun.COM * The mlsvc_handle_t is a wrapper that is used to associate an RPC handle 50*8334SJose.Borrego@Sun.COM * with the client context for an instance of the interface. The handle 51*8334SJose.Borrego@Sun.COM * is zeroed to ensure that it doesn't look like a valid handle - 52*8334SJose.Borrego@Sun.COM * handle content is provided by the remove service. 535331Samw * 54*8334SJose.Borrego@Sun.COM * The client points to this top-level handle so that we know when to 55*8334SJose.Borrego@Sun.COM * unbind and teardown the connection. As each handle is initialized it 56*8334SJose.Borrego@Sun.COM * will inherit a reference to the client context. 575331Samw */ 585331Samw int 59*8334SJose.Borrego@Sun.COM ndr_rpc_bind(mlsvc_handle_t *handle, char *server, char *domain, 60*8334SJose.Borrego@Sun.COM char *username, const char *service) 615331Samw { 62*8334SJose.Borrego@Sun.COM ndr_client_t *clnt; 63*8334SJose.Borrego@Sun.COM ndr_service_t *svc; 64*8334SJose.Borrego@Sun.COM smbrdr_session_info_t si; 65*8334SJose.Borrego@Sun.COM int fid; 66*8334SJose.Borrego@Sun.COM int rc; 675331Samw 68*8334SJose.Borrego@Sun.COM if (handle == NULL || server == NULL || 69*8334SJose.Borrego@Sun.COM domain == NULL || username == NULL) 705331Samw return (-1); 715331Samw 72*8334SJose.Borrego@Sun.COM if ((svc = ndr_svc_lookup_name(service)) == NULL) 73*8334SJose.Borrego@Sun.COM return (-1); 745331Samw 75*8334SJose.Borrego@Sun.COM if ((clnt = malloc(sizeof (ndr_client_t))) == NULL) 76*8334SJose.Borrego@Sun.COM return (-1); 775331Samw 78*8334SJose.Borrego@Sun.COM fid = smbrdr_open_pipe(server, domain, username, svc->endpoint); 79*8334SJose.Borrego@Sun.COM if (fid < 0) { 80*8334SJose.Borrego@Sun.COM free(clnt); 815331Samw return (-1); 825331Samw } 835331Samw 84*8334SJose.Borrego@Sun.COM bzero(clnt, sizeof (ndr_client_t)); 85*8334SJose.Borrego@Sun.COM clnt->handle = &handle->handle; 86*8334SJose.Borrego@Sun.COM clnt->fid = fid; 87*8334SJose.Borrego@Sun.COM 88*8334SJose.Borrego@Sun.COM ndr_svc_binding_pool_init(&clnt->binding_list, 89*8334SJose.Borrego@Sun.COM clnt->binding_pool, NDR_N_BINDING_POOL); 90*8334SJose.Borrego@Sun.COM 91*8334SJose.Borrego@Sun.COM clnt->xa_init = ndr_xa_init; 92*8334SJose.Borrego@Sun.COM clnt->xa_exchange = ndr_xa_exchange; 93*8334SJose.Borrego@Sun.COM clnt->xa_read = ndr_xa_read; 94*8334SJose.Borrego@Sun.COM clnt->xa_preserve = ndr_xa_preserve; 95*8334SJose.Borrego@Sun.COM clnt->xa_destruct = ndr_xa_destruct; 96*8334SJose.Borrego@Sun.COM clnt->xa_release = ndr_xa_release; 975331Samw 98*8334SJose.Borrego@Sun.COM (void) smbrdr_session_info(fid, &si); 99*8334SJose.Borrego@Sun.COM bzero(&handle->handle, sizeof (ndr_hdid_t)); 100*8334SJose.Borrego@Sun.COM handle->clnt = clnt; 101*8334SJose.Borrego@Sun.COM handle->remote_os = si.si_server_os; 1025331Samw 103*8334SJose.Borrego@Sun.COM if (ndr_rpc_get_heap(handle) == NULL) { 104*8334SJose.Borrego@Sun.COM free(clnt); 1055331Samw return (-1); 106*8334SJose.Borrego@Sun.COM } 107*8334SJose.Borrego@Sun.COM 108*8334SJose.Borrego@Sun.COM rc = ndr_clnt_bind(clnt, service, &clnt->binding); 109*8334SJose.Borrego@Sun.COM if (NDR_DRC_IS_FAULT(rc)) { 110*8334SJose.Borrego@Sun.COM (void) smbrdr_close_pipe(fid); 111*8334SJose.Borrego@Sun.COM ndr_heap_destroy(clnt->heap); 112*8334SJose.Borrego@Sun.COM free(clnt); 113*8334SJose.Borrego@Sun.COM handle->clnt = NULL; 114*8334SJose.Borrego@Sun.COM return (-1); 115*8334SJose.Borrego@Sun.COM } 1165331Samw 1175331Samw return (0); 1185331Samw } 1195331Samw 1205331Samw /* 121*8334SJose.Borrego@Sun.COM * Unbind and close the pipe to an RPC service. 122*8334SJose.Borrego@Sun.COM * 123*8334SJose.Borrego@Sun.COM * If the heap has been preserved we need to go through an xa release. 124*8334SJose.Borrego@Sun.COM * The heap is preserved during an RPC call because that's where data 125*8334SJose.Borrego@Sun.COM * returned from the server is stored. 1265331Samw * 127*8334SJose.Borrego@Sun.COM * Otherwise we destroy the heap directly. 128*8334SJose.Borrego@Sun.COM */ 129*8334SJose.Borrego@Sun.COM void 130*8334SJose.Borrego@Sun.COM ndr_rpc_unbind(mlsvc_handle_t *handle) 131*8334SJose.Borrego@Sun.COM { 132*8334SJose.Borrego@Sun.COM ndr_client_t *clnt = handle->clnt; 133*8334SJose.Borrego@Sun.COM 134*8334SJose.Borrego@Sun.COM if (clnt->heap_preserved) 135*8334SJose.Borrego@Sun.COM ndr_clnt_free_heap(clnt); 136*8334SJose.Borrego@Sun.COM else 137*8334SJose.Borrego@Sun.COM ndr_heap_destroy(clnt->heap); 138*8334SJose.Borrego@Sun.COM 139*8334SJose.Borrego@Sun.COM (void) smbrdr_close_pipe(clnt->fid); 140*8334SJose.Borrego@Sun.COM free(handle->clnt); 141*8334SJose.Borrego@Sun.COM bzero(handle, sizeof (mlsvc_handle_t)); 142*8334SJose.Borrego@Sun.COM } 143*8334SJose.Borrego@Sun.COM 144*8334SJose.Borrego@Sun.COM /* 145*8334SJose.Borrego@Sun.COM * Call the RPC function identified by opnum. The remote service is 146*8334SJose.Borrego@Sun.COM * identified by the handle, which should have been initialized by 147*8334SJose.Borrego@Sun.COM * ndr_rpc_bind. 148*8334SJose.Borrego@Sun.COM * 149*8334SJose.Borrego@Sun.COM * If the RPC call is successful (returns 0), the caller must call 150*8334SJose.Borrego@Sun.COM * ndr_rpc_release to release the heap. Otherwise, we release the 151*8334SJose.Borrego@Sun.COM * heap here. 1525331Samw */ 1535331Samw int 154*8334SJose.Borrego@Sun.COM ndr_rpc_call(mlsvc_handle_t *handle, int opnum, void *params) 155*8334SJose.Borrego@Sun.COM { 156*8334SJose.Borrego@Sun.COM ndr_client_t *clnt = handle->clnt; 157*8334SJose.Borrego@Sun.COM int rc; 158*8334SJose.Borrego@Sun.COM 159*8334SJose.Borrego@Sun.COM if (ndr_rpc_get_heap(handle) == NULL) 160*8334SJose.Borrego@Sun.COM return (-1); 161*8334SJose.Borrego@Sun.COM 162*8334SJose.Borrego@Sun.COM rc = ndr_clnt_call(clnt->binding, opnum, params); 163*8334SJose.Borrego@Sun.COM 164*8334SJose.Borrego@Sun.COM if (NDR_DRC_IS_FAULT(rc)) { 165*8334SJose.Borrego@Sun.COM ndr_rpc_release(handle); 166*8334SJose.Borrego@Sun.COM return (-1); 167*8334SJose.Borrego@Sun.COM } 168*8334SJose.Borrego@Sun.COM 169*8334SJose.Borrego@Sun.COM return (0); 170*8334SJose.Borrego@Sun.COM } 171*8334SJose.Borrego@Sun.COM 172*8334SJose.Borrego@Sun.COM /* 173*8334SJose.Borrego@Sun.COM * Returns the Native-OS of the RPC server. 174*8334SJose.Borrego@Sun.COM */ 175*8334SJose.Borrego@Sun.COM int 176*8334SJose.Borrego@Sun.COM ndr_rpc_server_os(mlsvc_handle_t *handle) 1775331Samw { 178*8334SJose.Borrego@Sun.COM return (handle->remote_os); 179*8334SJose.Borrego@Sun.COM } 180*8334SJose.Borrego@Sun.COM 181*8334SJose.Borrego@Sun.COM void * 182*8334SJose.Borrego@Sun.COM ndr_rpc_malloc(mlsvc_handle_t *handle, size_t size) 183*8334SJose.Borrego@Sun.COM { 184*8334SJose.Borrego@Sun.COM ndr_heap_t *heap; 185*8334SJose.Borrego@Sun.COM 186*8334SJose.Borrego@Sun.COM if ((heap = ndr_rpc_get_heap(handle)) == NULL) 187*8334SJose.Borrego@Sun.COM return (NULL); 188*8334SJose.Borrego@Sun.COM 189*8334SJose.Borrego@Sun.COM return (ndr_heap_malloc(heap, size)); 190*8334SJose.Borrego@Sun.COM } 191*8334SJose.Borrego@Sun.COM 192*8334SJose.Borrego@Sun.COM ndr_heap_t * 193*8334SJose.Borrego@Sun.COM ndr_rpc_get_heap(mlsvc_handle_t *handle) 194*8334SJose.Borrego@Sun.COM { 195*8334SJose.Borrego@Sun.COM ndr_client_t *clnt = handle->clnt; 196*8334SJose.Borrego@Sun.COM 197*8334SJose.Borrego@Sun.COM if (clnt->heap == NULL) 198*8334SJose.Borrego@Sun.COM clnt->heap = ndr_heap_create(); 199*8334SJose.Borrego@Sun.COM 200*8334SJose.Borrego@Sun.COM return (clnt->heap); 2015331Samw } 2025331Samw 2035331Samw /* 204*8334SJose.Borrego@Sun.COM * Must be called by RPC clients to free the heap after a successful RPC 205*8334SJose.Borrego@Sun.COM * call, i.e. ndr_rpc_call returned 0. The caller should take a copy 206*8334SJose.Borrego@Sun.COM * of any data returned by the RPC prior to calling this function because 207*8334SJose.Borrego@Sun.COM * returned data is in the heap. 2085331Samw */ 2095331Samw void 210*8334SJose.Borrego@Sun.COM ndr_rpc_release(mlsvc_handle_t *handle) 211*8334SJose.Borrego@Sun.COM { 212*8334SJose.Borrego@Sun.COM ndr_client_t *clnt = handle->clnt; 213*8334SJose.Borrego@Sun.COM 214*8334SJose.Borrego@Sun.COM if (clnt->heap_preserved) 215*8334SJose.Borrego@Sun.COM ndr_clnt_free_heap(clnt); 216*8334SJose.Borrego@Sun.COM else 217*8334SJose.Borrego@Sun.COM ndr_heap_destroy(clnt->heap); 218*8334SJose.Borrego@Sun.COM 219*8334SJose.Borrego@Sun.COM clnt->heap = NULL; 220*8334SJose.Borrego@Sun.COM } 221*8334SJose.Borrego@Sun.COM 222*8334SJose.Borrego@Sun.COM /* 223*8334SJose.Borrego@Sun.COM * Returns true if the handle is null. 224*8334SJose.Borrego@Sun.COM * Otherwise returns false. 225*8334SJose.Borrego@Sun.COM */ 226*8334SJose.Borrego@Sun.COM boolean_t 227*8334SJose.Borrego@Sun.COM ndr_is_null_handle(mlsvc_handle_t *handle) 2285331Samw { 229*8334SJose.Borrego@Sun.COM static ndr_hdid_t zero_handle; 230*8334SJose.Borrego@Sun.COM 231*8334SJose.Borrego@Sun.COM if (handle == NULL || handle->clnt == NULL) 232*8334SJose.Borrego@Sun.COM return (B_TRUE); 233*8334SJose.Borrego@Sun.COM 234*8334SJose.Borrego@Sun.COM if (!memcmp(&handle->handle, &zero_handle, sizeof (ndr_hdid_t))) 235*8334SJose.Borrego@Sun.COM return (B_TRUE); 236*8334SJose.Borrego@Sun.COM 237*8334SJose.Borrego@Sun.COM return (B_FALSE); 238*8334SJose.Borrego@Sun.COM } 239*8334SJose.Borrego@Sun.COM 240*8334SJose.Borrego@Sun.COM /* 241*8334SJose.Borrego@Sun.COM * Returns true if the handle is the top level bind handle. 242*8334SJose.Borrego@Sun.COM * Otherwise returns false. 243*8334SJose.Borrego@Sun.COM */ 244*8334SJose.Borrego@Sun.COM boolean_t 245*8334SJose.Borrego@Sun.COM ndr_is_bind_handle(mlsvc_handle_t *handle) 246*8334SJose.Borrego@Sun.COM { 247*8334SJose.Borrego@Sun.COM return (handle->clnt->handle == &handle->handle); 2485331Samw } 2495331Samw 2505331Samw /* 251*8334SJose.Borrego@Sun.COM * Pass the client reference from parent to child. 2525331Samw */ 253*8334SJose.Borrego@Sun.COM void 254*8334SJose.Borrego@Sun.COM ndr_inherit_handle(mlsvc_handle_t *child, mlsvc_handle_t *parent) 255*8334SJose.Borrego@Sun.COM { 256*8334SJose.Borrego@Sun.COM child->clnt = parent->clnt; 257*8334SJose.Borrego@Sun.COM child->remote_os = parent->remote_os; 258*8334SJose.Borrego@Sun.COM } 259*8334SJose.Borrego@Sun.COM 260*8334SJose.Borrego@Sun.COM void 261*8334SJose.Borrego@Sun.COM ndr_rpc_status(mlsvc_handle_t *handle, int opnum, DWORD status) 2625331Samw { 263*8334SJose.Borrego@Sun.COM ndr_service_t *svc; 264*8334SJose.Borrego@Sun.COM char *name = "NDR RPC"; 265*8334SJose.Borrego@Sun.COM char *s = "unknown"; 266*8334SJose.Borrego@Sun.COM 267*8334SJose.Borrego@Sun.COM if (status == 0) 268*8334SJose.Borrego@Sun.COM s = "success"; 269*8334SJose.Borrego@Sun.COM else if (NT_SC_IS_ERROR(status)) 270*8334SJose.Borrego@Sun.COM s = "error"; 271*8334SJose.Borrego@Sun.COM else if (NT_SC_IS_WARNING(status)) 272*8334SJose.Borrego@Sun.COM s = "warning"; 273*8334SJose.Borrego@Sun.COM else if (NT_SC_IS_INFO(status)) 274*8334SJose.Borrego@Sun.COM s = "info"; 275*8334SJose.Borrego@Sun.COM 276*8334SJose.Borrego@Sun.COM if (handle) { 277*8334SJose.Borrego@Sun.COM svc = handle->clnt->binding->service; 278*8334SJose.Borrego@Sun.COM name = svc->name; 279*8334SJose.Borrego@Sun.COM } 2805331Samw 281*8334SJose.Borrego@Sun.COM smb_tracef("%s[0x%02x]: %s: %s (0x%08x)", 282*8334SJose.Borrego@Sun.COM name, opnum, s, xlate_nt_status(status), status); 283*8334SJose.Borrego@Sun.COM } 284*8334SJose.Borrego@Sun.COM 285*8334SJose.Borrego@Sun.COM /* 286*8334SJose.Borrego@Sun.COM * The following functions provide the client callback interface. 287*8334SJose.Borrego@Sun.COM * If the caller hasn't provided a heap, create one here. 288*8334SJose.Borrego@Sun.COM */ 289*8334SJose.Borrego@Sun.COM static int 290*8334SJose.Borrego@Sun.COM ndr_xa_init(ndr_client_t *clnt, ndr_xa_t *mxa) 291*8334SJose.Borrego@Sun.COM { 292*8334SJose.Borrego@Sun.COM ndr_stream_t *recv_nds = &mxa->recv_nds; 293*8334SJose.Borrego@Sun.COM ndr_stream_t *send_nds = &mxa->send_nds; 294*8334SJose.Borrego@Sun.COM ndr_heap_t *heap = clnt->heap; 295*8334SJose.Borrego@Sun.COM 296*8334SJose.Borrego@Sun.COM if (heap == NULL) { 297*8334SJose.Borrego@Sun.COM if ((heap = ndr_heap_create()) == NULL) 2985331Samw return (-1); 299*8334SJose.Borrego@Sun.COM 300*8334SJose.Borrego@Sun.COM clnt->heap = heap; 3015331Samw } 3025331Samw 3035331Samw mxa->heap = heap; 3045331Samw 305*8334SJose.Borrego@Sun.COM nds_initialize(send_nds, 0, NDR_MODE_CALL_SEND, heap); 306*8334SJose.Borrego@Sun.COM nds_initialize(recv_nds, 16 * 1024, NDR_MODE_RETURN_RECV, heap); 3075331Samw return (0); 3085331Samw } 3095331Samw 3105331Samw /* 3115331Samw * This is the entry pointy for an RPC client call exchange with 3125331Samw * a server, which will result in an smbrdr SmbTransact request. 3135331Samw * 3145331Samw * SmbTransact should return the number of bytes received, which 3155331Samw * we record as the PDU size, or a negative error code. 3165331Samw */ 3175331Samw static int 318*8334SJose.Borrego@Sun.COM ndr_xa_exchange(ndr_client_t *clnt, ndr_xa_t *mxa) 3195331Samw { 320*8334SJose.Borrego@Sun.COM ndr_stream_t *recv_nds = &mxa->recv_nds; 321*8334SJose.Borrego@Sun.COM ndr_stream_t *send_nds = &mxa->send_nds; 322*8334SJose.Borrego@Sun.COM int nbytes; 3235331Samw 324*8334SJose.Borrego@Sun.COM nbytes = smbrdr_transact(clnt->fid, 325*8334SJose.Borrego@Sun.COM (char *)send_nds->pdu_base_offset, send_nds->pdu_size, 326*8334SJose.Borrego@Sun.COM (char *)recv_nds->pdu_base_offset, recv_nds->pdu_max_size); 3275331Samw 328*8334SJose.Borrego@Sun.COM if (nbytes < 0) { 329*8334SJose.Borrego@Sun.COM recv_nds->pdu_size = 0; 330*8334SJose.Borrego@Sun.COM return (-1); 331*8334SJose.Borrego@Sun.COM } 3325331Samw 333*8334SJose.Borrego@Sun.COM recv_nds->pdu_size = nbytes; 334*8334SJose.Borrego@Sun.COM return (nbytes); 3355331Samw } 3365331Samw 3375331Samw /* 3385331Samw * This entry point will be invoked if the xa-exchange response contained 3395331Samw * only the first fragment of a multi-fragment response. The RPC client 3405331Samw * code will then make repeated xa-read requests to obtain the remaining 3415331Samw * fragments, which will result in smbrdr SmbReadX requests. 3425331Samw * 3435331Samw * SmbReadX should return the number of bytes received, in which case we 3445331Samw * expand the PDU size to include the received data, or a negative error 3455331Samw * code. 3465331Samw */ 3475331Samw static int 348*8334SJose.Borrego@Sun.COM ndr_xa_read(ndr_client_t *clnt, ndr_xa_t *mxa) 3495331Samw { 350*8334SJose.Borrego@Sun.COM ndr_stream_t *nds = &mxa->recv_nds; 3515331Samw int len; 352*8334SJose.Borrego@Sun.COM int nbytes; 3535331Samw 354*8334SJose.Borrego@Sun.COM if ((len = (nds->pdu_max_size - nds->pdu_size)) < 0) 3555331Samw return (-1); 3565331Samw 357*8334SJose.Borrego@Sun.COM nbytes = smbrdr_readx(clnt->fid, 358*8334SJose.Borrego@Sun.COM (char *)nds->pdu_base_offset + nds->pdu_size, len); 3595331Samw 360*8334SJose.Borrego@Sun.COM if (nbytes < 0) 3615331Samw return (-1); 3625331Samw 363*8334SJose.Borrego@Sun.COM nds->pdu_size += nbytes; 3645331Samw 365*8334SJose.Borrego@Sun.COM if (nds->pdu_size > nds->pdu_max_size) { 366*8334SJose.Borrego@Sun.COM nds->pdu_size = nds->pdu_max_size; 3675331Samw return (-1); 3685331Samw } 3695331Samw 370*8334SJose.Borrego@Sun.COM return (nbytes); 3715331Samw } 3725331Samw 3735331Samw /* 374*8334SJose.Borrego@Sun.COM * Preserve the heap so that the client application has access to data 375*8334SJose.Borrego@Sun.COM * returned from the server after an RPC call. 3765331Samw */ 377*8334SJose.Borrego@Sun.COM static void 378*8334SJose.Borrego@Sun.COM ndr_xa_preserve(ndr_client_t *clnt, ndr_xa_t *mxa) 3795331Samw { 380*8334SJose.Borrego@Sun.COM assert(clnt->heap == mxa->heap); 3815331Samw 382*8334SJose.Borrego@Sun.COM clnt->heap_preserved = B_TRUE; 3835331Samw mxa->heap = NULL; 3845331Samw } 3855331Samw 3865331Samw /* 387*8334SJose.Borrego@Sun.COM * Dispose of the transaction streams. If the heap has not been 388*8334SJose.Borrego@Sun.COM * preserved, we can destroy it here. 3895331Samw */ 390*8334SJose.Borrego@Sun.COM static void 391*8334SJose.Borrego@Sun.COM ndr_xa_destruct(ndr_client_t *clnt, ndr_xa_t *mxa) 3925331Samw { 393*8334SJose.Borrego@Sun.COM nds_destruct(&mxa->recv_nds); 394*8334SJose.Borrego@Sun.COM nds_destruct(&mxa->send_nds); 395*8334SJose.Borrego@Sun.COM 396*8334SJose.Borrego@Sun.COM if (!clnt->heap_preserved) { 397*8334SJose.Borrego@Sun.COM ndr_heap_destroy(mxa->heap); 398*8334SJose.Borrego@Sun.COM mxa->heap = NULL; 399*8334SJose.Borrego@Sun.COM clnt->heap = NULL; 4005331Samw } 4015331Samw } 4025331Samw 4035331Samw /* 404*8334SJose.Borrego@Sun.COM * Dispose of a preserved heap. 4055331Samw */ 4065331Samw static void 407*8334SJose.Borrego@Sun.COM ndr_xa_release(ndr_client_t *clnt) 4085331Samw { 409*8334SJose.Borrego@Sun.COM if (clnt->heap_preserved) { 410*8334SJose.Borrego@Sun.COM ndr_heap_destroy(clnt->heap); 411*8334SJose.Borrego@Sun.COM clnt->heap = NULL; 412*8334SJose.Borrego@Sun.COM clnt->heap_preserved = B_FALSE; 4135331Samw } 4145331Samw } 415