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