2007-10-04 00:43:55 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1996-05-04 11:50:46 +04:00
NBT netbios library routines
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1994 - 1998
2007-10-04 00:43:55 +04:00
Copyright ( C ) Jeremy Allison 2007
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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1996-05-04 11:50:46 +04:00
( at your option ) any later version .
2007-10-04 00:43:55 +04:00
1996-05-04 11:50:46 +04:00
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 .
2007-10-04 00:43:55 +04:00
1996-05-04 11:50:46 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2007-10-04 00:43:55 +04:00
1996-05-04 11:50:46 +04:00
*/
# include "includes.h"
2011-03-23 16:18:59 +03:00
# include "libsmb/nmblib.h"
2020-08-07 21:17:34 +03:00
# include "lib/util/string_wrappers.h"
1996-05-04 11:50:46 +04:00
2001-10-29 11:12:44 +03:00
static const struct opcode_names {
2003-01-03 11:28:12 +03:00
const char * nmb_opcode_name ;
1997-09-14 20:37:18 +04:00
int opcode ;
1997-03-07 20:28:41 +03:00
} nmb_header_opcode_names [ ] = {
2002-11-13 02:20:50 +03:00
{ " Query " , 0 } ,
{ " Registration " , 5 } ,
{ " Release " , 6 } ,
{ " WACK " , 7 } ,
{ " Refresh " , 8 } ,
{ " Refresh(altcode) " , 9 } ,
{ " Multi-homed Registration " , 15 } ,
{ 0 , - 1 }
1997-03-07 20:28:41 +03:00
} ;
/****************************************************************************
2004-03-13 03:28:53 +03:00
Lookup a nmb opcode name .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-29 11:12:44 +03:00
static const char * lookup_opcode_name ( int opcode )
1997-03-07 20:28:41 +03:00
{
2004-03-13 03:28:53 +03:00
const struct opcode_names * op_namep ;
int i ;
for ( i = 0 ; nmb_header_opcode_names [ i ] . nmb_opcode_name ! = 0 ; i + + ) {
op_namep = & nmb_header_opcode_names [ i ] ;
if ( opcode = = op_namep - > opcode )
return op_namep - > nmb_opcode_name ;
}
return " <unknown opcode> " ;
1997-03-07 20:28:41 +03:00
}
1996-06-04 10:42:03 +04:00
/****************************************************************************
2004-03-13 03:28:53 +03:00
Print out a res_rec structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-01-03 11:28:12 +03:00
static void debug_nmb_res_rec ( struct res_rec * res , const char * hdr )
1996-06-04 10:42:03 +04:00
{
2004-03-13 03:28:53 +03:00
int i , j ;
DEBUGADD ( 4 , ( " %s: nmb_name=%s rr_type=%d rr_class=%d ttl=%d \n " ,
hdr ,
nmb_namestr ( & res - > rr_name ) ,
res - > rr_type ,
res - > rr_class ,
res - > ttl ) ) ;
2012-12-19 17:10:05 +04:00
if ( res - > rdlength = = 0 ) {
2004-03-13 03:28:53 +03:00
return ;
2012-12-19 17:10:05 +04:00
}
2004-03-13 03:28:53 +03:00
for ( i = 0 ; i < res - > rdlength ; i + = MAX_NETBIOSNAME_LEN ) {
DEBUGADD ( 4 , ( " %s %3x char " , hdr , i ) ) ;
for ( j = 0 ; j < MAX_NETBIOSNAME_LEN ; j + + ) {
unsigned char x = res - > rdata [ i + j ] ;
if ( x < 32 | | x > 127 )
x = ' . ' ;
2007-10-04 00:43:55 +04:00
2004-03-13 03:28:53 +03:00
if ( i + j > = res - > rdlength )
break ;
DEBUGADD ( 4 , ( " %c " , x ) ) ;
}
2007-10-04 00:43:55 +04:00
2004-03-13 03:28:53 +03:00
DEBUGADD ( 4 , ( " hex " ) ) ;
1996-06-04 10:42:03 +04:00
2004-03-13 03:28:53 +03:00
for ( j = 0 ; j < MAX_NETBIOSNAME_LEN ; j + + ) {
if ( i + j > = res - > rdlength )
break ;
DEBUGADD ( 4 , ( " %02X " , ( unsigned char ) res - > rdata [ i + j ] ) ) ;
}
2007-10-04 00:43:55 +04:00
2004-03-13 03:28:53 +03:00
DEBUGADD ( 4 , ( " \n " ) ) ;
}
1996-06-04 10:42:03 +04:00
}
/****************************************************************************
2004-03-13 03:28:53 +03:00
Process a nmb packet .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-06-04 10:42:03 +04:00
void debug_nmb_packet ( struct packet_struct * p )
{
2004-03-13 03:28:53 +03:00
struct nmb_packet * nmb = & p - > packet . nmb ;
if ( DEBUGLVL ( 4 ) ) {
2007-10-04 00:43:55 +04:00
dbgtext ( " nmb packet from %s(%d) header: id=%d "
" opcode=%s(%d) response=%s \n " ,
2004-03-13 03:28:53 +03:00
inet_ntoa ( p - > ip ) , p - > port ,
nmb - > header . name_trn_id ,
lookup_opcode_name ( nmb - > header . opcode ) ,
nmb - > header . opcode ,
BOOLSTR ( nmb - > header . response ) ) ;
2007-10-04 00:43:55 +04:00
dbgtext ( " header: flags: bcast=%s rec_avail=%s "
" rec_des=%s trunc=%s auth=%s \n " ,
2004-03-13 03:28:53 +03:00
BOOLSTR ( nmb - > header . nm_flags . bcast ) ,
BOOLSTR ( nmb - > header . nm_flags . recursion_available ) ,
BOOLSTR ( nmb - > header . nm_flags . recursion_desired ) ,
BOOLSTR ( nmb - > header . nm_flags . trunc ) ,
BOOLSTR ( nmb - > header . nm_flags . authoritative ) ) ;
2007-10-04 00:43:55 +04:00
dbgtext ( " header: rcode=%d qdcount=%d ancount=%d "
" nscount=%d arcount=%d \n " ,
2004-03-13 03:28:53 +03:00
nmb - > header . rcode ,
nmb - > header . qdcount ,
nmb - > header . ancount ,
nmb - > header . nscount ,
nmb - > header . arcount ) ;
}
if ( nmb - > header . qdcount ) {
DEBUGADD ( 4 , ( " question: q_name=%s q_type=%d q_class=%d \n " ,
nmb_namestr ( & nmb - > question . question_name ) ,
nmb - > question . question_type ,
nmb - > question . question_class ) ) ;
}
if ( nmb - > answers & & nmb - > header . ancount ) {
debug_nmb_res_rec ( nmb - > answers , " answers " ) ;
}
if ( nmb - > nsrecs & & nmb - > header . nscount ) {
debug_nmb_res_rec ( nmb - > nsrecs , " nsrecs " ) ;
}
if ( nmb - > additional & & nmb - > header . arcount ) {
debug_nmb_res_rec ( nmb - > additional , " additional " ) ;
}
1996-06-04 10:42:03 +04:00
}
1996-05-04 11:50:46 +04:00
/*******************************************************************
2004-03-13 03:28:53 +03:00
Handle " compressed " name pointers .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool handle_name_ptrs ( unsigned char * ubuf , int * offset , int length ,
bool * got_pointer , int * ret )
1996-05-04 11:50:46 +04:00
{
2004-03-13 03:28:53 +03:00
int loop_count = 0 ;
2007-10-04 00:43:55 +04:00
2004-03-13 03:28:53 +03:00
while ( ( ubuf [ * offset ] & 0xC0 ) = = 0xC0 ) {
if ( ! * got_pointer )
( * ret ) + = 2 ;
( * got_pointer ) = True ;
2020-01-19 05:08:58 +03:00
if ( * offset > length - 2 ) {
return False ;
}
2004-03-13 03:28:53 +03:00
( * offset ) = ( ( ubuf [ * offset ] & ~ 0xC0 ) < < 8 ) | ubuf [ ( * offset ) + 1 ] ;
2007-10-04 00:43:55 +04:00
if ( loop_count + + = = 10 | |
( * offset ) < 0 | | ( * offset ) > ( length - 2 ) ) {
return False ;
2004-03-13 03:28:53 +03:00
}
}
2007-10-04 00:43:55 +04:00
return True ;
1996-05-04 11:50:46 +04:00
}
/*******************************************************************
2004-03-13 03:28:53 +03:00
Parse a nmb name from " compressed " format to something readable
return the space taken by the name , or 0 if the name is invalid
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-27 06:50:53 +03:00
static int parse_nmb_name ( char * inbuf , int ofs , int length , struct nmb_name * name )
1996-05-04 11:50:46 +04:00
{
2017-12-07 19:52:39 +03:00
size_t m , n = 0 ;
2004-03-13 03:28:53 +03:00
unsigned char * ubuf = ( unsigned char * ) inbuf ;
int ret = 0 ;
2007-10-19 04:40:25 +04:00
bool got_pointer = False ;
2017-12-07 19:52:39 +03:00
size_t loop_count = 0 ;
2004-03-13 03:28:53 +03:00
int offset = ofs ;
if ( length - offset < 2 )
2007-10-04 00:43:55 +04:00
return ( 0 ) ;
2004-03-13 03:28:53 +03:00
/* handle initial name pointers */
if ( ! handle_name_ptrs ( ubuf , & offset , length , & got_pointer , & ret ) )
return ( 0 ) ;
2007-10-04 00:43:55 +04:00
2004-03-13 03:28:53 +03:00
m = ubuf [ offset ] ;
2020-01-18 00:49:48 +03:00
/* m must be 32 to exactly fill in the 16 bytes of the netbios name */
if ( m ! = 32 ) {
return 0 ;
}
/* Cannot go past length. */
if ( offset + m + 2 > length ) {
return 0 ;
}
2004-03-13 03:28:53 +03:00
memset ( ( char * ) name , ' \0 ' , sizeof ( * name ) ) ;
/* the "compressed" part */
if ( ! got_pointer )
ret + = m + 2 ;
offset + + ;
while ( m > 0 ) {
unsigned char c1 , c2 ;
c1 = ubuf [ offset + + ] - ' A ' ;
c2 = ubuf [ offset + + ] - ' A ' ;
2018-11-12 22:37:31 +03:00
if ( ( c1 & 0xF0 ) | | ( c2 & 0xF0 ) ) {
2004-03-13 03:28:53 +03:00
return ( 0 ) ;
2018-11-12 22:37:31 +03:00
}
if ( n > = sizeof ( name - > name ) ) {
return 0 ;
}
2004-03-13 03:28:53 +03:00
name - > name [ n + + ] = ( c1 < < 4 ) | c2 ;
m - = 2 ;
}
2018-11-12 22:37:31 +03:00
/*
* RFC1002 : For a valid NetBIOS name , exiting from the above ,
* n * must * be MAX_NETBIOSNAME_LEN ( 16 ) .
*/
if ( n ! = MAX_NETBIOSNAME_LEN ) {
return 0 ;
2004-03-13 03:28:53 +03:00
}
2018-11-12 22:37:31 +03:00
/* parse out the name type, its always
* in the 16 th byte of the name */
name - > name_type = ( ( unsigned char ) name - > name [ 15 ] ) & 0xff ;
/* remove trailing spaces */
name - > name [ 15 ] = 0 ;
n = 14 ;
while ( n & & name - > name [ n ] = = ' ' )
name - > name [ n - - ] = 0 ;
2004-03-13 03:28:53 +03:00
/* now the domain parts (if any) */
n = 0 ;
while ( ubuf [ offset ] ) {
/* we can have pointers within the domain part as well */
if ( ! handle_name_ptrs ( ubuf , & offset , length , & got_pointer , & ret ) )
return ( 0 ) ;
m = ubuf [ offset ] ;
/*
* Don ' t allow null domain parts .
*/
if ( ! m )
return ( 0 ) ;
if ( ! got_pointer )
ret + = m + 1 ;
if ( n )
name - > scope [ n + + ] = ' . ' ;
if ( m + 2 + offset > length | | n + m + 1 > sizeof ( name - > scope ) )
return ( 0 ) ;
offset + + ;
while ( m - - )
name - > scope [ n + + ] = ( char ) ubuf [ offset + + ] ;
/*
* Watch for malicious loops .
*/
if ( loop_count + + = = 10 )
return 0 ;
}
2007-10-04 00:43:55 +04:00
name - > scope [ n + + ] = 0 ;
2004-03-13 03:28:53 +03:00
return ( ret ) ;
1996-05-04 11:50:46 +04:00
}
2004-03-13 03:28:53 +03:00
/****************************************************************************
Put a netbios name , padding ( s ) and a name type into a 16 character buffer .
name is already in DOS charset .
[ 15 bytes name + padding ] [ 1 byte name type ] .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-04-25 16:24:25 +04:00
void put_name ( char * dest , const char * name , int pad , unsigned int name_type )
2004-03-13 03:28:53 +03:00
{
size_t len = strlen ( name ) ;
2007-10-04 00:43:55 +04:00
memcpy ( dest , name , ( len < MAX_NETBIOSNAME_LEN ) ?
len : MAX_NETBIOSNAME_LEN - 1 ) ;
2004-03-13 03:28:53 +03:00
if ( len < MAX_NETBIOSNAME_LEN - 1 ) {
memset ( dest + len , pad , MAX_NETBIOSNAME_LEN - 1 - len ) ;
}
dest [ MAX_NETBIOSNAME_LEN - 1 ] = name_type ;
}
1996-05-04 11:50:46 +04:00
/*******************************************************************
2004-03-13 03:28:53 +03:00
Put a compressed nmb name into a buffer . Return the length of the
compressed name .
Compressed names are really weird . The " compression " doubles the
size . The idea is that it also means that compressed names conform
2023-07-05 12:26:30 +03:00
to the domain name system . See RFC1002 .
2007-10-04 00:43:55 +04:00
If buf = = NULL this is a length calculation .
2004-03-13 03:28:53 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-05-04 11:50:46 +04:00
2011-05-04 01:52:01 +04:00
static int put_nmb_name ( char * buf , size_t buflen , int offset , struct nmb_name * name )
1996-05-04 11:50:46 +04:00
{
2004-03-13 03:28:53 +03:00
int ret , m ;
2004-03-13 05:16:21 +03:00
nstring buf1 ;
2004-03-13 03:28:53 +03:00
char * p ;
if ( strcmp ( name - > name , " * " ) = = 0 ) {
/* special case for wildcard name */
put_name ( buf1 , " * " , ' \0 ' , name - > name_type ) ;
} else {
put_name ( buf1 , name - > name , ' ' , name - > name_type ) ;
}
2007-10-04 00:43:55 +04:00
if ( buf ) {
2011-05-04 01:52:01 +04:00
if ( offset > = buflen ) {
return 0 ;
}
2007-10-04 00:43:55 +04:00
buf [ offset ] = 0x20 ;
}
2004-03-13 03:28:53 +03:00
ret = 34 ;
for ( m = 0 ; m < MAX_NETBIOSNAME_LEN ; m + + ) {
2007-10-04 00:43:55 +04:00
if ( buf ) {
2011-05-04 01:52:01 +04:00
if ( offset + 2 + 2 * m > = buflen ) {
return 0 ;
}
2007-10-04 00:43:55 +04:00
buf [ offset + 1 + 2 * m ] = ' A ' + ( ( buf1 [ m ] > > 4 ) & 0xF ) ;
buf [ offset + 2 + 2 * m ] = ' A ' + ( buf1 [ m ] & 0xF ) ;
}
2004-03-13 03:28:53 +03:00
}
offset + = 33 ;
2007-10-04 00:43:55 +04:00
if ( buf ) {
2011-05-04 01:52:01 +04:00
if ( offset > = buflen ) {
return 0 ;
}
2007-10-04 00:43:55 +04:00
buf [ offset ] = 0 ;
}
2004-03-13 03:28:53 +03:00
if ( name - > scope [ 0 ] ) {
/* XXXX this scope handling needs testing */
2011-05-04 01:52:01 +04:00
size_t scopenamelen = strlen ( name - > scope ) + 1 ;
ret + = scopenamelen ;
2007-10-04 00:43:55 +04:00
if ( buf ) {
2011-05-04 01:52:01 +04:00
if ( offset + 1 + scopenamelen > = buflen ) {
return 0 ;
}
strlcpy ( & buf [ offset + 1 ] , name - > scope ,
buflen - ( offset + 1 ) ) ;
2007-10-04 00:43:55 +04:00
2004-03-13 03:28:53 +03:00
p = & buf [ offset + 1 ] ;
2007-10-04 00:43:55 +04:00
while ( ( p = strchr_m ( p , ' . ' ) ) ) {
buf [ offset ] = PTR_DIFF ( p , & buf [ offset + 1 ] ) ;
offset + = ( buf [ offset ] + 1 ) ;
2011-05-04 01:52:01 +04:00
if ( offset + 1 > = buflen ) {
return 0 ;
}
2007-10-04 00:43:55 +04:00
p = & buf [ offset + 1 ] ;
}
buf [ offset ] = strlen ( & buf [ offset + 1 ] ) ;
2004-03-13 03:28:53 +03:00
}
}
2007-10-04 00:43:55 +04:00
return ret ;
1996-05-04 11:50:46 +04:00
}
/*******************************************************************
2003-08-22 04:26:37 +04:00
Useful for debugging messages .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-12-07 02:06:38 +03:00
char * nmb_namestr ( const struct nmb_name * n )
1996-05-04 11:50:46 +04:00
{
2003-08-22 04:26:37 +04:00
fstring name ;
2007-11-24 17:47:04 +03:00
char * result ;
2003-08-22 04:26:37 +04:00
pull_ascii_fstring ( name , n - > name ) ;
if ( ! n - > scope [ 0 ] )
2007-11-24 17:47:04 +03:00
result = talloc_asprintf ( talloc_tos ( ) , " %s<%02x> " , name ,
n - > name_type ) ;
2003-08-22 04:26:37 +04:00
else
2007-11-24 17:47:04 +03:00
result = talloc_asprintf ( talloc_tos ( ) , " %s<%02x>.%s " , name ,
n - > name_type , n - > scope ) ;
2003-08-22 04:26:37 +04:00
2007-11-24 17:47:04 +03:00
SMB_ASSERT ( result ! = NULL ) ;
return result ;
1996-05-04 11:50:46 +04:00
}
/*******************************************************************
2004-03-13 03:28:53 +03:00
Allocate and parse some resource records .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool parse_alloc_res_rec ( char * inbuf , int * offset , int length ,
1996-06-04 10:42:03 +04:00
struct res_rec * * recs , int count )
1996-05-04 11:50:46 +04:00
{
2004-03-13 03:28:53 +03:00
int i ;
2004-12-07 21:25:53 +03:00
* recs = SMB_MALLOC_ARRAY ( struct res_rec , count ) ;
2004-03-13 03:28:53 +03:00
if ( ! * recs )
return ( False ) ;
memset ( ( char * ) * recs , ' \0 ' , sizeof ( * * recs ) * count ) ;
for ( i = 0 ; i < count ; i + + ) {
2007-10-04 00:43:55 +04:00
int l = parse_nmb_name ( inbuf , * offset , length ,
& ( * recs ) [ i ] . rr_name ) ;
2004-03-13 03:28:53 +03:00
( * offset ) + = l ;
if ( ! l | | ( * offset ) + 10 > length ) {
SAFE_FREE ( * recs ) ;
return ( False ) ;
}
( * recs ) [ i ] . rr_type = RSVAL ( inbuf , ( * offset ) ) ;
( * recs ) [ i ] . rr_class = RSVAL ( inbuf , ( * offset ) + 2 ) ;
( * recs ) [ i ] . ttl = RIVAL ( inbuf , ( * offset ) + 4 ) ;
( * recs ) [ i ] . rdlength = RSVAL ( inbuf , ( * offset ) + 8 ) ;
( * offset ) + = 10 ;
2007-10-04 00:43:55 +04:00
if ( ( * recs ) [ i ] . rdlength > sizeof ( ( * recs ) [ i ] . rdata ) | |
2004-03-13 03:28:53 +03:00
( * offset ) + ( * recs ) [ i ] . rdlength > length ) {
SAFE_FREE ( * recs ) ;
return ( False ) ;
}
memcpy ( ( * recs ) [ i ] . rdata , inbuf + ( * offset ) , ( * recs ) [ i ] . rdlength ) ;
2007-10-04 00:43:55 +04:00
( * offset ) + = ( * recs ) [ i ] . rdlength ;
2004-03-13 03:28:53 +03:00
}
return ( True ) ;
1996-05-04 11:50:46 +04:00
}
/*******************************************************************
2004-03-13 03:28:53 +03:00
Put a resource record into a packet .
2007-10-04 00:43:55 +04:00
If buf = = NULL this is a length calculation .
2004-03-13 03:28:53 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-05-04 01:52:01 +04:00
static int put_res_rec ( char * buf , size_t buflen , int offset , struct res_rec * recs , int count )
1996-05-04 11:50:46 +04:00
{
2004-03-13 03:28:53 +03:00
int ret = 0 ;
int i ;
for ( i = 0 ; i < count ; i + + ) {
2011-05-04 01:52:01 +04:00
int l = put_nmb_name ( buf , buflen , offset , & recs [ i ] . rr_name ) ;
2004-03-13 03:28:53 +03:00
offset + = l ;
ret + = l ;
2007-10-04 00:43:55 +04:00
if ( buf ) {
RSSVAL ( buf , offset , recs [ i ] . rr_type ) ;
RSSVAL ( buf , offset + 2 , recs [ i ] . rr_class ) ;
2021-10-28 16:51:13 +03:00
RSIVAL ( buf , offset + 4 , ( unsigned int ) recs [ i ] . ttl ) ;
2007-10-04 00:43:55 +04:00
RSSVAL ( buf , offset + 8 , recs [ i ] . rdlength ) ;
memcpy ( buf + offset + 10 , recs [ i ] . rdata , recs [ i ] . rdlength ) ;
}
2004-03-13 03:28:53 +03:00
offset + = 10 + recs [ i ] . rdlength ;
ret + = 10 + recs [ i ] . rdlength ;
}
2007-10-04 00:43:55 +04:00
return ret ;
1996-05-04 11:50:46 +04:00
}
1998-03-25 04:27:27 +03:00
/*******************************************************************
2004-03-13 03:28:53 +03:00
Put a compressed name pointer record into a packet .
2007-10-04 00:43:55 +04:00
If buf = = NULL this is a length calculation .
2004-03-13 03:28:53 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-04 00:43:55 +04:00
static int put_compressed_name_ptr ( unsigned char * buf ,
int offset ,
struct res_rec * rec ,
int ptr_offset )
{
2019-08-08 16:59:55 +03:00
int ret = offset ;
2007-10-04 00:43:55 +04:00
if ( buf ) {
buf [ offset ] = ( 0xC0 | ( ( ptr_offset > > 8 ) & 0xFF ) ) ;
buf [ offset + 1 ] = ( ptr_offset & 0xFF ) ;
}
2004-03-13 03:28:53 +03:00
offset + = 2 ;
2007-10-04 00:43:55 +04:00
if ( buf ) {
RSSVAL ( buf , offset , rec - > rr_type ) ;
RSSVAL ( buf , offset + 2 , rec - > rr_class ) ;
RSIVAL ( buf , offset + 4 , rec - > ttl ) ;
RSSVAL ( buf , offset + 8 , rec - > rdlength ) ;
memcpy ( buf + offset + 10 , rec - > rdata , rec - > rdlength ) ;
}
2004-03-13 03:28:53 +03:00
offset + = 10 + rec - > rdlength ;
2019-08-08 16:59:55 +03:00
ret = ( offset - ret ) ;
2007-10-04 00:43:55 +04:00
return ret ;
1998-03-25 04:27:27 +03:00
}
1996-05-04 11:50:46 +04:00
/*******************************************************************
2007-10-04 00:43:55 +04:00
Parse a dgram packet . Return False if the packet can ' t be parsed
2004-03-13 03:28:53 +03:00
or is invalid for some reason , True otherwise .
This is documented in section 4.4 .1 of RFC1002 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-05-04 11:50:46 +04:00
2007-10-19 04:40:25 +04:00
static bool parse_dgram ( char * inbuf , int length , struct dgram_packet * dgram )
1996-05-04 11:50:46 +04:00
{
2017-12-07 19:52:39 +03:00
size_t offset ;
2004-03-13 03:28:53 +03:00
int flags ;
memset ( ( char * ) dgram , ' \0 ' , sizeof ( * dgram ) ) ;
if ( length < 14 )
return ( False ) ;
dgram - > header . msg_type = CVAL ( inbuf , 0 ) ;
flags = CVAL ( inbuf , 1 ) ;
dgram - > header . flags . node_type = ( enum node_type ) ( ( flags > > 2 ) & 3 ) ;
if ( flags & 1 )
dgram - > header . flags . more = True ;
if ( flags & 2 )
dgram - > header . flags . first = True ;
dgram - > header . dgm_id = RSVAL ( inbuf , 2 ) ;
putip ( ( char * ) & dgram - > header . source_ip , inbuf + 4 ) ;
dgram - > header . source_port = RSVAL ( inbuf , 8 ) ;
dgram - > header . dgm_length = RSVAL ( inbuf , 10 ) ;
dgram - > header . packet_offset = RSVAL ( inbuf , 12 ) ;
offset = 14 ;
if ( dgram - > header . msg_type = = 0x10 | |
dgram - > header . msg_type = = 0x11 | |
2007-10-04 00:43:55 +04:00
dgram - > header . msg_type = = 0x12 ) {
offset + = parse_nmb_name ( inbuf , offset , length ,
& dgram - > source_name ) ;
offset + = parse_nmb_name ( inbuf , offset , length ,
& dgram - > dest_name ) ;
2004-03-13 03:28:53 +03:00
}
1996-05-04 11:50:46 +04:00
2007-10-04 00:43:55 +04:00
if ( offset > = length | | ( length - offset > sizeof ( dgram - > data ) ) )
2004-03-13 03:28:53 +03:00
return ( False ) ;
1996-05-04 11:50:46 +04:00
2004-03-13 03:28:53 +03:00
dgram - > datasize = length - offset ;
memcpy ( dgram - > data , inbuf + offset , dgram - > datasize ) ;
1996-05-04 11:50:46 +04:00
2004-09-04 05:57:16 +04:00
/* Paranioa. Ensure the last 2 bytes in the dgram buffer are
2007-10-04 00:43:55 +04:00
zero . This should be true anyway , just enforce it for
paranioa sake . JRA . */
2004-09-04 05:57:16 +04:00
SMB_ASSERT ( dgram - > datasize < = ( sizeof ( dgram - > data ) - 2 ) ) ;
memset ( & dgram - > data [ sizeof ( dgram - > data ) - 2 ] , ' \0 ' , 2 ) ;
2004-03-13 03:28:53 +03:00
return ( True ) ;
1996-05-04 11:50:46 +04:00
}
/*******************************************************************
2007-10-04 00:43:55 +04:00
Parse a nmb packet . Return False if the packet can ' t be parsed
2004-03-13 03:28:53 +03:00
or is invalid for some reason , True otherwise .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool parse_nmb ( char * inbuf , int length , struct nmb_packet * nmb )
1996-05-04 11:50:46 +04:00
{
2004-03-13 03:28:53 +03:00
int nm_flags , offset ;
memset ( ( char * ) nmb , ' \0 ' , sizeof ( * nmb ) ) ;
if ( length < 12 )
return ( False ) ;
/* parse the header */
nmb - > header . name_trn_id = RSVAL ( inbuf , 0 ) ;
DEBUG ( 10 , ( " parse_nmb: packet id = %d \n " , nmb - > header . name_trn_id ) ) ;
nmb - > header . opcode = ( CVAL ( inbuf , 2 ) > > 3 ) & 0xF ;
nmb - > header . response = ( ( CVAL ( inbuf , 2 ) > > 7 ) & 1 ) ? True : False ;
nm_flags = ( ( CVAL ( inbuf , 2 ) & 0x7 ) < < 4 ) + ( CVAL ( inbuf , 3 ) > > 4 ) ;
nmb - > header . nm_flags . bcast = ( nm_flags & 1 ) ? True : False ;
nmb - > header . nm_flags . recursion_available = ( nm_flags & 8 ) ? True : False ;
nmb - > header . nm_flags . recursion_desired = ( nm_flags & 0x10 ) ? True : False ;
nmb - > header . nm_flags . trunc = ( nm_flags & 0x20 ) ? True : False ;
2007-10-04 00:43:55 +04:00
nmb - > header . nm_flags . authoritative = ( nm_flags & 0x40 ) ? True : False ;
2004-03-13 03:28:53 +03:00
nmb - > header . rcode = CVAL ( inbuf , 3 ) & 0xF ;
nmb - > header . qdcount = RSVAL ( inbuf , 4 ) ;
nmb - > header . ancount = RSVAL ( inbuf , 6 ) ;
nmb - > header . nscount = RSVAL ( inbuf , 8 ) ;
nmb - > header . arcount = RSVAL ( inbuf , 10 ) ;
2007-10-04 00:43:55 +04:00
2004-03-13 03:28:53 +03:00
if ( nmb - > header . qdcount ) {
2007-10-04 00:43:55 +04:00
offset = parse_nmb_name ( inbuf , 12 , length ,
& nmb - > question . question_name ) ;
2004-03-13 03:28:53 +03:00
if ( ! offset )
return ( False ) ;
if ( length - ( 12 + offset ) < 4 )
return ( False ) ;
nmb - > question . question_type = RSVAL ( inbuf , 12 + offset ) ;
nmb - > question . question_class = RSVAL ( inbuf , 12 + offset + 2 ) ;
offset + = 12 + 4 ;
} else {
offset = 12 ;
}
/* and any resource records */
2007-10-04 00:43:55 +04:00
if ( nmb - > header . ancount & &
! parse_alloc_res_rec ( inbuf , & offset , length , & nmb - > answers ,
2004-03-13 03:28:53 +03:00
nmb - > header . ancount ) )
return ( False ) ;
2007-10-04 00:43:55 +04:00
if ( nmb - > header . nscount & &
! parse_alloc_res_rec ( inbuf , & offset , length , & nmb - > nsrecs ,
2004-03-13 03:28:53 +03:00
nmb - > header . nscount ) )
return ( False ) ;
2007-10-04 00:43:55 +04:00
if ( nmb - > header . arcount & &
! parse_alloc_res_rec ( inbuf , & offset , length ,
& nmb - > additional , nmb - > header . arcount ) )
2004-03-13 03:28:53 +03:00
return ( False ) ;
1996-05-04 11:50:46 +04:00
2004-03-13 03:28:53 +03:00
return ( True ) ;
1996-05-04 11:50:46 +04:00
}
1997-12-13 17:16:07 +03:00
/*******************************************************************
2004-03-13 03:28:53 +03:00
' Copy constructor ' for an nmb packet .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-12-13 17:16:07 +03:00
static struct packet_struct * copy_nmb_packet ( struct packet_struct * packet )
2007-10-04 00:43:55 +04:00
{
2004-03-13 03:28:53 +03:00
struct nmb_packet * nmb ;
struct nmb_packet * copy_nmb ;
struct packet_struct * pkt_copy ;
2004-12-07 21:25:53 +03:00
if ( ( pkt_copy = SMB_MALLOC_P ( struct packet_struct ) ) = = NULL ) {
2004-03-13 03:28:53 +03:00
DEBUG ( 0 , ( " copy_nmb_packet: malloc fail. \n " ) ) ;
return NULL ;
}
/* Structure copy of entire thing. */
* pkt_copy = * packet ;
/* Ensure this copy is not locked. */
pkt_copy - > locked = False ;
2010-01-28 13:04:05 +03:00
pkt_copy - > recv_fd = - 1 ;
pkt_copy - > send_fd = - 1 ;
2004-03-13 03:28:53 +03:00
/* Ensure this copy has no resource records. */
nmb = & packet - > packet . nmb ;
copy_nmb = & pkt_copy - > packet . nmb ;
copy_nmb - > answers = NULL ;
copy_nmb - > nsrecs = NULL ;
copy_nmb - > additional = NULL ;
/* Now copy any resource records. */
if ( nmb - > answers ) {
2007-10-04 00:43:55 +04:00
if ( ( copy_nmb - > answers = SMB_MALLOC_ARRAY (
struct res_rec , nmb - > header . ancount ) ) = = NULL )
2004-03-13 03:28:53 +03:00
goto free_and_exit ;
2007-10-04 00:43:55 +04:00
memcpy ( ( char * ) copy_nmb - > answers , ( char * ) nmb - > answers ,
2004-03-13 03:28:53 +03:00
nmb - > header . ancount * sizeof ( struct res_rec ) ) ;
}
if ( nmb - > nsrecs ) {
2007-10-04 00:43:55 +04:00
if ( ( copy_nmb - > nsrecs = SMB_MALLOC_ARRAY (
struct res_rec , nmb - > header . nscount ) ) = = NULL )
2004-03-13 03:28:53 +03:00
goto free_and_exit ;
2007-10-04 00:43:55 +04:00
memcpy ( ( char * ) copy_nmb - > nsrecs , ( char * ) nmb - > nsrecs ,
2004-03-13 03:28:53 +03:00
nmb - > header . nscount * sizeof ( struct res_rec ) ) ;
}
if ( nmb - > additional ) {
2007-10-04 00:43:55 +04:00
if ( ( copy_nmb - > additional = SMB_MALLOC_ARRAY (
struct res_rec , nmb - > header . arcount ) ) = = NULL )
2004-03-13 03:28:53 +03:00
goto free_and_exit ;
2007-10-04 00:43:55 +04:00
memcpy ( ( char * ) copy_nmb - > additional , ( char * ) nmb - > additional ,
2004-03-13 03:28:53 +03:00
nmb - > header . arcount * sizeof ( struct res_rec ) ) ;
}
return pkt_copy ;
free_and_exit :
SAFE_FREE ( copy_nmb - > answers ) ;
SAFE_FREE ( copy_nmb - > nsrecs ) ;
SAFE_FREE ( copy_nmb - > additional ) ;
SAFE_FREE ( pkt_copy ) ;
DEBUG ( 0 , ( " copy_nmb_packet: malloc fail in resource records. \n " ) ) ;
return NULL ;
1997-12-13 17:16:07 +03:00
}
/*******************************************************************
2004-03-13 03:28:53 +03:00
' Copy constructor ' for a dgram packet .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-12-13 17:16:07 +03:00
static struct packet_struct * copy_dgram_packet ( struct packet_struct * packet )
2007-10-04 00:43:55 +04:00
{
2004-03-13 03:28:53 +03:00
struct packet_struct * pkt_copy ;
1997-12-13 17:16:07 +03:00
2004-12-07 21:25:53 +03:00
if ( ( pkt_copy = SMB_MALLOC_P ( struct packet_struct ) ) = = NULL ) {
2004-03-13 03:28:53 +03:00
DEBUG ( 0 , ( " copy_dgram_packet: malloc fail. \n " ) ) ;
return NULL ;
}
1997-12-13 17:16:07 +03:00
2004-03-13 03:28:53 +03:00
/* Structure copy of entire thing. */
1997-12-13 17:16:07 +03:00
2004-03-13 03:28:53 +03:00
* pkt_copy = * packet ;
1997-12-13 17:16:07 +03:00
2004-03-13 03:28:53 +03:00
/* Ensure this copy is not locked. */
pkt_copy - > locked = False ;
2010-01-28 13:04:05 +03:00
pkt_copy - > recv_fd = - 1 ;
pkt_copy - > send_fd = - 1 ;
1997-12-13 17:16:07 +03:00
2004-03-13 03:28:53 +03:00
/* There are no additional pointers in a dgram packet,
we are finished . */
return pkt_copy ;
1997-12-13 17:16:07 +03:00
}
/*******************************************************************
2004-03-13 03:28:53 +03:00
' Copy constructor ' for a generic packet .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-12-13 17:16:07 +03:00
struct packet_struct * copy_packet ( struct packet_struct * packet )
2007-10-04 00:43:55 +04:00
{
2004-03-13 03:28:53 +03:00
if ( packet - > packet_type = = NMB_PACKET )
return copy_nmb_packet ( packet ) ;
else if ( packet - > packet_type = = DGRAM_PACKET )
return copy_dgram_packet ( packet ) ;
return NULL ;
1997-12-13 17:16:07 +03:00
}
2007-10-04 00:43:55 +04:00
1996-05-04 11:50:46 +04:00
/*******************************************************************
2004-03-13 03:28:53 +03:00
Free up any resources associated with an nmb packet .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-12-13 17:16:07 +03:00
static void free_nmb_packet ( struct nmb_packet * nmb )
2007-10-04 00:43:55 +04:00
{
2004-03-13 03:28:53 +03:00
SAFE_FREE ( nmb - > answers ) ;
SAFE_FREE ( nmb - > nsrecs ) ;
SAFE_FREE ( nmb - > additional ) ;
1996-05-04 11:50:46 +04:00
}
1997-12-13 17:16:07 +03:00
/*******************************************************************
2004-03-13 03:28:53 +03:00
Free up any resources associated with a dgram packet .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-12-13 17:16:07 +03:00
static void free_dgram_packet ( struct dgram_packet * nmb )
2007-10-04 00:43:55 +04:00
{
2004-03-13 03:28:53 +03:00
/* We have nothing to do for a dgram packet. */
1997-12-13 17:16:07 +03:00
}
1996-05-04 11:50:46 +04:00
/*******************************************************************
2004-03-13 03:28:53 +03:00
Free up any resources associated with a packet .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-05-04 11:50:46 +04:00
void free_packet ( struct packet_struct * packet )
2007-10-04 00:43:55 +04:00
{
if ( packet - > locked )
2004-03-13 03:28:53 +03:00
return ;
if ( packet - > packet_type = = NMB_PACKET )
free_nmb_packet ( & packet - > packet . nmb ) ;
else if ( packet - > packet_type = = DGRAM_PACKET )
free_dgram_packet ( & packet - > packet . dgram ) ;
ZERO_STRUCTPN ( packet ) ;
SAFE_FREE ( packet ) ;
1996-05-04 11:50:46 +04:00
}
2011-01-04 20:07:12 +03:00
int packet_trn_id ( struct packet_struct * p )
{
int result ;
switch ( p - > packet_type ) {
case NMB_PACKET :
result = p - > packet . nmb . header . name_trn_id ;
break ;
case DGRAM_PACKET :
result = p - > packet . dgram . header . dgm_id ;
break ;
default :
result = - 1 ;
}
return result ;
}
1996-05-04 11:50:46 +04:00
/*******************************************************************
2004-03-13 03:28:53 +03:00
Parse a packet buffer into a packet structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-01-03 06:17:16 +03:00
struct packet_struct * parse_packet ( char * buf , int length ,
2007-10-04 00:43:55 +04:00
enum packet_type packet_type ,
struct in_addr ip ,
int port )
1996-05-04 11:50:46 +04:00
{
2000-01-03 06:17:16 +03:00
struct packet_struct * p ;
2007-10-19 04:40:25 +04:00
bool ok = False ;
2000-01-03 06:17:16 +03:00
2004-12-07 21:25:53 +03:00
p = SMB_MALLOC_P ( struct packet_struct ) ;
2004-03-13 03:28:53 +03:00
if ( ! p )
return ( NULL ) ;
2000-01-03 06:17:16 +03:00
2007-12-19 19:05:26 +03:00
ZERO_STRUCTP ( p ) ; /* initialize for possible padding */
2000-01-03 06:17:16 +03:00
p - > next = NULL ;
p - > prev = NULL ;
2007-10-04 00:43:55 +04:00
p - > ip = ip ;
p - > port = port ;
2000-01-03 06:17:16 +03:00
p - > locked = False ;
p - > timestamp = time ( NULL ) ;
p - > packet_type = packet_type ;
switch ( packet_type ) {
case NMB_PACKET :
ok = parse_nmb ( buf , length , & p - > packet . nmb ) ;
break ;
2007-10-04 00:43:55 +04:00
2000-01-03 06:17:16 +03:00
case DGRAM_PACKET :
ok = parse_dgram ( buf , length , & p - > packet . dgram ) ;
break ;
}
1996-05-04 11:50:46 +04:00
2000-01-03 06:17:16 +03:00
if ( ! ok ) {
free_packet ( p ) ;
return NULL ;
}
1996-05-04 11:50:46 +04:00
2000-01-03 06:17:16 +03:00
return p ;
}
1996-05-04 11:50:46 +04:00
2018-01-23 16:39:21 +03:00
static struct packet_struct * copy_packet_talloc (
TALLOC_CTX * mem_ctx , const struct packet_struct * src )
{
struct packet_struct * pkt ;
pkt = talloc_memdup ( mem_ctx , src , sizeof ( struct packet_struct ) ) ;
if ( pkt = = NULL ) {
return NULL ;
}
pkt - > locked = false ;
pkt - > recv_fd = - 1 ;
pkt - > send_fd = - 1 ;
if ( src - > packet_type = = NMB_PACKET ) {
const struct nmb_packet * nsrc = & src - > packet . nmb ;
struct nmb_packet * ndst = & pkt - > packet . nmb ;
if ( nsrc - > answers ! = NULL ) {
ndst - > answers = talloc_memdup (
pkt , nsrc - > answers ,
sizeof ( struct res_rec ) * nsrc - > header . ancount ) ;
if ( ndst - > answers = = NULL ) {
goto fail ;
}
}
if ( nsrc - > nsrecs ! = NULL ) {
ndst - > nsrecs = talloc_memdup (
pkt , nsrc - > nsrecs ,
sizeof ( struct res_rec ) * nsrc - > header . nscount ) ;
if ( ndst - > nsrecs = = NULL ) {
goto fail ;
}
}
if ( nsrc - > additional ! = NULL ) {
ndst - > additional = talloc_memdup (
pkt , nsrc - > additional ,
sizeof ( struct res_rec ) * nsrc - > header . arcount ) ;
2018-01-24 14:57:43 +03:00
if ( ndst - > additional = = NULL ) {
2018-01-23 16:39:21 +03:00
goto fail ;
}
}
}
return pkt ;
/*
* DGRAM packets have no substructures
*/
fail :
TALLOC_FREE ( pkt ) ;
return NULL ;
}
struct packet_struct * parse_packet_talloc ( TALLOC_CTX * mem_ctx ,
char * buf , int length ,
enum packet_type packet_type ,
struct in_addr ip ,
int port )
{
struct packet_struct * pkt , * result ;
pkt = parse_packet ( buf , length , packet_type , ip , port ) ;
if ( pkt = = NULL ) {
return NULL ;
}
result = copy_packet_talloc ( mem_ctx , pkt ) ;
free_packet ( pkt ) ;
return result ;
}
1996-05-04 11:50:46 +04:00
/*******************************************************************
2004-03-13 03:28:53 +03:00
Send a udp packet on a already open socket .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool send_udp ( int fd , char * buf , int len , struct in_addr ip , int port )
1996-05-04 11:50:46 +04:00
{
2007-10-19 04:40:25 +04:00
bool ret = False ;
2004-03-13 03:28:53 +03:00
int i ;
struct sockaddr_in sock_out ;
/* set the address and port */
memset ( ( char * ) & sock_out , ' \0 ' , sizeof ( sock_out ) ) ;
putip ( ( char * ) & sock_out . sin_addr , ( char * ) & ip ) ;
sock_out . sin_port = htons ( port ) ;
sock_out . sin_family = AF_INET ;
2007-10-04 00:43:55 +04:00
2004-03-13 03:28:53 +03:00
DEBUG ( 5 , ( " Sending a packet of len %d to (%s) on port %d \n " ,
len , inet_ntoa ( ip ) , port ) ) ;
2000-10-07 02:37:42 +04:00
2004-03-13 03:28:53 +03:00
/*
* Patch to fix asynch error notifications from Linux kernel .
*/
2007-10-04 00:43:55 +04:00
2004-03-13 03:28:53 +03:00
for ( i = 0 ; i < 5 ; i + + ) {
2007-10-04 00:43:55 +04:00
ret = ( sendto ( fd , buf , len , 0 , ( struct sockaddr * ) & sock_out ,
sizeof ( sock_out ) ) > = 0 ) ;
2004-03-13 03:28:53 +03:00
if ( ret | | errno ! = ECONNREFUSED )
break ;
}
1996-05-04 11:50:46 +04:00
2004-03-13 03:28:53 +03:00
if ( ! ret )
DEBUG ( 0 , ( " Packet send failed to %s(%d) ERRNO=%s \n " ,
inet_ntoa ( ip ) , port , strerror ( errno ) ) ) ;
1996-05-04 11:50:46 +04:00
2004-03-13 03:28:53 +03:00
return ( ret ) ;
1996-05-04 11:50:46 +04:00
}
/*******************************************************************
2004-03-13 03:28:53 +03:00
Build a dgram packet ready for sending .
2007-10-04 00:43:55 +04:00
If buf = = NULL this is a length calculation .
2004-03-13 03:28:53 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-04-22 07:09:23 +04:00
2008-03-02 11:43:19 +03:00
static int build_dgram ( char * buf , size_t len , struct dgram_packet * dgram )
1996-05-04 11:50:46 +04:00
{
2004-03-13 03:28:53 +03:00
unsigned char * ubuf = ( unsigned char * ) buf ;
int offset = 0 ;
/* put in the header */
2007-10-04 00:43:55 +04:00
if ( buf ) {
ubuf [ 0 ] = dgram - > header . msg_type ;
ubuf [ 1 ] = ( ( ( int ) dgram - > header . flags . node_type ) < < 2 ) ;
if ( dgram - > header . flags . more )
ubuf [ 1 ] | = 1 ;
if ( dgram - > header . flags . first )
ubuf [ 1 ] | = 2 ;
RSSVAL ( ubuf , 2 , dgram - > header . dgm_id ) ;
putip ( ubuf + 4 , ( char * ) & dgram - > header . source_ip ) ;
RSSVAL ( ubuf , 8 , dgram - > header . source_port ) ;
RSSVAL ( ubuf , 12 , dgram - > header . packet_offset ) ;
}
2004-03-13 03:28:53 +03:00
offset = 14 ;
if ( dgram - > header . msg_type = = 0x10 | |
dgram - > header . msg_type = = 0x11 | |
2007-10-04 00:43:55 +04:00
dgram - > header . msg_type = = 0x12 ) {
2011-05-04 01:52:01 +04:00
offset + = put_nmb_name ( ( char * ) ubuf , len , offset , & dgram - > source_name ) ;
offset + = put_nmb_name ( ( char * ) ubuf , len , offset , & dgram - > dest_name ) ;
2004-03-13 03:28:53 +03:00
}
2007-10-04 00:43:55 +04:00
if ( buf ) {
memcpy ( ubuf + offset , dgram - > data , dgram - > datasize ) ;
}
2004-03-13 03:28:53 +03:00
offset + = dgram - > datasize ;
/* automatically set the dgm_length
* NOTE : RFC1002 says the dgm_length does * not *
* include the fourteen - byte header . crh
*/
dgram - > header . dgm_length = ( offset - 14 ) ;
2007-10-04 00:43:55 +04:00
if ( buf ) {
RSSVAL ( ubuf , 10 , dgram - > header . dgm_length ) ;
}
2004-03-13 03:28:53 +03:00
2007-10-04 00:43:55 +04:00
return offset ;
1996-05-04 11:50:46 +04:00
}
/*******************************************************************
2002-11-13 02:20:50 +03:00
Build a nmb name
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-01-07 09:55:36 +03:00
void make_nmb_name ( struct nmb_name * n , const char * name , int type )
1996-05-04 11:50:46 +04:00
{
2004-03-13 05:47:21 +03:00
fstring unix_name ;
1998-11-14 07:16:07 +03:00
memset ( ( char * ) n , ' \0 ' , sizeof ( struct nmb_name ) ) ;
2004-03-13 05:47:21 +03:00
fstrcpy ( unix_name , name ) ;
2012-08-09 02:35:28 +04:00
( void ) strupper_m ( unix_name ) ;
2004-03-13 05:47:21 +03:00
push_ascii ( n - > name , unix_name , sizeof ( n - > name ) , STR_TERMINATE ) ;
1998-11-14 07:16:07 +03:00
n - > name_type = ( unsigned int ) type & 0xFF ;
2011-06-08 10:27:06 +04:00
push_ascii ( n - > scope , lp_netbios_scope ( ) , 64 , STR_TERMINATE ) ;
1996-05-04 11:50:46 +04:00
}
1997-12-13 17:16:07 +03:00
/*******************************************************************
Compare two nmb names
2004-03-13 03:28:53 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-12-13 17:16:07 +03:00
2007-10-19 04:40:25 +04:00
bool nmb_name_equal ( struct nmb_name * n1 , struct nmb_name * n2 )
1997-12-13 17:16:07 +03:00
{
2004-03-13 03:28:53 +03:00
return ( ( n1 - > name_type = = n2 - > name_type ) & &
strequal ( n1 - > name , n2 - > name ) & &
strequal ( n1 - > scope , n2 - > scope ) ) ;
1997-12-13 17:16:07 +03:00
}
1996-05-04 11:50:46 +04:00
/*******************************************************************
2004-03-13 03:28:53 +03:00
Build a nmb packet ready for sending .
2007-10-04 00:43:55 +04:00
If buf = = NULL this is a length calculation .
2004-03-13 03:28:53 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1996-05-04 11:50:46 +04:00
2008-03-02 11:43:19 +03:00
static int build_nmb ( char * buf , size_t len , struct nmb_packet * nmb )
1996-05-04 11:50:46 +04:00
{
2004-03-13 03:28:53 +03:00
unsigned char * ubuf = ( unsigned char * ) buf ;
int offset = 0 ;
2007-10-04 00:43:55 +04:00
if ( len & & len < 12 ) {
return 0 ;
}
2004-03-13 03:28:53 +03:00
/* put in the header */
2007-10-04 00:43:55 +04:00
if ( buf ) {
RSSVAL ( ubuf , offset , nmb - > header . name_trn_id ) ;
ubuf [ offset + 2 ] = ( nmb - > header . opcode & 0xF ) < < 3 ;
if ( nmb - > header . response )
ubuf [ offset + 2 ] | = ( 1 < < 7 ) ;
if ( nmb - > header . nm_flags . authoritative & &
nmb - > header . response )
ubuf [ offset + 2 ] | = 0x4 ;
if ( nmb - > header . nm_flags . trunc )
ubuf [ offset + 2 ] | = 0x2 ;
if ( nmb - > header . nm_flags . recursion_desired )
ubuf [ offset + 2 ] | = 0x1 ;
if ( nmb - > header . nm_flags . recursion_available & &
nmb - > header . response )
ubuf [ offset + 3 ] | = 0x80 ;
if ( nmb - > header . nm_flags . bcast )
ubuf [ offset + 3 ] | = 0x10 ;
ubuf [ offset + 3 ] | = ( nmb - > header . rcode & 0xF ) ;
RSSVAL ( ubuf , offset + 4 , nmb - > header . qdcount ) ;
RSSVAL ( ubuf , offset + 6 , nmb - > header . ancount ) ;
RSSVAL ( ubuf , offset + 8 , nmb - > header . nscount ) ;
RSSVAL ( ubuf , offset + 10 , nmb - > header . arcount ) ;
}
2004-03-13 03:28:53 +03:00
offset + = 12 ;
if ( nmb - > header . qdcount ) {
/* XXXX this doesn't handle a qdcount of > 1 */
2007-10-04 00:43:55 +04:00
if ( len ) {
/* Length check. */
2011-05-04 01:52:01 +04:00
int extra = put_nmb_name ( NULL , 0 , offset ,
2007-10-04 00:43:55 +04:00
& nmb - > question . question_name ) ;
if ( offset + extra > len ) {
return 0 ;
}
}
2011-05-04 01:52:01 +04:00
offset + = put_nmb_name ( ( char * ) ubuf , len , offset ,
2007-10-04 00:43:55 +04:00
& nmb - > question . question_name ) ;
if ( buf ) {
RSSVAL ( ubuf , offset , nmb - > question . question_type ) ;
RSSVAL ( ubuf , offset + 2 , nmb - > question . question_class ) ;
}
2004-03-13 03:28:53 +03:00
offset + = 4 ;
}
2007-10-04 00:43:55 +04:00
if ( nmb - > header . ancount ) {
if ( len ) {
/* Length check. */
2011-05-04 01:52:01 +04:00
int extra = put_res_rec ( NULL , 0 , offset , nmb - > answers ,
2007-10-04 00:43:55 +04:00
nmb - > header . ancount ) ;
if ( offset + extra > len ) {
return 0 ;
}
}
2011-05-04 01:52:01 +04:00
offset + = put_res_rec ( ( char * ) ubuf , len , offset , nmb - > answers ,
2004-03-13 03:28:53 +03:00
nmb - > header . ancount ) ;
2007-10-04 00:43:55 +04:00
}
2004-03-13 03:28:53 +03:00
2007-10-04 00:43:55 +04:00
if ( nmb - > header . nscount ) {
if ( len ) {
/* Length check. */
2011-05-04 01:52:01 +04:00
int extra = put_res_rec ( NULL , 0 , offset , nmb - > nsrecs ,
2007-10-04 00:43:55 +04:00
nmb - > header . nscount ) ;
if ( offset + extra > len ) {
return 0 ;
}
}
2011-05-04 01:52:01 +04:00
offset + = put_res_rec ( ( char * ) ubuf , len , offset , nmb - > nsrecs ,
2004-03-13 03:28:53 +03:00
nmb - > header . nscount ) ;
2007-10-04 00:43:55 +04:00
}
2004-03-13 03:28:53 +03:00
/*
* The spec says we must put compressed name pointers
* in the following outgoing packets :
* NAME_REGISTRATION_REQUEST , NAME_REFRESH_REQUEST ,
* NAME_RELEASE_REQUEST .
*/
if ( ( nmb - > header . response = = False ) & &
2007-10-04 00:43:55 +04:00
( ( nmb - > header . opcode = = NMB_NAME_REG_OPCODE ) | |
( nmb - > header . opcode = = NMB_NAME_RELEASE_OPCODE ) | |
( nmb - > header . opcode = = NMB_NAME_REFRESH_OPCODE_8 ) | |
( nmb - > header . opcode = = NMB_NAME_REFRESH_OPCODE_9 ) | |
( nmb - > header . opcode = = NMB_NAME_MULTIHOMED_REG_OPCODE ) ) & &
( nmb - > header . arcount = = 1 ) ) {
if ( len ) {
/* Length check. */
int extra = put_compressed_name_ptr ( NULL , offset ,
nmb - > additional , 12 ) ;
if ( offset + extra > len ) {
return 0 ;
}
}
offset + = put_compressed_name_ptr ( ubuf , offset ,
nmb - > additional , 12 ) ;
2004-03-13 03:28:53 +03:00
} else if ( nmb - > header . arcount ) {
2007-10-04 00:43:55 +04:00
if ( len ) {
/* Length check. */
2011-05-04 01:52:01 +04:00
int extra = put_res_rec ( NULL , 0 , offset , nmb - > additional ,
2007-10-04 00:43:55 +04:00
nmb - > header . arcount ) ;
if ( offset + extra > len ) {
return 0 ;
}
}
2011-05-04 01:52:01 +04:00
offset + = put_res_rec ( ( char * ) ubuf , len , offset , nmb - > additional ,
2007-10-04 00:43:55 +04:00
nmb - > header . arcount ) ;
2004-03-13 03:28:53 +03:00
}
2007-10-04 00:43:55 +04:00
return offset ;
2004-03-13 03:28:53 +03:00
}
1996-05-04 11:50:46 +04:00
2000-01-03 06:17:16 +03:00
/*******************************************************************
2004-03-13 03:28:53 +03:00
Linearise a packet .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-04 00:43:55 +04:00
int build_packet ( char * buf , size_t buflen , struct packet_struct * p )
2000-01-03 06:17:16 +03:00
{
int len = 0 ;
switch ( p - > packet_type ) {
case NMB_PACKET :
2008-03-02 11:43:19 +03:00
len = build_nmb ( buf , buflen , & p - > packet . nmb ) ;
2000-01-03 06:17:16 +03:00
break ;
case DGRAM_PACKET :
2008-03-02 11:43:19 +03:00
len = build_dgram ( buf , buflen , & p - > packet . dgram ) ;
2000-01-03 06:17:16 +03:00
break ;
}
return len ;
}
1996-05-04 11:50:46 +04:00
/*******************************************************************
2004-03-13 03:28:53 +03:00
Send a packet_struct .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
bool send_packet ( struct packet_struct * p )
1996-05-04 11:50:46 +04:00
{
2004-03-13 03:28:53 +03:00
char buf [ 1024 ] ;
int len = 0 ;
1996-05-04 11:50:46 +04:00
2004-03-13 03:28:53 +03:00
memset ( buf , ' \0 ' , sizeof ( buf ) ) ;
1996-05-04 11:50:46 +04:00
2007-10-04 00:43:55 +04:00
len = build_packet ( buf , sizeof ( buf ) , p ) ;
1996-05-04 11:50:46 +04:00
2004-03-13 03:28:53 +03:00
if ( ! len )
return ( False ) ;
1996-05-04 11:50:46 +04:00
2010-01-28 13:04:05 +03:00
return ( send_udp ( p - > send_fd , buf , len , p - > ip , p - > port ) ) ;
1996-05-04 11:50:46 +04:00
}
2000-01-03 09:30:50 +03:00
/****************************************************************************
2004-03-13 03:28:53 +03:00
Receive a UDP / 138 packet either via UDP or from the unexpected packet
queue . The packet must be a reply packet and have the specified mailslot name
The timeout is in milliseconds .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-01-03 09:30:50 +03:00
/****************************************************************************
2004-03-13 03:28:53 +03:00
See if a datagram has the right mailslot name .
2000-01-03 09:30:50 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-13 03:28:53 +03:00
2007-10-19 04:40:25 +04:00
bool match_mailslot_name ( struct packet_struct * p , const char * mailslot_name )
2000-01-03 09:30:50 +03:00
{
struct dgram_packet * dgram = & p - > packet . dgram ;
char * buf ;
buf = & dgram - > data [ 0 ] ;
buf - = 4 ;
buf = smb_buf ( buf ) ;
if ( memcmp ( buf , mailslot_name , strlen ( mailslot_name ) + 1 ) = = 0 ) {
return True ;
}
return False ;
1996-05-04 11:50:46 +04:00
}
1998-08-30 12:45:23 +04:00
/****************************************************************************
2007-10-25 01:16:54 +04:00
Return the number of bits that match between two len character buffers
2004-03-13 03:28:53 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-05-06 01:22:11 +04:00
int matching_len_bits ( const unsigned char * p1 , const unsigned char * p2 , size_t len )
1998-08-30 12:45:23 +04:00
{
2007-10-25 01:16:54 +04:00
size_t i , j ;
int ret = 0 ;
for ( i = 0 ; i < len ; i + + ) {
2004-03-13 03:28:53 +03:00
if ( p1 [ i ] ! = p2 [ i ] )
break ;
1998-08-30 12:45:23 +04:00
ret + = 8 ;
}
2007-10-25 01:16:54 +04:00
if ( i = = len )
2004-03-13 03:28:53 +03:00
return ret ;
1998-08-30 12:45:23 +04:00
for ( j = 0 ; j < 8 ; j + + ) {
2004-03-13 03:28:53 +03:00
if ( ( p1 [ i ] & ( 1 < < ( 7 - j ) ) ) ! = ( p2 [ i ] & ( 1 < < ( 7 - j ) ) ) )
break ;
1998-08-30 12:45:23 +04:00
ret + + ;
2007-10-04 00:43:55 +04:00
}
1998-08-30 12:45:23 +04:00
return ret ;
}
2004-03-13 03:28:53 +03:00
static unsigned char sort_ip [ 4 ] ;
1998-08-30 12:45:23 +04:00
/****************************************************************************
2004-03-13 03:28:53 +03:00
Compare two query reply records .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int name_query_comp ( unsigned char * p1 , unsigned char * p2 )
1998-08-30 12:45:23 +04:00
{
2007-10-25 01:16:54 +04:00
return matching_len_bits ( p2 + 2 , sort_ip , 4 ) -
matching_len_bits ( p1 + 2 , sort_ip , 4 ) ;
1998-08-30 12:45:23 +04:00
}
/****************************************************************************
2004-03-13 03:28:53 +03:00
Sort a set of 6 byte name query response records so that the IPs that
have the most leading bits in common with the specified address come first .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-30 12:45:23 +04:00
void sort_query_replies ( char * data , int n , struct in_addr ip )
{
2004-03-13 03:28:53 +03:00
if ( n < = 1 )
return ;
1998-08-30 12:45:23 +04:00
putip ( sort_ip , ( char * ) & ip ) ;
2010-02-14 02:00:49 +03:00
/* TODO:
this can ' t use TYPESAFE_QSORT ( ) as the types are wrong .
It should be fixed to use a real type instead of char *
*/
1998-08-31 07:13:20 +04:00
qsort ( data , n , 6 , QSORT_CAST name_query_comp ) ;
1998-08-30 12:45:23 +04:00
}
2000-03-27 05:33:43 +04:00
/****************************************************************************
2004-03-13 03:28:53 +03:00
Interpret the weird netbios " name " into a unix fstring . Return the name type .
2010-09-26 13:59:32 +04:00
Returns - 1 on error .
2000-03-27 05:33:43 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-13 03:28:53 +03:00
2010-09-26 13:59:32 +04:00
static int name_interpret ( unsigned char * buf , size_t buf_len ,
unsigned char * in , fstring name )
2000-03-27 05:33:43 +04:00
{
2010-09-26 13:59:32 +04:00
unsigned char * end_ptr = buf + buf_len ;
2004-03-13 03:28:53 +03:00
int ret ;
2010-09-26 13:59:32 +04:00
unsigned int len ;
2004-03-13 03:28:53 +03:00
fstring out_string ;
2010-09-26 13:59:32 +04:00
unsigned char * out = ( unsigned char * ) out_string ;
2004-03-13 03:28:53 +03:00
* out = 0 ;
2010-09-26 13:59:32 +04:00
if ( in > = end_ptr ) {
return - 1 ;
}
len = ( * in + + ) / 2 ;
if ( len < 1 ) {
return - 1 ;
}
2004-03-13 03:28:53 +03:00
while ( len - - ) {
2010-09-26 13:59:32 +04:00
if ( & in [ 1 ] > = end_ptr ) {
return - 1 ;
}
2004-03-13 03:28:53 +03:00
if ( in [ 0 ] < ' A ' | | in [ 0 ] > ' P ' | | in [ 1 ] < ' A ' | | in [ 1 ] > ' P ' ) {
* out = 0 ;
return ( 0 ) ;
}
* out = ( ( in [ 0 ] - ' A ' ) < < 4 ) + ( in [ 1 ] - ' A ' ) ;
in + = 2 ;
out + + ;
2010-09-26 13:59:32 +04:00
if ( PTR_DIFF ( out , out_string ) > = sizeof ( fstring ) ) {
return - 1 ;
}
2004-03-13 03:28:53 +03:00
}
ret = out [ - 1 ] ;
out [ - 1 ] = 0 ;
2000-03-27 05:33:43 +04:00
2004-03-13 03:28:53 +03:00
pull_ascii_fstring ( name , out_string ) ;
2003-07-27 06:28:25 +04:00
2004-03-13 03:28:53 +03:00
return ( ret ) ;
2000-03-27 05:33:43 +04:00
}
/****************************************************************************
2004-03-13 03:28:53 +03:00
Mangle a name into netbios format .
Note : < Out > must be ( 33 + strlen ( scope ) + 2 ) bytes long , at minimum .
2000-03-27 05:33:43 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-13 03:28:53 +03:00
2010-12-12 20:53:49 +03:00
char * name_mangle ( TALLOC_CTX * mem_ctx , const char * In , char name_type )
2004-03-13 03:28:53 +03:00
{
int i ;
int len ;
2004-03-13 05:16:21 +03:00
nstring buf ;
2009-02-22 13:53:50 +03:00
char * result ;
char * p ;
2011-06-08 10:27:06 +04:00
result = talloc_array ( mem_ctx , char , 33 + strlen ( lp_netbios_scope ( ) ) + 2 ) ;
2009-02-22 13:53:50 +03:00
if ( result = = NULL ) {
return NULL ;
}
p = result ;
2004-03-13 03:28:53 +03:00
/* Safely copy the input string, In, into buf[]. */
2004-03-13 05:16:21 +03:00
if ( strcmp ( In , " * " ) = = 0 )
put_name ( buf , " * " , ' \0 ' , 0x00 ) ;
else {
/* We use an fstring here as mb dos names can expend x3 when
going to utf8 . */
fstring buf_unix ;
nstring buf_dos ;
pull_ascii_fstring ( buf_unix , In ) ;
2012-08-09 02:35:28 +04:00
if ( ! strupper_m ( buf_unix ) ) {
return NULL ;
}
2004-03-13 05:16:21 +03:00
push_ascii_nstring ( buf_dos , buf_unix ) ;
put_name ( buf , buf_dos , ' ' , name_type ) ;
2004-03-13 03:28:53 +03:00
}
2000-03-27 05:33:43 +04:00
2004-03-13 03:28:53 +03:00
/* Place the length of the first field into the output buffer. */
p [ 0 ] = 32 ;
p + + ;
/* Now convert the name to the rfc1001/1002 format. */
for ( i = 0 ; i < MAX_NETBIOSNAME_LEN ; i + + ) {
2004-03-13 05:16:21 +03:00
p [ i * 2 ] = ( ( buf [ i ] > > 4 ) & 0x000F ) + ' A ' ;
p [ ( i * 2 ) + 1 ] = ( buf [ i ] & 0x000F ) + ' A ' ;
2004-03-13 03:28:53 +03:00
}
p + = 32 ;
p [ 0 ] = ' \0 ' ;
/* Add the scope string. */
2011-06-08 10:27:06 +04:00
for ( i = 0 , len = 0 ; * ( lp_netbios_scope ( ) ) ! = ' \0 ' ; i + + , len + + ) {
switch ( ( lp_netbios_scope ( ) ) [ i ] ) {
2004-03-13 03:28:53 +03:00
case ' \0 ' :
p [ 0 ] = len ;
if ( len > 0 )
p [ len + 1 ] = 0 ;
2009-02-22 13:53:50 +03:00
return result ;
2004-03-13 03:28:53 +03:00
case ' . ' :
p [ 0 ] = len ;
p + = ( len + 1 ) ;
len = - 1 ;
break ;
default :
2011-06-08 10:27:06 +04:00
p [ len + 1 ] = ( lp_netbios_scope ( ) ) [ i ] ;
2004-03-13 03:28:53 +03:00
break ;
}
}
2009-02-22 13:53:50 +03:00
return result ;
2004-03-13 03:28:53 +03:00
}
2000-03-27 05:33:43 +04:00
/****************************************************************************
2004-03-13 03:28:53 +03:00
Find a pointer to a netbios name .
2000-03-27 05:33:43 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-13 03:28:53 +03:00
2010-09-26 13:59:32 +04:00
static unsigned char * name_ptr ( unsigned char * buf , size_t buf_len , unsigned int ofs )
2000-03-27 05:33:43 +04:00
{
2010-09-26 13:59:32 +04:00
unsigned char c = 0 ;
if ( ofs > buf_len | | buf_len < 1 ) {
return NULL ;
}
2004-03-13 03:28:53 +03:00
2010-09-26 13:59:32 +04:00
c = * ( unsigned char * ) ( buf + ofs ) ;
2004-03-13 03:28:53 +03:00
if ( ( c & 0xC0 ) = = 0xC0 ) {
2015-05-10 02:59:45 +03:00
uint16_t l = 0 ;
2010-09-26 13:59:32 +04:00
if ( ofs > buf_len - 1 ) {
return NULL ;
}
l = RSVAL ( buf , ofs ) & 0x3FFF ;
if ( l > buf_len ) {
return NULL ;
}
2004-03-13 03:28:53 +03:00
DEBUG ( 5 , ( " name ptr to pos %d from %d is %s \n " , l , ofs , buf + l ) ) ;
return ( buf + l ) ;
} else {
return ( buf + ofs ) ;
}
2007-10-04 00:43:55 +04:00
}
2000-03-27 05:33:43 +04:00
/****************************************************************************
2004-03-13 03:28:53 +03:00
Extract a netbios name from a buf ( into a unix string ) return name type .
2010-09-26 13:59:32 +04:00
Returns - 1 on error .
2000-03-27 05:33:43 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-13 03:28:53 +03:00
2010-09-26 13:59:32 +04:00
int name_extract ( unsigned char * buf , size_t buf_len , unsigned int ofs , fstring name )
2000-03-27 05:33:43 +04:00
{
2010-09-26 13:59:32 +04:00
unsigned char * p = name_ptr ( buf , buf_len , ofs ) ;
2004-03-13 03:28:53 +03:00
name [ 0 ] = ' \0 ' ;
2010-09-26 13:59:32 +04:00
if ( p = = NULL ) {
return - 1 ;
}
return ( name_interpret ( buf , buf_len , p , name ) ) ;
2000-03-27 05:33:43 +04:00
}
2007-10-04 00:43:55 +04:00
2000-03-27 05:33:43 +04:00
/****************************************************************************
2004-03-13 03:28:53 +03:00
Return the total storage length of a mangled name .
2010-09-26 13:59:32 +04:00
Returns - 1 on error .
2000-03-27 05:33:43 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2004-03-13 03:28:53 +03:00
2010-09-26 13:59:32 +04:00
int name_len ( unsigned char * s1 , size_t buf_len )
2000-03-27 05:33:43 +04:00
{
/* NOTE: this argument _must_ be unsigned */
2004-03-13 03:28:53 +03:00
unsigned char * s = ( unsigned char * ) s1 ;
2010-09-26 13:59:32 +04:00
int len = 0 ;
2000-03-27 05:33:43 +04:00
2010-09-26 13:59:32 +04:00
if ( buf_len < 1 ) {
return - 1 ;
}
2000-03-27 05:33:43 +04:00
/* If the two high bits of the byte are set, return 2. */
2010-09-26 13:59:32 +04:00
if ( 0xC0 = = ( * s & 0xC0 ) ) {
if ( buf_len < 2 ) {
return - 1 ;
}
2000-03-27 05:33:43 +04:00
return ( 2 ) ;
2010-09-26 13:59:32 +04:00
}
2000-03-27 05:33:43 +04:00
/* Add up the length bytes. */
for ( len = 1 ; ( * s ) ; s + = ( * s ) + 1 ) {
len + = * s + 1 ;
2010-09-26 13:59:32 +04:00
if ( len > buf_len ) {
return - 1 ;
}
2000-03-27 05:33:43 +04:00
}
return ( len ) ;
2004-03-13 03:28:53 +03:00
}
2019-10-30 18:19:40 +03:00
/*******************************************************************
Setup the word count and byte count for a client smb message .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int cli_set_message ( char * buf , int num_words , int num_bytes , bool zero )
{
if ( zero & & ( num_words | | num_bytes ) ) {
memset ( buf + smb_size , ' \0 ' , num_words * 2 + num_bytes ) ;
}
SCVAL ( buf , smb_wct , num_words ) ;
SSVAL ( buf , smb_vwv + num_words * SIZEOFWORD , num_bytes ) ;
smb_setlen ( buf , smb_size + num_words * 2 + num_bytes - 4 ) ;
return ( smb_size + num_words * 2 + num_bytes ) ;
}