summaryrefslogtreecommitdiff
path: root/usr/src/lib/libmlrpc/common/ndr.h
blob: f6af9a22cf24371a1df7ad8941db226f05a14c4d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
/*
 * 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
 * or http://www.opensolaris.org/os/licensing.
 * 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 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 *
 * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
 */

#ifndef _SMBSRV_NDR_H
#define	_SMBSRV_NDR_H

/*
 * Network Data Representation (NDR) is a compatible subset of DCE RPC
 * and MSRPC NDR.  NDR is used to move parameters consisting of
 * complicated trees of data constructs between an RPC client and server.
 *
 * CAE Specification (1997)
 * DCE 1.1: Remote Procedure Call
 * Document Number: C706
 * The Open Group
 * ogspecs@opengroup.org
 */

#include <sys/types.h>
#include <sys/uio.h>
#include <stdlib.h>
#include <string.h>

#include <smb/wintypes.h>
#include <libmlrpc/ndrtypes.ndl>
#include <libmlrpc/rpcpdu.ndl>

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Normal sequence:
 *	- Application calls client-side stub w/ TOP-MOST arg structure
 *	- client stub performs NDR_M_OP_MARSHALL+NDR_DIR_IN
 *	- PDU conveyed (request, aka call, aka query)
 *	- server stub performs NDR_M_OP_UNMARSHALL+NDR_DIR_IN
 *	- server function called w/ TOP-MOST arg structure
 *	- server function returns w/ TOP-MOST arg structure modified
 *	- server stub performs NDR_M_OP_MARSHALL+NDR_DIR_OUT
 *	- PDU conveyed (reply, aka result, aka response)
 *	- client stub performs NDR_M_OP_UNMARSHALL+NDR_DIR_OUT
 *	- return to Application w/ TOP-MOST arg structure modified
 *
 * An interface is a sequence of top-most constructs.  Each top-most
 * construct corresponds to one parameter, either argument or return
 * value.
 *
 * A top-most construct is a sequence of outer constructs.  The first
 * outer construct is the referent of the argument, and the subsequent
 * outer constructs are descendents referenced by pointers from prior
 * constructs.
 *
 * An outer construct is a sequence of variable-sized info, fixed-sized
 * data, and variable-sized data.
 */

/*
 * Terminology
 *
 * The ALL UPPER CASE terms recur in the DCE/RPC documentation.
 * The mixed-case names have been introduced as a reading aid.
 *
 * Size		The size of an array in elements. Think of this
 *		as the amount to malloc().
 *
 * Length	The number of elements of an array which are significant
 *		Think of this as the amount to bcopy().
 *
 * Known	Size/length is known at build time.
 *
 * Determined	Size/length is determined at run time.
 *
 * FIXED	The Size and Length are Known.
 *		Think of this as a string constant or a DOS 8.3 file name.
 *		char array[] = "A Constant Size/Length";
 *
 * CONFORMANT	The Size is Determined. Length is the same as Size.
 *		Think of this as strdup().
 *		char *array = strdup("Something");
 *
 * VARYING	The Size is Known. The Length is determined.
 *		Think of this as a strcpy() of a variable length string
 *		into a fixed length buffer:
 *		char array[100];
 *		strcpy(array, "very short string");
 *
 * VARYING/CONFORMANT
 *		The Size is Determined. The Length is separately Determined.
 *		Think of this like:
 *		char *array = malloc(size);
 *		strcpy(array, "short string");
 *
 * STRING	Strings can be CONFORMANT, VARYING, or CONFORMANT/VARYING.
 *		A string is fundamentally an array with the last
 *		significant element some sort of NULL.
 */

