2001-01-03 08:19:21 +03:00
/*
Unix SMB / Netbios implementation .
Version 3.0
client dgram calls
Copyright ( C ) Andrew Tridgell 1994 - 1998
Copyright ( C ) Richard Sharpe 2001
Copyright ( C ) John Terpstra 2001
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 .
*/
# define NO_SYSLOG
# include "includes.h"
/*
* cli_send_mailslot , send a mailslot for client code . . .
*/
static int dgram_sock = - 1 ;
int cli_send_mailslot ( BOOL unique , char * mailslot , char * buf , int len ,
const char * srcname , int src_type ,
const char * dstname , int dest_type ,
struct in_addr dest_ip , struct in_addr src_ip ,
int dest_port )
{
struct packet_struct p ;
struct dgram_packet * dgram = & p . packet . dgram ;
struct sockaddr_in sock_out ;
char * ptr , * p2 ;
char tmp [ 4 ] ;
bzero ( ( char * ) & p , sizeof ( p ) ) ;
/*
* First , check if we have an open socket to the dest IP
*/
if ( dgram_sock < 1 ) {
int name_size ;
if ( ( dgram_sock = open_socket_out ( SOCK_DGRAM , & dest_ip , 138 , LONG_CONNECT_TIMEOUT ) ) < 0 ) {
DEBUG ( 4 , ( " open_sock_out failed ... " ) ) ;
return False ;
}
/* Make it a broadcast socket ... */
set_socket_options ( dgram_sock , " SO_BROADCAST " ) ;
/* Now, bind my addr to it ... */
bzero ( ( char * ) & sock_out , sizeof ( sock_out ) ) ;
putip ( ( char * ) & sock_out . sin_addr , ( char * ) & src_ip ) ;
sock_out . sin_port = INADDR_ANY ;
sock_out . sin_family = AF_INET ;
bind ( dgram_sock , ( struct sockaddr_in * ) & sock_out , sizeof ( sock_out ) ) ;
/* Now, figure out what socket name we were bound to. We want the port */
name_size = sizeof ( sock_out ) ;
getsockname ( dgram_sock , ( struct sockaddr_in * ) & sock_out , & name_size ) ;
fprintf ( stderr , " Socket bound to IP:%s, port: %d \n " , inet_ntoa ( sock_out . sin_addr ) , ntohs ( sock_out . sin_port ) ) ;
}
/*
* Next , build the DGRAM . . .
*/
/* DIRECT GROUP or UNIQUE datagram. */
dgram - > header . msg_type = unique ? 0x10 : 0x11 ;
dgram - > header . flags . node_type = M_NODE ;
dgram - > header . flags . first = True ;
dgram - > header . flags . more = False ;
dgram - > header . dgm_id = ( ( unsigned ) time ( NULL ) % ( unsigned ) 0x7FFF ) + ( ( unsigned ) sys_getpid ( ) % ( unsigned ) 100 ) ;
dgram - > header . source_ip = src_ip ;
dgram - > header . source_port = ntohs ( sock_out . sin_port ) ;
dgram - > header . dgm_length = 0 ; /* Let build_dgram() handle this. */
dgram - > header . packet_offset = 0 ;
make_nmb_name ( & dgram - > source_name , srcname , src_type ) ;
make_nmb_name ( & dgram - > dest_name , dstname , dest_type ) ;
ptr = & dgram - > data [ 0 ] ;
/* Setup the smb part. */
ptr - = 4 ; /* XXX Ugliness because of handling of tcp SMB length. */
memcpy ( tmp , ptr , 4 ) ;
set_message ( ptr , 17 , 17 + len , True ) ;
memcpy ( ptr , tmp , 4 ) ;
CVAL ( ptr , smb_com ) = SMBtrans ;
SSVAL ( ptr , smb_vwv1 , len ) ;
SSVAL ( ptr , smb_vwv11 , len ) ;
SSVAL ( ptr , smb_vwv12 , 70 + strlen ( mailslot ) ) ;
SSVAL ( ptr , smb_vwv13 , 3 ) ;
SSVAL ( ptr , smb_vwv14 , 1 ) ;
SSVAL ( ptr , smb_vwv15 , 1 ) ;
SSVAL ( ptr , smb_vwv16 , 2 ) ;
p2 = smb_buf ( ptr ) ;
pstrcpy ( p2 , mailslot ) ;
p2 = skip_string ( p2 , 1 ) ;
memcpy ( p2 , buf , len ) ;
p2 + = len ;
dgram - > datasize = PTR_DIFF ( p2 , ptr + 4 ) ; /* +4 for tcp length. */
p . ip = dest_ip ;
p . port = dest_port ;
p . fd = dgram_sock ;
p . timestamp = time ( NULL ) ;
p . packet_type = DGRAM_PACKET ;
DEBUG ( 4 , ( " send_mailslot: Sending to mailslot %s from %s IP %s " , mailslot ,
nmb_namestr ( & dgram - > source_name ) , inet_ntoa ( src_ip ) ) ) ;
DEBUG ( 4 , ( " to %s IP %s \n " , nmb_namestr ( & dgram - > dest_name ) , inet_ntoa ( dest_ip ) ) ) ;
return send_packet ( & p ) ;
}
/*
* cli_get_response : Get a response . . .
*/
int cli_get_response ( BOOL unique , char * mailslot , char * buf , int bufsiz )
{
struct packet_struct * packet ;
packet = read_packet ( dgram_sock , DGRAM_PACKET ) ;
if ( packet ) { /* We got one, pull what we want out of the SMB data ... */
struct dgram_packet * dgram = & packet - > packet . dgram ;
/*
* We should probably parse the SMB , but for now , we will pull what
* from fixed , known locations . . .
*/
/* Copy the data to buffer, respecting sizes ... */
bcopy ( & dgram - > data [ 92 ] , buf , MIN ( bufsiz , ( dgram - > datasize - 92 ) ) ) ;
}
else
return - 1 ;
}
/*
* cli_get_backup_list : Send a get backup list request . . .
*/
static char cli_backup_list [ 1024 ] ;
int cli_get_backup_list ( const char * myname , const char * send_to_name )
{
char outbuf [ 15 ] ;
char * p ;
struct in_addr sendto_ip , my_ip ;
if ( ! resolve_name ( send_to_name , & sendto_ip , 0x1d ) ) {
fprintf ( stderr , " Could not resolve name: %s<1D> \n " , send_to_name ) ;
}
2001-01-25 16:47:13 +03:00
bzero ( & my_ip , 4 ) ; /* Cheap way to get 0.0.0.0 in there */
2001-01-07 16:38:24 +03:00
if ( ! resolve_name ( myname , & my_ip , 0x00 ) ) { /* FIXME: Call others here */
2001-01-03 08:19:21 +03:00
fprintf ( stderr , " Could not resolve name: %s<00> \n " , myname ) ;
}
bzero ( cli_backup_list , sizeof ( cli_backup_list ) ) ;
bzero ( outbuf , sizeof ( outbuf ) ) ;
p = outbuf ;
SCVAL ( p , 0 , ANN_GetBackupListReq ) ;
p + + ;
SCVAL ( p , 0 , 1 ) ; /* Count pointer ... */
p + + ;
SIVAL ( p , 0 , 1 ) ; /* The sender's token ... */
p + = 4 ;
cli_send_mailslot ( True , " \\ MAILSLOT \\ BROWSE " , outbuf , PTR_DIFF ( p , outbuf ) ,
myname , 0 , send_to_name , 0x1d , sendto_ip , my_ip , 138 ) ;
/* We should check the error and return if we got one */
/* Now, get the response ... */
cli_get_response ( True , " \\ MAILSLOT \\ BROWSE " , cli_backup_list , sizeof ( cli_backup_list ) ) ;
/* Should check the response here ... FIXME */
2001-01-25 16:47:13 +03:00
2001-01-03 08:19:21 +03:00
}
/*
* cli_get_backup_server : Get the backup list and retrieve a server from it
*/
int cli_get_backup_server ( char * my_name , char * target , char * servername , int namesize )
{
/* Get the backup list first. We could pull this from the cache later */
cli_get_backup_list ( my_name , target ) ; /* FIXME: Check the response */
strncpy ( servername , cli_backup_list , MIN ( 16 , namesize ) ) ;
}