smbrdr_read_andx.c revision 12508:edb7861a1533
1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22/* 23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26/* 27 * SMB ReadX functions. 28 */ 29 30#include <strings.h> 31 32#include <smbsrv/libsmbrdr.h> 33#include <smbsrv/netbios.h> 34#include <smbrdr.h> 35 36#define SMBRDR_READX_RSP_OVERHEAD \ 37 (NETBIOS_HDR_SZ + SMB_HEADER_LEN + sizeof (smb_read_andx_rsp_t)) 38#define SMBRDR_READX_RSP_DATA_MAXLEN \ 39 (SMBRDR_REQ_BUFSZ - SMBRDR_READX_RSP_OVERHEAD) 40 41static int smbrdr_decode_readx_rsp(smb_msgbuf_t *, char *, unsigned, 42 smb_read_andx_rsp_t *); 43 44/* 45 * smbrdr_readx 46 * 47 * Send SMB_COM_READ_ANDX request. 48 */ 49int 50smbrdr_readx(int fid, char *in_buf, int in_len) 51{ 52 struct sdb_netuse *netuse; 53 struct sdb_ofile *ofile; 54 smb_read_andx_rsp_t rsp; 55 smbrdr_handle_t srh; 56 smb_msgbuf_t *mb; 57 DWORD status; 58 int rc, max_return; 59 60 if ((ofile = smbrdr_ofile_get(fid)) == NULL) 61 return (-1); 62 63 netuse = ofile->netuse; 64 65 status = smbrdr_request_init(&srh, SMB_COM_READ_ANDX, 66 netuse->session, &netuse->session->logon, netuse); 67 68 if (status != NT_STATUS_SUCCESS) { 69 smb_log(smbrdr_log_hdl, LOG_DEBUG, "smbrdr_readx: %s", 70 xlate_nt_status(status)); 71 smbrdr_ofile_put(ofile); 72 return (-1); 73 } 74 75 mb = &(srh.srh_mbuf); 76 77 max_return = (in_len > SMBRDR_READX_RSP_DATA_MAXLEN) ? 78 SMBRDR_READX_RSP_DATA_MAXLEN : in_len; 79 80 rc = smb_msgbuf_encode(mb, "bbbwwlwwlwlw", 81 12, /* Count of parameter words */ 82 0xFF, /* Secondary (X) command; 0xFF = none */ 83 0, /* Reserved (must be 0) */ 84 0, /* Offset to next command WordCount */ 85 ofile->fid, /* File handle */ 86 0, /* Offset in file to begin read */ 87 max_return, /* Max number of bytes to return */ 88 /* Reserved for obsolescent requests [0 = non-blocking read] */ 89 max_return, 90 /* 91 * High 16 bits of MaxCount if CAP_LARGE_READX; 92 * else MUST BE ZERO 93 */ 94 0, 95 max_return, /* Reserved for obsolescent requests */ 96 /* Upper 32 bits of offset (only if WordCount is 12) */ 97 0, 98 0); /* Count of data bytes = 0 */ 99 100 if (rc < 0) { 101 smb_log(smbrdr_log_hdl, LOG_DEBUG, "smbrdr_readx: prep failed"); 102 smbrdr_handle_free(&srh); 103 smbrdr_ofile_put(ofile); 104 return (rc); 105 } 106 107 smbrdr_lock_transport(); 108 109 status = smbrdr_send(&srh); 110 if (status != NT_STATUS_SUCCESS) { 111 smbrdr_unlock_transport(); 112 smbrdr_handle_free(&srh); 113 smbrdr_ofile_put(ofile); 114 smb_log(smbrdr_log_hdl, LOG_DEBUG, "smbrdr_readx: send failed"); 115 return (-1); 116 } 117 118 status = smbrdr_rcv(&srh, 1); 119 120 if (status != NT_STATUS_SUCCESS) { 121 smb_log(smbrdr_log_hdl, LOG_DEBUG, 122 "smbrdr_readx: nb_rcv failed"); 123 smbrdr_unlock_transport(); 124 smbrdr_handle_free(&srh); 125 smbrdr_ofile_put(ofile); 126 return (-1); 127 } 128 129 rc = smbrdr_decode_readx_rsp(mb, in_buf, in_len, &rsp); 130 131 if (rc < 0) { 132 smb_log(smbrdr_log_hdl, LOG_DEBUG, 133 "smbrdr_readx: decode failed"); 134 smbrdr_unlock_transport(); 135 smbrdr_handle_free(&srh); 136 smbrdr_ofile_put(ofile); 137 return (-1); 138 } 139 140 smbrdr_unlock_transport(); 141 smbrdr_handle_free(&srh); 142 smbrdr_ofile_put(ofile); 143 144 return ((rc < 0) ? rc : rsp.DataLength); 145} 146 147/* 148 * smbrdr_decode_readx_rsp 149 * 150 * Decode the response from the SMB_COM_READ_ANDX request. The payload 151 * of the response is appended to the end of SmbTransact response data 152 * in the RPC receive buffer. 153 * 154 * Return -1 on error, 0 upon success. 155 */ 156static int 157smbrdr_decode_readx_rsp(smb_msgbuf_t *mb, 158 char *in, 159 unsigned in_len, 160 smb_read_andx_rsp_t *rsp) 161{ 162 int rc; 163 164 rc = smb_msgbuf_decode(mb, "bbbwwwwwwlwwww", 165 &rsp->WordCount, 166 &rsp->AndXCmd, 167 &rsp->AndXReserved, 168 &rsp->AndXOffset, 169 &rsp->Remaining, 170 &rsp->DataCompactionMode, 171 &rsp->Reserved, 172 &rsp->DataLength, 173 &rsp->DataOffset, 174 &rsp->DataLengthHigh, 175 &rsp->Reserved2[0], 176 &rsp->Reserved2[1], 177 &rsp->Reserved2[2], 178 &rsp->ByteCount); 179 180 if (rc <= 0) 181 return (-1); 182 183 if (rsp->DataLength > in_len) 184 return (-1); 185 186 bcopy(mb->base + rsp->DataOffset, in, rsp->DataLength); 187 188 return (0); 189} 190