xref: /illumos-gate/usr/src/lib/libmlrpc/common/libmlrpc.h (revision 6ff4183c538023f1acb277f9d3b05296bb816e66)
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 2020 Tintri by DDN, 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
36 extern "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 #define	NDR_DRC_PTYPE_SEC(DRC)			((DRC) | 0x00CC)
121 
122 /* DRC Recognizers */
123 #define	NDR_DRC_IS_OK(DRC)	(((DRC) & NDR_DRC_MASK_SPECIFIER) == 0)
124 #define	NDR_DRC_IS_FAULT(DRC)	(((DRC) & NDR_DRC_MASK_FAULT) != 0)
125 
126 /*
127  * (Un)Marshalling category specifiers
128  */
129 #define	NDR_DRC_FAULT_MODE_MISMATCH		0x8100
130 #define	NDR_DRC_RECEIVED			0x0200
131 #define	NDR_DRC_FAULT_RECEIVED_RUNT		0x8300
132 #define	NDR_DRC_FAULT_RECEIVED_MALFORMED	0x8400
133 #define	NDR_DRC_DECODED				0x0500
134 #define	NDR_DRC_FAULT_DECODE_FAILED		0x8600
135 #define	NDR_DRC_ENCODED				0x0700
136 #define	NDR_DRC_FAULT_ENCODE_FAILED		0x8800
137 #define	NDR_DRC_FAULT_ENCODE_TOO_BIG		0x8900
138 #define	NDR_DRC_SENT				0x0A00
139 #define	NDR_DRC_FAULT_SEND_FAILED		0x8B00
140 
141 /*
142  * Resource category specifier
143  */
144 #define	NDR_DRC_FAULT_RESOURCE_1		0x9100
145 #define	NDR_DRC_FAULT_RESOURCE_2		0x9200
146 
147 /*
148  * Parameters. Usually #define'd with useful alias
149  */
150 #define	NDR_DRC_FAULT_PARAM_0_INVALID		0xC000
151 #define	NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED	0xD000
152 #define	NDR_DRC_FAULT_PARAM_1_INVALID		0xC100
153 #define	NDR_DRC_FAULT_PARAM_1_UNIMPLEMENTED	0xD100
154 #define	NDR_DRC_FAULT_PARAM_2_INVALID		0xC200
155 #define	NDR_DRC_FAULT_PARAM_2_UNIMPLEMENTED	0xD200
156 #define	NDR_DRC_FAULT_PARAM_3_INVALID		0xC300
157 #define	NDR_DRC_FAULT_PARAM_3_UNIMPLEMENTED	0xD300
158 #define	NDR_DRC_FAULT_PARAM_4_INVALID		0xC400
159 #define	NDR_DRC_FAULT_PARAM_4_UNIMPLEMENTED	0xD400
160 #define	NDR_DRC_FAULT_PARAM_5_INVALID		0xC500
161 #define	NDR_DRC_FAULT_PARAM_5_UNIMPLEMENTED	0xD500
162 
163 #define	NDR_DRC_FAULT_OUT_OF_MEMORY		0xF000
164 
165 /* RPCHDR */
166 #define	NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH	0x81FF
167 #define	NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT	0x83FF
168 #define	NDR_DRC_FAULT_RPCHDR_DECODE_FAILED	0x86FF
169 #define	NDR_DRC_FAULT_RPCHDR_PTYPE_INVALID	0xC0FF	/* PARAM_0_INVALID */
170 #define	NDR_DRC_FAULT_RPCHDR_PTYPE_UNIMPLEMENTED 0xD0FF	/* PARAM_0_UNIMP */
171 
172 /* Request */
173 #define	NDR_DRC_FAULT_REQUEST_PCONT_INVALID	0xC000	/* PARAM_0_INVALID */
174 #define	NDR_DRC_FAULT_REQUEST_OPNUM_INVALID	0xC100	/* PARAM_1_INVALID */
175 
176 /* Bind */
177 #define	NDR_DRC_BINDING_MADE			0x000B	/* OK */
178 #define	NDR_DRC_FAULT_BIND_PCONT_BUSY		0xC00B	/* PARAM_0_INVALID */
179 #define	NDR_DRC_FAULT_BIND_UNKNOWN_SERVICE	0xC10B	/* PARAM_1_INVALID */
180 #define	NDR_DRC_FAULT_BIND_NO_SLOTS		0x910B	/* RESOURCE_1 */
181 
182 /* API */
183 #define	NDR_DRC_FAULT_API_SERVICE_INVALID	0xC0AA	/* PARAM_0_INVALID */
184 #define	NDR_DRC_FAULT_API_BIND_NO_SLOTS		0x91AA	/* RESOURCE_1 */
185 #define	NDR_DRC_FAULT_API_OPNUM_INVALID		0xC1AA	/* PARAM_1_INVALID */
186 
187 /* Secure RPC and SSPs */
188 #define	NDR_DRC_FAULT_SEC_TYPE_UNIMPLEMENTED	\
189     NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED)
190 #define	NDR_DRC_FAULT_SEC_LEVEL_UNIMPLEMENTED	\
191     NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_PARAM_1_UNIMPLEMENTED)
192 #define	NDR_DRC_FAULT_SEC_SSP_FAILED		\
193     NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_RESOURCE_1)
194 #define	NDR_DRC_FAULT_SEC_ENCODE_TOO_BIG	\
195     NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_ENCODE_TOO_BIG)
196 #define	NDR_DRC_FAULT_SEC_AUTH_LENGTH_INVALID	\
197     NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_PARAM_2_INVALID)
198 #define	NDR_DRC_FAULT_SEC_AUTH_TYPE_INVALID	\
199     NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_PARAM_0_INVALID)
200 #define	NDR_DRC_FAULT_SEC_AUTH_LEVEL_INVALID	\
201     NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_PARAM_1_INVALID)
202 #define	NDR_DRC_FAULT_SEC_OUT_OF_MEMORY		\
203     NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_OUT_OF_MEMORY)
204 #define	NDR_DRC_FAULT_SEC_ENCODE_FAILED		\
205     NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_ENCODE_FAILED)
206 #define	NDR_DRC_FAULT_SEC_META_INVALID		\
207     NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_PARAM_3_INVALID)
208 #define	NDR_DRC_FAULT_SEC_SEQNUM_INVALID	\
209     NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_PARAM_4_INVALID)
210 #define	NDR_DRC_FAULT_SEC_SIG_INVALID		\
211     NDR_DRC_PTYPE_SEC(NDR_DRC_FAULT_PARAM_5_INVALID)
212 
213 struct ndr_xa;
214 struct ndr_client;
215 
216 typedef struct ndr_stub_table {
217 	int		(*func)(void *, struct ndr_xa *);
218 	unsigned short	opnum;
219 } ndr_stub_table_t;
220 
221 typedef struct ndr_service {
222 	char		*name;
223 	char		*desc;
224 	char		*endpoint;
225 	char		*sec_addr_port;
226 	char		*abstract_syntax_uuid;
227 	int		abstract_syntax_version;
228 	char		*transfer_syntax_uuid;
229 	int		transfer_syntax_version;
230 	unsigned	bind_instance_size;
231 	int		(*bind_req)();
232 	int		(*unbind_and_close)();
233 	int		(*call_stub)(struct ndr_xa *);
234 	ndr_typeinfo_t	*interface_ti;
235 	ndr_stub_table_t *stub_table;
236 } ndr_service_t;
237 
238 /*
239  * The list of bindings is anchored at a connection.  Nothing in the
240  * RPC mechanism allocates them.  Binding elements which have service==0
241  * indicate free elements.  When a connection is instantiated, at least
242  * one free binding entry should also be established.  Something like
243  * this should suffice for most (all) situations:
244  *
245  *	struct connection {
246  *		....
247  *		ndr_binding_t *binding_list_head;
248  *		ndr_binding_t binding_pool[N_BINDING_POOL];
249  *		....
250  *	};
251  *
252  *	init_connection(struct connection *conn) {
253  *		....
254  *		ndr_svc_binding_pool_init(&conn->binding_list_head,
255  *		    conn->binding_pool, N_BINDING_POOL);
256  */
257 typedef struct ndr_binding {
258 	struct ndr_binding	*next;
259 	ndr_p_context_id_t	p_cont_id;
260 	unsigned char		which_side;
261 	struct ndr_client	*clnt;
262 	ndr_service_t		*service;
263 	void			*instance_specific;
264 } ndr_binding_t;
265 
266 #define	NDR_BIND_SIDE_CLIENT	1
267 #define	NDR_BIND_SIDE_SERVER	2
268 
269 #define	NDR_BINDING_TO_SPECIFIC(BINDING, TYPE) \
270 	((TYPE *) (BINDING)->instance_specific)
271 
272 /*
273  * The binding list space must be provided by the application library
274  * for use by the underlying RPC library.  We need at least two binding
275  * slots per connection.
276  */
277 #define	NDR_N_BINDING_POOL	2
278 
279 typedef struct ndr_pipe {
280 	void			*np_listener;
281 	const char		*np_endpoint;
282 	struct smb_netuserinfo	*np_user;
283 	int			(*np_send)(struct ndr_pipe *, void *, size_t);
284 	int			(*np_recv)(struct ndr_pipe *, void *, size_t);
285 	int			np_fid;
286 	uint16_t		np_max_xmit_frag;
287 	uint16_t		np_max_recv_frag;
288 	ndr_binding_t		*np_binding;
289 	ndr_binding_t		np_binding_pool[NDR_N_BINDING_POOL];
290 } ndr_pipe_t;
291 
292 /*
293  * Number of bytes required to align SIZE on the next dword/4-byte
294  * boundary.
295  */
296 #define	NDR_ALIGN4(SIZE)	((4 - (SIZE)) & 3);
297 
298 /*
299  * DCE RPC strings (CAE section 14.3.4) are represented as varying or varying
300  * and conformant one-dimensional arrays. Characters can be single-byte
301  * or multi-byte as long as all characters conform to a fixed element size,
302  * i.e. UCS-2 is okay but UTF-8 is not a valid DCE RPC string format. The
303  * string is terminated by a null character of the appropriate element size.
304  *
305  * MSRPC strings should always be varying/conformant and not null terminated.
306  * This format uses the size_is, first_is and length_is attributes (CAE
307  * section 4.2.18).
308  *
309  *	typedef struct string {
310  *		DWORD size_is;
311  *		DWORD first_is;
312  *		DWORD length_is;
313  *		wchar_t string[ANY_SIZE_ARRAY];
314  *	} string_t;
315  *
316  * The size_is attribute is used to specify the number of data elements in
317  * each dimension of an array.
318  *
319  * The first_is attribute is used to define the lower bound for significant
320  * elements in each dimension of an array. For strings this is always 0.
321  *
322  * The length_is attribute is used to define the number of significant
323  * elements in each dimension of an array. For strings this is typically
324  * the same as size_is. Although it might be (size_is - 1) if the string
325  * is null terminated.
326  *
327  *   4 bytes   4 bytes   4 bytes  2bytes 2bytes 2bytes 2bytes
328  * +---------+---------+---------+------+------+------+------+
329  * |size_is  |first_is |length_is| char | char | char | char |
330  * +---------+---------+---------+------+------+------+------+
331  *
332  * Unfortunately, not all MSRPC Unicode strings are null terminated, which
333  * means that the recipient has to manually null-terminate the string after
334  * it has been unmarshalled.  There may be a wide-char pad following a
335  * string, and it may sometimes contains zero, but it's not guaranteed.
336  *
337  * To deal with this, MSRPC sometimes uses an additional wrapper with two
338  * more fields, as shown below.
339  *	length: the array length in bytes excluding terminating null bytes
340  *	maxlen: the array length in bytes including null terminator bytes
341  *	LPTSTR: converted to a string_t by NDR
342  *
343  * typedef struct ms_string {
344  *		WORD length;
345  *		WORD maxlen;
346  *		LPTSTR str;
347  * } ms_string_t;
348  */
349 typedef struct ndr_mstring {
350 	uint16_t length;
351 	uint16_t allosize;
352 	LPTSTR str;
353 } ndr_mstring_t;
354 
355 /*
356  * A number of heap areas are used during marshalling and unmarshalling.
357  * Under some circumstances these areas can be discarded by the library
358  * code, i.e. on the server side before returning to the client and on
359  * completion of a client side bind.  In the case of a client side RPC
360  * call, these areas must be preserved after an RPC returns to give the
361  * caller time to take a copy of the data.  In this case the client must
362  * call ndr_clnt_free_heap to free the memory.
363  *
364  * The heap management data definition looks a bit like this:
365  *
366  * heap -> +---------------+     +------------+
367  *         | iovec[0].base | --> | data block |
368  *         | iovec[0].len  |     +------------+
369  *         +---------------+
370  *                ::
371  *                ::
372  * iov  -> +---------------+     +------------+
373  *         | iovec[n].base | --> | data block |
374  *         | iovec[n].len  |     +------------+
375  *         +---------------+     ^            ^
376  *                               |            |
377  *    next ----------------------+            |
378  *    top  -----------------------------------+
379  *
380  */
381 
382 /*
383  * Setting MAXIOV to 384 will use ((8 * 384) + 16) = 3088 bytes
384  * of the first heap block.
385  */
386 #define	NDR_HEAP_MAXIOV		384
387 #define	NDR_HEAP_BLKSZ		8192
388 
389 typedef struct ndr_heap {
390 	struct iovec iovec[NDR_HEAP_MAXIOV];
391 	struct iovec *iov;
392 	int iovcnt;
393 	char *top;
394 	char *next;
395 } ndr_heap_t;
396 
397 /*
398  * Alternate varying/conformant string definition
399  * - for non-null-terminated strings.
400  */
401 typedef struct ndr_vcs {
402 	/*
403 	 * size_is (actually a copy of length_is) will
404 	 * be inserted here by the marshalling library.
405 	 */
406 	uint32_t vc_first_is;
407 	uint32_t vc_length_is;
408 	uint16_t buffer[ANY_SIZE_ARRAY];
409 } ndr_vcs_t;
410 
411 typedef struct ndr_vcstr {
412 	uint16_t wclen;
413 	uint16_t wcsize;
414 	ndr_vcs_t *vcs;
415 } ndr_vcstr_t;
416 
417 typedef struct ndr_vcb {
418 	/*
419 	 * size_is (actually a copy of length_is) will
420 	 * be inserted here by the marshalling library.
421 	 */
422 	uint32_t vc_first_is;
423 	uint32_t vc_length_is;
424 	uint8_t buffer[ANY_SIZE_ARRAY];
425 } ndr_vcb_t;
426 
427 typedef struct ndr_vcbuf {
428 	uint16_t len;
429 	uint16_t size;
430 	ndr_vcb_t *vcb;
431 } ndr_vcbuf_t;
432 
433 ndr_heap_t *ndr_heap_create(void);
434 void ndr_heap_destroy(ndr_heap_t *);
435 void *ndr_heap_dupmem(ndr_heap_t *, const void *, size_t);
436 void *ndr_heap_malloc(ndr_heap_t *, unsigned);
437 void *ndr_heap_strdup(ndr_heap_t *, const char *);
438 int ndr_heap_mstring(ndr_heap_t *, const char *, ndr_mstring_t *);
439 void ndr_heap_mkvcs(ndr_heap_t *, char *, ndr_vcstr_t *);
440 void ndr_heap_mkvcb(ndr_heap_t *, uint8_t *, uint32_t, ndr_vcbuf_t *);
441 int ndr_heap_used(ndr_heap_t *);
442 int ndr_heap_avail(ndr_heap_t *);
443 
444 #define	NDR_MALLOC(XA, SZ)	ndr_heap_malloc((XA)->heap, SZ)
445 #define	NDR_NEW(XA, T)		ndr_heap_malloc((XA)->heap, sizeof (T))
446 #define	NDR_NEWN(XA, T, N)	ndr_heap_malloc((XA)->heap, sizeof (T)*(N))
447 #define	NDR_STRDUP(XA, S)	ndr_heap_strdup((XA)->heap, (S))
448 #define	NDR_MSTRING(XA, S, OUT)	ndr_heap_mstring((XA)->heap, (S), (OUT))
449 #define	NDR_SIDDUP(XA, S)	ndr_heap_dupmem((XA)->heap, (S), smb_sid_len(S))
450 
451 typedef struct ndr_xa {
452 	unsigned short		ptype;		/* high bits special */
453 	unsigned short		opnum;
454 	ndr_stream_t		recv_nds;
455 	ndr_hdr_t		recv_hdr;
456 	ndr_sec_t		recv_auth;
457 	ndr_stream_t		send_nds;
458 	ndr_hdr_t		send_hdr;
459 	ndr_sec_t		send_auth;
460 	ndr_binding_t		*binding;	/* what we're using */
461 	ndr_binding_t		*binding_list;	/* from connection */
462 	ndr_heap_t		*heap;
463 	ndr_pipe_t		*pipe;
464 } ndr_xa_t;
465 
466 typedef struct ndr_auth_ops {
467 	int (*nao_init)(void *, ndr_xa_t *);
468 	int (*nao_recv)(void *, ndr_xa_t *);
469 	int (*nao_sign)(void *, ndr_xa_t *);
470 	int (*nao_verify)(void *, ndr_xa_t *, boolean_t);
471 } ndr_auth_ops_t;
472 
473 /*
474  * A client provides this structure during bind to indicate
475  * that the RPC runtime should use "Secure RPC" (RPC-level auth).
476  *
477  * Currently, only NETLOGON uses this, and only NETLOGON-based
478  * Integrity protection is supported.
479  */
480 typedef struct ndr_auth_ctx {
481 	ndr_auth_ops_t		auth_ops;
482 	void			*auth_ctx; /* SSP-specific context */
483 	uint32_t		auth_context_id;
484 	uint8_t			auth_type;
485 	uint8_t			auth_level;
486 	boolean_t		auth_verify_resp;
487 } ndr_auth_ctx_t;
488 
489 /*
490  * 20-byte opaque id used by various RPC services.
491  */
492 CONTEXT_HANDLE(ndr_hdid) ndr_hdid_t;
493 
494 typedef struct ndr_client {
495 	/* transport stuff (xa_* members) */
496 	int (*xa_init)(struct ndr_client *, ndr_xa_t *);
497 	int (*xa_exchange)(struct ndr_client *, ndr_xa_t *);
498 	int (*xa_read)(struct ndr_client *, ndr_xa_t *);
499 	void (*xa_preserve)(struct ndr_client *, ndr_xa_t *);
500 	void (*xa_destruct)(struct ndr_client *, ndr_xa_t *);
501 	void (*xa_release)(struct ndr_client *);
502 	void			*xa_private;
503 	int			xa_fd;
504 
505 	ndr_hdid_t		*handle;
506 	ndr_binding_t		*binding;
507 	ndr_binding_t		*binding_list;
508 	ndr_binding_t		binding_pool[NDR_N_BINDING_POOL];
509 
510 	boolean_t		nonull;
511 	boolean_t		heap_preserved;
512 	ndr_heap_t		*heap;
513 	ndr_stream_t		*recv_nds;
514 	ndr_stream_t		*send_nds;
515 
516 	uint32_t		next_call_id;
517 	unsigned		next_p_cont_id;
518 
519 	ndr_auth_ctx_t		auth_ctx;
520 } ndr_client_t;
521 
522 typedef struct ndr_handle {
523 	ndr_hdid_t		nh_id;
524 	struct ndr_handle	*nh_next;
525 	ndr_pipe_t		*nh_pipe;
526 	const ndr_service_t	*nh_svc;
527 	ndr_client_t		*nh_clnt;
528 	void			*nh_data;
529 	void			(*nh_data_free)(void *);
530 } ndr_handle_t;
531 
532 #define	NDR_PDU_SIZE_HINT_DEFAULT	(16*1024)
533 #define	NDR_BUF_MAGIC			0x4E425546	/* NBUF */
534 
535 typedef struct ndr_buf {
536 	uint32_t		nb_magic;
537 	ndr_stream_t		nb_nds;
538 	ndr_heap_t		*nb_heap;
539 	ndr_typeinfo_t		*nb_ti;
540 } ndr_buf_t;
541 
542 /* ndr_ops.c */
543 int nds_initialize(ndr_stream_t *, unsigned, int, ndr_heap_t *);
544 void nds_destruct(ndr_stream_t *);
545 void nds_show_state(ndr_stream_t *);
546 
547 /* ndr_client.c */
548 int ndr_clnt_bind(ndr_client_t *, ndr_service_t *, ndr_binding_t **);
549 int ndr_clnt_call(ndr_binding_t *, int, void *);
550 void ndr_clnt_free_heap(ndr_client_t *);
551 
552 /* ndr_marshal.c */
553 ndr_buf_t *ndr_buf_init(ndr_typeinfo_t *);
554 void ndr_buf_fini(ndr_buf_t *);
555 int ndr_buf_decode(ndr_buf_t *, unsigned, unsigned, const char *data, size_t,
556     void *);
557 int ndr_decode_call(ndr_xa_t *, void *);
558 int ndr_encode_return(ndr_xa_t *, void *);
559 int ndr_encode_call(ndr_xa_t *, void *);
560 int ndr_decode_return(ndr_xa_t *, void *);
561 int ndr_decode_pdu_hdr(ndr_xa_t *);
562 int ndr_encode_pdu_hdr(ndr_xa_t *);
563 void ndr_decode_frag_hdr(ndr_stream_t *, ndr_common_header_t *);
564 void ndr_remove_frag_hdr(ndr_stream_t *);
565 void ndr_show_hdr(ndr_common_header_t *);
566 unsigned ndr_bind_ack_hdr_size(ndr_xa_t *);
567 unsigned ndr_alter_context_rsp_hdr_size(void);
568 int ndr_decode_pdu_auth(ndr_xa_t *);
569 int ndr_encode_pdu_auth(ndr_xa_t *);
570 void ndr_show_auth(ndr_sec_t *);
571 
572 /*
573  * MS-RPCE "Secure RPC" (RPC-level auth).
574  * These call the functions in ndr_auth_ops_t, which should be
575  * GSSAPI (or equivalent) calls.
576  */
577 int ndr_add_sec_context(ndr_auth_ctx_t *, ndr_xa_t *);
578 int ndr_recv_sec_context(ndr_auth_ctx_t *, ndr_xa_t *);
579 int ndr_add_auth(ndr_auth_ctx_t *, ndr_xa_t *);
580 int ndr_check_auth(ndr_auth_ctx_t *, ndr_xa_t *);
581 
582 /* ndr_server.c */
583 void ndr_pipe_worker(ndr_pipe_t *);
584 
585 int ndr_generic_call_stub(ndr_xa_t *);
586 
587 /* ndr_svc.c */
588 ndr_stub_table_t *ndr_svc_find_stub(ndr_service_t *, int);
589 ndr_service_t *ndr_svc_lookup_name(const char *);
590 ndr_service_t *ndr_svc_lookup_uuid(ndr_uuid_t *, int, ndr_uuid_t *, int);
591 int ndr_svc_register(ndr_service_t *);
592 void ndr_svc_unregister(ndr_service_t *);
593 void ndr_svc_binding_pool_init(ndr_binding_t **, ndr_binding_t pool[], int);
594 ndr_binding_t *ndr_svc_find_binding(ndr_xa_t *, ndr_p_context_id_t);
595 ndr_binding_t *ndr_svc_new_binding(ndr_xa_t *);
596 
597 int ndr_uuid_parse(char *, ndr_uuid_t *);
598 void ndr_uuid_unparse(ndr_uuid_t *, char *);
599 
600 ndr_hdid_t *ndr_hdalloc(const ndr_xa_t *, const void *);
601 void ndr_hdfree(const ndr_xa_t *, const ndr_hdid_t *);
602 ndr_handle_t *ndr_hdlookup(const ndr_xa_t *, const ndr_hdid_t *);
603 void ndr_hdclose(ndr_pipe_t *);
604 
605 ssize_t ndr_uiomove(caddr_t, size_t, enum uio_rw, struct uio *);
606 
607 /*
608  * An ndr_client_t is created while binding a client connection to hold
609  * the context for calls made using that connection.
610  *
611  * Handles are RPC call specific and we use an inheritance mechanism to
612  * ensure that each handle has a pointer to the client_t.  When the top
613  * level (bind) handle is released, we close the connection.
614  *
615  * There are some places in libmlsvc where the code assumes that the
616  * handle member is first in this struct. Careful!
617  *
618  * Note that this entire structure is bzero()'d once the ndr_client_t
619  * has been created.
620  */
621 typedef struct mlrpc_handle {
622 	ndr_hdid_t	handle;		/* keep first */
623 	ndr_client_t	*clnt;
624 } mlrpc_handle_t;
625 
626 int mlrpc_clh_create(mlrpc_handle_t *, void *);
627 uint32_t mlrpc_clh_set_auth(mlrpc_handle_t *, ndr_auth_ctx_t *);
628 uint32_t mlrpc_clh_bind(mlrpc_handle_t *, ndr_service_t *);
629 void mlrpc_clh_unbind(mlrpc_handle_t *);
630 void *mlrpc_clh_free(mlrpc_handle_t *);
631 
632 int ndr_rpc_call(mlrpc_handle_t *, int, void *);
633 int ndr_rpc_get_ssnkey(mlrpc_handle_t *, unsigned char *, size_t);
634 void *ndr_rpc_malloc(mlrpc_handle_t *, size_t);
635 ndr_heap_t *ndr_rpc_get_heap(mlrpc_handle_t *);
636 void ndr_rpc_release(mlrpc_handle_t *);
637 void ndr_rpc_set_nonull(mlrpc_handle_t *);
638 
639 boolean_t ndr_is_null_handle(mlrpc_handle_t *);
640 boolean_t ndr_is_bind_handle(mlrpc_handle_t *);
641 void ndr_inherit_handle(mlrpc_handle_t *, mlrpc_handle_t *);
642 
643 #ifdef	__cplusplus
644 }
645 #endif
646 
647 #endif	/* _LIBMLRPC_H */
648