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 } 927