*/
#include "includes.h"
-
-int num_good_sends = 0;
-int num_good_receives = 0;
+#include "libsmb/nmblib.h"
static const struct opcode_names {
const char *nmb_opcode_name;
res->rr_class,
res->ttl ) );
- if( res->rdlength == 0 || res->rdata == NULL )
+ if (res->rdlength == 0) {
return;
+ }
for (i = 0; i < res->rdlength; i+= MAX_NETBIOSNAME_LEN) {
DEBUGADD(4, (" %s %3x char ", hdr, i));
If buf == NULL this is a length calculation.
******************************************************************/
-static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
+static int put_nmb_name(char *buf, size_t buflen, int offset,struct nmb_name *name)
{
int ret,m;
nstring buf1;
}
if (buf) {
+ if (offset >= buflen) {
+ return 0;
+ }
buf[offset] = 0x20;
}
for (m=0;m<MAX_NETBIOSNAME_LEN;m++) {
if (buf) {
+ if (offset+2+2*m >= buflen) {
+ return 0;
+ }
buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF);
buf[offset+2+2*m] = 'A' + (buf1[m]&0xF);
}
offset += 33;
if (buf) {
+ if (offset >= buflen) {
+ return 0;
+ }
buf[offset] = 0;
}
if (name->scope[0]) {
/* XXXX this scope handling needs testing */
- ret += strlen(name->scope) + 1;
+ size_t scopenamelen = strlen(name->scope) + 1;
+ ret += scopenamelen;
if (buf) {
- safe_strcpy(&buf[offset+1],name->scope,
- sizeof(name->scope));
+ if (offset+1+scopenamelen >= buflen) {
+ return 0;
+ }
+ strlcpy(&buf[offset+1],name->scope,
+ buflen - (offset+1));
p = &buf[offset+1];
while ((p = strchr_m(p,'.'))) {
buf[offset] = PTR_DIFF(p,&buf[offset+1]);
offset += (buf[offset] + 1);
+ if (offset+1 >= buflen) {
+ return 0;
+ }
p = &buf[offset+1];
}
buf[offset] = strlen(&buf[offset+1]);
If buf == NULL this is a length calculation.
******************************************************************/
-static int put_res_rec(char *buf,int offset,struct res_rec *recs,int count)
+static int put_res_rec(char *buf, size_t buflen, int offset,struct res_rec *recs,int count)
{
int ret=0;
int i;
for (i=0;i<count;i++) {
- int l = put_nmb_name(buf,offset,&recs[i].rr_name);
+ int l = put_nmb_name(buf,buflen,offset,&recs[i].rr_name);
offset += l;
ret += l;
if (buf) {
/* Ensure this copy is not locked. */
pkt_copy->locked = False;
+ pkt_copy->recv_fd = -1;
+ pkt_copy->send_fd = -1;
/* Ensure this copy has no resource records. */
nmb = &packet->packet.nmb;
/* Ensure this copy is not locked. */
pkt_copy->locked = False;
+ pkt_copy->recv_fd = -1;
+ pkt_copy->send_fd = -1;
/* There are no additional pointers in a dgram packet,
we are finished. */
SAFE_FREE(packet);
}
+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;
+}
+
/*******************************************************************
Parse a packet buffer into a packet structure.
******************************************************************/
if (!packet)
return NULL;
- packet->fd = fd;
-
- num_good_receives++;
+ packet->recv_fd = fd;
+ packet->send_fd = -1;
DEBUG(5,("Received a packet of len %d from (%s) port %d\n",
length, inet_ntoa(packet->ip), packet->port ) );
DEBUG(0,("Packet send failed to %s(%d) ERRNO=%s\n",
inet_ntoa(ip),port,strerror(errno)));
- if (ret)
- num_good_sends++;
-
return(ret);
}
If buf == NULL this is a length calculation.
******************************************************************/
-static int build_dgram(char *buf, size_t len, struct packet_struct *p)
+static int build_dgram(char *buf, size_t len, struct dgram_packet *dgram)
{
- struct dgram_packet *dgram = &p->packet.dgram;
unsigned char *ubuf = (unsigned char *)buf;
int offset=0;
if (dgram->header.msg_type == 0x10 ||
dgram->header.msg_type == 0x11 ||
dgram->header.msg_type == 0x12) {
- offset += put_nmb_name((char *)ubuf,offset,&dgram->source_name);
- offset += put_nmb_name((char *)ubuf,offset,&dgram->dest_name);
+ offset += put_nmb_name((char *)ubuf,len,offset,&dgram->source_name);
+ offset += put_nmb_name((char *)ubuf,len,offset,&dgram->dest_name);
}
if (buf) {
fstring unix_name;
memset( (char *)n, '\0', sizeof(struct nmb_name) );
fstrcpy(unix_name, name);
- strupper_m(unix_name);
+ (void)strupper_m(unix_name);
push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
n->name_type = (unsigned int)type & 0xFF;
- push_ascii(n->scope, global_scope(), 64, STR_TERMINATE);
+ push_ascii(n->scope, lp_netbios_scope(), 64, STR_TERMINATE);
}
/*******************************************************************
If buf == NULL this is a length calculation.
******************************************************************/
-static int build_nmb(char *buf, size_t len, struct packet_struct *p)
+static int build_nmb(char *buf, size_t len, struct nmb_packet *nmb)
{
- struct nmb_packet *nmb = &p->packet.nmb;
unsigned char *ubuf = (unsigned char *)buf;
int offset=0;
/* XXXX this doesn't handle a qdcount of > 1 */
if (len) {
/* Length check. */
- int extra = put_nmb_name(NULL,offset,
+ int extra = put_nmb_name(NULL,0,offset,
&nmb->question.question_name);
if (offset + extra > len) {
return 0;
}
}
- offset += put_nmb_name((char *)ubuf,offset,
+ offset += put_nmb_name((char *)ubuf,len,offset,
&nmb->question.question_name);
if (buf) {
RSSVAL(ubuf,offset,nmb->question.question_type);
if (nmb->header.ancount) {
if (len) {
/* Length check. */
- int extra = put_res_rec(NULL,offset,nmb->answers,
+ int extra = put_res_rec(NULL,0,offset,nmb->answers,
nmb->header.ancount);
if (offset + extra > len) {
return 0;
}
}
- offset += put_res_rec((char *)ubuf,offset,nmb->answers,
+ offset += put_res_rec((char *)ubuf,len,offset,nmb->answers,
nmb->header.ancount);
}
if (nmb->header.nscount) {
if (len) {
/* Length check. */
- int extra = put_res_rec(NULL,offset,nmb->nsrecs,
+ int extra = put_res_rec(NULL,0,offset,nmb->nsrecs,
nmb->header.nscount);
if (offset + extra > len) {
return 0;
}
}
- offset += put_res_rec((char *)ubuf,offset,nmb->nsrecs,
+ offset += put_res_rec((char *)ubuf,len,offset,nmb->nsrecs,
nmb->header.nscount);
}
} else if (nmb->header.arcount) {
if (len) {
/* Length check. */
- int extra = put_res_rec(NULL,offset,nmb->additional,
+ int extra = put_res_rec(NULL,0,offset,nmb->additional,
nmb->header.arcount);
if (offset + extra > len) {
return 0;
}
}
- offset += put_res_rec((char *)ubuf,offset,nmb->additional,
+ offset += put_res_rec((char *)ubuf,len,offset,nmb->additional,
nmb->header.arcount);
}
return offset;
switch (p->packet_type) {
case NMB_PACKET:
- len = build_nmb(buf,buflen,p);
+ len = build_nmb(buf,buflen,&p->packet.nmb);
break;
case DGRAM_PACKET:
- len = build_dgram(buf,buflen,p);
+ len = build_dgram(buf,buflen,&p->packet.dgram);
break;
}
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.
- The timeout is in milliseconds
-***************************************************************************/
-
-struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
-{
- fd_set fds;
- struct timeval timeout;
- int ret;
-
- FD_ZERO(&fds);
- FD_SET(fd,&fds);
- timeout.tv_sec = t/1000;
- timeout.tv_usec = 1000*(t%1000);
-
- if ((ret = sys_select_intr(fd+1,&fds,NULL,NULL,&timeout)) == -1) {
- /* errno should be EBADF or EINVAL. */
- DEBUG(0,("select returned -1, errno = %s (%d)\n",
- strerror(errno), errno));
- return NULL;
- }
-
- if (ret == 0) /* timeout */
- return NULL;
-
- if (FD_ISSET(fd,&fds))
- return(read_packet(fd,type));
-
- 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.
-***************************************************************************/
-
-struct packet_struct *receive_nmb_packet(int fd, int t, int trn_id)
-{
- struct packet_struct *p;
-
- p = receive_packet(fd, NMB_PACKET, t);
-
- if (p && p->packet.nmb.header.response &&
- p->packet.nmb.header.name_trn_id == trn_id) {
- return p;
- }
- if (p)
- free_packet(p);
-
- /* try the unexpected packet queue */
- return receive_unexpected(NMB_PACKET, trn_id, NULL);
+ return(send_udp(p->send_fd,buf,len,p->ip,p->port));
}
/****************************************************************************
The timeout is in milliseconds.
***************************************************************************/
-struct packet_struct *receive_dgram_packet(int fd, int t,
- const char *mailslot_name)
-{
- struct packet_struct *p;
-
- p = receive_packet(fd, DGRAM_PACKET, t);
-
- if (p && match_mailslot_name(p, mailslot_name)) {
- return 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.
***************************************************************************/
Return the number of bits that match between two len character buffers
***************************************************************************/
-int matching_len_bits(unsigned char *p1, unsigned char *p2, size_t len)
+int matching_len_bits(const unsigned char *p1, const unsigned char *p2, size_t len)
{
size_t i, j;
int ret = 0;
putip(sort_ip, (char *)&ip);
+ /* TODO:
+ this can't use TYPESAFE_QSORT() as the types are wrong.
+ It should be fixed to use a real type instead of char*
+ */
qsort(data, n, 6, QSORT_CAST name_query_comp);
}
/****************************************************************************
Interpret the weird netbios "name" into a unix fstring. Return the name type.
+ Returns -1 on error.
****************************************************************************/
-static int name_interpret(char *in, fstring name)
+static int name_interpret(unsigned char *buf, size_t buf_len,
+ unsigned char *in, fstring name)
{
+ unsigned char *end_ptr = buf + buf_len;
int ret;
- int len = (*in++) / 2;
+ unsigned int len;
fstring out_string;
- char *out = out_string;
+ unsigned char *out = (unsigned char *)out_string;
*out=0;
- if (len > 30 || len<1)
- return(0);
+ if (in >= end_ptr) {
+ return -1;
+ }
+ len = (*in++) / 2;
+
+ if (len<1) {
+ return -1;
+ }
while (len--) {
+ if (&in[1] >= end_ptr) {
+ return -1;
+ }
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++;
+ if (PTR_DIFF(out,out_string) >= sizeof(fstring)) {
+ return -1;
+ }
}
ret = out[-1];
out[-1] = 0;
-#ifdef NETBIOS_SCOPE
- /* Handle any scope names */
- while(*in) {
- *out++ = '.'; /* Scope names are separated by periods */
- len = *(unsigned char *)in++;
- StrnCpy(out, in, len);
- out += len;
- *out=0;
- in += len;
- }
-#endif
pull_ascii_fstring(name, out_string);
return(ret);
Note: <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum.
****************************************************************************/
-int name_mangle( char *In, char *Out, char name_type )
+char *name_mangle(TALLOC_CTX *mem_ctx, const char *In, char name_type)
{
int i;
int len;
nstring buf;
- char *p = Out;
+ char *result;
+ char *p;
+
+ result = talloc_array(mem_ctx, char, 33 + strlen(lp_netbios_scope()) + 2);
+ if (result == NULL) {
+ return NULL;
+ }
+ p = result;
/* Safely copy the input string, In, into buf[]. */
if (strcmp(In,"*") == 0)
nstring buf_dos;
pull_ascii_fstring(buf_unix, In);
- strupper_m(buf_unix);
+ if (!strupper_m(buf_unix)) {
+ return NULL;
+ }
push_ascii_nstring(buf_dos, buf_unix);
put_name(buf, buf_dos, ' ', 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; *(lp_netbios_scope()) != '\0'; i++, len++ ) {
+ switch( (lp_netbios_scope())[i] ) {
case '\0':
p[0] = len;
if( len > 0 )
p[len+1] = 0;
- return( name_len(Out) );
+ return result;
case '.':
p[0] = len;
p += (len + 1);
len = -1;
break;
default:
- p[len+1] = (global_scope())[i];
+ p[len+1] = (lp_netbios_scope())[i];
break;
}
}
- return( name_len(Out) );
+ return result;
}
/****************************************************************************
Find a pointer to a netbios name.
****************************************************************************/
-static char *name_ptr(char *buf,int ofs)
+static unsigned char *name_ptr(unsigned char *buf, size_t buf_len, unsigned int ofs)
{
- unsigned char c = *(unsigned char *)(buf+ofs);
+ unsigned char c = 0;
+
+ if (ofs > buf_len || buf_len < 1) {
+ return NULL;
+ }
+ c = *(unsigned char *)(buf+ofs);
if ((c & 0xC0) == 0xC0) {
- uint16 l = RSVAL(buf, ofs) & 0x3FFF;
+ uint16 l = 0;
+
+ if (ofs > buf_len - 1) {
+ return NULL;
+ }
+ l = RSVAL(buf, ofs) & 0x3FFF;
+ if (l > buf_len) {
+ return NULL;
+ }
DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
return(buf + l);
} else {
/****************************************************************************
Extract a netbios name from a buf (into a unix string) return name type.
+ Returns -1 on error.
****************************************************************************/
-int name_extract(char *buf,int ofs, fstring name)
+int name_extract(unsigned char *buf, size_t buf_len, unsigned int ofs, fstring name)
{
- char *p = name_ptr(buf,ofs);
- int d = PTR_DIFF(p,buf+ofs);
+ unsigned char *p = name_ptr(buf,buf_len,ofs);
name[0] = '\0';
- if (d < -50 || d > 50)
- return(0);
- return(name_interpret(p,name));
+ if (p == NULL) {
+ return -1;
+ }
+ return(name_interpret(buf,buf_len,p,name));
}
/****************************************************************************
Return the total storage length of a mangled name.
+ Returns -1 on error.
****************************************************************************/
-int name_len(char *s1)
+int name_len(unsigned char *s1, size_t buf_len)
{
/* NOTE: this argument _must_ be unsigned */
unsigned char *s = (unsigned char *)s1;
- int len;
+ int len = 0;
+ if (buf_len < 1) {
+ return -1;
+ }
/* If the two high bits of the byte are set, return 2. */
- if (0xC0 == (*s & 0xC0))
+ if (0xC0 == (*s & 0xC0)) {
+ if (buf_len < 2) {
+ return -1;
+ }
return(2);
+ }
/* Add up the length bytes. */
for (len = 1; (*s); s += (*s) + 1) {
len += *s + 1;
- SMB_ASSERT(len < 80);
+ if (len > buf_len) {
+ return -1;
+ }
}
return(len);