diff options
Diffstat (limited to 'channels.c')
-rw-r--r-- | channels.c | 35 |
1 files changed, 24 insertions, 11 deletions
diff --git a/channels.c b/channels.c index b431532a3..ed5903f6f 100644 --- a/channels.c +++ b/channels.c | |||
@@ -39,7 +39,7 @@ | |||
39 | */ | 39 | */ |
40 | 40 | ||
41 | #include "includes.h" | 41 | #include "includes.h" |
42 | RCSID("$OpenBSD: channels.c,v 1.230 2005/12/28 22:46:06 stevesk Exp $"); | 42 | RCSID("$OpenBSD: channels.c,v 1.231 2005/12/30 15:56:36 reyk Exp $"); |
43 | 43 | ||
44 | #include "ssh.h" | 44 | #include "ssh.h" |
45 | #include "ssh1.h" | 45 | #include "ssh1.h" |
@@ -58,8 +58,6 @@ RCSID("$OpenBSD: channels.c,v 1.230 2005/12/28 22:46:06 stevesk Exp $"); | |||
58 | 58 | ||
59 | /* -- channel core */ | 59 | /* -- channel core */ |
60 | 60 | ||
61 | #define CHAN_RBUF 16*1024 | ||
62 | |||
63 | /* | 61 | /* |
64 | * Pointer to an array containing all allocated channels. The array is | 62 | * Pointer to an array containing all allocated channels. The array is |
65 | * dynamically extended as needed. | 63 | * dynamically extended as needed. |
@@ -301,6 +299,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, | |||
301 | c->confirm = NULL; | 299 | c->confirm = NULL; |
302 | c->confirm_ctx = NULL; | 300 | c->confirm_ctx = NULL; |
303 | c->input_filter = NULL; | 301 | c->input_filter = NULL; |
302 | c->output_filter = NULL; | ||
304 | debug("channel %d: new [%s]", found, remote_name); | 303 | debug("channel %d: new [%s]", found, remote_name); |
305 | return c; | 304 | return c; |
306 | } | 305 | } |
@@ -681,7 +680,8 @@ channel_cancel_cleanup(int id) | |||
681 | c->detach_close = 0; | 680 | c->detach_close = 0; |
682 | } | 681 | } |
683 | void | 682 | void |
684 | channel_register_filter(int id, channel_filter_fn *fn) | 683 | channel_register_filter(int id, channel_infilter_fn *ifn, |
684 | channel_outfilter_fn *ofn) | ||
685 | { | 685 | { |
686 | Channel *c = channel_lookup(id); | 686 | Channel *c = channel_lookup(id); |
687 | 687 | ||
@@ -689,7 +689,8 @@ channel_register_filter(int id, channel_filter_fn *fn) | |||
689 | logit("channel_register_filter: %d: bad id", id); | 689 | logit("channel_register_filter: %d: bad id", id); |
690 | return; | 690 | return; |
691 | } | 691 | } |
692 | c->input_filter = fn; | 692 | c->input_filter = ifn; |
693 | c->output_filter = ofn; | ||
693 | } | 694 | } |
694 | 695 | ||
695 | void | 696 | void |
@@ -1454,7 +1455,7 @@ static int | |||
1454 | channel_handle_wfd(Channel *c, fd_set * readset, fd_set * writeset) | 1455 | channel_handle_wfd(Channel *c, fd_set * readset, fd_set * writeset) |
1455 | { | 1456 | { |
1456 | struct termios tio; | 1457 | struct termios tio; |
1457 | u_char *data; | 1458 | u_char *data = NULL, *buf; |
1458 | u_int dlen; | 1459 | u_int dlen; |
1459 | int len; | 1460 | int len; |
1460 | 1461 | ||
@@ -1462,11 +1463,22 @@ channel_handle_wfd(Channel *c, fd_set * readset, fd_set * writeset) | |||
1462 | if (c->wfd != -1 && | 1463 | if (c->wfd != -1 && |
1463 | FD_ISSET(c->wfd, writeset) && | 1464 | FD_ISSET(c->wfd, writeset) && |
1464 | buffer_len(&c->output) > 0) { | 1465 | buffer_len(&c->output) > 0) { |
1466 | if (c->output_filter != NULL) { | ||
1467 | if ((buf = c->output_filter(c, &data, &dlen)) == NULL) { | ||
1468 | debug2("channel %d: filter stops", c->self); | ||
1469 | chan_read_failed(c); | ||
1470 | } | ||
1471 | } else if (c->datagram) { | ||
1472 | buf = data = buffer_get_string(&c->output, &dlen); | ||
1473 | } else { | ||
1474 | buf = data = buffer_ptr(&c->output); | ||
1475 | dlen = buffer_len(&c->output); | ||
1476 | } | ||
1477 | |||
1465 | if (c->datagram) { | 1478 | if (c->datagram) { |
1466 | data = buffer_get_string(&c->output, &dlen); | ||
1467 | /* ignore truncated writes, datagrams might get lost */ | 1479 | /* ignore truncated writes, datagrams might get lost */ |
1468 | c->local_consumed += dlen + 4; | 1480 | c->local_consumed += dlen + 4; |
1469 | len = write(c->wfd, data, dlen); | 1481 | len = write(c->wfd, buf, dlen); |
1470 | xfree(data); | 1482 | xfree(data); |
1471 | if (len < 0 && (errno == EINTR || errno == EAGAIN)) | 1483 | if (len < 0 && (errno == EINTR || errno == EAGAIN)) |
1472 | return 1; | 1484 | return 1; |
@@ -1486,7 +1498,8 @@ channel_handle_wfd(Channel *c, fd_set * readset, fd_set * writeset) | |||
1486 | if (compat20 && c->wfd_isatty) | 1498 | if (compat20 && c->wfd_isatty) |
1487 | dlen = MIN(dlen, 8*1024); | 1499 | dlen = MIN(dlen, 8*1024); |
1488 | #endif | 1500 | #endif |
1489 | len = write(c->wfd, data, dlen); | 1501 | |
1502 | len = write(c->wfd, buf, dlen); | ||
1490 | if (len < 0 && (errno == EINTR || errno == EAGAIN)) | 1503 | if (len < 0 && (errno == EINTR || errno == EAGAIN)) |
1491 | return 1; | 1504 | return 1; |
1492 | if (len <= 0) { | 1505 | if (len <= 0) { |
@@ -1503,14 +1516,14 @@ channel_handle_wfd(Channel *c, fd_set * readset, fd_set * writeset) | |||
1503 | } | 1516 | } |
1504 | return -1; | 1517 | return -1; |
1505 | } | 1518 | } |
1506 | if (compat20 && c->isatty && dlen >= 1 && data[0] != '\r') { | 1519 | if (compat20 && c->isatty && dlen >= 1 && buf[0] != '\r') { |
1507 | if (tcgetattr(c->wfd, &tio) == 0 && | 1520 | if (tcgetattr(c->wfd, &tio) == 0 && |
1508 | !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { | 1521 | !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { |
1509 | /* | 1522 | /* |
1510 | * Simulate echo to reduce the impact of | 1523 | * Simulate echo to reduce the impact of |
1511 | * traffic analysis. We need to match the | 1524 | * traffic analysis. We need to match the |
1512 | * size of a SSH2_MSG_CHANNEL_DATA message | 1525 | * size of a SSH2_MSG_CHANNEL_DATA message |
1513 | * (4 byte channel id + data) | 1526 | * (4 byte channel id + buf) |
1514 | */ | 1527 | */ |
1515 | packet_send_ignore(4 + len); | 1528 | packet_send_ignore(4 + len); |
1516 | packet_send(); | 1529 | packet_send(); |