s3:lib: s/SMBkeepalive/NBSSkeepalive
[sfrench/samba-autobuild/.git] / source3 / lib / util_sock.c
index 3604be369f3f51305e757ab65a7de25b9e85e398..ebdd2c78f3de696e0a794ec8f1aa320b2593e914 100644 (file)
 */
 
 #include "includes.h"
-
-/*******************************************************************
- Map a text hostname or IP address (IPv4 or IPv6) into a
- struct sockaddr_storage.
-******************************************************************/
-
-bool interpret_string_addr(struct sockaddr_storage *pss,
-               const char *str,
-               int flags)
-{
-       struct addrinfo *res = NULL;
-#if defined(HAVE_IPV6)
-       char addr[INET6_ADDRSTRLEN];
-       unsigned int scope_id = 0;
-
-       if (strchr_m(str, ':')) {
-               char *p = strchr_m(str, '%');
-
-               /*
-                * Cope with link-local.
-                * This is IP:v6:addr%ifname.
-                */
-
-               if (p && (p > str) && ((scope_id = if_nametoindex(p+1)) != 0)) {
-                       strlcpy(addr, str,
-                               MIN(PTR_DIFF(p,str)+1,
-                                       sizeof(addr)));
-                       str = addr;
-               }
-       }
-#endif
-
-       zero_sockaddr(pss);
-
-       if (!interpret_string_addr_internal(&res, str, flags|AI_ADDRCONFIG)) {
-               return false;
-       }
-       if (!res) {
-               return false;
-       }
-       /* Copy the first sockaddr. */
-       memcpy(pss, res->ai_addr, res->ai_addrlen);
-
-#if defined(HAVE_IPV6)
-       if (pss->ss_family == AF_INET6 && scope_id) {
-               struct sockaddr_in6 *ps6 = (struct sockaddr_in6 *)pss;
-               if (IN6_IS_ADDR_LINKLOCAL(&ps6->sin6_addr) &&
-                               ps6->sin6_scope_id == 0) {
-                       ps6->sin6_scope_id = scope_id;
-               }
-       }
-#endif
-
-       freeaddrinfo(res);
-       return true;
-}
-
-/*******************************************************************
- Set an address to INADDR_ANY.
-******************************************************************/
-
-void zero_sockaddr(struct sockaddr_storage *pss)
-{
-       memset(pss, '\0', sizeof(*pss));
-       /* Ensure we're at least a valid sockaddr-storage. */
-       pss->ss_family = AF_INET;
-}
-
-/****************************************************************************
- Get a port number in host byte order from a sockaddr_storage.
-****************************************************************************/
-
-uint16_t get_sockaddr_port(const struct sockaddr_storage *pss)
-{
-       uint16_t port = 0;
-
-       if (pss->ss_family != AF_INET) {
-#if defined(HAVE_IPV6)
-               /* IPv6 */
-               const struct sockaddr_in6 *sa6 =
-                       (const struct sockaddr_in6 *)pss;
-               port = ntohs(sa6->sin6_port);
-#endif
-       } else {
-               const struct sockaddr_in *sa =
-                       (const struct sockaddr_in *)pss;
-               port = ntohs(sa->sin_port);
-       }
-       return port;
-}
-
-/****************************************************************************
- Print out an IPv4 or IPv6 address from a struct sockaddr_storage.
-****************************************************************************/
-
-static char *print_sockaddr_len(char *dest,
-                       size_t destlen,
-                       const struct sockaddr *psa,
-                       socklen_t psalen)
-{
-       if (destlen > 0) {
-               dest[0] = '\0';
-       }
-       (void)sys_getnameinfo(psa,
-                       psalen,
-                       dest, destlen,
-                       NULL, 0,
-                       NI_NUMERICHOST);
-       return dest;
-}
-
-/****************************************************************************
- Print out an IPv4 or IPv6 address from a struct sockaddr_storage.
-****************************************************************************/
-
-char *print_sockaddr(char *dest,
-                       size_t destlen,
-                       const struct sockaddr_storage *psa)
-{
-       return print_sockaddr_len(dest, destlen, (struct sockaddr *)psa,
-                       sizeof(struct sockaddr_storage));
-}
-
-/****************************************************************************
- Print out a canonical IPv4 or IPv6 address from a struct sockaddr_storage.
-****************************************************************************/
-
-char *print_canonical_sockaddr(TALLOC_CTX *ctx,
-                       const struct sockaddr_storage *pss)
-{
-       char addr[INET6_ADDRSTRLEN];
-       char *dest = NULL;
-       int ret;
-
-       /* Linux getnameinfo() man pages says port is unitialized if
-          service name is NULL. */
-
-       ret = sys_getnameinfo((const struct sockaddr *)pss,
-                       sizeof(struct sockaddr_storage),
-                       addr, sizeof(addr),
-                       NULL, 0,
-                       NI_NUMERICHOST);
-       if (ret != 0) {
-               return NULL;
-       }
-
-       if (pss->ss_family != AF_INET) {
-#if defined(HAVE_IPV6)
-               dest = talloc_asprintf(ctx, "[%s]", addr);
-#else
-               return NULL;
-#endif
-       } else {
-               dest = talloc_asprintf(ctx, "%s", addr);
-       }
-       
-       return dest;
-}
-
-/****************************************************************************
- Return the string of an IP address (IPv4 or IPv6).
-****************************************************************************/
-
-static const char *get_socket_addr(int fd, char *addr_buf, size_t addr_len)
-{
-       struct sockaddr_storage sa;
-       socklen_t length = sizeof(sa);
-
-       /* Ok, returning a hard coded IPv4 address
-        * is bogus, but it's just as bogus as a
-        * zero IPv6 address. No good choice here.
-        */
-
-       strlcpy(addr_buf, "0.0.0.0", addr_len);
-
-       if (fd == -1) {
-               return addr_buf;
-       }
-
-       if (getsockname(fd, (struct sockaddr *)&sa, &length) < 0) {
-               DEBUG(0,("getsockname failed. Error was %s\n",
-                       strerror(errno) ));
-               return addr_buf;
-       }
-
-       return print_sockaddr_len(addr_buf, addr_len, (struct sockaddr *)&sa, length);
-}
-
-#if 0
-/* Not currently used. JRA. */
-/****************************************************************************
- Return the port number we've bound to on a socket.
-****************************************************************************/
-
-static int get_socket_port(int fd)
-{
-       struct sockaddr_storage sa;
-       socklen_t length = sizeof(sa);
-
-       if (fd == -1) {
-               return -1;
-       }
-
-       if (getsockname(fd, (struct sockaddr *)&sa, &length) < 0) {
-               DEBUG(0,("getpeername failed. Error was %s\n",
-                       strerror(errno) ));
-               return -1;
-       }
-
-#if defined(HAVE_IPV6)
-       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;
-}
-#endif
+#include "system/filesys.h"
+#include "memcache.h"
+#include "../lib/async_req/async_sock.h"
+#include "../lib/util/select.h"
+#include "lib/socket/interfaces.h"
+#include "../lib/util/tevent_unix.h"
+#include "../lib/util/tevent_ntstatus.h"
+#include "../lib/tsocket/tsocket.h"
 
 const char *client_name(int fd)
 {
@@ -251,11 +39,6 @@ const char *client_addr(int fd, char *addr, size_t addrlen)
        return get_peer_addr(fd,addr,addrlen);
 }
 
