1 /* 2 * Copyright (c) 2000-2001, Boris Popov 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Boris Popov. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $Id: smb_rq.c,v 1.29 2005/02/11 01:44:17 lindak Exp $ 33 */ 34 35 /* 36 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 37 */ 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/time.h> 42 #include <sys/kmem.h> 43 #include <sys/proc.h> 44 #include <sys/lock.h> 45 #include <sys/socket.h> 46 #include <sys/mount.h> 47 #include <sys/sunddi.h> 48 #include <sys/cmn_err.h> 49 #include <sys/sdt.h> 50 51 #include <netsmb/smb_osdep.h> 52 53 #include <netsmb/smb.h> 54 #include <netsmb/smb_conn.h> 55 #include <netsmb/smb_subr.h> 56 #include <netsmb/smb_tran.h> 57 #include <netsmb/smb_rq.h> 58 59 /* 60 * How long to wait before restarting a request (after reconnect) 61 */ 62 #define SMB_RCNDELAY 2 /* seconds */ 63 64 /* 65 * leave this zero - we can't ssecond guess server side effects of 66 * duplicate ops, this isn't nfs! 67 */ 68 #define SMBMAXRESTARTS 0 69 70 71 static int smb_rq_reply(struct smb_rq *rqp); 72 static int smb_rq_enqueue(struct smb_rq *rqp); 73 static int smb_rq_getenv(struct smb_connobj *layer, 74 struct smb_vc **vcpp, struct smb_share **sspp); 75 static int smb_rq_new(struct smb_rq *rqp, uchar_t cmd); 76 static int smb_t2_reply(struct smb_t2rq *t2p); 77 static int smb_nt_reply(struct smb_ntrq *ntp); 78 79 80 /* 81 * Done with a request object. Free its contents. 82 * If it was allocated (SMBR_ALLOCED) free it too. 83 * Some of these are stack locals, not allocated. 84 * 85 * No locks here - this is the last ref. 86 */ 87 void 88 smb_rq_done(struct smb_rq *rqp) 89 { 90 91 /* 92 * No smb_vc_rele() here - see smb_rq_init() 93 */ 94 mb_done(&rqp->sr_rq); 95 md_done(&rqp->sr_rp); 96 mutex_destroy(&rqp->sr_lock); 97 cv_destroy(&rqp->sr_cond); 98 if (rqp->sr_flags & SMBR_ALLOCED) 99 kmem_free(rqp, sizeof (*rqp)); 100 } 101 102 int 103 smb_rq_alloc(struct smb_connobj *layer, uchar_t cmd, struct smb_cred *scred, 104 struct smb_rq **rqpp) 105 { 106 struct smb_rq *rqp; 107 int error; 108 109 rqp = (struct smb_rq *)kmem_alloc(sizeof (struct smb_rq), KM_SLEEP); 110 if (rqp == NULL) 111 return (ENOMEM); 112 error = smb_rq_init(rqp, layer, cmd, scred); 113 if (error) { 114 smb_rq_done(rqp); 115 return (error); 116 } 117 rqp->sr_flags |= SMBR_ALLOCED; 118 *rqpp = rqp; 119 return (0); 120 } 121 122 int 123 smb_rq_init(struct smb_rq *rqp, struct smb_connobj *co, uchar_t cmd, 124 struct smb_cred *scred) 125 { 126 int error; 127 128 bzero(rqp, sizeof (*rqp)); 129 mutex_init(&rqp->sr_lock, NULL, MUTEX_DRIVER, NULL); 130 cv_init(&rqp->sr_cond, NULL, CV_DEFAULT, NULL); 131 132 error = smb_rq_getenv(co, &rqp->sr_vc, &rqp->sr_share); 133 if (error) 134 return (error); 135 136 /* 137 * We copied a VC pointer (vcp) into rqp->sr_vc, 138 * but we do NOT do a smb_vc_hold here. Instead, 139 * the caller is responsible for the hold on the 140 * share or the VC as needed. For smbfs callers, 141 * the hold is on the share, via the smbfs mount. 142 * For nsmb ioctl callers, the hold is done when 143 * the driver handle gets VC or share references. 144 * This design avoids frequent hold/rele activity 145 * when creating and completing requests. 146 */ 147 148 rqp->sr_rexmit = SMBMAXRESTARTS; 149 rqp->sr_cred = scred; /* Note: ref hold done by caller. */ 150 rqp->sr_pid = (uint16_t)ddi_get_pid(); 151 error = smb_rq_new(rqp, cmd); 152 153 return (error); 154 } 155 156 static int 157 smb_rq_new(struct smb_rq *rqp, uchar_t cmd) 158 { 159 struct mbchain *mbp = &rqp->sr_rq; 160 struct smb_vc *vcp = rqp->sr_vc; 161 int error; 162 163 ASSERT(rqp != NULL); 164 165 rqp->sr_sendcnt = 0; 166 rqp->sr_cmd = cmd; 167 168 mb_done(mbp); 169 md_done(&rqp->sr_rp); 170 error = mb_init(mbp); 171 if (error) 172 return (error); 173 174 /* 175 * Is this the right place to save the flags? 176 */ 177 rqp->sr_rqflags = vcp->vc_hflags; 178 rqp->sr_rqflags2 = vcp->vc_hflags2; 179 180 /* 181 * The SMB header is filled in later by 182 * smb_rq_fillhdr (see below) 183 * Just reserve space here. 184 */ 185 mb_put_mem(mbp, NULL, SMB_HDRLEN, MB_MZERO); 186 187 return (0); 188 } 189 190 /* 191 * Given a request with it's body already composed, 192 * rewind to the start and fill in the SMB header. 193 * This is called after the request is enqueued, 194 * so we have the final MID, seq num. etc. 195 */ 196 void 197 smb_rq_fillhdr(struct smb_rq *rqp) 198 { 199 struct mbchain mbtmp, *mbp = &mbtmp; 200 mblk_t *m; 201 202 /* 203 * Fill in the SMB header using a dup of the first mblk, 204 * which points at the same data but has its own wptr, 205 * so we can rewind without trashing the message. 206 */ 207 m = dupb(rqp->sr_rq.mb_top); 208 m->b_wptr = m->b_rptr; /* rewind */ 209 mb_initm(mbp, m); 210 211 mb_put_mem(mbp, SMB_SIGNATURE, 4, MB_MSYSTEM); 212 mb_put_uint8(mbp, rqp->sr_cmd); 213 mb_put_uint32le(mbp, 0); /* status */ 214 mb_put_uint8(mbp, rqp->sr_rqflags); 215 mb_put_uint16le(mbp, rqp->sr_rqflags2); 216 mb_put_uint16le(mbp, 0); /* pid-high */ 217 mb_put_mem(mbp, NULL, 8, MB_MZERO); /* MAC sig. (later) */ 218 mb_put_uint16le(mbp, 0); /* reserved */ 219 mb_put_uint16le(mbp, rqp->sr_rqtid); 220 mb_put_uint16le(mbp, rqp->sr_pid); 221 mb_put_uint16le(mbp, rqp->sr_rquid); 222 mb_put_uint16le(mbp, rqp->sr_mid); 223 224 /* This will free the mblk from dupb. */ 225 mb_done(mbp); 226 } 227 228 int 229 smb_rq_simple(struct smb_rq *rqp) 230 { 231 return (smb_rq_simple_timed(rqp, smb_timo_default)); 232 } 233 234 /* 235 * Simple request-reply exchange 236 */ 237 int 238 smb_rq_simple_timed(struct smb_rq *rqp, int timeout) 239 { 240 int error = EINVAL; 241 242 for (; ; ) { 243 /* 244 * Don't send any new requests if force unmount is underway. 245 * This check was moved into smb_rq_enqueue. 246 */ 247 rqp->sr_flags &= ~SMBR_RESTART; 248 rqp->sr_timo = timeout; /* in seconds */ 249 rqp->sr_state = SMBRQ_NOTSENT; 250 error = smb_rq_enqueue(rqp); 251 if (error) { 252 break; 253 } 254 error = smb_rq_reply(rqp); 255 if (!error) 256 break; 257 if ((rqp->sr_flags & (SMBR_RESTART | SMBR_NORESTART)) != 258 SMBR_RESTART) 259 break; 260 if (rqp->sr_rexmit <= 0) 261 break; 262 SMBRQ_LOCK(rqp); 263 if (rqp->sr_share) { 264 (void) cv_reltimedwait(&rqp->sr_cond, &(rqp)->sr_lock, 265 SEC_TO_TICK(SMB_RCNDELAY), TR_CLOCK_TICK); 266 267 } else { 268 delay(SEC_TO_TICK(SMB_RCNDELAY)); 269 } 270 SMBRQ_UNLOCK(rqp); 271 rqp->sr_rexmit--; 272 } 273 return (error); 274 } 275 276 277 static int 278 smb_rq_enqueue(struct smb_rq *rqp) 279 { 280 struct smb_vc *vcp = rqp->sr_vc; 281 struct smb_share *ssp = rqp->sr_share; 282 int error = 0; 283 284 /* 285 * Normal requests may initiate a reconnect, 286 * and/or wait for state changes to finish. 287 * Some requests set the NORECONNECT flag 288 * to avoid all that (i.e. tree discon) 289 */ 290 if (rqp->sr_flags & SMBR_NORECONNECT) { 291 if (vcp->vc_state != SMBIOD_ST_VCACTIVE) { 292 SMBSDEBUG("bad vc_state=%d\n", vcp->vc_state); 293 return (ENOTCONN); 294 } 295 if (ssp != NULL && 296 ((ssp->ss_flags & SMBS_CONNECTED) == 0)) 297 return (ENOTCONN); 298 goto ok_out; 299 } 300 301 /* 302 * If we're not connected, initiate a reconnect 303 * and/or wait for an existing one to finish. 304 */ 305 if (vcp->vc_state != SMBIOD_ST_VCACTIVE) { 306 error = smb_iod_reconnect(vcp); 307 if (error != 0) 308 return (error); 309 } 310 311 /* 312 * If this request has a "share" object 313 * that needs a tree connect, do it now. 314 */ 315 if (ssp != NULL && (ssp->ss_flags & SMBS_CONNECTED) == 0) { 316 error = smb_share_tcon(ssp, rqp->sr_cred); 317 if (error) 318 return (error); 319 } 320 321 /* 322 * We now know what UID + TID to use. 323 * Store them in the request. 324 */ 325 ok_out: 326 rqp->sr_rquid = vcp->vc_smbuid; 327 rqp->sr_rqtid = ssp ? ssp->ss_tid : SMB_TID_UNKNOWN; 328 error = smb_iod_addrq(rqp); 329 330 return (error); 331 } 332 333 /* 334 * Mark location of the word count, which is filled in later by 335 * smb_rw_wend(). Also initialize the counter that it uses 336 * to figure out what value to fill in. 337 * 338 * Note that the word count happens to be 8-bit. 339 */ 340 void 341 smb_rq_wstart(struct smb_rq *rqp) 342 { 343 rqp->sr_wcount = mb_reserve(&rqp->sr_rq, sizeof (uint8_t)); 344 rqp->sr_rq.mb_count = 0; 345 } 346 347 void 348 smb_rq_wend(struct smb_rq *rqp) 349 { 350 uint_t wcnt; 351 352 if (rqp->sr_wcount == NULL) { 353 SMBSDEBUG("no wcount\n"); 354 return; 355 } 356 wcnt = rqp->sr_rq.mb_count; 357 if (wcnt > 0x1ff) 358 SMBSDEBUG("word count too large (%d)\n", wcnt); 359 if (wcnt & 1) 360 SMBSDEBUG("odd word count\n"); 361 /* Fill in the word count (8-bits) */ 362 *rqp->sr_wcount = (wcnt >> 1); 363 } 364 365 /* 366 * Mark location of the byte count, which is filled in later by 367 * smb_rw_bend(). Also initialize the counter that it uses 368 * to figure out what value to fill in. 369 * 370 * Note that the byte count happens to be 16-bit. 371 */ 372 void 373 smb_rq_bstart(struct smb_rq *rqp) 374 { 375 rqp->sr_bcount = mb_reserve(&rqp->sr_rq, sizeof (uint16_t)); 376 rqp->sr_rq.mb_count = 0; 377 } 378 379 void 380 smb_rq_bend(struct smb_rq *rqp) 381 { 382 uint_t bcnt; 383 384 if (rqp->sr_bcount == NULL) { 385 SMBSDEBUG("no bcount\n"); 386 return; 387 } 388 bcnt = rqp->sr_rq.mb_count; 389 if (bcnt > 0xffff) 390 SMBSDEBUG("byte count too large (%d)\n", bcnt); 391 /* 392 * Fill in the byte count (16-bits) 393 * The pointer is char * type due to 394 * typical off-by-one alignment. 395 */ 396 rqp->sr_bcount[0] = bcnt & 0xFF; 397 rqp->sr_bcount[1] = (bcnt >> 8); 398 } 399 400 int 401 smb_rq_intr(struct smb_rq *rqp) 402 { 403 if (rqp->sr_flags & SMBR_INTR) 404 return (EINTR); 405 406 return (0); 407 } 408 409 static int 410 smb_rq_getenv(struct smb_connobj *co, 411 struct smb_vc **vcpp, struct smb_share **sspp) 412 { 413 struct smb_vc *vcp = NULL; 414 struct smb_share *ssp = NULL; 415 int error = EINVAL; 416 417 if (co->co_flags & SMBO_GONE) { 418 SMBSDEBUG("zombie CO\n"); 419 error = EINVAL; 420 goto out; 421 } 422 423 switch (co->co_level) { 424 case SMBL_SHARE: 425 ssp = CPTOSS(co); 426 if ((co->co_flags & SMBO_GONE) || 427 co->co_parent == NULL) { 428 SMBSDEBUG("zombie share %s\n", ssp->ss_name); 429 break; 430 } 431 /* instead of recursion... */ 432 co = co->co_parent; 433 /* FALLTHROUGH */ 434 case SMBL_VC: 435 vcp = CPTOVC(co); 436 if ((co->co_flags & SMBO_GONE) || 437 co->co_parent == NULL) { 438 SMBSDEBUG("zombie VC %s\n", vcp->vc_srvname); 439 break; 440 } 441 error = 0; 442 break; 443 444 default: 445 SMBSDEBUG("invalid level %d passed\n", co->co_level); 446 } 447 448 out: 449 if (!error) { 450 if (vcpp) 451 *vcpp = vcp; 452 if (sspp) 453 *sspp = ssp; 454 } 455 456 return (error); 457 } 458 459 /* 460 * Wait for reply on the request 461 */ 462 static int 463 smb_rq_reply(struct smb_rq *rqp) 464 { 465 struct mdchain *mdp = &rqp->sr_rp; 466 u_int8_t tb; 467 int error, rperror = 0; 468 469 if (rqp->sr_timo == SMBNOREPLYWAIT) { 470 smb_iod_removerq(rqp); 471 return (0); 472 } 473 474 error = smb_iod_waitrq(rqp); 475 if (error) 476 return (error); 477 478 /* 479 * If the request was signed, validate the 480 * signature on the response. 481 */ 482 if (rqp->sr_rqflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) { 483 error = smb_rq_verify(rqp); 484 if (error) 485 return (error); 486 } 487 488 /* 489 * Parse the SMB header 490 */ 491 error = md_get_uint32le(mdp, NULL); 492 if (error) 493 return (error); 494 error = md_get_uint8(mdp, &tb); 495 error = md_get_uint32le(mdp, &rqp->sr_error); 496 error = md_get_uint8(mdp, &rqp->sr_rpflags); 497 error = md_get_uint16le(mdp, &rqp->sr_rpflags2); 498 if (rqp->sr_rpflags2 & SMB_FLAGS2_ERR_STATUS) { 499 /* 500 * Do a special check for STATUS_BUFFER_OVERFLOW; 501 * it's not an error. 502 */ 503 if (rqp->sr_error == NT_STATUS_BUFFER_OVERFLOW) { 504 /* 505 * Don't report it as an error to our caller; 506 * they can look at rqp->sr_error if they 507 * need to know whether we got a 508 * STATUS_BUFFER_OVERFLOW. 509 * XXX - should we do that for all errors 510 * where (error & 0xC0000000) is 0x80000000, 511 * i.e. all warnings? 512 */ 513 rperror = 0; 514 } else 515 rperror = smb_maperr32(rqp->sr_error); 516 } else { 517 rqp->sr_errclass = rqp->sr_error & 0xff; 518 rqp->sr_serror = rqp->sr_error >> 16; 519 rperror = smb_maperror(rqp->sr_errclass, rqp->sr_serror); 520 } 521 if (rperror == EMOREDATA) { 522 rperror = E2BIG; 523 rqp->sr_flags |= SMBR_MOREDATA; 524 } else 525 rqp->sr_flags &= ~SMBR_MOREDATA; 526 527 error = md_get_uint32le(mdp, NULL); 528 error = md_get_uint32le(mdp, NULL); 529 error = md_get_uint32le(mdp, NULL); 530 531 error = md_get_uint16le(mdp, &rqp->sr_rptid); 532 error = md_get_uint16le(mdp, &rqp->sr_rppid); 533 error = md_get_uint16le(mdp, &rqp->sr_rpuid); 534 error = md_get_uint16le(mdp, &rqp->sr_rpmid); 535 536 return ((error) ? error : rperror); 537 } 538 539 540 #define ALIGN4(a) (((a) + 3) & ~3) 541 542 /* 543 * TRANS2 request implementation 544 * TRANS implementation is in the "t2" routines 545 * NT_TRANSACTION implementation is the separate "nt" stuff 546 */ 547 int 548 smb_t2_alloc(struct smb_connobj *layer, ushort_t setup, struct smb_cred *scred, 549 struct smb_t2rq **t2pp) 550 { 551 struct smb_t2rq *t2p; 552 int error; 553 554 t2p = (struct smb_t2rq *)kmem_alloc(sizeof (*t2p), KM_SLEEP); 555 if (t2p == NULL) 556 return (ENOMEM); 557 error = smb_t2_init(t2p, layer, &setup, 1, scred); 558 t2p->t2_flags |= SMBT2_ALLOCED; 559 if (error) { 560 smb_t2_done(t2p); 561 return (error); 562 } 563 *t2pp = t2p; 564 return (0); 565 } 566 567 int 568 smb_nt_alloc(struct smb_connobj *layer, ushort_t fn, struct smb_cred *scred, 569 struct smb_ntrq **ntpp) 570 { 571 struct smb_ntrq *ntp; 572 int error; 573 574 ntp = (struct smb_ntrq *)kmem_alloc(sizeof (*ntp), KM_SLEEP); 575 if (ntp == NULL) 576 return (ENOMEM); 577 error = smb_nt_init(ntp, layer, fn, scred); 578 mutex_init(&ntp->nt_lock, NULL, MUTEX_DRIVER, NULL); 579 cv_init(&ntp->nt_cond, NULL, CV_DEFAULT, NULL); 580 ntp->nt_flags |= SMBT2_ALLOCED; 581 if (error) { 582 smb_nt_done(ntp); 583 return (error); 584 } 585 *ntpp = ntp; 586 return (0); 587 } 588 589 int 590 smb_t2_init(struct smb_t2rq *t2p, struct smb_connobj *source, ushort_t *setup, 591 int setupcnt, struct smb_cred *scred) 592 { 593 int i; 594 int error; 595 596 bzero(t2p, sizeof (*t2p)); 597 mutex_init(&t2p->t2_lock, NULL, MUTEX_DRIVER, NULL); 598 cv_init(&t2p->t2_cond, NULL, CV_DEFAULT, NULL); 599 600 t2p->t2_source = source; 601 t2p->t2_setupcount = (u_int16_t)setupcnt; 602 t2p->t2_setupdata = t2p->t2_setup; 603 for (i = 0; i < setupcnt; i++) 604 t2p->t2_setup[i] = setup[i]; 605 t2p->t2_fid = 0xffff; 606 t2p->t2_cred = scred; 607 t2p->t2_share = (source->co_level == SMBL_SHARE ? 608 CPTOSS(source) : NULL); /* for smb up/down */ 609 error = smb_rq_getenv(source, &t2p->t2_vc, NULL); 610 if (error) 611 return (error); 612 return (0); 613 } 614 615 int 616 smb_nt_init(struct smb_ntrq *ntp, struct smb_connobj *source, ushort_t fn, 617 struct smb_cred *scred) 618 { 619 int error; 620 621 bzero(ntp, sizeof (*ntp)); 622 ntp->nt_source = source; 623 ntp->nt_function = fn; 624 ntp->nt_cred = scred; 625 ntp->nt_share = (source->co_level == SMBL_SHARE ? 626 CPTOSS(source) : NULL); /* for smb up/down */ 627 error = smb_rq_getenv(source, &ntp->nt_vc, NULL); 628 if (error) 629 return (error); 630 return (0); 631 } 632 633 void 634 smb_t2_done(struct smb_t2rq *t2p) 635 { 636 mb_done(&t2p->t2_tparam); 637 mb_done(&t2p->t2_tdata); 638 md_done(&t2p->t2_rparam); 639 md_done(&t2p->t2_rdata); 640 mutex_destroy(&t2p->t2_lock); 641 cv_destroy(&t2p->t2_cond); 642 if (t2p->t2_flags & SMBT2_ALLOCED) 643 kmem_free(t2p, sizeof (*t2p)); 644 } 645 646 void 647 smb_nt_done(struct smb_ntrq *ntp) 648 { 649 mb_done(&ntp->nt_tsetup); 650 mb_done(&ntp->nt_tparam); 651 mb_done(&ntp->nt_tdata); 652 md_done(&ntp->nt_rparam); 653 md_done(&ntp->nt_rdata); 654 cv_destroy(&ntp->nt_cond); 655 mutex_destroy(&ntp->nt_lock); 656 if (ntp->nt_flags & SMBT2_ALLOCED) 657 kmem_free(ntp, sizeof (*ntp)); 658 } 659 660 /* 661 * Extract data [offset,count] from mtop and add to mdp. 662 */ 663 static int 664 smb_t2_placedata(mblk_t *mtop, u_int16_t offset, u_int16_t count, 665 struct mdchain *mdp) 666 { 667 mblk_t *n; 668 669 n = m_copym(mtop, offset, count, M_WAITOK); 670 if (n == NULL) 671 return (EBADRPC); 672 673 if (mdp->md_top == NULL) { 674 md_initm(mdp, n); 675 } else 676 m_cat(mdp->md_top, n); 677 678 return (0); 679 } 680 681 static int 682 smb_t2_reply(struct smb_t2rq *t2p) 683 { 684 struct mdchain *mdp; 685 struct smb_rq *rqp = t2p->t2_rq; 686 int error, error2, totpgot, totdgot; 687 u_int16_t totpcount, totdcount, pcount, poff, doff, pdisp, ddisp; 688 u_int16_t tmp, bc, dcount; 689 u_int8_t wc; 690 691 t2p->t2_flags &= ~SMBT2_MOREDATA; 692 693 error = smb_rq_reply(rqp); 694 if (rqp->sr_flags & SMBR_MOREDATA) 695 t2p->t2_flags |= SMBT2_MOREDATA; 696 t2p->t2_sr_errclass = rqp->sr_errclass; 697 t2p->t2_sr_serror = rqp->sr_serror; 698 t2p->t2_sr_error = rqp->sr_error; 699 t2p->t2_sr_rpflags2 = rqp->sr_rpflags2; 700 if (error && !(rqp->sr_flags & SMBR_MOREDATA)) 701 return (error); 702 /* 703 * Now we have to get all subseqent responses, if any. 704 * The CIFS specification says that they can be misordered, 705 * which is weird. 706 * TODO: timo 707 */ 708 totpgot = totdgot = 0; 709 totpcount = totdcount = 0xffff; 710 mdp = &rqp->sr_rp; 711 for (;;) { 712 DTRACE_PROBE2(smb_trans_reply, 713 (smb_rq_t *), rqp, (mblk_t *), mdp->md_top); 714 m_dumpm(mdp->md_top); 715 716 if ((error2 = md_get_uint8(mdp, &wc)) != 0) 717 break; 718 if (wc < 10) { 719 error2 = ENOENT; 720 break; 721 } 722 if ((error2 = md_get_uint16le(mdp, &tmp)) != 0) 723 break; 724 if (totpcount > tmp) 725 totpcount = tmp; 726 if ((error2 = md_get_uint16le(mdp, &tmp)) != 0) 727 break; 728 if (totdcount > tmp) 729 totdcount = tmp; 730 if ((error2 = md_get_uint16le(mdp, &tmp)) != 0 || /* reserved */ 731 (error2 = md_get_uint16le(mdp, &pcount)) != 0 || 732 (error2 = md_get_uint16le(mdp, &poff)) != 0 || 733 (error2 = md_get_uint16le(mdp, &pdisp)) != 0) 734 break; 735 if (pcount != 0 && pdisp != totpgot) { 736 SMBSDEBUG("Can't handle misordered parameters %d:%d\n", 737 pdisp, totpgot); 738 error2 = EINVAL; 739 break; 740 } 741 if ((error2 = md_get_uint16le(mdp, &dcount)) != 0 || 742 (error2 = md_get_uint16le(mdp, &doff)) != 0 || 743 (error2 = md_get_uint16le(mdp, &ddisp)) != 0) 744 break; 745 if (dcount != 0 && ddisp != totdgot) { 746 SMBSDEBUG("Can't handle misordered data: dcount %d\n", 747 dcount); 748 error2 = EINVAL; 749 break; 750 } 751 752 /* XXX: Skip setup words? We don't save them? */ 753 md_get_uint8(mdp, &wc); /* SetupCount */ 754 md_get_uint8(mdp, NULL); /* Reserved2 */ 755 tmp = wc; 756 while (tmp--) 757 md_get_uint16le(mdp, NULL); 758 759 if ((error2 = md_get_uint16le(mdp, &bc)) != 0) 760 break; 761 762 /* 763 * There are pad bytes here, and the poff value 764 * indicates where the next data are found. 765 * No need to guess at the padding size. 766 */ 767 if (pcount) { 768 error2 = smb_t2_placedata(mdp->md_top, poff, 769 pcount, &t2p->t2_rparam); 770 if (error2) 771 break; 772 } 773 totpgot += pcount; 774 775 if (dcount) { 776 error2 = smb_t2_placedata(mdp->md_top, doff, 777 dcount, &t2p->t2_rdata); 778 if (error2) 779 break; 780 } 781 totdgot += dcount; 782 783 if (totpgot >= totpcount && totdgot >= totdcount) { 784 error2 = 0; 785 t2p->t2_flags |= SMBT2_ALLRECV; 786 break; 787 } 788 /* 789 * We're done with this reply, look for the next one. 790 */ 791 SMBRQ_LOCK(rqp); 792 md_next_record(&rqp->sr_rp); 793 SMBRQ_UNLOCK(rqp); 794 error2 = smb_rq_reply(rqp); 795 if (rqp->sr_flags & SMBR_MOREDATA) 796 t2p->t2_flags |= SMBT2_MOREDATA; 797 if (!error2) 798 continue; 799 t2p->t2_sr_errclass = rqp->sr_errclass; 800 t2p->t2_sr_serror = rqp->sr_serror; 801 t2p->t2_sr_error = rqp->sr_error; 802 t2p->t2_sr_rpflags2 = rqp->sr_rpflags2; 803 error = error2; 804 if (!(rqp->sr_flags & SMBR_MOREDATA)) 805 break; 806 } 807 return (error ? error : error2); 808 } 809 810 static int 811 smb_nt_reply(struct smb_ntrq *ntp) 812 { 813 struct mdchain *mdp; 814 struct smb_rq *rqp = ntp->nt_rq; 815 int error, error2; 816 u_int32_t totpcount, totdcount, pcount, poff, doff, pdisp, ddisp; 817 u_int32_t tmp, dcount, totpgot, totdgot; 818 u_int16_t bc; 819 u_int8_t wc; 820 821 ntp->nt_flags &= ~SMBT2_MOREDATA; 822 823 error = smb_rq_reply(rqp); 824 if (rqp->sr_flags & SMBR_MOREDATA) 825 ntp->nt_flags |= SMBT2_MOREDATA; 826 ntp->nt_sr_error = rqp->sr_error; 827 ntp->nt_sr_rpflags2 = rqp->sr_rpflags2; 828 if (error && !(rqp->sr_flags & SMBR_MOREDATA)) 829 return (error); 830 /* 831 * Now we have to get all subseqent responses. The CIFS specification 832 * says that they can be misordered which is weird. 833 * TODO: timo 834 */ 835 totpgot = totdgot = 0; 836 totpcount = totdcount = 0xffffffff; 837 mdp = &rqp->sr_rp; 838 for (;;) { 839 DTRACE_PROBE2(smb_trans_reply, 840 (smb_rq_t *), rqp, (mblk_t *), mdp->md_top); 841 m_dumpm(mdp->md_top); 842 843 if ((error2 = md_get_uint8(mdp, &wc)) != 0) 844 break; 845 if (wc < 18) { 846 error2 = ENOENT; 847 break; 848 } 849 md_get_mem(mdp, NULL, 3, MB_MSYSTEM); /* reserved */ 850 if ((error2 = md_get_uint32le(mdp, &tmp)) != 0) 851 break; 852 if (totpcount > tmp) 853 totpcount = tmp; 854 if ((error2 = md_get_uint32le(mdp, &tmp)) != 0) 855 break; 856 if (totdcount > tmp) 857 totdcount = tmp; 858 if ((error2 = md_get_uint32le(mdp, &pcount)) != 0 || 859 (error2 = md_get_uint32le(mdp, &poff)) != 0 || 860 (error2 = md_get_uint32le(mdp, &pdisp)) != 0) 861 break; 862 if (pcount != 0 && pdisp != totpgot) { 863 SMBSDEBUG("Can't handle misordered parameters %d:%d\n", 864 pdisp, totpgot); 865 error2 = EINVAL; 866 break; 867 } 868 if ((error2 = md_get_uint32le(mdp, &dcount)) != 0 || 869 (error2 = md_get_uint32le(mdp, &doff)) != 0 || 870 (error2 = md_get_uint32le(mdp, &ddisp)) != 0) 871 break; 872 if (dcount != 0 && ddisp != totdgot) { 873 SMBSDEBUG("Can't handle misordered data: dcount %d\n", 874 dcount); 875 error2 = EINVAL; 876 break; 877 } 878 879 /* XXX: Skip setup words? We don't save them? */ 880 md_get_uint8(mdp, &wc); /* SetupCount */ 881 tmp = wc; 882 while (tmp--) 883 md_get_uint16le(mdp, NULL); 884 885 if ((error2 = md_get_uint16le(mdp, &bc)) != 0) 886 break; 887 888 /* 889 * There are pad bytes here, and the poff value 890 * indicates where the next data are found. 891 * No need to guess at the padding size. 892 */ 893 if (pcount) { 894 error2 = smb_t2_placedata(mdp->md_top, poff, pcount, 895 &ntp->nt_rparam); 896 if (error2) 897 break; 898 } 899 totpgot += pcount; 900 901 if (dcount) { 902 error2 = smb_t2_placedata(mdp->md_top, doff, dcount, 903 &ntp->nt_rdata); 904 if (error2) 905 break; 906 } 907 totdgot += dcount; 908 909 if (totpgot >= totpcount && totdgot >= totdcount) { 910 error2 = 0; 911 ntp->nt_flags |= SMBT2_ALLRECV; 912 break; 913 } 914 /* 915 * We're done with this reply, look for the next one. 916 */ 917 SMBRQ_LOCK(rqp); 918 md_next_record(&rqp->sr_rp); 919 SMBRQ_UNLOCK(rqp); 920 error2 = smb_rq_reply(rqp); 921 if (rqp->sr_flags & SMBR_MOREDATA) 922 ntp->nt_flags |= SMBT2_MOREDATA; 923 if (!error2) 924 continue; 925 ntp->nt_sr_error = rqp->sr_error; 926 ntp->nt_sr_rpflags2 = rqp->sr_rpflags2; 927 error = error2; 928 if (!(rqp->sr_flags & SMBR_MOREDATA)) 929 break; 930 } 931 return (error ? error : error2); 932 } 933 934 /* 935 * Perform a full round of TRANS2 request 936 */ 937 static int 938 smb_t2_request_int(struct smb_t2rq *t2p) 939 { 940 struct smb_vc *vcp = t2p->t2_vc; 941 struct smb_cred *scred = t2p->t2_cred; 942 struct mbchain *mbp; 943 struct mdchain *mdp, mbparam, mbdata; 944 mblk_t *m; 945 struct smb_rq *rqp; 946 int totpcount, leftpcount, totdcount, leftdcount, len, txmax, i; 947 int error, doff, poff, txdcount, txpcount, nmlen, nmsize; 948 949 m = t2p->t2_tparam.mb_top; 950 if (m) { 951 md_initm(&mbparam, m); /* do not free it! */ 952 totpcount = m_fixhdr(m); 953 if (totpcount > 0xffff) /* maxvalue for ushort_t */ 954 return (EINVAL); 955 } else 956 totpcount = 0; 957 m = t2p->t2_tdata.mb_top; 958 if (m) { 959 md_initm(&mbdata, m); /* do not free it! */ 960 totdcount = m_fixhdr(m); 961 if (totdcount > 0xffff) 962 return (EINVAL); 963 } else 964 totdcount = 0; 965 leftdcount = totdcount; 966 leftpcount = totpcount; 967 txmax = vcp->vc_txmax; 968 error = smb_rq_alloc(t2p->t2_source, t2p->t_name ? 969 SMB_COM_TRANSACTION : SMB_COM_TRANSACTION2, scred, &rqp); 970 if (error) 971 return (error); 972 rqp->sr_timo = smb_timo_default; 973 rqp->sr_flags |= SMBR_MULTIPACKET; 974 t2p->t2_rq = rqp; 975 mbp = &rqp->sr_rq; 976 smb_rq_wstart(rqp); 977 mb_put_uint16le(mbp, totpcount); 978 mb_put_uint16le(mbp, totdcount); 979 mb_put_uint16le(mbp, t2p->t2_maxpcount); 980 mb_put_uint16le(mbp, t2p->t2_maxdcount); 981 mb_put_uint8(mbp, t2p->t2_maxscount); 982 mb_put_uint8(mbp, 0); /* reserved */ 983 mb_put_uint16le(mbp, 0); /* flags */ 984 mb_put_uint32le(mbp, 0); /* Timeout */ 985 mb_put_uint16le(mbp, 0); /* reserved 2 */ 986 len = mb_fixhdr(mbp); 987 988 /* 989 * Now we know the size of the trans overhead stuff: 990 * ALIGN4(len + 5 * 2 + setupcount * 2 + 2 + nmsize), 991 * where nmsize is the OTW size of the name, including 992 * the unicode null terminator and any alignment. 993 * Use this to decide which parts (and how much) 994 * can go into this request: params, data 995 */ 996 nmlen = t2p->t_name ? t2p->t_name_len : 0; 997 nmsize = nmlen + 1; /* null term. */ 998 if (SMB_UNICODE_STRINGS(vcp)) { 999 nmsize *= 2; 1000 /* we know put_dmem will need to align */ 1001 nmsize += 1; 1002 } 1003 len = ALIGN4(len + 5 * 2 + t2p->t2_setupcount * 2 + 2 + nmsize); 1004 if (len + leftpcount > txmax) { 1005 txpcount = min(leftpcount, txmax - len); 1006 poff = len; 1007 txdcount = 0; 1008 doff = 0; 1009 } else { 1010 txpcount = leftpcount; 1011 poff = txpcount ? len : 0; 1012 /* 1013 * Other client traffic seems to "ALIGN2" here. The extra 1014 * 2 byte pad we use has no observed downside and may be 1015 * required for some old servers(?) 1016 */ 1017 len = ALIGN4(len + txpcount); 1018 txdcount = min(leftdcount, txmax - len); 1019 doff = txdcount ? len : 0; 1020 } 1021 leftpcount -= txpcount; 1022 leftdcount -= txdcount; 1023 mb_put_uint16le(mbp, txpcount); 1024 mb_put_uint16le(mbp, poff); 1025 mb_put_uint16le(mbp, txdcount); 1026 mb_put_uint16le(mbp, doff); 1027 mb_put_uint8(mbp, t2p->t2_setupcount); 1028 mb_put_uint8(mbp, 0); 1029 for (i = 0; i < t2p->t2_setupcount; i++) { 1030 mb_put_uint16le(mbp, t2p->t2_setupdata[i]); 1031 } 1032 smb_rq_wend(rqp); 1033 smb_rq_bstart(rqp); 1034 if (t2p->t_name) { 1035 /* Put the string and terminating null. */ 1036 error = smb_put_dmem(mbp, vcp, t2p->t_name, nmlen + 1, 1037 SMB_CS_NONE, NULL); 1038 } else { 1039 /* nmsize accounts for padding, char size. */ 1040 error = mb_put_mem(mbp, NULL, nmsize, MB_MZERO); 1041 } 1042 if (error) 1043 goto freerq; 1044 len = mb_fixhdr(mbp); 1045 if (txpcount) { 1046 mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); 1047 error = md_get_mbuf(&mbparam, txpcount, &m); 1048 SMBSDEBUG("%d:%d:%d\n", error, txpcount, txmax); 1049 if (error) 1050 goto freerq; 1051 mb_put_mbuf(mbp, m); 1052 } 1053 len = mb_fixhdr(mbp); 1054 if (txdcount) { 1055 mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); 1056 error = md_get_mbuf(&mbdata, txdcount, &m); 1057 if (error) 1058 goto freerq; 1059 mb_put_mbuf(mbp, m); 1060 } 1061 smb_rq_bend(rqp); /* incredible, but thats it... */ 1062 error = smb_rq_enqueue(rqp); 1063 if (error) 1064 goto freerq; 1065 if (leftpcount || leftdcount) { 1066 error = smb_rq_reply(rqp); 1067 if (error) 1068 goto bad; 1069 /* 1070 * this is an interim response, ignore it. 1071 */ 1072 SMBRQ_LOCK(rqp); 1073 md_next_record(&rqp->sr_rp); 1074 SMBRQ_UNLOCK(rqp); 1075 } 1076 while (leftpcount || leftdcount) { 1077 error = smb_rq_new(rqp, t2p->t_name ? 1078 SMB_COM_TRANSACTION_SECONDARY : 1079 SMB_COM_TRANSACTION2_SECONDARY); 1080 if (error) 1081 goto bad; 1082 mbp = &rqp->sr_rq; 1083 smb_rq_wstart(rqp); 1084 mb_put_uint16le(mbp, totpcount); 1085 mb_put_uint16le(mbp, totdcount); 1086 len = mb_fixhdr(mbp); 1087 /* 1088 * now we have known packet size as 1089 * ALIGN4(len + 7 * 2 + 2) for T2 request, and -2 for T one, 1090 * and need to decide which parts should go into request 1091 */ 1092 len = ALIGN4(len + 6 * 2 + 2); 1093 if (t2p->t_name == NULL) 1094 len += 2; 1095 if (len + leftpcount > txmax) { 1096 txpcount = min(leftpcount, txmax - len); 1097 poff = len; 1098 txdcount = 0; 1099 doff = 0; 1100 } else { 1101 txpcount = leftpcount; 1102 poff = txpcount ? len : 0; 1103 len = ALIGN4(len + txpcount); 1104 txdcount = min(leftdcount, txmax - len); 1105 doff = txdcount ? len : 0; 1106 } 1107 mb_put_uint16le(mbp, txpcount); 1108 mb_put_uint16le(mbp, poff); 1109 mb_put_uint16le(mbp, totpcount - leftpcount); 1110 mb_put_uint16le(mbp, txdcount); 1111 mb_put_uint16le(mbp, doff); 1112 mb_put_uint16le(mbp, totdcount - leftdcount); 1113 leftpcount -= txpcount; 1114 leftdcount -= txdcount; 1115 if (t2p->t_name == NULL) 1116 mb_put_uint16le(mbp, t2p->t2_fid); 1117 smb_rq_wend(rqp); 1118 smb_rq_bstart(rqp); 1119 mb_put_uint8(mbp, 0); /* name */ 1120 len = mb_fixhdr(mbp); 1121 if (txpcount) { 1122 mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); 1123 error = md_get_mbuf(&mbparam, txpcount, &m); 1124 if (error) 1125 goto bad; 1126 mb_put_mbuf(mbp, m); 1127 } 1128 len = mb_fixhdr(mbp); 1129 if (txdcount) { 1130 mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); 1131 error = md_get_mbuf(&mbdata, txdcount, &m); 1132 if (error) 1133 goto bad; 1134 mb_put_mbuf(mbp, m); 1135 } 1136 smb_rq_bend(rqp); 1137 error = smb_iod_multirq(rqp); 1138 if (error) 1139 goto bad; 1140 } /* while left params or data */ 1141 error = smb_t2_reply(t2p); 1142 if (error && !(t2p->t2_flags & SMBT2_MOREDATA)) 1143 goto bad; 1144 mdp = &t2p->t2_rdata; 1145 if (mdp->md_top) { 1146 md_initm(mdp, mdp->md_top); 1147 } 1148 mdp = &t2p->t2_rparam; 1149 if (mdp->md_top) { 1150 md_initm(mdp, mdp->md_top); 1151 } 1152 bad: 1153 smb_iod_removerq(rqp); 1154 freerq: 1155 if (error && !(t2p->t2_flags & SMBT2_MOREDATA)) { 1156 if (rqp->sr_flags & SMBR_RESTART) 1157 t2p->t2_flags |= SMBT2_RESTART; 1158 md_done(&t2p->t2_rparam); 1159 md_done(&t2p->t2_rdata); 1160 } 1161 smb_rq_done(rqp); 1162 return (error); 1163 } 1164 1165 1166 /* 1167 * Perform a full round of NT_TRANSACTION request 1168 */ 1169 static int 1170 smb_nt_request_int(struct smb_ntrq *ntp) 1171 { 1172 struct smb_vc *vcp = ntp->nt_vc; 1173 struct smb_cred *scred = ntp->nt_cred; 1174 struct mbchain *mbp; 1175 struct mdchain *mdp, mbsetup, mbparam, mbdata; 1176 mblk_t *m; 1177 struct smb_rq *rqp; 1178 int totpcount, leftpcount, totdcount, leftdcount, len, txmax; 1179 int error, doff, poff, txdcount, txpcount; 1180 int totscount; 1181 1182 m = ntp->nt_tsetup.mb_top; 1183 if (m) { 1184 md_initm(&mbsetup, m); /* do not free it! */ 1185 totscount = m_fixhdr(m); 1186 if (totscount > 2 * 0xff) 1187 return (EINVAL); 1188 } else 1189 totscount = 0; 1190 m = ntp->nt_tparam.mb_top; 1191 if (m) { 1192 md_initm(&mbparam, m); /* do not free it! */ 1193 totpcount = m_fixhdr(m); 1194 if (totpcount > 0x7fffffff) 1195 return (EINVAL); 1196 } else 1197 totpcount = 0; 1198 m = ntp->nt_tdata.mb_top; 1199 if (m) { 1200 md_initm(&mbdata, m); /* do not free it! */ 1201 totdcount = m_fixhdr(m); 1202 if (totdcount > 0x7fffffff) 1203 return (EINVAL); 1204 } else 1205 totdcount = 0; 1206 leftdcount = totdcount; 1207 leftpcount = totpcount; 1208 txmax = vcp->vc_txmax; 1209 error = smb_rq_alloc(ntp->nt_source, SMB_COM_NT_TRANSACT, scred, &rqp); 1210 if (error) 1211 return (error); 1212 rqp->sr_timo = smb_timo_default; 1213 rqp->sr_flags |= SMBR_MULTIPACKET; 1214 ntp->nt_rq = rqp; 1215 mbp = &rqp->sr_rq; 1216 smb_rq_wstart(rqp); 1217 mb_put_uint8(mbp, ntp->nt_maxscount); 1218 mb_put_uint16le(mbp, 0); /* reserved (flags?) */ 1219 mb_put_uint32le(mbp, totpcount); 1220 mb_put_uint32le(mbp, totdcount); 1221 mb_put_uint32le(mbp, ntp->nt_maxpcount); 1222 mb_put_uint32le(mbp, ntp->nt_maxdcount); 1223 len = mb_fixhdr(mbp); 1224 /* 1225 * now we have known packet size as 1226 * ALIGN4(len + 4 * 4 + 1 + 2 + ((totscount+1)&~1) + 2), 1227 * and need to decide which parts should go into the first request 1228 */ 1229 len = ALIGN4(len + 4 * 4 + 1 + 2 + ((totscount+1)&~1) + 2); 1230 if (len + leftpcount > txmax) { 1231 txpcount = min(leftpcount, txmax - len); 1232 poff = len; 1233 txdcount = 0; 1234 doff = 0; 1235 } else { 1236 txpcount = leftpcount; 1237 poff = txpcount ? len : 0; 1238 len = ALIGN4(len + txpcount); 1239 txdcount = min(leftdcount, txmax - len); 1240 doff = txdcount ? len : 0; 1241 } 1242 leftpcount -= txpcount; 1243 leftdcount -= txdcount; 1244 mb_put_uint32le(mbp, txpcount); 1245 mb_put_uint32le(mbp, poff); 1246 mb_put_uint32le(mbp, txdcount); 1247 mb_put_uint32le(mbp, doff); 1248 mb_put_uint8(mbp, (totscount+1)/2); 1249 mb_put_uint16le(mbp, ntp->nt_function); 1250 if (totscount) { 1251 error = md_get_mbuf(&mbsetup, totscount, &m); 1252 SMBSDEBUG("%d:%d:%d\n", error, totscount, txmax); 1253 if (error) 1254 goto freerq; 1255 mb_put_mbuf(mbp, m); 1256 if (totscount & 1) 1257 mb_put_uint8(mbp, 0); /* setup is in words */ 1258 } 1259 smb_rq_wend(rqp); 1260 smb_rq_bstart(rqp); 1261 len = mb_fixhdr(mbp); 1262 if (txpcount) { 1263 mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); 1264 error = md_get_mbuf(&mbparam, txpcount, &m); 1265 SMBSDEBUG("%d:%d:%d\n", error, txpcount, txmax); 1266 if (error) 1267 goto freerq; 1268 mb_put_mbuf(mbp, m); 1269 } 1270 len = mb_fixhdr(mbp); 1271 if (txdcount) { 1272 mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); 1273 error = md_get_mbuf(&mbdata, txdcount, &m); 1274 if (error) 1275 goto freerq; 1276 mb_put_mbuf(mbp, m); 1277 } 1278 smb_rq_bend(rqp); /* incredible, but thats it... */ 1279 error = smb_rq_enqueue(rqp); 1280 if (error) 1281 goto freerq; 1282 if (leftpcount || leftdcount) { 1283 error = smb_rq_reply(rqp); 1284 if (error) 1285 goto bad; 1286 /* 1287 * this is an interim response, ignore it. 1288 */ 1289 SMBRQ_LOCK(rqp); 1290 md_next_record(&rqp->sr_rp); 1291 SMBRQ_UNLOCK(rqp); 1292 } 1293 while (leftpcount || leftdcount) { 1294 error = smb_rq_new(rqp, SMB_COM_NT_TRANSACT_SECONDARY); 1295 if (error) 1296 goto bad; 1297 mbp = &rqp->sr_rq; 1298 smb_rq_wstart(rqp); 1299 mb_put_mem(mbp, NULL, 3, MB_MZERO); 1300 mb_put_uint32le(mbp, totpcount); 1301 mb_put_uint32le(mbp, totdcount); 1302 len = mb_fixhdr(mbp); 1303 /* 1304 * now we have known packet size as 1305 * ALIGN4(len + 6 * 4 + 2) 1306 * and need to decide which parts should go into request 1307 */ 1308 len = ALIGN4(len + 6 * 4 + 2); 1309 if (len + leftpcount > txmax) { 1310 txpcount = min(leftpcount, txmax - len); 1311 poff = len; 1312 txdcount = 0; 1313 doff = 0; 1314 } else { 1315 txpcount = leftpcount; 1316 poff = txpcount ? len : 0; 1317 len = ALIGN4(len + txpcount); 1318 txdcount = min(leftdcount, txmax - len); 1319 doff = txdcount ? len : 0; 1320 } 1321 mb_put_uint32le(mbp, txpcount); 1322 mb_put_uint32le(mbp, poff); 1323 mb_put_uint32le(mbp, totpcount - leftpcount); 1324 mb_put_uint32le(mbp, txdcount); 1325 mb_put_uint32le(mbp, doff); 1326 mb_put_uint32le(mbp, totdcount - leftdcount); 1327 leftpcount -= txpcount; 1328 leftdcount -= txdcount; 1329 smb_rq_wend(rqp); 1330 smb_rq_bstart(rqp); 1331 len = mb_fixhdr(mbp); 1332 if (txpcount) { 1333 mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); 1334 error = md_get_mbuf(&mbparam, txpcount, &m); 1335 if (error) 1336 goto bad; 1337 mb_put_mbuf(mbp, m); 1338 } 1339 len = mb_fixhdr(mbp); 1340 if (txdcount) { 1341 mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); 1342 error = md_get_mbuf(&mbdata, txdcount, &m); 1343 if (error) 1344 goto bad; 1345 mb_put_mbuf(mbp, m); 1346 } 1347 smb_rq_bend(rqp); 1348 error = smb_iod_multirq(rqp); 1349 if (error) 1350 goto bad; 1351 } /* while left params or data */ 1352 error = smb_nt_reply(ntp); 1353 if (error && !(ntp->nt_flags & SMBT2_MOREDATA)) 1354 goto bad; 1355 mdp = &ntp->nt_rdata; 1356 if (mdp->md_top) { 1357 md_initm(mdp, mdp->md_top); 1358 } 1359 mdp = &ntp->nt_rparam; 1360 if (mdp->md_top) { 1361 md_initm(mdp, mdp->md_top); 1362 } 1363 bad: 1364 smb_iod_removerq(rqp); 1365 freerq: 1366 if (error && !(ntp->nt_flags & SMBT2_MOREDATA)) { 1367 if (rqp->sr_flags & SMBR_RESTART) 1368 ntp->nt_flags |= SMBT2_RESTART; 1369 md_done(&ntp->nt_rparam); 1370 md_done(&ntp->nt_rdata); 1371 } 1372 smb_rq_done(rqp); 1373 return (error); 1374 } 1375 1376 int 1377 smb_t2_request(struct smb_t2rq *t2p) 1378 { 1379 int error = EINVAL, i; 1380 1381 for (i = 0; ; ) { 1382 /* 1383 * Don't send any new requests if force unmount is underway. 1384 * This check was moved into smb_rq_enqueue, called by 1385 * smb_t2_request_int() 1386 */ 1387 t2p->t2_flags &= ~SMBT2_RESTART; 1388 error = smb_t2_request_int(t2p); 1389 if (!error) 1390 break; 1391 if ((t2p->t2_flags & (SMBT2_RESTART | SMBT2_NORESTART)) != 1392 SMBT2_RESTART) 1393 break; 1394 if (++i > SMBMAXRESTARTS) 1395 break; 1396 mutex_enter(&(t2p)->t2_lock); 1397 if (t2p->t2_share) { 1398 (void) cv_reltimedwait(&t2p->t2_cond, &(t2p)->t2_lock, 1399 SEC_TO_TICK(SMB_RCNDELAY), TR_CLOCK_TICK); 1400 } else { 1401 delay(SEC_TO_TICK(SMB_RCNDELAY)); 1402 } 1403 mutex_exit(&(t2p)->t2_lock); 1404 } 1405 return (error); 1406 } 1407 1408 1409 int 1410 smb_nt_request(struct smb_ntrq *ntp) 1411 { 1412 int error = EINVAL, i; 1413 1414 for (i = 0; ; ) { 1415 /* 1416 * Don't send any new requests if force unmount is underway. 1417 * This check was moved into smb_rq_enqueue, called by 1418 * smb_nt_request_int() 1419 */ 1420 ntp->nt_flags &= ~SMBT2_RESTART; 1421 error = smb_nt_request_int(ntp); 1422 if (!error) 1423 break; 1424 if ((ntp->nt_flags & (SMBT2_RESTART | SMBT2_NORESTART)) != 1425 SMBT2_RESTART) 1426 break; 1427 if (++i > SMBMAXRESTARTS) 1428 break; 1429 mutex_enter(&(ntp)->nt_lock); 1430 if (ntp->nt_share) { 1431 (void) cv_reltimedwait(&ntp->nt_cond, &(ntp)->nt_lock, 1432 SEC_TO_TICK(SMB_RCNDELAY), TR_CLOCK_TICK); 1433 1434 } else { 1435 delay(SEC_TO_TICK(SMB_RCNDELAY)); 1436 } 1437 mutex_exit(&(ntp)->nt_lock); 1438 } 1439 return (error); 1440 } 1441