2003-08-13 05:53:07 +04:00
/*
Unix SMB / CIFS implementation .
SMB client transport context management functions
2005-01-16 14:15:08 +03:00
Copyright ( C ) Andrew Tridgell 1994 - 2005
2003-08-13 05:53:07 +04:00
Copyright ( C ) James Myers 2003 < myersjj @ samba . org >
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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2003-08-13 05:53:07 +04:00
( 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
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2003-08-13 05:53:07 +04:00
*/
# include "includes.h"
2011-09-23 10:35:17 +04:00
# include "system/network.h"
# include "../lib/async_req/async_sock.h"
# include "../lib/util/tevent_ntstatus.h"
2004-11-01 04:03:22 +03:00
# include "libcli/raw/libcliraw.h"
2008-04-02 06:53:27 +04:00
# include "libcli/raw/raw_proto.h"
2005-02-10 09:59:29 +03:00
# include "lib/socket/socket.h"
2005-02-03 14:56:03 +03:00
# include "lib/events/events.h"
2006-03-16 03:23:11 +03:00
# include "librpc/gen_ndr/ndr_nbt.h"
2008-09-23 10:06:33 +04:00
# include "../libcli/nbt/libnbt.h"
2011-09-23 10:35:17 +04:00
# include "../libcli/smb/smbXcli_base.h"
# include "../libcli/smb/read_smb.h"
2004-07-23 10:40:49 +04:00
2004-09-26 15:30:20 +04:00
/*
destroy a transport
*/
2006-05-24 11:34:11 +04:00
static int transport_destructor ( struct smbcli_transport * transport )
2004-09-26 15:30:20 +04:00
{
2006-07-13 21:37:45 +04:00
smbcli_transport_dead ( transport , NT_STATUS_LOCAL_DISCONNECT ) ;
2004-09-26 15:30:20 +04:00
return 0 ;
}
2003-08-13 05:53:07 +04:00
/*
create a transport structure based on an established socket
*/
2005-01-24 03:57:14 +03:00
struct smbcli_transport * smbcli_transport_init ( struct smbcli_socket * sock ,
2007-10-07 02:28:14 +04:00
TALLOC_CTX * parent_ctx ,
2007-12-03 23:25:06 +03:00
bool primary ,
2010-05-09 19:20:01 +04:00
struct smbcli_options * options )
2003-08-13 05:53:07 +04:00
{
2004-08-04 17:23:35 +04:00
struct smbcli_transport * transport ;
2011-09-23 10:35:17 +04:00
uint32_t smb1_capabilities ;
2003-08-13 05:53:07 +04:00
2005-01-24 03:57:14 +03:00
transport = talloc_zero ( parent_ctx , struct smbcli_transport ) ;
2003-08-13 05:53:07 +04:00
if ( ! transport ) return NULL ;
2011-11-22 12:36:30 +04:00
transport - > ev = sock - > event . ctx ;
2008-01-04 02:22:12 +03:00
transport - > options = * options ;
2005-11-09 11:13:41 +03:00
2011-09-23 10:35:17 +04:00
TALLOC_FREE ( sock - > event . fde ) ;
TALLOC_FREE ( sock - > event . te ) ;
smb1_capabilities = 0 ;
smb1_capabilities | = CAP_LARGE_FILES ;
smb1_capabilities | = CAP_NT_SMBS | CAP_RPC_REMOTE_APIS ;
smb1_capabilities | = CAP_LOCK_AND_READ | CAP_NT_FIND ;
smb1_capabilities | = CAP_DFS | CAP_W2K_SMBS ;
smb1_capabilities | = CAP_LARGE_READX | CAP_LARGE_WRITEX ;
smb1_capabilities | = CAP_LWIO ;
if ( options - > ntstatus_support ) {
smb1_capabilities | = CAP_STATUS32 ;
}
if ( options - > unicode ) {
smb1_capabilities | = CAP_UNICODE ;
}
if ( options - > use_spnego ) {
smb1_capabilities | = CAP_EXTENDED_SECURITY ;
}
if ( options - > use_level2_oplocks ) {
smb1_capabilities | = CAP_LEVEL_II_OPLOCKS ;
}
transport - > conn = smbXcli_conn_create ( transport ,
sock - > sock - > fd ,
sock - > hostname ,
options - > signing ,
smb1_capabilities ,
2012-02-29 05:02:29 +04:00
NULL , /* client_guid */
0 ) ; /* smb2_capabilities */
2011-09-23 10:35:17 +04:00
if ( transport - > conn = = NULL ) {
TALLOC_FREE ( sock ) ;
TALLOC_FREE ( transport ) ;
2005-11-09 11:13:41 +03:00
return NULL ;
}
2011-09-23 10:35:17 +04:00
sock - > sock - > fd = - 1 ;
TALLOC_FREE ( sock ) ;
2004-09-26 15:30:20 +04:00
talloc_set_destructor ( transport , transport_destructor ) ;
2003-08-13 05:53:07 +04:00
2004-09-26 15:30:20 +04:00
return transport ;
2003-08-13 05:53:07 +04:00
}
2004-04-23 08:21:22 +04:00
/*
mark the transport as dead
*/
2006-07-13 21:37:45 +04:00
void smbcli_transport_dead ( struct smbcli_transport * transport , NTSTATUS status )
2004-04-23 08:21:22 +04:00
{
2006-07-13 21:37:45 +04:00
if ( NT_STATUS_EQUAL ( NT_STATUS_UNSUCCESSFUL , status ) ) {
status = NT_STATUS_UNEXPECTED_NETWORK_ERROR ;
}
2011-09-23 10:35:17 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
status = NT_STATUS_LOCAL_DISCONNECT ;
2003-08-13 05:53:07 +04:00
}
2011-09-23 10:35:17 +04:00
smbXcli_conn_disconnect ( transport - > conn , status ) ;
2003-08-13 05:53:07 +04:00
}
2008-12-29 22:24:57 +03:00
static void idle_handler ( struct tevent_context * ev ,
2009-02-02 10:24:59 +03:00
struct tevent_timer * te , struct timeval t , void * private_data )
2004-07-23 10:40:49 +04:00
{
2009-02-02 10:24:59 +03:00
struct smbcli_transport * transport = talloc_get_type ( private_data ,
2005-02-03 05:35:52 +03:00
struct smbcli_transport ) ;
2011-09-23 10:35:17 +04:00
struct timeval next ;
2009-02-02 12:17:00 +03:00
transport - > idle . func ( transport , transport - > idle . private_data ) ;
2011-09-23 10:35:17 +04:00
next = timeval_current_ofs_usec ( transport - > idle . period ) ;
transport - > idle . te = tevent_add_timer ( transport - > ev ,
transport ,
next ,
idle_handler ,
transport ) ;
2004-07-23 10:40:49 +04:00
}
2003-08-13 05:53:07 +04:00
/*
setup the idle handler for a transport
2004-11-03 13:09:48 +03:00
the period is in microseconds
2003-08-13 05:53:07 +04:00
*/
2008-04-02 06:53:27 +04:00
_PUBLIC_ void smbcli_transport_idle_handler ( struct smbcli_transport * transport ,
2004-11-03 13:09:48 +03:00
void ( * idle_func ) ( struct smbcli_transport * , void * ) ,
uint64_t period ,
2009-02-02 10:24:59 +03:00
void * private_data )
2003-08-13 05:53:07 +04:00
{
2011-09-23 10:35:17 +04:00
TALLOC_FREE ( transport - > idle . te ) ;
2003-08-13 05:53:07 +04:00
transport - > idle . func = idle_func ;
2009-02-02 12:17:00 +03:00
transport - > idle . private_data = private_data ;
2003-08-13 05:53:07 +04:00
transport - > idle . period = period ;
2011-09-23 10:35:17 +04:00
transport - > idle . te = tevent_add_timer ( transport - > ev ,
transport ,
timeval_current_ofs_usec ( period ) ,
idle_handler ,
transport ) ;
2004-07-23 10:40:49 +04:00
}
2003-08-13 05:53:07 +04:00
/*
2011-09-23 10:35:17 +04:00
process some read / write requests that are pending
return false if the socket is dead
*/
_PUBLIC_ bool smbcli_transport_process ( struct smbcli_transport * transport )
2003-08-13 05:53:07 +04:00
{
2011-09-23 10:35:17 +04:00
struct tevent_req * subreq = NULL ;
int ret ;
2004-08-03 10:52:06 +04:00
2011-09-23 10:35:17 +04:00
if ( ! smbXcli_conn_is_connected ( transport - > conn ) ) {
return false ;
2003-08-13 05:53:07 +04:00
}
2011-09-23 10:35:17 +04:00
if ( ! smbXcli_conn_has_async_calls ( transport - > conn ) ) {
return true ;
2004-07-23 10:40:49 +04:00
}
2003-08-13 05:53:07 +04:00
2011-09-23 10:35:17 +04:00
/*
* do not block for more than 500 micro seconds
*/
subreq = tevent_wakeup_send ( transport ,
transport - > ev ,
timeval_current_ofs_usec ( 500 ) ) ;
if ( subreq = = NULL ) {
return false ;
2004-07-23 10:40:49 +04:00
}
2011-09-23 10:35:17 +04:00
ret = tevent_loop_once ( transport - > ev ) ;
if ( ret ! = 0 ) {
return false ;
2004-07-23 10:40:49 +04:00
}
2011-09-23 10:35:17 +04:00
TALLOC_FREE ( subreq ) ;
2005-11-10 19:09:44 +03:00
2011-09-23 10:35:17 +04:00
if ( ! smbXcli_conn_is_connected ( transport - > conn ) ) {
return false ;
2004-07-23 10:40:49 +04:00
}
2011-09-23 10:35:17 +04:00
return true ;
}
static void smbcli_transport_break_handler ( struct tevent_req * subreq ) ;
static void smbcli_request_done ( struct tevent_req * subreq ) ;
2004-07-23 10:40:49 +04:00
2011-09-23 10:35:17 +04:00
struct tevent_req * smbcli_transport_setup_subreq ( struct smbcli_request * req )
{
struct smbcli_transport * transport = req - > transport ;
uint8_t smb_command ;
uint8_t additional_flags ;
uint8_t clear_flags ;
uint16_t additional_flags2 ;
uint16_t clear_flags2 ;
uint32_t pid ;
2012-07-23 23:34:58 +04:00
struct smbXcli_tcon * tcon = NULL ;
2012-07-23 22:15:21 +04:00
struct smbXcli_session * session = NULL ;
2011-09-23 10:35:17 +04:00
uint32_t timeout_msec = transport - > options . request_timeout * 1000 ;
struct iovec * bytes_iov = NULL ;
struct tevent_req * subreq = NULL ;
smb_command = SVAL ( req - > out . hdr , HDR_COM ) ;
additional_flags = CVAL ( req - > out . hdr , HDR_FLG ) ;
additional_flags2 = SVAL ( req - > out . hdr , HDR_FLG2 ) ;
pid = SVAL ( req - > out . hdr , HDR_PID ) ;
pid | = SVAL ( req - > out . hdr , HDR_PIDHIGH ) < < 16 ;
clear_flags = ~ additional_flags ;
clear_flags2 = ~ additional_flags2 ;
2012-07-23 22:15:21 +04:00
if ( req - > session ) {
session = req - > session - > smbXcli ;
}
2012-07-23 23:34:58 +04:00
if ( req - > tree ) {
tcon = req - > tree - > smbXcli ;
}
2011-09-23 10:35:17 +04:00
bytes_iov = talloc ( req , struct iovec ) ;
if ( bytes_iov = = NULL ) {
return NULL ;
}
bytes_iov - > iov_base = ( void * ) req - > out . data ;
bytes_iov - > iov_len = req - > out . data_size ;
subreq = smb1cli_req_create ( req ,
transport - > ev ,
transport - > conn ,
smb_command ,
additional_flags ,
clear_flags ,
additional_flags2 ,
clear_flags2 ,
timeout_msec ,
pid ,
2012-07-23 23:34:58 +04:00
tcon ,
2012-07-23 22:15:21 +04:00
session ,
2011-09-23 10:35:17 +04:00
req - > out . wct ,
( uint16_t * ) req - > out . vwv ,
1 , bytes_iov ) ;
if ( subreq = = NULL ) {
return NULL ;
2004-08-14 22:24:33 +04:00
}
2011-09-23 10:35:17 +04:00
ZERO_STRUCT ( req - > out ) ;
return subreq ;
}
/*
put a request into the send queue
*/
void smbcli_transport_send ( struct smbcli_request * req )
{
struct smbcli_transport * transport = req - > transport ;
NTSTATUS status ;
bool need_pending_break = false ;
struct tevent_req * subreq = NULL ;
size_t i ;
size_t num_subreqs = 0 ;
if ( transport - > oplock . handler ) {
need_pending_break = true ;
}
if ( transport - > break_subreq ) {
need_pending_break = false ;
}
if ( need_pending_break ) {
subreq = smb1cli_req_create ( transport ,
transport - > ev ,
transport - > conn ,
0 , /* smb_command */
0 , /* additional_flags */
0 , /* clear_flags */
0 , /* additional_flags2 */
0 , /* clear_flags2 */
0 , /* timeout_msec */
0 , /* pid */
2012-07-23 23:34:58 +04:00
NULL , /* tcon */
2012-07-23 22:15:21 +04:00
NULL , /* session */
2011-09-23 10:35:17 +04:00
0 , /* wct */
NULL , /* vwv */
0 , /* iov_count */
NULL ) ; /* bytes_iov */
if ( subreq ! = NULL ) {
smb1cli_req_set_mid ( subreq , 0xFFFF ) ;
smbXcli_req_set_pending ( subreq ) ;
tevent_req_set_callback ( subreq ,
smbcli_transport_break_handler ,
transport ) ;
transport - > break_subreq = subreq ;
subreq = NULL ;
}
2004-07-23 10:40:49 +04:00
}
2011-09-23 10:35:17 +04:00
subreq = smbcli_transport_setup_subreq ( req ) ;
if ( subreq = = NULL ) {
2004-08-04 17:23:35 +04:00
req - > state = SMBCLI_REQUEST_ERROR ;
2011-09-23 10:35:17 +04:00
req - > status = NT_STATUS_NO_MEMORY ;
return ;
2004-07-23 10:40:49 +04:00
}
2011-09-23 10:35:17 +04:00
for ( i = 0 ; i < ARRAY_SIZE ( req - > subreqs ) ; i + + ) {
if ( req - > subreqs [ i ] = = NULL ) {
req - > subreqs [ i ] = subreq ;
subreq = NULL ;
}
if ( req - > subreqs [ i ] = = NULL ) {
break ;
2003-08-13 05:53:07 +04:00
}
2008-02-14 02:12:33 +03:00
2011-09-23 10:35:17 +04:00
if ( ! tevent_req_is_in_progress ( req - > subreqs [ i ] ) ) {
req - > state = SMBCLI_REQUEST_ERROR ;
req - > status = NT_STATUS_INTERNAL_ERROR ;
return ;
2005-07-04 05:23:38 +04:00
}
}
2011-09-23 10:35:17 +04:00
num_subreqs = i ;
2005-07-04 05:23:38 +04:00
2011-09-23 10:35:17 +04:00
req - > state = SMBCLI_REQUEST_RECV ;
tevent_req_set_callback ( req - > subreqs [ 0 ] , smbcli_request_done , req ) ;
status = smb1cli_req_chain_submit ( req - > subreqs , num_subreqs ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-12-09 14:05:47 +04:00
req - > status = status ;
req - > state = SMBCLI_REQUEST_ERROR ;
2011-09-23 10:35:17 +04:00
smbXcli_conn_disconnect ( transport - > conn , status ) ;
2004-07-23 10:40:49 +04:00
}
2011-09-23 10:35:17 +04:00
}
2004-07-23 10:40:49 +04:00
2011-09-23 10:35:17 +04:00
static void smbcli_request_done ( struct tevent_req * subreq )
{
struct smbcli_request * req =
tevent_req_callback_data ( subreq ,
struct smbcli_request ) ;
struct smbcli_transport * transport = req - > transport ;
ssize_t len ;
size_t i ;
uint8_t * hdr = NULL ;
uint8_t wct = 0 ;
uint16_t * vwv = NULL ;
uint32_t num_bytes = 0 ;
uint8_t * bytes = NULL ;
struct iovec * recv_iov = NULL ;
uint8_t * inbuf = NULL ;
req - > status = smb1cli_req_recv ( req - > subreqs [ 0 ] , req ,
& recv_iov ,
& hdr ,
& wct ,
& vwv ,
NULL , /* pvwv_offset */
& num_bytes ,
& bytes ,
NULL , /* pbytes_offset */
& inbuf ,
NULL , 0 ) ; /* expected */
TALLOC_FREE ( req - > subreqs [ 0 ] ) ;
if ( ! NT_STATUS_IS_OK ( req - > status ) ) {
if ( recv_iov = = NULL ) {
req - > state = SMBCLI_REQUEST_ERROR ;
transport - > error . e . nt_status = req - > status ;
transport - > error . etype = ETYPE_SOCKET ;
if ( req - > async . fn ) {
req - > async . fn ( req ) ;
}
return ;
}
}
2004-07-23 10:40:49 +04:00
2011-09-23 10:35:17 +04:00
/*
* For SMBreadBraw hdr is NULL
*/
len = recv_iov [ 0 ] . iov_len ;
for ( i = 1 ; hdr ! = NULL & & i < 3 ; i + + ) {
uint8_t * p = recv_iov [ i - 1 ] . iov_base ;
uint8_t * c1 = recv_iov [ i ] . iov_base ;
uint8_t * c2 = p + recv_iov [ i - 1 ] . iov_len ;
2008-07-04 21:52:23 +04:00
2011-09-23 10:35:17 +04:00
len + = recv_iov [ i ] . iov_len ;
2008-07-04 21:52:23 +04:00
2011-09-23 10:35:17 +04:00
c2 + = i ;
len + = i ;
2008-07-04 21:52:23 +04:00
2011-09-23 10:35:17 +04:00
if ( recv_iov [ i ] . iov_len = = 0 ) {
continue ;
2008-07-04 21:52:23 +04:00
}
2004-07-23 10:40:49 +04:00
2011-09-23 10:35:17 +04:00
if ( c1 ! = c2 ) {
req - > state = SMBCLI_REQUEST_ERROR ;
req - > status = NT_STATUS_INTERNAL_ERROR ;
transport - > error . e . nt_status = req - > status ;
transport - > error . etype = ETYPE_SMB ;
if ( req - > async . fn ) {
req - > async . fn ( req ) ;
}
return ;
2005-11-11 10:38:25 +03:00
}
2004-07-23 10:40:49 +04:00
}
2005-11-09 11:13:41 +03:00
2011-09-23 10:35:17 +04:00
/* fill in the 'in' portion of the matching request */
req - > in . buffer = inbuf ;
req - > in . size = NBT_HDR_SIZE + len ;
req - > in . allocated = req - > in . size ;
2005-11-09 11:13:41 +03:00
2011-09-23 10:35:17 +04:00
req - > in . hdr = hdr ;
req - > in . vwv = ( uint8_t * ) vwv ;
req - > in . wct = wct ;
req - > in . data = bytes ;
req - > in . data_size = num_bytes ;
req - > in . ptr = req - > in . data ;
if ( hdr ! = NULL ) {
req - > flags2 = SVAL ( req - > in . hdr , HDR_FLG2 ) ;
2004-07-23 10:40:49 +04:00
}
2004-04-07 11:18:37 +04:00
2011-09-23 10:35:17 +04:00
smb_setup_bufinfo ( req ) ;
2005-06-17 03:19:03 +04:00
2011-09-23 10:35:17 +04:00
transport - > error . e . nt_status = req - > status ;
if ( NT_STATUS_IS_OK ( req - > status ) ) {
transport - > error . etype = ETYPE_NONE ;
} else {
transport - > error . etype = ETYPE_SMB ;
2005-06-17 03:19:03 +04:00
}
2011-09-23 10:35:17 +04:00
req - > state = SMBCLI_REQUEST_DONE ;
2005-06-17 03:19:03 +04:00
if ( req - > async . fn ) {
req - > async . fn ( req ) ;
}
}
2011-09-23 10:35:17 +04:00
static void smbcli_transport_break_handler ( struct tevent_req * subreq )
2005-06-17 03:19:03 +04:00
{
2011-09-23 10:35:17 +04:00
struct smbcli_transport * transport =
tevent_req_callback_data ( subreq ,
struct smbcli_transport ) ;
2005-11-09 16:34:36 +03:00
NTSTATUS status ;
2011-09-23 10:35:17 +04:00
struct iovec * recv_iov = NULL ;
uint8_t * hdr = NULL ;
uint16_t * vwv = NULL ;
const struct smb1cli_req_expected_response expected [ ] = {
{
. status = NT_STATUS_OK ,
. wct = 8 ,
2004-08-03 12:04:11 +04:00
}
2011-09-23 10:35:17 +04:00
} ;
uint16_t tid ;
uint16_t fnum ;
uint8_t level ;
transport - > break_subreq = NULL ;
status = smb1cli_req_recv ( subreq , transport ,
& recv_iov ,
& hdr ,
NULL , /* pwct */
& vwv ,
NULL , /* pvwv_offset */
NULL , /* pnum_bytes */
NULL , /* pbytes */
NULL , /* pbytes_offset */
NULL , /* pinbuf */
expected ,
ARRAY_SIZE ( expected ) ) ;
TALLOC_FREE ( subreq ) ;
2005-11-09 16:34:36 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-09-23 10:35:17 +04:00
TALLOC_FREE ( recv_iov ) ;
smbcli_transport_dead ( transport , status ) ;
2005-11-09 16:34:36 +03:00
return ;
}
2004-07-23 10:40:49 +04:00
2011-09-23 10:35:17 +04:00
/*
* Setup the subreq to handle the
* next incoming SMB2 Break .
*/
subreq = smb1cli_req_create ( transport ,
transport - > ev ,
transport - > conn ,
0 , /* smb_command */
0 , /* additional_flags */
0 , /* clear_flags */
0 , /* additional_flags2 */
0 , /* clear_flags2 */
0 , /* timeout_msec */
0 , /* pid */
2012-07-23 23:34:58 +04:00
NULL , /* tcon */
2012-07-23 22:15:21 +04:00
NULL , /* session */
2011-09-23 10:35:17 +04:00
0 , /* wct */
NULL , /* vwv */
0 , /* iov_count */
NULL ) ; /* bytes_iov */
if ( subreq ! = NULL ) {
smb1cli_req_set_mid ( subreq , 0xFFFF ) ;
smbXcli_req_set_pending ( subreq ) ;
tevent_req_set_callback ( subreq ,
smbcli_transport_break_handler ,
transport ) ;
transport - > break_subreq = subreq ;
}
tid = SVAL ( hdr , HDR_TID ) ;
fnum = SVAL ( vwv + 2 , 0 ) ;
level = CVAL ( vwv + 3 , 1 ) ;
TALLOC_FREE ( recv_iov ) ;
if ( transport - > oplock . handler ) {
transport - > oplock . handler ( transport , tid , fnum , level ,
transport - > oplock . private_data ) ;
} else {
DEBUG ( 5 , ( " Got SMB oplock break with no handler \n " ) ) ;
2005-06-17 03:19:03 +04:00
}
2004-07-23 10:40:49 +04:00
}
2007-05-25 14:42:29 +04:00
/****************************************************************************
Send an SMBecho ( async send )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-04-02 06:53:27 +04:00
_PUBLIC_ struct smbcli_request * smb_raw_echo_send ( struct smbcli_transport * transport ,
2007-05-25 14:42:29 +04:00
struct smb_echo * p )
{
struct smbcli_request * req ;
req = smbcli_request_setup_transport ( transport , SMBecho , 1 , p - > in . size ) ;
if ( ! req ) return NULL ;
SSVAL ( req - > out . vwv , VWV ( 0 ) , p - > in . repeat_count ) ;
memcpy ( req - > out . data , p - > in . data , p - > in . size ) ;
ZERO_STRUCT ( p - > out ) ;
if ( ! smbcli_request_send ( req ) ) {
smbcli_request_destroy ( req ) ;
return NULL ;
}
return req ;
}
/****************************************************************************
raw echo interface ( async recv )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS smb_raw_echo_recv ( struct smbcli_request * req , TALLOC_CTX * mem_ctx ,
struct smb_echo * p )
{
if ( ! smbcli_request_receive ( req ) | |
smbcli_request_is_error ( req ) ) {
goto failed ;
}
SMBCLI_CHECK_WCT ( req , 1 ) ;
p - > out . count + + ;
p - > out . sequence_number = SVAL ( req - > in . vwv , VWV ( 0 ) ) ;
p - > out . size = req - > in . data_size ;
talloc_free ( p - > out . data ) ;
2007-09-07 17:31:15 +04:00
p - > out . data = talloc_array ( mem_ctx , uint8_t , p - > out . size ) ;
2007-05-25 14:42:29 +04:00
NT_STATUS_HAVE_NO_MEMORY ( p - > out . data ) ;
2008-02-14 02:12:33 +03:00
if ( ! smbcli_raw_pull_data ( & req - > in . bufinfo , req - > in . data , p - > out . size , p - > out . data ) ) {
2007-05-25 14:42:29 +04:00
req - > status = NT_STATUS_BUFFER_TOO_SMALL ;
}
if ( p - > out . count = = p - > in . repeat_count ) {
return smbcli_request_destroy ( req ) ;
}
return NT_STATUS_OK ;
failed :
return smbcli_request_destroy ( req ) ;
}
/****************************************************************************
Send a echo ( sync interface )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS smb_raw_echo ( struct smbcli_transport * transport , struct smb_echo * p )
{
struct smbcli_request * req = smb_raw_echo_send ( transport , p ) ;
return smbcli_request_simple_recv ( req ) ;
}