#define	NDR_F_NONE		0x0000	/* no flags */
#define	NDR_F_PARAMS_MASK	0x00FF
#define	NDR_F_SIZE_IS		0x0001	/* [size_is(X)] required/given */
#define	NDR_F_LENGTH_IS		0x0002	/* not implemented */
#define	NDR_F_SWITCH_IS		0x0004	/* [switch_is(X)] req./given */
#define	NDR_F_IS_STRING		0x0008	/* [string] req./given */
#define	NDR_F_IS_POINTER	0x0010	/* TYPE * ... req./given */
#define	NDR_F_IS_REFERENCE	0x0020	/* TYPE & ... req./given */
#define	NDR_F_DIMENSION_IS	0x0040	/* TYPE [N] req./given */

#define	NDR_F_WHENCE_MASK	0x00F0
#define	NDR_F_BACKPTR		0x0010	/* ref cause by pointer */
#define	NDR_F_OUTER		0x0020	/* ref caused by outer */
#define	NDR_F_TOPMOST		0x0040	/* ref caused by topmost */

#define	NDR_F_TYPEOP_MASK	0x0F00
#define	NDR_F_ARRAY		0x0100	/* type is array of somethings */
#define	NDR_F_POINTER		0x0200	/* type is pointer to something(s) */
#define	NDR_F_STRING		0x0300	/* type is string of somethings */
#define	NDR_F_UNION		0x0400	/* type is a union */
#define	NDR_F_STRUCT		0x0500	/* type is a structure */
#define	NDR_F_OPERATION		0x0600	/* type is a structure, special */
#define	NDR_F_INTERFACE		0x0700	/* type is a union, special */
#define	NDR_F_CONFORMANT	0x1000	/* struct conforming (var-size tail) */
#define	NDR_F_VARYING		0x2000	/* not implemented */

struct ndr_heap;
struct ndr_stream;
struct ndr_reference;

typedef uint16_t ndr_wchar_t;

typedef struct ndr_typeinfo {
	unsigned char		version;	/* sanity check */
	unsigned char		alignment;	/* mask */
	unsigned short		type_flags;	/* NDR_F_... */
	int			(*ndr_func)(struct ndr_reference *);
	unsigned short		pdu_size_fixed_part;
	unsigned short		pdu_size_variable_part;
	unsigned short		c_size_fixed_part;
	unsigned short		c_size_variable_part;
} ndr_typeinfo_t;

typedef struct ndr_reference {
	struct ndr_reference	*next;		/* queue list (outer only) */
	struct ndr_reference	*enclosing;	/* e.g. struct for this memb */
	struct ndr_stream	*stream;	/* root of NDR */
	ndr_typeinfo_t		*ti;		/* type of data referenced */
	char			*name;		/* name of this member */
	unsigned long		pdu_offset;	/* referent in stub data */
	char			*datum;		/* referent in local memory */
	char			**backptr;	/* referer to set */
	unsigned short		outer_flags;	/* XXX_is() from top level */
	unsigned short		inner_flags;	/* XXX_is() in encapsulated */
	unsigned short		type_flags;	/* "requires" */
	unsigned short		packed_alignment;
	unsigned long		size_is;	/* conforming constructs */
	unsigned long		strlen_is;	/* strings */
	unsigned long		switch_is;	/* union arg selector */
	unsigned long		dimension_is;	/* fixed-len array size */
	unsigned long		pdu_end_offset;	/* offset for limit of PDU */
} ndr_ref_t;

/*
 * For all operations, the ndr_stream, which is the root of NDR processing,
 * is the primary object.  When available, the appropriate ndr_ref_t
 * is passed, NULL otherwise.  Functions that return 'int' should return
 * TRUE (!0) or FALSE (0).  When functions return FALSE, including
 * ndo_malloc() returning NULL, they should set the stream->error to an
 * appropriate indicator of what went wrong.
 *
 * Functions ndo_get_pdu(), ndo_put_pdu(), and ndo_pad_pdu() must
 * never grow the PDU data.  A request for out-of-bounds data is an error.
 * The swap_bytes flag is 1 if NDR knows that the byte-order in the PDU
 * is different from the local system.  ndo_pad_pdu() advised that the
 * affected bytes should be zero filled.
 */
