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