version 1.406, 2021/04/03 06:18:40 |
version 1.407, 2021/05/19 01:24:05 |
|
|
debug2("channel %d: rfd %d isatty", c->self, c->rfd); |
debug2("channel %d: rfd %d isatty", c->self, c->rfd); |
|
|
/* enable nonblocking mode */ |
/* enable nonblocking mode */ |
if (nonblock) { |
c->restore_block = 0; |
|
if (nonblock == CHANNEL_NONBLOCK_STDIO) { |
|
/* |
|
* Special handling for stdio file descriptors: do not set |
|
* non-blocking mode if they are TTYs. Otherwise prepare to |
|
* restore their blocking state on exit to avoid interfering |
|
* with other programs that follow. |
|
*/ |
|
if (rfd != -1 && !isatty(rfd) && fcntl(rfd, F_GETFL) == 0) { |
|
c->restore_block |= CHANNEL_RESTORE_RFD; |
|
set_nonblock(rfd); |
|
} |
|
if (wfd != -1 && !isatty(wfd) && fcntl(wfd, F_GETFL) == 0) { |
|
c->restore_block |= CHANNEL_RESTORE_WFD; |
|
set_nonblock(wfd); |
|
} |
|
if (efd != -1 && !isatty(efd) && fcntl(efd, F_GETFL) == 0) { |
|
c->restore_block |= CHANNEL_RESTORE_EFD; |
|
set_nonblock(efd); |
|
} |
|
} else if (nonblock) { |
if (rfd != -1) |
if (rfd != -1) |
set_nonblock(rfd); |
set_nonblock(rfd); |
if (wfd != -1) |
if (wfd != -1) |
|
|
} |
} |
|
|
int |
int |
channel_close_fd(struct ssh *ssh, int *fdp) |
channel_close_fd(struct ssh *ssh, Channel *c, int *fdp) |
{ |
{ |
struct ssh_channels *sc = ssh->chanctxt; |
struct ssh_channels *sc = ssh->chanctxt; |
int ret = 0, fd = *fdp; |
int ret, fd = *fdp; |
|
|
if (fd != -1) { |
if (fd == -1) |
ret = close(fd); |
return 0; |
*fdp = -1; |
|
if (fd == sc->channel_max_fd) |
if ((*fdp == c->rfd && (c->restore_block & CHANNEL_RESTORE_RFD) != 0) || |
channel_find_maxfd(sc); |
(*fdp == c->wfd && (c->restore_block & CHANNEL_RESTORE_WFD) != 0) || |
} |
(*fdp == c->efd && (c->restore_block & CHANNEL_RESTORE_EFD) != 0)) |
|
(void)fcntl(*fdp, F_SETFL, 0); /* restore blocking */ |
|
|
|
ret = close(fd); |
|
*fdp = -1; |
|
if (fd == sc->channel_max_fd) |
|
channel_find_maxfd(sc); |
return ret; |
return ret; |
} |
} |
|
|
|
|
{ |
{ |
int sock = c->sock, rfd = c->rfd, wfd = c->wfd, efd = c->efd; |
int sock = c->sock, rfd = c->rfd, wfd = c->wfd, efd = c->efd; |
|
|
channel_close_fd(ssh, &c->sock); |
channel_close_fd(ssh, c, &c->sock); |
if (rfd != sock) |
if (rfd != sock) |
channel_close_fd(ssh, &c->rfd); |
channel_close_fd(ssh, c, &c->rfd); |
if (wfd != sock && wfd != rfd) |
if (wfd != sock && wfd != rfd) |
channel_close_fd(ssh, &c->wfd); |
channel_close_fd(ssh, c, &c->wfd); |
if (efd != sock && efd != rfd && efd != wfd) |
if (efd != sock && efd != rfd && efd != wfd) |
channel_close_fd(ssh, &c->efd); |
channel_close_fd(ssh, c, &c->efd); |
} |
} |
|
|
static void |
static void |
|
|
case SSH_CHANNEL_X11_LISTENER: |
case SSH_CHANNEL_X11_LISTENER: |
case SSH_CHANNEL_UNIX_LISTENER: |
case SSH_CHANNEL_UNIX_LISTENER: |
case SSH_CHANNEL_RUNIX_LISTENER: |
case SSH_CHANNEL_RUNIX_LISTENER: |
channel_close_fd(ssh, &c->sock); |
channel_close_fd(ssh, c, &c->sock); |
channel_free(ssh, c); |
channel_free(ssh, c); |
break; |
break; |
} |
} |
|
|
|
|
Channel * |
Channel * |
channel_connect_stdio_fwd(struct ssh *ssh, |
channel_connect_stdio_fwd(struct ssh *ssh, |
const char *host_to_connect, u_short port_to_connect, int in, int out) |
const char *host_to_connect, u_short port_to_connect, |
|
int in, int out, int nonblock) |
{ |
{ |
Channel *c; |
Channel *c; |
|
|
|
|
|
|
c = channel_new(ssh, "stdio-forward", SSH_CHANNEL_OPENING, in, out, |
c = channel_new(ssh, "stdio-forward", SSH_CHANNEL_OPENING, in, out, |
-1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, |
-1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, |
0, "stdio-forward", /*nonblock*/0); |
0, "stdio-forward", nonblock); |
|
|
c->path = xstrdup(host_to_connect); |
c->path = xstrdup(host_to_connect); |
c->host_port = port_to_connect; |
c->host_port = port_to_connect; |
|
|
if (c->single_connection) { |
if (c->single_connection) { |
oerrno = errno; |
oerrno = errno; |
debug2("single_connection: closing X11 listener."); |
debug2("single_connection: closing X11 listener."); |
channel_close_fd(ssh, &c->sock); |
channel_close_fd(ssh, c, &c->sock); |
chan_mark_dead(ssh, c); |
chan_mark_dead(ssh, c); |
errno = oerrno; |
errno = oerrno; |
} |
} |
|
|
return 1; |
return 1; |
if (len <= 0) { |
if (len <= 0) { |
debug2("channel %d: closing write-efd %d", c->self, c->efd); |
debug2("channel %d: closing write-efd %d", c->self, c->efd); |
channel_close_fd(ssh, &c->efd); |
channel_close_fd(ssh, c, &c->efd); |
} else { |
} else { |
if ((r = sshbuf_consume(c->extended, len)) != 0) |
if ((r = sshbuf_consume(c->extended, len)) != 0) |
fatal_fr(r, "channel %i: consume", c->self); |
fatal_fr(r, "channel %i: consume", c->self); |
|
|
return 1; |
return 1; |
if (len <= 0) { |
if (len <= 0) { |
debug2("channel %d: closing read-efd %d", c->self, c->efd); |
debug2("channel %d: closing read-efd %d", c->self, c->efd); |
channel_close_fd(ssh, &c->efd); |
channel_close_fd(ssh, c, &c->efd); |
} else if (c->extended_usage == CHAN_EXTENDED_IGNORE) |
} else if (c->extended_usage == CHAN_EXTENDED_IGNORE) |
debug3("channel %d: discard efd", c->self); |
debug3("channel %d: discard efd", c->self); |
else if ((r = sshbuf_put(c->extended, buf, len)) != 0) |
else if ((r = sshbuf_put(c->extended, buf, len)) != 0) |