diff options
author | Damien Miller <djm@mindrot.org> | 2004-06-15 10:34:08 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2004-06-15 10:34:08 +1000 |
commit | 0e220dbfbcc9fe252e8f1f4890dbfa415aad35db (patch) | |
tree | b78bab0c628cd5bdb0ec95340f533a1be2fae75f /channels.c | |
parent | 05202ffe214115afa24bf6e7a6d8c8457e6759bb (diff) |
- djm@cvs.openbsd.org 2004/06/13 15:03:02
[channels.c channels.h clientloop.c clientloop.h includes.h readconf.c]
[readconf.h scp.1 sftp.1 ssh.1 ssh.c ssh_config.5]
implement session multiplexing in the client (the server has supported
this since 2.0); ok markus@
Diffstat (limited to 'channels.c')
-rw-r--r-- | channels.c | 76 |
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" |
42 | RCSID("$OpenBSD: channels.c,v 1.203 2004/05/26 23:02:39 markus Exp $"); | 42 | RCSID("$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) | |||
304 | static void | 306 | static void |
305 | channel_close_fds(Channel *c) | 307 | channel_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 | } |
605 | void | 611 | void |
606 | channel_register_confirm(int id, channel_callback_fn *fn) | 612 | channel_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 | } |
616 | void | 623 | void |
617 | channel_register_cleanup(int id, channel_callback_fn *fn) | 624 | channel_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 | ||
734 | static void | 745 | static void |
@@ -1482,6 +1493,33 @@ channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset) | |||
1482 | return 1; | 1493 | return 1; |
1483 | } | 1494 | } |
1484 | static int | 1495 | static int |
1496 | channel_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 | } | ||
1522 | static int | ||
1485 | channel_check_window(Channel *c) | 1523 | channel_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 | ||
2573 | void | ||
2574 | channel_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 | /* |