diff options
Diffstat (limited to 'nchan.c')
-rw-r--r-- | nchan.c | 21 |
1 files changed, 15 insertions, 6 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: nchan.c,v 1.62 2008/11/07 18:50:18 stevesk Exp $ */ | 1 | /* $OpenBSD: nchan.c,v 1.63 2010/01/26 01:28:35 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -161,7 +161,7 @@ chan_ibuf_empty(Channel *c) | |||
161 | switch (c->istate) { | 161 | switch (c->istate) { |
162 | case CHAN_INPUT_WAIT_DRAIN: | 162 | case CHAN_INPUT_WAIT_DRAIN: |
163 | if (compat20) { | 163 | if (compat20) { |
164 | if (!(c->flags & CHAN_CLOSE_SENT)) | 164 | if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL))) |
165 | chan_send_eof2(c); | 165 | chan_send_eof2(c); |
166 | chan_set_istate(c, CHAN_INPUT_CLOSED); | 166 | chan_set_istate(c, CHAN_INPUT_CLOSED); |
167 | } else { | 167 | } else { |
@@ -278,9 +278,12 @@ static void | |||
278 | chan_rcvd_close2(Channel *c) | 278 | chan_rcvd_close2(Channel *c) |
279 | { | 279 | { |
280 | debug2("channel %d: rcvd close", c->self); | 280 | debug2("channel %d: rcvd close", c->self); |
281 | if (c->flags & CHAN_CLOSE_RCVD) | 281 | if (!(c->flags & CHAN_LOCAL)) { |
282 | error("channel %d: protocol error: close rcvd twice", c->self); | 282 | if (c->flags & CHAN_CLOSE_RCVD) |
283 | c->flags |= CHAN_CLOSE_RCVD; | 283 | error("channel %d: protocol error: close rcvd twice", |
284 | c->self); | ||
285 | c->flags |= CHAN_CLOSE_RCVD; | ||
286 | } | ||
284 | if (c->type == SSH_CHANNEL_LARVAL) { | 287 | if (c->type == SSH_CHANNEL_LARVAL) { |
285 | /* tear down larval channels immediately */ | 288 | /* tear down larval channels immediately */ |
286 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); | 289 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); |
@@ -302,11 +305,13 @@ chan_rcvd_close2(Channel *c) | |||
302 | chan_set_istate(c, CHAN_INPUT_CLOSED); | 305 | chan_set_istate(c, CHAN_INPUT_CLOSED); |
303 | break; | 306 | break; |
304 | case CHAN_INPUT_WAIT_DRAIN: | 307 | case CHAN_INPUT_WAIT_DRAIN: |
305 | chan_send_eof2(c); | 308 | if (!(c->flags & CHAN_LOCAL)) |
309 | chan_send_eof2(c); | ||
306 | chan_set_istate(c, CHAN_INPUT_CLOSED); | 310 | chan_set_istate(c, CHAN_INPUT_CLOSED); |
307 | break; | 311 | break; |
308 | } | 312 | } |
309 | } | 313 | } |
314 | |||
310 | void | 315 | void |
311 | chan_rcvd_eow(Channel *c) | 316 | chan_rcvd_eow(Channel *c) |
312 | { | 317 | { |
@@ -454,6 +459,10 @@ chan_is_dead(Channel *c, int do_send) | |||
454 | c->self, c->efd, buffer_len(&c->extended)); | 459 | c->self, c->efd, buffer_len(&c->extended)); |
455 | return 0; | 460 | return 0; |
456 | } | 461 | } |
462 | if (c->flags & CHAN_LOCAL) { | ||
463 | debug2("channel %d: is dead (local)", c->self); | ||
464 | return 1; | ||
465 | } | ||
457 | if (!(c->flags & CHAN_CLOSE_SENT)) { | 466 | if (!(c->flags & CHAN_CLOSE_SENT)) { |
458 | if (do_send) { | 467 | if (do_send) { |
459 | chan_send_close2(c); | 468 | chan_send_close2(c); |