xref: /onnv-gate/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c (revision 12065:0e89d02a32ea)
15772Sas200622 /*
25772Sas200622  * CDDL HEADER START
35772Sas200622  *
45772Sas200622  * The contents of this file are subject to the terms of the
55772Sas200622  * Common Development and Distribution License (the "License").
65772Sas200622  * You may not use this file except in compliance with the License.
75772Sas200622  *
85772Sas200622  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95772Sas200622  * or http://www.opensolaris.org/os/licensing.
105772Sas200622  * See the License for the specific language governing permissions
115772Sas200622  * and limitations under the License.
125772Sas200622  *
135772Sas200622  * When distributing Covered Code, include this CDDL HEADER in each
145772Sas200622  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155772Sas200622  * If applicable, add the following below this CDDL HEADER, with the
165772Sas200622  * fields enclosed by brackets "[]" replaced with your own identifying
175772Sas200622  * information: Portions Copyright [yyyy] [name of copyright owner]
185772Sas200622  *
195772Sas200622  * CDDL HEADER END
205772Sas200622  */
215772Sas200622 /*
22*12065SKeyur.Desai@Sun.COM  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
235772Sas200622  */
245772Sas200622 
259914Samw@Sun.COM #include <assert.h>
265772Sas200622 #include <strings.h>
275772Sas200622 #include <sys/param.h>
285772Sas200622 
295772Sas200622 #include <smbsrv/libsmb.h>
308334SJose.Borrego@Sun.COM #include <smbsrv/libmlrpc.h>
315772Sas200622 
325772Sas200622 #ifdef _BIG_ENDIAN
338334SJose.Borrego@Sun.COM static const int ndr_native_byte_order = NDR_REPLAB_INTG_BIG_ENDIAN;
345772Sas200622 #else
358334SJose.Borrego@Sun.COM static const int ndr_native_byte_order = NDR_REPLAB_INTG_LITTLE_ENDIAN;
365772Sas200622 #endif
375772Sas200622 
389914Samw@Sun.COM static int ndr_decode_hdr_common(ndr_stream_t *, ndr_common_header_t *);
39*12065SKeyur.Desai@Sun.COM static int ndr_decode_pac_hdr(ndr_stream_t *, ndr_pac_hdr_t *);
409914Samw@Sun.COM 
419914Samw@Sun.COM static int
ndr_encode_decode_common(ndr_stream_t * nds,unsigned opnum,ndr_typeinfo_t * ti,void * datum)429914Samw@Sun.COM ndr_encode_decode_common(ndr_stream_t *nds, unsigned opnum,
438334SJose.Borrego@Sun.COM     ndr_typeinfo_t *ti, void *datum)
445772Sas200622 {
459914Samw@Sun.COM 	int rc;
465772Sas200622 
475772Sas200622 	/*
485772Sas200622 	 * Perform the (un)marshalling
495772Sas200622 	 */
508334SJose.Borrego@Sun.COM 	if (ndo_operation(nds, ti, opnum, datum))
518334SJose.Borrego@Sun.COM 		return (NDR_DRC_OK);
525772Sas200622 
538334SJose.Borrego@Sun.COM 	switch (nds->error) {
545772Sas200622 	case NDR_ERR_MALLOC_FAILED:
558334SJose.Borrego@Sun.COM 		rc = NDR_DRC_FAULT_OUT_OF_MEMORY;
565772Sas200622 		break;
575772Sas200622 
585772Sas200622 	case NDR_ERR_SWITCH_VALUE_INVALID:
598334SJose.Borrego@Sun.COM 		rc = NDR_DRC_FAULT_PARAM_0_INVALID;
605772Sas200622 		break;
615772Sas200622 
625772Sas200622 	case NDR_ERR_UNDERFLOW:
638334SJose.Borrego@Sun.COM 		rc = NDR_DRC_FAULT_RECEIVED_RUNT;
645772Sas200622 		break;
655772Sas200622 
665772Sas200622 	case NDR_ERR_GROW_FAILED:
678334SJose.Borrego@Sun.COM 		rc = NDR_DRC_FAULT_ENCODE_TOO_BIG;
685772Sas200622 		break;
695772Sas200622 
705772Sas200622 	default:
719914Samw@Sun.COM 		if (nds->m_op == NDR_M_OP_MARSHALL)
728334SJose.Borrego@Sun.COM 			rc = NDR_DRC_FAULT_ENCODE_FAILED;
735772Sas200622 		else
748334SJose.Borrego@Sun.COM 			rc = NDR_DRC_FAULT_DECODE_FAILED;
755772Sas200622 		break;
765772Sas200622 	}
775772Sas200622 
785772Sas200622 	return (rc);
795772Sas200622 }
805772Sas200622 
819914Samw@Sun.COM ndr_buf_t *
ndr_buf_init(ndr_typeinfo_t * ti)829914Samw@Sun.COM ndr_buf_init(ndr_typeinfo_t *ti)
839914Samw@Sun.COM {
849914Samw@Sun.COM 	ndr_buf_t		*nbuf;
859914Samw@Sun.COM 
869914Samw@Sun.COM 	if ((nbuf = calloc(1, sizeof (ndr_buf_t))) == NULL)
879914Samw@Sun.COM 		return (NULL);
889914Samw@Sun.COM 
899914Samw@Sun.COM 	if ((nbuf->nb_heap = ndr_heap_create()) == NULL) {
909914Samw@Sun.COM 		free(nbuf);
919914Samw@Sun.COM 		return (NULL);
929914Samw@Sun.COM 	}
939914Samw@Sun.COM 
949914Samw@Sun.COM 	nbuf->nb_ti = ti;
959914Samw@Sun.COM 	nbuf->nb_magic = NDR_BUF_MAGIC;
969914Samw@Sun.COM 	return (nbuf);
979914Samw@Sun.COM }
989914Samw@Sun.COM 
999914Samw@Sun.COM void
ndr_buf_fini(ndr_buf_t * nbuf)1009914Samw@Sun.COM ndr_buf_fini(ndr_buf_t *nbuf)
1019914Samw@Sun.COM {
1029914Samw@Sun.COM 	assert(nbuf->nb_magic == NDR_BUF_MAGIC);
1039914Samw@Sun.COM 
1049914Samw@Sun.COM 	nds_destruct(&nbuf->nb_nds);
1059914Samw@Sun.COM 	ndr_heap_destroy(nbuf->nb_heap);
1069914Samw@Sun.COM 	nbuf->nb_magic = 0;
1079914Samw@Sun.COM 	free(nbuf);
1089914Samw@Sun.COM }
1099914Samw@Sun.COM 
1109914Samw@Sun.COM /*
1119914Samw@Sun.COM  * Decode an NDR encoded buffer.  The buffer is expected to contain
1129914Samw@Sun.COM  * a single fragment packet with a valid PDU header followed by NDR
1139914Samw@Sun.COM  * encoded data.  The structure to which result points should be
1149914Samw@Sun.COM  * of the appropriate type to hold the decoded output.  For example:
1159914Samw@Sun.COM  *
1169914Samw@Sun.COM  *	pac_info_t info;
1179914Samw@Sun.COM  *
1189914Samw@Sun.COM  * 	if ((nbuf = ndr_buf_init(&TYPEINFO(ndr_pac)) != NULL) {
1199914Samw@Sun.COM  *		rc = ndr_decode_buf(nbuf, opnum, data, datalen, &info);
1209914Samw@Sun.COM  *		...
1219914Samw@Sun.COM  *		ndr_buf_fini(nbuf);
1229914Samw@Sun.COM  *	}
1239914Samw@Sun.COM  */
1249914Samw@Sun.COM int
ndr_buf_decode(ndr_buf_t * nbuf,unsigned hdr_type,unsigned opnum,const char * data,size_t datalen,void * result)125*12065SKeyur.Desai@Sun.COM ndr_buf_decode(ndr_buf_t *nbuf, unsigned hdr_type, unsigned opnum,
126*12065SKeyur.Desai@Sun.COM     const char *data, size_t datalen, void *result)
1279914Samw@Sun.COM {
1289914Samw@Sun.COM 	ndr_common_header_t	hdr;
129*12065SKeyur.Desai@Sun.COM 	ndr_pac_hdr_t		pac_hdr;
1309914Samw@Sun.COM 	unsigned		pdu_size_hint;
1319914Samw@Sun.COM 	int			rc;
1329914Samw@Sun.COM 
1339914Samw@Sun.COM 	assert(nbuf->nb_magic == NDR_BUF_MAGIC);
1349914Samw@Sun.COM 	assert(nbuf->nb_heap != NULL);
1359914Samw@Sun.COM 	assert(nbuf->nb_ti != NULL);
1369914Samw@Sun.COM 
1379914Samw@Sun.COM 	if (datalen < NDR_PDU_SIZE_HINT_DEFAULT)
1389914Samw@Sun.COM 		pdu_size_hint = NDR_PDU_SIZE_HINT_DEFAULT;
1399914Samw@Sun.COM 	else
1409914Samw@Sun.COM 		pdu_size_hint = datalen;
1419914Samw@Sun.COM 
14211337SWilliam.Krier@Sun.COM 	rc = nds_initialize(&nbuf->nb_nds, pdu_size_hint, NDR_MODE_BUF_DECODE,
1439914Samw@Sun.COM 	    nbuf->nb_heap);
14411337SWilliam.Krier@Sun.COM 	if (NDR_DRC_IS_FAULT(rc))
14511337SWilliam.Krier@Sun.COM 		return (rc);
14611337SWilliam.Krier@Sun.COM 
1479914Samw@Sun.COM 	bcopy(data, nbuf->nb_nds.pdu_base_addr, datalen);
1489914Samw@Sun.COM 
149*12065SKeyur.Desai@Sun.COM 	switch (hdr_type) {
150*12065SKeyur.Desai@Sun.COM 	case NDR_PTYPE_COMMON:
151*12065SKeyur.Desai@Sun.COM 		rc = ndr_decode_hdr_common(&nbuf->nb_nds, &hdr);
152*12065SKeyur.Desai@Sun.COM 		if (NDR_DRC_IS_FAULT(rc))
153*12065SKeyur.Desai@Sun.COM 			return (rc);
154*12065SKeyur.Desai@Sun.COM 
155*12065SKeyur.Desai@Sun.COM 		if (!NDR_IS_SINGLE_FRAG(hdr.pfc_flags))
156*12065SKeyur.Desai@Sun.COM 			return (NDR_DRC_FAULT_DECODE_FAILED);
157*12065SKeyur.Desai@Sun.COM 		break;
1589914Samw@Sun.COM 
159*12065SKeyur.Desai@Sun.COM 	case NDR_PTYPE_PAC:
160*12065SKeyur.Desai@Sun.COM 		rc = ndr_decode_pac_hdr(&nbuf->nb_nds, &pac_hdr);
161*12065SKeyur.Desai@Sun.COM 		if (NDR_DRC_IS_FAULT(rc))
162*12065SKeyur.Desai@Sun.COM 			return (rc);
163*12065SKeyur.Desai@Sun.COM 
164*12065SKeyur.Desai@Sun.COM 		if (pac_hdr.common_hdr.hdrlen != sizeof (ndr_serialtype1_hdr_t))
165*12065SKeyur.Desai@Sun.COM 			return (NDR_DRC_FAULT_DECODE_FAILED);
166*12065SKeyur.Desai@Sun.COM 		break;
167*12065SKeyur.Desai@Sun.COM 
168*12065SKeyur.Desai@Sun.COM 	default:
169*12065SKeyur.Desai@Sun.COM 		return (NDR_ERR_UNIMPLEMENTED);
170*12065SKeyur.Desai@Sun.COM 	}
1719914Samw@Sun.COM 
1729914Samw@Sun.COM 	rc = ndr_encode_decode_common(&nbuf->nb_nds, opnum, nbuf->nb_ti,
1739914Samw@Sun.COM 	    result);
1749914Samw@Sun.COM 	return (rc);
1759914Samw@Sun.COM }
1769914Samw@Sun.COM 
1779914Samw@Sun.COM /*
1789914Samw@Sun.COM  * Use the receive stream to unmarshall data (NDR_MODE_CALL_RECV).
1799914Samw@Sun.COM  */
1805772Sas200622 int
ndr_decode_call(ndr_xa_t * mxa,void * params)1818334SJose.Borrego@Sun.COM ndr_decode_call(ndr_xa_t *mxa, void *params)
1825772Sas200622 {
1839914Samw@Sun.COM 	ndr_stream_t	*nds = &mxa->recv_nds;
1849914Samw@Sun.COM 	int		rc;
1855772Sas200622 
1869914Samw@Sun.COM 	if (!NDR_MODE_MATCH(nds, NDR_MODE_CALL_RECV))
1879914Samw@Sun.COM 		return (NDR_DRC_FAULT_MODE_MISMATCH);
1889914Samw@Sun.COM 
1899914Samw@Sun.COM 	rc = ndr_encode_decode_common(nds, mxa->opnum,
1909914Samw@Sun.COM 	    mxa->binding->service->interface_ti, params);
1915772Sas200622 
1928334SJose.Borrego@Sun.COM 	return (rc + NDR_PTYPE_REQUEST);
1935772Sas200622 }
1945772Sas200622 
1959914Samw@Sun.COM /*
1969914Samw@Sun.COM  * Use the send stream to marshall data (NDR_MODE_RETURN_SEND).
1979914Samw@Sun.COM  */
1985772Sas200622 int
ndr_encode_return(ndr_xa_t * mxa,void * params)1998334SJose.Borrego@Sun.COM ndr_encode_return(ndr_xa_t *mxa, void *params)
2005772Sas200622 {
2019914Samw@Sun.COM 	ndr_stream_t	*nds = &mxa->send_nds;
2029914Samw@Sun.COM 	int		rc;
2035772Sas200622 
2049914Samw@Sun.COM 	if (!NDR_MODE_MATCH(nds, NDR_MODE_RETURN_SEND))
2059914Samw@Sun.COM 		return (NDR_DRC_FAULT_MODE_MISMATCH);
2069914Samw@Sun.COM 
2079914Samw@Sun.COM 	rc = ndr_encode_decode_common(nds, mxa->opnum,
2089914Samw@Sun.COM 	    mxa->binding->service->interface_ti, params);
2095772Sas200622 
2108334SJose.Borrego@Sun.COM 	return (rc + NDR_PTYPE_RESPONSE);
2115772Sas200622 }
2125772Sas200622 
2139914Samw@Sun.COM /*
2149914Samw@Sun.COM  * Use the send stream to marshall data (NDR_MODE_CALL_SEND).
2159914Samw@Sun.COM  */
2165772Sas200622 int
ndr_encode_call(ndr_xa_t * mxa,void * params)2178334SJose.Borrego@Sun.COM ndr_encode_call(ndr_xa_t *mxa, void *params)
2185772Sas200622 {
2199914Samw@Sun.COM 	ndr_stream_t	*nds = &mxa->send_nds;
2209914Samw@Sun.COM 	int		rc;
2215772Sas200622 
2229914Samw@Sun.COM 	if (!NDR_MODE_MATCH(nds, NDR_MODE_CALL_SEND))
2239914Samw@Sun.COM 		return (NDR_DRC_FAULT_MODE_MISMATCH);
2249914Samw@Sun.COM 
2259914Samw@Sun.COM 	rc = ndr_encode_decode_common(nds, mxa->opnum,
2269914Samw@Sun.COM 	    mxa->binding->service->interface_ti, params);
2275772Sas200622 
2288334SJose.Borrego@Sun.COM 	return (rc + NDR_PTYPE_REQUEST);
2295772Sas200622 }
2305772Sas200622 
2319914Samw@Sun.COM /*
2329914Samw@Sun.COM  * Use the receive stream to unmarshall data (NDR_MODE_RETURN_RECV).
2339914Samw@Sun.COM  */
2345772Sas200622 int
ndr_decode_return(ndr_xa_t * mxa,void * params)2358334SJose.Borrego@Sun.COM ndr_decode_return(ndr_xa_t *mxa, void *params)
2365772Sas200622 {
2379914Samw@Sun.COM 	ndr_stream_t	*nds = &mxa->recv_nds;
2389914Samw@Sun.COM 	int		rc;
2395772Sas200622 
2409914Samw@Sun.COM 	if (!NDR_MODE_MATCH(nds, NDR_MODE_RETURN_RECV))
2419914Samw@Sun.COM 		return (NDR_DRC_FAULT_MODE_MISMATCH);
2429914Samw@Sun.COM 
2439914Samw@Sun.COM 	rc = ndr_encode_decode_common(nds, mxa->opnum,
2449914Samw@Sun.COM 	    mxa->binding->service->interface_ti, params);
2455772Sas200622 
2468334SJose.Borrego@Sun.COM 	return (rc + NDR_PTYPE_RESPONSE);
2475772Sas200622 }
2485772Sas200622 
2495772Sas200622 int
ndr_decode_pdu_hdr(ndr_xa_t * mxa)2508334SJose.Borrego@Sun.COM ndr_decode_pdu_hdr(ndr_xa_t *mxa)
2515772Sas200622 {
2528334SJose.Borrego@Sun.COM 	ndr_common_header_t	*hdr = &mxa->recv_hdr.common_hdr;
2538334SJose.Borrego@Sun.COM 	ndr_stream_t		*nds = &mxa->recv_nds;
2549914Samw@Sun.COM 	int			rc;
2559914Samw@Sun.COM 
2569914Samw@Sun.COM 	rc = ndr_decode_hdr_common(nds, hdr);
2579914Samw@Sun.COM 	if (NDR_DRC_IS_FAULT(rc))
2589914Samw@Sun.COM 		return (rc);
2599914Samw@Sun.COM 
2609914Samw@Sun.COM 	/*
2619914Samw@Sun.COM 	 * Verify the protocol version.
2629914Samw@Sun.COM 	 */
2639914Samw@Sun.COM 	if ((hdr->rpc_vers != 5) || (hdr->rpc_vers_minor != 0))
264*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
2659914Samw@Sun.COM 
2669914Samw@Sun.COM 	mxa->ptype = hdr->ptype;
2679914Samw@Sun.COM 	return (NDR_DRC_OK);
2689914Samw@Sun.COM }
2699914Samw@Sun.COM 
2709914Samw@Sun.COM static int
ndr_decode_hdr_common(ndr_stream_t * nds,ndr_common_header_t * hdr)2719914Samw@Sun.COM ndr_decode_hdr_common(ndr_stream_t *nds, ndr_common_header_t *hdr)
2729914Samw@Sun.COM {
2735772Sas200622 	int			ptype;
2745772Sas200622 	int			rc;
2755772Sas200622 	int			charset;
2765772Sas200622 	int			byte_order;
2775772Sas200622 
2788334SJose.Borrego@Sun.COM 	if (nds->m_op != NDR_M_OP_UNMARSHALL)
279*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH);
2805772Sas200622 
2815772Sas200622 	/*
2825772Sas200622 	 * All PDU headers are at least this big
2835772Sas200622 	 */
2848334SJose.Borrego@Sun.COM 	rc = NDS_GROW_PDU(nds, sizeof (ndr_common_header_t), 0);
2855772Sas200622 	if (!rc)
286*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT);
2875772Sas200622 
2885772Sas200622 	/*
2895772Sas200622 	 * Peek at the first eight bytes to figure out what we're doing.
2905772Sas200622 	 */
2918334SJose.Borrego@Sun.COM 	rc = NDS_GET_PDU(nds, 0, 8, (char *)hdr, 0, 0);
2925772Sas200622 	if (!rc)
293*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
2945772Sas200622 
2955772Sas200622 	/*
2965772Sas200622 	 * Check for ASCII as the character set.  This is an ASCII
2975772Sas200622 	 * versus EBCDIC option and has nothing to do with Unicode.
2985772Sas200622 	 */
2998334SJose.Borrego@Sun.COM 	charset = hdr->packed_drep.intg_char_rep & NDR_REPLAB_CHAR_MASK;
3008334SJose.Borrego@Sun.COM 	if (charset != NDR_REPLAB_CHAR_ASCII)
301*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
3025772Sas200622 
3035772Sas200622 	/*
3045772Sas200622 	 * Set the byte swap flag if the PDU byte-order
3055772Sas200622 	 * is different from the local byte-order.
3065772Sas200622 	 */
3078334SJose.Borrego@Sun.COM 	byte_order = hdr->packed_drep.intg_char_rep & NDR_REPLAB_INTG_MASK;
3088334SJose.Borrego@Sun.COM 	nds->swap = (byte_order != ndr_native_byte_order) ? 1 : 0;
3095772Sas200622 
3105772Sas200622 	ptype = hdr->ptype;
3118334SJose.Borrego@Sun.COM 	if (ptype == NDR_PTYPE_REQUEST &&
3128334SJose.Borrego@Sun.COM 	    (hdr->pfc_flags & NDR_PFC_OBJECT_UUID) != 0) {
3138334SJose.Borrego@Sun.COM 		ptype = NDR_PTYPE_REQUEST_WITH;	/* fake for sizing */
3145772Sas200622 	}
3155772Sas200622 
3169914Samw@Sun.COM 	rc = ndr_encode_decode_common(nds, ptype, &TYPEINFO(ndr_hdr), hdr);
3175772Sas200622 
3188334SJose.Borrego@Sun.COM 	return (NDR_DRC_PTYPE_RPCHDR(rc));
3195772Sas200622 }
3205772Sas200622 
321*12065SKeyur.Desai@Sun.COM static int
ndr_decode_pac_hdr(ndr_stream_t * nds,ndr_pac_hdr_t * hdr)322*12065SKeyur.Desai@Sun.COM ndr_decode_pac_hdr(ndr_stream_t *nds, ndr_pac_hdr_t *hdr)
323*12065SKeyur.Desai@Sun.COM {
324*12065SKeyur.Desai@Sun.COM 	int	rc;
325*12065SKeyur.Desai@Sun.COM 
326*12065SKeyur.Desai@Sun.COM 	if (nds->m_op != NDR_M_OP_UNMARSHALL)
327*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH);
328*12065SKeyur.Desai@Sun.COM 
329*12065SKeyur.Desai@Sun.COM 	/*
330*12065SKeyur.Desai@Sun.COM 	 * All PDU headers are at least this big
331*12065SKeyur.Desai@Sun.COM 	 */
332*12065SKeyur.Desai@Sun.COM 	rc = NDS_GROW_PDU(nds, sizeof (ndr_pac_hdr_t), 0);
333*12065SKeyur.Desai@Sun.COM 	if (!rc)
334*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT);
335*12065SKeyur.Desai@Sun.COM 
336*12065SKeyur.Desai@Sun.COM 	/*
337*12065SKeyur.Desai@Sun.COM 	 * Peek at the first eight bytes to figure out what we're doing.
338*12065SKeyur.Desai@Sun.COM 	 */
339*12065SKeyur.Desai@Sun.COM 	rc = NDS_GET_PDU(nds, 0, 8, (char *)hdr, 0, 0);
340*12065SKeyur.Desai@Sun.COM 	if (!rc)
341*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
342*12065SKeyur.Desai@Sun.COM 
343*12065SKeyur.Desai@Sun.COM 	/* Must be set to 1 to indicate type serialization version 1. */
344*12065SKeyur.Desai@Sun.COM 	if (hdr->common_hdr.version != 1)
345*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
346*12065SKeyur.Desai@Sun.COM 
347*12065SKeyur.Desai@Sun.COM 	/*
348*12065SKeyur.Desai@Sun.COM 	 * Set the byte swap flag if the PDU byte-order
349*12065SKeyur.Desai@Sun.COM 	 * is different from the local byte-order.
350*12065SKeyur.Desai@Sun.COM 	 */
351*12065SKeyur.Desai@Sun.COM 	nds->swap =
352*12065SKeyur.Desai@Sun.COM 	    (hdr->common_hdr.endianness != ndr_native_byte_order) ? 1 : 0;
353*12065SKeyur.Desai@Sun.COM 
354*12065SKeyur.Desai@Sun.COM 	rc = ndr_encode_decode_common(nds, NDR_PTYPE_PAC,
355*12065SKeyur.Desai@Sun.COM 	    &TYPEINFO(ndr_hdr), hdr);
356*12065SKeyur.Desai@Sun.COM 
357*12065SKeyur.Desai@Sun.COM 	return (NDR_DRC_PTYPE_RPCHDR(rc));
358*12065SKeyur.Desai@Sun.COM }
359*12065SKeyur.Desai@Sun.COM 
3605772Sas200622 /*
3618334SJose.Borrego@Sun.COM  * Decode an RPC fragment header.  Use ndr_decode_pdu_hdr() to process
3625772Sas200622  * the first fragment header then this function to process additional
3635772Sas200622  * fragment headers.
3645772Sas200622  */
3655772Sas200622 void
ndr_decode_frag_hdr(ndr_stream_t * nds,ndr_common_header_t * hdr)3668334SJose.Borrego@Sun.COM ndr_decode_frag_hdr(ndr_stream_t *nds, ndr_common_header_t *hdr)
3675772Sas200622 {
3687619SJose.Borrego@Sun.COM 	ndr_common_header_t *tmp;
3695772Sas200622 	uint8_t *pdu;
3705772Sas200622 	int byte_order;
3715772Sas200622 
3728334SJose.Borrego@Sun.COM 	pdu = (uint8_t *)nds->pdu_base_offset + nds->pdu_scan_offset;
3738334SJose.Borrego@Sun.COM 	bcopy(pdu, hdr, NDR_RSP_HDR_SIZE);
3745772Sas200622 
3755772Sas200622 	/*
3765772Sas200622 	 * Swap non-byte fields if the PDU byte-order
3775772Sas200622 	 * is different from the local byte-order.
3785772Sas200622 	 */
3798334SJose.Borrego@Sun.COM 	byte_order = hdr->packed_drep.intg_char_rep & NDR_REPLAB_INTG_MASK;
3805772Sas200622 
3818334SJose.Borrego@Sun.COM 	if (byte_order != ndr_native_byte_order) {
3825772Sas200622 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
3837619SJose.Borrego@Sun.COM 		tmp = (ndr_common_header_t *)pdu;
3845772Sas200622 
3858334SJose.Borrego@Sun.COM 		nds_bswap(&tmp->frag_length, &hdr->frag_length,
3865772Sas200622 		    sizeof (WORD));
3878334SJose.Borrego@Sun.COM 		nds_bswap(&tmp->auth_length, &hdr->auth_length,
3885772Sas200622 		    sizeof (WORD));
3898334SJose.Borrego@Sun.COM 		nds_bswap(&tmp->call_id, &hdr->call_id, sizeof (DWORD));
3905772Sas200622 	}
3915772Sas200622 }
3925772Sas200622 
39311963SAfshin.Ardakani@Sun.COM /*
39411963SAfshin.Ardakani@Sun.COM  * Remove an RPC fragment header from the received data stream.
39511963SAfshin.Ardakani@Sun.COM  *
39611963SAfshin.Ardakani@Sun.COM  * NDR stream on entry:
39711963SAfshin.Ardakani@Sun.COM  *
39811963SAfshin.Ardakani@Sun.COM  *                |<--- frag --->|
39911963SAfshin.Ardakani@Sun.COM  * +-----+--------+-----+--------+-----+---------+-----+
40011963SAfshin.Ardakani@Sun.COM  * | hdr |  data  | hdr |  data  | hdr |  data   | ... |
40111963SAfshin.Ardakani@Sun.COM  * +-----+--------+-----+--------+-----+---------+-----+
40211963SAfshin.Ardakani@Sun.COM  *                 <----
40311963SAfshin.Ardakani@Sun.COM  *
40411963SAfshin.Ardakani@Sun.COM  * NDR stream on return:
40511963SAfshin.Ardakani@Sun.COM  *
40611963SAfshin.Ardakani@Sun.COM  * +-----+----------------+-----+---------+-----+
40711963SAfshin.Ardakani@Sun.COM  * | hdr |       data     | hdr |  data   | ... |
40811963SAfshin.Ardakani@Sun.COM  * +-----+----------------+-----+---------+-----+
40911963SAfshin.Ardakani@Sun.COM  */
41011963SAfshin.Ardakani@Sun.COM void
ndr_remove_frag_hdr(ndr_stream_t * nds)41111963SAfshin.Ardakani@Sun.COM ndr_remove_frag_hdr(ndr_stream_t *nds)
41211963SAfshin.Ardakani@Sun.COM {
41311963SAfshin.Ardakani@Sun.COM 	char	*hdr;
41411963SAfshin.Ardakani@Sun.COM 	char	*data;
41511963SAfshin.Ardakani@Sun.COM 	int	nbytes;
41611963SAfshin.Ardakani@Sun.COM 
41711963SAfshin.Ardakani@Sun.COM 	hdr = (char *)nds->pdu_base_offset + nds->pdu_scan_offset;
41811963SAfshin.Ardakani@Sun.COM 	data = hdr + NDR_RSP_HDR_SIZE;
41911963SAfshin.Ardakani@Sun.COM 	nbytes = nds->pdu_size - nds->pdu_scan_offset - NDR_RSP_HDR_SIZE;
42011963SAfshin.Ardakani@Sun.COM 
42111963SAfshin.Ardakani@Sun.COM 	bcopy(data, hdr, nbytes);
42211963SAfshin.Ardakani@Sun.COM 	nds->pdu_size -= NDR_RSP_HDR_SIZE;
42311963SAfshin.Ardakani@Sun.COM }
42411963SAfshin.Ardakani@Sun.COM 
42510475Samw@Sun.COM void
ndr_show_hdr(ndr_common_header_t * hdr)42610475Samw@Sun.COM ndr_show_hdr(ndr_common_header_t *hdr)
42710475Samw@Sun.COM {
42810475Samw@Sun.COM 	char	*fragtype;
42910475Samw@Sun.COM 
43010475Samw@Sun.COM 	if (hdr == NULL) {
43110475Samw@Sun.COM 		ndo_printf(NULL, NULL, "ndr hdr: <null>");
43210475Samw@Sun.COM 		return;
43310475Samw@Sun.COM 	}
43410475Samw@Sun.COM 
43510475Samw@Sun.COM 	if (NDR_IS_SINGLE_FRAG(hdr->pfc_flags))
43610475Samw@Sun.COM 		fragtype = "single";
43710475Samw@Sun.COM 	else if (NDR_IS_FIRST_FRAG(hdr->pfc_flags))
43810475Samw@Sun.COM 		fragtype = "first";
43910475Samw@Sun.COM 	else if (NDR_IS_LAST_FRAG(hdr->pfc_flags))
44010475Samw@Sun.COM 		fragtype = "last";
44110475Samw@Sun.COM 	else
44210475Samw@Sun.COM 		fragtype = "intermediate";
44310475Samw@Sun.COM 
44410475Samw@Sun.COM 	ndo_printf(NULL, NULL,
44510475Samw@Sun.COM 	    "ndr hdr: %d.%d ptype=%d, %s frag (flags=0x%08x) len=%d",
44610475Samw@Sun.COM 	    hdr->rpc_vers, hdr->rpc_vers_minor, hdr->ptype,
44710475Samw@Sun.COM 	    fragtype, hdr->pfc_flags, hdr->frag_length);
44810475Samw@Sun.COM }
44910475Samw@Sun.COM 
4505772Sas200622 int
ndr_encode_pdu_hdr(ndr_xa_t * mxa)4518334SJose.Borrego@Sun.COM ndr_encode_pdu_hdr(ndr_xa_t *mxa)
4525772Sas200622 {
4538334SJose.Borrego@Sun.COM 	ndr_common_header_t	*hdr = &mxa->send_hdr.common_hdr;
4548334SJose.Borrego@Sun.COM 	ndr_stream_t		*nds = &mxa->send_nds;
4555772Sas200622 	int			ptype;
4565772Sas200622 	int			rc;
4575772Sas200622 
4588334SJose.Borrego@Sun.COM 	if (nds->m_op != NDR_M_OP_MARSHALL)
459*12065SKeyur.Desai@Sun.COM 		return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH);
4605772Sas200622 
4615772Sas200622 	ptype = hdr->ptype;
4628334SJose.Borrego@Sun.COM 	if (ptype == NDR_PTYPE_REQUEST &&
4638334SJose.Borrego@Sun.COM 	    (hdr->pfc_flags & NDR_PFC_OBJECT_UUID) != 0) {
4648334SJose.Borrego@Sun.COM 		ptype = NDR_PTYPE_REQUEST_WITH;	/* fake for sizing */
4655772Sas200622 	}
4665772Sas200622 
4679914Samw@Sun.COM 	rc = ndr_encode_decode_common(nds, ptype, &TYPEINFO(ndr_hdr), hdr);
4685772Sas200622 
4698334SJose.Borrego@Sun.COM 	return (NDR_DRC_PTYPE_RPCHDR(rc));
4705772Sas200622 }
4715772Sas200622 
4725772Sas200622 /*
4735772Sas200622  * This is a hand-coded derivative of the automatically generated
4745772Sas200622  * (un)marshalling routine for bind_ack headers. bind_ack headers
4755772Sas200622  * have an interior conformant array, which is inconsistent with
4765772Sas200622  * IDL/NDR rules.
4775772Sas200622  */
4785772Sas200622 extern struct ndr_typeinfo ndt__uchar;
4795772Sas200622 extern struct ndr_typeinfo ndt__ushort;
4805772Sas200622 extern struct ndr_typeinfo ndt__ulong;
4815772Sas200622 
4828334SJose.Borrego@Sun.COM int ndr__ndr_bind_ack_hdr(ndr_ref_t *encl_ref);
4838334SJose.Borrego@Sun.COM ndr_typeinfo_t ndt__ndr_bind_ack_hdr = {
4845772Sas200622     1,		/* NDR version */
4855772Sas200622     3,		/* alignment */
4865772Sas200622     NDR_F_STRUCT,	/* flags */
4878334SJose.Borrego@Sun.COM     ndr__ndr_bind_ack_hdr,	/* ndr_func */
4885772Sas200622     68,		/* pdu_size_fixed_part */
4895772Sas200622     0,		/* pdu_size_variable_part */
4905772Sas200622     68,		/* c_size_fixed_part */
4915772Sas200622     0,		/* c_size_variable_part */
4925772Sas200622 };
4935772Sas200622 
4945772Sas200622 /*
4955772Sas200622  * [_no_reorder]
4965772Sas200622  */
4975772Sas200622 int
ndr__ndr_bind_ack_hdr(ndr_ref_t * encl_ref)4988334SJose.Borrego@Sun.COM ndr__ndr_bind_ack_hdr(ndr_ref_t *encl_ref)
4995772Sas200622 {
5008334SJose.Borrego@Sun.COM 	ndr_stream_t		*nds = encl_ref->stream;
5017619SJose.Borrego@Sun.COM 	struct ndr_bind_ack_hdr	*val = /*LINTED E_BAD_PTR_CAST_ALIGN*/
5027619SJose.Borrego@Sun.COM 	    (struct ndr_bind_ack_hdr *)encl_ref->datum;
5038334SJose.Borrego@Sun.COM 	ndr_ref_t		myref;
5045772Sas200622 	unsigned long		offset;
5055772Sas200622 
5065772Sas200622 	bzero(&myref, sizeof (myref));
5075772Sas200622 	myref.enclosing = encl_ref;
5085772Sas200622 	myref.stream = encl_ref->stream;
5095772Sas200622 	myref.packed_alignment = 0;
5105772Sas200622 
5115772Sas200622 	/* do all members in order */
5127619SJose.Borrego@Sun.COM 	NDR_MEMBER(_ndr_common_header, common_hdr, 0UL);
5135772Sas200622 	NDR_MEMBER(_ushort, max_xmit_frag, 16UL);
5145772Sas200622 	NDR_MEMBER(_ushort, max_recv_frag, 18UL);
5155772Sas200622 	NDR_MEMBER(_ulong, assoc_group_id, 20UL);
5165772Sas200622 
5175772Sas200622 	/* port any is the conformant culprit */
5185772Sas200622 	offset = 24UL;
5195772Sas200622 
5208334SJose.Borrego@Sun.COM 	switch (nds->m_op) {
5215772Sas200622 	case NDR_M_OP_MARSHALL:
5225772Sas200622 		val->sec_addr.length =
5235772Sas200622 		    strlen((char *)val->sec_addr.port_spec) + 1;
5245772Sas200622 		break;
5255772Sas200622 
5265772Sas200622 	case NDR_M_OP_UNMARSHALL:
5275772Sas200622 		break;
5285772Sas200622 
5295772Sas200622 	default:
5305772Sas200622 		NDR_SET_ERROR(encl_ref, NDR_ERR_M_OP_INVALID);
5315772Sas200622 		return (0);
5325772Sas200622 	}
5335772Sas200622 
5345772Sas200622 	NDR_MEMBER(_ushort, sec_addr.length, offset);
5355772Sas200622 	NDR_MEMBER_ARR_WITH_DIMENSION(_uchar, sec_addr.port_spec,
5365772Sas200622 	    offset+2UL, val->sec_addr.length);
5375772Sas200622 
5385772Sas200622 	offset += 2;
5395772Sas200622 	offset += val->sec_addr.length;
5408334SJose.Borrego@Sun.COM 	offset += NDR_ALIGN4(offset);
5415772Sas200622 
5428334SJose.Borrego@Sun.COM 	NDR_MEMBER(_ndr_p_result_list, p_result_list, offset);
5435772Sas200622 	return (1);
5445772Sas200622 }
5455772Sas200622 
5467619SJose.Borrego@Sun.COM /*
5477619SJose.Borrego@Sun.COM  * Assume a single presentation context element in the result list.
5487619SJose.Borrego@Sun.COM  */
5495772Sas200622 unsigned
ndr_bind_ack_hdr_size(ndr_xa_t * mxa)5508334SJose.Borrego@Sun.COM ndr_bind_ack_hdr_size(ndr_xa_t *mxa)
5515772Sas200622 {
5527619SJose.Borrego@Sun.COM 	ndr_bind_ack_hdr_t *bahdr = &mxa->send_hdr.bind_ack_hdr;
5535772Sas200622 	unsigned	offset;
5545772Sas200622 	unsigned	length;
5555772Sas200622 
5565772Sas200622 	/* port any is the conformant culprit */
5575772Sas200622 	offset = 24UL;
5585772Sas200622 
5595772Sas200622 	length = strlen((char *)bahdr->sec_addr.port_spec) + 1;
5605772Sas200622 
5615772Sas200622 	offset += 2;
5625772Sas200622 	offset += length;
5638334SJose.Borrego@Sun.COM 	offset += NDR_ALIGN4(offset);
5648334SJose.Borrego@Sun.COM 	offset += sizeof (ndr_p_result_list_t);
5655772Sas200622 	return (offset);
5665772Sas200622 }
5677619SJose.Borrego@Sun.COM 
5687619SJose.Borrego@Sun.COM /*
5697619SJose.Borrego@Sun.COM  * This is a hand-coded derivative of the automatically generated
5707619SJose.Borrego@Sun.COM  * (un)marshalling routine for alter_context_rsp headers.
5717619SJose.Borrego@Sun.COM  * Alter context response headers have an interior conformant array,
5727619SJose.Borrego@Sun.COM  * which is inconsistent with IDL/NDR rules.
5737619SJose.Borrego@Sun.COM  */
5748334SJose.Borrego@Sun.COM int ndr__ndr_alter_context_rsp_hdr(ndr_ref_t *encl_ref);
5758334SJose.Borrego@Sun.COM ndr_typeinfo_t ndt__ndr_alter_context_rsp_hdr = {
5767619SJose.Borrego@Sun.COM     1,			/* NDR version */
5777619SJose.Borrego@Sun.COM     3,			/* alignment */
5787619SJose.Borrego@Sun.COM     NDR_F_STRUCT,	/* flags */
5798334SJose.Borrego@Sun.COM     ndr__ndr_alter_context_rsp_hdr,	/* ndr_func */
5807619SJose.Borrego@Sun.COM     56,			/* pdu_size_fixed_part */
5817619SJose.Borrego@Sun.COM     0,			/* pdu_size_variable_part */
5827619SJose.Borrego@Sun.COM     56,			/* c_size_fixed_part */
5837619SJose.Borrego@Sun.COM     0,			/* c_size_variable_part */
5847619SJose.Borrego@Sun.COM };
5857619SJose.Borrego@Sun.COM 
5867619SJose.Borrego@Sun.COM /*
5877619SJose.Borrego@Sun.COM  * [_no_reorder]
5887619SJose.Borrego@Sun.COM  */
5897619SJose.Borrego@Sun.COM int
ndr__ndr_alter_context_rsp_hdr(ndr_ref_t * encl_ref)5908334SJose.Borrego@Sun.COM ndr__ndr_alter_context_rsp_hdr(ndr_ref_t *encl_ref)
5917619SJose.Borrego@Sun.COM {
5928334SJose.Borrego@Sun.COM 	ndr_stream_t		*nds = encl_ref->stream;
5937619SJose.Borrego@Sun.COM 	ndr_alter_context_rsp_hdr_t *val = /*LINTED E_BAD_PTR_CAST_ALIGN*/
5947619SJose.Borrego@Sun.COM 	    (ndr_alter_context_rsp_hdr_t *)encl_ref->datum;
5958334SJose.Borrego@Sun.COM 	ndr_ref_t		myref;
5967619SJose.Borrego@Sun.COM 	unsigned long		offset;
5977619SJose.Borrego@Sun.COM 
5987619SJose.Borrego@Sun.COM 	bzero(&myref, sizeof (myref));
5997619SJose.Borrego@Sun.COM 	myref.enclosing = encl_ref;
6007619SJose.Borrego@Sun.COM 	myref.stream = encl_ref->stream;
6017619SJose.Borrego@Sun.COM 	myref.packed_alignment = 0;
6027619SJose.Borrego@Sun.COM 
6037619SJose.Borrego@Sun.COM 	/* do all members in order */
6047619SJose.Borrego@Sun.COM 	NDR_MEMBER(_ndr_common_header, common_hdr, 0UL);
6057619SJose.Borrego@Sun.COM 	NDR_MEMBER(_ushort, max_xmit_frag, 16UL);
6067619SJose.Borrego@Sun.COM 	NDR_MEMBER(_ushort, max_recv_frag, 18UL);
6077619SJose.Borrego@Sun.COM 	NDR_MEMBER(_ulong, assoc_group_id, 20UL);
6087619SJose.Borrego@Sun.COM 
6097619SJose.Borrego@Sun.COM 	offset = 24UL;	/* offset of sec_addr */
6107619SJose.Borrego@Sun.COM 
6118334SJose.Borrego@Sun.COM 	switch (nds->m_op) {
6127619SJose.Borrego@Sun.COM 	case NDR_M_OP_MARSHALL:
6137619SJose.Borrego@Sun.COM 		val->sec_addr.length = 0;
6147619SJose.Borrego@Sun.COM 		break;
6157619SJose.Borrego@Sun.COM 
6167619SJose.Borrego@Sun.COM 	case NDR_M_OP_UNMARSHALL:
6177619SJose.Borrego@Sun.COM 		break;
6187619SJose.Borrego@Sun.COM 
6197619SJose.Borrego@Sun.COM 	default:
6207619SJose.Borrego@Sun.COM 		NDR_SET_ERROR(encl_ref, NDR_ERR_M_OP_INVALID);
6217619SJose.Borrego@Sun.COM 		return (0);
6227619SJose.Borrego@Sun.COM 	}
6237619SJose.Borrego@Sun.COM 
6247619SJose.Borrego@Sun.COM 	NDR_MEMBER(_ushort, sec_addr.length, offset);
6257619SJose.Borrego@Sun.COM 	NDR_MEMBER_ARR_WITH_DIMENSION(_uchar, sec_addr.port_spec,
6267619SJose.Borrego@Sun.COM 	    offset+2UL, val->sec_addr.length);
6277619SJose.Borrego@Sun.COM 
6287619SJose.Borrego@Sun.COM 	offset += 2;	/* sizeof (sec_addr.length) */
6298334SJose.Borrego@Sun.COM 	offset += NDR_ALIGN4(offset);
6307619SJose.Borrego@Sun.COM 
6318334SJose.Borrego@Sun.COM 	NDR_MEMBER(_ndr_p_result_list, p_result_list, offset);
6327619SJose.Borrego@Sun.COM 	return (1);
6337619SJose.Borrego@Sun.COM }
6347619SJose.Borrego@Sun.COM 
6357619SJose.Borrego@Sun.COM /*
6367619SJose.Borrego@Sun.COM  * Assume a single presentation context element in the result list.
6377619SJose.Borrego@Sun.COM  */
6387619SJose.Borrego@Sun.COM unsigned
ndr_alter_context_rsp_hdr_size(void)6398334SJose.Borrego@Sun.COM ndr_alter_context_rsp_hdr_size(void)
6407619SJose.Borrego@Sun.COM {
6417619SJose.Borrego@Sun.COM 	unsigned	offset;
6427619SJose.Borrego@Sun.COM 
6437619SJose.Borrego@Sun.COM 	offset = 24UL;	/* offset of sec_addr */
6447619SJose.Borrego@Sun.COM 	offset += 2;	/* sizeof (sec_addr.length) */
6458334SJose.Borrego@Sun.COM 	offset += NDR_ALIGN4(offset);
6468334SJose.Borrego@Sun.COM 	offset += sizeof (ndr_p_result_list_t);
6477619SJose.Borrego@Sun.COM 	return (offset);
6487619SJose.Borrego@Sun.COM }
649