s3: Adding TCP_KEEPALIVE_THRESHOLD and TCP_KEEPALIVE_ABORT_THRESHOLD to the list...
[mat/samba.git] / source3 / lib / util_sock.c
index c46aa2ac49b75c7b43f5fd66416473a894b2853f..6782249bf6e5ad554fe7c22b55b07efca6e56048 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;
-}
+#include "memcache.h"
+#include "../lib/async_req/async_sock.h"
+#include "../lib/util/select.h"
 
 /****************************************************************************
  Get a port number in host byte order from a sockaddr_storage.
@@ -208,13 +144,11 @@ static const char *get_socket_addr(int fd, char *addr_buf, size_t addr_len)
        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)
+int get_socket_port(int fd)
 {
        struct sockaddr_storage sa;
        socklen_t length = sizeof(sa);
@@ -224,8 +158,9 @@ static int get_socket_port(int fd)
        }
 
        if (getsockname(fd, (struct sockaddr *)&sa, &length) < 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 -1;
        }
 
@@ -239,7 +174,6 @@ static int get_socket_port(int fd)
        }
        return -1;
 }
-#endif
 
 const char *client_name(int fd)
 {
@@ -351,6 +285,15 @@ static const smb_socket_option socket_options[] = {
 #endif
 #ifdef TCP_FASTACK
   {"TCP_FASTACK", IPPROTO_TCP, TCP_FASTACK, 0, OPT_INT},
+#endif
+#ifdef TCP_QUICKACK
+  {"TCP_QUICKACK", IPPROTO_TCP, TCP_QUICKACK, 0, OPT_BOOL},
+#endif
+#ifdef TCP_KEEPALIVE_THRESHOLD
+  {"TCP_KEEPALIVE_THRESHOLD", IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD, 0, OPT_INT},
+#endif
+#ifdef TCP_KEEPALIVE_ABORT_THRESHOLD
+  {"TCP_KEEPALIVE_ABORT_THRESHOLD", IPPROTO_TCP, TCP_KEEPALIVE_ABORT_THRESHOLD, 0, OPT_INT},
 #endif
   {NULL,0,0,0,0}};
 
@@ -490,13 +433,15 @@ 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)
@@ -506,7 +451,6 @@ NTSTATUS read_socket_with_timeout(int fd, char *buf,
        ssize_t readret;
        size_t nread = 0;
        struct timeval timeout;
-       char addr[INET6_ADDRSTRLEN];
 
        /* just checking .... */
        if (maxcnt <= 0)
@@ -522,24 +466,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;
@@ -565,25 +497,12 @@ NTSTATUS read_socket_with_timeout(int fd, char *buf,
 
                /* 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) ));
-                       }
                        return map_nt_error_from_unix(errno);
                }
 
                /* Did we timeout ? */
                if (selrtn == 0) {
-                       DEBUG(10,("read_socket_with_timeout: timeout read. "
+                       DEBUG(10,("read_fd_with_timeout: timeout read. "
                                "select timed out.\n"));
                        return NT_STATUS_IO_TIMEOUT;
                }
@@ -592,25 +511,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 +532,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)
@@ -683,7 +593,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 +615,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 = CONST_DISCARD(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);
 }
 
 /****************************************************************************
@@ -765,7 +657,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;
@@ -783,36 +675,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 +693,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 +709,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;
                }
 
@@ -953,7 +818,7 @@ struct open_socket_out_state {
        int wait_nsec;
 };
 
-static void open_socket_out_connected(struct async_req *subreq);
+static void open_socket_out_connected(struct tevent_req *subreq);
 
 static int open_socket_out_state_destructor(struct open_socket_out_state *s)
 {
@@ -967,19 +832,20 @@ static int open_socket_out_state_destructor(struct open_socket_out_state *s)
  Create an outgoing socket. timeout is in milliseconds.
 **************************************************************************/
 
-struct async_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
-                                      struct event_context *ev,
-                                      const struct sockaddr_storage *pss,
-                                      uint16_t port,
-                                      int timeout)
+struct tevent_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
+                                       struct event_context *ev,
+                                       const struct sockaddr_storage *pss,
+                                       uint16_t port,
+                                       int timeout)
 {
        char addr[INET6_ADDRSTRLEN];
-       struct async_req *result, *subreq;
+       struct tevent_req *result, *subreq;
        struct open_socket_out_state *state;
        NTSTATUS status;
 
-       if (!async_req_setup(mem_ctx, &result, &state,
-                            struct open_socket_out_state)) {
+       result = tevent_req_create(mem_ctx, &state,
+                                  struct open_socket_out_state);
+       if (result == NULL) {
                return NULL;
        }
        state->ev = ev;
@@ -995,7 +861,8 @@ struct async_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
        }
        talloc_set_destructor(state, open_socket_out_state_destructor);
 
-       if (!async_req_set_timeout(result, ev, timeval_set(0, timeout*1000))) {
+       if (!tevent_req_set_endtime(
+                   result, ev, timeval_current_ofs(0, timeout*1000))) {
                goto fail;
        }
 
@@ -1019,6 +886,10 @@ struct async_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));
 
@@ -1026,38 +897,35 @@ struct async_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
                                    (struct sockaddr *)&state->ss,
                                    state->salen);
        if ((subreq == NULL)
-           || !async_req_set_timeout(subreq, state->ev,
-                                     timeval_set(0, state->wait_nsec))) {
-               status = NT_STATUS_NO_MEMORY;
-               goto post_status;
+           || !tevent_req_set_endtime(
+                   subreq, state->ev,
+                   timeval_current_ofs(0, state->wait_nsec))) {
+               goto fail;
        }
-       subreq->async.fn = open_socket_out_connected;
-       subreq->async.priv = result;
+       tevent_req_set_callback(subreq, open_socket_out_connected, result);
        return result;
 
  post_status:
