xref: /illumos-gate/usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c (revision 24b9abbad58fdd63dad716fd35a99a7944c4e3eb)
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	"%Z%%M%	%I%	%E% 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++ = dosfs_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++ = dosfs_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 int
500 smb_mbc_vencodef(mbuf_chain_t *mbc, char *fmt, va_list ap)
501 {
502 	uint8_t		*cvalp;
503 	timestruc_t	*tvp;
504 	smb_vdb_t	*vdp;
505 	smb_request_t	*sr = NULL;
506 	uint64_t	llval;
507 	int64_t		nt_time;
508 	uint32_t	lval;
509 	uint_t		tag;
510 	int		unicode = 0;
511 	int		repc = 1;
512 	uint16_t	wval;
513 	uint8_t		cval;
514 	uint8_t		c;
515 
516 	while ((c = *fmt++) != 0) {
517 		repc = 1;
518 
519 		if ('0' <= c && c <= '9') {
520 			repc = 0;
521 			do {
522 				repc = repc * 10 + c - '0';
523 				c = *fmt++;
524 			} while ('0' <= c && c <= '9');
525 		} else if (c == '#') {
526 			repc = va_arg(ap, int);
527 			c = *fmt++;
528 		}
529 
530 		switch (c) {
531 		case '%':
532 			sr = va_arg(ap, struct smb_request *);
533 			unicode = sr->smb_flg2 & SMB_FLAGS2_UNICODE;
534 			break;
535 
536 		case 'C':	/* Mbuf_chain */
537 			if (mbc_marshal_put_mbuf_chain(mbc,
538 			    va_arg(ap, mbuf_chain_t *)) != 0)
539 				return (DECODE_NO_MORE_DATA);
540 			break;
541 
542 		case 'D':
543 			vdp = va_arg(ap, struct vardata_block *);
544 
545 			if (mbc_marshal_put_char(mbc, 1) != 0)
546 				return (DECODE_NO_MORE_DATA);
547 			if (mbc_marshal_put_short(mbc, vdp->len) != 0)
548 				return (DECODE_NO_MORE_DATA);
549 			if (mbc_marshal_put_uio(mbc, &vdp->uio) != 0)
550 				return (DECODE_NO_MORE_DATA);
551 			break;
552 
553 		case 'M':
554 			/* 0xFF S M B */
555 			if (mbc_marshal_put_long(mbc, 0x424D53FF))
556 				return (DECODE_NO_MORE_DATA);
557 			break;
558 
559 		case 'T':
560 			tvp = va_arg(ap, timestruc_t *);
561 			nt_time = unix_to_nt_time(tvp);
562 			if (mbc_marshal_put_long_long(mbc, nt_time) != 0)
563 				return (DECODE_NO_MORE_DATA);
564 			break;
565 
566 		case 'V':
567 			vdp = va_arg(ap, struct vardata_block *);
568 
569 			if (mbc_marshal_put_char(mbc, 5) != 0)
570 				return (DECODE_NO_MORE_DATA);
571 			if (mbc_marshal_put_short(mbc, vdp->len) != 0)
572 				return (DECODE_NO_MORE_DATA);
573 			if (mbc_marshal_put_uio(mbc, &vdp->uio) != 0)
574 				return (DECODE_NO_MORE_DATA);
575 			break;
576 
577 		case 'b':
578 			while (repc-- > 0) {
579 				cval = va_arg(ap, int);
580 				if (mbc_marshal_put_char(mbc, cval) != 0)
581 					return (DECODE_NO_MORE_DATA);
582 			}
583 			break;
584 
585 		case 'm':	/* struct_mbuf */
586 			if (mbc_marshal_put_mbufs(mbc,
587 			    va_arg(ap, mbuf_t *)) != 0)
588 				return (DECODE_NO_MORE_DATA);
589 			break;
590 
591 		case 'c':
592 			cvalp = va_arg(ap, uint8_t *);
593 			while (repc-- > 0) {
594 				if (mbc_marshal_put_char(mbc,
595 				    *cvalp++) != 0)
596 					return (DECODE_NO_MORE_DATA);
597 			}
598 			break;
599 
600 		case 'w':
601 			while (repc-- > 0) {
602 				wval = va_arg(ap, int);
603 				if (mbc_marshal_put_short(mbc, wval) != 0)
604 					return (DECODE_NO_MORE_DATA);
605 			}
606 			break;
607 
608 		case 'l':
609 			while (repc-- > 0) {
610 				lval = va_arg(ap, uint32_t);
611 				if (mbc_marshal_put_long(mbc, lval) != 0)
612 					return (DECODE_NO_MORE_DATA);
613 			}
614 			break;
615 
616 		case 'q':
617 			while (repc-- > 0) {
618 				llval = va_arg(ap, uint64_t);
619 				if (mbc_marshal_put_long_long(mbc, llval) != 0)
620 					return (DECODE_NO_MORE_DATA);
621 			}
622 			break;
623 
624 
625 		case 'L':
626 			tag = 2;
627 			goto ascii_conversion;
628 
629 		case 'S':
630 		case 'A':
631 			tag = 4;
632 			goto tagged_str;
633 
634 		case 'P':
635 			tag = 3;
636 			goto tagged_str;
637 
638 		tagged_str:
639 			if (mbc_marshal_put_char(mbc, tag) != 0)
640 				return (DECODE_NO_MORE_DATA);
641 			/* FALLTHROUGH */
642 
643 		case 'u':	/* Convert from unicode if flags are set */
644 			if (unicode)
645 				goto unicode_translation;
646 			/* FALLTHROUGH */
647 
648 		case 's':	/* ASCII/multibyte string */
649 ascii_conversion:	cvalp = va_arg(ap, uint8_t *);
650 			if (mbc_marshal_put_ascii_string(mbc,
651 			    (char *)cvalp, repc) != 0)
652 				return (DECODE_NO_MORE_DATA);
653 			break;
654 
655 		case 'Y':		/* int32_t, encode dos date/time */
656 			while (repc-- > 0) {
657 				uint16_t	d, t;
658 
659 				lval = va_arg(ap, uint32_t);
660 				(void) dosfs_ux_to_dos_time(lval,
661 				    (short *)&d, (short *)&t);
662 				if (mbc_marshal_put_short(mbc, t) != 0)
663 					return (DECODE_NO_MORE_DATA);
664 				if (mbc_marshal_put_short(mbc, d) != 0)
665 					return (DECODE_NO_MORE_DATA);
666 			}
667 			break;
668 
669 		case 'y':		/* int32_t, encode dos date/time */
670 			while (repc-- > 0) {
671 				uint16_t	d, t;
672 
673 				lval = va_arg(ap, uint32_t);
674 				(void) dosfs_ux_to_dos_time(lval,
675 				    (short *)&d, (short *)&t);
676 				if (mbc_marshal_put_short(mbc, d) != 0)
677 					return (DECODE_NO_MORE_DATA);
678 				if (mbc_marshal_put_short(mbc, t) != 0)
679 					return (DECODE_NO_MORE_DATA);
680 			}
681 			break;
682 
683 		case ',':
684 			if (unicode)
685 				repc *= 2;
686 			/* FALLTHROUGH */
687 
688 		case '.':
689 			while (repc-- > 0)
690 				if (mbc_marshal_put_char(mbc, 0) != 0)
691 					return (DECODE_NO_MORE_DATA);
692 			break;
693 
694 		case 'U': /* Convert to unicode, align to word boundary */
695 unicode_translation:
696 			if (mbc->chain_offset & 1)
697 				mbc->chain_offset++;
698 			/* FALLTHROUGH */
699 
700 		case 'Z': /* Convert to unicode, no alignment adjustment */
701 			cvalp = va_arg(ap, uint8_t *);
702 			if (mbc_marshal_put_unicode_string(mbc,
703 			    (char *)cvalp, repc) != 0)
704 				return (DECODE_NO_MORE_DATA);
705 			break;
706 
707 		default:
708 			ASSERT(0);
709 			return (-1);
710 		}
711 	}
712 	return (0);
713 }
714 
715 /*
716  * smb_mbc_encodef
717  *
718  * This function builds a stream of bytes in the mbc chain passed in under the
719  * control of the format fmt.
720  *
721  * (for a description of the format string see smb_mbc_vencodef()).
722  */
723 int
724 smb_mbc_encodef(mbuf_chain_t *mbc, char *fmt, ...)
725 {
726 	int	rc;
727 	va_list	ap;
728 
729 	va_start(ap, fmt);
730 	rc = smb_mbc_vencodef(mbc, fmt, ap);
731 	va_end(ap);
732 	return (rc);
733 }
734 
735 /*
736  * smb_mbc_poke
737  *
738  * This function writes a stream of bytes in the mbc passed in at the specified
739  * offset under the control of the format fmt. The offset of the chain passed in
740  * is not modified.
741  *
742  * (for a description of the format string see smb_mbc_vencodef()).
743  */
744 int
745 smb_mbc_poke(mbuf_chain_t *mbc, int offset, char *fmt, ...)
746 {
747 	int		xx;
748 	mbuf_chain_t	tmp;
749 	va_list		ap;
750 
751 	(void) MBC_SHADOW_CHAIN(&tmp, mbc, offset, mbc->max_bytes - offset);
752 	va_start(ap, fmt);
753 	xx = smb_mbc_vencodef(&tmp, fmt, ap);
754 	va_end(ap);
755 	return (xx);
756 }
757 
758 /*
759  * Put data into mbuf chain allocating as needed.
760  * Adds room to end of mbuf chain if needed.
761  */
762 static int
763 mbc_marshal_make_room(mbuf_chain_t *mbc, int32_t bytes_needed)
764 {
765 	mbuf_t	*m;
766 	mbuf_t	*l;
767 	int32_t	bytes_available;
768 
769 	bytes_needed += mbc->chain_offset;
770 	if (bytes_needed > mbc->max_bytes)
771 		return (EMSGSIZE);
772 
773 	if ((m = mbc->chain) == 0) {
774 		MGET(m, M_WAIT, MT_DATA);
775 		m->m_len = 0;
776 		if (mbc->max_bytes > MLEN)
777 			MCLGET(m, M_WAIT);
778 		mbc->chain = m;
779 		/* xxxx */
780 		/* ^    */
781 	}
782 
783 	/* ---- ----- --xx ---xxx */
784 	/* ^			  */
785 
786 	l = 0;
787 	while ((m != 0) && (bytes_needed >= m->m_len)) {
788 		l = m;
789 		bytes_needed -= m->m_len;
790 		m = m->m_next;
791 	}
792 
793 	if ((bytes_needed == 0) || (m != 0)) {
794 		/* We have enough room already */
795 		return (0);
796 	}
797 
798 	/* ---- ----- --xx ---xxx */
799 	/*			 ^ */
800 	/* Back up to start of last mbuf */
801 	m = l;
802 	bytes_needed += m->m_len;
803 
804 	/* ---- ----- --xx ---xxx */
805 	/*		   ^	  */
806 
807 	bytes_available = (m->m_flags & M_EXT) ?
808 	    m->m_ext.ext_size : MLEN;
809 
810 	/* ---- ----- --xx ---xxx */
811 	/*		   ^	  */
812 	while ((bytes_needed != 0) && (bytes_needed > bytes_available)) {
813 		m->m_len = bytes_available;
814 		bytes_needed -= m->m_len;
815 		/* ---- ----- --xx ------ */
816 		/*		   ^	  */
817 
818 		MGET(m->m_next, M_WAIT, MT_DATA);
819 		m = m->m_next;
820 		m->m_len = 0;
821 		if (bytes_needed > MLEN)
822 			MCLGET(m, M_WAIT);
823 
824 		bytes_available = (m->m_flags & M_EXT) ?
825 		    m->m_ext.ext_size : MLEN;
826 
827 		/* ---- ----- --xx ------ xxxx */
828 		/*			  ^    */
829 	}
830 
831 	/* ---- ----- --xx ------ xxxx */
832 	/*			  ^    */
833 	/* Expand last tail as needed */
834 	if (m->m_len <= bytes_needed) {
835 		m->m_len = bytes_needed;
836 		/* ---- ----- --xx ------ --xx */
837 		/*			   ^   */
838 	}
839 
840 	return (0);
841 }
842 
843 static void
844 mbc_marshal_store_byte(mbuf_chain_t *mbc, uint8_t data)
845 {
846 	mbuf_t	*m = mbc->chain;
847 	int32_t	cur_offset = mbc->chain_offset;
848 
849 	/*
850 	 * Scan forward looking for the last data currently in chain.
851 	 */
852 	while (cur_offset >= m->m_len) {
853 		cur_offset -= m->m_len;
854 		m = m->m_next;
855 	}
856 	((char *)m->m_data)[cur_offset] = data;
857 	mbc->chain_offset++;
858 }
859 
860 static int
861 mbc_marshal_put_char(mbuf_chain_t *mbc, uint8_t data)
862 {
863 	if (mbc_marshal_make_room(mbc, sizeof (char)) != 0)
864 		return (DECODE_NO_MORE_DATA);
865 	mbc_marshal_store_byte(mbc, data);
866 	return (0);
867 }
868 
869 static int
870 mbc_marshal_put_short(mbuf_chain_t *mbc, uint16_t data)
871 {
872 	if (mbc_marshal_make_room(mbc, sizeof (short)))
873 		return (DECODE_NO_MORE_DATA);
874 	mbc_marshal_store_byte(mbc, data);
875 	mbc_marshal_store_byte(mbc, data >> 8);
876 	return (0);
877 }
878 
879 static int
880 mbc_marshal_put_long(mbuf_chain_t *mbc, uint32_t data)
881 {
882 	if (mbc_marshal_make_room(mbc, sizeof (int32_t)))
883 		return (DECODE_NO_MORE_DATA);
884 	mbc_marshal_store_byte(mbc, data);
885 	mbc_marshal_store_byte(mbc, data >> 8);
886 	mbc_marshal_store_byte(mbc, data >> 16);
887 	mbc_marshal_store_byte(mbc, data >> 24);
888 	return (0);
889 }
890 
891 static int
892 mbc_marshal_put_long_long(mbuf_chain_t *mbc, uint64_t data)
893 {
894 	if (mbc_marshal_make_room(mbc, sizeof (int64_t)))
895 		return (DECODE_NO_MORE_DATA);
896 
897 	mbc_marshal_store_byte(mbc, data);
898 	mbc_marshal_store_byte(mbc, data >> 8);
899 	mbc_marshal_store_byte(mbc, data >> 16);
900 	mbc_marshal_store_byte(mbc, data >> 24);
901 	mbc_marshal_store_byte(mbc, data >> 32);
902 	mbc_marshal_store_byte(mbc, data >> 40);
903 	mbc_marshal_store_byte(mbc, data >> 48);
904 	mbc_marshal_store_byte(mbc, data >> 56);
905 	return (0);
906 }
907 
908 /*
909  * When need to convert from UTF-8 (internal format) to a single
910  * byte string (external format ) when marshalling a string.
911  */
912 static int
913 mbc_marshal_put_ascii_string(mbuf_chain_t *mbc, char *mbs, int repc)
914 {
915 	mts_wchar_t	wide_char;
916 	int		nbytes;
917 	int		length;
918 
919 	if ((length = mts_sbequiv_strlen(mbs)) == -1)
920 		return (DECODE_NO_MORE_DATA);
921 
922 	length += sizeof (char);
923 
924 	if ((repc > 1) && (repc < length))
925 		length = repc;
926 	if (mbc_marshal_make_room(mbc, length))
927 		return (DECODE_NO_MORE_DATA);
928 
929 	while (*mbs) {
930 		/*
931 		 * We should restore oem chars here.
932 		 */
933 		nbytes = mts_mbtowc(&wide_char, mbs, MTS_MB_CHAR_MAX);
934 		if (nbytes == -1)
935 			return (DECODE_NO_MORE_DATA);
936 
937 		mbc_marshal_store_byte(mbc, (uint8_t)wide_char);
938 
939 		if (wide_char & 0xFF00)
940 			mbc_marshal_store_byte(mbc, wide_char >> 8);
941 
942 		mbs += nbytes;
943 	}
944 
945 	mbc_marshal_store_byte(mbc, 0);
946 	return (0);
947 }
948 
949 static int
950 mbc_marshal_put_unicode_string(mbuf_chain_t *mbc, char *ascii, int repc)
951 {
952 	mts_wchar_t	wchar;
953 	int		consumed;
954 	int		length;
955 
956 	if ((length = mts_wcequiv_strlen(ascii)) == -1)
957 		return (DECODE_NO_MORE_DATA);
958 
959 	length += sizeof (mts_wchar_t);
960 
961 	if ((repc > 1) && (repc < length))
962 		length = repc;
963 
964 	if (mbc_marshal_make_room(mbc, length))
965 		return (DECODE_NO_MORE_DATA);
966 	while (length > 0) {
967 		consumed = mts_mbtowc(&wchar, ascii, MTS_MB_CHAR_MAX);
968 		if (consumed == -1)
969 			break;	/* Invalid sequence */
970 		/*
971 		 * Note that consumed will be 0 when the null terminator
972 		 * is encountered and ascii will not be advanced beyond
973 		 * that point. Length will continue to be decremented so
974 		 * we won't get stuck here.
975 		 */
976 		ascii += consumed;
977 		mbc_marshal_store_byte(mbc, wchar);
978 		mbc_marshal_store_byte(mbc, wchar >> 8);
979 		length -= sizeof (mts_wchar_t);
980 	}
981 	return (0);
982 }
983 
984 static int
985 mbc_marshal_put_uio(mbuf_chain_t *mbc, struct uio *uio)
986 {
987 	mbuf_t		**t;
988 	mbuf_t		*m = NULL;
989 	struct iovec	*iov = uio->uio_iov;
990 	int32_t		i, iov_cnt = uio->uio_iovcnt;
991 
992 	iov = uio->uio_iov;
993 	t = &mbc->chain;
994 	for (i = 0; i < iov_cnt; i++) {
995 		MGET(m, M_WAIT, MT_DATA);
996 		m->m_ext.ext_buf = iov->iov_base;
997 		m->m_ext.ext_ref = smb_noop;
998 		m->m_data = m->m_ext.ext_buf;
999 		m->m_flags |= M_EXT;
1000 		m->m_len = m->m_ext.ext_size = iov->iov_len;
1001 		mbc->max_bytes += m->m_len;
1002 		m->m_next = 0;
1003 		*t = m;
1004 		t = &m->m_next;
1005 		iov++;
1006 	}
1007 	return (0);
1008 }
1009 
1010 static int
1011 mbc_marshal_put_mbufs(mbuf_chain_t *mbc, mbuf_t *m)
1012 {
1013 	mbuf_t	*mt;
1014 	mbuf_t	**t;
1015 	int	bytes;
1016 
1017 	if (m != NULL) {
1018 		mt = m;
1019 		bytes = mt->m_len;
1020 		while (mt->m_next != 0) {
1021 			mt = mt->m_next;
1022 			bytes += mt->m_len;
1023 		}
1024 		if (bytes != 0) {
1025 			t = &mbc->chain;
1026 			while (*t != 0) {
1027 				bytes += (*t)->m_len;
1028 				t = &(*t)->m_next;
1029 			}
1030 			*t = m;
1031 			mbc->chain_offset = bytes;
1032 		} else {
1033 			m_freem(m);
1034 		}
1035 	}
1036 	return (0);
1037 }
1038 
1039 static int
1040 mbc_marshal_put_mbuf_chain(mbuf_chain_t *mbc, mbuf_chain_t *nmbc)
1041 {
1042 	if (nmbc->chain != 0) {
1043 		if (mbc_marshal_put_mbufs(mbc, nmbc->chain))
1044 			return (DECODE_NO_MORE_DATA);
1045 		MBC_SETUP(nmbc, nmbc->max_bytes);
1046 	}
1047 	return (0);
1048 }
1049 
1050 static uint8_t
1051 mbc_marshal_fetch_byte(mbuf_chain_t *mbc)
1052 {
1053 	uint8_t	data;
1054 	mbuf_t	*m = mbc->chain;
1055 	int32_t	offset = mbc->chain_offset;
1056 
1057 	while (offset >= m->m_len) {
1058 		offset -= m->m_len;
1059 		m = m->m_next;
1060 	}
1061 	data = ((uint8_t *)m->m_data)[offset];
1062 	mbc->chain_offset++;
1063 	return (data);
1064 }
1065 
1066 static int
1067 mbc_marshal_get_char(mbuf_chain_t *mbc, uint8_t *data)
1068 {
1069 	if (MBC_ROOM_FOR(mbc, sizeof (char)) == 0) {
1070 		/* Data will never be available */
1071 		return (DECODE_NO_MORE_DATA);
1072 	}
1073 	*data = mbc_marshal_fetch_byte(mbc);
1074 	return (0);
1075 }
1076 
1077 static int
1078 mbc_marshal_get_short(mbuf_chain_t *mbc, uint16_t *data)
1079 {
1080 	uint16_t	tmp;
1081 	mbuf_t		*m = mbc->chain;
1082 	int32_t		offset = mbc->chain_offset;
1083 
1084 	if (MBC_ROOM_FOR(mbc, sizeof (short)) == 0) {
1085 		/* Data will never be available */
1086 		return (DECODE_NO_MORE_DATA);
1087 	}
1088 
1089 	while (offset >= m->m_len) {
1090 		offset -= m->m_len;
1091 		m = m->m_next;
1092 	}
1093 	if ((m->m_len - offset) >= sizeof (short)) {
1094 		*data = LE_IN16(m->m_data + offset);
1095 		mbc->chain_offset += sizeof (short);
1096 	} else {
1097 		tmp = (uint16_t)mbc_marshal_fetch_byte(mbc);
1098 		tmp |= ((uint16_t)mbc_marshal_fetch_byte(mbc)) << 8;
1099 		*data = tmp;
1100 	}
1101 	return (0);
1102 }
1103 
1104 static int
1105 mbc_marshal_get_long(mbuf_chain_t *mbc, uint32_t *data)
1106 {
1107 	uint32_t	tmp;
1108 	mbuf_t		*m = mbc->chain;
1109 	int32_t		offset = mbc->chain_offset;
1110 
1111 	if (MBC_ROOM_FOR(mbc, sizeof (int32_t)) == 0) {
1112 		/* Data will never be available */
1113 		return (DECODE_NO_MORE_DATA);
1114 	}
1115 	while (offset >= m->m_len) {
1116 		offset -= m->m_len;
1117 		m = m->m_next;
1118 	}
1119 	if ((m->m_len - offset) >= sizeof (int32_t)) {
1120 		*data = LE_IN32(m->m_data + offset);
1121 		mbc->chain_offset += sizeof (int32_t);
1122 	} else {
1123 		tmp = (uint32_t)mbc_marshal_fetch_byte(mbc);
1124 		tmp |= ((uint32_t)mbc_marshal_fetch_byte(mbc)) << 8;
1125 		tmp |= ((uint32_t)mbc_marshal_fetch_byte(mbc)) << 16;
1126 		tmp |= ((uint32_t)mbc_marshal_fetch_byte(mbc)) << 24;
1127 		*data = tmp;
1128 	}
1129 	return (0);
1130 }
1131 
1132 static uint64_t
1133 qswap(uint64_t ll)
1134 {
1135 	uint64_t v;
1136 
1137 	v = ll >> 32;
1138 	v |= ll << 32;
1139 
1140 	return (v);
1141 }
1142 
1143 static int
1144 mbc_marshal_get_odd_long_long(mbuf_chain_t *mbc, uint64_t *data)
1145 {
1146 	uint64_t	tmp;
1147 	mbuf_t		*m = mbc->chain;
1148 	int32_t		offset = mbc->chain_offset;
1149 
1150 	if (MBC_ROOM_FOR(mbc, sizeof (int64_t)) == 0) {
1151 		/* Data will never be available */
1152 		return (DECODE_NO_MORE_DATA);
1153 	}
1154 	while (offset >= m->m_len) {
1155 		offset -= m->m_len;
1156 		m = m->m_next;
1157 	}
1158 
1159 	if ((m->m_len - offset) >= sizeof (int64_t)) {
1160 		*data = qswap(LE_IN64(m->m_data + offset));
1161 		mbc->chain_offset += sizeof (int64_t);
1162 	} else {
1163 		tmp = (uint64_t)mbc_marshal_fetch_byte(mbc) << 32;
1164 		tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 40;
1165 		tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 48;
1166 		tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 56;
1167 		tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc);
1168 		tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 8;
1169 		tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 16;
1170 		tmp |= (uint64_t)mbc_marshal_fetch_byte(mbc) << 24;
1171 
1172 		*(uint64_t *)data = tmp;
1173 	}
1174 	return (0);
1175 }
1176 
1177 static int
1178 mbc_marshal_get_long_long(mbuf_chain_t *mbc, uint64_t *data)
1179 {
1180 	uint64_t	tmp;
1181 	mbuf_t		*m = mbc->chain;
1182 	int32_t		offset = mbc->chain_offset;
1183 
1184 	if (MBC_ROOM_FOR(mbc, sizeof (int64_t)) == 0) {
1185 		/* Data will never be available */
1186 		return (DECODE_NO_MORE_DATA);
1187 	}
1188 	while (offset >= m->m_len) {
1189 		offset -= m->m_len;
1190 		m = m->m_next;
1191 	}
1192 	if ((m->m_len - offset) >= sizeof (int64_t)) {
1193 		*data = LE_IN64(m->m_data + offset);
1194 		mbc->chain_offset += sizeof (int64_t);
1195 	} else {
1196 		tmp = (uint32_t)mbc_marshal_fetch_byte(mbc);
1197 		tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 8;
1198 		tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 16;
1199 		tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 24;
1200 		tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 32;
1201 		tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 40;
1202 		tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 48;
1203 		tmp |= ((uint64_t)mbc_marshal_fetch_byte(mbc)) << 56;
1204 		*(uint64_t *)data = tmp;
1205 	}
1206 	return (0);
1207 }
1208 
1209 /*
1210  * mbc_marshal_get_ascii_string
1211  *
1212  * The ascii string in smb includes oem chars. Since the
1213  * system needs utf8 encodes unicode char, conversion is
1214  * required to convert the oem char to unicode and then
1215  * to encode the converted wchars to utf8 format.
1216  * Therefore, the **ascii returned will be in such format
1217  * instead of the real ASCII format.
1218  */
1219 static int
1220 mbc_marshal_get_ascii_string(
1221     struct smb_malloc_list	*ml,
1222     mbuf_chain_t		*mbc,
1223     uint8_t		**ascii,
1224     int				max_ascii)
1225 {
1226 	char		*rcvbuf;
1227 	char		*ch;
1228 	mts_wchar_t	*wtmpbuf;
1229 	int		max;
1230 	int		length = 0;
1231 	uint_t	cpid = oem_get_smb_cpid();
1232 
1233 	max = MALLOC_QUANTUM;
1234 	rcvbuf = smbsr_malloc(ml, max);
1235 
1236 	if (max_ascii == 0)
1237 		max_ascii = 0xffff;
1238 
1239 	ch = rcvbuf;
1240 	for (;;) {
1241 		while (length < max) {
1242 			if (max_ascii-- <= 0) {
1243 				*ch++ = 0;
1244 				goto multibyte_encode;
1245 			}
1246 			if (MBC_ROOM_FOR(mbc, sizeof (char)) == 0) {
1247 				/* Data will never be available */
1248 				return (DECODE_NO_MORE_DATA);
1249 			}
1250 			if ((*ch++ = mbc_marshal_fetch_byte(mbc)) == 0)
1251 				goto multibyte_encode;
1252 			length++;
1253 		}
1254 		max += MALLOC_QUANTUM;
1255 		rcvbuf = smbsr_realloc(rcvbuf, max);
1256 		ch = rcvbuf + length;
1257 	}
1258 
1259 multibyte_encode:
1260 	/*
1261 	 * UTF-8 encode the string for internal system use.
1262 	 */
1263 	length = strlen(rcvbuf) + 1;
1264 	wtmpbuf = smbsr_malloc(ml, length*sizeof (mts_wchar_t));
1265 	*ascii = smbsr_malloc(ml, length * MTS_MB_CHAR_MAX);
1266 
1267 	if (oemstounicodes(wtmpbuf, rcvbuf, length, cpid) > 0)
1268 		(void) mts_wcstombs((char *)*ascii, wtmpbuf,
1269 		    length * MTS_MB_CHAR_MAX);
1270 	else
1271 		(void) mts_stombs((char *)*ascii, rcvbuf, length * 2);
1272 	return (0);
1273 }
1274 
1275 static int
1276 mbc_marshal_get_unicode_string(struct smb_malloc_list *ml,
1277     mbuf_chain_t *mbc, uint8_t **ascii, int max_unicode)
1278 {
1279 	int		max;
1280 	uint16_t	wchar;
1281 	char		*ch;
1282 	int		emitted;
1283 	int		length = 0;
1284 
1285 	if (max_unicode == 0)
1286 		max_unicode = 0xffff;
1287 
1288 	max = MALLOC_QUANTUM;
1289 	*ascii = smbsr_malloc(ml, max);
1290 
1291 	ch = (char *)*ascii;
1292 	for (;;) {
1293 		while ((length + MTS_MB_CHAR_MAX) < max) {
1294 			if (max_unicode <= 0)
1295 				goto done;
1296 			max_unicode -= 2;
1297 
1298 			if (mbc_marshal_get_short(mbc, &wchar) != 0)
1299 				return (DECODE_NO_MORE_DATA);
1300 
1301 			if (wchar == 0)	goto done;
1302 
1303 			emitted = mts_wctomb(ch, wchar);
1304 			length += emitted;
1305 			ch += emitted;
1306 		}
1307 		max += MALLOC_QUANTUM;
1308 		*ascii = smbsr_realloc(*ascii, max);
1309 		ch = (char *)*ascii + length;
1310 	}
1311 done:	*ch = 0;
1312 	return (0);
1313 }
1314 
1315 static int /*ARGSUSED*/
1316 mbc_marshal_get_mbufs(mbuf_chain_t *mbc, int32_t bytes, mbuf_t **m)
1317 {
1318 	if (MBC_ROOM_FOR(mbc, bytes) == 0) {
1319 		/* Data will never be available */
1320 		return (DECODE_NO_MORE_DATA);
1321 	}
1322 	return (0);
1323 }
1324 
1325 static int
1326 mbc_marshal_get_mbuf_chain(mbuf_chain_t *mbc, int32_t bytes, mbuf_chain_t *nmbc)
1327 {
1328 	int	rc;
1329 	mbuf_t	*m;
1330 
1331 	if (bytes == 0) {
1332 		/* Get all the rest */
1333 		bytes = mbc->max_bytes - mbc->chain_offset;
1334 	}
1335 
1336 	MBC_SETUP(nmbc, mbc->max_bytes);
1337 	if ((rc = mbc_marshal_get_mbufs(mbc, bytes, &m)) != 0) {
1338 		if (m)
1339 			m_freem(m);
1340 		return (rc);
1341 	}
1342 	nmbc->chain = m;
1343 	while (m != 0) {
1344 		bytes += m->m_len;
1345 		m = m->m_next;
1346 	}
1347 	nmbc->max_bytes = bytes;
1348 	return (0);
1349 }
1350 
1351 static int
1352 mbc_marshal_get_uio(mbuf_chain_t *mbc, struct uio *uio)
1353 {
1354 	int		i, offset;
1355 	int32_t		bytes = uio->uio_resid;
1356 	int32_t		remainder;
1357 	struct iovec	*iov;
1358 	mbuf_t		*m;
1359 
1360 	/*
1361 	 * The residual count is tested because in the case of write requests
1362 	 * with no data (smbtorture RAW-WRITE test will generate that type of
1363 	 * request) this function is called with a residual count of zero
1364 	 * bytes.
1365 	 */
1366 	if (bytes) {
1367 		iov = uio->uio_iov;
1368 		uio->uio_segflg = UIO_SYSSPACE;
1369 
1370 		if (MBC_ROOM_FOR(mbc, bytes) == 0) {
1371 			/* Data will never be available */
1372 			return (DECODE_NO_MORE_DATA);
1373 		}
1374 
1375 		m = mbc->chain;
1376 		offset = mbc->chain_offset;
1377 		while (offset >= m->m_len) {
1378 			offset -= m->m_len;
1379 			m = m->m_next;
1380 			ASSERT((offset == 0) || (offset && m));
1381 		}
1382 
1383 		for (i = 0; (bytes > 0) && (i < uio->uio_iovcnt); i++) {
1384 			iov[i].iov_base = &m->m_data[offset];
1385 			remainder = m->m_len - offset;
1386 			if (remainder >= bytes) {
1387 				iov[i].iov_len = bytes;
1388 				mbc->chain_offset += bytes;
1389 				break;
1390 			}
1391 			iov[i].iov_len = remainder;
1392 			mbc->chain_offset += remainder;
1393 			bytes -= remainder;
1394 			m = m->m_next;
1395 			offset = 0;
1396 		}
1397 		if (i == uio->uio_iovcnt) {
1398 			return (DECODE_NO_MORE_DATA);
1399 		}
1400 		uio->uio_iovcnt = i;
1401 	}
1402 	return (0);
1403 }
1404 
1405 static int
1406 mbc_marshal_get_skip(mbuf_chain_t *mbc, uint_t skip)
1407 {
1408 	if (MBC_ROOM_FOR(mbc, skip) == 0)
1409 		return (DECODE_NO_MORE_DATA);
1410 	mbc->chain_offset += skip;
1411 	return (0);
1412 }
1413