xref: /illumos-gate/usr/src/lib/libmlrpc/common/libmlrpc.h (revision 3299f39fdcbdab4be7a9c70daa3873f2b78a398d)
1da6c28aaSamw /*
2da6c28aaSamw  * CDDL HEADER START
3da6c28aaSamw  *
4da6c28aaSamw  * The contents of this file are subject to the terms of the
5da6c28aaSamw  * Common Development and Distribution License (the "License").
6da6c28aaSamw  * You may not use this file except in compliance with the License.
7da6c28aaSamw  *
8da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw  * See the License for the specific language governing permissions
11da6c28aaSamw  * and limitations under the License.
12da6c28aaSamw  *
13da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw  *
19da6c28aaSamw  * CDDL HEADER END
20da6c28aaSamw  */
21da6c28aaSamw /*
22c5866007SKeyur Desai  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
2368b2bbf2SGordon Ross  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
24da6c28aaSamw  */
25da6c28aaSamw 
26da6c28aaSamw #ifndef	_LIBMLRPC_H
27da6c28aaSamw #define	_LIBMLRPC_H
28da6c28aaSamw 
293db3f65cSamw #include <sys/types.h>
308d7e4166Sjose borrego #include <sys/uio.h>
31*3299f39fSGordon Ross 
32*3299f39fSGordon Ross #include <smb/wintypes.h>
33*3299f39fSGordon Ross #include <libmlrpc/ndr.h>
343db3f65cSamw 
35da6c28aaSamw #ifdef	__cplusplus
36da6c28aaSamw extern "C" {
37da6c28aaSamw #endif
38da6c28aaSamw 
398d7e4166Sjose borrego /*
408d7e4166Sjose borrego  * An MSRPC compatible implementation of OSF DCE RPC.  DCE RPC is derived
418d7e4166Sjose borrego  * from the Apollo Network Computing Architecture (NCA) RPC implementation.
428d7e4166Sjose borrego  *
438d7e4166Sjose borrego  * CAE Specification (1997)
448d7e4166Sjose borrego  * DCE 1.1: Remote Procedure Call
458d7e4166Sjose borrego  * Document Number: C706
468d7e4166Sjose borrego  * The Open Group
478d7e4166Sjose borrego  * ogspecs@opengroup.org
488d7e4166Sjose borrego  *
498d7e4166Sjose borrego  * This implementation is based on the DCE Remote Procedure Call spec with
508d7e4166Sjose borrego  * enhancements to support Unicode strings.  The diagram below shows the
518d7e4166Sjose borrego  * DCE RPC layers compared against ONC SUN RPC.
528d7e4166Sjose borrego  *
538d7e4166Sjose borrego  *	NDR RPC Layers		Sun RPC Layers		Remark
548d7e4166Sjose borrego  *	+---------------+	+---------------+	+---------------+
558d7e4166Sjose borrego  *	+---------------+	+---------------+
568d7e4166Sjose borrego  *	| Application	|	| Application	|	The application
578d7e4166Sjose borrego  *	+---------------+	+---------------+
588d7e4166Sjose borrego  *	| Hand coded    |	| RPCGEN gen'd  |	Where the real
598d7e4166Sjose borrego  *	| client/server |	| client/server |	work happens
608d7e4166Sjose borrego  *	| srvsvc.ndl	|	| *_svc.c *_clnt|
618d7e4166Sjose borrego  *	| srvsvc.c	|	|               |
628d7e4166Sjose borrego  *	+---------------+	+---------------+
638d7e4166Sjose borrego  *	| RPC Library	|	| RPC Library   |	Calls/Return
648d7e4166Sjose borrego  *	| ndr_*.c       |	|               |	Binding/PMAP
658d7e4166Sjose borrego  *	+---------------+	+---------------+
668d7e4166Sjose borrego  *	| RPC Protocol	|	| RPC Protocol  |	Headers, Auth,
678d7e4166Sjose borrego  *	| rpcpdu.ndl    |	|               |
688d7e4166Sjose borrego  *	+---------------+	+---------------+
698d7e4166Sjose borrego  *	| IDL gen'd	|	| RPCGEN gen'd  |	Aggregate
708d7e4166Sjose borrego  *	| NDR stubs	|	| XDR stubs     |	Composition
718d7e4166Sjose borrego  *	| *__ndr.c      |	| *_xdr.c       |
728d7e4166Sjose borrego  *	+---------------+	+---------------+
738d7e4166Sjose borrego  *	| NDR Represen	|	| XDR Represen  |	Byte order, padding
748d7e4166Sjose borrego  *	+---------------+	+---------------+
758d7e4166Sjose borrego  *	| Packet Heaps  |	| Network Conn  |	DCERPC does not talk
768d7e4166Sjose borrego  *	| ndo_*.c       |	| clnt_{tcp,udp}|	directly to network.
778d7e4166Sjose borrego  *	+---------------+	+---------------+
788d7e4166Sjose borrego  *
798d7e4166Sjose borrego  * There are two major differences between the DCE RPC and ONC RPC:
808d7e4166Sjose borrego  *
818d7e4166Sjose borrego  * 1. NDR RPC only generates or processes packets from buffers.  Other
828d7e4166Sjose borrego  *    layers must take care of packet transmission and reception.
838d7e4166Sjose borrego  *    The packet heaps are managed through a simple interface provided
848d7e4166Sjose borrego  *    by the Network Data Representation (NDR) module called ndr_stream_t.
858d7e4166Sjose borrego  *    ndo_*.c modules implement the different flavors (operations) of
868d7e4166Sjose borrego  *    packet heaps.
878d7e4166Sjose borrego  *
888d7e4166Sjose borrego  *    ONC RPC communicates directly with the network.  You have to do
898d7e4166Sjose borrego  *    something special for the RPC packet to be placed in a buffer
908d7e4166Sjose borrego  *    rather than sent to the wire.
918d7e4166Sjose borrego  *
928d7e4166Sjose borrego  * 2. NDR RPC uses application provided heaps to support operations.
938d7e4166Sjose borrego  *    A heap is a single, monolithic chunk of memory that NDR RPC manages
948d7e4166Sjose borrego  *    as it allocates.  When the operation and its result are done, the
958d7e4166Sjose borrego  *    heap is disposed of as a single item.  The transaction, which
968d7e4166Sjose borrego  *    is the anchor of most operations, contains the necessary book-
978d7e4166Sjose borrego  *    keeping for the heap.
988d7e4166Sjose borrego  *
998d7e4166Sjose borrego  *    ONC RPC uses malloc() liberally throughout its run-time system.
1008d7e4166Sjose borrego  *    To free results, ONC RPC supports an XDR_FREE operation that
1018d7e4166Sjose borrego  *    traverses data structures freeing memory as it goes, whether
1028d7e4166Sjose borrego  *    it was malloc'd or not.
1038d7e4166Sjose borrego  */
1048d7e4166Sjose borrego 
1058d7e4166Sjose borrego /*
1068d7e4166Sjose borrego  * Dispatch Return Code (DRC)
1078d7e4166Sjose borrego  *
1088d7e4166Sjose borrego  *	0x8000	15:01	Set to indicate a fault, clear indicates status
1098d7e4166Sjose borrego  *	0x7F00	08:07	Status/Fault specific
1108d7e4166Sjose borrego  *	0x00FF	00:08	PTYPE_... of PDU, 0xFF for header
1118d7e4166Sjose borrego  */
1128d7e4166Sjose borrego #define	NDR_DRC_OK				0x0000
1138d7e4166Sjose borrego #define	NDR_DRC_MASK_FAULT			0x8000
1148d7e4166Sjose borrego #define	NDR_DRC_MASK_SPECIFIER			0xFF00
1158d7e4166Sjose borrego #define	NDR_DRC_MASK_PTYPE			0x00FF
1168d7e4166Sjose borrego 
1178d7e4166Sjose borrego /* Fake PTYPE DRC discriminators */
1188d7e4166Sjose borrego #define	NDR_DRC_PTYPE_RPCHDR(DRC)		((DRC) | 0x00FF)
1198d7e4166Sjose borrego #define	NDR_DRC_PTYPE_API(DRC)			((DRC) | 0x00AA)
1208d7e4166Sjose borrego 
1218d7e4166Sjose borrego /* DRC Recognizers */
1228d7e4166Sjose borrego #define	NDR_DRC_IS_OK(DRC)	(((DRC) & NDR_DRC_MASK_SPECIFIER) == 0)
1238d7e4166Sjose borrego #define	NDR_DRC_IS_FAULT(DRC)	(((DRC) & NDR_DRC_MASK_FAULT) != 0)
1248d7e4166Sjose borrego 
1258d7e4166Sjose borrego /*
1268d7e4166Sjose borrego  * (Un)Marshalling category specifiers
1278d7e4166Sjose borrego  */
1288d7e4166Sjose borrego #define	NDR_DRC_FAULT_MODE_MISMATCH		0x8100
1298d7e4166Sjose borrego #define	NDR_DRC_RECEIVED			0x0200
1308d7e4166Sjose borrego #define	NDR_DRC_FAULT_RECEIVED_RUNT		0x8300
1318d7e4166Sjose borrego #define	NDR_DRC_FAULT_RECEIVED_MALFORMED	0x8400
1328d7e4166Sjose borrego #define	NDR_DRC_DECODED				0x0500
1338d7e4166Sjose borrego #define	NDR_DRC_FAULT_DECODE_FAILED		0x8600
1348d7e4166Sjose borrego #define	NDR_DRC_ENCODED				0x0700
1358d7e4166Sjose borrego #define	NDR_DRC_FAULT_ENCODE_FAILED		0x8800
1368d7e4166Sjose borrego #define	NDR_DRC_FAULT_ENCODE_TOO_BIG		0x8900
1378d7e4166Sjose borrego #define	NDR_DRC_SENT				0x0A00
1388d7e4166Sjose borrego #define	NDR_DRC_FAULT_SEND_FAILED		0x8B00
1398d7e4166Sjose borrego 
1408d7e4166Sjose borrego /*
1418d7e4166Sjose borrego  * Resource category specifier
1428d7e4166Sjose borrego  */
1438d7e4166Sjose borrego #define	NDR_DRC_FAULT_RESOURCE_1		0x9100
1448d7e4166Sjose borrego #define	NDR_DRC_FAULT_RESOURCE_2		0x9200
1458d7e4166Sjose borrego 
1468d7e4166Sjose borrego /*
1478d7e4166Sjose borrego  * Parameters. Usually #define'd with useful alias
1488d7e4166Sjose borrego  */
1498d7e4166Sjose borrego #define	NDR_DRC_FAULT_PARAM_0_INVALID		0xC000
1508d7e4166Sjose borrego #define	NDR_DRC_FAULT_PARAM_0_UNIMPLEMENTED	0xD000
1518d7e4166Sjose borrego #define	NDR_DRC_FAULT_PARAM_1_INVALID		0xC100
1528d7e4166Sjose borrego #define	NDR_DRC_FAULT_PARAM_1_UNIMPLEMENTED	0xD100
1538d7e4166Sjose borrego #define	NDR_DRC_FAULT_PARAM_2_INVALID		0xC200
1548d7e4166Sjose borrego #define	NDR_DRC_FAULT_PARAM_2_UNIMPLEMENTED	0xD200
1558d7e4166Sjose borrego #define	NDR_DRC_FAULT_PARAM_3_INVALID		0xC300
1568d7e4166Sjose borrego #define	NDR_DRC_FAULT_PARAM_3_UNIMPLEMENTED	0xD300
1578d7e4166Sjose borrego 
1588d7e4166Sjose borrego #define	NDR_DRC_FAULT_OUT_OF_MEMORY		0xF000
1598d7e4166Sjose borrego 
1608d7e4166Sjose borrego /* RPCHDR */
161c5866007SKeyur Desai #define	NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH	0x81FF
162c5866007SKeyur Desai #define	NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT	0x83FF
163c5866007SKeyur Desai #define	NDR_DRC_FAULT_RPCHDR_DECODE_FAILED	0x86FF
1648d7e4166Sjose borrego #define	NDR_DRC_FAULT_RPCHDR_PTYPE_INVALID	0xC0FF	/* PARAM_0_INVALID */
165c5866007SKeyur Desai #define	NDR_DRC_FAULT_RPCHDR_PTYPE_UNIMPLEMENTED 0xD0FF	/* PARAM_0_UNIMP */
1668d7e4166Sjose borrego 
1678d7e4166Sjose borrego /* Request */
1688d7e4166Sjose borrego #define	NDR_DRC_FAULT_REQUEST_PCONT_INVALID	0xC000	/* PARAM_0_INVALID */
1698d7e4166Sjose borrego #define	NDR_DRC_FAULT_REQUEST_OPNUM_INVALID	0xC100	/* PARAM_1_INVALID */
1708d7e4166Sjose borrego 
1718d7e4166Sjose borrego /* Bind */
172c5866007SKeyur Desai #define	NDR_DRC_BINDING_MADE			0x000B	/* OK */
1738d7e4166Sjose borrego #define	NDR_DRC_FAULT_BIND_PCONT_BUSY		0xC00B	/* PARAM_0_INVALID */
1748d7e4166Sjose borrego #define	NDR_DRC_FAULT_BIND_UNKNOWN_SERVICE	0xC10B	/* PARAM_1_INVALID */
1758d7e4166Sjose borrego #define	NDR_DRC_FAULT_BIND_NO_SLOTS		0x910B	/* RESOURCE_1 */
1768d7e4166Sjose borrego 
1778d7e4166Sjose borrego /* API */
1788d7e4166Sjose borrego #define	NDR_DRC_FAULT_API_SERVICE_INVALID	0xC0AA	/* PARAM_0_INVALID */
1798d7e4166Sjose borrego #define	NDR_DRC_FAULT_API_BIND_NO_SLOTS		0x91AA	/* RESOURCE_1 */
1808d7e4166Sjose borrego #define	NDR_DRC_FAULT_API_OPNUM_INVALID		0xC1AA	/* PARAM_1_INVALID */
1818d7e4166Sjose borrego 
1828d7e4166Sjose borrego struct ndr_xa;
1838d7e4166Sjose borrego struct ndr_client;
1848d7e4166Sjose borrego 
1858d7e4166Sjose borrego typedef struct ndr_stub_table {
1868d7e4166Sjose borrego 	int		(*func)(void *, struct ndr_xa *);
1878d7e4166Sjose borrego 	unsigned short	opnum;
1888d7e4166Sjose borrego } ndr_stub_table_t;
1898d7e4166Sjose borrego 
1908d7e4166Sjose borrego typedef struct ndr_service {
1918d7e4166Sjose borrego 	char		*name;
1928d7e4166Sjose borrego 	char		*desc;
1938d7e4166Sjose borrego 	char		*endpoint;
1948d7e4166Sjose borrego 	char		*sec_addr_port;
1958d7e4166Sjose borrego 	char		*abstract_syntax_uuid;
1968d7e4166Sjose borrego 	int		abstract_syntax_version;
1978d7e4166Sjose borrego 	char		*transfer_syntax_uuid;
1988d7e4166Sjose borrego 	int		transfer_syntax_version;
1998d7e4166Sjose borrego 	unsigned	bind_instance_size;
2008d7e4166Sjose borrego 	int		(*bind_req)();
2018d7e4166Sjose borrego 	int		(*unbind_and_close)();
2028d7e4166Sjose borrego 	int		(*call_stub)(struct ndr_xa *);
2038d7e4166Sjose borrego 	ndr_typeinfo_t	*interface_ti;
2048d7e4166Sjose borrego 	ndr_stub_table_t *stub_table;
2058d7e4166Sjose borrego } ndr_service_t;
2068d7e4166Sjose borrego 
2078d7e4166Sjose borrego /*
2088d7e4166Sjose borrego  * The list of bindings is anchored at a connection.  Nothing in the
2098d7e4166Sjose borrego  * RPC mechanism allocates them.  Binding elements which have service==0
2108d7e4166Sjose borrego  * indicate free elements.  When a connection is instantiated, at least
2118d7e4166Sjose borrego  * one free binding entry should also be established.  Something like
2128d7e4166Sjose borrego  * this should suffice for most (all) situations:
2138d7e4166Sjose borrego  *
2148d7e4166Sjose borrego  *	struct connection {
2158d7e4166Sjose borrego  *		....
2168d7e4166Sjose borrego  *		ndr_binding_t *binding_list_head;
2178d7e4166Sjose borrego  *		ndr_binding_t binding_pool[N_BINDING_POOL];
2188d7e4166Sjose borrego  *		....
2198d7e4166Sjose borrego  *	};
2208d7e4166Sjose borrego  *
2218d7e4166Sjose borrego  *	init_connection(struct connection *conn) {
2228d7e4166Sjose borrego  *		....
2238d7e4166Sjose borrego  *		ndr_svc_binding_pool_init(&conn->binding_list_head,
2248d7e4166Sjose borrego  *		    conn->binding_pool, N_BINDING_POOL);
2258d7e4166Sjose borrego  */
2268d7e4166Sjose borrego typedef struct ndr_binding {
2278d7e4166Sjose borrego 	struct ndr_binding 	*next;
2288d7e4166Sjose borrego 	ndr_p_context_id_t	p_cont_id;
2298d7e4166Sjose borrego 	unsigned char		which_side;
2308d7e4166Sjose borrego 	struct ndr_client	*clnt;
2318d7e4166Sjose borrego 	ndr_service_t		*service;
2328d7e4166Sjose borrego 	void 			*instance_specific;
2338d7e4166Sjose borrego } ndr_binding_t;
2348d7e4166Sjose borrego 
2358d7e4166Sjose borrego #define	NDR_BIND_SIDE_CLIENT	1
2368d7e4166Sjose borrego #define	NDR_BIND_SIDE_SERVER	2
2378d7e4166Sjose borrego 
2388d7e4166Sjose borrego #define	NDR_BINDING_TO_SPECIFIC(BINDING, TYPE) \
2398d7e4166Sjose borrego 	((TYPE *) (BINDING)->instance_specific)
2408d7e4166Sjose borrego 
2418d7e4166Sjose borrego /*
2428d7e4166Sjose borrego  * The binding list space must be provided by the application library
2438d7e4166Sjose borrego  * for use by the underlying RPC library.  We need at least two binding
2448d7e4166Sjose borrego  * slots per connection.
2458d7e4166Sjose borrego  */
2468d7e4166Sjose borrego #define	NDR_N_BINDING_POOL	2
2478d7e4166Sjose borrego 
2488d7e4166Sjose borrego typedef struct ndr_pipe {
249*3299f39fSGordon Ross 	void			*np_listener;
25068b2bbf2SGordon Ross 	const char		*np_endpoint;
251*3299f39fSGordon Ross 	struct smb_netuserinfo	*np_user;
25268b2bbf2SGordon Ross 	int			(*np_send)(struct ndr_pipe *, void *, size_t);
25368b2bbf2SGordon Ross 	int			(*np_recv)(struct ndr_pipe *, void *, size_t);
2548d7e4166Sjose borrego 	int			np_fid;
2558d7e4166Sjose borrego 	uint16_t		np_max_xmit_frag;
2568d7e4166Sjose borrego 	uint16_t		np_max_recv_frag;
2578d7e4166Sjose borrego 	ndr_binding_t		*np_binding;
2588d7e4166Sjose borrego 	ndr_binding_t		np_binding_pool[NDR_N_BINDING_POOL];
2598d7e4166Sjose borrego } ndr_pipe_t;
2608d7e4166Sjose borrego 
2618d7e4166Sjose borrego /*
2628d7e4166Sjose borrego  * Number of bytes required to align SIZE on the next dword/4-byte
2638d7e4166Sjose borrego  * boundary.
2648d7e4166Sjose borrego  */
2658d7e4166Sjose borrego #define	NDR_ALIGN4(SIZE)	((4 - (SIZE)) & 3);
2668d7e4166Sjose borrego 
2678d7e4166Sjose borrego /*
2688d7e4166Sjose borrego  * DCE RPC strings (CAE section 14.3.4) are represented as varying or varying
2698d7e4166Sjose borrego  * and conformant one-dimensional arrays. Characters can be single-byte
2708d7e4166Sjose borrego  * or multi-byte as long as all characters conform to a fixed element size,
2718d7e4166Sjose borrego  * i.e. UCS-2 is okay but UTF-8 is not a valid DCE RPC string format. The
2728d7e4166Sjose borrego  * string is terminated by a null character of the appropriate element size.
2738d7e4166Sjose borrego  *
2748d7e4166Sjose borrego  * MSRPC strings should always be varying/conformant and not null terminated.
2758d7e4166Sjose borrego  * This format uses the size_is, first_is and length_is attributes (CAE
2768d7e4166Sjose borrego  * section 4.2.18).
2778d7e4166Sjose borrego  *
2788d7e4166Sjose borrego  *	typedef struct string {
2798d7e4166Sjose borrego  *		DWORD size_is;
2808d7e4166Sjose borrego  *		DWORD first_is;
2818d7e4166Sjose borrego  *		DWORD length_is;
2828d7e4166Sjose borrego  *		wchar_t string[ANY_SIZE_ARRAY];
2838d7e4166Sjose borrego  *	} string_t;
2848d7e4166Sjose borrego  *
2858d7e4166Sjose borrego  * The size_is attribute is used to specify the number of data elements in
2868d7e4166Sjose borrego  * each dimension of an array.
2878d7e4166Sjose borrego  *
2888d7e4166Sjose borrego  * The first_is attribute is used to define the lower bound for significant
2898d7e4166Sjose borrego  * elements in each dimension of an array. For strings this is always 0.
2908d7e4166Sjose borrego  *
2918d7e4166Sjose borrego  * The length_is attribute is used to define the number of significant
2928d7e4166Sjose borrego  * elements in each dimension of an array. For strings this is typically
2938d7e4166Sjose borrego  * the same as size_is. Although it might be (size_is - 1) if the string
2948d7e4166Sjose borrego  * is null terminated.
2958d7e4166Sjose borrego  *
2968d7e4166Sjose borrego  *   4 bytes   4 bytes   4 bytes  2bytes 2bytes 2bytes 2bytes
2978d7e4166Sjose borrego  * +---------+---------+---------+------+------+------+------+
2988d7e4166Sjose borrego  * |size_is  |first_is |length_is| char | char | char | char |
2998d7e4166Sjose borrego  * +---------+---------+---------+------+------+------+------+
3008d7e4166Sjose borrego  *
3018d7e4166Sjose borrego  * Unfortunately, not all MSRPC Unicode strings are null terminated, which
3028d7e4166Sjose borrego  * means that the recipient has to manually null-terminate the string after
3038d7e4166Sjose borrego  * it has been unmarshalled.  There may be a wide-char pad following a
3048d7e4166Sjose borrego  * string, and it may sometimes contains zero, but it's not guaranteed.
3058d7e4166Sjose borrego  *
3068d7e4166Sjose borrego  * To deal with this, MSRPC sometimes uses an additional wrapper with two
3078d7e4166Sjose borrego  * more fields, as shown below.
3088d7e4166Sjose borrego  *	length: the array length in bytes excluding terminating null bytes
3098d7e4166Sjose borrego  *	maxlen: the array length in bytes including null terminator bytes
3108d7e4166Sjose borrego  *	LPTSTR: converted to a string_t by NDR
3118d7e4166Sjose borrego  *
3128d7e4166Sjose borrego  * typedef struct ms_string {
3138d7e4166Sjose borrego  *		WORD length;
3148d7e4166Sjose borrego  *		WORD maxlen;
3158d7e4166Sjose borrego  *		LPTSTR str;
3168d7e4166Sjose borrego  * } ms_string_t;
3178d7e4166Sjose borrego  */
3188d7e4166Sjose borrego typedef struct ndr_mstring {
3198d7e4166Sjose borrego 	uint16_t length;
3208d7e4166Sjose borrego 	uint16_t allosize;
3218d7e4166Sjose borrego 	LPTSTR str;
3228d7e4166Sjose borrego } ndr_mstring_t;
3238d7e4166Sjose borrego 
3248d7e4166Sjose borrego /*
3258d7e4166Sjose borrego  * A number of heap areas are used during marshalling and unmarshalling.
3268d7e4166Sjose borrego  * Under some circumstances these areas can be discarded by the library
3278d7e4166Sjose borrego  * code, i.e. on the server side before returning to the client and on
3288d7e4166Sjose borrego  * completion of a client side bind.  In the case of a client side RPC
3298d7e4166Sjose borrego  * call, these areas must be preserved after an RPC returns to give the
3308d7e4166Sjose borrego  * caller time to take a copy of the data.  In this case the client must
3318d7e4166Sjose borrego  * call ndr_clnt_free_heap to free the memory.
3328d7e4166Sjose borrego  *
3338d7e4166Sjose borrego  * The heap management data definition looks a bit like this:
3348d7e4166Sjose borrego  *
3358d7e4166Sjose borrego  * heap -> +---------------+     +------------+
3368d7e4166Sjose borrego  *         | iovec[0].base | --> | data block |
3378d7e4166Sjose borrego  *         | iovec[0].len  |     +------------+
3388d7e4166Sjose borrego  *         +---------------+
3398d7e4166Sjose borrego  *                ::
3408d7e4166Sjose borrego  *                ::
3418d7e4166Sjose borrego  * iov  -> +---------------+     +------------+
3428d7e4166Sjose borrego  *         | iovec[n].base | --> | data block |
3438d7e4166Sjose borrego  *         | iovec[n].len  |     +------------+
3448d7e4166Sjose borrego  *         +---------------+     ^            ^
3458d7e4166Sjose borrego  *                               |            |
3468d7e4166Sjose borrego  *    next ----------------------+            |
3478d7e4166Sjose borrego  *    top  -----------------------------------+
3488d7e4166Sjose borrego  *
3498d7e4166Sjose borrego  */
3508d7e4166Sjose borrego 
3518d7e4166Sjose borrego /*
3528d7e4166Sjose borrego  * Setting MAXIOV to 384 will use ((8 * 384) + 16) = 3088 bytes
3538d7e4166Sjose borrego  * of the first heap block.
3548d7e4166Sjose borrego  */
3558d7e4166Sjose borrego #define	NDR_HEAP_MAXIOV		384
3568d7e4166Sjose borrego #define	NDR_HEAP_BLKSZ		8192
3578d7e4166Sjose borrego 
3588d7e4166Sjose borrego typedef struct ndr_heap {
3598d7e4166Sjose borrego 	struct iovec iovec[NDR_HEAP_MAXIOV];
3608d7e4166Sjose borrego 	struct iovec *iov;
3618d7e4166Sjose borrego 	int iovcnt;
3628d7e4166Sjose borrego 	char *top;
3638d7e4166Sjose borrego 	char *next;
3648d7e4166Sjose borrego } ndr_heap_t;
3658d7e4166Sjose borrego 
3668d7e4166Sjose borrego /*
3678d7e4166Sjose borrego  * Alternate varying/conformant string definition
3688d7e4166Sjose borrego  * - for non-null-terminated strings.
3698d7e4166Sjose borrego  */
3708d7e4166Sjose borrego typedef struct ndr_vcs {
3718d7e4166Sjose borrego 	/*
3728d7e4166Sjose borrego 	 * size_is (actually a copy of length_is) will
3738d7e4166Sjose borrego 	 * be inserted here by the marshalling library.
3748d7e4166Sjose borrego 	 */
3758d7e4166Sjose borrego 	uint32_t vc_first_is;
3768d7e4166Sjose borrego 	uint32_t vc_length_is;
3778d7e4166Sjose borrego 	uint16_t buffer[ANY_SIZE_ARRAY];
3788d7e4166Sjose borrego } ndr_vcs_t;
3798d7e4166Sjose borrego 
3808d7e4166Sjose borrego typedef struct ndr_vcstr {
3818d7e4166Sjose borrego 	uint16_t wclen;
3828d7e4166Sjose borrego 	uint16_t wcsize;
3838d7e4166Sjose borrego 	ndr_vcs_t *vcs;
3848d7e4166Sjose borrego } ndr_vcstr_t;
3858d7e4166Sjose borrego 
3868d7e4166Sjose borrego typedef struct ndr_vcb {
3878d7e4166Sjose borrego 	/*
3888d7e4166Sjose borrego 	 * size_is (actually a copy of length_is) will
3898d7e4166Sjose borrego 	 * be inserted here by the marshalling library.
3908d7e4166Sjose borrego 	 */
3918d7e4166Sjose borrego 	uint32_t vc_first_is;
3928d7e4166Sjose borrego 	uint32_t vc_length_is;
3938d7e4166Sjose borrego 	uint8_t buffer[ANY_SIZE_ARRAY];
3948d7e4166Sjose borrego } ndr_vcb_t;
3958d7e4166Sjose borrego 
3968d7e4166Sjose borrego typedef struct ndr_vcbuf {
3978d7e4166Sjose borrego 	uint16_t len;
3988d7e4166Sjose borrego 	uint16_t size;
3998d7e4166Sjose borrego 	ndr_vcb_t *vcb;
4008d7e4166Sjose borrego } ndr_vcbuf_t;
4018d7e4166Sjose borrego 
4028d7e4166Sjose borrego ndr_heap_t *ndr_heap_create(void);
4038d7e4166Sjose borrego void ndr_heap_destroy(ndr_heap_t *);
404*3299f39fSGordon Ross void *ndr_heap_dupmem(ndr_heap_t *, const void *, size_t);
4058d7e4166Sjose borrego void *ndr_heap_malloc(ndr_heap_t *, unsigned);
4068d7e4166Sjose borrego void *ndr_heap_strdup(ndr_heap_t *, const char *);
4078d7e4166Sjose borrego int ndr_heap_mstring(ndr_heap_t *, const char *, ndr_mstring_t *);
4088d7e4166Sjose borrego void ndr_heap_mkvcs(ndr_heap_t *, char *, ndr_vcstr_t *);
4098d7e4166Sjose borrego void ndr_heap_mkvcb(ndr_heap_t *, uint8_t *, uint32_t, ndr_vcbuf_t *);
4108d7e4166Sjose borrego int ndr_heap_used(ndr_heap_t *);
4118d7e4166Sjose borrego int ndr_heap_avail(ndr_heap_t *);
4128d7e4166Sjose borrego 
4138d7e4166Sjose borrego #define	NDR_MALLOC(XA, SZ)	ndr_heap_malloc((XA)->heap, SZ)
4148d7e4166Sjose borrego #define	NDR_NEW(XA, T)		ndr_heap_malloc((XA)->heap, sizeof (T))
4158d7e4166Sjose borrego #define	NDR_NEWN(XA, T, N)	ndr_heap_malloc((XA)->heap, sizeof (T)*(N))
4168d7e4166Sjose borrego #define	NDR_STRDUP(XA, S)	ndr_heap_strdup((XA)->heap, (S))
4178d7e4166Sjose borrego #define	NDR_MSTRING(XA, S, OUT)	ndr_heap_mstring((XA)->heap, (S), (OUT))
418*3299f39fSGordon Ross #define	NDR_SIDDUP(XA, S)	ndr_heap_dupmem((XA)->heap, (S), smb_sid_len(S))
4198d7e4166Sjose borrego 
4208d7e4166Sjose borrego typedef struct ndr_xa {
4218d7e4166Sjose borrego 	unsigned short		ptype;		/* high bits special */
4228d7e4166Sjose borrego 	unsigned short		opnum;
4238d7e4166Sjose borrego 	ndr_stream_t		recv_nds;
4248d7e4166Sjose borrego 	ndr_hdr_t		recv_hdr;
4258d7e4166Sjose borrego 	ndr_stream_t		send_nds;
4268d7e4166Sjose borrego 	ndr_hdr_t		send_hdr;
4278d7e4166Sjose borrego 	ndr_binding_t		*binding;	/* what we're using */
4288d7e4166Sjose borrego 	ndr_binding_t		*binding_list;	/* from connection */
4298d7e4166Sjose borrego 	ndr_heap_t		*heap;
4308d7e4166Sjose borrego 	ndr_pipe_t		*pipe;
4318d7e4166Sjose borrego } ndr_xa_t;
4328d7e4166Sjose borrego 
4338d7e4166Sjose borrego /*
4348d7e4166Sjose borrego  * 20-byte opaque id used by various RPC services.
4358d7e4166Sjose borrego  */
4368d7e4166Sjose borrego CONTEXT_HANDLE(ndr_hdid) ndr_hdid_t;
4378d7e4166Sjose borrego 
4388d7e4166Sjose borrego typedef struct ndr_client {
439ed9aabc7SGordon Ross 	/* transport stuff (xa_* members) */
4408d7e4166Sjose borrego 	int (*xa_init)(struct ndr_client *, ndr_xa_t *);
4418d7e4166Sjose borrego 	int (*xa_exchange)(struct ndr_client *, ndr_xa_t *);
4428d7e4166Sjose borrego 	int (*xa_read)(struct ndr_client *, ndr_xa_t *);
4438d7e4166Sjose borrego 	void (*xa_preserve)(struct ndr_client *, ndr_xa_t *);
4448d7e4166Sjose borrego 	void (*xa_destruct)(struct ndr_client *, ndr_xa_t *);
4458d7e4166Sjose borrego 	void (*xa_release)(struct ndr_client *);
446ed9aabc7SGordon Ross 	void			*xa_private;
447ed9aabc7SGordon Ross 	int			xa_fd;
4488d7e4166Sjose borrego 
4498d7e4166Sjose borrego 	ndr_hdid_t		*handle;
4508d7e4166Sjose borrego 	ndr_binding_t		*binding;
4518d7e4166Sjose borrego 	ndr_binding_t		*binding_list;
4528d7e4166Sjose borrego 	ndr_binding_t		binding_pool[NDR_N_BINDING_POOL];
4538d7e4166Sjose borrego 
454fe1c642dSBill Krier 	boolean_t		nonull;
4558d7e4166Sjose borrego 	boolean_t		heap_preserved;
4568d7e4166Sjose borrego 	ndr_heap_t		*heap;
4578d7e4166Sjose borrego 	ndr_stream_t		*recv_nds;
4588d7e4166Sjose borrego 	ndr_stream_t		*send_nds;
4598d7e4166Sjose borrego 
4608d7e4166Sjose borrego 	uint32_t		next_call_id;
4618d7e4166Sjose borrego 	unsigned		next_p_cont_id;
4628d7e4166Sjose borrego } ndr_client_t;
4638d7e4166Sjose borrego 
4648d7e4166Sjose borrego typedef struct ndr_handle {
4658d7e4166Sjose borrego 	ndr_hdid_t		nh_id;
4668d7e4166Sjose borrego 	struct ndr_handle	*nh_next;
46768b2bbf2SGordon Ross 	ndr_pipe_t		*nh_pipe;
4688d7e4166Sjose borrego 	const ndr_service_t	*nh_svc;
4698d7e4166Sjose borrego 	ndr_client_t		*nh_clnt;
47089dc44ceSjose borrego 	void			*nh_data;
47189dc44ceSjose borrego 	void			(*nh_data_free)(void *);
4728d7e4166Sjose borrego } ndr_handle_t;
4738d7e4166Sjose borrego 
474b1352070SAlan Wright #define	NDR_PDU_SIZE_HINT_DEFAULT	(16*1024)
475b1352070SAlan Wright #define	NDR_BUF_MAGIC			0x4E425546	/* NBUF */
476b1352070SAlan Wright 
477b1352070SAlan Wright typedef struct ndr_buf {
478b1352070SAlan Wright 	uint32_t		nb_magic;
479b1352070SAlan Wright 	ndr_stream_t		nb_nds;
480b1352070SAlan Wright 	ndr_heap_t		*nb_heap;
481b1352070SAlan Wright 	ndr_typeinfo_t		*nb_ti;
482b1352070SAlan Wright } ndr_buf_t;
483b1352070SAlan Wright 
4848d7e4166Sjose borrego /* ndr_ops.c */
485fe1c642dSBill Krier int nds_initialize(ndr_stream_t *, unsigned, int, ndr_heap_t *);
4868d7e4166Sjose borrego void nds_destruct(ndr_stream_t *);
4870658b32dSAlan Wright void nds_show_state(ndr_stream_t *);
4888d7e4166Sjose borrego 
4898d7e4166Sjose borrego /* ndr_client.c */
490*3299f39fSGordon Ross int ndr_clnt_bind(ndr_client_t *, ndr_service_t *, ndr_binding_t **);
4918d7e4166Sjose borrego int ndr_clnt_call(ndr_binding_t *, int, void *);
4928d7e4166Sjose borrego void ndr_clnt_free_heap(ndr_client_t *);
4938d7e4166Sjose borrego 
4948d7e4166Sjose borrego /* ndr_marshal.c */
495b1352070SAlan Wright ndr_buf_t *ndr_buf_init(ndr_typeinfo_t *);
496b1352070SAlan Wright void ndr_buf_fini(ndr_buf_t *);
497c5866007SKeyur Desai int ndr_buf_decode(ndr_buf_t *, unsigned, unsigned, const char *data, size_t,
498c5866007SKeyur Desai     void *);
4998d7e4166Sjose borrego int ndr_decode_call(ndr_xa_t *, void *);
5008d7e4166Sjose borrego int ndr_encode_return(ndr_xa_t *, void *);
5018d7e4166Sjose borrego int ndr_encode_call(ndr_xa_t *, void *);
5028d7e4166Sjose borrego int ndr_decode_return(ndr_xa_t *, void *);
5038d7e4166Sjose borrego int ndr_decode_pdu_hdr(ndr_xa_t *);
5048d7e4166Sjose borrego int ndr_encode_pdu_hdr(ndr_xa_t *);
5058d7e4166Sjose borrego void ndr_decode_frag_hdr(ndr_stream_t *, ndr_common_header_t *);
5069fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void ndr_remove_frag_hdr(ndr_stream_t *);
5070658b32dSAlan Wright void ndr_show_hdr(ndr_common_header_t *);
5088d7e4166Sjose borrego unsigned ndr_bind_ack_hdr_size(ndr_xa_t *);
5098d7e4166Sjose borrego unsigned ndr_alter_context_rsp_hdr_size(void);
5108d7e4166Sjose borrego 
5118d7e4166Sjose borrego /* ndr_server.c */
51268b2bbf2SGordon Ross void ndr_pipe_worker(ndr_pipe_t *);
5138d7e4166Sjose borrego 
5148d7e4166Sjose borrego int ndr_generic_call_stub(ndr_xa_t *);
5158d7e4166Sjose borrego 
5168d7e4166Sjose borrego /* ndr_svc.c */
5178d7e4166Sjose borrego ndr_stub_table_t *ndr_svc_find_stub(ndr_service_t *, int);
5188d7e4166Sjose borrego ndr_service_t *ndr_svc_lookup_name(const char *);
5198d7e4166Sjose borrego ndr_service_t *ndr_svc_lookup_uuid(ndr_uuid_t *, int, ndr_uuid_t *, int);
5208d7e4166Sjose borrego int ndr_svc_register(ndr_service_t *);
5218d7e4166Sjose borrego void ndr_svc_unregister(ndr_service_t *);
5228d7e4166Sjose borrego void ndr_svc_binding_pool_init(ndr_binding_t **, ndr_binding_t pool[], int);
5238d7e4166Sjose borrego ndr_binding_t *ndr_svc_find_binding(ndr_xa_t *, ndr_p_context_id_t);
5248d7e4166Sjose borrego ndr_binding_t *ndr_svc_new_binding(ndr_xa_t *);
5258d7e4166Sjose borrego 
5268d7e4166Sjose borrego int ndr_uuid_parse(char *, ndr_uuid_t *);
5278d7e4166Sjose borrego void ndr_uuid_unparse(ndr_uuid_t *, char *);
5288d7e4166Sjose borrego 
5298d7e4166Sjose borrego ndr_hdid_t *ndr_hdalloc(const ndr_xa_t *, const void *);
5308d7e4166Sjose borrego void ndr_hdfree(const ndr_xa_t *, const ndr_hdid_t *);
5318d7e4166Sjose borrego ndr_handle_t *ndr_hdlookup(const ndr_xa_t *, const ndr_hdid_t *);
53268b2bbf2SGordon Ross void ndr_hdclose(ndr_pipe_t *);
5338d7e4166Sjose borrego 
5348d7e4166Sjose borrego ssize_t ndr_uiomove(caddr_t, size_t, enum uio_rw, struct uio *);
535da6c28aaSamw 
536*3299f39fSGordon Ross /*
537*3299f39fSGordon Ross  * An ndr_client_t is created while binding a client connection to hold
538*3299f39fSGordon Ross  * the context for calls made using that connection.
539*3299f39fSGordon Ross  *
540*3299f39fSGordon Ross  * Handles are RPC call specific and we use an inheritance mechanism to
541*3299f39fSGordon Ross  * ensure that each handle has a pointer to the client_t.  When the top
542*3299f39fSGordon Ross  * level (bind) handle is released, we close the connection.
543*3299f39fSGordon Ross  *
544*3299f39fSGordon Ross  * There are some places in libmlsvc where the code assumes that the
545*3299f39fSGordon Ross  * handle member is first in this struct.  careful
546*3299f39fSGordon Ross  */
547*3299f39fSGordon Ross typedef struct mlrpc_handle {
548*3299f39fSGordon Ross 	ndr_hdid_t	handle;		/* keep first */
549*3299f39fSGordon Ross 	ndr_client_t	*clnt;
550*3299f39fSGordon Ross } mlrpc_handle_t;
551*3299f39fSGordon Ross 
552*3299f39fSGordon Ross int mlrpc_clh_create(mlrpc_handle_t *, void *);
553*3299f39fSGordon Ross uint32_t mlrpc_clh_bind(mlrpc_handle_t *, ndr_service_t *);
554*3299f39fSGordon Ross void mlrpc_clh_unbind(mlrpc_handle_t *);
555*3299f39fSGordon Ross void *mlrpc_clh_free(mlrpc_handle_t *);
556*3299f39fSGordon Ross 
557*3299f39fSGordon Ross int ndr_rpc_call(mlrpc_handle_t *, int, void *);
558*3299f39fSGordon Ross int ndr_rpc_get_ssnkey(mlrpc_handle_t *, unsigned char *, size_t);
559*3299f39fSGordon Ross void *ndr_rpc_malloc(mlrpc_handle_t *, size_t);
560*3299f39fSGordon Ross ndr_heap_t *ndr_rpc_get_heap(mlrpc_handle_t *);
561*3299f39fSGordon Ross void ndr_rpc_release(mlrpc_handle_t *);
562*3299f39fSGordon Ross void ndr_rpc_set_nonull(mlrpc_handle_t *);
563*3299f39fSGordon Ross 
564*3299f39fSGordon Ross boolean_t ndr_is_null_handle(mlrpc_handle_t *);
565*3299f39fSGordon Ross boolean_t ndr_is_bind_handle(mlrpc_handle_t *);
566*3299f39fSGordon Ross void ndr_inherit_handle(mlrpc_handle_t *, mlrpc_handle_t *);
567*3299f39fSGordon Ross 
568da6c28aaSamw #ifdef	__cplusplus
569da6c28aaSamw }
570da6c28aaSamw #endif
571da6c28aaSamw 
572da6c28aaSamw #endif	/* _LIBMLRPC_H */
573