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-15578 SMB2 durable handle redesign
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-15578 SMB2 durable handle redesign
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-5844 want SMB2 ioctl FSCTL_SRV_COPYCHUNK
NEX-6124 smb_fsop_read/write should allow file != sr->fid_ofile
NEX-6125 smbtorture invalid response with smb2.ioctl
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-4538 SMB1 create file should support extended_response format (2)
NEX-6116 Failures in smbtorture raw.open
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Include this commit if upstreaming/backporting any of:
NEX-4540 SMB server declines EA support incorrectly
NEX-4239 smbtorture create failures re. allocation size
(illumos) 6398 SMB should support path names longer than 1024
NEX-4538 SMB1 create file should support extended_response format
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
NEX-2522 svcadm disable network/smb/server may hang
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-3662 Backport illumos 1501: taskq_create_proc ... TQ_DYNAMIC puts tasks in p0 (take 2)
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Dan McDonald <danmcd@omniti.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Marcel Telka <marcel.telka@nexenta.com>
NEX-3576 RPC error when displaying open files via Windows MMC
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-2188 Browsing top level share produces RPC error 1728
SMB-119 Text file contains garbage when re-opened
SMB-120 Share enumeration fails with Windows 8
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
SMB-39 Use AF_UNIX pipes for RPC
SMB-50 User-mode SMB server
 Includes work by these authors:
 Thomas Keiser <thomas.keiser@nexenta.com>
 Albert Lee <trisk@nexenta.com>
