1996-05-04 11:50:46 +04:00
/*
Unix SMB / Netbios implementation .
Version 1.9 .
Inter - process communication and named pipe handling
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1992 - 1998
1997-07-09 15:04:45 +04:00
SMB Version handling
1998-01-22 16:27:43 +03:00
Copyright ( C ) John H Terpstra 1995 - 1998
1996-05-04 11:50:46 +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
the Free Software Foundation ; either version 2 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 , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
/*
This file handles the named pipe and mailslot calls
in the SMBtrans protocol
*/
# include "includes.h"
1997-02-28 23:39:36 +03:00
extern int max_send ;
1996-05-04 11:50:46 +04:00
1998-10-23 04:58:28 +04:00
extern fstring local_machine ;
1996-05-04 11:50:46 +04:00
# define NERR_notsupported 50
1997-11-19 02:30:49 +03:00
extern int smb_read_error ;
1996-05-04 11:50:46 +04:00
1998-03-12 00:11:04 +03:00
/*******************************************************************
copies parameters and data , as needed , into the smb buffer
* both * the data and params sections should be aligned . this
is fudged in the rpc pipes by
at present , only the data section is . this may be a possible
cause of some of the ipc problems being experienced . lkcl26dec97
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1998-03-12 00:11:04 +03:00
static void copy_trans_params_and_data ( char * outbuf , int align ,
1999-12-13 16:27:58 +03:00
char * rparam , int param_offset , int param_len ,
char * rdata , int data_offset , int data_len )
1998-03-12 00:11:04 +03:00
{
1998-09-03 09:37:15 +04:00
char * copy_into = smb_buf ( outbuf ) + 1 ;
1998-03-12 00:11:04 +03:00
1999-12-13 16:27:58 +03:00
if ( param_len < 0 )
param_len = 0 ;
if ( data_len < 0 )
data_len = 0 ;
1998-03-12 00:11:04 +03:00
DEBUG ( 5 , ( " copy_trans_params_and_data: params[%d..%d] data[%d..%d] \n " ,
param_offset , param_offset + param_len ,
data_offset , data_offset + data_len ) ) ;
1999-12-13 16:27:58 +03:00
if ( param_len )
memcpy ( copy_into , & rparam [ param_offset ] , param_len ) ;
1998-03-12 00:11:04 +03:00
copy_into + = param_len + align ;
1999-12-13 16:27:58 +03:00
if ( data_len )
memcpy ( copy_into , & rdata [ data_offset ] , data_len ) ;
1998-03-12 00:11:04 +03:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
1999-12-13 16:27:58 +03:00
Send a trans reply .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-19 11:00:22 +04:00
void send_trans_reply ( char * outbuf ,
1999-12-13 16:27:58 +03:00
char * rparam , int rparam_len ,
char * rdata , int rdata_len ,
BOOL buffer_too_large )
1996-05-04 11:50:46 +04:00
{
1998-03-12 00:11:04 +03:00
int this_ldata , this_lparam ;
1999-12-13 16:27:58 +03:00
int tot_data_sent = 0 ;
int tot_param_sent = 0 ;
1998-03-12 00:11:04 +03:00
int align ;
1999-12-13 16:27:58 +03:00
int ldata = rdata ? rdata_len : 0 ;
int lparam = rparam ? rparam_len : 0 ;
1998-03-12 00:11:04 +03:00
if ( buffer_too_large )
1999-12-13 16:27:58 +03:00
DEBUG ( 5 , ( " send_trans_reply: buffer %d too large \n " , ldata ) ) ;
1998-03-12 00:11:04 +03:00
1999-12-13 16:27:58 +03:00
this_lparam = MIN ( lparam , max_send - 500 ) ; /* hack */
this_ldata = MIN ( ldata , max_send - ( 500 + this_lparam ) ) ;
1996-05-04 11:50:46 +04:00
1998-09-03 09:37:15 +04:00
align = ( ( this_lparam ) % 4 ) ;
1996-05-04 11:50:46 +04:00
2001-08-27 12:19:43 +04:00
if ( buffer_too_large ) {
ERROR_NT ( STATUS_BUFFER_OVERFLOW ) ;
1998-03-12 00:11:04 +03:00
}
2001-08-27 12:19:43 +04:00
set_message ( outbuf , 10 , 1 + align + this_ldata + this_lparam , True ) ;
1998-03-12 00:11:04 +03:00
copy_trans_params_and_data ( outbuf , align ,
1999-12-13 16:27:58 +03:00
rparam , tot_param_sent , this_lparam ,
rdata , tot_data_sent , this_ldata ) ;
1998-03-12 00:11:04 +03:00
SSVAL ( outbuf , smb_vwv0 , lparam ) ;
SSVAL ( outbuf , smb_vwv1 , ldata ) ;
SSVAL ( outbuf , smb_vwv3 , this_lparam ) ;
1998-09-03 09:37:15 +04:00
SSVAL ( outbuf , smb_vwv4 , smb_offset ( smb_buf ( outbuf ) + 1 , outbuf ) ) ;
1998-03-12 00:11:04 +03:00
SSVAL ( outbuf , smb_vwv5 , 0 ) ;
SSVAL ( outbuf , smb_vwv6 , this_ldata ) ;
1998-09-03 09:37:15 +04:00
SSVAL ( outbuf , smb_vwv7 , smb_offset ( smb_buf ( outbuf ) + 1 + this_lparam + align , outbuf ) ) ;
1998-03-12 00:11:04 +03:00
SSVAL ( outbuf , smb_vwv8 , 0 ) ;
1999-12-13 16:27:58 +03:00
SSVAL ( outbuf , smb_vwv9 , 0 ) ;
1998-03-12 00:11:04 +03:00
show_msg ( outbuf ) ;
2001-06-09 05:38:54 +04:00
if ( ! send_smb ( smbd_server_fd ( ) , outbuf ) )
2001-11-05 03:02:38 +03:00
exit_server ( " send_trans_reply: send_smb failed. " ) ;
1998-03-12 00:11:04 +03:00
1999-12-13 16:27:58 +03:00
tot_data_sent = this_ldata ;
tot_param_sent = this_lparam ;
1998-03-12 00:11:04 +03:00
1999-12-13 16:27:58 +03:00
while ( tot_data_sent < ldata | | tot_param_sent < lparam )
1998-03-12 00:11:04 +03:00
{
1999-12-13 16:27:58 +03:00
this_lparam = MIN ( lparam - tot_param_sent , max_send - 500 ) ; /* hack */
this_ldata = MIN ( ldata - tot_data_sent , max_send - ( 500 + this_lparam ) ) ;
if ( this_lparam < 0 )
this_lparam = 0 ;
if ( this_ldata < 0 )
this_ldata = 0 ;
1998-03-12 00:11:04 +03:00
align = ( this_lparam % 4 ) ;
1998-09-03 09:37:15 +04:00
set_message ( outbuf , 10 , 1 + this_ldata + this_lparam + align , False ) ;
1998-03-12 00:11:04 +03:00
copy_trans_params_and_data ( outbuf , align ,
1999-12-13 16:27:58 +03:00
rparam , tot_param_sent , this_lparam ,
rdata , tot_data_sent , this_ldata ) ;
1998-03-12 00:11:04 +03:00
SSVAL ( outbuf , smb_vwv3 , this_lparam ) ;
1998-09-03 09:37:15 +04:00
SSVAL ( outbuf , smb_vwv4 , smb_offset ( smb_buf ( outbuf ) + 1 , outbuf ) ) ;
1999-12-13 16:27:58 +03:00
SSVAL ( outbuf , smb_vwv5 , tot_param_sent ) ;
1998-03-12 00:11:04 +03:00
SSVAL ( outbuf , smb_vwv6 , this_ldata ) ;
1998-09-03 09:37:15 +04:00
SSVAL ( outbuf , smb_vwv7 , smb_offset ( smb_buf ( outbuf ) + 1 + this_lparam + align , outbuf ) ) ;
1999-12-13 16:27:58 +03:00
SSVAL ( outbuf , smb_vwv8 , tot_data_sent ) ;
1998-03-12 00:11:04 +03:00
SSVAL ( outbuf , smb_vwv9 , 0 ) ;
show_msg ( outbuf ) ;
2001-06-09 05:38:54 +04:00
if ( ! send_smb ( smbd_server_fd ( ) , outbuf ) )
2001-11-05 03:02:38 +03:00
exit_server ( " send_trans_reply: send_smb failed. " ) ;
1998-03-12 00:11:04 +03:00
1999-12-13 16:27:58 +03:00
tot_data_sent + = this_ldata ;
tot_param_sent + = this_lparam ;
1998-03-12 00:11:04 +03:00
}
1996-05-04 11:50:46 +04:00
}
1999-12-13 16:27:58 +03:00
/****************************************************************************
Start the first part of an RPC reply which began with an SMBtrans request .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-03-10 00:45:16 +03:00
static BOOL api_rpc_trans_reply ( char * outbuf , pipes_struct * p )
1998-03-12 00:11:04 +03:00
{
2000-03-10 00:45:16 +03:00
char * rdata = malloc ( p - > max_trans_reply ) ;
1999-12-13 16:27:58 +03:00
int data_len ;
1998-03-12 00:11:04 +03:00
1999-12-13 16:27:58 +03:00
if ( rdata = = NULL ) {
DEBUG ( 0 , ( " api_rpc_trans_reply: malloc fail. \n " ) ) ;
return False ;
1998-03-12 00:11:04 +03:00
}
1999-12-13 16:27:58 +03:00
if ( ( data_len = read_from_pipe ( p , rdata , p - > max_trans_reply ) ) < 0 ) {
2001-09-17 15:25:41 +04:00
SAFE_FREE ( rdata ) ;
1999-12-13 16:27:58 +03:00
return False ;
}
2000-03-30 02:19:58 +04:00
send_trans_reply ( outbuf , NULL , 0 , rdata , data_len , p - > out_data . current_pdu_len > data_len ) ;
1999-12-13 16:27:58 +03:00
2001-09-17 15:25:41 +04:00
SAFE_FREE ( rdata ) ;
1999-12-13 16:27:58 +03:00
return True ;
1998-03-12 00:11:04 +03:00
}
1998-10-15 09:47:29 +04:00
/****************************************************************************
WaitNamedPipeHandleState
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
static BOOL api_WNPHS ( char * outbuf , pipes_struct * p , char * param , int param_len )
1998-10-15 09:47:29 +04:00
{
uint16 priority ;
1999-12-13 16:27:58 +03:00
if ( ! param | | param_len < 2 )
return False ;
1998-10-15 09:47:29 +04:00
1999-12-13 16:27:58 +03:00
priority = SVAL ( param , 0 ) ;
1998-10-15 09:47:29 +04:00
DEBUG ( 4 , ( " WaitNamedPipeHandleState priority %x \n " , priority ) ) ;
1999-12-13 16:27:58 +03:00
if ( wait_rpc_pipe_hnd_state ( p , priority ) ) {
1998-10-15 09:47:29 +04:00
/* now send the reply */
1999-12-13 16:27:58 +03:00
send_trans_reply ( outbuf , NULL , 0 , NULL , 0 , False ) ;
1998-10-15 09:47:29 +04:00
return True ;
}
return False ;
}
1998-03-12 00:11:04 +03:00
/****************************************************************************
SetNamedPipeHandleState
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
static BOOL api_SNPHS ( char * outbuf , pipes_struct * p , char * param , int param_len )
1998-03-12 00:11:04 +03:00
{
uint16 id ;
1999-12-13 16:27:58 +03:00
if ( ! param | | param_len < 2 )
return False ;
1998-03-12 00:11:04 +03:00
1999-12-13 16:27:58 +03:00
id = SVAL ( param , 0 ) ;
1998-10-15 09:47:29 +04:00
DEBUG ( 4 , ( " SetNamedPipeHandleState to code %x \n " , id ) ) ;
1998-03-12 00:11:04 +03:00
1999-12-13 16:27:58 +03:00
if ( set_rpc_pipe_hnd_state ( p , id ) ) {
1998-03-12 00:11:04 +03:00
/* now send the reply */
1999-12-13 16:27:58 +03:00
send_trans_reply ( outbuf , NULL , 0 , NULL , 0 , False ) ;
1998-03-12 00:11:04 +03:00
return True ;
}
return False ;
1996-08-15 19:11:34 +04:00
}
1998-03-12 00:11:04 +03:00
/****************************************************************************
1999-12-13 16:27:58 +03:00
When no reply is generated , indicate unsupported .
1998-03-12 00:11:04 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1998-03-12 00:11:04 +03:00
static BOOL api_no_reply ( char * outbuf , int max_rdata_len )
{
1999-12-13 16:27:58 +03:00
char rparam [ 4 ] ;
1998-03-12 00:11:04 +03:00
/* unsupported */
1999-12-13 16:27:58 +03:00
SSVAL ( rparam , 0 , NERR_notsupported ) ;
SSVAL ( rparam , 2 , 0 ) ; /* converter word */
1998-03-12 00:11:04 +03:00
DEBUG ( 3 , ( " Unsupported API fd command \n " ) ) ;
/* now send the reply */
1999-12-13 16:27:58 +03:00
send_trans_reply ( outbuf , rparam , 4 , NULL , 0 , False ) ;
1998-03-12 00:11:04 +03:00
1999-12-13 16:27:58 +03:00
return - 1 ;
1998-03-12 00:11:04 +03:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Handle remote api calls delivered to a named pipe already opened .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
static int api_fd_reply ( connection_struct * conn , uint16 vuid , char * outbuf ,
1998-03-12 00:11:04 +03:00
uint16 * setup , char * data , char * params ,
int suwcnt , int tdscnt , int tpscnt , int mdrcnt , int mprcnt )
{
1999-12-13 16:27:58 +03:00
BOOL reply = False ;
1998-03-12 00:11:04 +03:00
pipes_struct * p = NULL ;
1999-12-13 16:27:58 +03:00
int pnum ;
int subcommand ;
1998-03-12 00:11:04 +03:00
DEBUG ( 5 , ( " api_fd_reply \n " ) ) ;
/* First find out the name of this file. */
1999-12-13 16:27:58 +03:00
if ( suwcnt ! = 2 ) {
1998-03-12 00:11:04 +03:00
DEBUG ( 0 , ( " Unexpected named pipe transaction. \n " ) ) ;
return ( - 1 ) ;
}
/* Get the file handle and hence the file name. */
1999-12-13 16:27:58 +03:00
/*
* NB . The setup array has already been transformed
* via SVAL and so is in gost byte order .
*/
pnum = ( ( int ) setup [ 1 ] ) & 0xFFFF ;
subcommand = ( ( int ) setup [ 0 ] ) & 0xFFFF ;
1998-03-12 00:11:04 +03:00
1999-12-13 16:27:58 +03:00
if ( ! ( p = get_rpc_pipe ( pnum ) ) ) {
DEBUG ( 1 , ( " api_fd_reply: INVALID PIPE HANDLE: %x \n " , pnum ) ) ;
return api_no_reply ( outbuf , mdrcnt ) ;
}
1998-03-12 00:11:04 +03:00
1999-12-13 16:27:58 +03:00
DEBUG ( 3 , ( " Got API command 0x%x on pipe \" %s \" (pnum %x) " , subcommand , p - > name , pnum ) ) ;
1998-03-12 00:11:04 +03:00
1999-12-13 16:27:58 +03:00
/* record maximum data length that can be transmitted in an SMBtrans */
p - > max_trans_reply = mdrcnt ;
1998-04-10 22:21:16 +04:00
1999-12-13 16:27:58 +03:00
DEBUG ( 10 , ( " api_fd_reply: p:%p max_trans_reply: %d \n " , p , p - > max_trans_reply ) ) ;
switch ( subcommand ) {
case 0x26 :
2000-03-10 00:45:16 +03:00
/* dce/rpc command */
reply = write_to_pipe ( p , data , tdscnt ) ;
1999-12-13 16:27:58 +03:00
if ( reply )
2000-03-10 00:45:16 +03:00
reply = api_rpc_trans_reply ( outbuf , p ) ;
1999-12-13 16:27:58 +03:00
break ;
case 0x53 :
/* Wait Named Pipe Handle state */
reply = api_WNPHS ( outbuf , p , params , tpscnt ) ;
break ;
case 0x01 :
/* Set Named Pipe Handle state */
reply = api_SNPHS ( outbuf , p , params , tpscnt ) ;
break ;
1998-03-12 00:11:04 +03:00
}
if ( ! reply )
return api_no_reply ( outbuf , mdrcnt ) ;
1999-12-13 16:27:58 +03:00
1998-03-12 00:11:04 +03:00
return - 1 ;
}
1996-08-15 19:11:34 +04:00
1996-05-04 11:50:46 +04:00
/****************************************************************************
handle named pipe commands
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
static int named_pipe ( connection_struct * conn , uint16 vuid , char * outbuf , char * name ,
1996-05-04 11:50:46 +04:00
uint16 * setup , char * data , char * params ,
int suwcnt , int tdscnt , int tpscnt ,
int msrcnt , int mdrcnt , int mprcnt )
{
1997-10-24 17:15:34 +04:00
DEBUG ( 3 , ( " named pipe command on <%s> name \n " , name ) ) ;
1996-05-04 11:50:46 +04:00
1997-10-22 22:37:43 +04:00
if ( strequal ( name , " LANMAN " ) )
1998-08-14 21:38:29 +04:00
return api_reply ( conn , vuid , outbuf , data , params , tdscnt , tpscnt , mdrcnt , mprcnt ) ;
1996-05-04 11:50:46 +04:00
1998-10-15 09:47:29 +04:00
if ( strequal ( name , " WKSSVC " ) | |
strequal ( name , " SRVSVC " ) | |
strequal ( name , " WINREG " ) | |
strequal ( name , " SAMR " ) | |
strequal ( name , " LSARPC " ) )
{
DEBUG ( 4 , ( " named pipe command from Win95 (wow!) \n " ) ) ;
return api_fd_reply ( conn , vuid , outbuf , setup , data , params , suwcnt , tdscnt , tpscnt , mdrcnt , mprcnt ) ;
}
1997-10-22 22:37:43 +04:00
if ( strlen ( name ) < 1 )
1998-08-14 21:38:29 +04:00
return api_fd_reply ( conn , vuid , outbuf , setup , data , params , suwcnt , tdscnt , tpscnt , mdrcnt , mprcnt ) ;
1996-08-15 19:11:34 +04:00
1997-10-22 22:37:43 +04:00
if ( setup )
DEBUG ( 3 , ( " unknown named pipe: setup 0x%X setup1=%d \n " , ( int ) setup [ 0 ] , ( int ) setup [ 1 ] ) ) ;
1996-08-15 19:11:34 +04:00
1997-10-22 22:37:43 +04:00
return 0 ;
1996-05-04 11:50:46 +04:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Reply to a SMBtrans .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
int reply_trans ( connection_struct * conn , char * inbuf , char * outbuf , int size , int bufsize )
{
fstring name ;
1999-12-13 16:27:58 +03:00
int name_offset = 0 ;
1998-08-14 21:38:29 +04:00
char * data = NULL , * params = NULL ;
uint16 * setup = NULL ;
int outsize = 0 ;
uint16 vuid = SVAL ( inbuf , smb_uid ) ;
int tpscnt = SVAL ( inbuf , smb_vwv0 ) ;
int tdscnt = SVAL ( inbuf , smb_vwv1 ) ;
int mprcnt = SVAL ( inbuf , smb_vwv2 ) ;
int mdrcnt = SVAL ( inbuf , smb_vwv3 ) ;
int msrcnt = CVAL ( inbuf , smb_vwv4 ) ;
BOOL close_on_completion = BITSETW ( inbuf + smb_vwv5 , 0 ) ;
BOOL one_way = BITSETW ( inbuf + smb_vwv5 , 1 ) ;
int pscnt = SVAL ( inbuf , smb_vwv9 ) ;
int psoff = SVAL ( inbuf , smb_vwv10 ) ;
int dscnt = SVAL ( inbuf , smb_vwv11 ) ;
int dsoff = SVAL ( inbuf , smb_vwv12 ) ;
int suwcnt = CVAL ( inbuf , smb_vwv13 ) ;
2000-10-11 09:31:39 +04:00
START_PROFILE ( SMBtrans ) ;
1998-08-14 21:38:29 +04:00
1999-12-13 16:27:58 +03:00
memset ( name , ' \0 ' , sizeof ( name ) ) ;
2001-07-04 11:15:53 +04:00
srvstr_pull ( inbuf , name , smb_buf ( inbuf ) , sizeof ( name ) , - 1 , STR_TERMINATE ) ;
1998-08-14 21:38:29 +04:00
if ( dscnt > tdscnt | | pscnt > tpscnt ) {
2001-11-05 03:02:38 +03:00
exit_server ( " invalid trans parameters " ) ;
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
if ( tdscnt ) {
1998-09-29 03:55:09 +04:00
if ( ( data = ( char * ) malloc ( tdscnt ) ) = = NULL ) {
1998-10-08 10:49:00 +04:00
DEBUG ( 0 , ( " reply_trans: data malloc fail for %d bytes ! \n " , tdscnt ) ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBtrans ) ;
2001-08-27 12:19:43 +04:00
return ( ERROR_DOS ( ERRDOS , ERRnomem ) ) ;
1998-10-08 10:49:00 +04:00
}
1998-08-14 21:38:29 +04:00
memcpy ( data , smb_base ( inbuf ) + dsoff , dscnt ) ;
}
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
if ( tpscnt ) {
1998-09-29 03:55:09 +04:00
if ( ( params = ( char * ) malloc ( tpscnt ) ) = = NULL ) {
1998-10-08 10:49:00 +04:00
DEBUG ( 0 , ( " reply_trans: param malloc fail for %d bytes ! \n " , tpscnt ) ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBtrans ) ;
2001-08-27 12:19:43 +04:00
return ( ERROR_DOS ( ERRDOS , ERRnomem ) ) ;
1998-10-08 10:49:00 +04:00
}
1998-08-14 21:38:29 +04:00
memcpy ( params , smb_base ( inbuf ) + psoff , pscnt ) ;
}
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
if ( suwcnt ) {
int i ;
1998-09-29 03:55:09 +04:00
if ( ( setup = ( uint16 * ) malloc ( suwcnt * sizeof ( uint16 ) ) ) = = NULL ) {
1999-12-13 16:27:58 +03:00
DEBUG ( 0 , ( " reply_trans: setup malloc fail for %d bytes ! \n " , ( int ) ( suwcnt * sizeof ( uint16 ) ) ) ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBtrans ) ;
2001-08-27 12:19:43 +04:00
return ( ERROR_DOS ( ERRDOS , ERRnomem ) ) ;
1998-09-29 03:55:09 +04:00
}
1998-08-14 21:38:29 +04:00
for ( i = 0 ; i < suwcnt ; i + + )
setup [ i ] = SVAL ( inbuf , smb_vwv14 + i * SIZEOFWORD ) ;
}
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
if ( pscnt < tpscnt | | dscnt < tdscnt ) {
/* We need to send an interim response then receive the rest
of the parameter / data bytes */
outsize = set_message ( outbuf , 0 , 0 , True ) ;
show_msg ( outbuf ) ;
2001-06-09 05:38:54 +04:00
if ( ! send_smb ( smbd_server_fd ( ) , outbuf ) )
2001-11-05 03:02:38 +03:00
exit_server ( " reply_trans: send_smb failed. " ) ;
1998-08-14 21:38:29 +04:00
}
1996-06-10 09:16:19 +04:00
1998-08-14 21:38:29 +04:00
/* receive the rest of the trans packet */
while ( pscnt < tpscnt | | dscnt < tdscnt ) {
BOOL ret ;
int pcnt , poff , dcnt , doff , pdisp , ddisp ;
1996-05-04 11:50:46 +04:00
1998-09-23 05:48:45 +04:00
ret = receive_next_smb ( inbuf , bufsize , SMB_SECONDARY_WAIT ) ;
1998-08-14 21:38:29 +04:00
1999-12-13 16:27:58 +03:00
if ( ( ret & & ( CVAL ( inbuf , smb_com ) ! = SMBtranss ) ) | | ! ret ) {
1998-08-14 21:38:29 +04:00
if ( ret ) {
DEBUG ( 0 , ( " reply_trans: Invalid secondary trans packet \n " ) ) ;
} else {
DEBUG ( 0 , ( " reply_trans: %s in getting secondary trans response. \n " ,
( smb_read_error = = READ_ERROR ) ? " error " : " timeout " ) ) ;
}
2001-09-17 15:25:41 +04:00
SAFE_FREE ( params ) ;
SAFE_FREE ( data ) ;
SAFE_FREE ( setup ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBtrans ) ;
2001-08-27 12:19:43 +04:00
return ( ERROR_DOS ( ERRSRV , ERRerror ) ) ;
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
show_msg ( inbuf ) ;
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
tpscnt = SVAL ( inbuf , smb_vwv0 ) ;
tdscnt = SVAL ( inbuf , smb_vwv1 ) ;
pcnt = SVAL ( inbuf , smb_vwv2 ) ;
poff = SVAL ( inbuf , smb_vwv3 ) ;
pdisp = SVAL ( inbuf , smb_vwv4 ) ;
dcnt = SVAL ( inbuf , smb_vwv5 ) ;
doff = SVAL ( inbuf , smb_vwv6 ) ;
ddisp = SVAL ( inbuf , smb_vwv7 ) ;
pscnt + = pcnt ;
dscnt + = dcnt ;
if ( dscnt > tdscnt | | pscnt > tpscnt ) {
2001-11-05 03:02:38 +03:00
exit_server ( " invalid trans parameters " ) ;
1998-08-14 21:38:29 +04:00
}
if ( pcnt )
memcpy ( params + pdisp , smb_base ( inbuf ) + poff , pcnt ) ;
if ( dcnt )
memcpy ( data + ddisp , smb_base ( inbuf ) + doff , dcnt ) ;
}
DEBUG ( 3 , ( " trans <%s> data=%d params=%d setup=%d \n " ,
name , tdscnt , tpscnt , suwcnt ) ) ;
1999-12-13 16:27:58 +03:00
/*
* WinCE wierdness . . . .
*/
1998-10-15 04:55:17 +04:00
1999-12-13 16:27:58 +03:00
if ( name [ 0 ] = = ' \\ ' & & ( StrnCaseCmp ( & name [ 1 ] , local_machine , strlen ( local_machine ) ) = = 0 ) & &
( name [ strlen ( local_machine ) + 1 ] = = ' \\ ' ) )
name_offset = strlen ( local_machine ) + 1 ;
1998-10-15 04:55:17 +04:00
2001-06-29 05:58:48 +04:00
if ( strnequal ( & name [ name_offset ] , " \\ PIPE " , strlen ( " \\ PIPE " ) ) ) {
name_offset + = strlen ( " \\ PIPE " ) ;
/* Win9x weirdness. When talking to a unicode server Win9x
only sends \ PIPE instead of \ PIPE \ */
if ( name [ name_offset ] = = ' \\ ' )
name_offset + + ;
1998-08-14 21:38:29 +04:00
DEBUG ( 5 , ( " calling named_pipe \n " ) ) ;
1998-10-08 10:49:00 +04:00
outsize = named_pipe ( conn , vuid , outbuf ,
2001-06-29 05:58:48 +04:00
name + name_offset , setup , data , params ,
1998-08-14 21:38:29 +04:00
suwcnt , tdscnt , tpscnt , msrcnt , mdrcnt , mprcnt ) ;
} else {
DEBUG ( 3 , ( " invalid pipe name \n " ) ) ;
outsize = 0 ;
}
1996-05-04 11:50:46 +04:00
1998-08-14 21:38:29 +04:00
2001-09-17 15:25:41 +04:00
SAFE_FREE ( data ) ;
SAFE_FREE ( params ) ;
SAFE_FREE ( setup ) ;
1998-08-14 21:38:29 +04:00
if ( close_on_completion )
close_cnum ( conn , vuid ) ;
1996-05-04 11:50:46 +04:00
2000-10-11 09:31:39 +04:00
if ( one_way ) {
END_PROFILE ( SMBtrans ) ;
1998-08-14 21:38:29 +04:00
return ( - 1 ) ;
2000-10-11 09:31:39 +04:00
}
1998-08-14 21:38:29 +04:00
2000-10-11 09:31:39 +04:00
if ( outsize = = 0 ) {
END_PROFILE ( SMBtrans ) ;
2001-08-27 12:19:43 +04:00
return ( ERROR_DOS ( ERRSRV , ERRnosupport ) ) ;
2000-10-11 09:31:39 +04:00
}
1998-08-14 21:38:29 +04:00
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBtrans ) ;
1998-08-14 21:38:29 +04:00
return ( outsize ) ;
1996-05-04 11:50:46 +04:00
}