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 * Portions Copyright (C) 2001 - 2014 Apple Inc. All rights reserved. 37 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 38 * Copyright 2018 Nexenta Systems, Inc. All rights reserved. 39 */ 40 41 /* 42 * various SMB requests. Most of the routines merely packs data into mbufs. 43 */ 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/kmem.h> 47 #include <sys/proc.h> 48 #include <sys/lock.h> 49 #include <sys/socket.h> 50 #include <sys/uio.h> 51 #include <sys/random.h> 52 #include <sys/note.h> 53 #include <sys/errno.h> 54 #include <sys/cmn_err.h> 55 56 #include <netsmb/smb_osdep.h> 57 58 #include <netsmb/smb.h> 59 #include <netsmb/smb_conn.h> 60 #include <netsmb/smb_rq.h> 61 #include <netsmb/smb_subr.h> 62 #include <netsmb/smb_tran.h> 63 64 #define STYPE_LEN 8 /* share type strings */ 65 66 struct smb_dialect { 67 int d_id; 68 const char *d_name; 69 }; 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 86 /* 87 * Default timeout values, all in seconds. 88 * Make these tunable (only via mdb for now). 89 */ 90 int smb_timo_notice = 15; 91 int smb_timo_default = 30; /* was SMB_DEFRQTIMO */ 92 int smb_timo_logon = 45; 93 int smb_timo_open = 45; 94 int smb_timo_read = 45; 95 int smb_timo_write = 60; /* was SMBWRTTIMO */ 96 int smb_timo_append = 90; 97 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; 112 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; 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 613 /* 614 * Get the string representation of a share "use" type, 615 * as needed for the "service" in tree connect. 616 */ 617 static const char * 618 smb_share_typename(uint32_t stype) 619 { 620 const char *p; 621 622 switch (stype) { 623 case STYPE_DISKTREE: 624 p = "A:"; 625 break; 626 case STYPE_PRINTQ: 627 p = "LPT1:"; 628 break; 629 case STYPE_DEVICE: 630 p = "COMM"; 631 break; 632 case STYPE_IPC: 633 p = "IPC"; 634 break; 635 case STYPE_UNKNOWN: 636 default: 637 p = "?????"; 638 break; 639 } 640 return (p); 641 } 642 643 /* 644 * Parse a share type name (inverse of above) 645 */ 646 static uint32_t 647 smb_share_parsetype(char *name) 648 { 649 int stype; 650 651 switch (*name) { 652 case 'A': /* A: */ 653 stype = STYPE_DISKTREE; 654 break; 655 case 'C': /* COMM */ 656 stype = STYPE_DEVICE; 657 break; 658 case 'I': /* IPC */ 659 stype = STYPE_IPC; 660 break; 661 case 'L': /* LPT: */ 662 stype = STYPE_PRINTQ; 663 break; 664 default: 665 stype = STYPE_UNKNOWN; 666 break; 667 } 668 return (stype); 669 } 670 671 int 672 smb_smb_treeconnect(struct smb_share *ssp, struct smb_cred *scred) 673 { 674 struct smb_vc *vcp; 675 struct smb_rq *rqp = NULL; 676 struct mbchain *mbp; 677 struct mdchain *mdp; 678 const char *tname; 679 char *pbuf, *unc_name = NULL; 680 int error, tlen, plen, unc_len; 681 uint16_t bcnt, options; 682 uint8_t wc; 683 char stype_str[STYPE_LEN]; 684 685 vcp = SSTOVC(ssp); 686 687 /* 688 * Make this a "VC-level" request, so it will have 689 * rqp->sr_share == NULL, and smb_iod_sendrq() 690 * will send it with TID = SMB_TID_UNKNOWN 691 * 692 * This also serves to bypass the wait for 693 * share state changes, which this call is 694 * trying to carry out. 695 */ 696 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_TREE_CONNECT_ANDX, 697 scred, &rqp); 698 if (error) 699 return (error); 700 701 /* 702 * Build the UNC name, i.e. "//server/share" 703 * but with backslashes of course. 704 * size math: three slashes, one null. 705 */ 706 unc_len = 4 + strlen(vcp->vc_srvname) + strlen(ssp->ss_name); 707 unc_name = kmem_alloc(unc_len, KM_SLEEP); 708 (void) snprintf(unc_name, unc_len, "\\\\%s\\%s", 709 vcp->vc_srvname, ssp->ss_name); 710 SMBSDEBUG("unc_name: \"%s\"", unc_name); 711 712 713 /* 714 * Share-level password (pre-computed in user-space) 715 * MS-SMB 2.2.6 says this should be null terminated, 716 * and the pw length includes the null. 717 */ 718 pbuf = ssp->ss_pass; 719 plen = strlen(pbuf) + 1; 720 721 /* 722 * Build the request. 723 */ 724 mbp = &rqp->sr_rq; 725 smb_rq_wstart(rqp); 726 mb_put_uint8(mbp, 0xff); 727 mb_put_uint8(mbp, 0); 728 mb_put_uint16le(mbp, 0); 729 mb_put_uint16le(mbp, 0); /* Flags */ 730 mb_put_uint16le(mbp, plen); 731 smb_rq_wend(rqp); 732 smb_rq_bstart(rqp); 733 734 /* Tree connect password, if any */ 735 error = mb_put_mem(mbp, pbuf, plen, MB_MSYSTEM); 736 if (error) 737 goto out; 738 739 /* UNC resource name */ 740 error = smb_put_dstring(mbp, vcp, unc_name, SMB_CS_NONE); 741 if (error) 742 goto out; 743 744 /* 745 * Put the type string (always ASCII), 746 * including the null. 747 */ 748 tname = smb_share_typename(ssp->ss_use); 749 tlen = strlen(tname) + 1; 750 error = mb_put_mem(mbp, tname, tlen, MB_MSYSTEM); 751 if (error) 752 goto out; 753 754 smb_rq_bend(rqp); 755 756 /* 757 * Run the request. 758 * 759 * Using NOINTR_RECV because we don't want to risk 760 * missing a successful tree connect response, 761 * which would "leak" Tree IDs. 762 */ 763 rqp->sr_flags |= SMBR_NOINTR_RECV; 764 error = smb_rq_simple(rqp); 765 SMBSDEBUG("%d\n", error); 766 if (error) { 767 /* 768 * If we get the server name wrong, i.e. due to 769 * mis-configured name services, this will be 770 * NT_STATUS_DUPLICATE_NAME. Log this error. 771 */ 772 SMBERROR("(%s) failed, status=0x%x", 773 unc_name, rqp->sr_error); 774 goto out; 775 } 776 777 /* 778 * Parse the TCON response 779 */ 780 smb_rq_getreply(rqp, &mdp); 781 md_get_uint8(mdp, &wc); 782 if (wc != 3 && wc != 7) { 783 error = EBADRPC; 784 goto out; 785 } 786 md_get_uint16le(mdp, NULL); /* AndX cmd */ 787 md_get_uint16le(mdp, NULL); /* AndX off */ 788 md_get_uint16le(mdp, &options); /* option bits (DFS, search) */ 789 if (wc == 7) { 790 md_get_uint32le(mdp, NULL); /* MaximalShareAccessRights */ 791 md_get_uint32le(mdp, NULL); /* GuestMaximalShareAcc... */ 792 } 793 error = md_get_uint16le(mdp, &bcnt); /* byte count */ 794 if (error) 795 goto out; 796 797 /* 798 * Get the returned share type string, i.e. "IPC" or whatever. 799 * (See smb_share_typename, smb_share_parsetype). If we get 800 * an error reading the type, just say STYPE_UNKNOWN. 801 */ 802 tlen = STYPE_LEN; 803 bzero(stype_str, tlen--); 804 if (tlen > bcnt) 805 tlen = bcnt; 806 md_get_mem(mdp, stype_str, tlen, MB_MSYSTEM); 807 stype_str[tlen] = '\0'; 808 ssp->ss_type = smb_share_parsetype(stype_str); 809 810 /* Success! */ 811 SMB_SS_LOCK(ssp); 812 ssp->ss_tid = rqp->sr_rptid; 813 ssp->ss_vcgenid = vcp->vc_genid; 814 ssp->ss_options = options; 815 ssp->ss_flags |= SMBS_CONNECTED; 816 SMB_SS_UNLOCK(ssp); 817 818 out: 819 if (unc_name) 820 kmem_free(unc_name, unc_len); 821 smb_rq_done(rqp); 822 return (error); 823 } 824 825 int 826 smb_smb_treedisconnect(struct smb_share *ssp, struct smb_cred *scred) 827 { 828 struct smb_vc *vcp; 829 struct smb_rq *rqp; 830 int error; 831 832 if (ssp->ss_tid == SMB_TID_UNKNOWN) 833 return (0); 834 835 /* 836 * Build this as a "VC-level" request, so it will 837 * avoid testing the _GONE flag on the share, 838 * which has already been set at this point. 839 * Add the share pointer "by hand" below, so 840 * smb_iod_sendrq will plug in the TID. 841 */ 842 vcp = SSTOVC(ssp); 843 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_TREE_DISCONNECT, scred, &rqp); 844 if (error) 845 return (error); 846 rqp->sr_share = ssp; /* by hand */ 847 848 smb_rq_wstart(rqp); 849 smb_rq_wend(rqp); 850 smb_rq_bstart(rqp); 851 smb_rq_bend(rqp); 852 853 /* 854 * Run this with a relatively short timeout. (5 sec.) 855 * We don't really care about the result here, but we 856 * do need to make sure we send this out, or we could 857 * "leak" active tree IDs on interrupt or timeout. 858 * The NOINTR_SEND flag makes this request immune to 859 * interrupt or timeout until the send is done. 860 * Also, don't reconnect for this, of course! 861 */ 862 rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT); 863 error = smb_rq_simple_timed(rqp, 5); 864 SMBSDEBUG("%d\n", error); 865 smb_rq_done(rqp); 866 ssp->ss_tid = SMB_TID_UNKNOWN; 867 return (error); 868 } 869 870 /* 871 * Modern create/open of file or directory. 872 */ 873 int 874 smb1_smb_ntcreate( 875 struct smb_share *ssp, 876 struct mbchain *name_mb, 877 uint32_t cr_flags, /* create flags */ 878 uint32_t req_acc, /* requested access */ 879 uint32_t efa, /* ext. file attrs (DOS attr +) */ 880 uint32_t share_acc, 881 uint32_t open_disp, /* open disposition */ 882 uint32_t createopt, /* NTCREATEX_OPTIONS_ */ 883 uint32_t impersonate, /* NTCREATEX_IMPERSONATION_... */ 884 struct smb_cred *scrp, 885 uint16_t *fidp, /* returned FID */ 886 uint32_t *cr_act_p, /* optional create action */ 887 struct smbfattr *fap) /* optional attributes */ 888 { 889 struct smb_rq rq, *rqp = &rq; 890 struct smb_vc *vcp = SSTOVC(ssp); 891 struct mbchain *mbp; 892 struct mdchain *mdp; 893 struct smbfattr fa; 894 uint64_t llongint; 895 uint32_t longint, createact; 896 uint16_t fid; 897 uint8_t wc; 898 int error; 899 900 bzero(&fa, sizeof (fa)); 901 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_NT_CREATE_ANDX, scrp); 902 if (error) 903 return (error); 904 smb_rq_getrequest(rqp, &mbp); 905 906 /* Word parameters */ 907 smb_rq_wstart(rqp); 908 mb_put_uint8(mbp, 0xff); /* secondary command */ 909 mb_put_uint8(mbp, 0); /* MBZ */ 910 mb_put_uint16le(mbp, 0); /* offset to next command (none) */ 911 mb_put_uint8(mbp, 0); /* MBZ */ 912 mb_put_uint16le(mbp, name_mb->mb_count); 913 mb_put_uint32le(mbp, cr_flags); /* NTCREATEX_FLAGS_* */ 914 mb_put_uint32le(mbp, 0); /* FID - basis for path if not root */ 915 mb_put_uint32le(mbp, req_acc); 916 mb_put_uint64le(mbp, 0); /* "initial allocation size" */ 917 mb_put_uint32le(mbp, efa); 918 mb_put_uint32le(mbp, share_acc); 919 mb_put_uint32le(mbp, open_disp); 920 mb_put_uint32le(mbp, createopt); 921 mb_put_uint32le(mbp, impersonate); 922 mb_put_uint8(mbp, 0); /* security flags (?) */ 923 smb_rq_wend(rqp); 924 925 /* 926 * Byte parameters: Just the path name, aligned. 927 * Note: mb_put_mbuf consumes mb_top, so clear it. 928 */ 929 smb_rq_bstart(rqp); 930 if (SMB_UNICODE_STRINGS(vcp)) 931 mb_put_padbyte(mbp); 932 mb_put_mbuf(mbp, name_mb->mb_top); 933 bzero(name_mb, sizeof (*name_mb)); 934 smb_rq_bend(rqp); 935 936 /* 937 * Don't want to risk missing a successful 938 * open response, or we could "leak" FIDs. 939 */ 940 rqp->sr_flags |= SMBR_NOINTR_RECV; 941 error = smb_rq_simple_timed(rqp, smb_timo_open); 942 if (error) 943 goto done; 944 smb_rq_getreply(rqp, &mdp); 945 /* 946 * spec says 26 for word count, but 34 words are defined 947 * and observed from win2000 948 */ 949 error = md_get_uint8(mdp, &wc); 950 if (error) 951 goto done; 952 if (wc != 26 && wc < 34) { 953 error = EBADRPC; 954 goto done; 955 } 956 md_get_uint8(mdp, NULL); /* secondary cmd */ 957 md_get_uint8(mdp, NULL); /* mbz */ 958 md_get_uint16le(mdp, NULL); /* andxoffset */ 959 md_get_uint8(mdp, NULL); /* oplock lvl granted */ 960 md_get_uint16le(mdp, &fid); /* file ID */ 961 md_get_uint32le(mdp, &createact); /* create_action */ 962 963 md_get_uint64le(mdp, &llongint); /* creation time */ 964 smb_time_NT2local(llongint, &fa.fa_createtime); 965 md_get_uint64le(mdp, &llongint); /* access time */ 966 smb_time_NT2local(llongint, &fa.fa_atime); 967 md_get_uint64le(mdp, &llongint); /* write time */ 968 smb_time_NT2local(llongint, &fa.fa_mtime); 969 md_get_uint64le(mdp, &llongint); /* change time */ 970 smb_time_NT2local(llongint, &fa.fa_ctime); 971 972 md_get_uint32le(mdp, &longint); /* attributes */ 973 fa.fa_attr = longint; 974 md_get_uint64le(mdp, &llongint); /* allocation size */ 975 fa.fa_allocsz = llongint; 976 md_get_uint64le(mdp, &llongint); /* EOF position */ 977 fa.fa_size = llongint; 978 979 error = md_get_uint16le(mdp, NULL); /* file type */ 980 /* other stuff we don't care about */ 981 982 done: 983 smb_rq_done(rqp); 984 if (error) 985 return (error); 986 987 *fidp = fid; 988 if (cr_act_p) 989 *cr_act_p = createact; 990 if (fap) 991 *fap = fa; /* struct copy */ 992 993 return (0); 994 } 995 996 int 997 smb1_smb_close(struct smb_share *ssp, uint16_t fid, struct timespec *mtime, 998 struct smb_cred *scrp) 999 { 1000 struct smb_rq rq, *rqp = &rq; 1001 struct mbchain *mbp; 1002 long time; 1003 int error; 1004 1005 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CLOSE, scrp); 1006 if (error) 1007 return (error); 1008 smb_rq_getrequest(rqp, &mbp); 1009 smb_rq_wstart(rqp); 1010 mb_put_uint16le(mbp, fid); 1011 if (mtime) { 1012 int sv_tz = SSTOVC(ssp)->vc_sopt.sv_tz; 1013 smb_time_local2server(mtime, sv_tz, &time); 1014 } else { 1015 time = 0; 1016 } 1017 mb_put_uint32le(mbp, time); 1018 smb_rq_wend(rqp); 1019 smb_rq_bstart(rqp); 1020 smb_rq_bend(rqp); 1021 1022 /* Make sure we send, but only if already connected */ 1023 rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT); 1024 error = smb_rq_simple(rqp); 1025 smb_rq_done(rqp); 1026 return (error); 1027 } 1028 1029 int 1030 smb_smb_open_prjob( 1031 struct smb_share *ssp, 1032 char *title, 1033 uint16_t setuplen, 1034 uint16_t mode, 1035 struct smb_cred *scrp, 1036 uint16_t *fidp) 1037 { 1038 struct smb_rq rq, *rqp = &rq; 1039 struct smb_vc *vcp = SSTOVC(ssp); 1040 struct mbchain *mbp; 1041 struct mdchain *mdp; 1042 uint16_t fid; 1043 uint8_t wc; 1044 int error; 1045 1046 error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_OPEN_PRINT_FILE, scrp); 1047 if (error) 1048 return (error); 1049 smb_rq_getrequest(rqp, &mbp); 1050 1051 /* Word parameters */ 1052 smb_rq_wstart(rqp); 1053 mb_put_uint16le(mbp, setuplen); 1054 mb_put_uint16le(mbp, mode); 1055 smb_rq_wend(rqp); 1056 1057 /* 1058 * Byte parameters: Just the title 1059 */ 1060 smb_rq_bstart(rqp); 1061 mb_put_uint8(mbp, SMB_DT_ASCII); 1062 error = smb_put_dstring(mbp, vcp, title, SMB_CS_NONE); 1063 smb_rq_bend(rqp); 1064 if (error) 1065 goto done; 1066 1067 /* 1068 * Don't want to risk missing a successful 1069 * open response, or we could "leak" FIDs. 1070 */ 1071 rqp->sr_flags |= SMBR_NOINTR_RECV; 1072 error = smb_rq_simple_timed(rqp, smb_timo_open); 1073 if (error) 1074 goto done; 1075 1076 smb_rq_getreply(rqp, &mdp); 1077 error = md_get_uint8(mdp, &wc); 1078 if (error || wc < 1) { 1079 error = EBADRPC; 1080 goto done; 1081 } 1082 error = md_get_uint16le(mdp, &fid); 1083 1084 done: 1085 smb_rq_done(rqp); 1086 if (error) 1087 return (error); 1088 1089 *fidp = fid; 1090 return (0); 1091 } 1092 1093 /* 1094 * Like smb_smb_close, but for print shares. 1095 */ 1096 int 1097 smb_smb_close_prjob(struct smb_share *ssp, uint16_t fid, 1098 struct smb_cred *scrp) 1099 { 1100 struct smb_rq rq, *rqp = &rq; 1101 struct mbchain *mbp; 1102 int error; 1103 1104 error = smb_rq_init(rqp, SSTOCP(ssp), 1105 SMB_COM_CLOSE_PRINT_FILE, scrp); 1106 if (error) 1107 return (error); 1108 smb_rq_getrequest(rqp, &mbp); 1109 smb_rq_wstart(rqp); 1110 mb_put_uint16le(mbp, fid); 1111 smb_rq_wend(rqp); 1112 smb_rq_bstart(rqp); 1113 smb_rq_bend(rqp); 1114 1115 /* Make sure we send but only if already connected */ 1116 rqp->sr_flags |= (SMBR_NOINTR_SEND | SMBR_NORECONNECT); 1117 error = smb_rq_simple(rqp); 1118 smb_rq_done(rqp); 1119 return (error); 1120 } 1121 1122 int 1123 smb_smb_readx(smb_fh_t *fhp, uint32_t *lenp, 1124 uio_t *uiop, smb_cred_t *scred, int timo) 1125 { 1126 struct smb_share *ssp = FHTOSS(fhp); 1127 struct smb_rq *rqp; 1128 struct mbchain *mbp; 1129 struct mdchain *mdp; 1130 int error; 1131 uint32_t offlo, offhi, rlen; 1132 uint16_t lenhi, lenlo, off, doff; 1133 uint8_t wc; 1134 1135 lenhi = (uint16_t)(*lenp >> 16); 1136 lenlo = (uint16_t)*lenp; 1137 offhi = (uint32_t)(uiop->uio_loffset >> 32); 1138 offlo = (uint32_t)uiop->uio_loffset; 1139 1140 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ_ANDX, scred, &rqp); 1141 if (error) 1142 return (error); 1143 smb_rq_getrequest(rqp, &mbp); 1144 smb_rq_wstart(rqp); 1145 mb_put_uint8(mbp, 0xff); /* no secondary command */ 1146 mb_put_uint8(mbp, 0); /* MBZ */ 1147 mb_put_uint16le(mbp, 0); /* offset to secondary */ 1148 mb_put_uint16le(mbp, fhp->fh_fid1); 1149 mb_put_uint32le(mbp, offlo); /* offset (low part) */ 1150 mb_put_uint16le(mbp, lenlo); /* MaxCount */ 1151 mb_put_uint16le(mbp, 1); /* MinCount */ 1152 /* (only indicates blocking) */ 1153 mb_put_uint32le(mbp, lenhi); /* MaxCountHigh */ 1154 mb_put_uint16le(mbp, lenlo); /* Remaining ("obsolete") */ 1155 mb_put_uint32le(mbp, offhi); /* offset (high part) */ 1156 smb_rq_wend(rqp); 1157 smb_rq_bstart(rqp); 1158 smb_rq_bend(rqp); 1159 1160 if (timo == 0) 1161 timo = smb_timo_read; 1162 error = smb_rq_simple_timed(rqp, timo); 1163 if (error) 1164 goto out; 1165 1166 smb_rq_getreply(rqp, &mdp); 1167 error = md_get_uint8(mdp, &wc); 1168 if (error) 1169 goto out; 1170 if (wc != 12) { 1171 error = EBADRPC; 1172 goto out; 1173 } 1174 md_get_uint8(mdp, NULL); 1175 md_get_uint8(mdp, NULL); 1176 md_get_uint16le(mdp, NULL); 1177 md_get_uint16le(mdp, NULL); 1178 md_get_uint16le(mdp, NULL); /* data compaction mode */ 1179 md_get_uint16le(mdp, NULL); 1180 md_get_uint16le(mdp, &lenlo); /* data len ret. */ 1181 md_get_uint16le(mdp, &doff); /* data offset */ 1182 md_get_uint16le(mdp, &lenhi); 1183 rlen = (lenhi << 16) | lenlo; 1184 md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM); 1185 error = md_get_uint16le(mdp, NULL); /* ByteCount */ 1186 if (error) 1187 goto out; 1188 /* 1189 * Does the data offset indicate padding? 1190 * The current offset is a constant, found 1191 * by counting the md_get_ calls above. 1192 */ 1193 off = SMB_HDRLEN + 3 + (12 * 2); /* =59 */ 1194 if (doff > off) /* pad byte(s)? */ 1195 md_get_mem(mdp, NULL, doff - off, MB_MSYSTEM); 1196 if (rlen == 0) { 1197 *lenp = rlen; 1198 goto out; 1199 } 1200 /* paranoid */ 1201 if (rlen > *lenp) { 1202 SMBSDEBUG("bad server! rlen %d, len %d\n", 1203 rlen, *lenp); 1204 rlen = *lenp; 1205 } 1206 error = md_get_uio(mdp, uiop, rlen); 1207 if (error) 1208 goto out; 1209 1210 /* Success */ 1211 *lenp = rlen; 1212 1213 out: 1214 smb_rq_done(rqp); 1215 return (error); 1216 } 1217 1218 int 1219 smb_smb_writex(smb_fh_t *fhp, uint32_t *lenp, 1220 uio_t *uiop, smb_cred_t *scred, int timo) 1221 { 1222 struct smb_share *ssp = FHTOSS(fhp); 1223 struct smb_rq *rqp; 1224 struct mbchain *mbp; 1225 struct mdchain *mdp; 1226 int error; 1227 uint32_t offlo, offhi, rlen; 1228 uint16_t lenhi, lenlo; 1229 uint8_t wc; 1230 1231 lenhi = (uint16_t)(*lenp >> 16); 1232 lenlo = (uint16_t)*lenp; 1233 offhi = (uint32_t)(uiop->uio_loffset >> 32); 1234 offlo = (uint32_t)uiop->uio_loffset; 1235 1236 error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE_ANDX, scred, &rqp); 1237 if (error) 1238 return (error); 1239 smb_rq_getrequest(rqp, &mbp); 1240 smb_rq_wstart(rqp); 1241 mb_put_uint8(mbp, 0xff); /* no secondary command */ 1242 mb_put_uint8(mbp, 0); /* MBZ */ 1243 mb_put_uint16le(mbp, 0); /* offset to secondary */ 1244 mb_put_uint16le(mbp, fhp->fh_fid1); 1245 mb_put_uint32le(mbp, offlo); /* offset (low part) */ 1246 mb_put_uint32le(mbp, 0); /* MBZ (timeout) */ 1247 mb_put_uint16le(mbp, 0); /* !write-thru */ 1248 mb_put_uint16le(mbp, 0); 1249 mb_put_uint16le(mbp, lenhi); 1250 mb_put_uint16le(mbp, lenlo); 1251 mb_put_uint16le(mbp, 64); /* data offset from header start */ 1252 mb_put_uint32le(mbp, offhi); /* offset (high part) */ 1253 smb_rq_wend(rqp); 1254 smb_rq_bstart(rqp); 1255 1256 mb_put_uint8(mbp, 0); /* pad byte */ 1257 error = mb_put_uio(mbp, uiop, *lenp); 1258 if (error) 1259 goto out; 1260 smb_rq_bend(rqp); 1261 if (timo == 0) 1262 timo = smb_timo_write; 1263 error = smb_rq_simple_timed(rqp, timo); 1264 if (error) 1265 goto out; 1266 smb_rq_getreply(rqp, &mdp); 1267 error = md_get_uint8(mdp, &wc); 1268 if (error) 1269 goto out; 1270 if (wc != 6) { 1271 error = EBADRPC; 1272 goto out; 1273 } 1274 md_get_uint8(mdp, NULL); /* andx cmd */ 1275 md_get_uint8(mdp, NULL); /* reserved */ 1276 md_get_uint16le(mdp, NULL); /* andx offset */ 1277 md_get_uint16le(mdp, &lenlo); /* data len ret. */ 1278 md_get_uint16le(mdp, NULL); /* remaining */ 1279 error = md_get_uint16le(mdp, &lenhi); 1280 if (error) 1281 goto out; 1282 1283 /* Success */ 1284 rlen = (lenhi << 16) | lenlo; 1285 *lenp = rlen; 1286 1287 out: 1288 smb_rq_done(rqp); 1289 return (error); 1290 } 1291 1292 1293 static u_int32_t smbechoes = 0; 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 */ 1299 int 1300 smb_smb_echo(struct smb_vc *vcp, struct smb_cred *scred, int timo) 1301 { 1302 struct smb_rq *rqp; 1303 struct mbchain *mbp; 1304 int error; 1305 1306 error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_ECHO, scred, &rqp); 1307 if (error) 1308 return (error); 1309 mbp = &rqp->sr_rq; 1310 smb_rq_wstart(rqp); 1311 mb_put_uint16le(mbp, 1); /* echo count */ 1312 smb_rq_wend(rqp); 1313 smb_rq_bstart(rqp); 1314 mb_put_uint32le(mbp, atomic_inc_32_nv(&smbechoes)); 1315 smb_rq_bend(rqp); 1316 rqp->sr_flags |= SMBR_NORECONNECT; 1317 error = smb_rq_internal(rqp, timo); 1318 SMBSDEBUG("%d\n", error); 1319 smb_rq_done(rqp); 1320 return (error); 1321 } 1322