r25492: Start adding IPv6 compatible code to lib/util_sock.c and deal with
authorJeremy Allison <jra@samba.org>
Wed, 3 Oct 2007 20:43:55 +0000 (20:43 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:31:09 +0000 (12:31 -0500)
the ripple effects this causes. utmp has to change etc. Remove some
global varables and store address/port in the unexpected db.
Jeremy.
(This used to be commit 18c6a2211d9e25233d01715b3f78977edcd6d869)

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

index 1f5c1a857039c149bb53e25f9969b108291a2f10..2aca1df94d7dd0eb7e2c83ff648eb9e2e94836cf 100644 (file)
@@ -36,7 +36,7 @@ struct sessionid {
        fstring id_str;
        uint32  id_num;
        struct server_id pid;
        fstring id_str;
        uint32  id_num;
        struct server_id pid;
-       fstring ip_addr;
+       fstring ip_addr_str;
        time_t connect_start;
 };
 
        time_t connect_start;
 };
 
index eecbb9eec4e441f41aba18e6db8cd8d7160188cf..bcc1e8e15e54bae64d0d3fc01245b567f113e203 100644 (file)
@@ -3,7 +3,7 @@
    Samba utility functions
    Copyright (C) Andrew Tridgell 1992-1998
    Copyright (C) Tim Potter      2000-2001
    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
 
    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. */
    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)
 {
 
 void client_setfd(int fd)
 {
@@ -38,44 +66,49 @@ void client_setfd(int fd)
 
 static char *get_socket_addr(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);
        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 (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",
                DEBUG(0,("getsockname failed. Error was %s\n",
-                                       strerror(errno) ));
+                       strerror(errno) ));
                return addr_buf;
        }
 
                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)
 {
 }
 
 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);
 
        socklen_t length = sizeof(sa);
 
-       if (fd == -1)
+       if (fd == -1) {
                return -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",
                DEBUG(0,("getpeername failed. Error was %s\n",
-                                       strerror(errno) ));
+                       strerror(errno) ));
                return -1;
        }
 
                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)
 }
 
 char *client_name(void)
@@ -98,26 +131,6 @@ int client_socket_port(void)
        return get_socket_port(client_fd);
 }
 
        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;
 
 /****************************************************************************
 int smb_read_error = 0;
 
 /****************************************************************************
@@ -281,35 +294,42 @@ void set_socket_options(int fd, const char *options)
  Read from a socket.
 ****************************************************************************/
 
  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;
 {
        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,
        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) {
        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 {
                } 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;
 }
 
        return res;
 }
 
-
 /*******************************************************************
  Matchname - determine if host name matches IP address. Used to
  confirm a hostname lookup to prevent spoof attacks.
 /*******************************************************************
  Matchname - determine if host name matches IP address. Used to
  confirm a hostname lookup to prevent spoof attacks.
index 348555baf88920f953a41422480714aaa7cd9cd1..74deb91a73a1e1d414b3fd2c30e58b0c03f8a890 100644 (file)
@@ -1,28 +1,26 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
    NBT netbios library routines
    Copyright (C) Andrew Tridgell 1994-1998
    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 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.
    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/>.
    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"
 
 */
 
 #include "includes.h"
 
-extern struct in_addr lastip;
-extern int lastport;
-
 int num_good_sends = 0;
 int num_good_receives = 0;
 
 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 = '.';
                        unsigned char x = res->rdata[i+j];
                        if (x < 32 || x > 127)
                                x = '.';
-         
+
                        if (i+j >= res->rdlength)
                                break;
                        DEBUGADD(4, ("%c", x));
                }
                        if (i+j >= res->rdlength)
                                break;
                        DEBUGADD(4, ("%c", x));
                }
-      
+
                DEBUGADD(4, ("   hex "));
 
                for (j = 0; j < MAX_NETBIOSNAME_LEN; j++) {
                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]));
                }
                                break;
                        DEBUGADD(4, ("%02X", (unsigned char)res->rdata[i+j]));
                }
-      
+
                DEBUGADD(4, ("\n"));
        }
 }
                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 ) ) {
        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) );
                        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) );
                        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,
                        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;
                             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];
        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)
        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);
 
        /* handle initial name pointers */
        if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret))
                return(0);
-  
+
        m = ubuf[offset];
 
        if (!m)
        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) {
        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;
                name->name_type = ((unsigned char)name->name[15]) & 0xff;
-  
+
                /* remove trailing spaces */
                name->name[15] = 0;
                n = 14;
                while (n && name->name[n]==' ')
                /* 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) */
        }
 
        /* 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;
        }
                if (loop_count++ == 10)
                        return 0;
        }
-       name->scope[n++] = 0;  
+       name->scope[n++] = 0;
 
        return(ret);
 }
 
        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);
 
 {
        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);
        }
        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.
  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)
 ******************************************************************/
 
 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);
        }
 
                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++) {
 
        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;
 
        }
        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;
 
        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];
                        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
        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);
 
        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++) {
        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);
                (*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;
                (*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 > 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.
        }
        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)
 ******************************************************************/
 
 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;
                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;
        }
 
                offset += 10+recs[i].rdlength;
                ret += 10+recs[i].rdlength;
        }
 
