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 2009 Sun Microsystems, Inc. All rights reserved. 37 * Use is subject to license terms. 38 */ 39 40 #include <sys/param.h> 41 #include <sys/systm.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 cv_timedwait(&rqp->sr_cond, &(rqp)->sr_lock, 265 lbolt + (hz * SMB_RCNDELAY)); 266 267 } else { 268 delay(lbolt + (hz * SMB_RCNDELAY)); 269 } 270 SMBRQ_UNLOCK(rqp); 271 rqp->sr_rexmit--; 272 #ifdef XXX 273 timeout *= 2; 274 #endif 275 } 276 return (error); 277 } 278 279 280 static int 281 smb_rq_enqueue(struct smb_rq *rqp) 282 { 283 struct smb_vc *vcp = rqp->sr_vc; 284 struct smb_share *ssp = rqp->sr_share; 285 int error = 0; 286 287 /* 288 * Normal requests may initiate a reconnect, 289 * and/or wait for state changes to finish. 290 * Some requests set the NORECONNECT flag 291 * to avoid all that (i.e. tree discon) 292 */ 293 if (rqp->sr_flags & SMBR_NORECONNECT) { 294 if (vcp->vc_state != SMBIOD_ST_VCACTIVE) { 295 SMBSDEBUG("bad vc_state=%d\n", vcp->vc_state); 296 return (ENOTCONN); 297 } 298 if (ssp != NULL && 299 ((ssp->ss_flags & SMBS_CONNECTED) == 0)) 300 return (ENOTCONN); 301 goto ok_out; 302 } 303 304 /* 305 * If we're not connected, initiate a reconnect 306 * and/or wait for an existing one to finish. 307 */ 308 if (vcp->vc_state != SMBIOD_ST_VCACTIVE) { 309 error = smb_iod_reconnect(vcp); 310 if (error != 0) 311 return (error); 312 } 313 314 /* 315 * If this request has a "share" object 316 * that needs a tree connect, do it now. 317 */ 318 if (ssp != NULL && (ssp->ss_flags & SMBS_CONNECTED) == 0) { 319 error = smb_share_tcon(ssp, rqp->sr_cred); 320 if (error) 321 return (error); 322 } 323 324 /* 325 * We now know what UID + TID to use. 326 * Store them in the request. 327 */ 328 ok_out: 329 rqp->sr_rquid = vcp->vc_smbuid; 330 rqp->sr_rqtid = ssp ? ssp->ss_tid : SMB_TID_UNKNOWN; 331 error = smb_iod_addrq(rqp); 332 333 return (error); 334 } 335 336 /* 337 * Mark location of the word count, which is filled in later by 338 * smb_rw_wend(). Also initialize the counter that it uses 339 * to figure out what value to fill in. 340 * 341 * Note that the word count happens to be 8-bit. 342 */ 343 void 344 smb_rq_wstart(struct smb_rq *rqp) 345 { 346 rqp->sr_wcount = mb_reserve(&rqp->sr_rq, sizeof (uint8_t)); 347 rqp->sr_rq.mb_count = 0; 348 } 349 350 void 351 smb_rq_wend(struct smb_rq *rqp) 352 { 353 uint_t wcnt; 354 355 if (rqp->sr_wcount == NULL) { 356 SMBSDEBUG("no wcount\n"); 357 return; 358 } 359 wcnt = rqp->sr_rq.mb_count; 360 if (wcnt > 0x1ff) 361 SMBSDEBUG("word count too large (%d)\n", wcnt); 362 if (wcnt & 1) 363 SMBSDEBUG("odd word count\n"); 364 /* Fill in the word count (8-bits) */ 365 *rqp->sr_wcount = (wcnt >> 1); 366 } 367 368 /* 369 * Mark location of the byte count, which is filled in later by 370 * smb_rw_bend(). Also initialize the counter that it uses 371 * to figure out what value to fill in. 372 * 373 * Note that the byte count happens to be 16-bit. 374 */ 375 void 376 smb_rq_bstart(struct smb_rq *rqp) 377 { 378 rqp->sr_bcount = mb_reserve(&rqp->sr_rq, sizeof (uint16_t)); 379 rqp->sr_rq.mb_count = 0; 380 } 381 382 void 383 smb_rq_bend(struct smb_rq *rqp) 384 { 385 uint_t bcnt; 386 387 if (rqp->sr_bcount == NULL) { 388 SMBSDEBUG("no bcount\n"); 389 return; 390 } 391 bcnt = rqp->sr_rq.mb_count; 392 if (bcnt > 0xffff) 393 SMBSDEBUG("byte count too large (%d)\n", bcnt); 394 /* 395 * Fill in the byte count (16-bits) 396 * The pointer is char * type due to 397 * typical off-by-one alignment. 398 */ 399 rqp->sr_bcount[0] = bcnt & 0xFF; 400 rqp->sr_bcount[1] = (bcnt >> 8); 401 } 402 403 int 404 smb_rq_intr(struct smb_rq *rqp) 405 { 406 if (rqp->sr_flags & SMBR_INTR) 407 return (EINTR); 408 409 return (0); 410 } 411 412 static int 413 smb_rq_getenv(struct smb_connobj *co, 414 struct smb_vc **vcpp, struct smb_share **sspp) 415 { 416 struct smb_vc *vcp = NULL; 417 struct smb_share *ssp = NULL; 418 int error = EINVAL; 419 420 if (co->co_flags & SMBO_GONE) { 421 SMBSDEBUG("zombie CO\n"); 422 error = EINVAL; 423 goto out; 424 } 425 426 switch (co->co_level) { 427 case SMBL_SHARE: 428 ssp = CPTOSS(co); 429 if ((co->co_flags & SMBO_GONE) || 430 co->co_parent == NULL) { 431 SMBSDEBUG("zombie share %s\n", ssp->ss_name); 432 break; 433 } 434 /* instead of recursion... */ 435 co = co->co_parent; 436 /* FALLTHROUGH */ 437 case SMBL_VC: 438 vcp = CPTOVC(co); 439 if ((co->co_flags & SMBO_GONE) || 440 co->co_parent == NULL) { 441 SMBSDEBUG("zombie VC %s\n", vcp->vc_srvname); 442 break; 443 } 444 error = 0; 445 break; 446 447 default: 448 SMBSDEBUG("invalid level %d passed\n", co->co_level); 449 } 450 451 out: 452 if (!error) { 453 if (vcpp) 454 *vcpp = vcp; 455 if (sspp) 456 *sspp = ssp; 457 } 458 459 return (error); 460 } 461 462 /* 463 * Wait for reply on the request 464 */ 465 static int 466 smb_rq_reply(struct smb_rq *rqp) 467 { 468 struct mdchain *mdp = &rqp->sr_rp; 469 u_int8_t tb; 470 int error, rperror = 0; 471 472 if (rqp->sr_timo == SMBNOREPLYWAIT) 473 return (smb_iod_removerq(rqp)); 474 475 error = smb_iod_waitrq(rqp); 476 if (error) 477 return (error); 478 479 /* 480 * If the request was signed, validate the 481 * signature on the response. 482 */ 483 if (rqp->sr_rqflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) { 484 error = smb_rq_verify(rqp); 485 if (error) 486 return (error); 487 } 488 489 /* 490 * Parse the SMB header 491 */ 492 error = md_get_uint32le(mdp, NULL); 493 if (error) 494 return (error); 495 error = md_get_uint8(mdp, &tb); 496 error = md_get_uint32le(mdp, &rqp->sr_error); 497 error = md_get_uint8(mdp, &rqp->sr_rpflags); 498 error = md_get_uint16le(mdp, &rqp->sr_rpflags2); 499 if (rqp->sr_rpflags2 & SMB_FLAGS2_ERR_STATUS) { 500 /* 501 * Do a special check for STATUS_BUFFER_OVERFLOW; 502 * it's not an error. 503 */ 504 if (rqp->sr_error == NT_STATUS_BUFFER_OVERFLOW) { 505 /* 506 * Don't report it as an error to our caller; 507 * they can look at rqp->sr_error if they 508 * need to know whether we got a 509 * STATUS_BUFFER_OVERFLOW. 510 * XXX - should we do that for all errors 511 * where (error & 0xC0000000) is 0x80000000, 512 * i.e. all warnings? 513 */ 514 rperror = 0; 515 } else 516 rperror = smb_maperr32(rqp->sr_error); 517 } else { 518 rqp->sr_errclass = rqp->sr_error & 0xff; 519 rqp->sr_serror = rqp->sr_error >> 16; 520 rperror = smb_maperror(rqp->sr_errclass, rqp->sr_serror); 521 } 522 if (rperror == EMOREDATA) { 523 rperror = E2BIG; 524 rqp->sr_flags |= SMBR_MOREDATA; 525 } else 526 rqp->sr_flags &= ~SMBR_MOREDATA; 527 528 error = md_get_uint32le(mdp, NULL); 529 error = md_get_uint32le(mdp, NULL); 530 error = md_get_uint32le(mdp, NULL); 531 532 error = md_get_uint16le(mdp, &rqp->sr_rptid); 533 error = md_get_uint16le(mdp, &rqp->sr_rppid); 534 error = md_get_uint16le(mdp, &rqp->sr_rpuid); 535 error = md_get_uint16le(mdp, &rqp->sr_rpmid); 536 537 SMBSDEBUG("M:%04x, P:%04x, U:%04x, T:%04x, E: %d:%d\n", 538 rqp->sr_rpmid, rqp->sr_rppid, rqp->sr_rpuid, rqp->sr_rptid, 539 rqp->sr_errclass, rqp->sr_serror); 540 541 return ((error) ? error : rperror); 542 } 543 544 545 #define ALIGN4(a) (((a) + 3) & ~3) 546 547 /* 548 * TRANS2 request implementation 549 * TRANS implementation is in the "t2" routines 550 * NT_TRANSACTION implementation is the separate "nt" stuff 551 */ 552 int 553 smb_t2_alloc(struct smb_connobj *layer, ushort_t setup, struct smb_cred *scred, 554 struct smb_t2rq **t2pp) 555 { 556 struct smb_t2rq *t2p; 557 int error; 558 559 t2p = (struct smb_t2rq *)kmem_alloc(sizeof (*t2p), KM_SLEEP); 560 if (t2p == NULL) 561 return (ENOMEM); 562 error = smb_t2_init(t2p, layer, &setup, 1, scred); 563 t2p->t2_flags |= SMBT2_ALLOCED; 564 if (error) { 565 smb_t2_done(t2p); 566 return (error); 567 } 568 *t2pp = t2p; 569 return (0); 570 } 571 572 int 573 smb_nt_alloc(struct smb_connobj *layer, ushort_t fn, struct smb_cred *scred, 574 struct smb_ntrq **ntpp) 575 { 576 struct smb_ntrq *ntp; 577 int error; 578 579 ntp = (struct smb_ntrq *)kmem_alloc(sizeof (*ntp), KM_SLEEP); 580 if (ntp == NULL) 581 return (ENOMEM); 582 error = smb_nt_init(ntp, layer, fn, scred); 583 mutex_init(&ntp->nt_lock, NULL, MUTEX_DRIVER, NULL); 584 cv_init(&ntp->nt_cond, NULL, CV_DEFAULT, NULL); 585 ntp->nt_flags |= SMBT2_ALLOCED; 586 if (error) { 587 smb_nt_done(ntp); 588 return (error); 589 } 590 *ntpp = ntp; 591 return (0); 592 } 593 594 int 595 smb_t2_init(struct smb_t2rq *t2p, struct smb_connobj *source, ushort_t *setup, 596 int setupcnt, struct smb_cred *scred) 597 { 598 int i; 599 int error; 600 601 bzero(t2p, sizeof (*t2p)); 602 mutex_init(&t2p->t2_lock, NULL, MUTEX_DRIVER, NULL); 603 cv_init(&t2p->t2_cond, NULL, CV_DEFAULT, NULL); 604 605 t2p->t2_source = source; 606 t2p->t2_setupcount = (u_int16_t)setupcnt; 607 t2p->t2_setupdata = t2p->t2_setup; 608 for (i = 0; i < setupcnt; i++) 609 t2p->t2_setup[i] = setup[i]; 610 t2p->t2_fid = 0xffff; 611 t2p->t2_cred = scred; 612 t2p->t2_share = (source->co_level == SMBL_SHARE ? 613 CPTOSS(source) : NULL); /* for smb up/down */ 614 error = smb_rq_getenv(source, &t2p->t2_vc, NULL); 615 if (error) 616 return (error); 617 return (0); 618 } 619 620 int 621 smb_nt_init(struct smb_ntrq *ntp, struct smb_connobj *source, ushort_t fn, 622 struct smb_cred *scred) 623 { 624 int error; 625 626 bzero(ntp, sizeof (*ntp)); 627 ntp->nt_source = source; 628 ntp->nt_function = fn; 629 ntp->nt_cred = scred; 630 ntp->nt_share = (source->co_level == SMBL_SHARE ? 631 CPTOSS(source) : NULL); /* for smb up/down */ 632 error = smb_rq_getenv(source, &ntp->nt_vc, NULL); 633 if (error) 634 return (error); 635 return (0); 636 } 637 638 void 639 smb_t2_done(struct smb_t2rq *t2p) 640 { 641 mb_done(&t2p->t2_tparam); 642 mb_done(&t2p->t2_tdata); 643 md_done(&t2p->t2_rparam); 644 md_done(&t2p->t2_rdata); 645 mutex_destroy(&t2p->t2_lock); 646 cv_destroy(&t2p->t2_cond); 647 if (t2p->t2_flags & SMBT2_ALLOCED) 648 kmem_free(t2p, sizeof (*t2p)); 649 } 650 651 u_int32_t 652 smb_t2_err(struct smb_t2rq *t2p) 653 { 654 /* mask off "severity" and the "component" bit */ 655 return (t2p->t2_sr_error & ~(0xe0000000)); 656 } 657 658 void 659 smb_nt_done(struct smb_ntrq *ntp) 660 { 661 mb_done(&ntp->nt_tsetup); 662 mb_done(&ntp->nt_tparam); 663 mb_done(&ntp->nt_tdata); 664 md_done(&ntp->nt_rparam); 665 md_done(&ntp->nt_rdata); 666 cv_destroy(&ntp->nt_cond); 667 mutex_destroy(&ntp->nt_lock); 668 if (ntp->nt_flags & SMBT2_ALLOCED) 669 kmem_free(ntp, sizeof (*ntp)); 670 } 671 672 /* 673 * Extract data [offset,count] from mtop and add to mdp. 674 */ 675 static int 676 smb_t2_placedata(mblk_t *mtop, u_int16_t offset, u_int16_t count, 677 struct mdchain *mdp) 678 { 679 mblk_t *n; 680 681 n = m_copym(mtop, offset, count, M_WAITOK); 682 if (n == NULL) 683 return (EBADRPC); 684 685 if (mdp->md_top == NULL) { 686 md_initm(mdp, n); 687 } else 688 m_cat(mdp->md_top, n); 689 690 return (0); 691 } 692 693 static int 694 smb_t2_reply(struct smb_t2rq *t2p) 695 { 696 struct mdchain *mdp; 697 struct smb_rq *rqp = t2p->t2_rq; 698 int error, error2, totpgot, totdgot; 699 u_int16_t totpcount, totdcount, pcount, poff, doff, pdisp, ddisp; 700 u_int16_t tmp, bc, dcount; 701 u_int8_t wc; 702 703 t2p->t2_flags &= ~SMBT2_MOREDATA; 704 705 error = smb_rq_reply(rqp); 706 if (rqp->sr_flags & SMBR_MOREDATA) 707 t2p->t2_flags |= SMBT2_MOREDATA; 708 t2p->t2_sr_errclass = rqp->sr_errclass; 709 t2p->t2_sr_serror = rqp->sr_serror; 710 t2p->t2_sr_error = rqp->sr_error; 711 t2p->t2_sr_rpflags2 = rqp->sr_rpflags2; 712 if (error && !(rqp->sr_flags & SMBR_MOREDATA)) 713 return (error); 714 /* 715 * Now we have to get all subseqent responses, if any. 716 * The CIFS specification says that they can be misordered, 717 * which is weird. 718 * TODO: timo 719 */ 720 totpgot = totdgot = 0; 721 totpcount = totdcount = 0xffff; 722 mdp = &rqp->sr_rp; 723 for (;;) { 724 DTRACE_PROBE2(smb_trans_reply, 725 (smb_rq_t *), rqp, (mblk_t *), mdp->md_top); 726 m_dumpm(mdp->md_top); 727 728 if ((error2 = md_get_uint8(mdp, &wc)) != 0) 729 break; 730 if (wc < 10) { 731 error2 = ENOENT; 732 break; 733 } 734 if ((error2 = md_get_uint16le(mdp, &tmp)) != 0) 735 break; 736 if (totpcount > tmp) 737 totpcount = tmp; 738 if ((error2 = md_get_uint16le(mdp, &tmp)) != 0) 739 break; 740 if (totdcount > tmp) 741 totdcount = tmp; 742 if ((error2 = md_get_uint16le(mdp, &tmp)) != 0 || /* reserved */ 743 (error2 = md_get_uint16le(mdp, &pcount)) != 0 || 744 (error2 = md_get_uint16le(mdp, &poff)) != 0 || 745 (error2 = md_get_uint16le(mdp, &pdisp)) != 0) 746 break; 747 if (pcount != 0 && pdisp != totpgot) { 748 SMBSDEBUG("Can't handle misordered parameters %d:%d\n", 749 pdisp, totpgot); 750 error2 = EINVAL; 751 break; 752 } 753 if ((error2 = md_get_uint16le(mdp, &dcount)) != 0 || 754 (error2 = md_get_uint16le(mdp, &doff)) != 0 || 755 (error2 = md_get_uint16le(mdp, &ddisp)) != 0) 756 break; 757 if (dcount != 0 && ddisp != totdgot) { 758 SMBSDEBUG("Can't handle misordered data: dcount %d\n", 759 dcount); 760 error2 = EINVAL; 761 break; 762 } 763 764 /* XXX: Skip setup words? We don't save them? */ 765 md_get_uint8(mdp, &wc); /* SetupCount */ 766 md_get_uint8(mdp, NULL); /* Reserved2 */ 767 tmp = wc; 768 while (tmp--) 769 md_get_uint16le(mdp, NULL); 770 771 if ((error2 = md_get_uint16le(mdp, &bc)) != 0) 772 break; 773 774 /* 775 * There are pad bytes here, and the poff value 776 * indicates where the next data are found. 777 * No need to guess at the padding size. 778 */ 779 if (pcount) { 780 error2 = smb_t2_placedata(mdp->md_top, poff, 781 pcount, &t2p->t2_rparam); 782 if (error2) 783 break; 784 } 785 totpgot += pcount; 786 787 if (dcount) { 788 error2 = smb_t2_placedata(mdp->md_top, doff, 789 dcount, &t2p->t2_rdata); 790 if (error2) 791 break; 792 } 793 totdgot += dcount; 794 795 if (totpgot >= totpcount && totdgot >= totdcount) { 796 error2 = 0; 797 t2p->t2_flags |= SMBT2_ALLRECV; 798 break; 799 } 800 /* 801 * We're done with this reply, look for the next one. 802 */ 803 SMBRQ_LOCK(rqp); 804 md_next_record(&rqp->sr_rp); 805 SMBRQ_UNLOCK(rqp); 806 error2 = smb_rq_reply(rqp); 807 if (rqp->sr_flags & SMBR_MOREDATA) 808 t2p->t2_flags |= SMBT2_MOREDATA; 809 if (!error2) 810 continue; 811 t2p->t2_sr_errclass = rqp->sr_errclass; 812 t2p->t2_sr_serror = rqp->sr_serror; 813 t2p->t2_sr_error = rqp->sr_error; 814 t2p->t2_sr_rpflags2 = rqp->sr_rpflags2; 815 error = error2; 816 if (!(rqp->sr_flags & SMBR_MOREDATA)) 817 break; 818 } 819 return (error ? error : error2); 820 } 821 822 static int 823 smb_nt_reply(struct smb_ntrq *ntp) 824 { 825 struct mdchain *mdp; 826 struct smb_rq *rqp = ntp->nt_rq; 827 int error, error2; 828 u_int32_t totpcount, totdcount, pcount, poff, doff, pdisp, ddisp; 829 u_int32_t tmp, dcount, totpgot, totdgot; 830 u_int16_t bc; 831 u_int8_t wc; 832 833 ntp->nt_flags &= ~SMBT2_MOREDATA; 834 835 error = smb_rq_reply(rqp); 836 if (rqp->sr_flags & SMBR_MOREDATA) 837 ntp->nt_flags |= SMBT2_MOREDATA; 838 ntp->nt_sr_error = rqp->sr_error; 839 ntp->nt_sr_rpflags2 = rqp->sr_rpflags2; 840 if (error && !(rqp->sr_flags & SMBR_MOREDATA)) 841 return (error); 842 /* 843 * Now we have to get all subseqent responses. The CIFS specification 844 * says that they can be misordered which is weird. 845 * TODO: timo 846 */ 847 totpgot = totdgot = 0; 848 totpcount = totdcount = 0xffffffff; 849 mdp = &rqp->sr_rp; 850 for (;;) { 851 DTRACE_PROBE2(smb_trans_reply, 852 (smb_rq_t *), rqp, (mblk_t *), mdp->md_top); 853 m_dumpm(mdp->md_top); 854 855 if ((error2 = md_get_uint8(mdp, &wc)) != 0) 856 break; 857 if (wc < 18) { 858 error2 = ENOENT; 859 break; 860 } 861 md_get_mem(mdp, NULL, 3, MB_MSYSTEM); /* reserved */ 862 if ((error2 = md_get_uint32le(mdp, &tmp)) != 0) 863 break; 864 if (totpcount > tmp) 865 totpcount = tmp; 866 if ((error2 = md_get_uint32le(mdp, &tmp)) != 0) 867 break; 868 if (totdcount > tmp) 869 totdcount = tmp; 870 if ((error2 = md_get_uint32le(mdp, &pcount)) != 0 || 871 (error2 = md_get_uint32le(mdp, &poff)) != 0 || 872 (error2 = md_get_uint32le(mdp, &pdisp)) != 0) 873 break; 874 if (pcount != 0 && pdisp != totpgot) { 875 SMBSDEBUG("Can't handle misordered parameters %d:%d\n", 876 pdisp, totpgot); 877 error2 = EINVAL; 878 break; 879 } 880 if ((error2 = md_get_uint32le(mdp, &dcount)) != 0 || 881 (error2 = md_get_uint32le(mdp, &doff)) != 0 || 882 (error2 = md_get_uint32le(mdp, &ddisp)) != 0) 883 break; 884 if (dcount != 0 && ddisp != totdgot) { 885 SMBSDEBUG("Can't handle misordered data: dcount %d\n", 886 dcount); 887 error2 = EINVAL; 888 break; 889 } 890 891 /* XXX: Skip setup words? We don't save them? */ 892 md_get_uint8(mdp, &wc); /* SetupCount */ 893 tmp = wc; 894 while (tmp--) 895 md_get_uint16le(mdp, NULL); 896 897 if ((error2 = md_get_uint16le(mdp, &bc)) != 0) 898 break; 899 900 /* 901 * There are pad bytes here, and the poff value 902 * indicates where the next data are found. 903 * No need to guess at the padding size. 904 */ 905 if (pcount) { 906 error2 = smb_t2_placedata(mdp->md_top, poff, pcount, 907 &ntp->nt_rparam); 908 if (error2) 909 break; 910 } 911 totpgot += pcount; 912 913 if (dcount) { 914 error2 = smb_t2_placedata(mdp->md_top, doff, dcount, 915 &ntp->nt_rdata); 916 if (error2) 917 break; 918 } 919 totdgot += dcount; 920 921 if (totpgot >= totpcount && totdgot >= totdcount) { 922 error2 = 0; 923 ntp->nt_flags |= SMBT2_ALLRECV; 924 break; 925 } 926 /* 927 * We're done with this reply, look for the next one. 928 */ 929 SMBRQ_LOCK(rqp); 930 md_next_record(&rqp->sr_rp); 931 SMBRQ_UNLOCK(rqp); 932 error2 = smb_rq_reply(rqp); 933 if (rqp->sr_flags & SMBR_MOREDATA) 934 ntp->nt_flags |= SMBT2_MOREDATA; 935 if (!error2) 936 continue; 937 ntp->nt_sr_error = rqp->sr_error; 938 ntp->nt_sr_rpflags2 = rqp->sr_rpflags2; 939 error = error2; 940 if (!(rqp->sr_flags & SMBR_MOREDATA)) 941 break; 942 } 943 return (error ? error : error2); 944 } 945 946 /* 947 * Perform a full round of TRANS2 request 948 */ 949 static int 950 smb_t2_request_int(struct smb_t2rq *t2p) 951 { 952 struct smb_vc *vcp = t2p->t2_vc; 953 struct smb_cred *scred = t2p->t2_cred; 954 struct mbchain *mbp; 955 struct mdchain *mdp, mbparam, mbdata; 956 mblk_t *m; 957 struct smb_rq *rqp; 958 int totpcount, leftpcount, totdcount, leftdcount, len, txmax, i; 959 int error, doff, poff, txdcount, txpcount, nmlen, nmsize; 960 961 m = t2p->t2_tparam.mb_top; 962 if (m) { 963 md_initm(&mbparam, m); /* do not free it! */ 964 totpcount = m_fixhdr(m); 965 if (totpcount > 0xffff) /* maxvalue for ushort_t */ 966 return (EINVAL); 967 } else 968 totpcount = 0; 969 m = t2p->t2_tdata.mb_top; 970 if (m) { 971 md_initm(&mbdata, m); /* do not free it! */ 972 totdcount = m_fixhdr(m); 973 if (totdcount > 0xffff) 974 return (EINVAL); 975 } else 976 totdcount = 0; 977 leftdcount = totdcount; 978 leftpcount = totpcount; 979 txmax = vcp->vc_txmax; 980 error = smb_rq_alloc(t2p->t2_source, t2p->t_name ? 981 SMB_COM_TRANSACTION : SMB_COM_TRANSACTION2, scred, &rqp); 982 if (error) 983 return (error); 984 rqp->sr_timo = smb_timo_default; 985 rqp->sr_flags |= SMBR_MULTIPACKET; 986 t2p->t2_rq = rqp; 987 mbp = &rqp->sr_rq; 988 smb_rq_wstart(rqp); 989 mb_put_uint16le(mbp, totpcount); 990 mb_put_uint16le(mbp, totdcount); 991 mb_put_uint16le(mbp, t2p->t2_maxpcount); 992 mb_put_uint16le(mbp, t2p->t2_maxdcount); 993 mb_put_uint8(mbp, t2p->t2_maxscount); 994 mb_put_uint8(mbp, 0); /* reserved */ 995 mb_put_uint16le(mbp, 0); /* flags */ 996 mb_put_uint32le(mbp, 0); /* Timeout */ 997 mb_put_uint16le(mbp, 0); /* reserved 2 */ 998 len = mb_fixhdr(mbp); 999 1000 /* 1001 * Now we know the size of the trans overhead stuff: 1002 * ALIGN4(len + 5 * 2 + setupcount * 2 + 2 + nmsize), 1003 * where nmsize is the OTW size of the name, including 1004 * the unicode null terminator and any alignment. 1005 * Use this to decide which parts (and how much) 1006 * can go into this request: params, data 1007 */ 1008 nmlen = t2p->t_name ? t2p->t_name_len : 0; 1009 nmsize = nmlen + 1; /* null term. */ 1010 if (SMB_UNICODE_STRINGS(vcp)) { 1011 nmsize *= 2; 1012 /* we know put_dmem will need to align */ 1013 nmsize += 1; 1014 } 1015 len = ALIGN4(len + 5 * 2 + t2p->t2_setupcount * 2 + 2 + nmsize); 1016 if (len + leftpcount > txmax) { 1017 txpcount = min(leftpcount, txmax - len); 1018 poff = len; 1019 txdcount = 0; 1020 doff = 0; 1021 } else { 1022 txpcount = leftpcount; 1023 poff = txpcount ? len : 0; 1024 /* 1025 * Other client traffic seems to "ALIGN2" here. The extra 1026 * 2 byte pad we use has no observed downside and may be 1027 * required for some old servers(?) 1028 */ 1029 len = ALIGN4(len + txpcount); 1030 txdcount = min(leftdcount, txmax - len); 1031 doff = txdcount ? len : 0; 1032 } 1033 leftpcount -= txpcount; 1034 leftdcount -= txdcount; 1035 mb_put_uint16le(mbp, txpcount); 1036 mb_put_uint16le(mbp, poff); 1037 mb_put_uint16le(mbp, txdcount); 1038 mb_put_uint16le(mbp, doff); 1039 mb_put_uint8(mbp, t2p->t2_setupcount); 1040 mb_put_uint8(mbp, 0); 1041 for (i = 0; i < t2p->t2_setupcount; i++) { 1042 mb_put_uint16le(mbp, t2p->t2_setupdata[i]); 1043 } 1044 smb_rq_wend(rqp); 1045 smb_rq_bstart(rqp); 1046 if (t2p->t_name) { 1047 /* Put the string and terminating null. */ 1048 smb_put_dmem(mbp, vcp, t2p->t_name, nmlen + 1, 1049 SMB_CS_NONE, NULL); 1050 } else { 1051 /* nmsize accounts for padding, char size. */ 1052 mb_put_mem(mbp, NULL, nmsize, MB_MZERO); 1053 } 1054 len = mb_fixhdr(mbp); 1055 if (txpcount) { 1056 mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); 1057 error = md_get_mbuf(&mbparam, txpcount, &m); 1058 SMBSDEBUG("%d:%d:%d\n", error, txpcount, txmax); 1059 if (error) 1060 goto freerq; 1061 mb_put_mbuf(mbp, m); 1062 } 1063 len = mb_fixhdr(mbp); 1064 if (txdcount) { 1065 mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); 1066 error = md_get_mbuf(&mbdata, txdcount, &m); 1067 if (error) 1068 goto freerq; 1069 mb_put_mbuf(mbp, m); 1070 } 1071 smb_rq_bend(rqp); /* incredible, but thats it... */ 1072 error = smb_rq_enqueue(rqp); 1073 if (error) 1074 goto freerq; 1075 if (leftpcount || leftdcount) { 1076 error = smb_rq_reply(rqp); 1077 if (error) 1078 goto bad; 1079 /* 1080 * this is an interim response, ignore it. 1081 */ 1082 SMBRQ_LOCK(rqp); 1083 md_next_record(&rqp->sr_rp); 1084 SMBRQ_UNLOCK(rqp); 1085 } 1086 while (leftpcount || leftdcount) { 1087 error = smb_rq_new(rqp, t2p->t_name ? 1088 SMB_COM_TRANSACTION_SECONDARY : 1089 SMB_COM_TRANSACTION2_SECONDARY); 1090 if (error) 1091 goto bad; 1092 mbp = &rqp->sr_rq; 1093 smb_rq_wstart(rqp); 1094 mb_put_uint16le(mbp, totpcount); 1095 mb_put_uint16le(mbp, totdcount); 1096 len = mb_fixhdr(mbp); 1097 /* 1098 * now we have known packet size as 1099 * ALIGN4(len + 7 * 2 + 2) for T2 request, and -2 for T one, 1100 * and need to decide which parts should go into request 1101 */ 1102 len = ALIGN4(len + 6 * 2 + 2); 1103 if (t2p->t_name == NULL) 1104 len += 2; 1105 if (len + leftpcount > txmax) { 1106 txpcount = min(leftpcount, txmax - len); 1107 poff = len; 1108 txdcount = 0; 1109 doff = 0; 1110 } else { 1111 txpcount = leftpcount; 1112 poff = txpcount ? len : 0; 1113 len = ALIGN4(len + txpcount); 1114 txdcount = min(leftdcount, txmax - len); 1115 doff = txdcount ? len : 0; 1116 } 1117 mb_put_uint16le(mbp, txpcount); 1118 mb_put_uint16le(mbp, poff); 1119 mb_put_uint16le(mbp, totpcount - leftpcount); 1120 mb_put_uint16le(mbp, txdcount); 1121 mb_put_uint16le(mbp, doff); 1122 mb_put_uint16le(mbp, totdcount - leftdcount); 1123 leftpcount -= txpcount; 1124 leftdcount -= txdcount; 1125 if (t2p->t_name == NULL) 1126 mb_put_uint16le(mbp, t2p->t2_fid); 1127 smb_rq_wend(rqp); 1128 smb_rq_bstart(rqp); 1129 mb_put_uint8(mbp, 0); /* name */ 1130 len = mb_fixhdr(mbp); 1131 if (txpcount) { 1132 mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); 1133 error = md_get_mbuf(&mbparam, txpcount, &m); 1134 if (error) 1135 goto bad; 1136 mb_put_mbuf(mbp, m); 1137 } 1138 len = mb_fixhdr(mbp); 1139 if (txdcount) { 1140 mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); 1141 error = md_get_mbuf(&mbdata, txdcount, &m); 1142 if (error) 1143 goto bad; 1144 mb_put_mbuf(mbp, m); 1145 } 1146 smb_rq_bend(rqp); 1147 error = smb_iod_multirq(rqp); 1148 if (error) 1149 goto bad; 1150 } /* while left params or data */ 1151 error = smb_t2_reply(t2p); 1152 if (error && !(t2p->t2_flags & SMBT2_MOREDATA)) 1153 goto bad; 1154 mdp = &t2p->t2_rdata; 1155 if (mdp->md_top) { 1156 m_fixhdr(mdp->md_top); 1157 md_initm(mdp, mdp->md_top); 1158 } 1159 mdp = &t2p->t2_rparam; 1160 if (mdp->md_top) { 1161 m_fixhdr(mdp->md_top); 1162 md_initm(mdp, mdp->md_top); 1163 } 1164 bad: 1165 smb_iod_removerq(rqp); 1166 freerq: 1167 if (error && !(t2p->t2_flags & SMBT2_MOREDATA)) { 1168 if (rqp->sr_flags & SMBR_RESTART) 1169 t2p->t2_flags |= SMBT2_RESTART; 1170 md_done(&t2p->t2_rparam); 1171 md_done(&t2p->t2_rdata); 1172 } 1173 smb_rq_done(rqp); 1174 return (error); 1175 } 1176 1177 1178 /* 1179 * Perform a full round of NT_TRANSACTION request 1180 */ 1181 static int 1182 smb_nt_request_int(struct smb_ntrq *ntp) 1183 { 1184 struct smb_vc *vcp = ntp->nt_vc; 1185 struct smb_cred *scred = ntp->nt_cred; 1186 struct mbchain *mbp; 1187 struct mdchain *mdp, mbsetup, mbparam, mbdata; 1188 mblk_t *m; 1189 struct smb_rq *rqp; 1190 int totpcount, leftpcount, totdcount, leftdcount, len, txmax; 1191 int error, doff, poff, txdcount, txpcount; 1192 int totscount; 1193 1194 m = ntp->nt_tsetup.mb_top; 1195 if (m) { 1196 md_initm(&mbsetup, m); /* do not free it! */ 1197 totscount = m_fixhdr(m); 1198 if (totscount > 2 * 0xff) 1199 return (EINVAL); 1200 } else 1201 totscount = 0; 1202 m = ntp->nt_tparam.mb_top; 1203 if (m) { 1204 md_initm(&mbparam, m); /* do not free it! */ 1205 totpcount = m_fixhdr(m); 1206 if (totpcount > 0x7fffffff) 1207 return (EINVAL); 1208 } else 1209 totpcount = 0; 1210 m = ntp->nt_tdata.mb_top; 1211 if (m) { 1212 md_initm(&mbdata, m); /* do not free it! */ 1213 totdcount = m_fixhdr(m); 1214 if (totdcount > 0x7fffffff) 1215 return (EINVAL); 1216 } else 1217 totdcount = 0; 1218 leftdcount = totdcount; 1219 leftpcount = totpcount; 1220 txmax = vcp->vc_txmax; 1221 error = smb_rq_alloc(ntp->nt_source, SMB_COM_NT_TRANSACT, scred, &rqp); 1222 if (error) 1223 return (error); 1224 rqp->sr_timo = smb_timo_default; 1225 rqp->sr_flags |= SMBR_MULTIPACKET; 1226 ntp->nt_rq = rqp; 1227 mbp = &rqp->sr_rq; 1228 smb_rq_wstart(rqp); 1229 mb_put_uint8(mbp, ntp->nt_maxscount); 1230 mb_put_uint16le(mbp, 0); /* reserved (flags?) */ 1231 mb_put_uint32le(mbp, totpcount); 1232 mb_put_uint32le(mbp, totdcount); 1233 mb_put_uint32le(mbp, ntp->nt_maxpcount); 1234 mb_put_uint32le(mbp, ntp->nt_maxdcount); 1235 len = mb_fixhdr(mbp); 1236 /* 1237 * now we have known packet size as 1238 * ALIGN4(len + 4 * 4 + 1 + 2 + ((totscount+1)&~1) + 2), 1239 * and need to decide which parts should go into the first request 1240 */ 1241 len = ALIGN4(len + 4 * 4 + 1 + 2 + ((totscount+1)&~1) + 2); 1242 if (len + leftpcount > txmax) { 1243 txpcount = min(leftpcount, txmax - len); 1244 poff = len; 1245 txdcount = 0; 1246 doff = 0; 1247 } else { 1248 txpcount = leftpcount; 1249 poff = txpcount ? len : 0; 1250 len = ALIGN4(len + txpcount); 1251 txdcount = min(leftdcount, txmax - len); 1252 doff = txdcount ? len : 0; 1253 } 1254 leftpcount -= txpcount; 1255 leftdcount -= txdcount; 1256 mb_put_uint32le(mbp, txpcount); 1257 mb_put_uint32le(mbp, poff); 1258 mb_put_uint32le(mbp, txdcount); 1259 mb_put_uint32le(mbp, doff); 1260 mb_put_uint8(mbp, (totscount+1)/2); 1261 mb_put_uint16le(mbp, ntp->nt_function); 1262 if (totscount) { 1263 error = md_get_mbuf(&mbsetup, totscount, &m); 1264 SMBSDEBUG("%d:%d:%d\n", error, totscount, txmax); 1265 if (error) 1266 goto freerq; 1267 mb_put_mbuf(mbp, m); 1268 if (totscount & 1) 1269 mb_put_uint8(mbp, 0); /* setup is in words */ 1270 } 1271 smb_rq_wend(rqp); 1272 smb_rq_bstart(rqp); 1273 len = mb_fixhdr(mbp); 1274 if (txpcount) { 1275 mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); 1276 error = md_get_mbuf(&mbparam, txpcount, &m); 1277 SMBSDEBUG("%d:%d:%d\n", error, txpcount, txmax); 1278 if (error) 1279 goto freerq; 1280 mb_put_mbuf(mbp, m); 1281 } 1282 len = mb_fixhdr(mbp); 1283 if (txdcount) { 1284 mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); 1285 error = md_get_mbuf(&mbdata, txdcount, &m); 1286 if (error) 1287 goto freerq; 1288 mb_put_mbuf(mbp, m); 1289 } 1290 smb_rq_bend(rqp); /* incredible, but thats it... */ 1291 error = smb_rq_enqueue(rqp); 1292 if (error) 1293 goto freerq; 1294 if (leftpcount || leftdcount) { 1295 error = smb_rq_reply(rqp); 1296 if (error) 1297 goto bad; 1298 /* 1299 * this is an interim response, ignore it. 1300 */ 1301 SMBRQ_LOCK(rqp); 1302 md_next_record(&rqp->sr_rp); 1303 SMBRQ_UNLOCK(rqp); 1304 } 1305 while (leftpcount || leftdcount) { 1306 error = smb_rq_new(rqp, SMB_COM_NT_TRANSACT_SECONDARY); 1307 if (error) 1308 goto bad; 1309 mbp = &rqp->sr_rq; 1310 smb_rq_wstart(rqp); 1311 mb_put_mem(mbp, NULL, 3, MB_MZERO); 1312 mb_put_uint32le(mbp, totpcount); 1313 mb_put_uint32le(mbp, totdcount); 1314 len = mb_fixhdr(mbp); 1315 /* 1316 * now we have known packet size as 1317 * ALIGN4(len + 6 * 4 + 2) 1318 * and need to decide which parts should go into request 1319 */ 1320 len = ALIGN4(len + 6 * 4 + 2); 1321 if (len + leftpcount > txmax) { 1322 txpcount = min(leftpcount, txmax - len); 1323 poff = len; 1324 txdcount = 0; 1325 doff = 0; 1326 } else { 1327 txpcount = leftpcount; 1328 poff = txpcount ? len : 0; 1329 len = ALIGN4(len + txpcount); 1330 txdcount = min(leftdcount, txmax - len); 1331 doff = txdcount ? len : 0; 1332 } 1333 mb_put_uint32le(mbp, txpcount); 1334 mb_put_uint32le(mbp, poff); 1335 mb_put_uint32le(mbp, totpcount - leftpcount); 1336 mb_put_uint32le(mbp, txdcount); 1337 mb_put_uint32le(mbp, doff); 1338 mb_put_uint32le(mbp, totdcount - leftdcount); 1339 leftpcount -= txpcount; 1340 leftdcount -= txdcount; 1341 smb_rq_wend(rqp); 1342 smb_rq_bstart(rqp); 1343 len = mb_fixhdr(mbp); 1344 if (txpcount) { 1345 mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); 1346 error = md_get_mbuf(&mbparam, txpcount, &m); 1347 if (error) 1348 goto bad; 1349 mb_put_mbuf(mbp, m); 1350 } 1351 len = mb_fixhdr(mbp); 1352 if (txdcount) { 1353 mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); 1354 error = md_get_mbuf(&mbdata, txdcount, &m); 1355 if (error) 1356 goto bad; 1357 mb_put_mbuf(mbp, m); 1358 } 1359 smb_rq_bend(rqp); 1360 error = smb_iod_multirq(rqp); 1361 if (error) 1362 goto bad; 1363 } /* while left params or data */ 1364 error = smb_nt_reply(ntp); 1365 if (error && !(ntp->nt_flags & SMBT2_MOREDATA)) 1366 goto bad; 1367 mdp = &ntp->nt_rdata; 1368 if (mdp->md_top) { 1369 m_fixhdr(mdp->md_top); 1370 md_initm(mdp, mdp->md_top); 1371 } 1372 mdp = &ntp->nt_rparam; 1373 if (mdp->md_top) { 1374 m_fixhdr(mdp->md_top); 1375 md_initm(mdp, mdp->md_top); 1376 } 1377 bad: 1378 smb_iod_removerq(rqp); 1379 freerq: 1380 if (error && !(ntp->nt_flags & SMBT2_MOREDATA)) { 1381 if (rqp->sr_flags & SMBR_RESTART) 1382 ntp->nt_flags |= SMBT2_RESTART; 1383 md_done(&ntp->nt_rparam); 1384 md_done(&ntp->nt_rdata); 1385 } 1386 smb_rq_done(rqp); 1387 return (error); 1388 } 1389 1390 int 1391 smb_t2_request(struct smb_t2rq *t2p) 1392 { 1393 int error = EINVAL, i; 1394 1395 for (i = 0; ; ) { 1396 /* 1397 * Don't send any new requests if force unmount is underway. 1398 * This check was moved into smb_rq_enqueue, called by 1399 * smb_t2_request_int() 1400 */ 1401 t2p->t2_flags &= ~SMBT2_RESTART; 1402 error = smb_t2_request_int(t2p); 1403 if (!error) 1404 break; 1405 if ((t2p->t2_flags & (SMBT2_RESTART | SMBT2_NORESTART)) != 1406 SMBT2_RESTART) 1407 break; 1408 if (++i > SMBMAXRESTARTS) 1409 break; 1410 mutex_enter(&(t2p)->t2_lock); 1411 if (t2p->t2_share) { 1412 cv_timedwait(&t2p->t2_cond, &(t2p)->t2_lock, 1413 lbolt + (hz * SMB_RCNDELAY)); 1414 } else { 1415 delay(lbolt + (hz * SMB_RCNDELAY)); 1416 } 1417 mutex_exit(&(t2p)->t2_lock); 1418 } 1419 return (error); 1420 } 1421 1422 1423 int 1424 smb_nt_request(struct smb_ntrq *ntp) 1425 { 1426 int error = EINVAL, i; 1427 1428 for (i = 0; ; ) { 1429 /* 1430 * Don't send any new requests if force unmount is underway. 1431 * This check was moved into smb_rq_enqueue, called by 1432 * smb_nt_request_int() 1433 */ 1434 ntp->nt_flags &= ~SMBT2_RESTART; 1435 error = smb_nt_request_int(ntp); 1436 if (!error) 1437 break; 1438 if ((ntp->nt_flags & (SMBT2_RESTART | SMBT2_NORESTART)) != 1439 SMBT2_RESTART) 1440 break; 1441 if (++i > SMBMAXRESTARTS) 1442 break; 1443 mutex_enter(&(ntp)->nt_lock); 1444 if (ntp->nt_share) { 1445 cv_timedwait(&ntp->nt_cond, &(ntp)->nt_lock, 1446 lbolt + (hz * SMB_RCNDELAY)); 1447 1448 } else { 1449 delay(lbolt + (hz * SMB_RCNDELAY)); 1450 } 1451 mutex_exit(&(ntp)->nt_lock); 1452 } 1453 return (error); 1454 } 1455