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 * $Id: smb_smb.c,v 1.35.100.2 2005/06/02 00:55:39 lindak Exp $ 33 */ 34 35 /* 36 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 37 * Copyright 2017 Nexenta Systems, Inc. All rights reserved. 38 */ 39 40 /* 41 * various SMB requests. Most of the routines merely packs data into mbufs. 42 */ 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/kmem.h> 46 #include <sys/proc.h> 47 #include <sys/lock.h> 48 #include <sys/socket.h> 49 #include <sys/uio.h> 50 #include <sys/random.h> 51 #include <sys/note.h> 52 #include <sys/errno.h> 53 #include <sys/cmn_err.h> 54 55 #include <netsmb/smb_osdep.h> 56 57 #include <netsmb/smb.h> 58 #include <netsmb/smb_conn.h> 59 #include <netsmb/smb_rq.h> 60 #include <netsmb/smb_subr.h> 61 #include <netsmb/smb_tran.h> 62 63 #define STYPE_LEN 8 /* share type strings */ 64 65 /* 66 * Largest size to use with LARGE_READ/LARGE_WRITE. 67 * Specs say up to 64k data bytes, but Windows traffic 68 * uses 60k... no doubt for some good reason. 69 * (Probably to keep 4k block alignment.) 70 * XXX: Move to smb.h maybe? 71 */ 72 #define SMB_MAX_LARGE_RW_SIZE (60*1024) 73 74 /* 75 * Default timeout values, all in seconds. 76 * Make these tunable (only via mdb for now). 77 */ 78 int smb_timo_notice = 15; 79 int smb_timo_default = 30; /* was SMB_DEFRQTIMO */ 80 int smb_timo_open = 45; 81 int smb_timo_read = 45; 82 int smb_timo_write = 60; /* was SMBWRTTIMO */ 83 int smb_timo_append = 90; 84 85 static int smb_smb_read(struct smb_share *ssp, uint16_t fid, 86 uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo); 87 static int smb_smb_write(struct smb_share *ssp, uint16_t fid, 88 uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo); 89 90 static int smb_smb_readx(struct smb_share *ssp, uint16_t fid, 91 uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo); 92 static int smb_smb_writex(struct smb_share *ssp, uint16_t fid, 93 uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo); 94 95 /* 96 * Get the string representation of a share "use" type, 97 * as needed for the "service" in tree connect. 98 */ 99 static const char * 100 smb_share_typename(uint32_t stype) 101 { 102 const char *p; 103 104 switch (stype) { 105 case STYPE_DISKTREE: 106 p = "A:"; 107 break; 108 case STYPE_PRINTQ: 109 p = "LPT1:"; 110 break; 111 case STYPE_DEVICE: 112 p = "COMM"; 113 break; 114 case STYPE_IPC: 115 p = "IPC"; 116 break; 117 case STYPE_UNKNOWN: 118 default: 119 p = "?????"; 120 break; 121 } 122 return (p); 123 } 124 125 /* 126 * Parse a share type name (inverse of above) 127 */ 128 static uint32_t 129 smb_share_parsetype(char *name) 130 { 131 int stype; 132 133 switch (*name) { 134 case 'A': /* A: */ 135 stype = STYPE_DISKTREE; 136 break; 137 case 'C': /* COMM */ 138 stype = STYPE_DEVICE; 139 break; 140 case 'I': /* IPC */ 141 stype = STYPE_IPC; 142 break; 143 case 'L': /* LPT: */ 144 stype = STYPE_PRINTQ; 145 break; 146 default: 147 stype = STYPE_UNKNOWN; 148 break; 149 } 150 return (stype); 151 } 152 153 int 154 smb_smb_treeconnect(struct smb_share *ssp, struct smb_cred *scred) 155 { 156 struct smb_vc *vcp; 157 struct smb_rq *rqp = NULL; 158 struct mbchain *mbp; 159 struct mdchain *mdp; 160 const char *tname; 161 char *pbuf, *unc_name = NULL; 162 int error, tlen, plen, unc_len; 163 uint16_t bcnt, options; 164 uint8_t wc; 165 char stype_str[STYPE_LEN]; 166 167 vcp = SSTOVC(ssp); 168 169 /* 170 * Make this a "VC-level" request, so it will have 171 * rqp->sr_share == NULL, and smb_iod_sendrq() 172 * will send it with TID = SMB_TID_UNKNOWN 173 * 174 * This also serves to bypass the wait for 175 * share state changes, which this call is 176 * trying to carry out. 177 */ 178 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_TREE_CONNECT_ANDX, 179 scred, &rqp); 180 if (error) 181 return (error); 182 183 /* 184 * Build the UNC name, i.e. "//server/share" 185 * but with backslashes of course. 186 * size math: three slashes, one null. 187 */ 188 unc_len = 4 + strlen(vcp->vc_srvname) + strlen(ssp->ss_name); 189 unc_name = kmem_alloc(unc_len, KM_SLEEP); 190 (void) snprintf(unc_name, unc_len, "\\\\%s\\%s", 191 vcp->vc_srvname, ssp->ss_name); 192 SMBSDEBUG("unc_name: \"%s\"", unc_name); 193 194 195 /* 196 * Share-level password (pre-computed in user-space) 197 * MS-SMB 2.2.6 says this should be null terminated, 198 * and the pw length includes the null. 199 */ 200 pbuf = ssp->ss_pass; 201 plen = strlen(pbuf) + 1; 202 203 /* 204 * Build the request. 205 */ 206 mbp = &rqp->sr_rq; 207 smb_rq_wstart(rqp); 208 mb_put_uint8(mbp, 0xff); 209 mb_put_uint8(mbp, 0); 210 mb_put_uint16le(mbp, 0); 211 mb_put_uint16le(mbp, 0); /* Flags */ 212 mb_put_uint16le(mbp, plen); 213 smb_rq_wend(rqp); 214 smb_rq_bstart(rqp); 215 216 /* Tree connect password, if any */ 217 error = mb_put_mem(mbp, pbuf, plen, MB_MSYSTEM); 218 if (error) 219 goto out; 220 221 /* UNC resource name */ 222 error = smb_put_dstring(mbp, vcp, unc_name, SMB_CS_NONE); 223 if (error) 224 goto out; 225 226 /* 227 * Put the type string (always ASCII), 228 * including the null. 229 */ 230 tname = smb_share_typename(ssp->ss_use); 231 tlen = strlen(tname) + 1; 232 error = mb_put_mem(mbp, tname, tlen, MB_MSYSTEM); 233 if (error) 234 goto out; 235 236 smb_rq_bend(rqp); 237 238 /* 239 * Run the request. 240 * 241 * Using NOINTR_RECV because we don't want to risk 242 * missing a successful tree connect response, 243 * which would "leak" Tree IDs. 244 */ 245 rqp->sr_flags |= SMBR_NOINTR_RECV; 246 error = smb_rq_simple(rqp); 247 SMBSDEBUG("%d\n", error); 248 if (error) { 249 /* 250 * If we get the server name wrong, i.e. due to 251 * mis-configured name services, this will be 252 * NT_STATUS_DUPLICATE_NAME. Log this error. 253 */ 254 SMBERROR("(%s) failed, status=0x%x", 255 unc_name, rqp->sr_error); 256 goto out; 257 } 258 259 /* 260 * Parse the TCON response 261 */ 262 smb_rq_getreply(rqp, &mdp); 263 md_get_uint8(mdp, &wc); 264 if (wc != 3 && wc != 7) { 265 error = EBADRPC; 266 goto out; 267 } 268 md_get_uint16le(mdp, NULL); /* AndX cmd */ 269 md_get_uint16le(mdp, NULL); /* AndX off */ 270 md_get_uint16le(mdp, &options); /* option bits (DFS, search) */ 271 if (wc == 7) { 272 md_get_uint32le(mdp, NULL); /* MaximalShareAccessRights */ 273 md_get_uint32le(mdp, NULL); /* GuestMaximalShareAcc... */ 274 } 275 error = md_get_uint16le(mdp, &bcnt); /* byte count */ 276 if (error) 277 goto out; 278 279 /* 280 * Get the returned share type string, i.e. "IPC" or whatever. 281 * (See smb_share_typename, smb_share_parsetype). If we get 282 * an error reading the type, just say STYPE_UNKNOWN. 283 */ 284 tlen = STYPE_LEN; 285 bzero(stype_str, tlen--); 286 if (tlen > bcnt) 287 tlen = bcnt; 288 md_get_mem(mdp, stype_str, tlen, MB_MSYSTEM); 289 stype_str[tlen] = '\0'; 290 ssp->ss_type = smb_share_parsetype(stype_str); 291 292 /* Success! */ 293 SMB_SS_LOCK(ssp); 294 ssp->ss_tid = rqp->sr_rptid; 295 ssp->ss_vcgenid = vcp->vc_genid; 296 ssp->ss_options = options; 297 ssp->ss_flags |= SMBS_CONNECTED; 298 SMB_SS_UNLOCK(ssp); 299 300 out: 301 if (unc_name) 302 kmem_free(unc_name, unc_len); 303 smb_rq_done(rqp); 304 return (error); 305 } 306 307 int 308 smb_smb_treedisconnect(struct smb_share *ssp, struct smb_cred *scred) 309 { 310 struct smb_vc *vcp; 311 struct smb_rq *rqp; 312 int error; 313 314 if (ssp->ss_tid == SMB_TID_UNKNOWN) 315 return (0); 316 317 /* 318 * Build this as a "VC-level" request, so it will 319 * avoid testing the _GONE flag on the share, 320 * which has already been set at this point. 321 * Add the share pointer "by hand" below, so 322 * smb_iod_sendrq will plug in the TID. 323 */ 324 vcp = SSTOVC(ssp); 325 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_TREE_DISCONNECT, scred, &rqp); 326 if (error) 327 return (error); 328 rqp->sr_share = ssp; /* by hand */ 329 330 smb_rq_wstart(rqp); 331 smb_rq_wend(rqp); 332 smb_rq_bstart(rqp); 333 smb_rq_bend(rqp); 334 335 /* 336 * Run this with a relatively short timeout. (5 sec.) 337 * We don't really care about the result here, but we 338 * do need to make sure we send this out, or we could 339 * "leak" active tree IDs on interrupt or timeout. 340 * The NOINTR_SEND flag makes this request immune to 341 * interrupt or timeout until the send is done. 342 * Also, don't reconnect for this, of course! 343 */ 344 rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT); 345 error = smb_rq_simple_timed(rqp, 5); 346 SMBSDEBUG("%d\n", error); 347 smb_rq_done(rqp); 348 ssp->ss_tid = SMB_TID_UNKNOWN; 349 return (error); 350 } 351 352 /* 353 * Modern create/open of file or directory. 354 */ 355 int 356 smb_smb_ntcreate( 357 struct smb_share *ssp, 358 struct mbchain *name_mb, 359 uint32_t cr_flags, /* create flags */ 360 uint32_t req_acc, /* requested access */ 361 uint32_t efa, /* ext. file attrs (DOS attr +) */ 362 uint32_t share_acc, 363 uint32_t open_disp, /* open disposition */ 364 uint32_t createopt, /* NTCREATEX_OPTIONS_ */ 365 uint32_t impersonate, /* NTCREATEX_IMPERSONATION_... */ 366 struct smb_cred *scrp, 367 uint16_t *fidp, /* returned FID */ 368 uint32_t *cr_act_p, /* optional create action */ 369 struct smbfattr *fap) /* optional attributes */ 370 { 371 struct smb_rq rq, *rqp = &rq; 372 struct smb_vc *vcp = SSTOVC(ssp); 373 struct mbchain *mbp; 374 struct mdchain *mdp; 375 struct smbfattr fa; 376 uint64_t llongint; 377 uint32_t longint, createact; 378 uint16_t fid; 379 uint8_t wc; 380 int error; 381 382 bzero(&fa, sizeof (fa)); 383 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_NT_CREATE_ANDX, scrp); 384 if (error) 385 return (error); 386 smb_rq_getrequest(rqp, &mbp); 387 388 /* Word parameters */ 389 smb_rq_wstart(rqp); 390 mb_put_uint8(mbp, 0xff); /* secondary command */ 391 mb_put_uint8(mbp, 0); /* MBZ */ 392 mb_put_uint16le(mbp, 0); /* offset to next command (none) */ 393 mb_put_uint8(mbp, 0); /* MBZ */ 394 mb_put_uint16le(mbp, name_mb->mb_count); 395 mb_put_uint32le(mbp, cr_flags); /* NTCREATEX_FLAGS_* */ 396 mb_put_uint32le(mbp, 0); /* FID - basis for path if not root */ 397 mb_put_uint32le(mbp, req_acc); 398 mb_put_uint64le(mbp, 0); /* "initial allocation size" */ 399 mb_put_uint32le(mbp, efa); 400 mb_put_uint32le(mbp, share_acc); 401 mb_put_uint32le(mbp, open_disp); 402 mb_put_uint32le(mbp, createopt); 403 mb_put_uint32le(mbp, impersonate); 404 mb_put_uint8(mbp, 0); /* security flags (?) */ 405 smb_rq_wend(rqp); 406 407 /* 408 * Byte parameters: Just the path name, aligned. 409 * Note: mb_put_mbuf consumes mb_top, so clear it. 410 */ 411 smb_rq_bstart(rqp); 412 if (SMB_UNICODE_STRINGS(vcp)) 413 mb_put_padbyte(mbp); 414 mb_put_mbuf(mbp, name_mb->mb_top); 415 bzero(name_mb, sizeof (*name_mb)); 416 smb_rq_bend(rqp); 417 418 /* 419 * Don't want to risk missing a successful 420 * open response, or we could "leak" FIDs. 421 */ 422 rqp->sr_flags |= SMBR_NOINTR_RECV; 423 error = smb_rq_simple_timed(rqp, smb_timo_open); 424 if (error) 425 goto done; 426 smb_rq_getreply(rqp, &mdp); 427 /* 428 * spec says 26 for word count, but 34 words are defined 429 * and observed from win2000 430 */ 431 error = md_get_uint8(mdp, &wc); 432 if (error) 433 goto done; 434 if (wc != 26 && wc < 34) { 435 error = EBADRPC; 436 goto done; 437 } 438 md_get_uint8(mdp, NULL); /* secondary cmd */ 439 md_get_uint8(mdp, NULL); /* mbz */ 440 md_get_uint16le(mdp, NULL); /* andxoffset */ 441 md_get_uint8(mdp, NULL); /* oplock lvl granted */ 442 md_get_uint16le(mdp, &fid); /* file ID */ 443 md_get_uint32le(mdp, &createact); /* create_action */ 444 445 md_get_uint64le(mdp, &llongint); /* creation time */ 446 smb_time_NT2local(llongint, &fa.fa_createtime); 447 md_get_uint64le(mdp, &llongint); /* access time */ 448 smb_time_NT2local(llongint, &fa.fa_atime); 449 md_get_uint64le(mdp, &llongint); /* write time */ 450 smb_time_NT2local(llongint, &fa.fa_mtime); 451 md_get_uint64le(mdp, &llongint); /* change time */ 452 smb_time_NT2local(llongint, &fa.fa_ctime); 453 454 md_get_uint32le(mdp, &longint); /* attributes */ 455 fa.fa_attr = longint; 456 md_get_uint64le(mdp, &llongint); /* allocation size */ 457 fa.fa_allocsz = llongint; 458 md_get_uint64le(mdp, &llongint); /* EOF position */ 459 fa.fa_size = llongint; 460 461 error = md_get_uint16le(mdp, NULL); /* file type */ 462 /* other stuff we don't care about */ 463 464 done: 465 smb_rq_done(rqp); 466 if (error) 467 return (error); 468 469 *fidp = fid; 470 if (cr_act_p) 471 *cr_act_p = createact; 472 if (fap) 473 *fap = fa; /* struct copy */ 474 475 return (0); 476 } 477 478 int 479 smb_smb_close(struct smb_share *ssp, uint16_t fid, struct timespec *mtime, 480 struct smb_cred *scrp) 481 { 482 struct smb_rq rq, *rqp = &rq; 483 struct mbchain *mbp; 484 long time; 485 int error; 486 487 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CLOSE, scrp); 488 if (error) 489 return (error); 490 smb_rq_getrequest(rqp, &mbp); 491 smb_rq_wstart(rqp); 492 mb_put_uint16le(mbp, fid); 493 if (mtime) { 494 int sv_tz = SSTOVC(ssp)->vc_sopt.sv_tz; 495 smb_time_local2server(mtime, sv_tz, &time); 496 } else { 497 time = 0; 498 } 499 mb_put_uint32le(mbp, time); 500 smb_rq_wend(rqp); 501 smb_rq_bstart(rqp); 502 smb_rq_bend(rqp); 503 504 /* Make sure we send, but only if already connected */ 505 rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT); 506 error = smb_rq_simple(rqp); 507 smb_rq_done(rqp); 508 return (error); 509 } 510 511 int 512 smb_smb_open_prjob( 513 struct smb_share *ssp, 514 char *title, 515 uint16_t setuplen, 516 uint16_t mode, 517 struct smb_cred *scrp, 518 uint16_t *fidp) 519 { 520 struct smb_rq rq, *rqp = &rq; 521 struct smb_vc *vcp = SSTOVC(ssp); 522 struct mbchain *mbp; 523 struct mdchain *mdp; 524 uint16_t fid; 525 uint8_t wc; 526 int error; 527 528 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_OPEN_PRINT_FILE, scrp); 529 if (error) 530 return (error); 531 smb_rq_getrequest(rqp, &mbp); 532 533 /* Word parameters */ 534 smb_rq_wstart(rqp); 535 mb_put_uint16le(mbp, setuplen); 536 mb_put_uint16le(mbp, mode); 537 smb_rq_wend(rqp); 538 539 /* 540 * Byte parameters: Just the title 541 */ 542 smb_rq_bstart(rqp); 543 mb_put_uint8(mbp, SMB_DT_ASCII); 544 error = smb_put_dstring(mbp, vcp, title, SMB_CS_NONE); 545 smb_rq_bend(rqp); 546 if (error) 547 goto done; 548 549 /* 550 * Don't want to risk missing a successful 551 * open response, or we could "leak" FIDs. 552 */ 553 rqp->sr_flags |= SMBR_NOINTR_RECV; 554 error = smb_rq_simple_timed(rqp, smb_timo_open); 555 if (error) 556 goto done; 557 558 smb_rq_getreply(rqp, &mdp); 559 error = md_get_uint8(mdp, &wc); 560 if (error || wc < 1) { 561 error = EBADRPC; 562 goto done; 563 } 564 error = md_get_uint16le(mdp, &fid); 565 566 done: 567 smb_rq_done(rqp); 568 if (error) 569 return (error); 570 571 *fidp = fid; 572 return (0); 573 } 574 575 /* 576 * Like smb_smb_close, but for print shares. 577 */ 578 int 579 smb_smb_close_prjob(struct smb_share *ssp, uint16_t fid, 580 struct smb_cred *scrp) 581 { 582 struct smb_rq rq, *rqp = &rq; 583 struct mbchain *mbp; 584 int error; 585 586 error = smb_rq_init(rqp, SSTOCP(ssp), 587 SMB_COM_CLOSE_PRINT_FILE, scrp); 588 if (error) 589 return (error); 590 smb_rq_getrequest(rqp, &mbp); 591 smb_rq_wstart(rqp); 592 mb_put_uint16le(mbp, fid); 593 smb_rq_wend(rqp); 594 smb_rq_bstart(rqp); 595 smb_rq_bend(rqp); 596 597 /* Make sure we send but only if already connected */ 598 rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT); 599 error = smb_rq_simple(rqp); 600 smb_rq_done(rqp); 601 return (error); 602 } 603 604 /* 605 * Common function for read/write with UIO. 606 * Called by netsmb smb_usr_rw, 607 * smbfs_readvnode, smbfs_writevnode 608 */ 609 int 610 smb_rwuio(struct smb_share *ssp, uint16_t fid, uio_rw_t rw, 611 uio_t *uiop, smb_cred_t *scred, int timo) 612 { 613 struct smb_vc *vcp = SSTOVC(ssp); 614 ssize_t save_resid; 615 uint32_t len, rlen, maxlen; 616 int error = 0; 617 int (*iofun)(struct smb_share *, uint16_t, uint32_t *, 618 uio_t *, smb_cred_t *, int); 619 620 /* 621 * Determine which function to use, 622 * and the transfer size per call. 623 */ 624 if (SMB_DIALECT(vcp) >= SMB_DIALECT_NTLM0_12) { 625 /* 626 * Using NT LM 0.12, so readx, writex. 627 * Make sure we can represent the offset. 628 */ 629 if ((vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_FILES) == 0 && 630 (uiop->uio_loffset + uiop->uio_resid) > UINT32_MAX) 631 return (EFBIG); 632 633 if (rw == UIO_READ) { 634 iofun = smb_smb_readx; 635 if (vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_READX) 636 maxlen = SMB_MAX_LARGE_RW_SIZE; 637 else 638 maxlen = vcp->vc_rxmax; 639 } else { /* UIO_WRITE */ 640 iofun = smb_smb_writex; 641 if (vcp->vc_sopt.sv_caps & SMB_CAP_LARGE_WRITEX) 642 maxlen = SMB_MAX_LARGE_RW_SIZE; 643 else 644 maxlen = vcp->vc_wxmax; 645 } 646 } else { 647 /* 648 * Using the old SMB_READ and SMB_WRITE so 649 * we're limited to 32-bit offsets, etc. 650 * XXX: Someday, punt the old dialects. 651 */ 652 if ((uiop->uio_loffset + uiop->uio_resid) > UINT32_MAX) 653 return (EFBIG); 654 655 if (rw == UIO_READ) { 656 iofun = smb_smb_read; 657 maxlen = vcp->vc_rxmax; 658 } else { /* UIO_WRITE */ 659 iofun = smb_smb_write; 660 maxlen = vcp->vc_wxmax; 661 } 662 } 663 664 save_resid = uiop->uio_resid; 665 while (uiop->uio_resid > 0) { 666 /* Lint: uio_resid may be 64-bits */ 667 rlen = len = (uint32_t)min(maxlen, uiop->uio_resid); 668 error = (*iofun)(ssp, fid, &rlen, uiop, scred, timo); 669 670 /* 671 * Note: the iofun called uio_update, so 672 * not doing that here as one might expect. 673 * 674 * Quit the loop either on error, or if we 675 * transferred less then requested. 676 */ 677 if (error || (rlen < len)) 678 break; 679 680 timo = 0; /* only first I/O should wait */ 681 } 682 if (error && (save_resid != uiop->uio_resid)) { 683 /* 684 * Stopped on an error after having 685 * successfully transferred data. 686 * Suppress this error. 687 */ 688 SMBSDEBUG("error %d suppressed\n", error); 689 error = 0; 690 } 691 692 return (error); 693 } 694 695 static int 696 smb_smb_readx(struct smb_share *ssp, uint16_t fid, uint32_t *lenp, 697 uio_t *uiop, smb_cred_t *scred, int timo) 698 { 699 struct smb_rq *rqp; 700 struct mbchain *mbp; 701 struct mdchain *mdp; 702 int error; 703 uint32_t offlo, offhi, rlen; 704 uint16_t lenhi, lenlo, off, doff; 705 uint8_t wc; 706 707 lenhi = (uint16_t)(*lenp >> 16); 708 lenlo = (uint16_t)*lenp; 709 offhi = (uint32_t)(uiop->uio_loffset >> 32); 710 offlo = (uint32_t)uiop->uio_loffset; 711 712 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ_ANDX, scred, &rqp); 713 if (error) 714 return (error); 715 smb_rq_getrequest(rqp, &mbp); 716 smb_rq_wstart(rqp); 717 mb_put_uint8(mbp, 0xff); /* no secondary command */ 718 mb_put_uint8(mbp, 0); /* MBZ */ 719 mb_put_uint16le(mbp, 0); /* offset to secondary */ 720 mb_put_uint16le(mbp, fid); 721 mb_put_uint32le(mbp, offlo); /* offset (low part) */ 722 mb_put_uint16le(mbp, lenlo); /* MaxCount */ 723 mb_put_uint16le(mbp, 1); /* MinCount */ 724 /* (only indicates blocking) */ 725 mb_put_uint32le(mbp, lenhi); /* MaxCountHigh */ 726 mb_put_uint16le(mbp, lenlo); /* Remaining ("obsolete") */ 727 mb_put_uint32le(mbp, offhi); /* offset (high part) */ 728 smb_rq_wend(rqp); 729 smb_rq_bstart(rqp); 730 smb_rq_bend(rqp); 731 732 if (timo == 0) 733 timo = smb_timo_read; 734 error = smb_rq_simple_timed(rqp, timo); 735 if (error) 736 goto out; 737 738 smb_rq_getreply(rqp, &mdp); 739 error = md_get_uint8(mdp, &wc); 740 if (error) 741 goto out; 742 if (wc != 12) { 743 error = EBADRPC; 744 goto out; 745 } 746 md_get_uint8(mdp, NULL); 747 md_get_uint8(mdp, NULL); 748 md_get_uint16le(mdp, NULL); 749 md_get_uint16le(mdp, NULL); 750 md_get_uint16le(mdp, NULL); /* data compaction mode */ 751 md_get_uint16le(mdp, NULL); 752 md_get_uint16le(mdp, &lenlo); /* data len ret. */ 753 md_get_uint16le(mdp, &doff); /* data offset */ 754 md_get_uint16le(mdp, &lenhi); 755 rlen = (lenhi << 16) | lenlo; 756 md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM); 757 error = md_get_uint16le(mdp, NULL); /* ByteCount */ 758 if (error) 759 goto out; 760 /* 761 * Does the data offset indicate padding? 762 * The current offset is a constant, found 763 * by counting the md_get_ calls above. 764 */ 765 off = SMB_HDRLEN + 3 + (12 * 2); /* =59 */ 766 if (doff > off) /* pad byte(s)? */ 767 md_get_mem(mdp, NULL, doff - off, MB_MSYSTEM); 768 if (rlen == 0) { 769 *lenp = rlen; 770 goto out; 771 } 772 /* paranoid */ 773 if (rlen > *lenp) { 774 SMBSDEBUG("bad server! rlen %d, len %d\n", 775 rlen, *lenp); 776 rlen = *lenp; 777 } 778 error = md_get_uio(mdp, uiop, rlen); 779 if (error) 780 goto out; 781 782 /* Success */ 783 *lenp = rlen; 784 785 out: 786 smb_rq_done(rqp); 787 return (error); 788 } 789 790 static int 791 smb_smb_writex(struct smb_share *ssp, uint16_t fid, uint32_t *lenp, 792 uio_t *uiop, smb_cred_t *scred, int timo) 793 { 794 struct smb_rq *rqp; 795 struct mbchain *mbp; 796 struct mdchain *mdp; 797 int error; 798 uint32_t offlo, offhi, rlen; 799 uint16_t lenhi, lenlo; 800 uint8_t wc; 801 802 lenhi = (uint16_t)(*lenp >> 16); 803 lenlo = (uint16_t)*lenp; 804 offhi = (uint32_t)(uiop->uio_loffset >> 32); 805 offlo = (uint32_t)uiop->uio_loffset; 806 807 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE_ANDX, scred, &rqp); 808 if (error) 809 return (error); 810 smb_rq_getrequest(rqp, &mbp); 811 smb_rq_wstart(rqp); 812 mb_put_uint8(mbp, 0xff); /* no secondary command */ 813 mb_put_uint8(mbp, 0); /* MBZ */ 814 mb_put_uint16le(mbp, 0); /* offset to secondary */ 815 mb_put_uint16le(mbp, fid); 816 mb_put_uint32le(mbp, offlo); /* offset (low part) */ 817 mb_put_uint32le(mbp, 0); /* MBZ (timeout) */ 818 mb_put_uint16le(mbp, 0); /* !write-thru */ 819 mb_put_uint16le(mbp, 0); 820 mb_put_uint16le(mbp, lenhi); 821 mb_put_uint16le(mbp, lenlo); 822 mb_put_uint16le(mbp, 64); /* data offset from header start */ 823 mb_put_uint32le(mbp, offhi); /* offset (high part) */ 824 smb_rq_wend(rqp); 825 smb_rq_bstart(rqp); 826 827 mb_put_uint8(mbp, 0); /* pad byte */ 828 error = mb_put_uio(mbp, uiop, *lenp); 829 if (error) 830 goto out; 831 smb_rq_bend(rqp); 832 if (timo == 0) 833 timo = smb_timo_write; 834 error = smb_rq_simple_timed(rqp, timo); 835 if (error) 836 goto out; 837 smb_rq_getreply(rqp, &mdp); 838 error = md_get_uint8(mdp, &wc); 839 if (error) 840 goto out; 841 if (wc != 6) { 842 error = EBADRPC; 843 goto out; 844 } 845 md_get_uint8(mdp, NULL); /* andx cmd */ 846 md_get_uint8(mdp, NULL); /* reserved */ 847 md_get_uint16le(mdp, NULL); /* andx offset */ 848 md_get_uint16le(mdp, &lenlo); /* data len ret. */ 849 md_get_uint16le(mdp, NULL); /* remaining */ 850 error = md_get_uint16le(mdp, &lenhi); 851 if (error) 852 goto out; 853 854 /* Success */ 855 rlen = (lenhi << 16) | lenlo; 856 *lenp = rlen; 857 858 out: 859 smb_rq_done(rqp); 860 return (error); 861 } 862 863 static int 864 smb_smb_read(struct smb_share *ssp, uint16_t fid, uint32_t *lenp, 865 uio_t *uiop, smb_cred_t *scred, int timo) 866 { 867 struct smb_rq *rqp; 868 struct mbchain *mbp; 869 struct mdchain *mdp; 870 int error; 871 uint32_t off32; 872 uint16_t bc, cnt, dlen, rcnt, todo; 873 uint8_t wc; 874 875 ASSERT(uiop->uio_loffset <= UINT32_MAX); 876 off32 = (uint32_t)uiop->uio_loffset; 877 ASSERT(*lenp <= UINT16_MAX); 878 cnt = (uint16_t)*lenp; 879 /* This next is an "estimate" of planned reads. */ 880 todo = (uint16_t)min(uiop->uio_resid, UINT16_MAX); 881 882 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ, scred, &rqp); 883 if (error) 884 return (error); 885 smb_rq_getrequest(rqp, &mbp); 886 smb_rq_wstart(rqp); 887 mb_put_uint16le(mbp, fid); 888 mb_put_uint16le(mbp, cnt); 889 mb_put_uint32le(mbp, off32); 890 mb_put_uint16le(mbp, todo); 891 smb_rq_wend(rqp); 892 smb_rq_bstart(rqp); 893 smb_rq_bend(rqp); 894 895 if (timo == 0) 896 timo = smb_timo_read; 897 error = smb_rq_simple_timed(rqp, timo); 898 if (error) 899 goto out; 900 smb_rq_getreply(rqp, &mdp); 901 error = md_get_uint8(mdp, &wc); 902 if (error) 903 goto out; 904 if (wc != 5) { 905 error = EBADRPC; 906 goto out; 907 } 908 md_get_uint16le(mdp, &rcnt); /* ret. count */ 909 md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM); /* res. */ 910 md_get_uint16le(mdp, &bc); /* byte count */ 911 md_get_uint8(mdp, NULL); /* buffer format */ 912 error = md_get_uint16le(mdp, &dlen); /* data len */ 913 if (error) 914 goto out; 915 if (dlen < rcnt) { 916 SMBSDEBUG("oops: dlen=%d rcnt=%d\n", 917 (int)dlen, (int)rcnt); 918 rcnt = dlen; 919 } 920 if (rcnt == 0) { 921 *lenp = 0; 922 goto out; 923 } 924 /* paranoid */ 925 if (rcnt > cnt) { 926 SMBSDEBUG("bad server! rcnt %d, cnt %d\n", 927 (int)rcnt, (int)cnt); 928 rcnt = cnt; 929 } 930 error = md_get_uio(mdp, uiop, (int)rcnt); 931 if (error) 932 goto out; 933 934 /* success */ 935 *lenp = (int)rcnt; 936 937 out: 938 smb_rq_done(rqp); 939 return (error); 940 } 941 942 static int 943 smb_smb_write(struct smb_share *ssp, uint16_t fid, uint32_t *lenp, 944 uio_t *uiop, smb_cred_t *scred, int timo) 945 { 946 struct smb_rq *rqp; 947 struct mbchain *mbp; 948 struct mdchain *mdp; 949 int error; 950 uint32_t off32; 951 uint16_t cnt, rcnt, todo; 952 uint8_t wc; 953 954 ASSERT(uiop->uio_loffset <= UINT32_MAX); 955 off32 = (uint32_t)uiop->uio_loffset; 956 ASSERT(*lenp <= UINT16_MAX); 957 cnt = (uint16_t)*lenp; 958 /* This next is an "estimate" of planned writes. */ 959 todo = (uint16_t)min(uiop->uio_resid, UINT16_MAX); 960 961 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp); 962 if (error) 963 return (error); 964 smb_rq_getrequest(rqp, &mbp); 965 smb_rq_wstart(rqp); 966 mb_put_uint16le(mbp, fid); 967 mb_put_uint16le(mbp, cnt); 968 mb_put_uint32le(mbp, off32); 969 mb_put_uint16le(mbp, todo); 970 smb_rq_wend(rqp); 971 smb_rq_bstart(rqp); 972 mb_put_uint8(mbp, SMB_DT_DATA); 973 mb_put_uint16le(mbp, cnt); 974 975 error = mb_put_uio(mbp, uiop, *lenp); 976 if (error) 977 goto out; 978 smb_rq_bend(rqp); 979 if (timo == 0) 980 timo = smb_timo_write; 981 error = smb_rq_simple_timed(rqp, timo); 982 if (error) 983 goto out; 984 smb_rq_getreply(rqp, &mdp); 985 error = md_get_uint8(mdp, &wc); 986 if (error) 987 goto out; 988 if (wc != 1) { 989 error = EBADRPC; 990 goto out; 991 } 992 error = md_get_uint16le(mdp, &rcnt); 993 if (error) 994 goto out; 995 *lenp = rcnt; 996 997 out: 998 smb_rq_done(rqp); 999 return (error); 1000 } 1001 1002 1003 static u_int32_t smbechoes = 0; 1004 1005 int 1006 smb_smb_echo(struct smb_vc *vcp, struct smb_cred *scred, int timo) 1007 { 1008 struct smb_rq *rqp; 1009 struct mbchain *mbp; 1010 int error; 1011 1012 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_ECHO, scred, &rqp); 1013 if (error) 1014 return (error); 1015 mbp = &rqp->sr_rq; 1016 smb_rq_wstart(rqp); 1017 mb_put_uint16le(mbp, 1); /* echo count */ 1018 smb_rq_wend(rqp); 1019 smb_rq_bstart(rqp); 1020 mb_put_uint32le(mbp, atomic_inc_32_nv(&smbechoes)); 1021 smb_rq_bend(rqp); 1022 /* 1023 * Note: the IOD calls this, so 1024 * this request must not wait for 1025 * connection state changes, etc. 1026 */ 1027 rqp->sr_flags |= SMBR_NORECONNECT; 1028 error = smb_rq_simple_timed(rqp, timo); 1029 SMBSDEBUG("%d\n", error); 1030 smb_rq_done(rqp); 1031 return (error); 1032 } 1033