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