1*5331Samw /* 2*5331Samw * CDDL HEADER START 3*5331Samw * 4*5331Samw * The contents of this file are subject to the terms of the 5*5331Samw * Common Development and Distribution License (the "License"). 6*5331Samw * You may not use this file except in compliance with the License. 7*5331Samw * 8*5331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*5331Samw * or http://www.opensolaris.org/os/licensing. 10*5331Samw * See the License for the specific language governing permissions 11*5331Samw * and limitations under the License. 12*5331Samw * 13*5331Samw * When distributing Covered Code, include this CDDL HEADER in each 14*5331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*5331Samw * If applicable, add the following below this CDDL HEADER, with the 16*5331Samw * fields enclosed by brackets "[]" replaced with your own identifying 17*5331Samw * information: Portions Copyright [yyyy] [name of copyright owner] 18*5331Samw * 19*5331Samw * CDDL HEADER END 20*5331Samw */ 21*5331Samw /* 22*5331Samw * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23*5331Samw * Use is subject to license terms. 24*5331Samw */ 25*5331Samw 26*5331Samw #pragma ident "%Z%%M% %I% %E% SMI" 27*5331Samw 28*5331Samw #include <sys/syslog.h> 29*5331Samw #include <smbsrv/smb_incl.h> 30*5331Samw #include <smbsrv/smb_fsops.h> 31*5331Samw 32*5331Samw 33*5331Samw typedef struct smb_read_param { 34*5331Samw uint64_t r_offset; 35*5331Samw uint16_t r_count; 36*5331Samw uint16_t r_mincnt; 37*5331Samw } smb_read_param_t; 38*5331Samw 39*5331Samw 40*5331Samw int smb_common_read(struct smb_request *sr, smb_read_param_t *param); 41*5331Samw 42*5331Samw 43*5331Samw /* 44*5331Samw * Read bytes from a file or named pipe (SMB Core). 45*5331Samw * 46*5331Samw * The requested count specifies the number of bytes desired. Offset 47*5331Samw * is limited to 32 bits, so this client request is inappropriate for 48*5331Samw * files with 64 bit offsets. 49*5331Samw * 50*5331Samw * On return, count is the number of bytes actually being returned, which 51*5331Samw * may be less than the count requested only if a read specifies bytes 52*5331Samw * beyond the current file size. In this case only the bytes that exist 53*5331Samw * are returned. A read completely beyond the end of file results in a 54*5331Samw * response of length zero. This is the only circumstance when a zero 55*5331Samw * length response is generated. A count returned which is less than the 56*5331Samw * count requested is the end of file indicator. 57*5331Samw */ 58*5331Samw int 59*5331Samw smb_com_read(struct smb_request *sr) 60*5331Samw { 61*5331Samw smb_read_param_t param; 62*5331Samw uint32_t off_low; 63*5331Samw uint16_t remcnt; 64*5331Samw int rc; 65*5331Samw 66*5331Samw rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid, 67*5331Samw ¶m.r_count, &off_low, &remcnt); 68*5331Samw if (rc != 0) { 69*5331Samw smbsr_decode_error(sr); 70*5331Samw /* NOTREACHED */ 71*5331Samw } 72*5331Samw 73*5331Samw param.r_offset = (uint64_t)off_low; 74*5331Samw param.r_mincnt = 0; 75*5331Samw 76*5331Samw sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); 77*5331Samw if (sr->fid_ofile == NULL) { 78*5331Samw smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, 79*5331Samw ERRDOS, ERRbadfid); 80*5331Samw /* NOTREACHED */ 81*5331Samw } 82*5331Samw 83*5331Samw if ((rc = smb_common_read(sr, ¶m)) != 0) { 84*5331Samw smbsr_raise_errno(sr, rc); 85*5331Samw /* NOTREACHED */ 86*5331Samw } 87*5331Samw 88*5331Samw smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC", 89*5331Samw 5, param.r_count, VAR_BCC, 0x01, param.r_count, &sr->raw_data); 90*5331Samw 91*5331Samw return (SDRC_NORMAL_REPLY); 92*5331Samw } 93*5331Samw 94*5331Samw /* 95*5331Samw * Lock and read bytes from a file (SMB Core Plus). The SmbLockAndRead/ 96*5331Samw * SmbLockAndWrite sub-dialect is only valid on disk files: reject any 97*5331Samw * attempt to use it on non-disk shares. 98*5331Samw * 99*5331Samw * The requested count specifies the number of bytes desired. Offset 100*5331Samw * specifies the offset in the file of the first byte to be locked then 101*5331Samw * read. Note that offset is limited to 32 bits, so this client request 102*5331Samw * is inappropriate for files with 64 bit offsets. 103*5331Samw * 104*5331Samw * As with SMB_LOCK_BYTE_RANGE request, if the lock cannot be granted 105*5331Samw * immediately an error should be returned to the client. If an error 106*5331Samw * occurs on the lock, the bytes should not be read. 107*5331Samw * 108*5331Samw * On return, count is the number of bytes actually being returned, which 109*5331Samw * may be less than the count requested only if a read specifies bytes 110*5331Samw * beyond the current file size. In this case only the bytes that exist 111*5331Samw * are returned. A read completely beyond the end of file results in a 112*5331Samw * response of length zero. This is the only circumstance when a zero 113*5331Samw * length response is generated. A count returned which is less than the 114*5331Samw * count requested is the end of file indicator. 115*5331Samw */ 116*5331Samw int 117*5331Samw smb_com_lock_and_read(struct smb_request *sr) 118*5331Samw { 119*5331Samw smb_read_param_t param; 120*5331Samw uint16_t remcnt; 121*5331Samw uint32_t off_low; 122*5331Samw DWORD result; 123*5331Samw int rc; 124*5331Samw 125*5331Samw if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) { 126*5331Samw smbsr_raise_error(sr, ERRDOS, ERRnoaccess); 127*5331Samw /* NOTREACHED */ 128*5331Samw } 129*5331Samw 130*5331Samw rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid, 131*5331Samw ¶m.r_count, &off_low, &remcnt); 132*5331Samw if (rc != 0) { 133*5331Samw smbsr_decode_error(sr); 134*5331Samw /* NOTREACHED */ 135*5331Samw } 136*5331Samw 137*5331Samw param.r_offset = (uint64_t)off_low; 138*5331Samw param.r_mincnt = 0; 139*5331Samw 140*5331Samw sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); 141*5331Samw if (sr->fid_ofile == NULL) { 142*5331Samw smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, 143*5331Samw ERRDOS, ERRbadfid); 144*5331Samw /* NOTREACHED */ 145*5331Samw } 146*5331Samw 147*5331Samw result = smb_lock_range(sr, sr->fid_ofile, param.r_offset, 148*5331Samw (uint64_t)param.r_count, 0xffffffff, SMB_LOCK_TYPE_READWRITE); 149*5331Samw if (result != NT_STATUS_SUCCESS) { 150*5331Samw smb_lock_range_raise_error(sr, result); 151*5331Samw } 152*5331Samw 153*5331Samw if ((rc = smb_common_read(sr, ¶m)) != 0) { 154*5331Samw smbsr_raise_errno(sr, rc); 155*5331Samw /* NOTREACHED */ 156*5331Samw } 157*5331Samw 158*5331Samw smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC", 159*5331Samw 5, param.r_count, VAR_BCC, 0x1, param.r_count, &sr->raw_data); 160*5331Samw 161*5331Samw return (SDRC_NORMAL_REPLY); 162*5331Samw } 163*5331Samw 164*5331Samw /* 165*5331Samw * The SMB_COM_READ_RAW protocol is a negotiated option introduced in 166*5331Samw * SMB Core Plus to maximize performance when reading a large block 167*5331Samw * of data from a server. This request was extended in LM 0.12 to 168*5331Samw * support 64-bit offsets; the server can indicate support by setting 169*5331Samw * CAP_LARGE_FILES in the negotiated capabilities. 170*5331Samw * 171*5331Samw * The client must guarantee that there is (and will be) no other request 172*5331Samw * to the server for the duration of the SMB_COM_READ_RAW, since the 173*5331Samw * server response has no header or trailer. To help ensure that there 174*5331Samw * are no interruptions, we block all I/O for the session during read raw. 175*5331Samw * 176*5331Samw * If this is the first SMB request received since we sent an oplock break 177*5331Samw * to this client, we don't know if it's safe to send the raw data because 178*5331Samw * the requests may have crossed on the wire and the client may have 179*5331Samw * interpreted the oplock break as part of the raw data. To avoid problems, 180*5331Samw * we send a zero length session packet, which will force the client to 181*5331Samw * retry the read. 182*5331Samw * 183*5331Samw * Read errors are handled by sending a zero length response. 184*5331Samw */ 185*5331Samw int 186*5331Samw smb_com_read_raw(struct smb_request *sr) 187*5331Samw { 188*5331Samw smb_read_param_t param; 189*5331Samw smb_node_t *node; 190*5331Samw uint32_t off_low; 191*5331Samw uint32_t off_high; 192*5331Samw uint32_t timeout; 193*5331Samw int rc; 194*5331Samw 195*5331Samw switch (sr->session->s_state) { 196*5331Samw case SMB_SESSION_STATE_NEGOTIATED: 197*5331Samw if (sr->smb_wct == 8) { 198*5331Samw rc = smbsr_decode_vwv(sr, "wlwwl2.", &sr->smb_fid, 199*5331Samw &off_low, ¶m.r_count, ¶m.r_mincnt, 200*5331Samw &timeout); 201*5331Samw param.r_offset = (uint64_t)off_low; 202*5331Samw } else { 203*5331Samw rc = smbsr_decode_vwv(sr, "wlwwl2.l", &sr->smb_fid, 204*5331Samw &off_low, ¶m.r_count, ¶m.r_mincnt, &timeout, 205*5331Samw &off_high); 206*5331Samw param.r_offset = ((uint64_t)off_high << 32) | off_low; 207*5331Samw } 208*5331Samw 209*5331Samw if (rc != 0) { 210*5331Samw smbsr_decode_error(sr); 211*5331Samw /* NOTREACHED */ 212*5331Samw } 213*5331Samw 214*5331Samw sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, 215*5331Samw sr->smb_fid); 216*5331Samw if (sr->fid_ofile == NULL) { 217*5331Samw smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, 218*5331Samw ERRDOS, ERRbadfid); 219*5331Samw /* NOTREACHED */ 220*5331Samw } 221*5331Samw 222*5331Samw rc = smb_common_read(sr, ¶m); 223*5331Samw /* 224*5331Samw * XXX Do we need to handle errors here? What if we have an 225*5331Samw * access error (either permissions or range lock violations? 226*5331Samw */ 227*5331Samw if (STYPE_ISDSK(sr->tid_tree->t_res_type)) { 228*5331Samw node = sr->fid_ofile->f_node; 229*5331Samw if (node->n_oplock.op_flags & OPLOCK_FLAG_BREAKING) { 230*5331Samw rc = EAGAIN; 231*5331Samw } 232*5331Samw } 233*5331Samw 234*5331Samw if (rc != 0) { 235*5331Samw (void) smb_session_send(sr->session, 0, NULL); 236*5331Samw m_freem(sr->raw_data.chain); 237*5331Samw sr->raw_data.chain = 0; 238*5331Samw } else { 239*5331Samw (void) smb_session_send(sr->session, 0, &sr->raw_data); 240*5331Samw } 241*5331Samw return (SDRC_NO_REPLY); 242*5331Samw 243*5331Samw case SMB_SESSION_STATE_OPLOCK_BREAKING: 244*5331Samw (void) smb_session_send(sr->session, 0, NULL); 245*5331Samw sr->session->s_state = SMB_SESSION_STATE_NEGOTIATED; 246*5331Samw return (SDRC_NO_REPLY); 247*5331Samw 248*5331Samw case SMB_SESSION_STATE_WRITE_RAW_ACTIVE: 249*5331Samw ASSERT(0); 250*5331Samw return (SDRC_DROP_VC); 251*5331Samw 252*5331Samw case SMB_SESSION_STATE_TERMINATED: 253*5331Samw ASSERT(0); 254*5331Samw return (SDRC_NO_REPLY); 255*5331Samw 256*5331Samw case SMB_SESSION_STATE_DISCONNECTED: 257*5331Samw return (SDRC_NO_REPLY); 258*5331Samw 259*5331Samw case SMB_SESSION_STATE_CONNECTED: 260*5331Samw case SMB_SESSION_STATE_ESTABLISHED: 261*5331Samw default: 262*5331Samw ASSERT(0); 263*5331Samw return (SDRC_DROP_VC); 264*5331Samw } 265*5331Samw } 266*5331Samw 267*5331Samw /* 268*5331Samw * Read bytes from a file (SMB Core). This request was extended in 269*5331Samw * LM 0.12 to support 64-bit offsets, indicated by sending a wct of 270*5331Samw * 12 and including additional offset information. 271*5331Samw */ 272*5331Samw int 273*5331Samw smb_com_read_andx(struct smb_request *sr) 274*5331Samw { 275*5331Samw smb_read_param_t param; 276*5331Samw uint32_t off_low; 277*5331Samw uint32_t off_high; 278*5331Samw uint16_t remcnt; 279*5331Samw uint16_t offset2; 280*5331Samw uint8_t secondary; 281*5331Samw int rc; 282*5331Samw 283*5331Samw if (sr->smb_wct == 12) { 284*5331Samw rc = smbsr_decode_vwv(sr, "b3.wlw6.wl", &secondary, 285*5331Samw &sr->smb_fid, &off_low, ¶m.r_count, &remcnt, &off_high); 286*5331Samw 287*5331Samw param.r_offset = ((uint64_t)off_high << 32) | off_low; 288*5331Samw } else { 289*5331Samw rc = smbsr_decode_vwv(sr, "b3.wlw6.w", &secondary, 290*5331Samw &sr->smb_fid, &off_low, ¶m.r_count, &remcnt); 291*5331Samw 292*5331Samw param.r_offset = (uint64_t)off_low; 293*5331Samw } 294*5331Samw 295*5331Samw if (rc != 0) { 296*5331Samw smbsr_decode_error(sr); 297*5331Samw /* NOTREACHED */ 298*5331Samw } 299*5331Samw 300*5331Samw param.r_mincnt = 0; 301*5331Samw 302*5331Samw sr->fid_ofile = smb_ofile_lookup_by_fid(sr->tid_tree, sr->smb_fid); 303*5331Samw if (sr->fid_ofile == NULL) { 304*5331Samw smbsr_raise_cifs_error(sr, NT_STATUS_INVALID_HANDLE, 305*5331Samw ERRDOS, ERRbadfid); 306*5331Samw /* NOTREACHED */ 307*5331Samw } 308*5331Samw 309*5331Samw if ((rc = smb_common_read(sr, ¶m)) != 0) { 310*5331Samw smbsr_raise_errno(sr, rc); 311*5331Samw /* NOTREACHED */ 312*5331Samw } 313*5331Samw 314*5331Samw /* 315*5331Samw * Ensure that the next response offset is zero 316*5331Samw * if there is no secondary command. 317*5331Samw */ 318*5331Samw offset2 = (secondary == 0xFF) ? 0 : param.r_count + 59; 319*5331Samw 320*5331Samw /* 321*5331Samw * The STYPE_IPC response format is different. 322*5331Samw * The unknown value (2) may be to indicate that it 323*5331Samw * is a follow-up to an earlier RPC transaction. 324*5331Samw */ 325*5331Samw if (STYPE_ISIPC(sr->tid_tree->t_res_type)) { 326*5331Samw smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.ww10.wbC", 327*5331Samw 12, /* wct */ 328*5331Samw secondary, /* Secondary andx command */ 329*5331Samw offset2, /* offset to next */ 330*5331Samw 0, /* must be 0 */ 331*5331Samw param.r_count, /* data byte count */ 332*5331Samw 60, /* Offset from start to data */ 333*5331Samw VAR_BCC, /* BCC marker */ 334*5331Samw 0x02, /* unknown */ 335*5331Samw &sr->raw_data); 336*5331Samw } else { 337*5331Samw smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.ww10.wC", 338*5331Samw 12, /* wct */ 339*5331Samw secondary, /* Secondary andx command */ 340*5331Samw offset2, /* offset to next */ 341*5331Samw -1, /* must be -1 */ 342*5331Samw param.r_count, /* data byte count */ 343*5331Samw 59, /* Offset from start to data */ 344*5331Samw VAR_BCC, /* BCC marker */ 345*5331Samw &sr->raw_data); 346*5331Samw } 347*5331Samw 348*5331Samw return (SDRC_NORMAL_REPLY); 349*5331Samw } 350*5331Samw 351*5331Samw /* 352*5331Samw * Common function for reading files or IPC/MSRPC named pipes. All 353*5331Samw * protocol read functions should lookup the fid before calling this 354*5331Samw * function. We can't move the fid lookup here because lock-and-read 355*5331Samw * requires the fid to do locking before attempting the read. 356*5331Samw * 357*5331Samw * Returns errno values. 358*5331Samw */ 359*5331Samw int 360*5331Samw smb_common_read(struct smb_request *sr, smb_read_param_t *param) 361*5331Samw { 362*5331Samw smb_ofile_t *ofile = sr->fid_ofile; 363*5331Samw smb_node_t *node; 364*5331Samw struct vardata_block *vdb; 365*5331Samw struct mbuf *top; 366*5331Samw int rc; 367*5331Samw 368*5331Samw vdb = kmem_alloc(sizeof (struct vardata_block), KM_SLEEP); 369*5331Samw vdb->tag = 0; 370*5331Samw vdb->uio.uio_iov = &vdb->iovec[0]; 371*5331Samw vdb->uio.uio_iovcnt = MAX_IOVEC; 372*5331Samw vdb->uio.uio_resid = param->r_count; 373*5331Samw vdb->uio.uio_offset = param->r_offset; 374*5331Samw vdb->uio.uio_segflg = UIO_SYSSPACE; 375*5331Samw 376*5331Samw switch (sr->tid_tree->t_res_type & STYPE_MASK) { 377*5331Samw case STYPE_DISKTREE: 378*5331Samw node = ofile->f_node; 379*5331Samw 380*5331Samw if (node->attr.sa_vattr.va_type != VDIR) { 381*5331Samw rc = smb_lock_range_access(sr, node, param->r_offset, 382*5331Samw param->r_count, FILE_READ_DATA); 383*5331Samw if (rc != NT_STATUS_SUCCESS) { 384*5331Samw rc = ERANGE; 385*5331Samw break; 386*5331Samw } 387*5331Samw } 388*5331Samw 389*5331Samw (void) smb_sync_fsattr(sr, sr->user_cr, node); 390*5331Samw 391*5331Samw sr->raw_data.max_bytes = vdb->uio.uio_resid; 392*5331Samw top = smb_mbuf_allocate(&vdb->uio); 393*5331Samw 394*5331Samw rc = smb_fsop_read(sr, sr->user_cr, node, &vdb->uio, 395*5331Samw &node->attr); 396*5331Samw 397*5331Samw sr->raw_data.max_bytes -= vdb->uio.uio_resid; 398*5331Samw smb_mbuf_trim(top, sr->raw_data.max_bytes); 399*5331Samw MBC_ATTACH_MBUF(&sr->raw_data, top); 400*5331Samw break; 401*5331Samw 402*5331Samw case STYPE_IPC: 403*5331Samw rc = smb_rpc_read(sr, &vdb->uio); 404*5331Samw break; 405*5331Samw 406*5331Samw default: 407*5331Samw rc = EACCES; 408*5331Samw break; 409*5331Samw } 410*5331Samw 411*5331Samw param->r_count -= vdb->uio.uio_resid; 412*5331Samw kmem_free(vdb, sizeof (struct vardata_block)); 413*5331Samw 414*5331Samw if (rc != 0) 415*5331Samw return (rc); 416*5331Samw 417*5331Samw if (param->r_mincnt != 0 && param->r_count < param->r_mincnt) { 418*5331Samw /* 419*5331Samw * mincnt is only used by read-raw and is typically 420*5331Samw * zero. If mincnt is greater than zero and the 421*5331Samw * number of bytes read is less than mincnt, tell 422*5331Samw * the client that we read nothing. 423*5331Samw */ 424*5331Samw param->r_count = 0; 425*5331Samw } 426*5331Samw 427*5331Samw param->r_offset += param->r_count; 428*5331Samw mutex_enter(&sr->fid_ofile->f_mutex); 429*5331Samw ofile->f_seek_pos = param->r_offset; 430*5331Samw mutex_exit(&sr->fid_ofile->f_mutex); 431*5331Samw return (rc); 432*5331Samw } 433*5331Samw 434*5331Samw /* 435*5331Samw * The Read Block Multiplexed protocol is used to maximize performance 436*5331Samw * when reading a large block of data from server to client while still 437*5331Samw * allowing other operations to take place between the client and server 438*5331Samw * in parallel. 439*5331Samw * 440*5331Samw * The mpx sub protocol is not supported because we support only 441*5331Samw * connection oriented transports and NT supports SMB_COM_READ_MPX 442*5331Samw * only over connectionless transports. 443*5331Samw */ 444*5331Samw /*ARGSUSED*/ 445*5331Samw int 446*5331Samw smb_com_read_mpx(struct smb_request *sr) 447*5331Samw { 448*5331Samw return (SDRC_UNIMPLEMENTED); 449*5331Samw } 450*5331Samw 451*5331Samw /*ARGSUSED*/ 452*5331Samw int 453*5331Samw smb_com_read_mpx_secondary(struct smb_request *sr) 454*5331Samw { 455*5331Samw return (SDRC_UNIMPLEMENTED); 456*5331Samw } 457