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