/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org> * Copyright (c) 2009-2011 by Daniel Stenberg * Copyright (c) 2010 Simon Josefsson <simon@josefsson.org> * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * Neither the name of the copyright holder nor the names * of any other contributors may be used to endorse or * promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. */ #include "libssh2_priv.h"#include <errno.h>#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include <stdlib.h>#include <fcntl.h> #ifdef HAVE_GETTIMEOFDAY#include <sys/time.h>#endif#ifdef HAVE_ALLOCA_H#include <alloca.h>#endif #include "transport.h"#include "session.h"#include "channel.h"#include "mac.h"#include "misc.h" /* libssh2_default_alloc */staticLIBSSH2_ALLOC_FUNC(libssh2_default_alloc){ (void) abstract; return malloc(count);} /* libssh2_default_free */staticLIBSSH2_FREE_FUNC(libssh2_default_free){ (void) abstract; free(ptr);} /* libssh2_default_realloc */staticLIBSSH2_REALLOC_FUNC(libssh2_default_realloc){ (void) abstract; return realloc(ptr, count);} /* * banner_receive * * Wait for a hello from the remote host * Allocate a buffer and store the banner in session->remote.banner * Returns: 0 on success, LIBSSH2_ERROR_EAGAIN if read would block, negative * on failure */static intbanner_receive(LIBSSH2_SESSION * session){ int ret; int banner_len; if (session->banner_TxRx_state == libssh2_NB_state_idle) { banner_len = 0; session->banner_TxRx_state = libssh2_NB_state_created; } else { banner_len = session->banner_TxRx_total_send; } while ((banner_len < (int) sizeof(session->banner_TxRx_banner)) && ((banner_len == 0) || (session->banner_TxRx_banner[banner_len - 1] != '\n'))) { char c = '\0'; /* no incoming block yet! */ session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND; ret = LIBSSH2_RECV(session, &c, 1, LIBSSH2_SOCKET_RECV_FLAGS(session)); if (ret < 0) { if(session->api_block_mode || (ret != -EAGAIN)) /* ignore EAGAIN when non-blocking */ _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, "Error recving %d bytes: %d", 1, -ret); } else _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, "Recved %d bytes banner", ret); if (ret < 0) { if (ret == -EAGAIN) { session->socket_block_directions = LIBSSH2_SESSION_BLOCK_INBOUND; session->banner_TxRx_total_send = banner_len; return LIBSSH2_ERROR_EAGAIN; } /* Some kinda error */ session->banner_TxRx_state = libssh2_NB_state_idle; session->banner_TxRx_total_send = 0; return LIBSSH2_ERROR_SOCKET_RECV; } if (ret == 0) { session->socket_state = LIBSSH2_SOCKET_DISCONNECTED; return LIBSSH2_ERROR_SOCKET_DISCONNECT; } if (c == '\0') { /* NULLs are not allowed in SSH banners */ session->banner_TxRx_state = libssh2_NB_state_idle; session->banner_TxRx_total_send = 0; return LIBSSH2_ERROR_BANNER_RECV; } session->banner_TxRx_banner[banner_len++] = c; } while (banner_len && ((session->banner_TxRx_banner[banner_len - 1] == '\n') || (session->banner_TxRx_banner[banner_len - 1] == '\r'))) { banner_len--; } /* From this point on, we are done here */ session->banner_TxRx_state = libssh2_NB_state_idle; session->banner_TxRx_total_send = 0; if (!banner_len) return LIBSSH2_ERROR_BANNER_RECV; session->remote.banner = LIBSSH2_ALLOC(session, banner_len + 1); if (!session->remote.banner) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Error allocating space for remote banner"); } memcpy(session->remote.banner, session->banner_TxRx_banner, banner_len); session->remote.banner[banner_len] = '\0'; _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Received Banner: %s", session->remote.banner); return LIBSSH2_ERROR_NONE;} /* * banner_send * * Send the default banner, or the one set via libssh2_setopt_string * * Returns LIBSSH2_ERROR_EAGAIN if it would block - and if it does so, you * should call this function again as soon as it is likely that more data can * be sent, and this function should then be called with the same argument set * (same data pointer and same data_len) until zero or failure is returned. */static intbanner_send(LIBSSH2_SESSION * session){ char *banner = (char *) LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF; int banner_len = sizeof(LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF) - 1; ssize_t ret;#ifdef LIBSSH2DEBUG char banner_dup[256];#endif if (session->banner_TxRx_state == libssh2_NB_state_idle) { if (session->local.banner) { /* setopt_string will have given us our \r\n characters */ banner_len = strlen((char *) session->local.banner); banner = (char *) session->local.banner; }#ifdef LIBSSH2DEBUG /* Hack and slash to avoid sending CRLF in debug output */ if (banner_len < 256) { memcpy(banner_dup, banner, banner_len - 2); banner_dup[banner_len - 2] = '\0'; } else { memcpy(banner_dup, banner, 255); banner[255] = '\0'; } _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Sending Banner: %s", banner_dup);#endif session->banner_TxRx_state = libssh2_NB_state_created; } /* no outgoing block yet! */ session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND; ret = LIBSSH2_SEND(session, banner + session->banner_TxRx_total_send, banner_len - session->banner_TxRx_total_send, LIBSSH2_SOCKET_SEND_FLAGS(session)); if (ret < 0) _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, "Error sending %d bytes: %d", banner_len - session->banner_TxRx_total_send, -ret); else _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, "Sent %d/%d bytes at %p+%d", ret, banner_len - session->banner_TxRx_total_send, banner, session->banner_TxRx_total_send); if (ret != (banner_len - session->banner_TxRx_total_send)) { if (ret >= 0 || ret == -EAGAIN) { /* the whole packet could not be sent, save the what was */ session->socket_block_directions = LIBSSH2_SESSION_BLOCK_OUTBOUND; if (ret > 0) session->banner_TxRx_total_send += ret; return LIBSSH2_ERROR_EAGAIN; } session->banner_TxRx_state = libssh2_NB_state_idle; session->banner_TxRx_total_send = 0; return LIBSSH2_ERROR_SOCKET_RECV; } /* Set the state back to idle */ session->banner_TxRx_state = libssh2_NB_state_idle; session->banner_TxRx_total_send = 0; return 0;} /* * session_nonblock() sets the given socket to either blocking or * non-blocking mode based on the 'nonblock' boolean argument. This function * is copied from the libcurl sources with permission. */static intsession_nonblock(libssh2_socket_t sockfd, /* operate on this */ int nonblock /* TRUE or FALSE */ ){#undef SETBLOCK#define SETBLOCK 0#ifdef HAVE_O_NONBLOCK /* most recent unix versions */ int flags; flags = fcntl(sockfd, F_GETFL, 0); if (nonblock) return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); else return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK));#undef SETBLOCK#define SETBLOCK 1#endif #if defined(HAVE_FIONBIO) && (SETBLOCK == 0) /* older unix versions and VMS*/ int flags; flags = nonblock; return ioctl(sockfd, FIONBIO, &flags);#undef SETBLOCK#define SETBLOCK 2#endif #if defined(HAVE_IOCTLSOCKET) && (SETBLOCK == 0) /* Windows? */ unsigned long flags; flags = nonblock; return ioctlsocket(sockfd, FIONBIO, &flags);#undef SETBLOCK#define SETBLOCK 3#endif #if defined(HAVE_IOCTLSOCKET_CASE) && (SETBLOCK == 0) /* presumably for Amiga */ return IoctlSocket(sockfd, FIONBIO, (long) nonblock);#undef SETBLOCK#define SETBLOCK 4#endif #if defined(HAVE_SO_NONBLOCK) && (SETBLOCK == 0) /* BeOS */ long b = nonblock ? 1 : 0; return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));#undef SETBLOCK#define SETBLOCK 5#endif #ifdef HAVE_DISABLED_NONBLOCKING return 0; /* returns success */#undef SETBLOCK#define SETBLOCK 6#endif #if (SETBLOCK == 0)#error "no non-blocking method was found/used/set"#endif} /* * get_socket_nonblocking() * * gets the given blocking or non-blocking state of the socket. */static intget_socket_nonblocking(int sockfd){ /* operate on this */#undef GETBLOCK#define GETBLOCK 0#ifdef HAVE_O_NONBLOCK /* most recent unix versions */ int flags; if ((flags = fcntl(sockfd, F_GETFL, 0)) == -1) { /* Assume blocking on error */ return 1; } return (flags & O_NONBLOCK);#undef GETBLOCK#define GETBLOCK 1#endif #if defined(WSAEWOULDBLOCK) && (GETBLOCK == 0) /* Windows? */ unsigned int option_value; socklen_t option_len = sizeof(option_value); if (getsockopt (sockfd, SOL_SOCKET, SO_ERROR, (void *) &option_value, &option_len)) { /* Assume blocking on error */ return 1; } return (int) option_value;#undef GETBLOCK#define GETBLOCK 2#endif #if defined(HAVE_SO_NONBLOCK) && (GETBLOCK == 0) /* BeOS */ long b; if (getsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b))) { /* Assume blocking on error */ return 1; } return (int) b;#undef GETBLOCK#define GETBLOCK 5#endif #if defined(SO_STATE) && defined( __VMS ) && (GETBLOCK == 0) /* VMS TCP/IP Services */ size_t sockstat = 0; int callstat = 0; size_t size = sizeof( int ); callstat = getsockopt(sockfd, SOL_SOCKET, SO_STATE, (char *)&sockstat, &size); if ( callstat == -1 ) return(0); if ( (sockstat&SS_NBIO) )return(1); return(0); #undef GETBLOCK#define GETBLOCK 6#endif #ifdef HAVE_DISABLED_NONBLOCKING return 1; /* returns blocking */#undef GETBLOCK#define GETBLOCK 7#endif #if (GETBLOCK == 0)#error "no non-blocking method was found/used/get"#endif} /* libssh2_session_banner_set * Set the local banner to use in the server handshake. */LIBSSH2_API intlibssh2_session_banner_set(LIBSSH2_SESSION * session, const char *banner){ size_t banner_len = banner ? strlen(banner) : 0; if (session->local.banner) { LIBSSH2_FREE(session, session->local.banner); session->local.banner = NULL; } if (!banner_len) return 0; session->local.banner = LIBSSH2_ALLOC(session, banner_len + 3); if (!session->local.banner) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for local banner"); } memcpy(session->local.banner, banner, banner_len); /* first zero terminate like this so that the debug output is nice */ session->local.banner[banner_len] = '\0'; _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Setting local Banner: %s", session->local.banner); session->local.banner[banner_len++] = '\r'; session->local.banner[banner_len++] = '\n'; session->local.banner[banner_len] = '\0'; return 0;} /* libssh2_banner_set * Set the local banner. DEPRECATED VERSION */LIBSSH2_API intlibssh2_banner_set(LIBSSH2_SESSION * session, const char *banner){ return libssh2_session_banner_set(session, banner);} /* * libssh2_session_init_ex * * Allocate and initialize a libssh2 session structure. Allows for malloc * callbacks in case the calling program has its own memory manager It's * allowable (but unadvisable) to define some but not all of the malloc * callbacks An additional pointer value may be optionally passed to be sent * to the callbacks (so they know who's asking) */LIBSSH2_API LIBSSH2_SESSION *libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)), LIBSSH2_FREE_FUNC((*my_free)), LIBSSH2_REALLOC_FUNC((*my_realloc)), void *abstract){ LIBSSH2_ALLOC_FUNC((*local_alloc)) = libssh2_default_alloc; LIBSSH2_FREE_FUNC((*local_free)) = libssh2_default_free; LIBSSH2_REALLOC_FUNC((*local_realloc)) = libssh2_default_realloc; LIBSSH2_SESSION *session; if (my_alloc) { local_alloc = my_alloc; } if (my_free) { local_free = my_free; } if (my_realloc) { local_realloc = my_realloc; } session = local_alloc(sizeof(LIBSSH2_SESSION), &abstract); if (session) { memset(session, 0, sizeof(LIBSSH2_SESSION)); session->alloc = local_alloc; session->free = local_free; session->realloc = local_realloc; session->send = _libssh2_send; session->recv = _libssh2_recv; session->abstract = abstract; session->api_timeout = 0; /* timeout-free API by default */ session->api_block_mode = 1; /* blocking API by default */ _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "New session resource allocated"); _libssh2_init_if_needed ();Lines 1–500 of 1751. Load more
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org> * Copyright (c) 2009-2011 by Daniel Stenberg * Copyright (c) 2010 Simon Josefsson <simon@josefsson.org> * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * Neither the name of the copyright holder nor the names * of any other contributors may be used to endorse or * promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. */ #include "libssh2_priv.h" #include <errno.h> #ifdef HAVE_UNISTD_H #include <unistd.h> #endif #include <stdlib.h> #include <fcntl.h> #ifdef HAVE_GETTIMEOFDAY #include <sys/time.h> #endif #ifdef HAVE_ALLOCA_H #include <alloca.h> #endif #include "transport.h" #include "session.h" #include "channel.h" #include "mac.h" #include "misc.h" /* libssh2_default_alloc */ static LIBSSH2_ALLOC_FUNC(libssh2_default_alloc) { (void) abstract; return malloc(count); } /* libssh2_default_free */ static LIBSSH2_FREE_FUNC(libssh2_default_free) { (void) abstract; free(ptr); } /* libssh2_default_realloc */ static LIBSSH2_REALLOC_FUNC(libssh2_default_realloc) { (void) abstract; return realloc(ptr, count); } /* * banner_receive * * Wait for a hello from the remote host * Allocate a buffer and store the banner in session->remote.banner * Returns: 0 on success, LIBSSH2_ERROR_EAGAIN if read would block, negative * on failure */ static int banner_receive(LIBSSH2_SESSION * session) { int ret; int banner_len; if (session->banner_TxRx_state == libssh2_NB_state_idle) { banner_len = 0; session->banner_TxRx_state = libssh2_NB_state_created; } else { banner_len = session->banner_TxRx_total_send; } while ((banner_len < (int) sizeof(session->banner_TxRx_banner)) && ((banner_len == 0) || (session->banner_TxRx_banner[banner_len - 1] != '\n'))) { char c = '\0'; /* no incoming block yet! */ session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_INBOUND; ret = LIBSSH2_RECV(session, &c, 1, LIBSSH2_SOCKET_RECV_FLAGS(session)); if (ret < 0) { if(session->api_block_mode || (ret != -EAGAIN)) /* ignore EAGAIN when non-blocking */ _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, "Error recving %d bytes: %d", 1, -ret); } else _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, "Recved %d bytes banner", ret); if (ret < 0) { if (ret == -EAGAIN) { session->socket_block_directions = LIBSSH2_SESSION_BLOCK_INBOUND; session->banner_TxRx_total_send = banner_len; return LIBSSH2_ERROR_EAGAIN; } /* Some kinda error */ session->banner_TxRx_state = libssh2_NB_state_idle; session->banner_TxRx_total_send = 0; return LIBSSH2_ERROR_SOCKET_RECV; } if (ret == 0) { session->socket_state = LIBSSH2_SOCKET_DISCONNECTED; return LIBSSH2_ERROR_SOCKET_DISCONNECT; } if (c == '\0') { /* NULLs are not allowed in SSH banners */ session->banner_TxRx_state = libssh2_NB_state_idle; session->banner_TxRx_total_send = 0; return LIBSSH2_ERROR_BANNER_RECV; } session->banner_TxRx_banner[banner_len++] = c; } while (banner_len && ((session->banner_TxRx_banner[banner_len - 1] == '\n') || (session->banner_TxRx_banner[banner_len - 1] == '\r'))) { banner_len--; } /* From this point on, we are done here */ session->banner_TxRx_state = libssh2_NB_state_idle; session->banner_TxRx_total_send = 0; if (!banner_len) return LIBSSH2_ERROR_BANNER_RECV; session->remote.banner = LIBSSH2_ALLOC(session, banner_len + 1); if (!session->remote.banner) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Error allocating space for remote banner"); } memcpy(session->remote.banner, session->banner_TxRx_banner, banner_len); session->remote.banner[banner_len] = '\0'; _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Received Banner: %s", session->remote.banner); return LIBSSH2_ERROR_NONE; } /* * banner_send * * Send the default banner, or the one set via libssh2_setopt_string * * Returns LIBSSH2_ERROR_EAGAIN if it would block - and if it does so, you * should call this function again as soon as it is likely that more data can * be sent, and this function should then be called with the same argument set * (same data pointer and same data_len) until zero or failure is returned. */ static int banner_send(LIBSSH2_SESSION * session) { char *banner = (char *) LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF; int banner_len = sizeof(LIBSSH2_SSH_DEFAULT_BANNER_WITH_CRLF) - 1; ssize_t ret; #ifdef LIBSSH2DEBUG char banner_dup[256]; #endif if (session->banner_TxRx_state == libssh2_NB_state_idle) { if (session->local.banner) { /* setopt_string will have given us our \r\n characters */ banner_len = strlen((char *) session->local.banner); banner = (char *) session->local.banner; } #ifdef LIBSSH2DEBUG /* Hack and slash to avoid sending CRLF in debug output */ if (banner_len < 256) { memcpy(banner_dup, banner, banner_len - 2); banner_dup[banner_len - 2] = '\0'; } else { memcpy(banner_dup, banner, 255); banner[255] = '\0'; } _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Sending Banner: %s", banner_dup); #endif session->banner_TxRx_state = libssh2_NB_state_created; } /* no outgoing block yet! */ session->socket_block_directions &= ~LIBSSH2_SESSION_BLOCK_OUTBOUND; ret = LIBSSH2_SEND(session, banner + session->banner_TxRx_total_send, banner_len - session->banner_TxRx_total_send, LIBSSH2_SOCKET_SEND_FLAGS(session)); if (ret < 0) _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, "Error sending %d bytes: %d", banner_len - session->banner_TxRx_total_send, -ret); else _libssh2_debug(session, LIBSSH2_TRACE_SOCKET, "Sent %d/%d bytes at %p+%d", ret, banner_len - session->banner_TxRx_total_send, banner, session->banner_TxRx_total_send); if (ret != (banner_len - session->banner_TxRx_total_send)) { if (ret >= 0 || ret == -EAGAIN) { /* the whole packet could not be sent, save the what was */ session->socket_block_directions = LIBSSH2_SESSION_BLOCK_OUTBOUND; if (ret > 0) session->banner_TxRx_total_send += ret; return LIBSSH2_ERROR_EAGAIN; } session->banner_TxRx_state = libssh2_NB_state_idle; session->banner_TxRx_total_send = 0; return LIBSSH2_ERROR_SOCKET_RECV; } /* Set the state back to idle */ session->banner_TxRx_state = libssh2_NB_state_idle; session->banner_TxRx_total_send = 0; return 0; } /* * session_nonblock() sets the given socket to either blocking or * non-blocking mode based on the 'nonblock' boolean argument. This function * is copied from the libcurl sources with permission. */ static int session_nonblock(libssh2_socket_t sockfd, /* operate on this */ int nonblock /* TRUE or FALSE */ ) { #undef SETBLOCK #define SETBLOCK 0 #ifdef HAVE_O_NONBLOCK /* most recent unix versions */ int flags; flags = fcntl(sockfd, F_GETFL, 0); if (nonblock) return fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); else return fcntl(sockfd, F_SETFL, flags & (~O_NONBLOCK)); #undef SETBLOCK #define SETBLOCK 1 #endif #if defined(HAVE_FIONBIO) && (SETBLOCK == 0) /* older unix versions and VMS*/ int flags; flags = nonblock; return ioctl(sockfd, FIONBIO, &flags); #undef SETBLOCK #define SETBLOCK 2 #endif #if defined(HAVE_IOCTLSOCKET) && (SETBLOCK == 0) /* Windows? */ unsigned long flags; flags = nonblock; return ioctlsocket(sockfd, FIONBIO, &flags); #undef SETBLOCK #define SETBLOCK 3 #endif #if defined(HAVE_IOCTLSOCKET_CASE) && (SETBLOCK == 0) /* presumably for Amiga */ return IoctlSocket(sockfd, FIONBIO, (long) nonblock); #undef SETBLOCK #define SETBLOCK 4 #endif #if defined(HAVE_SO_NONBLOCK) && (SETBLOCK == 0) /* BeOS */ long b = nonblock ? 1 : 0; return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); #undef SETBLOCK #define SETBLOCK 5 #endif #ifdef HAVE_DISABLED_NONBLOCKING return 0; /* returns success */ #undef SETBLOCK #define SETBLOCK 6 #endif #if (SETBLOCK == 0) #error "no non-blocking method was found/used/set" #endif } /* * get_socket_nonblocking() * * gets the given blocking or non-blocking state of the socket. */ static int get_socket_nonblocking(int sockfd) { /* operate on this */ #undef GETBLOCK #define GETBLOCK 0 #ifdef HAVE_O_NONBLOCK /* most recent unix versions */ int flags; if ((flags = fcntl(sockfd, F_GETFL, 0)) == -1) { /* Assume blocking on error */ return 1; } return (flags & O_NONBLOCK); #undef GETBLOCK #define GETBLOCK 1 #endif #if defined(WSAEWOULDBLOCK) && (GETBLOCK == 0) /* Windows? */ unsigned int option_value; socklen_t option_len = sizeof(option_value); if (getsockopt (sockfd, SOL_SOCKET, SO_ERROR, (void *) &option_value, &option_len)) { /* Assume blocking on error */ return 1; } return (int) option_value; #undef GETBLOCK #define GETBLOCK 2 #endif #if defined(HAVE_SO_NONBLOCK) && (GETBLOCK == 0) /* BeOS */ long b; if (getsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b))) { /* Assume blocking on error */ return 1; } return (int) b; #undef GETBLOCK #define GETBLOCK 5 #endif #if defined(SO_STATE) && defined( __VMS ) && (GETBLOCK == 0) /* VMS TCP/IP Services */ size_t sockstat = 0; int callstat = 0; size_t size = sizeof( int ); callstat = getsockopt(sockfd, SOL_SOCKET, SO_STATE, (char *)&sockstat, &size); if ( callstat == -1 ) return(0); if ( (sockstat&SS_NBIO) )return(1); return(0); #undef GETBLOCK #define GETBLOCK 6 #endif #ifdef HAVE_DISABLED_NONBLOCKING return 1; /* returns blocking */ #undef GETBLOCK #define GETBLOCK 7 #endif #if (GETBLOCK == 0) #error "no non-blocking method was found/used/get" #endif } /* libssh2_session_banner_set * Set the local banner to use in the server handshake. */ LIBSSH2_API int libssh2_session_banner_set(LIBSSH2_SESSION * session, const char *banner) { size_t banner_len = banner ? strlen(banner) : 0; if (session->local.banner) { LIBSSH2_FREE(session, session->local.banner); session->local.banner = NULL; } if (!banner_len) return 0; session->local.banner = LIBSSH2_ALLOC(session, banner_len + 3); if (!session->local.banner) { return _libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocate memory for local banner"); } memcpy(session->local.banner, banner, banner_len); /* first zero terminate like this so that the debug output is nice */ session->local.banner[banner_len] = '\0'; _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Setting local Banner: %s", session->local.banner); session->local.banner[banner_len++] = '\r'; session->local.banner[banner_len++] = '\n'; session->local.banner[banner_len] = '\0'; return 0; } /* libssh2_banner_set * Set the local banner. DEPRECATED VERSION */ LIBSSH2_API int libssh2_banner_set(LIBSSH2_SESSION * session, const char *banner) { return libssh2_session_banner_set(session, banner); } /* * libssh2_session_init_ex * * Allocate and initialize a libssh2 session structure. Allows for malloc * callbacks in case the calling program has its own memory manager It's * allowable (but unadvisable) to define some but not all of the malloc * callbacks An additional pointer value may be optionally passed to be sent * to the callbacks (so they know who's asking) */ LIBSSH2_API LIBSSH2_SESSION * libssh2_session_init_ex(LIBSSH2_ALLOC_FUNC((*my_alloc)), LIBSSH2_FREE_FUNC((*my_free)), LIBSSH2_REALLOC_FUNC((*my_realloc)), void *abstract) { LIBSSH2_ALLOC_FUNC((*local_alloc)) = libssh2_default_alloc; LIBSSH2_FREE_FUNC((*local_free)) = libssh2_default_free; LIBSSH2_REALLOC_FUNC((*local_realloc)) = libssh2_default_realloc; LIBSSH2_SESSION *session; if (my_alloc) { local_alloc = my_alloc; } if (my_free) { local_free = my_free; } if (my_realloc) { local_realloc = my_realloc; } session = local_alloc(sizeof(LIBSSH2_SESSION), &abstract); if (session) { memset(session, 0, sizeof(LIBSSH2_SESSION)); session->alloc = local_alloc; session->free = local_free; session->realloc = local_realloc; session->send = _libssh2_send; session->recv = _libssh2_recv; session->abstract = abstract; session->api_timeout = 0; /* timeout-free API by default */ session->api_block_mode = 1; /* blocking API by default */ _libssh2_debug(session, LIBSSH2_TRACE_TRANS, "New session resource allocated"); _libssh2_init_if_needed ();