typedef struct ndr_stream_ops {
	char *(*ndo_malloc)(struct ndr_stream *, unsigned, ndr_ref_t *);
	int (*ndo_free)(struct ndr_stream *, char *, ndr_ref_t *);
	int (*ndo_grow_pdu)(struct ndr_stream *, unsigned long, ndr_ref_t *);
	int (*ndo_pad_pdu)(struct ndr_stream *, unsigned long,
	    unsigned long, ndr_ref_t *);
	int (*ndo_get_pdu)(struct ndr_stream *, unsigned long,
	    unsigned long, char *, int, ndr_ref_t *);
	int (*ndo_put_pdu)(struct ndr_stream *, unsigned long,
	    unsigned long, char *, int, ndr_ref_t *);
	void (*ndo_tattle)(struct ndr_stream *, char *, ndr_ref_t *);
	void (*ndo_tattle_error)(struct ndr_stream *, ndr_ref_t *);
	int (*ndo_reset)(struct ndr_stream *);
	void (*ndo_destruct)(struct ndr_stream *);
} ndr_stream_ops_t;

#define	NDS_MALLOC(NDS, LEN, REF) \
	(*(NDS)->ndo->ndo_malloc)(NDS, LEN, REF)
#define	NDS_GROW_PDU(NDS, WANT_END_OFF, REF) \
	(*(NDS)->ndo->ndo_grow_pdu)(NDS, WANT_END_OFF, REF)
#define	NDS_PAD_PDU(NDS, PDU_OFFSET, N_BYTES, REF) \
	(*(NDS)->ndo->ndo_pad_pdu)(NDS, PDU_OFFSET, N_BYTES, REF)
#define	NDS_GET_PDU(NDS, PDU_OFFSET, N_BYTES, BUF, SWAP, REF) \
	(*(NDS)->ndo->ndo_get_pdu)(NDS, PDU_OFFSET, N_BYTES, BUF, SWAP, REF)
#define	NDS_PUT_PDU(NDS, PDU_OFFSET, N_BYTES, BUF, SWAP, REF) \
	(*(NDS)->ndo->ndo_put_pdu)(NDS, PDU_OFFSET, N_BYTES, BUF, SWAP, REF)
#define	NDS_TATTLE(NDS, WHAT, REF) \
	(*(NDS)->ndo->ndo_tattle)(NDS, WHAT, REF)
#define	NDS_TATTLE_ERROR(NDS, WHAT, REF) \
	(*(NDS)->ndo->ndo_tattle_error)(NDS, REF)
#define	NDS_RESET(NDS)		(*(NDS)->ndo->ndo_reset)(NDS)
#define	NDS_DESTRUCT(NDS)	(*(NDS)->ndo->ndo_destruct)(NDS)

typedef struct ndr_stream {
	unsigned long		pdu_size;
	unsigned long		pdu_max_size;
	unsigned long		pdu_base_offset;
	unsigned long		pdu_scan_offset;
	unsigned char		*pdu_base_addr;

	ndr_stream_ops_t	*ndo;

	unsigned char		m_op;
	unsigned char		dir;
	unsigned char		swap;		/* native/net endian swap */
	unsigned char		flags;
	short			error;
	short			error_ref;

	ndr_ref_t *outer_queue_head;
	ndr_ref_t **outer_queue_tailp;
	ndr_ref_t *outer_current;
	struct ndr_heap *heap;
} ndr_stream_t;

#define	NDR_M_OP_NONE		0x00
#define	NDR_M_OP_MARSHALL	0x01	/* data moving from datum to PDU */
#define	NDR_M_OP_UNMARSHALL	0x02	/* data moving from PDU to datum */

#define	NDR_DIR_NONE		0x00
#define	NDR_DIR_IN		0x10	/* data moving from caller to callee */
#define	NDR_DIR_OUT		0x20	/* data moving from callee to caller */

