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