2005-11-11 04:45:38 +00:00
/*
Unix SMB / CIFS implementation .
SMB2 client library header
Copyright ( C ) Andrew Tridgell 2005
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 02:07:03 +00:00
the Free Software Foundation ; either version 3 of the License , or
2005-11-11 04:45:38 +00: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 02:07:03 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-11-11 04:45:38 +00:00
*/
2008-05-16 15:03:58 +10:00
# ifndef __LIBCLI_SMB2_SMB2_H__
# define __LIBCLI_SMB2_SMB2_H__
2008-02-14 10:12:33 +11:00
# include "libcli/raw/request.h"
2008-05-30 17:03:54 +10:00
# include "libcli/raw/libcliraw.h"
2008-02-14 10:12:33 +11:00
2008-04-18 22:27:24 +02:00
struct smb2_handle ;
2009-03-30 15:57:57 -07:00
struct smb2_lease_break ;
2008-04-18 22:27:24 +02:00
2009-06-08 16:24:27 +02:00
struct smb2_request_buffer {
/* the raw SMB2 buffer, including the 4 byte length header */
uint8_t * buffer ;
/* the size of the raw buffer, including 4 byte header */
size_t size ;
/* how much has been allocated - on reply the buffer is over-allocated to
prevent too many realloc ( ) calls
*/
size_t allocated ;
/* the start of the SMB2 header - this is always buffer+4 */
uint8_t * hdr ;
/* the packet body */
uint8_t * body ;
size_t body_fixed ;
size_t body_size ;
/* this point to the next dynamic byte that can be used
* this will be moved when some dynamic data is pushed
*/
uint8_t * dynamic ;
/* this is used to range check and align strings and buffers */
struct request_bufinfo bufinfo ;
} ;
2005-11-11 04:45:38 +00:00
/* this is the context for the smb2 transport layer */
struct smb2_transport {
2011-09-20 20:59:45 +02:00
struct tevent_context * ev ; /* TODO: remove this !!! */
struct smbXcli_conn * conn ;
2005-11-11 04:45:38 +00:00
2009-06-08 16:24:27 +02:00
/* the details for coumpounded requests */
struct {
bool related ;
2011-09-20 20:59:45 +02:00
struct tevent_req * * reqs ;
2009-06-08 16:24:27 +02:00
} compound ;
2006-07-17 07:45:23 +00:00
/* an idle function - if this is defined then it will be
called once every period microseconds while we are waiting
for a packet */
struct {
void ( * func ) ( struct smb2_transport * , void * ) ;
2009-02-02 09:56:47 +01:00
void * private_data ;
2010-01-05 09:42:54 -08:00
unsigned int period ;
2011-11-22 10:10:30 +01:00
struct tevent_timer * te ;
2006-07-17 07:45:23 +00:00
} idle ;
2008-04-18 22:27:24 +02:00
struct {
/* a oplock break request handler */
bool ( * handler ) ( struct smb2_transport * transport ,
const struct smb2_handle * handle ,
uint8_t level , void * private_data ) ;
/* private data passed to the oplock handler */
void * private_data ;
} oplock ;
2008-05-30 17:03:54 +10:00
2009-03-30 15:57:57 -07:00
struct {
/* a lease break request handler */
bool ( * handler ) ( struct smb2_transport * transport ,
const struct smb2_lease_break * lease_break ,
void * private_data ) ;
/* private data passed to the oplock handler */
void * private_data ;
} lease ;
2011-09-20 20:59:45 +02:00
struct tevent_req * break_subreq ;
2009-03-30 15:57:57 -07:00
2008-05-30 17:03:54 +10:00
struct smbcli_options options ;
2005-11-11 04:45:38 +00:00
} ;
2005-11-11 09:11:51 +00:00
/*
SMB2 tree context
*/
struct smb2_tree {
struct smb2_session * session ;
2012-07-23 22:11:19 +02:00
struct smbXcli_tcon * smbXcli ;
2005-11-11 09:11:51 +00:00
} ;
2005-11-11 05:53:54 +00:00
/*
SMB2 session context
*/
struct smb2_session {
struct smb2_transport * transport ;
2005-11-11 06:26:42 +00:00
struct gensec_security * gensec ;
2011-09-20 20:59:45 +02:00
struct smbXcli_session * smbXcli ;
2014-06-24 00:22:30 +02:00
bool needs_bind ;
2005-11-11 05:53:54 +00:00
} ;
2005-11-11 09:11:51 +00:00
2005-11-11 04:45:38 +00:00
/*
a client request moves between the following 4 states .
*/
enum smb2_request_state { SMB2_REQUEST_INIT , /* we are creating the request */
SMB2_REQUEST_RECV , /* we are waiting for a matching reply */
SMB2_REQUEST_DONE , /* the request is finished */
SMB2_REQUEST_ERROR } ; /* a packet or transport level error has occurred */
/* the context for a single SMB2 request */
struct smb2_request {
/* each request is in one of 3 possible states */
enum smb2_request_state state ;
2010-09-22 13:23:49 -07:00
2011-09-20 20:59:45 +02:00
struct tevent_req * subreq ;
2005-11-11 04:45:38 +00:00
struct smb2_transport * transport ;
2005-11-12 01:08:43 +00:00
struct smb2_session * session ;
struct smb2_tree * tree ;
2005-11-11 04:45:38 +00:00
2006-07-17 09:36:52 +00:00
struct {
2007-08-27 18:10:19 +00:00
bool can_cancel ;
2006-07-17 09:36:52 +00:00
} cancel ;
2005-11-11 04:45:38 +00:00
/* the NT status for this request. Set by packet receive code
or code detecting error . */
NTSTATUS status ;
2010-09-22 13:23:49 -07:00
2005-11-11 04:45:38 +00:00
struct smb2_request_buffer in ;
struct smb2_request_buffer out ;
2011-09-20 20:59:45 +02:00
struct iovec * recv_iov ;
uint16_t credit_charge ;
2005-11-11 04:45:38 +00:00
/* information on what to do with a reply when it is received
asyncronously . If this is not setup when a reply is received then
the reply is discarded
The private pointer is private to the caller of the client
library ( the application ) , not private to the library
*/
struct {
void ( * fn ) ( struct smb2_request * ) ;
2008-05-16 15:03:58 +10:00
void * private_data ;
2005-11-11 04:45:38 +00:00
} async ;
} ;
2005-11-17 00:48:24 +00:00
# define SMB2_MIN_SIZE 0x42
2008-09-24 18:58:38 -07:00
# define SMB2_MIN_SIZE_NO_BODY 0x40
2005-11-11 04:45:38 +00:00
2005-11-11 23:27:47 +00:00
/*
2005-11-16 11:01:15 +00:00
check that a body has the expected size
2005-11-11 23:27:47 +00:00
*/
2005-11-16 11:01:15 +00:00
# define SMB2_CHECK_PACKET_RECV(req, size, dynamic) do { \
2006-04-24 09:36:09 +00:00
size_t is_size = req - > in . body_size ; \
2005-11-16 11:01:15 +00:00
uint16_t field_size = SVAL ( req - > in . body , 0 ) ; \
uint16_t want_size = ( ( dynamic ) ? ( size ) + 1 : ( size ) ) ; \
if ( is_size < ( size ) ) { \
DEBUG ( 0 , ( " %s: buffer too small 0x%x. Expected 0x%x \n " , \
2006-09-09 10:05:58 +00:00
__location__ , ( unsigned ) is_size , ( unsigned ) want_size ) ) ; \
2005-11-16 11:01:15 +00:00
return NT_STATUS_BUFFER_TOO_SMALL ; \
} \
if ( field_size ! = want_size ) { \
DEBUG ( 0 , ( " %s: unexpected fixed body size 0x%x. Expected 0x%x \n " , \
2006-09-09 10:05:58 +00:00
__location__ , ( unsigned ) field_size , ( unsigned ) want_size ) ) ; \
2005-11-11 23:27:47 +00:00
return NT_STATUS_INVALID_PARAMETER ; \
} \
} while ( 0 )
2008-05-16 15:03:58 +10:00
# endif