1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

r25492: Start adding IPv6 compatible code to lib/util_sock.c and deal with

the ripple effects this causes. utmp has to change etc. Remove some
global varables and store address/port in the unexpected db.
Jeremy.
This commit is contained in:
Jeremy Allison 2007-10-03 20:43:55 +00:00 committed by Gerald (Jerry) Carter
parent 2cab825634
commit 18c6a2211d
8 changed files with 521 additions and 366 deletions

View File

@ -36,7 +36,7 @@ struct sessionid {
fstring id_str;
uint32 id_num;
struct server_id pid;
fstring ip_addr;
fstring ip_addr_str;
time_t connect_start;
};

View File

@ -3,7 +3,7 @@
Samba utility functions
Copyright (C) Andrew Tridgell 1992-1998
Copyright (C) Tim Potter 2000-2001
Copyright (C) Jeremy Allison 1992-2005
Copyright (C) Jeremy Allison 1992-2007
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
@ -26,7 +26,35 @@
particular modules */
static int client_fd = -1;
/* What to print out on a client disconnect error. */
static char client_ip_string[16];
static char client_ip_string[INET6_ADDRSTRLEN];
/****************************************************************************
Pritn out an IPv4 or IPv6 address from a struct sockaddr_storage.
****************************************************************************/
char *print_sockaddr(char *dest,
size_t destlen,
struct sockaddr_storage *psa)
{
if (destlen > 0) {
dest[0] = '\0';
}
#ifdef AF_INET6
if (psa->ss_family == AF_INET6) {
inet_ntop(AF_INET6,
&((struct sockaddr_in6 *)psa)->sin6_addr,
dest,
destlen);
}
#endif
if (psa->ss_family == AF_INET) {
inet_ntop(AF_INET,
&((struct sockaddr_in *)psa)->sin_addr,
dest,
destlen);
}
return dest;
}
void client_setfd(int fd)
{
@ -38,44 +66,49 @@ void client_setfd(int fd)
static char *get_socket_addr(int fd)
{
struct sockaddr sa;
struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
struct sockaddr_storage sa;
socklen_t length = sizeof(sa);
static fstring addr_buf;
static char addr_buf[INET6_ADDRSTRLEN];
fstrcpy(addr_buf,"0.0.0.0");
addr_buf[0] = '\0';
if (fd == -1) {
return addr_buf;
}
if (getsockname(fd, &sa, &length) < 0) {
if (getsockname(fd, (struct sockaddr *)&sa, &length) < 0) {
DEBUG(0,("getsockname failed. Error was %s\n",
strerror(errno) ));
strerror(errno) ));
return addr_buf;
}
fstrcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr));
return addr_buf;
return print_sockaddr(addr_buf, sizeof(addr_buf), &sa);
}
static int get_socket_port(int fd)
{
struct sockaddr sa;
struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
struct sockaddr_storage sa;
socklen_t length = sizeof(sa);
if (fd == -1)
return -1;
if (getsockname(fd, &sa, &length) < 0) {
DEBUG(0,("getpeername failed. Error was %s\n",
strerror(errno) ));
if (fd == -1) {
return -1;
}
return ntohs(sockin->sin_port);
if (getsockname(fd, (struct sockaddr *)&sa, &length) < 0) {
DEBUG(0,("getpeername failed. Error was %s\n",
strerror(errno) ));
return -1;
}
#ifdef AF_INET6
if (sa.ss_family == AF_INET6) {
return ntohs(((struct sockaddr_in6 *)&sa)->sin6_port);
}
#endif
if (sa.ss_family == AF_INET) {
return ntohs(((struct sockaddr_in *)&sa)->sin_port);
}
return -1;
}
char *client_name(void)
@ -98,26 +131,6 @@ int client_socket_port(void)
return get_socket_port(client_fd);
}
struct in_addr *client_inaddr(struct sockaddr *sa)
{
struct sockaddr_in *sockin = (struct sockaddr_in *) (sa);
socklen_t length = sizeof(*sa);
if (getpeername(client_fd, sa, &length) < 0) {
DEBUG(0,("getpeername failed. Error was %s\n",
strerror(errno) ));
return NULL;
}
return &sockin->sin_addr;
}
/* the last IP received from */
struct in_addr lastip;
/* the last port received from */
int lastport=0;
int smb_read_error = 0;
/****************************************************************************
@ -281,35 +294,42 @@ void set_socket_options(int fd, const char *options)
Read from a socket.
****************************************************************************/
ssize_t read_udp_socket(int fd,char *buf,size_t len)
ssize_t read_udp_v4_socket(int fd,
char *buf,
size_t len,
struct sockaddr_storage *psa)
{
ssize_t ret;
struct sockaddr_in sock;
socklen_t socklen = sizeof(sock);
socklen_t socklen = sizeof(*psa);
struct sockaddr_in *si = (struct sockaddr_in *)psa;
memset((char *)psa,'\0',socklen);
memset((char *)&sock,'\0',socklen);
memset((char *)&lastip,'\0',sizeof(lastip));
ret = (ssize_t)sys_recvfrom(fd,buf,len,0,
(struct sockaddr *)&sock,&socklen);
(struct sockaddr *)psa,&socklen);
if (ret <= 0) {
/* Don't print a low debug error for a non-blocking socket. */
if (errno == EAGAIN) {
DEBUG(10,("read socket returned EAGAIN. ERRNO=%s\n",
strerror(errno)));
DEBUG(10,("read_udp_v4_socket: returned EAGAIN\n"));
} else {
DEBUG(2,("read socket failed. ERRNO=%s\n",
strerror(errno)));
DEBUG(2,("read_udp_v4_socket: failed. errno=%s\n",
strerror(errno)));
}
return(0);
return 0;
}
lastip = sock.sin_addr;
lastport = ntohs(sock.sin_port);
if (psa->ss_family != AF_INET) {
DEBUG(2,("read_udp_v4_socket:: invalid address family %d "
"(not IPv4)\n", (int)psa->ss_family));
return 0;
}
DEBUG(10,("read_udp_socket: lastip %s lastport %d read: %lu\n",
inet_ntoa(lastip), lastport, (unsigned long)ret));
DEBUG(10,("read_udp_socket: ip %s port %d read: %lu\n",
inet_ntoa(si->sin_addr),
si->sin_port,
(unsigned long)ret));
return(ret);
return ret;
}
/****************************************************************************
@ -1232,7 +1252,6 @@ int open_udp_socket(const char *host, int port)
return res;
}
/*******************************************************************
Matchname - determine if host name matches IP address. Used to
confirm a hostname lookup to prevent spoof attacks.

View File

@ -1,28 +1,26 @@
/*
/*
Unix SMB/CIFS implementation.
NBT netbios library routines
Copyright (C) Andrew Tridgell 1994-1998
Copyright (C) Jeremy Allison 2007
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
extern struct in_addr lastip;
extern int lastport;
int num_good_sends = 0;
int num_good_receives = 0;
@ -82,12 +80,12 @@ static void debug_nmb_res_rec(struct res_rec *res, const char *hdr)
unsigned char x = res->rdata[i+j];
if (x < 32 || x > 127)
x = '.';
if (i+j >= res->rdlength)
break;
DEBUGADD(4, ("%c", x));
}
DEBUGADD(4, (" hex "));
for (j = 0; j < MAX_NETBIOSNAME_LEN; j++) {
@ -95,7 +93,7 @@ static void debug_nmb_res_rec(struct res_rec *res, const char *hdr)
break;
DEBUGADD(4, ("%02X", (unsigned char)res->rdata[i+j]));
}
DEBUGADD(4, ("\n"));
}
}
@ -109,19 +107,22 @@ void debug_nmb_packet(struct packet_struct *p)
struct nmb_packet *nmb = &p->packet.nmb;
if( DEBUGLVL( 4 ) ) {
dbgtext( "nmb packet from %s(%d) header: id=%d opcode=%s(%d) response=%s\n",
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,
lookup_opcode_name(nmb->header.opcode),
nmb->header.opcode,
BOOLSTR(nmb->header.response) );
dbgtext( " header: flags: bcast=%s rec_avail=%s rec_des=%s trunc=%s auth=%s\n",
dbgtext( " header: flags: bcast=%s rec_avail=%s "
"rec_des=%s trunc=%s auth=%s\n",
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) );
dbgtext( " header: rcode=%d qdcount=%d ancount=%d nscount=%d arcount=%d\n",
dbgtext( " header: rcode=%d qdcount=%d ancount=%d "
"nscount=%d arcount=%d\n",
nmb->header.rcode,
nmb->header.qdcount,
nmb->header.ancount,
@ -155,17 +156,18 @@ 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;
(*got_pointer)=True;
(*offset) = ((ubuf[*offset] & ~0xC0)<<8) | ubuf[(*offset)+1];
if (loop_count++ == 10 || (*offset) < 0 || (*offset)>(length-2)) {
return(False);
if (loop_count++ == 10 ||
(*offset) < 0 || (*offset)>(length-2)) {
return False;
}
}
return(True);
return True;
}
/*******************************************************************
@ -183,12 +185,12 @@ static int parse_nmb_name(char *inbuf,int ofs,int length, struct nmb_name *name)
int offset = ofs;
if (length - offset < 2)
return(0);
return(0);
/* handle initial name pointers */
if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret))
return(0);
m = ubuf[offset];
if (!m)
@ -214,14 +216,15 @@ static int parse_nmb_name(char *inbuf,int ofs,int length, struct nmb_name *name)
name->name[n] = 0;
if (n==MAX_NETBIOSNAME_LEN) {
/* parse out the name type, its always in the 16th byte of the name */
/* 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;
n = 14;
while (n && name->name[n]==' ')
name->name[n--] = 0;
name->name[n--] = 0;
}
/* now the domain parts (if any) */
@ -253,7 +256,7 @@ static int parse_nmb_name(char *inbuf,int ofs,int length, struct nmb_name *name)
if (loop_count++ == 10)
return 0;
}
name->scope[n++] = 0;
name->scope[n++] = 0;
return(ret);
}
@ -268,7 +271,8 @@ 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);
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);
}
@ -282,6 +286,8 @@ void put_name(char *dest, const char *name, int pad, unsigned int name_type)
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.
If buf == NULL this is a length calculation.
******************************************************************/
static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
@ -297,33 +303,42 @@ static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
put_name(buf1, name->name, ' ', name->name_type);
}
buf[offset] = 0x20;
if (buf) {
buf[offset] = 0x20;
}
ret = 34;
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);
if (buf) {
buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF);
buf[offset+2+2*m] = 'A' + (buf1[m]&0xF);
}
}
offset += 33;
buf[offset] = 0;
if (buf) {
buf[offset] = 0;
}
if (name->scope[0]) {
/* XXXX this scope handling needs testing */
ret += strlen(name->scope) + 1;
safe_strcpy(&buf[offset+1],name->scope,sizeof(name->scope));
p = &buf[offset+1];
while ((p = strchr_m(p,'.'))) {
buf[offset] = PTR_DIFF(p,&buf[offset+1]);
offset += (buf[offset] + 1);
if (buf) {
safe_strcpy(&buf[offset+1],name->scope,
sizeof(name->scope));
p = &buf[offset+1];
while ((p = strchr_m(p,'.'))) {
buf[offset] = PTR_DIFF(p,&buf[offset+1]);
offset += (buf[offset] + 1);
p = &buf[offset+1];
}
buf[offset] = strlen(&buf[offset+1]);
}
buf[offset] = strlen(&buf[offset+1]);
}
return(ret);
return ret;
}
/*******************************************************************
@ -341,7 +356,8 @@ char *nmb_namestr(const struct nmb_name *n)
if (!n->scope[0])
slprintf(p,sizeof(fstring)-1, "%s<%02x>",name,n->name_type);
else
slprintf(p,sizeof(fstring)-1, "%s<%02x>.%s",name,n->name_type,n->scope);
slprintf(p,sizeof(fstring)-1, "%s<%02x>.%s",
name,n->name_type,n->scope);
i = (i+1)%4;
return(p);
@ -363,7 +379,8 @@ static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length,
memset((char *)*recs,'\0',sizeof(**recs)*count);
for (i=0;i<count;i++) {
int l = parse_nmb_name(inbuf,*offset,length,&(*recs)[i].rr_name);
int l = parse_nmb_name(inbuf,*offset,length,
&(*recs)[i].rr_name);
(*offset) += l;
if (!l || (*offset)+10 > length) {
SAFE_FREE(*recs);
@ -374,19 +391,20 @@ static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length,
(*recs)[i].ttl = RIVAL(inbuf,(*offset)+4);
(*recs)[i].rdlength = RSVAL(inbuf,(*offset)+8);
(*offset) += 10;
if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) ||
if ((*recs)[i].rdlength>sizeof((*recs)[i].rdata) ||
(*offset)+(*recs)[i].rdlength > length) {
SAFE_FREE(*recs);
return(False);
}
memcpy((*recs)[i].rdata,inbuf+(*offset),(*recs)[i].rdlength);
(*offset) += (*recs)[i].rdlength;
(*offset) += (*recs)[i].rdlength;
}
return(True);
}
/*******************************************************************
Put a resource record into a packet.
If buf == NULL this is a length calculation.
******************************************************************/
static int put_res_rec(char *buf,int offset,struct res_rec *recs,int count)
@ -398,42 +416,52 @@ static int put_res_rec(char *buf,int offset,struct res_rec *recs,int count)
int l = put_nmb_name(buf,offset,&recs[i].rr_name);
offset += l;
ret += l;
RSSVAL(buf,offset,recs[i].rr_type);
RSSVAL(buf,offset+2,recs[i].rr_class);
RSIVAL(buf,offset+4,recs[i].ttl);
RSSVAL(buf,offset+8,recs[i].rdlength);
memcpy(buf+offset+10,recs[i].rdata,recs[i].rdlength);
if (buf) {
RSSVAL(buf,offset,recs[i].rr_type);
RSSVAL(buf,offset+2,recs[i].rr_class);
RSIVAL(buf,offset+4,recs[i].ttl);
RSSVAL(buf,offset+8,recs[i].rdlength);
memcpy(buf+offset+10,recs[i].rdata,recs[i].rdlength);
}
offset += 10+recs[i].rdlength;
ret += 10+recs[i].rdlength;
}
return(ret);
return ret;
}
/*******************************************************************
Put a compressed name pointer record into a packet.
If buf == NULL this is a length calculation.
******************************************************************/
static int put_compressed_name_ptr(unsigned char *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));
buf[offset+1] = (ptr_offset & 0xFF);
if (buf) {
buf[offset] = (0xC0 | ((ptr_offset >> 8) & 0xFF));
buf[offset+1] = (ptr_offset & 0xFF);
}
offset += 2;
ret += 2;
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);
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);
}
offset += 10+rec->rdlength;
ret += 10+rec->rdlength;
return(ret);
return ret;
}
/*******************************************************************
Parse a dgram packet. Return False if the packet can't be parsed
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.
@ -466,19 +494,22 @@ static BOOL parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
if (dgram->header.msg_type == 0x10 ||
dgram->header.msg_type == 0x11 ||
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);
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);
}
if (offset >= length || (length-offset > sizeof(dgram->data)))
if (offset >= length || (length-offset > sizeof(dgram->data)))
return(False);
dgram->datasize = length-offset;
memcpy(dgram->data,inbuf+offset,dgram->datasize);
/* Paranioa. Ensure the last 2 bytes in the dgram buffer are
zero. This should be true anyway, just enforce it for paranioa sake. JRA. */
zero. This should be true anyway, just enforce it for
paranioa sake. JRA. */
SMB_ASSERT(dgram->datasize <= (sizeof(dgram->data)-2));
memset(&dgram->data[sizeof(dgram->data)-2], '\0', 2);
@ -486,7 +517,7 @@ static BOOL parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
}
/*******************************************************************
Parse a nmb packet. Return False if the packet can't be parsed
Parse a nmb packet. Return False if the packet can't be parsed
or is invalid for some reason, True otherwise.
******************************************************************/
@ -511,15 +542,16 @@ static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
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;
nmb->header.nm_flags.authoritative = (nm_flags&0x40)?True:False;
nmb->header.nm_flags.authoritative = (nm_flags&0x40)?True:False;
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);
if (nmb->header.qdcount) {
offset = parse_nmb_name(inbuf,12,length,&nmb->question.question_name);
offset = parse_nmb_name(inbuf,12,length,
&nmb->question.question_name);
if (!offset)
return(False);
@ -534,16 +566,19 @@ 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,
nmb->header.arcount))
if (nmb->header.arcount &&
!parse_alloc_res_rec(inbuf,&offset,length,
&nmb->additional, nmb->header.arcount))
return(False);
return(True);
@ -554,7 +589,7 @@ static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
******************************************************************/
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;
@ -582,21 +617,24 @@ static struct packet_struct *copy_nmb_packet(struct packet_struct *packet)
/* Now copy any resource records. */
if (nmb->answers) {
if((copy_nmb->answers = SMB_MALLOC_ARRAY(struct res_rec,nmb->header.ancount)) == NULL)
if((copy_nmb->answers = SMB_MALLOC_ARRAY(
struct res_rec,nmb->header.ancount)) == NULL)
goto free_and_exit;
memcpy((char *)copy_nmb->answers, (char *)nmb->answers,
memcpy((char *)copy_nmb->answers, (char *)nmb->answers,
nmb->header.ancount * sizeof(struct res_rec));
}
if (nmb->nsrecs) {
if((copy_nmb->nsrecs = SMB_MALLOC_ARRAY(struct res_rec, nmb->header.nscount)) == NULL)
if((copy_nmb->nsrecs = SMB_MALLOC_ARRAY(
struct res_rec, nmb->header.nscount)) == NULL)
goto free_and_exit;
memcpy((char *)copy_nmb->nsrecs, (char *)nmb->nsrecs,
memcpy((char *)copy_nmb->nsrecs, (char *)nmb->nsrecs,
nmb->header.nscount * sizeof(struct res_rec));
}
if (nmb->additional) {
if((copy_nmb->additional = SMB_MALLOC_ARRAY(struct res_rec, nmb->header.arcount)) == NULL)
if((copy_nmb->additional = SMB_MALLOC_ARRAY(
struct res_rec, nmb->header.arcount)) == NULL)
goto free_and_exit;
memcpy((char *)copy_nmb->additional, (char *)nmb->additional,
memcpy((char *)copy_nmb->additional, (char *)nmb->additional,
nmb->header.arcount * sizeof(struct res_rec));
}
@ -618,7 +656,7 @@ static struct packet_struct *copy_nmb_packet(struct packet_struct *packet)
******************************************************************/
static struct packet_struct *copy_dgram_packet(struct packet_struct *packet)
{
{
struct packet_struct *pkt_copy;
if(( pkt_copy = SMB_MALLOC_P(struct packet_struct)) == NULL) {
@ -643,20 +681,20 @@ static struct packet_struct *copy_dgram_packet(struct packet_struct *packet)
******************************************************************/
struct packet_struct *copy_packet(struct packet_struct *packet)
{
{
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;
}
/*******************************************************************
Free up any resources associated with an nmb packet.
******************************************************************/
static void free_nmb_packet(struct nmb_packet *nmb)
{
{
SAFE_FREE(nmb->answers);
SAFE_FREE(nmb->nsrecs);
SAFE_FREE(nmb->additional);
@ -667,7 +705,7 @@ static void free_nmb_packet(struct nmb_packet *nmb)
******************************************************************/
static void free_dgram_packet(struct dgram_packet *nmb)
{
{
/* We have nothing to do for a dgram packet. */
}
@ -676,8 +714,8 @@ static void free_dgram_packet(struct dgram_packet *nmb)
******************************************************************/
void free_packet(struct packet_struct *packet)
{
if (packet->locked)
{
if (packet->locked)
return;
if (packet->packet_type == NMB_PACKET)
free_nmb_packet(&packet->packet.nmb);
@ -692,7 +730,9 @@ void free_packet(struct packet_struct *packet)
******************************************************************/
struct packet_struct *parse_packet(char *buf,int length,
enum packet_type packet_type)
enum packet_type packet_type,
struct in_addr ip,
int port)
{
struct packet_struct *p;
BOOL ok=False;
@ -703,8 +743,8 @@ struct packet_struct *parse_packet(char *buf,int length,
p->next = NULL;
p->prev = NULL;
p->ip = lastip;
p->port = lastport;
p->ip = ip;
p->port = port;
p->locked = False;
p->timestamp = time(NULL);
p->packet_type = packet_type;
@ -713,7 +753,7 @@ struct packet_struct *parse_packet(char *buf,int length,
case NMB_PACKET:
ok = parse_nmb(buf,length,&p->packet.nmb);
break;
case DGRAM_PACKET:
ok = parse_dgram(buf,length,&p->packet.dgram);
break;
@ -735,27 +775,34 @@ struct packet_struct *parse_packet(char *buf,int length,
struct packet_struct *read_packet(int fd,enum packet_type packet_type)
{
struct packet_struct *packet;
struct sockaddr_storage sa;
struct sockaddr_in *si = (struct sockaddr_in *)&sa;
char buf[MAX_DGRAM_SIZE];
int length;
length = read_udp_socket(fd,buf,sizeof(buf));
if (length < MIN_DGRAM_SIZE)
return(NULL);
packet = parse_packet(buf, length, packet_type);
length = read_udp_v4_socket(fd,buf,sizeof(buf),&sa);
if (length < MIN_DGRAM_SIZE || sa.ss_family != AF_INET) {
return NULL;
}
packet = parse_packet(buf,
length,
packet_type,
si->sin_addr,
si->sin_port);
if (!packet)
return NULL;
packet->fd = fd;
num_good_receives++;
DEBUG(5,("Received a packet of len %d from (%s) port %d\n",
length, inet_ntoa(packet->ip), packet->port ) );
return(packet);
}
/*******************************************************************
Send a udp packet on a already open socket.
******************************************************************/
@ -771,16 +818,17 @@ static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
putip((char *)&sock_out.sin_addr,(char *)&ip);
sock_out.sin_port = htons( port );
sock_out.sin_family = AF_INET;
DEBUG( 5, ( "Sending a packet of len %d to (%s) on port %d\n",
len, inet_ntoa(ip), port ) );
/*
* Patch to fix asynch error notifications from Linux kernel.
*/
for (i = 0; i < 5; i++) {
ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out, sizeof(sock_out)) >= 0);
ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out,
sizeof(sock_out)) >= 0);
if (ret || errno != ECONNREFUSED)
break;
}
@ -797,48 +845,41 @@ static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
/*******************************************************************
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
first flags to handle the fragmentation. Yuck.
[...but it isn't clear that we would ever need to send a
a fragmented NBT Datagram. The IP layer does its own
fragmentation to ensure that messages can fit into the path
MTU. It *is* important to be able to receive and rebuild
fragmented NBT datagrams, just in case someone out there
really has implemented this 'feature'. crh -)------ ]
If buf == NULL this is a length calculation.
******************************************************************/
static int build_dgram(char *buf,struct packet_struct *p)
static int build_dgram(char *buf, size_t len, struct packet_struct *p)
{
struct dgram_packet *dgram = &p->packet.dgram;
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;
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);
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);
}
offset = 14;
if (dgram->header.msg_type == 0x10 ||
dgram->header.msg_type == 0x11 ||
dgram->header.msg_type == 0x12) {
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);
}
memcpy(ubuf+offset,dgram->data,dgram->datasize);
if (buf) {
memcpy(ubuf+offset,dgram->data,dgram->datasize);
}
offset += dgram->datasize;
/* automatically set the dgm_length
@ -846,9 +887,11 @@ static int build_dgram(char *buf,struct packet_struct *p)
* include the fourteen-byte header. crh
*/
dgram->header.dgm_length = (offset - 14);
RSSVAL(ubuf,10,dgram->header.dgm_length);
if (buf) {
RSSVAL(ubuf,10,dgram->header.dgm_length);
}
return(offset);
return offset;
}
/*******************************************************************
@ -879,59 +922,90 @@ BOOL nmb_name_equal(struct nmb_name *n1, struct nmb_name *n2)
/*******************************************************************
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)
If buf == NULL this is a length calculation.
******************************************************************/
static int build_nmb(char *buf,struct packet_struct *p)
static int build_nmb(char *buf, size_t len, struct packet_struct *p)
{
struct nmb_packet *nmb = &p->packet.nmb;
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.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);
if (len && len < 12) {
return 0;
}
/* put in the header */
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);
}
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);
offset += 12;
if (nmb->header.qdcount) {
/* XXXX this doesn't handle a qdcount of > 1 */
offset += put_nmb_name((char *)ubuf,offset,&nmb->question.question_name);
RSSVAL(ubuf,offset,nmb->question.question_type);
RSSVAL(ubuf,offset+2,nmb->question.question_class);
if (len) {
/* Length check. */
int extra = put_nmb_name(NULL,offset,
&nmb->question.question_name);
if (offset + extra > len) {
return 0;
}
}
offset += put_nmb_name((char *)ubuf,offset,
&nmb->question.question_name);
if (buf) {
RSSVAL(ubuf,offset,nmb->question.question_type);
RSSVAL(ubuf,offset+2,nmb->question.question_class);
}
offset += 4;
}
if (nmb->header.ancount)
if (nmb->header.ancount) {
if (len) {
/* Length check. */
int extra = put_res_rec(NULL,offset,nmb->answers,
nmb->header.ancount);
if (offset + extra > len) {
return 0;
}
}
offset += put_res_rec((char *)ubuf,offset,nmb->answers,
nmb->header.ancount);
}
if (nmb->header.nscount)
if (nmb->header.nscount) {
if (len) {
/* Length check. */
int extra = put_res_rec(NULL,offset,nmb->nsrecs,
nmb->header.nscount);
if (offset + extra > len) {
return 0;
}
}
offset += put_res_rec((char *)ubuf,offset,nmb->nsrecs,
nmb->header.nscount);
}
/*
* The spec says we must put compressed name pointers
@ -941,37 +1015,53 @@ static int build_nmb(char *buf,struct packet_struct *p)
*/
if((nmb->header.response == False) &&
((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)) {
offset += put_compressed_name_ptr(ubuf,offset,nmb->additional,12);
((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);
} else if (nmb->header.arcount) {
if (len) {
/* Length check. */
int extra = put_res_rec(NULL,offset,nmb->additional,
nmb->header.arcount);
if (offset + extra > len) {
return 0;
}
}
offset += put_res_rec((char *)ubuf,offset,nmb->additional,
nmb->header.arcount);
nmb->header.arcount);
}
return(offset);
return offset;
}
/*******************************************************************
Linearise a packet.
******************************************************************/
int build_packet(char *buf, struct packet_struct *p)
int build_packet(char *buf, size_t buflen, struct packet_struct *p)
{
int len = 0;
switch (p->packet_type) {
case NMB_PACKET:
len = build_nmb(buf,p);
len = build_nmb(buf,buflen,p);
break;
case DGRAM_PACKET:
len = build_dgram(buf,p);
len = build_dgram(buf,buflen,p);
break;
}
@ -989,7 +1079,7 @@ BOOL send_packet(struct packet_struct *p)
memset(buf,'\0',sizeof(buf));
len = build_packet(buf, p);
len = build_packet(buf, sizeof(buf), p);
if (!len)
return(False);
@ -1015,16 +1105,17 @@ struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
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));
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))
if (FD_ISSET(fd,&fds))
return(read_packet(fd,type));
return(NULL);
}
@ -1057,7 +1148,8 @@ struct packet_struct *receive_nmb_packet(int fd, int t, int trn_id)
The timeout is in milliseconds.
***************************************************************************/
struct packet_struct *receive_dgram_packet(int fd, int t, const char *mailslot_name)
struct packet_struct *receive_dgram_packet(int fd, int t,
const char *mailslot_name)
{
struct packet_struct *p;
@ -1114,8 +1206,8 @@ int matching_quad_bits(unsigned char *p1, unsigned char *p2)
if ((p1[i] & (1<<(7-j))) != (p2[i] & (1<<(7-j))))
break;
ret++;
}
}
return ret;
}
@ -1127,7 +1219,8 @@ static unsigned char sort_ip[4];
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);
return matching_quad_bits(p2+2, sort_ip) -
matching_quad_bits(p1+2, sort_ip);
}
/****************************************************************************
@ -1163,7 +1256,7 @@ char *dns_to_netbios_name(const char *dns_name)
int i;
StrnCpy(netbios_name, dns_name, MAX_NETBIOSNAME_LEN-1);
netbios_name[15] = 0;
/* ok. this is because of a stupid microsoft-ism. if the called host
name contains a '.', microsoft clients expect you to truncate the
netbios name up to and including the '.' this even applies, by
@ -1300,7 +1393,7 @@ static char *name_ptr(char *buf,int ofs)
} else {
return(buf+ofs);
}
}
}
/****************************************************************************
Extract a netbios name from a buf (into a unix string) return name type.
@ -1316,7 +1409,7 @@ int name_extract(char *buf,int ofs, fstring name)
return(0);
return(name_interpret(p,name));
}
/****************************************************************************
Return the total storage length of a mangled name.
****************************************************************************/

