Home | History | Annotate | Download | only in smbsrv
      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 2008 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #ifndef _SMBSRV_MLRPC_H
     27 #define	_SMBSRV_MLRPC_H
     28 
     29 #pragma ident	"@(#)mlrpc.h	1.3	08/01/04 SMI"
     30 
     31 /*
     32  * MSRPC Like RPC (MLRPC) is an MSRPC compatible implementation of OSF
     33  * DCE RPC.  DCE RPC is derived from the Apollo Network Computing
     34  * Architecture (NCA) RPC implementation.  This implementation is based
     35  * on the X/Open DCE: Remote Procedure Call specification.  The main
     36  * MSRPC compatibility issue is the use of Unicode strings.  This work
     37  * was originally based on the X/Open DCE Remote Procedure Call CAE
     38  * 1994 Specification.  The current DCE RPC specification is detailed
     39  * below.
     40  *
     41  * CAE Specification (1997)
     42  * DCE 1.1: Remote Procedure Call
     43  * Document Number: C706
     44  * The Open Group
     45  * ogspecs (at) opengroup.org
     46  */
     47 
     48 /*
     49  * Layering
     50  *
     51  * This shows the software layers of the DCE RPC system compared against
     52  * ONC SUN RPC.
     53  *
     54  *	MLRPC Layers		Sun RPC Layers		Remark
     55  *	+---------------+	+---------------+	+---------------+
     56  *	+---------------+	+---------------+
     57  *	| Application	|	| Application	|	The application
     58  *	+---------------+	+---------------+
     59  *	| Hand coded    |	| RPCGEN gen'd  |	Where the real
     60  *	| client/server |	| client/server |	work happens
     61  *	| srvsvc.ndl	|	| *_svc.c *_clnt|
     62  *	| srvsvc.c	|	|               |
     63  *	+---------------+	+---------------+
     64  *	| RPC Library	|	| RPC Library   |	Calls/Return
     65  *	| mlrpc_*.c     |	|               |	Binding/PMAP
     66  *	+---------------+	+---------------+
     67  *	| RPC Protocol	|	| RPC Protocol  |	Headers, Auth,
     68  *	| mlrpcpdu.ndl  |	|               |
     69  *	+---------------+	+---------------+
     70  *	| IDL gen'd	|	| RPCGEN gen'd  |	Aggregate
     71  *	| NDR stubs	|	| XDR stubs     |	Composition
     72  *	| *__ndr.c      |	| *_xdr.c       |
     73  *	+---------------+	+---------------+
     74  *	| NDR Represen	|	| XDR Represen  |	Byte order, padding
     75  *	+---------------+	+---------------+
     76  *	| Packet Heaps  |	| Network Conn  |	BIG DIFF: DCERPC does
     77  *	| mlndo_*.c     |	| clnt_{tcp,udp}|	not talk directly to
     78  *	+---------------+	+---------------+	network.
     79  *
     80  * There are two major differences between the DCE RPC and ONC RPC:
     81  *
     82  * 1. MLRPC only generates or processes packets from buffers.  Other
     83  *    layers must take care of packet transmission and reception.
     84  *    The packet heaps are managed through a simple interface provided
     85  *    by the Network Data Representation (NDR) module, called struct
     86  *    mlndr_stream.  mlndo_*.c modules implement the different flavors
     87  *    (operations) of packet heaps.
     88  *
     89  *    ONC RPC communicates directly with the network.  You have to do
     90  *    something special for the RPC packet to be placed in a buffer
     91  *    rather than sent to the wire.
     92  *
     93  * 2. MLRPC uses application provided heaps to support operations.
     94  *    A heap is a single, monolithic chunk of memory that MLRPC manages
     95  *    as it allocates.  When the operation and its result are done, the
     96  *    heap is disposed of as a single item.  The mlrpc_xaction, which
     97  *    is the anchor of most operations, contains the necessary book-
     98  *    keeping for the heap.
     99  *
    100  *    ONC RPC uses malloc() liberally throughout its run-time system.
    101  *    To free results, ONC RPC supports an XDR_FREE operation that
    102  *    traverses data structures freeing memory as it goes, whether
    103  *    it was malloc'd or not.
    104  */
    105 
    106 #include <smbsrv/ndl/rpcpdu.ndl>
    107 #include <sys/uio.h>
    108 #include <smbsrv/mlsvc.h>
    109 #include <smbsrv/ndr.h>
    110 
    111 #ifdef __cplusplus
    112 extern "C" {
    113 #endif
    114 
    115 /*
    116  * Dispatch Return Code (DRC)
    117  *
    118  *	0x8000	15:01	Set to indicate a fault, clear indicates status
    119  *	0x7F00	08:07	Status/Fault specific
    120  *	0x00FF	00:08	MLRPC_PTYPE_... of PDU, 0xFF for header
    121  */
    122 #define	MLRPC_DRC_MASK_FAULT			0x8000
    123 #define	MLRPC_DRC_MASK_SPECIFIER		0xFF00
    124 #define	MLRPC_DRC_MASK_PTYPE			0x00FF
    125 
    126 /* Usual stuff */
    127 #define	MLRPC_DRC_OK				0x0000
    128 
    129 /* Fake PTYPEs for MLRPC_DRC */
    130 #define	MLRPC_DRC_PTYPE_RPCHDR			0x00FF
    131 #define	MLRPC_DRC_PTYPE_API			0x00AA
    132 
    133 /* DRC Recognizers */
    134 #define	MLRPC_DRC_IS_OK(DRC)	(((DRC)&MLRPC_DRC_MASK_SPECIFIER) == 0)
    135 #define	MLRPC_DRC_IS_FAULT(DRC)	(((DRC)&MLRPC_DRC_MASK_FAULT) != 0)
    136 
    137 /*
    138  * (Un)Marshalling category specifiers
    139  */
    140 #define	MLRPC_DRC_FAULT_MODE_MISMATCH		0x8100
    141 #define	MLRPC_DRC_RECEIVED			0x0200
    142 #define	MLRPC_DRC_FAULT_RECEIVED_RUNT		0x8300
    143 #define	MLRPC_DRC_FAULT_RECEIVED_MALFORMED	0x8400
    144 #define	MLRPC_DRC_DECODED			0x0500
    145 #define	MLRPC_DRC_FAULT_DECODE_FAILED		0x8600
    146 #define	MLRPC_DRC_ENCODED			0x0700
    147 #define	MLRPC_DRC_FAULT_ENCODE_FAILED		0x8800
    148 #define	MLRPC_DRC_FAULT_ENCODE_TOO_BIG		0x8900
    149 #define	MLRPC_DRC_SENT				0x0A00
    150 #define	MLRPC_DRC_FAULT_SEND_FAILED		0x8B00
    151 
    152 /*
    153  * Resource category specifier
    154  */
    155 #define	MLRPC_DRC_FAULT_RESOURCE_1		0x9100
    156 #define	MLRPC_DRC_FAULT_RESOURCE_2		0x9200
    157 
    158 /*
    159  * Parameters. Usually #define'd with useful alias
    160  */
    161 #define	MLRPC_DRC_FAULT_PARAM_0_INVALID		0xC000
    162 #define	MLRPC_DRC_FAULT_PARAM_0_UNIMPLEMENTED	0xD000
    163 #define	MLRPC_DRC_FAULT_PARAM_1_INVALID		0xC100
    164 #define	MLRPC_DRC_FAULT_PARAM_1_UNIMPLEMENTED	0xD100
    165 #define	MLRPC_DRC_FAULT_PARAM_2_INVALID		0xC200
    166 #define	MLRPC_DRC_FAULT_PARAM_2_UNIMPLEMENTED	0xD200
    167 #define	MLRPC_DRC_FAULT_PARAM_3_INVALID		0xC300
    168 #define	MLRPC_DRC_FAULT_PARAM_3_UNIMPLEMENTED	0xD300
    169 
    170 #define	MLRPC_DRC_FAULT_OUT_OF_MEMORY		0xF000
    171 
    172 /* RPCHDR */
    173 #define	MLRPC_DRC_FAULT_RPCHDR_PTYPE_INVALID	0xC0FF	/* PARAM_0_INVALID */
    174 #define	MLRPC_DRC_FAULT_RPCHDR_PTYPE_UNIMPLEMENTED 0xD0FF /* PARAM_0_UNIMP */
    175 
    176 /* Request */
    177 #define	MLRPC_DRC_FAULT_REQUEST_PCONT_INVALID	0xC000	/* PARAM_0_INVALID */
    178 #define	MLRPC_DRC_FAULT_REQUEST_OPNUM_INVALID	0xC100	/* PARAM_1_INVALID */
    179 
    180 /* Bind */
    181 #define	MLRPC_DRC_FAULT_BIND_PCONT_BUSY		0xC00B	/* PARAM_0_INVALID */
    182 #define	MLRPC_DRC_FAULT_BIND_UNKNOWN_SERVICE	0xC10B	/* PARAM_1_INVALID */
    183 #define	MLRPC_DRC_FAULT_BIND_NO_SLOTS		0x910B	/* RESOURCE_1 */
    184 #define	MLRPC_DRC_BINDING_MADE			0x000B	/* OK */
    185 
    186 /* API */
    187 #define	MLRPC_DRC_FAULT_API_SERVICE_INVALID	0xC0AA	/* PARAM_0_INVALID */
    188 #define	MLRPC_DRC_FAULT_API_BIND_NO_SLOTS	0x91AA	/* RESOURCE_1 */
    189 #define	MLRPC_DRC_FAULT_API_OPNUM_INVALID	0xC1AA	/* PARAM_1_INVALID */
    190 
    191 struct mlrpc_xaction;
    192 
    193 typedef struct mlrpc_stub_table {
    194 	int		(*func)(void *param, struct mlrpc_xaction *mreq);
    195 	unsigned short	opnum;
    196 } mlrpc_stub_table_t;
    197 
    198 typedef struct mlrpc_service {
    199 	char		*name;
    200 	char		*desc;
    201 	char		*endpoint;
    202 	char		*sec_addr_port;
    203 	char		*abstract_syntax_uuid;
    204 	int		abstract_syntax_version;
    205 	char		*transfer_syntax_uuid;
    206 	int		transfer_syntax_version;
    207 	unsigned	bind_instance_size;
    208 	int		(*bind_req)();
    209 	int		(*unbind_and_close)();
    210 	int		(*call_stub)(struct mlrpc_xaction *mreq);
    211 	struct ndr_typeinfo *interface_ti;
    212 	struct mlrpc_stub_table *stub_table;
    213 } mlrpc_service_t;
    214 
    215 /*
    216  * 20-byte opaque id used by various RPC services.
    217  */
    218 typedef struct ndr_hdid {
    219 	uint32_t data[5];
    220 } ndr_hdid_t;
    221 
    222 typedef struct ndr_handle {
    223 	struct ndr_handle *nh_next;
    224 	ndr_hdid_t nh_id;
    225 	int nh_fid;
    226 	const mlrpc_service_t *nh_svc;
    227 	void *nh_data;
    228 } ndr_handle_t;
    229 
    230 /*
    231  * The list of bindings is anchored at a connection.  Nothing in the
    232  * RPC mechanism allocates them.  Binding elements which have service==0
    233  * indicate free elements.  When a connection is instantiated, at least
    234  * one free binding entry should also be established.  Something like
    235  * this should suffice for most (all) situations:
    236  *
    237  *	struct connection {
    238  *		....
    239  *		struct mlrpc_binding *binding_list_head;
    240  *		struct mlrpc_binding binding_pool[N_BINDING_POOL];
    241  *		....
    242  *	};
    243  *
    244  *	init_connection(struct connection *conn) {
    245  *		....
    246  *		mlrpc_binding_pool_initialize(&conn->binding_list_head,
    247  *		    conn->binding_pool, N_BINDING_POOL);
    248  */
    249 struct mlrpc_binding {
    250 	struct mlrpc_binding 	*next;
    251 	mlrpc_p_context_id_t	p_cont_id;
    252 	unsigned char		which_side;
    253 	void *			context;
    254 	struct mlrpc_service 	*service;
    255 	void 			*instance_specific;
    256 };
    257 
    258 #define	MLRPC_BIND_SIDE_CLIENT	1
    259 #define	MLRPC_BIND_SIDE_SERVER	2
    260 
    261 #define	MLRPC_BINDING_TO_SPECIFIC(BINDING, TYPE) \
    262 	((TYPE *) (BINDING)->instance_specific)
    263 
    264 /*
    265  * mlrpc_heap.c
    266  *
    267  * A number of heap areas are used during marshalling and unmarshalling.
    268  * Under some circumstances these areas can be discarded by the library
    269  * code, i.e. on the server side before returning to the client and on
    270  * completion of a client side bind.  In the case of a client side RPC
    271  * call, these areas must be preserved after an RPC returns to give the
    272  * caller time to take a copy of the data.  In this case the client must
    273  * call mlrpc_c_free_heap to free the memory.
    274  *
    275  * The heap management data definition looks a bit like this:
    276  *
    277  * heap -> +---------------+     +------------+
    278  *         | iovec[0].base | --> | data block |
    279  *         | iovec[0].len  |     +------------+
    280  *         +---------------+
    281  *                ::
    282  *                ::
    283  * iov  -> +---------------+     +------------+
    284  *         | iovec[n].base | --> | data block |
    285  *         | iovec[n].len  |     +------------+
    286  *         +---------------+     ^            ^
    287  *                               |            |
    288  *    next ----------------------+            |
    289  *    top  -----------------------------------+
    290  *
    291  */
    292 
    293 /*
    294  * Setting MAXIOV to 384 will use ((8 * 384) + 16) = 3088 bytes
    295  * of the first heap block.
    296  */
    297 #define	MLRPC_HEAP_MAXIOV		384
    298 #define	MLRPC_HEAP_BLKSZ		4096
    299 
    300 typedef struct mlrpc_heap {
    301 	struct iovec iovec[MLRPC_HEAP_MAXIOV];
    302 	struct iovec *iov;
    303 	int iovcnt;
    304 	char *top;
    305 	char *next;
    306 } mlrpc_heap_t;
    307 
    308 /*
    309  * To support the client-side heap preserve functionality.
    310  */
    311 #define	MLRPC_HRST_PRESERVED		1
    312 
    313 typedef struct mlrpc_heapref {
    314 	mlrpc_heap_t *heap;
    315 	char *recv_pdu_buf;
    316 	char *send_pdu_buf;
    317 	unsigned int state;
    318 } mlrpc_heapref_t;
    319 
    320 /*
    321  * Alternate varying/conformant string definition
    322  * - for non-null-terminated strings.
    323  */
    324 struct mlrpc_vcb {
    325 	/*
    326 	 * size_is (actually a copy of length_is) will
    327 	 * be inserted here by the marshalling library.
    328 	 */
    329 	DWORD vc_first_is;
    330 	DWORD vc_length_is;
    331 	WORD buffer[ANY_SIZE_ARRAY];
    332 };
    333 
    334 typedef struct mlrpc_vcbuf {
    335 	WORD wclen;
    336 	WORD wcsize;
    337 	struct mlrpc_vcb *vcb;
    338 } mlrpc_vcbuf_t;
    339 
    340 mlrpc_heap_t *mlrpc_heap_create(void);
    341 void mlrpc_heap_destroy(mlrpc_heap_t *);
    342 void *mlrpc_heap_malloc(mlrpc_heap_t *, unsigned);
    343 void *mlrpc_heap_strsave(mlrpc_heap_t *, char *);
    344 void mlrpc_heap_mkvcs(mlrpc_heap_t *, char *, mlrpc_vcbuf_t *);
    345 int mlrpc_heap_used(mlrpc_heap_t *);
    346 int mlrpc_heap_avail(mlrpc_heap_t *);
    347 
    348 #define	MLRPC_HEAP_MALLOC(MXA, SIZE) \
    349 	mlrpc_heap_malloc((MXA)->heap, SIZE)
    350 
    351 #define	MLRPC_HEAP_NEW(MXA, TYPE) \
    352 	mlrpc_heap_malloc((MXA)->heap, sizeof (TYPE))
    353 
    354 #define	MLRPC_HEAP_NEWN(MXA, TYPE, N) \
    355 	mlrpc_heap_malloc((MXA)->heap, sizeof (TYPE)*(N))
    356 
    357 #define	MLRPC_HEAP_STRSAVE(MXA, STR) \
    358 	mlrpc_heap_strsave((MXA)->heap, (STR))
    359 
    360 typedef struct mlrpc_xaction {
    361 	int			fid;
    362 	unsigned short		ptype;		/* just handy, hi bits spcl */
    363 	unsigned short		opnum;		/* for requests */
    364 	struct mlndr_stream	recv_mlnds;
    365 	mlrpcconn_hdr_t		recv_hdr;
    366 	struct mlndr_stream	send_mlnds;
    367 	mlrpcconn_hdr_t		send_hdr;
    368 	struct mlrpc_binding	*binding;	/* what we're using */
    369 	struct mlrpc_binding	*binding_list;	/* from connection */
    370 	mlrpc_heap_t		*heap;
    371 	struct mlsvc_rpc_context *context;
    372 } ndr_xa_t;
    373 
    374 struct mlrpc_client {
    375 	int (*xa_init)(struct mlrpc_client *, struct mlrpc_xaction *,
    376 	    mlrpc_heap_t *);
    377 	int (*xa_exchange)(struct mlrpc_client *, struct mlrpc_xaction *);
    378 	int (*xa_read)(struct mlrpc_client *, struct mlrpc_xaction *);
    379 	int (*xa_preserve)(struct mlrpc_client *, struct mlrpc_xaction *,
    380 	    mlrpc_heapref_t *);
    381 	int (*xa_destruct)(struct mlrpc_client *, struct mlrpc_xaction *);
    382 	void (*xa_release)(struct mlrpc_client *, mlrpc_heapref_t *);
    383 
    384 	void *context;
    385 	struct mlrpc_binding *binding_list;
    386 	uint32_t next_call_id;
    387 	unsigned next_p_cont_id;
    388 };
    389 
    390 /* ndr_ops.c */
    391 int mlnds_initialize(struct mlndr_stream *, unsigned, int, mlrpc_heap_t *);
    392 void mlnds_destruct(struct mlndr_stream *);
    393 
    394 /* ndr_client.c */
    395 int mlrpc_c_bind(struct mlrpc_client *, char *, struct mlrpc_binding **);
    396 int mlrpc_c_call(struct mlrpc_binding *, int, void *, mlrpc_heapref_t *);
    397 void mlrpc_c_free_heap(struct mlrpc_binding *, mlrpc_heapref_t *);
    398 
    399 /* ndr_marshal.c */
    400 int mlrpc_encode_decode_common(struct mlrpc_xaction *, int, unsigned,
    401     struct ndr_typeinfo *, void *);
    402 int mlrpc_decode_call(struct mlrpc_xaction *, void *);
    403 int mlrpc_encode_return(struct mlrpc_xaction *, void *);
    404 int mlrpc_encode_call(struct mlrpc_xaction *, void *);
    405 int mlrpc_decode_return(struct mlrpc_xaction *, void *);
    406 int mlrpc_decode_pdu_hdr(struct mlrpc_xaction *);
    407 int mlrpc_encode_pdu_hdr(struct mlrpc_xaction *);
    408 void mlrpc_decode_frag_hdr(struct mlndr_stream *, mlrpcconn_common_header_t *);
    409 unsigned mlrpc_bind_ack_hdr_size(struct mlrpcconn_bind_ack_hdr *);
    410 
    411 /* ndr_server.c */
    412 int mlrpc_generic_call_stub(struct mlrpc_xaction *);
    413 
    414 /* ndr_svc.c */
    415 struct mlrpc_stub_table *mlrpc_find_stub_in_svc(mlrpc_service_t *, int);
    416 mlrpc_service_t *mlrpc_find_service_by_name(const char *);
    417 mlrpc_service_t *mlrpc_find_service_by_uuids(ndr_uuid_t *, int,
    418     ndr_uuid_t *, int);
    419 int mlrpc_register_service(mlrpc_service_t *);
    420 void mlrpc_unregister_service(mlrpc_service_t *);
    421 void mlrpc_uuid_to_str(ndr_uuid_t *, char *);
    422 int mlrpc_str_to_uuid(char *, ndr_uuid_t *);
    423 void mlrpc_binding_pool_initialize(struct mlrpc_binding **,
    424     struct mlrpc_binding pool[], unsigned);
    425 struct mlrpc_binding *mlrpc_find_binding(struct mlrpc_xaction *,
    426     mlrpc_p_context_id_t);
    427 struct mlrpc_binding *mlrpc_new_binding(struct mlrpc_xaction *);
    428 
    429 ndr_hdid_t *ndr_hdalloc(const ndr_xa_t *, const void *);
    430 void ndr_hdfree(const ndr_xa_t *, const ndr_hdid_t *);
    431 ndr_handle_t *ndr_hdlookup(const ndr_xa_t *, const ndr_hdid_t *);
    432 void ndr_hdclose(int fid);
    433 
    434 
    435 #ifdef __cplusplus
    436 }
    437 #endif
    438 
    439 #endif /* _SMBSRV_MLRPC_H */
    440