summaryrefslogtreecommitdiffstats
path: root/libssh/src/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'libssh/src/socket.c')
-rw-r--r--libssh/src/socket.c872
1 files changed, 0 insertions, 872 deletions
diff --git a/libssh/src/socket.c b/libssh/src/socket.c
deleted file mode 100644
index 498da77e..00000000
--- a/libssh/src/socket.c
+++ /dev/null
@@ -1,872 +0,0 @@
-/*
- * socket.c - socket functions for the library
- *
- * This file is part of the SSH Library
- *
- * Copyright (c) 2008-2010 by Aris Adamantiadis
- *
- * The SSH Library is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or (at your
- * option) any later version.
- *
- * The SSH Library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with the SSH Library; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#ifdef _WIN32
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#if _MSC_VER >= 1400
-#include <io.h>
-#undef open
-#define open _open
-#undef close
-#define close _close
-#undef read
-#define read _read
-#undef write
-#define write _write
-#endif /* _MSC_VER */
-#else /* _WIN32 */
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#endif /* _WIN32 */
-
-#include "libssh/priv.h"
-#include "libssh/callbacks.h"
-#include "libssh/socket.h"
-#include "libssh/buffer.h"
-#include "libssh/poll.h"
-#include "libssh/session.h"
-
-/**
- * @internal
- *
- * @defgroup libssh_socket The SSH socket functions.
- * @ingroup libssh
- *
- * Functions for handling sockets.
- *
- * @{
- */
-
-enum ssh_socket_states_e {
- SSH_SOCKET_NONE,
- SSH_SOCKET_CONNECTING,
- SSH_SOCKET_CONNECTED,
- SSH_SOCKET_EOF,
- SSH_SOCKET_ERROR,
- SSH_SOCKET_CLOSED
-};
-
-struct ssh_socket_struct {
- socket_t fd_in;
- socket_t fd_out;
- int fd_is_socket;
- int last_errno;
- int read_wontblock; /* reading now on socket will
- not block */
- int write_wontblock;
- int data_except;
- enum ssh_socket_states_e state;
- ssh_buffer out_buffer;
- ssh_buffer in_buffer;
- ssh_session session;
- ssh_socket_callbacks callbacks;
- ssh_poll_handle poll_in;
- ssh_poll_handle poll_out;
-};
-
-static int sockets_initialized = 0;
-
-static int ssh_socket_unbuffered_read(ssh_socket s, void *buffer, uint32_t len);
-static int ssh_socket_unbuffered_write(ssh_socket s, const void *buffer,
- uint32_t len);
-
-/**
- * \internal
- * \brief inits the socket system (windows specific)
- */
-int ssh_socket_init(void) {
- if (sockets_initialized == 0) {
-#ifdef _WIN32
- struct WSAData wsaData;
-
- /* Initiates use of the Winsock DLL by a process. */
- if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
- return -1;
- }
-
-#endif
- ssh_poll_init();
-
- sockets_initialized = 1;
- }
-
- return 0;
-}
-
-/**
- * @brief Cleanup the socket system.
- */
-void ssh_socket_cleanup(void) {
- if (sockets_initialized == 1) {
- ssh_poll_cleanup();
-#ifdef _WIN32
- WSACleanup();
-#endif
- sockets_initialized = 0;
- }
-}
-
-
-/**
- * \internal
- * \brief creates a new Socket object
- */
-ssh_socket ssh_socket_new(ssh_session session) {
- ssh_socket s;
-
- s = malloc(sizeof(struct ssh_socket_struct));
- if (s == NULL) {
- ssh_set_error_oom(session);
- return NULL;
- }
- s->fd_in = SSH_INVALID_SOCKET;
- s->fd_out= SSH_INVALID_SOCKET;
- s->last_errno = -1;
- s->fd_is_socket = 1;
- s->session = session;
- s->in_buffer = ssh_buffer_new();
- if (s->in_buffer == NULL) {
- ssh_set_error_oom(session);
- SAFE_FREE(s);
- return NULL;
- }
- s->out_buffer=ssh_buffer_new();
- if (s->out_buffer == NULL) {
- ssh_set_error_oom(session);
- ssh_buffer_free(s->in_buffer);
- SAFE_FREE(s);
- return NULL;
- }
- s->read_wontblock = 0;
- s->write_wontblock = 0;
- s->data_except = 0;
- s->poll_in=s->poll_out=NULL;
- s->state=SSH_SOCKET_NONE;
- return s;
-}
-
-/**
- * @internal
- * @brief Reset the state of a socket so it looks brand-new
- * @param[in] s socket to rest
- */
-void ssh_socket_reset(ssh_socket s){
- s->fd_in = SSH_INVALID_SOCKET;
- s->fd_out= SSH_INVALID_SOCKET;
- s->last_errno = -1;
- s->fd_is_socket = 1;
- ssh_buffer_reinit(s->in_buffer);
- ssh_buffer_reinit(s->out_buffer);
- s->read_wontblock = 0;
- s->write_wontblock = 0;
- s->data_except = 0;
- s->poll_in=s->poll_out=NULL;
- s->state=SSH_SOCKET_NONE;
-}
-
-/**
- * @internal
- * @brief the socket callbacks, i.e. callbacks to be called
- * upon a socket event.
- * @param s socket to set callbacks on.
- * @param callbacks a ssh_socket_callback object reference.
- */
-
-void ssh_socket_set_callbacks(ssh_socket s, ssh_socket_callbacks callbacks){
- s->callbacks=callbacks;
-}
-
-/**
- * @brief SSH poll callback. This callback will be used when an event
- * caught on the socket.
- *
- * @param p Poll object this callback belongs to.
- * @param fd The raw socket.
- * @param revents The current poll events on the socket.
- * @param userdata Userdata to be passed to the callback function,
- * in this case the socket object.
- *
- * @return 0 on success, < 0 when the poll object has been removed
- * from its poll context.
- */
-int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd,
- int revents, void *v_s) {
- ssh_socket s = (ssh_socket)v_s;
- char buffer[MAX_BUF_SIZE];
- int r;
- int err = 0;
- socklen_t errlen = sizeof(err);
- /* Do not do anything if this socket was already closed */
- if (!ssh_socket_is_open(s)) {
- return -1;
- }
- if (revents & POLLERR || revents & POLLHUP) {
- /* Check if we are in a connecting state */
- if (s->state == SSH_SOCKET_CONNECTING) {
- s->state = SSH_SOCKET_ERROR;
- r = getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen);
- if (r < 0) {
- err = errno;
- }
- s->last_errno = err;
- ssh_socket_close(s);
- if (s->callbacks && s->callbacks->connected) {
- s->callbacks->connected(SSH_SOCKET_CONNECTED_ERROR, err,
- s->callbacks->userdata);
- }
- return -1;
- }
- /* Then we are in a more standard kind of error */
- /* force a read to get an explanation */
- revents |= POLLIN;
- }
- if ((revents & POLLIN) && s->state == SSH_SOCKET_CONNECTED) {
- s->read_wontblock = 1;
- r = ssh_socket_unbuffered_read(s, buffer, sizeof(buffer));
- if (r < 0) {
- if (p != NULL) {
- ssh_poll_remove_events(p, POLLIN);
- }
- if (s->callbacks && s->callbacks->exception) {
- s->callbacks->exception(SSH_SOCKET_EXCEPTION_ERROR,
- s->last_errno, s->callbacks->userdata);
- /* p may have been freed, so don't use it
- * anymore in this function */
- p = NULL;
- return -2;
- }
- }
- if (r == 0) {
- if (p != NULL) {
- ssh_poll_remove_events(p, POLLIN);
- }
- if (p != NULL) {
- ssh_poll_remove_events(p, POLLIN);
- }
- if (s->callbacks && s->callbacks->exception) {
- s->callbacks->exception(SSH_SOCKET_EXCEPTION_EOF,
- 0, s->callbacks->userdata);
- /* p may have been freed, so don't use it
- * anymore in this function */
- p = NULL;
- return -2;
- }
- }
- if (r > 0) {
- if (s->session->socket_counter != NULL) {
- s->session->socket_counter->in_bytes += r;
- }
- /* Bufferize the data and then call the callback */
- r = ssh_buffer_add_data(s->in_buffer, buffer, r);
- if (r < 0) {
- return -1;
- }
- if (s->callbacks && s->callbacks->data) {
- do {
- r = s->callbacks->data(buffer_get_rest(s->in_buffer),
- buffer_get_rest_len(s->in_buffer),
- s->callbacks->userdata);
- buffer_pass_bytes(s->in_buffer, r);
- } while ((r > 0) && (s->state == SSH_SOCKET_CONNECTED));
- /* p may have been freed, so don't use it
- * anymore in this function */
- p = NULL;
- }
- }
- }
-#ifdef _WIN32
- if (revents & POLLOUT || revents & POLLWRNORM) {
-#else
- if (revents & POLLOUT) {
-#endif
- /* First, POLLOUT is a sign we may be connected */
- if (s->state == SSH_SOCKET_CONNECTING) {
- SSH_LOG(SSH_LOG_PACKET, "Received POLLOUT in connecting state");
- s->state = SSH_SOCKET_CONNECTED;
- if (p != NULL) {
- ssh_poll_set_events(p, POLLOUT | POLLIN);
- }
- r = ssh_socket_set_blocking(ssh_socket_get_fd_in(s));
- if (r < 0) {
- return -1;
- }
- if (s->callbacks && s->callbacks->connected) {
- s->callbacks->connected(SSH_SOCKET_CONNECTED_OK, 0,
- s->callbacks->userdata);
- }
- return 0;
- }
- /* So, we can write data */
- s->write_wontblock=1;
- if (p != NULL) {
- ssh_poll_remove_events(p, POLLOUT);
- }
-
- /* If buffered data is pending, write it */
- if (buffer_get_rest_len(s->out_buffer) > 0) {
- ssh_socket_nonblocking_flush(s);
- } else if (s->callbacks && s->callbacks->controlflow) {
- /* Otherwise advertise the upper level that write can be done */
- s->callbacks->controlflow(SSH_SOCKET_FLOW_WRITEWONTBLOCK,
- s->callbacks->userdata);
- }
- /* TODO: Find a way to put back POLLOUT when buffering occurs */
- }
- /* Return -1 if one of the poll handlers disappeared */
- return (s->poll_in == NULL || s->poll_out == NULL) ? -1 : 0;
-}
-
-/** @internal
- * @brief returns the input poll handle corresponding to the socket,
- * creates it if it does not exist.
- * @returns allocated and initialized ssh_poll_handle object
- */
-ssh_poll_handle ssh_socket_get_poll_handle_in(ssh_socket s){
- if(s->poll_in)
- return s->poll_in;
- s->poll_in=ssh_poll_new(s->fd_in,0,ssh_socket_pollcallback,s);
- if(s->fd_in == s->fd_out && s->poll_out == NULL)
- s->poll_out=s->poll_in;
- return s->poll_in;
-}
-
-/** @internal
- * @brief returns the output poll handle corresponding to the socket,
- * creates it if it does not exist.
- * @returns allocated and initialized ssh_poll_handle object
- */
-ssh_poll_handle ssh_socket_get_poll_handle_out(ssh_socket s){
- if(s->poll_out)
- return s->poll_out;
- s->poll_out=ssh_poll_new(s->fd_out,0,ssh_socket_pollcallback,s);
- if(s->fd_in == s->fd_out && s->poll_in == NULL)
- s->poll_in=s->poll_out;
- return s->poll_out;
-}
-
-/** \internal
- * \brief Deletes a socket object
- */
-void ssh_socket_free(ssh_socket s){
- if (s == NULL) {
- return;
- }
- ssh_socket_close(s);
- ssh_buffer_free(s->in_buffer);
- ssh_buffer_free(s->out_buffer);
- SAFE_FREE(s);
-}
-
-#ifndef _WIN32
-int ssh_socket_unix(ssh_socket s, const char *path) {
- struct sockaddr_un sunaddr;
- socket_t fd;
- sunaddr.sun_family = AF_UNIX;
- snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path), "%s", path);
-
- fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (fd == SSH_INVALID_SOCKET) {
- ssh_set_error(s->session, SSH_FATAL,
- "Error from socket(AF_UNIX, SOCK_STREAM, 0): %s",
- strerror(errno));
- return -1;
- }
-
- if (fcntl(fd, F_SETFD, 1) == -1) {
- ssh_set_error(s->session, SSH_FATAL,
- "Error from fcntl(fd, F_SETFD, 1): %s",
- strerror(errno));
- close(fd);
- return -1;
- }
-
- if (connect(fd, (struct sockaddr *) &sunaddr,
- sizeof(sunaddr)) < 0) {
- ssh_set_error(s->session, SSH_FATAL, "Error from connect(): %s",
- strerror(errno));
- close(fd);
- return -1;
- }
- ssh_socket_set_fd(s,fd);
- return 0;
-}
-#endif
-
-/** \internal
- * \brief closes a socket
- */
-void ssh_socket_close(ssh_socket s){
- if (ssh_socket_is_open(s)) {
-#ifdef _WIN32
- closesocket(s->fd_in);
- /* fd_in = fd_out under win32 */
- s->last_errno = WSAGetLastError();
-#else
- close(s->fd_in);
- if(s->fd_out != s->fd_in && s->fd_out != -1)
- close(s->fd_out);
- s->last_errno = errno;
-#endif
- s->fd_in = s->fd_out = SSH_INVALID_SOCKET;
- }
- if(s->poll_in != NULL){
- if(s->poll_out == s->poll_in)
- s->poll_out = NULL;
- ssh_poll_free(s->poll_in);
- s->poll_in=NULL;
- }
- if(s->poll_out != NULL){
- ssh_poll_free(s->poll_out);
- s->poll_out=NULL;
- }
-
- s->state = SSH_SOCKET_CLOSED;
-}
-
-/**
- * @internal
- * @brief sets the file descriptor of the socket.
- * @param[out] s ssh_socket to update
- * @param[in] fd file descriptor to set
- * @warning this function updates boths the input and output
- * file descriptors
- */
-void ssh_socket_set_fd(ssh_socket s, socket_t fd) {
- s->fd_in = s->fd_out = fd;
-
- if (s->poll_in) {
- ssh_poll_set_fd(s->poll_in,fd);
- } else {
- s->state = SSH_SOCKET_CONNECTING;
-
- /* POLLOUT is the event to wait for in a nonblocking connect */
- ssh_poll_set_events(ssh_socket_get_poll_handle_in(s), POLLOUT);
-#ifdef _WIN32
- ssh_poll_add_events(ssh_socket_get_poll_handle_in(s), POLLWRNORM);
-#endif
- }
-}
-
-/**
- * @internal
- * @brief sets the input file descriptor of the socket.
- * @param[out] s ssh_socket to update
- * @param[in] fd file descriptor to set
- */
-void ssh_socket_set_fd_in(ssh_socket s, socket_t fd) {
- s->fd_in = fd;
- if(s->poll_in)
- ssh_poll_set_fd(s->poll_in,fd);
-}
-
-/**
- * @internal
- * @brief sets the output file descriptor of the socket.
- * @param[out] s ssh_socket to update
- * @param[in] fd file descriptor to set
- */
-void ssh_socket_set_fd_out(ssh_socket s, socket_t fd) {
- s->fd_out = fd;
- if(s->poll_out)
- ssh_poll_set_fd(s->poll_out,fd);
-}
-
-
-
-/** \internal
- * \brief returns the input file descriptor of the socket
- */
-socket_t ssh_socket_get_fd_in(ssh_socket s) {
- return s->fd_in;
-}
-
-/** \internal
- * \brief returns nonzero if the socket is open
- */
-int ssh_socket_is_open(ssh_socket s) {
- return s->fd_in != SSH_INVALID_SOCKET;
-}
-
-/** \internal
- * \brief read len bytes from socket into buffer
- */
-static int ssh_socket_unbuffered_read(ssh_socket s, void *buffer, uint32_t len) {
- int rc = -1;
-
- if (s->data_except) {
- return -1;
- }
- if(s->fd_is_socket)
- rc = recv(s->fd_in,buffer, len, 0);
- else
- rc = read(s->fd_in,buffer, len);
-#ifdef _WIN32
- s->last_errno = WSAGetLastError();
-#else
- s->last_errno = errno;
-#endif
- s->read_wontblock = 0;
-
- if (rc < 0) {
- s->data_except = 1;
- }
-
- return rc;
-}
-
-/** \internal
- * \brief writes len bytes from buffer to socket
- */
-static int ssh_socket_unbuffered_write(ssh_socket s, const void *buffer,
- uint32_t len) {
- int w = -1;
-
- if (s->data_except) {
- return -1;
- }
- if (s->fd_is_socket)
- w = send(s->fd_out,buffer, len, 0);
- else
- w = write(s->fd_out, buffer, len);
-#ifdef _WIN32
- s->last_errno = WSAGetLastError();
-#else
- s->last_errno = errno;
-#endif
- s->write_wontblock = 0;
- /* Reactive the POLLOUT detector in the poll multiplexer system */
- if(s->poll_out){
- SSH_LOG(SSH_LOG_PACKET, "Enabling POLLOUT for socket");
- ssh_poll_set_events(s->poll_out,ssh_poll_get_events(s->poll_out) | POLLOUT);
- }
- if (w < 0) {
- s->data_except = 1;
- }
-
- return w;
-}
-
-/** \internal
- * \brief returns nonzero if the current socket is in the fd_set
- */
-int ssh_socket_fd_isset(ssh_socket s, fd_set *set) {
- if(s->fd_in == SSH_INVALID_SOCKET) {
- return 0;
- }
- return FD_ISSET(s->fd_in,set) || FD_ISSET(s->fd_out,set);
-}
-
-/** \internal
- * \brief sets the current fd in a fd_set and updates the max_fd
- */
-
-void ssh_socket_fd_set(ssh_socket s, fd_set *set, socket_t *max_fd) {
- if (s->fd_in == SSH_INVALID_SOCKET) {
- return;
- }
-
- FD_SET(s->fd_in,set);
- FD_SET(s->fd_out,set);
-
- if (s->fd_in >= 0 &&
- s->fd_in >= *max_fd &&
- s->fd_in != SSH_INVALID_SOCKET) {
- *max_fd = s->fd_in + 1;
- }
- if (s->fd_out >= 0 &&
- s->fd_out >= *max_fd &&
- s->fd_out != SSH_INVALID_SOCKET) {
- *max_fd = s->fd_out + 1;
- }
-}
-
-/** \internal
- * \brief buffered write of data
- * \returns SSH_OK, or SSH_ERROR
- * \warning has no effect on socket before a flush
- */
-int ssh_socket_write(ssh_socket s, const void *buffer, int len) {
- if(len > 0) {
- if (ssh_buffer_add_data(s->out_buffer, buffer, len) < 0) {
- ssh_set_error_oom(s->session);
- return SSH_ERROR;
- }
- ssh_socket_nonblocking_flush(s);
- }
-
- return SSH_OK;
-}
-
-
-/** \internal
- * \brief starts a nonblocking flush of the output buffer
- *
- */
-int ssh_socket_nonblocking_flush(ssh_socket s) {
- ssh_session session = s->session;
- uint32_t len;
- int w;
-
- if (!ssh_socket_is_open(s)) {
- session->alive = 0;
- /* FIXME use ssh_socket_get_errno */
- ssh_set_error(session, SSH_FATAL,
- "Writing packet: error on socket (or connection closed): %s",
- strerror(s->last_errno));
-
- return SSH_ERROR;
- }
-
- len = buffer_get_rest_len(s->out_buffer);
- if (!s->write_wontblock && s->poll_out && len > 0) {
- /* force the poll system to catch pollout events */
- ssh_poll_add_events(s->poll_out, POLLOUT);
-
- return SSH_AGAIN;
- }
- if (s->write_wontblock && len > 0) {
- w = ssh_socket_unbuffered_write(s, buffer_get_rest(s->out_buffer), len);
- if (w < 0) {
- session->alive = 0;
- ssh_socket_close(s);
- /* FIXME use ssh_socket_get_errno() */
- /* FIXME use callback for errors */
- ssh_set_error(session, SSH_FATAL,
- "Writing packet: error on socket (or connection closed): %s",
- strerror(s->last_errno));
-
- return SSH_ERROR;
- }
- buffer_pass_bytes(s->out_buffer, w);
- if (s->session->socket_counter != NULL) {
- s->session->socket_counter->out_bytes += w;
- }
- }
-
- /* Is there some data pending? */
- len = buffer_get_rest_len(s->out_buffer);
- if (s->poll_out && len > 0) {
- /* force the poll system to catch pollout events */
- ssh_poll_add_events(s->poll_out, POLLOUT);
-
- return SSH_AGAIN;
- }
-
- /* all data written */
- return SSH_OK;
-}
-
-void ssh_socket_set_write_wontblock(ssh_socket s) {
- s->write_wontblock = 1;
-}
-
-void ssh_socket_set_read_wontblock(ssh_socket s) {
- s->read_wontblock = 1;
-}
-
-void ssh_socket_set_except(ssh_socket s) {
- s->data_except = 1;
-}
-
-int ssh_socket_data_available(ssh_socket s) {
- return s->read_wontblock;
-}
-
-int ssh_socket_data_writable(ssh_socket s) {
- return s->write_wontblock;
-}
-
-/** @internal
- * @brief returns the number of outgoing bytes currently buffered
- * @param s the socket
- * @returns numbers of bytes buffered, or 0 if the socket isn't connected
- */
-int ssh_socket_buffered_write_bytes(ssh_socket s){
- if(s==NULL || s->out_buffer == NULL)
- return 0;
- return buffer_get_rest_len(s->out_buffer);
-}
-
-
-int ssh_socket_get_status(ssh_socket s) {
- int r = 0;
-
- if (ssh_buffer_get_len(s->in_buffer) > 0) {
- r |= SSH_READ_PENDING;
- }
-
- if (ssh_buffer_get_len(s->out_buffer) > 0) {
- r |= SSH_WRITE_PENDING;
- }
-
- if (s->data_except) {
- r |= SSH_CLOSED_ERROR;
- }
-
- return r;
-}
-
-int ssh_socket_get_poll_flags(ssh_socket s) {
- int r = 0;
- if (s->poll_in != NULL && (ssh_poll_get_events (s->poll_in) & POLLIN) > 0) {
- r |= SSH_READ_PENDING;
- }
- if (s->poll_out != NULL && (ssh_poll_get_events (s->poll_out) & POLLOUT) > 0) {
- r |= SSH_WRITE_PENDING;
- }
- return r;
-}
-
-#ifdef _WIN32
-int ssh_socket_set_nonblocking(socket_t fd) {
- u_long nonblocking = 1;
- return ioctlsocket(fd, FIONBIO, &nonblocking);
-}
-
-int ssh_socket_set_blocking(socket_t fd) {
- u_long nonblocking = 0;
- return ioctlsocket(fd, FIONBIO, &nonblocking);
-}
-
-#else /* _WIN32 */
-int ssh_socket_set_nonblocking(socket_t fd) {
- return fcntl(fd, F_SETFL, O_NONBLOCK);
-}
-
-int ssh_socket_set_blocking(socket_t fd) {
- return fcntl(fd, F_SETFL, 0);
-}
-#endif /* _WIN32 */
-
-/**
- * @internal
- * @brief Launches a socket connection
- * If a the socket connected callback has been defined and
- * a poll object exists, this call will be non blocking.
- * @param s socket to connect.
- * @param host hostname or ip address to connect to.
- * @param port port number to connect to.
- * @param bind_addr address to bind to, or NULL for default.
- * @returns SSH_OK socket is being connected.
- * @returns SSH_ERROR error while connecting to remote host.
- * @bug It only tries connecting to one of the available AI's
- * which is problematic for hosts having DNS fail-over.
- */
-
-int ssh_socket_connect(ssh_socket s, const char *host, int port, const char *bind_addr){
- socket_t fd;
-
- if(s->state != SSH_SOCKET_NONE) {
- ssh_set_error(s->session, SSH_FATAL,
- "ssh_socket_connect called on socket not unconnected");
- return SSH_ERROR;
- }
- fd=ssh_connect_host_nonblocking(s->session,host,bind_addr,port);
- SSH_LOG(SSH_LOG_PROTOCOL,"Nonblocking connection socket: %d",fd);
- if(fd == SSH_INVALID_SOCKET)
- return SSH_ERROR;
- ssh_socket_set_fd(s,fd);
-
- return SSH_OK;
-}
-
-#ifndef _WIN32
-/**
- * @internal
- * @brief executes a command and redirect input and outputs
- * @param command command to execute
- * @param in input file descriptor
- * @param out output file descriptor
- */
-void ssh_execute_command(const char *command, socket_t in, socket_t out){
- const char *args[]={"/bin/sh","-c",command,NULL};
- /* redirect in and out to stdin, stdout and stderr */
- dup2(in, 0);
- dup2(out,1);
- dup2(out,2);
- close(in);
- close(out);
- execv(args[0],(char * const *)args);
- exit(1);
-}
-
-/**
- * @internal
- * @brief Open a socket on a ProxyCommand
- * This call will always be nonblocking.
- * @param s socket to connect.
- * @param command Command to execute.
- * @returns SSH_OK socket is being connected.
- * @returns SSH_ERROR error while executing the command.
- */
-
-int ssh_socket_connect_proxycommand(ssh_socket s, const char *command){
- socket_t in_pipe[2];
- socket_t out_pipe[2];
- int pid;
- int rc;
-
- if(s->state != SSH_SOCKET_NONE)
- return SSH_ERROR;
-
- rc = pipe(in_pipe);
- if (rc < 0) {
- return SSH_ERROR;
- }
- rc = pipe(out_pipe);
- if (rc < 0) {
- return SSH_ERROR;
- }
-
- SSH_LOG(SSH_LOG_PROTOCOL,"Executing proxycommand '%s'",command);
- pid = fork();
- if(pid == 0){
- ssh_execute_command(command,out_pipe[0],in_pipe[1]);
- }
- close(in_pipe[1]);
- close(out_pipe[0]);
- SSH_LOG(SSH_LOG_PROTOCOL,"ProxyCommand connection pipe: [%d,%d]",in_pipe[0],out_pipe[1]);
- ssh_socket_set_fd_in(s,in_pipe[0]);
- ssh_socket_set_fd_out(s,out_pipe[1]);
- s->state=SSH_SOCKET_CONNECTED;
- s->fd_is_socket=0;
- /* POLLOUT is the event to wait for in a nonblocking connect */
- ssh_poll_set_events(ssh_socket_get_poll_handle_in(s),POLLIN);
- ssh_poll_set_events(ssh_socket_get_poll_handle_out(s),POLLOUT);
- if(s->callbacks && s->callbacks->connected)
- s->callbacks->connected(SSH_SOCKET_CONNECTED_OK,0,s->callbacks->userdata);
-
- return SSH_OK;
-}
-
-#endif /* _WIN32 */
-/** @} */
-
-/* vim: set ts=4 sw=4 et cindent: */