xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c (revision 21d23cc145f4b4679726016486c401c0abf3c34a)
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 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"@(#)smb_mbuf_marshaling.c	1.6	08/08/08 SMI"
27 
28 /*
29  * SMB mbuf marshaling encode/decode.
30  */
31 
32 #include <smbsrv/smb_incl.h>
33 
34 #define	MALLOC_QUANTUM	80
35 
36 #define	DECODE_NO_ERROR		0
37 #define	DECODE_NO_MORE_DATA	1
38 #define	DECODE_ALLOCATION_ERROR	2
39 #define	DECODE_CONVERSION_ERROR	3
40 
41 static int mbc_marshal_make_room(mbuf_chain_t *, int32_t);
42 static void mbc_marshal_store_byte(mbuf_chain_t *, uint8_t);
43 static int mbc_marshal_put_char(mbuf_chain_t *mbc, uint8_t);
44 static int mbc_marshal_put_short(mbuf_chain_t *mbc, uint16_t);
45 static int mbc_marshal_put_long(mbuf_chain_t *mbc, uint32_t);
46 static int mbc_marshal_put_long_long(mbuf_chain_t *mbc, uint64_t);
47 static int mbc_marshal_put_ascii_string(mbuf_chain_t *, char *, int);
48 static int mbc_marshal_put_unicode_string(mbuf_chain_t *, char *, int);
49 static int mbc_marshal_put_uio(mbuf_chain_t *, struct uio *);
50 static int mbc_marshal_put_mbufs(mbuf_chain_t *mbc, mbuf_t *m);
51 static int mbc_marshal_put_mbuf_chain(mbuf_chain_t *mbc, mbuf_chain_t *nmbc);
52 static uint8_t mbc_marshal_fetch_byte(mbuf_chain_t *mbc);
53 static int mbc_marshal_get_char(mbuf_chain_t *mbc, uint8_t *data);
54 static int mbc_marshal_get_short(mbuf_chain_t *mbc, uint16_t *data);
55 static int mbc_marshal_get_long(mbuf_chain_t *mbc, uint32_t *data);
56 static uint64_t qswap(uint64_t ll);
57 static int mbc_marshal_get_odd_long_long(mbuf_chain_t *mbc, uint64_t *data);
58 static int mbc_marshal_get_long_long(mbuf_chain_t *mbc, uint64_t *data);
59 static int mbc_marshal_get_ascii_string(struct smb_malloc_list *,
60     mbuf_chain_t *, uint8_t **ascii, int);
61 static int mbc_marshal_get_unicode_string(struct smb_malloc_list *,
62     mbuf_chain_t *, uint8_t **, int);
63 static int mbc_marshal_get_mbufs(mbuf_chain_t *, int32_t, mbuf_t **);
64 static int mbc_marshal_get_mbuf_chain(mbuf_chain_t *, int32_t, mbuf_chain_t *);
65 static int mbc_marshal_get_uio(mbuf_chain_t *, struct uio *);
66 static int mbc_marshal_get_skip(mbuf_chain_t *, uint_t);
67 
68 /*
69  * smb_mbc_vdecodef
70  *
71  * This function reads the contents of the mbc chain passed in under the list
72  * of arguments passed in.
73  *
74  * The format string provides a description of the parameters passed in as well
75  * as an action to be taken by smb_mbc_vdecodef().
76  *
77  *	%	Pointer to an SMB request structure (smb_request_t *). There
78  *		should be only one of these in the string.
79  *
80  *	C	Pointer to an mbuf chain. Copy to that mbuf chain the number of
81  *		bytes specified (number preceding C).
82  *
83  *	m	Pointer to an mbuf. Copy to that mbuf the number of bytes
84  *		specified (number preceding m).
85  *
86  *	M	Read the 32 bit value at the current location of the mbuf chain
87  *		and check if it matches the signature of an SMB request (SMBX).
88  *
89  *	b	Pointer to a buffer. Copy to that buffer the number of bytes
90  *		specified (number preceding b).
91  *
92  *	c	Same as 'b'.
93  *
94  *	w	Pointer to a word (16bit value). Copy the next 16bit value into
95  *		that location.
96  *
97  *	l	Pointer to a long (32bit value). Copy the next 32bit value into
98  *		that location.
99  *
100  *	q	Pointer to a quad (64bit value). Copy the next 64bit value into
101  *		that location.
102  *
103  *	Q	Same as above with a call to qswap().
104  *
105  *	B	Pointer to a vardata_block structure. That structure is used to
106  *		retrieve data from the mbuf chain (an iovec type structure is
107  *		embedded in a vardata_block).
108  *
109  *	D	Pointer to a vardata_block structure. That structure is used to
110  *		retrieve data from the mbuf chain, however, two fields of the
111  *		vardata_block structure (tag and len) are first initialized
112  *		using the mbuf chain itself.
113  *
114  *	V	Same as 'D'.
115  *
116  *	L
117  *
118  *	A
119  *
120  *	P	Same as 'A'
121  *
122  *	S	Same as 'A'
123  *
124  *	u	Pointer to a string pointer. Allocate memory and retrieve the
125  *		string at the current location in the mbuf chain. Store the
126  *		address to the buffer allocated at the address specified by
127  *		the pointer. In addition if an sr was passed and it indicates
128  *		that the string is an unicode string, convert it.
129  *
130  *	s	Same as 'u' without convertion.
131  *
132  *	U	Same as 'u'. The string to retrieve is unicode.
133  *
134  *	y	Pointer to a 32bit value. Read the dos time at the current mbuf
135  *		chain location, convert it to unix time and store it at the
136  *		location indicated by the pointer.
137  *
138  *	Y	Same as 'y' bt the dos time coded in the mbuf chain is inverted.
139  *
140  *	.	Skip the number of bytes indicated by the number preceding '.'.
141  *
142  *	,	Same as '.' but take in account it is an unicode string.
143  */
144 int
145 smb_mbc_vdecodef(mbuf_chain_t *mbc, char *fmt, va_list ap)
146 {
147 	uint8_t		c;
148 	uint8_t		cval;
149 	uint8_t		*cvalp;
150 	uint8_t		**cvalpp;
151 	uint16_t	*wvalp;
152 	uint32_t	*lvalp;
153 	uint64_t	*llvalp;
154 	smb_vdb_t	*vdp;
155 	smb_request_t	*sr = NULL;
156 	uint32_t	lval;
157 	int		unicode = 0;
158 	int		repc;
159 
160 	while ((c = *fmt++) != 0) {
161 		repc = 1;
162 
163 		if ('0' <= c && c <= '9') {
164 			repc = 0;
165 			do {
166 				repc = repc * 10 + c - '0';
167 				c = *fmt++;
168 			} while ('0' <= c && c <= '9');
169 		} else if (c == '#') {
170 			repc = va_arg(ap, int);
171 			c = *fmt++;
172 		}
173 
174 		switch (c) {
175 		case '%':
176 			sr = va_arg(ap, struct smb_request *);
177 			unicode = sr->smb_flg2 & SMB_FLAGS2_UNICODE;
178 			break;
179 
180 		case 'C':	/* Mbuf_chain */
181 			if (mbc_marshal_get_mbuf_chain(mbc, repc,
182 			    va_arg(ap, mbuf_chain_t *)) != 0)
183 				return (-1);
184 			break;
185 
186 		case 'm':	/* struct_mbuf */
187 			if (mbc_marshal_get_mbufs(mbc, repc,
188 			    va_arg(ap, mbuf_t **)) != 0)
189 				return (-1);
190 			break;
191 
192 		case 'M':
193 			if (mbc_marshal_get_long(mbc, &lval) != 0)
194 				/* Data will never be available */
195 				return (-1);
196 
197 			if (lval != 0x424D53FF) /* 0xFF S M B */
198 				return (-1);
199 			break;
200 
201 		case 'b':
202 		case 'c':
203 			cvalp = va_arg(ap, uint8_t *);
204 			if (MBC_ROOM_FOR(mbc, repc) == 0)
205 				/* Data will never be available */
206 				return (-1);
207 
208 			while (repc-- > 0)
209 				*cvalp++ = mbc_marshal_fetch_byte(mbc);
210 			break;
211 
212 		case 'w':
213 			wvalp = va_arg(ap, uint16_t *);
214 			while (repc-- > 0)
215 				if (mbc_marshal_get_short(mbc, wvalp++) != 0)
216 					return (-1);
217 			break;
218 
219 		case 'l':
220 			lvalp = va_arg(ap, uint32_t *);
221 			while (repc-- > 0)
222 				if (mbc_marshal_get_long(mbc, lvalp++) != 0)
223 					return (-1);
224 			break;
225 
226 		case 'q':
227 			llvalp = va_arg(ap, uint64_t *);
228 			while (repc-- > 0)
229 				if (mbc_marshal_get_long_long(
230 				    mbc, llvalp++) != 0)
231 					return (-1);
232 			break;
233 
234 		case 'Q':
235 			llvalp = va_arg(ap, uint64_t *);
236 			while (repc-- > 0)
237 				if (mbc_marshal_get_odd_long_long(
238 				    mbc, llvalp++) != 0)
239 					return (-1);
240 			break;
241 
242 		case 'B':
243 			vdp = va_arg(ap, struct vardata_block *);
244 			vdp->tag = 0;
245 
246 			/*LINTED E_ASSIGN_NARROW_CONV (BYTE)*/
247 			vdp->len = repc;
248 			vdp->uio.uio_iov = &vdp->iovec[0];
249 			vdp->uio.uio_iovcnt = MAX_IOVEC;
250 			vdp->uio.uio_resid = repc;
251 			if (mbc_marshal_get_uio(mbc, &vdp->uio) != 0)
252 				return (-1);
253 			break;
254 
255 		case 'D':
256 		case 'V':
257 			vdp = va_arg(ap, struct vardata_block *);
258 			if (mbc_marshal_get_char(mbc, &vdp->tag) != 0)
259 				return (-1);
260 			if (mbc_marshal_get_short(mbc, &vdp->len) != 0)
261 				return (-1);
262 			vdp->uio.uio_iov = &vdp->iovec[0];
263 			vdp->uio.uio_iovcnt = MAX_IOVEC;
264 			vdp->uio.uio_resid = vdp->len;
265 			if (vdp->len != 0) {
266 				if (mbc_marshal_get_uio(mbc, &vdp->uio) != 0)
267 					return (-1);
268 			}
269 			break;
270 
271 		case 'L':
272 			if (mbc_marshal_get_char(mbc, &cval) != 0)
273 				return (-1);
274 			if (cval != 2)
275 				return (-1);
276 			goto ascii_conversion;
277 
278 		case 'A':
279 		case 'S':
280 			if (mbc_marshal_get_char(mbc, &cval) != 0)
281 				return (-1);
282 			if (((c == 'A' || c == 'S') && cval != 4) ||
283 			    (c == 'L' && cval != 2))
284 				return (-1);
285 			/* FALLTHROUGH */
286 
287 		case 'u': /* Convert from unicode if flags are set */
288 			if (unicode)
289 				goto unicode_translation;
290 			/* FALLTHROUGH */
291 
292 		case 's':
293 ascii_conversion:
294 			ASSERT(sr != NULL);
295 			cvalpp = va_arg(ap, uint8_t **);
296 			if (repc <= 1)
297 				repc = 0;
298 			if (mbc_marshal_get_ascii_string(&sr->request_storage,
299 			    mbc, cvalpp, repc) != 0)
300 				return (-1);
301 			break;
302 
303 		case 'U': /* Convert from unicode */
304 unicode_translation:
305 			ASSERT(sr != 0);
306 			cvalpp = va_arg(ap, uint8_t **);
307 			if (repc <= 1)
308 				repc = 0;
309 			if (mbc->chain_offset & 1)
310 				mbc->chain_offset++;
311 			if (mbc_marshal_get_unicode_string(&sr->request_storage,
312 			    mbc, cvalpp, repc) != 0)
313 				return (-1);
314 			break;
315 
316 		case 'Y': /* dos time to unix time tt/dd */
317 			lvalp = va_arg(ap, uint32_t *);
318 			while (repc-- > 0) {
319 				short	d, t;
320 
321 				if (mbc_marshal_get_short(mbc,
322 				    (uint16_t *)&t) != 0)
323 					return (-1);
324 				if (mbc_marshal_get_short(mbc,
325 				    (uint16_t *)&d) != 0)
326 					return (-1);
327 				*lvalp++ = smb_dos_to_ux_time(d, t);
328 			}
329 			break;
330 
331 		case 'y': /* dos time to unix time dd/tt */
332 			lvalp = va_arg(ap, uint32_t *);
333 			while (repc-- > 0) {
334 				short	d, t;
335 
336 				if (mbc_marshal_get_short(mbc,
337 				    (uint16_t *)&d) != 0)
338 					return (-1);
339 				if (mbc_marshal_get_short(mbc,
340 				    (uint16_t *)&t) != 0)
341 					return (-1);
342 				*lvalp++ = smb_dos_to_ux_time(d, t);
343 			}
344 			break;
345 
346 		case ',':
347 			if (unicode)
348 				repc *= 2;
349 			/* FALLTHROUGH */
350 
351 		case '.':
352 			if (mbc_marshal_get_skip(mbc, repc) != 0)
353 				return (-1);
354 			break;
355 
356 		default:
357 			ASSERT(0);
358 			return (-1);
359 		}
360 	}
361 	return (0);
362 }
363 
364 /*
365  * smb_mbc_decodef
366  *
367  * This function reads the contents of the mbc chain passed in under the
368  * control of the format fmt.
369  *
370  * (for a description of the format string see smb_mbc_vencodef()).
371  */
372 int
373 smb_mbc_decodef(mbuf_chain_t *mbc, char *fmt, ...)
374 {
375 	int	xx;
376 	va_list	ap;
377 
378 	va_start(ap, fmt);
379 	xx = smb_mbc_vdecodef(mbc, fmt, ap);
380 	va_end(ap);
381 	return (xx);
382 }
383 
384 /*
385  * smb_mbc_peek
386  *
387  * This function reads the contents of the mbc passed in at the specified offset
388  * under the control of the format fmt. The offset of the chain passed in is not
389  * modified.
390  *
391  * (for a description of the format string see smb_mbc_vdecodef()).
392  */
393 int
394 smb_mbc_peek(mbuf_chain_t *mbc, int offset, char *fmt, ...)
395 {
396 	mbuf_chain_t	tmp;
397 	va_list		ap;
398 	int		xx;
399 
400 	va_start(ap, fmt);
401 
402 	(void) MBC_SHADOW_CHAIN(&tmp, mbc, offset, mbc->max_bytes - offset);
403 	xx = smb_mbc_vdecodef(&tmp, fmt, ap);
404 	va_end(ap);
405 	return (xx);
406 }
407 
408 /*
409  * smb_mbc_vencodef
410  *
411  * This function builds a stream of bytes in the mbc chain passed in under the
412  * control of the list of arguments passed in.
413  *
414  * The format string provides a description of the parameters passed in as well
415  * as an action to be taken by smb_mbc_vencodef().
416  *
417  *	\b	Restore the mbuf chain offset to its initial value.
418  *
419  *	%	Pointer to an SMB request structure (smb_request_t *). There
420  *		should be only one of these in the string. If an sr in present
421  *		it will be used to determine if unicode conversion should be
422  *		applied to the strings.
423  *
424  *	C	Pointer to an mbuf chain. Copy that mbuf chain into the
425  *		destination mbuf chain.
426  *
427  *	D	Pointer to a vardata_block structure. Copy the data described
428  *		by that structure into the mbuf chain. The tag field is hard
429  *		coded to '1'.
430  *
431  *	M	Write the SMB request signature ('SMBX') into the mbuf chain.
432  *
433  *	T	Pointer to a timestruc_t. Convert the content of the structure
434  *		into NT time and store the result of the conversion in the
435  *		mbuf chain.
436  *
437  *	V	Same as 'D' but the tag field is hard coded to '5'.
438  *
439  *	b	Byte. Store the byte or the nymber of bytes specified into the
440  *		the mbuf chain. A format string like this "2b" would require 2
441  *		bytes to be passed in.
442  *
443  *	m	Pointer to an mbuf. Copy the contents of the mbuf into the mbuf
444  *		chain.
445  *
446  *	c	Pointer to a buffer. Copy the buffer into the mbuf chain. The
447  *		size of the buffer is indicated by the number preceding 'c'.
448  *
449  *	w	Word (16bit value). Store the word or the number of words
450  *              specified into the the mbuf chain. A format string like this
451  *		"2w" would require 2 words to be passed in.
452  *
453  *	l	Long (32bit value). Store the long or the number of longs
454  *		specified into the the mbuf chain. A format string like this
455  *		"2l" would require 2 longs to be passed in.
456  *
457  *	q	Quad (64bit value). Store the quad or the number of quads
458  *		specified into the the mbuf chain. A format string like this
459  *		"2q" would require 2 quads to be passed in.
460  *
461  *	L	Pointer to a string. Store the string passed in into the mbuf
462  *		chain preceded with a tag value of '2'.
463  *
464  *	S	Pointer to a string. Store the string passed in into the mbuf
465  *		chain preceded with a tag value of '4'. Applied a unicode
466  *		conversion is appropriate.
467  *
468  *	A	Same as 'S'
469  *
470  *	P	Pointer to a string. Store the string passed in into the mbuf
471  *		chain preceded with a tag value of '5'. Applied a unicode
472  *		conversion is appropriate.
473  *
474  *	u	Pointer to a string. Store the string passed in into the mbuf
475  *		chain. Applied a unicode conversion is appropriate.
476  *
477  *	s	Pointer to a string. Store the string passed in into the mbuf
478  *		chain.
479  *
480  *	Y	Date/Time.  Store the Date/Time or the number of Date/Time(s)
481  *		specified into the the mbuf chain. A format string like this
482  *		"2Y" would require 2 Date/Time values. The Date/Time is
483  *		converted to DOS before storing.
484  *
485  *	y	Same as 'Y'. The order of Date and Time is reversed.
486  *
487  *	,	Character. Store the character or number of character specified
488  *		into the mbuf chain.  A format string like this "2c" would
489  *		require 2 characters to be passed in. A unicode conversion is
490  *		applied if appropriate.
491  *
492  *	.	Same as '`' without unicode conversion.
493  *
494  *	U	Align the offset of the mbuf chain on a 16bit boundary.
495  *
496  *	Z	Unicode string. Store the unicode string into the mbuf chain
497  *		without alignment considerations.
498  *
499  *	z	Pointer to a string. If appropriate convert to unicode and store
500  *		in mbuf chain without alignment ajustment (same as 'Z'),
501  *		otherwise store in mbuf chain as ascii (same as 's').
502  */
503 int
504 smb_mbc_vencodef(mbuf_chain_t *mbc, char *fmt, va_list ap)
505 {
506 	uint8_t		*cvalp;
507 	timestruc_t	*tvp;
508 	smb_vdb_t	*vdp;
509 	smb_request_t	*sr = NULL;
510 	uint64_t	llval;
511 	int64_t		nt_time;
512 	uint32_t	lval;
513 	uint_t		tag;
514 	int		unicode = 0;
515 	int		repc = 1;
516 	uint16_t	wval;
517 	uint8_t		cval;
518 	uint8_t		c;
519 
520 	while ((c = *fmt++) != 0) {
521 		repc = 1;
522 
523 		if ('0' <= c && c <= '9') {
524 			repc = 0;
525 			do {
526 				repc = repc * 10 + c - '0';
527 				c = *fmt++;
528 			} while ('0' <= c && c <= '9');
529 		} else if (c == '#') {
530 			repc = va_arg(ap, int);
531 			c = *fmt++;
532 		}
533 
534 		switch (c) {
535 		case '%':
536 			sr = va_arg(ap, struct smb_request *);
537 			unicode = sr->smb_flg2 & SMB_FLAGS2_UNICODE;
538 			break;
539 
540 		case 'C':	/* Mbuf_chain */
541 			if (mbc_marshal_put_mbuf_chain(mbc,
542 			    va_arg(ap, mbuf_chain_t *)) != 0)
543 				return (DECODE_NO_MORE_DATA);
544 			break;
545 
546 		case 'D':
547 			vdp = va_arg(ap, struct vardata_block *);
548 
549 			if (mbc_marshal_put_char(mbc, 1) != 0)
550 				return (DECODE_NO_MORE_DATA);
551 			if (mbc_marshal_put_short(mbc, vdp->len) != 0)
552 				return (DECODE_NO_MORE_DATA);
553 			if (mbc_marshal_put_uio(mbc, &vdp->uio) != 0)
554 				return (DECODE_NO_MORE_DATA);
555 			break;
556 
557 		case 'M':
558 			/* 0xFF S M B */
559 			if (mbc_marshal_put_long(mbc, 0x424D53FF))
560 				return (DECODE_NO_MORE_DATA);
561 			break;
562 
563 		case 'T':
564 			tvp = va_arg(ap, timestruc_t *);
565 			nt_time = unix_to_nt_time(tvp);
566 			if (mbc_marshal_put_long_long(mbc, nt_time) != 0)
567 				return (DECODE_NO_MORE_DATA);
568 			break;
569 
570 		case 'V':
571 			vdp = va_arg(ap, struct vardata_block *);
572 
573 			if (mbc_marshal_put_char(mbc, 5) != 0)
574 				return (DECODE_NO_MORE_DATA);
575 			if (mbc_marshal_put_short(mbc, vdp->len) != 0)
576 				return (DECODE_NO_MORE_DATA);
577 			if (mbc_marshal_put_uio(mbc, &vdp->uio) != 0)
578 				return (DECODE_NO_MORE_DATA);
579 			break;
580 
581 		case 'b':
582 			while (repc-- > 0) {
583 				cval = va_arg(ap, int);
584 				if (mbc_marshal_put_char(mbc, cval) != 0)
585 					return (DECODE_NO_MORE_DATA);
586 			}
587 			break;
588 
589 		case 'm':	/* struct_mbuf */
590 			if (mbc_marshal_put_mbufs(mbc,
591 			    va_arg(ap, mbuf_t *)) != 0)
592 				return (DECODE_NO_MORE_DATA);
593 			break;
594 
595 		case 'c':
596 			cvalp = va_arg(ap, uint8_t *);
597 			while (repc-- > 0) {
598 				if (mbc_marshal_put_char(mbc,
599 				    *cvalp++) != 0)
600 					return (DECODE_NO_MORE_DATA);
601 			}
602 			break;
603 
604 		case 'w':
605 			while (repc-- > 0) {
606 				wval = va_arg(ap, int);
607 				if (mbc_marshal_put_short(mbc, wval) != 0)
608 					return (DECODE_NO_MORE_DATA);
609 			}
610 			break;
611 
612 		case 'l':
613 			while (repc-- > 0) {
614 				lval = va_arg(ap, uint32_t);
615 				if (mbc_marshal_put_long(mbc, lval) != 0)
616 					return (DECODE_NO_MORE_DATA);
617 			}
618 			break;
619 
620 		case 'q':
621 			while (repc-- > 0) {
622 				llval = va_arg(ap, uint64_t);
623 				if (mbc_marshal_put_long_long(mbc, llval) != 0)
624 					return (DECODE_NO_MORE_DATA);
625 			}
626 			break;
627 
628 
629 		case 'L':
630 			tag = 2;
631 			goto ascii_conversion;
632 
633 		case 'S':
634 		case 'A':
635 			tag = 4;
636 			goto tagged_str;
637 
638 		case 'P':
639 			tag = 3;
640 			goto tagged_str;
641 
642 		tagged_str:
643 			if (mbc_marshal_put_char(mbc, tag) != 0)
644 				return (DECODE_NO_MORE_DATA);
645 			/* FALLTHROUGH */
646 
647 		case 'u':	/* Convert from unicode if flags are set */
648 			if (unicode)
649 				goto unicode_translation;
650 			/* FALLTHROUGH */
651 
652 		case 's':	/* ASCII/multibyte string */
653 ascii_conversion:	cvalp = va_arg(ap, uint8_t *);
654 			if (mbc_marshal_put_ascii_string(mbc,
655 			    (char *)cvalp, repc) != 0)
656 				return (DECODE_NO_MORE_DATA);
657 			break;
658 
659 		case 'Y':		/* int32_t, encode dos date/time */
660 			while (repc-- > 0) {
661 				uint16_t	d, t;
662 
663 				lval = va_arg(ap, uint32_t);
664 				(void) smb_ux_to_dos_time(lval,
665 				    (short *)&d, (short *)&t);
666 				if (mbc_marshal_put_short(mbc, t) != 0)
667 					return (DECODE_NO_MORE_DATA);
668 				if (mbc_marshal_put_short(mbc, d) != 0)
669 					return (DECODE_NO_MORE_DATA);
670 			}
671 			break;
672 
673 		case 'y':		/* int32_t, encode dos date/time */
674 			while (repc-- > 0) {
675 				uint16_t	d, t;
676 
677 				lval = va_arg(ap, uint32_t);
678 				(void) smb_ux_to_dos_time(lval,
679 				    (short *)&d, (short *)&t);
680 				if (mbc_marshal_put_short(mbc, d) != 0)
681 					return (DECODE_NO_MORE_DATA);
682 				if (mbc_marshal_put_short(mbc, t) != 0)
683 					return (DECODE_NO_MORE_DATA);
684 			}
685 			break;
686 
687 		case ',':
688 			if (unicode)
689 				repc *= 2;
690 			/* FALLTHROUGH */
691 
692 		case '.':
693 			while (repc-- > 0)
694 				if (mbc_marshal_put_char(mbc, 0) != 0)
695 					return (DECODE_NO_MORE_DATA);
696 			break;
697 
698 		case 'U': /* Convert to unicode, align to word boundary */
699 unicode_translation:
700 			if (mbc->chain_offset & 1)
701 				mbc->chain_offset++;
702 			/* FALLTHROUGH */
703 
704 		case 'Z': /* Convert to unicode, no alignment adjustment */
705 			cvalp = va_arg(ap, uint8_t *);
706 			if (mbc_marshal_put_unicode_string(mbc,
707 			    (char *)cvalp, repc) != 0)
708 				return (DECODE_NO_MORE_DATA);
709 			break;
710 
711 		case 'z':
712 			cvalp = va_arg(ap, uint8_t *);
713 			if (unicode) {
714 				if (mbc_marshal_put_unicode_string(mbc,
715 				    (char *)cvalp, repc) != 0)
716 					return (DECODE_NO_MORE_DATA);
717 			} else {
718 				if (mbc_marshal_put_ascii_string(mbc,
719 				    (char *)cvalp, repc) != 0)
720 					return (DECODE_NO_MORE_DATA);
721 			}
722 			break;
723 
724 		default:
725 			ASSERT(0);
726 			return (-1);
727 		}
728 	}
729 	return (0);
730 }
731 
732 /*
733  * smb_mbc_encodef
734  *
735  * This function builds a stream of bytes in the mbc chain passed in under the
736  * control of the format fmt.
737  *
738  * (for a description of the format string see smb_mbc_vencodef()).
739  */
740 int
741 smb_mbc_encodef(mbuf_chain_t *mbc, char *fmt, ...)
742 {
743 	int	rc;
744 	va_list	ap;
745 
746 	va_start(ap, fmt);
747 	rc = smb_mbc_vencodef(mbc, fmt, ap);
748 	va_end(ap);
749 	return (rc);
750 }
751 
752 /*
753  * smb_mbc_poke
754  *
755  * This function writes a stream of bytes in the mbc passed in at the specified
756  * offset under the control of the format fmt. The offset of the chain passed in
757  * is not modified.
758  *
759  * (for a description of the format string see smb_mbc_vencodef()).
760  */
761 int
762 smb_mbc_poke(mbuf_chain_t *mbc, int offset, char *fmt, ...)
763 {
764 	int		xx;
765 	mbuf_chain_t	tmp;
766 	va_list		ap;
767 
768 	(void) MBC_SHADOW_CHAIN(&tmp, mbc, offset, mbc->max_bytes - offset);
769 	va_start(ap, fmt);
770 	xx = smb_mbc_vencodef(&tmp, fmt, ap);
771 	va_end(ap);
772 	return (xx);
773 }
774 
775 /*
776  * Put data into mbuf chain allocating as needed.
777  * Adds room to end of mbuf chain if needed.
778  */
779 static int
780 mbc_marshal_make_room(mbuf_chain_t *mbc, int32_t bytes_needed)
781 {
782 	mbuf_t	*m;
783 	mbuf_t	*l;
784 	int32_t	bytes_available;
785 
786 	bytes_needed += mbc->chain_offset;
787 	if (bytes_needed > mbc->max_bytes)
788 		return (EMSGSIZE);
789 
790 	if ((m = mbc->chain) == 0) {
791 		MGET(m, M_WAIT, MT_DATA);
792 		m->m_len = 0;
793 		if (mbc->max_bytes > MLEN)
794 			MCLGET(m, M_WAIT);
795 		mbc->chain = m;
796 		/* xxxx */
797 		/* ^    */
798 	}
799 
800 	/* ---- ----- --xx ---xxx */
801 	/* ^			  */
802 
803 	l = 0;
804 	while ((m != 0) && (bytes_needed >= m->m_len)) {
805 		l = m;
806 		bytes_needed -= m->m_len;
807 		m = m->m_next;
808 	}
809 
810 	if ((bytes_needed == 0) || (m != 0)) {
811 		/* We have enough room already */
812 		return (0);
813 	}
814 
815 	/* ---- ----- --xx ---xxx */
816 	/*			 ^ */
817 	/* Back up to start of last mbuf */
818 	m = l;
819 	bytes_needed += m->m_len;
820 
821 	/* ---- ----- --xx ---xxx */
822 	/*		   ^	  */
823 
824 	bytes_available = (m->m_flags & M_EXT) ?
825 	    m->m_ext.ext_size : MLEN;
826 
827 	/* ---- ----- --xx ---xxx */
828 	/*		   ^	  */
829 	while ((bytes_needed != 0) && (bytes_needed > bytes_available)) {
830 		m->m_len = bytes_available;
831 		bytes_needed -= m->m_len;
832 		/* ---- ----- --xx ------ */
833 		/*		   ^	  */
834 
835 		MGET(m->m_next, M_WAIT, MT_DATA);
836 		m = m->m_next;
837 		m->m_len = 0;
838 		if (bytes_needed > MLEN)
839 			MCLGET(m, M_WAIT);
840 
841 		bytes_available = (m->m_flags & M_EXT) ?
842 		    m->m_ext.ext_size : MLEN;
843 
844 		/* ---- ----- --xx ------ xxxx */
845 		/*			  ^    */
846 	}
847 
848 	/* ---- ----- --xx ------ xxxx */
849 	/*			  ^    */
850 	/* Expand last tail as needed */
851 	if (m->m_len <= bytes_needed) {
852 		m->m_len = bytes_needed;
853 		/* ---- ----- --xx ------ --xx */
854 		/*			   ^   */
855 	}
856 
857 	return (0);
858 }
859 
860 static void
861 mbc_marshal_store_byte(mbuf_chain_t *mbc, uint8_t data)
862 {
863 	mbuf_t	*m = mbc->chain;
864 	int32_t	cur_offset = mbc->chain_offset;
865 
866 	/*
867 	 * Scan forward looking for the last data currently in chain.
868 	 */
869 	while (cur_offset >= m->m_len) {
870 		cur_offset -= m->m_len;
871 		m = m->m_next;
872 	}
873 	((char *)m->m_data)[cur_offset] = data;
874 	mbc->chain_offset++;
875 }
876 
877 static int
878 mbc_marshal_put_char(mbuf_chain_t *mbc, uint8_t data)
879 {
880 	if (mbc_marshal_make_room(mbc, sizeof (char)) != 0)
881 		return (DECODE_NO_MORE_DATA);
882 	mbc_marshal_store_byte(mbc, data);
883 	return (0);
884 }
885 
886 static int
887 mbc_marshal_put_short(mbuf_chain_t *mbc, uint16_t data)
888 {
889 	if (mbc_marshal_make_room(mbc, sizeof (short)))
890 		return (DECODE_NO_MORE_DATA);
891 	mbc_marshal_store_byte(mbc, data);
892 	mbc_marshal_store_byte(mbc, data >> 8);
893 	return (0);
894 }
895 
896 static int
897 mbc_marshal_put_long(mbuf_chain_t *mbc, uint32_t data)
898 {
899 	if (mbc_marshal_make_room(mbc, sizeof (int32_t)))
900 		return (DECODE_NO_MORE_DATA);
901 	mbc_marshal_store_byte(mbc, data);
902 	mbc_marshal_store_byte(mbc, data >> 8);
903 	mbc_marshal_store_byte(mbc, data >> 16);
904 	mbc_marshal_store_byte(mbc, data >> 24);
905 	return (0);
906 }
907 
908 static int
909 mbc_marshal_put_long_long(mbuf_chain_t *mbc, uint64_t data)
910 {
911 	if (mbc_marshal_make_room(mbc, sizeof (int64_t)))
912 		return (DECODE_NO_MORE_DATA);
913 
914 	mbc_marshal_store_byte(mbc, data);
915 	mbc_marshal_store_byte(mbc, data >> 8);
916 	mbc_marshal_store_byte(mbc, data >> 16);
917 	mbc_marshal_store_byte(mbc, data >> 24);
918 	mbc_marshal_store_byte(mbc, data >> 32);
919 	mbc_marshal_store_byte(mbc, data >> 40);
920 	mbc_marshal_store_byte(mbc, data >> 48);
921 	mbc_marshal_store_byte(mbc, data >> 56);
922 	return (0);
923 }
924 
925 /*
926  * When need to convert from UTF-8 (internal format) to a single
927  * byte string (external format ) when marshalling a string.
928  */
929 static int
930 mbc_marshal_put_ascii_string(mbuf_chain_t *mbc, char *mbs, int repc)
931 {
932 	mts_wchar_t	wide_char;
933 	int		nbytes;
934 	int		length;
935 
936 	if ((length = mts_sbequiv_strlen(mbs)) == -1)
937 		return (DECODE_NO_MORE_DATA);
938 
939 	length += sizeof (char);
940 
941 	if ((repc > 1) && (repc < length))
942 		length = repc;
943 	if (mbc_marshal_make_room(mbc, length))
944 		return (DECODE_NO_MORE_DATA);
945 
946 	while (*mbs) {
947 		/*
948 		 * We should restore oem chars here.
949 		 */
950 		nbytes = mts_mbtowc(&wide_char, mbs, MTS_MB_CHAR_MAX);
951 		if (nbytes == -1)
952 			return (DECODE_NO_MORE_DATA);
953 
954 		mbc_marshal_store_byte(mbc, (uint8_t)wide_char);
955 
956 		if (wide_char & 0xFF00)
957 			mbc_marshal_store_byte(mbc, wide_char >> 8);
958 
959 		mbs += nbytes;
960 	}
961 
962 	mbc_marshal_store_byte(mbc, 0);
963 	return (0);
964 }
965 
966 static int
967 mbc_marshal_put_unicode_string(mbuf_chain_t *mbc, char *ascii, int repc)
968 {
969 	mts_wchar_t	wchar;
970 	int		consumed;
971 	int		length;
972 
973 	if ((length = mts_wcequiv_strlen(ascii)) == -1)
974 		return (DECODE_NO_MORE_DATA);
975 
976 	length += sizeof (mts_wchar_t);
977 
978 	if ((repc > 1) && (repc < length))
979 		length = repc;
980 
981 	if (mbc_marshal_make_room(mbc, length))
982 		return (DECODE_NO_MORE_DATA);
983 	while (length > 0) {
984 		consumed = mts_mbtowc(&wchar, ascii, MTS_MB_CHAR_MAX);
985 		if (consumed == -1)
986 			break;	/* Invalid sequence */
987 		/*
988 		 * Note that consumed will be 0 when the null terminator
989 		 * is encountered and ascii will not be advanced beyond
990 		 * that point. Length will continue to be decremented so
991 		 * we won't get stuck here.
992 		 */
993 		ascii += consumed;
994 		mbc_marshal_store_byte(mbc, wchar);
995 		mbc_marshal_store_byte(mbc, wchar >> 8);
996 		length -= sizeof (mts_wchar_t);
997 	}
998 	return (0);
999 }
1000 
1001 static int
1002 mbc_marshal_put_uio(mbuf_chain_t *mbc, struct uio *uio)
1003 {
1004 	mbuf_t		**t;
1005 	mbuf_t		*m = NULL;
1006 	struct iovec	*iov = uio->uio_iov;
1007 	int32_t		i, iov_cnt = uio->uio_iovcnt;
1008 
1009 	iov = uio->uio_iov;
1010 	t = &mbc->chain;
1011 	for (i = 0; i < iov_cnt; i++) {
1012 		MGET(m, M_WAIT, MT_DATA);
1013 		m->m_ext.ext_buf = iov->iov_base;
1014 		m->m_ext.ext_ref = smb_noop;
1015 		m->m_data = m->m_ext.ext_buf;
1016 		m->m_flags |= M_EXT;
1017 		m->m_len = m->m_ext.ext_size = iov->iov_len;
1018 		mbc->max_bytes += m->m_len;
1019 		m->m_next = 0;
1020 		*t = m;
1021 		t = &m->m_next;
1022 		iov++;
1023 	}
1024 	return (0);
1025 }
1026 
1027 static int
1028 mbc_marshal_put_mbufs(mbuf_chain_t *mbc, mbuf_t *m)
1029 {
1030 	mbuf_t	*mt;
1031 	mbuf_t	**t;
1032 	int	bytes;
1033 
1034 	if (m != NULL) {
1035 		mt = m;
1036 		bytes = mt->m_len;
1037 		while (mt->m_next != 0) {
1038 			mt = mt->m_next;
1039 			bytes += mt->m_len;
1040 		}
1041 		if (bytes != 0) {
1042 			t = &mbc->chain;
1043 			while (*t != 0) {
1044 				bytes += (*t)->m_len;
1045 				t = &(*t)->m_next;
1046 			}
1047 			*t = m;
1048 			mbc->chain_offset = bytes;
1049 		} else {
1050 			m_freem(m);
1051 		}
1052 	}
1053 	return (0);
1054 }
1055 
1056 static int
1057 mbc_marshal_put_mbuf_chain(mbuf_chain_t *mbc, mbuf_chain_t *nmbc)
1058 {
1059 	if (nmbc->chain != 0) {
1060 		if (mbc_marshal_put_mbufs(mbc, nmbc->chain))
1061 			return (DECODE_NO_MORE_DATA);
1062 		MBC_SETUP(nmbc, nmbc->max_bytes);
1063 	}
1064 	return (0);
1065 }
1066 
1067 static uint8_t
1068 mbc_marshal_fetch_byte(mbuf_chain_t *mbc)
1069 {
1070 	uint8_t	data;
1071 	mbuf_t	*m = mbc->chain;
1072 	int32_t	offset = mbc->chain_offset;
1073 
1074 	while (offset >= m->m_len) {
1075 		offset -= m->m_len;
1076 		m = m->m_next;
1077 	}
1078 	data = ((uint8_t *)m->m_data)[offset];
1079 	mbc->chain_offset++;
1080 	return (data);
1081 }
1082 
1083 static int
1084 mbc_marshal_get_char(mbuf_chain_t *mbc, uint8_t *data)
1085 {
1086 	if (MBC_ROOM_FOR(mbc, sizeof (char)) == 0) {
1087 		/* Data will never be available */
1088 		return (DECODE_NO_MORE_DATA);
1089 	}
1090 	*data = mbc_marshal_fetch_byte(mbc);
1091 	return (0);
1092 }
1093 
1094 static int
1095 mbc_marshal_get_short(mbuf_chain_t *mbc, uint16_t *data)
1096 {
1097 	uint16_t	tmp;
1098 	mbuf_t		*m = mbc->chain;
1099 	int32_t		offset = mbc->chain_offset;
1100 
1101 	if (MBC_ROOM_FOR(mbc, sizeof (short)) == 0) {
1102 		/* Data will never be available */
1103 		return (DECODE_NO_MORE_DATA);
1104 	}
1105 
1106 	while (offset >= m->m_len) {
1107 		offset -= m->m_len;
1108 		m = m->m_next;
1109 	}
1110 	if ((m->m_len - offset) >= sizeof (short)) {
1111 		*data = LE_IN16(m->m_data + offset);
1112 		mbc->chain_offset += sizeof (short);
1113 	} else {
1114 		tmp = (uint16_t)mbc_marshal_fetch_byte(mbc);
1115 		tmp |= ((uint16_t)mbc_marshal_fetch_byte(mbc)) << 8;
1116 		*data = tmp;
1117 	}
1118 	return (0);
1119 }
1120 
1121 static int
1122 mbc_marshal_get_long(mbuf_chain_t *mbc, uint32_t *data)
1123 {
1124 	uint32_t	tmp;
1125 	mbuf_t		*m = mbc->chain;
1126 	int32_t		offset = mbc->chain_offset;
1127 
1128 	if (MBC_ROOM_FOR(mbc, sizeof (int32_t)) == 0) {
1129 		/* Data will never be available */
1130 		return (DECODE_NO_MORE_DATA);
1131 	}
1132 	while (offset >= m->m_len) {
1133 		offset -= m->m_len;
1134 		m = m->m_next;
1135 	}
1136 	if ((m->m_len - offset) >= sizeof (int32_t)) {
1137 		*data = LE_IN32(m->m_data + offset);
1138 		mbc->chain_offset += sizeof (int32_t);
1139 	} else {
1140 		tmp = (uint32_t)mbc_marshal_fetch_byte(mbc);
1141 		tmp |= ((uint32_t)mbc_marshal_fetch_byte(mbc)) << 8;
1142 		tmp |= ((uint32_t)mbc_marshal_fetch_byte(mbc)) << 16;
1143 		tmp |= ((uint32_t)mbc_marshal_fetch_byte(mbc)) << 24;
1144 		*data = tmp;
1145 	}
1146 	return (0);
1147 }
1148 
1149 static uint64_t
1150 qswap(uint64_t ll)
1151 {
1152 	uint64_t v;
1153 
1154 	v = ll >> 32;
1155 	v |= ll << 32;
1156 
1157 	return (v);
1158 }
1159 
1160 static int
1161 mbc_marshal_get_odd_long_long(mbuf_chain_t *mbc, uint64_t *data)
1162 {
1163 	uint64_t	tmp;
1164 	mbuf_t		*m = mbc->chain;
1165 	int32_t		offset = mbc->chain_offset;
1166 
1167 	if (MBC_ROOM_FOR(mbc, sizeof (int64_t)) == 0) {
1168 		/* Data will never be available */
1169 		return (DECODE_NO_MORE_DATA);
1170 	}
1171 	while (offset >= m->m_len) {
1172 		offset -= m->m_len;
1173 		m = m->m_next;
1174 	}
1175 
1176 	if ((m->m_len - offset) >= sizeof (int64_t)) {
1177 		*data = qswap(LE_IN64(m->m_data + offset));
1178 		mbc->chain_offset += sizeof (int64_t);
1179 	} else {
1180 		tmp = (uint64_t)mbc_marshal_fetch_byte(mbc) << 32;
1181 		tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 40;
1182 		tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 48;
1183 		tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 56;
1184 		tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc);
1185 		tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 8;
1186 		tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 16;
1187 		tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 24;
1188 
1189 		*(uint64_t *)data = tmp;
1190 	}
1191 	return (0);
1192 }
1193 
1194 static int
1195 mbc_marshal_get_long_long(mbuf_chain_t *mbc, uint64_t *data)
1196 {
1197 	uint64_t	tmp;
1198 	mbuf_t		*m = mbc->chain;
1199 	int32_t		offset = mbc->chain_offset;
1200 
1201 	if (MBC_ROOM_FOR(mbc, sizeof (int64_t)) == 0) {
1202 		/* Data will never be available */
1203 		return (DECODE_NO_MORE_DATA);
1204 	}
1205 	while (offset >= m->m_len) {
1206 		offset -= m->m_len;
1207 		m = m->m_next;
1208 	}
1209 	if ((m->m_len - offset) >= sizeof (int64_t)) {
1210 		*data = LE_IN64(m->m_data + offset);
1211 		mbc->chain_offset += sizeof (int64_t);
1212 	} else {
1213 		tmp = (uint32_t)mbc_marshal_fetch_byte(mbc);
1214 		tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 8;
1215 		tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 16;
1216 		tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 24;
1217 		tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 32;
1218 		tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 40;
1219 		tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 48;
1220 		tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 56;
1221 		*(uint64_t *)data = tmp;
1222 	}
1223 	return (0);
1224 }
1225 
1226 /*
1227  * mbc_marshal_get_ascii_string
1228  *
1229  * The ascii string in smb includes oem chars. Since the
1230  * system needs utf8 encodes unicode char, conversion is
1231  * required to convert the oem char to unicode and then
1232  * to encode the converted wchars to utf8 format.
1233  * Therefore, the **ascii returned will be in such format
1234  * instead of the real ASCII format.
1235  */
1236 static int
1237 mbc_marshal_get_ascii_string(
1238     struct smb_malloc_list	*ml,
1239     mbuf_chain_t		*mbc,
1240     uint8_t		**ascii,
1241     int				max_ascii)
1242 {
1243 	char		*rcvbuf;
1244 	char		*ch;
1245 	mts_wchar_t	*wtmpbuf;
1246 	int		max;
1247 	int		length = 0;
1248 	uint_t	cpid = oem_get_smb_cpid();
1249 
1250 	max = MALLOC_QUANTUM;
1251 	rcvbuf = smbsr_malloc(ml, max);
1252 
1253 	if (max_ascii == 0)
1254 		max_ascii = 0xffff;
1255 
1256 	ch = rcvbuf;
1257 	for (;;) {
1258 		while (length < max) {
1259 			if (max_ascii-- <= 0) {
1260 				*ch++ = 0;
1261 				goto multibyte_encode;
1262 			}
1263 			if (MBC_ROOM_FOR(mbc, sizeof (char)) == 0) {
1264 				/* Data will never be available */
1265 				return (DECODE_NO_MORE_DATA);
1266 			}
1267 			if ((*ch++ = mbc_marshal_fetch_byte(mbc)) == 0)
1268 				goto multibyte_encode;
1269 			length++;
1270 		}
1271 		max += MALLOC_QUANTUM;
1272 		rcvbuf = smbsr_realloc(rcvbuf, max);
1273 		ch = rcvbuf + length;
1274 	}
1275 
1276 multibyte_encode:
1277 	/*
1278 	 * UTF-8 encode the string for internal system use.
1279 	 */
1280 	length = strlen(rcvbuf) + 1;
1281 	wtmpbuf = smbsr_malloc(ml, length*sizeof (mts_wchar_t));
1282 	*ascii = smbsr_malloc(ml, length * MTS_MB_CHAR_MAX);
1283 
1284 	if (oemstounicodes(wtmpbuf, rcvbuf, length, cpid) > 0)
1285 		(void) mts_wcstombs((char *)*ascii, wtmpbuf,
1286 		    length * MTS_MB_CHAR_MAX);
1287 	else
1288 		(void) mts_stombs((char *)*ascii, rcvbuf, length * 2);
1289 	return (0);
1290 }
1291 
1292 static int
1293 mbc_marshal_get_unicode_string(struct smb_malloc_list *ml,
1294     mbuf_chain_t *mbc, uint8_t **ascii, int max_unicode)
1295 {
1296 	int		max;
1297 	uint16_t	wchar;
1298 	char		*ch;
1299 	int		emitted;
1300 	int		length = 0;
1301 
1302 	if (max_unicode == 0)
1303 		max_unicode = 0xffff;
1304 
1305 	max = MALLOC_QUANTUM;
1306 	*ascii = smbsr_malloc(ml, max);
1307 
1308 	ch = (char *)*ascii;
1309 	for (;;) {
1310 		while ((length + MTS_MB_CHAR_MAX) < max) {
1311 			if (max_unicode <= 0)
1312 				goto done;
1313 			max_unicode -= 2;
1314 
1315 			if (mbc_marshal_get_short(mbc, &wchar) != 0)
1316 				return (DECODE_NO_MORE_DATA);
1317 
1318 			if (wchar == 0)	goto done;
1319 
1320 			emitted = mts_wctomb(ch, wchar);
1321 			length += emitted;
1322 			ch += emitted;
1323 		}
1324 		max += MALLOC_QUANTUM;
1325 		*ascii = smbsr_realloc(*ascii, max);
1326 		ch = (char *)*ascii + length;
1327 	}
1328 done:	*ch = 0;
1329 	return (0);
1330 }
1331 
1332 static int /*ARGSUSED*/
1333 mbc_marshal_get_mbufs(mbuf_chain_t *mbc, int32_t bytes, mbuf_t **m)
1334 {
1335 	if (MBC_ROOM_FOR(mbc, bytes) == 0) {
1336 		/* Data will never be available */
1337 		return (DECODE_NO_MORE_DATA);
1338 	}
1339 	return (0);
1340 }
1341 
1342 static int
1343 mbc_marshal_get_mbuf_chain(mbuf_chain_t *mbc, int32_t bytes, mbuf_chain_t *nmbc)
1344 {
1345 	int	rc;
1346 	mbuf_t	*m;
1347 
1348 	if (bytes == 0) {
1349 		/* Get all the rest */
1350 		bytes = mbc->max_bytes - mbc->chain_offset;
1351 	}
1352 
1353 	MBC_SETUP(nmbc, mbc->max_bytes);
1354 	if ((rc = mbc_marshal_get_mbufs(mbc, bytes, &m)) != 0) {
1355 		if (m)
1356 			m_freem(m);
1357 		return (rc);
1358 	}
1359 	nmbc->chain = m;
1360 	while (m != 0) {
1361 		bytes += m->m_len;
1362 		m = m->m_next;
1363 	}
1364 	nmbc->max_bytes = bytes;
1365 	return (0);
1366 }
1367 
1368 static int
1369 mbc_marshal_get_uio(mbuf_chain_t *mbc, struct uio *uio)
1370 {
1371 	int		i, offset;
1372 	int32_t		bytes = uio->uio_resid;
1373 	int32_t		remainder;
1374 	struct iovec	*iov;
1375 	mbuf_t		*m;
1376 
1377 	/*
1378 	 * The residual count is tested because in the case of write requests
1379 	 * with no data (smbtorture RAW-WRITE test will generate that type of
1380 	 * request) this function is called with a residual count of zero
1381 	 * bytes.
1382 	 */
1383 	if (bytes) {
1384 		iov = uio->uio_iov;
1385 		uio->uio_segflg = UIO_SYSSPACE;
1386 
1387 		if (MBC_ROOM_FOR(mbc, bytes) == 0) {
1388 			/* Data will never be available */
1389 			return (DECODE_NO_MORE_DATA);
1390 		}
1391 
1392 		m = mbc->chain;
1393 		offset = mbc->chain_offset;
1394 		while (offset >= m->m_len) {
1395 			offset -= m->m_len;
1396 			m = m->m_next;
1397 			ASSERT((offset == 0) || (offset && m));
1398 		}
1399 
1400 		for (i = 0; (bytes > 0) && (i < uio->uio_iovcnt); i++) {
1401 			iov[i].iov_base = &m->m_data[offset];
1402 			remainder = m->m_len - offset;
1403 			if (remainder >= bytes) {
1404 				iov[i].iov_len = bytes;
1405 				mbc->chain_offset += bytes;
1406 				break;
1407 			}
1408 			iov[i].iov_len = remainder;
1409 			mbc->chain_offset += remainder;
1410 			bytes -= remainder;
1411 			m = m->m_next;
1412 			offset = 0;
1413 		}
1414 		if (i == uio->uio_iovcnt) {
1415 			return (DECODE_NO_MORE_DATA);
1416 		}
1417 		uio->uio_iovcnt = i;
1418 	}
1419 	return (0);
1420 }
1421 
1422 static int
1423 mbc_marshal_get_skip(mbuf_chain_t *mbc, uint_t skip)
1424 {
1425 	if (MBC_ROOM_FOR(mbc, skip) == 0)
1426 		return (DECODE_NO_MORE_DATA);
1427 	mbc->chain_offset += skip;
1428 	return (0);
1429 }
1430