2003-08-13 01:53:07 +00:00
/*
Unix SMB / CIFS implementation .
RAW_QFS_ * operations
Copyright ( C ) Andrew Tridgell 2003
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 .
*/
# include "includes.h"
/****************************************************************************
Query FS Info - SMBdskattr call ( async send )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-08-04 13:23:35 +00:00
static struct smbcli_request * smb_raw_dskattr_send ( struct smbcli_tree * tree ,
2003-08-13 01:53:07 +00:00
union smb_fsinfo * fsinfo )
{
2004-08-04 13:23:35 +00:00
struct smbcli_request * req ;
2003-08-13 01:53:07 +00:00
2004-08-04 13:23:35 +00:00
req = smbcli_request_setup ( tree , SMBdskattr , 0 , 0 ) ;
2003-08-13 01:53:07 +00:00
2004-08-04 13:23:35 +00:00
if ( ! smbcli_request_send ( req ) ) {
smbcli_request_destroy ( req ) ;
2003-08-13 01:53:07 +00:00
return NULL ;
}
return req ;
}
/****************************************************************************
Query FS Info - SMBdskattr call ( async recv )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-08-04 13:23:35 +00:00
static NTSTATUS smb_raw_dskattr_recv ( struct smbcli_request * req ,
2003-08-13 01:53:07 +00:00
union smb_fsinfo * fsinfo )
{
2004-08-04 13:23:35 +00:00
if ( ! smbcli_request_receive ( req ) | |
smbcli_request_is_error ( req ) ) {
2003-08-13 01:53:07 +00:00
goto failed ;
}
2004-08-04 13:23:35 +00:00
SMBCLI_CHECK_WCT ( req , 5 ) ;
2003-08-13 01:53:07 +00:00
fsinfo - > dskattr . out . units_total = SVAL ( req - > in . vwv , VWV ( 0 ) ) ;
fsinfo - > dskattr . out . blocks_per_unit = SVAL ( req - > in . vwv , VWV ( 1 ) ) ;
fsinfo - > dskattr . out . block_size = SVAL ( req - > in . vwv , VWV ( 2 ) ) ;
fsinfo - > dskattr . out . units_free = SVAL ( req - > in . vwv , VWV ( 3 ) ) ;
failed :
2004-08-04 13:23:35 +00:00
return smbcli_request_destroy ( req ) ;
2003-08-13 01:53:07 +00:00
}
/****************************************************************************
RAW_QFS_ trans2 interface via blobs ( async send )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-08-04 13:23:35 +00:00
static struct smbcli_request * smb_raw_qfsinfo_send ( struct smbcli_tree * tree ,
2003-08-13 01:53:07 +00:00
TALLOC_CTX * mem_ctx ,
2004-05-25 17:24:24 +00:00
uint16_t info_level )
2003-08-13 01:53:07 +00:00
{
struct smb_trans2 tp ;
2004-05-25 17:24:24 +00:00
uint16_t setup = TRANSACT2_QFSINFO ;
2003-08-13 01:53:07 +00:00
tp . in . max_setup = 0 ;
tp . in . flags = 0 ;
tp . in . timeout = 0 ;
tp . in . setup_count = 1 ;
tp . in . max_param = 0 ;
tp . in . max_data = 0x1000 ; /* plenty for all possible QFS levels */
tp . in . setup = & setup ;
tp . in . data = data_blob ( NULL , 0 ) ;
tp . in . timeout = 0 ;
tp . in . params = data_blob_talloc ( mem_ctx , NULL , 2 ) ;
if ( ! tp . in . params . data ) {
return NULL ;
}
SSVAL ( tp . in . params . data , 0 , info_level ) ;
return smb_raw_trans2_send ( tree , & tp ) ;
}
/****************************************************************************
RAW_QFS_ trans2 interface via blobs ( async recv )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-08-04 13:23:35 +00:00
static NTSTATUS smb_raw_qfsinfo_blob_recv ( struct smbcli_request * req ,
2003-08-13 01:53:07 +00:00
TALLOC_CTX * mem_ctx ,
DATA_BLOB * blob )
{
struct smb_trans2 tp ;
NTSTATUS status ;
status = smb_raw_trans2_recv ( req , mem_ctx , & tp ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
( * blob ) = tp . out . data ;
}
return status ;
}
/* local macros to make the code more readable */
# define QFS_CHECK_MIN_SIZE(size) if (blob.length < (size)) { \
DEBUG ( 1 , ( " Unexpected QFS reply size %d for level %u - expected min of %d \n " , \
blob . length , fsinfo - > generic . level , ( size ) ) ) ; \
status = NT_STATUS_INFO_LENGTH_MISMATCH ; \
goto failed ; \
}
# define QFS_CHECK_SIZE(size) if (blob.length != (size)) { \
DEBUG ( 1 , ( " Unexpected QFS reply size %d for level %u - expected %d \n " , \
blob . length , fsinfo - > generic . level , ( size ) ) ) ; \
status = NT_STATUS_INFO_LENGTH_MISMATCH ; \
goto failed ; \
}
/****************************************************************************
Query FSInfo raw interface ( async send )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-08-04 13:23:35 +00:00
struct smbcli_request * smb_raw_fsinfo_send ( struct smbcli_tree * tree ,
2003-08-13 01:53:07 +00:00
TALLOC_CTX * mem_ctx ,
union smb_fsinfo * fsinfo )
{
2004-05-25 17:24:24 +00:00
uint16_t info_level ;
2003-08-13 01:53:07 +00:00
/* handle the only non-trans2 call separately */
if ( fsinfo - > generic . level = = RAW_QFS_DSKATTR ) {
return smb_raw_dskattr_send ( tree , fsinfo ) ;
}
if ( fsinfo - > generic . level > = RAW_QFS_GENERIC ) {
return NULL ;
}
/* the headers map the trans2 levels direct to info levels */
2004-05-25 17:24:24 +00:00
info_level = ( uint16_t ) fsinfo - > generic . level ;
2003-08-13 01:53:07 +00:00
return smb_raw_qfsinfo_send ( tree , mem_ctx , info_level ) ;
}
/****************************************************************************
Query FSInfo raw interface ( async recv )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-08-04 13:23:35 +00:00
NTSTATUS smb_raw_fsinfo_recv ( struct smbcli_request * req ,
2003-08-13 01:53:07 +00:00
TALLOC_CTX * mem_ctx ,
union smb_fsinfo * fsinfo )
{
DATA_BLOB blob ;
NTSTATUS status ;
int i ;
2004-08-04 13:23:35 +00:00
struct smbcli_session * session = req ? req - > session : NULL ;
2003-08-13 01:53:07 +00:00
if ( fsinfo - > generic . level = = RAW_QFS_DSKATTR ) {
return smb_raw_dskattr_recv ( req , fsinfo ) ;
}
status = smb_raw_qfsinfo_blob_recv ( req , mem_ctx , & blob ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
/* parse the results */
switch ( fsinfo - > generic . level ) {
case RAW_QFS_GENERIC :
case RAW_QFS_DSKATTR :
/* handled above */
break ;
case RAW_QFS_ALLOCATION :
QFS_CHECK_SIZE ( 18 ) ;
fsinfo - > allocation . out . fs_id = IVAL ( blob . data , 0 ) ;
fsinfo - > allocation . out . sectors_per_unit = IVAL ( blob . data , 4 ) ;
fsinfo - > allocation . out . total_alloc_units = IVAL ( blob . data , 8 ) ;
fsinfo - > allocation . out . avail_alloc_units = IVAL ( blob . data , 12 ) ;
fsinfo - > allocation . out . bytes_per_sector = SVAL ( blob . data , 16 ) ;
break ;
case RAW_QFS_VOLUME :
QFS_CHECK_MIN_SIZE ( 5 ) ;
fsinfo - > volume . out . serial_number = IVAL ( blob . data , 0 ) ;
2004-08-04 13:23:35 +00:00
smbcli_blob_pull_string ( session , mem_ctx , & blob ,
2003-08-13 01:53:07 +00:00
& fsinfo - > volume . out . volume_name ,
4 , 5 , STR_LEN8BIT | STR_NOALIGN ) ;
break ;
case RAW_QFS_VOLUME_INFO :
case RAW_QFS_VOLUME_INFORMATION :
QFS_CHECK_MIN_SIZE ( 18 ) ;
2004-08-04 13:23:35 +00:00
fsinfo - > volume_info . out . create_time = smbcli_pull_nttime ( blob . data , 0 ) ;
2003-08-13 01:53:07 +00:00
fsinfo - > volume_info . out . serial_number = IVAL ( blob . data , 8 ) ;
2004-08-04 13:23:35 +00:00
smbcli_blob_pull_string ( session , mem_ctx , & blob ,
2003-08-13 01:53:07 +00:00
& fsinfo - > volume_info . out . volume_name ,
12 , 18 , STR_UNICODE ) ;
break ;
case RAW_QFS_SIZE_INFO :
case RAW_QFS_SIZE_INFORMATION :
QFS_CHECK_SIZE ( 24 ) ;
fsinfo - > size_info . out . total_alloc_units = BVAL ( blob . data , 0 ) ;
fsinfo - > size_info . out . avail_alloc_units = BVAL ( blob . data , 8 ) ;
fsinfo - > size_info . out . sectors_per_unit = IVAL ( blob . data , 16 ) ;
fsinfo - > size_info . out . bytes_per_sector = IVAL ( blob . data , 20 ) ;
break ;
case RAW_QFS_DEVICE_INFO :
case RAW_QFS_DEVICE_INFORMATION :
QFS_CHECK_SIZE ( 8 ) ;
fsinfo - > device_info . out . device_type = IVAL ( blob . data , 0 ) ;
fsinfo - > device_info . out . characteristics = IVAL ( blob . data , 4 ) ;
break ;
case RAW_QFS_ATTRIBUTE_INFO :
case RAW_QFS_ATTRIBUTE_INFORMATION :
QFS_CHECK_MIN_SIZE ( 12 ) ;
fsinfo - > attribute_info . out . fs_attr = IVAL ( blob . data , 0 ) ;
fsinfo - > attribute_info . out . max_file_component_length = IVAL ( blob . data , 4 ) ;
2004-08-04 13:23:35 +00:00
smbcli_blob_pull_string ( session , mem_ctx , & blob ,
2003-08-13 01:53:07 +00:00
& fsinfo - > attribute_info . out . fs_type ,
8 , 12 , STR_UNICODE ) ;
break ;
case RAW_QFS_UNIX_INFO :
QFS_CHECK_SIZE ( 12 ) ;
fsinfo - > unix_info . out . major_version = SVAL ( blob . data , 0 ) ;
fsinfo - > unix_info . out . minor_version = SVAL ( blob . data , 2 ) ;
fsinfo - > unix_info . out . capability = SVAL ( blob . data , 4 ) ;
break ;
case RAW_QFS_QUOTA_INFORMATION :
QFS_CHECK_SIZE ( 48 ) ;
fsinfo - > quota_information . out . unknown [ 0 ] = BVAL ( blob . data , 0 ) ;
fsinfo - > quota_information . out . unknown [ 1 ] = BVAL ( blob . data , 8 ) ;
fsinfo - > quota_information . out . unknown [ 2 ] = BVAL ( blob . data , 16 ) ;
fsinfo - > quota_information . out . quota_soft = BVAL ( blob . data , 24 ) ;
fsinfo - > quota_information . out . quota_hard = BVAL ( blob . data , 32 ) ;
fsinfo - > quota_information . out . quota_flags = BVAL ( blob . data , 40 ) ;
break ;
case RAW_QFS_FULL_SIZE_INFORMATION :
QFS_CHECK_SIZE ( 32 ) ;
fsinfo - > full_size_information . out . total_alloc_units = BVAL ( blob . data , 0 ) ;
fsinfo - > full_size_information . out . call_avail_alloc_units = BVAL ( blob . data , 8 ) ;
fsinfo - > full_size_information . out . actual_avail_alloc_units = BVAL ( blob . data , 16 ) ;
fsinfo - > full_size_information . out . sectors_per_unit = IVAL ( blob . data , 24 ) ;
fsinfo - > full_size_information . out . bytes_per_sector = IVAL ( blob . data , 28 ) ;
break ;
case RAW_QFS_OBJECTID_INFORMATION :
QFS_CHECK_SIZE ( 64 ) ;
2003-12-16 09:02:58 +00:00
status = ndr_pull_struct_blob ( & blob , mem_ctx , & fsinfo - > objectid_information . out . guid ,
( ndr_pull_flags_fn_t ) ndr_pull_GUID ) ;
2003-08-13 01:53:07 +00:00
for ( i = 0 ; i < 6 ; i + + ) {
fsinfo - > objectid_information . out . unknown [ i ] = BVAL ( blob . data , 16 + i * 8 ) ;
}
break ;
}
failed :
return status ;
}
/****************************************************************************
Query FSInfo raw interface ( sync interface )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-08-04 13:23:35 +00:00
NTSTATUS smb_raw_fsinfo ( struct smbcli_tree * tree ,
2003-08-13 01:53:07 +00:00
TALLOC_CTX * mem_ctx ,
union smb_fsinfo * fsinfo )
{
2004-08-04 13:23:35 +00:00
struct smbcli_request * req = smb_raw_fsinfo_send ( tree , mem_ctx , fsinfo ) ;
2003-08-13 01:53:07 +00:00
return smb_raw_fsinfo_recv ( req , mem_ctx , fsinfo ) ;
}