-       return(ret);
+       return ret;
 }
 
 /*******************************************************************
  Put a compressed name pointer record into a packet.
 }
 
 /*******************************************************************
  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;
        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;
        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;
        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.
  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 ||
 
        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
                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);
 
        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.
 ******************************************************************/
 
  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.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);
        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) {
        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);
 
                if (!offset)
                        return(False);
 
@@ -534,16 +566,19 @@ static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
        }
 
        /* and any resource records */
        }
 
        /* 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);
 
                                        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);
                                        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);
                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)
 ******************************************************************/
 
 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;
        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) {
        /* 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;
                        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) {
                                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;
                        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) {
                                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;
                        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));
        }
 
                                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)
 ******************************************************************/
 
 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) {
        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)
 ******************************************************************/
 
 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;
 }
        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)
 /*******************************************************************
  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);
        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)
 ******************************************************************/
 
 static void free_dgram_packet(struct dgram_packet *nmb)
-{  
+{
        /* We have nothing to do for a dgram packet. */
 }
 
        /* 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)
 ******************************************************************/
 
 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);
                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,
 ******************************************************************/
 
 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;
 {
        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->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;
        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 NMB_PACKET:
                ok = parse_nmb(buf,length,&p->packet.nmb);
                break;
-               
+
        case DGRAM_PACKET:
                ok = parse_dgram(buf,length,&p->packet.dgram);
                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 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;
        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;
        if (!packet)
                return NULL;
 
        packet->fd = fd;
-       
+
        num_good_receives++;
        num_good_receives++;
-       
+
        DEBUG(5,("Received a packet of len %d from (%s) port %d\n",
                 length, inet_ntoa(packet->ip), packet->port ) );
        DEBUG(5,("Received a packet of len %d from (%s) port %d\n",
                 length, inet_ntoa(packet->ip), packet->port ) );
-       
+
        return(packet);
 }
        return(packet);
 }
-                                        
+
 /*******************************************************************
  Send a udp packet on a already open socket.
 ******************************************************************/
 /*******************************************************************
  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;
        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.
         */
        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++) {
        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;
        }
                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.
 
 /*******************************************************************
  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 */
 {
        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 ||
 
        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);
        }
 
                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
        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);
         *       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.
 
 /*******************************************************************
  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;
 
 {
        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 */
        /* 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 += 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;
        }
 
                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);
                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);
                offset += put_res_rec((char *)ubuf,offset,nmb->nsrecs,
                                nmb->header.nscount);
+       }
 
        /*
         * The spec says we must put compressed name pointers
 
        /*
         * 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) &&
         */
 
        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) {
        } 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,
                offset += put_res_rec((char *)ubuf,offset,nmb->additional,
-                       nmb->header.arcount);  
+                       nmb->header.arcount);
        }
        }
-       return(offset);
+       return offset;
 }
 
 /*******************************************************************
  Linearise a packet.
 ******************************************************************/
 
 }
 
 /*******************************************************************
  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:
 {
        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:
                break;
 
        case DGRAM_PACKET:
-               len = build_dgram(buf,p);
+               len = build_dgram(buf,buflen,p);
                break;
        }
 
                break;
        }
 
@@ -989,7 +1079,7 @@ BOOL send_packet(struct packet_struct *p)
 
        memset(buf,'\0',sizeof(buf));
 
 
        memset(buf,'\0',sizeof(buf));
 
-       len = build_packet(buf, p);
+       len = build_packet(buf, sizeof(buf), p);
 
        if (!len)
                return(False);
 
        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. */
 
        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;
 
                return NULL;
        }
 
        if (ret == 0) /* timeout */
                return NULL;
 
-       if (FD_ISSET(fd,&fds)) 
+       if (FD_ISSET(fd,&fds))
                return(read_packet(fd,type));
                return(read_packet(fd,type));
-       
+
        return(NULL);
 }
 
        return(NULL);
 }
 
@@ -1057,7 +1148,8 @@ struct packet_struct *receive_nmb_packet(int fd, int t, int trn_id)
  The timeout is in milliseconds.
 ***************************************************************************/
 
  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;
 
 {
        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++;
                if ((p1[i] & (1<<(7-j))) != (p2[i] & (1<<(7-j))))
                        break;
                ret++;
-       }       
-       
+       }
+
        return ret;
 }
 
        return ret;
 }
 