View File

@ -1,21 +1,21 @@
/*
/*
Unix SMB/CIFS implementation.
handle unexpected packets
Copyright (C) Andrew Tridgell 2000
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
@ -29,13 +29,12 @@ struct unexpected_key {
int count;
};
/****************************************************************************
all unexpected packets are passed in here, to be stored in a unexpected
All unexpected packets are passed in here, to be stored in a unexpected
packet database. This allows nmblookup and other tools to receive packets
erroneoously sent to the wrong port by broken MS systems
**************************************************************************/
erroneoously sent to the wrong port by broken MS systems.
**************************************************************************/
void unexpected_packet(struct packet_struct *p)
{
static int count;
@ -43,9 +42,10 @@ void unexpected_packet(struct packet_struct *p)
struct unexpected_key key;
char buf[1024];
int len=0;
uint32_t enc_ip;
if (!tdbd) {
tdbd = tdb_open_log(lock_path("unexpected.tdb"), 0,
tdbd = tdb_open_log(lock_path("unexpected.tdb"), 0,
TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
O_RDWR | O_CREAT, 0644);
if (!tdbd) {
@ -55,8 +55,13 @@ void unexpected_packet(struct packet_struct *p)
}
memset(buf,'\0',sizeof(buf));
len = build_packet(buf, p);
/* Encode the ip addr and port. */
enc_ip = ntohl(p->ip.s_addr);
SIVAL(buf,0,enc_ip);
SSVAL(buf,4,p->port);
len = build_packet(&buf[6], sizeof(buf)-6, p) + 6;
key.packet_type = p->packet_type;
key.timestamp = p->timestamp;
@ -74,8 +79,9 @@ void unexpected_packet(struct packet_struct *p)
static time_t lastt;
/****************************************************************************
delete the record if it is too old
**************************************************************************/
Delete the record if it is too old.
**************************************************************************/
static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
{
struct unexpected_key key;
@ -91,8 +97,9 @@ static int traverse_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st
/****************************************************************************
delete all old unexpected packets
**************************************************************************/
Delete all old unexpected packets.
**************************************************************************/
void clear_unexpected(time_t t)
{
if (!tdbd) return;
@ -112,22 +119,39 @@ static enum packet_type match_type;
static const char *match_name;
/****************************************************************************
tdb traversal fn to find a matching 137 packet
**************************************************************************/
tdb traversal fn to find a matching 137 packet.
**************************************************************************/
static int traverse_match(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
{
struct unexpected_key key;
struct in_addr ip;
uint32_t enc_ip;
int port;
struct packet_struct *p;
memcpy(&key, kbuf.dptr, sizeof(key));
if (key.packet_type != match_type) return 0;
p = parse_packet((char *)dbuf.dptr, dbuf.dsize, match_type);
if (dbuf.dsize < 6) {
return 0;
}
if ((match_type == NMB_PACKET &&
/* Decode the ip addr and port. */
enc_ip = IVAL(dbuf.dptr,0);
ip.s_addr = htonl(enc_ip);
port = SVAL(dbuf.dptr,4);
p = parse_packet((char *)&dbuf.dptr[6],
dbuf.dsize-6,
match_type,
ip,
port);
if ((match_type == NMB_PACKET &&
p->packet.nmb.header.name_trn_id == match_id) ||
(match_type == DGRAM_PACKET &&
(match_type == DGRAM_PACKET &&
match_mailslot_name(p, match_name))) {
matched_packet = p;
return -1;
@ -138,11 +162,11 @@ static int traverse_match(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void
return 0;
}
/****************************************************************************
check for a particular packet in the unexpected packet queue
**************************************************************************/
struct packet_struct *receive_unexpected(enum packet_type packet_type, int id,
Check for a particular packet in the unexpected packet queue.
**************************************************************************/
struct packet_struct *receive_unexpected(enum packet_type packet_type, int id,
const char *mailslot_name)
{
TDB_CONTEXT *tdb2;

View File

@ -766,7 +766,7 @@ struct response_record *queue_query_name( struct subnet_record *subrec,
/****************************************************************************
Queue a query name packet to a given address from the WINS subnet.
****************************************************************************/
struct response_record *queue_query_name_from_wins_server( struct in_addr to_ip,
response_function resp_fn,
timeout_response_function timeout_fn,
@ -805,7 +805,7 @@ struct response_record *queue_query_name_from_wins_server( struct in_addr to_ip,
/****************************************************************************
Queue a node status packet to a given name and address.
****************************************************************************/
struct response_record *queue_node_status( struct subnet_record *subrec,
response_function resp_fn,
timeout_response_function timeout_fn,
@ -835,7 +835,7 @@ unicast subnet. subnet is %s\n.", subrec->subnet_name ));
p->locked = False;
free_packet(p);
return NULL;
}
}
if((rrec = make_response_record(subrec, /* subnet record. */
p, /* packet we sent. */
@ -867,11 +867,11 @@ void reply_netbios_packet(struct packet_struct *orig_packet,
BOOL loopback_this_packet = False;
int rr_type = RR_TYPE_NB;
const char *packet_type = "unknown";
/* Check if we are sending to or from ourselves. */
if(ismyip(orig_packet->ip) && (orig_packet->port == global_nmb_port))
loopback_this_packet = True;
nmb = &packet.packet.nmb;
/* Do a partial copy of the packet. We clear the locked flag and
@ -944,28 +944,28 @@ for id %hu\n", packet_type, nmb_namestr(&orig_nmb->question.question_name),
nmb->header.nm_flags.bcast = False;
nmb->header.nm_flags.trunc = False;
nmb->header.nm_flags.authoritative = True;
nmb->header.rcode = rcode;
nmb->header.qdcount = 0;
nmb->header.ancount = 1;
nmb->header.nscount = 0;
nmb->header.arcount = 0;
memset((char*)&nmb->question,'\0',sizeof(nmb->question));
nmb->answers = &answers;
memset((char*)nmb->answers,'\0',sizeof(*nmb->answers));
nmb->answers->rr_name = orig_nmb->question.question_name;
nmb->answers->rr_type = rr_type;
nmb->answers->rr_class = RR_CLASS_IN;
nmb->answers->ttl = ttl;
if (data && len) {
nmb->answers->rdlength = len;
memcpy(nmb->answers->rdata, data, len);
}
packet.packet_type = NMB_PACKET;
/* Ensure we send out on the same fd that the original
packet came in on to give the correct source IP address. */
@ -973,7 +973,7 @@ for id %hu\n", packet_type, nmb_namestr(&orig_nmb->question.question_name),
packet.timestamp = time(NULL);
debug_nmb_packet(&packet);
if(loopback_this_packet) {
struct packet_struct *lo_packet;
DEBUG(5,("reply_netbios_packet: sending packet to ourselves.\n"));
@ -1000,9 +1000,9 @@ static void queue_packet(struct packet_struct *packet)
packet_queue = packet;
return;
}
/* find the bottom */
for (p=packet_queue;p->next;p=p->next)
for (p=packet_queue;p->next;p=p->next)
;
p->next = packet;
@ -1104,7 +1104,7 @@ packet from %s IP %s\n", nmb_namestr(&dgram->source_name), inet_ntoa(p->ip)));
process_master_browser_announce(subrec, p, buf+1);
break;
case ANN_BecomeBackup:
/*
/*
* We don't currently implement this. Log it just in case.
*/
debug_browse_data(buf, len);
@ -1118,7 +1118,7 @@ command ANN_BecomeBackup from %s IP %s to %s\n", subrec->subnet_name, nmb_namest
command code %d from %s IP %s to %s\n", subrec->subnet_name, command, nmb_namestr(&dgram->source_name),
inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name)));
break;
}
}
}
/****************************************************************************
@ -1345,7 +1345,7 @@ static BOOL validate_nmb_response_packet( struct nmb_packet *nmb )
return ignore;
}
/****************************************************************************
Validate a request nmb packet.
****************************************************************************/
@ -1510,7 +1510,7 @@ not allowed.\n"));
break;
}
break;
case NMB_NAME_RELEASE_OPCODE:
if(subrec == wins_server_subnet)
wins_process_name_release_request(subrec, p);
@ -1549,7 +1549,7 @@ found for id = %hu. Ignoring packet.\n", nmb->header.name_trn_id));
rrec->num_msgs++;
/* Ensure we don't re-send the request. */
rrec->repeat_count = 0;
/* Call the response received function for this packet. */
(*rrec->resp_fn)(subrec, rrec, p);
}
@ -1582,7 +1582,7 @@ void run_packet_queue(void)
}
free_packet(p);
}
}
}
/*******************************************************************
Retransmit or timeout elements from all the outgoing subnet response
@ -1601,7 +1601,7 @@ void retransmit_or_expire_response_records(time_t t)
for (rrec = subrec->responselist; rrec; rrec = nextrrec) {
nextrrec = rrec->next;
if (rrec->repeat_time <= t) {
if (rrec->repeat_count > 0) {
/* Resend while we have a non-zero repeat_count. */
@ -1712,7 +1712,7 @@ only use %d.\n", (count*2) + 2, FD_SETSIZE));
*ppset = pset;
*psock_array = sock_array;
return False;
}
@ -1756,7 +1756,7 @@ BOOL listen_for_packets(BOOL run_election)
}
#endif
/*
/*
* During elections and when expecting a netbios response packet we
* need to send election packets at tighter intervals.
* Ideally it needs to be the interval (in ms) between time now and
@ -1778,7 +1778,7 @@ BOOL listen_for_packets(BOOL run_election)
return False;
}
}
/* Prepare for the select - allow certain signals. */
BlockSignals(False, SIGTERM);
@ -1886,7 +1886,7 @@ BOOL send_mailslot(BOOL unique, const char *mailslot,char *buf, size_t len,
/* generate_name_trn_id(); */ /* Not used, so gone, RJS */
/* DIRECT GROUP or UNIQUE datagram. */
dgram->header.msg_type = unique ? 0x10 : 0x11;
dgram->header.msg_type = unique ? 0x10 : 0x11;
dgram->header.flags.node_type = M_NODE;
dgram->header.flags.first = True;
dgram->header.flags.more = False;
@ -1895,7 +1895,7 @@ BOOL send_mailslot(BOOL unique, const char *mailslot,char *buf, size_t len,
dgram->header.source_port = DGRAM_PORT;
dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
dgram->header.packet_offset = 0;
make_nmb_name(&dgram->source_name,srcname,src_type);
make_nmb_name(&dgram->dest_name,dstname,dest_type);
@ -1918,7 +1918,7 @@ BOOL send_mailslot(BOOL unique, const char *mailslot,char *buf, size_t len,
p2 = smb_buf(ptr);
safe_strcpy_base(p2, mailslot, dgram->data, sizeof(dgram->data));
p2 = skip_string(ptr,MAX_DGRAM_SIZE,p2);
if (((p2+len) > dgram->data+sizeof(dgram->data)) || ((p2+len) < p2)) {
DEBUG(0, ("send_mailslot: Cannot write beyond end of packet\n"));
return False;

View File

@ -62,8 +62,6 @@ BOOL session_claim(user_struct *vuser)
{
TDB_DATA key, data;
int i = 0;
struct sockaddr sa;
struct in_addr *client_ip;
struct sessionid sessionid;
struct server_id pid = procid_self();
fstring keystr;
@ -124,7 +122,7 @@ BOOL session_claim(user_struct *vuser)
TALLOC_FREE(rec);
}
if (i == MAX_SESSION_ID) {
SMB_ASSERT(rec == NULL);
DEBUG(1,("session_claim: out of session IDs "
@ -147,16 +145,16 @@ BOOL session_claim(user_struct *vuser)
return False;
}
snprintf(sessionid.id_str, sizeof(sessionid.id_str),
SESSION_TEMPLATE, (long unsigned int)sys_getpid(),
snprintf(sessionid.id_str, sizeof(sessionid.id_str),
SESSION_TEMPLATE, (long unsigned int)sys_getpid(),
vuser->vuid);
}
SMB_ASSERT(rec != NULL);
/* If 'hostname lookup' == yes, then do the DNS lookup. This is
needed because utmp and PAM both expect DNS names
needed because utmp and PAM both expect DNS names
client_name() handles this case internally.
*/
@ -172,11 +170,9 @@ BOOL session_claim(user_struct *vuser)
sessionid.uid = vuser->uid;
sessionid.gid = vuser->gid;
fstrcpy(sessionid.remote_machine, get_remote_machine_name());
fstrcpy(sessionid.ip_addr, client_addr());
fstrcpy(sessionid.ip_addr_str, client_addr());
sessionid.connect_start = time(NULL);
client_ip = client_inaddr(&sa);
if (!smb_pam_claim_session(sessionid.username, sessionid.id_str,
sessionid.hostname)) {
DEBUG(1,("pam_session rejected the session for %s [%s]\n",
@ -200,8 +196,8 @@ BOOL session_claim(user_struct *vuser)
}
if (lp_utmp()) {
sys_utmp_claim(sessionid.username, sessionid.hostname,
client_ip,
sys_utmp_claim(sessionid.username, sessionid.hostname,
sessionid.ip_addr_str,
sessionid.id_str, sessionid.id_num);
}
@ -224,7 +220,6 @@ void session_yield(user_struct *vuser)
{
TDB_DATA key;
struct sessionid sessionid;
struct in_addr *client_ip;
struct db_context *ctx;
struct db_record *rec;
@ -245,11 +240,9 @@ void session_yield(user_struct *vuser)
memcpy(&sessionid, rec->value.dptr, sizeof(sessionid));
client_ip = interpret_addr2(sessionid.ip_addr);
if (lp_utmp()) {
sys_utmp_yield(sessionid.username, sessionid.hostname,
client_ip,
sessionid.ip_addr_str,
sessionid.id_str, sessionid.id_num);
}

View File

@ -1,19 +1,19 @@
/*
/*
Unix SMB/CIFS implementation.
Copyright (C) Andrew Tridgell 1992-1998
Copyright (C) James Peach 2007
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@ -43,11 +43,11 @@ static int init_sockets_smbd(const char *smb_ports, int listenset[FD_SETSIZE])
}
if (lp_interfaces() && lp_bind_interfaces_only()) {
/* We have been given an interfaces line, and been
/* We have been given an interfaces line, and been
told to only bind to those interfaces. Create a
socket per interface and bind to only these.
*/
/* Now open a listen socket for each of the
interfaces. */
for(i = 0; i < num_interfaces; i++) {
@ -56,35 +56,45 @@ static int init_sockets_smbd(const char *smb_ports, int listenset[FD_SETSIZE])
const char *ptr;
if(ifip == NULL) {
DEBUG(0,("init_sockets_smbd: interface %d has NULL IP address !\n", i));
DEBUG(0,("init_sockets_smbd: interface %d has "
"NULL IP address !\n", i));
continue;
}
for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) {
for (ptr=ports; next_token(&ptr, tok, " \t,",
sizeof(tok)); ) {
unsigned port = atoi(tok);
if (port == 0 || port > 0xffff) {
continue;
}
s = listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True);
s = listenset[num_sockets] =
open_socket_in(SOCK_STREAM,
port,
0,
ifip->s_addr,
True);
if(s == -1)
return 0;
/* ready to listen */
set_socket_options(s,"SO_KEEPALIVE");
set_socket_options(s,"SO_KEEPALIVE");
set_socket_options(s,user_socket_options);
/* Set server socket to non-blocking for the accept. */
set_blocking(s,False);
/* Set server socket to non-blocking
* for the accept. */
set_blocking(s,False);
if (listen(s, SMBD_LISTEN_BACKLOG) == -1) {
DEBUG(0,("listen: %s\n",strerror(errno)));
DEBUG(0,("listen: %s\n",
strerror(errno)));
close(s);
return 0;
}
num_sockets++;
if (num_sockets >= FD_SETSIZE) {
DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n"));
DEBUG(0,("init_sockets_smbd: "
"Too many sockets to bind to\n"));
return 0;
}
}
@ -97,23 +107,24 @@ static int init_sockets_smbd(const char *smb_ports, int listenset[FD_SETSIZE])
const char *ptr;
num_interfaces = 1;
for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) {
unsigned port = atoi(tok);
if (port == 0 || port > 0xffff) continue;
/* open an incoming socket */
s = open_socket_in(SOCK_STREAM, port, 0,
interpret_addr(lp_socket_address()),True);
interpret_addr(lp_socket_address()),
True);
if (s == -1)
return 0;
/* ready to listen */
set_socket_options(s,"SO_KEEPALIVE");
set_socket_options(s,"SO_KEEPALIVE");
set_socket_options(s,user_socket_options);
/* Set server socket to non-blocking for the accept. */
set_blocking(s,False);
set_blocking(s,False);
if (listen(s, SMBD_LISTEN_BACKLOG) == -1) {
DEBUG(0,("init_sockets_smbd: listen: %s\n",
strerror(errno)));
@ -125,11 +136,12 @@ static int init_sockets_smbd(const char *smb_ports, int listenset[FD_SETSIZE])
num_sockets++;
if (num_sockets >= FD_SETSIZE) {
DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n"));
DEBUG(0,("init_sockets_smbd: "
"Too many sockets to bind to\n"));
return 0;
}
}
}
}
SAFE_FREE(ports);
return num_sockets;
@ -197,4 +209,3 @@ int smbd_sockinit(const char *cmdline_ports, int listenset[FD_SETSIZE],
return num_sockets;
}

View File

@ -112,14 +112,14 @@ Notes:
* Not WITH_UTMP? Simply supply dummy routines.
*/
void sys_utmp_claim(const char *username, const char *hostname,
struct in_addr *ipaddr,
const char *id_str, int id_num)
void sys_utmp_claim(const char *username, const char *hostname,
const char *ip_addr_str,
const char *id_str, int id_num)
{}
void sys_utmp_yield(const char *username, const char *hostname,
struct in_addr *ipaddr,
const char *id_str, int id_num)
void sys_utmp_yield(const char *username, const char *hostname,
const char *ip_addr_str,
const char *id_str, int id_num)
{}
#else /* WITH_UTMP */
@ -448,7 +448,7 @@ static int ut_id_encode(int i, char *fourbyte)
{
int nbase;
const char *ut_id_encstr = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
fourbyte[0] = 'S';
fourbyte[1] = 'M';
@ -470,13 +470,13 @@ static int ut_id_encode(int i, char *fourbyte)
/*
fill a system utmp structure given all the info we can gather
fill a system utmp structure given all the info we can gather
*/
static BOOL sys_utmp_fill(struct utmp *u,
const char *username, const char *hostname,
struct in_addr *ipaddr,
const char *id_str, int id_num)
{
const char *username, const char *hostname,
const char *ip_addr_str,
const char *id_str, int id_num)
{
struct timeval timeval;
/*
@ -507,7 +507,7 @@ static BOOL sys_utmp_fill(struct utmp *u,
#endif
/*
* ut_time, ut_tv:
* ut_time, ut_tv:
* Some have one, some the other. Many have both, but defined (aliased).
* It is easier and clearer simply to let the following take its course.
* But note that we do the more precise ut_tv as the final assignment.
@ -525,9 +525,22 @@ static BOOL sys_utmp_fill(struct utmp *u,
#if defined(HAVE_UT_UT_HOST)
utmp_strcpy(u->ut_host, hostname, sizeof(u->ut_host));
#endif
#if defined(HAVE_UT_UT_ADDR)
if (ipaddr)
u->ut_addr = ipaddr->s_addr;
#if defined(AF_INET6) && defined(HAVE_UT_UT_ADDR_V6)
memset(&u->ut_addr_v6, '\0', sizeof(u->ut_addr_v6));
if (ip_addr_str) {
struct in6_addr addr;
if (inet_pton(AF_INET6, ip_addr_str, &addr) > 0) {
memcpy(&u->ut_addr_v6, &addr, sizeof(addr));
}
}
#elif defined(HAVE_UT_UT_ADDR)
memset(&u->ut_addr, '\0', sizeof(u->ut_addr));
if (ip_addr_str) {
struct in_addr addr;
if (inet_pton(AF_INET, ip_addr_str, &addr) > 0) {
memcpy(&u->ut_addr, &addr, sizeof(addr));
}
}
/*
* "(unsigned long) ut_addr" apparently exists on at least HP-UX 10.20.
* Volunteer to implement, please ...
@ -548,9 +561,9 @@ static BOOL sys_utmp_fill(struct utmp *u,
Close a connection.
****************************************************************************/
void sys_utmp_yield(const char *username, const char *hostname,
struct in_addr *ipaddr,
const char *id_str, int id_num)
void sys_utmp_yield(const char *username, const char *hostname,
const char *ip_addr_str,
const char *id_str, int id_num)
{
struct utmp u;
@ -565,7 +578,8 @@ void sys_utmp_yield(const char *username, const char *hostname,
u.ut_type = DEAD_PROCESS;
#endif
if (!sys_utmp_fill(&u, username, hostname, ipaddr, id_str, id_num)) return;
if (!sys_utmp_fill(&u, username, hostname, ip_addr_str, id_str, id_num))
return;
sys_utmp_update(&u, NULL, False);
}
@ -574,9 +588,9 @@ void sys_utmp_yield(const char *username, const char *hostname,
Claim a entry in whatever utmp system the OS uses.
****************************************************************************/
void sys_utmp_claim(const char *username, const char *hostname,
struct in_addr *ipaddr,
const char *id_str, int id_num)
void sys_utmp_claim(const char *username, const char *hostname,
const char *ip_addr_str,
const char *id_str, int id_num)
{
struct utmp u;
@ -586,7 +600,8 @@ void sys_utmp_claim(const char *username, const char *hostname,
u.ut_type = USER_PROCESS;
#endif
if (!sys_utmp_fill(&u, username, hostname, ipaddr, id_str, id_num)) return;
if (!sys_utmp_fill(&u, username, hostname, ip_addr_str, id_str, id_num))
return;
sys_utmp_update(&u, hostname, True);
}