diff --git a/Makefile b/Makefile
index b0d6043..1198dc6 100644
--- a/Makefile
+++ b/Makefile
@@ -16,20 +16,20 @@ else
 endif
 
 all:
-	@cd client && make
+	@cd client && $(MAKE)
 	@echo "Compile complete!"
 	@echo "* Client: client/dnscat"
 	@echo "* Server: server/dnscat_*.rb"
 
 clean:
-	@cd client && make clean
+	@cd client && $(MAKE) clean
 
 debug:
-	@cd client && make debug
+	@cd client && $(MAKE) debug
 	@echo "Debug compile complete!"
 
 release:
-	@make clean
+	@$(MAKE) clean
 	-mkdir dist/
 	@cd client && make release
 	@mv client/dnscat .
@@ -40,7 +40,7 @@ release:
 	@echo "Release compile complete!"
 
 source_release:
-	@make clean
+	@$(MAKE) clean
 	-mkdir dist/
 	@cp -r client dnscat2_client
 	@tar -cvvjf dist/dnscat2-${VERSION}-client-source.tar.bz2 dnscat2_client
@@ -52,5 +52,5 @@ source_release:
 	@rm -rf dnscat2_server
 
 dnscat:
-	@cd client && make dnscat
+	@cd client && $(MAKE) dnscat
 
diff --git a/README.md b/README.md
index 7153665..0c1c48f 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,5 @@
+***** NOTE: The password for the .zip downloads are all "password"! *****
+
 # Introduction
 
 Welcome to dnscat2, a DNS tunnel that WON'T make you sick and kill you!
diff --git a/client/Makefile b/client/Makefile
index 297bc92..3049ead 100644
--- a/client/Makefile
+++ b/client/Makefile
@@ -9,8 +9,15 @@
 CC?=gcc
 DEBUG_CFLAGS?=-DTESTMEMORY -Werror -O0
 RELEASE_CFLAGS?=-Os
-CFLAGS?=--std=c89 -I. -Wall -D_DEFAULT_SOURCE -fstack-protector-all -Wformat -Wformat-security -g
-LIBS=-pie -Wl,-z,relro,-z,now
+CFLAGS?=--std=c89 -I. -Wall -D_DEFAULT_SOURCE  -Wformat -Wformat-security -g
+LIBS=-pie -Wl,-z,relro,-z,now 
+LDFLAGS=
+
+OS=$(shell uname -s)
+ifeq ($(OS),SunOS)
+# Solaris CC
+LDFLAGS       = -lsocket -lnsl
+endif
 
 OBJS=controller/packet.o \
 		 controller/session.o \
