Print this page
NEX-14666 Need to provide SMB 2.1 Client
NEX-17187 panic in smbfs_acl_store
NEX-17231 smbfs create xattr files finds wrong file
NEX-17224 smbfs lookup EINVAL should be ENOENT
NEX-17260 SMB1 client fails to list directory after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
and: (cleanup)
NEX-16824 SMB client connection setup rework
NEX-17232 SMB client reconnect failures
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
and: (improve debug)

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.c
          +++ new/usr/src/uts/common/fs/smbclnt/netsmb/smb_rq.c
↓ open down ↓ 26 lines elided ↑ open up ↑
  27   27   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28   28   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29   29   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30   30   * SUCH DAMAGE.
  31   31   *
  32   32   * $Id: smb_rq.c,v 1.29 2005/02/11 01:44:17 lindak Exp $
  33   33   */
  34   34  
  35   35  /*
  36   36   * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
       37 + * Portions Copyright (C) 2001 - 2013 Apple Inc. All rights reserved.
       38 + * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  37   39   */
  38   40  
  39   41  #include <sys/param.h>
  40   42  #include <sys/systm.h>
  41   43  #include <sys/time.h>
  42   44  #include <sys/kmem.h>
  43   45  #include <sys/proc.h>
  44   46  #include <sys/lock.h>
  45   47  #include <sys/socket.h>
  46   48  #include <sys/mount.h>
  47   49  #include <sys/sunddi.h>
  48   50  #include <sys/cmn_err.h>
  49   51  #include <sys/sdt.h>
  50   52  
  51   53  #include <netsmb/smb_osdep.h>
  52   54  
  53   55  #include <netsmb/smb.h>
       56 +#include <netsmb/smb2.h>
  54   57  #include <netsmb/smb_conn.h>
  55   58  #include <netsmb/smb_subr.h>
  56   59  #include <netsmb/smb_tran.h>
  57   60  #include <netsmb/smb_rq.h>
       61 +#include <netsmb/smb2_rq.h>
  58   62  
  59   63  /*
  60   64   * How long to wait before restarting a request (after reconnect)
  61   65   */
  62   66  #define SMB_RCNDELAY            2       /* seconds */
  63   67  
  64   68  /*
  65   69   * leave this zero - we can't ssecond guess server side effects of
  66   70   * duplicate ops, this isn't nfs!
  67   71   */
  68   72  #define SMBMAXRESTARTS          0
  69   73  
  70   74  
  71   75  static int  smb_rq_reply(struct smb_rq *rqp);
       76 +static int  smb_rq_parsehdr(struct smb_rq *rqp);
  72   77  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   78  static int  smb_rq_new(struct smb_rq *rqp, uchar_t cmd);
  76   79  static int  smb_t2_reply(struct smb_t2rq *t2p);
  77   80  static int  smb_nt_reply(struct smb_ntrq *ntp);
  78   81  
  79   82  
  80   83  /*
  81   84   * Done with a request object.  Free its contents.
  82   85   * If it was allocated (SMBR_ALLOCED) free it too.
  83   86   * Some of these are stack locals, not allocated.
  84   87   *
↓ open down ↓ 14 lines elided ↑ open up ↑
  99  102                  kmem_free(rqp, sizeof (*rqp));
 100  103  }
 101  104  
 102  105  int
 103  106  smb_rq_alloc(struct smb_connobj *layer, uchar_t cmd, struct smb_cred *scred,
 104  107          struct smb_rq **rqpp)
 105  108  {
 106  109          struct smb_rq *rqp;
 107  110          int error;
 108  111  
      112 +        // XXX kmem cache?
 109  113          rqp = (struct smb_rq *)kmem_alloc(sizeof (struct smb_rq), KM_SLEEP);
 110  114          if (rqp == NULL)
 111  115                  return (ENOMEM);
 112  116          error = smb_rq_init(rqp, layer, cmd, scred);
 113  117          if (error) {
 114  118                  smb_rq_done(rqp);
 115  119                  return (error);
 116  120          }
 117  121          rqp->sr_flags |= SMBR_ALLOCED;
 118  122          *rqpp = rqp;
↓ open down ↓ 21 lines elided ↑ open up ↑
 140  144           * share or the VC as needed.  For smbfs callers,
 141  145           * the hold is on the share, via the smbfs mount.
 142  146           * For nsmb ioctl callers, the hold is done when
 143  147           * the driver handle gets VC or share references.
 144  148           * This design avoids frequent hold/rele activity
 145  149           * when creating and completing requests.
 146  150           */
 147  151  
 148  152          rqp->sr_rexmit = SMBMAXRESTARTS;
 149  153          rqp->sr_cred = scred;   /* Note: ref hold done by caller. */
 150      -        rqp->sr_pid = (uint16_t)ddi_get_pid();
 151  154          error = smb_rq_new(rqp, cmd);
 152  155  
 153  156          return (error);
 154  157  }
 155  158  
 156  159  static int
 157  160  smb_rq_new(struct smb_rq *rqp, uchar_t cmd)
 158  161  {
 159  162          struct mbchain *mbp = &rqp->sr_rq;
 160  163          struct smb_vc *vcp = rqp->sr_vc;
 161  164          int error;
 162  165  
 163  166          ASSERT(rqp != NULL);
 164  167  
 165  168          rqp->sr_sendcnt = 0;
 166      -        rqp->sr_cmd = cmd;
 167  169  
 168  170          mb_done(mbp);
 169  171          md_done(&rqp->sr_rp);
 170  172          error = mb_init(mbp);
 171  173          if (error)
 172  174                  return (error);
 173  175  
 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;
      176 +        if (vcp->vc_flags & SMBV_SMB2) {
      177 +                /*
      178 +                 * SMB2 request initialization
      179 +                 */
      180 +                rqp->sr2_command = cmd;
      181 +                rqp->sr2_creditcharge = 1;
      182 +                rqp->sr2_creditsrequested = 1;
      183 +                rqp->sr_pid = 0xFEFF;   /* Made up, just like Windows */
      184 +                rqp->sr2_rqflags = 0;
      185 +                if ((vcp->vc_flags & SMBV_SIGNING) != 0 &&
      186 +                    vcp->vc_mackey != NULL) {
      187 +                        rqp->sr2_rqflags |= SMB2_FLAGS_SIGNED;
      188 +                }
 179  189  
 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);
      190 +                /*
      191 +                 * The SMB2 header is filled in later by
      192 +                 * smb2_rq_fillhdr (see smb2_rq.c)
      193 +                 * Just reserve space here.
      194 +                 */
      195 +                mb_put_mem(mbp, NULL, SMB2_HDRLEN, MB_MZERO);
      196 +        } else {
      197 +                /*
      198 +                 * SMB1 request initialization
      199 +                 */
      200 +                rqp->sr_cmd = cmd;
      201 +                rqp->sr_pid = (uint32_t)ddi_get_pid();
      202 +                rqp->sr_rqflags  = vcp->vc_hflags;
      203 +                rqp->sr_rqflags2 = vcp->vc_hflags2;
 186  204  
      205 +                /*
      206 +                 * The SMB header is filled in later by
      207 +                 * smb_rq_fillhdr (see below)
      208 +                 * Just reserve space here.
      209 +                 */
      210 +                mb_put_mem(mbp, NULL, SMB_HDRLEN, MB_MZERO);
      211 +        }
      212 +
 187  213          return (0);
 188  214  }
 189  215  
 190  216  /*
 191  217   * Given a request with it's body already composed,
 192  218   * rewind to the start and fill in the SMB header.
 193      - * This is called after the request is enqueued,
      219 + * This is called when the request is enqueued,
 194  220   * so we have the final MID, seq num. etc.
 195  221   */
 196  222  void
 197  223  smb_rq_fillhdr(struct smb_rq *rqp)
 198  224  {
 199  225          struct mbchain mbtmp, *mbp = &mbtmp;
 200  226          mblk_t *m;
 201  227  
 202  228          /*
 203  229           * Fill in the SMB header using a dup of the first mblk,
↓ open down ↓ 6 lines elided ↑ open up ↑
 210  236  
 211  237          mb_put_mem(mbp, SMB_SIGNATURE, 4, MB_MSYSTEM);
 212  238          mb_put_uint8(mbp, rqp->sr_cmd);
 213  239          mb_put_uint32le(mbp, 0);        /* status */
 214  240          mb_put_uint8(mbp, rqp->sr_rqflags);
 215  241          mb_put_uint16le(mbp, rqp->sr_rqflags2);
 216  242          mb_put_uint16le(mbp, 0);        /* pid-high */
 217  243          mb_put_mem(mbp, NULL, 8, MB_MZERO);     /* MAC sig. (later) */
 218  244          mb_put_uint16le(mbp, 0);        /* reserved */
 219  245          mb_put_uint16le(mbp, rqp->sr_rqtid);
 220      -        mb_put_uint16le(mbp, rqp->sr_pid);
      246 +        mb_put_uint16le(mbp, (uint16_t)rqp->sr_pid);
 221  247          mb_put_uint16le(mbp, rqp->sr_rquid);
 222  248          mb_put_uint16le(mbp, rqp->sr_mid);
 223  249  
 224  250          /* This will free the mblk from dupb. */
 225  251          mb_done(mbp);
 226  252  }
 227  253  
 228  254  int
 229  255  smb_rq_simple(struct smb_rq *rqp)
 230  256  {
↓ open down ↓ 43 lines elided ↑ open up ↑
 274  300  }
 275  301  
 276  302  
 277  303  static int
 278  304  smb_rq_enqueue(struct smb_rq *rqp)
 279  305  {
 280  306          struct smb_vc *vcp = rqp->sr_vc;
 281  307          struct smb_share *ssp = rqp->sr_share;
 282  308          int error = 0;
 283  309  
      310 +        ASSERT((vcp->vc_flags & SMBV_SMB2) == 0);
      311 +
 284  312          /*
 285  313           * Normal requests may initiate a reconnect,
 286  314           * and/or wait for state changes to finish.
 287  315           * Some requests set the NORECONNECT flag
 288  316           * to avoid all that (i.e. tree discon)
 289  317           */
 290  318          if (rqp->sr_flags & SMBR_NORECONNECT) {
 291  319                  if (vcp->vc_state != SMBIOD_ST_VCACTIVE) {
 292  320                          SMBSDEBUG("bad vc_state=%d\n", vcp->vc_state);
 293  321                          return (ENOTCONN);
↓ open down ↓ 24 lines elided ↑ open up ↑
 318  346                          return (error);
 319  347          }
 320  348  
 321  349          /*
 322  350           * We now know what UID + TID to use.
 323  351           * Store them in the request.
 324  352           */
 325  353  ok_out:
 326  354          rqp->sr_rquid = vcp->vc_smbuid;
 327  355          rqp->sr_rqtid = ssp ? ssp->ss_tid : SMB_TID_UNKNOWN;
 328      -        error = smb_iod_addrq(rqp);
      356 +        error = smb1_iod_addrq(rqp);
 329  357  
 330  358          return (error);
 331  359  }
 332  360  
 333  361  /*
      362 + * Used by the IOD thread during connection setup,
      363 + * and for smb_echo after network timeouts.  Note that
      364 + * unlike smb_rq_simple, callers must check sr_error.
      365 + */
      366 +int
      367 +smb_rq_internal(struct smb_rq *rqp, int timeout)
      368 +{
      369 +        struct smb_vc *vcp = rqp->sr_vc;
      370 +        int error;
      371 +
      372 +        ASSERT((vcp->vc_flags & SMBV_SMB2) == 0);
      373 +
      374 +        rqp->sr_flags &= ~SMBR_RESTART;
      375 +        rqp->sr_timo = timeout; /* in seconds */
      376 +        rqp->sr_state = SMBRQ_NOTSENT;
      377 +
      378 +        /*
      379 +         * In-line smb_rq_enqueue(rqp) here, as we don't want it
      380 +         * trying to reconnect etc. for an internal request.
      381 +         */
      382 +        rqp->sr_rquid = vcp->vc_smbuid;
      383 +        rqp->sr_rqtid = SMB_TID_UNKNOWN;
      384 +        rqp->sr_flags |= SMBR_INTERNAL;
      385 +        error = smb1_iod_addrq(rqp);
      386 +        if (error != 0)
      387 +                return (error);
      388 +
      389 +        /*
      390 +         * In-line a variant of smb_rq_reply(rqp) here as we may
      391 +         * need to do custom parsing for SMB1-to-SMB2 negotiate.
      392 +         */
      393 +        if (rqp->sr_timo == SMBNOREPLYWAIT) {
      394 +                smb_iod_removerq(rqp);
      395 +                return (0);
      396 +        }
      397 +
      398 +        error = smb_iod_waitrq_int(rqp);
      399 +        if (error)
      400 +                return (error);
      401 +
      402 +        /*
      403 +         * If the request was signed, validate the
      404 +         * signature on the response.
      405 +         */
      406 +        if (rqp->sr_rqflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) {
      407 +                error = smb_rq_verify(rqp);
      408 +                if (error)
      409 +                        return (error);
      410 +        }
      411 +
      412 +        /*
      413 +         * Parse the SMB header.
      414 +         */
      415 +        error = smb_rq_parsehdr(rqp);
      416 +
      417 +        /*
      418 +         * Skip the error translation smb_rq_reply does.
      419 +         * Callers of this expect "raw" NT status.
      420 +         */
      421 +
      422 +        return (error);
      423 +}
      424 +
      425 +/*
 334  426   * Mark location of the word count, which is filled in later by
 335  427   * smb_rw_wend().  Also initialize the counter that it uses
 336  428   * to figure out what value to fill in.
 337  429   *
 338  430   * Note that the word count happens to be 8-bit.
 339  431   */
 340  432  void
 341  433  smb_rq_wstart(struct smb_rq *rqp)
 342  434  {
 343  435          rqp->sr_wcount = mb_reserve(&rqp->sr_rq, sizeof (uint8_t));
↓ open down ↓ 47 lines elided ↑ open up ↑
 391  483          /*
 392  484           * Fill in the byte count (16-bits)
 393  485           * The pointer is char * type due to
 394  486           * typical off-by-one alignment.
 395  487           */
 396  488          rqp->sr_bcount[0] = bcnt & 0xFF;
 397  489          rqp->sr_bcount[1] = (bcnt >> 8);
 398  490  }
 399  491  
 400  492  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  493  smb_rq_getenv(struct smb_connobj *co,
 411  494          struct smb_vc **vcpp, struct smb_share **sspp)
 412  495  {
 413  496          struct smb_vc *vcp = NULL;
 414  497          struct smb_share *ssp = NULL;
 415  498          int error = EINVAL;
 416  499  
 417  500          if (co->co_flags & SMBO_GONE) {
 418  501                  SMBSDEBUG("zombie CO\n");
 419  502                  error = EINVAL;
↓ open down ↓ 30 lines elided ↑ open up ↑
 450  533                  if (vcpp)
 451  534                          *vcpp = vcp;
 452  535                  if (sspp)
 453  536                          *sspp = ssp;
 454  537          }
 455  538  
 456  539          return (error);
 457  540  }
 458  541  
 459  542  /*
 460      - * Wait for reply on the request
      543 + * Wait for a reply to this request, then parse it.
 461  544   */
 462  545  static int
 463  546  smb_rq_reply(struct smb_rq *rqp)
 464  547  {
 465      -        struct mdchain *mdp = &rqp->sr_rp;
 466      -        u_int8_t tb;
 467      -        int error, rperror = 0;
      548 +        int error;
 468  549  
 469  550          if (rqp->sr_timo == SMBNOREPLYWAIT) {
 470  551                  smb_iod_removerq(rqp);
 471  552                  return (0);
 472  553          }
 473  554  
 474  555          error = smb_iod_waitrq(rqp);
 475  556          if (error)
 476  557                  return (error);
 477  558  
↓ open down ↓ 3 lines elided ↑ open up ↑
 481  562           */
 482  563          if (rqp->sr_rqflags2 & SMB_FLAGS2_SECURITY_SIGNATURE) {
 483  564                  error = smb_rq_verify(rqp);
 484  565                  if (error)
 485  566                          return (error);
 486  567          }
 487  568  
 488  569          /*
 489  570           * Parse the SMB header
 490  571           */
 491      -        error = md_get_uint32le(mdp, NULL);
 492      -        if (error)
      572 +        error = smb_rq_parsehdr(rqp);
      573 +        if (error != 0)
 493  574                  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) {
      575 +
      576 +        if (rqp->sr_error != 0) {
      577 +                if (rqp->sr_rpflags2 & SMB_FLAGS2_ERR_STATUS) {
      578 +                        error = smb_maperr32(rqp->sr_error);
      579 +                } else {
      580 +                        uint8_t errClass = rqp->sr_error & 0xff;
      581 +                        uint16_t errCode = rqp->sr_error >> 16;
      582 +                        /* Convert to NT status */
      583 +                        rqp->sr_error = smb_doserr2status(errClass, errCode);
      584 +                        error = smb_maperror(errClass, errCode);
      585 +                }
      586 +        }
      587 +
      588 +        if (error != 0) {
 499  589                  /*
 500  590                   * Do a special check for STATUS_BUFFER_OVERFLOW;
 501  591                   * it's not an error.
 502  592                   */
 503  593                  if (rqp->sr_error == NT_STATUS_BUFFER_OVERFLOW) {
 504  594                          /*
 505  595                           * Don't report it as an error to our caller;
 506  596                           * they can look at rqp->sr_error if they
 507  597                           * need to know whether we got a
 508  598                           * STATUS_BUFFER_OVERFLOW.
 509      -                         * XXX - should we do that for all errors
 510      -                         * where (error & 0xC0000000) is 0x80000000,
 511      -                         * i.e. all warnings?
 512  599                           */
 513      -                        rperror = 0;
 514      -                } else
 515      -                        rperror = smb_maperr32(rqp->sr_error);
      600 +                        rqp->sr_flags |= SMBR_MOREDATA;
      601 +                        error = 0;
      602 +                }
 516  603          } 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  604                  rqp->sr_flags &= ~SMBR_MOREDATA;
      605 +        }
 526  606  
 527      -        error = md_get_uint32le(mdp, NULL);
 528      -        error = md_get_uint32le(mdp, NULL);
 529      -        error = md_get_uint32le(mdp, NULL);
      607 +        return (error);
      608 +}
 530  609  
 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);
      610 +/*
      611 + * Parse the SMB header
      612 + */
      613 +static int
      614 +smb_rq_parsehdr(struct smb_rq *rqp)
      615 +{
      616 +        struct mdchain mdp_save;
      617 +        struct mdchain *mdp = &rqp->sr_rp;
      618 +        u_int8_t tb, sig[4];
      619 +        int error;
      620 +
      621 +        /*
      622 +         * Parse the signature.  The reader already checked that
      623 +         * the signature is valid.  Here we just have to check
      624 +         * for SMB1-to-SMB2 negotiate.  Caller handles an EPROTO
      625 +         * as a signal that we got an SMB2 reply.  If we return
      626 +         * EPROTO, rewind the mdchain back where it was.
      627 +         */
      628 +        mdp_save = *mdp;
      629 +        error = md_get_mem(mdp, sig, 4, MB_MSYSTEM);
      630 +        if (error)
      631 +                return (error);
      632 +        if (sig[0] != SMB_HDR_V1) {
      633 +                if (rqp->sr_cmd == SMB_COM_NEGOTIATE) {
      634 +                        *mdp = mdp_save;
      635 +                        return (EPROTO);
      636 +                }
      637 +                return (EBADRPC);
      638 +        }
      639 +
      640 +        /* Check cmd */
      641 +        error = md_get_uint8(mdp, &tb);
      642 +        if (tb != rqp->sr_cmd)
      643 +                return (EBADRPC);
      644 +
      645 +        md_get_uint32le(mdp, &rqp->sr_error);
      646 +        md_get_uint8(mdp, &rqp->sr_rpflags);
      647 +        md_get_uint16le(mdp, &rqp->sr_rpflags2);
      648 +
      649 +        /* Skip: pid-high(2), MAC sig(8), reserved(2) */
      650 +        md_get_mem(mdp, NULL, 12, MB_MSYSTEM);
      651 +
      652 +        md_get_uint16le(mdp, &rqp->sr_rptid);
      653 +        md_get_uint16le(mdp, &rqp->sr_rppid);
      654 +        md_get_uint16le(mdp, &rqp->sr_rpuid);
 534  655          error = md_get_uint16le(mdp, &rqp->sr_rpmid);
 535  656  
 536      -        return ((error) ? error : rperror);
      657 +        return (error);
 537  658  }
 538  659  
 539  660  
 540  661  #define ALIGN4(a)       (((a) + 3) & ~3)
 541  662  
 542  663  /*
 543  664   * TRANS2 request implementation
 544  665   * TRANS implementation is in the "t2" routines
 545  666   * NT_TRANSACTION implementation is the separate "nt" stuff
 546  667   */