#define	NDR_MODE_CALL_SEND	(NDR_M_OP_MARSHALL + NDR_DIR_IN)
#define	NDR_MODE_CALL_RECV	(NDR_M_OP_UNMARSHALL + NDR_DIR_IN)
#define	NDR_MODE_RETURN_SEND	(NDR_M_OP_MARSHALL + NDR_DIR_OUT)
#define	NDR_MODE_RETURN_RECV	(NDR_M_OP_UNMARSHALL + NDR_DIR_OUT)
#define	NDR_MODE_BUF_ENCODE	NDR_MODE_CALL_SEND
#define	NDR_MODE_BUF_DECODE	NDR_MODE_RETURN_RECV

#define	NDR_MODE_TO_M_OP(MODE)	((MODE) & 0x0F)
#define	NDR_MODE_TO_DIR(MODE)	((MODE) & 0xF0)
#define	NDR_M_OP_AND_DIR_TO_MODE(M_OP, DIR)	((M_OP)|(DIR))

#define	NDR_MODE_MATCH(NDS, MODE) \
	(NDR_M_OP_AND_DIR_TO_MODE((NDS)->m_op, (NDS)->dir) == (MODE))

#define	NDR_IS_FIRST_FRAG(F)	((F) & NDR_PFC_FIRST_FRAG)
#define	NDR_IS_LAST_FRAG(F)	((F) & NDR_PFC_LAST_FRAG)
#define	NDR_IS_SINGLE_FRAG(F)	\
	(NDR_IS_FIRST_FRAG((F)) && NDR_IS_LAST_FRAG((F)))

#define	NDS_F_NONE		0x00
#define	NDS_F_NOTERM		0x01	/* strings are not null terminated */
#define	NDS_F_NONULL		0x02	/* strings: no null on size_is */
#define	NDS_SETF(S, F)		((S)->flags |= (F))
#define	NDS_CLEARF(S, F)	((S)->flags &= ~(F))

#define	NDR_ERR_MALLOC_FAILED		-1
#define	NDR_ERR_M_OP_INVALID		-2
#define	NDR_ERR_UNDERFLOW		-3
#define	NDR_ERR_GROW_FAILED		-4	/* overflow */
#define	NDR_ERR_PAD_FAILED		-5	/* couldn't possibly happen */
#define	NDR_ERR_OUTER_HEADER_BAD	-6
#define	NDR_ERR_SWITCH_VALUE_ILLEGAL	-7
#define	NDR_ERR_SWITCH_VALUE_INVALID	-8
#define	NDR_ERR_SWITCH_VALUE_MISSING	-9
#define	NDR_ERR_SIZE_IS_MISMATCH_PDU	-10
#define	NDR_ERR_SIZE_IS_MISMATCH_AFTER	-11
#define	NDR_ERR_SIZE_IS_UNEXPECTED	-12
#define	NDR_ERR_SIZE_IS_DUPLICATED	-13
#define	NDR_ERR_OUTER_PARAMS_MISMATCH	-14
#define	NDR_ERR_ARRAY_VARLEN_ILLEGAL	-15
#define	NDR_ERR_ARRAY_UNION_ILLEGAL	-16
#define	NDR_ERR_OUTER_PARAMS_BAD	-17
#define	NDR_ERR_OUTER_UNION_ILLEGAL	-18
#define	NDR_ERR_TOPMOST_UNION_ILLEGAL	-19
#define	NDR_ERR_TOPMOST_VARLEN_ILLEGAL	-20
#define	NDR_ERR_INNER_PARAMS_BAD	-21
#define	NDR_ERR_UNIMPLEMENTED		-22
#define	NDR_ERR_NOT_AN_INTERFACE	-23
#define	NDR_ERR_STRLEN			-24
#define	NDR_ERR_STRING_SIZING		-25
#define	NDR_ERR_BOUNDS_CHECK		-26

#define	NDR_SET_ERROR(REF, ERROR)			\
	((REF)->stream->error = (ERROR),		\
	(REF)->stream->error_ref = __LINE__,		\
	NDS_TATTLE_ERROR((REF)->stream, 0, REF))

