summaryrefslogtreecommitdiff
path: root/nchan.c
diff options
context:
space:
mode:
Diffstat (limited to 'nchan.c')
-rw-r--r--nchan.c74
1 files changed, 53 insertions, 21 deletions
diff --git a/nchan.c b/nchan.c
index 24929556d..8294d7fca 100644
--- a/nchan.c
+++ b/nchan.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: nchan.c,v 1.67 2017/09/12 06:35:32 djm Exp $ */ 1/* $OpenBSD: nchan.c,v 1.69 2018/10/04 07:47: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 *
@@ -80,6 +80,7 @@ static void chan_send_eow2(struct ssh *, Channel *);
80/* helper */ 80/* helper */
81static void chan_shutdown_write(struct ssh *, Channel *); 81static void chan_shutdown_write(struct ssh *, Channel *);
82static void chan_shutdown_read(struct ssh *, Channel *); 82static void chan_shutdown_read(struct ssh *, Channel *);
83static void chan_shutdown_extended_read(struct ssh *, Channel *);
83 84
84static const char *ostates[] = { "open", "drain", "wait_ieof", "closed" }; 85static const char *ostates[] = { "open", "drain", "wait_ieof", "closed" };
85static const char *istates[] = { "open", "drain", "wait_oclose", "closed" }; 86static const char *istates[] = { "open", "drain", "wait_oclose", "closed" };
@@ -289,11 +290,13 @@ chan_rcvd_oclose(struct ssh *ssh, Channel *c)
289 switch (c->istate) { 290 switch (c->istate) {
290 case CHAN_INPUT_OPEN: 291 case CHAN_INPUT_OPEN:
291 chan_shutdown_read(ssh, c); 292 chan_shutdown_read(ssh, c);
293 chan_shutdown_extended_read(ssh, c);
292 chan_set_istate(c, CHAN_INPUT_CLOSED); 294 chan_set_istate(c, CHAN_INPUT_CLOSED);
293 break; 295 break;
294 case CHAN_INPUT_WAIT_DRAIN: 296 case CHAN_INPUT_WAIT_DRAIN:
295 if (!(c->flags & CHAN_LOCAL)) 297 if (!(c->flags & CHAN_LOCAL))
296 chan_send_eof2(ssh, c); 298 chan_send_eof2(ssh, c);
299 chan_shutdown_extended_read(ssh, c);
297 chan_set_istate(c, CHAN_INPUT_CLOSED); 300 chan_set_istate(c, CHAN_INPUT_CLOSED);
298 break; 301 break;
299 } 302 }
@@ -373,17 +376,23 @@ chan_shutdown_write(struct ssh *ssh, Channel *c)
373 if (c->type == SSH_CHANNEL_LARVAL) 376 if (c->type == SSH_CHANNEL_LARVAL)
374 return; 377 return;
375 /* shutdown failure is allowed if write failed already */ 378 /* shutdown failure is allowed if write failed already */
376 debug2("channel %d: close_write", c->self); 379 debug2("channel %d: %s (i%d o%d sock %d wfd %d efd %d [%s])",
380 c->self, __func__, c->istate, c->ostate, c->sock, c->wfd, c->efd,
381 channel_format_extended_usage(c));
377 if (c->sock != -1) { 382 if (c->sock != -1) {
378 if (shutdown(c->sock, SHUT_WR) < 0) 383 if (shutdown(c->sock, SHUT_WR) < 0) {
379 debug2("channel %d: chan_shutdown_write: " 384 debug2("channel %d: %s: shutdown() failed for "
380 "shutdown() failed for fd %d: %.100s", 385 "fd %d [i%d o%d]: %.100s", c->self, __func__,
381 c->self, c->sock, strerror(errno)); 386 c->sock, c->istate, c->ostate,
387 strerror(errno));
388 }
382 } else { 389 } else {
383 if (channel_close_fd(ssh, &c->wfd) < 0) 390 if (channel_close_fd(ssh, &c->wfd) < 0) {
384 logit("channel %d: chan_shutdown_write: " 391 logit("channel %d: %s: close() failed for "
385 "close() failed for fd %d: %.100s", 392 "fd %d [i%d o%d]: %.100s",
386 c->self, c->wfd, strerror(errno)); 393 c->self, __func__, c->wfd, c->istate, c->ostate,
394 strerror(errno));
395 }
387 } 396 }
388} 397}
389 398
@@ -392,23 +401,46 @@ chan_shutdown_read(struct ssh *ssh, Channel *c)
392{ 401{
393 if (c->type == SSH_CHANNEL_LARVAL) 402 if (c->type == SSH_CHANNEL_LARVAL)
394 return; 403 return;
395 debug2("channel %d: close_read", c->self); 404 debug2("channel %d: %s (i%d o%d sock %d wfd %d efd %d [%s])",
405 c->self, __func__, c->istate, c->ostate, c->sock, c->rfd, c->efd,
406 channel_format_extended_usage(c));
396 if (c->sock != -1) { 407 if (c->sock != -1) {
397 /* 408 /*
398 * shutdown(sock, SHUT_READ) may return ENOTCONN if the 409 * shutdown(sock, SHUT_READ) may return ENOTCONN if the
399 * write side has been closed already. (bug on Linux) 410 * write side has been closed already. (bug on Linux)
400 * HP-UX may return ENOTCONN also. 411 * HP-UX may return ENOTCONN also.
401 */ 412 */
402 if (shutdown(c->sock, SHUT_RD) < 0 413 if (shutdown(c->sock, SHUT_RD) < 0 && errno != ENOTCONN) {
403 && errno != ENOTCONN) 414 error("channel %d: %s: shutdown() failed for "
404 error("channel %d: chan_shutdown_read: " 415 "fd %d [i%d o%d]: %.100s",
405 "shutdown() failed for fd %d [i%d o%d]: %.100s", 416 c->self, __func__, c->sock, c->istate, c->ostate,
406 c->self, c->sock, c->istate, c->ostate, 417 strerror(errno));
407 strerror(errno)); 418 }
408 } else { 419 } else {
409 if (channel_close_fd(ssh, &c->rfd) < 0) 420 if (channel_close_fd(ssh, &c->rfd) < 0) {
410 logit("channel %d: chan_shutdown_read: " 421 logit("channel %d: %s: close() failed for "
411 "close() failed for fd %d: %.100s", 422 "fd %d [i%d o%d]: %.100s",
412 c->self, c->rfd, strerror(errno)); 423 c->self, __func__, c->rfd, c->istate, c->ostate,
424 strerror(errno));
425 }
426 }
427}
428
429static void
430chan_shutdown_extended_read(struct ssh *ssh, Channel *c)
431{
432 if (c->type == SSH_CHANNEL_LARVAL || c->efd == -1)
433 return;
434 if (c->extended_usage != CHAN_EXTENDED_READ &&
435 c->extended_usage != CHAN_EXTENDED_IGNORE)
436 return;
437 debug2("channel %d: %s (i%d o%d sock %d wfd %d efd %d [%s])",
438 c->self, __func__, c->istate, c->ostate, c->sock, c->rfd, c->efd,
439 channel_format_extended_usage(c));
440 if (channel_close_fd(ssh, &c->efd) < 0) {
441 logit("channel %d: %s: close() failed for "
442 "extended fd %d [i%d o%d]: %.100s",
443 c->self, __func__, c->efd, c->istate, c->ostate,
444 strerror(errno));
413 } 445 }
414} 446}