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)