summaryrefslogtreecommitdiff
path: root/channels.c
diff options
context:
space:
mode:
Diffstat (limited to 'channels.c')
-rw-r--r--channels.c41
1 files changed, 26 insertions, 15 deletions
diff --git a/channels.c b/channels.c
index fd6244d48..1cd5004c4 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: channels.c,v 1.308 2010/07/13 23:13:16 djm Exp $ */ 1/* $OpenBSD: channels.c,v 1.309 2010/08/05 13:08:42 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1644,13 +1644,14 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset)
1644{ 1644{
1645 struct termios tio; 1645 struct termios tio;
1646 u_char *data = NULL, *buf; 1646 u_char *data = NULL, *buf;
1647 u_int dlen; 1647 u_int dlen, olen = 0;
1648 int len; 1648 int len;
1649 1649
1650 /* Send buffered output data to the socket. */ 1650 /* Send buffered output data to the socket. */
1651 if (c->wfd != -1 && 1651 if (c->wfd != -1 &&
1652 FD_ISSET(c->wfd, writeset) && 1652 FD_ISSET(c->wfd, writeset) &&
1653 buffer_len(&c->output) > 0) { 1653 buffer_len(&c->output) > 0) {
1654 olen = buffer_len(&c->output);
1654 if (c->output_filter != NULL) { 1655 if (c->output_filter != NULL) {
1655 if ((buf = c->output_filter(c, &data, &dlen)) == NULL) { 1656 if ((buf = c->output_filter(c, &data, &dlen)) == NULL) {
1656 debug2("channel %d: filter stops", c->self); 1657 debug2("channel %d: filter stops", c->self);
@@ -1669,7 +1670,6 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset)
1669 1670
1670 if (c->datagram) { 1671 if (c->datagram) {
1671 /* ignore truncated writes, datagrams might get lost */ 1672 /* ignore truncated writes, datagrams might get lost */
1672 c->local_consumed += dlen + 4;
1673 len = write(c->wfd, buf, dlen); 1673 len = write(c->wfd, buf, dlen);
1674 xfree(data); 1674 xfree(data);
1675 if (len < 0 && (errno == EINTR || errno == EAGAIN || 1675 if (len < 0 && (errno == EINTR || errno == EAGAIN ||
@@ -1682,7 +1682,7 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset)
1682 chan_write_failed(c); 1682 chan_write_failed(c);
1683 return -1; 1683 return -1;
1684 } 1684 }
1685 return 1; 1685 goto out;
1686 } 1686 }
1687#ifdef _AIX 1687#ifdef _AIX
1688 /* XXX: Later AIX versions can't push as much data to tty */ 1688 /* XXX: Later AIX versions can't push as much data to tty */
@@ -1724,10 +1724,10 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset)
1724 } 1724 }
1725#endif 1725#endif
1726 buffer_consume(&c->output, len); 1726 buffer_consume(&c->output, len);
1727 if (compat20 && len > 0) {
1728 c->local_consumed += len;
1729 }
1730 } 1727 }
1728 out:
1729 if (compat20 && olen > 0)
1730 c->local_consumed += olen - buffer_len(&c->output);
1731 return 1; 1731 return 1;
1732} 1732}
1733 1733
@@ -2172,6 +2172,14 @@ channel_output_poll(void)
2172 2172
2173 data = buffer_get_string(&c->input, 2173 data = buffer_get_string(&c->input,
2174 &dlen); 2174 &dlen);
2175 if (dlen > c->remote_window ||
2176 dlen > c->remote_maxpacket) {
2177 debug("channel %d: datagram "
2178 "too big for channel",
2179 c->self);
2180 xfree(data);
2181 continue;
2182 }
2175 packet_start(SSH2_MSG_CHANNEL_DATA); 2183 packet_start(SSH2_MSG_CHANNEL_DATA);
2176 packet_put_int(c->remote_id); 2184 packet_put_int(c->remote_id);
2177 packet_put_string(data, dlen); 2185 packet_put_string(data, dlen);
@@ -2257,7 +2265,7 @@ channel_input_data(int type, u_int32_t seq, void *ctxt)
2257{ 2265{
2258 int id; 2266 int id;
2259 char *data; 2267 char *data;
2260 u_int data_len; 2268 u_int data_len, win_len;
2261 Channel *c; 2269 Channel *c;
2262 2270
2263 /* Get the channel number and verify it. */ 2271 /* Get the channel number and verify it. */
@@ -2273,6 +2281,9 @@ channel_input_data(int type, u_int32_t seq, void *ctxt)
2273 2281
2274 /* Get the data. */ 2282 /* Get the data. */
2275 data = packet_get_string_ptr(&data_len); 2283 data = packet_get_string_ptr(&data_len);
2284 win_len = data_len;
2285 if (c->datagram)
2286 win_len += 4; /* string length header */
2276 2287
2277 /* 2288 /*
2278 * Ignore data for protocol > 1.3 if output end is no longer open. 2289 * Ignore data for protocol > 1.3 if output end is no longer open.
@@ -2283,23 +2294,23 @@ channel_input_data(int type, u_int32_t seq, void *ctxt)
2283 */ 2294 */
2284 if (!compat13 && c->ostate != CHAN_OUTPUT_OPEN) { 2295 if (!compat13 && c->ostate != CHAN_OUTPUT_OPEN) {
2285 if (compat20) { 2296 if (compat20) {
2286 c->local_window -= data_len; 2297 c->local_window -= win_len;
2287 c->local_consumed += data_len; 2298 c->local_consumed += win_len;
2288 } 2299 }
2289 return; 2300 return;
2290 } 2301 }
2291 2302
2292 if (compat20) { 2303 if (compat20) {
2293 if (data_len > c->local_maxpacket) { 2304 if (win_len > c->local_maxpacket) {
2294 logit("channel %d: rcvd big packet %d, maxpack %d", 2305 logit("channel %d: rcvd big packet %d, maxpack %d",
2295 c->self, data_len, c->local_maxpacket); 2306 c->self, win_len, c->local_maxpacket);
2296 } 2307 }
2297 if (data_len > c->local_window) { 2308 if (win_len > c->local_window) {
2298 logit("channel %d: rcvd too much data %d, win %d", 2309 logit("channel %d: rcvd too much data %d, win %d",
2299 c->self, data_len, c->local_window); 2310 c->self, win_len, c->local_window);
2300 return; 2311 return;
2301 } 2312 }
2302 c->local_window -= data_len; 2313 c->local_window -= win_len;
2303 } 2314 }
2304 if (c->datagram) 2315 if (c->datagram)
2305 buffer_put_string(&c->output, data, data_len); 2316 buffer_put_string(&c->output, data, data_len);