1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-28 01:58:17 +03:00

First part of patch from moriyama@miraclelinux.com (MORIYAMA Masayuki) to

fix up netbios names with mb strings. Includes reformat of libsmb/nmblib.c
so it's readable.
Jeremy.
(This used to be commit 966e49a48c352563cdd7f75fe2768f2d6612ec7e)
This commit is contained in:
Jeremy Allison 2004-03-13 00:28:53 +00:00
parent 220d663b74
commit fd2d4f87d4
5 changed files with 809 additions and 731 deletions

View File

@ -1504,7 +1504,8 @@ struct cnotify_fns {
#include "smb_macros.h"
typedef char nstring[16];
#define MAX_NETBIOSNAME_LEN 16
typedef char nstring[MAX_NETBIOSNAME_LEN];
/* A netbios name structure. */
struct nmb_name {

View File

@ -823,9 +823,37 @@ size_t push_ascii_pstring(void *dest, const char *src)
return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE);
}
/********************************************************************
Push an nstring - ensure null terminated. Written by
moriyama@miraclelinux.com (MORIYAMA Masayuki).
********************************************************************/
size_t push_ascii_nstring(void *dest, const char *src)
{
return push_ascii(dest, src, sizeof(nstring), STR_TERMINATE);
size_t i, buffer_len, dest_len;
smb_ucs2_t *buffer;
buffer_len = push_ucs2_allocate(&buffer, src);
if (buffer_len == (size_t)-1) {
smb_panic("failed to create UCS2 buffer");
}
dest_len = 0;
for (i = 0; i < buffer_len; i++) {
unsigned char mb[10];
/* Convert one smb_ucs2_t character at a time. */
size_t mb_len = convert_string(CH_UCS2, CH_DOS, buffer+i, sizeof(smb_ucs2_t), mb, sizeof(mb), False);
if ((mb_len != (size_t)-1) && (dest_len + mb_len <= MAX_NETBIOSNAME_LEN - 1)) {
memcpy((char *)dest + dest_len, mb, mb_len);
dest_len += mb_len;
} else {
break;
}
}
((char *)dest)[dest_len] = '\0';
SAFE_FREE(buffer);
return dest_len;
}
/**

View File

@ -202,7 +202,7 @@ BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr t
if (i == count)
goto done;
pull_ascii(name, status[i].name, 16, 15, STR_TERMINATE);
pull_ascii_nstring(name, status[i].name);
/* Store the result in the cache. */
/* but don't store an entry for 0x1c names here. Here we have

View File

@ -39,8 +39,9 @@ static const struct opcode_names {
};
/****************************************************************************
* Lookup a nmb opcode name.
Lookup a nmb opcode name.
****************************************************************************/
static const char *lookup_opcode_name( int opcode )
{
const struct opcode_names *op_namep;
@ -55,8 +56,9 @@ static const char *lookup_opcode_name( int opcode )
}
/****************************************************************************
print out a res_rec structure
Print out a res_rec structure.
****************************************************************************/
static void debug_nmb_res_rec(struct res_rec *res, const char *hdr)
{
int i, j;
@ -71,25 +73,25 @@ static void debug_nmb_res_rec(struct res_rec *res, const char *hdr)
if( res->rdlength == 0 || res->rdata == NULL )
return;
for (i = 0; i < res->rdlength; i+= 16)
{
for (i = 0; i < res->rdlength; i+= MAX_NETBIOSNAME_LEN) {
DEBUGADD(4, (" %s %3x char ", hdr, i));
for (j = 0; j < 16; j++)
{
uchar x = res->rdata[i+j];
if (x < 32 || x > 127) x = '.';
for (j = 0; j < MAX_NETBIOSNAME_LEN; j++) {
unsigned char x = res->rdata[i+j];
if (x < 32 || x > 127)
x = '.';
if (i+j >= res->rdlength) break;
if (i+j >= res->rdlength)
break;
DEBUGADD(4, ("%c", x));
}
DEBUGADD(4, (" hex "));
for (j = 0; j < 16; j++)
{
if (i+j >= res->rdlength) break;
DEBUGADD(4, ("%02X", (uchar)res->rdata[i+j]));
for (j = 0; j < MAX_NETBIOSNAME_LEN; j++) {
if (i+j >= res->rdlength)
break;
DEBUGADD(4, ("%02X", (unsigned char)res->rdata[i+j]));
}
DEBUGADD(4, ("\n"));
@ -97,14 +99,14 @@ static void debug_nmb_res_rec(struct res_rec *res, const char *hdr)
}
/****************************************************************************
process a nmb packet
Process a nmb packet.
****************************************************************************/
void debug_nmb_packet(struct packet_struct *p)
{
struct nmb_packet *nmb = &p->packet.nmb;
if( DEBUGLVL( 4 ) )
{
if( DEBUGLVL( 4 ) ) {
dbgtext( "nmb packet from %s(%d) header: id=%d opcode=%s(%d) response=%s\n",
inet_ntoa(p->ip), p->port,
nmb->header.name_trn_id,
@ -125,38 +127,36 @@ void debug_nmb_packet(struct packet_struct *p)
nmb->header.arcount );
}
if (nmb->header.qdcount)
{
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)
{
if (nmb->answers && nmb->header.ancount) {
debug_nmb_res_rec(nmb->answers,"answers");
}
if (nmb->nsrecs && nmb->header.nscount)
{
if (nmb->nsrecs && nmb->header.nscount) {
debug_nmb_res_rec(nmb->nsrecs,"nsrecs");
}
if (nmb->additional && nmb->header.arcount)
{
if (nmb->additional && nmb->header.arcount) {
debug_nmb_res_rec(nmb->additional,"additional");
}
}
/*******************************************************************
handle "compressed" name pointers
Handle "compressed" name pointers.
******************************************************************/
static BOOL handle_name_ptrs(uchar *ubuf,int *offset,int length,
static BOOL handle_name_ptrs(unsigned char *ubuf,int *offset,int length,
BOOL *got_pointer,int *ret)
{
int loop_count=0;
while ((ubuf[*offset] & 0xC0) == 0xC0) {
if (!*got_pointer) (*ret) += 2;
if (!*got_pointer)
(*ret) += 2;
(*got_pointer)=True;
(*offset) = ((ubuf[*offset] & ~0xC0)<<8) | ubuf[(*offset)+1];
if (loop_count++ == 10 || (*offset) < 0 || (*offset)>(length-2)) {
@ -167,13 +167,14 @@ static BOOL handle_name_ptrs(uchar *ubuf,int *offset,int length,
}
/*******************************************************************
parse a nmb name from "compressed" format to something readable
Parse a nmb name from "compressed" format to something readable
return the space taken by the name, or 0 if the name is invalid
******************************************************************/
static int parse_nmb_name(char *inbuf,int ofs,int length, struct nmb_name *name)
{
int m,n=0;
uchar *ubuf = (uchar *)inbuf;
unsigned char *ubuf = (unsigned char *)inbuf;
int ret = 0;
BOOL got_pointer=False;
int loop_count=0;
@ -200,7 +201,7 @@ static int parse_nmb_name(char *inbuf,int ofs,int length, struct nmb_name *name)
ret += m + 2;
offset++;
while (m > 0) {
uchar c1,c2;
unsigned char c1,c2;
c1 = ubuf[offset++]-'A';
c2 = ubuf[offset++]-'A';
if ((c1 & 0xF0) || (c2 & 0xF0) || (n > sizeof(name->name)-1))
@ -210,10 +211,9 @@ static int parse_nmb_name(char *inbuf,int ofs,int length, struct nmb_name *name)
}
name->name[n] = 0;
if (n==16) {
/* parse out the name type,
its always in the 16th byte of the name */
name->name_type = ((uchar)name->name[15]) & 0xff;
if (n==MAX_NETBIOSNAME_LEN) {
/* parse out the name type, its always in the 16th byte of the name */
name->name_type = ((unsigned char)name->name[15]) & 0xff;
/* remove trailing spaces */
name->name[15] = 0;
@ -256,15 +256,32 @@ static int parse_nmb_name(char *inbuf,int ofs,int length, struct nmb_name *name)
return(ret);
}
/****************************************************************************
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].
****************************************************************************/
static void put_name(char *dest, const char *name, int pad, unsigned int name_type)
{
size_t len = strlen(name);
memcpy(dest, name, (len < MAX_NETBIOSNAME_LEN) ? len : MAX_NETBIOSNAME_LEN - 1);
if (len < MAX_NETBIOSNAME_LEN - 1) {
memset(dest + len, pad, MAX_NETBIOSNAME_LEN - 1 - len);
}
dest[MAX_NETBIOSNAME_LEN - 1] = name_type;
}
/*******************************************************************
put a compressed nmb name into a buffer. return the length of the
compressed name
Put a compressed nmb name into a buffer. Return the length of the
compressed name.
compressed names are really weird. The "compression" doubles the
Compressed names are really weird. The "compression" doubles the
size. The idea is that it also means that compressed names conform
to the doman name system. See RFC1002.
******************************************************************/
static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
{
int ret,m;
@ -273,18 +290,16 @@ static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
if (strcmp(name->name,"*") == 0) {
/* special case for wildcard name */
memset(buf1,'\0',20);
buf1[0] = '*';
buf1[15] = name->name_type;
put_name(buf1, "*", '\0', name->name_type);
} else {
slprintf(buf1, sizeof(buf1) - 1,"%-15.15s%c",name->name,name->name_type);
put_name(buf1, name->name, ' ', name->name_type);
}
buf[offset] = 0x20;
ret = 34;
for (m=0;m<16;m++) {
for (m=0;m<MAX_NETBIOSNAME_LEN;m++) {
buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF);
buf[offset+2+2*m] = 'A' + (buf1[m]&0xF);
}
@ -331,14 +346,17 @@ char *nmb_namestr(struct nmb_name *n)
}
/*******************************************************************
allocate and parse some resource records
Allocate and parse some resource records.
******************************************************************/
static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length,
struct res_rec **recs, int count)
{
int i;
*recs = (struct res_rec *)malloc(sizeof(**recs)*count);
if (!*recs) return(False);
if (!*recs)
return(False);
memset((char *)*recs,'\0',sizeof(**recs)*count);
@ -366,8 +384,9 @@ static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length,
}
/*******************************************************************
put a resource record into a packet
Put a resource record into a packet.
******************************************************************/
static int put_res_rec(char *buf,int offset,struct res_rec *recs,int count)
{
int ret=0;
@ -390,9 +409,10 @@ static int put_res_rec(char *buf,int offset,struct res_rec *recs,int count)
}
/*******************************************************************
put a compressed name pointer record into a packet
Put a compressed name pointer record into a packet.
******************************************************************/
static int put_compressed_name_ptr(uchar *buf,int offset,struct res_rec *rec,int ptr_offset)
static int put_compressed_name_ptr(unsigned char *buf,int offset,struct res_rec *rec,int ptr_offset)
{
int ret=0;
buf[offset] = (0xC0 | ((ptr_offset >> 8) & 0xFF));
@ -411,11 +431,12 @@ static int put_compressed_name_ptr(uchar *buf,int offset,struct res_rec *rec,int
}
/*******************************************************************
parse a dgram packet. Return False if the packet can't be parsed
or is invalid for some reason, True otherwise
Parse a dgram packet. Return False if the packet can't be parsed
or is invalid for some reason, True otherwise.
this is documented in section 4.4.1 of RFC1002
This is documented in section 4.4.1 of RFC1002.
******************************************************************/
static BOOL parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
{
int offset;
@ -423,13 +444,16 @@ static BOOL parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
memset((char *)dgram,'\0',sizeof(*dgram));
if (length < 14) return(False);
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;
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);
@ -454,18 +478,19 @@ static BOOL parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
return(True);
}
/*******************************************************************
parse a nmb packet. Return False if the packet can't be parsed
or is invalid for some reason, True otherwise
Parse a nmb packet. Return False if the packet can't be parsed
or is invalid for some reason, True otherwise.
******************************************************************/
static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
{
int nm_flags,offset;
memset((char *)nmb,'\0',sizeof(*nmb));
if (length < 12) return(False);
if (length < 12)
return(False);
/* parse the header */
nmb->header.name_trn_id = RSVAL(inbuf,0);
@ -488,9 +513,11 @@ static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
if (nmb->header.qdcount) {
offset = parse_nmb_name(inbuf,12,length,&nmb->question.question_name);
if (!offset) return(False);
if (!offset)
return(False);
if (length - (12+offset) < 4) 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);
@ -500,18 +527,15 @@ static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
}
/* and any resource records */
if (nmb->header.ancount &&
!parse_alloc_res_rec(inbuf,&offset,length,&nmb->answers,
if (nmb->header.ancount && !parse_alloc_res_rec(inbuf,&offset,length,&nmb->answers,
nmb->header.ancount))
return(False);
if (nmb->header.nscount &&
!parse_alloc_res_rec(inbuf,&offset,length,&nmb->nsrecs,
if (nmb->header.nscount && !parse_alloc_res_rec(inbuf,&offset,length,&nmb->nsrecs,
nmb->header.nscount))
return(False);
if (nmb->header.arcount &&
!parse_alloc_res_rec(inbuf,&offset,length,&nmb->additional,
if (nmb->header.arcount && !parse_alloc_res_rec(inbuf,&offset,length,&nmb->additional,
nmb->header.arcount))
return(False);
@ -519,16 +543,16 @@ static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
}
/*******************************************************************
'Copy constructor' for an nmb packet
'Copy constructor' for an nmb packet.
******************************************************************/
static struct packet_struct *copy_nmb_packet(struct packet_struct *packet)
{
struct nmb_packet *nmb;
struct nmb_packet *copy_nmb;
struct packet_struct *pkt_copy;
if(( pkt_copy = (struct packet_struct *)malloc(sizeof(*packet))) == NULL)
{
if(( pkt_copy = (struct packet_struct *)malloc(sizeof(*packet))) == NULL) {
DEBUG(0,("copy_nmb_packet: malloc fail.\n"));
return NULL;
}
@ -550,24 +574,21 @@ static struct packet_struct *copy_nmb_packet(struct packet_struct *packet)
/* Now copy any resource records. */
if (nmb->answers)
{
if (nmb->answers) {
if((copy_nmb->answers = (struct res_rec *)
malloc(nmb->header.ancount * sizeof(struct res_rec))) == NULL)
goto free_and_exit;
memcpy((char *)copy_nmb->answers, (char *)nmb->answers,
nmb->header.ancount * sizeof(struct res_rec));
}
if (nmb->nsrecs)
{
if (nmb->nsrecs) {
if((copy_nmb->nsrecs = (struct res_rec *)
malloc(nmb->header.nscount * sizeof(struct res_rec))) == NULL)
goto free_and_exit;
memcpy((char *)copy_nmb->nsrecs, (char *)nmb->nsrecs,
nmb->header.nscount * sizeof(struct res_rec));
}
if (nmb->additional)
{
if (nmb->additional) {
if((copy_nmb->additional = (struct res_rec *)
malloc(nmb->header.arcount * sizeof(struct res_rec))) == NULL)
goto free_and_exit;
@ -589,14 +610,14 @@ free_and_exit:
}
/*******************************************************************
'Copy constructor' for a dgram packet
'Copy constructor' for a dgram packet.
******************************************************************/
static struct packet_struct *copy_dgram_packet(struct packet_struct *packet)
{
struct packet_struct *pkt_copy;
if(( pkt_copy = (struct packet_struct *)malloc(sizeof(*packet))) == NULL)
{
if(( pkt_copy = (struct packet_struct *)malloc(sizeof(*packet))) == NULL) {
DEBUG(0,("copy_dgram_packet: malloc fail.\n"));
return NULL;
}
@ -614,8 +635,9 @@ static struct packet_struct *copy_dgram_packet(struct packet_struct *packet)
}
/*******************************************************************
'Copy constructor' for a generic packet
'Copy constructor' for a generic packet.
******************************************************************/
struct packet_struct *copy_packet(struct packet_struct *packet)
{
if(packet->packet_type == NMB_PACKET)
@ -626,8 +648,9 @@ struct packet_struct *copy_packet(struct packet_struct *packet)
}
/*******************************************************************
free up any resources associated with an nmb packet
Free up any resources associated with an nmb packet.
******************************************************************/
static void free_nmb_packet(struct nmb_packet *nmb)
{
SAFE_FREE(nmb->answers);
@ -636,16 +659,18 @@ static void free_nmb_packet(struct nmb_packet *nmb)
}
/*******************************************************************
free up any resources associated with a dgram packet
Free up any resources associated with a dgram packet.
******************************************************************/
static void free_dgram_packet(struct dgram_packet *nmb)
{
/* We have nothing to do for a dgram packet. */
}
/*******************************************************************
free up any resources associated with a packet
Free up any resources associated with a packet.
******************************************************************/
void free_packet(struct packet_struct *packet)
{
if (packet->locked)
@ -659,8 +684,9 @@ void free_packet(struct packet_struct *packet)
}
/*******************************************************************
parse a packet buffer into a packet structure
Parse a packet buffer into a packet structure.
******************************************************************/
struct packet_struct *parse_packet(char *buf,int length,
enum packet_type packet_type)
{
@ -670,7 +696,8 @@ struct packet_struct *parse_packet(char *buf,int length,
BOOL ok=False;
p = (struct packet_struct *)malloc(sizeof(*p));
if (!p) return(NULL);
if (!p)
return(NULL);
p->next = NULL;
p->prev = NULL;
@ -699,9 +726,10 @@ struct packet_struct *parse_packet(char *buf,int length,
}
/*******************************************************************
read a packet from a socket and parse it, returning a packet ready
to be used or put on the queue. This assumes a UDP socket
Read a packet from a socket and parse it, returning a packet ready
to be used or put on the queue. This assumes a UDP socket.
******************************************************************/
struct packet_struct *read_packet(int fd,enum packet_type packet_type)
{
struct packet_struct *packet;
@ -709,10 +737,12 @@ struct packet_struct *read_packet(int fd,enum packet_type packet_type)
int length;
length = read_udp_socket(fd,buf,sizeof(buf));
if (length < MIN_DGRAM_SIZE) return(NULL);
if (length < MIN_DGRAM_SIZE)
return(NULL);
packet = parse_packet(buf, length, packet_type);
if (!packet) return NULL;
if (!packet)
return NULL;
packet->fd = fd;
@ -724,10 +754,10 @@ struct packet_struct *read_packet(int fd,enum packet_type packet_type)
return(packet);
}
/*******************************************************************
send a udp packet on a already open socket
Send a udp packet on a already open socket.
******************************************************************/
static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
{
BOOL ret = False;
@ -764,7 +794,7 @@ static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
}
/*******************************************************************
build a dgram packet ready for sending
Build a dgram packet ready for sending.
XXXX This currently doesn't handle packets too big for one
datagram. It should split them and use the packet_offset, more and
@ -778,17 +808,20 @@ static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
really has implemented this 'feature'. crh -)------ ]
******************************************************************/
static int build_dgram(char *buf,struct packet_struct *p)
{
struct dgram_packet *dgram = &p->packet.dgram;
uchar *ubuf = (uchar *)buf;
unsigned char *ubuf = (unsigned char *)buf;
int offset=0;
/* put in the header */
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;
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);
@ -840,30 +873,37 @@ BOOL nmb_name_equal(struct nmb_name *n1, struct nmb_name *n2)
}
/*******************************************************************
build a nmb packet ready for sending
Build a nmb packet ready for sending.
XXXX this currently relies on not being passed something that expands
to a packet too big for the buffer. Eventually this should be
changed to set the trunc bit so the receiver can request the rest
via tcp (when that becomes supported)
******************************************************************/
static int build_nmb(char *buf,struct packet_struct *p)
{
struct nmb_packet *nmb = &p->packet.nmb;
uchar *ubuf = (uchar *)buf;
unsigned char *ubuf = (unsigned char *)buf;
int offset=0;
/* put in the header */
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.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;
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;
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);
@ -912,10 +952,10 @@ static int build_nmb(char *buf,struct packet_struct *p)
return(offset);
}
/*******************************************************************
linearise a packet
Linearise a packet.
******************************************************************/
int build_packet(char *buf, struct packet_struct *p)
{
int len = 0;
@ -934,8 +974,9 @@ int build_packet(char *buf, struct packet_struct *p)
}
/*******************************************************************
send a packet_struct
Send a packet_struct.
******************************************************************/
BOOL send_packet(struct packet_struct *p)
{
char buf[1024];
@ -945,15 +986,17 @@ BOOL send_packet(struct packet_struct *p)
len = build_packet(buf, p);
if (!len) return(False);
if (!len)
return(False);
return(send_udp(p->fd,buf,len,p->ip,p->port));
}
/****************************************************************************
receive a packet with timeout on a open UDP filedescriptor
Receive a packet with timeout on a open UDP filedescriptor.
The timeout is in milliseconds
***************************************************************************/
struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
{
fd_set fds;
@ -980,12 +1023,12 @@ struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
return(NULL);
}
/****************************************************************************
receive a UDP/137 packet either via UDP or from the unexpected packet
queue. The packet must be a reply packet and have the specified trn_id
The timeout is in milliseconds
Receive a UDP/137 packet either via UDP or from the unexpected packet
queue. The packet must be a reply packet and have the specified trn_id.
The timeout is in milliseconds.
***************************************************************************/
struct packet_struct *receive_nmb_packet(int fd, int t, int trn_id)
{
struct packet_struct *p;
@ -996,17 +1039,19 @@ struct packet_struct *receive_nmb_packet(int fd, int t, int trn_id)
p->packet.nmb.header.name_trn_id == trn_id) {
return p;
}
if (p) free_packet(p);
if (p)
free_packet(p);
/* try the unexpected packet queue */
return receive_unexpected(NMB_PACKET, trn_id, NULL);
}
/****************************************************************************
receive a UDP/138 packet either via UDP or from the unexpected packet
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
The timeout is in milliseconds.
***************************************************************************/
struct packet_struct *receive_dgram_packet(int fd, int t, const char *mailslot_name)
{
struct packet_struct *p;
@ -1016,16 +1061,17 @@ struct packet_struct *receive_dgram_packet(int fd, int t, const char *mailslot_n
if (p && match_mailslot_name(p, mailslot_name)) {
return p;
}
if (p) free_packet(p);
if (p)
free_packet(p);
/* try the unexpected packet queue */
return receive_unexpected(DGRAM_PACKET, 0, mailslot_name);
}
/****************************************************************************
see if a datagram has the right mailslot name
See if a datagram has the right mailslot name.
***************************************************************************/
BOOL match_mailslot_name(struct packet_struct *p, const char *mailslot_name)
{
struct dgram_packet *dgram = &p->packet.dgram;
@ -1043,71 +1089,76 @@ BOOL match_mailslot_name(struct packet_struct *p, const char *mailslot_name)
return False;
}
/****************************************************************************
return the number of bits that match between two 4 character buffers
Return the number of bits that match between two 4 character buffers
***************************************************************************/
int matching_quad_bits(uchar *p1, uchar *p2)
int matching_quad_bits(unsigned char *p1, unsigned char *p2)
{
int i, j, ret = 0;
for (i=0; i<4; i++) {
if (p1[i] != p2[i]) break;
if (p1[i] != p2[i])
break;
ret += 8;
}
if (i==4) return ret;
if (i==4)
return ret;
for (j=0; j<8; j++) {
if ((p1[i] & (1<<(7-j))) != (p2[i] & (1<<(7-j)))) break;
if ((p1[i] & (1<<(7-j))) != (p2[i] & (1<<(7-j))))
break;
ret++;
}
return ret;
}
static uchar sort_ip[4];
static unsigned char sort_ip[4];
/****************************************************************************
compare two query reply records
Compare two query reply records.
***************************************************************************/
static int name_query_comp(uchar *p1, uchar *p2)
static int name_query_comp(unsigned char *p1, unsigned char *p2)
{
return matching_quad_bits(p2+2, sort_ip) - matching_quad_bits(p1+2, sort_ip);
}
/****************************************************************************
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
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.
***************************************************************************/
void sort_query_replies(char *data, int n, struct in_addr ip)
{
if (n <= 1) return;
if (n <= 1)
return;
putip(sort_ip, (char *)&ip);
qsort(data, n, 6, QSORT_CAST name_query_comp);
}
#define TRUNCATE_NETBIOS_NAME 1
/*******************************************************************
convert, possibly using a stupid microsoft-ism which has destroyed
Convert, possibly using a stupid microsoft-ism which has destroyed
the transport independence of netbios (for CIFS vendors that usually
use the Win95-type methods, not for NT to NT communication, which uses
DCE/RPC and therefore full-length unicode strings...) a dns name into
a netbios name.
the netbios name (NOT necessarily null-terminated) is truncated to 15
The netbios name (NOT necessarily null-terminated) is truncated to 15
characters.
******************************************************************/
char *dns_to_netbios_name(char *dns_name)
char *dns_to_netbios_name(const char *dns_name)
{
static char netbios_name[16];
static nstring netbios_name;
int i;
StrnCpy(netbios_name, dns_name, 15);
StrnCpy(netbios_name, dns_name, MAX_NETBIOSNAME_LEN-1);
netbios_name[15] = 0;
#ifdef TRUNCATE_NETBIOS_NAME
@ -1116,10 +1167,8 @@ char *dns_to_netbios_name(char *dns_name)
netbios name up to and including the '.' this even applies, by
mistake, to workgroup (domain) names, which is _really_ daft.
*/
for (i = 0; i >= 15; i--)
{
if (netbios_name[i] == '.')
{
for (i = 0; i >= 15; i--) {
if (netbios_name[i] == '.') {
netbios_name[i] = 0;
break;
}
@ -1129,10 +1178,10 @@ char *dns_to_netbios_name(char *dns_name)
return netbios_name;
}
/****************************************************************************
interpret the weird netbios "name" into a unix fstring. Return the name type
Interpret the weird netbios "name" into a unix fstring. Return the name type.
****************************************************************************/
static int name_interpret(char *in, fstring name)
{
int ret;
@ -1142,10 +1191,10 @@ static int name_interpret(char *in, fstring name)
*out=0;
if (len > 30 || len<1) return(0);
if (len > 30 || len<1)
return(0);
while (len--)
{
while (len--) {
if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
*out = 0;
return(0);
@ -1159,26 +1208,25 @@ static int name_interpret(char *in, fstring name)
#ifdef NETBIOS_SCOPE
/* Handle any scope names */
while(*in)
{
while(*in) {
*out++ = '.'; /* Scope names are separated by periods */
len = *(uchar *)in++;
len = *(unsigned char *)in++;
StrnCpy(out, in, len);
out += len;
*out=0;
in += len;
}
#endif
pull_ascii(name, out_string, sizeof(fstring), sizeof(out_string), STR_TERMINATE);
pull_ascii_fstring(name, out_string);
return(ret);
}
/****************************************************************************
mangle a name into netbios format
Mangle a name into netbios format.
Note: <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum.
****************************************************************************/
int name_mangle( char *In, char *Out, char name_type )
{
int i;
@ -1188,19 +1236,19 @@ int name_mangle( char *In, char *Out, char name_type )
char *p = Out;
/* Safely copy the input string, In, into buf[]. */
(void)memset( buf, 0, 20 );
if (strcmp(In,"*") == 0)
memset( buf, 0, 20 );
if (strcmp(In,"*") == 0) {
buf[0] = '*';
else
(void)slprintf( buf, sizeof(buf) - 1, "%-15.15s%c", In, name_type );
} else {
slprintf( buf, sizeof(buf) - 1, "%-15.15s%c", In, name_type );
}
/* 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 < 16; i++ )
{
for( i = 0; i < MAX_NETBIOSNAME_LEN; i++ ) {
c = toupper( buf[i] );
p[i*2] = ( (c >> 4) & 0x000F ) + 'A';
p[(i*2)+1] = (c & 0x000F) + 'A';
@ -1209,10 +1257,8 @@ int name_mangle( char *In, char *Out, char name_type )
p[0] = '\0';
/* Add the scope string. */
for( i = 0, len = 0; *(global_scope()) != '\0'; i++, len++ )
{
switch( (global_scope())[i] )
{
for( i = 0, len = 0; *(global_scope()) != '\0'; i++, len++ ) {
switch( (global_scope())[i] ) {
case '\0':
p[0] = len;
if( len > 0 )
@ -1230,45 +1276,48 @@ int name_mangle( char *In, char *Out, char name_type )
}
return( name_len(Out) );
} /* name_mangle */
}
/****************************************************************************
find a pointer to a netbios name
Find a pointer to a netbios name.
****************************************************************************/
static char *name_ptr(char *buf,int ofs)
{
uchar c = *(uchar *)(buf+ofs);
unsigned char c = *(unsigned char *)(buf+ofs);
if ((c & 0xC0) == 0xC0)
{
if ((c & 0xC0) == 0xC0) {
uint16 l = RSVAL(buf, ofs) & 0x3FFF;
DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
return(buf + l);
}
else
} else {
return(buf+ofs);
}
}
/****************************************************************************
extract a netbios name from a buf (into a unix string) return name type
Extract a netbios name from a buf (into a unix string) return name type.
****************************************************************************/
int name_extract(char *buf,int ofs, fstring name)
{
char *p = name_ptr(buf,ofs);
int d = PTR_DIFF(p,buf+ofs);
pstrcpy(name,"");
if (d < -50 || d > 50) return(0);
name[0] = '\0';
if (d < -50 || d > 50)
return(0);
return(name_interpret(p,name));
}
/****************************************************************************
return the total storage length of a mangled name
Return the total storage length of a mangled name.
****************************************************************************/
int name_len(char *s1)
{
/* NOTE: this argument _must_ be unsigned */
uchar *s = (uchar *)s1;
unsigned char *s = (unsigned char *)s1;
int len;
/* If the two high bits of the byte are set, return 2. */
@ -1282,4 +1331,4 @@ int name_len(char *s1)
}
return(len);
} /* name_len */
}

View File

@ -171,7 +171,7 @@ int reply_special(char *inbuf,char *outbuf)
int outsize = 4;
int msg_type = CVAL(inbuf,0);
int msg_flags = CVAL(inbuf,1);
pstring name1,name2;
fstring name1,name2;
char name_type = 0;
static BOOL already_got_session = False;