2
* connect.c - handles connections to ssh servers
4
* This file is part of the SSH Library
6
* Copyright (c) 2003-2009 by Aris Adamantiadis
8
* The SSH Library is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU Lesser General Public License as published by
10
* the Free Software Foundation; either version 2.1 of the License, or (at your
11
* option) any later version.
13
* The SSH Library is distributed in the hope that it will be useful, but
14
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16
* License for more details.
18
* You should have received a copy of the GNU Lesser General Public License
19
* along with the SSH Library; see the file COPYING. If not, write to
20
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
32
#include "libssh/libssh.h"
33
#include "libssh/misc.h"
37
* Only use Windows API functions available on Windows 2000 SP4 or later.
38
* The available constants are in <sdkddkver.h>.
39
* http://msdn.microsoft.com/en-us/library/aa383745.aspx
40
* http://blogs.msdn.com/oldnewthing/archive/2007/04/11/2079137.aspx
44
#define _WIN32_WINNT 0x0500 /* _WIN32_WINNT_WIN2K */
46
#define NTDDI_VERSION 0x05000400 /* NTDDI_WIN2KSP4 */
48
#define _WIN32_WINNT 0x0501 /* _WIN32_WINNT_WINXP */
50
#define NTDDI_VERSION 0x05010000 /* NTDDI_WINXP */
61
/* <wspiapi.h> is necessary for getaddrinfo before Windows XP, but it isn't
62
* available on some platforms like MinGW. */
70
#include <sys/socket.h>
71
#include <sys/select.h>
72
#include <netinet/in.h>
76
#include "libssh/priv.h"
77
#include "libssh/socket.h"
78
#include "libssh/channels.h"
79
#include "libssh/session.h"
80
#include "libssh/poll.h"
82
#ifndef HAVE_GETADDRINFO
83
#error "Your system must have getaddrinfo()"
87
void ssh_sock_set_nonblocking(socket_t sock) {
88
u_long nonblocking = 1;
89
ioctlsocket(sock, FIONBIO, &nonblocking);
92
void ssh_sock_set_blocking(socket_t sock) {
93
u_long nonblocking = 0;
94
ioctlsocket(sock, FIONBIO, &nonblocking);
98
char WSAAPI *gai_strerrorA(int code) {
101
snprintf(buf, sizeof(buf), "Undetermined error code (%d)", code);
105
#endif /* gai_strerror */
108
void ssh_sock_set_nonblocking(socket_t sock) {
109
fcntl(sock, F_SETFL, O_NONBLOCK);
112
void ssh_sock_set_blocking(socket_t sock) {
113
fcntl(sock, F_SETFL, 0);
118
static int ssh_connect_socket_close(socket_t s){
120
return closesocket(s);
127
static int getai(ssh_session session, const char *host, int port, struct addrinfo **ai) {
128
const char *service = NULL;
129
struct addrinfo hints;
134
hints.ai_protocol = IPPROTO_TCP;
135
hints.ai_family = PF_UNSPEC;
136
hints.ai_socktype = SOCK_STREAM;
139
hints.ai_flags = AI_PASSIVE;
141
snprintf(s_port, sizeof(s_port), "%hu", (unsigned short)port);
143
#ifdef AI_NUMERICSERV
144
hints.ai_flags=AI_NUMERICSERV;
148
if (ssh_is_ipaddr(host)) {
149
/* this is an IP address */
150
ssh_log(session,SSH_LOG_PACKET,"host %s matches an IP address",host);
151
hints.ai_flags |= AI_NUMERICHOST;
154
return getaddrinfo(host, service, &hints, ai);
157
static int ssh_connect_ai_timeout(ssh_session session, const char *host,
158
int port, struct addrinfo *ai, long timeout, long usec, socket_t s) {
162
unsigned int len = sizeof(rc);
166
/* I know we're losing some precision. But it's not like poll-like family
167
* type of mechanisms are precise up to the microsecond.
169
timeout_ms=timeout * 1000 + usec / 1000;
171
ssh_sock_set_nonblocking(s);
173
ssh_log(session, SSH_LOG_RARE, "Trying to connect to host: %s:%d with "
174
"timeout %d ms", host, port, timeout_ms);
176
/* The return value is checked later */
177
connect(s, ai->ai_addr, ai->ai_addrlen);
184
fds.events |= POLLWRNORM;
186
rc = ssh_poll(&fds,1,timeout_ms);
190
ssh_set_error(session, SSH_FATAL,
191
"Timeout while connecting to %s:%d", host, port);
192
ssh_connect_socket_close(s);
198
ssh_set_error(session, SSH_FATAL,
199
"poll error: %s", strerror(errno));
200
ssh_connect_socket_close(s);
206
/* Get connect(2) return code. Zero means no error */
207
getsockopt(s, SOL_SOCKET, SO_ERROR,(char *) &rc, &len);
209
ssh_set_error(session, SSH_FATAL,
210
"Connect to %s:%d failed: %s", host, port, strerror(rc));
211
ssh_connect_socket_close(s);
216
/* s is connected ? */
217
ssh_log(session, SSH_LOG_PACKET, "Socket connected with timeout\n");
218
ssh_sock_set_blocking(s);
227
* @brief Connect to an IPv4 or IPv6 host specified by its IP address or
230
* @returns A file descriptor, < 0 on error.
232
socket_t ssh_connect_host(ssh_session session, const char *host,
233
const char *bind_addr, int port, long timeout, long usec) {
237
struct addrinfo *itr;
241
rc = getai(session,host, port, &ai);
243
ssh_set_error(session, SSH_FATAL,
244
"Failed to resolve hostname %s (%s)", host, gai_strerror(rc));
249
for (itr = ai; itr != NULL; itr = itr->ai_next){
251
s = socket(itr->ai_family, itr->ai_socktype, itr->ai_protocol);
253
ssh_set_error(session, SSH_FATAL,
254
"Socket create failed: %s", strerror(errno));
259
struct addrinfo *bind_ai;
260
struct addrinfo *bind_itr;
262
ssh_log(session, SSH_LOG_PACKET, "Resolving %s\n", bind_addr);
264
rc = getai(session,bind_addr, 0, &bind_ai);
266
ssh_set_error(session, SSH_FATAL,
267
"Failed to resolve bind address %s (%s)",
274
for (bind_itr = bind_ai; bind_itr != NULL; bind_itr = bind_itr->ai_next) {
275
if (bind(s, bind_itr->ai_addr, bind_itr->ai_addrlen) < 0) {
276
ssh_set_error(session, SSH_FATAL,
277
"Binding local address: %s", strerror(errno));
283
freeaddrinfo(bind_ai);
285
/* Cannot bind to any local addresses */
286
if (bind_itr == NULL) {
287
ssh_connect_socket_close(s);
293
if (timeout || usec) {
294
socket_t ret = ssh_connect_ai_timeout(session, host, port, itr,
300
if (connect(s, itr->ai_addr, itr->ai_addrlen) < 0) {
301
ssh_set_error(session, SSH_FATAL, "Connect failed: %s", strerror(errno));
302
ssh_connect_socket_close(s);
307
/* We are connected */
321
* @brief Launches a nonblocking connect to an IPv4 or IPv6 host
322
* specified by its IP address or hostname.
324
* @returns A file descriptor, < 0 on error.
325
* @warning very ugly !!!
327
socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
328
const char *bind_addr, int port) {
332
struct addrinfo *itr;
336
rc = getai(session,host, port, &ai);
338
ssh_set_error(session, SSH_FATAL,
339
"Failed to resolve hostname %s (%s)", host, gai_strerror(rc));
344
for (itr = ai; itr != NULL; itr = itr->ai_next){
346
s = socket(itr->ai_family, itr->ai_socktype, itr->ai_protocol);
348
ssh_set_error(session, SSH_FATAL,
349
"Socket create failed: %s", strerror(errno));
354
struct addrinfo *bind_ai;
355
struct addrinfo *bind_itr;
357
ssh_log(session, SSH_LOG_PACKET, "Resolving %s\n", bind_addr);
359
rc = getai(session,bind_addr, 0, &bind_ai);
361
ssh_set_error(session, SSH_FATAL,
362
"Failed to resolve bind address %s (%s)",
370
for (bind_itr = bind_ai; bind_itr != NULL; bind_itr = bind_itr->ai_next) {
371
if (bind(s, bind_itr->ai_addr, bind_itr->ai_addrlen) < 0) {
372
ssh_set_error(session, SSH_FATAL,
373
"Binding local address: %s", strerror(errno));
379
freeaddrinfo(bind_ai);
381
/* Cannot bind to any local addresses */
382
if (bind_itr == NULL) {
383
ssh_connect_socket_close(s);
388
ssh_sock_set_nonblocking(s);
390
connect(s, itr->ai_addr, itr->ai_addrlen);
401
* @addtogroup libssh_session
407
* @brief A wrapper for the select syscall
409
* This functions acts more or less like the select(2) syscall.\n
410
* There is no support for writing or exceptions.\n
412
* @param[in] channels Arrays of channels pointers terminated by a NULL.
413
* It is never rewritten.
415
* @param[out] outchannels Arrays of same size that "channels", there is no need
418
* @param[in] maxfd Maximum +1 file descriptor from readfds.
420
* @param[in] readfds A fd_set of file descriptors to be select'ed for
423
* @param[in] timeout A timeout for the select.
425
* @return -1 if an error occured. SSH_EINTR if it was interrupted, in
426
* that case, just restart it.
428
* @warning libssh is not threadsafe here. That means that if a signal is caught
429
* during the processing of this function, you cannot call ssh
430
* functions on sessions that are busy with ssh_select().
434
int ssh_select(ssh_channel *channels, ssh_channel *outchannels, socket_t maxfd,
435
fd_set *readfds, struct timeval *timeout) {
436
struct timeval zerotime;
437
fd_set localset, localset2;
445
zerotime.tv_usec = 0;
448
* First, poll the maxfd file descriptors from the user with a zero-second
449
* timeout. They have the bigger priority.
452
memcpy(&localset, readfds, sizeof(fd_set));
453
rep = select(maxfd, &localset, NULL, NULL, &zerotime);
454
/* catch the eventual errors */
460
/* Poll every channel */
462
for (i = 0; channels[i]; i++) {
463
if (channels[i]->session->alive) {
464
if(ssh_channel_poll(channels[i], 0) > 0) {
465
outchannels[j] = channels[i];
468
if(ssh_channel_poll(channels[i], 1) > 0) {
469
outchannels[j] = channels[i];
475
outchannels[j] = NULL;
477
/* Look into the localset for active fd */
479
for (f = 0; (f < maxfd) && !set; f++) {
480
if (FD_ISSET(f, &localset)) {
485
/* j != 0 means a channel has data */
486
if( (j != 0) || (set != 0)) {
488
memcpy(readfds, &localset, sizeof(fd_set));
494
* At this point, not any channel had any data ready for reading, nor any fd
495
* had data for reading.
497
memcpy(&localset, readfds, sizeof(fd_set));
498
for (i = 0; channels[i]; i++) {
499
if (channels[i]->session->alive) {
500
ssh_socket_fd_set(channels[i]->session->socket, &localset, &maxfd);
504
rep = select(maxfd, &localset, NULL, NULL, timeout);
505
if (rep == -1 && errno == EINTR) {
506
/* Interrupted by a signal */
512
* Was the error due to a libssh's channel or from a closed descriptor from
513
* the user? User closed descriptors have been caught in the first select
514
* and not closed since that moment. That case shouldn't occur at all
519
/* Set the data_to_read flag on each session */
520
for (i = 0; channels[i]; i++) {
521
if (channels[i]->session->alive &&
522
ssh_socket_fd_isset(channels[i]->session->socket,&localset)) {
523
ssh_socket_set_read_wontblock(channels[i]->session->socket);
527
/* Now, test each channel */
529
for (i = 0; channels[i]; i++) {
530
if (channels[i]->session->alive &&
531
ssh_socket_fd_isset(channels[i]->session->socket,&localset)) {
532
if ((ssh_channel_poll(channels[i],0) > 0) ||
533
(ssh_channel_poll(channels[i], 1) > 0)) {
534
outchannels[j] = channels[i];
539
outchannels[j] = NULL;
542
for (f = 0; f < maxfd; f++) {
543
if (FD_ISSET(f, readfds) && FD_ISSET(f, &localset)) {
544
FD_SET(f, &localset2);
548
memcpy(readfds, &localset2, sizeof(fd_set));
555
/* vim: set ts=4 sw=4 et cindent: */