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
26 /*
27 * SMB mbuf marshaling encode/decode.
28 */
29
30 #include <smbsrv/smb_kproto.h>
31
32
33 #define MALLOC_QUANTUM 80
34
35 #define DECODE_NO_ERROR 0
36 #define DECODE_NO_MORE_DATA 1
37 #define DECODE_ALLOCATION_ERROR 2
38 #define DECODE_CONVERSION_ERROR 3
39
40 static int mbc_marshal_cstou8(char *, char *, size_t, char *, size_t);
41 static int mbc_marshal_make_room(mbuf_chain_t *, int32_t);
42 static void mbc_marshal_store_byte(mbuf_chain_t *, uint8_t);
43 static int mbc_marshal_put_char(mbuf_chain_t *mbc, uint8_t);
44 static int mbc_marshal_put_short(mbuf_chain_t *mbc, uint16_t);
45 static int mbc_marshal_put_long(mbuf_chain_t *mbc, uint32_t);
46 static int mbc_marshal_put_long_long(mbuf_chain_t *mbc, uint64_t);
47 static int mbc_marshal_put_ascii_string(mbuf_chain_t *, char *, int);
48 static int mbc_marshal_put_unicode_string(mbuf_chain_t *, char *, int);
49 static int mbc_marshal_put_uio(mbuf_chain_t *, struct uio *);
50 static int mbc_marshal_put_mbufs(mbuf_chain_t *mbc, mbuf_t *m);
51 static int mbc_marshal_put_mbuf_chain(mbuf_chain_t *mbc, mbuf_chain_t *nmbc);
52 static uint8_t mbc_marshal_fetch_byte(mbuf_chain_t *mbc);
53 static int mbc_marshal_get_char(mbuf_chain_t *mbc, uint8_t *data);
54 static int mbc_marshal_get_short(mbuf_chain_t *mbc, uint16_t *data);
55 static int mbc_marshal_get_long(mbuf_chain_t *mbc, uint32_t *data);
56 static uint64_t qswap(uint64_t ll);
57 static int mbc_marshal_get_odd_long_long(mbuf_chain_t *mbc, uint64_t *data);
58 static int mbc_marshal_get_long_long(mbuf_chain_t *mbc, uint64_t *data);
59 static int mbc_marshal_get_ascii_string(smb_request_t *, mbuf_chain_t *,
60 uint8_t **ascii, int);
61 static int mbc_marshal_get_unicode_string(smb_request_t *, mbuf_chain_t *,
62 uint8_t **, int);
63 static int mbc_marshal_get_mbufs(mbuf_chain_t *, int32_t, mbuf_t **);
64 static int mbc_marshal_get_mbuf_chain(mbuf_chain_t *, int32_t, mbuf_chain_t *);
65 static int mbc_marshal_get_uio(mbuf_chain_t *, struct uio *);
66 static int mbc_marshal_get_skip(mbuf_chain_t *, uint_t);
67
68 /*
69 * smb_mbc_vdecodef
70 *
71 * This function reads the contents of the mbc chain passed in under the list
72 * of arguments passed in.
73 *
74 * The format string provides a description of the parameters passed in as well
75 * as an action to be taken by smb_mbc_vdecodef().
76 *
77 * % Pointer to an SMB request structure (smb_request_t *). There
78 * should be only one of these in the string.
79 *
80 * C Pointer to an mbuf chain. Copy to that mbuf chain the number of
81 * bytes specified (number preceding C).
82 *
83 * m Pointer to an mbuf. Copy to that mbuf the number of bytes
84 * specified (number preceding m).
85 *
86 * M Read the 32 bit value at the current location of the mbuf chain
87 * and check if it matches the signature of an SMB request (SMBX).
88 *
89 * b Pointer to a buffer. Copy to that buffer the number of bytes
90 * specified (number preceding b).
91 *
92 * c Same as 'b'.
93 *
94 * w Pointer to a word (16bit value). Copy the next 16bit value into
95 * that location.
96 *
97 * l Pointer to a long (32bit value). Copy the next 32bit value into
98 * that location.
99 *
100 * q Pointer to a quad (64bit value). Copy the next 64bit value into
101 * that location.
102 *
103 * Q Same as above with a call to qswap().
104 *
105 * B Pointer to a vardata_block structure. That structure is used to
106 * retrieve data from the mbuf chain (an iovec type structure is
107 * embedded in a vardata_block).
108 *
109 * D Pointer to a vardata_block structure. That structure is used to
110 * retrieve data from the mbuf chain, however, two fields of the
111 * vardata_block structure (tag and len) are first initialized
112 * using the mbuf chain itself.
113 *
114 * V Same as 'D'.
115 *
116 * L
117 *
118 * A
119 *
120 * P Same as 'A'
121 *
122 * S Same as 'A'
123 *
124 * u Pointer to a string pointer. Allocate memory and retrieve the
125 * string at the current location in the mbuf chain. Store the
126 * address to the buffer allocated at the address specified by
127 * the pointer. In addition if an sr was passed and it indicates
128 * that the string is an unicode string, convert it.
129 *
130 * s Same as 'u' without convertion.
131 *
132 * U Same as 'u'. The string to retrieve is unicode.
133 *
134 * y Pointer to a 32bit value. Read the dos time at the current mbuf
135 * chain location, convert it to unix time and store it at the
136 * location indicated by the pointer.
137 *
138 * Y Same as 'y' bt the dos time coded in the mbuf chain is inverted.
139 *
140 * . Skip the number of bytes indicated by the number preceding '.'.
141 *
142 * , Same as '.' but take in account it is an unicode string.
143 */
144 int
smb_mbc_vdecodef(mbuf_chain_t * mbc,char * fmt,va_list ap)145 smb_mbc_vdecodef(mbuf_chain_t *mbc, char *fmt, va_list ap)
146 {
147 uint8_t c;
148 uint8_t cval;
149 uint8_t *cvalp;
150 uint8_t **cvalpp;
151 uint16_t wval;
152 uint16_t *wvalp;
153 uint32_t *lvalp;
154 uint64_t *llvalp;
155 smb_vdb_t *vdp;
156 smb_request_t *sr = NULL;
157 uint32_t lval;
158 int unicode = 0;
159 int repc;
160
161 while ((c = *fmt++) != 0) {
162 repc = 1;
163
164 if ('0' <= c && c <= '9') {
165 repc = 0;
166 do {
167 repc = repc * 10 + c - '0';
168 c = *fmt++;
169 } while ('0' <= c && c <= '9');
170 } else if (c == '#') {
171 repc = va_arg(ap, int);
172 c = *fmt++;
173 }
174
175 switch (c) {
176 case '%':
177 sr = va_arg(ap, struct smb_request *);
178 unicode = sr->smb_flg2 & SMB_FLAGS2_UNICODE;
179 break;
180
181 case 'C': /* Mbuf_chain */
182 if (mbc_marshal_get_mbuf_chain(mbc, repc,
183 va_arg(ap, mbuf_chain_t *)) != 0)
184 return (-1);
185 break;
186
187 case 'm': /* struct_mbuf */
188 if (mbc_marshal_get_mbufs(mbc, repc,
189 va_arg(ap, mbuf_t **)) != 0)
190 return (-1);
191 break;
192
193 case 'M':
194 if (mbc_marshal_get_long(mbc, &lval) != 0)
195 /* Data will never be available */
196 return (-1);
197
198 if (lval != 0x424D53FF) /* 0xFF S M B */
199 return (-1);
200 break;
201
202 case 'b':
203 case 'c':
204 cvalp = va_arg(ap, uint8_t *);
205 if (MBC_ROOM_FOR(mbc, repc) == 0)
206 /* Data will never be available */
207 return (-1);
208
209 while (repc-- > 0)
210 *cvalp++ = mbc_marshal_fetch_byte(mbc);
211 break;
212
213 case 'w':
214 wvalp = va_arg(ap, uint16_t *);
215 while (repc-- > 0)
216 if (mbc_marshal_get_short(mbc, wvalp++) != 0)
217 return (-1);
218 break;
219
220 case 'l':
221 lvalp = va_arg(ap, uint32_t *);
222 while (repc-- > 0)
223 if (mbc_marshal_get_long(mbc, lvalp++) != 0)
224 return (-1);
225 break;
226
227 case 'q':
228 llvalp = va_arg(ap, uint64_t *);
229 while (repc-- > 0)
230 if (mbc_marshal_get_long_long(
231 mbc, llvalp++) != 0)
232 return (-1);
233 break;
234
235 case 'Q':
236 llvalp = va_arg(ap, uint64_t *);
237 while (repc-- > 0)
238 if (mbc_marshal_get_odd_long_long(
239 mbc, llvalp++) != 0)
240 return (-1);
241 break;
242
243 case 'B':
244 vdp = va_arg(ap, struct vardata_block *);
245 vdp->vdb_tag = 0;
246 vdp->vdb_len = repc;
247 vdp->vdb_uio.uio_iov = &vdp->vdb_iovec[0];
248 vdp->vdb_uio.uio_iovcnt = MAX_IOVEC;
249 vdp->vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
250 vdp->vdb_uio.uio_resid = repc;
251 if (mbc_marshal_get_uio(mbc, &vdp->vdb_uio) != 0)
252 return (-1);
253 break;
254
255 case 'D':
256 case 'V':
257 vdp = va_arg(ap, struct vardata_block *);
258 if (mbc_marshal_get_char(mbc, &vdp->vdb_tag) != 0)
259 return (-1);
260 if (mbc_marshal_get_short(mbc, &wval) != 0)
261 return (-1);
262 vdp->vdb_len = (uint32_t)wval;
263 vdp->vdb_uio.uio_iov = &vdp->vdb_iovec[0];
264 vdp->vdb_uio.uio_iovcnt = MAX_IOVEC;
265 vdp->vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
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,
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,
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
smb_mbc_decodef(mbuf_chain_t * mbc,char * fmt,...)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
smb_mbc_peek(mbuf_chain_t * mbc,int offset,char * fmt,...)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
smb_mbc_vencodef(mbuf_chain_t * mbc,char * fmt,va_list ap)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
smb_mbc_encodef(mbuf_chain_t * mbc,char * fmt,...)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
smb_mbc_poke(mbuf_chain_t * mbc,int offset,char * fmt,...)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
mbc_marshal_make_room(mbuf_chain_t * mbc,int32_t bytes_needed)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
mbc_marshal_store_byte(mbuf_chain_t * mbc,uint8_t data)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
mbc_marshal_put_char(mbuf_chain_t * mbc,uint8_t data)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
mbc_marshal_put_short(mbuf_chain_t * mbc,uint16_t data)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
mbc_marshal_put_long(mbuf_chain_t * mbc,uint32_t data)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
mbc_marshal_put_long_long(mbuf_chain_t * mbc,uint64_t data)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
mbc_marshal_put_ascii_string(mbuf_chain_t * mbc,char * mbs,int repc)910 mbc_marshal_put_ascii_string(mbuf_chain_t *mbc, char *mbs, int repc)
911 {
912 smb_wchar_t wide_char;
913 int nbytes;
914 int length;
915
916 if ((length = smb_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 = smb_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
mbc_marshal_put_unicode_string(mbuf_chain_t * mbc,char * ascii,int repc)947 mbc_marshal_put_unicode_string(mbuf_chain_t *mbc, char *ascii, int repc)
948 {
949 smb_wchar_t wchar;
950 int consumed;
951 int length;
952
953 if ((length = smb_wcequiv_strlen(ascii)) == -1)
954 return (DECODE_NO_MORE_DATA);
955
956 length += sizeof (smb_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 = smb_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 (smb_wchar_t);
977 }
978 return (0);
979 }
980
981 static int
mbc_marshal_put_uio(mbuf_chain_t * mbc,struct uio * uio)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
mbc_marshal_put_mbufs(mbuf_chain_t * mbc,mbuf_t * m)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
mbc_marshal_put_mbuf_chain(mbuf_chain_t * mbc,mbuf_chain_t * nmbc)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
mbc_marshal_fetch_byte(mbuf_chain_t * mbc)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
mbc_marshal_get_char(mbuf_chain_t * mbc,uint8_t * data)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
mbc_marshal_get_short(mbuf_chain_t * mbc,uint16_t * data)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
mbc_marshal_get_long(mbuf_chain_t * mbc,uint32_t * data)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
qswap(uint64_t ll)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
mbc_marshal_get_odd_long_long(mbuf_chain_t * mbc,uint64_t * data)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
mbc_marshal_get_long_long(mbuf_chain_t * mbc,uint64_t * data)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
mbc_marshal_get_ascii_string(smb_request_t * sr,mbuf_chain_t * mbc,uint8_t ** ascii,int max_ascii)1217 mbc_marshal_get_ascii_string(
1218 smb_request_t *sr,
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 = smb_srm_zalloc(sr, 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 = smb_srm_rezalloc(sr, 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 = smb_srm_zalloc(sr, 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
mbc_marshal_get_unicode_string(smb_request_t * sr,mbuf_chain_t * mbc,uint8_t ** ascii,int max_unicode)1265 mbc_marshal_get_unicode_string(smb_request_t *sr,
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 = smb_srm_zalloc(sr, 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 = smb_wctomb(ch, wchar);
1293 length += emitted;
1294 ch += emitted;
1295 }
1296 max += MALLOC_QUANTUM;
1297 *ascii = smb_srm_rezalloc(sr, *ascii, max);
1298 ch = (char *)*ascii + length;
1299 }
1300 done: *ch = 0;
1301 return (0);
1302 }
1303
1304 static int /*ARGSUSED*/
mbc_marshal_get_mbufs(mbuf_chain_t * mbc,int32_t bytes,mbuf_t ** m)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
mbc_marshal_get_mbuf_chain(mbuf_chain_t * mbc,int32_t bytes,mbuf_chain_t * nmbc)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
mbc_marshal_get_uio(mbuf_chain_t * mbc,struct uio * uio)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 != 0) {
1356 iov = uio->uio_iov;
1357 uio->uio_segflg = UIO_SYSSPACE;
1358 uio->uio_extflg = UIO_COPY_DEFAULT;
1359
1360 if (MBC_ROOM_FOR(mbc, bytes) == 0) {
1361 /* Data will never be available */
1362 return (DECODE_NO_MORE_DATA);
1363 }
1364
1365 m = mbc->chain;
1366 offset = mbc->chain_offset;
1367 while (offset >= m->m_len) {
1368 offset -= m->m_len;
1369 m = m->m_next;
1370 ASSERT((offset == 0) || (offset && m));
1371 }
1372
1373 for (i = 0; (bytes > 0) && (i < uio->uio_iovcnt); i++) {
1374 iov[i].iov_base = &m->m_data[offset];
1375 remainder = m->m_len - offset;
1376 if (remainder >= bytes) {
1377 iov[i].iov_len = bytes;
1378 mbc->chain_offset += bytes;
1379 uio->uio_iovcnt = i + 1;
1380 return (0);
1381 }
1382 iov[i].iov_len = remainder;
1383 mbc->chain_offset += remainder;
1384 bytes -= remainder;
1385 m = m->m_next;
1386 offset = 0;
1387 }
1388 return (DECODE_NO_MORE_DATA);
1389 }
1390 return (0);
1391 }
1392
1393 static int
mbc_marshal_get_skip(mbuf_chain_t * mbc,uint_t skip)1394 mbc_marshal_get_skip(mbuf_chain_t *mbc, uint_t skip)
1395 {
1396 if (MBC_ROOM_FOR(mbc, skip) == 0)
1397 return (DECODE_NO_MORE_DATA);
1398 mbc->chain_offset += skip;
1399 return (0);
1400 }
1401
1402 /*
1403 * Converts oem string to UTF-8 string with an output string of max
1404 * maxconv bytes. The string may be truncated or not null-terminated if
1405 * there is not enough room.
1406 *
1407 * returns -1, cnt (partial conversion) or 0 (success)
1408 */
1409
1410 static int
mbc_marshal_cstou8(char * cs,char * outbuf,size_t maxconv,char * inbuf,size_t srcbytes)1411 mbc_marshal_cstou8(char *cs, char *outbuf, size_t maxconv,
1412 char *inbuf, size_t srcbytes)
1413 {
1414 kiconv_t t2u;
1415 size_t inlen = srcbytes;
1416 size_t outlen = maxconv;
1417 int err = 0;
1418 size_t rc;
1419
1420 if ((t2u = kiconv_open("UTF-8", cs)) == (kiconv_t)-1)
1421 return (-1);
1422
1423 rc = kiconv(t2u, &inbuf, &inlen, &outbuf, &outlen, &err);
1424 (void) kiconv_close(t2u);
1425 return ((int)rc);
1426 }
1427