2007-12-01 05:02:19 +03:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2000-04-25 18:04:06 +04:00
client transaction calls
Copyright ( C ) Andrew Tridgell 1994 - 1998
2007-12-01 05:02:19 +03:00
2000-04-25 18:04:06 +04:00
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-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2000-04-25 18:04:06 +04:00
( at your option ) any later version .
2007-12-01 05:02:19 +03:00
2000-04-25 18:04:06 +04:00
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 .
2007-12-01 05:02:19 +03:00
2000-04-25 18:04:06 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2000-04-25 18:04:06 +04:00
*/
# include "includes.h"
2011-05-06 13:47:43 +04:00
# include "libsmb/libsmb.h"
2011-04-28 19:38:09 +04:00
# include "../lib/util/tevent_ntstatus.h"
2010-08-26 11:58:09 +04:00
# include "async_smb.h"
2011-08-28 20:05:04 +04:00
# include "../libcli/smb/smbXcli_base.h"
2008-09-09 16:47:23 +04:00
struct cli_trans_state {
struct cli_state * cli ;
2018-11-16 23:03:45 +03:00
struct tevent_req * subreq ;
2018-11-16 23:01:19 +03:00
uint16_t recv_flags2 ;
uint16_t * setup ;
uint8_t num_setup ;
uint8_t * param ;
uint32_t num_param ;
uint8_t * data ;
uint32_t num_data ;
2008-09-09 16:47:23 +04:00
} ;
2018-11-16 23:01:19 +03:00
static void cli_trans_done ( struct tevent_req * subreq ) ;
2018-11-16 23:03:45 +03:00
static bool cli_trans_cancel ( struct tevent_req * req ) ;
2008-09-09 16:47:23 +04:00
2009-04-05 22:51:52 +04:00
struct tevent_req * cli_trans_send (
2011-10-26 17:43:08 +04:00
TALLOC_CTX * mem_ctx , struct tevent_context * ev ,
2016-08-18 22:45:32 +03:00
struct cli_state * cli , uint16_t additional_flags2 , uint8_t cmd ,
2009-04-05 22:51:52 +04:00
const char * pipe_name , uint16_t fid , uint16_t function , int flags ,
uint16_t * setup , uint8_t num_setup , uint8_t max_setup ,
uint8_t * param , uint32_t num_param , uint32_t max_param ,
uint8_t * data , uint32_t num_data , uint32_t max_data )
2008-09-09 16:47:23 +04:00
{
2018-11-16 23:03:45 +03:00
struct tevent_req * req ;
2009-04-05 22:51:52 +04:00
struct cli_trans_state * state ;
2011-08-28 20:05:04 +04:00
uint8_t additional_flags = 0 ;
uint8_t clear_flags = 0 ;
uint16_t clear_flags2 = 0 ;
2009-03-09 11:50:36 +03:00
2018-11-16 23:01:19 +03:00
req = tevent_req_create ( mem_ctx , & state , struct cli_trans_state ) ;
if ( req = = NULL ) {
2009-04-05 22:51:52 +04:00
return NULL ;
2008-09-09 16:47:23 +04:00
}
2009-04-05 22:51:52 +04:00
state - > cli = cli ;
2018-11-16 23:01:19 +03:00
2018-11-16 23:03:45 +03:00
state - > subreq = smb1cli_trans_send ( state , ev ,
cli - > conn , cmd ,
additional_flags , clear_flags ,
additional_flags2 , clear_flags2 ,
cli - > timeout ,
cli - > smb1 . pid ,
cli - > smb1 . tcon ,
cli - > smb1 . session ,
pipe_name , fid , function , flags ,
setup , num_setup , max_setup ,
param , num_param , max_param ,
data , num_data , max_data ) ;
if ( tevent_req_nomem ( state - > subreq , req ) ) {
2018-11-16 23:01:19 +03:00
return tevent_req_post ( req , ev ) ;
2008-09-09 16:47:23 +04:00
}
2018-11-16 23:03:45 +03:00
tevent_req_set_callback ( state - > subreq , cli_trans_done , req ) ;
tevent_req_set_cancel_fn ( req , cli_trans_cancel ) ;
2018-11-16 23:01:19 +03:00
return req ;
}
2011-06-08 18:11:00 +04:00
2018-11-16 23:03:45 +03:00
static bool cli_trans_cancel ( struct tevent_req * req )
{
struct cli_trans_state * state = tevent_req_data (
req , struct cli_trans_state ) ;
bool ok ;
ok = tevent_req_cancel ( state - > subreq ) ;
return ok ;
}
2018-11-16 23:01:19 +03:00
static void cli_trans_done ( struct tevent_req * subreq )
{
struct tevent_req * req = tevent_req_callback_data (
subreq , struct tevent_req ) ;
struct cli_trans_state * state = tevent_req_data (
req , struct cli_trans_state ) ;
NTSTATUS status ;
2011-06-08 18:11:00 +04:00
2018-11-16 23:01:19 +03:00
status = smb1cli_trans_recv (
subreq ,
state ,
& state - > recv_flags2 ,
& state - > setup , 0 , & state - > num_setup ,
& state - > param , 0 , & state - > num_param ,
& state - > data , 0 , & state - > num_data ) ;
TALLOC_FREE ( subreq ) ;
if ( tevent_req_nterror ( req , status ) ) {
return ;
}
tevent_req_done ( req ) ;
2008-09-09 16:47:23 +04:00
}
2009-04-05 22:51:52 +04:00
NTSTATUS cli_trans_recv ( struct tevent_req * req , TALLOC_CTX * mem_ctx ,
2010-08-05 14:48:52 +04:00
uint16_t * recv_flags2 ,
2009-11-14 13:12:50 +03:00
uint16_t * * setup , uint8_t min_setup ,
uint8_t * num_setup ,
uint8_t * * param , uint32_t min_param ,
uint32_t * num_param ,
uint8_t * * data , uint32_t min_data ,
uint32_t * num_data )
2008-09-09 16:47:23 +04:00
{
2018-11-16 23:01:19 +03:00
struct cli_trans_state * state = tevent_req_data (
req , struct cli_trans_state ) ;
NTSTATUS status = NT_STATUS_OK ;
2011-08-28 20:05:04 +04:00
bool map_dos_errors = true ;
2018-11-16 23:01:19 +03:00
if ( tevent_req_is_nterror ( req , & status ) ) {
goto map_error ;
}
if ( ( state - > num_setup < min_setup ) | |
( state - > num_param < min_param ) | |
( state - > num_data < min_data ) ) {
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2011-08-28 20:05:04 +04:00
2018-11-16 23:01:19 +03:00
if ( recv_flags2 ! = NULL ) {
* recv_flags2 = state - > recv_flags2 ;
}
if ( setup ! = NULL ) {
* setup = talloc_move ( mem_ctx , & state - > setup ) ;
* num_setup = state - > num_setup ;
}
if ( param ! = NULL ) {
* param = talloc_move ( mem_ctx , & state - > param ) ;
* num_param = state - > num_param ;
}
if ( data ! = NULL ) {
* data = talloc_move ( mem_ctx , & state - > data ) ;
* num_data = state - > num_data ;
2011-08-28 20:05:04 +04:00
}
2018-11-16 23:01:19 +03:00
map_error :
map_dos_errors = state - > cli - > map_dos_errors ;
state - > cli - > raw_status = status ;
2011-08-28 20:05:04 +04:00
if ( NT_STATUS_IS_DOS ( status ) & & map_dos_errors ) {
uint8_t eclass = NT_STATUS_DOS_CLASS ( status ) ;
uint16_t ecode = NT_STATUS_DOS_CODE ( status ) ;
/*
* TODO : is it really a good idea to do a mapping here ?
*
* The old cli_pull_error ( ) also does it , so I do not change
* the behavior yet .
*/
status = dos_to_ntstatus ( eclass , ecode ) ;
2008-09-09 16:47:23 +04:00
}
2011-08-28 20:05:04 +04:00
return status ;
2008-09-09 16:47:23 +04:00
}
NTSTATUS cli_trans ( TALLOC_CTX * mem_ctx , struct cli_state * cli ,
uint8_t trans_cmd ,
const char * pipe_name , uint16_t fid , uint16_t function ,
int flags ,
uint16_t * setup , uint8_t num_setup , uint8_t max_setup ,
uint8_t * param , uint32_t num_param , uint32_t max_param ,
uint8_t * data , uint32_t num_data , uint32_t max_data ,
2010-08-05 14:48:52 +04:00
uint16_t * recv_flags2 ,
2009-11-14 13:12:50 +03:00
uint16_t * * rsetup , uint8_t min_rsetup , uint8_t * num_rsetup ,
uint8_t * * rparam , uint32_t min_rparam , uint32_t * num_rparam ,
uint8_t * * rdata , uint32_t min_rdata , uint32_t * num_rdata )
2008-09-09 16:47:23 +04:00
{
2018-11-16 23:01:19 +03:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
struct tevent_context * ev ;
struct tevent_req * req ;
NTSTATUS status = NT_STATUS_NO_MEMORY ;
2008-09-09 16:47:23 +04:00
2018-11-16 23:01:19 +03:00
if ( smbXcli_conn_has_async_calls ( cli - > conn ) ) {
2008-09-09 16:47:23 +04:00
/*
2018-11-16 23:01:19 +03:00
* Can ' t use sync call while an async call is in flight
2008-09-09 16:47:23 +04:00
*/
2018-11-16 23:01:19 +03:00
status = NT_STATUS_INVALID_PARAMETER ;
goto fail ;
2008-09-09 16:47:23 +04:00
}
2018-11-16 23:01:19 +03:00
ev = samba_tevent_context_init ( frame ) ;
if ( ev = = NULL ) {
goto fail ;
}
req = cli_trans_send (
frame , /* mem_ctx */
ev , /* ev */
cli , /* cli */
0 , /* additional_flags2 */
trans_cmd , /* cmd */
pipe_name , fid , function , flags ,
setup , num_setup , max_setup ,
param , num_param , max_param ,
data , num_data , max_data ) ;
if ( req = = NULL ) {
goto fail ;
}
if ( ! tevent_req_poll_ntstatus ( req , ev , & status ) ) {
goto fail ;
}
status = cli_trans_recv (
req , mem_ctx , recv_flags2 ,
rsetup , min_rsetup , num_rsetup ,
rparam , min_rparam , num_rparam ,
rdata , min_rdata , num_rdata ) ;
fail :
TALLOC_FREE ( frame ) ;
2008-09-09 16:47:23 +04:00
return status ;
}