diff options
Diffstat (limited to 'nchan.c')
-rw-r--r-- | nchan.c | 74 |
1 files changed, 53 insertions, 21 deletions
@@ -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 */ |
81 | static void chan_shutdown_write(struct ssh *, Channel *); | 81 | static void chan_shutdown_write(struct ssh *, Channel *); |
82 | static void chan_shutdown_read(struct ssh *, Channel *); | 82 | static void chan_shutdown_read(struct ssh *, Channel *); |
83 | static void chan_shutdown_extended_read(struct ssh *, Channel *); | ||
83 | 84 | ||
84 | static const char *ostates[] = { "open", "drain", "wait_ieof", "closed" }; | 85 | static const char *ostates[] = { "open", "drain", "wait_ieof", "closed" }; |
85 | static const char *istates[] = { "open", "drain", "wait_oclose", "closed" }; | 86 | static 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 | |||
429 | static void | ||
430 | chan_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 | } |