@@ -1127,7 +1219,8 @@ static unsigned char sort_ip[4];
 
 static int name_query_comp(unsigned char *p1, unsigned char *p2)
 {
 
 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;
        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
        /* 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);
        }
        } else {
                return(buf+ofs);
        }
-}  
+}
 
 /****************************************************************************
  Extract a netbios name from a buf (into a unix string) return name type.
 
 /****************************************************************************
  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(0);
        return(name_interpret(p,name));
 }
-  
+
 /****************************************************************************
  Return the total storage length of a mangled name.
 ****************************************************************************/
 /****************************************************************************
  Return the total storage length of a mangled name.
 ****************************************************************************/
index 6f85f36a6219d99e52835802540f02f29bddb9d6..f5837f321cbe0783ecd6b282278832ac39ae693f 100644 (file)
@@ -1,21 +1,21 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
    handle unexpected packets
    Copyright (C) Andrew Tridgell 2000
    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 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.
    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/>.
    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"
 */
 
 #include "includes.h"
@@ -29,13 +29,12 @@ struct unexpected_key {
        int count;
 };
 
        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
  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;
 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;
        struct unexpected_key key;
        char buf[1024];
        int len=0;
+       uint32_t enc_ip;
 
        if (!tdbd) {
 
        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) {
                               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));
        }
 
        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;
 
        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;
 
 /****************************************************************************
 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;
 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;
 void clear_unexpected(time_t t)
 {
        if (!tdbd) return;
@@ -112,22 +119,39 @@ static enum packet_type match_type;
 static const char *match_name;
 
 /****************************************************************************
 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;
 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;
 
        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) ||
             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;
             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;
 }
 
        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;
                                         const char *mailslot_name)
 {
        TDB_CONTEXT *tdb2;
index baf243cda1fe4337073b849dcbd9cb871e3ffcea..bf01075d1421008843655c9722ba6a55e17170e7 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.
 ****************************************************************************/
 /****************************************************************************
  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,
 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.
 ****************************************************************************/
 /****************************************************************************
  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,
 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;
                p->locked = False;
                free_packet(p);
                return NULL;
-       } 
+       }
 
        if((rrec = make_response_record(subrec,           /* subnet record. */
                                        p,                     /* packet we sent. */
 
        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";
        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;
        /* 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
        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.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;
        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));
        memset((char*)&nmb->question,'\0',sizeof(nmb->question));
-  
+
        nmb->answers = &answers;
        memset((char*)nmb->answers,'\0',sizeof(*nmb->answers));
        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;
        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);
        }
        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. */
        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);
        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"));
        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;
        }
                packet_queue = packet;
                return;
        }
-  
+
        /* find the bottom */
        /* find the bottom */
-       for (p=packet_queue;p->next;p=p->next) 
+       for (p=packet_queue;p->next;p=p->next)
                ;
 
        p->next = packet;
                ;
 
        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:
                        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);
                         * 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;
 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;
 }
 
        return ignore;
 }
+
 /****************************************************************************
   Validate a request nmb packet.
 ****************************************************************************/
 /****************************************************************************
   Validate a request nmb packet.
 ****************************************************************************/
@@ -1510,7 +1510,7 @@ not allowed.\n"));
                                        break;
                        }
                        break;
                                        break;
                        }
                        break;
-      
+
                case NMB_NAME_RELEASE_OPCODE:
                        if(subrec == wins_server_subnet)
                                wins_process_name_release_request(subrec, p);
                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;
        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);
 }
        /* 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);
        }
                }
                free_packet(p);
        }
-} 
+}
 
 /*******************************************************************
  Retransmit or timeout elements from all the outgoing subnet response
 
 /*******************************************************************
  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;
 
                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. */
                        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;
 
        *ppset = pset;
        *psock_array = sock_array;
+
        return False;
 }
 
        return False;
 }
 
@@ -1756,7 +1756,7 @@ BOOL listen_for_packets(BOOL run_election)
        }
 #endif
 
        }
 #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
         * 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;
                }
        }
                        return False;
                }
        }
-       
+
        /* Prepare for the select - allow certain signals. */
 
        BlockSignals(False, SIGTERM);
        /* 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. */
        /* 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;
        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;
        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);
 
        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);
        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;
        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 3cc93c1a7f42d46eba012ffb87bc13523439a860..c7cdf41fb5b0ed19c4feb1512e6ea68252d91fa7 100644 (file)
@@ -62,8 +62,6 @@ BOOL session_claim(user_struct *vuser)
 {
        TDB_DATA key, data;
        int i = 0;
 {
        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;
        struct sessionid sessionid;
        struct server_id pid = procid_self();
        fstring keystr;
@@ -124,7 +122,7 @@ BOOL session_claim(user_struct *vuser)
 
                        TALLOC_FREE(rec);
                }
 
                        TALLOC_FREE(rec);
                }
-               
+
                if (i == MAX_SESSION_ID) {
                        SMB_ASSERT(rec == NULL);
                        DEBUG(1,("session_claim: out of session IDs "
                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;
                }
 
                        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
                         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.
        */
 
           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());
        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);
 
        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",
        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()) {
        }
 
        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);
        }
 
                               sessionid.id_str, sessionid.id_num);
        }
 
