diff --git a/lib/modules/SSL.pmod/ClientConnection.pike b/lib/modules/SSL.pmod/ClientConnection.pike
index 30a68259f753683917f64a78f4166ccdb4cf43eb..11da241e91041a22ea29fd3fea5108c1e6eece98 100644
--- a/lib/modules/SSL.pmod/ClientConnection.pike
+++ b/lib/modules/SSL.pmod/ClientConnection.pike
@@ -233,6 +233,14 @@ protected void create(Context ctx, string(8bit)|void server_name)
   send_packet(client_hello(server_name));
 }
 
+//! Renegotiate the connection (client initiated).
+//!
+//! Sends a @[client_hello] to force a new round of handshaking.
+void send_renegotiate()
+{
+  send_packet(client_hello(), PRI_application);
+}
+
 //! Do handshake processing. Type is one of HANDSHAKE_*, data is the
 //! contents of the packet, and raw is the raw packet received (needed
 //! for supporting SSLv2 hello messages).
diff --git a/lib/modules/SSL.pmod/Connection.pike b/lib/modules/SSL.pmod/Connection.pike
index 5ca17788e8c09846621450da5fe3a48cac062a38..f1f57c3ffcf27aaaebe63ef296b196cbac16c952 100644
--- a/lib/modules/SSL.pmod/Connection.pike
+++ b/lib/modules/SSL.pmod/Connection.pike
@@ -415,6 +415,22 @@ void send_packet(Packet packet, int|void priority)
 	          PACKET_handshake : PRI_urgent,
 		  PACKET_heartbeat : PRI_urgent,
 		  PACKET_application_data : PRI_application ])[packet->content_type];
+
+  if ((state & CONNECTION_local_closing) && (priority >= PRI_application)) {
+    SSL3_DEBUG_MSG("send_packet: Ignoring application packet during close.\n");
+    return;
+  }
+
+  if ((packet->content_type == PACKET_handshake) &&
+      (priority == PRI_application)) {
+    // Assume the packet is either hello_request or client_hello,
+    // and that we want to renegotiate.
+    expect_change_cipher = 0;
+    certificate_state = 0;
+    state = [int(0..0)|ConnectionState](state | CONNECTION_handshaking);
+    handshake_state = STATE_wait_for_hello;
+  }
+
   SSL3_DEBUG_MSG("SSL.Connection->send_packet: type %d, pri %d, %O\n",
 		 packet->content_type, priority, packet->fragment[..5]);
   switch (priority)
@@ -496,6 +512,9 @@ void send_close()
                     "Closing connection.\n"), PRI_application);
 }
 
+//! Renegotiate the connection.
+void send_renegotiate();
+
 //! Send an application data packet. If the data block is too large
 //! then as much as possible of the beginning of it is sent. The size
 //! of the sent data is returned.
diff --git a/lib/modules/SSL.pmod/File.pike b/lib/modules/SSL.pmod/File.pike
index 0b44631b68c87cdbe91536c52ee71ed4f83787ca..b4ed6cee56c3a5bfb11611f765964193eced1d49 100644
--- a/lib/modules/SSL.pmod/File.pike
+++ b/lib/modules/SSL.pmod/File.pike
@@ -1027,19 +1027,13 @@ int renegotiate()
 
     local_errno = 0;
 
-    // FIXME: Change this state with a packet instead so that things
-    // currently in the queue aren't affect by it.
-    conn->expect_change_cipher = 0;
-    conn->certificate_state = 0;
-    conn->state |= CONNECTION_handshaking;
+    conn->send_renegotiate();
 
     SSL3_DEBUG_MSG("renegotiate: Installing read/close callbacks.\n");
 
     stream->set_read_callback(ssl_read_callback);
     stream->set_close_callback(ssl_close_callback);
 
-    conn->send_packet(conn->hello_request());
-
     RETURN (direct_write());
   } LEAVE;
 }
diff --git a/lib/modules/SSL.pmod/ServerConnection.pike b/lib/modules/SSL.pmod/ServerConnection.pike
index acb286faf87704872e4634daf1ed746e005b08b0..08c95125e73270b9aeac209b54dc8c87e9dc8541 100644
--- a/lib/modules/SSL.pmod/ServerConnection.pike
+++ b/lib/modules/SSL.pmod/ServerConnection.pike
@@ -151,6 +151,14 @@ Packet certificate_request_packet(Context context)
 				 struct->pop_data());
 }
 
+//! Renegotiate the connection (server initiated).
+//!
+//! Sends a @[hello_request] to force a new round of handshaking.
+void send_renegotiate()
+{
+  send_packet(hello_request(), PRI_application);
+}
+
 int(0..1) not_ecc_suite(int cipher_suite)
 {
   array(int) suite = [array(int)]CIPHER_SUITES[cipher_suite];