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