Bugzilla – Attachment 2615 Details for
Bug 2393
Remote dynamic port forwarding for OpenSSH client
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Remote dynamic port forwarding patch against OpenSSH Portable 70860b6d07
openssh.diff (text/plain), 20.88 KB, created by
Anthony Steinhauser
on 2015-05-05 02:59:36 AEST
(
hide
)
Description:
Remote dynamic port forwarding patch against OpenSSH Portable 70860b6d07
Filename:
MIME Type:
Creator:
Anthony Steinhauser
Created:
2015-05-05 02:59:36 AEST
Size:
20.88 KB
patch
obsolete
>diff --git a/channels.c b/channels.c >index 9486c1c..6882e99 100644 >--- a/channels.c >+++ b/channels.c >@@ -219,6 +219,7 @@ channel_lookup(int id) > case SSH_CHANNEL_LARVAL: > case SSH_CHANNEL_CONNECTING: > case SSH_CHANNEL_DYNAMIC: >+ case SSH_CHANNEL_RDYNAMIC: > case SSH_CHANNEL_OPENING: > case SSH_CHANNEL_OPEN: > case SSH_CHANNEL_INPUT_DRAINING: >@@ -556,6 +557,7 @@ channel_still_open(void) > continue; > case SSH_CHANNEL_OPENING: > case SSH_CHANNEL_OPEN: >+ case SSH_CHANNEL_RDYNAMIC: > case SSH_CHANNEL_X11_OPEN: > case SSH_CHANNEL_MUX_CLIENT: > return 1; >@@ -601,6 +603,7 @@ channel_find_open(void) > case SSH_CHANNEL_LARVAL: > case SSH_CHANNEL_AUTH_SOCKET: > case SSH_CHANNEL_OPEN: >+ case SSH_CHANNEL_RDYNAMIC: > case SSH_CHANNEL_X11_OPEN: > return i; > case SSH_CHANNEL_INPUT_DRAINING: >@@ -654,6 +657,7 @@ channel_open_message(void) > case SSH_CHANNEL_OPENING: > case SSH_CHANNEL_CONNECTING: > case SSH_CHANNEL_DYNAMIC: >+ case SSH_CHANNEL_RDYNAMIC: > case SSH_CHANNEL_OPEN: > case SSH_CHANNEL_X11_OPEN: > case SSH_CHANNEL_INPUT_DRAINING: >@@ -1041,7 +1045,8 @@ channel_pre_mux_client(Channel *c, fd_set *readset, fd_set *writeset) > /* try to decode a socks4 header */ > /* ARGSUSED */ > static int >-channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) >+channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset, >+ Buffer * input, Buffer * output) > { > char *p, *host; > u_int len, have, i, found, need; >@@ -1055,11 +1060,11 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) > > debug2("channel %d: decode socks4", c->self); > >- have = buffer_len(&c->input); >+ have = buffer_len(input); > len = sizeof(s4_req); > if (have < len) > return 0; >- p = (char *)buffer_ptr(&c->input); >+ p = (char *)buffer_ptr(input); > > need = 1; > /* SOCKS4A uses an invalid IP address 0.0.0.x */ >@@ -1084,23 +1089,27 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) > } > if (found < need) > return 0; >- buffer_get(&c->input, (char *)&s4_req.version, 1); >- buffer_get(&c->input, (char *)&s4_req.command, 1); >- buffer_get(&c->input, (char *)&s4_req.dest_port, 2); >- buffer_get(&c->input, (char *)&s4_req.dest_addr, 4); >- have = buffer_len(&c->input); >- p = (char *)buffer_ptr(&c->input); >- if (memchr(p, '\0', have) == NULL) >- fatal("channel %d: decode socks4: user not nul terminated", >+ buffer_get(input, (char *)&s4_req.version, 1); >+ buffer_get(input, (char *)&s4_req.command, 1); >+ buffer_get(input, (char *)&s4_req.dest_port, 2); >+ buffer_get(input, (char *)&s4_req.dest_addr, 4); >+ have = buffer_len(input); >+ p = (char *)buffer_ptr(input); >+ if (memchr(p, '\0', have) == NULL) { >+ error("channel %d: decode socks4: user not nul terminated", > c->self); >+ return -1; >+ } > len = strlen(p); > debug2("channel %d: decode socks4: user %s/%d", c->self, p, len); > len++; /* trailing '\0' */ >- if (len > have) >- fatal("channel %d: decode socks4: len %d > have %d", >+ if (len > have) { >+ error("channel %d: decode socks4: len %d > have %d", > c->self, len, have); >+ return -1; >+ } > strlcpy(username, p, sizeof(username)); >- buffer_consume(&c->input, len); >+ buffer_consume(input, len); > > free(c->path); > c->path = NULL; >@@ -1108,22 +1117,24 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) > host = inet_ntoa(s4_req.dest_addr); > c->path = xstrdup(host); > } else { /* SOCKS4A: two strings */ >- have = buffer_len(&c->input); >- p = (char *)buffer_ptr(&c->input); >+ have = buffer_len(input); >+ p = (char *)buffer_ptr(input); > len = strlen(p); > debug2("channel %d: decode socks4a: host %s/%d", > c->self, p, len); > len++; /* trailing '\0' */ >- if (len > have) >- fatal("channel %d: decode socks4a: len %d > have %d", >+ if (len > have) { >+ error("channel %d: decode socks4a: len %d > have %d", > c->self, len, have); >+ return -1; >+ } > if (len > NI_MAXHOST) { > error("channel %d: hostname \"%.100s\" too long", > c->self, p); > return -1; > } > c->path = xstrdup(p); >- buffer_consume(&c->input, len); >+ buffer_consume(input, len); > } > c->host_port = ntohs(s4_req.dest_port); > >@@ -1139,7 +1150,7 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) > s4_rsp.command = 90; /* cd: req granted */ > s4_rsp.dest_port = 0; /* ignored */ > s4_rsp.dest_addr.s_addr = INADDR_ANY; /* ignored */ >- buffer_append(&c->output, &s4_rsp, sizeof(s4_rsp)); >+ buffer_append(output, &s4_rsp, sizeof(s4_rsp)); > return 1; > } > >@@ -1154,7 +1165,8 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) > > /* ARGSUSED */ > static int >-channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset) >+channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset, >+ Buffer * input, Buffer * output) > { > struct { > u_int8_t version; >@@ -1168,10 +1180,10 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset) > u_int have, need, i, found, nmethods, addrlen, af; > > debug2("channel %d: decode socks5", c->self); >- p = buffer_ptr(&c->input); >+ p = buffer_ptr(input); > if (p[0] != 0x05) > return -1; >- have = buffer_len(&c->input); >+ have = buffer_len(input); > if (!(c->flags & SSH_SOCKS5_AUTHDONE)) { > /* format: ver | nmethods | methods */ > if (have < 2) >@@ -1191,10 +1203,13 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset) > c->self); > return -1; > } >- buffer_consume(&c->input, nmethods + 2); >- buffer_put_char(&c->output, 0x05); /* version */ >- buffer_put_char(&c->output, SSH_SOCKS5_NOAUTH); /* method */ >- FD_SET(c->sock, writeset); >+ buffer_consume(input, nmethods + 2); >+ buffer_put_char(output, 0x05); /* version */ >+ buffer_put_char(output, SSH_SOCKS5_NOAUTH); /* method */ >+ >+ if (c->type == SSH_CHANNEL_DYNAMIC) >+ FD_SET(c->sock, writeset); >+ > c->flags |= SSH_SOCKS5_AUTHDONE; > debug2("channel %d: socks5 auth done", c->self); > return 0; /* need more */ >@@ -1231,11 +1246,11 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset) > need++; > if (have < need) > return 0; >- buffer_consume(&c->input, sizeof(s5_req)); >+ buffer_consume(input, sizeof(s5_req)); > if (s5_req.atyp == SSH_SOCKS5_DOMAIN) >- buffer_consume(&c->input, 1); /* host string length */ >- buffer_get(&c->input, &dest_addr, addrlen); >- buffer_get(&c->input, (char *)&dest_port, 2); >+ buffer_consume(input, 1); /* host string length */ >+ buffer_get(input, &dest_addr, addrlen); >+ buffer_get(input, (char *)&dest_port, 2); > dest_addr[addrlen] = '\0'; > free(c->path); > c->path = NULL; >@@ -1262,9 +1277,9 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset) > s5_rsp.atyp = SSH_SOCKS5_IPV4; > dest_port = 0; /* ignored */ > >- buffer_append(&c->output, &s5_rsp, sizeof(s5_rsp)); >- buffer_put_int(&c->output, ntohl(INADDR_ANY)); /* bind address */ >- buffer_append(&c->output, &dest_port, sizeof(dest_port)); >+ buffer_append(output, &s5_rsp, sizeof(s5_rsp)); >+ buffer_put_int(output, ntohl(INADDR_ANY)); /* bind address */ >+ buffer_append(output, &dest_port, sizeof(dest_port)); > return 1; > } > >@@ -1298,40 +1313,125 @@ channel_pre_dynamic(Channel *c, fd_set *readset, fd_set *writeset) > { > u_char *p; > u_int have; >- int ret; >+ int ret, gaierr, sock = -1; >+ char strport[NI_MAXSERV]; >+ Buffer * inbuf, * outbuf; >+ struct addrinfo hints; >+ struct channel_connect cctx; >+ >+ if (c->type == SSH_CHANNEL_DYNAMIC) { >+ inbuf = &c->input; >+ outbuf = &c->output; >+ } else if (c->type == SSH_CHANNEL_RDYNAMIC) { >+ inbuf = &c->output; >+ outbuf = &c->input; >+ } else { >+ fatal("cannot happen"); >+ } > >- have = buffer_len(&c->input); >+ have = buffer_len(inbuf); > debug2("channel %d: pre_dynamic: have %d", c->self, have); > /* buffer_dump(&c->input); */ > /* check if the fixed size part of the packet is in buffer. */ > if (have < 3) { > /* need more */ >- FD_SET(c->sock, readset); >+ if (c->type == SSH_CHANNEL_DYNAMIC) >+ FD_SET(c->sock, readset); >+ > return; > } > /* try to guess the protocol */ >- p = buffer_ptr(&c->input); >+ p = buffer_ptr(inbuf); > switch (p[0]) { > case 0x04: >- ret = channel_decode_socks4(c, readset, writeset); >+ ret = channel_decode_socks4(c, readset, writeset, inbuf, outbuf); > break; > case 0x05: >- ret = channel_decode_socks5(c, readset, writeset); >+ ret = channel_decode_socks5(c, readset, writeset, inbuf, outbuf); > break; > default: > ret = -1; > break; > } > if (ret < 0) { >- chan_mark_dead(c); >+ if (c->type == SSH_CHANNEL_DYNAMIC) >+ chan_mark_dead(c); >+ else { >+ close(c->sock); >+ c->sock = c->rfd = c->wfd = c->efd = -1; >+ buffer_clear(&c->input); >+ buffer_clear(&c->output); >+ if (compat20) >+ packet_start(SSH2_MSG_CHANNEL_CLOSE); >+ else >+ packet_start(SSH_MSG_CHANNEL_CLOSE); >+ packet_put_int(c->remote_id); >+ packet_send(); >+ c->flags |= CHAN_CLOSE_SENT; >+ c->type = SSH_CHANNEL_ABANDONED; >+ } > } else if (ret == 0) { > debug2("channel %d: pre_dynamic: need more", c->self); > /* need more */ >- FD_SET(c->sock, readset); >+ if (c->type == SSH_CHANNEL_DYNAMIC) >+ FD_SET(c->sock, readset); > } else { >- /* switch to the next state */ >- c->type = SSH_CHANNEL_OPENING; >- port_open_helper(c, "direct-tcpip"); >+ if (c->type == SSH_CHANNEL_DYNAMIC) { >+ /* switch to the next state */ >+ c->type = SSH_CHANNEL_OPENING; >+ port_open_helper(c, "direct-tcpip"); >+ } else { >+ close(c->sock); >+ c->sock = c->rfd = c->wfd = c->efd = -1; >+ memset(&hints, 0, sizeof(hints)); >+ hints.ai_family = IPv4or6; >+ hints.ai_socktype = SOCK_STREAM; >+ snprintf(strport, sizeof strport, "%d", c->host_port); >+ if ((gaierr = getaddrinfo(c->path, strport, &hints, &cctx.aitop)) != 0) { >+ error("channel_pre_dynamic %.100s: unknown host (%s)", c->path, >+ ssh_gai_strerror(gaierr)); >+ buffer_clear(&c->input); >+ buffer_clear(&c->output); >+ if (compat20) >+ packet_start(SSH2_MSG_CHANNEL_CLOSE); >+ else >+ packet_start(SSH_MSG_CHANNEL_CLOSE); >+ packet_put_int(c->remote_id); >+ packet_send(); >+ c->flags |= CHAN_CLOSE_SENT; >+ c->type = SSH_CHANNEL_ABANDONED; >+ return; >+ } >+ >+ cctx.host = xstrdup(c->path); >+ cctx.port = c->host_port; >+ cctx.ai = cctx.aitop; >+ >+ if ((sock = connect_next(&cctx)) == -1) { >+ error("connect to %.100s port %d failed: %s", >+ c->path, c->host_port, strerror(errno)); >+ channel_connect_ctx_free(&cctx); >+ buffer_clear(&c->input); >+ buffer_clear(&c->output); >+ if (compat20) >+ packet_start(SSH2_MSG_CHANNEL_CLOSE); >+ else >+ packet_start(SSH_MSG_CHANNEL_CLOSE); >+ packet_put_int(c->remote_id); >+ packet_send(); >+ c->flags |= CHAN_CLOSE_SENT; >+ c->type = SSH_CHANNEL_ABANDONED; >+ return; >+ } >+ >+ c->type = SSH_CHANNEL_CONNECTING; >+ c->connect_ctx = cctx; >+ c->rfd = sock; >+ c->wfd = sock; >+ c->flags |= CHAN_RD_ACKD; >+ channel_register_fds(c, c->rfd, c->wfd, c->efd, 0, 1, 0); >+ FD_SET(c->sock, writeset); >+ } > } > } > >@@ -1587,7 +1687,7 @@ channel_post_auth_listener(Channel *c, fd_set *readset, fd_set *writeset) > static void > channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset) > { >- int err = 0, sock; >+ int err = 0, sock, ackd = 0; > socklen_t sz = sizeof(err); > > if (FD_ISSET(c->sock, writeset)) { >@@ -1600,16 +1700,21 @@ channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset) > c->self, c->connect_ctx.host, c->connect_ctx.port); > channel_connect_ctx_free(&c->connect_ctx); > c->type = SSH_CHANNEL_OPEN; >- if (compat20) { >- packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); >- packet_put_int(c->remote_id); >- packet_put_int(c->self); >- packet_put_int(c->local_window); >- packet_put_int(c->local_maxpacket); >+ if (c->flags & CHAN_RD_ACKD) { >+ ackd = 1; >+ c->flags &= ~CHAN_RD_ACKD; > } else { >- packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); >- packet_put_int(c->remote_id); >- packet_put_int(c->self); >+ if (compat20) { >+ packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); >+ packet_put_int(c->remote_id); >+ packet_put_int(c->self); >+ packet_put_int(c->local_window); >+ packet_put_int(c->local_maxpacket); >+ } else { >+ packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); >+ packet_put_int(c->remote_id); >+ packet_put_int(c->self); >+ } > } > } else { > debug("channel %d: connection failed: %s", >@@ -1625,21 +1730,50 @@ channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset) > error("connect_to %.100s port %d: failed.", > c->connect_ctx.host, c->connect_ctx.port); > channel_connect_ctx_free(&c->connect_ctx); >- if (compat20) { >- packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); >+ if (c->flags & CHAN_RD_ACKD) { >+ ackd = 1; >+ c->flags &= ~CHAN_RD_ACKD; >+ close(c->sock); >+ c->sock = c->rfd = c->wfd = c->efd = -1; >+ buffer_clear(&c->input); >+ buffer_clear(&c->output); >+ if (compat20) >+ packet_start(SSH2_MSG_CHANNEL_CLOSE); >+ else >+ packet_start(SSH_MSG_CHANNEL_CLOSE); > packet_put_int(c->remote_id); >- packet_put_int(SSH2_OPEN_CONNECT_FAILED); >- if (!(datafellows & SSH_BUG_OPENFAILURE)) { >- packet_put_cstring(strerror(err)); >- packet_put_cstring(""); >- } >+ packet_send(); >+ c->flags |= CHAN_CLOSE_SENT; >+ c->type = SSH_CHANNEL_ABANDONED; > } else { >- packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); >- packet_put_int(c->remote_id); >+ if (compat20) { >+ packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); >+ packet_put_int(c->remote_id); >+ packet_put_int(SSH2_OPEN_CONNECT_FAILED); >+ if (!(datafellows & SSH_BUG_OPENFAILURE)) { >+ packet_put_cstring(strerror(err)); >+ packet_put_cstring(""); >+ } >+ } else { >+ packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); >+ packet_put_int(c->remote_id); >+ } > } >- chan_mark_dead(c); >+ if (!ackd) >+ chan_mark_dead(c); > } >- packet_send(); >+ >+ if (!ackd) >+ packet_send(); >+ } >+} >+ >+static void >+channel_post_rdynamic(Channel *c, fd_set *readset, fd_set *writeset) >+{ >+ if (c->sock != -1) { >+ FD_SET(c->sock, readset); >+ FD_SET(c->sock, writeset); > } > } > >@@ -2024,6 +2158,7 @@ channel_handler_init_20(void) > channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; > channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; > channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic; >+ channel_pre[SSH_CHANNEL_RDYNAMIC] = &channel_pre_dynamic; > channel_pre[SSH_CHANNEL_MUX_LISTENER] = &channel_pre_listener; > channel_pre[SSH_CHANNEL_MUX_CLIENT] = &channel_pre_mux_client; > >@@ -2036,6 +2171,7 @@ channel_handler_init_20(void) > channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; > channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; > channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; >+ channel_post[SSH_CHANNEL_RDYNAMIC] = &channel_post_rdynamic; > channel_post[SSH_CHANNEL_MUX_LISTENER] = &channel_post_mux_listener; > channel_post[SSH_CHANNEL_MUX_CLIENT] = &channel_post_mux_client; > } >@@ -2052,6 +2188,7 @@ channel_handler_init_13(void) > channel_pre[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_pre_output_draining; > channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; > channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic; >+ channel_pre[SSH_CHANNEL_RDYNAMIC] = &channel_pre_dynamic; > > channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; > channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; >@@ -2060,6 +2197,7 @@ channel_handler_init_13(void) > channel_post[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_post_output_drain_13; > channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; > channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; >+ channel_post[SSH_CHANNEL_RDYNAMIC] = &channel_post_rdynamic; > } > > static void >@@ -2072,6 +2210,7 @@ channel_handler_init_15(void) > channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; > channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; > channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic; >+ channel_pre[SSH_CHANNEL_RDYNAMIC] = &channel_pre_dynamic; > > channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; > channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; >@@ -2079,6 +2218,7 @@ channel_handler_init_15(void) > channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; > channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; > channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; >+ channel_post[SSH_CHANNEL_RDYNAMIC] = &channel_post_rdynamic; > } > > static void >@@ -2234,10 +2374,12 @@ channel_output_poll(void) > */ > if (compat13) { > if (c->type != SSH_CHANNEL_OPEN && >- c->type != SSH_CHANNEL_INPUT_DRAINING) >+ c->type != SSH_CHANNEL_INPUT_DRAINING && >+ c->type != SSH_CHANNEL_RDYNAMIC) > continue; > } else { >- if (c->type != SSH_CHANNEL_OPEN) >+ if (c->type != SSH_CHANNEL_OPEN && >+ c->type != SSH_CHANNEL_RDYNAMIC) > continue; > } > if (compat20 && >@@ -2362,7 +2504,8 @@ channel_input_data(int type, u_int32_t seq, void *ctxt) > > /* Ignore any data for non-open channels (might happen on close) */ > if (c->type != SSH_CHANNEL_OPEN && >- c->type != SSH_CHANNEL_X11_OPEN) >+ c->type != SSH_CHANNEL_X11_OPEN && >+ c->type != SSH_CHANNEL_RDYNAMIC) > return 0; > > /* Get the data. */ >@@ -3296,6 +3439,10 @@ open_listen_match_tcpip(ForwardPermission *allowed_open, > return 0; > if (allowed_open->listen_port != requestedport) > return 0; >+ if (allowed_open->port_to_connect == 0 && >+ strcmp("socks", allowed_open->host_to_connect)==0 && >+ allowed_open->listen_port == requestedport) >+ return 1; > if (!translate && allowed_open->listen_host == NULL && > requestedhost == NULL) > return 1; >@@ -3684,7 +3831,12 @@ connect_to(const char *name, int port, char *ctype, char *rname) > > memset(&cctx, 0, sizeof(cctx)); > >- if (port == PORT_STREAMLOCAL) { >+ if (port == 0) { >+ sock = socket(AF_INET, SOCK_STREAM, 0); >+ c = channel_new(ctype, SSH_CHANNEL_RDYNAMIC, sock, sock, -1, >+ CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1); >+ return c; >+ } else if (port == PORT_STREAMLOCAL) { > struct sockaddr_un *sunaddr; > struct addrinfo *ai; > >diff --git a/channels.h b/channels.h >index 5a672f2..6a54c1d 100644 >--- a/channels.h >+++ b/channels.h >@@ -58,7 +58,8 @@ > #define SSH_CHANNEL_ABANDONED 17 /* Abandoned session, eg mux */ > #define SSH_CHANNEL_UNIX_LISTENER 18 /* Listening on a domain socket. */ > #define SSH_CHANNEL_RUNIX_LISTENER 19 /* Listening to a R-style domain socket. */ >-#define SSH_CHANNEL_MAX_TYPE 20 >+#define SSH_CHANNEL_RDYNAMIC 20 >+#define SSH_CHANNEL_MAX_TYPE 21 > > #define CHANNEL_CANCEL_PORT_STATIC -1 > >@@ -193,6 +194,7 @@ struct Channel { > #define CHAN_EOF_SENT 0x04 > #define CHAN_EOF_RCVD 0x08 > #define CHAN_LOCAL 0x10 >+#define CHAN_RD_ACKD 0x20 > > #define CHAN_RBUF 16*1024 > >diff --git a/clientloop.c b/clientloop.c >index a9c8a90..eae7267 100644 >--- a/clientloop.c >+++ b/clientloop.c >@@ -873,7 +873,7 @@ process_cmdline(void) > { > void (*handler)(int); > char *s, *cmd; >- int ok, delete = 0, local = 0, remote = 0, dynamic = 0; >+ int ok, delete = 0, remote, dynamic; > struct Forward fwd; > > memset(&fwd, 0, sizeof(fwd)); >@@ -898,12 +898,16 @@ process_cmdline(void) > "Request remote forward"); > logit(" -D[bind_address:]port " > "Request dynamic forward"); >+ logit(" -d[bind_address:]port " >+ "Request remote dynamic forward"); > logit(" -KL[bind_address:]port " > "Cancel local forward"); > logit(" -KR[bind_address:]port " > "Cancel remote forward"); > logit(" -KD[bind_address:]port " > "Cancel dynamic forward"); >+ logit(" -Kd[bind_address:]port " >+ "Cancel remote dynamic forward"); > if (!options.permit_local_command) > goto out; > logit(" !args " >@@ -921,13 +925,19 @@ process_cmdline(void) > delete = 1; > s++; > } >- if (*s == 'L') >- local = 1; >- else if (*s == 'R') >+ if (*s == 'L') { >+ dynamic = 0; >+ remote = 0; >+ } else if (*s == 'R') { >+ dynamic = 0; > remote = 1; >- else if (*s == 'D') >+ } else if (*s == 'D') { > dynamic = 1; >- else { >+ remote = 0; >+ } else if (*s == 'd') { >+ dynamic = 1; >+ remote = 1; >+ } else { > logit("Invalid command."); > goto out; > } >@@ -966,7 +976,7 @@ process_cmdline(void) > logit("Bad forwarding specification."); > goto out; > } >- if (local || dynamic) { >+ if (!remote) { > if (!channel_setup_local_fwd_listener(&fwd, > &options.fwd_opts)) { > logit("Port forwarding failed."); >diff --git a/ssh.c b/ssh.c >index 0ad82f0..c4ede68 100644 >--- a/ssh.c >+++ b/ssh.c >@@ -596,7 +596,7 @@ main(int ac, char **av) > argv0 = av[0]; > > again: >- while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" >+ while ((opt = getopt(ac, av, "1246ab:c:d:e:fgi:kl:m:no:p:qstvx" > "ACD:E:F:GI:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { > switch (opt) { > case '1': >@@ -876,6 +876,17 @@ main(int ac, char **av) > } > break; > >+ case 'd': >+ if (parse_forward(&fwd, optarg, 1, 1)) { >+ add_remote_forward(&options, &fwd); >+ } else { >+ fprintf(stderr, >+ "Bad remote dynamic forwarding specification " >+ "'%s'\n", optarg); >+ exit(255); >+ } >+ break; >+ > case 'C': > options.compression = 1; > break;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 2393
: 2615