↓ open down ↓ 580 lines elided ↑ open up ↑
1127 1248                  }
1128 1249                  len = mb_fixhdr(mbp);
1129 1250                  if (txdcount) {
1130 1251                          mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO);
1131 1252                          error = md_get_mbuf(&mbdata, txdcount, &m);
1132 1253                          if (error)
1133 1254                                  goto bad;
1134 1255                          mb_put_mbuf(mbp, m);
1135 1256                  }
1136 1257                  smb_rq_bend(rqp);
1137      -                error = smb_iod_multirq(rqp);
     1258 +                error = smb1_iod_multirq(rqp);
1138 1259                  if (error)
1139 1260                          goto bad;
1140 1261          }       /* while left params or data */
1141 1262          error = smb_t2_reply(t2p);
1142 1263          if (error && !(t2p->t2_flags & SMBT2_MOREDATA))
1143 1264                  goto bad;
1144 1265          mdp = &t2p->t2_rdata;
1145 1266          if (mdp->md_top) {
1146 1267                  md_initm(mdp, mdp->md_top);
1147 1268          }
↓ open down ↓ 190 lines elided ↑ open up ↑
1338 1459                  }
1339 1460                  len = mb_fixhdr(mbp);
1340 1461                  if (txdcount) {
1341 1462                          mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO);
1342 1463                          error = md_get_mbuf(&mbdata, txdcount, &m);
1343 1464                          if (error)
1344 1465                                  goto bad;
1345 1466                          mb_put_mbuf(mbp, m);
1346 1467                  }
1347 1468                  smb_rq_bend(rqp);
1348      -                error = smb_iod_multirq(rqp);
     1469 +                error = smb1_iod_multirq(rqp);
