|
Packit |
6c0a39 |
/*
|
|
Packit |
6c0a39 |
* connect.c - handles connections to ssh servers
|
|
Packit |
6c0a39 |
*
|
|
Packit |
6c0a39 |
* This file is part of the SSH Library
|
|
Packit |
6c0a39 |
*
|
|
Packit |
6c0a39 |
* Copyright (c) 2003-2013 by Aris Adamantiadis
|
|
Packit |
6c0a39 |
*
|
|
Packit |
6c0a39 |
* The SSH Library is free software; you can redistribute it and/or modify
|
|
Packit |
6c0a39 |
* it under the terms of the GNU Lesser General Public License as published by
|
|
Packit |
6c0a39 |
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
|
Packit |
6c0a39 |
* option) any later version.
|
|
Packit |
6c0a39 |
*
|
|
Packit |
6c0a39 |
* The SSH Library is distributed in the hope that it will be useful, but
|
|
Packit |
6c0a39 |
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
Packit |
6c0a39 |
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
|
Packit |
6c0a39 |
* License for more details.
|
|
Packit |
6c0a39 |
*
|
|
Packit |
6c0a39 |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit |
6c0a39 |
* along with the SSH Library; see the file COPYING. If not, write to
|
|
Packit |
6c0a39 |
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
|
Packit |
6c0a39 |
* MA 02111-1307, USA.
|
|
Packit |
6c0a39 |
*/
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
#include "config.h"
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
#include <errno.h>
|
|
Packit |
6c0a39 |
#include <fcntl.h>
|
|
Packit Service |
fcc0d2 |
#include <stdbool.h>
|
|
Packit |
6c0a39 |
#include <stdio.h>
|
|
Packit |
6c0a39 |
#include <stdlib.h>
|
|
Packit |
6c0a39 |
#include <string.h>
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
#include "libssh/libssh.h"
|
|
Packit |
6c0a39 |
#include "libssh/misc.h"
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
#ifdef _WIN32
|
|
Packit |
6c0a39 |
/*
|
|
Packit |
6c0a39 |
* Only use Windows API functions available on Windows 2000 SP4 or later.
|
|
Packit |
6c0a39 |
* The available constants are in <sdkddkver.h>.
|
|
Packit |
6c0a39 |
* http://msdn.microsoft.com/en-us/library/aa383745.aspx
|
|
Packit |
6c0a39 |
* http://blogs.msdn.com/oldnewthing/archive/2007/04/11/2079137.aspx
|
|
Packit |
6c0a39 |
*/
|
|
Packit |
6c0a39 |
#undef _WIN32_WINNT
|
|
Packit |
6c0a39 |
#ifdef HAVE_WSPIAPI_H
|
|
Packit |
6c0a39 |
#define _WIN32_WINNT 0x0500 /* _WIN32_WINNT_WIN2K */
|
|
Packit |
6c0a39 |
#undef NTDDI_VERSION
|
|
Packit |
6c0a39 |
#define NTDDI_VERSION 0x05000400 /* NTDDI_WIN2KSP4 */
|
|
Packit |
6c0a39 |
#else
|
|
Packit |
6c0a39 |
#define _WIN32_WINNT 0x0501 /* _WIN32_WINNT_WINXP */
|
|
Packit |
6c0a39 |
#undef NTDDI_VERSION
|
|
Packit |
6c0a39 |
#define NTDDI_VERSION 0x05010000 /* NTDDI_WINXP */
|
|
Packit |
6c0a39 |
#endif
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
#if _MSC_VER >= 1400
|
|
Packit |
6c0a39 |
#include <io.h>
|
|
Packit |
6c0a39 |
#undef close
|
|
Packit |
6c0a39 |
#define close _close
|
|
Packit |
6c0a39 |
#endif /* _MSC_VER */
|
|
Packit |
6c0a39 |
#include <winsock2.h>
|
|
Packit |
6c0a39 |
#include <ws2tcpip.h>
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
/* <wspiapi.h> is necessary for getaddrinfo before Windows XP, but it isn't
|
|
Packit |
6c0a39 |
* available on some platforms like MinGW. */
|
|
Packit |
6c0a39 |
#ifdef HAVE_WSPIAPI_H
|
|
Packit |
6c0a39 |
#include <wspiapi.h>
|
|
Packit |
6c0a39 |
#endif
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
#ifndef EINPROGRESS
|
|
Packit |
6c0a39 |
#define EINPROGRESS WSAEINPROGRESS
|
|
Packit |
6c0a39 |
#endif
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
#else /* _WIN32 */
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
#include <netdb.h>
|
|
Packit |
6c0a39 |
#include <sys/socket.h>
|
|
Packit |
6c0a39 |
#include <sys/select.h>
|
|
Packit |
6c0a39 |
#include <netinet/in.h>
|
|
Packit |
6c0a39 |
#include <netinet/tcp.h>
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
#endif /* _WIN32 */
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
#include "libssh/priv.h"
|
|
Packit |
6c0a39 |
#include "libssh/socket.h"
|
|
Packit |
6c0a39 |
#include "libssh/channels.h"
|
|
Packit |
6c0a39 |
#include "libssh/session.h"
|
|
Packit |
6c0a39 |
#include "libssh/poll.h"
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
#ifndef HAVE_GETADDRINFO
|
|
Packit |
6c0a39 |
#error "Your system must have getaddrinfo()"
|
|
Packit |
6c0a39 |
#endif
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
#ifdef _WIN32
|
|
Packit |
6c0a39 |
#ifndef gai_strerror
|
|
Packit |
6c0a39 |
char WSAAPI *gai_strerrorA(int code)
|
|
Packit |
6c0a39 |
{
|
|
Packit |
6c0a39 |
static char buf[256];
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
snprintf(buf, sizeof(buf), "Undetermined error code (%d)", code);
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
return buf;
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
#endif /* gai_strerror */
|
|
Packit |
6c0a39 |
#endif /* _WIN32 */
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
static int ssh_connect_socket_close(socket_t s)
|
|
Packit |
6c0a39 |
{
|
|
Packit |
6c0a39 |
#ifdef _WIN32
|
|
Packit |
6c0a39 |
return closesocket(s);
|
|
Packit |
6c0a39 |
#else
|
|
Packit |
6c0a39 |
return close(s);
|
|
Packit |
6c0a39 |
#endif
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
static int getai(const char *host, int port, struct addrinfo **ai)
|
|
Packit |
6c0a39 |
{
|
|
Packit |
6c0a39 |
const char *service = NULL;
|
|
Packit |
6c0a39 |
struct addrinfo hints;
|
|
Packit |
6c0a39 |
char s_port[10];
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
ZERO_STRUCT(hints);
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
hints.ai_protocol = IPPROTO_TCP;
|
|
Packit |
6c0a39 |
hints.ai_family = PF_UNSPEC;
|
|
Packit |
6c0a39 |
hints.ai_socktype = SOCK_STREAM;
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
if (port == 0) {
|
|
Packit |
6c0a39 |
hints.ai_flags = AI_PASSIVE;
|
|
Packit |
6c0a39 |
} else {
|
|
Packit |
6c0a39 |
snprintf(s_port, sizeof(s_port), "%hu", (unsigned short)port);
|
|
Packit |
6c0a39 |
service = s_port;
|
|
Packit |
6c0a39 |
#ifdef AI_NUMERICSERV
|
|
Packit |
6c0a39 |
hints.ai_flags = AI_NUMERICSERV;
|
|
Packit |
6c0a39 |
#endif
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
if (ssh_is_ipaddr(host)) {
|
|
Packit |
6c0a39 |
/* this is an IP address */
|
|
Packit |
6c0a39 |
SSH_LOG(SSH_LOG_PACKET, "host %s matches an IP address", host);
|
|
Packit |
6c0a39 |
hints.ai_flags |= AI_NUMERICHOST;
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
return getaddrinfo(host, service, &hints, ai);
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
static int set_tcp_nodelay(socket_t socket)
|
|
Packit |
6c0a39 |
{
|
|
Packit |
6c0a39 |
int opt = 1;
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
return setsockopt(socket,
|
|
Packit |
6c0a39 |
IPPROTO_TCP,
|
|
Packit |
6c0a39 |
TCP_NODELAY,
|
|
Packit |
6c0a39 |
(void *)&opt,
|
|
Packit |
6c0a39 |
sizeof(opt));
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
/**
|
|
Packit |
6c0a39 |
* @internal
|
|
Packit |
6c0a39 |
*
|
|
Packit |
6c0a39 |
* @brief Launches a nonblocking connect to an IPv4 or IPv6 host
|
|
Packit |
6c0a39 |
* specified by its IP address or hostname.
|
|
Packit |
6c0a39 |
*
|
|
Packit |
6c0a39 |
* @returns A file descriptor, < 0 on error.
|
|
Packit |
6c0a39 |
* @warning very ugly !!!
|
|
Packit |
6c0a39 |
*/
|
|
Packit |
6c0a39 |
socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
|
Packit |
6c0a39 |
const char *bind_addr, int port)
|
|
Packit |
6c0a39 |
{
|
|
Packit |
6c0a39 |
socket_t s = -1;
|
|
Packit |
6c0a39 |
int rc;
|
|
Packit |
6c0a39 |
struct addrinfo *ai = NULL;
|
|
Packit |
6c0a39 |
struct addrinfo *itr = NULL;
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
rc = getai(host, port, &ai;;
|
|
Packit |
6c0a39 |
if (rc != 0) {
|
|
Packit |
6c0a39 |
ssh_set_error(session, SSH_FATAL,
|
|
Packit |
6c0a39 |
"Failed to resolve hostname %s (%s)",
|
|
Packit |
6c0a39 |
host, gai_strerror(rc));
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
return -1;
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
for (itr = ai; itr != NULL; itr = itr->ai_next) {
|
|
Packit |
6c0a39 |
/* create socket */
|
|
Packit |
6c0a39 |
s = socket(itr->ai_family, itr->ai_socktype, itr->ai_protocol);
|
|
Packit |
6c0a39 |
if (s < 0) {
|
|
Packit |
6c0a39 |
ssh_set_error(session, SSH_FATAL,
|
|
Packit |
6c0a39 |
"Socket create failed: %s", strerror(errno));
|
|
Packit |
6c0a39 |
continue;
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
if (bind_addr) {
|
|
Packit |
6c0a39 |
struct addrinfo *bind_ai;
|
|
Packit |
6c0a39 |
struct addrinfo *bind_itr;
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
SSH_LOG(SSH_LOG_PACKET, "Resolving %s", bind_addr);
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
rc = getai(bind_addr, 0, &bind_ai);
|
|
Packit |
6c0a39 |
if (rc != 0) {
|
|
Packit |
6c0a39 |
ssh_set_error(session, SSH_FATAL,
|
|
Packit |
6c0a39 |
"Failed to resolve bind address %s (%s)",
|
|
Packit |
6c0a39 |
bind_addr,
|
|
Packit |
6c0a39 |
gai_strerror(rc));
|
|
Packit |
6c0a39 |
ssh_connect_socket_close(s);
|
|
Packit |
6c0a39 |
s = -1;
|
|
Packit |
6c0a39 |
break;
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
for (bind_itr = bind_ai;
|
|
Packit |
6c0a39 |
bind_itr != NULL;
|
|
Packit |
6c0a39 |
bind_itr = bind_itr->ai_next)
|
|
Packit |
6c0a39 |
{
|
|
Packit |
6c0a39 |
if (bind(s, bind_itr->ai_addr, bind_itr->ai_addrlen) < 0) {
|
|
Packit |
6c0a39 |
ssh_set_error(session, SSH_FATAL,
|
|
Packit |
6c0a39 |
"Binding local address: %s", strerror(errno));
|
|
Packit |
6c0a39 |
continue;
|
|
Packit |
6c0a39 |
} else {
|
|
Packit |
6c0a39 |
break;
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
freeaddrinfo(bind_ai);
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
/* Cannot bind to any local addresses */
|
|
Packit |
6c0a39 |
if (bind_itr == NULL) {
|
|
Packit |
6c0a39 |
ssh_connect_socket_close(s);
|
|
Packit |
6c0a39 |
s = -1;
|
|
Packit |
6c0a39 |
continue;
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
rc = ssh_socket_set_nonblocking(s);
|
|
Packit |
6c0a39 |
if (rc < 0) {
|
|
Packit |
6c0a39 |
ssh_set_error(session, SSH_FATAL,
|
|
Packit |
6c0a39 |
"Failed to set socket non-blocking for %s:%d",
|
|
Packit |
6c0a39 |
host, port);
|
|
Packit |
6c0a39 |
ssh_connect_socket_close(s);
|
|
Packit |
6c0a39 |
s = -1;
|
|
Packit |
6c0a39 |
continue;
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
if (session->opts.nodelay) {
|
|
Packit |
6c0a39 |
/* For winsock, socket options are only effective before connect */
|
|
Packit |
6c0a39 |
rc = set_tcp_nodelay(s);
|
|
Packit |
6c0a39 |
if (rc < 0) {
|
|
Packit |
6c0a39 |
ssh_set_error(session, SSH_FATAL,
|
|
Packit |
6c0a39 |
"Failed to set TCP_NODELAY on socket: %s",
|
|
Packit |
6c0a39 |
strerror(errno));
|
|
Packit |
6c0a39 |
ssh_connect_socket_close(s);
|
|
Packit |
6c0a39 |
s = -1;
|
|
Packit |
6c0a39 |
continue;
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
errno = 0;
|
|
Packit |
6c0a39 |
rc = connect(s, itr->ai_addr, itr->ai_addrlen);
|
|
Packit |
6c0a39 |
if (rc == -1 && (errno != 0) && (errno != EINPROGRESS)) {
|
|
Packit |
6c0a39 |
ssh_set_error(session, SSH_FATAL,
|
|
Packit |
6c0a39 |
"Failed to connect: %s", strerror(errno));
|
|
Packit |
6c0a39 |
ssh_connect_socket_close(s);
|
|
Packit |
6c0a39 |
s = -1;
|
|
Packit |
6c0a39 |
continue;
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
break;
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
freeaddrinfo(ai);
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
return s;
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
/**
|
|
Packit |
6c0a39 |
* @addtogroup libssh_session
|
|
Packit |
6c0a39 |
*
|
|
Packit |
6c0a39 |
* @{
|
|
Packit |
6c0a39 |
*/
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
static int ssh_select_cb (socket_t fd, int revents, void *userdata)
|
|
Packit |
6c0a39 |
{
|
|
Packit |
6c0a39 |
fd_set *set = (fd_set *)userdata;
|
|
Packit |
6c0a39 |
if (revents & POLLIN) {
|
|
Packit |
6c0a39 |
FD_SET(fd, set);
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
return 0;
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
/**
|
|
Packit |
6c0a39 |
* @brief A wrapper for the select syscall
|
|
Packit |
6c0a39 |
*
|
|
Packit |
6c0a39 |
* This functions acts more or less like the select(2) syscall.\n
|
|
Packit |
6c0a39 |
* There is no support for writing or exceptions.\n
|
|
Packit |
6c0a39 |
*
|
|
Packit |
6c0a39 |
* @param[in] channels Arrays of channels pointers terminated by a NULL.
|
|
Packit |
6c0a39 |
* It is never rewritten.
|
|
Packit |
6c0a39 |
*
|
|
Packit |
6c0a39 |
* @param[out] outchannels Arrays of same size that "channels", there is no need
|
|
Packit |
6c0a39 |
* to initialize it.
|
|
Packit |
6c0a39 |
*
|
|
Packit |
6c0a39 |
* @param[in] maxfd Maximum +1 file descriptor from readfds.
|
|
Packit |
6c0a39 |
*
|
|
Packit |
6c0a39 |
* @param[in] readfds A fd_set of file descriptors to be select'ed for
|
|
Packit |
6c0a39 |
* reading.
|
|
Packit |
6c0a39 |
*
|
|
Packit |
6c0a39 |
* @param[in] timeout The timeout in milliseconds.
|
|
Packit |
6c0a39 |
*
|
|
Packit |
6c0a39 |
* @return SSH_OK on success,
|
|
Packit |
6c0a39 |
* SSH_ERROR on error,
|
|
Packit |
6c0a39 |
* SSH_EINTR if it was interrupted. In that case,
|
|
Packit |
6c0a39 |
* just restart it.
|
|
Packit |
6c0a39 |
*
|
|
Packit |
6c0a39 |
* @warning libssh is not reentrant here. That means that if a signal is caught
|
|
Packit |
6c0a39 |
* during the processing of this function, you cannot call libssh
|
|
Packit |
6c0a39 |
* functions on sessions that are busy with ssh_select().
|
|
Packit |
6c0a39 |
*
|
|
Packit |
6c0a39 |
* @see select(2)
|
|
Packit |
6c0a39 |
*/
|
|
Packit |
6c0a39 |
int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
|
|
Packit |
6c0a39 |
fd_set *readfds, struct timeval *timeout)
|
|
Packit |
6c0a39 |
{
|
|
Packit |
6c0a39 |
fd_set origfds;
|
|
Packit |
6c0a39 |
socket_t fd;
|
|
Packit |
6c0a39 |
size_t i, j;
|
|
Packit |
6c0a39 |
int rc;
|
|
Packit |
6c0a39 |
int base_tm, tm;
|
|
Packit |
6c0a39 |
struct ssh_timestamp ts;
|
|
Packit |
6c0a39 |
ssh_event event = ssh_event_new();
|
|
Packit |
6c0a39 |
int firstround = 1;
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
base_tm = tm = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000);
|
|
Packit |
6c0a39 |
for (i = 0 ; channels[i] != NULL; ++i) {
|
|
Packit |
6c0a39 |
ssh_event_add_session(event, channels[i]->session);
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
ZERO_STRUCT(origfds);
|
|
Packit |
6c0a39 |
FD_ZERO(&origfds);
|
|
Packit |
6c0a39 |
for (fd = 0; fd < maxfd ; fd++) {
|
|
Packit |
6c0a39 |
if (FD_ISSET(fd, readfds)) {
|
|
Packit |
6c0a39 |
ssh_event_add_fd(event, fd, POLLIN, ssh_select_cb, readfds);
|
|
Packit |
6c0a39 |
FD_SET(fd, &origfds);
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
outchannels[0] = NULL;
|
|
Packit |
6c0a39 |
FD_ZERO(readfds);
|
|
Packit |
6c0a39 |
ssh_timestamp_init(&ts);
|
|
Packit |
6c0a39 |
do {
|
|
Packit |
6c0a39 |
/* Poll every channel */
|
|
Packit |
6c0a39 |
j = 0;
|
|
Packit |
6c0a39 |
for (i = 0; channels[i]; i++) {
|
|
Packit |
6c0a39 |
rc = ssh_channel_poll(channels[i], 0);
|
|
Packit |
6c0a39 |
if (rc != 0) {
|
|
Packit |
6c0a39 |
outchannels[j] = channels[i];
|
|
Packit |
6c0a39 |
j++;
|
|
Packit |
6c0a39 |
} else {
|
|
Packit |
6c0a39 |
rc = ssh_channel_poll(channels[i], 1);
|
|
Packit |
6c0a39 |
if (rc != 0) {
|
|
Packit |
6c0a39 |
outchannels[j] = channels[i];
|
|
Packit |
6c0a39 |
j++;
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
outchannels[j] = NULL;
|
|
Packit |
6c0a39 |
if (j != 0) {
|
|
Packit |
6c0a39 |
break;
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
/* watch if a user socket was triggered */
|
|
Packit |
6c0a39 |
for (fd = 0; fd < maxfd; fd++) {
|
|
Packit |
6c0a39 |
if (FD_ISSET(fd, readfds)) {
|
|
Packit |
6c0a39 |
goto out;
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
/* If the timeout is elapsed, we should go out */
|
|
Packit |
6c0a39 |
if (!firstround && ssh_timeout_elapsed(&ts, base_tm)) {
|
|
Packit |
6c0a39 |
goto out;
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
/* since there's nothing, let's fire the polling */
|
|
Packit |
6c0a39 |
rc = ssh_event_dopoll(event,tm);
|
|
Packit |
6c0a39 |
if (rc == SSH_ERROR) {
|
|
Packit |
6c0a39 |
goto out;
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
tm = ssh_timeout_update(&ts, base_tm);
|
|
Packit |
6c0a39 |
firstround = 0;
|
|
Packit |
6c0a39 |
} while (1);
|
|
Packit |
6c0a39 |
out:
|
|
Packit |
6c0a39 |
for (fd = 0; fd < maxfd; fd++) {
|
|
Packit |
6c0a39 |
if (FD_ISSET(fd, &origfds)) {
|
|
Packit |
6c0a39 |
ssh_event_remove_fd(event, fd);
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
ssh_event_free(event);
|
|
Packit |
6c0a39 |
return SSH_OK;
|
|
Packit |
6c0a39 |
}
|
|
Packit |
6c0a39 |
|
|
Packit |
6c0a39 |
/** @} */
|