version 1.409, 2022/01/01 01:55:30 |
version 1.410, 2022/01/06 21:46:23 |
|
|
#define MAX_DISPLAYS 1000 |
#define MAX_DISPLAYS 1000 |
|
|
/* Per-channel callback for pre/post select() actions */ |
/* Per-channel callback for pre/post select() actions */ |
typedef void chan_fn(struct ssh *, Channel *c, |
typedef void chan_fn(struct ssh *, Channel *c); |
fd_set *readset, fd_set *writeset); |
|
|
|
/* |
/* |
* Data structure for storing which hosts are permitted for forward requests. |
* Data structure for storing which hosts are permitted for forward requests. |
|
|
} |
} |
|
|
static void |
static void |
channel_pre_listener(struct ssh *ssh, Channel *c, |
channel_pre_listener(struct ssh *ssh, Channel *c) |
fd_set *readset, fd_set *writeset) |
|
{ |
{ |
FD_SET(c->sock, readset); |
c->io_want = SSH_CHAN_IO_SOCK_R; |
} |
} |
|
|
static void |
static void |
channel_pre_connecting(struct ssh *ssh, Channel *c, |
channel_pre_connecting(struct ssh *ssh, Channel *c) |
fd_set *readset, fd_set *writeset) |
|
{ |
{ |
debug3("channel %d: waiting for connection", c->self); |
debug3("channel %d: waiting for connection", c->self); |
FD_SET(c->sock, writeset); |
c->io_want = SSH_CHAN_IO_SOCK_W; |
} |
} |
|
|
static void |
static void |
channel_pre_open(struct ssh *ssh, Channel *c, |
channel_pre_open(struct ssh *ssh, Channel *c) |
fd_set *readset, fd_set *writeset) |
|
{ |
{ |
|
c->io_want = 0; |
if (c->istate == CHAN_INPUT_OPEN && |
if (c->istate == CHAN_INPUT_OPEN && |
c->remote_window > 0 && |
c->remote_window > 0 && |
sshbuf_len(c->input) < c->remote_window && |
sshbuf_len(c->input) < c->remote_window && |
sshbuf_check_reserve(c->input, CHAN_RBUF) == 0) |
sshbuf_check_reserve(c->input, CHAN_RBUF) == 0) |
FD_SET(c->rfd, readset); |
c->io_want |= SSH_CHAN_IO_RFD; |
if (c->ostate == CHAN_OUTPUT_OPEN || |
if (c->ostate == CHAN_OUTPUT_OPEN || |
c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { |
c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { |
if (sshbuf_len(c->output) > 0) { |
if (sshbuf_len(c->output) > 0) { |
FD_SET(c->wfd, writeset); |
c->io_want |= SSH_CHAN_IO_WFD; |
} else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { |
} else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { |
if (CHANNEL_EFD_OUTPUT_ACTIVE(c)) |
if (CHANNEL_EFD_OUTPUT_ACTIVE(c)) |
debug2("channel %d: " |
debug2("channel %d: " |
|
|
c->ostate == CHAN_OUTPUT_CLOSED)) { |
c->ostate == CHAN_OUTPUT_CLOSED)) { |
if (c->extended_usage == CHAN_EXTENDED_WRITE && |
if (c->extended_usage == CHAN_EXTENDED_WRITE && |
sshbuf_len(c->extended) > 0) |
sshbuf_len(c->extended) > 0) |
FD_SET(c->efd, writeset); |
c->io_want |= SSH_CHAN_IO_EFD_W; |
else if (c->efd != -1 && !(c->flags & CHAN_EOF_SENT) && |
else if (c->efd != -1 && !(c->flags & CHAN_EOF_SENT) && |
(c->extended_usage == CHAN_EXTENDED_READ || |
(c->extended_usage == CHAN_EXTENDED_READ || |
c->extended_usage == CHAN_EXTENDED_IGNORE) && |
c->extended_usage == CHAN_EXTENDED_IGNORE) && |
sshbuf_len(c->extended) < c->remote_window) |
sshbuf_len(c->extended) < c->remote_window) |
FD_SET(c->efd, readset); |
c->io_want |= SSH_CHAN_IO_EFD_R; |
} |
} |
/* XXX: What about efd? races? */ |
/* XXX: What about efd? races? */ |
} |
} |
|
|
} |
} |
|
|
static void |
static void |
channel_pre_x11_open(struct ssh *ssh, Channel *c, |
channel_pre_x11_open(struct ssh *ssh, Channel *c) |
fd_set *readset, fd_set *writeset) |
|
{ |
{ |
int ret = x11_open_helper(ssh, c->output); |
int ret = x11_open_helper(ssh, c->output); |
|
|
|
|
|
|
if (ret == 1) { |
if (ret == 1) { |
c->type = SSH_CHANNEL_OPEN; |
c->type = SSH_CHANNEL_OPEN; |
channel_pre_open(ssh, c, readset, writeset); |
channel_pre_open(ssh, c); |
} else if (ret == -1) { |
} else if (ret == -1) { |
logit("X11 connection rejected because of wrong authentication."); |
logit("X11 connection rejected because of wrong authentication."); |
debug2("X11 rejected %d i%d/o%d", |
debug2("X11 rejected %d i%d/o%d", |
|
|
} |
} |
|
|
static void |
static void |
channel_pre_mux_client(struct ssh *ssh, |
channel_pre_mux_client(struct ssh *ssh, Channel *c) |
Channel *c, fd_set *readset, fd_set *writeset) |
|
{ |
{ |
|
c->io_want = 0; |
if (c->istate == CHAN_INPUT_OPEN && !c->mux_pause && |
if (c->istate == CHAN_INPUT_OPEN && !c->mux_pause && |
sshbuf_check_reserve(c->input, CHAN_RBUF) == 0) |
sshbuf_check_reserve(c->input, CHAN_RBUF) == 0) |
FD_SET(c->rfd, readset); |
c->io_want |= SSH_CHAN_IO_RFD; |
if (c->istate == CHAN_INPUT_WAIT_DRAIN) { |
if (c->istate == CHAN_INPUT_WAIT_DRAIN) { |
/* clear buffer immediately (discard any partial packet) */ |
/* clear buffer immediately (discard any partial packet) */ |
sshbuf_reset(c->input); |
sshbuf_reset(c->input); |
|
|
if (c->ostate == CHAN_OUTPUT_OPEN || |
if (c->ostate == CHAN_OUTPUT_OPEN || |
c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { |
c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { |
if (sshbuf_len(c->output) > 0) |
if (sshbuf_len(c->output) > 0) |
FD_SET(c->wfd, writeset); |
c->io_want |= SSH_CHAN_IO_WFD; |
else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) |
else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) |
chan_obuf_empty(ssh, c); |
chan_obuf_empty(ssh, c); |
} |
} |
|
|
|
|
/* dynamic port forwarding */ |
/* dynamic port forwarding */ |
static void |
static void |
channel_pre_dynamic(struct ssh *ssh, Channel *c, |
channel_pre_dynamic(struct ssh *ssh, Channel *c) |
fd_set *readset, fd_set *writeset) |
|
{ |
{ |
const u_char *p; |
const u_char *p; |
u_int have; |
u_int have; |
int ret; |
int ret; |
|
|
|
c->io_want = 0; |
have = sshbuf_len(c->input); |
have = sshbuf_len(c->input); |
debug2("channel %d: pre_dynamic: have %d", c->self, have); |
debug2("channel %d: pre_dynamic: have %d", c->self, have); |
/* sshbuf_dump(c->input, stderr); */ |
/* sshbuf_dump(c->input, stderr); */ |
/* check if the fixed size part of the packet is in buffer. */ |
/* check if the fixed size part of the packet is in buffer. */ |
if (have < 3) { |
if (have < 3) { |
/* need more */ |
/* need more */ |
FD_SET(c->sock, readset); |
c->io_want |= SSH_CHAN_IO_RFD; |
return; |
return; |
} |
} |
/* try to guess the protocol */ |
/* try to guess the protocol */ |
|
|
} else if (ret == 0) { |
} else if (ret == 0) { |
debug2("channel %d: pre_dynamic: need more", c->self); |
debug2("channel %d: pre_dynamic: need more", c->self); |
/* need more */ |
/* need more */ |
FD_SET(c->sock, readset); |
c->io_want |= SSH_CHAN_IO_RFD; |
if (sshbuf_len(c->output)) |
if (sshbuf_len(c->output)) |
FD_SET(c->sock, writeset); |
c->io_want |= SSH_CHAN_IO_WFD; |
} else { |
} else { |
/* switch to the next state */ |
/* switch to the next state */ |
c->type = SSH_CHANNEL_OPENING; |
c->type = SSH_CHANNEL_OPENING; |
|
|
|
|
/* This is our fake X11 server socket. */ |
/* This is our fake X11 server socket. */ |
static void |
static void |
channel_post_x11_listener(struct ssh *ssh, Channel *c, |
channel_post_x11_listener(struct ssh *ssh, Channel *c) |
fd_set *readset, fd_set *writeset) |
|
{ |
{ |
Channel *nc; |
Channel *nc; |
struct sockaddr_storage addr; |
struct sockaddr_storage addr; |
|
|
socklen_t addrlen; |
socklen_t addrlen; |
char buf[16384], *remote_ipaddr; |
char buf[16384], *remote_ipaddr; |
|
|
if (!FD_ISSET(c->sock, readset)) |
if ((c->io_ready & SSH_CHAN_IO_SOCK_R) == 0) |
return; |
return; |
|
|
debug("X11 connection requested."); |
debug("X11 connection requested."); |
|
|
* This socket is listening for connections to a forwarded TCP/IP port. |
* This socket is listening for connections to a forwarded TCP/IP port. |
*/ |
*/ |
static void |
static void |
channel_post_port_listener(struct ssh *ssh, Channel *c, |
channel_post_port_listener(struct ssh *ssh, Channel *c) |
fd_set *readset, fd_set *writeset) |
|
{ |
{ |
Channel *nc; |
Channel *nc; |
struct sockaddr_storage addr; |
struct sockaddr_storage addr; |
|
|
socklen_t addrlen; |
socklen_t addrlen; |
char *rtype; |
char *rtype; |
|
|
if (!FD_ISSET(c->sock, readset)) |
if ((c->io_ready & SSH_CHAN_IO_SOCK_R) == 0) |
return; |
return; |
|
|
debug("Connection to port %d forwarding to %.100s port %d requested.", |
debug("Connection to port %d forwarding to %.100s port %d requested.", |
|
|
* clients. |
* clients. |
*/ |
*/ |
static void |
static void |
channel_post_auth_listener(struct ssh *ssh, Channel *c, |
channel_post_auth_listener(struct ssh *ssh, Channel *c) |
fd_set *readset, fd_set *writeset) |
|
{ |
{ |
Channel *nc; |
Channel *nc; |
int r, newsock; |
int r, newsock; |
struct sockaddr_storage addr; |
struct sockaddr_storage addr; |
socklen_t addrlen; |
socklen_t addrlen; |
|
|
if (!FD_ISSET(c->sock, readset)) |
if ((c->io_ready & SSH_CHAN_IO_SOCK_R) == 0) |
return; |
return; |
|
|
addrlen = sizeof(addr); |
addrlen = sizeof(addr); |
|
|
} |
} |
|
|
static void |
static void |
channel_post_connecting(struct ssh *ssh, Channel *c, |
channel_post_connecting(struct ssh *ssh, Channel *c) |
fd_set *readset, fd_set *writeset) |
|
{ |
{ |
int err = 0, sock, isopen, r; |
int err = 0, sock, isopen, r; |
socklen_t sz = sizeof(err); |
socklen_t sz = sizeof(err); |
|
|
if (!FD_ISSET(c->sock, writeset)) |
if ((c->io_ready & SSH_CHAN_IO_SOCK_W) == 0) |
return; |
return; |
if (!c->have_remote_id) |
if (!c->have_remote_id) |
fatal_f("channel %d: no remote id", c->self); |
fatal_f("channel %d: no remote id", c->self); |
|
|
} |
} |
|
|
static int |
static int |
channel_handle_rfd(struct ssh *ssh, Channel *c, |
channel_handle_rfd(struct ssh *ssh, Channel *c) |
fd_set *readset, fd_set *writeset) |
|
{ |
{ |
char buf[CHAN_RBUF]; |
char buf[CHAN_RBUF]; |
ssize_t len; |
ssize_t len; |
int r; |
int r; |
|
|
if (c->rfd == -1 || !FD_ISSET(c->rfd, readset)) |
if ((c->io_ready & SSH_CHAN_IO_RFD) == 0) |
return 1; |
return 1; |
|
|
len = read(c->rfd, buf, sizeof(buf)); |
len = read(c->rfd, buf, sizeof(buf)); |
|
|
} |
} |
|
|
static int |
static int |
channel_handle_wfd(struct ssh *ssh, Channel *c, |
channel_handle_wfd(struct ssh *ssh, Channel *c) |
fd_set *readset, fd_set *writeset) |
|
{ |
{ |
struct termios tio; |
struct termios tio; |
u_char *data = NULL, *buf; /* XXX const; need filter API change */ |
u_char *data = NULL, *buf; /* XXX const; need filter API change */ |
size_t dlen, olen = 0; |
size_t dlen, olen = 0; |
int r, len; |
int r, len; |
|
|
if (c->wfd == -1 || !FD_ISSET(c->wfd, writeset) || |
if ((c->io_ready & SSH_CHAN_IO_WFD) == 0) |
sshbuf_len(c->output) == 0) |
|
return 1; |
return 1; |
|
if (sshbuf_len(c->output) == 0) |
|
return 1; |
|
|
/* Send buffered output data to the socket. */ |
/* Send buffered output data to the socket. */ |
olen = sshbuf_len(c->output); |
olen = sshbuf_len(c->output); |
|
|
} |
} |
|
|
static int |
static int |
channel_handle_efd_write(struct ssh *ssh, Channel *c, |
channel_handle_efd_write(struct ssh *ssh, Channel *c) |
fd_set *readset, fd_set *writeset) |
|
{ |
{ |
int r; |
int r; |
ssize_t len; |
ssize_t len; |
|
|
if (!FD_ISSET(c->efd, writeset) || sshbuf_len(c->extended) == 0) |
if ((c->io_ready & SSH_CHAN_IO_EFD_W) == 0) |
return 1; |
return 1; |
|
if (sshbuf_len(c->extended) == 0) |
|
return 1; |
|
|
len = write(c->efd, sshbuf_ptr(c->extended), |
len = write(c->efd, sshbuf_ptr(c->extended), |
sshbuf_len(c->extended)); |
sshbuf_len(c->extended)); |
|
|
} |
} |
|
|
static int |
static int |
channel_handle_efd_read(struct ssh *ssh, Channel *c, |
channel_handle_efd_read(struct ssh *ssh, Channel *c) |
fd_set *readset, fd_set *writeset) |
|
{ |
{ |
char buf[CHAN_RBUF]; |
char buf[CHAN_RBUF]; |
int r; |
int r; |
ssize_t len; |
ssize_t len; |
|
|
if (!FD_ISSET(c->efd, readset)) |
if ((c->io_ready & SSH_CHAN_IO_EFD_R) == 0) |
return 1; |
return 1; |
|
|
len = read(c->efd, buf, sizeof(buf)); |
len = read(c->efd, buf, sizeof(buf)); |
|
|
} |
} |
|
|
static int |
static int |
channel_handle_efd(struct ssh *ssh, Channel *c, |
channel_handle_efd(struct ssh *ssh, Channel *c) |
fd_set *readset, fd_set *writeset) |
|
{ |
{ |
if (c->efd == -1) |
if (c->efd == -1) |
return 1; |
return 1; |
|
|
/** XXX handle drain efd, too */ |
/** XXX handle drain efd, too */ |
|
|
if (c->extended_usage == CHAN_EXTENDED_WRITE) |
if (c->extended_usage == CHAN_EXTENDED_WRITE) |
return channel_handle_efd_write(ssh, c, readset, writeset); |
return channel_handle_efd_write(ssh, c); |
else if (c->extended_usage == CHAN_EXTENDED_READ || |
else if (c->extended_usage == CHAN_EXTENDED_READ || |
c->extended_usage == CHAN_EXTENDED_IGNORE) |
c->extended_usage == CHAN_EXTENDED_IGNORE) |
return channel_handle_efd_read(ssh, c, readset, writeset); |
return channel_handle_efd_read(ssh, c); |
|
|
return 1; |
return 1; |
} |
} |
|
|
} |
} |
|
|
static void |
static void |
channel_post_open(struct ssh *ssh, Channel *c, |
channel_post_open(struct ssh *ssh, Channel *c) |
fd_set *readset, fd_set *writeset) |
|
{ |
{ |
channel_handle_rfd(ssh, c, readset, writeset); |
channel_handle_rfd(ssh, c); |
channel_handle_wfd(ssh, c, readset, writeset); |
channel_handle_wfd(ssh, c); |
channel_handle_efd(ssh, c, readset, writeset); |
channel_handle_efd(ssh, c); |
channel_check_window(ssh, c); |
channel_check_window(ssh, c); |
} |
} |
|
|
|
|
} |
} |
|
|
static void |
static void |
channel_post_mux_client_read(struct ssh *ssh, Channel *c, |
channel_post_mux_client_read(struct ssh *ssh, Channel *c) |
fd_set *readset, fd_set *writeset) |
|
{ |
{ |
u_int need; |
u_int need; |
|
|
if (c->rfd == -1 || !FD_ISSET(c->rfd, readset)) |
if ((c->io_ready & SSH_CHAN_IO_RFD) == 0) |
return; |
return; |
if (c->istate != CHAN_INPUT_OPEN && c->istate != CHAN_INPUT_WAIT_DRAIN) |
if (c->istate != CHAN_INPUT_OPEN && c->istate != CHAN_INPUT_WAIT_DRAIN) |
return; |
return; |
|
|
} |
} |
|
|
static void |
static void |
channel_post_mux_client_write(struct ssh *ssh, Channel *c, |
channel_post_mux_client_write(struct ssh *ssh, Channel *c) |
fd_set *readset, fd_set *writeset) |
|
{ |
{ |
ssize_t len; |
ssize_t len; |
int r; |
int r; |
|
|
if (c->wfd == -1 || !FD_ISSET(c->wfd, writeset) || |
if ((c->io_ready & SSH_CHAN_IO_WFD) == 0) |
sshbuf_len(c->output) == 0) |
|
return; |
return; |
|
if (sshbuf_len(c->output) == 0) |
|
return; |
|
|
len = write(c->wfd, sshbuf_ptr(c->output), sshbuf_len(c->output)); |
len = write(c->wfd, sshbuf_ptr(c->output), sshbuf_len(c->output)); |
if (len == -1 && (errno == EINTR || errno == EAGAIN)) |
if (len == -1 && (errno == EINTR || errno == EAGAIN)) |
|
|
} |
} |
|
|
static void |
static void |
channel_post_mux_client(struct ssh *ssh, Channel *c, |
channel_post_mux_client(struct ssh *ssh, Channel *c) |
fd_set *readset, fd_set *writeset) |
|
{ |
{ |
channel_post_mux_client_read(ssh, c, readset, writeset); |
channel_post_mux_client_read(ssh, c); |
channel_post_mux_client_write(ssh, c, readset, writeset); |
channel_post_mux_client_write(ssh, c); |
} |
} |
|
|
static void |
static void |
channel_post_mux_listener(struct ssh *ssh, Channel *c, |
channel_post_mux_listener(struct ssh *ssh, Channel *c) |
fd_set *readset, fd_set *writeset) |
|
{ |
{ |
Channel *nc; |
Channel *nc; |
struct sockaddr_storage addr; |
struct sockaddr_storage addr; |
|
|
uid_t euid; |
uid_t euid; |
gid_t egid; |
gid_t egid; |
|
|
if (!FD_ISSET(c->sock, readset)) |
if ((c->io_ready & SSH_CHAN_IO_SOCK_R) == 0) |
return; |
return; |
|
|
debug("multiplexing control connection"); |
debug("multiplexing control connection"); |
|
|
enum channel_table { CHAN_PRE, CHAN_POST }; |
enum channel_table { CHAN_PRE, CHAN_POST }; |
|
|
static void |
static void |
channel_handler(struct ssh *ssh, int table, |
channel_handler(struct ssh *ssh, int table, time_t *unpause_secs) |
fd_set *readset, fd_set *writeset, time_t *unpause_secs) |
|
{ |
{ |
struct ssh_channels *sc = ssh->chanctxt; |
struct ssh_channels *sc = ssh->chanctxt; |
chan_fn **ftab = table == CHAN_PRE ? sc->channel_pre : sc->channel_post; |
chan_fn **ftab = table == CHAN_PRE ? sc->channel_pre : sc->channel_post; |
|
|
* Run handlers that are not paused. |
* Run handlers that are not paused. |
*/ |
*/ |
if (c->notbefore <= now) |
if (c->notbefore <= now) |
(*ftab[c->type])(ssh, c, readset, writeset); |
(*ftab[c->type])(ssh, c); |
else if (unpause_secs != NULL) { |
else if (unpause_secs != NULL) { |
/* |
/* |
* Collect the time that the earliest |
* Collect the time that the earliest |
|
|
channel_prepare_select(struct ssh *ssh, fd_set **readsetp, fd_set **writesetp, |
channel_prepare_select(struct ssh *ssh, fd_set **readsetp, fd_set **writesetp, |
int *maxfdp, u_int *nallocp, time_t *minwait_secs) |
int *maxfdp, u_int *nallocp, time_t *minwait_secs) |
{ |
{ |
u_int n, sz, nfdset; |
struct ssh_channels *sc = ssh->chanctxt; |
|
u_int i, n, sz, nfdset, oalloc = sc->channels_alloc; |
|
Channel *c; |
|
|
channel_before_prepare_select(ssh); /* might update channel_max_fd */ |
channel_before_prepare_select(ssh); /* might update channel_max_fd */ |
|
|
|
|
memset(*writesetp, 0, sz); |
memset(*writesetp, 0, sz); |
|
|
if (!ssh_packet_is_rekeying(ssh)) |
if (!ssh_packet_is_rekeying(ssh)) |
channel_handler(ssh, CHAN_PRE, *readsetp, *writesetp, |
channel_handler(ssh, CHAN_PRE, minwait_secs); |
minwait_secs); |
|
|
/* Convert c->io_want into FD_SET */ |
|
for (i = 0; i < oalloc; i++) { |
|
c = sc->channels[i]; |
|
if (c == NULL) |
|
continue; |
|
if ((c->io_want & SSH_CHAN_IO_RFD) != 0) { |
|
if (c->rfd == -1) |
|
fatal_f("channel %d: no rfd", c->self); |
|
FD_SET(c->rfd, *readsetp); |
|
} |
|
if ((c->io_want & SSH_CHAN_IO_WFD) != 0) { |
|
if (c->wfd == -1) |
|
fatal_f("channel %d: no wfd", c->self); |
|
FD_SET(c->wfd, *writesetp); |
|
} |
|
if ((c->io_want & SSH_CHAN_IO_EFD_R) != 0) { |
|
if (c->efd == -1) |
|
fatal_f("channel %d: no efd(r)", c->self); |
|
FD_SET(c->efd, *readsetp); |
|
} |
|
if ((c->io_want & SSH_CHAN_IO_EFD_W) != 0) { |
|
if (c->efd == -1) |
|
fatal_f("channel %d: no efd(w)", c->self); |
|
FD_SET(c->efd, *writesetp); |
|
} |
|
if ((c->io_want & SSH_CHAN_IO_SOCK_R) != 0) { |
|
if (c->sock == -1) |
|
fatal_f("channel %d: no sock(r)", c->self); |
|
FD_SET(c->sock, *readsetp); |
|
} |
|
if ((c->io_want & SSH_CHAN_IO_SOCK_W) != 0) { |
|
if (c->sock == -1) |
|
fatal_f("channel %d: no sock(w)", c->self); |
|
FD_SET(c->sock, *writesetp); |
|
} |
|
} |
} |
} |
|
|
/* |
/* |
|
|
void |
void |
channel_after_select(struct ssh *ssh, fd_set *readset, fd_set *writeset) |
channel_after_select(struct ssh *ssh, fd_set *readset, fd_set *writeset) |
{ |
{ |
channel_handler(ssh, CHAN_POST, readset, writeset, NULL); |
struct ssh_channels *sc = ssh->chanctxt; |
|
Channel *c; |
|
u_int i, oalloc = sc->channels_alloc; |
|
|
|
/* Convert FD_SET into c->io_ready */ |
|
for (i = 0; i < oalloc; i++) { |
|
c = sc->channels[i]; |
|
if (c == NULL) |
|
continue; |
|
c->io_ready = 0; |
|
if (c->rfd != -1 && FD_ISSET(c->rfd, readset)) |
|
c->io_ready |= SSH_CHAN_IO_RFD; |
|
if (c->wfd != -1 && FD_ISSET(c->wfd, writeset)) |
|
c->io_ready |= SSH_CHAN_IO_WFD; |
|
if (c->efd != -1 && FD_ISSET(c->efd, readset)) |
|
c->io_ready |= SSH_CHAN_IO_EFD_R; |
|
if (c->efd != -1 && FD_ISSET(c->efd, writeset)) |
|
c->io_ready |= SSH_CHAN_IO_EFD_W; |
|
if (c->sock != -1 && FD_ISSET(c->sock, readset)) |
|
c->io_ready |= SSH_CHAN_IO_SOCK_R; |
|
if (c->sock != -1 && FD_ISSET(c->sock, writeset)) |
|
c->io_ready |= SSH_CHAN_IO_SOCK_W; |
|
} |
|
channel_handler(ssh, CHAN_POST, NULL); |
} |
} |
|
|
/* |
/* |