sss_sockets.c revision 5dbf360f2d6b0281c32f1bba6ebf5cc834c1716e
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce/*
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce SSSD
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce Socket utils
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce Copyright (C) Simo Sorce <ssorce@redhat.com> 2016
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce Copyright (C) Sumit Bose <sbose@redhat.com> 2009
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce This program is free software; you can redistribute it and/or modify
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce it under the terms of the GNU General Public License as published by
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce the Free Software Foundation; either version 3 of the License, or
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce (at your option) any later version.
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce This program is distributed in the hope that it will be useful,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce but WITHOUT ANY WARRANTY; without even the implied warranty of
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce GNU General Public License for more details.
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce You should have received a copy of the GNU General Public License
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce along with this program. If not, see <http://www.gnu.org/licenses/>.
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce*/
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#include "config.h"
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#include <stdlib.h>
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#include <unistd.h>
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#include <fcntl.h>
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#include <sys/socket.h>
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#include <netinet/in.h>
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#include <netinet/tcp.h>
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce#include "util/util.h"
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic errno_t set_fd_flags_and_opts(int fd)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce int ret;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce long flags;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce int dummy = 1;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce flags = fcntl(fd, F_GETFD, 0);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (flags == -1) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret = errno;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce "fcntl F_GETFD failed [%d][%s].\n", ret, strerror(ret));
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return ret;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce flags = fcntl(fd, F_SETFD, flags| FD_CLOEXEC);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (flags == -1) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret = errno;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce "fcntl F_SETFD failed [%d][%s].\n", ret, strerror(ret));
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return ret;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce /* SO_KEEPALIVE and TCP_NODELAY are set by OpenLDAP client libraries but
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce * failures are ignored.*/
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &dummy, sizeof(dummy));
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (ret != 0) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret = errno;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_FUNC_DATA,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce "setsockopt SO_KEEPALIVE failed.[%d][%s].\n", ret,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce strerror(ret));
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &dummy, sizeof(dummy));
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (ret != 0) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret = errno;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_FUNC_DATA,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce "setsockopt TCP_NODELAY failed.[%d][%s].\n", ret,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce strerror(ret));
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return EOK;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestruct sssd_async_connect_state {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce long old_flags;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct tevent_fd *fde;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce int fd;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce socklen_t addr_len;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct sockaddr_storage addr;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce};
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic void sssd_async_connect_done(struct tevent_context *ev,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct tevent_fd *fde, uint16_t flags,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce void *priv);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestruct tevent_req *sssd_async_connect_send(TALLOC_CTX *mem_ctx,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct tevent_context *ev,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce int fd,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce const struct sockaddr *addr,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce socklen_t addr_len)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct tevent_req *req;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct sssd_async_connect_state *state;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce long flags;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce int ret;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce int fret;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce flags = fcntl(fd, F_GETFL, 0);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (flags == -1) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE, "fcntl F_GETFL failed.\n");
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return NULL;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce req = tevent_req_create(mem_ctx, &state,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct sssd_async_connect_state);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (req == NULL) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create failed.\n");
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return NULL;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce state->old_flags = flags;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce state->fd = fd;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce state->addr_len = addr_len;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce memcpy(&state->addr, addr, addr_len);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (ret != EOK) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE, "fcntl F_SETFL failed.\n");
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce goto done;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret = connect(fd, addr, addr_len);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (ret == EOK) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce goto done;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret = errno;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce switch (ret) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce case EINPROGRESS:
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce case EINTR:
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce state->fde = tevent_add_fd(ev, state, fd,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce TEVENT_FD_READ | TEVENT_FD_WRITE,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce sssd_async_connect_done, req);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (state->fde == NULL) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_fd failed.\n");
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret = ENOMEM;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce goto done;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return req;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce break;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce default:
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce "connect failed [%d][%s].\n", ret, strerror(ret));
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcedone:
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce fret = fcntl(fd, F_SETFL, flags);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (fret != EOK) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE, "fcntl F_SETFL failed.\n");
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (ret == EOK) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_done(req);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce } else {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_error(req, ret);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_post(req, ev);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return req;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic void sssd_async_connect_done(struct tevent_context *ev,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct tevent_fd *fde, uint16_t flags,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce void *priv)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct tevent_req *req = talloc_get_type(priv, struct tevent_req);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct sssd_async_connect_state *state =
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_data(req, struct sssd_async_connect_state);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce int ret;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce int fret;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce errno = 0;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret = connect(state->fd, (struct sockaddr *) &state->addr,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce state->addr_len);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (ret != EOK) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret = errno;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (ret == EINPROGRESS || ret == EINTR) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return; /* Try again later */
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce "connect failed [%d][%s].\n", ret, strerror(ret));
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce talloc_zfree(fde);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce fret = fcntl(state->fd, F_SETFL, state->old_flags);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (fret != EOK) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE, "fcntl F_SETFL failed.\n");
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (ret == EOK) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_done(req);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce } else {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_error(req, ret);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorceint sssd_async_connect_recv(struct tevent_req *req)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce TEVENT_REQ_RETURN_ON_ERROR(req);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return EOK;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic void sssd_async_connect_timeout(struct tevent_context *ev,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct tevent_timer *te,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct timeval tv, void *pvt)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct tevent_req *connection_request;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CONF_SETTINGS, "The connection timed out\n");
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce connection_request = talloc_get_type(pvt, struct tevent_req);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_error(connection_request, ETIMEDOUT);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestruct sssd_async_socket_state {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct tevent_timer *connect_timeout;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce int sd;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce};
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic int sssd_async_socket_state_destructor(void *data);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic void sssd_async_socket_init_done(struct tevent_req *subreq);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestruct tevent_req *sssd_async_socket_init_send(TALLOC_CTX *mem_ctx,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct tevent_context *ev,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct sockaddr_storage *addr,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce socklen_t addr_len, int timeout)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct sssd_async_socket_state *state;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct tevent_req *req, *subreq;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct timeval tv;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce int ret;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce req = tevent_req_create(mem_ctx, &state, struct sssd_async_socket_state);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (req == NULL) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create failed.\n");
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return NULL;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce state->sd = -1;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce talloc_set_destructor((TALLOC_CTX *)state,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce sssd_async_socket_state_destructor);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce state->sd = socket(addr->ss_family, SOCK_STREAM, 0);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (state->sd == -1) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret = errno;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce "socket failed [%d][%s].\n", ret, strerror(ret));
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce goto fail;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret = set_fd_flags_and_opts(state->sd);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (ret != EOK) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE, "set_fd_flags_and_opts failed.\n");
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce goto fail;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_TRACE_ALL,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce "Using file descriptor [%d] for LDAP connection.\n", state->sd);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce subreq = sssd_async_connect_send(state, ev, state->sd,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce (struct sockaddr *) addr, addr_len);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (subreq == NULL) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret = ENOMEM;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE, "sssd_async_connect_send failed.\n");
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce goto fail;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_TRACE_FUNC,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce "Setting %d seconds timeout for connecting\n", timeout);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tv = tevent_timeval_current_ofs(timeout, 0);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce state->connect_timeout = tevent_add_timer(ev, subreq, tv,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce sssd_async_connect_timeout,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce subreq);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (state->connect_timeout == NULL) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_timer failed.\n");
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret = ENOMEM;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce goto fail;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_set_callback(subreq, sssd_async_socket_init_done, req);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return req;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcefail:
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_error(req, ret);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_post(req, ev);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return req;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic void sssd_async_socket_init_done(struct tevent_req *subreq)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct tevent_req *req =
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_callback_data(subreq, struct tevent_req);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct sssd_async_socket_state *state =
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_data(req, struct sssd_async_socket_state);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce int ret;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce /* kill the timeout handler now that we got a reply */
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce talloc_zfree(state->connect_timeout);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret = sssd_async_connect_recv(subreq);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce talloc_zfree(subreq);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (ret != EOK) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce "sdap_async_sys_connect request failed: [%d]: %s.\n",
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret, sss_strerror(ret));
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce goto fail;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_done(req);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcefail:
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_error(req, ret);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorceint sssd_async_socket_init_recv(struct tevent_req *req, int *sd)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct sssd_async_socket_state *state =
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_data(req, struct sssd_async_socket_state);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce TEVENT_REQ_RETURN_ON_ERROR(req);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce /* steal the sd and neutralize destructor actions */
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce *sd = state->sd;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce state->sd = -1;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return EOK;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic int sssd_async_socket_state_destructor(void *data)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct sssd_async_socket_state *state =
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce talloc_get_type(data, struct sssd_async_socket_state);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (state->sd != -1) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_TRACE_FUNC, "closing socket [%d]\n", state->sd);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce close(state->sd);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce state->sd = -1;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce return 0;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce}