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