#define	NDR_TATTLE(REF, WHAT) \
	(*(REF)->stream->ndo->ndo_tattle)((REF)->stream, WHAT, REF)

#define	MEMBER_STR(MEMBER) #MEMBER

#define	NDR_DIR_IS_IN  (encl_ref->stream->dir == NDR_DIR_IN)
#define	NDR_DIR_IS_OUT (encl_ref->stream->dir == NDR_DIR_OUT)

#define	NDR_MEMBER_WITH_ARG(TYPE, MEMBER, OFFSET, \
		ARGFLAGS, ARGMEM, ARGVAL) { \
		myref.pdu_offset = encl_ref->pdu_offset + (OFFSET);	\
		myref.name = MEMBER_STR(MEMBER);			\
		myref.datum = (char *)&val->MEMBER;			\
		myref.inner_flags = ARGFLAGS;				\
		myref.ti = &ndt_##TYPE;					\
		myref.ARGMEM = ARGVAL;					\
		if (!ndr_inner(&myref))					\
			return (0);					\
	}

#define	NDR_MEMBER(TYPE, MEMBER, OFFSET) \
	NDR_MEMBER_WITH_ARG(TYPE, MEMBER, OFFSET, \
		NDR_F_NONE, size_is, 0)

#define	NDR_MEMBER_ARR_WITH_SIZE_IS(TYPE, MEMBER, OFFSET, SIZE_IS) \
	NDR_MEMBER_WITH_ARG(TYPE, MEMBER, OFFSET, \
		NDR_F_SIZE_IS, size_is, SIZE_IS)

#define	NDR_MEMBER_ARR_WITH_DIMENSION(TYPE, MEMBER, OFFSET, SIZE_IS) \
	NDR_MEMBER_WITH_ARG(TYPE, MEMBER, OFFSET, \
		NDR_F_DIMENSION_IS, dimension_is, SIZE_IS)

#define	NDR_MEMBER_PTR_WITH_SIZE_IS(TYPE, MEMBER, OFFSET, SIZE_IS) \
	NDR_MEMBER_WITH_ARG(TYPE, MEMBER, OFFSET, \
		NDR_F_SIZE_IS+NDR_F_IS_POINTER, size_is, SIZE_IS)

#define	NDR_MEMBER_PTR(TYPE, MEMBER, OFFSET)		\
	NDR_MEMBER_WITH_ARG(TYPE, MEMBER, OFFSET,	\
		NDR_F_IS_POINTER, size_is, 0)

#define	NDR_MEMBER_WITH_SWITCH_IS(TYPE, MEMBER, OFFSET, SWITCH_IS)	\
	NDR_MEMBER_WITH_ARG(TYPE, MEMBER, OFFSET,			\
		NDR_F_SWITCH_IS, switch_is, SWITCH_IS)


#define	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER, \
		ARGFLAGS, ARGMEM, ARGVAL) { \
		myref.pdu_offset = -1;					\
		myref.name = MEMBER_STR(MEMBER);			\
		myref.datum = (char *)&val->MEMBER;			\
		myref.inner_flags = ARGFLAGS;				\
		myref.ti = &ndt_##TYPE;					\
		myref.ARGMEM = ARGVAL;					\
		if (!ndr_topmost(&myref))				\
			return (0);					\
	}

#define	NDR_TOPMOST_MEMBER(TYPE, MEMBER)	   			\
	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,			\
		NDR_F_NONE, size_is, 0)

#define	NDR_TOPMOST_MEMBER_ARR_WITH_SIZE_IS(TYPE, MEMBER, SIZE_IS)	\
	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,		    	\
		NDR_F_SIZE_IS, size_is, SIZE_IS)

#define	NDR_TOPMOST_MEMBER_ARR_WITH_DIMENSION(TYPE, MEMBER, SIZE_IS)	\
	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,		      	\
		NDR_F_DIMENSION_IS, dimension_is, SIZE_IS)

