2010-08-12 14:00:15 +04:00
/*
Unix SMB / CIFS implementation .
Copyright ( C ) Stefan Metzmacher 2010
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
# include "system/network.h"
2011-04-28 19:38:09 +04:00
# include "../lib/util/tevent_ntstatus.h"
2010-08-12 14:00:15 +04:00
# include "../lib/tsocket/tsocket.h"
# include "../lib/tsocket/tsocket_internal.h"
2013-09-13 17:50:10 +04:00
# include "smb_common.h"
# include "smbXcli_base.h"
# include "tstream_smbXcli_np.h"
2013-11-29 14:58:18 +04:00
# include "libcli/security/security.h"
2010-08-12 14:00:15 +04:00
2013-11-29 15:24:50 +04:00
static const struct tstream_context_ops tstream_smbXcli_np_ops ;
2010-08-12 14:00:15 +04:00
/*
2011-06-07 20:27:41 +04:00
* Windows uses 4280 ( the max xmit / recv size negotiated on DCERPC ) .
* This is fits into the max_xmit negotiated at the SMB layer .
*
* On the sending side they may use SMBtranss if the request does not
* fit into a single SMBtrans call .
*
* Windows uses 1024 as max data size of a SMBtrans request and then
* possibly reads the rest of the DCERPC fragment ( up to 3256 bytes )
* via a SMBreadX .
*
* For now we just ask for the full 4280 bytes ( max data size ) in the SMBtrans
* request to get the whole fragment at once ( like samba 3.5 . x and below did .
*
* It is important that we use do SMBwriteX with the size of a full fragment ,
* otherwise we may get NT_STATUS_PIPE_BUSY on the SMBtrans request
* from NT4 servers . ( See bug # 8195 )
2010-08-12 14:00:15 +04:00
*/
2013-11-29 15:18:29 +04:00
# define TSTREAM_SMBXCLI_NP_MAX_BUF_SIZE 4280
2010-08-12 14:00:15 +04:00
2013-11-29 15:18:29 +04:00
# define TSTREAM_SMBXCLI_NP_DESIRED_ACCESS ( \
2013-11-29 14:58:18 +04:00
SEC_STD_READ_CONTROL | \
SEC_FILE_READ_DATA | \
SEC_FILE_WRITE_DATA | \
SEC_FILE_APPEND_DATA | \
SEC_FILE_READ_EA | \
SEC_FILE_WRITE_EA | \
SEC_FILE_READ_ATTRIBUTE | \
SEC_FILE_WRITE_ATTRIBUTE | \
0 )
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_ref ;
2013-09-20 03:11:40 +04:00
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np {
struct tstream_smbXcli_np_ref * ref ;
2013-09-13 14:55:34 +04:00
struct smbXcli_conn * conn ;
struct smbXcli_session * session ;
struct smbXcli_tcon * tcon ;
uint16_t pid ;
unsigned int timeout ;
2010-08-12 14:00:15 +04:00
const char * npipe ;
2012-04-25 22:18:22 +04:00
bool is_smb1 ;
2010-08-12 14:00:15 +04:00
uint16_t fnum ;
2012-04-25 22:18:22 +04:00
uint64_t fid_persistent ;
uint64_t fid_volatile ;
2010-08-12 14:00:15 +04:00
2010-09-04 13:01:55 +04:00
struct {
bool active ;
2010-12-21 17:43:44 +03:00
struct tevent_req * read_req ;
2010-09-04 13:01:55 +04:00
struct tevent_req * write_req ;
uint16_t setup [ 2 ] ;
} trans ;
2010-08-12 14:00:15 +04:00
struct {
off_t ofs ;
size_t left ;
2011-06-07 20:45:54 +04:00
uint8_t * buf ;
2010-08-12 14:00:15 +04:00
} read , write ;
} ;
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_ref {
struct tstream_smbXcli_np * cli_nps ;
2013-09-20 03:11:40 +04:00
} ;
2013-11-29 15:24:50 +04:00
static int tstream_smbXcli_np_destructor ( struct tstream_smbXcli_np * cli_nps )
2010-08-12 14:00:15 +04:00
{
NTSTATUS status ;
2013-09-20 03:11:40 +04:00
if ( cli_nps - > ref ! = NULL ) {
cli_nps - > ref - > cli_nps = NULL ;
TALLOC_FREE ( cli_nps - > ref ) ;
}
2013-09-13 14:55:34 +04:00
if ( ! smbXcli_conn_is_connected ( cli_nps - > conn ) ) {
2010-08-12 14:00:15 +04:00
return 0 ;
}
/*
* TODO : do not use a sync call with a destructor ! ! !
*
* This only happens , if a caller does talloc_free ( ) ,
* while the everything was still ok .
*
* If we get an unexpected failure within a normal
* operation , we already do an async cli_close_send ( ) / _recv ( ) .
*
* Once we ' ve fixed all callers to call
* tstream_disconnect_send ( ) / _recv ( ) , this will
* never be called .
*/
2012-04-25 22:18:22 +04:00
if ( cli_nps - > is_smb1 ) {
2013-09-13 14:55:34 +04:00
status = smb1cli_close ( cli_nps - > conn ,
cli_nps - > timeout ,
cli_nps - > pid ,
cli_nps - > tcon ,
cli_nps - > session ,
2013-09-12 12:10:06 +04:00
cli_nps - > fnum , UINT32_MAX ) ;
2012-04-25 22:18:22 +04:00
} else {
2013-09-13 14:55:34 +04:00
status = smb2cli_close ( cli_nps - > conn ,
cli_nps - > timeout ,
cli_nps - > session ,
cli_nps - > tcon ,
2012-07-24 00:32:49 +04:00
0 , /* flags */
2012-04-25 22:18:22 +04:00
cli_nps - > fid_persistent ,
cli_nps - > fid_volatile ) ;
}
2010-08-12 14:00:15 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2013-11-29 15:24:50 +04:00
DEBUG ( 1 , ( " tstream_smbXcli_np_destructor: cli_close "
2010-08-12 14:00:15 +04:00
" failed on pipe %s. Error was %s \n " ,
cli_nps - > npipe , nt_errstr ( status ) ) ) ;
}
/*
* We can ' t do much on failure
*/
return 0 ;
2011-02-09 21:43:56 +03:00
}
2010-08-12 14:00:15 +04:00
2013-11-29 15:24:50 +04:00
static int tstream_smbXcli_np_ref_destructor ( struct tstream_smbXcli_np_ref * ref )
2013-09-20 03:11:40 +04:00
{
if ( ref - > cli_nps = = NULL ) {
return 0 ;
}
ref - > cli_nps - > conn = NULL ;
ref - > cli_nps - > session = NULL ;
ref - > cli_nps - > tcon = NULL ;
ref - > cli_nps - > ref = NULL ;
return 0 ;
} ;
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_open_state {
2013-09-13 14:55:34 +04:00
struct smbXcli_conn * conn ;
struct smbXcli_session * session ;
struct smbXcli_tcon * tcon ;
uint16_t pid ;
unsigned int timeout ;
2012-04-25 22:18:22 +04:00
bool is_smb1 ;
2010-08-12 14:00:15 +04:00
uint16_t fnum ;
2012-04-25 22:18:22 +04:00
uint64_t fid_persistent ;
uint64_t fid_volatile ;
2010-08-12 14:00:15 +04:00
const char * npipe ;
} ;
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_open_done ( struct tevent_req * subreq ) ;
2010-08-12 14:00:15 +04:00
2013-11-29 15:24:50 +04:00
struct tevent_req * tstream_smbXcli_np_open_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct smbXcli_conn * conn ,
struct smbXcli_session * session ,
struct smbXcli_tcon * tcon ,
uint16_t pid ,
unsigned int timeout ,
const char * npipe )
2010-08-12 14:00:15 +04:00
{
struct tevent_req * req ;
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_open_state * state ;
2010-08-12 14:00:15 +04:00
struct tevent_req * subreq ;
req = tevent_req_create ( mem_ctx , & state ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_open_state ) ;
2010-08-12 14:00:15 +04:00
if ( ! req ) {
return NULL ;
}
2013-09-13 14:55:34 +04:00
state - > conn = conn ;
state - > tcon = tcon ;
state - > session = session ;
state - > pid = pid ;
state - > timeout = timeout ;
2010-08-12 14:00:15 +04:00
state - > npipe = talloc_strdup ( state , npipe ) ;
if ( tevent_req_nomem ( state - > npipe , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2013-09-13 14:55:34 +04:00
if ( smbXcli_conn_protocol ( conn ) < PROTOCOL_SMB2_02 ) {
2012-04-25 22:18:22 +04:00
state - > is_smb1 = true ;
}
if ( state - > is_smb1 ) {
2012-05-28 17:29:17 +04:00
const char * smb1_npipe ;
/*
* Windows and newer Samba versions allow
* the pipe name without leading backslash ,
* but we should better behave like windows clients
*/
smb1_npipe = talloc_asprintf ( state , " \\ %s " , state - > npipe ) ;
if ( tevent_req_nomem ( smb1_npipe , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2013-09-13 14:55:34 +04:00
subreq = smb1cli_ntcreatex_send ( state , ev , state - > conn ,
state - > timeout ,
state - > pid ,
state - > tcon ,
state - > session ,
2013-09-11 17:54:31 +04:00
smb1_npipe ,
0 , /* CreatFlags */
0 , /* RootDirectoryFid */
2013-11-29 15:18:29 +04:00
TSTREAM_SMBXCLI_NP_DESIRED_ACCESS ,
2013-09-11 17:54:31 +04:00
0 , /* AllocationSize */
0 , /* FileAttributes */
FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_OPEN , /* CreateDisposition */
0 , /* CreateOptions */
2 , /* NTCREATEX_IMPERSONATION_IMPERSONATION */
0 ) ; /* SecurityFlags */
2012-04-25 22:18:22 +04:00
} else {
2013-09-13 14:55:34 +04:00
subreq = smb2cli_create_send ( state , ev , state - > conn ,
state - > timeout , state - > session ,
state - > tcon ,
2012-04-25 22:18:22 +04:00
npipe ,
SMB2_OPLOCK_LEVEL_NONE ,
SMB2_IMPERSONATION_IMPERSONATION ,
2013-11-29 15:18:29 +04:00
TSTREAM_SMBXCLI_NP_DESIRED_ACCESS ,
2012-04-25 22:18:22 +04:00
0 , /* file_attributes */
FILE_SHARE_READ | FILE_SHARE_WRITE ,
FILE_OPEN ,
0 , /* create_options */
NULL ) ; /* blobs */
}
2010-08-12 14:00:15 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2013-11-29 15:24:50 +04:00
tevent_req_set_callback ( subreq , tstream_smbXcli_np_open_done , req ) ;
2010-08-12 14:00:15 +04:00
return req ;
}
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_open_done ( struct tevent_req * subreq )
2010-08-12 14:00:15 +04:00
{
struct tevent_req * req =
tevent_req_callback_data ( subreq , struct tevent_req ) ;
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_open_state * state =
tevent_req_data ( req , struct tstream_smbXcli_np_open_state ) ;
2010-08-12 14:00:15 +04:00
NTSTATUS status ;
2012-04-25 22:18:22 +04:00
if ( state - > is_smb1 ) {
2013-09-11 17:54:31 +04:00
status = smb1cli_ntcreatex_recv ( subreq , & state - > fnum ) ;
2012-04-25 22:18:22 +04:00
} else {
status = smb2cli_create_recv ( subreq ,
& state - > fid_persistent ,
2013-08-08 02:01:50 +04:00
& state - > fid_volatile ,
NULL ) ;
2012-04-25 22:18:22 +04:00
}
2010-08-12 14:00:15 +04:00
TALLOC_FREE ( subreq ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
tevent_req_nterror ( req , status ) ;
return ;
}
tevent_req_done ( req ) ;
}
2013-11-29 15:24:50 +04:00
NTSTATUS _tstream_smbXcli_np_open_recv ( struct tevent_req * req ,
TALLOC_CTX * mem_ctx ,
struct tstream_context * * _stream ,
const char * location )
2010-08-12 14:00:15 +04:00
{
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_open_state * state =
tevent_req_data ( req , struct tstream_smbXcli_np_open_state ) ;
2010-08-12 14:00:15 +04:00
struct tstream_context * stream ;
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np * cli_nps ;
2010-08-12 14:00:15 +04:00
NTSTATUS status ;
if ( tevent_req_is_nterror ( req , & status ) ) {
tevent_req_received ( req ) ;
return status ;
}
stream = tstream_context_create ( mem_ctx ,
2013-11-29 15:24:50 +04:00
& tstream_smbXcli_np_ops ,
2010-08-12 14:00:15 +04:00
& cli_nps ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np ,
2010-08-12 14:00:15 +04:00
location ) ;
if ( ! stream ) {
tevent_req_received ( req ) ;
return NT_STATUS_NO_MEMORY ;
}
ZERO_STRUCTP ( cli_nps ) ;
2013-11-29 15:24:50 +04:00
cli_nps - > ref = talloc_zero ( state - > conn , struct tstream_smbXcli_np_ref ) ;
2013-09-20 03:11:40 +04:00
if ( cli_nps - > ref = = NULL ) {
TALLOC_FREE ( cli_nps ) ;
tevent_req_received ( req ) ;
return NT_STATUS_NO_MEMORY ;
}
cli_nps - > ref - > cli_nps = cli_nps ;
2013-09-13 14:55:34 +04:00
cli_nps - > conn = state - > conn ;
cli_nps - > session = state - > session ;
cli_nps - > tcon = state - > tcon ;
cli_nps - > pid = state - > pid ;
cli_nps - > timeout = state - > timeout ;
2010-08-12 14:00:15 +04:00
cli_nps - > npipe = talloc_move ( cli_nps , & state - > npipe ) ;
2012-04-25 22:18:22 +04:00
cli_nps - > is_smb1 = state - > is_smb1 ;
2010-08-12 14:00:15 +04:00
cli_nps - > fnum = state - > fnum ;
2012-04-25 22:18:22 +04:00
cli_nps - > fid_persistent = state - > fid_persistent ;
cli_nps - > fid_volatile = state - > fid_volatile ;
2010-08-12 14:00:15 +04:00
2013-11-29 15:24:50 +04:00
talloc_set_destructor ( cli_nps , tstream_smbXcli_np_destructor ) ;
talloc_set_destructor ( cli_nps - > ref , tstream_smbXcli_np_ref_destructor ) ;
2010-08-12 14:00:15 +04:00
2010-09-04 13:01:55 +04:00
cli_nps - > trans . active = false ;
2010-12-21 17:43:44 +03:00
cli_nps - > trans . read_req = NULL ;
2010-09-04 13:01:55 +04:00
cli_nps - > trans . write_req = NULL ;
SSVAL ( cli_nps - > trans . setup + 0 , 0 , TRANSACT_DCERPCCMD ) ;
SSVAL ( cli_nps - > trans . setup + 1 , 0 , cli_nps - > fnum ) ;
2010-08-12 14:00:15 +04:00
* _stream = stream ;
tevent_req_received ( req ) ;
return NT_STATUS_OK ;
}
2013-11-29 15:24:50 +04:00
static ssize_t tstream_smbXcli_np_pending_bytes ( struct tstream_context * stream )
2010-08-12 14:00:15 +04:00
{
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np * cli_nps = tstream_context_data ( stream ,
struct tstream_smbXcli_np ) ;
2010-08-12 14:00:15 +04:00
2013-09-13 14:55:34 +04:00
if ( ! smbXcli_conn_is_connected ( cli_nps - > conn ) ) {
2010-08-12 14:00:15 +04:00
errno = ENOTCONN ;
return - 1 ;
}
return cli_nps - > read . left ;
}
2013-11-29 15:24:50 +04:00
bool tstream_is_smbXcli_np ( struct tstream_context * stream )
2010-09-04 13:00:31 +04:00
{
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np * cli_nps =
2010-09-04 13:00:31 +04:00
talloc_get_type ( _tstream_context_data ( stream ) ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np ) ;
2010-09-04 13:00:31 +04:00
if ( ! cli_nps ) {
return false ;
}
return true ;
}
2013-11-29 15:24:50 +04:00
NTSTATUS tstream_smbXcli_np_use_trans ( struct tstream_context * stream )
2010-09-04 13:01:55 +04:00
{
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np * cli_nps = tstream_context_data ( stream ,
struct tstream_smbXcli_np ) ;
2010-09-04 13:01:55 +04:00
2010-12-21 17:43:44 +03:00
if ( cli_nps - > trans . read_req ) {
return NT_STATUS_PIPE_BUSY ;
}
2010-09-04 13:01:55 +04:00
if ( cli_nps - > trans . write_req ) {
return NT_STATUS_PIPE_BUSY ;
}
if ( cli_nps - > trans . active ) {
return NT_STATUS_PIPE_BUSY ;
}
cli_nps - > trans . active = true ;
return NT_STATUS_OK ;
}
2013-11-29 15:24:50 +04:00
unsigned int tstream_smbXcli_np_set_timeout ( struct tstream_context * stream ,
unsigned int timeout )
2010-12-14 20:17:45 +03:00
{
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np * cli_nps = tstream_context_data ( stream ,
struct tstream_smbXcli_np ) ;
2013-09-13 14:55:34 +04:00
unsigned int old_timeout = cli_nps - > timeout ;
2010-12-14 20:17:45 +03:00
2013-09-13 14:55:34 +04:00
cli_nps - > timeout = timeout ;
return old_timeout ;
2010-12-14 20:17:45 +03:00
}
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_writev_state {
2010-08-12 14:00:15 +04:00
struct tstream_context * stream ;
struct tevent_context * ev ;
struct iovec * vector ;
size_t count ;
int ret ;
struct {
int val ;
const char * location ;
} error ;
} ;
2013-11-29 15:24:50 +04:00
static int tstream_smbXcli_np_writev_state_destructor ( struct tstream_smbXcli_np_writev_state * state )
2010-09-04 13:01:55 +04:00
{
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np * cli_nps =
2010-09-04 13:01:55 +04:00
tstream_context_data ( state - > stream ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np ) ;
2010-09-04 13:01:55 +04:00
cli_nps - > trans . write_req = NULL ;
return 0 ;
}
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_writev_write_next ( struct tevent_req * req ) ;
2010-08-12 14:00:15 +04:00
2013-11-29 15:24:50 +04:00
static struct tevent_req * tstream_smbXcli_np_writev_send ( TALLOC_CTX * mem_ctx ,
2010-08-12 14:00:15 +04:00
struct tevent_context * ev ,
struct tstream_context * stream ,
const struct iovec * vector ,
size_t count )
{
struct tevent_req * req ;
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_writev_state * state ;
struct tstream_smbXcli_np * cli_nps = tstream_context_data ( stream ,
struct tstream_smbXcli_np ) ;
2010-08-12 14:00:15 +04:00
req = tevent_req_create ( mem_ctx , & state ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_writev_state ) ;
2010-08-12 14:00:15 +04:00
if ( ! req ) {
return NULL ;
}
state - > stream = stream ;
state - > ev = ev ;
state - > ret = 0 ;
2013-11-29 15:24:50 +04:00
talloc_set_destructor ( state , tstream_smbXcli_np_writev_state_destructor ) ;
2010-09-04 13:01:55 +04:00
2013-09-13 14:55:34 +04:00
if ( ! smbXcli_conn_is_connected ( cli_nps - > conn ) ) {
2010-08-12 14:00:15 +04:00
tevent_req_error ( req , ENOTCONN ) ;
return tevent_req_post ( req , ev ) ;
}
/*
* we make a copy of the vector so we can change the structure
*/
state - > vector = talloc_array ( state , struct iovec , count ) ;
if ( tevent_req_nomem ( state - > vector , req ) ) {
return tevent_req_post ( req , ev ) ;
}
memcpy ( state - > vector , vector , sizeof ( struct iovec ) * count ) ;
state - > count = count ;
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_writev_write_next ( req ) ;
2010-08-12 14:00:15 +04:00
if ( ! tevent_req_is_in_progress ( req ) ) {
return tevent_req_post ( req , ev ) ;
}
return req ;
}
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_readv_trans_start ( struct tevent_req * req ) ;
static void tstream_smbXcli_np_writev_write_done ( struct tevent_req * subreq ) ;
2010-08-12 14:00:15 +04:00
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_writev_write_next ( struct tevent_req * req )
2010-08-12 14:00:15 +04:00
{
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_writev_state * state =
2010-08-12 14:00:15 +04:00
tevent_req_data ( req ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_writev_state ) ;
struct tstream_smbXcli_np * cli_nps =
2010-08-12 14:00:15 +04:00
tstream_context_data ( state - > stream ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np ) ;
2010-08-12 14:00:15 +04:00
struct tevent_req * subreq ;
2011-06-07 20:45:54 +04:00
size_t i ;
size_t left = 0 ;
for ( i = 0 ; i < state - > count ; i + + ) {
left + = state - > vector [ i ] . iov_len ;
}
if ( left = = 0 ) {
TALLOC_FREE ( cli_nps - > write . buf ) ;
tevent_req_done ( req ) ;
return ;
}
2010-08-12 14:00:15 +04:00
cli_nps - > write . ofs = 0 ;
2013-11-29 15:18:29 +04:00
cli_nps - > write . left = MIN ( left , TSTREAM_SMBXCLI_NP_MAX_BUF_SIZE ) ;
2011-06-07 20:45:54 +04:00
cli_nps - > write . buf = talloc_realloc ( cli_nps , cli_nps - > write . buf ,
uint8_t , cli_nps - > write . left ) ;
if ( tevent_req_nomem ( cli_nps - > write . buf , req ) ) {
return ;
}
2010-08-12 14:00:15 +04:00
/*
* copy the pending buffer first
*/
while ( cli_nps - > write . left > 0 & & state - > count > 0 ) {
uint8_t * base = ( uint8_t * ) state - > vector [ 0 ] . iov_base ;
size_t len = MIN ( cli_nps - > write . left , state - > vector [ 0 ] . iov_len ) ;
memcpy ( cli_nps - > write . buf + cli_nps - > write . ofs , base , len ) ;
base + = len ;
state - > vector [ 0 ] . iov_base = base ;
state - > vector [ 0 ] . iov_len - = len ;
cli_nps - > write . ofs + = len ;
cli_nps - > write . left - = len ;
if ( state - > vector [ 0 ] . iov_len = = 0 ) {
state - > vector + = 1 ;
state - > count - = 1 ;
}
state - > ret + = len ;
}
2010-09-04 13:01:55 +04:00
if ( cli_nps - > trans . active & & state - > count = = 0 ) {
cli_nps - > trans . active = false ;
cli_nps - > trans . write_req = req ;
return ;
}
2010-12-21 17:43:44 +03:00
if ( cli_nps - > trans . read_req & & state - > count = = 0 ) {
cli_nps - > trans . write_req = req ;
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_readv_trans_start ( cli_nps - > trans . read_req ) ;
2010-12-21 17:43:44 +03:00
return ;
}
2012-04-25 22:18:22 +04:00
if ( cli_nps - > is_smb1 ) {
2013-09-12 13:43:30 +04:00
subreq = smb1cli_writex_send ( state , state - > ev ,
2013-09-13 14:55:34 +04:00
cli_nps - > conn ,
cli_nps - > timeout ,
cli_nps - > pid ,
cli_nps - > tcon ,
cli_nps - > session ,
2012-04-25 22:18:22 +04:00
cli_nps - > fnum ,
8 , /* 8 means message mode. */
cli_nps - > write . buf ,
0 , /* offset */
cli_nps - > write . ofs ) ; /* size */
} else {
2012-05-10 20:40:56 +04:00
subreq = smb2cli_write_send ( state , state - > ev ,
2013-09-13 14:55:34 +04:00
cli_nps - > conn ,
cli_nps - > timeout ,
cli_nps - > session ,
cli_nps - > tcon ,
2012-05-10 20:40:56 +04:00
cli_nps - > write . ofs , /* length */
0 , /* offset */
cli_nps - > fid_persistent ,
cli_nps - > fid_volatile ,
0 , /* remaining_bytes */
0 , /* flags */
cli_nps - > write . buf ) ;
2012-04-25 22:18:22 +04:00
}
2010-08-12 14:00:15 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return ;
}
tevent_req_set_callback ( subreq ,
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_writev_write_done ,
2010-08-12 14:00:15 +04:00
req ) ;
}
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_writev_disconnect_now ( struct tevent_req * req ,
2010-08-12 14:00:15 +04:00
int error ,
const char * location ) ;
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_writev_write_done ( struct tevent_req * subreq )
2010-08-12 14:00:15 +04:00
{
struct tevent_req * req =
tevent_req_callback_data ( subreq , struct tevent_req ) ;
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_writev_state * state =
tevent_req_data ( req , struct tstream_smbXcli_np_writev_state ) ;
struct tstream_smbXcli_np * cli_nps =
2010-08-12 14:00:15 +04:00
tstream_context_data ( state - > stream ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np ) ;
2013-09-12 13:43:30 +04:00
uint32_t written ;
2010-08-12 14:00:15 +04:00
NTSTATUS status ;
2012-04-25 22:18:22 +04:00
if ( cli_nps - > is_smb1 ) {
2013-09-12 13:43:30 +04:00
status = smb1cli_writex_recv ( subreq , & written , NULL ) ;
2012-04-25 22:18:22 +04:00
} else {
2013-09-12 13:43:30 +04:00
status = smb2cli_write_recv ( subreq , & written ) ;
2012-04-25 22:18:22 +04:00
}
2010-08-12 14:00:15 +04:00
TALLOC_FREE ( subreq ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_writev_disconnect_now ( req , EIO , __location__ ) ;
2010-08-12 14:00:15 +04:00
return ;
}
if ( written ! = cli_nps - > write . ofs ) {
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_writev_disconnect_now ( req , EIO , __location__ ) ;
2010-08-12 14:00:15 +04:00
return ;
}
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_writev_write_next ( req ) ;
2010-08-12 14:00:15 +04:00
}
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_writev_disconnect_done ( struct tevent_req * subreq ) ;
2010-08-12 14:00:15 +04:00
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_writev_disconnect_now ( struct tevent_req * req ,
2010-08-12 14:00:15 +04:00
int error ,
const char * location )
{
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_writev_state * state =
2010-08-12 14:00:15 +04:00
tevent_req_data ( req ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_writev_state ) ;
struct tstream_smbXcli_np * cli_nps =
2010-08-12 14:00:15 +04:00
tstream_context_data ( state - > stream ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np ) ;
2010-08-12 14:00:15 +04:00
struct tevent_req * subreq ;
state - > error . val = error ;
state - > error . location = location ;
2013-09-13 14:55:34 +04:00
if ( ! smbXcli_conn_is_connected ( cli_nps - > conn ) ) {
2010-08-12 14:00:15 +04:00
/* return the original error */
_tevent_req_error ( req , state - > error . val , state - > error . location ) ;
return ;
}
2012-04-25 22:18:22 +04:00
if ( cli_nps - > is_smb1 ) {
2013-09-12 12:10:06 +04:00
subreq = smb1cli_close_send ( state , state - > ev ,
2013-09-13 14:55:34 +04:00
cli_nps - > conn ,
cli_nps - > timeout ,
cli_nps - > pid ,
cli_nps - > tcon ,
cli_nps - > session ,
2013-09-12 12:10:06 +04:00
cli_nps - > fnum , UINT32_MAX ) ;
2012-04-25 22:18:22 +04:00
} else {
2012-05-10 20:32:49 +04:00
subreq = smb2cli_close_send ( state , state - > ev ,
2013-09-13 14:55:34 +04:00
cli_nps - > conn ,
cli_nps - > timeout ,
cli_nps - > session ,
cli_nps - > tcon ,
2012-04-25 22:18:22 +04:00
0 , /* flags */
cli_nps - > fid_persistent ,
cli_nps - > fid_volatile ) ;
}
2010-08-12 14:00:15 +04:00
if ( subreq = = NULL ) {
/* return the original error */
_tevent_req_error ( req , state - > error . val , state - > error . location ) ;
return ;
}
tevent_req_set_callback ( subreq ,
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_writev_disconnect_done ,
2010-08-12 14:00:15 +04:00
req ) ;
}
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_writev_disconnect_done ( struct tevent_req * subreq )
2010-08-12 14:00:15 +04:00
{
struct tevent_req * req =
tevent_req_callback_data ( subreq , struct tevent_req ) ;
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_writev_state * state =
tevent_req_data ( req , struct tstream_smbXcli_np_writev_state ) ;
struct tstream_smbXcli_np * cli_nps =
tstream_context_data ( state - > stream , struct tstream_smbXcli_np ) ;
2010-08-12 14:00:15 +04:00
2012-04-25 22:18:22 +04:00
if ( cli_nps - > is_smb1 ) {
2013-09-12 12:10:06 +04:00
smb1cli_close_recv ( subreq ) ;
2012-04-25 22:18:22 +04:00
} else {
smb2cli_close_recv ( subreq ) ;
}
2010-08-12 14:00:15 +04:00
TALLOC_FREE ( subreq ) ;
2013-09-13 14:55:34 +04:00
cli_nps - > conn = NULL ;
cli_nps - > tcon = NULL ;
cli_nps - > session = NULL ;
2010-08-12 14:00:15 +04:00
/* return the original error */
_tevent_req_error ( req , state - > error . val , state - > error . location ) ;
}
2013-11-29 15:24:50 +04:00
static int tstream_smbXcli_np_writev_recv ( struct tevent_req * req ,
2010-08-12 14:00:15 +04:00
int * perrno )
{
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_writev_state * state =
2010-08-12 14:00:15 +04:00
tevent_req_data ( req ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_writev_state ) ;
2010-08-12 14:00:15 +04:00
int ret ;
ret = tsocket_simple_int_recv ( req , perrno ) ;
if ( ret = = 0 ) {
ret = state - > ret ;
}
tevent_req_received ( req ) ;
return ret ;
}
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_readv_state {
2010-08-12 14:00:15 +04:00
struct tstream_context * stream ;
struct tevent_context * ev ;
struct iovec * vector ;
size_t count ;
int ret ;
2010-09-04 13:01:55 +04:00
struct {
struct tevent_immediate * im ;
} trans ;
2010-08-12 14:00:15 +04:00
struct {
int val ;
const char * location ;
} error ;
} ;
2013-11-29 15:24:50 +04:00
static int tstream_smbXcli_np_readv_state_destructor ( struct tstream_smbXcli_np_readv_state * state )
2010-12-21 17:43:44 +03:00
{
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np * cli_nps =
2010-12-21 17:43:44 +03:00
tstream_context_data ( state - > stream ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np ) ;
2010-12-21 17:43:44 +03:00
cli_nps - > trans . read_req = NULL ;
return 0 ;
}
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_readv_read_next ( struct tevent_req * req ) ;
2010-08-12 14:00:15 +04:00
2013-11-29 15:24:50 +04:00
static struct tevent_req * tstream_smbXcli_np_readv_send ( TALLOC_CTX * mem_ctx ,
2010-08-12 14:00:15 +04:00
struct tevent_context * ev ,
struct tstream_context * stream ,
struct iovec * vector ,
size_t count )
{
struct tevent_req * req ;
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_readv_state * state ;
struct tstream_smbXcli_np * cli_nps =
tstream_context_data ( stream , struct tstream_smbXcli_np ) ;
2010-08-12 14:00:15 +04:00
req = tevent_req_create ( mem_ctx , & state ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_readv_state ) ;
2010-08-12 14:00:15 +04:00
if ( ! req ) {
return NULL ;
}
state - > stream = stream ;
state - > ev = ev ;
state - > ret = 0 ;
2013-11-29 15:24:50 +04:00
talloc_set_destructor ( state , tstream_smbXcli_np_readv_state_destructor ) ;
2010-12-21 17:43:44 +03:00
2013-09-13 14:55:34 +04:00
if ( ! smbXcli_conn_is_connected ( cli_nps - > conn ) ) {
2010-08-12 14:00:15 +04:00
tevent_req_error ( req , ENOTCONN ) ;
return tevent_req_post ( req , ev ) ;
}
/*
* we make a copy of the vector so we can change the structure
*/
state - > vector = talloc_array ( state , struct iovec , count ) ;
if ( tevent_req_nomem ( state - > vector , req ) ) {
return tevent_req_post ( req , ev ) ;
}
memcpy ( state - > vector , vector , sizeof ( struct iovec ) * count ) ;
state - > count = count ;
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_readv_read_next ( req ) ;
2010-08-12 14:00:15 +04:00
if ( ! tevent_req_is_in_progress ( req ) ) {
return tevent_req_post ( req , ev ) ;
}
return req ;
}
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_readv_read_done ( struct tevent_req * subreq ) ;
2010-08-12 14:00:15 +04:00
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_readv_read_next ( struct tevent_req * req )
2010-08-12 14:00:15 +04:00
{
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_readv_state * state =
2010-08-12 14:00:15 +04:00
tevent_req_data ( req ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_readv_state ) ;
struct tstream_smbXcli_np * cli_nps =
2010-08-12 14:00:15 +04:00
tstream_context_data ( state - > stream ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np ) ;
2010-08-12 14:00:15 +04:00
struct tevent_req * subreq ;
/*
* copy the pending buffer first
*/
while ( cli_nps - > read . left > 0 & & state - > count > 0 ) {
uint8_t * base = ( uint8_t * ) state - > vector [ 0 ] . iov_base ;
size_t len = MIN ( cli_nps - > read . left , state - > vector [ 0 ] . iov_len ) ;
memcpy ( base , cli_nps - > read . buf + cli_nps - > read . ofs , len ) ;
base + = len ;
state - > vector [ 0 ] . iov_base = base ;
state - > vector [ 0 ] . iov_len - = len ;
cli_nps - > read . ofs + = len ;
cli_nps - > read . left - = len ;
if ( state - > vector [ 0 ] . iov_len = = 0 ) {
state - > vector + = 1 ;
state - > count - = 1 ;
}
state - > ret + = len ;
}
2011-06-07 20:45:54 +04:00
if ( cli_nps - > read . left = = 0 ) {
TALLOC_FREE ( cli_nps - > read . buf ) ;
}
2010-08-12 14:00:15 +04:00
if ( state - > count = = 0 ) {
tevent_req_done ( req ) ;
return ;
}
2010-12-21 17:43:44 +03:00
if ( cli_nps - > trans . active ) {
cli_nps - > trans . active = false ;
cli_nps - > trans . read_req = req ;
return ;
}
2010-09-04 13:01:55 +04:00
2010-12-21 17:43:44 +03:00
if ( cli_nps - > trans . write_req ) {
cli_nps - > trans . read_req = req ;
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_readv_trans_start ( req ) ;
2010-09-04 13:01:55 +04:00
return ;
}
2012-04-25 22:18:22 +04:00
if ( cli_nps - > is_smb1 ) {
2013-09-13 11:26:25 +04:00
subreq = smb1cli_readx_send ( state , state - > ev ,
2013-09-13 14:55:34 +04:00
cli_nps - > conn ,
cli_nps - > timeout ,
cli_nps - > pid ,
cli_nps - > tcon ,
cli_nps - > session ,
2012-04-25 22:18:22 +04:00
cli_nps - > fnum ,
0 , /* offset */
2013-11-29 15:18:29 +04:00
TSTREAM_SMBXCLI_NP_MAX_BUF_SIZE ) ;
2012-04-25 22:18:22 +04:00
} else {
2012-05-10 20:30:25 +04:00
subreq = smb2cli_read_send ( state , state - > ev ,
2013-09-13 14:55:34 +04:00
cli_nps - > conn ,
cli_nps - > timeout ,
cli_nps - > session ,
cli_nps - > tcon ,
2013-11-29 15:18:29 +04:00
TSTREAM_SMBXCLI_NP_MAX_BUF_SIZE , /* length */
2012-04-25 22:18:22 +04:00
0 , /* offset */
cli_nps - > fid_persistent ,
cli_nps - > fid_volatile ,
0 , /* minimum_count */
0 ) ; /* remaining_bytes */
}
2010-08-12 14:00:15 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return ;
}
tevent_req_set_callback ( subreq ,
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_readv_read_done ,
2010-08-12 14:00:15 +04:00
req ) ;
}
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_readv_trans_done ( struct tevent_req * subreq ) ;
2010-12-21 17:43:44 +03:00
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_readv_trans_start ( struct tevent_req * req )
2010-12-21 17:43:44 +03:00
{
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_readv_state * state =
2010-12-21 17:43:44 +03:00
tevent_req_data ( req ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_readv_state ) ;
struct tstream_smbXcli_np * cli_nps =
2010-12-21 17:43:44 +03:00
tstream_context_data ( state - > stream ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np ) ;
2010-12-21 17:43:44 +03:00
struct tevent_req * subreq ;
state - > trans . im = tevent_create_immediate ( state ) ;
if ( tevent_req_nomem ( state - > trans . im , req ) ) {
return ;
}
2012-04-25 22:18:22 +04:00
if ( cli_nps - > is_smb1 ) {
2013-09-11 18:16:15 +04:00
subreq = smb1cli_trans_send ( state , state - > ev ,
2013-09-13 14:55:34 +04:00
cli_nps - > conn , SMBtrans ,
2013-09-11 18:16:15 +04:00
0 , 0 , /* *_flags */
0 , 0 , /* *_flags2 */
2013-09-13 14:55:34 +04:00
cli_nps - > timeout ,
cli_nps - > pid ,
cli_nps - > tcon ,
cli_nps - > session ,
2013-09-11 18:16:15 +04:00
" \\ PIPE \\ " ,
0 , 0 , 0 ,
cli_nps - > trans . setup , 2 ,
0 ,
NULL , 0 , 0 ,
cli_nps - > write . buf ,
cli_nps - > write . ofs ,
2013-11-29 15:18:29 +04:00
TSTREAM_SMBXCLI_NP_MAX_BUF_SIZE ) ;
2012-04-25 22:18:22 +04:00
} else {
DATA_BLOB in_input_buffer = data_blob_null ;
DATA_BLOB in_output_buffer = data_blob_null ;
in_input_buffer = data_blob_const ( cli_nps - > write . buf ,
cli_nps - > write . ofs ) ;
subreq = smb2cli_ioctl_send ( state , state - > ev ,
2013-09-13 14:55:34 +04:00
cli_nps - > conn ,
cli_nps - > timeout ,
cli_nps - > session ,
cli_nps - > tcon ,
2012-04-25 22:18:22 +04:00
cli_nps - > fid_persistent ,
cli_nps - > fid_volatile ,
FSCTL_NAMED_PIPE_READ_WRITE ,
0 , /* in_max_input_length */
& in_input_buffer ,
/* in_max_output_length */
2013-11-29 15:18:29 +04:00
TSTREAM_SMBXCLI_NP_MAX_BUF_SIZE ,
2012-04-25 22:18:22 +04:00
& in_output_buffer ,
SMB2_IOCTL_FLAG_IS_FSCTL ) ;
}
2010-12-21 17:43:44 +03:00
if ( tevent_req_nomem ( subreq , req ) ) {
return ;
}
tevent_req_set_callback ( subreq ,
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_readv_trans_done ,
2010-12-21 17:43:44 +03:00
req ) ;
}
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_readv_disconnect_now ( struct tevent_req * req ,
2010-08-12 14:00:15 +04:00
int error ,
const char * location ) ;
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_readv_trans_next ( struct tevent_context * ctx ,
struct tevent_immediate * im ,
void * private_data ) ;
2010-09-04 13:01:55 +04:00
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_readv_trans_done ( struct tevent_req * subreq )
2010-09-04 13:01:55 +04:00
{
struct tevent_req * req =
tevent_req_callback_data ( subreq , struct tevent_req ) ;
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_readv_state * state =
tevent_req_data ( req , struct tstream_smbXcli_np_readv_state ) ;
struct tstream_smbXcli_np * cli_nps =
tstream_context_data ( state - > stream , struct tstream_smbXcli_np ) ;
2010-09-04 13:01:55 +04:00
uint8_t * rcvbuf ;
uint32_t received ;
NTSTATUS status ;
2012-04-25 22:18:22 +04:00
if ( cli_nps - > is_smb1 ) {
2013-09-11 18:16:15 +04:00
status = smb1cli_trans_recv ( subreq , state , NULL , NULL , 0 , NULL ,
NULL , 0 , NULL ,
& rcvbuf , 0 , & received ) ;
2012-04-25 22:18:22 +04:00
} else {
DATA_BLOB out_input_buffer = data_blob_null ;
DATA_BLOB out_output_buffer = data_blob_null ;
status = smb2cli_ioctl_recv ( subreq , state ,
& out_input_buffer ,
& out_output_buffer ) ;
/* Note that rcvbuf is not a talloc pointer here */
rcvbuf = out_output_buffer . data ;
received = out_output_buffer . length ;
}
2010-09-04 13:01:55 +04:00
TALLOC_FREE ( subreq ) ;
if ( NT_STATUS_EQUAL ( status , NT_STATUS_BUFFER_TOO_SMALL ) ) {
status = NT_STATUS_OK ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_readv_disconnect_now ( req , EIO , __location__ ) ;
2010-09-04 13:01:55 +04:00
return ;
}
2013-11-29 15:18:29 +04:00
if ( received > TSTREAM_SMBXCLI_NP_MAX_BUF_SIZE ) {
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_readv_disconnect_now ( req , EIO , __location__ ) ;
2010-09-04 13:01:55 +04:00
return ;
}
if ( received = = 0 ) {
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_readv_disconnect_now ( req , EPIPE , __location__ ) ;
2010-09-04 13:01:55 +04:00
return ;
}
cli_nps - > read . ofs = 0 ;
cli_nps - > read . left = received ;
2012-04-25 22:18:22 +04:00
cli_nps - > read . buf = talloc_array ( cli_nps , uint8_t , received ) ;
if ( cli_nps - > read . buf = = NULL ) {
TALLOC_FREE ( subreq ) ;
tevent_req_nomem ( cli_nps - > read . buf , req ) ;
return ;
}
memcpy ( cli_nps - > read . buf , rcvbuf , received ) ;
2010-09-04 13:01:55 +04:00
if ( cli_nps - > trans . write_req = = NULL ) {
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_readv_read_next ( req ) ;
2010-09-04 13:01:55 +04:00
return ;
}
tevent_schedule_immediate ( state - > trans . im , state - > ev ,
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_readv_trans_next , req ) ;
2010-09-04 13:01:55 +04:00
tevent_req_done ( cli_nps - > trans . write_req ) ;
}
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_readv_trans_next ( struct tevent_context * ctx ,
2010-09-04 13:01:55 +04:00
struct tevent_immediate * im ,
void * private_data )
{
struct tevent_req * req =
talloc_get_type_abort ( private_data ,
struct tevent_req ) ;
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_readv_read_next ( req ) ;
2010-09-04 13:01:55 +04:00
}
2010-08-12 14:00:15 +04:00
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_readv_read_done ( struct tevent_req * subreq )
2010-08-12 14:00:15 +04:00
{
struct tevent_req * req =
tevent_req_callback_data ( subreq , struct tevent_req ) ;
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_readv_state * state =
tevent_req_data ( req , struct tstream_smbXcli_np_readv_state ) ;
struct tstream_smbXcli_np * cli_nps =
tstream_context_data ( state - > stream , struct tstream_smbXcli_np ) ;
2010-08-12 14:00:15 +04:00
uint8_t * rcvbuf ;
2013-09-13 11:26:25 +04:00
uint32_t received ;
2010-08-12 14:00:15 +04:00
NTSTATUS status ;
/*
* We must free subreq in this function as there is
* a timer event attached to it .
*/
2012-04-25 22:18:22 +04:00
if ( cli_nps - > is_smb1 ) {
2013-09-13 11:26:25 +04:00
status = smb1cli_readx_recv ( subreq , & received , & rcvbuf ) ;
2012-04-25 22:18:22 +04:00
} else {
2013-09-13 11:26:25 +04:00
status = smb2cli_read_recv ( subreq , state , & rcvbuf , & received ) ;
2012-04-25 22:18:22 +04:00
}
2010-08-12 14:00:15 +04:00
/*
* We can ' t TALLOC_FREE ( subreq ) as usual here , as rcvbuf still is a
* child of that .
*/
if ( NT_STATUS_EQUAL ( status , NT_STATUS_BUFFER_TOO_SMALL ) ) {
/*
* NT_STATUS_BUFFER_TOO_SMALL means that there ' s
* more data to read when the named pipe is used
* in message mode ( which is the case here ) .
*
* But we hide this from the caller .
*/
status = NT_STATUS_OK ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
TALLOC_FREE ( subreq ) ;
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_readv_disconnect_now ( req , EIO , __location__ ) ;
2010-08-12 14:00:15 +04:00
return ;
}
2013-11-29 15:18:29 +04:00
if ( received > TSTREAM_SMBXCLI_NP_MAX_BUF_SIZE ) {
2010-08-12 14:00:15 +04:00
TALLOC_FREE ( subreq ) ;
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_readv_disconnect_now ( req , EIO , __location__ ) ;
2010-08-12 14:00:15 +04:00
return ;
}
if ( received = = 0 ) {
TALLOC_FREE ( subreq ) ;
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_readv_disconnect_now ( req , EPIPE , __location__ ) ;
2010-08-12 14:00:15 +04:00
return ;
}
cli_nps - > read . ofs = 0 ;
cli_nps - > read . left = received ;
2011-06-07 20:45:54 +04:00
cli_nps - > read . buf = talloc_array ( cli_nps , uint8_t , received ) ;
if ( cli_nps - > read . buf = = NULL ) {
TALLOC_FREE ( subreq ) ;
tevent_req_nomem ( cli_nps - > read . buf , req ) ;
return ;
}
2010-08-12 14:00:15 +04:00
memcpy ( cli_nps - > read . buf , rcvbuf , received ) ;
TALLOC_FREE ( subreq ) ;
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_readv_read_next ( req ) ;
2010-08-12 14:00:15 +04:00
}
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_readv_disconnect_done ( struct tevent_req * subreq ) ;
2010-08-12 14:00:15 +04:00
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_readv_error ( struct tevent_req * req ) ;
2010-08-12 14:00:15 +04:00
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_readv_disconnect_now ( struct tevent_req * req ,
2010-08-12 14:00:15 +04:00
int error ,
const char * location )
{
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_readv_state * state =
2010-08-12 14:00:15 +04:00
tevent_req_data ( req ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_readv_state ) ;
struct tstream_smbXcli_np * cli_nps =
2010-08-12 14:00:15 +04:00
tstream_context_data ( state - > stream ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np ) ;
2010-08-12 14:00:15 +04:00
struct tevent_req * subreq ;
state - > error . val = error ;
state - > error . location = location ;
2013-09-13 14:55:34 +04:00
if ( ! smbXcli_conn_is_connected ( cli_nps - > conn ) ) {
2010-08-12 14:00:15 +04:00
/* return the original error */
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_readv_error ( req ) ;
2010-08-12 14:00:15 +04:00
return ;
}
2012-04-25 22:18:22 +04:00
if ( cli_nps - > is_smb1 ) {
2013-09-12 12:10:06 +04:00
subreq = smb1cli_close_send ( state , state - > ev ,
2013-09-13 14:55:34 +04:00
cli_nps - > conn ,
cli_nps - > timeout ,
cli_nps - > pid ,
cli_nps - > tcon ,
cli_nps - > session ,
2013-09-12 12:10:06 +04:00
cli_nps - > fnum , UINT32_MAX ) ;
2012-04-25 22:18:22 +04:00
} else {
2012-05-10 20:32:49 +04:00
subreq = smb2cli_close_send ( state , state - > ev ,
2013-09-13 14:55:34 +04:00
cli_nps - > conn ,
cli_nps - > timeout ,
cli_nps - > session ,
cli_nps - > tcon ,
2012-04-25 22:18:22 +04:00
0 , /* flags */
cli_nps - > fid_persistent ,
cli_nps - > fid_volatile ) ;
}
2010-08-12 14:00:15 +04:00
if ( subreq = = NULL ) {
/* return the original error */
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_readv_error ( req ) ;
2010-08-12 14:00:15 +04:00
return ;
}
tevent_req_set_callback ( subreq ,
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_readv_disconnect_done ,
2010-08-12 14:00:15 +04:00
req ) ;
}
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_readv_disconnect_done ( struct tevent_req * subreq )
2010-08-12 14:00:15 +04:00
{
struct tevent_req * req =
tevent_req_callback_data ( subreq , struct tevent_req ) ;
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_readv_state * state =
tevent_req_data ( req , struct tstream_smbXcli_np_readv_state ) ;
struct tstream_smbXcli_np * cli_nps =
tstream_context_data ( state - > stream , struct tstream_smbXcli_np ) ;
2010-08-12 14:00:15 +04:00
2012-04-25 22:18:22 +04:00
if ( cli_nps - > is_smb1 ) {
2013-09-12 12:10:06 +04:00
smb1cli_close_recv ( subreq ) ;
2012-04-25 22:18:22 +04:00
} else {
smb2cli_close_recv ( subreq ) ;
}
2010-08-12 14:00:15 +04:00
TALLOC_FREE ( subreq ) ;
2013-09-13 14:55:34 +04:00
cli_nps - > conn = NULL ;
cli_nps - > session = NULL ;
cli_nps - > tcon = NULL ;
2010-08-12 14:00:15 +04:00
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_readv_error ( req ) ;
2010-08-12 14:00:15 +04:00
}
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_readv_error_trigger ( struct tevent_context * ctx ,
struct tevent_immediate * im ,
void * private_data ) ;
2010-09-04 13:01:55 +04:00
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_readv_error ( struct tevent_req * req )
2010-08-12 14:00:15 +04:00
{
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_readv_state * state =
2010-08-12 14:00:15 +04:00
tevent_req_data ( req ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_readv_state ) ;
struct tstream_smbXcli_np * cli_nps =
2010-09-04 13:01:55 +04:00
tstream_context_data ( state - > stream ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np ) ;
2010-09-04 13:01:55 +04:00
if ( cli_nps - > trans . write_req = = NULL ) {
/* return the original error */
_tevent_req_error ( req , state - > error . val , state - > error . location ) ;
return ;
}
if ( state - > trans . im = = NULL ) {
/* return the original error */
_tevent_req_error ( req , state - > error . val , state - > error . location ) ;
return ;
}
tevent_schedule_immediate ( state - > trans . im , state - > ev ,
2013-11-29 15:24:50 +04:00
tstream_smbXcli_np_readv_error_trigger , req ) ;
2010-09-04 13:01:55 +04:00
/* return the original error for writev */
_tevent_req_error ( cli_nps - > trans . write_req ,
state - > error . val , state - > error . location ) ;
}
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_readv_error_trigger ( struct tevent_context * ctx ,
struct tevent_immediate * im ,
void * private_data )
2010-09-04 13:01:55 +04:00
{
struct tevent_req * req =
talloc_get_type_abort ( private_data ,
struct tevent_req ) ;
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_readv_state * state =
2010-09-04 13:01:55 +04:00
tevent_req_data ( req ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_readv_state ) ;
2010-08-12 14:00:15 +04:00
/* return the original error */
_tevent_req_error ( req , state - > error . val , state - > error . location ) ;
}
2013-11-29 15:24:50 +04:00
static int tstream_smbXcli_np_readv_recv ( struct tevent_req * req ,
int * perrno )
2010-08-12 14:00:15 +04:00
{
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_readv_state * state =
tevent_req_data ( req , struct tstream_smbXcli_np_readv_state ) ;
2010-08-12 14:00:15 +04:00
int ret ;
ret = tsocket_simple_int_recv ( req , perrno ) ;
if ( ret = = 0 ) {
ret = state - > ret ;
}
tevent_req_received ( req ) ;
return ret ;
}
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_disconnect_state {
2010-08-12 14:00:15 +04:00
struct tstream_context * stream ;
} ;
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_disconnect_done ( struct tevent_req * subreq ) ;
2010-08-12 14:00:15 +04:00
2013-11-29 15:24:50 +04:00
static struct tevent_req * tstream_smbXcli_np_disconnect_send ( TALLOC_CTX * mem_ctx ,
2010-08-12 14:00:15 +04:00
struct tevent_context * ev ,
struct tstream_context * stream )
{
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np * cli_nps = tstream_context_data ( stream ,
struct tstream_smbXcli_np ) ;
2010-08-12 14:00:15 +04:00
struct tevent_req * req ;
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_disconnect_state * state ;
2010-08-12 14:00:15 +04:00
struct tevent_req * subreq ;
req = tevent_req_create ( mem_ctx , & state ,
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_disconnect_state ) ;
2010-08-12 14:00:15 +04:00
if ( req = = NULL ) {
return NULL ;
}
state - > stream = stream ;
2013-09-13 14:55:34 +04:00
if ( ! smbXcli_conn_is_connected ( cli_nps - > conn ) ) {
2010-08-12 14:00:15 +04:00
tevent_req_error ( req , ENOTCONN ) ;
return tevent_req_post ( req , ev ) ;
}
2012-04-25 22:18:22 +04:00
if ( cli_nps - > is_smb1 ) {
2013-09-13 14:55:34 +04:00
subreq = smb1cli_close_send ( state , ev , cli_nps - > conn ,
cli_nps - > timeout ,
cli_nps - > pid ,
cli_nps - > tcon ,
cli_nps - > session ,
2013-09-12 12:10:06 +04:00
cli_nps - > fnum , UINT32_MAX ) ;
2012-04-25 22:18:22 +04:00
} else {
2013-09-13 14:55:34 +04:00
subreq = smb2cli_close_send ( state , ev , cli_nps - > conn ,
cli_nps - > timeout ,
cli_nps - > session ,
cli_nps - > tcon ,
2012-04-25 22:18:22 +04:00
0 , /* flags */
cli_nps - > fid_persistent ,
cli_nps - > fid_volatile ) ;
}
2010-08-12 14:00:15 +04:00
if ( tevent_req_nomem ( subreq , req ) ) {
return tevent_req_post ( req , ev ) ;
}
2013-11-29 15:24:50 +04:00
tevent_req_set_callback ( subreq , tstream_smbXcli_np_disconnect_done , req ) ;
2010-08-12 14:00:15 +04:00
return req ;
}
2013-11-29 15:24:50 +04:00
static void tstream_smbXcli_np_disconnect_done ( struct tevent_req * subreq )
2010-08-12 14:00:15 +04:00
{
struct tevent_req * req = tevent_req_callback_data ( subreq ,
struct tevent_req ) ;
2013-11-29 15:24:50 +04:00
struct tstream_smbXcli_np_disconnect_state * state =
tevent_req_data ( req , struct tstream_smbXcli_np_disconnect_state ) ;
struct tstream_smbXcli_np * cli_nps =
tstream_context_data ( state - > stream , struct tstream_smbXcli_np ) ;
2010-08-12 14:00:15 +04:00
NTSTATUS status ;
2012-04-25 22:18:22 +04:00
if ( cli_nps - > is_smb1 ) {
2013-09-12 12:10:06 +04:00
status = smb1cli_close_recv ( subreq ) ;
2012-04-25 22:18:22 +04:00
} else {
status = smb2cli_close_recv ( subreq ) ;
}
2010-08-12 14:00:15 +04:00
TALLOC_FREE ( subreq ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
tevent_req_error ( req , EIO ) ;
return ;
}
2013-09-13 14:55:34 +04:00
cli_nps - > conn = NULL ;
cli_nps - > session = NULL ;
cli_nps - > tcon = NULL ;
2010-08-12 14:00:15 +04:00
tevent_req_done ( req ) ;
}
2013-11-29 15:24:50 +04:00
static int tstream_smbXcli_np_disconnect_recv ( struct tevent_req * req ,
int * perrno )
2010-08-12 14:00:15 +04:00
{
int ret ;
ret = tsocket_simple_int_recv ( req , perrno ) ;
tevent_req_received ( req ) ;
return ret ;
}
2013-11-29 15:24:50 +04:00
static const struct tstream_context_ops tstream_smbXcli_np_ops = {
. name = " smbXcli_np " ,
2010-08-12 14:00:15 +04:00
2013-11-29 15:24:50 +04:00
. pending_bytes = tstream_smbXcli_np_pending_bytes ,
2010-08-12 14:00:15 +04:00
2013-11-29 15:24:50 +04:00
. readv_send = tstream_smbXcli_np_readv_send ,
. readv_recv = tstream_smbXcli_np_readv_recv ,
2010-08-12 14:00:15 +04:00
2013-11-29 15:24:50 +04:00
. writev_send = tstream_smbXcli_np_writev_send ,
. writev_recv = tstream_smbXcli_np_writev_recv ,
2010-08-12 14:00:15 +04:00
2013-11-29 15:24:50 +04:00
. disconnect_send = tstream_smbXcli_np_disconnect_send ,
. disconnect_recv = tstream_smbXcli_np_disconnect_recv ,
2010-08-12 14:00:15 +04:00
} ;