]> andersk Git - openssh.git/blobdiff - packet.c
- djm@cvs.openbsd.org 2010/01/30 02:54:53
[openssh.git] / packet.c
index f3f8389a3c3c2ef40e3236e8a4a0d9b7ca17ad88..994e35b6df50f926455475e6121fa6a16c252a6c 100644 (file)
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.163 2009/05/28 16:50:16 andreas Exp $ */
+/* $OpenBSD: packet.c,v 1.166 2009/06/27 09:29:06 andreas Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -182,13 +182,22 @@ struct session_state {
        /* Used in packet_read_poll2() */
        u_int packlen;
 
+       /* Used in packet_send2 */
+       int rekeying;
+
+       /* Used in packet_set_interactive */
+       int set_interactive_called;
+
+       /* Used in packet_set_maxsize */
+       int set_maxsize_called;
+
        TAILQ_HEAD(, packet) outgoing;
 };
 
-static struct session_state *active_state;
+static struct session_state *active_state, *backup_state;
 
 static struct session_state *
-alloc_session_state()
+alloc_session_state(void)
 {
     struct session_state *s = xcalloc(1, sizeof(*s));
 
@@ -950,7 +959,6 @@ packet_send2_wrapped(void)
 static void
 packet_send2(void)
 {
-       static int rekeying = 0;
        struct packet *p;
        u_char type, *cp;
 
@@ -958,7 +966,7 @@ packet_send2(void)
        type = cp[5];
 
        /* during rekeying we can only send key exchange messages */
-       if (rekeying) {
+       if (active_state->rekeying) {
                if (!((type >= SSH2_MSG_TRANSPORT_MIN) &&
                    (type <= SSH2_MSG_TRANSPORT_MAX))) {
                        debug("enqueue packet: %u", type);
@@ -974,13 +982,13 @@ packet_send2(void)
 
        /* rekeying starts with sending KEXINIT */
        if (type == SSH2_MSG_KEXINIT)
-               rekeying = 1;
+               active_state->rekeying = 1;
 
        packet_send2_wrapped();
 
        /* after a NEWKEYS message we can send the complete queue */
        if (type == SSH2_MSG_NEWKEYS) {
-               rekeying = 0;
+               active_state->rekeying = 0;
                while ((p = TAILQ_FIRST(&active_state->outgoing))) {
                        type = p->type;
                        debug("dequeue packet: %u", type);
@@ -1062,7 +1070,8 @@ packet_read_seqnr(u_int32_t *seqnr_p)
                        if ((ret = select(active_state->connection_in + 1, setp,
                            NULL, NULL, timeoutp)) >= 0)
                                break;
-                       if (errno != EAGAIN && errno != EINTR)
+                       if (errno != EAGAIN && errno != EINTR &&
+                           errno != EWOULDBLOCK)
                                break;
                        if (active_state->packet_timeout_ms == -1)
                                continue;
@@ -1635,7 +1644,8 @@ packet_write_poll(void)
                len = roaming_write(active_state->connection_out,
                    buffer_ptr(&active_state->output), len, &cont);
                if (len == -1) {
-                       if (errno == EINTR || errno == EAGAIN)
+                       if (errno == EINTR || errno == EAGAIN ||
+                           errno == EWOULDBLOCK)
                                return;
                        fatal("Write failed: %.100s", strerror(errno));
                }
@@ -1677,7 +1687,8 @@ packet_write_wait(void)
                        if ((ret = select(active_state->connection_out + 1,
                            NULL, setp, NULL, timeoutp)) >= 0)
                                break;
-                       if (errno != EAGAIN && errno != EINTR)
+                       if (errno != EAGAIN && errno != EINTR &&
+                           errno != EWOULDBLOCK)
                                break;
                        if (active_state->packet_timeout_ms == -1)
                                continue;
@@ -1737,11 +1748,9 @@ packet_set_tos(int interactive)
 void
 packet_set_interactive(int interactive)
 {
-       static int called = 0;
-
-       if (called)
+       if (active_state->set_interactive_called)
                return;
-       called = 1;
+       active_state->set_interactive_called = 1;
 
        /* Record that we are in interactive mode. */
        active_state->interactive_mode = interactive;
@@ -1764,9 +1773,7 @@ packet_is_interactive(void)
 int
 packet_set_maxsize(u_int s)
 {
-       static int called = 0;
-
-       if (called) {
+       if (active_state->set_maxsize_called) {
                logit("packet_set_maxsize: called twice: old %d new %d",
                    active_state->max_packet_size, s);
                return -1;
@@ -1775,7 +1782,7 @@ packet_set_maxsize(u_int s)
                logit("packet_set_maxsize: bad size %d", s);
                return -1;
        }
-       called = 1;
+       active_state->set_maxsize_called = 1;
        debug("packet_set_maxsize: setting to %d", s);
        active_state->max_packet_size = s;
        return s;
@@ -1883,3 +1890,50 @@ packet_get_newkeys(int mode)
 {
        return (void *)active_state->newkeys[mode];
 }
+
+/*
+ * Save the state for the real connection, and use a separate state when
+ * resuming a suspended connection.
+ */
+void
+packet_backup_state(void)
+{
+       struct session_state *tmp;
+
+       close(active_state->connection_in);
+       active_state->connection_in = -1;
+       close(active_state->connection_out);
+       active_state->connection_out = -1;
+       if (backup_state)
+               tmp = backup_state;
+       else
+               tmp = alloc_session_state();
+       backup_state = active_state;
+       active_state = tmp;
+}
+
+/*
+ * Swap in the old state when resuming a connecion.
+ */
+void
+packet_restore_state(void)
+{
+       struct session_state *tmp;
+       void *buf;
+       u_int len;
+
+       tmp = backup_state;
+       backup_state = active_state;
+       active_state = tmp;
+       active_state->connection_in = backup_state->connection_in;
+       backup_state->connection_in = -1;
+       active_state->connection_out = backup_state->connection_out;
+       backup_state->connection_out = -1;
+       len = buffer_len(&backup_state->input);
+       if (len > 0) {
+               buf = buffer_ptr(&backup_state->input);
+               buffer_append(&active_state->input, buf, len);
+               buffer_clear(&backup_state->input);
+               add_recv_bytes(len);
+       }
+}
This page took 0.217178 seconds and 4 git commands to generate.