1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +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) ));
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)
if (fd == -1) {
return -1;
}
if (getsockname(fd, &sa, &length) < 0) {
if (getsockname(fd, (struct sockaddr *)&sa, &length) < 0) {
DEBUG(0,("getpeername failed. Error was %s\n",
strerror(errno) ));
return -1;
}
return ntohs(sockin->sin_port);
#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",
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

@ -2,6 +2,7 @@
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
@ -20,9 +21,6 @@
#include "includes.h"
extern struct in_addr lastip;
extern int lastport;
int num_good_sends = 0;
int num_good_receives = 0;
@ -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,
@ -161,11 +162,12 @@ static BOOL handle_name_ptrs(unsigned char *ubuf,int *offset,int length,
(*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;
}
/*******************************************************************
@ -214,7 +216,8 @@ 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 */
@ -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,22 +303,30 @@ static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
put_name(buf1, name->name, ' ', name->name_type);
}
if (buf) {
buf[offset] = 0x20;
}
ret = 34;
for (m=0;m<MAX_NETBIOSNAME_LEN;m++) {
if (buf) {
buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF);
buf[offset+2+2*m] = 'A' + (buf1[m]&0xF);
}
}
offset += 33;
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));
if (buf) {
safe_strcpy(&buf[offset+1],name->scope,
sizeof(name->scope));
p = &buf[offset+1];
while ((p = strchr_m(p,'.'))) {
@ -322,8 +336,9 @@ static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
}
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);
@ -387,6 +404,7 @@ static BOOL parse_alloc_res_rec(char *inbuf,int *offset,int length,
/*******************************************************************
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,38 +416,48 @@ 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;
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;
if (buf) {
buf[offset] = (0xC0 | ((ptr_offset >> 8) & 0xFF));
buf[offset+1] = (ptr_offset & 0xFF);
}
offset += 2;
ret += 2;
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;
}
/*******************************************************************
@ -467,8 +495,10 @@ 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);
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)))
@ -478,7 +508,8 @@ static BOOL parse_dgram(char *inbuf,int length,struct dgram_packet *dgram)
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);
@ -519,7 +550,8 @@ static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
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);
@ -582,19 +617,22 @@ 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,
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,
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,
nmb->header.arcount * sizeof(struct res_rec));
@ -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;
@ -735,14 +775,21 @@ 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);
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);
packet = parse_packet(buf,
length,
packet_type,
si->sin_addr,
si->sin_port);
if (!packet)
return NULL;
@ -780,7 +827,8 @@ static BOOL send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
*/
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,27 +845,17 @@ 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 */
if (buf) {
ubuf[0] = dgram->header.msg_type;
ubuf[1] = (((int)dgram->header.flags.node_type)<<2);
if (dgram->header.flags.more)
@ -828,6 +866,7 @@ static int build_dgram(char *buf,struct packet_struct *p)
putip(ubuf+4,(char *)&dgram->header.source_ip);
RSSVAL(ubuf,8,dgram->header.source_port);
RSSVAL(ubuf,12,dgram->header.packet_offset);
}
offset = 14;
@ -838,7 +877,9 @@ static int build_dgram(char *buf,struct packet_struct *p)
offset += put_nmb_name((char *)ubuf,offset,&dgram->dest_name);
}
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);
if (buf) {
RSSVAL(ubuf,10,dgram->header.dgm_length);
}
return(offset);
return offset;
}
/*******************************************************************
@ -879,20 +922,21 @@ 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;
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)
@ -915,23 +959,53 @@ static int build_nmb(char *buf,struct packet_struct *p)
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);
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
@ -948,30 +1022,46 @@ static int build_nmb(char *buf,struct packet_struct *p)
(nmb->header.opcode == NMB_NAME_MULTIHOMED_REG_OPCODE)) &&
(nmb->header.arcount == 1)) {
offset += put_compressed_name_ptr(ubuf,offset,nmb->additional,12);
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);
}
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,7 +1105,8 @@ 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;
}
@ -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;
@ -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);
}
/****************************************************************************

View File

@ -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,6 +42,7 @@ 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,
@ -56,7 +56,12 @@ 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,18 +119,35 @@ 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;
}
/* 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) ||
@ -138,10 +162,10 @@ 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
**************************************************************************/
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)
{

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;
@ -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",
@ -201,7 +197,7 @@ BOOL session_claim(user_struct *vuser)
if (lp_utmp()) {
sys_utmp_claim(sessionid.username, sessionid.hostname,
client_ip,
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

@ -56,16 +56,23 @@ 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;
@ -73,18 +80,21 @@ static int init_sockets_smbd(const char *smb_ports, int listenset[FD_SETSIZE])
set_socket_options(s,"SO_KEEPALIVE");
set_socket_options(s,user_socket_options);
/* Set server socket to non-blocking for the accept. */
/* 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;
}
}
@ -103,7 +113,8 @@ static int init_sockets_smbd(const char *smb_ports, int listenset[FD_SETSIZE])
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;
@ -125,7 +136,8 @@ 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;
}
}
@ -197,4 +209,3 @@ int smbd_sockinit(const char *cmdline_ports, int listenset[FD_SETSIZE],
return num_sockets;
}

View File

@ -113,12 +113,12 @@ Notes:
*/
void sys_utmp_claim(const char *username, const char *hostname,
struct in_addr *ipaddr,
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 *ip_addr_str,
const char *id_str, int id_num)
{}
@ -474,7 +474,7 @@ static int ut_id_encode(int i, char *fourbyte)
*/
static BOOL sys_utmp_fill(struct utmp *u,
const char *username, const char *hostname,
struct in_addr *ipaddr,
const char *ip_addr_str,
const char *id_str, int id_num)
{
struct timeval timeval;
@ -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 ...
@ -549,7 +562,7 @@ static BOOL sys_utmp_fill(struct utmp *u,
****************************************************************************/
void sys_utmp_yield(const char *username, const char *hostname,
struct in_addr *ipaddr,
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);
}
@ -575,7 +589,7 @@ void sys_utmp_yield(const char *username, const char *hostname,
****************************************************************************/
void sys_utmp_claim(const char *username, const char *hostname,
struct in_addr *ipaddr,
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);
}