Home | History | Annotate | Download | only in common
      1   5331   amw /*
      2   5331   amw  * CDDL HEADER START
      3   5331   amw  *
      4   5331   amw  * The contents of this file are subject to the terms of the
      5   5331   amw  * Common Development and Distribution License (the "License").
      6   5331   amw  * You may not use this file except in compliance with the License.
      7   5331   amw  *
      8   5331   amw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9   5331   amw  * or http://www.opensolaris.org/os/licensing.
     10   5331   amw  * See the License for the specific language governing permissions
     11   5331   amw  * and limitations under the License.
     12   5331   amw  *
     13   5331   amw  * When distributing Covered Code, include this CDDL HEADER in each
     14   5331   amw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15   5331   amw  * If applicable, add the following below this CDDL HEADER, with the
     16   5331   amw  * fields enclosed by brackets "[]" replaced with your own identifying
     17   5331   amw  * information: Portions Copyright [yyyy] [name of copyright owner]
     18   5331   amw  *
     19   5331   amw  * CDDL HEADER END
     20   5331   amw  */
     21   5331   amw /*
     22   9914   amw  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23   5331   amw  * Use is subject to license terms.
     24   5331   amw  */
     25   5331   amw 
     26   5331   amw /*
     27   8334  Jose  * Server-side NDR stream (PDU) operations. Stream operations should
     28   8334  Jose  * return TRUE (non-zero) on success or FALSE (zero or a null pointer)
     29   8334  Jose  * on failure. When an operation returns FALSE, including ndo_malloc()
     30   8334  Jose  * returning NULL, it should set the nds->error to indicate what went
     31   8334  Jose  * wrong.
     32   5331   amw  *
     33   8334  Jose  * When available, the relevant ndr reference is passed to the
     34   5331   amw  * operation but keep in mind that it may be a null pointer.
     35   5331   amw  *
     36   8334  Jose  * Functions ndo_get_pdu(), ndo_put_pdu(), and ndo_pad_pdu()
     37   5331   amw  * must never grow the PDU data. A request for out-of-bounds data is
     38   5331   amw  * an error. The swap_bytes flag is 1 if NDR knows that the byte-
     39   5331   amw  * order in the PDU is different from the local system.
     40   5331   amw  */
     41   5331   amw 
     42   5331   amw #include <sys/types.h>
     43   5331   amw #include <stdarg.h>
     44   5331   amw #include <ctype.h>
     45   5331   amw #include <stdio.h>
     46   5331   amw #include <stdlib.h>
     47   5331   amw #include <strings.h>
     48   5331   amw #include <string.h>
     49   5331   amw #include <assert.h>
     50   5331   amw 
     51   5331   amw #include <smbsrv/libsmb.h>
     52   8334  Jose #include <smbsrv/libmlrpc.h>
     53   5331   amw #include <smbsrv/ntstatus.h>
     54   5331   amw 
     55   5331   amw #define	NDOBUFSZ		128
     56   5331   amw 
     57   5331   amw #define	NDR_PDU_BLOCK_SIZE	(4*1024)
     58   5331   amw #define	NDR_PDU_BLOCK_MASK	(NDR_PDU_BLOCK_SIZE - 1)
     59   5331   amw #define	NDR_PDU_ALIGN(N) \
     60   5331   amw 	(((N) + NDR_PDU_BLOCK_SIZE) & ~NDR_PDU_BLOCK_MASK)
     61   5331   amw #define	NDR_PDU_MAX_SIZE		(64*1024*1024)
     62   5331   amw 
     63   8334  Jose static char *ndo_malloc(ndr_stream_t *, unsigned, ndr_ref_t *);
     64   8334  Jose static int ndo_free(ndr_stream_t *, char *, ndr_ref_t *);
     65   8334  Jose static int ndo_grow_pdu(ndr_stream_t *, unsigned long, ndr_ref_t *);
     66   8334  Jose static int ndo_pad_pdu(ndr_stream_t *, unsigned long, unsigned long,
     67   8334  Jose     ndr_ref_t *);
     68   8334  Jose static int ndo_get_pdu(ndr_stream_t *, unsigned long, unsigned long,
     69   8334  Jose     char *, int, ndr_ref_t *);
     70   8334  Jose static int ndo_put_pdu(ndr_stream_t *, unsigned long, unsigned long,
     71   8334  Jose     char *, int, ndr_ref_t *);
     72   8334  Jose static void ndo_tattle(ndr_stream_t *, char *, ndr_ref_t *);
     73   8334  Jose static void ndo_tattle_error(ndr_stream_t *, ndr_ref_t *);
     74   8334  Jose static int ndo_reset(ndr_stream_t *);
     75   8334  Jose static void ndo_destruct(ndr_stream_t *);
     76   8334  Jose static void ndo_hexfmt(uint8_t *, int, int, char *, int);
     77   5331   amw 
     78   5331   amw /*
     79   8334  Jose  * The ndr stream operations table.
     80   5331   amw  */
     81   8334  Jose static ndr_stream_ops_t nds_ops = {
     82   8334  Jose     ndo_malloc,
     83   8334  Jose     ndo_free,
     84   8334  Jose     ndo_grow_pdu,
     85   8334  Jose     ndo_pad_pdu,
     86   8334  Jose     ndo_get_pdu,
     87   8334  Jose     ndo_put_pdu,
     88   8334  Jose     ndo_tattle,
     89   8334  Jose     ndo_tattle_error,
     90   8334  Jose     ndo_reset,
     91   8334  Jose     ndo_destruct
     92   5331   amw };
     93   5331   amw 
     94   5331   amw /*
     95   8334  Jose  * nds_bswap
     96   5331   amw  *
     97   5331   amw  * Copies len bytes from src to dst such that dst contains the bytes
     98   5331   amw  * from src in reverse order.
     99   5331   amw  *
    100   5331   amw  * We expect to be dealing with bytes, words, dwords etc. So the
    101   5331   amw  * length must be non-zero and a power of 2.
    102   5331   amw  */
    103   5331   amw void
    104   8334  Jose nds_bswap(void *srcbuf, void *dstbuf, size_t len)
    105   5331   amw {
    106   5331   amw 	uint8_t *src = (uint8_t *)srcbuf;
    107   5331   amw 	uint8_t *dst = (uint8_t *)dstbuf;
    108   5331   amw 
    109   5331   amw 	if ((len != 0) && ((len & (len - 1)) == 0)) {
    110   5331   amw 		src += len;
    111   5331   amw 
    112   5331   amw 		while (len--)
    113   5331   amw 			*dst++ = *(--src);
    114   5331   amw 	}
    115   5331   amw }
    116   5331   amw 
    117   5331   amw /*
    118   8334  Jose  * nds_initialize
    119   5331   amw  *
    120   5331   amw  * Initialize a stream. Sets up the PDU parameters and assigns the stream
    121   5331   amw  * operations and the reference to the heap. An external heap is provided
    122   5331   amw  * to the stream, rather than each stream creating its own heap.
    123   5331   amw  */
    124   7052   amw void
    125   8334  Jose nds_initialize(ndr_stream_t *nds, unsigned pdu_size_hint,
    126   8334  Jose     int composite_op, ndr_heap_t *heap)
    127   5331   amw {
    128   5331   amw 	unsigned size;
    129   5331   amw 
    130   8334  Jose 	assert(nds);
    131   5331   amw 	assert(heap);
    132   5331   amw 
    133   8334  Jose 	bzero(nds, sizeof (*nds));
    134   5331   amw 
    135   5331   amw 	if (pdu_size_hint > NDR_PDU_MAX_SIZE)
    136   7052   amw 		return;
    137   5331   amw 
    138   5331   amw 	size = (pdu_size_hint == 0) ? NDR_PDU_BLOCK_SIZE : pdu_size_hint;
    139   8334  Jose 	nds->pdu_base_addr = malloc(size);
    140   8334  Jose 	assert(nds->pdu_base_addr);
    141   5331   amw 
    142   8334  Jose 	nds->pdu_max_size = size;
    143   8334  Jose 	nds->pdu_size = 0;
    144   8334  Jose 	nds->pdu_base_offset = (unsigned long)nds->pdu_base_addr;
    145   5331   amw 
    146   8334  Jose 	nds->ndo = &nds_ops;
    147   8334  Jose 	nds->heap = (struct ndr_heap *)heap;
    148   5331   amw 
    149   8334  Jose 	nds->m_op = NDR_MODE_TO_M_OP(composite_op);
    150   8334  Jose 	nds->dir  = NDR_MODE_TO_DIR(composite_op);
    151   5331   amw 
    152   8334  Jose 	nds->outer_queue_tailp = &nds->outer_queue_head;
    153   6482   amw }
    154   6482   amw 
    155   7052   amw void
    156   8334  Jose nds_finalize(ndr_stream_t *nds, ndr_fraglist_t *frags)
    157   6482   amw {
    158   7052   amw 	iovec_t *iov;
    159   6482   amw 	ndr_frag_t *frag;
    160   6482   amw 	uint32_t size = 0;
    161   6482   amw 
    162   7052   amw 	bzero(frags, sizeof (ndr_fraglist_t));
    163   7052   amw 
    164   8334  Jose 	for (frag = nds->frags.head; frag; frag = frag->next)
    165   6482   amw 		size += frag->len;
    166   6482   amw 
    167   7052   amw 	if (size == 0 || size >= NDR_PDU_MAX_SIZE)
    168   7052   amw 		return;
    169   6482   amw 
    170   8334  Jose 	frags->iov = malloc(nds->frags.nfrag * sizeof (iovec_t));
    171   7052   amw 	if (frags->iov == NULL)
    172   7052   amw 		return;
    173   7052   amw 
    174   8334  Jose 	frags->head = nds->frags.head;
    175   8334  Jose 	frags->tail = nds->frags.tail;
    176   8334  Jose 	frags->nfrag = nds->frags.nfrag;
    177   8334  Jose 	bzero(&nds->frags, sizeof (ndr_fraglist_t));
    178   7052   amw 
    179   7052   amw 	frags->uio.uio_iov = frags->iov;
    180   7052   amw 	frags->uio.uio_iovcnt = frags->nfrag;
    181   7052   amw 	frags->uio.uio_offset = 0;
    182   7052   amw 	frags->uio.uio_segflg = UIO_USERSPACE;
    183   7052   amw 	frags->uio.uio_resid = size;
    184   7052   amw 
    185   7052   amw 	iov = frags->uio.uio_iov;
    186   7052   amw 	for (frag = frags->head; frag; frag = frag->next) {
    187   7052   amw 		iov->iov_base = (caddr_t)frag->buf;
    188   7052   amw 		iov->iov_len = frag->len;
    189   7052   amw 		++iov;
    190   6482   amw 	}
    191   5331   amw }
    192   5331   amw 
    193   5331   amw /*
    194   8334  Jose  * nds_destruct
    195   5331   amw  *
    196   5331   amw  * Destroy a stream. This is an external interface to provide access to
    197   5331   amw  * the stream's destruct operation.
    198   5331   amw  */
    199   5331   amw void
    200   8334  Jose nds_destruct(ndr_stream_t *nds)
    201   5331   amw {
    202  10475   amw 	if ((nds == NULL) || (nds->ndo == NULL))
    203  10475   amw 		return;
    204  10475   amw 
    205   8334  Jose 	NDS_DESTRUCT(nds);
    206  10475   amw }
    207  10475   amw 
    208  10475   amw /*
    209  10475   amw  * Print NDR stream state.
    210  10475   amw  */
    211  10475   amw void
    212  10475   amw nds_show_state(ndr_stream_t *nds)
    213  10475   amw {
    214  10475   amw 	if (nds == NULL) {
    215  10475   amw 		ndo_printf(NULL, NULL, "nds: <null");
    216  10475   amw 		return;
    217  10475   amw 	}
    218  10475   amw 
    219  10475   amw 	ndo_printf(NULL, NULL, "nds: base=0x%x, size=%d, max=%d, scan=%d",
    220  10475   amw 	    nds->pdu_base_offset, nds->pdu_size, nds->pdu_max_size,
    221  10475   amw 	    nds->pdu_scan_offset);
    222   5331   amw }
    223   5331   amw 
    224   5331   amw /*
    225   8334  Jose  * ndo_malloc
    226   5331   amw  *
    227   5331   amw  * Allocate memory from the stream heap.
    228   5331   amw  */
    229   5331   amw /*ARGSUSED*/
    230   5331   amw static char *
    231   8334  Jose ndo_malloc(ndr_stream_t *nds, unsigned len, ndr_ref_t *ref)
    232   5331   amw {
    233   8334  Jose 	return (ndr_heap_malloc((ndr_heap_t *)nds->heap, len));
    234   5331   amw }
    235   5331   amw 
    236   5331   amw /*
    237   8334  Jose  * ndo_free
    238   5331   amw  *
    239   5331   amw  * Always succeeds: cannot free individual stream allocations.
    240   5331   amw  */
    241   5331   amw /*ARGSUSED*/
    242   5331   amw static int
    243   8334  Jose ndo_free(ndr_stream_t *nds, char *p, ndr_ref_t *ref)
    244   5331   amw {
    245   5331   amw 	return (1);
    246   5331   amw }
    247   5331   amw 
    248   5331   amw /*
    249   8334  Jose  * ndo_grow_pdu
    250   5331   amw  *
    251   5331   amw  * This is the only place that should change the size of the PDU. If the
    252   5331   amw  * desired offset is beyond the current PDU size, we realloc the PDU
    253   5331   amw  * buffer to accommodate the request. For efficiency, the PDU is always
    254   5331   amw  * extended to a NDR_PDU_BLOCK_SIZE boundary. Requests to grow the PDU
    255   5331   amw  * beyond NDR_PDU_MAX_SIZE are rejected.
    256   5331   amw  *
    257   5331   amw  * Returns 1 to indicate success. Otherwise 0 to indicate failure.
    258   5331   amw  */
    259   5331   amw static int
    260   8334  Jose ndo_grow_pdu(ndr_stream_t *nds, unsigned long want_end_offset, ndr_ref_t *ref)
    261   5331   amw {
    262   5331   amw 	unsigned char *pdu_addr;
    263   5331   amw 	unsigned pdu_max_size;
    264   5331   amw 
    265   8334  Jose 	ndo_printf(nds, ref, "grow %d", want_end_offset);
    266   5331   amw 
    267   8334  Jose 	pdu_max_size = nds->pdu_max_size;
    268   5331   amw 
    269   5331   amw 	if (want_end_offset > pdu_max_size) {
    270   5331   amw 		pdu_max_size = NDR_PDU_ALIGN(want_end_offset);
    271   5331   amw 
    272   5331   amw 		if (pdu_max_size >= NDR_PDU_MAX_SIZE)
    273   5331   amw 			return (0);
    274   5331   amw 
    275   8334  Jose 		pdu_addr = realloc(nds->pdu_base_addr, pdu_max_size);
    276   5331   amw 		if (pdu_addr == 0)
    277   5331   amw 			return (0);
    278   5331   amw 
    279   8334  Jose 		nds->pdu_max_size = pdu_max_size;
    280   8334  Jose 		nds->pdu_base_addr = pdu_addr;
    281   8334  Jose 		nds->pdu_base_offset = (unsigned long)pdu_addr;
    282   5331   amw 	}
    283   5331   amw 
    284   8334  Jose 	nds->pdu_size = want_end_offset;
    285   5331   amw 	return (1);
    286   5331   amw }
    287   5331   amw 
    288   5331   amw static int
    289   8334  Jose ndo_pad_pdu(ndr_stream_t *nds, unsigned long pdu_offset,
    290   8334  Jose     unsigned long n_bytes, ndr_ref_t *ref)
    291   5331   amw {
    292   5331   amw 	unsigned char *data;
    293   5331   amw 
    294   8334  Jose 	data = (unsigned char *)nds->pdu_base_offset;
    295   5331   amw 	data += pdu_offset;
    296   5331   amw 
    297   8334  Jose 	ndo_printf(nds, ref, "pad %d@%-3d", n_bytes, pdu_offset);
    298   5331   amw 
    299   5331   amw 	bzero(data, n_bytes);
    300   5331   amw 	return (1);
    301   5331   amw }
    302   5331   amw 
    303   5331   amw /*
    304   8334  Jose  * ndo_get_pdu
    305   5331   amw  *
    306   5331   amw  * The swap flag is 1 if NDR knows that the byte-order in the PDU
    307   5331   amw  * is different from the local system.
    308   5331   amw  *
    309   5331   amw  * Returns 1 on success or 0 to indicate failure.
    310   5331   amw  */
    311   5331   amw static int
    312   8334  Jose ndo_get_pdu(ndr_stream_t *nds, unsigned long pdu_offset,
    313   8334  Jose     unsigned long n_bytes, char *buf, int swap_bytes, ndr_ref_t *ref)
    314   5331   amw {
    315   5331   amw 	unsigned char *data;
    316   5331   amw 	char hexbuf[NDOBUFSZ];
    317   5331   amw 
    318   8334  Jose 	data = (unsigned char *)nds->pdu_base_offset;
    319   5331   amw 	data += pdu_offset;
    320   5331   amw 
    321   8334  Jose 	ndo_hexfmt(data, n_bytes, swap_bytes, hexbuf, NDOBUFSZ);
    322   5331   amw 
    323   8334  Jose 	ndo_printf(nds, ref, "get %d@%-3d = %s",
    324   5331   amw 	    n_bytes, pdu_offset, hexbuf);
    325   5331   amw 
    326   5331   amw 	if (!swap_bytes)
    327   5331   amw 		bcopy(data, buf, n_bytes);
    328   5331   amw 	else
    329   8334  Jose 		nds_bswap(data, (unsigned char *)buf, n_bytes);
    330   5331   amw 
    331   5331   amw 	return (1);
    332   5331   amw }
    333   5331   amw 
    334   5331   amw /*
    335   8334  Jose  * ndo_put_pdu
    336   5331   amw  *
    337   5331   amw  * This is a receiver makes right protocol. So we do not need
    338   5331   amw  * to be concerned about the byte-order of an outgoing PDU.
    339   5331   amw  */
    340   5331   amw /*ARGSUSED*/
    341   5331   amw static int
    342   8334  Jose ndo_put_pdu(ndr_stream_t *nds, unsigned long pdu_offset,
    343   8334  Jose     unsigned long n_bytes, char *buf, int swap_bytes, ndr_ref_t *ref)
    344   5331   amw {
    345   5331   amw 	unsigned char *data;
    346   5331   amw 	char hexbuf[NDOBUFSZ];
    347   5331   amw 
    348   8334  Jose 	data = (unsigned char *)nds->pdu_base_offset;
    349   5331   amw 	data += pdu_offset;
    350   5331   amw 
    351   8334  Jose 	ndo_hexfmt((uint8_t *)buf, n_bytes, 0, hexbuf, NDOBUFSZ);
    352   5331   amw 
    353   8334  Jose 	ndo_printf(nds, ref, "put %d@%-3d = %s",
    354   5331   amw 	    n_bytes, pdu_offset, hexbuf);
    355   5331   amw 
    356   5331   amw 	bcopy(buf, data, n_bytes);
    357   5331   amw 	return (1);
    358   5331   amw }
    359   5331   amw 
    360   5331   amw static void
    361   8334  Jose ndo_tattle(ndr_stream_t *nds, char *what, ndr_ref_t *ref)
    362   5331   amw {
    363   8334  Jose 	ndo_printf(nds, ref, what);
    364   5331   amw }
    365   5331   amw 
    366   5331   amw static void
    367   8334  Jose ndo_tattle_error(ndr_stream_t *nds, ndr_ref_t *ref)
    368   5331   amw {
    369   5331   amw 	unsigned char *data;
    370   5331   amw 	char hexbuf[NDOBUFSZ];
    371   5331   amw 
    372   8334  Jose 	data = (unsigned char *)nds->pdu_base_offset;
    373   5331   amw 	if (ref)
    374   5331   amw 		data += ref->pdu_offset;
    375   5331   amw 	else
    376   8334  Jose 		data += nds->pdu_scan_offset;
    377   5331   amw 
    378   8334  Jose 	ndo_hexfmt(data, 16, 0, hexbuf, NDOBUFSZ);
    379   5331   amw 
    380   8334  Jose 	ndo_printf(nds, ref, "ERROR=%d REF=%d OFFSET=%d SIZE=%d/%d",
    381   8334  Jose 	    nds->error, nds->error_ref, nds->pdu_scan_offset,
    382   8334  Jose 	    nds->pdu_size, nds->pdu_max_size);
    383   8334  Jose 	ndo_printf(nds, ref, "      %s", hexbuf);
    384   5331   amw }
    385   5331   amw 
    386   5331   amw /*
    387   8334  Jose  * ndo_reset
    388   5331   amw  *
    389   5331   amw  * Reset a stream: zap the outer_queue. We don't need to tamper
    390   5331   amw  * with the stream heap: it's handled externally to the stream.
    391   5331   amw  */
    392   5331   amw static int
    393   8334  Jose ndo_reset(ndr_stream_t *nds)
    394   5331   amw {
    395   8334  Jose 	ndo_printf(nds, 0, "reset");
    396   5331   amw 
    397   8334  Jose 	nds->pdu_size = 0;
    398   8334  Jose 	nds->pdu_scan_offset = 0;
    399   8334  Jose 	nds->outer_queue_head = 0;
    400   8334  Jose 	nds->outer_current = 0;
    401   8334  Jose 	nds->outer_queue_tailp = &nds->outer_queue_head;
    402   5331   amw 
    403   5331   amw 	return (1);
    404   5331   amw }
    405   5331   amw 
    406   5331   amw /*
    407   8334  Jose  * ndo_destruct
    408   5331   amw  *
    409   6482   amw  * Destruct a stream: zap the outer_queue.
    410   6482   amw  * Note: heap management (creation/destruction) is external to the stream.
    411   5331   amw  */
    412   5331   amw static void
    413   8334  Jose ndo_destruct(ndr_stream_t *nds)
    414   5331   amw {
    415   6482   amw 	ndr_frag_t *frag;
    416   6482   amw 
    417   8334  Jose 	ndo_printf(nds, 0, "destruct");
    418   5331   amw 
    419   8334  Jose 	if (nds == NULL)
    420   8334  Jose 		return;
    421   8334  Jose 
    422   8334  Jose 	if (nds->pdu_base_addr != NULL) {
    423   8334  Jose 		free(nds->pdu_base_addr);
    424   8334  Jose 		nds->pdu_base_addr = NULL;
    425   8334  Jose 		nds->pdu_base_offset = 0;
    426   5331   amw 	}
    427   5331   amw 
    428   8334  Jose 	while ((frag = nds->frags.head) != NULL) {
    429   8334  Jose 		nds->frags.head = frag->next;
    430   6482   amw 		free(frag);
    431   6482   amw 	}
    432   6482   amw 
    433   8334  Jose 	bzero(&nds->frags, sizeof (ndr_fraglist_t));
    434   7052   amw 
    435   8334  Jose 	nds->outer_queue_head = 0;
    436   8334  Jose 	nds->outer_current = 0;
    437   8334  Jose 	nds->outer_queue_tailp = &nds->outer_queue_head;
    438   5331   amw }
    439   5331   amw 
    440   5331   amw /*
    441   5331   amw  * Printf style formatting for NDR operations.
    442   5331   amw  */
    443   5331   amw void
    444   8334  Jose ndo_printf(ndr_stream_t *nds, ndr_ref_t *ref, const char *fmt, ...)
    445   5331   amw {
    446   5331   amw 	va_list ap;
    447   5331   amw 	char buf[NDOBUFSZ];
    448   5331   amw 
    449   5331   amw 	va_start(ap, fmt);
    450   5331   amw 	(void) vsnprintf(buf, NDOBUFSZ, fmt, ap);
    451   5331   amw 	va_end(ap);
    452   5331   amw 
    453   8334  Jose 	if (nds)
    454   8334  Jose 		ndo_fmt(nds, ref, buf);
    455   5331   amw 	else
    456   8334  Jose 		ndo_trace(buf);
    457   5331   amw }
    458   5331   amw 
    459   5331   amw /*
    460   5331   amw  * Main output formatter for NDR operations.
    461   5331   amw  *
    462   5331   amw  *	UI 03 ... rpc_vers           get 1@0   =    5 {05}
    463   5331   amw  *	UI 03 ... rpc_vers_minor     get 1@1   =    0 {00}
    464   5331   amw  *
    465   5331   amw  *	U       Marshalling flag (M=marshal, U=unmarshal)
    466   5331   amw  *	I       Direction flag (I=in, O=out)
    467   5331   amw  *	...     Field name
    468   5331   amw  *	get     PDU operation (get or put)
    469   5331   amw  *	1@0	Bytes @ offset (i.e. 1 byte at offset 0)
    470   5331   amw  *	{05}    Value
    471   5331   amw  */
    472   5331   amw void
    473   8334  Jose ndo_fmt(ndr_stream_t *nds, ndr_ref_t *ref, char *note)
    474   5331   amw {
    475   8334  Jose 	ndr_ref_t	*p;
    476   8334  Jose 	int		indent;
    477   8334  Jose 	char		ref_name[NDOBUFSZ];
    478   8334  Jose 	char		buf[NDOBUFSZ];
    479   8334  Jose 	int		m_op_c = '?', dir_c = '?';
    480   5331   amw 
    481   8334  Jose 	switch (nds->m_op) {
    482   5331   amw 	case 0:				m_op_c = '-';	break;
    483   5331   amw 	case NDR_M_OP_MARSHALL:		m_op_c = 'M';	break;
    484   5331   amw 	case NDR_M_OP_UNMARSHALL:	m_op_c = 'U';	break;
    485   5331   amw 	default:			m_op_c = '?';	break;
    486   5331   amw 	}
    487   5331   amw 
    488   8334  Jose 	switch (nds->dir) {
    489   5331   amw 	case 0:				dir_c = '-';	break;
    490   5331   amw 	case NDR_DIR_IN:		dir_c = 'I';	break;
    491   5331   amw 	case NDR_DIR_OUT:		dir_c = 'O';	break;
    492   5331   amw 	default:			dir_c = '?';	break;
    493   5331   amw 	}
    494   5331   amw 
    495   5331   amw 	for (indent = 0, p = ref; p; p = p->enclosing)
    496   5331   amw 		indent++;
    497   5331   amw 
    498   5331   amw 	if (ref && ref->name) {
    499   5331   amw 		if (*ref->name == '[' && ref->enclosing) {
    500   5331   amw 			indent--;
    501   5331   amw 			(void) snprintf(ref_name, NDOBUFSZ, "%s%s",
    502   5331   amw 			    ref->enclosing->name, ref->name);
    503   5331   amw 		} else {
    504   5331   amw 			(void) strlcpy(ref_name, ref->name, NDOBUFSZ);
    505   5331   amw 		}
    506   5331   amw 	} else {
    507   5331   amw 		(void) strlcpy(ref_name, "----", NDOBUFSZ);
    508   5331   amw 	}
    509   5331   amw 
    510   9914   amw 	(void) snprintf(buf, NDOBUFSZ, "%c%c %-.*s %-*s  %s",
    511   9914   amw 	    m_op_c, dir_c, indent,
    512   5331   amw 	    "....+....+....+....+....+....",
    513   5331   amw 	    20 - indent, ref_name, note);
    514   5331   amw 
    515   8334  Jose 	ndo_trace(buf);
    516   5331   amw }
    517   5331   amw 
    518   5331   amw /*ARGSUSED*/
    519   5331   amw void
    520   8334  Jose ndo_trace(const char *s)
    521   5331   amw {
    522   5331   amw 	/*
    523   5331   amw 	 * Temporary fbt for dtrace until user space sdt enabled.
    524   5331   amw 	 */
    525   5331   amw }
    526   5331   amw 
    527   5331   amw /*
    528   5331   amw  * Format data as hex bytes (limit is 10 bytes):
    529   5331   amw  *
    530   5331   amw  *	1188689424 {10 f6 d9 46}
    531   5331   amw  *
    532   5331   amw  * If the input data is greater than 10 bytes, an ellipsis will
    533   5331   amw  * be inserted before the closing brace.
    534   5331   amw  */
    535   5331   amw static void
    536   8334  Jose ndo_hexfmt(uint8_t *data, int size, int swap_bytes, char *buf, int len)
    537   5331   amw {
    538   5331   amw 	char *p = buf;
    539   5331   amw 	int interp = 1;
    540   5331   amw 	uint32_t c;
    541   5331   amw 	int n;
    542   5331   amw 	int i;
    543   5331   amw 
    544   5331   amw 	n = (size > 10) ? 10 : size;
    545   5331   amw 	if (n > len-1)
    546   5331   amw 		n = len-1;
    547   5331   amw 
    548   5331   amw 	switch (size) {
    549   5331   amw 	case 1:
    550   5331   amw 		c = *(uint8_t *)data;
    551   5331   amw 		break;
    552   5331   amw 	case 2:
    553   5331   amw 		if (swap_bytes == 0) /*LINTED E_BAD_PTR_CAST_ALIGN*/
    554   5331   amw 			c = *(uint16_t *)data;
    555   5331   amw 		else
    556   5331   amw 			c = (data[0] << 8) | data[1];
    557   5331   amw 		break;
    558   5331   amw 	case 4:
    559   5331   amw 		if (swap_bytes == 0) { /*LINTED E_BAD_PTR_CAST_ALIGN*/
    560   5331   amw 			c = *(uint32_t *)data;
    561   5331   amw 		} else {
    562   5331   amw 			c = (data[0] << 24) | (data[1] << 16)
    563   5331   amw 			    | (data[2] << 8) | data[3];
    564   5331   amw 		}
    565   5331   amw 		break;
    566   5331   amw 	default:
    567   5331   amw 		c = 0;
    568   5331   amw 		interp = 0;
    569   5331   amw 		break;
    570   5331   amw 	}
    571   5331   amw 
    572   5331   amw 	if (interp)
    573   5331   amw 		p += sprintf(p, "%4u {", c);
    574   5331   amw 	else
    575   5331   amw 		p += sprintf(p, " {");
    576   5331   amw 
    577   5331   amw 	p += sprintf(p, "%02x", data[0]);
    578   5331   amw 	for (i = 1; i < n; i++)
    579   5331   amw 		p += sprintf(p, " %02x", data[i]);
    580   5331   amw 	if (size > 10)
    581   5331   amw 		p += sprintf(p, " ...}");
    582   5331   amw 	else
    583   5331   amw 		p += sprintf(p, "}");
    584   5331   amw 
    585   5331   amw 	/*
    586   5331   amw 	 * Show c if it's a printable character or wide-char.
    587   5331   amw 	 */
    588   5331   amw 	if (size < 4 && isprint((uint8_t)c))
    589   5331   amw 		(void) sprintf(p, " %c", (uint8_t)c);
    590   5331   amw }
    591