summaryrefslogtreecommitdiff
path: root/clientloop.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2010-01-26 13:26:22 +1100
committerDamien Miller <djm@mindrot.org>2010-01-26 13:26:22 +1100
commite1537f951fa87e4d070adda82b474b25cf4902ec (patch)
tree3c9d794dcf7fca1d880ffd9db24b20038d3f800b /clientloop.c
parentf589fd1ea8c352e6bf819733ecd505119a694c51 (diff)
- djm@cvs.openbsd.org 2010/01/26 01:28:35
[channels.c channels.h clientloop.c clientloop.h mux.c nchan.c ssh.c] rewrite ssh(1) multiplexing code to a more sensible protocol. The new multiplexing code uses channels for the listener and accepted control sockets to make the mux master non-blocking, so no stalls when processing messages from a slave. avoid use of fatal() in mux master protocol parsing so an errant slave process cannot take down a running master. implement requesting of port-forwards over multiplexed sessions. Any port forwards requested by the slave are added to those the master has established. add support for stdio forwarding ("ssh -W host:port ...") in mux slaves. document master/slave mux protocol so that other tools can use it to control a running ssh(1). Note: there are no guarantees that this protocol won't be incompatibly changed (though it is versioned). feedback Salvador Fandino, dtucker@ channel changes ok markus@
Diffstat (limited to 'clientloop.c')
-rw-r--r--clientloop.c35
1 files changed, 12 insertions, 23 deletions
diff --git a/clientloop.c b/clientloop.c
index 5793a6e91..05f4720a1 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: clientloop.c,v 1.216 2010/01/09 05:04:24 djm Exp $ */ 1/* $OpenBSD: clientloop.c,v 1.217 2010/01/26 01:28:35 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
@@ -121,7 +121,7 @@ extern int stdin_null_flag;
121extern int no_shell_flag; 121extern int no_shell_flag;
122 122
123/* Control socket */ 123/* Control socket */
124extern int muxserver_sock; 124extern int muxserver_sock; /* XXX use mux_client_cleanup() instead */
125 125
126/* 126/*
127 * Name of the host we are connecting to. This is the name given on the 127 * Name of the host we are connecting to. This is the name given on the
@@ -146,7 +146,7 @@ static volatile sig_atomic_t received_signal = 0;
146static int in_non_blocking_mode = 0; 146static int in_non_blocking_mode = 0;
147 147
148/* Common data for the client loop code. */ 148/* Common data for the client loop code. */
149static volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */ 149volatile sig_atomic_t quit_pending; /* Set non-zero to quit the loop. */
150static int escape_char1; /* Escape character. (proto1 only) */ 150static int escape_char1; /* Escape character. (proto1 only) */
151static int escape_pending1; /* Last character was an escape (proto1 only) */ 151static int escape_pending1; /* Last character was an escape (proto1 only) */
152static int last_was_cr; /* Last character was a newline. */ 152static int last_was_cr; /* Last character was a newline. */
@@ -564,9 +564,6 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
564 if (packet_have_data_to_write()) 564 if (packet_have_data_to_write())
565 FD_SET(connection_out, *writesetp); 565 FD_SET(connection_out, *writesetp);
566 566
567 if (muxserver_sock != -1)
568 FD_SET(muxserver_sock, *readsetp);
569
570 /* 567 /*
571 * Wait for something to happen. This will suspend the process until 568 * Wait for something to happen. This will suspend the process until
572 * some selected descriptor can be read, written, or has some other 569 * some selected descriptor can be read, written, or has some other
@@ -695,7 +692,7 @@ client_status_confirm(int type, Channel *c, void *ctx)
695 692
696 /* XXX supress on mux _client_ quietmode */ 693 /* XXX supress on mux _client_ quietmode */
697 tochan = options.log_level >= SYSLOG_LEVEL_ERROR && 694 tochan = options.log_level >= SYSLOG_LEVEL_ERROR &&
698 c->ctl_fd != -1 && c->extended_usage == CHAN_EXTENDED_WRITE; 695 c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE;
699 696
700 if (type == SSH2_MSG_CHANNEL_SUCCESS) { 697 if (type == SSH2_MSG_CHANNEL_SUCCESS) {
701 debug2("%s request accepted on channel %d", 698 debug2("%s request accepted on channel %d",
@@ -839,6 +836,7 @@ process_cmdline(void)
839 while (isspace(*++s)) 836 while (isspace(*++s))
840 ; 837 ;
841 838
839 /* XXX update list of forwards in options */
842 if (delete) { 840 if (delete) {
843 cancel_port = 0; 841 cancel_port = 0;
844 cancel_host = hpdelim(&s); /* may be NULL */ 842 cancel_host = hpdelim(&s); /* may be NULL */
@@ -936,7 +934,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
936 escape_char); 934 escape_char);
937 buffer_append(berr, string, strlen(string)); 935 buffer_append(berr, string, strlen(string));
938 936
939 if (c && c->ctl_fd != -1) { 937 if (c && c->ctl_chan != -1) {
940 chan_read_failed(c); 938 chan_read_failed(c);
941 chan_write_failed(c); 939 chan_write_failed(c);
942 return 0; 940 return 0;
@@ -946,7 +944,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
946 944
947 case 'Z' - 64: 945 case 'Z' - 64:
948 /* XXX support this for mux clients */ 946 /* XXX support this for mux clients */
949 if (c && c->ctl_fd != -1) { 947 if (c && c->ctl_chan != -1) {
950 noescape: 948 noescape:
951 snprintf(string, sizeof string, 949 snprintf(string, sizeof string,
952 "%c%c escape not available to " 950 "%c%c escape not available to "
@@ -991,7 +989,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
991 continue; 989 continue;
992 990
993 case '&': 991 case '&':
994 if (c && c->ctl_fd != -1) 992 if (c && c->ctl_chan != -1)
995 goto noescape; 993 goto noescape;
996 /* 994 /*
997 * Detach the program (continue to serve 995 * Detach the program (continue to serve
@@ -1042,7 +1040,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
1042 continue; 1040 continue;
1043 1041
1044 case '?': 1042 case '?':
1045 if (c && c->ctl_fd != -1) { 1043 if (c && c->ctl_chan != -1) {
1046 snprintf(string, sizeof string, 1044 snprintf(string, sizeof string,
1047"%c?\r\n\ 1045"%c?\r\n\
1048Supported escape sequences:\r\n\ 1046Supported escape sequences:\r\n\
@@ -1091,7 +1089,7 @@ Supported escape sequences:\r\n\
1091 continue; 1089 continue;
1092 1090
1093 case 'C': 1091 case 'C':
1094 if (c && c->ctl_fd != -1) 1092 if (c && c->ctl_chan != -1)
1095 goto noescape; 1093 goto noescape;
1096 process_cmdline(); 1094 process_cmdline();
1097 continue; 1095 continue;
@@ -1327,8 +1325,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1327 connection_in = packet_get_connection_in(); 1325 connection_in = packet_get_connection_in();
1328 connection_out = packet_get_connection_out(); 1326 connection_out = packet_get_connection_out();
1329 max_fd = MAX(connection_in, connection_out); 1327 max_fd = MAX(connection_in, connection_out);
1330 if (muxserver_sock != -1)
1331 max_fd = MAX(max_fd, muxserver_sock);
1332 1328
1333 if (!compat20) { 1329 if (!compat20) {
1334 /* enable nonblocking unless tty */ 1330 /* enable nonblocking unless tty */
@@ -1446,12 +1442,6 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
1446 /* Buffer input from the connection. */ 1442 /* Buffer input from the connection. */
1447 client_process_net_input(readset); 1443 client_process_net_input(readset);
1448 1444
1449 /* Accept control connections. */
1450 if (muxserver_sock != -1 &&FD_ISSET(muxserver_sock, readset)) {
1451 if (muxserver_accept_control())
1452 quit_pending = 1;
1453 }
1454
1455 if (quit_pending) 1445 if (quit_pending)
1456 break; 1446 break;
1457 1447
@@ -1859,9 +1849,8 @@ client_input_channel_req(int type, u_int32_t seq, void *ctxt)
1859 chan_rcvd_eow(c); 1849 chan_rcvd_eow(c);
1860 } else if (strcmp(rtype, "exit-status") == 0) { 1850 } else if (strcmp(rtype, "exit-status") == 0) {
1861 exitval = packet_get_int(); 1851 exitval = packet_get_int();
1862 if (c->ctl_fd != -1) { 1852 if (c->ctl_chan != -1) {
1863 /* Dispatch to mux client */ 1853 mux_exit_message(c, exitval);
1864 atomicio(vwrite, c->ctl_fd, &exitval, sizeof(exitval));
1865 success = 1; 1854 success = 1;
1866 } else if (id == session_ident) { 1855 } else if (id == session_ident) {
1867 /* Record exit value of local session */ 1856 /* Record exit value of local session */