1 NDRGEN(1ONBLD) illumos Build Tools NDRGEN(1ONBLD)
2
3
4
5 NAME
6 ndrgen - NDL RPC protocol compiler
7
8 SYNOPSIS
9 ndrgen [ -Y cpp-path ] file [ file ] ...
10
11
12 DESCRIPTION
13 The ndrgen utility is a tool that generates C code to implement a
14 DCERPC/MSRPC Network Data Representation (NDR) protocol. The input to
15 ndrgen is a language similar to C known as Network Data Language (NDL).
16
17
18 The ndrgen utility takes an input protocol definition file and
19 generates an output C source file that contains the marshalling
20 routines to implement the RPC protocol. If the input file is named
21 proto.ndl, ndrgen generates NDR routines in proto_ndr.c. Applications
22 must define the service definition and server-side stub table for use
23 with the RPC protocol.
24
25
26 The following is an example stub table and service definition:
27
28 static stub_table_t net_svc_stub_table[] = {
29 { svc_close, SVC_CLOSE },
30 { svc_open, SVC_OPEN },
31 { svc_read, SVC_READ },
32 { svc_write, SVC_WRITE },
33 {0}
34 };
35
36 static service_t net_svc = {
37 "NETSVC", /* name */
38 "Network Service", /* description */
39 "\\netsvc", /* endpoint */
40 "\\pipe\\netsvc", /* secondary address port */
41 "12345678-1234-abcd-ef0001234567abcd", 1, /* abstract syntax */
42 "8a885d04-1ceb-11c9-9fe808002b104860", 2, /* transfer syntax */
43 0, /* bind_instance_size */
44 0, /* bind_req() */
45 0, /* unbind_and_close() */
46 0, /* call_stub() */
47 &TYPEINFO(svc_interface), /* interface ti */
48 net_svc_stub_table /* stub_table */
49 };
50
51
52
53 The C preprocessor, which can be specified in the CC environment
54 variable or on the command line, is run on the input file before it is
55 interpreted by ndrgen. The NDRGEN preprocessor symbol is defined by
56 ndrgen for use by the ndrgen programmer.
57
58
59 The NDR generated by ndrgen is an MSRPC compatible implementation of
60 OSF DCE NDR. This implementation is based on the X/Open DCE: Remote
61 Procedure Call specification (CAE Specification (1997), DCE 1.1: Remote
62 Procedure Call Document Number: C706), enhanced for compatibility with
63 MSRPC Unicode (UCS-2) strings.
64
65
66 The following table shows the DCE RPC layering compared against ONC
67 RPC.
68
69 DCE RPC Layers ONC RPC Layers Remark
70 +---------------+ +---------------+ +----------------+
71 +---------------+ +---------------+
72 | Application | | Application | The application
73 +---------------+ +---------------+
74 | Hand coded | | RPCGEN gen'd |
75 | client/server | | client/server | Generated stubs
76 | proto.ndl | | *_svc.c *_clnt|
77 | proto.c | | |
78 +---------------+ +---------------+
79 | | | | Binding/PMAP
80 | RPC Library | | RPC Library | Calls/Return
81 +---------------+ +---------------+
82 | RPC Protocol | | RPC Protocol | Headers
83 | rpcpdu.ndl | | | Authentication
84 +---------------+ +---------------+
85 | NDRGEN gen'd | | RPCGEN gen'd | Aggregation
86 | NDR stubs | | XDR stubs | Composition
87 | *__ndr.c | | *_xdr.c |
88 +---------------+ +---------------+
89 | NDR | | XDR | Byte order, padding
90 +---------------+ +---------------+
91 | | | Network Conn | Large difference:
92 | Heap | | clnt_tcp | see below.
93 | Management | | clnt_udp |
94 +---------------+ +---------------+
95
96
97
98 There are two major differences between the DCE RPC and ONC RPC:
99
100 1. DCE RPC only generates or processes packets from buffers.
101 Other layers must take care of packet transmission and
102 reception. The packet heaps are managed through a simple
103 interface provided by NDR streams.
104
105 ONC RPC communicates directly with the network. The
106 programmer must do specific setup for the RPC packet to be
107 placed in a buffer rather than sent to the wire.
108
109 2. DCE RPC uses application provided heaps to support
110 operations. A heap is a managed chunk of memory that NDR
111 manages as it allocates. When the operation and its result
112 are complete, the heap is disposed of as a single item.
113 Transactions, which are the anchor of most operations,
114 perform heap bookkeeping.
115
116 ONC RPC uses malloc() liberally throughout its run-time
117 system. To free results, ONC RPC supports an XDR_FREE
118 operation that traverses data structures freeing memory as
119 it goes.
120
121
122 The following terminology is used in the subsequent discussion of NDR.
123
124 Size
125 The size of an array in elements, such as the amount to malloc().
126
127
128 Length
129 The number of significant elements of an array.
130
131
132 Known
133 Size or Length is known at build time.
134
135
136 Determined
137 Size or Length is determined at run time.
138
139
140 Fixed
141 The Size and Length are Known, such as a string constant:
142
143 char array[] = "A constant Size/Length";
144
145
146
147
148 The following DCE RPC terminology is used in the subsequent discussion.
149
150 Conformant
151 The Size is Determined. The Length is the same as Size.
152
153
154
155
156 Varying
157 The Size is Known. The Length is Determined, such as a strcpy() of
158 a variable length string into a fixed length buffer:
159
160 char array[100];
161 strcpy(array, "very short string");
162
163
164
165 Varying and Conformant
166 The Size is Determined. The Length is separately Determined, such
167 as:
168
169 char *array = malloc(size);
170 strcpy(array, "short string");
171
172
173
174 Strings
175 DCE RPC strings are represented as varying or varying and conformant
176 one-dimensional arrays. Characters can be single-byte or multi-byte as
177 long as all characters conform to a fixed element size. For instance,
178 UCS-2 is valid, but UTF-8 is not a valid DCE RPC string format. The
179 string is terminated by a null character of the appropriate element
180 size.
181
182
183 MSRPC strings are always varying and conformant format and not null
184 terminated. This format uses the size_is, first_is, and length_is
185 attributes:
186
187 typedef struct string {
188 DWORD size_is;
189 DWORD first_is;
190 DWORD length_is;
191 wchar_t string[ANY_SIZE_ARRAY];
192 } string_t;
193
194
195
196 The size_is attribute is used to specify the number of data elements in
197 each dimension of an array.
198
199
200 The first_is attribute is used to define the lower bound for
201 significant elements in each dimension of an array. For strings, this
202 value is always zero.
203
204
205 The length_is attribute is used to define the number of significant
206 elements in each dimension of an array. For strings, this value is
207 typically the same as size_is, although it might be (size_is - 1) if
208 the string is null terminated.
209
210
211 MSRPC Unicode strings are not null terminated, which means that the
212 recipient must manually null-terminate the string after it has been
213 received. Note that there is often a wide-char pad following a string,
214 which might contain zero but this situation is not guaranteed.
215
216 4 bytes 4 bytes 4 bytes 2bytes 2bytes 2bytes 2bytes
217 +---------+---------+---------+------+------+------+------+
218 |size_is |first_is |length_is| char | char | char | char |
219 +---------+---------+---------+------+------+------+------+
220
221
222
223 Despite the general rule, some MSRPC services use null-terminated
224 Unicode strings. To compensate, MSRPC uses the following additional
225 string wrapper with two additional fields. Note that LPTSTR is
226 automatically converted to string_t by the NDR library.
227
228 typedef struct msrpc_string {
229 WORD length;
230 WORD maxlen;
231 LPTSTR str;
232 } msrpc_string_t;
233
234
235
236 Here, length is the array length in bytes excluding any terminating
237 null bytes and maxlen is the array length in bytes including the
238 terminating null bytes.
239
240 NDL Syntax
241 The ndrgen input must be a valid C header file. Thus, NDL is defined by
242 using macros to map to DCE RPC IDL. The following shows the mappings:
243
244 NDRGEN NDL DCE RPC IDL
245 ================================
246 OPERATION(X) [operation(X)]
247 IN [in]
248 OUT [out]
249 INOUT [in out]
250 STRING [string]
251 SIZE_IS(X) [size_is(X)]
252 SWITCH(X) [switch_is(X)]
253 CASE(X) [case(X)]
254 DEFAULT [default]
255 INTERFACE(X) [interface(X)]
256 UUID(X) [uuid(X)]
257 ARG_IS(X) [arg_is(X)]
258 REFERENCE [reference]
259 ANY_SIZE_ARRAY *
260 IMPORT_EXTERN [extern]
261
262
263
264 The following shows the C data type associated with the NDRGEN NDL:
265
266 NDRGEN NDL C Data Type
267 ==============================
268 BYTE unsigned char
269 WORD unsigned short
270 DWORD unsigned long
271 LPTSTR wchar_t *
272 LPBYTE unsigned char *
273 LPWORD unsigned short *
274 LPDWORD unsigned long *
275
276
277 OPTIONS
278 The smbutil command supports the following global option:
279
280 -Y
281 Specifies the path to the cpp program.
282
283
284 EXAMPLES
285 The following is an example NDL header file:
286
287 #ifndef _SVC_NDL_
288 #define _SVC_NDL_
289
290 #include "ndrtypes.ndl"
291
292 /*
293 * Opnums: note that ndrgen does not automatically number
294 * operations and the values do not have to be sequential.
295 */
296 #define SVC_CLOSE 0x00
297 #define SVC_OPEN 0x01
298 #define SVC_READ 0x02
299 #define SVC_WRITE 0x03
300
301 /*
302 * Define a file handle - choice of UUID format is
303 * arbitrary. Note that typedef's cannot be declared
304 * with the struct definition.
305 */
306 struct svc_uuid {
307 DWORD data1;
308 DWORD data2;
309 WORD data3[2];
310 BYTE data4[8];
311 };
312 typedef struct svc_uuid svc_handle_t;
313
314 struct xferbuf {
315 DWORD nbytes;
316 DWORD offset;
317 SIZE_IS(nbytes) BYTE *data;
318 };
319 typedef struct xferbuf xferbuf_t;
320
321 /*
322 * Define the RPC operations.
323 */
324 OPERATION(SVC_CLOSE)
325 struct svc_close {
326 IN svc_handle_t handle;
327 OUT DWORD status;
328 };
329
330 OPERATION(SVC_OPEN)
331 struct svc_open {
332 IN LPTSTR servername;
333 IN LPTSTR path;
334 OUT svc_handle_t handle;
335 OUT DWORD status;
336 };
337
338 OPERATION(SVC_READ)
339 struct svc_read {
340 IN svc_handle_t handle;
341 IN DWORD nbytes;
342 IN DWORD offset;
343 OUT xferbuf_t buf;
344 OUT DWORD status;
345 };
346
347 OPERATION(SVC_WRITE)
348 struct svc_write {
349 IN svc_handle_t handle;
350 IN xferbuf_t buf;
351 OUT DWORD nbytes;
352 OUT DWORD status;
353 };
354
355 /*
356 * Define the interface.
357 */
358 INTERFACE(0)
359 union svc_interface {
360 CASE(SVC_CLOSE)
361 struct svc_close net_close;
362 CASE(SVC_OPEN)
363 struct svc_open net_open;
364 CASE(SVC_READ)
365 struct svc_read net_read;
366 CASE(SVC_WRITE)
367 struct svc_write net_write;
368 };
369 typedef union svc_interface svc_interface_t;
370 EXTERNTYPEINFO(svc_interface)
371
372 #endif /* _SVC_NDL_ */
373
374
375 EXIT STATUS
376 The following exit values are returned:
377
378 0
379 Successful operation.
380
381
382 >0
383 An error occurred.
384
385
386 ATTRIBUTES
387 See the attributes(5) man page for descriptions of the following
388 attributes:
389
390
391
392
393 +---------------+-----------------+
394 |ATTRIBUTE TYPE | ATTRIBUTE VALUE |
395 +---------------+-----------------+
396 |Availability | SUNWbtool |
397 +---------------+-----------------+
398
399 SEE ALSO
400 cpp(1), rpcgen(1), cc(1B), attributes(5)
401
402 BUGS
403 Some cpp(1) macros used by ndrgen are not understood by /usr/bin/cpp or
404 /usr/sfw/bin/cpp. Simple NDL files generally do not pose a problem. If
405 problems occur, for example, when using unions, use /usr/libexec/cpp or
406 cw.
407
408
409
410 October 22, 2007 NDRGEN(1ONBLD)