]> andersk Git - openssh.git/blobdiff - packet.c
- djm@cvs.openbsd.org 2010/01/30 02:54:53
[openssh.git] / packet.c
index cecab82e90e8af44d68b86735a7d5b73e902af05..994e35b6df50f926455475e6121fa6a16c252a6c 100644 (file)
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.162 2009/05/27 06:36:07 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
@@ -77,6 +77,7 @@
 #include "canohost.h"
 #include "misc.h"
 #include "ssh.h"
+#include "roaming.h"
 
 #ifdef PACKET_DEBUG
 #define DBG(x) x
@@ -181,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));
 
@@ -949,7 +959,6 @@ packet_send2_wrapped(void)
 static void
 packet_send2(void)
 {
-       static int rekeying = 0;
        struct packet *p;
        u_char type, *cp;
 
@@ -957,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);
@@ -973,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);
@@ -1012,7 +1021,7 @@ packet_send(void)
 int
 packet_read_seqnr(u_int32_t *seqnr_p)
 {
-       int type, len, ret, ms_remain;
+       int type, len, ret, ms_remain, cont;
        fd_set *setp;
        char buf[8192];
        struct timeval timeout, start, *timeoutp = NULL;
@@ -1078,7 +1087,11 @@ packet_read_seqnr(u_int32_t *seqnr_p)
                        cleanup_exit(255);
                }
                /* Read data from the socket. */
-               len = read(active_state->connection_in, buf, sizeof(buf));
+               do {
+                       cont = 0;
+                       len = roaming_read(active_state->connection_in, buf,
+                           sizeof(buf), &cont);
+               } while (len == 0 && cont);
                if (len == 0) {
                        logit("Connection closed by %.200s", get_remote_ipaddr());
                        cleanup_exit(255);
@@ -1624,23 +1637,24 @@ void
 packet_write_poll(void)
 {
        int len = buffer_len(&active_state->output);
+       int cont;
 
        if (len > 0) {
-               len = write(active_state->connection_out,
-                   buffer_ptr(&active_state->output), len);
+               cont = 0;
+               len = roaming_write(active_state->connection_out,
+                   buffer_ptr(&active_state->output), len, &cont);
                if (len == -1) {
                        if (errno == EINTR || errno == EAGAIN ||
                            errno == EWOULDBLOCK)
                                return;
                        fatal("Write failed: %.100s", strerror(errno));
                }
-               if (len == 0)
+               if (len == 0 && !cont)
                        fatal("Write connection closed");
                buffer_consume(&active_state->output, len);
        }
 }
 
-
 /*
  * Calls packet_write_poll repeatedly until all pending output data has been
  * written.
@@ -1713,7 +1727,6 @@ packet_not_very_much_data_to_write(void)
                return buffer_len(&active_state->output) < 128 * 1024;
 }
 
-
 static void
 packet_set_tos(int interactive)
 {
@@ -1735,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;
@@ -1762,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;
@@ -1773,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;
@@ -1881,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.04875 seconds and 4 git commands to generate.