@@ -66,7 +73,7 @@ clean:
 	-rm -rf win32/*.vcproj.*
 
 dnscat: ${DNSCAT_DNS_OBJS}
-	${CC} ${CFLAGS} -o dnscat ${DNSCAT_DNS_OBJS}
+	${CC} ${CFLAGS} -o dnscat ${DNSCAT_DNS_OBJS} ${LDFLAGS}
 	@echo "*** dnscat successfully compiled"
 
 COMMANDS=drivers/command/commands_standard.h \
diff --git a/client/Makefile.win b/client/Makefile.win
new file mode 100644
index 0000000..3ddfc99
--- /dev/null
+++ b/client/Makefile.win
@@ -0,0 +1,84 @@
+# Makefile
+# By Ron Bowes
+# Created January, 2013
+#
+# (See LICENSE.md)
+#
+# Should work for Linux and BSD make.
+
+CC=i686-w64-mingw32-gcc
+DEBUG_CFLAGS?=-DTESTMEMORY -Werror -O0
+RELEASE_CFLAGS?=-Os
+# CFLAGS?=--std=c89 -I. -Wall -D_DEFAULT_SOURCE  -Wformat -Wformat-security -g -DWIN32=1 -DWINDOWS=1
+CFLAGS?=-I. -g
+LIBS=-pie -Wl,-z,relro,-z,now
+LDFLAGS= -lws2_32  -ldnsapi
+
+OS=$(shell uname -s)
+ifeq ($(OS),SunOS)
+# Solaris CC
+LDFLAGS       = -lsocket -lnsl
+endif
+
+OBJS=controller/packet.o \
+		 controller/session.o \
+		 controller/controller.o \
+		 drivers/driver.o \
+		 drivers/command/driver_command.o \
+		 drivers/command/command_packet.o \
+		 drivers/driver_console.o \
+		 drivers/driver_exec.o \
+		 drivers/driver_ping.o \
+		 libs/buffer.o \
+		 libs/crypto/encryptor.o \
+		 libs/crypto/micro-ecc/uECC.o \
+		 libs/crypto/salsa20.o \
+		 libs/crypto/sha3.o \
+		 libs/dns.o \
+		 libs/ll.o \
+		 libs/log.o \
+		 libs/memory.o \
+		 libs/select_group.o \
+		 libs/tcp.o \
+		 libs/types.o \
+		 libs/udp.o \
+		 tunnel_drivers/driver_dns.o \
+
+DNSCAT_DNS_OBJS=${OBJS} dnscat.o
+
+all: dnscat.exe
+	@echo "*** Build complete! Run 'make debug' to build a debug version!"
+
+debug: CFLAGS += $(DEBUG_CFLAGS)
+debug: dnscat
+	@echo "*** Debug build complete"
+
+release: CFLAGS += ${RELEASE_CFLAGS}
+release: dnscat
+
+nocrypto: CFLAGS += -DNO_ENCRYPTION
+nocrypto: all
+
+remove:
+	rm -f /usr/local/bin/dnscat
+
+uninstall: remove
+
+clean:
+	-rm -f *.o */*.o */*/*.o */*/*/*.o *.exe *.stackdump dnscat tcpcat test driver_tcp driver_dns
+	-rm -rf win32/Debug/
+	-rm -rf win32/Release/
+	-rm -rf win32/*.ncb
+	-rm -rf win32/*.sln
+	-rm -rf win32/*.suo
+	-rm -rf win32/*.vcproj.*
+
+dnscat.exe: ${DNSCAT_DNS_OBJS}
+	${CC} ${CFLAGS} -o dnscat.exe ${DNSCAT_DNS_OBJS} ${LDFLAGS}
+	@echo "*** dnscat successfully compiled"
+
+COMMANDS=drivers/command/commands_standard.h \
+				 drivers/command/commands_tunnel.h
+
+drivers/command/driver_command.o: drivers/command/driver_command.c ${COMMANDS}
+	${CC} -c ${CFLAGS} -o drivers/command/driver_command.o drivers/command/driver_command.c
diff --git a/client/dnscat.c b/client/dnscat.c
index c5844fb..4356373 100644
--- a/client/dnscat.c
+++ b/client/dnscat.c
@@ -17,6 +17,8 @@
 #else
 #include <getopt.h>
 #include <sys/socket.h>
+#include <sys/wait.h>
+#include <signal.h>
 #endif
 
 #include "controller/controller.h"
@@ -417,6 +419,15 @@ int main(int argc, char *argv[])
   /* This is required for win32 support. */
   winsock_initialize();
 
+#ifndef WIN32  
+  /* set the SIGCHLD handler to SIG_IGN causing zombie child processes to be reaped automatically */
+  if(signal(SIGCHLD, SIG_IGN) == SIG_ERR) 
+  {
+    perror("Couldn't set SIGCHLD handler to SIG_IGN");
+    exit(1);
+  }  
+#endif
+
   /* Set the default log level */
   log_set_min_console_level(min_log_level);
 
@@ -546,6 +557,14 @@ int main(int argc, char *argv[])
     }
   }
 
