diff --git a/source/include/session.h b/source/include/session.h index 1f5c1a85703..2aca1df94d7 100644 --- a/source/include/session.h +++ b/source/include/session.h @@ -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; }; diff --git a/source/lib/util_sock.c b/source/lib/util_sock.c index eecbb9eec4e..bcc1e8e15e5 100644 --- a/source/lib/util_sock.c +++ b/source/lib/util_sock.c @@ -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. diff --git a/source/libsmb/nmblib.c b/source/libsmb/nmblib.c index 348555baf88..74deb91a73a 100644 --- a/source/libsmb/nmblib.c +++ b/source/libsmb/nmblib.c @@ -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 . - + */ #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>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 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. ****************************************************************************/ diff --git a/source/libsmb/unexpected.c b/source/libsmb/unexpected.c index 6f85f36a621..f5837f321cb 100644 --- a/source/libsmb/unexpected.c +++ b/source/libsmb/unexpected.c @@ -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 . - + */ #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; diff --git a/source/nmbd/nmbd_packets.c b/source/nmbd/nmbd_packets.c index baf243cda1f..bf01075d142 100644 --- a/source/nmbd/nmbd_packets.c +++ b/source/nmbd/nmbd_packets.c @@ -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; diff --git a/source/smbd/session.c b/source/smbd/session.c index 3cc93c1a7f4..c7cdf41fb5b 100644 --- a/source/smbd/session.c +++ b/source/smbd/session.c @@ -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); } diff --git a/source/smbd/sockinit.c b/source/smbd/sockinit.c index c526a181d34..598bbd1bda7 100644 --- a/source/smbd/sockinit.c +++ b/source/smbd/sockinit.c @@ -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 . */ @@ -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; } - diff --git a/source/smbd/utmp.c b/source/smbd/utmp.c index eb2152dac2f..52174c4d837 100644 --- a/source/smbd/utmp.c +++ b/source/smbd/utmp.c @@ -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); }