-const char *client_socket_addr(int fd, char *addr, size_t addr_len)
-{
-       return get_socket_addr(fd, addr, addr_len);
-}
-
 #if 0
 /* Not currently used. JRA. */
 int client_socket_port(int fd)
@@ -264,26 +47,6 @@ int client_socket_port(int fd)
 }
 #endif
 
-/****************************************************************************
- Accessor functions to make thread-safe code easier later...
-****************************************************************************/
-
-void set_smb_read_error(enum smb_read_errors *pre,
-                       enum smb_read_errors newerr)
-{
-       if (pre) {
-               *pre = newerr;
-       }
-}
-
-void cond_set_smb_read_error(enum smb_read_errors *pre,
-                       enum smb_read_errors newerr)
-{
-       if (pre && *pre == SMB_READ_OK) {
-               *pre = newerr;
-       }
-}
-
 /****************************************************************************
  Determine if a file descriptor is in fact a socket.
 ****************************************************************************/
@@ -296,157 +59,6 @@ bool is_a_socket(int fd)
        return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
 }
 
-enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
-
-typedef struct smb_socket_option {
-       const char *name;
-       int level;
-       int option;
-       int value;
-       int opttype;
-} smb_socket_option;
-
-static const smb_socket_option socket_options[] = {
-  {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL},
-  {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL},
-  {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL},
-#ifdef TCP_NODELAY
-  {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL},
-#endif
-#ifdef TCP_KEEPCNT
-  {"TCP_KEEPCNT", IPPROTO_TCP, TCP_KEEPCNT, 0, OPT_INT},
-#endif
-#ifdef TCP_KEEPIDLE
-  {"TCP_KEEPIDLE", IPPROTO_TCP, TCP_KEEPIDLE, 0, OPT_INT},
-#endif
-#ifdef TCP_KEEPINTVL
-  {"TCP_KEEPINTVL", IPPROTO_TCP, TCP_KEEPINTVL, 0, OPT_INT},
-#endif
-#ifdef IPTOS_LOWDELAY
-  {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON},
-#endif
-#ifdef IPTOS_THROUGHPUT
-  {"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON},
-#endif
-#ifdef SO_REUSEPORT
-  {"SO_REUSEPORT", SOL_SOCKET, SO_REUSEPORT, 0, OPT_BOOL},
-#endif
-#ifdef SO_SNDBUF
-  {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT},
-#endif
-#ifdef SO_RCVBUF
-  {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT},
-#endif
-#ifdef SO_SNDLOWAT
-  {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT},
-#endif
-#ifdef SO_RCVLOWAT
-  {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT},
-#endif
-#ifdef SO_SNDTIMEO
-  {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT},
-#endif
-#ifdef SO_RCVTIMEO
-  {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT},
-#endif
-#ifdef TCP_FASTACK
-  {"TCP_FASTACK", IPPROTO_TCP, TCP_FASTACK, 0, OPT_INT},
-#endif
-  {NULL,0,0,0,0}};
-
-/****************************************************************************
- Print socket options.
-****************************************************************************/
-
-static void print_socket_options(int s)
-{
-       int value;
-       socklen_t vlen = 4;
-       const smb_socket_option *p = &socket_options[0];
-
-       /* wrapped in if statement to prevent streams
-        * leak in SCO Openserver 5.0 */
-       /* reported on samba-technical  --jerry */
-       if ( DEBUGLEVEL >= 5 ) {
-               DEBUG(5,("Socket options:\n"));
-               for (; p->name != NULL; p++) {
-                       if (getsockopt(s, p->level, p->option,
-                                               (void *)&value, &vlen) == -1) {
-                               DEBUGADD(5,("\tCould not test socket option %s.\n",
-                                                       p->name));
-                       } else {
-                               DEBUGADD(5,("\t%s = %d\n",
-                                                       p->name,value));
-                       }
-               }
-       }
- }
-
-/****************************************************************************
- Set user socket options.
-****************************************************************************/
-
-void set_socket_options(int fd, const char *options)
-{
-       TALLOC_CTX *ctx = talloc_stackframe();
-       char *tok;
-
-       while (next_token_talloc(ctx, &options, &tok," \t,")) {
-               int ret=0,i;
-               int value = 1;
-               char *p;
-               bool got_value = false;
-
-               if ((p = strchr_m(tok,'='))) {
-                       *p = 0;
-                       value = atoi(p+1);
-                       got_value = true;
-               }
-
-               for (i=0;socket_options[i].name;i++)
-                       if (strequal(socket_options[i].name,tok))
-                               break;
-
-               if (!socket_options[i].name) {
-                       DEBUG(0,("Unknown socket option %s\n",tok));
-                       continue;
-               }
-
-               switch (socket_options[i].opttype) {
-               case OPT_BOOL:
-               case OPT_INT:
-                       ret = setsockopt(fd,socket_options[i].level,
-                                       socket_options[i].option,
-                                       (char *)&value,sizeof(int));
-                       break;
-
-               case OPT_ON:
-                       if (got_value)
-                               DEBUG(0,("syntax error - %s "
-                                       "does not take a value\n",tok));
-
-                       {
-                               int on = socket_options[i].value;
-                               ret = setsockopt(fd,socket_options[i].level,
-                                       socket_options[i].option,
-                                       (char *)&on,sizeof(int));
-                       }
-                       break;
-               }
-
-               if (ret != 0) {
-                       /* be aware that some systems like Solaris return
-                        * EINVAL to a setsockopt() call when the client
-                        * sent a RST previously - no need to worry */
-                       DEBUG(2,("Failed to set socket option %s (Error %s)\n",
-                               tok, strerror(errno) ));
-               }
-       }
-
-       TALLOC_FREE(ctx);
-       print_socket_options(fd);
-}
-
 /****************************************************************************
  Read from a socket.
 ****************************************************************************/
@@ -490,23 +102,22 @@ ssize_t read_udp_v4_socket(int fd,
 }
 
 /****************************************************************************
- Read data from a socket with a timout in msec.
+ Read data from a file descriptor with a timout in msec.
  mincount = if timeout, minimum to read before returning
  maxcount = number to be read.
  time_out = timeout in milliseconds
+ NB. This can be called with a non-socket fd, don't change
+ sys_read() to sys_recv() or other socket call.
 ****************************************************************************/
 
-NTSTATUS read_socket_with_timeout(int fd, char *buf,
+NTSTATUS read_fd_with_timeout(int fd, char *buf,
                                  size_t mincnt, size_t maxcnt,
                                  unsigned int time_out,
                                  size_t *size_ret)
 {
-       fd_set fds;
-       int selrtn;
+       int pollrtn;
        ssize_t readret;
        size_t nread = 0;
-       struct timeval timeout;
-       char addr[INET6_ADDRSTRLEN];
 
        /* just checking .... */
        if (maxcnt <= 0)
@@ -522,24 +133,12 @@ NTSTATUS read_socket_with_timeout(int fd, char *buf,
                        readret = sys_read(fd, buf + nread, maxcnt - nread);
 
                        if (readret == 0) {
-                               DEBUG(5,("read_socket_with_timeout: "
+                               DEBUG(5,("read_fd_with_timeout: "
                                        "blocking read. EOF from client.\n"));
                                return NT_STATUS_END_OF_FILE;
                        }
 
                        if (readret == -1) {
-                               if (fd == get_client_fd()) {
-                                       /* Try and give an error message
-                                        * saying what client failed. */
-                                       DEBUG(0,("read_socket_with_timeout: "
-                                               "client %s read error = %s.\n",
-                                               get_peer_addr(fd,addr,sizeof(addr)),
-                                               strerror(errno) ));
-                               } else {
-                                       DEBUG(0,("read_socket_with_timeout: "
-                                               "read error = %s.\n",
-                                               strerror(errno) ));
-                               }
                                return map_nt_error_from_unix(errno);
                        }
                        nread += readret;
@@ -553,37 +152,21 @@ NTSTATUS read_socket_with_timeout(int fd, char *buf,
           system performance will suffer severely as
           select always returns true on disk files */
 
-       /* Set initial timeout */
-       timeout.tv_sec = (time_t)(time_out / 1000);
-       timeout.tv_usec = (long)(1000 * (time_out % 1000));
-
        for (nread=0; nread < mincnt; ) {
-               FD_ZERO(&fds);
-               FD_SET(fd,&fds);
+               int revents;
 
-               selrtn = sys_select_intr(fd+1,&fds,NULL,NULL,&timeout);
+               pollrtn = poll_intr_one_fd(fd, POLLIN|POLLHUP, time_out,
+                                          &revents);
 
                /* Check if error */
-               if (selrtn == -1) {
-                       /* something is wrong. Maybe the socket is dead? */
-                       if (fd == get_client_fd()) {
-                               /* Try and give an error message saying
-                                * what client failed. */
-                               DEBUG(0,("read_socket_with_timeout: timeout "
-                               "read for client %s. select error = %s.\n",
-                               get_peer_addr(fd,addr,sizeof(addr)),
-                               strerror(errno) ));
-                       } else {
-                               DEBUG(0,("read_socket_with_timeout: timeout "
-                               "read. select error = %s.\n",
-                               strerror(errno) ));
-                       }
+               if (pollrtn == -1) {
                        return map_nt_error_from_unix(errno);
                }
 
                /* Did we timeout ? */
-               if (selrtn == 0) {
-                       DEBUG(10,("read_socket_with_timeout: timeout read. "
+               if ((pollrtn == 0) ||
+                   ((revents & (POLLIN|POLLHUP|POLLERR)) == 0)) {
+                       DEBUG(10,("read_fd_with_timeout: timeout read. "
                                "select timed out.\n"));
                        return NT_STATUS_IO_TIMEOUT;
                }
@@ -592,25 +175,12 @@ NTSTATUS read_socket_with_timeout(int fd, char *buf,
 
                if (readret == 0) {
                        /* we got EOF on the file descriptor */
-                       DEBUG(5,("read_socket_with_timeout: timeout read. "
+                       DEBUG(5,("read_fd_with_timeout: timeout read. "
                                "EOF from client.\n"));
                        return NT_STATUS_END_OF_FILE;
                }
 
                if (readret == -1) {
-                       /* the descriptor is probably dead */
-                       if (fd == get_client_fd()) {
-                               /* Try and give an error message
-                                * saying what client failed. */
-                               DEBUG(0,("read_socket_with_timeout: timeout "
-                                       "read to client %s. read error = %s.\n",
-                                       get_peer_addr(fd,addr,sizeof(addr)),
-                                       strerror(errno) ));
-                       } else {
-                               DEBUG(0,("read_socket_with_timeout: timeout "
-                                       "read. read error = %s.\n",
-                                       strerror(errno) ));
-                       }
                        return map_nt_error_from_unix(errno);
                }
 
@@ -626,16 +196,20 @@ NTSTATUS read_socket_with_timeout(int fd, char *buf,
 }
 
 /****************************************************************************
- Read data from the client, reading exactly N bytes.
+ Read data from an fd, reading exactly N bytes.
+ NB. This can be called with a non-socket fd, don't add dependencies
+ on socket calls.
 ****************************************************************************/
 
 NTSTATUS read_data(int fd, char *buffer, size_t N)
 {
-       return read_socket_with_timeout(fd, buffer, N, N, 0, NULL);
+       return read_fd_with_timeout(fd, buffer, N, N, 0, NULL);
 }
 
 /****************************************************************************
  Write all data from an iov array
+ NB. This can be called with a non-socket fd, don't add dependencies
+ on socket calls.
 ****************************************************************************/
 
 ssize_t write_data_iov(int fd, const struct iovec *orig_iov, int iovcnt)
@@ -664,7 +238,7 @@ ssize_t write_data_iov(int fd, const struct iovec *orig_iov, int iovcnt)
         * discarding elements.
         */
 
-       iov_copy = (struct iovec *)TALLOC_MEMDUP(
+       iov_copy = (struct iovec *)talloc_memdup(
                talloc_tos(), orig_iov, sizeof(struct iovec) * iovcnt);
 
        if (iov_copy == NULL) {
@@ -683,7 +257,7 @@ ssize_t write_data_iov(int fd, const struct iovec *orig_iov, int iovcnt)
                        if (thistime < iov[0].iov_len) {
                                char *new_base =
                                        (char *)iov[0].iov_base + thistime;
-                               iov[0].iov_base = new_base;
+                               iov[0].iov_base = (void *)new_base;
                                iov[0].iov_len -= thistime;
                                break;
                        }
@@ -705,35 +279,17 @@ ssize_t write_data_iov(int fd, const struct iovec *orig_iov, int iovcnt)
 
 /****************************************************************************
  Write data to a fd.
+ NB. This can be called with a non-socket fd, don't add dependencies
+ on socket calls.
 ****************************************************************************/
 
 ssize_t write_data(int fd, const char *buffer, size_t N)
 {
-       ssize_t ret;
        struct iovec iov;
 
-       iov.iov_base = CONST_DISCARD(char *, buffer);
+       iov.iov_base = discard_const_p(void, buffer);
        iov.iov_len = N;
-
-       ret = write_data_iov(fd, &iov, 1);
-       if (ret >= 0) {
-               return ret;
-       }
-
-       if (fd == get_client_fd()) {
-               char addr[INET6_ADDRSTRLEN];
-               /*
-                * Try and give an error message saying what client failed.
-                */
-               DEBUG(0, ("write_data: write failure in writing to client %s. "
-                         "Error %s\n", get_peer_addr(fd,addr,sizeof(addr)),
-                         strerror(errno)));
-       } else {
-               DEBUG(0,("write_data: write failure. Error = %s\n",
-                        strerror(errno) ));
-       }
-
-       return -1;
+       return write_data_iov(fd, &iov, 1);
 }
 
 /****************************************************************************
@@ -744,7 +300,7 @@ bool send_keepalive(int client)
 {
        unsigned char buf[4];
 
-       buf[0] = SMBkeepalive;
+       buf[0] = NBSSkeepalive;
        buf[1] = buf[2] = buf[3] = 0;
 
        return(write_data(client,(char *)buf,4) == 4);
@@ -765,7 +321,7 @@ NTSTATUS read_smb_length_return_keepalive(int fd, char *inbuf,
        int msg_type;
        NTSTATUS status;
 
-       status = read_socket_with_timeout(fd, inbuf, 4, 4, timeout, NULL);
+       status = read_fd_with_timeout(fd, inbuf, 4, 4, timeout, NULL);
 
        if (!NT_STATUS_IS_OK(status)) {
                return status;
@@ -774,7 +330,7 @@ NTSTATUS read_smb_length_return_keepalive(int fd, char *inbuf,
        *len = smb_len(inbuf);
        msg_type = CVAL(inbuf,0);
 
-       if (msg_type == SMBkeepalive) {
+       if (msg_type == NBSSkeepalive) {
                DEBUG(5,("Got keepalive packet\n"));
        }
 
@@ -783,36 +339,6 @@ NTSTATUS read_smb_length_return_keepalive(int fd, char *inbuf,
        return NT_STATUS_OK;
 }
 
-/****************************************************************************
- Read 4 bytes of a smb packet and return the smb length of the packet.
- Store the result in the buffer. This version of the function will
- never return a session keepalive (length of zero).
- Timeout is in milliseconds.
-****************************************************************************/
-
-NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
-                        size_t *len)
-{
-       uint8_t msgtype = SMBkeepalive;
-
-       while (msgtype == SMBkeepalive) {
-               NTSTATUS status;
-
-               status = read_smb_length_return_keepalive(fd, inbuf, timeout,
-                                                         len);
-               if (!NT_STATUS_IS_OK(status)) {
-                       return status;
-               }
-
-               msgtype = CVAL(inbuf, 0);
-       }
-
-       DEBUG(10,("read_smb_length: got smb length of %lu\n",
-                 (unsigned long)len));
-
-       return NT_STATUS_OK;
-}
-
 /****************************************************************************
  Read an smb from a fd.
  The timeout is in milliseconds.
@@ -831,7 +357,8 @@ NTSTATUS receive_smb_raw(int fd, char *buffer, size_t buflen, unsigned int timeo
        status = read_smb_length_return_keepalive(fd,buffer,timeout,&len);
 
        if (!NT_STATUS_IS_OK(status)) {
-               DEBUG(10, ("receive_smb_raw: %s!\n", nt_errstr(status)));
+               DEBUG(0, ("read_fd_with_timeout failed, read "
+                         "error = %s.\n", nt_errstr(status)));
                return status;
        }
 
@@ -846,10 +373,12 @@ NTSTATUS receive_smb_raw(int fd, char *buffer, size_t buflen, unsigned int timeo
                        len = MIN(len,maxlen);
                }
 
-               status = read_socket_with_timeout(
+               status = read_fd_with_timeout(
                        fd, buffer+4, len, len, timeout, &len);
 
                if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(0, ("read_fd_with_timeout failed, read error = "
+                                 "%s.\n", nt_errstr(status)));
                        return status;
                }
 
@@ -925,6 +454,32 @@ int open_socket_in(int type,
 #endif /* SO_REUSEPORT */
        }
 
+#ifdef HAVE_IPV6
+       /*
+        * As IPV6_V6ONLY is the default on some systems,
+        * we better try to be consistent and always use it.
+        *
+        * This also avoids using IPv4 via AF_INET6 sockets
+        * and makes sure %I never resolves to a '::ffff:192.168.0.1'
+        * string.
+        */
+       if (sock.ss_family == AF_INET6) {
+               int val = 1;
+               int ret;
+
+               ret = setsockopt(res, IPPROTO_IPV6, IPV6_V6ONLY,
+                                (const void *)&val, sizeof(val));
+               if (ret == -1) {
+                       if(DEBUGLVL(0)) {
+                               dbgtext("open_socket_in(): IPV6_ONLY failed: ");
+                               dbgtext("%s\n", strerror(errno));
+                       }
+                       close(res);
+                       return -1;
+               }
+       }
+#endif
+
        /* now we've got a socket - we need to bind it */
        if (bind(res, (struct sockaddr *)&sock, slen) == -1 ) {
                if( DEBUGLVL(dlevel) && (port == SMB_PORT1 ||
@@ -950,7 +505,7 @@ struct open_socket_out_state {
        struct sockaddr_storage ss;
        socklen_t salen;
        uint16_t port;
-       int wait_nsec;
+       int wait_usec;
 };
 
 static void open_socket_out_connected(struct tevent_req *subreq);
@@ -986,7 +541,7 @@ struct tevent_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
        state->ev = ev;
        state->ss = *pss;
        state->port = port;
-       state->wait_nsec = 10000;
+       state->wait_usec = 10000;
        state->salen = -1;
 
        state->fd = socket(state->ss.ss_family, SOCK_STREAM, 0);
@@ -997,7 +552,7 @@ struct tevent_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
        talloc_set_destructor(state, open_socket_out_state_destructor);
 
        if (!tevent_req_set_endtime(
-                   result, ev, timeval_current_ofs(0, timeout*1000))) {
+                   result, ev, timeval_current_ofs_msec(timeout))) {
                goto fail;
        }
 
@@ -1021,6 +576,10 @@ struct tevent_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
                state->salen = sizeof(struct sockaddr_in);
        }
 
+       if (pss->ss_family == AF_UNIX) {
+               state->salen = sizeof(struct sockaddr_un);
+       }
+
        print_sockaddr(addr, sizeof(addr), &state->ss);
        DEBUG(3,("Connecting to %s at port %u\n", addr, (unsigned int)port));
 
@@ -1030,7 +589,7 @@ struct tevent_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
        if ((subreq == NULL)
            || !tevent_req_set_endtime(
                    subreq, state->ev,
-                   timeval_current_ofs(0, state->wait_nsec))) {
+                   timeval_current_ofs(0, state->wait_usec))) {
                goto fail;
        }
        tevent_req_set_callback(subreq, open_socket_out_connected, result);
@@ -1072,8 +631,8 @@ static void open_socket_out_connected(struct tevent_req *subreq)
                 * retry
                 */
 
-               if (state->wait_nsec < 250000) {
-                       state->wait_nsec *= 1.5;
+               if (state->wait_usec < 250000) {
+                       state->wait_usec *= 1.5;
                }
 
                subreq = async_connect_send(state, state->ev, state->fd,
@@ -1084,7 +643,7 @@ static void open_socket_out_connected(struct tevent_req *subreq)
                }
                if (!tevent_req_set_endtime(
                            subreq, state->ev,
-                           timeval_current_ofs(0, state->wait_nsec))) {
+                           timeval_current_ofs_usec(state->wait_usec))) {
                        tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
                        return;
                }
@@ -1117,6 +676,16 @@ NTSTATUS open_socket_out_recv(struct tevent_req *req, int *pfd)
        return NT_STATUS_OK;
 }
 
+/**
+* @brief open a socket
+*
+* @param pss a struct sockaddr_storage defining the address to connect to
+* @param port to connect to
+* @param timeout in MILLISECONDS
+* @param pfd file descriptor returned
+*
+* @return NTSTATUS code
+*/
 NTSTATUS open_socket_out(const struct sockaddr_storage *pss, uint16_t port,
                         int timeout, int *pfd)
 {
@@ -1152,22 +721,22 @@ struct open_socket_out_defer_state {
        int fd;
 };
 
-static void open_socket_out_defer_waited(struct async_req *subreq);
+static void open_socket_out_defer_waited(struct tevent_req *subreq);
 static void open_socket_out_defer_connected(struct tevent_req *subreq);
 
-struct async_req *open_socket_out_defer_send(TALLOC_CTX *mem_ctx,
-                                            struct event_context *ev,
-                                            struct timeval wait_time,
-                                            const struct sockaddr_storage *pss,
-                                            uint16_t port,
-                                            int timeout)
+struct tevent_req *open_socket_out_defer_send(TALLOC_CTX *mem_ctx,
+                                             struct event_context *ev,
+                                             struct timeval wait_time,
+                                             const struct sockaddr_storage *pss,
+                                             uint16_t port,
+                                             int timeout)
 {
-       struct async_req *result, *subreq;
+       struct tevent_req *req, *subreq;
        struct open_socket_out_defer_state *state;
-       NTSTATUS status;
 
-       if (!async_req_setup(mem_ctx, &result, &state,
-                            struct open_socket_out_defer_state)) {
+       req = tevent_req_create(mem_ctx, &state,
+                               struct open_socket_out_defer_state);
+       if (req == NULL) {
                return NULL;
        }
        state->ev = ev;
@@ -1175,73 +744,66 @@ struct async_req *open_socket_out_defer_send(TALLOC_CTX *mem_ctx,
        state->port = port;
        state->timeout = timeout;
 
-       subreq = async_wait_send(state, ev, wait_time);
+       subreq = tevent_wakeup_send(
+               state, ev,
+               timeval_current_ofs(wait_time.tv_sec, wait_time.tv_usec));
        if (subreq == NULL) {
-               status = NT_STATUS_NO_MEMORY;
-               goto post_status;
-       }
-       subreq->async.fn = open_socket_out_defer_waited;
-       subreq->async.priv = result;
-       return result;
-
- post_status:
-       if (!async_post_ntstatus(result, ev, status)) {
                goto fail;
        }
-       return result;
+       tevent_req_set_callback(subreq, open_socket_out_defer_waited, req);
+       return req;
  fail:
-       TALLOC_FREE(result);
+       TALLOC_FREE(req);
        return NULL;
 }
 
-static void open_socket_out_defer_waited(struct async_req *subreq)
+static void open_socket_out_defer_waited(struct tevent_req *subreq)
 {
-       struct async_req *req = talloc_get_type_abort(
-               subreq->async.priv, struct async_req);
-       struct open_socket_out_defer_state *state = talloc_get_type_abort(
-               req->private_data, struct open_socket_out_defer_state);
-       struct tevent_req *subreq2;
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct open_socket_out_defer_state *state = tevent_req_data(
+               req, struct open_socket_out_defer_state);
        bool ret;
 
-       ret = async_wait_recv(subreq);
+       ret = tevent_wakeup_recv(subreq);
        TALLOC_FREE(subreq);
        if (!ret) {
-               async_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+               tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
                return;
        }
 
-       subreq2 = open_socket_out_send(state, state->ev, &state->ss,
-                                      state->port, state->timeout);
-       if (async_req_nomem(subreq2, req)) {
+       subreq = open_socket_out_send(state, state->ev, &state->ss,
+                                     state->port, state->timeout);
+       if (tevent_req_nomem(subreq, req)) {
                return;
        }
-       tevent_req_set_callback(subreq2, open_socket_out_defer_connected, req);
+       tevent_req_set_callback(subreq, open_socket_out_defer_connected, req);
 }
 
 static void open_socket_out_defer_connected(struct tevent_req *subreq)
 {
-       struct async_req *req =
-               tevent_req_callback_data(subreq, struct async_req);
-       struct open_socket_out_defer_state *state = talloc_get_type_abort(
-               req->private_data, struct open_socket_out_defer_state);
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       struct open_socket_out_defer_state *state = tevent_req_data(
+               req, struct open_socket_out_defer_state);
        NTSTATUS status;
 
        status = open_socket_out_recv(subreq, &state->fd);
        TALLOC_FREE(subreq);
        if (!NT_STATUS_IS_OK(status)) {
-               async_req_nterror(req, status);
+               tevent_req_nterror(req, status);
                return;
        }
-       async_req_done(req);
+       tevent_req_done(req);
 }
 
-NTSTATUS open_socket_out_defer_recv(struct async_req *req, int *pfd)
+NTSTATUS open_socket_out_defer_recv(struct tevent_req *req, int *pfd)
 {
-       struct open_socket_out_defer_state *state = talloc_get_type_abort(
-               req->private_data, struct open_socket_out_defer_state);
+       struct open_socket_out_defer_state *state = tevent_req_data(
+               req, struct open_socket_out_defer_state);
        NTSTATUS status;
 
-       if (async_req_is_nterror(req, &status)) {
+       if (tevent_req_is_nterror(req, &status)) {
                return status;
        }
        *pfd = state->fd;
@@ -1249,195 +811,45 @@ NTSTATUS open_socket_out_defer_recv(struct async_req *req, int *pfd)
        return NT_STATUS_OK;
 }
 
-/*******************************************************************
- Create an outgoing TCP socket to the first addr that connects.
-
- This is for simultaneous connection attempts to port 445 and 139 of a host
- or for simultatneous connection attempts to multiple DCs at once.  We return
- a socket fd of the first successful connection.
-
- @param[in] addrs list of Internet addresses and ports to connect to
- @param[in] num_addrs number of address/port pairs in the addrs list
- @param[in] timeout time after which we stop waiting for a socket connection
-            to succeed, given in milliseconds
- @param[out] fd_index the entry in addrs which we successfully connected to
- @param[out] fd fd of the open and connected socket
- @return true on a successful connection, false if all connection attempts
-         failed or we timed out
-*******************************************************************/
-
-bool open_any_socket_out(struct sockaddr_storage *addrs, int num_addrs,
-                        int timeout, int *fd_index, int *fd)
-{
-       int i, resulting_index, res;
-       int *sockets;
-       bool good_connect;
-
-       fd_set r_fds, wr_fds;
-       struct timeval tv;
-       int maxfd;
-
-       int connect_loop = 10000; /* 10 milliseconds */
-
-       timeout *= 1000;        /* convert to microseconds */
-
-       sockets = SMB_MALLOC_ARRAY(int, num_addrs);
-
-       if (sockets == NULL)
-               return false;
-
-       resulting_index = -1;
-
-       for (i=0; i<num_addrs; i++)
-               sockets[i] = -1;
-
-       for (i=0; i<num_addrs; i++) {
-               sockets[i] = socket(addrs[i].ss_family, SOCK_STREAM, 0);
-               if (sockets[i] < 0)
-                       goto done;
-               set_blocking(sockets[i], false);
-       }
-
- connect_again:
-       good_connect = false;
-
-       for (i=0; i<num_addrs; i++) {
-               const struct sockaddr * a = 
-                   (const struct sockaddr *)&(addrs[i]);
-
-               if (sockets[i] == -1)
-                       continue;
-
-               if (sys_connect(sockets[i], a) == 0) {
-                       /* Rather unlikely as we are non-blocking, but it
-                        * might actually happen. */
-                       resulting_index = i;
-                       goto done;
-               }
-
-               if (errno == EINPROGRESS || errno == EALREADY ||
-#ifdef EISCONN
-                       errno == EISCONN ||
-#endif
-                   errno == EAGAIN || errno == EINTR) {
-                       /* These are the error messages that something is
-                          progressing. */
-                       good_connect = true;
-               } else if (errno != 0) {
-                       /* There was a direct error */
-                       close(sockets[i]);
-                       sockets[i] = -1;
-               }
-       }
-
-       if (!good_connect) {
-               /* All of the connect's resulted in real error conditions */
-               goto done;
-       }
-
-       /* Lets see if any of the connect attempts succeeded */
-
-       maxfd = 0;
-       FD_ZERO(&wr_fds);
-       FD_ZERO(&r_fds);
-
-       for (i=0; i<num_addrs; i++) {
-               if (sockets[i] == -1)
-                       continue;
-               FD_SET(sockets[i], &wr_fds);
-               FD_SET(sockets[i], &r_fds);
-               if (sockets[i]>maxfd)
-                       maxfd = sockets[i];
-       }
-
-       tv.tv_sec = 0;
-       tv.tv_usec = connect_loop;
-
-       res = sys_select_intr(maxfd+1, &r_fds, &wr_fds, NULL, &tv);
-
-       if (res < 0)
-               goto done;
-
-       if (res == 0)
-               goto next_round;
-
-       for (i=0; i<num_addrs; i++) {
-
-               if (sockets[i] == -1)
-                       continue;
-
-               /* Stevens, Network Programming says that if there's a
-                * successful connect, the socket is only writable. Upon an
-                * error, it's both readable and writable. */
-
-               if (FD_ISSET(sockets[i], &r_fds) &&
-                   FD_ISSET(sockets[i], &wr_fds)) {
-                       /* readable and writable, so it's an error */
-                       close(sockets[i]);
-                       sockets[i] = -1;
-                       continue;
-               }
-
-               if (!FD_ISSET(sockets[i], &r_fds) &&
-                   FD_ISSET(sockets[i], &wr_fds)) {
-                       /* Only writable, so it's connected */
-                       resulting_index = i;
-                       goto done;
-               }
-       }
-
- next_round:
-
-       timeout -= connect_loop;
-       if (timeout <= 0)
-               goto done;
-       connect_loop *= 1.5;
-       if (connect_loop > timeout)
-               connect_loop = timeout;
-       goto connect_again;
-
- done:
-       for (i=0; i<num_addrs; i++) {
-               if (i == resulting_index)
-                       continue;
-               if (sockets[i] >= 0)
-                       close(sockets[i]);
-       }
-
-       if (resulting_index >= 0) {
-               *fd_index = resulting_index;
-               *fd = sockets[*fd_index];
-               set_blocking(*fd, true);
-       }
-
-       free(sockets);
-
-       return (resulting_index >= 0);
-}
 /****************************************************************************
  Open a connected UDP socket to host on port
 **************************************************************************/
 
 int open_udp_socket(const char *host, int port)
 {
-       int type = SOCK_DGRAM;
-       struct sockaddr_in sock_out;
+       struct sockaddr_storage ss;
        int res;
-       struct in_addr addr;
 
-       addr = interpret_addr2(host);
+       if (!interpret_string_addr(&ss, host, 0)) {
+               DEBUG(10,("open_udp_socket: can't resolve name %s\n",
+                       host));
+               return -1;
+       }
 
-       res = socket(PF_INET, type, 0);
+       res = socket(ss.ss_family, SOCK_DGRAM, 0);
        if (res == -1) {
                return -1;
        }
 
-       memset((char *)&sock_out,'\0',sizeof(sock_out));
-       putip((char *)&sock_out.sin_addr,(char *)&addr);
-       sock_out.sin_port = htons(port);
-       sock_out.sin_family = PF_INET;
+#if defined(HAVE_IPV6)
+       if (ss.ss_family == AF_INET6) {
+               struct sockaddr_in6 *psa6;
+               psa6 = (struct sockaddr_in6 *)&ss;
+               psa6->sin6_port = htons(port);
+               if (psa6->sin6_scope_id == 0
+                               && IN6_IS_ADDR_LINKLOCAL(&psa6->sin6_addr)) {
+                       setup_linklocal_scope_id(
+                               (struct sockaddr *)&ss);
+               }
+       }
+#endif
+        if (ss.ss_family == AF_INET) {
+                struct sockaddr_in *psa;
+                psa = (struct sockaddr_in *)&ss;
+                psa->sin_port = htons(port);
+        }
 
-       if (sys_connect(res,(struct sockaddr *)&sock_out)) {
+       if (sys_connect(res,(struct sockaddr *)&ss)) {
                close(res);
                return -1;
        }
@@ -1471,8 +883,9 @@ static const char *get_peer_addr_internal(int fd,
        }
 
        if (getpeername(fd, (struct sockaddr *)pss, plength) < 0) {
-               DEBUG(0,("getpeername failed. Error was %s\n",
-                                       strerror(errno) ));
+               int level = (errno == ENOTCONN) ? 2 : 0;
+               DEBUG(level, ("getpeername failed. Error was %s\n",
+                              strerror(errno)));
                return addr_buf;
        }
 
@@ -1528,7 +941,7 @@ static bool matchname(const char *remotehost,
                        continue;
                }
                if (sockaddr_equal((const struct sockaddr *)res->ai_addr,
-                                       (struct sockaddr *)pss)) {
+                                       (const struct sockaddr *)pss)) {
                        freeaddrinfo(ailist);
                        return true;
                }
@@ -1671,10 +1084,6 @@ const char *get_peer_name(int fd, bool force_lookup)
                }
        }
 
-       /* can't pass the same source and dest strings in when you
-          use --enable-developer or the clobber_region() call will
-          get you */
-
        strlcpy(tmp_name, name_buf, sizeof(tmp_name));
        alpha_strcpy(name_buf, tmp_name, "_-.", sizeof(name_buf));
        if (strstr(name_buf,"..")) {
@@ -1698,6 +1107,113 @@ const char *get_peer_addr(int fd, char *addr, size_t addr_len)
        return get_peer_addr_internal(fd, addr, addr_len, NULL, NULL);
 }
 
+int get_remote_hostname(const struct tsocket_address *remote_address,
+                       char **name,
+                       TALLOC_CTX *mem_ctx)
+{
+       char name_buf[MAX_DNS_NAME_LENGTH];
+       char tmp_name[MAX_DNS_NAME_LENGTH];
+       struct name_addr_pair nc;
+       struct sockaddr_storage ss;
+       ssize_t len;
+       int rc;
+
+       if (!lp_hostname_lookups()) {
+               nc.name = tsocket_address_inet_addr_string(remote_address,
+                                                          mem_ctx);
+               if (nc.name == NULL) {
+                       return -1;
+               }
+
+               len = tsocket_address_bsd_sockaddr(remote_address,
+                                                  (struct sockaddr *) &nc.ss,
+                                                  sizeof(struct sockaddr_storage));
+               if (len < 0) {
+                       return -1;
+               }
+
+               store_nc(&nc);
+               lookup_nc(&nc);
+
+               if (nc.name == NULL) {
+                       *name = talloc_strdup(mem_ctx, "UNKNOWN");
+               } else {
+                       *name = talloc_strdup(mem_ctx, nc.name);
+               }
+               return 0;
+       }
+
+       lookup_nc(&nc);
+
+       ZERO_STRUCT(ss);
+
+       len = tsocket_address_bsd_sockaddr(remote_address,
+                                          (struct sockaddr *) &ss,
+                                          sizeof(struct sockaddr_storage));
+       if (len < 0) {
+               return -1;
+       }
+
+       /* it might be the same as the last one - save some DNS work */
+       if (sockaddr_equal((struct sockaddr *)&ss, (struct sockaddr *)&nc.ss)) {
+               if (nc.name == NULL) {
+                       *name = talloc_strdup(mem_ctx, "UNKNOWN");
+               } else {
+                       *name = talloc_strdup(mem_ctx, nc.name);
+               }
+               return 0;
+       }
+
+       /* Look up the remote host name. */
+       rc = sys_getnameinfo((struct sockaddr *) &ss,
+                            len,
+                            name_buf,
+                            sizeof(name_buf),
+                            NULL,
+                            0,
+                            0);
+       if (rc < 0) {
+               char *p;
+
+               p = tsocket_address_inet_addr_string(remote_address, mem_ctx);
+               if (p == NULL) {
+                       return -1;
+               }
+
+               DEBUG(1,("getnameinfo failed for %s with error %s\n",
+                        p,
+                        gai_strerror(rc)));
+               strlcpy(name_buf, p, sizeof(name_buf));
+
+               TALLOC_FREE(p);
+       } else {
+               if (!matchname(name_buf, (struct sockaddr *)&ss, len)) {
+                       DEBUG(0,("matchname failed on %s\n", name_buf));
+                       strlcpy(name_buf, "UNKNOWN", sizeof(name_buf));
+               }
+       }
+
+       strlcpy(tmp_name, name_buf, sizeof(tmp_name));
+       alpha_strcpy(name_buf, tmp_name, "_-.", sizeof(name_buf));
+       if (strstr(name_buf,"..")) {
+               strlcpy(name_buf, "UNKNOWN", sizeof(name_buf));
+       }
+
+       nc.name = name_buf;
+       nc.ss = ss;
+
+       store_nc(&nc);
+       lookup_nc(&nc);
+
+       if (nc.name == NULL) {
+               *name = talloc_strdup(mem_ctx, "UNKOWN");
+       } else {
+               *name = talloc_strdup(mem_ctx, nc.name);
+       }
+
+       return 0;
+}
+
 /*******************************************************************
  Create protected unix domain socket.
 
@@ -1738,14 +1254,21 @@ int create_pipe_sock(const char *socket_dir,
        } else {
                /* Check ownership and permission on existing directory */
                if (!S_ISDIR(st.st_mode)) {
-                       DEBUG(0, ("socket directory %s isn't a directory\n",
+                       DEBUG(0, ("socket directory '%s' isn't a directory\n",
                                socket_dir));
                        goto out_umask;
                }
-               if ((st.st_uid != sec_initial_uid()) ||
-                               ((st.st_mode & 0777) != dir_perms)) {
-                       DEBUG(0, ("invalid permissions on socket directory "
-                               "%s\n", socket_dir));
+               if (st.st_uid != sec_initial_uid()) {
+                       DEBUG(0, ("invalid ownership on directory "
+                                 "'%s'\n", socket_dir));
+                       umask(old_umask);
+                       goto out_umask;
+               }
+               if ((st.st_mode & 0777) != dir_perms) {
+                       DEBUG(0, ("invalid permissions on directory "
+                                 "'%s': has 0%o should be 0%o\n", socket_dir,
+                                 (st.st_mode & 0777), dir_perms));
+                       umask(old_umask);
                        goto out_umask;
                }
        }
@@ -1872,6 +1395,40 @@ const char *get_mydnsfullname(void)
        return (const char *)tmp.data;
 }
 
+/************************************************************
+ Is this my ip address ?
+************************************************************/
+
+static bool is_my_ipaddr(const char *ipaddr_str)
+{
+       struct sockaddr_storage ss;
+       struct iface_struct *nics;
+       int i, n;
+
+       if (!interpret_string_addr(&ss, ipaddr_str, AI_NUMERICHOST)) {
+               return false;
+       }
+
+       if (is_zero_addr(&ss)) {
+               return false;
+       }
+
+       if (ismyaddr((struct sockaddr *)&ss) ||
+                       is_loopback_addr((struct sockaddr *)&ss)) {
+               return true;
+       }
+
+       n = get_interfaces(talloc_tos(), &nics);
+       for (i=0; i<n; i++) {
+               if (sockaddr_equal((struct sockaddr *)&nics[i].ip, (struct sockaddr *)&ss)) {
+                       TALLOC_FREE(nics);
+                       return true;
+               }
+       }
+       TALLOC_FREE(nics);
+       return false;
+}
+
 /************************************************************
  Is this my name ?
 ************************************************************/
@@ -1879,7 +1436,6 @@ const char *get_mydnsfullname(void)
 bool is_myname_or_ipaddr(const char *s)
 {
        TALLOC_CTX *ctx = talloc_tos();
-       char addr[INET6_ADDRSTRLEN];
        char *name = NULL;
        const char *dnsname;
        char *servername = NULL;
@@ -1902,7 +1458,7 @@ bool is_myname_or_ipaddr(const char *s)
        }
 
        /* Optimize for the common case */
-       if (strequal(servername, global_myname())) {
+       if (strequal(servername, lp_netbios_name())) {
                return true;
        }
 
@@ -1927,48 +1483,166 @@ bool is_myname_or_ipaddr(const char *s)
                return true;
        }
 
-       /* Handle possible CNAME records - convert to an IP addr. */
-       if (!is_ipaddress(servername)) {
-               /* Use DNS to resolve the name, but only the first address */
-               struct sockaddr_storage ss;
-               if (interpret_string_addr(&ss, servername, 0)) {
-                       print_sockaddr(addr,
-                                       sizeof(addr),
-                                       &ss);
-                       servername = addr;
-               }
-       }
-
        /* Maybe its an IP address? */
        if (is_ipaddress(servername)) {
-               struct sockaddr_storage ss;
-               struct iface_struct *nics;
-               int i, n;
+               return is_my_ipaddr(servername);
+       }
 
-               if (!interpret_string_addr(&ss, servername, AI_NUMERICHOST)) {
-                       return false;
-               }
+       /* Handle possible CNAME records - convert to an IP addr. list. */
+       {
+               /* Use DNS to resolve the name, check all addresses. */
+               struct addrinfo *p = NULL;
+               struct addrinfo *res = NULL;
 
-               if (is_zero_addr((struct sockaddr *)&ss) || 
-                       is_loopback_addr((struct sockaddr *)&ss)) {
+               if (!interpret_string_addr_internal(&res,
+                               servername,
+                               AI_ADDRCONFIG)) {
                        return false;
                }
 
-               nics = TALLOC_ARRAY(ctx, struct iface_struct,
-                                       MAX_INTERFACES);
-               if (!nics) {
-                       return false;
-               }
-               n = get_interfaces(nics, MAX_INTERFACES);
-               for (i=0; i<n; i++) {
-                       if (sockaddr_equal((struct sockaddr *)&nics[i].ip, (struct sockaddr *)&ss)) {
-                               TALLOC_FREE(nics);
+               for (p = res; p; p = p->ai_next) {
+                       char addr[INET6_ADDRSTRLEN];
+                       struct sockaddr_storage ss;
+
+                       ZERO_STRUCT(ss);
+                       memcpy(&ss, p->ai_addr, p->ai_addrlen);
+                       print_sockaddr(addr,
+                                       sizeof(addr),
+                                       &ss);
+                       if (is_my_ipaddr(addr)) {
+                               freeaddrinfo(res);
                                return true;
                        }
                }
-               TALLOC_FREE(nics);
+               freeaddrinfo(res);
        }
 
        /* No match */
        return false;
 }
+
+struct getaddrinfo_state {
+       const char *node;
+       const char *service;
+       const struct addrinfo *hints;
+       struct addrinfo *res;
+       int ret;
+};
+
+static void getaddrinfo_do(void *private_data);
+static void getaddrinfo_done(struct tevent_req *subreq);
+
+struct tevent_req *getaddrinfo_send(TALLOC_CTX *mem_ctx,
+                                   struct tevent_context *ev,
+                                   struct fncall_context *ctx,
+                                   const char *node,
+                                   const char *service,
+                                   const struct addrinfo *hints)
+{
+       struct tevent_req *req, *subreq;
+       struct getaddrinfo_state *state;
+
+       req = tevent_req_create(mem_ctx, &state, struct getaddrinfo_state);
+       if (req == NULL) {
+               return NULL;
+       }
+
+       state->node = node;
+       state->service = service;
+       state->hints = hints;
+
+       subreq = fncall_send(state, ev, ctx, getaddrinfo_do, state);
+       if (tevent_req_nomem(subreq, req)) {
+               return tevent_req_post(req, ev);
+       }
+       tevent_req_set_callback(subreq, getaddrinfo_done, req);
+       return req;
+}
+
+static void getaddrinfo_do(void *private_data)
+{
+       struct getaddrinfo_state *state =
+               (struct getaddrinfo_state *)private_data;
+
+       state->ret = getaddrinfo(state->node, state->service, state->hints,
+                                &state->res);
+}
+
+static void getaddrinfo_done(struct tevent_req *subreq)
+{
+       struct tevent_req *req = tevent_req_callback_data(
+               subreq, struct tevent_req);
+       int ret, err;
+
+       ret = fncall_recv(subreq, &err);
+       TALLOC_FREE(subreq);
+       if (ret == -1) {
+               tevent_req_error(req, err);
+               return;
+       }
+       tevent_req_done(req);
+}
+
+int getaddrinfo_recv(struct tevent_req *req, struct addrinfo **res)
+{
+       struct getaddrinfo_state *state = tevent_req_data(
+               req, struct getaddrinfo_state);
+       int err;
+
+       if (tevent_req_is_unix_error(req, &err)) {
+               switch(err) {
+               case ENOMEM:
+                       return EAI_MEMORY;
+               default:
+                       return EAI_FAIL;
+               }
+       }
+       if (state->ret == 0) {
+               *res = state->res;
+       }
+       return state->ret;
+}
+
+int poll_one_fd(int fd, int events, int timeout, int *revents)
+{
+       struct pollfd *fds;
+       int ret;
+       int saved_errno;
+
+       fds = talloc_zero_array(talloc_tos(), struct pollfd, 2);
+       if (fds == NULL) {
+               errno = ENOMEM;
+               return -1;
+       }
+       fds[0].fd = fd;
+       fds[0].events = events;
+
+       ret = sys_poll(fds, 1, timeout);
+
+       /*
+        * Assign whatever poll did, even in the ret<=0 case.
+        */
+       *revents = fds[0].revents;
+       saved_errno = errno;
+       TALLOC_FREE(fds);
+       errno = saved_errno;
+
+       return ret;
+}
+
+int poll_intr_one_fd(int fd, int events, int timeout, int *revents)
+{
+       struct pollfd pfd;
+       int ret;
+
+       pfd.fd = fd;
+       pfd.events = events;
+
+       ret = sys_poll_intr(&pfd, 1, timeout);
+       if (ret <= 0) {
+               *revents = 0;
+               return ret;
+       }
+       *revents = pfd.revents;
+       return 1;
+}