summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2013-03-31 23:15:35 +0800
committerMatt Johnston <matt@ucc.asn.au>2013-03-31 23:15:35 +0800
commitb46080d31a27389c5d9b277a32948aab8abee5d0 (patch)
tree51608aae2944423ab4b8cfd8f3c7dfd2474f5d54
parent8a13425b1699d47f785b68ebac3104c46bbd21b5 (diff)
downloaddropbear-b46080d31a27389c5d9b277a32948aab8abee5d0.tar.gz
Try using writev() for writing packets out to tcp
-rw-r--r--configure.ac4
-rw-r--r--includes.h4
-rw-r--r--packet.c66
-rw-r--r--queue.h2
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))
diff --git a/includes.h b/includes.h
index 571a3be..203ccfd 100644
--- a/includes.h
+++ b/includes.h
@@ -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"
diff --git a/packet.c b/packet.c
index f979cae..5cd60c2 100644
--- a/packet.c
+++ b/packet.c
@@ -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"))
}
diff --git a/queue.h b/queue.h
index 80fbb9d..8cffab7 100644
--- a/queue.h
+++ b/queue.h
@@ -36,7 +36,7 @@ struct Queue {
struct Link* head;
struct Link* tail;
- unsigned int count; /* safety value */
+ unsigned int count;
};