-       if (!async_post_ntstatus(result, ev, status)) {
-               goto fail;
-       }
-       return result;
+       tevent_req_nterror(result, status);
+       return tevent_req_post(result, ev);
  fail:
        TALLOC_FREE(result);
        return NULL;
 }
 
-static void open_socket_out_connected(struct async_req *subreq)
+static void open_socket_out_connected(struct tevent_req *subreq)
 {
-       struct async_req *req = talloc_get_type_abort(
-               subreq->async.priv, struct async_req);
-       struct open_socket_out_state *state = talloc_get_type_abort(
-               req->private_data, struct open_socket_out_state);
-       int err;
+       struct tevent_req *req =
+               tevent_req_callback_data(subreq, struct tevent_req);
+       struct open_socket_out_state *state =
+               tevent_req_data(req, struct open_socket_out_state);
+       int ret;
        int sys_errno;
 
-       err = async_connect_recv(subreq, &sys_errno);
+       ret = async_connect_recv(subreq, &sys_errno);
        TALLOC_FREE(subreq);
-       if (err == 0) {
-               async_req_done(req);
+       if (ret == 0) {
+               tevent_req_done(req);
                return;
        }
 
@@ -1080,38 +948,38 @@ static void open_socket_out_connected(struct async_req *subreq)
                subreq = async_connect_send(state, state->ev, state->fd,
                                            (struct sockaddr *)&state->ss,
                                            state->salen);
-               if (async_req_nomem(subreq, req)) {
+               if (tevent_req_nomem(subreq, req)) {
                        return;
                }
-               if (!async_req_set_timeout(subreq, state->ev,
-                                          timeval_set(0, state->wait_nsec))) {
-                       async_req_error(req, ENOMEM);
+               if (!tevent_req_set_endtime(
+                           subreq, state->ev,
+                           timeval_current_ofs(0, state->wait_nsec))) {
+                       tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
                        return;
                }
-               subreq->async.fn = open_socket_out_connected;
-               subreq->async.priv = req;
+               tevent_req_set_callback(subreq, open_socket_out_connected, req);
                return;
        }
 
 #ifdef EISCONN
        if (sys_errno == EISCONN) {
-               async_req_done(req);
+               tevent_req_done(req);
                return;
        }
 #endif
 
        /* real error */
-       async_req_error(req, sys_errno);
+       tevent_req_nterror(req, map_nt_error_from_unix(sys_errno));
 }
 
-NTSTATUS open_socket_out_recv(struct async_req *req, int *pfd)
+NTSTATUS open_socket_out_recv(struct tevent_req *req, int *pfd)
 {
-       struct open_socket_out_state *state = talloc_get_type_abort(
-               req->private_data, struct open_socket_out_state);
-       int err;
+       struct open_socket_out_state *state =
+               tevent_req_data(req, struct open_socket_out_state);
+       NTSTATUS status;
 
-       if (async_req_is_errno(req, &err)) {
-               return map_nt_error_from_unix(err);
+       if (tevent_req_is_nterror(req, &status)) {
+               return status;
        }
        *pfd = state->fd;
        state->fd = -1;
@@ -1123,7 +991,7 @@ NTSTATUS open_socket_out(const struct sockaddr_storage *pss, uint16_t port,
 {
        TALLOC_CTX *frame = talloc_stackframe();
        struct event_context *ev;
-       struct async_req *req;
+       struct tevent_req *req;
        NTSTATUS status = NT_STATUS_NO_MEMORY;
 
        ev = event_context_init(frame);
@@ -1135,10 +1003,10 @@ NTSTATUS open_socket_out(const struct sockaddr_storage *pss, uint16_t port,
        if (req == NULL) {
                goto fail;
        }
-       while (req->state < ASYNC_REQ_DONE) {
-               event_loop_once(ev);
+       if (!tevent_req_poll(req, ev)) {
+               status = NT_STATUS_INTERNAL_ERROR;
+               goto fail;
        }
-
        status = open_socket_out_recv(req, pfd);
  fail:
        TALLOC_FREE(frame);
@@ -1153,22 +1021,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_connected(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;
@@ -1176,73 +1044,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 *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;
        }
 
        subreq = open_socket_out_send(state, state->ev, &state->ss,
                                      state->port, state->timeout);
-       if (async_req_nomem(subreq, req)) {
+       if (tevent_req_nomem(subreq, req)) {
                return;
        }
-       subreq->async.fn = open_socket_out_defer_connected;
-       subreq->async.priv = req;
+       tevent_req_set_callback(subreq, open_socket_out_defer_connected, req);
 }
 
-static void open_socket_out_defer_connected(struct async_req *subreq)
+static void open_socket_out_defer_connected(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 *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;
@@ -1421,24 +1282,39 @@ bool open_any_socket_out(struct sockaddr_storage *addrs, int num_addrs,
 
 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;
        }
@@ -1472,8 +1348,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;
        }
 
@@ -1950,17 +1827,16 @@ bool is_myname_or_ipaddr(const char *s)
                        return false;
                }
 
+               if (ismyaddr((struct sockaddr *)&ss)) {
+                       return true;
+               }
+
                if (is_zero_addr((struct sockaddr *)&ss) || 
                        is_loopback_addr((struct sockaddr *)&ss)) {
                        return false;
                }
 
-               nics = TALLOC_ARRAY(ctx, struct iface_struct,
-                                       MAX_INTERFACES);
-               if (!nics) {
-                       return false;
-               }
-               n = get_interfaces(nics, MAX_INTERFACES);
+               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);
@@ -1973,3 +1849,85 @@ bool is_myname_or_ipaddr(const char *s)
        /* 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;
+}