summaryrefslogtreecommitdiff
path: root/channels.c
diff options
context:
space:
mode:
Diffstat (limited to 'channels.c')
-rw-r--r--channels.c76
1 files changed, 68 insertions, 8 deletions
diff --git a/channels.c b/channels.c
index 437befa34..1fb1092c8 100644
--- a/channels.c
+++ b/channels.c
@@ -39,7 +39,7 @@
39 */ 39 */
40 40
41#include "includes.h" 41#include "includes.h"
42RCSID("$OpenBSD: channels.c,v 1.203 2004/05/26 23:02:39 markus Exp $"); 42RCSID("$OpenBSD: channels.c,v 1.204 2004/06/13 15:03:02 djm Exp $");
43 43
44#include "ssh.h" 44#include "ssh.h"
45#include "ssh1.h" 45#include "ssh1.h"
@@ -172,6 +172,7 @@ channel_register_fds(Channel *c, int rfd, int wfd, int efd,
172 c->rfd = rfd; 172 c->rfd = rfd;
173 c->wfd = wfd; 173 c->wfd = wfd;
174 c->sock = (rfd == wfd) ? rfd : -1; 174 c->sock = (rfd == wfd) ? rfd : -1;
175 c->ctl_fd = -1; /* XXX: set elsewhere */
175 c->efd = efd; 176 c->efd = efd;
176 c->extended_usage = extusage; 177 c->extended_usage = extusage;
177 178
@@ -263,6 +264,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd,
263 c->single_connection = 0; 264 c->single_connection = 0;
264 c->detach_user = NULL; 265 c->detach_user = NULL;
265 c->confirm = NULL; 266 c->confirm = NULL;
267 c->confirm_ctx = NULL;
266 c->input_filter = NULL; 268 c->input_filter = NULL;
267 debug("channel %d: new [%s]", found, remote_name); 269 debug("channel %d: new [%s]", found, remote_name);
268 return c; 270 return c;
@@ -304,10 +306,11 @@ channel_close_fd(int *fdp)
304static void 306static void
305channel_close_fds(Channel *c) 307channel_close_fds(Channel *c)
306{ 308{
307 debug3("channel %d: close_fds r %d w %d e %d", 309 debug3("channel %d: close_fds r %d w %d e %d c %d",
308 c->self, c->rfd, c->wfd, c->efd); 310 c->self, c->rfd, c->wfd, c->efd, c->ctl_fd);
309 311
310 channel_close_fd(&c->sock); 312 channel_close_fd(&c->sock);
313 channel_close_fd(&c->ctl_fd);
311 channel_close_fd(&c->rfd); 314 channel_close_fd(&c->rfd);
312 channel_close_fd(&c->wfd); 315 channel_close_fd(&c->wfd);
313 channel_close_fd(&c->efd); 316 channel_close_fd(&c->efd);
@@ -333,6 +336,8 @@ channel_free(Channel *c)
333 336
334 if (c->sock != -1) 337 if (c->sock != -1)
335 shutdown(c->sock, SHUT_RDWR); 338 shutdown(c->sock, SHUT_RDWR);
339 if (c->ctl_fd != -1)
340 shutdown(c->ctl_fd, SHUT_RDWR);
336 channel_close_fds(c); 341 channel_close_fds(c);
337 buffer_free(&c->input); 342 buffer_free(&c->input);
338 buffer_free(&c->output); 343 buffer_free(&c->output);
@@ -550,12 +555,13 @@ channel_open_message(void)
550 case SSH_CHANNEL_X11_OPEN: 555 case SSH_CHANNEL_X11_OPEN:
551 case SSH_CHANNEL_INPUT_DRAINING: 556 case SSH_CHANNEL_INPUT_DRAINING:
552 case SSH_CHANNEL_OUTPUT_DRAINING: 557 case SSH_CHANNEL_OUTPUT_DRAINING:
553 snprintf(buf, sizeof buf, " #%d %.300s (t%d r%d i%d/%d o%d/%d fd %d/%d)\r\n", 558 snprintf(buf, sizeof buf,
559 " #%d %.300s (t%d r%d i%d/%d o%d/%d fd %d/%d cfd %d)\r\n",
554 c->self, c->remote_name, 560 c->self, c->remote_name,
555 c->type, c->remote_id, 561 c->type, c->remote_id,
556 c->istate, buffer_len(&c->input), 562 c->istate, buffer_len(&c->input),
557 c->ostate, buffer_len(&c->output), 563 c->ostate, buffer_len(&c->output),
558 c->rfd, c->wfd); 564 c->rfd, c->wfd, c->ctl_fd);
559 buffer_append(&buffer, buf, strlen(buf)); 565 buffer_append(&buffer, buf, strlen(buf));
560 continue; 566 continue;
561 default: 567 default:
@@ -596,14 +602,14 @@ channel_request_start(int id, char *service, int wantconfirm)
596 logit("channel_request_start: %d: unknown channel id", id); 602 logit("channel_request_start: %d: unknown channel id", id);
597 return; 603 return;
598 } 604 }
599 debug2("channel %d: request %s", id, service) ; 605 debug2("channel %d: request %s confirm %d", id, service, wantconfirm);
600 packet_start(SSH2_MSG_CHANNEL_REQUEST); 606 packet_start(SSH2_MSG_CHANNEL_REQUEST);
601 packet_put_int(c->remote_id); 607 packet_put_int(c->remote_id);
602 packet_put_cstring(service); 608 packet_put_cstring(service);
603 packet_put_char(wantconfirm); 609 packet_put_char(wantconfirm);
604} 610}
605void 611void
606channel_register_confirm(int id, channel_callback_fn *fn) 612channel_register_confirm(int id, channel_callback_fn *fn, void *ctx)
607{ 613{
608 Channel *c = channel_lookup(id); 614 Channel *c = channel_lookup(id);
609 615
@@ -612,6 +618,7 @@ channel_register_confirm(int id, channel_callback_fn *fn)
612 return; 618 return;
613 } 619 }
614 c->confirm = fn; 620 c->confirm = fn;
621 c->confirm_ctx = ctx;
615} 622}
616void 623void
617channel_register_cleanup(int id, channel_callback_fn *fn) 624channel_register_cleanup(int id, channel_callback_fn *fn)
@@ -729,6 +736,10 @@ channel_pre_open(Channel *c, fd_set * readset, fd_set * writeset)
729 buffer_len(&c->extended) < c->remote_window) 736 buffer_len(&c->extended) < c->remote_window)
730 FD_SET(c->efd, readset); 737 FD_SET(c->efd, readset);
731 } 738 }
739 /* XXX: What about efd? races? */
740 if (compat20 && c->ctl_fd != -1 &&
741 c->istate == CHAN_INPUT_OPEN && c->ostate == CHAN_OUTPUT_OPEN)
742 FD_SET(c->ctl_fd, readset);
732} 743}
733 744
734static void 745static void
@@ -1482,6 +1493,33 @@ channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset)
1482 return 1; 1493 return 1;
1483} 1494}
1484static int 1495static int
1496channel_handle_ctl(Channel *c, fd_set * readset, fd_set * writeset)
1497{
1498 char buf[16];
1499 int len;
1500
1501 /* Monitor control fd to detect if the slave client exits */
1502 if (c->ctl_fd != -1 && FD_ISSET(c->ctl_fd, readset)) {
1503 len = read(c->ctl_fd, buf, sizeof(buf));
1504 if (len < 0 && (errno == EINTR || errno == EAGAIN))
1505 return 1;
1506 if (len <= 0) {
1507 debug2("channel %d: ctl read<=0", c->self);
1508 if (c->type != SSH_CHANNEL_OPEN) {
1509 debug2("channel %d: not open", c->self);
1510 chan_mark_dead(c);
1511 return -1;
1512 } else {
1513 chan_read_failed(c);
1514 chan_write_failed(c);
1515 }
1516 return -1;
1517 } else
1518 fatal("%s: unexpected data on ctl fd", __func__);
1519 }
1520 return 1;
1521}
1522static int
1485channel_check_window(Channel *c) 1523channel_check_window(Channel *c)
1486{ 1524{
1487 if (c->type == SSH_CHANNEL_OPEN && 1525 if (c->type == SSH_CHANNEL_OPEN &&
@@ -1511,6 +1549,7 @@ channel_post_open(Channel *c, fd_set * readset, fd_set * writeset)
1511 if (!compat20) 1549 if (!compat20)
1512 return; 1550 return;
1513 channel_handle_efd(c, readset, writeset); 1551 channel_handle_efd(c, readset, writeset);
1552 channel_handle_ctl(c, readset, writeset);
1514 channel_check_window(c); 1553 channel_check_window(c);
1515} 1554}
1516 1555
@@ -2011,7 +2050,7 @@ channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt)
2011 c->remote_maxpacket = packet_get_int(); 2050 c->remote_maxpacket = packet_get_int();
2012 if (c->confirm) { 2051 if (c->confirm) {
2013 debug2("callback start"); 2052 debug2("callback start");
2014 c->confirm(c->self, NULL); 2053 c->confirm(c->self, c->confirm_ctx);
2015 debug2("callback done"); 2054 debug2("callback done");
2016 } 2055 }
2017 debug2("channel %d: open confirm rwindow %u rmax %u", c->self, 2056 debug2("channel %d: open confirm rwindow %u rmax %u", c->self,
@@ -2531,6 +2570,27 @@ channel_connect_to(const char *host, u_short port)
2531 return connect_to(host, port); 2570 return connect_to(host, port);
2532} 2571}
2533 2572
2573void
2574channel_send_window_changes(void)
2575{
2576 int i;
2577 struct winsize ws;
2578
2579 for (i = 0; i < channels_alloc; i++) {
2580 if (channels[i] == NULL ||
2581 channels[i]->type != SSH_CHANNEL_OPEN)
2582 continue;
2583 if (ioctl(channels[i]->rfd, TIOCGWINSZ, &ws) < 0)
2584 continue;
2585 channel_request_start(i, "window-change", 0);
2586 packet_put_int(ws.ws_col);
2587 packet_put_int(ws.ws_row);
2588 packet_put_int(ws.ws_xpixel);
2589 packet_put_int(ws.ws_ypixel);
2590 packet_send();
2591 }
2592}
2593
2534/* -- X11 forwarding */ 2594/* -- X11 forwarding */
2535 2595
2536/* 2596/*