5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce Socket utils
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce Copyright (C) Simo Sorce <ssorce@redhat.com> 2016
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce Copyright (C) Sumit Bose <sbose@redhat.com> 2009
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 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 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/>.
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorcestatic errno_t set_fcntl_flags(int fd, int fd_flags, int fl_flags)
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce "fcntl F_GETFD failed [%d][%s].\n", ret, strerror(ret));
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce "fcntl F_SETFD failed [%d][%s].\n", ret, strerror(ret));
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce "fcntl F_GETFD failed [%d][%s].\n", ret, strerror(ret));
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce "fcntl F_SETFD failed [%d][%s].\n", ret, strerror(ret));
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 "setsockopt SO_KEEPALIVE failed.[%d][%s].\n", ret,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &dummy, sizeof(dummy));
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce "setsockopt TCP_NODELAY failed.[%d][%s].\n", ret,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic void sssd_async_connect_done(struct tevent_context *ev,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestruct tevent_req *sssd_async_connect_send(TALLOC_CTX *mem_ctx,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create failed.\n");
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.
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_fd failed.\n");
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce "connect failed [%d][%s].\n", ret, strerror(ret));
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic void sssd_async_connect_done(struct tevent_context *ev,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce struct tevent_req *req = talloc_get_type(priv, struct tevent_req);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_data(req, struct sssd_async_connect_state);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce ret = connect(state->fd, (struct sockaddr *) &state->addr,
265c7b5e5333befdadd4ac8d09f4147f211959fdLukas Slebodnik if (ret == EALREADY || ret == EINPROGRESS || ret == EINTR) {
265c7b5e5333befdadd4ac8d09f4147f211959fdLukas Slebodnik return; /* Try again later */
e05d3f5872263aadfbc2f6a2a8c9735219922387Simo Sorce "connect failed [%d][%s].\n", ret, strerror(ret));
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorceint sssd_async_connect_recv(struct tevent_req *req)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic void sssd_async_connect_timeout(struct tevent_context *ev,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CONF_SETTINGS, "The connection timed out\n");
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce connection_request = talloc_get_type(pvt, struct tevent_req);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic int sssd_async_socket_state_destructor(void *data);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic void sssd_async_socket_init_done(struct tevent_req *subreq);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestruct tevent_req *sssd_async_socket_init_send(TALLOC_CTX *mem_ctx,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce req = tevent_req_create(mem_ctx, &state, struct sssd_async_socket_state);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create failed.\n");
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce state->sd = socket(addr->ss_family, SOCK_STREAM, 0);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce "socket failed [%d][%s].\n", ret, strerror(ret));
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce DEBUG(SSSDBG_CRIT_FAILURE, "set_fd_common_opts failed.\n");
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce ret = set_fcntl_flags(state->sd, FD_CLOEXEC, O_NONBLOCK);
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce DEBUG(SSSDBG_CRIT_FAILURE, "settting fd flags failed.\n");
75e66c388862a4ba05afe0791c5503226395bad0Simo Sorce "Using file descriptor [%d] for the connection.\n", state->sd);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce subreq = sssd_async_connect_send(state, ev, state->sd,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE, "sssd_async_connect_send failed.\n");
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce "Setting %d seconds timeout for connecting\n", timeout);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce state->connect_timeout = tevent_add_timer(ev, subreq, tv,
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_timer failed.\n");
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_set_callback(subreq, sssd_async_socket_init_done, req);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic void sssd_async_socket_init_done(struct tevent_req *subreq)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_callback_data(subreq, struct tevent_req);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_data(req, struct sssd_async_socket_state);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce /* kill the timeout handler now that we got a reply */
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce "sdap_async_sys_connect request failed: [%d]: %s.\n",
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorceint sssd_async_socket_init_recv(struct tevent_req *req, int *sd)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce tevent_req_data(req, struct sssd_async_socket_state);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce /* steal the sd and neutralize destructor actions */
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorcestatic int sssd_async_socket_state_destructor(void *data)
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce talloc_get_type(data, struct sssd_async_socket_state);
5dbf360f2d6b0281c32f1bba6ebf5cc834c1716eSimo Sorce DEBUG(SSSDBG_TRACE_FUNC, "closing socket [%d]\n", state->sd);