diff --git a/README b/README index 6fcba7d..3946712 100644 --- a/README +++ b/README @@ -4,6 +4,10 @@ libssh2 - SSH2 library Version 0.6 ----------- + Added LIBSSH2_FLAG_SIGPIPE to enable/disable SIGPIPE generated by send()/recv() calls. Default off. + + Added libssh2_session_flag() to set optional session flags. + Collapsed exchanging_keys/newkeys/authenticated flags into single state attribute. Fix zlib compression issue when internal buffer state misses partial sync. diff --git a/include/libssh2.h b/include/libssh2.h index 6ba59bb..47ae541 100644 --- a/include/libssh2.h +++ b/include/libssh2.h @@ -67,7 +67,7 @@ typedef long long libssh2_int64_t; #endif #define LIBSSH2_VERSION "0.5" -#define LIBSSH2_APINO 200412301450 +#define LIBSSH2_APINO 200502022145 /* Part of every banner, user specified or not */ #define LIBSSH2_SSH_BANNER "SSH-2.0-libssh2_" LIBSSH2_VERSION @@ -180,6 +180,9 @@ typedef long long libssh2_int64_t; #define LIBSSH2_METHOD_LANG_CS 8 #define LIBSSH2_METHOD_LANG_SC 9 +/* session.flags bits */ +#define LIBSSH2_FLAG_SIGPIPE 0x00000001 + typedef struct _LIBSSH2_SESSION LIBSSH2_SESSION; typedef struct _LIBSSH2_CHANNEL LIBSSH2_CHANNEL; typedef struct _LIBSSH2_LISTENER LIBSSH2_LISTENER; @@ -259,6 +262,8 @@ LIBSSH2_API int libssh2_session_method_pref(LIBSSH2_SESSION *session, int method LIBSSH2_API char *libssh2_session_methods(LIBSSH2_SESSION *session, int method_type); LIBSSH2_API int libssh2_session_last_error(LIBSSH2_SESSION *session, char **errmsg, int *errmsg_len, int want_buf); +LIBSSH2_API int libssh2_session_flag(LIBSSH2_SESSION *session, int flag, int value); + /* Userauth API */ LIBSSH2_API char *libssh2_userauth_list(LIBSSH2_SESSION *session, char *username, int username_len); LIBSSH2_API int libssh2_userauth_authenticated(LIBSSH2_SESSION *session); diff --git a/include/libssh2_priv.h b/include/libssh2_priv.h index 9074782..d79da93 100644 --- a/include/libssh2_priv.h +++ b/include/libssh2_priv.h @@ -181,6 +181,7 @@ struct _LIBSSH2_SESSION { char *hostkey_prefs; int state; + int flags; /* Agreed Key Exchange Method */ LIBSSH2_KEX_METHOD *kex; @@ -236,6 +237,16 @@ struct _LIBSSH2_SESSION { #define LIBSSH2_STATE_NEWKEYS 0x00000002 #define LIBSSH2_STATE_AUTHENTICATED 0x00000004 +/* session.flag helpers */ +#ifdef MSG_NOSIGNAL +#define LIBSSH2_SOCKET_SEND_FLAGS(session) (((session)->flags & LIBSSH2_FLAG_SIGPIPE) ? 0 : MSG_NOSIGNAL) +#define LIBSSH2_SOCKET_RECV_FLAGS(session) (((session)->flags & LIBSSH2_FLAG_SIGPIPE) ? 0 : MSG_NOSIGNAL) +#else +/* If MSG_NOSIGNAL isn't defined we're SOL on blocking SIGPIPE */ +#define LIBSSH2_SOCKET_SEND_FLAGS(session) 0 +#define LIBSSH2_SOCKET_RECV_FLAGS(session) 0 +#endif + /* libssh2 extensible ssh api, ultimately I'd like to allow loading additional methods via .so/.dll */ struct _LIBSSH2_KEX_METHOD { diff --git a/src/packet.c b/src/packet.c index 0880e7a..0ffc579 100644 --- a/src/packet.c +++ b/src/packet.c @@ -534,7 +534,7 @@ static int libssh2_blocking_read(LIBSSH2_SESSION *session, unsigned char *buf, s while (bytes_read < count) { int ret; - ret = recv(session->socket_fd, buf + bytes_read, count - bytes_read, 0); + ret = recv(session->socket_fd, buf + bytes_read, count - bytes_read, LIBSSH2_SOCKET_RECV_FLAGS(session)); if (ret < 0) { #ifdef WIN32 switch (WSAGetLastError()) { @@ -611,7 +611,7 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block) if (should_block) { read_len = libssh2_blocking_read(session, block, blocksize); } else { - read_len = recv(session->socket_fd, block, 1, 0); + read_len = recv(session->socket_fd, block, 1, LIBSSH2_SOCKET_RECV_FLAGS(session)); if (read_len <= 0) { return 0; } @@ -736,7 +736,7 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block) if (should_block) { buf_len = libssh2_blocking_read(session, buf, 5); } else { - buf_len = recv(session->socket_fd, buf, 1, 0); + buf_len = recv(session->socket_fd, buf, 1, LIBSSH2_SOCKET_RECV_FLAGS(session)); if (buf_len <= 0) { return 0; } @@ -936,7 +936,7 @@ int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned session->local.seqno++; /* Send It */ - ret = ((4 + packet_length + session->local.mac->mac_len) == send(session->socket_fd, encbuf, 4 + packet_length + session->local.mac->mac_len, 0)) ? 0 : -1; + ret = ((4 + packet_length + session->local.mac->mac_len) == send(session->socket_fd, encbuf, 4 + packet_length + session->local.mac->mac_len, LIBSSH2_SOCKET_SEND_FLAGS(session))) ? 0 : -1; /* Cleanup environment */ LIBSSH2_FREE(session, encbuf); diff --git a/src/session.c b/src/session.c index fa5b3c0..7b1987e 100644 --- a/src/session.c +++ b/src/session.c @@ -81,7 +81,7 @@ static int libssh2_banner_receive(LIBSSH2_SESSION *session) char c = '\0'; int ret; - ret = recv(session->socket_fd, &c, 1, 0); + ret = recv(session->socket_fd, &c, 1, LIBSSH2_SOCKET_RECV_FLAGS(session)); if ((ret < 0) && (ret != EAGAIN)) { /* Some kinda error, but don't break for non-blocking issues */ @@ -126,7 +126,7 @@ static int libssh2_banner_send(LIBSSH2_SESSION *session) banner = session->local.banner; } - return (send(session->socket_fd, banner, banner_len, 0) == banner_len) ? 0 : 1; + return (send(session->socket_fd, banner, banner_len, LIBSSH2_SOCKET_SEND_FLAGS(session)) == banner_len) ? 0 : 1; } /* }}} */ @@ -600,3 +600,19 @@ LIBSSH2_API int libssh2_session_last_error(LIBSSH2_SESSION *session, char **errm return session->err_code; } /* }}} */ + +/* {{{ libssh2_session_flag + * Set/Get session flags + * Passing flag==0 will avoid changing session->flags while still returning its current value + */ +LIBSSH2_API int libssh2_session_flag(LIBSSH2_SESSION *session, int flag, int value) +{ + if (value) { + session->flags |= flag; + } else { + session->flags &= ~flag; + } + + return session->flags; +} +/* }}} */