+  if(getenv("DNSCAT_DOMAIN")!=NULL) {
+    if(getenv("DNSCAT_SECRET")!=NULL) {
+      session_set_preshared_secret(getenv("DNSCAT_SECRET"));
+    }
+    tunnel_driver = create_dns_driver_internal(group, getenv("DNSCAT_DOMAIN"), "0.0.0.0", 53, DEFAULT_TYPES, NULL);
+    tunnel_driver_created = TRUE;
+  }
+
   create_drivers(drivers_to_create);
   ll_destroy(drivers_to_create);
 
diff --git a/client/libs/crypto/byte_order.h b/client/libs/crypto/byte_order.h
index 9c45c97..14026f3 100644
--- a/client/libs/crypto/byte_order.h
+++ b/client/libs/crypto/byte_order.h
@@ -134,6 +134,9 @@ static inline uint64_t bswap_64(uint64_t x) {
 #elif defined(__APPLE__)
 # include <libkern/OSByteOrder.h>
 # define bswap_64 OSSwapInt64
+#elif defined(__sun)
+# include <sys/byteorder.h>
+# define bswap_64 BSWAP64
 #else
 # error "bswap_64 unsupported"
 #endif
diff --git a/client/libs/dns.c b/client/libs/dns.c
index 6d98ad5..909b3b0 100644
--- a/client/libs/dns.c
+++ b/client/libs/dns.c
@@ -73,10 +73,12 @@ static char *buffer_read_dns_name_at(buffer_t *buffer, uint32_t offset, uint32_t
   {
     if(piece_length & 0x80)
     {
-      if(piece_length == 0xc0)
+      if(piece_length & 0xc0)
       {
         uint8_t relative_pos = buffer_read_int8_at(buffer, offset + pos);
         char *new_data;
+
+	relative_pos |= ((piece_length & 0x03) << 8);
         pos++;
 
         new_data = buffer_read_dns_name_at(buffer, relative_pos, NULL);
@@ -136,7 +138,7 @@ static char *buffer_read_next_dns_name(buffer_t *buffer)
 static char *buffer_read_ipv4_address_at(buffer_t *buffer, uint32_t offset, char result[16])
 {
 #ifdef WIN32
-  printf("NOT IMPLEMENTED!\n");
+  printf("NOT IMPLEMENTED IPv4!\n");
   exit(1);
 #else
   uint8_t addr[4];
@@ -180,7 +182,7 @@ static buffer_t *buffer_add_ipv4_address(buffer_t *buffer, char *address)
 static char *buffer_read_ipv6_address_at(buffer_t *buffer, uint32_t offset, char result[40])
 {
 #ifdef WIN32
-  printf("NOT IMPLEMENTED!\n");
+  printf("NOT IMPLEMENTED IPv6!\n");
   exit(1);
 #else
   uint8_t addr[16];
diff --git a/client/libs/pstdint.h b/client/libs/pstdint.h
old mode 100755
new mode 100644
index 27d4d19..baf4c19
--- a/client/libs/pstdint.h
+++ b/client/libs/pstdint.h
@@ -190,7 +190,7 @@
  *  do nothing else.  On the Mac OS X version of gcc this is _STDINT_H_.
  */
 
-#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) )) && !defined (_PSTDINT_H_INCLUDED)
+#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || defined(__MINGW32__) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) )) && !defined (_PSTDINT_H_INCLUDED)
 #include <stdint.h>
 #define _PSTDINT_H_INCLUDED
 # ifndef PRINTF_INT64_MODIFIER
diff --git a/doc/protocol.md b/doc/protocol.md
index 8a88b01..2391a7f 100644
--- a/doc/protocol.md
+++ b/doc/protocol.md
@@ -23,7 +23,7 @@ messages, and, finally, a breakdown of the messages themselves.
 
 # License
 
-See LICENSE.md.
+See [LICENSE.md](../LICENSE.md).
 
 # Challenges
 
diff --git a/server/controller/controller_commands.rb b/server/controller/controller_commands.rb
index 4b85d5f..905d8df 100644
--- a/server/controller/controller_commands.rb
+++ b/server/controller/controller_commands.rb
@@ -196,7 +196,7 @@ module ControllerCommands
         TunnelDrivers.start({
           :controller => self,
           :driver     => DriverDNS,
-          :args       => [dns[:host], dns[:port], dns[:domains]]
+          :args       => [dns[:host], dns[:port], dns[:domains], opts[:cache]]
         })
       end
     )
diff --git a/server/controller/crypto_helper.rb b/server/controller/crypto_helper.rb
index 5fdef1f..3bf2d24 100644
--- a/server/controller/crypto_helper.rb
+++ b/server/controller/crypto_helper.rb
@@ -10,16 +10,16 @@
 
 class CryptoHelper
   def CryptoHelper.bignum_to_binary(bn, size=32)
-    if(!bn.is_a?(Bignum))
-      raise(ArgumentError, "Expected: Bignum; received: #{bn.class}")
+    if(!bn.is_a?(Integer))
+      raise(ArgumentError, "Expected: Integer; received: #{bn.class}")
     end
 
     return [bn.to_s(16).rjust(size*2, "\0")].pack("H*")
   end
 
   def CryptoHelper.bignum_to_text(bn, size=32)
-    if(!bn.is_a?(Bignum))
-      raise(ArgumentError, "Expected: Bignum; received: #{bn.class}")
+    if(!bn.is_a?(Integer))
+      raise(ArgumentError, "Expected: Integer; received: #{bn.class}")
     end
 
     return CryptoHelper.bignum_to_binary(bn, size).unpack("H*").pop()
diff --git a/server/controller/packet.rb b/server/controller/packet.rb
index 35b02e3..7be365a 100644
--- a/server/controller/packet.rb
+++ b/server/controller/packet.rb
@@ -225,8 +225,8 @@ class Packet
         @public_key_x = params[:public_key_x] || raise(DnscatException, "params[:public_key_x] is required!")
         @public_key_y = params[:public_key_y] || raise(DnscatException, "params[:public_key_y] is required!")
 
-        if(!@public_key_x.is_a?(Bignum) || !@public_key_y.is_a?(Bignum))
-          raise(DnscatException, "Public keys have to be Bignums! (Seen: #{@public_key_x.class} #{@public_key_y.class})")
+        if(!@public_key_x.is_a?(Integer) || !@public_key_y.is_a?(Integer))
+          raise(DnscatException, "Public keys have to be Integers! (Seen: #{@public_key_x.class} #{@public_key_y.class})")
         end
       elsif(@subtype == SUBTYPE_AUTH)
         @authenticator = params[:authenticator] || raise(DnscatException, "params[:authenticator] is required!")
diff --git a/server/controller/session.rb b/server/controller/session.rb
index 1d6b080..bf61ab7 100644
--- a/server/controller/session.rb
+++ b/server/controller/session.rb
@@ -149,9 +149,9 @@ class Session
     options = 0
 
     # Ignore errant SYNs - they are, at worst, retransmissions that we don't care about
-    if(@state != STATE_NEW)
-      raise(DnscatException, "Duplicate SYN received!")
-    end
+    #if(@state != STATE_NEW)
+    #  raise(DnscatException, "Duplicate SYN received!")
+    #end
 
     _do_display_crypto_values()
 
diff --git a/server/dnscat2.rb b/server/dnscat2.rb
index 6d8fade..7f16b4a 100755
--- a/server/dnscat2.rb
+++ b/server/dnscat2.rb
@@ -10,7 +10,9 @@
 ##
 
 $LOAD_PATH << File.dirname(__FILE__) # A hack to make this work on 1.8/1.9
-
+trap "SIGINT" do
+  puts "Ctrl-C is disabled, use exit"
+end
 # Create the window right away so other includes can create their own windows if they want
 require 'libs/swindow'
 WINDOW = SWindow.new(nil, true, { :prompt => "dnscat2> ", :name => "main" })
@@ -88,6 +90,9 @@ opts = Trollop::options do
 
   opt :firehose,       "If set, all output goes to stdout instead of being put in windows.",
     :type => :boolean, :default => false
+
+  opt :cache,       "If set, caching is enabled on the server.",
+    :type => :boolean, :default => true
 end
 
 SWindow.set_firehose(opts[:firehose])
@@ -205,7 +210,7 @@ dns_settings[:domains] += ARGV
 TunnelDrivers.start({
   :controller => controller,
   :driver     => DriverDNS,
-  :args       => [dns_settings[:host], dns_settings[:port], dns_settings[:domains]],
+  :args       => [dns_settings[:host], dns_settings[:port], dns_settings[:domains], opts[:cache]],
 })
 
 # Wait for the input window to finish its thing
diff --git a/server/drivers/driver_command.rb b/server/drivers/driver_command.rb
index b15ddb3..853571c 100644
--- a/server/drivers/driver_command.rb
+++ b/server/drivers/driver_command.rb
@@ -105,31 +105,36 @@ class DriverCommand
 
     if(command_packet.get(:is_request))
       tunnel_data_incoming(command_packet)
-    else
-      handler = @handlers.delete(command_packet.get(:request_id))
-      if(handler.nil?)
-        @window.puts("Received a response that we have no record of sending:")
-        @window.puts("#{command_packet}")
-        @window.puts()
-        @window.puts("Here are the responses we're waiting for:")
-        @handlers.each_pair do |request_id, the_handler|
-          @window.puts("#{request_id}: #{the_handler[:request]}")
-        end
-
-        if(handler.get(:command_id) != response.get(:command_id) && command_packet.get(:command_id) != CommandPacket::ERROR)
-          @window.puts("Received a response of a different packet type (that's really weird, please report if you can reproduce!")
-          @window.puts("#{command_packet}")
-          @window.puts()
-          @window.puts("The original packet was:")
-          @window.puts("#{handler}")
-        end
-
-        return
+      return
+    end
+
+    handler = @handlers.delete(command_packet.get(:request_id))
+    if(handler.nil?)
+      @window.puts("Received a response that we have no record of sending:")
+      @window.puts("#{command_packet}")
+      @window.puts()
+      @window.puts("Here are the responses we're waiting for:")
+      @handlers.each_pair do |request_id, the_handler|
+        @window.puts("#{request_id}: #{the_handler[:request]}")
       end
+      return
+    end
+
+    if(command_packet.get(:command_id) == CommandPacket::COMMAND_ERROR)
+      @window.puts("Client returned an error: #{command_packet.get(:status)} :: #{command_packet.get(:reason)}")
+      return
+    end
 
-      handler[:proc].call(handler[:request], command_packet)
+    if(handler[:request].get(:command_id) != command_packet.get(:command_id))
+      @window.puts("Received a response of a different packet type (that's really weird, please report if you can reproduce!")
+      @window.puts("#{command_packet}")
+      @window.puts()
+      @window.puts("The original packet was:")
+      @window.puts("#{handler}")
+      return
     end
 
+    handler[:proc].call(handler[:request], command_packet)
   end
 
   def feed(data)
diff --git a/server/drivers/driver_console.rb b/server/drivers/driver_console.rb
index b32bd2e..697884f 100644
--- a/server/drivers/driver_console.rb
+++ b/server/drivers/driver_console.rb
@@ -39,4 +39,7 @@ class DriverConsole
 
     return out
   end
+
+  def shutdown()
+  end
 end
diff --git a/server/libs/dnser.rb b/server/libs/dnser.rb
index 69f734e..0af84ae 100644
--- a/server/libs/dnser.rb
+++ b/server/libs/dnser.rb
@@ -376,7 +376,7 @@ class DNSer
       attr_accessor :preference, :name
 
       def initialize(name, preference = 10)
-        if(!name.is_a?(String) || !preference.is_a?(Fixnum))
+        if(!name.is_a?(String) || !preference.is_a?(Integer))
           raise ArgumentError("Creating an MX record wrong! Please file a bug!")
         end
         @name = name
@@ -804,7 +804,7 @@ class DNSer
       @sent = true
     end
 
-    def reply!()
+    def reply!(_="")
       raise ArgumentError("Already sent!") if(@sent)
 
       # Cache it if we have a cache
@@ -842,39 +842,43 @@ class DNSer
       begin
         loop do
           data = @s.recvfrom(65536)
-
-          # Data is an array where the first element is the actual data, and the second is the host/port
-          request = DNSer::Packet.parse(data[0])
-
-          # Create a transaction object, which we can use to respond
-          transaction = Transaction.new(@s, request, data[1][3], data[1][1], @cache)
-
-          # If caching is enabled, deal with it
-          if(@cache)
-            # This is somewhat expensive, but we aren't using the cache for performance
-            @cache.cleanup!()
-
-            # See if the transaction is cached
-            cached = @cache[request.trn_id]
-
-            # Verify it deeper (for security reasons)
-            if(!cached.nil?)
-              puts("POTENTIAL CACHE HIT")
-              if(request == cached[:request])
-                puts("CACHE HIT")
-                transaction.reply!(cached[:response])
+          
+          begin   
+            # Data is an array where the first element is the actual data, and the second is the host/port
+            request = DNSer::Packet.parse(data[0])
+
+            # Create a transaction object, which we can use to respond
+            transaction = Transaction.new(@s, request, data[1][3], data[1][1], @cache)
+
+            # If caching is enabled, deal with it
+            if(@cache)
+              # This is somewhat expensive, but we aren't using the cache for performance
+              @cache.cleanup!()
+
+              # See if the transaction is cached
+              cached = @cache[request.trn_id]
+
+              # Verify it deeper (for security reasons)
+              if(!cached.nil?)
+                if(request == cached[:request])
+                  puts("CACHE HIT")
+                  transaction.reply!(cached[:response])
+                end
               end
             end
-          end
 
-          if(!transaction.sent)
-            begin
-              proc.call(transaction)
-            rescue StandardError => e
-              puts("Caught an error: #{e}")
-              puts(e.backtrace())
-              transaction.reply!(transaction.response_template({:rcode => DNSer::Packet::RCODE_SERVER_FAILURE}))
+            if(!transaction.sent)
+              begin
+                proc.call(transaction)
+              rescue StandardError => e
+                puts("Caught an error: #{e}")
+                puts(e.backtrace())
+                transaction.reply!(transaction.response_template({:rcode => DNSer::Packet::RCODE_SERVER_FAILURE}))
+              end
             end
+          rescue StandardError => e
+            puts("Caught an error: #{e}")
+            puts(e.backtrace())
           end
         end
       ensure
diff --git a/server/tunnel_drivers/driver_dns.rb b/server/tunnel_drivers/driver_dns.rb
index 39aa68a..f4e778e 100644
--- a/server/tunnel_drivers/driver_dns.rb
+++ b/server/tunnel_drivers/driver_dns.rb
@@ -242,13 +242,13 @@ class DriverDNS
     return response
   end
 
-  def initialize(parent_window, host, port, domains)
+  def initialize(parent_window, host, port, domains, cache)
     if(domains.nil?)
       domains = []
     end
 
     # Do this as early as we can, so we can fail early
-    @dnser = DNSer.new(host, port, true)
+    @dnser = DNSer.new(host, port, cache)
 
     @id = 'dns%d' % (@@id += 1)
     @window = SWindow.new(parent_window, false, {