version 1.367, 2017/09/12 06:32:07 |
version 1.368, 2017/09/12 06:35:31 |
|
|
} |
} |
|
|
Channel * |
Channel * |
channel_by_remote_id(struct ssh *ssh, int remote_id) |
channel_by_remote_id(struct ssh *ssh, u_int remote_id) |
{ |
{ |
Channel *c; |
Channel *c; |
u_int i; |
u_int i; |
|
|
for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { |
for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { |
c = ssh->chanctxt->channels[i]; |
c = ssh->chanctxt->channels[i]; |
if (c != NULL && c->remote_id == remote_id) |
if (c != NULL && c->have_remote_id && c->remote_id == remote_id) |
return c; |
return c; |
} |
} |
return NULL; |
return NULL; |
|
|
c->local_window = window; |
c->local_window = window; |
c->local_window_max = window; |
c->local_window_max = window; |
c->local_maxpacket = maxpack; |
c->local_maxpacket = maxpack; |
c->remote_id = -1; |
|
c->remote_name = xstrdup(remote_name); |
c->remote_name = xstrdup(remote_name); |
c->ctl_chan = -1; |
c->ctl_chan = -1; |
c->delayed = 1; /* prevent call to channel_post handler */ |
c->delayed = 1; /* prevent call to channel_post handler */ |
|
|
|
|
for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { |
for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { |
c = ssh->chanctxt->channels[i]; |
c = ssh->chanctxt->channels[i]; |
if (c == NULL || c->remote_id < 0) |
if (c == NULL || !c->have_remote_id) |
continue; |
continue; |
switch (c->type) { |
switch (c->type) { |
case SSH_CHANNEL_CLOSED: |
case SSH_CHANNEL_CLOSED: |
|
|
case SSH_CHANNEL_MUX_PROXY: |
case SSH_CHANNEL_MUX_PROXY: |
case SSH_CHANNEL_MUX_CLIENT: |
case SSH_CHANNEL_MUX_CLIENT: |
if ((r = sshbuf_putf(buf, " #%d %.300s " |
if ((r = sshbuf_putf(buf, " #%d %.300s " |
"(t%d r%d i%u/%zu o%u/%zu fd %d/%d cc %d)\r\n", |
"(t%d %s%u i%u/%zu o%u/%zu fd %d/%d cc %d)\r\n", |
c->self, c->remote_name, |
c->self, c->remote_name, |
c->type, c->remote_id, |
c->type, |
|
c->have_remote_id ? "r" : "nr", c->remote_id, |
c->istate, sshbuf_len(c->input), |
c->istate, sshbuf_len(c->input), |
c->ostate, sshbuf_len(c->output), |
c->ostate, sshbuf_len(c->output), |
c->rfd, c->wfd, c->ctl_chan)) != 0) |
c->rfd, c->wfd, c->ctl_chan)) != 0) |
|
|
logit("%s: %d: unknown channel id", __func__, id); |
logit("%s: %d: unknown channel id", __func__, id); |
return; |
return; |
} |
} |
|
if (!c->have_remote_id) |
|
fatal(":%s: channel %d: no remote id", __func__, c->self); |
|
|
debug2("channel %d: request %s confirm %d", id, service, wantconfirm); |
debug2("channel %d: request %s confirm %d", id, service, wantconfirm); |
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST)) != 0 || |
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST)) != 0 || |
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
|
|
|
|
if (c == NULL || c->type != SSH_CHANNEL_LARVAL) |
if (c == NULL || c->type != SSH_CHANNEL_LARVAL) |
fatal("channel_activate for non-larval channel %d.", id); |
fatal("channel_activate for non-larval channel %d.", id); |
|
if (!c->have_remote_id) |
|
fatal(":%s: channel %d: no remote id", __func__, c->self); |
|
|
channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, is_tty); |
channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, is_tty); |
c->type = SSH_CHANNEL_OPEN; |
c->type = SSH_CHANNEL_OPEN; |
c->local_window = c->local_window_max = window_max; |
c->local_window = c->local_window_max = window_max; |
|
|
|
|
if (!FD_ISSET(c->sock, writeset)) |
if (!FD_ISSET(c->sock, writeset)) |
return; |
return; |
|
if (!c->have_remote_id) |
|
fatal(":%s: channel %d: no remote id", __func__, c->self); |
|
|
if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) < 0) { |
if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) < 0) { |
err = errno; |
err = errno; |
|
|
c->local_maxpacket*3) || |
c->local_maxpacket*3) || |
c->local_window < c->local_window_max/2) && |
c->local_window < c->local_window_max/2) && |
c->local_consumed > 0) { |
c->local_consumed > 0) { |
|
if (!c->have_remote_id) |
|
fatal(":%s: channel %d: no remote id", |
|
__func__, c->self); |
if ((r = sshpkt_start(ssh, |
if ((r = sshpkt_start(ssh, |
SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 || |
SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 || |
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
|
|
return; |
return; |
} |
} |
|
|
|
if (!c->have_remote_id) |
|
fatal(":%s: channel %d: no remote id", __func__, c->self); |
|
|
if (c->datagram) { |
if (c->datagram) { |
/* Check datagram will fit; drop if not */ |
/* Check datagram will fit; drop if not */ |
if ((r = sshbuf_peek_string_direct(c->input, NULL, &dlen)) != 0) |
if ((r = sshbuf_peek_string_direct(c->input, NULL, &dlen)) != 0) |
|
|
len = c->remote_maxpacket; |
len = c->remote_maxpacket; |
if (len == 0) |
if (len == 0) |
return; |
return; |
|
if (!c->have_remote_id) |
|
fatal(":%s: channel %d: no remote id", __func__, c->self); |
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA)) != 0 || |
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA)) != 0 || |
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
(r = sshpkt_put_u32(ssh, SSH2_EXTENDED_DATA_STDERR)) != 0 || |
(r = sshpkt_put_u32(ssh, SSH2_EXTENDED_DATA_STDERR)) != 0 || |
|
|
c->mux_ctx = downstream; /* point to mux client */ |
c->mux_ctx = downstream; /* point to mux client */ |
c->mux_downstream_id = id; |
c->mux_downstream_id = id; |
c->remote_id = remote_id; |
c->remote_id = remote_id; |
|
c->have_remote_id = 1; |
if ((r = sshbuf_put_u32(modified, remote_id)) != 0 || |
if ((r = sshbuf_put_u32(modified, remote_id)) != 0 || |
(r = sshbuf_put_u32(modified, c->self)) != 0 || |
(r = sshbuf_put_u32(modified, c->self)) != 0 || |
(r = sshbuf_putb(modified, original)) != 0) { |
(r = sshbuf_putb(modified, original)) != 0) { |
|
|
switch (type) { |
switch (type) { |
case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: |
case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: |
/* record remote_id for SSH2_MSG_CHANNEL_CLOSE */ |
/* record remote_id for SSH2_MSG_CHANNEL_CLOSE */ |
if (cp && len > 4) |
if (cp && len > 4) { |
c->remote_id = PEEK_U32(cp); |
c->remote_id = PEEK_U32(cp); |
|
c->have_remote_id = 1; |
|
} |
break; |
break; |
case SSH2_MSG_CHANNEL_CLOSE: |
case SSH2_MSG_CHANNEL_CLOSE: |
if (c->flags & CHAN_CLOSE_SENT) |
if (c->flags & CHAN_CLOSE_SENT) |
|
|
* Record the remote channel number and mark that the channel |
* Record the remote channel number and mark that the channel |
* is now open. |
* is now open. |
*/ |
*/ |
c->remote_id = channel_parse_id(ssh, __func__, "open confirmation"); |
if ((r = sshpkt_get_u32(ssh, &c->remote_id)) != 0 || |
if ((r = sshpkt_get_u32(ssh, &remote_window)) != 0 || |
(r = sshpkt_get_u32(ssh, &remote_window)) != 0 || |
(r = sshpkt_get_u32(ssh, &remote_maxpacket)) != 0) { |
(r = sshpkt_get_u32(ssh, &remote_maxpacket)) != 0) { |
error("%s: window/maxpacket: %s", __func__, ssh_err(r)); |
error("%s: window/maxpacket: %s", __func__, ssh_err(r)); |
packet_disconnect("Invalid open confirmation message"); |
packet_disconnect("Invalid open confirmation message"); |
} |
} |
ssh_packet_check_eom(ssh); |
ssh_packet_check_eom(ssh); |
|
|
|
c->have_remote_id = 1; |
c->remote_window = remote_window; |
c->remote_window = remote_window; |
c->remote_maxpacket = remote_maxpacket; |
c->remote_maxpacket = remote_maxpacket; |
c->type = SSH_CHANNEL_OPEN; |
c->type = SSH_CHANNEL_OPEN; |