diff packet.c @ 1069:2fa71c3b2827 pam

merge pam branch up to date
author Matt Johnston <matt@ucc.asn.au>
date Mon, 16 Mar 2015 21:34:05 +0800
parents 16584026a1f0
children 686cd3e8e13e
line wrap: on
line diff
--- a/packet.c	Fri Jan 23 22:32:49 2015 +0800
+++ b/packet.c	Mon Mar 16 21:34:05 2015 +0800
@@ -34,6 +34,7 @@
 #include "service.h"
 #include "auth.h"
 #include "channel.h"
+#include "netio.h"
 
 static int read_packet_init();
 static void make_mac(unsigned int seqno, const struct key_context_directional * key_state,
@@ -55,14 +56,10 @@
 /* non-blocking function writing out a current encrypted packet */
 void write_packet() {
 
-	int len, written;
-	buffer * writebuf = NULL;
-	unsigned packet_type;
+	ssize_t written;
 #ifdef HAVE_WRITEV
 	struct iovec *iov = NULL;
-	int i;
-	struct Link *l;
-	int iov_max_count;
+	int iov_count;
 #endif
 	
 	TRACE2(("enter write_packet"))
@@ -70,62 +67,28 @@
 
 #if defined(HAVE_WRITEV) && (defined(IOV_MAX) || defined(UIO_MAXIOV))
 
-#ifndef IOV_MAX
-#define IOV_MAX UIO_MAXIOV
-#endif
-
-	/* Make sure the size of the iov is below the maximum allowed by the OS. */
-	iov_max_count = ses.writequeue.count;
-	if (iov_max_count > IOV_MAX)
-	{
-		iov_max_count = IOV_MAX;
-	}
-
-	iov = m_malloc(sizeof(*iov) * iov_max_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);
-		TRACE2(("write_packet writev #%d  type %d len %d/%d", i, packet_type,
-				len, writebuf->len-1))
-		iov[i].iov_base = buf_getptr(writebuf, len);
-		iov[i].iov_len = len;
-	}
+	iov = packet_queue_to_iovec(&ses.writequeue, &iov_count);
 	/* This may return EAGAIN. The main loop sometimes
 	calls write_packet() without bothering to test with select() since
 	it's likely to be necessary */
-	written = writev(ses.sock_out, iov, iov_max_count);
+	written = writev(ses.sock_out, iov, iov_count);
 	if (written < 0) {
 		if (errno == EINTR || errno == EAGAIN) {
+			TRACE2(("leave write_packet: EINTR"))
 			m_free(iov);
-			TRACE2(("leave write_packet: EINTR"))
 			return;
 		} else {
 			dropbear_exit("Error writing: %s", strerror(errno));
 		}
 	}
+	m_free(iov);
+
+	packet_queue_consume(&ses.writequeue, written);
 
 	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 /* No writev () */
 	/* Get the next buffer in the queue of encrypted packets to write*/
 	writebuf = (buffer*)examine(&ses.writequeue);
@@ -283,18 +246,18 @@
 	}
 	len = buf_getint(ses.readbuf) + 4 + macsize;
 
-	TRACE2(("packet size is %d, block %d mac %d", len, blocksize, macsize))
+	TRACE2(("packet size is %u, block %u mac %u", len, blocksize, macsize))
 
 
 	/* check packet length */
 	if ((len > RECV_MAX_PACKET_LEN) ||
 		(len < MIN_PACKET_LEN + macsize) ||
 		((len - macsize) % blocksize != 0)) {
-		dropbear_exit("Integrity error (bad packet size %d)", len);
+		dropbear_exit("Integrity error (bad packet size %u)", len);
 	}
 
 	if (len > ses.readbuf->size) {
-		buf_resize(ses.readbuf, len);		
+		ses.readbuf = buf_resize(ses.readbuf, len);		
 	}
 	buf_setlen(ses.readbuf, len);
 	buf_setpos(ses.readbuf, blocksize);
@@ -342,7 +305,7 @@
 	/* - 4 - 1 is for LEN and PADLEN values */
 	len = ses.readbuf->len - padlen - 4 - 1 - macsize;
 	if ((len > RECV_MAX_PAYLOAD_LEN+ZLIB_COMPRESS_EXPANSION) || (len < 1)) {
-		dropbear_exit("Bad packet size %d", len);
+		dropbear_exit("Bad packet size %u", len);
 	}
 
 	buf_setpos(ses.readbuf, PACKET_PAYLOAD_OFF);
