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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
24 */
25
26#ifndef	_LIBMLRPC_H
27#define	_LIBMLRPC_H
28
29#include <sys/types.h>
30#include <sys/uio.h>
31
32#include <smb/wintypes.h>
33#include <libmlrpc/ndr.h>
34
35#ifdef	__cplusplus
36extern "C" {
37#endif
38
39/*
40 * An MSRPC compatible implementation of OSF DCE RPC.  DCE RPC is derived
41 * from the Apollo Network Computing Architecture (NCA) RPC implementation.
42 *
43 * CAE Specification (1997)
44 * DCE 1.1: Remote Procedure Call
45 * Document Number: C706
46 * The Open Group
47 * ogspecs@opengroup.org
48 *
49 * This implementation is based on the DCE Remote Procedure Call spec with
50 * enhancements to support Unicode strings.  The diagram below shows the
51 * DCE RPC layers compared against ONC SUN RPC.
52 *
53 *	NDR RPC Layers		Sun RPC Layers		Remark
54 *	+---------------+	+---------------+	+---------------+
55 *	+---------------+	+---------------+
56 *	| Application	|	| Application	|	The application
57 *	+---------------+	+---------------+
58 *	| Hand coded    |	| RPCGEN gen'd  |	Where the real
59 *	| client/server |	| client/server |	work happens
60 *	| srvsvc.ndl	|	| *_svc.c *_clnt|
61 *	| srvsvc.c	|	|               |
62 *	+---------------+	+---------------+
63 *	| RPC Library	|	| RPC Library   |	Calls/Return
64 *	| ndr_*.c       |	|               |	Binding/PMAP
65 *	+---------------+	+---------------+
66 *	| RPC Protocol	|	| RPC Protocol  |	Headers, Auth,
67 *	| rpcpdu.ndl    |	|               |
68 *	+---------------+	+---------------+
69 *	| IDL gen'd	|	| RPCGEN gen'd  |	Aggregate
70 *	| NDR stubs	|	| XDR stubs     |	Composition
71 *	| *__ndr.c      |	| *_xdr.c       |
72 *	+---------------+	+---------------+
73 *	| NDR Represen	|	| XDR Represen  |	Byte order, padding
74 *	+---------------+	+---------------+
75 *	| Packet Heaps  |	| Network Conn  |	DCERPC does not talk
76 *	| ndo_*.c       |	| clnt_{tcp,udp}|	directly to network.
77 *	+---------------+	+---------------+
78 *
79 * There are two major differences between the DCE RPC and ONC RPC:
80 *
81 * 1. NDR RPC only generates or processes packets from buffers.  Other
82 *    layers must take care of packet transmission and reception.
83 *    The packet heaps are managed through a simple interface provided
84 *    by the Network Data Representation (NDR) module called ndr_stream_t.
85 *    ndo_*.c modules implement the different flavors (operations) of
86 *    packet heaps.
87 *
88 *    ONC RPC communicates directly with the network.  You have to do
89 *    something special for the RPC packet to be placed in a buffer
90 *    rather than sent to the wire.
91 *
92 * 2. NDR RPC uses application provided heaps to support operations.
93 *    A heap is a single, monolithic chunk of memory that NDR RPC manages
94 *    as it allocates.  When the operation and its result are done, the
95 *    heap is disposed of as a single item.  The transaction, which
96 *    is the anchor of most operations, contains the necessary book-
97 *    keeping for the heap.
98 *
99 *    ONC RPC uses malloc() liberally throughout its run-time system.
100 *    To free results, ONC RPC supports an XDR_FREE operation that
101 *    traverses data structures freeing memory as it goes, whether
102 *    it was malloc'd or not.
103 */
104
105/*
106 * Dispatch Return Code (DRC)
107 *
108 *	0x8000	15:01	Set to indicate a fault, clear indicates status
109 *	0x7F00	08:07	Status/Fault specific
110 *	0x00FF	00:08	PTYPE_... of PDU, 0xFF for header
111 */
112#define	NDR_DRC_OK				0x0000
113#define	NDR_DRC_MASK_FAULT			0x8000
114#define	NDR_DRC_MASK_SPECIFIER			0xFF00
115#define	NDR_DRC_MASK_PTYPE			0x00FF
116
117/* Fake PTYPE DRC discriminators */
118#define	NDR_DRC_PTYPE_RPCHDR(DRC)		((DRC) | 0x00FF)
119#define	NDR_DRC_PTYPE_API(DRC)			((DRC) | 0x00AA)
120
121/* DRC Recognizers */
122#define	NDR_DRC_IS_OK(DRC)	(((DRC) & NDR_DRC_MASK_SPECIFIER) == 0)
123#define	NDR_DRC_IS_FAULT(DRC)	(((DRC) & NDR_DRC_MASK_FAULT) != 0)
124
125/*
126 * (Un)Marshalling category specifiers
127 */
128#define	NDR_DRC_FAULT_MODE_MISMATCH		0x8100
129#define	NDR_DRC_RECEIVED			0x0200
130#define	NDR_DRC_FAULT_RECEIVED_RUNT		0x8300
131#define	NDR_DRC_FAULT_RECEIVED_MALFORMED	0x8400
132#define	NDR_DRC_DECODED				0x0500
133#define	NDR_DRC_FAULT_DECODE_FAILED		0x8600
134#define	NDR_DRC_ENCODED				0x0700
135#define	NDR_DRC_FAULT_ENCODE_FAILED		0x8800
136#define	NDR_DRC_FAULT_ENCODE_TOO_BIG		0x8900
137#define	NDR_DRC_SENT				0x0A00
138#define	NDR_DRC_FAULT_SEND_FAILED		0x8B00
139
140/*
141 * Resource category specifier
142 */
143#define	NDR_DRC_FAULT_RESOURCE_1		0x9100
144#define	NDR_DRC_FAULT_RESOURCE_2		0x9200
145
146/*
147 * Parameters. Usually #define'd with useful alias
148 */
149#define	NDR_DRC_FAULT_PARAM_0_INVALID		0xC000
150#define	NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED	0xD000
151#define	NDR_DRC_FAULT_PARAM_1_INVALID		0xC100
152#define	NDR_DRC_FAULT_PARAM_1_UNIMPLEMENTED	0xD100
153#define	NDR_DRC_FAULT_PARAM_2_INVALID		0xC200
154#define	NDR_DRC_FAULT_PARAM_2_UNIMPLEMENTED	0xD200
155#define	NDR_DRC_FAULT_PARAM_3_INVALID		0xC300
156#define	NDR_DRC_FAULT_PARAM_3_UNIMPLEMENTED	0xD300
157
158#define	NDR_DRC_FAULT_OUT_OF_MEMORY		0xF000
159
160/* RPCHDR */
161#define	NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH	0x81FF
162#define	NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT	0x83FF
163#define	NDR_DRC_FAULT_RPCHDR_DECODE_FAILED	0x86FF
164#define	NDR_DRC_FAULT_RPCHDR_PTYPE_INVALID	0xC0FF	/* PARAM_0_INVALID */
165#define	NDR_DRC_FAULT_RPCHDR_PTYPE_UNIMPLEMENTED 0xD0FF	/* PARAM_0_UNIMP */
166
167/* Request */
168#define	NDR_DRC_FAULT_REQUEST_PCONT_INVALID	0xC000	/* PARAM_0_INVALID */
169#define	NDR_DRC_FAULT_REQUEST_OPNUM_INVALID	0xC100	/* PARAM_1_INVALID */
170
171/* Bind */
172#define	NDR_DRC_BINDING_MADE			0x000B	/* OK */
173#define	NDR_DRC_FAULT_BIND_PCONT_BUSY		0xC00B	/* PARAM_0_INVALID */
174#define	NDR_DRC_FAULT_BIND_UNKNOWN_SERVICE	0xC10B	/* PARAM_1_INVALID */
175#define	NDR_DRC_FAULT_BIND_NO_SLOTS		0x910B	/* RESOURCE_1 */
176
177/* API */
178#define	NDR_DRC_FAULT_API_SERVICE_INVALID	0xC0AA	/* PARAM_0_INVALID */
179#define	NDR_DRC_FAULT_API_BIND_NO_SLOTS		0x91AA	/* RESOURCE_1 */
180#define	NDR_DRC_FAULT_API_OPNUM_INVALID		0xC1AA	/* PARAM_1_INVALID */
181
182struct ndr_xa;
183struct ndr_client;
184
185typedef struct ndr_stub_table {
186	int		(*func)(void *, struct ndr_xa *);
187	unsigned short	opnum;
188} ndr_stub_table_t;
189
190typedef struct ndr_service {
191	char		*name;
192	char		*desc;
193	char		*endpoint;
194	char		*sec_addr_port;
195	char		*abstract_syntax_uuid;
196	int		abstract_syntax_version;
197	char		*transfer_syntax_uuid;
198	int		transfer_syntax_version;
199	unsigned	bind_instance_size;
200	int		(*bind_req)();
201	int		(*unbind_and_close)();
202	int		(*call_stub)(struct ndr_xa *);
203	ndr_typeinfo_t	*interface_ti;
204	ndr_stub_table_t *stub_table;
205} ndr_service_t;
206
207/*
208 * The list of bindings is anchored at a connection.  Nothing in the
209 * RPC mechanism allocates them.  Binding elements which have service==0
210 * indicate free elements.  When a connection is instantiated, at least
211 * one free binding entry should also be established.  Something like
212 * this should suffice for most (all) situations:
213 *
214 *	struct connection {
215 *		....
216 *		ndr_binding_t *binding_list_head;
217 *		ndr_binding_t binding_pool[N_BINDING_POOL];
218 *		....
219 *	};
220 *
221 *	init_connection(struct connection *conn) {
222 *		....
223 *		ndr_svc_binding_pool_init(&conn->binding_list_head,
224 *		    conn->binding_pool, N_BINDING_POOL);
225 */
226typedef struct ndr_binding {
227	struct ndr_binding 	*next;
228	ndr_p_context_id_t	p_cont_id;
229	unsigned char		which_side;
230	struct ndr_client	*clnt;
231	ndr_service_t		*service;
232	void 			*instance_specific;
233} ndr_binding_t;
234
235#define	NDR_BIND_SIDE_CLIENT	1
236#define	NDR_BIND_SIDE_SERVER	2
237
238#define	NDR_BINDING_TO_SPECIFIC(BINDING, TYPE) \
239	((TYPE *) (BINDING)->instance_specific)
240
241/*
242 * The binding list space must be provided by the application library
243 * for use by the underlying RPC library.  We need at least two binding
244 * slots per connection.
245 */
246#define	NDR_N_BINDING_POOL	2
247
248typedef struct ndr_pipe {
249	void			*np_listener;
250	const char		*np_endpoint;
251	struct smb_netuserinfo	*np_user;
252	int			(*np_send)(struct ndr_pipe *, void *, size_t);
253	int			(*np_recv)(struct ndr_pipe *, void *, size_t);
254	int			np_fid;
255	uint16_t		np_max_xmit_frag;
256	uint16_t		np_max_recv_frag;
257	ndr_binding_t		*np_binding;
258	ndr_binding_t		np_binding_pool[NDR_N_BINDING_POOL];
259} ndr_pipe_t;
260
261/*
262 * Number of bytes required to align SIZE on the next dword/4-byte
263 * boundary.
264 */
265#define	NDR_ALIGN4(SIZE)	((4 - (SIZE)) & 3);
266
267/*
268 * DCE RPC strings (CAE section 14.3.4) are represented as varying or varying
269 * and conformant one-dimensional arrays. Characters can be single-byte
270 * or multi-byte as long as all characters conform to a fixed element size,
271 * i.e. UCS-2 is okay but UTF-8 is not a valid DCE RPC string format. The
272 * string is terminated by a null character of the appropriate element size.
273 *
274 * MSRPC strings should always be varying/conformant and not null terminated.
275 * This format uses the size_is, first_is and length_is attributes (CAE
276 * section 4.2.18).
277 *
278 *	typedef struct string {
279 *		DWORD size_is;
280 *		DWORD first_is;
281 *		DWORD length_is;
282 *		wchar_t string[ANY_SIZE_ARRAY];
283 *	} string_t;
284 *
285 * The size_is attribute is used to specify the number of data elements in
286 * each dimension of an array.
287 *
288 * The first_is attribute is used to define the lower bound for significant
289 * elements in each dimension of an array. For strings this is always 0.
290 *
291 * The length_is attribute is used to define the number of significant
292 * elements in each dimension of an array. For strings this is typically
293 * the same as size_is. Although it might be (size_is - 1) if the string
294 * is null terminated.
295 *
296 *   4 bytes   4 bytes   4 bytes  2bytes 2bytes 2bytes 2bytes
297 * +---------+---------+---------+------+------+------+------+
298 * |size_is  |first_is |length_is| char | char | char | char |
299 * +---------+---------+---------+------+------+------+------+
300 *
301 * Unfortunately, not all MSRPC Unicode strings are null terminated, which
302 * means that the recipient has to manually null-terminate the string after
303 * it has been unmarshalled.  There may be a wide-char pad following a
304 * string, and it may sometimes contains zero, but it's not guaranteed.
305 *
306 * To deal with this, MSRPC sometimes uses an additional wrapper with two
307 * more fields, as shown below.
308 *	length: the array length in bytes excluding terminating null bytes
309 *	maxlen: the array length in bytes including null terminator bytes
310 *	LPTSTR: converted to a string_t by NDR
311 *
312 * typedef struct ms_string {
313 *		WORD length;
314 *		WORD maxlen;
315 *		LPTSTR str;
316 * } ms_string_t;
317 */
318typedef struct ndr_mstring {
319	uint16_t length;
320	uint16_t allosize;
321	LPTSTR str;
322} ndr_mstring_t;
323
324/*
325 * A number of heap areas are used during marshalling and unmarshalling.
326 * Under some circumstances these areas can be discarded by the library
327 * code, i.e. on the server side before returning to the client and on
328 * completion of a client side bind.  In the case of a client side RPC
329 * call, these areas must be preserved after an RPC returns to give the
330 * caller time to take a copy of the data.  In this case the client must
331 * call ndr_clnt_free_heap to free the memory.
332 *
333 * The heap management data definition looks a bit like this:
334 *
335 * heap -> +---------------+     +------------+
336 *         | iovec[0].base | --> | data block |
337 *         | iovec[0].len  |     +------------+
338 *         +---------------+
339 *                ::
340 *                ::
341 * iov  -> +---------------+     +------------+
342 *         | iovec[n].base | --> | data block |
343 *         | iovec[n].len  |     +------------+
344 *         +---------------+     ^            ^
345 *                               |            |
346 *    next ----------------------+            |
347 *    top  -----------------------------------+
348 *
349 */
350
351/*
352 * Setting MAXIOV to 384 will use ((8 * 384) + 16) = 3088 bytes
353 * of the first heap block.
354 */
355#define	NDR_HEAP_MAXIOV		384
356#define	NDR_HEAP_BLKSZ		8192
357
358typedef struct ndr_heap {
359	struct iovec iovec[NDR_HEAP_MAXIOV];
360	struct iovec *iov;
361	int iovcnt;
362	char *top;
363	char *next;
364} ndr_heap_t;
365
366/*
367 * Alternate varying/conformant string definition
368 * - for non-null-terminated strings.
369 */
370typedef struct ndr_vcs {
371	/*
372	 * size_is (actually a copy of length_is) will
373	 * be inserted here by the marshalling library.
374	 */
375	uint32_t vc_first_is;
376	uint32_t vc_length_is;
377	uint16_t buffer[ANY_SIZE_ARRAY];
378} ndr_vcs_t;
379
380typedef struct ndr_vcstr {
381	uint16_t wclen;
382	uint16_t wcsize;
383	ndr_vcs_t *vcs;
384} ndr_vcstr_t;
385
386typedef struct ndr_vcb {
387	/*
388	 * size_is (actually a copy of length_is) will
389	 * be inserted here by the marshalling library.
390	 */
391	uint32_t vc_first_is;
392	uint32_t vc_length_is;
393	uint8_t buffer[ANY_SIZE_ARRAY];
394} ndr_vcb_t;
395
396typedef struct ndr_vcbuf {
397	uint16_t len;
398	uint16_t size;
399	ndr_vcb_t *vcb;
400} ndr_vcbuf_t;
401
402ndr_heap_t *ndr_heap_create(void);
403void ndr_heap_destroy(ndr_heap_t *);
404void *ndr_heap_dupmem(ndr_heap_t *, const void *, size_t);
405void *ndr_heap_malloc(ndr_heap_t *, unsigned);
406void *ndr_heap_strdup(ndr_heap_t *, const char *);
407int ndr_heap_mstring(ndr_heap_t *, const char *, ndr_mstring_t *);
408void ndr_heap_mkvcs(ndr_heap_t *, char *, ndr_vcstr_t *);
409void ndr_heap_mkvcb(ndr_heap_t *, uint8_t *, uint32_t, ndr_vcbuf_t *);
410int ndr_heap_used(ndr_heap_t *);
411int ndr_heap_avail(ndr_heap_t *);
412
413#define	NDR_MALLOC(XA, SZ)	ndr_heap_malloc((XA)->heap, SZ)
414#define	NDR_NEW(XA, T)		ndr_heap_malloc((XA)->heap, sizeof (T))
415#define	NDR_NEWN(XA, T, N)	ndr_heap_malloc((XA)->heap, sizeof (T)*(N))
416#define	NDR_STRDUP(XA, S)	ndr_heap_strdup((XA)->heap, (S))
417#define	NDR_MSTRING(XA, S, OUT)	ndr_heap_mstring((XA)->heap, (S), (OUT))
418#define	NDR_SIDDUP(XA, S)	ndr_heap_dupmem((XA)->heap, (S), smb_sid_len(S))
419
420typedef struct ndr_xa {
421	unsigned short		ptype;		/* high bits special */
422	unsigned short		opnum;
423	ndr_stream_t		recv_nds;
424	ndr_hdr_t		recv_hdr;
425	ndr_stream_t		send_nds;
426	ndr_hdr_t		send_hdr;
427	ndr_binding_t		*binding;	/* what we're using */
428	ndr_binding_t		*binding_list;	/* from connection */
429	ndr_heap_t		*heap;
430	ndr_pipe_t		*pipe;
431} ndr_xa_t;
432
433/*
434 * 20-byte opaque id used by various RPC services.
435 */
436CONTEXT_HANDLE(ndr_hdid) ndr_hdid_t;
437
438typedef struct ndr_client {
439	/* transport stuff (xa_* members) */
440	int (*xa_init)(struct ndr_client *, ndr_xa_t *);
441	int (*xa_exchange)(struct ndr_client *, ndr_xa_t *);
442	int (*xa_read)(struct ndr_client *, ndr_xa_t *);
443	void (*xa_preserve)(struct ndr_client *, ndr_xa_t *);
444	void (*xa_destruct)(struct ndr_client *, ndr_xa_t *);
445	void (*xa_release)(struct ndr_client *);
446	void			*xa_private;
447	int			xa_fd;
448
449	ndr_hdid_t		*handle;
450	ndr_binding_t		*binding;
451	ndr_binding_t		*binding_list;
452	ndr_binding_t		binding_pool[NDR_N_BINDING_POOL];
453
454	boolean_t		nonull;
455	boolean_t		heap_preserved;
456	ndr_heap_t		*heap;
457	ndr_stream_t		*recv_nds;
458	ndr_stream_t		*send_nds;
459
460	uint32_t		next_call_id;
461	unsigned		next_p_cont_id;
462} ndr_client_t;
463
464typedef struct ndr_handle {
465	ndr_hdid_t		nh_id;
466	struct ndr_handle	*nh_next;
467	ndr_pipe_t		*nh_pipe;
468	const ndr_service_t	*nh_svc;
469	ndr_client_t		*nh_clnt;
470	void			*nh_data;
471	void			(*nh_data_free)(void *);
472} ndr_handle_t;
473
474#define	NDR_PDU_SIZE_HINT_DEFAULT	(16*1024)
475#define	NDR_BUF_MAGIC			0x4E425546	/* NBUF */
476
477typedef struct ndr_buf {
478	uint32_t		nb_magic;
479	ndr_stream_t		nb_nds;
480	ndr_heap_t		*nb_heap;
481	ndr_typeinfo_t		*nb_ti;
482} ndr_buf_t;
483
484/* ndr_ops.c */
485int nds_initialize(ndr_stream_t *, unsigned, int, ndr_heap_t *);
486void nds_destruct(ndr_stream_t *);
487void nds_show_state(ndr_stream_t *);
488
489/* ndr_client.c */
490int ndr_clnt_bind(ndr_client_t *, ndr_service_t *, ndr_binding_t **);
491int ndr_clnt_call(ndr_binding_t *, int, void *);
492void ndr_clnt_free_heap(ndr_client_t *);
493
494/* ndr_marshal.c */
495ndr_buf_t *ndr_buf_init(ndr_typeinfo_t *);
496void ndr_buf_fini(ndr_buf_t *);
497int ndr_buf_decode(ndr_buf_t *, unsigned, unsigned, const char *data, size_t,
498    void *);
499int ndr_decode_call(ndr_xa_t *, void *);
500int ndr_encode_return(ndr_xa_t *, void *);
501int ndr_encode_call(ndr_xa_t *, void *);
502int ndr_decode_return(ndr_xa_t *, void *);
503int ndr_decode_pdu_hdr(ndr_xa_t *);
504int ndr_encode_pdu_hdr(ndr_xa_t *);
505void ndr_decode_frag_hdr(ndr_stream_t *, ndr_common_header_t *);
506void ndr_remove_frag_hdr(ndr_stream_t *);
507void ndr_show_hdr(ndr_common_header_t *);
508unsigned ndr_bind_ack_hdr_size(ndr_xa_t *);
509unsigned ndr_alter_context_rsp_hdr_size(void);
510
511/* ndr_server.c */
512void ndr_pipe_worker(ndr_pipe_t *);
513
514int ndr_generic_call_stub(ndr_xa_t *);
515
516/* ndr_svc.c */
517ndr_stub_table_t *ndr_svc_find_stub(ndr_service_t *, int);
518ndr_service_t *ndr_svc_lookup_name(const char *);
519ndr_service_t *ndr_svc_lookup_uuid(ndr_uuid_t *, int, ndr_uuid_t *, int);
520int ndr_svc_register(ndr_service_t *);
521void ndr_svc_unregister(ndr_service_t *);
522void ndr_svc_binding_pool_init(ndr_binding_t **, ndr_binding_t pool[], int);
523ndr_binding_t *ndr_svc_find_binding(ndr_xa_t *, ndr_p_context_id_t);
524ndr_binding_t *ndr_svc_new_binding(ndr_xa_t *);
525
526int ndr_uuid_parse(char *, ndr_uuid_t *);
527void ndr_uuid_unparse(ndr_uuid_t *, char *);
528
529ndr_hdid_t *ndr_hdalloc(const ndr_xa_t *, const void *);
530void ndr_hdfree(const ndr_xa_t *, const ndr_hdid_t *);
531ndr_handle_t *ndr_hdlookup(const ndr_xa_t *, const ndr_hdid_t *);
532void ndr_hdclose(ndr_pipe_t *);
533
534ssize_t ndr_uiomove(caddr_t, size_t, enum uio_rw, struct uio *);
535
536/*
537 * An ndr_client_t is created while binding a client connection to hold
538 * the context for calls made using that connection.
539 *
540 * Handles are RPC call specific and we use an inheritance mechanism to
541 * ensure that each handle has a pointer to the client_t.  When the top
542 * level (bind) handle is released, we close the connection.
543 *
544 * There are some places in libmlsvc where the code assumes that the
545 * handle member is first in this struct.  careful
546 */
547typedef struct mlrpc_handle {
548	ndr_hdid_t	handle;		/* keep first */
549	ndr_client_t	*clnt;
550} mlrpc_handle_t;
551
552int mlrpc_clh_create(mlrpc_handle_t *, void *);
553uint32_t mlrpc_clh_bind(mlrpc_handle_t *, ndr_service_t *);
554void mlrpc_clh_unbind(mlrpc_handle_t *);
555void *mlrpc_clh_free(mlrpc_handle_t *);
556
557int ndr_rpc_call(mlrpc_handle_t *, int, void *);
558int ndr_rpc_get_ssnkey(mlrpc_handle_t *, unsigned char *, size_t);
559void *ndr_rpc_malloc(mlrpc_handle_t *, size_t);
560ndr_heap_t *ndr_rpc_get_heap(mlrpc_handle_t *);
561void ndr_rpc_release(mlrpc_handle_t *);
562void ndr_rpc_set_nonull(mlrpc_handle_t *);
563
564boolean_t ndr_is_null_handle(mlrpc_handle_t *);
565boolean_t ndr_is_bind_handle(mlrpc_handle_t *);
566void ndr_inherit_handle(mlrpc_handle_t *, mlrpc_handle_t *);
567
568#ifdef	__cplusplus
569}
570#endif
571
572#endif	/* _LIBMLRPC_H */
573