#define	NDR_TOPMOST_MEMBER_PTR_WITH_SIZE_IS(TYPE, MEMBER, SIZE_IS)	\
	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,			\
		NDR_F_SIZE_IS+NDR_F_IS_POINTER, size_is, SIZE_IS)

#define	NDR_TOPMOST_MEMBER_PTR(TYPE, MEMBER)		\
	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,	\
		NDR_F_IS_POINTER, size_is, 0)

#define	NDR_TOPMOST_MEMBER_REF(TYPE, MEMBER)		\
	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,	\
		NDR_F_IS_REFERENCE, size_is, 0)

#define	NDR_TOPMOST_MEMBER_REF_WITH_SIZE_IS(TYPE, MEMBER, SIZE_IS)	\
	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,			\
		NDR_F_SIZE_IS+NDR_F_IS_REFERENCE, size_is, SIZE_IS)

#define	NDR_TOPMOST_MEMBER_WITH_SWITCH_IS(TYPE, MEMBER, SWITCH_IS)	\
	NDR_TOPMOST_MEMBER_WITH_ARG(TYPE, MEMBER,			\
		NDR_F_SWITCH_IS, switch_is, SWITCH_IS)

/* this is assuming offset+0 */
#define	NDR_PARAMS_MEMBER_WITH_ARG(TYPE, MEMBER, ARGFLAGS, \
	ARGMEM, ARGVAL) { \
		myref.pdu_offset = encl_ref->pdu_offset;		\
		myref.name = MEMBER_STR(MEMBER);			\
		myref.datum = (char *)&val->MEMBER;			\
		myref.inner_flags = ARGFLAGS;				\
		myref.ti = &ndt_##TYPE;					\
		myref.ARGMEM = ARGVAL;					\
		if (!ndr_params(&myref))				\
			return (0);					\
	}

#define	NDR_PARAMS_MEMBER(TYPE, MEMBER)			\
	NDR_PARAMS_MEMBER_WITH_ARG(TYPE, MEMBER,	\
	NDR_F_NONE, size_is, 0)

#define	NDR_STRING_DIM		1
#define	NDR_ANYSIZE_DIM		1

int ndo_process(struct ndr_stream *, ndr_typeinfo_t *, char *);
int ndo_operation(struct ndr_stream *, ndr_typeinfo_t *, int opnum, char *);
void ndo_printf(struct ndr_stream *, ndr_ref_t *, const char *, ...);
void ndo_trace(const char *);
void ndo_fmt(struct ndr_stream *, ndr_ref_t *, char *);

int ndr_params(ndr_ref_t *);
int ndr_topmost(ndr_ref_t *);
int ndr_run_outer_queue(struct ndr_stream *);
int ndr_outer(ndr_ref_t *);
int ndr_outer_fixed(ndr_ref_t *);
int ndr_outer_fixed_array(ndr_ref_t *);
int ndr_outer_conformant_array(ndr_ref_t *);
int ndr_outer_conformant_construct(ndr_ref_t *);
int ndr_size_is(ndr_ref_t *);
int ndr_outer_string(ndr_ref_t *);
int ndr_outer_peek_sizing(ndr_ref_t *, unsigned, unsigned long *);
int ndr_outer_poke_sizing(ndr_ref_t *, unsigned, unsigned long *);
int ndr_outer_align(ndr_ref_t *);
int ndr_outer_grow(ndr_ref_t *, unsigned);
int ndr_inner(ndr_ref_t *);
int ndr_inner_pointer(ndr_ref_t *);
int ndr_inner_reference(ndr_ref_t *);
int ndr_inner_array(ndr_ref_t *);

size_t ndr_mbstowcs(struct ndr_stream *, ndr_wchar_t *, const char *, size_t);

void nds_bswap(void *src, void *dst, size_t len);

#ifdef __cplusplus
}
#endif

#endif /* _SMBSRV_NDR_H */