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)
NEX-16818 Add fksmbcl development tool
NEX-17264 SMB client test tp_smbutil_013 fails after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
and: (fix ref leaks)
re #11128 nsmb_close locking and teardown deadlock
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c
          +++ new/usr/src/uts/common/fs/smbclnt/netsmb/smb_smb.c
   1    1  /*
   2    2   * Copyright (c) 2000-2001 Boris Popov
   3    3   * All rights reserved.
   4    4   *
   5    5   * Redistribution and use in source and binary forms, with or without
   6    6   * modification, are permitted provided that the following conditions
   7    7   * are met:
   8    8   * 1. Redistributions of source code must retain the above copyright
   9    9   *    notice, this list of conditions and the following disclaimer.
  10   10   * 2. Redistributions in binary form must reproduce the above copyright
  11   11   *    notice, this list of conditions and the following disclaimer in the
  12   12   *    documentation and/or other materials provided with the distribution.
  13   13   * 3. All advertising materials mentioning features or use of this software
  14   14   *    must display the following acknowledgement:
  15   15   *    This product includes software developed by Boris Popov.
  16   16   * 4. Neither the name of the author nor the names of any co-contributors
  17   17   *    may be used to endorse or promote products derived from this software
  18   18   *    without specific prior written permission.
  19   19   *
  20   20   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  21   21   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22   22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23   23   * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  24   24   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25   25   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  
    | 
      ↓ open down ↓ | 
    25 lines elided | 
    
      ↑ open up ↑ | 
  
  26   26   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  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_smb.c,v 1.35.100.2 2005/06/02 00:55:39 lindak Exp $
  33   33   */
  34   34  
  35   35  /*
  36      - * Copyright 2012 Nexenta Systems, Inc.  All rights reserved.
       36 + * Portions Copyright (C) 2001 - 2014 Apple Inc. All rights reserved.
  37   37   * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
       38 + * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  38   39   */
  39   40  
  40   41  /*
  41   42   * various SMB requests. Most of the routines merely packs data into mbufs.
  42   43   */
  43   44  #include <sys/param.h>
  44   45  #include <sys/systm.h>
  45   46  #include <sys/kmem.h>
  46   47  #include <sys/proc.h>
  47   48  #include <sys/lock.h>
  48   49  #include <sys/socket.h>
  49   50  #include <sys/uio.h>
  50   51  #include <sys/random.h>
  51   52  #include <sys/note.h>
       53 +#include <sys/errno.h>
  52   54  #include <sys/cmn_err.h>
  53   55  
  54   56  #include <netsmb/smb_osdep.h>
  55   57  
  56   58  #include <netsmb/smb.h>
  57   59  #include <netsmb/smb_conn.h>
  58   60  #include <netsmb/smb_rq.h>
  59   61  #include <netsmb/smb_subr.h>
  60   62  #include <netsmb/smb_tran.h>
  61   63  
  62   64  #define STYPE_LEN       8       /* share type strings */
  63   65  
  64      -/*
  65      - * Largest size to use with LARGE_READ/LARGE_WRITE.
  66      - * Specs say up to 64k data bytes, but Windows traffic
  67      - * uses 60k... no doubt for some good reason.
  68      - * (Probably to keep 4k block alignment.)
  69      - * XXX: Move to smb.h maybe?
  70      - */
  71      -#define SMB_MAX_LARGE_RW_SIZE (60*1024)
       66 +struct smb_dialect {
       67 +        int             d_id;
       68 +        const char      *d_name;
       69 +};
  72   70  
       71 +static struct smb_dialect smb_dialects[3] = {
       72 +        {SMB_DIALECT_NTLM0_12,  "NT LANMAN 1.0"},
       73 +        {SMB_DIALECT_NTLM0_12,  "NT LM 0.12"},
       74 +#define NDIALECT_SMB1   2
       75 +        {SMB_DIALECT_SMB2_FF,   "SMB 2.???"},
       76 +#define NDIALECT_SMB2   3
       77 +};
       78 +
       79 +static const uint32_t smb_clnt_caps_mask =
       80 +    SMB_CAP_UNICODE |
       81 +    SMB_CAP_LARGE_FILES |
       82 +    SMB_CAP_NT_SMBS |
       83 +    SMB_CAP_STATUS32 |
       84 +    SMB_CAP_EXT_SECURITY;
       85 +
  73   86  /*
  74   87   * Default timeout values, all in seconds.
  75   88   * Make these tunable (only via mdb for now).
  76   89   */
  77   90  int smb_timo_notice = 15;
  78   91  int smb_timo_default = 30;      /* was SMB_DEFRQTIMO */
       92 +int smb_timo_logon = 45;
  79   93  int smb_timo_open = 45;
  80   94  int smb_timo_read = 45;
  81   95  int smb_timo_write = 60;        /* was SMBWRTTIMO */
  82   96  int smb_timo_append = 90;
  83   97  
  84      -static int smb_smb_read(struct smb_share *ssp, uint16_t fid,
  85      -        uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
  86      -static int smb_smb_write(struct smb_share *ssp, uint16_t fid,
  87      -        uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
       98 +int
       99 +smb_smb_negotiate(struct smb_vc *vcp, struct smb_cred *scred)
      100 +{
      101 +        smb_sopt_t *sv = &vcp->vc_sopt;
      102 +        smbioc_ssn_work_t *wk = &vcp->vc_work;
      103 +        struct smb_rq *rqp = NULL;
      104 +        struct mbchain *mbp = NULL;
      105 +        struct mdchain *mdp = NULL;
      106 +        struct smb_dialect *dp;
      107 +        int err, sblen, tlen;
      108 +        uint8_t wc, eklen;
      109 +        uint16_t dindex, bc;
      110 +        uint16_t ndialects;
      111 +        boolean_t will_sign = B_FALSE;
  88  112  
  89      -static int smb_smb_readx(struct smb_share *ssp, uint16_t fid,
  90      -        uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
  91      -static int smb_smb_writex(struct smb_share *ssp, uint16_t fid,
  92      -        uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo);
      113 +        /*
      114 +         * Initialize: vc_hflags and vc_hflags2.
      115 +         * Note: vcp->vc_hflags* are copied into the
      116 +         * (per request) rqp->rq_hflags* by smb_rq_init.
      117 +         *
      118 +         * Like Windows, set FLAGS2_UNICODE in our first request,
      119 +         * even though technically we don't yet know whether the
      120 +         * server supports Unicode.  Will clear this flag below
      121 +         * if we find out it doesn't.  Need to do this because
      122 +         * some servers reject all non-Unicode requests.
      123 +         */
      124 +        vcp->vc_hflags =
      125 +            SMB_FLAGS_CASELESS |
      126 +            SMB_FLAGS_CANONICAL_PATHNAMES;
      127 +        vcp->vc_hflags2 =
      128 +            SMB_FLAGS2_KNOWS_LONG_NAMES |
      129 +            SMB_FLAGS2_KNOWS_EAS |
      130 +            SMB_FLAGS2_IS_LONG_NAME |
      131 +            SMB_FLAGS2_EXT_SEC |
      132 +            SMB_FLAGS2_ERR_STATUS |
      133 +            SMB_FLAGS2_UNICODE;
  93  134  
      135 +        /*
      136 +         * The initial UID needs to be zero,
      137 +         */
      138 +        vcp->vc_smbuid = 0;
      139 +
      140 +        /*
      141 +         * (Re)init negotiated values
      142 +         */
      143 +        bzero(sv, sizeof (*sv));
      144 +        sv->sv_maxmux = 1;
      145 +        sv->sv_maxvcs = 1;
      146 +        sv->sv_maxtx = 1024;
      147 +
      148 +        /*
      149 +         * Should we offer the magic SMB2 dialect?
      150 +         */
      151 +        if (vcp->vc_ssn.ssn_maxver >= SMB2_DIALECT_BASE)
      152 +                ndialects = NDIALECT_SMB2;
      153 +        else
      154 +                ndialects = NDIALECT_SMB1;
      155 +
      156 +        err = smb_rq_alloc(VCTOCP(vcp), SMB_COM_NEGOTIATE, scred, &rqp);
      157 +        if (err)
      158 +                return (err);
      159 +
      160 +        /*
      161 +         * Build the SMB request.
      162 +         */
      163 +        smb_rq_getrequest(rqp, &mbp);
      164 +        smb_rq_wstart(rqp);
      165 +        smb_rq_wend(rqp);
      166 +        smb_rq_bstart(rqp);
      167 +        for (dindex = 0; dindex < ndialects; dindex++) {
      168 +                dp = &smb_dialects[dindex];
      169 +                mb_put_uint8(mbp, SMB_DT_DIALECT);
      170 +                tlen = strlen(dp->d_name) + 1;
      171 +                mb_put_mem(mbp, dp->d_name, tlen, MB_MSYSTEM);
      172 +        }
      173 +        smb_rq_bend(rqp);
      174 +
      175 +        /*
      176 +         * Do the OTW call.
      177 +         */
      178 +        err = smb_rq_internal(rqp, smb_timo_default);
      179 +        /*
      180 +         * If it's an SMB1-to-SMB2 negotiate response,
      181 +         * call the special handler and then skip the
      182 +         * whole rest of this function.
      183 +         */
      184 +        if (err == EPROTO) {
      185 +                err = smb2_parse_smb1nego_resp(rqp);
      186 +                smb_rq_done(rqp);
      187 +                return (err);
      188 +        }
      189 +        if (err) {
      190 +                SMBSDEBUG("smb_rq_internal, err %d", err);
      191 +                goto errout;
      192 +        }
      193 +        /* Should only get status success. */
      194 +        if (rqp->sr_error != NT_STATUS_SUCCESS) {
      195 +                err = ENOTSUP;
      196 +                goto errout;
      197 +        }
      198 +
      199 +        /*
      200 +         * Decode the response
      201 +         *
      202 +         * Comments to right show names as described in
      203 +         * The Microsoft SMB Protocol spec. [MS-SMB]
      204 +         * section 2.2.3
      205 +         */
      206 +        smb_rq_getreply(rqp, &mdp);
      207 +        (void) md_get_uint8(mdp, &wc);
      208 +        err = md_get_uint16le(mdp, &dindex);
      209 +        if (err != 0)
      210 +                goto errout;
      211 +        if (dindex >= ndialects) {
      212 +                SMBERROR("Invalid dialect index from server: %s\n",
      213 +                    vcp->vc_srvname);
      214 +                err = EBADRPC;
      215 +                goto errout;
      216 +        }
      217 +        dp = smb_dialects + dindex;
      218 +        sv->sv_proto = dp->d_id;
      219 +        SMBSDEBUG("Dialect %s", dp->d_name);
      220 +        if (dp->d_id < SMB_DIALECT_NTLM0_12) {
      221 +                SMBSDEBUG("old dialect %s", dp->d_name);
      222 +                goto errout;
      223 +        }
      224 +        if (wc != 17) {
      225 +                SMBSDEBUG("bad wc %d", (int)wc);
      226 +                goto errout;
      227 +        }
      228 +        md_get_uint8(mdp, &sv->sv_sm);          /* SecurityMode */
      229 +        md_get_uint16le(mdp, &sv->sv_maxmux);   /* MaxMpxCount */
      230 +        md_get_uint16le(mdp, &sv->sv_maxvcs);   /* MaxCountVCs */
      231 +        md_get_uint32le(mdp, &sv->sv_maxtx);    /* MaxBufferSize */
      232 +        md_get_uint32le(mdp, &sv->sv_maxraw);   /* MaxRawSize */
      233 +        md_get_uint32le(mdp, &sv->sv_skey);     /* SessionKey */
      234 +        md_get_uint32le(mdp, &sv->sv_caps);     /* Capabilities */
      235 +        md_get_mem(mdp, NULL, 8, MB_MSYSTEM);   /* SystemTime(s) */
      236 +        md_get_uint16le(mdp, (uint16_t *)&sv->sv_tz);
      237 +        md_get_uint8(mdp, &eklen);      /* EncryptionKeyLength */
      238 +        err = md_get_uint16le(mdp, &bc);        /* ByteCount */
      239 +        if (err)
      240 +                goto errout;
      241 +
      242 +        /* BEGIN CSTYLED */
      243 +        /*
      244 +         * Will we do SMB signing?  Or block the connection?
      245 +         * The table below describes this logic.  References:
      246 +         * [Windows Server Protocols: MS-SMB, sec. 3.2.4.2.3]
      247 +         * http://msdn.microsoft.com/en-us/library/cc212511.aspx
      248 +         * http://msdn.microsoft.com/en-us/library/cc212929.aspx
      249 +         *
      250 +         * Srv/Cli     | Required | Enabled    | If Required | Disabled
      251 +         * ------------+----------+------------+-------------+-----------
      252 +         * Required    | Signed   | Signed     | Signed      | Blocked [1]
      253 +         * ------------+----------+------------+-------------+-----------
      254 +         * Enabled     | Signed   | Signed     | Not Signed  | Not Signed
      255 +         * ------------+----------+------------+-------------+-----------
      256 +         * If Required | Signed   | Not Signed | Not Signed  | Not Signed
      257 +         * ------------+----------+------------+-------------+-----------
      258 +         * Disabled    | Blocked  | Not Signed | Not Signed  | Not Signed
      259 +         *
      260 +         * [1] Like Windows 2003 and later, we don't really implement
      261 +         * the "Disabled" setting.  Instead we implement "If Required",
      262 +         * so we always sign if the server requires signing.
      263 +         */
      264 +        /* END CSTYLED */
      265 +
      266 +        if (sv->sv_sm & SMB_SM_SIGS_REQUIRE) {
      267 +                /*
      268 +                 * Server requires signing.  We will sign,
      269 +                 * even if local setting is "disabled".
      270 +                 */
      271 +                will_sign = B_TRUE;
      272 +        } else if (sv->sv_sm & SMB_SM_SIGS) {
      273 +                /*
      274 +                 * Server enables signing (client's option).
      275 +                 * If enabled locally, do signing.
      276 +                 */
      277 +                if (vcp->vc_vopt & SMBVOPT_SIGNING_ENABLED)
      278 +                        will_sign = B_TRUE;
      279 +                /* else not signing. */
      280 +        } else {
      281 +                /*
      282 +                 * Server does not support signing.
      283 +                 * If we "require" it, bail now.
      284 +                 */
      285 +                if (vcp->vc_vopt & SMBVOPT_SIGNING_REQUIRED) {
      286 +                        SMBERROR("Client requires signing "
      287 +                            "but server has it disabled.");
      288 +                        err = EBADRPC;
      289 +                        goto errout;
      290 +                }
      291 +        }
      292 +
      293 +        /*
      294 +         * Anonymous sessions can't sign.
      295 +         */
      296 +        if (vcp->vc_vopt & SMBVOPT_ANONYMOUS) {
      297 +                will_sign = B_FALSE;
      298 +        }
      299 +
      300 +        SMBSDEBUG("Security signatures: %d", (int)will_sign);
      301 +        if (will_sign) {
      302 +                vcp->vc_flags |= SMBV_SIGNING;
      303 +                vcp->vc_hflags2 |= SMB_FLAGS2_SECURITY_SIGNATURE;
      304 +
      305 +                /*
      306 +                 * MS-SMB 2.2.4.5 says that when SMB signing is enabled,
      307 +                 * we should NOT use "large read/write" even though the
      308 +                 * server might offer those capabilities.
      309 +                 */
      310 +                sv->sv_caps &= ~(SMB_CAP_LARGE_READX | SMB_CAP_LARGE_WRITEX);
      311 +        }
      312 +
      313 +        /* See comment above re. FLAGS2_UNICODE */
      314 +        if ((sv->sv_caps & SMB_CAP_UNICODE) != 0)
      315 +                vcp->vc_flags |= SMBV_UNICODE;
      316 +        else
      317 +                vcp->vc_hflags2 &= ~SMB_FLAGS2_UNICODE;
      318 +
      319 +        if ((sv->sv_caps & SMB_CAP_STATUS32) == 0) {
      320 +                /* They don't do NT error codes. */
      321 +                vcp->vc_hflags2 &= ~SMB_FLAGS2_ERR_STATUS;
      322 +        }
      323 +
      324 +        /*
      325 +         * Warn if they don't support SMB_CAP_NT_SMBS
      326 +         * (We'll try to use NtCreate anyway)
      327 +         */
      328 +        if ((sv->sv_caps & SMB_CAP_NT_SMBS) == 0) {
      329 +                cmn_err(CE_NOTE, "%s does not support SMB_CAP_NT_SMBS",
      330 +                    vcp->vc_srvname);
      331 +        }
      332 +
      333 +        /*
      334 +         * The rest of the message varies depending on
      335 +         * whether we've negotiated "extended security".
      336 +         *
      337 +         * With extended security, we have:
      338 +         *      Server_GUID     (length 16)
      339 +         *      Security_BLOB
      340 +         * Otherwise we have:
      341 +         *      EncryptionKey (length is eklen)
      342 +         *      PrimaryDomain
      343 +         */
      344 +        if (sv->sv_caps & SMB_CAP_EXT_SECURITY) {
      345 +                SMBSDEBUG("Ext.Security: yes");
      346 +
      347 +                /*
      348 +                 * Skip the server GUID.
      349 +                 */
      350 +                err = md_get_mem(mdp, NULL, SMB_GUIDLEN, MB_MSYSTEM);
      351 +                if (err)
      352 +                        goto errout;
      353 +                /*
      354 +                 * Remainder is the security blob.
      355 +                 * Note: eklen "must be ignored" [MS-SMB]
      356 +                 */
      357 +                sblen = (int)bc - SMB_GUIDLEN;
      358 +                if (sblen < 0)
      359 +                        goto errout;
      360 +                /* Security blob (hint) is next */
      361 +        } else {
      362 +                SMBSDEBUG("Ext.Security: no");
      363 +                err = ENOTSUP;
      364 +                goto errout;
      365 +        }
      366 +
      367 +        /*
      368 +         * Copy the security blob out to user space.
      369 +         * Buffer addr,size in vc_auth_rbuf,rlen
      370 +         */
      371 +        if (wk->wk_u_auth_rlen < sblen) {
      372 +                SMBSDEBUG("vc_auth_rbuf too small");
      373 +                /* Give caller required size. */
      374 +                wk->wk_u_auth_rlen = sblen;
      375 +                err = EMSGSIZE;
      376 +                goto errout;
      377 +        }
      378 +        wk->wk_u_auth_rlen = sblen;
      379 +        err = md_get_mem(mdp, wk->wk_u_auth_rbuf.lp_ptr, sblen, MB_MUSER);
      380 +        if (err)
      381 +                goto errout;
      382 +
      383 +        /*
      384 +         * A few sanity checks on what we received,
      385 +         * becuse we will send these in ssnsetup.
      386 +         *
      387 +         * Maximum outstanding requests (we care),
      388 +         * and Max. VCs (we only use one).  Also,
      389 +         * MaxBufferSize lower limit per spec.
      390 +         */
      391 +        if (sv->sv_maxmux < 1)
      392 +                sv->sv_maxmux = 1;
      393 +        if (sv->sv_maxvcs < 1)
      394 +                sv->sv_maxvcs = 1;
      395 +        if (sv->sv_maxtx < 1024)
      396 +                sv->sv_maxtx = 1024;
      397 +
      398 +        /*
      399 +         * Maximum transfer size.
      400 +         * Sanity checks:
      401 +         *
      402 +         * Let's be conservative about an upper limit here.
      403 +         * Win2k uses 16644 (and others) so 32k should be a
      404 +         * reasonable sanity limit for this value.
      405 +         *
      406 +         * Note that this limit does NOT affect READX/WRITEX
      407 +         * with CAP_LARGE_..., which we nearly always use.
      408 +         */
      409 +        vcp->vc_txmax = sv->sv_maxtx;
      410 +        if (vcp->vc_txmax > 0x8000)
      411 +                vcp->vc_txmax = 0x8000;
      412 +
      413 +        /*
      414 +         * Max read/write sizes, WITHOUT overhead.
      415 +         * This is just the payload size, so we must
      416 +         * leave room for the SMB headers, etc.
      417 +         * This is just the ct_txmax value, but
      418 +         * reduced and rounded down.  Tricky bit:
      419 +         *
      420 +         * Servers typically give us a value that's
      421 +         * some nice "round" number, i.e 0x4000 plus
      422 +         * some overhead, i.e. Win2k: 16644==0x4104
      423 +         * Subtract for the SMB header (32) and the
      424 +         * SMB command word and byte vectors (34?),
      425 +         * then round down to a 512 byte multiple.
      426 +         */
      427 +        tlen = vcp->vc_txmax - 68;
      428 +        tlen &= 0xFE00;
      429 +
      430 +        vcp->vc_rwmax = tlen;
      431 +        vcp->vc_rxmax = tlen;
      432 +        vcp->vc_wxmax = tlen;
      433 +
      434 +        /*
      435 +         * Most of the "capability" bits we offer in session setup
      436 +         * are just copied from those offered by the server.
      437 +         */
      438 +        sv->sv_caps &= smb_clnt_caps_mask;
      439 +
      440 +        smb_rq_done(rqp);
      441 +        return (0);
      442 +
      443 +errout:
      444 +        smb_rq_done(rqp);
      445 +        if (err == 0)
      446 +                err = EBADRPC;
      447 +        return (err);
      448 +}
      449 +
      450 +static const char NativeOS[] = "illumos";
      451 +static const char LanMan[] = "NETSMB";
      452 +
      453 +int
      454 +smb_smb_ssnsetup(struct smb_vc *vcp, struct smb_cred *scred)
      455 +{
      456 +        smb_sopt_t *sv = &vcp->vc_sopt;
      457 +        smbioc_ssn_work_t *wk = &vcp->vc_work;
      458 +        struct smb_rq *rqp = NULL;
      459 +        struct mbchain *mbp = NULL;
      460 +        struct mdchain *mdp = NULL;
      461 +        char *sb;
      462 +        int err, ret;
      463 +        uint32_t caps;
      464 +        uint16_t action, bc, sblen;
      465 +        uint8_t wc;
      466 +
      467 +        caps = sv->sv_caps;
      468 +        sb = wk->wk_u_auth_wbuf.lp_ptr;
      469 +        sblen = (uint16_t)wk->wk_u_auth_wlen;
      470 +
      471 +        err = smb_rq_alloc(VCTOCP(vcp), SMB_COM_SESSION_SETUP_ANDX,
      472 +            scred, &rqp);
      473 +        if (err != 0) {
      474 +                ret = err;
      475 +                goto out;
      476 +        }
      477 +
      478 +        /*
      479 +         * Build the SMB Session Setup request.
      480 +         * Always extended security form.
      481 +         */
      482 +        mbp = &rqp->sr_rq;
      483 +        smb_rq_wstart(rqp);
      484 +        mb_put_uint16le(mbp, 0xff);             /* 0: AndXCommand */
      485 +        mb_put_uint16le(mbp, 0);                /* 1: AndXOffset */
      486 +        mb_put_uint16le(mbp, sv->sv_maxtx);     /* 2: MaxBufferSize */
      487 +        mb_put_uint16le(mbp, sv->sv_maxmux);    /* 3: MaxMpxCount */
      488 +        mb_put_uint16le(mbp, 1);                /* 4: VcNumber */
      489 +        mb_put_uint32le(mbp, sv->sv_skey);      /* 5,6: Session Key */
      490 +        mb_put_uint16le(mbp, sblen);    /* 7: Sec. Blob Len */
      491 +        mb_put_uint32le(mbp, 0);        /* 8,9: reserved */
      492 +        mb_put_uint32le(mbp, caps);     /* 10,11: Capabilities */
      493 +        smb_rq_wend(rqp);               /* 12: Byte Count */
      494 +        smb_rq_bstart(rqp);
      495 +        err = mb_put_mem(mbp, sb, sblen, MB_MUSER);
      496 +        if (err != 0) {
      497 +                ret = err;
      498 +                goto out;
      499 +        }
      500 +        (void) smb_put_dstring(mbp, vcp, NativeOS, SMB_CS_NONE);
      501 +        (void) smb_put_dstring(mbp, vcp, LanMan, SMB_CS_NONE);
      502 +        smb_rq_bend(rqp);
      503 +
      504 +        /*
      505 +         * Run the request.  The return value here should be the
      506 +         * return from this function, unless we fail decoding.
      507 +         * Note: NT_STATUS_MORE_PROCESSING_REQUIRED is OK, and
      508 +         * the caller expects EINPROGRESS for that case.
      509 +         */
      510 +        ret = smb_rq_internal(rqp, smb_timo_logon);
      511 +        if (ret != 0)
      512 +                goto out;
      513 +        switch (rqp->sr_error) {
      514 +        case NT_STATUS_SUCCESS:
      515 +                break;
      516 +        case NT_STATUS_MORE_PROCESSING_REQUIRED:
      517 +                /* Keep going, but return... */
      518 +                ret = EINPROGRESS;
      519 +                break;
      520 +        default:
      521 +                ret = EAUTH;
      522 +                goto out;
      523 +        }
      524 +
      525 +        if (vcp->vc_smbuid == 0)
      526 +                vcp->vc_smbuid = rqp->sr_rpuid;
      527 +
      528 +        /*
      529 +         * Parse the reply
      530 +         */
      531 +        smb_rq_getreply(rqp, &mdp);
      532 +
      533 +        err = md_get_uint8(mdp, &wc);
      534 +        if (err != 0)
      535 +                wc = 0;
      536 +        if (wc != 4) {
      537 +                ret = EBADRPC;
      538 +                goto out;
      539 +        }
      540 +        md_get_uint16le(mdp, NULL);     /* secondary cmd */
      541 +        md_get_uint16le(mdp, NULL);     /* andxoffset */
      542 +        md_get_uint16le(mdp, &action);  /* action XXX */
      543 +        md_get_uint16le(mdp, &sblen);   /* sec. blob len */
      544 +        md_get_uint16le(mdp, &bc);      /* byte count */
      545 +        /*
      546 +         * Get the security blob, after
      547 +         * sanity-checking the length.
      548 +         */
      549 +        if (sblen == 0 || sblen > bc) {
      550 +                ret = EBADRPC;
      551 +                goto out;
      552 +        }
      553 +        if (sblen > wk->wk_u_auth_rlen) {
      554 +                ret = EBADRPC;
      555 +                goto out;
      556 +        }
      557 +        sb = wk->wk_u_auth_rbuf.lp_ptr;
      558 +        err = md_get_mem(mdp, sb, sblen, MB_MUSER);
      559 +        if (err) {
      560 +                ret = EBADRPC;
      561 +                goto out;
      562 +        }
      563 +
      564 +        /*
      565 +         * Native OS, LANMGR, & Domain follow here.
      566 +         * We don't need them and don't parse them.
      567 +         */
      568 +
      569 +out:
      570 +        if (err != 0 && err != EINPROGRESS) {
      571 +                /* UID no longer valid. */
      572 +                vcp->vc_smbuid = 0;
      573 +        }
      574 +        if (rqp)
      575 +                smb_rq_done(rqp);
      576 +
      577 +        return (ret);
      578 +}
      579 +
      580 +int
      581 +smb_smb_logoff(struct smb_vc *vcp, struct smb_cred *scred)
      582 +{
      583 +        struct smb_rq *rqp;
      584 +        struct mbchain *mbp;
      585 +        int error;
      586 +
      587 +        if (vcp->vc_smbuid == SMB_UID_UNKNOWN)
      588 +                return (0);
      589 +
      590 +        error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_LOGOFF_ANDX, scred, &rqp);
      591 +        if (error)
      592 +                return (error);
      593 +        mbp = &rqp->sr_rq;
      594 +        smb_rq_wstart(rqp);
      595 +        mb_put_uint8(mbp, 0xff);
      596 +        mb_put_uint8(mbp, 0);
      597 +        mb_put_uint16le(mbp, 0);
      598 +        smb_rq_wend(rqp);
      599 +        smb_rq_bstart(rqp);
      600 +        smb_rq_bend(rqp);
      601 +
      602 +        /*
      603 +         * Run this with a relatively short timeout. (5 sec.)
      604 +         * We don't really care about the result here.
      605 +         * Also, don't reconnect for this, of course!
      606 +         */
      607 +        rqp->sr_flags |= SMBR_NORECONNECT;
      608 +        error = smb_rq_internal(rqp, 5);
      609 +        smb_rq_done(rqp);
      610 +        return (error);
      611 +}
      612 +
  94  613  /*
  95  614   * Get the string representation of a share "use" type,
  96  615   * as needed for the "service" in tree connect.
  97  616   */
  98  617  static const char *
  99  618  smb_share_typename(uint32_t stype)
 100  619  {
 101  620          const char *p;
 102  621  
 103  622          switch (stype) {
 104  623          case STYPE_DISKTREE:
 105  624                  p = "A:";
 106  625                  break;
 107  626          case STYPE_PRINTQ:
 108  627                  p = "LPT1:";
 109  628                  break;
 110  629          case STYPE_DEVICE:
 111  630                  p = "COMM";
 112  631                  break;
 113  632          case STYPE_IPC:
 114  633                  p = "IPC";
 115  634                  break;
 116  635          case STYPE_UNKNOWN:
 117  636          default:
 118  637                  p = "?????";
 119  638                  break;
 120  639          }
 121  640          return (p);
 122  641  }
 123  642  
 124  643  /*
 125  644   * Parse a share type name (inverse of above)
 126  645   */
 127  646  static uint32_t
 128  647  smb_share_parsetype(char *name)
 129  648  {
 130  649          int stype;
 131  650  
 132  651          switch (*name) {
 133  652          case 'A':       /* A: */
 134  653                  stype = STYPE_DISKTREE;
 135  654                  break;
 136  655          case 'C':       /* COMM */
 137  656                  stype = STYPE_DEVICE;
 138  657                  break;
 139  658          case 'I':       /* IPC */
 140  659                  stype = STYPE_IPC;
 141  660                  break;
 142  661          case 'L':       /* LPT: */
 143  662                  stype = STYPE_PRINTQ;
 144  663                  break;
 145  664          default:
 146  665                  stype = STYPE_UNKNOWN;
 147  666                  break;
 148  667          }
 149  668          return (stype);
 150  669  }
 151  670  
 152  671  int
 153  672  smb_smb_treeconnect(struct smb_share *ssp, struct smb_cred *scred)
 154  673  {
 155  674          struct smb_vc *vcp;
 156  675          struct smb_rq *rqp = NULL;
 157  676          struct mbchain *mbp;
 158  677          struct mdchain *mdp;
 159  678          const char *tname;
 160  679          char *pbuf, *unc_name = NULL;
 161  680          int error, tlen, plen, unc_len;
 162  681          uint16_t bcnt, options;
 163  682          uint8_t wc;
 164  683          char stype_str[STYPE_LEN];
 165  684  
 166  685          vcp = SSTOVC(ssp);
 167  686  
 168  687          /*
 169  688           * Make this a "VC-level" request, so it will have
 170  689           * rqp->sr_share == NULL, and smb_iod_sendrq()
 171  690           * will send it with TID = SMB_TID_UNKNOWN
 172  691           *
 173  692           * This also serves to bypass the wait for
 174  693           * share state changes, which this call is
 175  694           * trying to carry out.
 176  695           */
 177  696          error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_TREE_CONNECT_ANDX,
 178  697              scred, &rqp);
 179  698          if (error)
 180  699                  return (error);
 181  700  
 182  701          /*
 183  702           * Build the UNC name, i.e. "//server/share"
 184  703           * but with backslashes of course.
 185  704           * size math: three slashes, one null.
 186  705           */
 187  706          unc_len = 4 + strlen(vcp->vc_srvname) + strlen(ssp->ss_name);
 188  707          unc_name = kmem_alloc(unc_len, KM_SLEEP);
 189  708          (void) snprintf(unc_name, unc_len, "\\\\%s\\%s",
 190  709              vcp->vc_srvname, ssp->ss_name);
 191  710          SMBSDEBUG("unc_name: \"%s\"", unc_name);
 192  711  
 193  712  
 194  713          /*
 195  714           * Share-level password (pre-computed in user-space)
 196  715           * MS-SMB 2.2.6 says this should be null terminated,
 197  716           * and the pw length includes the null.
 198  717           */
 199  718          pbuf = ssp->ss_pass;
 200  719          plen = strlen(pbuf) + 1;
 201  720  
 202  721          /*
 203  722           * Build the request.
 204  723           */
 205  724          mbp = &rqp->sr_rq;
 206  725          smb_rq_wstart(rqp);
 207  726          mb_put_uint8(mbp, 0xff);
 208  727          mb_put_uint8(mbp, 0);
 209  728          mb_put_uint16le(mbp, 0);
 210  729          mb_put_uint16le(mbp, 0);                /* Flags */
 211  730          mb_put_uint16le(mbp, plen);
 212  731          smb_rq_wend(rqp);
 213  732          smb_rq_bstart(rqp);
 214  733  
 215  734          /* Tree connect password, if any */
 216  735          error = mb_put_mem(mbp, pbuf, plen, MB_MSYSTEM);
 217  736          if (error)
 218  737                  goto out;
 219  738  
 220  739          /* UNC resource name */
 221  740          error = smb_put_dstring(mbp, vcp, unc_name, SMB_CS_NONE);
 222  741          if (error)
 223  742                  goto out;
 224  743  
 225  744          /*
 226  745           * Put the type string (always ASCII),
 227  746           * including the null.
 228  747           */
 229  748          tname = smb_share_typename(ssp->ss_use);
 230  749          tlen = strlen(tname) + 1;
 231  750          error = mb_put_mem(mbp, tname, tlen, MB_MSYSTEM);
 232  751          if (error)
 233  752                  goto out;
 234  753  
 235  754          smb_rq_bend(rqp);
 236  755  
 237  756          /*
 238  757           * Run the request.
 239  758           *
 240  759           * Using NOINTR_RECV because we don't want to risk
 241  760           * missing a successful tree connect response,
 242  761           * which would "leak" Tree IDs.
 243  762           */
 244  763          rqp->sr_flags |= SMBR_NOINTR_RECV;
 245  764          error = smb_rq_simple(rqp);
 246  765          SMBSDEBUG("%d\n", error);
 247  766          if (error) {
 248  767                  /*
 249  768                   * If we get the server name wrong, i.e. due to
 250  769                   * mis-configured name services, this will be
 251  770                   * NT_STATUS_DUPLICATE_NAME.  Log this error.
 252  771                   */
 253  772                  SMBERROR("(%s) failed, status=0x%x",
 254  773                      unc_name, rqp->sr_error);
 255  774                  goto out;
 256  775          }
 257  776  
 258  777          /*
 259  778           * Parse the TCON response
 260  779           */
 261  780          smb_rq_getreply(rqp, &mdp);
 262  781          md_get_uint8(mdp, &wc);
 263  782          if (wc != 3 && wc != 7) {
 264  783                  error = EBADRPC;
 265  784                  goto out;
 266  785          }
 267  786          md_get_uint16le(mdp, NULL);             /* AndX cmd */
 268  787          md_get_uint16le(mdp, NULL);             /* AndX off */
 269  788          md_get_uint16le(mdp, &options);         /* option bits (DFS, search) */
 270  789          if (wc == 7) {
 271  790                  md_get_uint32le(mdp, NULL);     /* MaximalShareAccessRights */
 272  791                  md_get_uint32le(mdp, NULL);     /* GuestMaximalShareAcc... */
 273  792          }
 274  793          error = md_get_uint16le(mdp, &bcnt);    /* byte count */
 275  794          if (error)
 276  795                  goto out;
 277  796  
 278  797          /*
 279  798           * Get the returned share type string, i.e. "IPC" or whatever.
 280  799           * (See smb_share_typename, smb_share_parsetype).  If we get
 281  800           * an error reading the type, just say STYPE_UNKNOWN.
 282  801           */
 283  802          tlen = STYPE_LEN;
 284  803          bzero(stype_str, tlen--);
 285  804          if (tlen > bcnt)
 286  805                  tlen = bcnt;
 287  806          md_get_mem(mdp, stype_str, tlen, MB_MSYSTEM);
 288  807          stype_str[tlen] = '\0';
 289  808          ssp->ss_type = smb_share_parsetype(stype_str);
 290  809  
 291  810          /* Success! */
 292  811          SMB_SS_LOCK(ssp);
 293  812          ssp->ss_tid = rqp->sr_rptid;
 294  813          ssp->ss_vcgenid = vcp->vc_genid;
 295  814          ssp->ss_options = options;
 296  815          ssp->ss_flags |= SMBS_CONNECTED;
 297  816          SMB_SS_UNLOCK(ssp);
 298  817  
 299  818  out:
 300  819          if (unc_name)
 301  820                  kmem_free(unc_name, unc_len);
 302  821          smb_rq_done(rqp);
 303  822          return (error);
 304  823  }
 305  824  
 306  825  int
 307  826  smb_smb_treedisconnect(struct smb_share *ssp, struct smb_cred *scred)
 308  827  {
 309  828          struct smb_vc *vcp;
 310  829          struct smb_rq *rqp;
 311  830          int error;
 312  831  
 313  832          if (ssp->ss_tid == SMB_TID_UNKNOWN)
 314  833                  return (0);
 315  834  
 316  835          /*
 317  836           * Build this as a "VC-level" request, so it will
 318  837           * avoid testing the _GONE flag on the share,
 319  838           * which has already been set at this point.
 320  839           * Add the share pointer "by hand" below, so
 321  840           * smb_iod_sendrq will plug in the TID.
 322  841           */
 323  842          vcp = SSTOVC(ssp);
 324  843          error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_TREE_DISCONNECT, scred, &rqp);
 325  844          if (error)
 326  845                  return (error);
 327  846          rqp->sr_share = ssp; /* by hand */
 328  847  
 329  848          smb_rq_wstart(rqp);
 330  849          smb_rq_wend(rqp);
 331  850          smb_rq_bstart(rqp);
 332  851          smb_rq_bend(rqp);
 333  852  
 334  853          /*
 335  854           * Run this with a relatively short timeout. (5 sec.)
 336  855           * We don't really care about the result here, but we
 337  856           * do need to make sure we send this out, or we could
 338  857           * "leak" active tree IDs on interrupt or timeout.
 339  858           * The NOINTR_SEND flag makes this request immune to
 340  859           * interrupt or timeout until the send is done.
 341  860           * Also, don't reconnect for this, of course!
 342  861           */
 343  862          rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT);
 344  863          error = smb_rq_simple_timed(rqp, 5);
  
    | 
      ↓ open down ↓ | 
    241 lines elided | 
    
      ↑ open up ↑ | 
  
 345  864          SMBSDEBUG("%d\n", error);
 346  865          smb_rq_done(rqp);
 347  866          ssp->ss_tid = SMB_TID_UNKNOWN;
 348  867          return (error);
 349  868  }
 350  869  
 351  870  /*
 352  871   * Modern create/open of file or directory.
 353  872   */
 354  873  int
 355      -smb_smb_ntcreate(
      874 +smb1_smb_ntcreate(
 356  875          struct smb_share *ssp,
 357  876          struct mbchain  *name_mb,
 358  877          uint32_t cr_flags,      /* create flags */
 359  878          uint32_t req_acc,       /* requested access */
 360  879          uint32_t efa,           /* ext. file attrs (DOS attr +) */
 361  880          uint32_t share_acc,
 362  881          uint32_t open_disp,     /* open disposition */
 363  882          uint32_t createopt,     /* NTCREATEX_OPTIONS_ */
 364  883          uint32_t impersonate,   /* NTCREATEX_IMPERSONATION_... */
 365  884          struct smb_cred *scrp,
 366  885          uint16_t *fidp,         /* returned FID */
 367  886          uint32_t *cr_act_p,     /* optional create action */
 368  887          struct smbfattr *fap)   /* optional attributes */
 369  888  {
 370  889          struct smb_rq rq, *rqp = &rq;
 371  890          struct smb_vc *vcp = SSTOVC(ssp);
 372  891          struct mbchain *mbp;
 373  892          struct mdchain *mdp;
 374  893          struct smbfattr fa;
 375  894          uint64_t llongint;
 376  895          uint32_t longint, createact;
 377  896          uint16_t fid;
 378  897          uint8_t wc;
 379  898          int error;
 380  899  
 381  900          bzero(&fa, sizeof (fa));
 382  901          error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_NT_CREATE_ANDX, scrp);
 383  902          if (error)
 384  903                  return (error);
 385  904          smb_rq_getrequest(rqp, &mbp);
 386  905  
 387  906          /* Word parameters */
 388  907          smb_rq_wstart(rqp);
 389  908          mb_put_uint8(mbp, 0xff);        /* secondary command */
 390  909          mb_put_uint8(mbp, 0);           /* MBZ */
 391  910          mb_put_uint16le(mbp, 0);        /* offset to next command (none) */
 392  911          mb_put_uint8(mbp, 0);           /* MBZ */
 393  912          mb_put_uint16le(mbp, name_mb->mb_count);
 394  913          mb_put_uint32le(mbp, cr_flags); /* NTCREATEX_FLAGS_* */
 395  914          mb_put_uint32le(mbp, 0);        /* FID - basis for path if not root */
 396  915          mb_put_uint32le(mbp, req_acc);
 397  916          mb_put_uint64le(mbp, 0);        /* "initial allocation size" */
 398  917          mb_put_uint32le(mbp, efa);
 399  918          mb_put_uint32le(mbp, share_acc);
 400  919          mb_put_uint32le(mbp, open_disp);
 401  920          mb_put_uint32le(mbp, createopt);
 402  921          mb_put_uint32le(mbp, impersonate);
 403  922          mb_put_uint8(mbp, 0);   /* security flags (?) */
 404  923          smb_rq_wend(rqp);
 405  924  
 406  925          /*
 407  926           * Byte parameters: Just the path name, aligned.
 408  927           * Note: mb_put_mbuf consumes mb_top, so clear it.
 409  928           */
 410  929          smb_rq_bstart(rqp);
 411  930          if (SMB_UNICODE_STRINGS(vcp))
 412  931                  mb_put_padbyte(mbp);
 413  932          mb_put_mbuf(mbp, name_mb->mb_top);
 414  933          bzero(name_mb, sizeof (*name_mb));
 415  934          smb_rq_bend(rqp);
 416  935  
 417  936          /*
 418  937           * Don't want to risk missing a successful
 419  938           * open response, or we could "leak" FIDs.
 420  939           */
 421  940          rqp->sr_flags |= SMBR_NOINTR_RECV;
 422  941          error = smb_rq_simple_timed(rqp, smb_timo_open);
 423  942          if (error)
 424  943                  goto done;
 425  944          smb_rq_getreply(rqp, &mdp);
 426  945          /*
 427  946           * spec says 26 for word count, but 34 words are defined
 428  947           * and observed from win2000
 429  948           */
 430  949          error = md_get_uint8(mdp, &wc);
 431  950          if (error)
 432  951                  goto done;
 433  952          if (wc != 26 && wc < 34) {
 434  953                  error = EBADRPC;
 435  954                  goto done;
 436  955          }
 437  956          md_get_uint8(mdp, NULL);                /* secondary cmd */
 438  957          md_get_uint8(mdp, NULL);                /* mbz */
 439  958          md_get_uint16le(mdp, NULL);             /* andxoffset */
 440  959          md_get_uint8(mdp, NULL);                /* oplock lvl granted */
 441  960          md_get_uint16le(mdp, &fid);             /* file ID */
 442  961          md_get_uint32le(mdp, &createact);       /* create_action */
 443  962  
 444  963          md_get_uint64le(mdp, &llongint);        /* creation time */
 445  964          smb_time_NT2local(llongint, &fa.fa_createtime);
 446  965          md_get_uint64le(mdp, &llongint);        /* access time */
 447  966          smb_time_NT2local(llongint, &fa.fa_atime);
 448  967          md_get_uint64le(mdp, &llongint);        /* write time */
 449  968          smb_time_NT2local(llongint, &fa.fa_mtime);
 450  969          md_get_uint64le(mdp, &llongint);        /* change time */
 451  970          smb_time_NT2local(llongint, &fa.fa_ctime);
 452  971  
 453  972          md_get_uint32le(mdp, &longint);         /* attributes */
 454  973          fa.fa_attr = longint;
 455  974          md_get_uint64le(mdp, &llongint);        /* allocation size */
 456  975          fa.fa_allocsz = llongint;
 457  976          md_get_uint64le(mdp, &llongint);        /* EOF position */
 458  977          fa.fa_size = llongint;
 459  978  
 460  979          error = md_get_uint16le(mdp, NULL);     /* file type */
 461  980          /* other stuff we don't care about */
 462  981  
 463  982  done:
 464  983          smb_rq_done(rqp);
 465  984          if (error)
 466  985                  return (error);
 467  986  
  
    | 
      ↓ open down ↓ | 
    102 lines elided | 
    
      ↑ open up ↑ | 
  
 468  987          *fidp = fid;
 469  988          if (cr_act_p)
 470  989                  *cr_act_p = createact;
 471  990          if (fap)
 472  991                  *fap = fa; /* struct copy */
 473  992  
 474  993          return (0);
 475  994  }
 476  995  
 477  996  int
 478      -smb_smb_close(struct smb_share *ssp, uint16_t fid, struct timespec *mtime,
      997 +smb1_smb_close(struct smb_share *ssp, uint16_t fid, struct timespec *mtime,
 479  998          struct smb_cred *scrp)
 480  999  {
 481 1000          struct smb_rq rq, *rqp = &rq;
 482 1001          struct mbchain *mbp;
 483 1002          long time;
 484 1003          int error;
 485 1004  
 486 1005          error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CLOSE, scrp);
 487 1006          if (error)
 488 1007                  return (error);
 489 1008          smb_rq_getrequest(rqp, &mbp);
 490 1009          smb_rq_wstart(rqp);
 491 1010          mb_put_uint16le(mbp, fid);
 492 1011          if (mtime) {
 493 1012                  int sv_tz = SSTOVC(ssp)->vc_sopt.sv_tz;
 494 1013                  smb_time_local2server(mtime, sv_tz, &time);
 495 1014          } else {
 496 1015                  time = 0;
 497 1016          }
 498 1017          mb_put_uint32le(mbp, time);
 499 1018          smb_rq_wend(rqp);
 500 1019          smb_rq_bstart(rqp);
 501 1020          smb_rq_bend(rqp);
 502 1021  
 503 1022          /* Make sure we send, but only if already connected */
 504 1023          rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT);
 505 1024          error = smb_rq_simple(rqp);
 506 1025          smb_rq_done(rqp);
 507 1026          return (error);
 508 1027  }
 509 1028  
 510 1029  int
 511 1030  smb_smb_open_prjob(
 512 1031          struct smb_share *ssp,
 513 1032          char    *title,
 514 1033          uint16_t setuplen,
 515 1034          uint16_t mode,
 516 1035          struct smb_cred *scrp,
 517 1036          uint16_t *fidp)
 518 1037  {
 519 1038          struct smb_rq rq, *rqp = &rq;
 520 1039          struct smb_vc *vcp = SSTOVC(ssp);
 521 1040          struct mbchain *mbp;
 522 1041          struct mdchain *mdp;
 523 1042          uint16_t fid;
 524 1043          uint8_t wc;
 525 1044          int error;
 526 1045  
 527 1046          error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_OPEN_PRINT_FILE, scrp);
 528 1047          if (error)
 529 1048                  return (error);
 530 1049          smb_rq_getrequest(rqp, &mbp);
 531 1050  
 532 1051          /* Word parameters */
 533 1052          smb_rq_wstart(rqp);
 534 1053          mb_put_uint16le(mbp, setuplen);
 535 1054          mb_put_uint16le(mbp, mode);
 536 1055          smb_rq_wend(rqp);
 537 1056  
 538 1057          /*
 539 1058           * Byte parameters: Just the title
 540 1059           */
 541 1060          smb_rq_bstart(rqp);
 542 1061          mb_put_uint8(mbp, SMB_DT_ASCII);
 543 1062          error = smb_put_dstring(mbp, vcp, title, SMB_CS_NONE);
 544 1063          smb_rq_bend(rqp);
 545 1064          if (error)
 546 1065                  goto done;
 547 1066  
 548 1067          /*
 549 1068           * Don't want to risk missing a successful
 550 1069           * open response, or we could "leak" FIDs.
 551 1070           */
 552 1071          rqp->sr_flags |= SMBR_NOINTR_RECV;
 553 1072          error = smb_rq_simple_timed(rqp, smb_timo_open);
 554 1073          if (error)
 555 1074                  goto done;
 556 1075  
 557 1076          smb_rq_getreply(rqp, &mdp);
 558 1077          error = md_get_uint8(mdp, &wc);
 559 1078          if (error || wc < 1) {
 560 1079                  error = EBADRPC;
 561 1080                  goto done;
 562 1081          }
 563 1082          error = md_get_uint16le(mdp, &fid);
 564 1083  
 565 1084  done:
 566 1085          smb_rq_done(rqp);
 567 1086          if (error)
 568 1087                  return (error);
 569 1088  
 570 1089          *fidp = fid;
 571 1090          return (0);
 572 1091  }
 573 1092  
 574 1093  /*
 575 1094   * Like smb_smb_close, but for print shares.
 576 1095   */
 577 1096  int
 578 1097  smb_smb_close_prjob(struct smb_share *ssp, uint16_t fid,
 579 1098          struct smb_cred *scrp)
 580 1099  {
 581 1100          struct smb_rq rq, *rqp = &rq;
 582 1101          struct mbchain *mbp;
 583 1102          int error;
 584 1103  
 585 1104          error = smb_rq_init(rqp, SSTOCP(ssp),
 586 1105              SMB_COM_CLOSE_PRINT_FILE, scrp);
 587 1106          if (error)
 588 1107                  return (error);
 589 1108          smb_rq_getrequest(rqp, &mbp);
 590 1109          smb_rq_wstart(rqp);
 591 1110          mb_put_uint16le(mbp, fid);
 592 1111          smb_rq_wend(rqp);
  
    | 
      ↓ open down ↓ | 
    104 lines elided | 
    
      ↑ open up ↑ | 
  
 593 1112          smb_rq_bstart(rqp);
 594 1113          smb_rq_bend(rqp);
 595 1114  
 596 1115          /* Make sure we send but only if already connected */
 597 1116          rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT);
 598 1117          error = smb_rq_simple(rqp);
 599 1118          smb_rq_done(rqp);
 600 1119          return (error);
 601 1120  }
 602 1121  
 603      -/*
 604      - * Common function for read/write with UIO.
 605      - * Called by netsmb smb_usr_rw,
 606      - *  smbfs_readvnode, smbfs_writevnode
 607      - */
 608 1122  int
 609      -smb_rwuio(struct smb_share *ssp, uint16_t fid, uio_rw_t rw,
     1123 +smb_smb_readx(smb_fh_t *fhp, uint32_t *lenp,
 610 1124          uio_t *uiop, smb_cred_t *scred, int timo)
 611 1125  {
 612      -        struct smb_vc *vcp = SSTOVC(ssp);
 613      -        ssize_t  save_resid;
 614      -        uint32_t len, rlen, maxlen;
 615      -        int error = 0;
 616      -        int (*iofun)(struct smb_share *, uint16_t, uint32_t *,
 617      -            uio_t *, smb_cred_t *, int);
 618      -
 619      -        /*
 620      -         * Determine which function to use,
 621      -         * and the transfer size per call.
 622      -         */
 623      -        if (SMB_DIALECT(vcp) >= SMB_DIALECT_NTLM0_12) {
 624      -                /*
 625      -                 * Using NT LM 0.12, so readx, writex.
 626      -                 * Make sure we can represent the offset.
 627      -                 */
 628      -                if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES) == 0 &&
 629      -                    (uiop->uio_loffset + uiop->uio_resid) > UINT32_MAX)
 630      -                        return (EFBIG);
 631      -
 632      -                if (rw == UIO_READ) {
 633      -                        iofun = smb_smb_readx;
 634      -                        if (vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_READX)
 635      -                                maxlen = SMB_MAX_LARGE_RW_SIZE;
 636      -                        else
 637      -                                maxlen = vcp->vc_rxmax;
 638      -                } else { /* UIO_WRITE */
 639      -                        iofun = smb_smb_writex;
 640      -                        if (vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_WRITEX)
 641      -                                maxlen = SMB_MAX_LARGE_RW_SIZE;
 642      -                        else
 643      -                                maxlen = vcp->vc_wxmax;
 644      -                }
 645      -        } else {
 646      -                /*
 647      -                 * Using the old SMB_READ and SMB_WRITE so
 648      -                 * we're limited to 32-bit offsets, etc.
 649      -                 * XXX: Someday, punt the old dialects.
 650      -                 */
 651      -                if ((uiop->uio_loffset + uiop->uio_resid) > UINT32_MAX)
 652      -                        return (EFBIG);
 653      -
 654      -                if (rw == UIO_READ) {
 655      -                        iofun = smb_smb_read;
 656      -                        maxlen = vcp->vc_rxmax;
 657      -                } else { /* UIO_WRITE */
 658      -                        iofun = smb_smb_write;
 659      -                        maxlen = vcp->vc_wxmax;
 660      -                }
 661      -        }
 662      -
 663      -        save_resid = uiop->uio_resid;
 664      -        while (uiop->uio_resid > 0) {
 665      -                /* Lint: uio_resid may be 64-bits */
 666      -                rlen = len = (uint32_t)min(maxlen, uiop->uio_resid);
 667      -                error = (*iofun)(ssp, fid, &rlen, uiop, scred, timo);
 668      -
 669      -                /*
 670      -                 * Note: the iofun called uio_update, so
 671      -                 * not doing that here as one might expect.
 672      -                 *
 673      -                 * Quit the loop either on error, or if we
 674      -                 * transferred less then requested.
 675      -                 */
 676      -                if (error || (rlen < len))
 677      -                        break;
 678      -
 679      -                timo = 0; /* only first I/O should wait */
 680      -        }
 681      -        if (error && (save_resid != uiop->uio_resid)) {
 682      -                /*
 683      -                 * Stopped on an error after having
 684      -                 * successfully transferred data.
 685      -                 * Suppress this error.
 686      -                 */
 687      -                SMBSDEBUG("error %d suppressed\n", error);
 688      -                error = 0;
 689      -        }
 690      -
 691      -        return (error);
 692      -}
 693      -
 694      -static int
 695      -smb_smb_readx(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
 696      -        uio_t *uiop, smb_cred_t *scred, int timo)
 697      -{
     1126 +        struct smb_share *ssp = FHTOSS(fhp);
 698 1127          struct smb_rq *rqp;
 699 1128          struct mbchain *mbp;
 700 1129          struct mdchain *mdp;
 701 1130          int error;
 702 1131          uint32_t offlo, offhi, rlen;
 703 1132          uint16_t lenhi, lenlo, off, doff;
 704 1133          uint8_t wc;
 705 1134  
 706 1135          lenhi = (uint16_t)(*lenp >> 16);
 707 1136          lenlo = (uint16_t)*lenp;
 708 1137          offhi = (uint32_t)(uiop->uio_loffset >> 32);
  
    | 
      ↓ open down ↓ | 
    1 lines elided | 
    
      ↑ open up ↑ | 
  
 709 1138          offlo = (uint32_t)uiop->uio_loffset;
 710 1139  
 711 1140          error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ_ANDX, scred, &rqp);
 712 1141          if (error)
 713 1142                  return (error);
 714 1143          smb_rq_getrequest(rqp, &mbp);
 715 1144          smb_rq_wstart(rqp);
 716 1145          mb_put_uint8(mbp, 0xff);        /* no secondary command */
 717 1146          mb_put_uint8(mbp, 0);           /* MBZ */
 718 1147          mb_put_uint16le(mbp, 0);        /* offset to secondary */
 719      -        mb_put_uint16le(mbp, fid);
     1148 +        mb_put_uint16le(mbp, fhp->fh_fid1);
 720 1149          mb_put_uint32le(mbp, offlo);    /* offset (low part) */
 721 1150          mb_put_uint16le(mbp, lenlo);    /* MaxCount */
 722 1151          mb_put_uint16le(mbp, 1);        /* MinCount */
 723 1152                                          /* (only indicates blocking) */
 724 1153          mb_put_uint32le(mbp, lenhi);    /* MaxCountHigh */
 725 1154          mb_put_uint16le(mbp, lenlo);    /* Remaining ("obsolete") */
 726 1155          mb_put_uint32le(mbp, offhi);    /* offset (high part) */
 727 1156          smb_rq_wend(rqp);
 728 1157          smb_rq_bstart(rqp);
 729 1158          smb_rq_bend(rqp);
 730 1159  
 731 1160          if (timo == 0)
 732 1161                  timo = smb_timo_read;
 733 1162          error = smb_rq_simple_timed(rqp, timo);
 734 1163          if (error)
 735 1164                  goto out;
 736 1165  
 737 1166          smb_rq_getreply(rqp, &mdp);
 738 1167          error = md_get_uint8(mdp, &wc);
 739 1168          if (error)
 740 1169                  goto out;
 741 1170          if (wc != 12) {
 742 1171                  error = EBADRPC;
 743 1172                  goto out;
 744 1173          }
 745 1174          md_get_uint8(mdp, NULL);
 746 1175          md_get_uint8(mdp, NULL);
 747 1176          md_get_uint16le(mdp, NULL);
 748 1177          md_get_uint16le(mdp, NULL);
 749 1178          md_get_uint16le(mdp, NULL);     /* data compaction mode */
 750 1179          md_get_uint16le(mdp, NULL);
 751 1180          md_get_uint16le(mdp, &lenlo);   /* data len ret. */
 752 1181          md_get_uint16le(mdp, &doff);    /* data offset */
 753 1182          md_get_uint16le(mdp, &lenhi);
 754 1183          rlen = (lenhi << 16) | lenlo;
 755 1184          md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM);
 756 1185          error = md_get_uint16le(mdp, NULL);     /* ByteCount */
 757 1186          if (error)
 758 1187                  goto out;
 759 1188          /*
 760 1189           * Does the data offset indicate padding?
 761 1190           * The current offset is a constant, found
 762 1191           * by counting the md_get_ calls above.
 763 1192           */
 764 1193          off = SMB_HDRLEN + 3 + (12 * 2); /* =59 */
 765 1194          if (doff > off) /* pad byte(s)? */
 766 1195                  md_get_mem(mdp, NULL, doff - off, MB_MSYSTEM);
 767 1196          if (rlen == 0) {
 768 1197                  *lenp = rlen;
 769 1198                  goto out;
 770 1199          }
 771 1200          /* paranoid */
 772 1201          if (rlen > *lenp) {
 773 1202                  SMBSDEBUG("bad server! rlen %d, len %d\n",
 774 1203                      rlen, *lenp);
 775 1204                  rlen = *lenp;
 776 1205          }
 777 1206          error = md_get_uio(mdp, uiop, rlen);
 778 1207          if (error)
  
    | 
      ↓ open down ↓ | 
    49 lines elided | 
    
      ↑ open up ↑ | 
  
 779 1208                  goto out;
 780 1209  
 781 1210          /* Success */
 782 1211          *lenp = rlen;
 783 1212  
 784 1213  out:
 785 1214          smb_rq_done(rqp);
 786 1215          return (error);
 787 1216  }
 788 1217  
 789      -static int
 790      -smb_smb_writex(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
     1218 +int
     1219 +smb_smb_writex(smb_fh_t *fhp, uint32_t *lenp,
 791 1220          uio_t *uiop, smb_cred_t *scred, int timo)
 792 1221  {
     1222 +        struct smb_share *ssp = FHTOSS(fhp);
 793 1223          struct smb_rq *rqp;
 794 1224          struct mbchain *mbp;
 795 1225          struct mdchain *mdp;
 796 1226          int error;
 797 1227          uint32_t offlo, offhi, rlen;
 798 1228          uint16_t lenhi, lenlo;
 799 1229          uint8_t wc;
 800 1230  
 801 1231          lenhi = (uint16_t)(*lenp >> 16);
 802 1232          lenlo = (uint16_t)*lenp;
 803 1233          offhi = (uint32_t)(uiop->uio_loffset >> 32);
  
    | 
      ↓ open down ↓ | 
    1 lines elided | 
    
      ↑ open up ↑ | 
  
 804 1234          offlo = (uint32_t)uiop->uio_loffset;
 805 1235  
 806 1236          error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE_ANDX, scred, &rqp);
 807 1237          if (error)
 808 1238                  return (error);
 809 1239          smb_rq_getrequest(rqp, &mbp);
 810 1240          smb_rq_wstart(rqp);
 811 1241          mb_put_uint8(mbp, 0xff);        /* no secondary command */
 812 1242          mb_put_uint8(mbp, 0);           /* MBZ */
 813 1243          mb_put_uint16le(mbp, 0);        /* offset to secondary */
 814      -        mb_put_uint16le(mbp, fid);
     1244 +        mb_put_uint16le(mbp, fhp->fh_fid1);
 815 1245          mb_put_uint32le(mbp, offlo);    /* offset (low part) */
 816 1246          mb_put_uint32le(mbp, 0);        /* MBZ (timeout) */
 817 1247          mb_put_uint16le(mbp, 0);        /* !write-thru */
 818 1248          mb_put_uint16le(mbp, 0);
 819 1249          mb_put_uint16le(mbp, lenhi);
 820 1250          mb_put_uint16le(mbp, lenlo);
 821 1251          mb_put_uint16le(mbp, 64);       /* data offset from header start */
 822 1252          mb_put_uint32le(mbp, offhi);    /* offset (high part) */
 823 1253          smb_rq_wend(rqp);
 824 1254          smb_rq_bstart(rqp);
 825 1255  
 826 1256          mb_put_uint8(mbp, 0);   /* pad byte */
 827 1257          error = mb_put_uio(mbp, uiop, *lenp);
 828 1258          if (error)
 829 1259                  goto out;
 830 1260          smb_rq_bend(rqp);
 831 1261          if (timo == 0)
 832 1262                  timo = smb_timo_write;
 833 1263          error = smb_rq_simple_timed(rqp, timo);
 834 1264          if (error)
 835 1265                  goto out;
 836 1266          smb_rq_getreply(rqp, &mdp);
 837 1267          error = md_get_uint8(mdp, &wc);
 838 1268          if (error)
 839 1269                  goto out;
 840 1270          if (wc != 6) {
 841 1271                  error = EBADRPC;
 842 1272                  goto out;
 843 1273          }
 844 1274          md_get_uint8(mdp, NULL);        /* andx cmd */
 845 1275          md_get_uint8(mdp, NULL);        /* reserved */
 846 1276          md_get_uint16le(mdp, NULL);     /* andx offset */
 847 1277          md_get_uint16le(mdp, &lenlo);   /* data len ret. */
 848 1278          md_get_uint16le(mdp, NULL);     /* remaining */
 849 1279          error = md_get_uint16le(mdp, &lenhi);
 850 1280          if (error)
 851 1281                  goto out;
  
    | 
      ↓ open down ↓ | 
    27 lines elided | 
    
      ↑ open up ↑ | 
  
 852 1282  
 853 1283          /* Success */
 854 1284          rlen = (lenhi << 16) | lenlo;
 855 1285          *lenp = rlen;
 856 1286  
 857 1287  out:
 858 1288          smb_rq_done(rqp);
 859 1289          return (error);
 860 1290  }
 861 1291  
 862      -static int
 863      -smb_smb_read(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
 864      -        uio_t *uiop, smb_cred_t *scred, int timo)
 865      -{
 866      -        struct smb_rq *rqp;
 867      -        struct mbchain *mbp;
 868      -        struct mdchain *mdp;
 869      -        int error;
 870      -        uint32_t off32;
 871      -        uint16_t bc, cnt, dlen, rcnt, todo;
 872      -        uint8_t wc;
 873 1292  
 874      -        ASSERT(uiop->uio_loffset <= UINT32_MAX);
 875      -        off32 = (uint32_t)uiop->uio_loffset;
 876      -        ASSERT(*lenp <= UINT16_MAX);
 877      -        cnt = (uint16_t)*lenp;
 878      -        /* This next is an "estimate" of planned reads. */
 879      -        todo = (uint16_t)min(uiop->uio_resid, UINT16_MAX);
 880      -
 881      -        error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ, scred, &rqp);
 882      -        if (error)
 883      -                return (error);
 884      -        smb_rq_getrequest(rqp, &mbp);
 885      -        smb_rq_wstart(rqp);
 886      -        mb_put_uint16le(mbp, fid);
 887      -        mb_put_uint16le(mbp, cnt);
 888      -        mb_put_uint32le(mbp, off32);
 889      -        mb_put_uint16le(mbp, todo);
 890      -        smb_rq_wend(rqp);
 891      -        smb_rq_bstart(rqp);
 892      -        smb_rq_bend(rqp);
 893      -
 894      -        if (timo == 0)
 895      -                timo = smb_timo_read;
 896      -        error = smb_rq_simple_timed(rqp, timo);
 897      -        if (error)
 898      -                goto out;
 899      -        smb_rq_getreply(rqp, &mdp);
 900      -        error = md_get_uint8(mdp, &wc);
 901      -        if (error)
 902      -                goto out;
 903      -        if (wc != 5) {
 904      -                error = EBADRPC;
 905      -                goto out;
 906      -        }
 907      -        md_get_uint16le(mdp, &rcnt);            /* ret. count */
 908      -        md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM);  /* res. */
 909      -        md_get_uint16le(mdp, &bc);              /* byte count */
 910      -        md_get_uint8(mdp, NULL);                /* buffer format */
 911      -        error = md_get_uint16le(mdp, &dlen);    /* data len */
 912      -        if (error)
 913      -                goto out;
 914      -        if (dlen < rcnt) {
 915      -                SMBSDEBUG("oops: dlen=%d rcnt=%d\n",
 916      -                    (int)dlen, (int)rcnt);
 917      -                rcnt = dlen;
 918      -        }
 919      -        if (rcnt == 0) {
 920      -                *lenp = 0;
 921      -                goto out;
 922      -        }
 923      -        /* paranoid */
 924      -        if (rcnt > cnt) {
 925      -                SMBSDEBUG("bad server! rcnt %d, cnt %d\n",
 926      -                    (int)rcnt, (int)cnt);
 927      -                rcnt = cnt;
 928      -        }
 929      -        error = md_get_uio(mdp, uiop, (int)rcnt);
 930      -        if (error)
 931      -                goto out;
 932      -
 933      -        /* success */
 934      -        *lenp = (int)rcnt;
 935      -
 936      -out:
 937      -        smb_rq_done(rqp);
 938      -        return (error);
 939      -}
 940      -
 941      -static int
 942      -smb_smb_write(struct smb_share *ssp, uint16_t fid, uint32_t *lenp,
 943      -        uio_t *uiop, smb_cred_t *scred, int timo)
 944      -{
 945      -        struct smb_rq *rqp;
 946      -        struct mbchain *mbp;
 947      -        struct mdchain *mdp;
 948      -        int error;
 949      -        uint32_t off32;
 950      -        uint16_t cnt, rcnt, todo;
 951      -        uint8_t wc;
 952      -
 953      -        ASSERT(uiop->uio_loffset <= UINT32_MAX);
 954      -        off32 = (uint32_t)uiop->uio_loffset;
 955      -        ASSERT(*lenp <= UINT16_MAX);
 956      -        cnt = (uint16_t)*lenp;
 957      -        /* This next is an "estimate" of planned writes. */
 958      -        todo = (uint16_t)min(uiop->uio_resid, UINT16_MAX);
 959      -
 960      -        error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp);
 961      -        if (error)
 962      -                return (error);
 963      -        smb_rq_getrequest(rqp, &mbp);
 964      -        smb_rq_wstart(rqp);
 965      -        mb_put_uint16le(mbp, fid);
 966      -        mb_put_uint16le(mbp, cnt);
 967      -        mb_put_uint32le(mbp, off32);
 968      -        mb_put_uint16le(mbp, todo);
 969      -        smb_rq_wend(rqp);
 970      -        smb_rq_bstart(rqp);
 971      -        mb_put_uint8(mbp, SMB_DT_DATA);
 972      -        mb_put_uint16le(mbp, cnt);
 973      -
 974      -        error = mb_put_uio(mbp, uiop, *lenp);
 975      -        if (error)
 976      -                goto out;
 977      -        smb_rq_bend(rqp);
 978      -        if (timo == 0)
 979      -                timo = smb_timo_write;
 980      -        error = smb_rq_simple_timed(rqp, timo);
 981      -        if (error)
 982      -                goto out;
 983      -        smb_rq_getreply(rqp, &mdp);
 984      -        error = md_get_uint8(mdp, &wc);
 985      -        if (error)
 986      -                goto out;
 987      -        if (wc != 1) {
 988      -                error = EBADRPC;
 989      -                goto out;
 990      -        }
 991      -        error = md_get_uint16le(mdp, &rcnt);
 992      -        if (error)
 993      -                goto out;
 994      -        *lenp = rcnt;
 995      -
 996      -out:
 997      -        smb_rq_done(rqp);
 998      -        return (error);
 999      -}
1000      -
1001      -
1002 1293  static u_int32_t        smbechoes = 0;
1003 1294  
     1295 +/*
     1296 + * Note: the IOD calls this, so this request must not wait for
     1297 + * connection state changes, etc. (uses smb_rq_internal)
     1298 + */
1004 1299  int
1005 1300  smb_smb_echo(struct smb_vc *vcp, struct smb_cred *scred, int timo)
1006 1301  {
1007 1302          struct smb_rq *rqp;
1008 1303          struct mbchain *mbp;
1009 1304          int error;
1010 1305  
1011 1306          error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_ECHO, scred, &rqp);
1012 1307          if (error)
1013 1308                  return (error);
1014 1309          mbp = &rqp->sr_rq;
1015 1310          smb_rq_wstart(rqp);
1016 1311          mb_put_uint16le(mbp, 1); /* echo count */
1017 1312          smb_rq_wend(rqp);
1018 1313          smb_rq_bstart(rqp);
1019 1314          mb_put_uint32le(mbp, atomic_inc_32_nv(&smbechoes));
1020 1315          smb_rq_bend(rqp);
1021      -        /*
1022      -         * Note: the IOD calls this, so
1023      -         * this request must not wait for
1024      -         * connection state changes, etc.
1025      -         */
1026 1316          rqp->sr_flags |= SMBR_NORECONNECT;
1027      -        error = smb_rq_simple_timed(rqp, timo);
     1317 +        error = smb_rq_internal(rqp, timo);
1028 1318          SMBSDEBUG("%d\n", error);
1029 1319          smb_rq_done(rqp);
1030 1320          return (error);
1031 1321  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX