Start adding IPv6 compatible code to lib/util_sock.c and deal with
authorjra <jra@0c0555d6-39d7-0310-84fc-f1cc0bd64818>
Wed, 3 Oct 2007 20:43:55 +0000 (20:43 +0000)
committerjra <jra@0c0555d6-39d7-0310-84fc-f1cc0bd64818>
Wed, 3 Oct 2007 20:43:55 +0000 (20:43 +0000)
the ripple effects this causes. utmp has to change etc. Remove some
global varables and store address/port in the unexpected db.
Jeremy.

git-svn-id: svn+ssh://svn.samba.org/data/svn/samba/branches/SAMBA_3_2@25492 0c0555d6-39d7-0310-84fc-f1cc0bd64818

source/include/session.h
source/lib/util_sock.c
source/libsmb/nmblib.c
source/libsmb/unexpected.c
source/nmbd/nmbd_packets.c
source/smbd/session.c
source/smbd/sockinit.c
source/smbd/utmp.c

index 1f5c1a8..2aca1df 100644 (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;
 };
 
index eecbb9e..bcc1e8e 100644 (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
    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)
+       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) ));
+                       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",
-                                               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.
index 348555b..74deb91 100644 (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;
 
+       if (len && len < 12) {
+               return 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);
-
-       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);
-  
+       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);
+       }
+
        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.
 ****************************************************************************/
index 6f85f36..f5837f3 100644 (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;
+       }
+
+       /* 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 && 
+       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;
index baf243c..bf01075 100644 (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;
index 3cc93c1..c7cdf41 100644 (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);
        }
 
index c526a18..598bbd1 100644 (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;
 }
-
index eb2152d..52174c4 100644 (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);
 }