diff --git a/common-kex.c b/common-kex.c
index 052324b499a3ed15403a2a80aabfe10f082300a8..cb5cd96425b709741f35bae67cd70a0840ecbdcb 100644
--- a/common-kex.c
+++ b/common-kex.c
@@ -371,7 +371,9 @@ static void gen_new_zstreams() {
 		ses.newkeys->trans.zstream->zalloc = Z_NULL;
 		ses.newkeys->trans.zstream->zfree = Z_NULL;
 	
-		if (deflateInit(ses.newkeys->trans.zstream, Z_DEFAULT_COMPRESSION) 
+		if (deflateInit2(ses.newkeys->trans.zstream, Z_DEFAULT_COMPRESSION,
+					Z_DEFLATED, DROPBEAR_ZLIB_WINDOW_BITS, 
+					DROPBEAR_ZLIB_MEM_LEVEL, Z_DEFAULT_STRATEGY)
 				!= Z_OK) {
 			dropbear_exit("zlib error");
 		}
diff --git a/options.h b/options.h
index 021457cf1b9651659f2ed53629f7dc472244a96a..412cfc6ad78ea84daee1b5d5c8ec32bcbb78b199 100644
--- a/options.h
+++ b/options.h
@@ -87,7 +87,8 @@ much traffic. */
 #define DROPBEAR_AES128
 #define DROPBEAR_3DES
 #define DROPBEAR_AES256
-#define DROPBEAR_BLOWFISH
+/* Compiling in Blowfish will add ~6kB to runtime heap memory usage */
+/*#define DROPBEAR_BLOWFISH*/
 #define DROPBEAR_TWOFISH256
 #define DROPBEAR_TWOFISH128
 
@@ -130,6 +131,21 @@ much traffic. */
  * if the random number source isn't good. In general this isn't required */
 /* #define DSS_PROTOK */
 
+/* Control the memory/performance/compression tradeoff for zlib.
+ * Set windowBits=8, memLevel=1 for least memory usage, see your system's
+ * zlib.h for full details.
+ * Default settings (windowBits=15, memLevel=8) will use 
+ * 256kB for compression + 32kB for decompression.
+ * windowBits=8, memLevel=1 will use 10kB compression + 32kB decompression.
+ * Note that windowBits is only set for deflate() - inflate() always uses the
+ * default of 15 so as to interoperate with other clients. */
+#ifndef DROPBEAR_ZLIB_WINDOW_BITS
+#define DROPBEAR_ZLIB_WINDOW_BITS 15 
+#endif
+#ifndef DROPBEAR_ZLIB_MEM_LEVEL
+#define DROPBEAR_ZLIB_MEM_LEVEL 8
+#endif
+
 /* Whether to do reverse DNS lookups. */
 #define DO_HOST_LOOKUP
 
@@ -248,13 +264,19 @@ much traffic. */
    significant difference to network performance. 24kB was empirically
    chosen for a 100mbit ethernet network. The value can be altered at
    runtime with the -W argument. */
+#ifndef DEFAULT_RECV_WINDOW
 #define DEFAULT_RECV_WINDOW 24576
+#endif
 /* Maximum size of a received SSH data packet - this _MUST_ be >= 32768
    in order to interoperate with other implementations */
+#ifndef RECV_MAX_PAYLOAD_LEN
 #define RECV_MAX_PAYLOAD_LEN 32768
+#endif
 /* Maximum size of a transmitted data packet - this can be any value,
    though increasing it may not make a significant difference. */
+#ifndef TRANS_MAX_PAYLOAD_LEN
 #define TRANS_MAX_PAYLOAD_LEN 16384
+#endif
 
 /* Ensure that data is transmitted every KEEPALIVE seconds. This can
 be overridden at runtime with -K. 0 disables keepalives */
diff --git a/packet.c b/packet.c
index 37ffdd2dd988e42b3467b35570c998b3dea4452b..9621bbd3b5d734b0ce3b202f614c69a5a24e47ee 100644
--- a/packet.c
+++ b/packet.c
@@ -261,7 +261,7 @@ void decrypt_packet() {
 		
 	/* payload length */
 	/* - 4 - 1 is for LEN and PADLEN values */
-	len = ses.readbuf->len - padlen - 4 - 1;
+	len = ses.readbuf->len - padlen - 4 - 1 - macsize;
 	if ((len > RECV_MAX_PAYLOAD_LEN) || (len < 1)) {
 		dropbear_exit("bad packet size");
 	}
diff --git a/session.h b/session.h
index d02666dd388e3a9bb40034a196cb86bc034056c5..eec7f01ab3f0c72a25ceee5c385b4628427ced92 100644
--- a/session.h
+++ b/session.h
@@ -213,6 +213,10 @@ struct serversession {
 	/* The numeric address they connected from, used for logging */
 	char * addrstring;
 
+#ifdef __uClinux__
+	pid_t server_pid;
+#endif
+
 };
 
 typedef enum {
diff --git a/svr-session.c b/svr-session.c
index eaccfe531fd81b7951460932d60d57dcdb07e42c..89b16cb2fc1c8ddeec28259fe22c413fb2e28761 100644
--- a/svr-session.c
+++ b/svr-session.c
@@ -85,6 +85,10 @@ void svr_session(int sock, int childpipe,
 	/* Initialise server specific parts of the session */
 	svr_ses.childpipe = childpipe;
 	svr_ses.addrstring = addrstring;
+#ifdef __uClinux__
+	svr_ses.server_pid = getpid();
+#endif
+	svr_ses.addrstring = addrstring;
 	svr_authinitialise();
 	chaninitialise(svr_chantypes);
 	svr_chansessinitialise();
@@ -144,11 +148,20 @@ void svr_dropbear_exit(int exitcode, const char* format, va_list param) {
 
 	_dropbear_log(LOG_INFO, fmtbuf, param);
 
-	/* free potential public key options */
-	svr_pubkey_options_cleanup();
+#ifdef __uClinux__
+	/* only the main server process should cleanup - we don't want
+	 * forked children doing that */
+	if (svr_ses.server_pid == getpid())
+#else
+	if (1)
+#endif
+	{
+		/* free potential public key options */
+		svr_pubkey_options_cleanup();
 
-	/* must be after we've done with username etc */
-	common_session_cleanup();
+		/* must be after we've done with username etc */
+		common_session_cleanup();
+	}
 
 	exit(exitcode);