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