diff options
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | includes.h | 4 | ||||
-rw-r--r-- | packet.c | 66 | ||||
-rw-r--r-- | queue.h | 2 |
4 files changed, 66 insertions, 10 deletions
diff --git a/configure.ac b/configure.ac index 3b82bb7..05461f3 100644 --- a/configure.ac +++ b/configure.ac @@ -211,7 +211,7 @@ AC_ARG_ENABLE(shadow, # Checks for header files. AC_HEADER_STDC AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS([fcntl.h limits.h netinet/in.h netinet/tcp.h stdlib.h string.h sys/socket.h sys/time.h termios.h unistd.h crypt.h pty.h ioctl.h libutil.h libgen.h inttypes.h stropts.h utmp.h utmpx.h lastlog.h paths.h util.h netdb.h security/pam_appl.h pam/pam_appl.h netinet/in_systm.h]) +AC_CHECK_HEADERS([fcntl.h limits.h netinet/in.h netinet/tcp.h stdlib.h string.h sys/socket.h sys/time.h termios.h unistd.h crypt.h pty.h ioctl.h libutil.h libgen.h inttypes.h stropts.h utmp.h utmpx.h lastlog.h paths.h util.h netdb.h security/pam_appl.h pam/pam_appl.h netinet/in_systm.h, sys/uio.h]) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST @@ -616,7 +616,7 @@ AC_PROG_GCC_TRADITIONAL AC_FUNC_MEMCMP AC_FUNC_SELECT_ARGTYPES AC_TYPE_SIGNAL -AC_CHECK_FUNCS([dup2 getspnam getusershell memset putenv select socket strdup clearenv strlcpy strlcat daemon basename _getpty getaddrinfo freeaddrinfo getnameinfo fork]) +AC_CHECK_FUNCS([dup2 getspnam getusershell memset putenv select socket strdup clearenv strlcpy strlcat daemon basename _getpty getaddrinfo freeaddrinfo getnameinfo fork writev]) AC_SEARCH_LIBS(basename, gen, AC_DEFINE(HAVE_BASENAME)) @@ -120,6 +120,10 @@ #include <libgen.h> #endif +#ifdef HAVE_SYS_UIO_H +#include <sys/uio.h> +#endif + #ifdef BUNDLED_LIBTOM #include "libtomcrypt/src/headers/tomcrypt.h" #include "libtommath/tommath.h" @@ -55,10 +55,60 @@ void write_packet() { buffer * writebuf = NULL; time_t now; unsigned packet_type; + int all_ignore = 1; +#ifdef HAVE_WRITEV + struct iovec *iov = NULL; + int i; + struct Link *l; +#endif TRACE(("enter write_packet")) dropbear_assert(!isempty(&ses.writequeue)); +#ifdef HAVE_WRITEV + iov = m_malloc(sizeof(*iov) * ses.writequeue.count); + for (l = ses.writequeue.head, i = 0; l; l = l->link, i++) + { + writebuf = (buffer*)l->item; + packet_type = writebuf->data[writebuf->len-1]; + len = writebuf->len - 1 - writebuf->pos; + dropbear_assert(len > 0); + all_ignore &= (packet_type == SSH_MSG_IGNORE); + iov[i].iov_base = buf_getptr(writebuf, len); + iov[i].iov_len = len; + } + written = writev(ses.sock_out, iov, ses.writequeue.count); + if (written < 0) { + if (errno == EINTR) { + m_free(iov); + TRACE(("leave writepacket: EINTR")) + return; + } else { + dropbear_exit("Error writing"); + } + } + + if (written == 0) { + ses.remoteclosed(); + } + + while (written > 0) { + writebuf = (buffer*)examine(&ses.writequeue); + len = writebuf->len - 1 - writebuf->pos; + if (len > written) { + // partial buffer write + buf_incrpos(writebuf, written); + written = 0; + } else { + written -= len; + dequeue(&ses.writequeue); + buf_free(writebuf); + } + } + + m_free(iov); + +#else /* Get the next buffer in the queue of encrypted packets to write*/ writebuf = (buffer*)examine(&ses.writequeue); @@ -78,13 +128,7 @@ void write_packet() { dropbear_exit("Error writing"); } } - - now = time(NULL); - ses.last_trx_packet_time = now; - - if (packet_type != SSH_MSG_IGNORE) { - ses.last_packet_time = now; - } + all_ignore = (packet_type == SSH_MSG_IGNORE); if (written == 0) { ses.remoteclosed(); @@ -100,6 +144,14 @@ void write_packet() { buf_incrpos(writebuf, written); } +#endif + now = time(NULL); + ses.last_trx_packet_time = now; + + if (!all_ignore) { + ses.last_packet_time = now; + } + TRACE(("leave write_packet")) } @@ -36,7 +36,7 @@ struct Queue { struct Link* head; struct Link* tail; - unsigned int count; /* safety value */ + unsigned int count; }; |