@@ -351,18 +314,21 @@
 	if (is_compress_recv()) {
 		/* decompress */
 		ses.payload = buf_decompress(ses.readbuf, len);
+		buf_setpos(ses.payload, 0);
+		ses.payload_beginning = 0;
+		buf_free(ses.readbuf);
 	} else 
 #endif
 	{
+		ses.payload = ses.readbuf;
+		ses.payload_beginning = ses.payload->pos;
+		buf_setlen(ses.payload, ses.payload->pos + len);
 		/* copy payload */
-		ses.payload = buf_new(len);
-		memcpy(ses.payload->data, buf_getptr(ses.readbuf, len), len);
-		buf_incrlen(ses.payload, len);
+		//ses.payload = buf_new(len);
+		//memcpy(ses.payload->data, buf_getptr(ses.readbuf, len), len);
+		//buf_incrlen(ses.payload, len);
 	}
-
-	buf_free(ses.readbuf);
 	ses.readbuf = NULL;
-	buf_setpos(ses.payload, 0);
 
 	ses.recvseq++;
 
@@ -435,7 +401,7 @@
 				dropbear_exit("bad packet, oversized decompressed");
 			}
 			new_size = MIN(RECV_MAX_PAYLOAD_LEN, ret->size + ZLIB_DECOMPRESS_INCR);
-			buf_resize(ret, new_size);
+			ret = buf_resize(ret, new_size);
 		}
 	}
 }
@@ -674,7 +640,8 @@
 
 #ifndef DISABLE_ZLIB
 /* compresses len bytes from src, outputting to dest (starting from the
- * respective current positions. */
+ * respective current positions. dest must have sufficient space,
+ * len+ZLIB_COMPRESS_EXPANSION */
 static void buf_compress(buffer * dest, buffer * src, unsigned int len) {
 
 	unsigned int endpos = src->pos + len;
@@ -682,38 +649,28 @@
 
 	TRACE2(("enter buf_compress"))
 
-	while (1) {
-
-		ses.keys->trans.zstream->avail_in = endpos - src->pos;
-		ses.keys->trans.zstream->next_in = 
-			buf_getptr(src, ses.keys->trans.zstream->avail_in);
+	dropbear_assert(dest->size - dest->pos >= len+ZLIB_COMPRESS_EXPANSION);
 
-		ses.keys->trans.zstream->avail_out = dest->size - dest->pos;
-		ses.keys->trans.zstream->next_out =
-			buf_getwriteptr(dest, ses.keys->trans.zstream->avail_out);
+	ses.keys->trans.zstream->avail_in = endpos - src->pos;
+	ses.keys->trans.zstream->next_in = 
+		buf_getptr(src, ses.keys->trans.zstream->avail_in);
 
-		result = deflate(ses.keys->trans.zstream, Z_SYNC_FLUSH);
-
-		buf_setpos(src, endpos - ses.keys->trans.zstream->avail_in);
-		buf_setlen(dest, dest->size - ses.keys->trans.zstream->avail_out);
-		buf_setpos(dest, dest->len);
+	ses.keys->trans.zstream->avail_out = dest->size - dest->pos;
+	ses.keys->trans.zstream->next_out =
+		buf_getwriteptr(dest, ses.keys->trans.zstream->avail_out);
 
-		if (result != Z_OK) {
-			dropbear_exit("zlib error");
-		}
+	result = deflate(ses.keys->trans.zstream, Z_SYNC_FLUSH);
 
-		if (ses.keys->trans.zstream->avail_in == 0) {
-			break;
-		}
+	buf_setpos(src, endpos - ses.keys->trans.zstream->avail_in);
+	buf_setlen(dest, dest->size - ses.keys->trans.zstream->avail_out);
+	buf_setpos(dest, dest->len);
 
-		dropbear_assert(ses.keys->trans.zstream->avail_out == 0);
+	if (result != Z_OK) {
+		dropbear_exit("zlib error");
+	}
 
-		/* the buffer has been filled, we must extend. This only happens in
-		 * unusual circumstances where the data grows in size after deflate(),
-		 * but it is possible */
-		buf_resize(dest, dest->size + ZLIB_COMPRESS_EXPANSION);
-
-	}
+	/* fails if destination buffer wasn't large enough */
+	dropbear_assert(ses.keys->trans.zstream->avail_in == 0);
 	TRACE2(("leave buf_compress"))
 }
 #endif