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