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