/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _LIBMLRPC_H
#define _LIBMLRPC_H
#include <smbsrv/wintypes.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* An MSRPC compatible implementation of OSF DCE RPC. DCE RPC is derived
* from the Apollo Network Computing Architecture (NCA) RPC implementation.
*
* CAE Specification (1997)
* DCE 1.1: Remote Procedure Call
* Document Number: C706
* The Open Group
* ogspecs@opengroup.org
*
* This implementation is based on the DCE Remote Procedure Call spec with
* enhancements to support Unicode strings. The diagram below shows the
* DCE RPC layers compared against ONC SUN RPC.
*
* NDR RPC Layers Sun RPC Layers Remark
* +---------------+ +---------------+ +---------------+
* +---------------+ +---------------+
* | Application | | Application | The application
* +---------------+ +---------------+
* | Hand coded | | RPCGEN gen'd | Where the real
* | srvsvc.ndl | | *_svc.c *_clnt|
* | srvsvc.c | | |
* +---------------+ +---------------+
* +---------------+ +---------------+
* | RPC Protocol | | RPC Protocol | Headers, Auth,
* | rpcpdu.ndl | | |
* +---------------+ +---------------+
* | IDL gen'd | | RPCGEN gen'd | Aggregate
* | NDR stubs | | XDR stubs | Composition
* +---------------+ +---------------+
* | NDR Represen | | XDR Represen | Byte order, padding
* +---------------+ +---------------+
* | Packet Heaps | | Network Conn | DCERPC does not talk
* | ndo_*.c | | clnt_{tcp,udp}| directly to network.
* +---------------+ +---------------+
*
* There are two major differences between the DCE RPC and ONC RPC:
*
* 1. NDR RPC only generates or processes packets from buffers. Other
* layers must take care of packet transmission and reception.
* The packet heaps are managed through a simple interface provided
* by the Network Data Representation (NDR) module called ndr_stream_t.
* ndo_*.c modules implement the different flavors (operations) of
* packet heaps.
*
* ONC RPC communicates directly with the network. You have to do
* something special for the RPC packet to be placed in a buffer
* rather than sent to the wire.
*
* 2. NDR RPC uses application provided heaps to support operations.
* A heap is a single, monolithic chunk of memory that NDR RPC manages
* as it allocates. When the operation and its result are done, the
* heap is disposed of as a single item. The transaction, which
* is the anchor of most operations, contains the necessary book-
* keeping for the heap.
*
* ONC RPC uses malloc() liberally throughout its run-time system.
* To free results, ONC RPC supports an XDR_FREE operation that
* traverses data structures freeing memory as it goes, whether
* it was malloc'd or not.
*/
/*
* Dispatch Return Code (DRC)
*
* 0x8000 15:01 Set to indicate a fault, clear indicates status
* 0x00FF 00:08 PTYPE_... of PDU, 0xFF for header
*/
/* Fake PTYPE DRC discriminators */
/* DRC Recognizers */
/*
* (Un)Marshalling category specifiers
*/
/*
* Resource category specifier
*/
/*
* Parameters. Usually #define'd with useful alias
*/
/* RPCHDR */
/* Request */
/* Bind */
/* API */
struct ndr_xa;
struct ndr_client;
typedef struct ndr_stub_table {
unsigned short opnum;
typedef struct ndr_service {
char *name;
char *desc;
char *endpoint;
char *sec_addr_port;
char *abstract_syntax_uuid;
char *transfer_syntax_uuid;
unsigned bind_instance_size;
int (*bind_req)();
int (*unbind_and_close)();
/*
* The list of bindings is anchored at a connection. Nothing in the
* RPC mechanism allocates them. Binding elements which have service==0
* indicate free elements. When a connection is instantiated, at least
* one free binding entry should also be established. Something like
* this should suffice for most (all) situations:
*
* struct connection {
* ....
* ndr_binding_t *binding_list_head;
* ndr_binding_t binding_pool[N_BINDING_POOL];
* ....
* };
*
* init_connection(struct connection *conn) {
* ....
* ndr_svc_binding_pool_init(&conn->binding_list_head,
* conn->binding_pool, N_BINDING_POOL);
*/
typedef struct ndr_binding {
unsigned char which_side;
void *instance_specific;
/*
* The binding list space must be provided by the application library
* for use by the underlying RPC library. We need at least two binding
* slots per connection.
*/
typedef struct ndr_pipe {
void *np_listener;
const char *np_endpoint;
int np_fid;
} ndr_pipe_t;
/*
* Number of bytes required to align SIZE on the next dword/4-byte
* boundary.
*/
/*
* DCE RPC strings (CAE section 14.3.4) are represented as varying or varying
* and conformant one-dimensional arrays. Characters can be single-byte
* or multi-byte as long as all characters conform to a fixed element size,
* i.e. UCS-2 is okay but UTF-8 is not a valid DCE RPC string format. The
* string is terminated by a null character of the appropriate element size.
*
* MSRPC strings should always be varying/conformant and not null terminated.
* This format uses the size_is, first_is and length_is attributes (CAE
* section 4.2.18).
*
* typedef struct string {
* DWORD size_is;
* DWORD first_is;
* DWORD length_is;
* wchar_t string[ANY_SIZE_ARRAY];
* } string_t;
*
* The size_is attribute is used to specify the number of data elements in
* each dimension of an array.
*
* The first_is attribute is used to define the lower bound for significant
* elements in each dimension of an array. For strings this is always 0.
*
* The length_is attribute is used to define the number of significant
* elements in each dimension of an array. For strings this is typically
* the same as size_is. Although it might be (size_is - 1) if the string
* is null terminated.
*
* 4 bytes 4 bytes 4 bytes 2bytes 2bytes 2bytes 2bytes
* +---------+---------+---------+------+------+------+------+
* |size_is |first_is |length_is| char | char | char | char |
* +---------+---------+---------+------+------+------+------+
*
* Unfortunately, not all MSRPC Unicode strings are null terminated, which
* means that the recipient has to manually null-terminate the string after
* it has been unmarshalled. There may be a wide-char pad following a
* string, and it may sometimes contains zero, but it's not guaranteed.
*
* To deal with this, MSRPC sometimes uses an additional wrapper with two
* more fields, as shown below.
* length: the array length in bytes excluding terminating null bytes
* maxlen: the array length in bytes including null terminator bytes
* LPTSTR: converted to a string_t by NDR
*
* typedef struct ms_string {
* WORD length;
* WORD maxlen;
* LPTSTR str;
* } ms_string_t;
*/
typedef struct ndr_mstring {
/*
* A number of heap areas are used during marshalling and unmarshalling.
* Under some circumstances these areas can be discarded by the library
* code, i.e. on the server side before returning to the client and on
* completion of a client side bind. In the case of a client side RPC
* call, these areas must be preserved after an RPC returns to give the
* caller time to take a copy of the data. In this case the client must
* call ndr_clnt_free_heap to free the memory.
*
* The heap management data definition looks a bit like this:
*
* heap -> +---------------+ +------------+
* | iovec[0].base | --> | data block |
* | iovec[0].len | +------------+
* +---------------+
* ::
* ::
* iov -> +---------------+ +------------+
* | iovec[n].base | --> | data block |
* | iovec[n].len | +------------+
* +---------------+ ^ ^
* | |
* next ----------------------+ |
* top -----------------------------------+
*
*/
/*
* Setting MAXIOV to 384 will use ((8 * 384) + 16) = 3088 bytes
* of the first heap block.
*/
typedef struct ndr_heap {
int iovcnt;
char *top;
char *next;
} ndr_heap_t;
/*
* Alternate varying/conformant string definition
* - for non-null-terminated strings.
*/
typedef struct ndr_vcs {
/*
* size_is (actually a copy of length_is) will
* be inserted here by the marshalling library.
*/
} ndr_vcs_t;
typedef struct ndr_vcstr {
} ndr_vcstr_t;
typedef struct ndr_vcb {
/*
* size_is (actually a copy of length_is) will
* be inserted here by the marshalling library.
*/
} ndr_vcb_t;
typedef struct ndr_vcbuf {
} ndr_vcbuf_t;
ndr_heap_t *ndr_heap_create(void);
void ndr_heap_destroy(ndr_heap_t *);
void *ndr_heap_malloc(ndr_heap_t *, unsigned);
void *ndr_heap_strdup(ndr_heap_t *, const char *);
int ndr_heap_used(ndr_heap_t *);
int ndr_heap_avail(ndr_heap_t *);
typedef struct ndr_xa {
unsigned short opnum;
} ndr_xa_t;
/*
* 20-byte opaque id used by various RPC services.
*/
typedef struct ndr_client {
/* transport stuff (xa_* members) */
void *xa_private;
int xa_fd;
unsigned next_p_cont_id;
} ndr_client_t;
typedef struct ndr_handle {
void *nh_data;
void (*nh_data_free)(void *);
} ndr_handle_t;
typedef struct ndr_buf {
} ndr_buf_t;
/* ndr_ops.c */
void nds_destruct(ndr_stream_t *);
void nds_show_state(ndr_stream_t *);
/* ndr_client.c */
int ndr_clnt_call(ndr_binding_t *, int, void *);
void ndr_clnt_free_heap(ndr_client_t *);
/* ndr_marshal.c */
void ndr_buf_fini(ndr_buf_t *);
void *);
int ndr_decode_call(ndr_xa_t *, void *);
int ndr_encode_return(ndr_xa_t *, void *);
int ndr_encode_call(ndr_xa_t *, void *);
int ndr_decode_return(ndr_xa_t *, void *);
int ndr_decode_pdu_hdr(ndr_xa_t *);
int ndr_encode_pdu_hdr(ndr_xa_t *);
void ndr_remove_frag_hdr(ndr_stream_t *);
void ndr_show_hdr(ndr_common_header_t *);
unsigned ndr_bind_ack_hdr_size(ndr_xa_t *);
unsigned ndr_alter_context_rsp_hdr_size(void);
/* ndr_server.c */
void ndr_pipe_worker(ndr_pipe_t *);
int ndr_generic_call_stub(ndr_xa_t *);
/* ndr_svc.c */
ndr_service_t *ndr_svc_lookup_name(const char *);
int ndr_svc_register(ndr_service_t *);
void ndr_svc_unregister(ndr_service_t *);
int ndr_uuid_parse(char *, ndr_uuid_t *);
void ndr_uuid_unparse(ndr_uuid_t *, char *);
void ndr_hdclose(ndr_pipe_t *);
#ifdef __cplusplus
}
#endif
#endif /* _LIBMLRPC_H */