1349 1470                  if (error)
1350 1471                          goto bad;
1351 1472          }       /* while left params or data */
1352 1473          error = smb_nt_reply(ntp);
1353 1474          if (error && !(ntp->nt_flags & SMBT2_MOREDATA))
1354 1475                  goto bad;
1355 1476          mdp = &ntp->nt_rdata;
1356 1477          if (mdp->md_top) {
1357 1478                  md_initm(mdp, mdp->md_top);
1358 1479          }
↓ open down ↓ 71 lines elided ↑ open up ↑
1430 1551                  if (ntp->nt_share) {
1431 1552                          (void) cv_reltimedwait(&ntp->nt_cond, &(ntp)->nt_lock,
1432 1553                              SEC_TO_TICK(SMB_RCNDELAY), TR_CLOCK_TICK);
1433 1554  
1434 1555                  } else {
1435 1556                          delay(SEC_TO_TICK(SMB_RCNDELAY));
1436 1557                  }
1437 1558                  mutex_exit(&(ntp)->nt_lock);
1438 1559          }
1439 1560          return (error);
     1561 +}
     1562 +
     1563 +/*
     1564 + * Run an SMB transact named pipe.
     1565 + * Note: send_mb is consumed.
     1566 + */
     1567 +int
     1568 +smb_t2_xnp(struct smb_share *ssp, uint16_t fid,
     1569 +    struct mbchain *send_mb, struct mdchain *recv_md,
     1570 +    uint32_t *data_out_sz, /* max / returned */
     1571 +    uint32_t *more, struct smb_cred *scrp)
     1572 +{
     1573 +        struct smb_t2rq *t2p = NULL;
     1574 +        mblk_t *m;
     1575 +        uint16_t setup[2];
     1576 +        int err;
     1577 +
     1578 +        setup[0] = TRANS_TRANSACT_NAMED_PIPE;
     1579 +        setup[1] = fid;
     1580 +
     1581 +        t2p = kmem_alloc(sizeof (*t2p), KM_SLEEP);
     1582 +        err = smb_t2_init(t2p, SSTOCP(ssp), setup, 2, scrp);
     1583 +        if (err) {
     1584 +                *data_out_sz = 0;
     1585 +                goto out;
     1586 +        }
     1587 +
     1588 +        t2p->t2_setupcount = 2;
     1589 +        t2p->t2_setupdata  = setup;
     1590 +
     1591 +        t2p->t_name = "\\PIPE\\";
     1592 +        t2p->t_name_len = 6;
     1593 +
     1594 +        t2p->t2_maxscount = 0;
     1595 +        t2p->t2_maxpcount = 0;
     1596 +        t2p->t2_maxdcount = (uint16_t)*data_out_sz;
     1597 +
     1598 +        /* Transmit parameters (none) */
     1599 +
     1600 +        /*
     1601 +         * Transmit data
     1602 +         *
     1603 +         * Copy the mb, and clear the source so we
     1604 +         * don't end up with a double free.
     1605 +         */
     1606 +        t2p->t2_tdata = *send_mb;
     1607 +        bzero(send_mb, sizeof (*send_mb));
     1608 +
     1609 +        /*
     1610 +         * Run the request
     1611 +         */
     1612 +        err = smb_t2_request(t2p);
     1613 +
     1614 +        /* No returned parameters. */
     1615 +
     1616 +        if (err == 0 && (m = t2p->t2_rdata.md_top) != NULL) {
     1617 +                /*
     1618 +                 * Received data
     1619 +                 *
     1620 +                 * Copy the mdchain, and clear the source so we
     1621 +                 * don't end up with a double free.
     1622 +                 */
     1623 +                *data_out_sz = msgdsize(m);
     1624 +                md_initm(recv_md, m);
     1625 +                t2p->t2_rdata.md_top = NULL;
     1626 +        } else {
     1627 +                *data_out_sz = 0;
     1628 +        }
     1629 +
     1630 +        if (t2p->t2_sr_error == NT_STATUS_BUFFER_OVERFLOW)
     1631 +                *more = 1;
     1632 +
     1633 +out:
     1634 +        if (t2p != NULL) {
     1635 +                /* Note: t2p->t_name no longer allocated */
     1636 +                smb_t2_done(t2p);
     1637 +                kmem_free(t2p, sizeof (*t2p));
     1638 +        }
     1639 +
     1640 +        return (err);
1440 1641  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX