summaryrefslogtreecommitdiff
path: root/mux.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2011-05-05 14:16:22 +1000
committerDamien Miller <djm@mindrot.org>2011-05-05 14:16:22 +1000
commit6c3eec7ab23d58157ded8a0e6283f93e45390d07 (patch)
tree3beb55b3ca050613a158865ec350008dcdd0ab72 /mux.c
parentad21032e656aefcddb2cc52f014885026ba82d56 (diff)
- djm@cvs.openbsd.org 2011/04/17 22:42:42
[PROTOCOL.mux clientloop.c clientloop.h mux.c ssh.1 ssh.c] allow graceful shutdown of multiplexing: request that a mux server removes its listener socket and refuse future multiplexing requests; ok markus@
Diffstat (limited to 'mux.c')
-rw-r--r--mux.c86
1 files changed, 85 insertions, 1 deletions
diff --git a/mux.c b/mux.c
index e370462db..09468359f 100644
--- a/mux.c
+++ b/mux.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: mux.c,v 1.24 2011/01/13 21:54:53 djm Exp $ */ 1/* $OpenBSD: mux.c,v 1.25 2011/04/17 22:42:41 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org> 3 * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
4 * 4 *
@@ -146,6 +146,7 @@ struct mux_master_state {
146#define MUX_C_OPEN_FWD 0x10000006 146#define MUX_C_OPEN_FWD 0x10000006
147#define MUX_C_CLOSE_FWD 0x10000007 147#define MUX_C_CLOSE_FWD 0x10000007
148#define MUX_C_NEW_STDIO_FWD 0x10000008 148#define MUX_C_NEW_STDIO_FWD 0x10000008
149#define MUX_C_STOP_LISTENING 0x10000009
149#define MUX_S_OK 0x80000001 150#define MUX_S_OK 0x80000001
150#define MUX_S_PERMISSION_DENIED 0x80000002 151#define MUX_S_PERMISSION_DENIED 0x80000002
151#define MUX_S_FAILURE 0x80000003 152#define MUX_S_FAILURE 0x80000003
@@ -168,6 +169,7 @@ static int process_mux_terminate(u_int, Channel *, Buffer *, Buffer *);
168static int process_mux_open_fwd(u_int, Channel *, Buffer *, Buffer *); 169static int process_mux_open_fwd(u_int, Channel *, Buffer *, Buffer *);
169static int process_mux_close_fwd(u_int, Channel *, Buffer *, Buffer *); 170static int process_mux_close_fwd(u_int, Channel *, Buffer *, Buffer *);
170static int process_mux_stdio_fwd(u_int, Channel *, Buffer *, Buffer *); 171static int process_mux_stdio_fwd(u_int, Channel *, Buffer *, Buffer *);
172static int process_mux_stop_listening(u_int, Channel *, Buffer *, Buffer *);
171 173
172static const struct { 174static const struct {
173 u_int type; 175 u_int type;
@@ -180,6 +182,7 @@ static const struct {
180 { MUX_C_OPEN_FWD, process_mux_open_fwd }, 182 { MUX_C_OPEN_FWD, process_mux_open_fwd },
181 { MUX_C_CLOSE_FWD, process_mux_close_fwd }, 183 { MUX_C_CLOSE_FWD, process_mux_close_fwd },
182 { MUX_C_NEW_STDIO_FWD, process_mux_stdio_fwd }, 184 { MUX_C_NEW_STDIO_FWD, process_mux_stdio_fwd },
185 { MUX_C_STOP_LISTENING, process_mux_stop_listening },
183 { 0, NULL } 186 { 0, NULL }
184}; 187};
185 188
@@ -915,6 +918,39 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
915 return 0; 918 return 0;
916} 919}
917 920
921static int
922process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r)
923{
924 debug("%s: channel %d: stop listening", __func__, c->self);
925
926 if (options.control_master == SSHCTL_MASTER_ASK ||
927 options.control_master == SSHCTL_MASTER_AUTO_ASK) {
928 if (!ask_permission("Disable further multiplexing on shared "
929 "connection to %s? ", host)) {
930 debug2("%s: stop listen refused by user", __func__);
931 buffer_put_int(r, MUX_S_PERMISSION_DENIED);
932 buffer_put_int(r, rid);
933 buffer_put_cstring(r, "Permission denied");
934 return 0;
935 }
936 }
937
938 if (mux_listener_channel != NULL) {
939 channel_free(mux_listener_channel);
940 client_stop_mux();
941 xfree(options.control_path);
942 options.control_path = NULL;
943 mux_listener_channel = NULL;
944 muxserver_sock = -1;
945 }
946
947 /* prepare reply */
948 buffer_put_int(r, MUX_S_OK);
949 buffer_put_int(r, rid);
950
951 return 0;
952}
953
918/* Channel callbacks fired on read/write from mux slave fd */ 954/* Channel callbacks fired on read/write from mux slave fd */
919static int 955static int
920mux_master_read_cb(Channel *c) 956mux_master_read_cb(Channel *c)
@@ -1813,6 +1849,50 @@ mux_client_request_stdio_fwd(int fd)
1813 fatal("%s: master returned unexpected message %u", __func__, type); 1849 fatal("%s: master returned unexpected message %u", __func__, type);
1814} 1850}
1815 1851
1852static void
1853mux_client_request_stop_listening(int fd)
1854{
1855 Buffer m;
1856 char *e;
1857 u_int type, rid;
1858
1859 debug3("%s: entering", __func__);
1860
1861 buffer_init(&m);
1862 buffer_put_int(&m, MUX_C_STOP_LISTENING);
1863 buffer_put_int(&m, muxclient_request_id);
1864
1865 if (mux_client_write_packet(fd, &m) != 0)
1866 fatal("%s: write packet: %s", __func__, strerror(errno));
1867
1868 buffer_clear(&m);
1869
1870 /* Read their reply */
1871 if (mux_client_read_packet(fd, &m) != 0)
1872 fatal("%s: read from master failed: %s",
1873 __func__, strerror(errno));
1874
1875 type = buffer_get_int(&m);
1876 if ((rid = buffer_get_int(&m)) != muxclient_request_id)
1877 fatal("%s: out of sequence reply: my id %u theirs %u",
1878 __func__, muxclient_request_id, rid);
1879 switch (type) {
1880 case MUX_S_OK:
1881 break;
1882 case MUX_S_PERMISSION_DENIED:
1883 e = buffer_get_string(&m, NULL);
1884 fatal("Master refused stop listening request: %s", e);
1885 case MUX_S_FAILURE:
1886 e = buffer_get_string(&m, NULL);
1887 fatal("%s: stop listening request failed: %s", __func__, e);
1888 default:
1889 fatal("%s: unexpected response from master 0x%08x",
1890 __func__, type);
1891 }
1892 buffer_free(&m);
1893 muxclient_request_id++;
1894}
1895
1816/* Multiplex client main loop. */ 1896/* Multiplex client main loop. */
1817void 1897void
1818muxclient(const char *path) 1898muxclient(const char *path)
@@ -1906,6 +1986,10 @@ muxclient(const char *path)
1906 case SSHMUX_COMMAND_STDIO_FWD: 1986 case SSHMUX_COMMAND_STDIO_FWD:
1907 mux_client_request_stdio_fwd(sock); 1987 mux_client_request_stdio_fwd(sock);
1908 exit(0); 1988 exit(0);
1989 case SSHMUX_COMMAND_STOP:
1990 mux_client_request_stop_listening(sock);
1991 fprintf(stderr, "Stop listening request sent.\r\n");
1992 exit(0);
1909 default: 1993 default:
1910 fatal("unrecognised muxclient_command %d", muxclient_command); 1994 fatal("unrecognised muxclient_command %d", muxclient_command);
1911 } 1995 }