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
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorcestatic errno_t set_fcntl_flags(int fd, int fd_flags, int fl_flags)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce{
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce int ret;
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce int cur_flags;
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce ret = fcntl(fd, F_GETFD, 0);
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce if (ret == -1) {
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce ret = errno;
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce DEBUG(SSSDBG_CRIT_FAILURE,
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce "fcntl F_GETFD failed [%d][%s].\n", ret, strerror(ret));
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce return ret;
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce }
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce cur_flags = ret;
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce ret = fcntl(fd, F_SETFD, cur_flags | fd_flags);
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce if (ret == -1) {
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce ret = errno;
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce DEBUG(SSSDBG_CRIT_FAILURE,
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce "fcntl F_SETFD failed [%d][%s].\n", ret, strerror(ret));
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce return ret;
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce ret = fcntl(fd, F_GETFL, 0);
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce if (ret == -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 }
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce cur_flags = ret;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce ret = fcntl(fd, F_SETFL, cur_flags | fl_flags);
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce if (ret == -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
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce return EOK;
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce}
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorcestatic errno_t set_fd_common_opts(int fd)
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce{
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce int dummy = 1;
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce int ret;
75e66c388862a4ba05afe0791c5503226395bad0Simo 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 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 int ret;
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->fd = fd;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce state->addr_len = addr_len;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce memcpy(&state->addr, addr, addr_len);
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:
bdadcaf271818e88e56e86c2bd90663a08fd9721Lukas Slebodnik
bdadcaf271818e88e56e86c2bd90663a08fd9721Lukas Slebodnik /* Despite the connect() man page says waiting on a non-blocking
bdadcaf271818e88e56e86c2bd90663a08fd9721Lukas Slebodnik * connect should be done by checking for writability, we need to check
bdadcaf271818e88e56e86c2bd90663a08fd9721Lukas Slebodnik * also for readability.
bdadcaf271818e88e56e86c2bd90663a08fd9721Lukas Slebodnik * With TEVENT_FD_READ, connect fails much faster in offline mode with
bdadcaf271818e88e56e86c2bd90663a08fd9721Lukas Slebodnik * errno 113/No route to host.
bdadcaf271818e88e56e86c2bd90663a08fd9721Lukas Slebodnik */
bdadcaf271818e88e56e86c2bd90663a08fd9721Lukas Slebodnik state->fde = tevent_add_fd(ev, state, fd,
bdadcaf271818e88e56e86c2bd90663a08fd9721Lukas Slebodnik 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 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 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
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce errno = 0;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret = connect(state->fd, (struct sockaddr *) &state->addr,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce state->addr_len);
265c7b5e5333befdadd4ac8d09f4147f211959fdLukas Slebodnik if (ret == -1) {
265c7b5e5333befdadd4ac8d09f4147f211959fdLukas Slebodnik ret = errno;
265c7b5e5333befdadd4ac8d09f4147f211959fdLukas Slebodnik if (ret == EALREADY || ret == EINPROGRESS || ret == EINTR) {
265c7b5e5333befdadd4ac8d09f4147f211959fdLukas Slebodnik return; /* Try again later */
265c7b5e5333befdadd4ac8d09f4147f211959fdLukas Slebodnik }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce talloc_zfree(fde);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (ret == EOK) {
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_done(req);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce } else {
3108e0cce47ee168b86ac0de1deccee7e7f09119Lukas Slebodnik ret = errno;
e05d3f5872263aadfbc2f6a2a8c9735219922387Simo Sorce DEBUG(SSSDBG_CRIT_FAILURE,
e05d3f5872263aadfbc2f6a2a8c9735219922387Simo Sorce "connect failed [%d][%s].\n", ret, strerror(ret));
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_error(req, ret);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
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
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce ret = set_fd_common_opts(state->sd);
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce if (ret != EOK) {
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce DEBUG(SSSDBG_CRIT_FAILURE, "set_fd_common_opts failed.\n");
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce goto fail;
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce }
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce ret = set_fcntl_flags(state->sd, FD_CLOEXEC, O_NONBLOCK);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce if (ret != EOK) {
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce DEBUG(SSSDBG_CRIT_FAILURE, "settting fd flags failed.\n");
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce goto fail;
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce }
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_TRACE_ALL,
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce "Using file descriptor [%d] for the 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}