1 /*
   2  * Copyright (c) 2000-2001 Boris Popov
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 1. Redistributions of source code must retain the above copyright
   9  *    notice, this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright
  11  *    notice, this list of conditions and the following disclaimer in the
  12  *    documentation and/or other materials provided with the distribution.
  13  * 3. All advertising materials mentioning features or use of this software
  14  *    must display the following acknowledgement:
  15  *    This product includes software developed by Boris Popov.
  16  * 4. Neither the name of the author nor the names of any co-contributors
  17  *    may be used to endorse or promote products derived from this software
  18  *    without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30  * SUCH DAMAGE.
  31  */
  32 
  33 /*
  34  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  35  * Use is subject to license terms.
  36  *
  37  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  38  */
  39 
  40 #include <sys/param.h>
  41 #include <sys/systm.h>
  42 #include <sys/inttypes.h>
  43 #include <sys/time.h>
  44 #include <sys/vnode.h>
  45 #include <sys/sunddi.h>
  46 #include <sys/cmn_err.h>
  47 
  48 #include <netsmb/smb_osdep.h>
  49 
  50 #include <netsmb/smb.h>
  51 #include <netsmb/smb_conn.h>
  52 #include <netsmb/smb_subr.h>
  53 #include <netsmb/smb_rq.h>
  54 
  55 #include <smbfs/smbfs.h>
  56 #include <smbfs/smbfs_node.h>
  57 #include <smbfs/smbfs_subr.h>
  58 
  59 
  60 /*
  61  * Todo: locking over-the-wire
  62  */
  63 #if 0   // todo
  64 
  65 int
  66 smbfs_smb1_lockandx(struct smbnode *np, int op, uint32_t pid,
  67         offset_t start, uint64_t len, int largelock,
  68         struct smb_cred *scrp, uint32_t timeout)
  69 {
  70         struct smb_share *ssp = np->n_mount->smi_share;
  71         struct smb_rq rq, *rqp = &rq;
  72         struct mbchain *mbp;
  73         uint8_t ltype = 0;
  74         int error;
  75 
  76         /* Shared lock for n_fid use below. */
  77         ASSERT(smbfs_rw_lock_held(&np->r_lkserlock, RW_READER));
  78 
  79         /* After reconnect, n_fid is invalid */
  80         if (np->n_vcgenid != ssp->ss_vcgenid)
  81                 return (ESTALE);
  82 
  83         if (op == SMB_LOCK_SHARED)
  84                 ltype |= SMB_LOCKING_ANDX_SHARED_LOCK;
  85         /* XXX: if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES)? */
  86         if (largelock)
  87                 ltype |= SMB_LOCKING_ANDX_LARGE_FILES;
  88         error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_LOCKING_ANDX, scrp);
  89         if (error)
  90                 return (error);
  91         smb_rq_getrequest(rqp, &mbp);
  92         smb_rq_wstart(rqp);
  93         mb_put_uint8(mbp, 0xff);        /* secondary command */
  94         mb_put_uint8(mbp, 0);           /* MBZ */
  95         mb_put_uint16le(mbp, 0);
  96         mb_put_uint16le(mbp, np->n_fid);
  97         mb_put_uint8(mbp, ltype);       /* locktype */
  98         mb_put_uint8(mbp, 0);           /* oplocklevel - 0 seems is NO_OPLOCK */
  99         mb_put_uint32le(mbp, timeout);  /* 0 nowait, -1 infinite wait */
 100         mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 1 : 0);
 101         mb_put_uint16le(mbp, op == SMB_LOCK_RELEASE ? 0 : 1);
 102         smb_rq_wend(rqp);
 103         smb_rq_bstart(rqp);
 104         mb_put_uint16le(mbp, pid);
 105         if (!largelock) {
 106                 mb_put_uint32le(mbp, start);
 107                 mb_put_uint32le(mbp, len);
 108         } else {
 109                 mb_put_uint16le(mbp, 0); /* pad */
 110                 mb_put_uint32le(mbp, start >> 32); /* OffsetHigh */
 111                 mb_put_uint32le(mbp, start & 0xffffffff); /* OffsetLow */
 112                 mb_put_uint32le(mbp, len >> 32); /* LengthHigh */
 113                 mb_put_uint32le(mbp, len & 0xffffffff); /* LengthLow */
 114         }
 115         smb_rq_bend(rqp);
 116         /*
 117          * Don't want to risk missing a successful
 118          * unlock send or lock response, or we could
 119          * lose track of an outstanding lock.
 120          */
 121         if (op == SMB_LOCK_RELEASE)
 122                 rqp->sr_flags |= SMBR_NOINTR_SEND;
 123         else
 124                 rqp->sr_flags |= SMBR_NOINTR_RECV;
 125 
 126         error = smb_rq_simple(rqp);
 127         smb_rq_done(rqp);
 128         return (error);
 129 }
 130 
 131 #endif  // todo
 132 
 133 /*
 134  * Common function for QueryFileInfo, QueryPathInfo.
 135  */
 136 int
 137 smbfs_smb1_trans2_query(struct smbnode *np,  uint16_t fid,
 138         struct smbfattr *fap, struct smb_cred *scrp)
 139 {
 140         struct smb_share *ssp = np->n_mount->smi_share;
 141         struct smb_vc *vcp = SSTOVC(ssp);
 142         struct smb_t2rq *t2p;
 143         struct mbchain *mbp;
 144         struct mdchain *mdp;
 145         uint16_t cmd;
 146         uint16_t infolevel = SMB_QFILEINFO_ALL_INFO;
 147         int error;
 148 
 149         /*
 150          * If we have a valid open FID, use it.
 151          */
 152         if (fid != SMB_FID_UNUSED)
 153                 cmd = SMB_TRANS2_QUERY_FILE_INFORMATION;
 154         else
 155                 cmd = SMB_TRANS2_QUERY_PATH_INFORMATION;
 156 
 157         error = smb_t2_alloc(SSTOCP(ssp), cmd, scrp, &t2p);
 158         if (error)
 159                 return (error);
 160         mbp = &t2p->t2_tparam;
 161         mb_init(mbp);
 162 
 163         if (cmd == SMB_TRANS2_QUERY_FILE_INFORMATION)
 164                 mb_put_uint16le(mbp, fid);
 165 
 166         mb_put_uint16le(mbp, infolevel);
 167 
 168         if (cmd == SMB_TRANS2_QUERY_PATH_INFORMATION) {
 169                 mb_put_uint32le(mbp, 0);
 170                 /* mb_put_uint8(mbp, SMB_DT_ASCII); specs are wrong */
 171                 error = smbfs_fullpath(mbp, vcp, np, NULL, 0, '\\');
 172                 if (error)
 173                         goto out;
 174         }
 175 
 176         t2p->t2_maxpcount = 2;
 177         t2p->t2_maxdcount = vcp->vc_txmax;
 178         error = smb_t2_request(t2p);
 179         if (error)
 180                 goto out;
 181 
 182         /*
 183          * Parse the SMB_QFILEINFO_ALL_INFO
 184          */
 185         mdp = &t2p->t2_rdata;
 186         error = smbfs_decode_file_all_info(ssp, mdp, fap);
 187 
 188 out:
 189         smb_t2_done(t2p);
 190 
 191         return (error);
 192 }
 193 
 194 /*
 195  * Get some FS information
 196  */
 197 static int
 198 smbfs_smb1_query_fs_info(struct smb_share *ssp, struct mdchain *info_mdp,
 199         uint16_t level, struct smb_cred *scrp)
 200 {
 201         struct smb_t2rq *t2p;
 202         struct mbchain *mbp;
 203         struct mdchain *mdp;
 204         int error;
 205 
 206         error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION,
 207             scrp, &t2p);
 208         if (error)
 209                 return (error);
 210         mbp = &t2p->t2_tparam;
 211         mb_init(mbp);
 212         mb_put_uint16le(mbp, level);
 213         t2p->t2_maxpcount = 4;
 214         t2p->t2_maxdcount = 1024;
 215         error = smb_t2_request(t2p);
 216         if (error)
 217                 goto out;
 218 
 219         mdp = &t2p->t2_rdata;
 220         *info_mdp = *mdp;
 221         bzero(mdp, sizeof (*mdp));
 222 
 223 out:
 224         smb_t2_done(t2p);
 225         return (error);
 226 }
 227 
 228 /*
 229  * Get FILE_FS_ATTRIBUTE_INFORMATION
 230  */
 231 int
 232 smbfs_smb1_qfsattr(struct smb_share *ssp, struct smb_fs_attr_info *fsa,
 233         struct smb_cred *scrp)
 234 {
 235         struct mdchain info_mdc, *mdp = &info_mdc;
 236         int error;
 237 
 238         bzero(mdp, sizeof (*mdp));
 239 
 240         error = smbfs_smb1_query_fs_info(ssp, mdp,
 241             SMB_QFS_ATTRIBUTE_INFO, scrp);
 242         if (error)
 243                 goto out;
 244         error = smbfs_decode_fs_attr_info(ssp, mdp, fsa);
 245 
 246 out:
 247         md_done(mdp);
 248 
 249         return (error);
 250 }
 251 
 252 /*
 253  * Get FileFsFullSizeInformation and
 254  * parse into *info
 255  */
 256 int
 257 smbfs_smb1_statfs(struct smb_share *ssp,
 258         struct smb_fs_size_info *info,
 259         struct smb_cred *scrp)
 260 {
 261         struct mdchain info_mdc, *mdp = &info_mdc;
 262         struct smb_vc *vcp = SSTOVC(ssp);
 263         uint16_t level;
 264         int error;
 265 
 266         bzero(mdp, sizeof (*mdp));
 267 
 268         if (vcp->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU)
 269                 level = SMB_QFS_FULL_SIZE_INFORMATION;
 270         else
 271                 level = SMB_QFS_SIZE_INFO;
 272         error = smbfs_smb1_query_fs_info(ssp, mdp, level, scrp);
 273         if (error)
 274                 goto out;
 275 
 276         md_get_uint64le(mdp, &info->total_units);
 277         md_get_uint64le(mdp, &info->caller_avail);
 278         if (level == SMB_QFS_FULL_SIZE_INFORMATION)
 279                 md_get_uint64le(mdp, &info->actual_avail);
 280         else
 281                 info->actual_avail = info->caller_avail;
 282 
 283         md_get_uint32le(mdp, &info->sect_per_unit);
 284         error = md_get_uint32le(mdp, &info->bytes_per_sect);
 285 
 286 out:
 287         md_done(mdp);
 288 
 289         return (error);
 290 }
 291 
 292 int
 293 smbfs_smb1_flush(struct smb_share *ssp, uint16_t fid, struct smb_cred *scrp)
 294 {
 295         struct smb_rq rq, *rqp = &rq;
 296         struct mbchain *mbp;
 297         int error;
 298 
 299         error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_FLUSH, scrp);
 300         if (error)
 301                 return (error);
 302         smb_rq_getrequest(rqp, &mbp);
 303         smb_rq_wstart(rqp);
 304         mb_put_uint16le(mbp, fid);
 305         smb_rq_wend(rqp);
 306         smb_rq_bstart(rqp);
 307         smb_rq_bend(rqp);
 308         error = smb_rq_simple(rqp);
 309         smb_rq_done(rqp);
 310         return (error);
 311 }
 312 
 313 /*
 314  * Set file info via an open handle.
 315  * Caller provides payload, info level.
 316  */
 317 static int
 318 smbfs_smb1_setinfo_file(struct smb_share *ssp, uint16_t fid,
 319         struct mbchain *info_mbp, uint16_t level, struct smb_cred *scrp)
 320 {
 321         struct smb_t2rq *t2p = NULL;
 322         struct mbchain *mbp;
 323         uint16_t cmd = SMB_TRANS2_SET_FILE_INFORMATION;
 324         int error;
 325 
 326         ASSERT(fid != SMB_FID_UNUSED);
 327 
 328         error = smb_t2_alloc(SSTOCP(ssp), cmd, scrp, &t2p);
 329         if (error)
 330                 return (error);
 331         mbp = &t2p->t2_tparam;
 332         mb_init(mbp);
 333         mb_put_uint16le(mbp, fid);
 334         mb_put_uint16le(mbp, level);
 335         mb_put_uint16le(mbp, 0); /* pad */
 336 
 337         /* put the payload */
 338         mbp = &t2p->t2_tdata;
 339         mb_init(mbp);
 340         error = mb_put_mbchain(mbp, info_mbp);
 341         if (error)
 342                 goto out;
 343 
 344         t2p->t2_maxpcount = 2;
 345         t2p->t2_maxdcount = 0;
 346         error = smb_t2_request(t2p);
 347 
 348 out:
 349         smb_t2_done(t2p);
 350 
 351         return (error);
 352 }
 353 
 354 int
 355 smbfs_smb1_seteof(struct smb_share *ssp, uint16_t fid,
 356         uint64_t newsize, struct smb_cred *scrp)
 357 {
 358         struct mbchain data_mb, *mbp = &data_mb;
 359         uint16_t level;
 360         int error;
 361 
 362         if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU)
 363                 level = SMB_SFILEINFO_END_OF_FILE_INFORMATION;
 364         else
 365                 level = SMB_SFILEINFO_END_OF_FILE_INFO;
 366 
 367         mb_init(mbp);
 368         error = mb_put_uint64le(mbp, newsize);
 369         if (error)
 370                 goto out;
 371         error = smbfs_smb1_setinfo_file(ssp, fid, mbp, level, scrp);
 372 
 373 out:
 374         mb_done(mbp);
 375         return (error);
 376 }
 377 
 378 int
 379 smbfs_smb1_setdisp(struct smb_share *ssp, uint16_t fid,
 380         uint8_t newdisp, struct smb_cred *scrp)
 381 {
 382         struct mbchain data_mb, *mbp = &data_mb;
 383         uint16_t level;
 384         int error;
 385 
 386         if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU)
 387                 level = SMB_SFILEINFO_DISPOSITION_INFORMATION;
 388         else
 389                 level = SMB_SFILEINFO_DISPOSITION_INFO;
 390 
 391         mb_init(mbp);
 392         error = mb_put_uint8(mbp, newdisp);
 393         if (error)
 394                 goto out;
 395         error = smbfs_smb1_setinfo_file(ssp, fid, mbp, level, scrp);
 396 
 397 out:
 398         mb_done(mbp);
 399 
 400         return (error);
 401 }
 402 
 403 /*
 404  * Set FileBasicInformation on an open handle
 405  * Caller builds the mbchain.
 406  * Always have a FID here.
 407  */
 408 int
 409 smbfs_smb1_setfattr(struct smb_share *ssp, uint16_t fid,
 410         struct mbchain *mbp, struct smb_cred *scrp)
 411 {
 412         uint16_t level;
 413         int error;
 414 
 415         if (SSTOVC(ssp)->vc_sopt.sv_caps & SMB_CAP_INFOLEVEL_PASSTHRU)
 416                 level = SMB_SFILEINFO_BASIC_INFORMATION;
 417         else
 418                 level = SMB_SFILEINFO_BASIC_INFO;
 419         error = smbfs_smb1_setinfo_file(ssp, fid, mbp, level, scrp);
 420 
 421         return (error);
 422 }
 423 
 424 /*
 425  * On SMB1, the trans2 rename only allows a rename where the
 426  * source and target are in the same directory.  If you give
 427  * the server any separators, you get "status not supported".
 428  *
 429  * Why bother using this instead of smbfs_smb1_oldrename?
 430  * Because it works with an open file, and some servers don't
 431  * allow oldrename of a file that's currently open.  We call
 432  * this when deleting an open file in smbfsremove(), where
 433  * the rename is always in the same directory.
 434  */
 435 /*ARGSUSED*/
 436 int
 437 smbfs_smb1_t2rename(struct smbnode *np,
 438         const char *tname, int tnlen,
 439         uint16_t fid, struct smb_cred *scrp)
 440 {
 441         struct smb_share *ssp = np->n_mount->smi_share;
 442         struct mbchain data_mb, *mbp = &data_mb;
 443         struct smb_vc *vcp = SSTOVC(ssp);
 444         uint32_t *name_lenp;
 445         uint16_t level = SMB_SFILEINFO_RENAME_INFORMATION;
 446         int base, len;
 447         int error;
 448 
 449         mb_init(mbp);
 450         mb_put_uint32le(mbp, 0); /* don't overwrite */
 451         mb_put_uint32le(mbp, 0); /* obsolete target dir fid */
 452         name_lenp = mb_reserve(mbp, 4); /* name len */
 453 
 454         /* New name */
 455         base = mbp->mb_count;
 456         error = smb_put_dmem(mbp, vcp, tname, tnlen, SMB_CS_NONE, NULL);
 457         if (error)
 458                 goto out;
 459         len = mbp->mb_count - base;
 460         *name_lenp = htolel(len);
 461 
 462         error = smbfs_smb1_setinfo_file(ssp, fid, mbp, level, scrp);
 463 
 464 out:
 465         mb_done(mbp);
 466         return (error);
 467 }
 468 
 469 /*
 470  * Do an SMB1 (old style) rename using a full dest. path.
 471  * This is used when renaming to a different directory,
 472  * because the (preferred) t2rename can't do that.
 473  */
 474 int
 475 smbfs_smb1_oldrename(struct smbnode *src, struct smbnode *tdnp,
 476     const char *tname, int tnmlen, struct smb_cred *scrp)
 477 {
 478         struct smb_rq rq, *rqp = &rq;
 479         struct smb_share *ssp = src->n_mount->smi_share;
 480         struct mbchain *mbp;
 481         int error;
 482         uint16_t fa;
 483         char sep;
 484 
 485         error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_RENAME, scrp);
 486         if (error)
 487                 return (error);
 488         smb_rq_getrequest(rqp, &mbp);
 489         smb_rq_wstart(rqp);
 490         /* freebsd bug: Let directories be renamed - Win98 requires DIR bit */
 491         fa = (SMBTOV(src)->v_type == VDIR) ? SMB_FA_DIR : 0;
 492         fa |= SMB_FA_SYSTEM | SMB_FA_HIDDEN;
 493         mb_put_uint16le(mbp, fa);
 494         smb_rq_wend(rqp);
 495         smb_rq_bstart(rqp);
 496 
 497         /*
 498          * When we're not adding any component name, the
 499          * passed sep is ignored, so just pass sep=0.
 500          */
 501         mb_put_uint8(mbp, SMB_DT_ASCII);
 502         error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, 0, 0);
 503         if (error)
 504                 goto out;
 505 
 506         /*
 507          * After XATTR directories, separator is ":"
 508          */
 509         sep = (src->n_flag & N_XATTR) ? ':' : '\\';
 510         mb_put_uint8(mbp, SMB_DT_ASCII);
 511         error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, tnmlen, sep);
 512         if (error)
 513                 goto out;
 514 
 515         smb_rq_bend(rqp);
 516         error = smb_rq_simple(rqp);
 517 out:
 518         smb_rq_done(rqp);
 519         return (error);
 520 }
 521 
 522 
 523 /*
 524  * TRANS2_FIND_FIRST2/NEXT2, used for NT LM12 dialect
 525  */
 526 static int
 527 smbfs_smb1_trans2find2(struct smbfs_fctx *ctx)
 528 {
 529         struct smb_t2rq *t2p;
 530         struct smb_vc *vcp = SSTOVC(ctx->f_ssp);
 531         struct mbchain *mbp;
 532         struct mdchain *mdp;
 533         uint16_t ecnt, eos, lno, flags;
 534         uint16_t amask, limit;
 535         int error;
 536 
 537         /* smbfs_smb_findnextLM2 sets this */
 538         limit = ctx->f_limit;
 539         amask = (uint16_t)ctx->f_attrmask;
 540 
 541         if (ctx->f_t2) {
 542                 smb_t2_done(ctx->f_t2);
 543                 ctx->f_t2 = NULL;
 544         }
 545         flags = FIND2_RETURN_RESUME_KEYS | FIND2_CLOSE_ON_EOS;
 546         if (ctx->f_flags & SMBFS_RDD_FINDSINGLE) {
 547                 flags |= FIND2_CLOSE_AFTER_REQUEST;
 548                 ctx->f_flags |= SMBFS_RDD_NOCLOSE;
 549         }
 550         if (ctx->f_flags & SMBFS_RDD_FINDFIRST) {
 551                 error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_FIRST2,
 552                     ctx->f_scred, &t2p);
 553                 if (error)
 554                         return (error);
 555                 ctx->f_t2 = t2p;
 556                 mbp = &t2p->t2_tparam;
 557                 mb_init(mbp);
 558                 mb_put_uint16le(mbp, amask);
 559                 mb_put_uint16le(mbp, limit);
 560                 mb_put_uint16le(mbp, flags);
 561                 mb_put_uint16le(mbp, ctx->f_infolevel);
 562                 mb_put_uint32le(mbp, 0);
 563                 error = smbfs_fullpath(mbp, vcp, ctx->f_dnp,
 564                     ctx->f_wildcard, ctx->f_wclen, '\\');
 565                 if (error)
 566                         return (error);
 567         } else  {
 568                 error = smb_t2_alloc(SSTOCP(ctx->f_ssp), SMB_TRANS2_FIND_NEXT2,
 569                     ctx->f_scred, &t2p);
 570                 if (error)
 571                         return (error);
 572                 ctx->f_t2 = t2p;
 573                 mbp = &t2p->t2_tparam;
 574                 mb_init(mbp);
 575                 mb_put_uint16le(mbp, ctx->f_Sid);
 576                 mb_put_uint16le(mbp, limit);
 577                 mb_put_uint16le(mbp, ctx->f_infolevel);
 578                 /* Send whatever resume key we received... */
 579                 mb_put_uint32le(mbp, ctx->f_rkey);
 580                 mb_put_uint16le(mbp, flags);
 581                 /* ... and the resume name if we have one. */
 582                 if (ctx->f_rname) {
 583                         /* resume file name */
 584                         mb_put_mem(mbp, ctx->f_rname, ctx->f_rnamelen,
 585                             MB_MSYSTEM);
 586                 }
 587                 /* Add trailing null - 1 byte if ASCII, 2 if Unicode */
 588                 if (SMB_UNICODE_STRINGS(SSTOVC(ctx->f_ssp)))
 589                         mb_put_uint8(mbp, 0);   /* 1st byte NULL Unicode char */
 590                 mb_put_uint8(mbp, 0);
 591         }
 592         t2p->t2_maxpcount = 5 * 2;
 593         t2p->t2_maxdcount = 0xF000;  /* 64K less some overhead */
 594         error = smb_t2_request(t2p);
 595         if (error)
 596                 return (error);
 597 
 598         /*
 599          * This is the "resume name" we just sent.
 600          * We want the new one (if any) that may be
 601          * found in the response we just received and
 602          * will now begin parsing.  Free the old one
 603          * now so we'll know if we found a new one.
 604          */
 605         if (ctx->f_rname) {
 606                 kmem_free(ctx->f_rname, ctx->f_rnamelen);
 607                 ctx->f_rname = NULL;
 608                 ctx->f_rnamelen = 0;
 609         }
 610 
 611         mdp = &t2p->t2_rparam;
 612         if (ctx->f_flags & SMBFS_RDD_FINDFIRST) {
 613                 if ((error = md_get_uint16le(mdp, &ctx->f_Sid)) != 0)
 614                         goto nodata;
 615                 ctx->f_flags &= ~SMBFS_RDD_FINDFIRST;
 616         }
 617         md_get_uint16le(mdp, &ecnt);                /* entry count */
 618         md_get_uint16le(mdp, &eos);         /* end of search */
 619         md_get_uint16le(mdp, NULL);             /* EA err. off. */
 620         error = md_get_uint16le(mdp, &lno); /* last name off. */
 621         if (error != 0)
 622                 goto nodata;
 623 
 624         /*
 625          * The "end of search" flag from an XP server sometimes
 626          * comes back zero when the prior find_next returned exactly
 627          * the number of entries requested.  in which case we'd try again
 628          * but the search has in fact been closed so an EBADF results.
 629          * our circumvention is to check here for a zero entry count.
 630          */
 631         ctx->f_ecnt = ecnt;
 632         if (eos || ctx->f_ecnt == 0)
 633                 ctx->f_flags |= SMBFS_RDD_EOF | SMBFS_RDD_NOCLOSE;
 634         if (ctx->f_ecnt == 0)
 635                 return (ENOENT);
 636 
 637         /* Last Name Off (LNO) is the entry with the resume name. */
 638         ctx->f_rnameofs = lno;
 639         ctx->f_eofs = 0;
 640 
 641         /*
 642          * Have data. Put the payload in ctx->f_mdchain
 643          * Note struct assignments here.
 644          */
 645         mdp = &t2p->t2_rdata;
 646         md_done(&ctx->f_mdchain);
 647         ctx->f_mdchain = *mdp;
 648         ctx->f_left = m_fixhdr(mdp->md_top);
 649         bzero(mdp, sizeof (*mdp));
 650 
 651         return (0);
 652 
 653 nodata:
 654         /*
 655          * Failed parsing the FindFirst or FindNext response.
 656          * Force this directory listing closed, otherwise the
 657          * calling process may hang in an infinite loop.
 658          */
 659         ctx->f_ecnt = 0; /* Force closed. */
 660         ctx->f_flags |= SMBFS_RDD_EOF;
 661         return (EIO);
 662 }
 663 
 664 static int
 665 smbfs_smb1_findclose2(struct smbfs_fctx *ctx)
 666 {
 667         struct smb_rq rq, *rqp = &rq;
 668         struct mbchain *mbp;
 669         int error;
 670 
 671         error = smb_rq_init(rqp, SSTOCP(ctx->f_ssp), SMB_COM_FIND_CLOSE2,
 672             ctx->f_scred);
 673         if (error)
 674                 return (error);
 675         smb_rq_getrequest(rqp, &mbp);
 676         smb_rq_wstart(rqp);
 677         mb_put_uint16le(mbp, ctx->f_Sid);
 678         smb_rq_wend(rqp);
 679         smb_rq_bstart(rqp);
 680         smb_rq_bend(rqp);
 681         /* Ditto comments at _smb_close */
 682         rqp->sr_flags |= SMBR_NOINTR_SEND;
 683         error = smb_rq_simple(rqp);
 684         smb_rq_done(rqp);
 685         return (error);
 686 }
 687 
 688 /*ARGSUSED*/
 689 int
 690 smbfs_smb_findopenLM2(struct smbfs_fctx *ctx, struct smbnode *dnp,
 691     const char *wildcard, int wclen, uint32_t attr)
 692 {
 693 
 694         ctx->f_type = ft_LM2;
 695         ctx->f_namesz = SMB_MAXFNAMELEN + 1;
 696         ctx->f_name = kmem_alloc(ctx->f_namesz, KM_SLEEP);
 697         ctx->f_infolevel = SMB_FIND_FULL_DIRECTORY_INFO;
 698         ctx->f_attrmask = attr;
 699         ctx->f_wildcard = wildcard;
 700         ctx->f_wclen = wclen;
 701         return (0);
 702 }
 703 
 704 int
 705 smbfs_smb_findcloseLM2(struct smbfs_fctx *ctx)
 706 {
 707         int error = 0;
 708         if (ctx->f_name)
 709                 kmem_free(ctx->f_name, ctx->f_namesz);
 710         if (ctx->f_t2)
 711                 smb_t2_done(ctx->f_t2);
 712         md_done(&ctx->f_mdchain);
 713 
 714         /*
 715          * If SMBFS_RDD_FINDFIRST is still set, we were opened
 716          * but never saw a findfirst, so we don't have any
 717          * search handle to close.
 718          */
 719         if ((ctx->f_flags & (SMBFS_RDD_FINDFIRST | SMBFS_RDD_NOCLOSE)) == 0)
 720                 error = smbfs_smb1_findclose2(ctx);
 721         return (error);
 722 }
 723 
 724 /*
 725  * Get a buffer of directory entries (if we don't already have
 726  * some remaining in the current buffer) then decode one.
 727  */
 728 int
 729 smbfs_smb_findnextLM2(struct smbfs_fctx *ctx, uint16_t limit)
 730 {
 731         int error;
 732 
 733         /*
 734          * If we've scanned to the end of the current buffer
 735          * try to read anohther buffer of dir entries.
 736          * Treat anything less than 8 bytes as an "empty"
 737          * buffer to ensure we can read something.
 738          * (There may be up to 8 bytes of padding.)
 739          */
 740         if ((ctx->f_eofs + 8) > ctx->f_left) {
 741                 /* Scanned the whole buffer. */
 742                 if (ctx->f_flags & SMBFS_RDD_EOF)
 743                         return (ENOENT);
 744                 ctx->f_limit = limit;
 745                 error = smbfs_smb1_trans2find2(ctx);
 746                 if (error)
 747                         return (error);
 748                 ctx->f_otws++;
 749         }
 750 
 751         /*
 752          * Decode one entry, advance f_eofs
 753          */
 754         error = smbfs_decode_dirent(ctx);
 755 
 756         return (error);
 757 }
 758 
 759 /*
 760  * Helper for smbfs_xa_get_streaminfo
 761  * Query stream info
 762  */
 763 int
 764 smbfs_smb1_get_streaminfo(smbnode_t *np, struct mdchain *mdp,
 765         struct smb_cred *scrp)
 766 {
 767         smb_share_t *ssp = np->n_mount->smi_share;
 768         struct smb_vc *vcp = SSTOVC(ssp);
 769         struct smb_t2rq *t2p = NULL;
 770         struct mbchain *mbp;
 771         mblk_t *m;
 772         uint16_t cmd = SMB_TRANS2_QUERY_PATH_INFORMATION;
 773         int error;
 774 
 775         error = smb_t2_alloc(SSTOCP(ssp), cmd, scrp, &t2p);
 776         if (error)
 777                 return (error);
 778 
 779         mbp = &t2p->t2_tparam;
 780         (void) mb_init(mbp);
 781         (void) mb_put_uint16le(mbp, SMB_QFILEINFO_STREAM_INFO);
 782         (void) mb_put_uint32le(mbp, 0);
 783         error = smbfs_fullpath(mbp, vcp, np, NULL, NULL, 0);
 784         if (error)
 785                 goto out;
 786 
 787         t2p->t2_maxpcount = 2;
 788         t2p->t2_maxdcount = INT16_MAX;
 789         error = smb_t2_request(t2p);
 790         if (error) {
 791                 if (t2p->t2_sr_error == NT_STATUS_INVALID_PARAMETER)
 792                         error = ENOTSUP;
 793                 goto out;
 794         }
 795 
 796         /*
 797          * Have data.  Move it to *mdp
 798          */
 799         m = t2p->t2_rdata.md_top;
 800         if (m == NULL) {
 801                 error = EBADRPC;
 802                 goto out;
 803         }
 804         t2p->t2_rdata.md_top = NULL;
 805         md_initm(mdp, m);
 806 
 807 out:
 808         smb_t2_done(t2p);
 809         return (error);
 810 }
 811 
 812 /*
 813  * OTW function to Get a security descriptor (SD).
 814  *
 815  * The *reslen param is bufsize(in) / length(out)
 816  * Note: On success, this fills in mdp->md_top,
 817  * which the caller should free.
 818  */
 819 int
 820 smbfs_smb1_getsec(struct smb_share *ssp, uint16_t fid,
 821         uint32_t selector, mblk_t **res, uint32_t *reslen,
 822         struct smb_cred *scrp)
 823 {
 824         struct smb_ntrq *ntp;
 825         struct mbchain *mbp;
 826         struct mdchain *mdp;
 827         uint32_t dlen;
 828         int error;
 829 
 830         *res = NULL;
 831 
 832         error = smb_nt_alloc(SSTOCP(ssp), NT_TRANSACT_QUERY_SECURITY_DESC,
 833             scrp, &ntp);
 834         if (error)
 835                 return (error);
 836 
 837         /* Parameters part */
 838         mbp = &ntp->nt_tparam;
 839         mb_init(mbp);
 840         mb_put_uint16le(mbp, fid);
 841         mb_put_uint16le(mbp, 0); /* reserved */
 842         mb_put_uint32le(mbp, selector);
 843         /* Data part (none) */
 844 
 845         /* Max. returned parameters and data. */
 846         ntp->nt_maxpcount = 4;
 847         ntp->nt_maxdcount = *reslen; // out buf size
 848 
 849         error = smb_nt_request(ntp);
 850         if (error && !(ntp->nt_flags & SMBT2_MOREDATA))
 851                 goto done;
 852 
 853         /* Get data len */
 854         mdp = &ntp->nt_rparam;
 855         error = md_get_uint32le(mdp, &dlen);
 856         if (error)
 857                 goto done;
 858 
 859         /*
 860          * if there's more data than we said we could receive,
 861          * here is where we pick up the length of it
 862          */
 863         *reslen = dlen;
 864         if (dlen == 0) {
 865                 error = EBADRPC;
 866                 goto done;
 867         }
 868 
 869         /*
 870          * get the SD data part.
 871          */
 872         mdp = &ntp->nt_rdata;
 873         error = md_get_mbuf(mdp, dlen, res);
 874 
 875 done:
 876         if (error == 0 && *res == NULL) {
 877                 ASSERT(*res);
 878                 error = EBADRPC;
 879         }
 880 
 881         smb_nt_done(ntp);
 882         return (error);
 883 }
 884 
 885 
 886 /*
 887  * OTW function to Set a security descriptor (SD).
 888  * Caller data are carried in an mbchain_t.
 889  *
 890  * Note: This normally consumes mbp->mb_top, and clears
 891  * that pointer when it does.
 892  */
 893 int
 894 smbfs_smb1_setsec(struct smb_share *ssp, uint16_t fid,
 895         uint32_t selector, mblk_t **mp, struct smb_cred *scrp)
 896 {
 897         struct smb_ntrq *ntp;
 898         struct mbchain *mbp;
 899         int error;
 900 
 901         error = smb_nt_alloc(SSTOCP(ssp), NT_TRANSACT_SET_SECURITY_DESC,
 902             scrp, &ntp);
 903         if (error)
 904                 return (error);
 905 
 906         /* Parameters part */
 907         mbp = &ntp->nt_tparam;
 908         mb_init(mbp);
 909         mb_put_uint16le(mbp, fid);
 910         mb_put_uint16le(mbp, 0); /* reserved */
 911         mb_put_uint32le(mbp, selector);
 912 
 913         /* Data part */
 914         mbp = &ntp->nt_tdata;
 915         mb_initm(mbp, *mp);
 916         *mp = NULL; /* consumed */
 917 
 918         /* No returned parameters or data. */
 919         ntp->nt_maxpcount = 0;
 920         ntp->nt_maxdcount = 0;
 921 
 922         error = smb_nt_request(ntp);
 923         smb_nt_done(ntp);
 924 
 925         return (error);
 926 }