2005-04-05 12:35:02 +04:00
/*
Unix SMB / CIFS implementation .
2005-06-08 02:09:18 +04:00
packet handling for mailslot requests .
2005-04-05 12:35:02 +04:00
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 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2005-04-05 12:35:02 +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/>.
2005-04-05 12:35:02 +04:00
*/
2005-06-08 02:09:18 +04:00
/*
This implements " Class 2 mailslots " , i . e . the communication mechanism
2006-06-08 19:20:05 +04:00
used for all mailslot packets smaller than 425 bytes .
2005-06-08 02:09:18 +04:00
" Class 1 mailslots " ( which use SMB ) are used for messages larger
2006-06-08 19:20:05 +04:00
than 426 bytes and are supported on some systems . These are not implemented
2005-06-08 02:09:18 +04:00
in Samba4 yet , as there don ' t appear to be any core services that use
them .
425 and 426 - byte sized messages are not supported at all .
*/
2005-04-05 12:35:02 +04:00
# include "includes.h"
# include "lib/events/events.h"
2008-10-11 23:31:42 +04:00
# include "../lib/util/dlinklist.h"
2005-04-05 12:35:02 +04:00
# include "libcli/dgram/libdgram.h"
# include "lib/socket/socket.h"
/*
destroy a mailslot handler
*/
2006-05-24 11:34:11 +04:00
static int dgram_mailslot_destructor ( struct dgram_mailslot_handler * dgmslot )
2005-04-05 12:35:02 +04:00
{
DLIST_REMOVE ( dgmslot - > dgmsock - > mailslot_handlers , dgmslot ) ;
return 0 ;
}
/*
start listening on a mailslot . talloc_free ( ) the handle to stop listening
*/
struct dgram_mailslot_handler * dgram_mailslot_listen ( struct nbt_dgram_socket * dgmsock ,
const char * mailslot_name ,
dgram_mailslot_handler_t handler ,
2009-02-02 10:24:00 +03:00
void * private_data )
2005-04-05 12:35:02 +04:00
{
struct dgram_mailslot_handler * dgmslot ;
dgmslot = talloc ( dgmsock , struct dgram_mailslot_handler ) ;
if ( dgmslot = = NULL ) return NULL ;
dgmslot - > dgmsock = dgmsock ;
dgmslot - > mailslot_name = talloc_strdup ( dgmslot , mailslot_name ) ;
if ( dgmslot - > mailslot_name = = NULL ) {
talloc_free ( dgmslot ) ;
return NULL ;
}
dgmslot - > handler = handler ;
2009-02-02 11:55:58 +03:00
dgmslot - > private_data = private_data ;
2005-04-05 12:35:02 +04:00
DLIST_ADD ( dgmsock - > mailslot_handlers , dgmslot ) ;
talloc_set_destructor ( dgmslot , dgram_mailslot_destructor ) ;
2005-04-08 09:34:13 +04:00
EVENT_FD_READABLE ( dgmsock - > fde ) ;
2005-04-05 12:35:02 +04:00
return dgmslot ;
}
/*
find the handler for a specific mailslot name
*/
struct dgram_mailslot_handler * dgram_mailslot_find ( struct nbt_dgram_socket * dgmsock ,
const char * mailslot_name )
{
struct dgram_mailslot_handler * h ;
for ( h = dgmsock - > mailslot_handlers ; h ; h = h - > next ) {
if ( strcasecmp ( h - > mailslot_name , mailslot_name ) = = 0 ) {
return h ;
}
}
return NULL ;
}
/*
check that a datagram packet is a valid mailslot request , and return the
mailslot name if it is , otherwise return NULL
*/
const char * dgram_mailslot_name ( struct nbt_dgram_packet * packet )
{
if ( packet - > msg_type ! = DGRAM_DIRECT_UNIQUE & &
packet - > msg_type ! = DGRAM_DIRECT_GROUP & &
packet - > msg_type ! = DGRAM_BCAST ) {
return NULL ;
}
if ( packet - > data . msg . dgram_body_type ! = DGRAM_SMB ) return NULL ;
if ( packet - > data . msg . body . smb . smb_command ! = SMB_TRANSACTION ) return NULL ;
return packet - > data . msg . body . smb . body . trans . mailslot_name ;
}
/*
create a temporary mailslot handler for a reply mailslot , allocating
a new mailslot name using the given base name and a random integer extension
*/
struct dgram_mailslot_handler * dgram_mailslot_temp ( struct nbt_dgram_socket * dgmsock ,
const char * mailslot_name ,
dgram_mailslot_handler_t handler ,
2009-02-02 10:24:00 +03:00
void * private_data )
2005-04-05 12:35:02 +04:00
{
char * name ;
int i ;
struct dgram_mailslot_handler * dgmslot ;
/* try a 100 times at most */
for ( i = 0 ; i < 100 ; i + + ) {
2005-04-06 15:17:08 +04:00
name = talloc_asprintf ( dgmsock , " %s%03u " ,
2005-04-05 12:35:02 +04:00
mailslot_name ,
2005-04-06 15:17:08 +04:00
generate_random ( ) % 1000 ) ;
2005-04-05 12:35:02 +04:00
if ( name = = NULL ) return NULL ;
if ( dgram_mailslot_find ( dgmsock , name ) ) {
talloc_free ( name ) ;
return NULL ;
}
2009-02-02 10:24:00 +03:00
dgmslot = dgram_mailslot_listen ( dgmsock , name , handler , private_data ) ;
2005-04-05 12:35:02 +04:00
talloc_free ( name ) ;
2006-03-13 08:02:49 +03:00
if ( dgmslot ! = NULL ) {
return dgmslot ;
}
2005-04-05 12:35:02 +04:00
}
DEBUG ( 2 , ( " Unable to create temporary mailslot from %s \n " , mailslot_name ) ) ;
return NULL ;
}
2005-04-06 15:17:08 +04:00
/*
send a mailslot request
*/
NTSTATUS dgram_mailslot_send ( struct nbt_dgram_socket * dgmsock ,
enum dgram_msg_type msg_type ,
const char * mailslot_name ,
struct nbt_name * dest_name ,
2007-12-06 18:41:53 +03:00
struct socket_address * dest ,
2005-04-06 15:17:08 +04:00
struct nbt_name * src_name ,
DATA_BLOB * request )
{
TALLOC_CTX * tmp_ctx = talloc_new ( dgmsock ) ;
struct nbt_dgram_packet packet ;
struct dgram_message * msg ;
struct dgram_smb_packet * smb ;
struct smb_trans_body * trans ;
2006-01-10 01:12:53 +03:00
struct socket_address * src ;
2005-04-06 15:17:08 +04:00
NTSTATUS status ;
2007-12-06 18:41:53 +03:00
if ( dest - > port = = 0 ) {
return NT_STATUS_INVALID_PARAMETER ;
2005-04-11 03:09:38 +04:00
}
2005-04-06 15:17:08 +04:00
ZERO_STRUCT ( packet ) ;
packet . msg_type = msg_type ;
2005-04-13 07:43:17 +04:00
packet . flags = DGRAM_FLAG_FIRST | DGRAM_NODE_NBDD ;
2005-04-06 15:17:08 +04:00
packet . dgram_id = generate_random ( ) % UINT16_MAX ;
2006-01-10 01:12:53 +03:00
src = socket_get_my_addr ( dgmsock - > sock , tmp_ctx ) ;
if ( ! src ) {
return NT_STATUS_NO_MEMORY ;
}
packet . src_addr = src - > addr ;
packet . src_port = src - > port ;
2005-04-06 15:17:08 +04:00
msg = & packet . data . msg ;
/* this length calculation is very crude - it should be based on gensize
calls */
2005-04-13 09:50:02 +04:00
msg - > length = 138 + strlen ( mailslot_name ) + request - > length ;
2005-04-06 15:17:08 +04:00
msg - > offset = 0 ;
msg - > source_name = * src_name ;
msg - > dest_name = * dest_name ;
msg - > dgram_body_type = DGRAM_SMB ;
smb = & msg - > body . smb ;
smb - > smb_command = SMB_TRANSACTION ;
trans = & smb - > body . trans ;
trans - > total_data_count = request - > length ;
2005-04-13 07:43:17 +04:00
trans - > timeout = 1000 ;
2005-04-06 15:17:08 +04:00
trans - > data_count = request - > length ;
trans - > data_offset = 70 + strlen ( mailslot_name ) ;
trans - > opcode = 1 ; /* write mail slot */
trans - > priority = 1 ;
2008-10-15 23:32:01 +04:00
trans - > _class = 2 ;
2005-04-06 15:17:08 +04:00
trans - > mailslot_name = mailslot_name ;
trans - > data = * request ;
2006-01-10 01:12:53 +03:00
status = nbt_dgram_send ( dgmsock , & packet , dest ) ;
2005-04-06 15:17:08 +04:00
talloc_free ( tmp_ctx ) ;
return status ;
}
2005-04-13 09:50:02 +04:00
/*
return the mailslot data portion from a mailslot packet
*/
DATA_BLOB dgram_mailslot_data ( struct nbt_dgram_packet * dgram )
{
struct smb_trans_body * trans = & dgram - > data . msg . body . smb . body . trans ;
DATA_BLOB ret = trans - > data ;
int pad = trans - > data_offset - ( 70 + strlen ( trans - > mailslot_name ) ) ;
if ( pad < 0 | | pad > ret . length ) {
DEBUG ( 2 , ( " Badly formatted data in mailslot - pad = %d \n " , pad ) ) ;
return data_blob ( NULL , 0 ) ;
}
ret . data + = pad ;
ret . length - = pad ;
return ret ;
}