SMB-65 SMB server in non-global zones (data structure changes)
Many things move to the smb_server_t object, and
many functions gain an sv arg (which server).
SMB-65 SMB server in non-global zones (kmem_caches)
common kmem_cache instances across zones
separate GZ-only init from NGZ init
SMB-63 taskq_create_proc ... TQ_DYNAMIC puts tasks in p0
re #11974 CIFS Share - Tree connect fails from Windows 7 Clients
re #6812 rb1753 backport illumos 1604 smbd print_enable doesn't really work
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/fs/smbsrv/smb_opipe.c
          +++ new/usr/src/uts/common/fs/smbsrv/smb_opipe.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  
    | 
      ↓ open down ↓ | 
    12 lines elided | 
    
      ↑ open up ↑ | 
  
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23      - * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
       23 + * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  24   24   */
  25   25  
  26   26  /*
  27   27   * This module provides the interface to NDR RPC.
  28   28   */
  29   29  
  30   30  #include <sys/stat.h>
  31   31  #include <sys/uio.h>
  32   32  #include <sys/ksynch.h>
  33   33  #include <sys/stropts.h>
  34   34  #include <sys/socket.h>
  35   35  #include <sys/filio.h>
  36   36  #include <smbsrv/smb_kproto.h>
  37   37  #include <smbsrv/smb_xdr.h>
  38      -#include <smbsrv/winioctl.h>
       38 +#include <smb/winioctl.h>
  39   39  
  40      -static uint32_t smb_opipe_transceive(smb_request_t *, smb_fsctl_t *);
  41      -
  42   40  /*
  43   41   * Allocate a new opipe and return it, or NULL, in which case
  44   42   * the caller will report "internal error".
  45   43   */
  46   44  static smb_opipe_t *
  47   45  smb_opipe_alloc(smb_request_t *sr)
  48   46  {
  49   47          smb_server_t    *sv = sr->sr_server;
  50   48          smb_opipe_t     *opipe;
  51   49          ksocket_t       sock;
  52   50  
  53   51          if (ksocket_socket(&sock, AF_UNIX, SOCK_STREAM, 0,
  54   52              KSOCKET_SLEEP, sr->user_cr) != 0)
  55   53                  return (NULL);
  56   54  
  57   55          opipe = kmem_cache_alloc(smb_cache_opipe, KM_SLEEP);
  58   56  
  59   57          bzero(opipe, sizeof (smb_opipe_t));
  60   58          mutex_init(&opipe->p_mutex, NULL, MUTEX_DEFAULT, NULL);
  61   59          cv_init(&opipe->p_cv, NULL, CV_DEFAULT, NULL);
  62   60          opipe->p_magic = SMB_OPIPE_MAGIC;
  63   61          opipe->p_server = sv;
  64   62          opipe->p_refcnt = 1;
  65   63          opipe->p_socket = sock;
  66   64  
  67   65          return (opipe);
  68   66  }
  69   67  
  70   68  /*
  71   69   * Destroy an opipe.  This is normally called from smb_ofile_delete
  72   70   * when the ofile has no more references and is about to be free'd.
  73   71   * This is also called here in error handling code paths, before
  74   72   * the opipe is installed under an ofile.
  75   73   */
  76   74  void
  77   75  smb_opipe_dealloc(smb_opipe_t *opipe)
  78   76  {
  79   77          smb_server_t *sv;
  80   78  
  81   79          SMB_OPIPE_VALID(opipe);
  82   80          sv = opipe->p_server;
  83   81          SMB_SERVER_VALID(sv);
  84   82  
  85   83          /*
  86   84           * This is called in the error path when opening,
  87   85           * in which case we close the socket here.
  88   86           */
  89   87          if (opipe->p_socket != NULL)
  
    | 
      ↓ open down ↓ | 
    38 lines elided | 
    
      ↑ open up ↑ | 
  
  90   88                  (void) ksocket_close(opipe->p_socket, zone_kcred());
  91   89  
  92   90          opipe->p_magic = (uint32_t)~SMB_OPIPE_MAGIC;
  93   91          cv_destroy(&opipe->p_cv);
  94   92          mutex_destroy(&opipe->p_mutex);
  95   93  
  96   94          kmem_cache_free(smb_cache_opipe, opipe);
  97   95  }
  98   96  
  99   97  /*
       98 + * Unblock a request that might be blocked reading some
       99 + * pipe (AF_UNIX socket).  We don't have an easy way to
      100 + * interrupt just the thread servicing this request, so
      101 + * we shutdown(3socket) the socket, waking all readers.
      102 + * That's a bit heavy-handed, making the socket unusable
      103 + * after this, so we do this only when disconnecting a
      104 + * session (i.e. stopping the SMB service), and not when
      105 + * handling an SMB2_cancel or SMB_nt_cancel request.
      106 + */
      107 +static void
      108 +smb_opipe_cancel(smb_request_t *sr)
      109 +{
      110 +        ksocket_t so;
      111 +
      112 +        switch (sr->session->s_state) {
      113 +        case SMB_SESSION_STATE_DISCONNECTED:
      114 +        case SMB_SESSION_STATE_TERMINATED:
      115 +                if ((so = sr->cancel_arg2) != NULL)
      116 +                        (void) ksocket_shutdown(so, SHUT_RDWR, sr->user_cr);
      117 +                break;
      118 +        }
      119 +}
      120 +
      121 +/*
 100  122   * Helper for open: build pipe name and connect.
 101  123   */
 102  124  static int
 103  125  smb_opipe_connect(smb_request_t *sr, smb_opipe_t *opipe)
 104  126  {
 105  127          struct sockaddr_un saddr;
 106  128          smb_arg_open_t  *op = &sr->sr_open;
 107  129          const char *name;
 108  130          int rc;
 109  131  
 110  132          name = op->fqi.fq_path.pn_path;
 111  133          name += strspn(name, "\\");
 112  134          if (smb_strcasecmp(name, "PIPE", 4) == 0) {
 113  135                  name += 4;
 114  136                  name += strspn(name, "\\");
 115  137          }
 116  138          (void) strlcpy(opipe->p_name, name, SMB_OPIPE_MAXNAME);
 117  139          (void) smb_strlwr(opipe->p_name);
 118  140  
 119  141          bzero(&saddr, sizeof (saddr));
 120  142          saddr.sun_family = AF_UNIX;
 121  143          (void) snprintf(saddr.sun_path, sizeof (saddr.sun_path),
 122  144              "%s/%s", SMB_PIPE_DIR, opipe->p_name);
 123  145          rc = ksocket_connect(opipe->p_socket, (struct sockaddr *)&saddr,
 124  146              sizeof (saddr), sr->user_cr);
 125  147  
 126  148          return (rc);
 127  149  }
 128  150  
 129  151  /*
 130  152   * Helper for open: encode and send the user info.
 131  153   *
 132  154   * We send information about this client + user to the
 133  155   * pipe service so it can use it for access checks.
 134  156   * The service MAY deny the open based on this info,
 135  157   * (i.e. anonymous session trying to open a pipe that
 136  158   * requires authentication) in which case we will read
 137  159   * an error status from the service and return that.
 138  160   */
 139  161  static void
 140  162  smb_opipe_send_userinfo(smb_request_t *sr, smb_opipe_t *opipe,
 141  163      smb_error_t *errp)
 142  164  {
 143  165          XDR xdrs;
 144  166          smb_netuserinfo_t nui;
 145  167          smb_pipehdr_t phdr;
 146  168          char *buf;
 147  169          uint32_t buflen;
 148  170          uint32_t status;
 149  171          size_t iocnt = 0;
 150  172          int rc;
 151  173  
 152  174          /*
 153  175           * Any errors building the XDR message etc.
 154  176           */
 155  177          errp->status = NT_STATUS_INTERNAL_ERROR;
 156  178  
 157  179          smb_user_netinfo_init(sr->uid_user, &nui);
 158  180          phdr.ph_magic = SMB_PIPE_HDR_MAGIC;
 159  181          phdr.ph_uilen = xdr_sizeof(smb_netuserinfo_xdr, &nui);
  
    | 
      ↓ open down ↓ | 
    50 lines elided | 
    
      ↑ open up ↑ | 
  
 160  182  
 161  183          buflen = sizeof (phdr) + phdr.ph_uilen;
 162  184          buf = kmem_alloc(buflen, KM_SLEEP);
 163  185  
 164  186          bcopy(&phdr, buf, sizeof (phdr));
 165  187          xdrmem_create(&xdrs, buf + sizeof (phdr),
 166  188              buflen - (sizeof (phdr)), XDR_ENCODE);
 167  189          if (!smb_netuserinfo_xdr(&xdrs, &nui))
 168  190                  goto out;
 169  191  
 170      -        /*
 171      -         * If we fail sending the netuserinfo or recv'ing the
 172      -         * status reponse, we have probably run into the limit
 173      -         * on the number of open pipes.  That's this status:
 174      -         */
 175      -        errp->status = NT_STATUS_PIPE_NOT_AVAILABLE;
      192 +        mutex_enter(&sr->sr_mutex);
      193 +        if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
      194 +                mutex_exit(&sr->sr_mutex);
      195 +                errp->status = NT_STATUS_CANCELLED;
      196 +                goto out;
      197 +        }
      198 +        sr->sr_state = SMB_REQ_STATE_WAITING_PIPE;
      199 +        sr->cancel_method = smb_opipe_cancel;
      200 +        sr->cancel_arg2 = opipe->p_socket;
      201 +        mutex_exit(&sr->sr_mutex);
 176  202  
 177  203          rc = ksocket_send(opipe->p_socket, buf, buflen, 0,
 178  204              &iocnt, sr->user_cr);
 179  205          if (rc == 0 && iocnt != buflen)
 180  206                  rc = EIO;
 181      -        if (rc != 0)
 182      -                goto out;
      207 +        if (rc == 0)
      208 +                rc = ksocket_recv(opipe->p_socket, &status, sizeof (status),
      209 +                    0, &iocnt, sr->user_cr);
      210 +        if (rc == 0 && iocnt != sizeof (status))
      211 +                rc = EIO;
 183  212  
 184      -        rc = ksocket_recv(opipe->p_socket, &status, sizeof (status), 0,
 185      -            &iocnt, sr->user_cr);
 186      -        if (rc != 0 || iocnt != sizeof (status))
 187      -                goto out;
      213 +        mutex_enter(&sr->sr_mutex);
      214 +        sr->cancel_method = NULL;
      215 +        sr->cancel_arg2 = NULL;
      216 +        switch (sr->sr_state) {
      217 +        case SMB_REQ_STATE_WAITING_PIPE:
      218 +                sr->sr_state = SMB_REQ_STATE_ACTIVE;
      219 +                break;
      220 +        case SMB_REQ_STATE_CANCEL_PENDING:
      221 +                sr->sr_state = SMB_REQ_STATE_CANCELLED;
      222 +                rc = EINTR;
      223 +                break;
      224 +        default:
      225 +                /* keep rc from above */
      226 +                break;
      227 +        }
      228 +        mutex_exit(&sr->sr_mutex);
 188  229  
      230 +
 189  231          /*
 190  232           * Return the status we read from the pipe service,
 191  233           * normally NT_STATUS_SUCCESS, but could be something
 192  234           * else like NT_STATUS_ACCESS_DENIED.
 193  235           */
 194      -        errp->status = status;
      236 +        switch (rc) {
      237 +        case 0:
      238 +                errp->status = status;
      239 +                break;
      240 +        case EINTR:
      241 +                errp->status = NT_STATUS_CANCELLED;
      242 +                break;
      243 +        /*
      244 +         * If we fail sending the netuserinfo or recv'ing the
      245 +         * status reponse, we have probably run into the limit
      246 +         * on the number of open pipes.  That's this status:
      247 +         */
      248 +        default:
      249 +                errp->status = NT_STATUS_PIPE_NOT_AVAILABLE;
      250 +                break;
      251 +        }
 195  252  
 196  253  out:
 197  254          xdr_destroy(&xdrs);
 198  255          kmem_free(buf, buflen);
 199  256          smb_user_netinfo_fini(&nui);
 200  257  }
 201  258  
 202  259  /*
 203  260   * smb_opipe_open
 204  261   *
 205  262   * Open an RPC named pipe. This routine should be called if
 206  263   * a file open is requested on a share of type STYPE_IPC.
 207  264   * If we recognize the pipe, we setup a new ofile.
 208  265   *
 209  266   * Returns 0 on success, Otherwise an NT status code.
 210  267   */
 211  268  int
 212      -smb_opipe_open(smb_request_t *sr, uint32_t uniqid)
      269 +smb_opipe_open(smb_request_t *sr, smb_ofile_t *ofile)
 213  270  {
 214  271          smb_arg_open_t  *op = &sr->sr_open;
 215      -        smb_ofile_t *ofile;
      272 +        smb_attr_t *ap = &op->fqi.fq_fattr;
 216  273          smb_opipe_t *opipe;
 217  274          smb_error_t err;
 218  275  
 219  276          opipe = smb_opipe_alloc(sr);
 220  277          if (opipe == NULL)
 221  278                  return (NT_STATUS_INTERNAL_ERROR);
 222  279  
 223  280          if (smb_opipe_connect(sr, opipe) != 0) {
 224  281                  smb_opipe_dealloc(opipe);
 225  282                  return (NT_STATUS_OBJECT_NAME_NOT_FOUND);
 226  283          }
 227  284  
 228  285          smb_opipe_send_userinfo(sr, opipe, &err);
 229  286          if (err.status != 0) {
 230  287                  smb_opipe_dealloc(opipe);
 231  288                  return (err.status);
 232  289          }
 233  290  
 234  291          /*
 235      -         * Note: If smb_ofile_open succeeds, the new ofile is
 236      -         * in the FID lists can can be used by I/O requests.
      292 +         * We might have blocked in smb_opipe_connect long enough so
      293 +         * a tree disconnect might have happened.  In that case, we
      294 +         * would be adding an ofile to a tree that's disconnecting,
      295 +         * which would interfere with tear-down.
 237  296           */
 238      -        op->create_options = 0;
 239      -        op->pipe = opipe;
 240      -        ofile = smb_ofile_open(sr, NULL, op,
 241      -            SMB_FTYPE_MESG_PIPE, uniqid, &err);
 242      -        op->pipe = NULL;
 243      -        if (ofile == NULL) {
      297 +        if (!smb_tree_is_connected(sr->tid_tree)) {
 244  298                  smb_opipe_dealloc(opipe);
 245      -                return (err.status);
      299 +                return (NT_STATUS_NETWORK_NAME_DELETED);
 246  300          }
 247  301  
      302 +        /*
      303 +         * Note: The new opipe is given to smb_ofile_open
      304 +         * via op->pipe
      305 +         */
      306 +        op->pipe = opipe;
      307 +        smb_ofile_open(sr, op, ofile);
      308 +        op->pipe = NULL;
      309 +
 248  310          /* An "up" pointer, for debug. */
 249  311          opipe->p_ofile = ofile;
 250  312  
 251      -        op->dsize = 0x01000;
 252      -        op->dattr = FILE_ATTRIBUTE_NORMAL;
      313 +        /*
      314 +         * Caller expects attributes in op->fqi
      315 +         */
      316 +        (void) smb_opipe_getattr(ofile, &op->fqi.fq_fattr);
      317 +
      318 +        op->dsize = 0;
      319 +        op->dattr = ap->sa_dosattr;
      320 +        op->fileid = ap->sa_vattr.va_nodeid;
 253  321          op->ftype = SMB_FTYPE_MESG_PIPE;
 254      -        op->action_taken = SMB_OACT_LOCK | SMB_OACT_OPENED; /* 0x8001 */
      322 +        op->action_taken = SMB_OACT_OPLOCK | SMB_OACT_OPENED;
 255  323          op->devstate = SMB_PIPE_READMODE_MESSAGE
 256  324              | SMB_PIPE_TYPE_MESSAGE
 257  325              | SMB_PIPE_UNLIMITED_INSTANCES; /* 0x05ff */
 258      -        op->fileid = ofile->f_fid;
 259  326  
 260  327          sr->smb_fid = ofile->f_fid;
 261  328          sr->fid_ofile = ofile;
 262  329  
 263  330          return (NT_STATUS_SUCCESS);
 264  331  }
 265  332  
 266  333  /*
 267  334   * smb_opipe_close
 268  335   *
 269  336   * Called by smb_ofile_close for pipes.
 270  337   *
 271  338   * Note: ksocket_close may block while waiting for
 272  339   * any I/O threads with a hold to get out.
 273  340   */
 274  341  void
 275  342  smb_opipe_close(smb_ofile_t *of)
 276  343  {
 277  344          smb_opipe_t *opipe;
 278  345          ksocket_t sock;
 279  346  
 280  347          ASSERT(of->f_state == SMB_OFILE_STATE_CLOSING);
 281  348          ASSERT(of->f_ftype == SMB_FTYPE_MESG_PIPE);
 282  349          opipe = of->f_pipe;
 283  350          SMB_OPIPE_VALID(opipe);
 284  351  
 285  352          mutex_enter(&opipe->p_mutex);
 286  353          sock = opipe->p_socket;
 287  354          opipe->p_socket = NULL;
 288  355          mutex_exit(&opipe->p_mutex);
 289  356  
 290  357          (void) ksocket_shutdown(sock, SHUT_RDWR, of->f_cr);
 291  358          (void) ksocket_close(sock, of->f_cr);
 292  359  }
 293  360  
 294  361  /*
 295  362   * smb_opipe_write
 296  363   *
 297  364   * Write RPC request data to the pipe.  The client should call smb_opipe_read
 298  365   * to complete the exchange and obtain the RPC response.
 299  366   *
 300  367   * Returns 0 on success or an errno on failure.
 301  368   */
 302  369  int
 303  370  smb_opipe_write(smb_request_t *sr, struct uio *uio)
 304  371  {
 305  372          struct nmsghdr msghdr;
 306  373          smb_ofile_t *ofile;
 307  374          smb_opipe_t *opipe;
 308  375          ksocket_t sock;
 309  376          size_t sent = 0;
 310  377          int rc = 0;
 311  378  
 312  379          ofile = sr->fid_ofile;
 313  380          ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
 314  381          opipe = ofile->f_pipe;
 315  382          SMB_OPIPE_VALID(opipe);
 316  383  
 317  384          mutex_enter(&opipe->p_mutex);
 318  385          sock = opipe->p_socket;
 319  386          if (sock != NULL)
 320  387                  ksocket_hold(sock);
 321  388          mutex_exit(&opipe->p_mutex);
 322  389          if (sock == NULL)
 323  390                  return (EBADF);
 324  391  
 325  392          bzero(&msghdr, sizeof (msghdr));
 326  393          msghdr.msg_iov = uio->uio_iov;
 327  394          msghdr.msg_iovlen = uio->uio_iovcnt;
 328  395  
 329  396          /*
 330  397           * This should block until we've sent it all,
 331  398           * or given up due to errors (pipe closed).
 332  399           */
 333  400          while (uio->uio_resid > 0) {
 334  401                  rc = ksocket_sendmsg(sock, &msghdr, 0, &sent, ofile->f_cr);
 335  402                  if (rc != 0)
 336  403                          break;
 337  404                  uio->uio_resid -= sent;
 338  405          }
 339  406  
 340  407          ksocket_rele(sock);
 341  408  
 342  409          return (rc);
 343  410  }
 344  411  
 345  412  /*
 346  413   * smb_opipe_read
 347  414   *
 348  415   * This interface may be called from smb_opipe_transact (write, read)
 349  416   * or from smb_read / smb2_read to get the rest of an RPC response.
 350  417   * The response data (and length) are returned via the uio.
 351  418   */
 352  419  int
 353  420  smb_opipe_read(smb_request_t *sr, struct uio *uio)
 354  421  {
 355  422          struct nmsghdr msghdr;
 356  423          smb_ofile_t *ofile;
 357  424          smb_opipe_t *opipe;
 358  425          ksocket_t sock;
 359  426          size_t recvcnt = 0;
 360  427          int rc;
 361  428  
 362  429          ofile = sr->fid_ofile;
 363  430          ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
 364  431          opipe = ofile->f_pipe;
  
    | 
      ↓ open down ↓ | 
    96 lines elided | 
    
      ↑ open up ↑ | 
  
 365  432          SMB_OPIPE_VALID(opipe);
 366  433  
 367  434          mutex_enter(&opipe->p_mutex);
 368  435          sock = opipe->p_socket;
 369  436          if (sock != NULL)
 370  437                  ksocket_hold(sock);
 371  438          mutex_exit(&opipe->p_mutex);
 372  439          if (sock == NULL)
 373  440                  return (EBADF);
 374  441  
 375      -        bzero(&msghdr, sizeof (msghdr));
 376      -        msghdr.msg_iov = uio->uio_iov;
 377      -        msghdr.msg_iovlen = uio->uio_iovcnt;
      442 +        mutex_enter(&sr->sr_mutex);
      443 +        if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
      444 +                mutex_exit(&sr->sr_mutex);
      445 +                rc = EINTR;
      446 +                goto out;
      447 +        }
      448 +        sr->sr_state = SMB_REQ_STATE_WAITING_PIPE;
      449 +        sr->cancel_method = smb_opipe_cancel;
      450 +        sr->cancel_arg2 = sock;
      451 +        mutex_exit(&sr->sr_mutex);
 378  452  
 379  453          /*
 380  454           * This should block only if there's no data.
 381  455           * A single call to recvmsg does just that.
 382  456           * (Intentionaly no recv loop here.)
 383  457           */
      458 +        bzero(&msghdr, sizeof (msghdr));
      459 +        msghdr.msg_iov = uio->uio_iov;
      460 +        msghdr.msg_iovlen = uio->uio_iovcnt;
 384  461          rc = ksocket_recvmsg(sock, &msghdr, 0,
 385  462              &recvcnt, ofile->f_cr);
      463 +
      464 +        mutex_enter(&sr->sr_mutex);
      465 +        sr->cancel_method = NULL;
      466 +        sr->cancel_arg2 = NULL;
      467 +        switch (sr->sr_state) {
      468 +        case SMB_REQ_STATE_WAITING_PIPE:
      469 +                sr->sr_state = SMB_REQ_STATE_ACTIVE;
      470 +                break;
      471 +        case SMB_REQ_STATE_CANCEL_PENDING:
      472 +                sr->sr_state = SMB_REQ_STATE_CANCELLED;
      473 +                rc = EINTR;
      474 +                break;
      475 +        default:
      476 +                /* keep rc from above */
      477 +                break;
      478 +        }
      479 +        mutex_exit(&sr->sr_mutex);
      480 +
 386  481          if (rc != 0)
 387  482                  goto out;
 388  483  
 389  484          if (recvcnt == 0) {
 390  485                  /* Other side closed. */
 391  486                  rc = EPIPE;
 392  487                  goto out;
 393  488          }
 394  489          uio->uio_resid -= recvcnt;
 395  490  
 396  491  out:
 397  492          ksocket_rele(sock);
 398  493  
 399  494          return (rc);
 400  495  }
 401  496  
 402  497  int
 403  498  smb_opipe_ioctl(smb_request_t *sr, int cmd, void *arg, int *rvalp)
 404  499  {
 405  500          smb_ofile_t *ofile;
 406  501          smb_opipe_t *opipe;
 407  502          ksocket_t sock;
 408  503          int rc;
 409  504  
 410  505          ofile = sr->fid_ofile;
 411  506          ASSERT(ofile->f_ftype == SMB_FTYPE_MESG_PIPE);
 412  507          opipe = ofile->f_pipe;
 413  508          SMB_OPIPE_VALID(opipe);
 414  509  
 415  510          mutex_enter(&opipe->p_mutex);
 416  511          sock = opipe->p_socket;
 417  512          if (sock != NULL)
 418  513                  ksocket_hold(sock);
 419  514          mutex_exit(&opipe->p_mutex);
 420  515          if (sock == NULL)
 421  516                  return (EBADF);
 422  517  
 423  518          rc = ksocket_ioctl(sock, cmd, (intptr_t)arg, rvalp, ofile->f_cr);
 424  519  
 425  520          ksocket_rele(sock);
 426  521  
 427  522          return (rc);
 428  523  }
 429  524  
 430  525  /*
 431  526   * Get the smb_attr_t for a named pipe.
 432  527   * Caller has already cleared to zero.
  
    | 
      ↓ open down ↓ | 
    37 lines elided | 
    
      ↑ open up ↑ | 
  
 433  528   */
 434  529  int
 435  530  smb_opipe_getattr(smb_ofile_t *of, smb_attr_t *ap)
 436  531  {
 437  532  
 438  533          if (of->f_pipe == NULL)
 439  534                  return (EINVAL);
 440  535  
 441  536          ap->sa_vattr.va_type = VFIFO;
 442  537          ap->sa_vattr.va_nlink = 1;
      538 +        ap->sa_vattr.va_nodeid = (uintptr_t)of->f_pipe;
 443  539          ap->sa_dosattr = FILE_ATTRIBUTE_NORMAL;
 444      -        ap->sa_allocsz = 0x1000LL;
      540 +        ap->sa_allocsz = SMB_PIPE_MAX_MSGSIZE;
 445  541  
 446  542          return (0);
 447  543  }
 448  544  
 449  545  int
 450  546  smb_opipe_getname(smb_ofile_t *of, char *buf, size_t buflen)
 451  547  {
 452  548          smb_opipe_t *opipe;
 453  549  
 454  550          if ((opipe = of->f_pipe) == NULL)
 455  551                  return (EINVAL);
 456  552  
 457  553          (void) snprintf(buf, buflen, "\\%s", opipe->p_name);
 458  554          return (0);
 459  555  }
 460  556  
 461  557  /*
 462      - * Handler for smb2_ioctl
      558 + * Handle device type FILE_DEVICE_NAMED_PIPE
      559 + * for smb2_ioctl
 463  560   */
 464  561  /* ARGSUSED */
 465  562  uint32_t
 466  563  smb_opipe_fsctl(smb_request_t *sr, smb_fsctl_t *fsctl)
 467  564  {
 468  565          uint32_t status;
 469  566  
      567 +        if (!STYPE_ISIPC(sr->tid_tree->t_res_type))
      568 +                return (NT_STATUS_INVALID_DEVICE_REQUEST);
      569 +
 470  570          switch (fsctl->CtlCode) {
 471  571          case FSCTL_PIPE_TRANSCEIVE:
 472  572                  status = smb_opipe_transceive(sr, fsctl);
 473  573                  break;
 474  574  
 475  575          case FSCTL_PIPE_PEEK:
 476  576          case FSCTL_PIPE_WAIT:
 477  577                  /* XXX todo */
 478  578                  status = NT_STATUS_NOT_SUPPORTED;
 479  579                  break;
 480  580  
 481  581          default:
 482  582                  ASSERT(!"CtlCode");
 483  583                  status = NT_STATUS_INTERNAL_ERROR;
 484  584                  break;
 485  585          }
 486  586  
 487  587          return (status);
 488  588  }
 489  589  
 490      -static uint32_t
      590 +uint32_t
 491  591  smb_opipe_transceive(smb_request_t *sr, smb_fsctl_t *fsctl)
 492  592  {
 493  593          smb_vdb_t       vdb;
 494  594          smb_ofile_t     *ofile;
 495  595          struct mbuf     *mb;
 496  596          uint32_t        status;
 497  597          int             len, rc;
 498  598  
 499  599          /*
 500  600           * Caller checked that this is the IPC$ share,
 501  601           * and that this call has a valid open handle.
 502  602           * Just check the type.
 503  603           */
 504  604          ofile = sr->fid_ofile;
 505  605          if (ofile->f_ftype != SMB_FTYPE_MESG_PIPE)
 506  606                  return (NT_STATUS_INVALID_HANDLE);
 507  607  
 508  608          rc = smb_mbc_decodef(fsctl->in_mbc, "#B",
 509  609              fsctl->InputCount, &vdb);
 510  610          if (rc != 0) {
 511  611                  /* Not enough data sent. */
 512  612                  return (NT_STATUS_INVALID_PARAMETER);
 513  613          }
 514  614  
 515  615          rc = smb_opipe_write(sr, &vdb.vdb_uio);
 516  616          if (rc != 0)
 517  617                  return (smb_errno2status(rc));
 518  618  
 519  619          vdb.vdb_tag = 0;
 520  620          vdb.vdb_uio.uio_iov = &vdb.vdb_iovec[0];
 521  621          vdb.vdb_uio.uio_iovcnt = MAX_IOVEC;
 522  622          vdb.vdb_uio.uio_segflg = UIO_SYSSPACE;
 523  623          vdb.vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
 524  624          vdb.vdb_uio.uio_loffset = (offset_t)0;
 525  625          vdb.vdb_uio.uio_resid = fsctl->MaxOutputResp;
 526  626          mb = smb_mbuf_allocate(&vdb.vdb_uio);
 527  627  
 528  628          rc = smb_opipe_read(sr, &vdb.vdb_uio);
 529  629          if (rc != 0) {
 530  630                  m_freem(mb);
 531  631                  return (smb_errno2status(rc));
 532  632          }
 533  633  
 534  634          len = fsctl->MaxOutputResp - vdb.vdb_uio.uio_resid;
 535  635          smb_mbuf_trim(mb, len);
 536  636          MBC_ATTACH_MBUF(fsctl->out_mbc, mb);
 537  637  
 538  638          /*
 539  639           * If the output buffer holds a partial pipe message,
 540  640           * we're supposed to return NT_STATUS_BUFFER_OVERFLOW.
 541  641           * As we don't have message boundary markers, the best
 542  642           * we can do is return that status when we have ALL of:
 543  643           *      Output buffer was < SMB_PIPE_MAX_MSGSIZE
 544  644           *      We filled the output buffer (resid==0)
 545  645           *      There's more data (ioctl FIONREAD)
 546  646           */
 547  647          status = NT_STATUS_SUCCESS;
 548  648          if (fsctl->MaxOutputResp < SMB_PIPE_MAX_MSGSIZE &&
 549  649              vdb.vdb_uio.uio_resid == 0) {
 550  650                  int nread = 0, trval;
 551  651                  rc = smb_opipe_ioctl(sr, FIONREAD, &nread, &trval);
 552  652                  if (rc == 0 && nread != 0)
 553  653                          status = NT_STATUS_BUFFER_OVERFLOW;
 554  654          }
 555  655  
 556  656          return (status);
 557  657  }
  
    | 
      ↓ open down ↓ | 
    57 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX