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