@@ -224,7 +220,6 @@ void session_yield(user_struct *vuser)
 {
        TDB_DATA key;
        struct sessionid sessionid;
 {
        TDB_DATA key;
        struct sessionid sessionid;
-       struct in_addr *client_ip;
        struct db_context *ctx;
        struct db_record *rec;
 
        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));
 
 
        memcpy(&sessionid, rec->value.dptr, sizeof(sessionid));
 
-       client_ip = interpret_addr2(sessionid.ip_addr);
-
        if (lp_utmp()) {
                sys_utmp_yield(sessionid.username, sessionid.hostname, 
        if (lp_utmp()) {
                sys_utmp_yield(sessionid.username, sessionid.hostname, 
-                              client_ip,
+                              sessionid.ip_addr_str,
                               sessionid.id_str, sessionid.id_num);
        }
 
                               sessionid.id_str, sessionid.id_num);
        }
 
index c526a181d34d32c2ac4fe5b4cae2d43a2f1dd4e5..598bbd1bda7a2993fc3e4b96d586ee035e11df50 100644 (file)
@@ -1,19 +1,19 @@
-/* 
+/*
    Unix SMB/CIFS implementation.
 
    Copyright (C) Andrew Tridgell               1992-1998
    Copyright (C) James Peach                   2007
    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 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.
    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/>.
 */
    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()) {
        }
 
        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.
                */
                   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++) {
                /* 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) {
                        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;
                        }
 
                                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;
                                }
                                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 */
                                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_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) {
                                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) {
                                        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;
                                }
                        }
                                        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;
                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,
                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;
                        if (s == -1)
                                return 0;
-               
+
                        /* ready to listen */
                        /* ready to listen */
-                       set_socket_options(s,"SO_KEEPALIVE"); 
+                       set_socket_options(s,"SO_KEEPALIVE");
                        set_socket_options(s,user_socket_options);
                        set_socket_options(s,user_socket_options);
-                       
+
                        /* Set server socket to non-blocking for the accept. */
                        /* Set server socket to non-blocking for the accept. */
-                       set_blocking(s,False); 
+                       set_blocking(s,False);
+
                        if (listen(s, SMBD_LISTEN_BACKLOG) == -1) {
                                DEBUG(0,("init_sockets_smbd: listen: %s\n",
                                         strerror(errno)));
                        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) {
                        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;
                        }
                }
                                return 0;
                        }
                }
-       } 
+       }
 
        SAFE_FREE(ports);
        return num_sockets;
 
        SAFE_FREE(ports);
        return num_sockets;
@@ -197,4 +209,3 @@ int smbd_sockinit(const char *cmdline_ports, int listenset[FD_SETSIZE],
 
        return num_sockets;
 }
 
        return num_sockets;
 }
-
index eb2152dac2f8976bfd841753cfb870fe9c74055d..52174c4d8379484a27ea88e087ecd84a318fe8ce 100644 (file)
@@ -112,14 +112,14 @@ Notes:
  * Not WITH_UTMP?  Simply supply dummy routines.
  */
 
  * 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 */
 {}
 
 #else /* WITH_UTMP */
@@ -448,7 +448,7 @@ static int ut_id_encode(int i, char *fourbyte)
 {
        int nbase;
        const char *ut_id_encstr = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
 {
        int nbase;
        const char *ut_id_encstr = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
-       
+
        fourbyte[0] = 'S';
        fourbyte[1] = 'M';
 
        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,
 */
 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;
 
        /*
        struct timeval timeval;
 
        /*
@@ -507,7 +507,7 @@ static BOOL sys_utmp_fill(struct utmp *u,
 #endif
 
 /*
 #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.
  *     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_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 ...
        /*
         * "(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.
 ****************************************************************************/
 
  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;
 
 {
        struct utmp u;
 
@@ -565,7 +578,8 @@ void sys_utmp_yield(const char *username, const char *hostname,
        u.ut_type = DEAD_PROCESS;
 #endif
 
        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);
 }
 
        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.
 ****************************************************************************/
 
  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;
 
 {
        struct utmp u;
 
@@ -586,7 +600,8 @@ void sys_utmp_claim(const char *username, const char *hostname,
        u.ut_type = USER_PROCESS;
 #endif
 
        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);
 }
 
        sys_utmp_update(&u, hostname, True);
 }