xref: /titanic_52/usr/src/lib/smbsrv/libmlrpc/common/ndr_marshal.c (revision ad8ef92ae01ac09e533731f5a517162c634308b4)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 #include <assert.h>
26 #include <strings.h>
27 #include <sys/param.h>
28 
29 #include <smbsrv/libsmb.h>
30 #include <smbsrv/libmlrpc.h>
31 
32 #ifdef _BIG_ENDIAN
33 static const int ndr_native_byte_order = NDR_REPLAB_INTG_BIG_ENDIAN;
34 #else
35 static const int ndr_native_byte_order = NDR_REPLAB_INTG_LITTLE_ENDIAN;
36 #endif
37 
38 static int ndr_decode_hdr_common(ndr_stream_t *, ndr_common_header_t *);
39 static int ndr_decode_pac_hdr(ndr_stream_t *, ndr_pac_hdr_t *);
40 
41 static int
42 ndr_encode_decode_common(ndr_stream_t *nds, unsigned opnum,
43     ndr_typeinfo_t *ti, void *datum)
44 {
45 	int rc;
46 
47 	/*
48 	 * Perform the (un)marshalling
49 	 */
50 	if (ndo_operation(nds, ti, opnum, datum))
51 		return (NDR_DRC_OK);
52 
53 	switch (nds->error) {
54 	case NDR_ERR_MALLOC_FAILED:
55 		rc = NDR_DRC_FAULT_OUT_OF_MEMORY;
56 		break;
57 
58 	case NDR_ERR_SWITCH_VALUE_INVALID:
59 		rc = NDR_DRC_FAULT_PARAM_0_INVALID;
60 		break;
61 
62 	case NDR_ERR_UNDERFLOW:
63 		rc = NDR_DRC_FAULT_RECEIVED_RUNT;
64 		break;
65 
66 	case NDR_ERR_GROW_FAILED:
67 		rc = NDR_DRC_FAULT_ENCODE_TOO_BIG;
68 		break;
69 
70 	default:
71 		if (nds->m_op == NDR_M_OP_MARSHALL)
72 			rc = NDR_DRC_FAULT_ENCODE_FAILED;
73 		else
74 			rc = NDR_DRC_FAULT_DECODE_FAILED;
75 		break;
76 	}
77 
78 	return (rc);
79 }
80 
81 ndr_buf_t *
82 ndr_buf_init(ndr_typeinfo_t *ti)
83 {
84 	ndr_buf_t		*nbuf;
85 
86 	if ((nbuf = calloc(1, sizeof (ndr_buf_t))) == NULL)
87 		return (NULL);
88 
89 	if ((nbuf->nb_heap = ndr_heap_create()) == NULL) {
90 		free(nbuf);
91 		return (NULL);
92 	}
93 
94 	nbuf->nb_ti = ti;
95 	nbuf->nb_magic = NDR_BUF_MAGIC;
96 	return (nbuf);
97 }
98 
99 void
100 ndr_buf_fini(ndr_buf_t *nbuf)
101 {
102 	assert(nbuf->nb_magic == NDR_BUF_MAGIC);
103 
104 	nds_destruct(&nbuf->nb_nds);
105 	ndr_heap_destroy(nbuf->nb_heap);
106 	nbuf->nb_magic = 0;
107 	free(nbuf);
108 }
109 
110 /*
111  * Decode an NDR encoded buffer.  The buffer is expected to contain
112  * a single fragment packet with a valid PDU header followed by NDR
113  * encoded data.  The structure to which result points should be
114  * of the appropriate type to hold the decoded output.  For example:
115  *
116  *	pac_info_t info;
117  *
118  * 	if ((nbuf = ndr_buf_init(&TYPEINFO(ndr_pac)) != NULL) {
119  *		rc = ndr_decode_buf(nbuf, opnum, data, datalen, &info);
120  *		...
121  *		ndr_buf_fini(nbuf);
122  *	}
123  */
124 int
125 ndr_buf_decode(ndr_buf_t *nbuf, unsigned hdr_type, unsigned opnum,
126     const char *data, size_t datalen, void *result)
127 {
128 	ndr_common_header_t	hdr;
129 	ndr_pac_hdr_t		pac_hdr;
130 	unsigned		pdu_size_hint;
131 	int			rc;
132 
133 	assert(nbuf->nb_magic == NDR_BUF_MAGIC);
134 	assert(nbuf->nb_heap != NULL);
135 	assert(nbuf->nb_ti != NULL);
136 
137 	if (datalen < NDR_PDU_SIZE_HINT_DEFAULT)
138 		pdu_size_hint = NDR_PDU_SIZE_HINT_DEFAULT;
139 	else
140 		pdu_size_hint = datalen;
141 
142 	rc = nds_initialize(&nbuf->nb_nds, pdu_size_hint, NDR_MODE_BUF_DECODE,
143 	    nbuf->nb_heap);
144 	if (NDR_DRC_IS_FAULT(rc))
145 		return (rc);
146 
147 	bcopy(data, nbuf->nb_nds.pdu_base_addr, datalen);
148 
149 	switch (hdr_type) {
150 	case NDR_PTYPE_COMMON:
151 		rc = ndr_decode_hdr_common(&nbuf->nb_nds, &hdr);
152 		if (NDR_DRC_IS_FAULT(rc))
153 			return (rc);
154 
155 		if (!NDR_IS_SINGLE_FRAG(hdr.pfc_flags))
156 			return (NDR_DRC_FAULT_DECODE_FAILED);
157 		break;
158 
159 	case NDR_PTYPE_PAC:
160 		rc = ndr_decode_pac_hdr(&nbuf->nb_nds, &pac_hdr);
161 		if (NDR_DRC_IS_FAULT(rc))
162 			return (rc);
163 
164 		if (pac_hdr.common_hdr.hdrlen != sizeof (ndr_serialtype1_hdr_t))
165 			return (NDR_DRC_FAULT_DECODE_FAILED);
166 		break;
167 
168 	default:
169 		return (NDR_ERR_UNIMPLEMENTED);
170 	}
171 
172 	rc = ndr_encode_decode_common(&nbuf->nb_nds, opnum, nbuf->nb_ti,
173 	    result);
174 	return (rc);
175 }
176 
177 /*
178  * Use the receive stream to unmarshall data (NDR_MODE_CALL_RECV).
179  */
180 int
181 ndr_decode_call(ndr_xa_t *mxa, void *params)
182 {
183 	ndr_stream_t	*nds = &mxa->recv_nds;
184 	int		rc;
185 
186 	if (!NDR_MODE_MATCH(nds, NDR_MODE_CALL_RECV))
187 		return (NDR_DRC_FAULT_MODE_MISMATCH);
188 
189 	rc = ndr_encode_decode_common(nds, mxa->opnum,
190 	    mxa->binding->service->interface_ti, params);
191 
192 	return (rc + NDR_PTYPE_REQUEST);
193 }
194 
195 /*
196  * Use the send stream to marshall data (NDR_MODE_RETURN_SEND).
197  */
198 int
199 ndr_encode_return(ndr_xa_t *mxa, void *params)
200 {
201 	ndr_stream_t	*nds = &mxa->send_nds;
202 	int		rc;
203 
204 	if (!NDR_MODE_MATCH(nds, NDR_MODE_RETURN_SEND))
205 		return (NDR_DRC_FAULT_MODE_MISMATCH);
206 
207 	rc = ndr_encode_decode_common(nds, mxa->opnum,
208 	    mxa->binding->service->interface_ti, params);
209 
210 	return (rc + NDR_PTYPE_RESPONSE);
211 }
212 
213 /*
214  * Use the send stream to marshall data (NDR_MODE_CALL_SEND).
215  */
216 int
217 ndr_encode_call(ndr_xa_t *mxa, void *params)
218 {
219 	ndr_stream_t	*nds = &mxa->send_nds;
220 	int		rc;
221 
222 	if (!NDR_MODE_MATCH(nds, NDR_MODE_CALL_SEND))
223 		return (NDR_DRC_FAULT_MODE_MISMATCH);
224 
225 	rc = ndr_encode_decode_common(nds, mxa->opnum,
226 	    mxa->binding->service->interface_ti, params);
227 
228 	return (rc + NDR_PTYPE_REQUEST);
229 }
230 
231 /*
232  * Use the receive stream to unmarshall data (NDR_MODE_RETURN_RECV).
233  */
234 int
235 ndr_decode_return(ndr_xa_t *mxa, void *params)
236 {
237 	ndr_stream_t	*nds = &mxa->recv_nds;
238 	int		rc;
239 
240 	if (!NDR_MODE_MATCH(nds, NDR_MODE_RETURN_RECV))
241 		return (NDR_DRC_FAULT_MODE_MISMATCH);
242 
243 	rc = ndr_encode_decode_common(nds, mxa->opnum,
244 	    mxa->binding->service->interface_ti, params);
245 
246 	return (rc + NDR_PTYPE_RESPONSE);
247 }
248 
249 int
250 ndr_decode_pdu_hdr(ndr_xa_t *mxa)
251 {
252 	ndr_common_header_t	*hdr = &mxa->recv_hdr.common_hdr;
253 	ndr_stream_t		*nds = &mxa->recv_nds;
254 	int			rc;
255 
256 	rc = ndr_decode_hdr_common(nds, hdr);
257 	if (NDR_DRC_IS_FAULT(rc))
258 		return (rc);
259 
260 	/*
261 	 * Verify the protocol version.
262 	 */
263 	if ((hdr->rpc_vers != 5) || (hdr->rpc_vers_minor != 0))
264 		return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
265 
266 	mxa->ptype = hdr->ptype;
267 	return (NDR_DRC_OK);
268 }
269 
270 static int
271 ndr_decode_hdr_common(ndr_stream_t *nds, ndr_common_header_t *hdr)
272 {
273 	int			ptype;
274 	int			rc;
275 	int			charset;
276 	int			byte_order;
277 
278 	if (nds->m_op != NDR_M_OP_UNMARSHALL)
279 		return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH);
280 
281 	/*
282 	 * All PDU headers are at least this big
283 	 */
284 	rc = NDS_GROW_PDU(nds, sizeof (ndr_common_header_t), 0);
285 	if (!rc)
286 		return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT);
287 
288 	/*
289 	 * Peek at the first eight bytes to figure out what we're doing.
290 	 */
291 	rc = NDS_GET_PDU(nds, 0, 8, (char *)hdr, 0, 0);
292 	if (!rc)
293 		return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
294 
295 	/*
296 	 * Check for ASCII as the character set.  This is an ASCII
297 	 * versus EBCDIC option and has nothing to do with Unicode.
298 	 */
299 	charset = hdr->packed_drep.intg_char_rep & NDR_REPLAB_CHAR_MASK;
300 	if (charset != NDR_REPLAB_CHAR_ASCII)
301 		return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
302 
303 	/*
304 	 * Set the byte swap flag if the PDU byte-order
305 	 * is different from the local byte-order.
306 	 */
307 	byte_order = hdr->packed_drep.intg_char_rep & NDR_REPLAB_INTG_MASK;
308 	nds->swap = (byte_order != ndr_native_byte_order) ? 1 : 0;
309 
310 	ptype = hdr->ptype;
311 	if (ptype == NDR_PTYPE_REQUEST &&
312 	    (hdr->pfc_flags & NDR_PFC_OBJECT_UUID) != 0) {
313 		ptype = NDR_PTYPE_REQUEST_WITH;	/* fake for sizing */
314 	}
315 
316 	rc = ndr_encode_decode_common(nds, ptype, &TYPEINFO(ndr_hdr), hdr);
317 
318 	return (NDR_DRC_PTYPE_RPCHDR(rc));
319 }
320 
321 static int
322 ndr_decode_pac_hdr(ndr_stream_t *nds, ndr_pac_hdr_t *hdr)
323 {
324 	int	rc;
325 
326 	if (nds->m_op != NDR_M_OP_UNMARSHALL)
327 		return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH);
328 
329 	/*
330 	 * All PDU headers are at least this big
331 	 */
332 	rc = NDS_GROW_PDU(nds, sizeof (ndr_pac_hdr_t), 0);
333 	if (!rc)
334 		return (NDR_DRC_FAULT_RPCHDR_RECEIVED_RUNT);
335 
336 	/*
337 	 * Peek at the first eight bytes to figure out what we're doing.
338 	 */
339 	rc = NDS_GET_PDU(nds, 0, 8, (char *)hdr, 0, 0);
340 	if (!rc)
341 		return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
342 
343 	/* Must be set to 1 to indicate type serialization version 1. */
344 	if (hdr->common_hdr.version != 1)
345 		return (NDR_DRC_FAULT_RPCHDR_DECODE_FAILED);
346 
347 	/*
348 	 * Set the byte swap flag if the PDU byte-order
349 	 * is different from the local byte-order.
350 	 */
351 	nds->swap =
352 	    (hdr->common_hdr.endianness != ndr_native_byte_order) ? 1 : 0;
353 
354 	rc = ndr_encode_decode_common(nds, NDR_PTYPE_PAC,
355 	    &TYPEINFO(ndr_hdr), hdr);
356 
357 	return (NDR_DRC_PTYPE_RPCHDR(rc));
358 }
359 
360 /*
361  * Decode an RPC fragment header.  Use ndr_decode_pdu_hdr() to process
362  * the first fragment header then this function to process additional
363  * fragment headers.
364  */
365 void
366 ndr_decode_frag_hdr(ndr_stream_t *nds, ndr_common_header_t *hdr)
367 {
368 	ndr_common_header_t *tmp;
369 	uint8_t *pdu;
370 	int byte_order;
371 
372 	pdu = (uint8_t *)nds->pdu_base_offset + nds->pdu_scan_offset;
373 	bcopy(pdu, hdr, NDR_RSP_HDR_SIZE);
374 
375 	/*
376 	 * Swap non-byte fields if the PDU byte-order
377 	 * is different from the local byte-order.
378 	 */
379 	byte_order = hdr->packed_drep.intg_char_rep & NDR_REPLAB_INTG_MASK;
380 
381 	if (byte_order != ndr_native_byte_order) {
382 		/*LINTED E_BAD_PTR_CAST_ALIGN*/
383 		tmp = (ndr_common_header_t *)pdu;
384 
385 		nds_bswap(&tmp->frag_length, &hdr->frag_length,
386 		    sizeof (WORD));
387 		nds_bswap(&tmp->auth_length, &hdr->auth_length,
388 		    sizeof (WORD));
389 		nds_bswap(&tmp->call_id, &hdr->call_id, sizeof (DWORD));
390 	}
391 }
392 
393 /*
394  * Remove an RPC fragment header from the received data stream.
395  *
396  * NDR stream on entry:
397  *
398  *                |<--- frag --->|
399  * +-----+--------+-----+--------+-----+---------+-----+
400  * | hdr |  data  | hdr |  data  | hdr |  data   | ... |
401  * +-----+--------+-----+--------+-----+---------+-----+
402  *                 <----
403  *
404  * NDR stream on return:
405  *
406  * +-----+----------------+-----+---------+-----+
407  * | hdr |       data     | hdr |  data   | ... |
408  * +-----+----------------+-----+---------+-----+
409  */
410 void
411 ndr_remove_frag_hdr(ndr_stream_t *nds)
412 {
413 	char	*hdr;
414 	char	*data;
415 	int	nbytes;
416 
417 	hdr = (char *)nds->pdu_base_offset + nds->pdu_scan_offset;
418 	data = hdr + NDR_RSP_HDR_SIZE;
419 	nbytes = nds->pdu_size - nds->pdu_scan_offset - NDR_RSP_HDR_SIZE;
420 
421 	bcopy(data, hdr, nbytes);
422 	nds->pdu_size -= NDR_RSP_HDR_SIZE;
423 }
424 
425 void
426 ndr_show_hdr(ndr_common_header_t *hdr)
427 {
428 	char	*fragtype;
429 
430 	if (hdr == NULL) {
431 		ndo_printf(NULL, NULL, "ndr hdr: <null>");
432 		return;
433 	}
434 
435 	if (NDR_IS_SINGLE_FRAG(hdr->pfc_flags))
436 		fragtype = "single";
437 	else if (NDR_IS_FIRST_FRAG(hdr->pfc_flags))
438 		fragtype = "first";
439 	else if (NDR_IS_LAST_FRAG(hdr->pfc_flags))
440 		fragtype = "last";
441 	else
442 		fragtype = "intermediate";
443 
444 	ndo_printf(NULL, NULL,
445 	    "ndr hdr: %d.%d ptype=%d, %s frag (flags=0x%08x) len=%d",
446 	    hdr->rpc_vers, hdr->rpc_vers_minor, hdr->ptype,
447 	    fragtype, hdr->pfc_flags, hdr->frag_length);
448 }
449 
450 int
451 ndr_encode_pdu_hdr(ndr_xa_t *mxa)
452 {
453 	ndr_common_header_t	*hdr = &mxa->send_hdr.common_hdr;
454 	ndr_stream_t		*nds = &mxa->send_nds;
455 	int			ptype;
456 	int			rc;
457 
458 	if (nds->m_op != NDR_M_OP_MARSHALL)
459 		return (NDR_DRC_FAULT_RPCHDR_MODE_MISMATCH);
460 
461 	ptype = hdr->ptype;
462 	if (ptype == NDR_PTYPE_REQUEST &&
463 	    (hdr->pfc_flags & NDR_PFC_OBJECT_UUID) != 0) {
464 		ptype = NDR_PTYPE_REQUEST_WITH;	/* fake for sizing */
465 	}
466 
467 	rc = ndr_encode_decode_common(nds, ptype, &TYPEINFO(ndr_hdr), hdr);
468 
469 	return (NDR_DRC_PTYPE_RPCHDR(rc));
470 }
471 
472 /*
473  * This is a hand-coded derivative of the automatically generated
474  * (un)marshalling routine for bind_ack headers. bind_ack headers
475  * have an interior conformant array, which is inconsistent with
476  * IDL/NDR rules.
477  */
478 extern struct ndr_typeinfo ndt__uchar;
479 extern struct ndr_typeinfo ndt__ushort;
480 extern struct ndr_typeinfo ndt__ulong;
481 
482 int ndr__ndr_bind_ack_hdr(ndr_ref_t *encl_ref);
483 ndr_typeinfo_t ndt__ndr_bind_ack_hdr = {
484     1,		/* NDR version */
485     3,		/* alignment */
486     NDR_F_STRUCT,	/* flags */
487     ndr__ndr_bind_ack_hdr,	/* ndr_func */
488     68,		/* pdu_size_fixed_part */
489     0,		/* pdu_size_variable_part */
490     68,		/* c_size_fixed_part */
491     0,		/* c_size_variable_part */
492 };
493 
494 /*
495  * [_no_reorder]
496  */
497 int
498 ndr__ndr_bind_ack_hdr(ndr_ref_t *encl_ref)
499 {
500 	ndr_stream_t		*nds = encl_ref->stream;
501 	struct ndr_bind_ack_hdr	*val = /*LINTED E_BAD_PTR_CAST_ALIGN*/
502 	    (struct ndr_bind_ack_hdr *)encl_ref->datum;
503 	ndr_ref_t		myref;
504 	unsigned long		offset;
505 
506 	bzero(&myref, sizeof (myref));
507 	myref.enclosing = encl_ref;
508 	myref.stream = encl_ref->stream;
509 	myref.packed_alignment = 0;
510 
511 	/* do all members in order */
512 	NDR_MEMBER(_ndr_common_header, common_hdr, 0UL);
513 	NDR_MEMBER(_ushort, max_xmit_frag, 16UL);
514 	NDR_MEMBER(_ushort, max_recv_frag, 18UL);
515 	NDR_MEMBER(_ulong, assoc_group_id, 20UL);
516 
517 	/* port any is the conformant culprit */
518 	offset = 24UL;
519 
520 	switch (nds->m_op) {
521 	case NDR_M_OP_MARSHALL:
522 		val->sec_addr.length =
523 		    strlen((char *)val->sec_addr.port_spec) + 1;
524 		break;
525 
526 	case NDR_M_OP_UNMARSHALL:
527 		break;
528 
529 	default:
530 		NDR_SET_ERROR(encl_ref, NDR_ERR_M_OP_INVALID);
531 		return (0);
532 	}
533 
534 	NDR_MEMBER(_ushort, sec_addr.length, offset);
535 	NDR_MEMBER_ARR_WITH_DIMENSION(_uchar, sec_addr.port_spec,
536 	    offset+2UL, val->sec_addr.length);
537 
538 	offset += 2;
539 	offset += val->sec_addr.length;
540 	offset += NDR_ALIGN4(offset);
541 
542 	NDR_MEMBER(_ndr_p_result_list, p_result_list, offset);
543 	return (1);
544 }
545 
546 /*
547  * Assume a single presentation context element in the result list.
548  */
549 unsigned
550 ndr_bind_ack_hdr_size(ndr_xa_t *mxa)
551 {
552 	ndr_bind_ack_hdr_t *bahdr = &mxa->send_hdr.bind_ack_hdr;
553 	unsigned	offset;
554 	unsigned	length;
555 
556 	/* port any is the conformant culprit */
557 	offset = 24UL;
558 
559 	length = strlen((char *)bahdr->sec_addr.port_spec) + 1;
560 
561 	offset += 2;
562 	offset += length;
563 	offset += NDR_ALIGN4(offset);
564 	offset += sizeof (ndr_p_result_list_t);
565 	return (offset);
566 }
567 
568 /*
569  * This is a hand-coded derivative of the automatically generated
570  * (un)marshalling routine for alter_context_rsp headers.
571  * Alter context response headers have an interior conformant array,
572  * which is inconsistent with IDL/NDR rules.
573  */
574 int ndr__ndr_alter_context_rsp_hdr(ndr_ref_t *encl_ref);
575 ndr_typeinfo_t ndt__ndr_alter_context_rsp_hdr = {
576     1,			/* NDR version */
577     3,			/* alignment */
578     NDR_F_STRUCT,	/* flags */
579     ndr__ndr_alter_context_rsp_hdr,	/* ndr_func */
580     56,			/* pdu_size_fixed_part */
581     0,			/* pdu_size_variable_part */
582     56,			/* c_size_fixed_part */
583     0,			/* c_size_variable_part */
584 };
585 
586 /*
587  * [_no_reorder]
588  */
589 int
590 ndr__ndr_alter_context_rsp_hdr(ndr_ref_t *encl_ref)
591 {
592 	ndr_stream_t		*nds = encl_ref->stream;
593 	ndr_alter_context_rsp_hdr_t *val = /*LINTED E_BAD_PTR_CAST_ALIGN*/
594 	    (ndr_alter_context_rsp_hdr_t *)encl_ref->datum;
595 	ndr_ref_t		myref;
596 	unsigned long		offset;
597 
598 	bzero(&myref, sizeof (myref));
599 	myref.enclosing = encl_ref;
600 	myref.stream = encl_ref->stream;
601 	myref.packed_alignment = 0;
602 
603 	/* do all members in order */
604 	NDR_MEMBER(_ndr_common_header, common_hdr, 0UL);
605 	NDR_MEMBER(_ushort, max_xmit_frag, 16UL);
606 	NDR_MEMBER(_ushort, max_recv_frag, 18UL);
607 	NDR_MEMBER(_ulong, assoc_group_id, 20UL);
608 
609 	offset = 24UL;	/* offset of sec_addr */
610 
611 	switch (nds->m_op) {
612 	case NDR_M_OP_MARSHALL:
613 		val->sec_addr.length = 0;
614 		break;
615 
616 	case NDR_M_OP_UNMARSHALL:
617 		break;
618 
619 	default:
620 		NDR_SET_ERROR(encl_ref, NDR_ERR_M_OP_INVALID);
621 		return (0);
622 	}
623 
624 	NDR_MEMBER(_ushort, sec_addr.length, offset);
625 	NDR_MEMBER_ARR_WITH_DIMENSION(_uchar, sec_addr.port_spec,
626 	    offset+2UL, val->sec_addr.length);
627 
628 	offset += 2;	/* sizeof (sec_addr.length) */
629 	offset += NDR_ALIGN4(offset);
630 
631 	NDR_MEMBER(_ndr_p_result_list, p_result_list, offset);
632 	return (1);
633 }
634 
635 /*
636  * Assume a single presentation context element in the result list.
637  */
638 unsigned
639 ndr_alter_context_rsp_hdr_size(void)
640 {
641 	unsigned	offset;
642 
643 	offset = 24UL;	/* offset of sec_addr */
644 	offset += 2;	/* sizeof (sec_addr.length) */
645 	offset += NDR_ALIGN4(offset);
646 	offset += sizeof (ndr_p_result_list_t);
647 	return (offset);
648 }
649